I am calculating histogram of red component of the image and stored it in redhisto[]. The index of the array represent the intensity(0 to 255)
and the value represent the number of pixel with that intensity. Then plotting those values with JFreeChart.
My question is:
How to make X-axis value start from 0. Now its starting from negative number.
Can we change the color of the bars in the graph
code is :
public class Histogram extends ApplicationFrame {
public Histogram(final String title) throws IOException {
super(title);
IntervalXYDataset dataset = createDataset();
JFreeChart chart = createChart(dataset);
final ChartPanel chartPanel = new ChartPanel(chart);
chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
setContentPane(chartPanel);
}
private IntervalXYDataset createDataset() throws IOException {
BufferedImage imageA = ImageIO.read(new File("XYZ.bmp"));
int[] red = new int[imageA.getHeight()*imageA.getWidth()];
int[] redhisto = new int[256];
int[] pixel;
int k= 0;
for (int y = 0; y < imageA.getHeight(); y++) {
for (int x = 0; x < imageA.getWidth(); x++) {
pixel = imageA.getRaster().getPixel(x, y, new int[3]);
red[k] = pixel[0];
k++;
}
}
for(int x=0;x<red.length;x++){
int y = red[x];
redhisto[y]++;
}
final XYSeries series = new XYSeries("No of pixels");
for(int i=0; i<redhisto.length;i++)
series.add(i,redhisto[i]);
final XYSeriesCollection dataset = new XYSeriesCollection(series);
return dataset;
}
private JFreeChart createChart(IntervalXYDataset dataset) {
final JFreeChart chart = ChartFactory.createXYBarChart("Color Intensity Histogram","X",false,"Y",dataset,PlotOrientation.VERTICAL,true,true,false);
XYPlot plot = (XYPlot) chart.getPlot();
return chart;
}
public static void main(final String[] args) throws IOException {
final Histogram demo = new Histogram("Image Histogram");
demo.pack();
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
}
}
You can change the lower bound of the domain axis and set the series paint as shown below. The default XYBarPainter has a gradient color highlight, so I used a StandardXYBarPainter.
XYPlot plot = (XYPlot) chart.getPlot();
ValueAxis axis = plot.getDomainAxis();
axis.setLowerBound(0);
XYBarRenderer r = (XYBarRenderer) plot.getRenderer();
r.setBarPainter(new StandardXYBarPainter());
r.setSeriesPaint(0, Color.blue);
XYPlot plot = (XYPlot) chart.getPlot();
//To change the lower bound of X-axis
NumberAxis xAxis = (NumberAxis) plot.getDomainAxis();
xAxis.setLowerBound(0);
//To change the lower bound of Y-axis
NumberAxis yAxis = (NumberAxis) plot.getRangeAxis();
yAxis.setLowerBound(0);
// To change the color
XYItemRenderer renderer = plot.getRenderer();
renderer.setSeriesPaint(0, Color.green);
Related
I am trying to add annotations to my XYPlot; but unfortunately, they don't seem to show up.
Here is my code:
public JFreeChart createGraph() {
int[][] audiogramR = {{250, 25}, {500, 15}, {1000, 30}, {2000, 40}, {4000, 50}, {8000, 60}};
int[][] audiogramL = {{250, 60}, {500, 50}, {1000, 40}, {2000, 30}, {4000, 15}, {8000, 25}};
XYSeries r = new XYSeries("Right");
XYSeries l = new XYSeries("Left");
for (int i = 0; i <= 5; i++) { //add data to series
r.add(audiogramR[i][0], audiogramR[i][1]);
l.add(audiogramL[i][0], audiogramL[i][1]);
}
XYSeriesCollection dataset = new XYSeriesCollection(); //add series to dataset
dataset.addSeries(r);
dataset.addSeries(l);
NumberAxis yAxis = new NumberAxis("Decibels"); //create axes
LogAxis xAxis = new LogAxis("Frequency");
xAxis.setBase(2);
xAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
yAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
yAxis.setInverted(true);
yAxis.setRange(-10, 120);
Shape cross = ShapeUtilities.createDiagonalCross(3, 1);
Shape outer = new Ellipse2D.Float(-3.5f, -3.5f, 7, 7);
Shape inner = new Ellipse2D.Float(-3f, -3f, 6, 6); //shapes for plot
Area area = new Area(outer);
area.subtract(new Area(inner));
Shape ring = area;
XYPlot plot = new XYPlot(dataset, xAxis, yAxis, new XYLineAndShapeRenderer(true, true)); //create xy plot for dataset and axes
plot.getRenderer().setSeriesShape(1, cross);
plot.getRenderer().setSeriesShape(0, ring);
plot.setDomainGridlinesVisible(false);
XYTextAnnotation label = new XYTextAnnotation("Annotation text here", 50, 1024); //create annotation
plot.addAnnotation(label, true);
JFreeChart chart = new JFreeChart("Audiogram", JFreeChart.DEFAULT_TITLE_FONT, plot, true);
ChartPanel myChart = new ChartPanel(chart);
myChart.setPreferredSize(pGraph.getSize()); //size according to my window
myChart.setMouseWheelEnabled(false);
pGraph.setLayout(new java.awt.BorderLayout());
pGraph.add(myChart, BorderLayout.CENTER); //add chart to jPanel in netbeans
pGraph.validate();
}
which produces this:
Evidently, there is no annotation. Any thoughts?
As noted here,
The coordinates are specified in data space (they will be converted to Java2D space for display).
Your y value of 1024 is outside the range specified for your yAxis. As noted here, it may be useful to query the data itself for the required coordinates. In the fragment below, the series r provides the data space coordinates for the penultimate point:
double x = (double) r.getX(r.getItemCount() - 2);
double y = (double) r.getY(r.getItemCount() - 2);
XYTextAnnotation label = new XYTextAnnotation("Annotation", x, y);
plot.addAnnotation(label);
I am trying to obtain the equivalent of a matlab Pcolor added on a polar() function but in java.
I am pretty new to the language, but managed to obtain a polar plot already, with the following code:
public class Polar extends JFrame {
public Polar(double[][] vec){
XYDataset dataset = getXYDataset(vec);
JFreeChart chart = ChartFactory.createPolarChart("test", dataset, true, true, true);
PolarPlot plot = (PolarPlot) chart.getPlot();
DefaultPolarItemRenderer render = (DefaultPolarItemRenderer)
plot.getRenderer();
render.setFillComposite(...);
render.setSeriesFilled(0,true);
ChartPanel panel = new ChartPanel(chart);
panel.setMouseZoomable(false);
setContentPane(panel);
}
private XYDataset getXYDataset(double[][] vec){
XYSeriesCollection dataset = new XYSeriesCollection();
XYSeries faultDP =new XYSeries("Serie1");
for(int i = 0; i<vec.length; i++){
faultDP.add(vec[i][1],vec[i][0]);
}
dataset.addSeries(faultDP);
return dataset;
}
}
The array vec contains the speed and angle of my variable, and should be plotted on the polar plot. this works fine.
The next step would be to pass a new variable, a double[][] vector of dimension 90x360. Each cell should be plotted on the polar plot with background color value, a bit like in the picture below.
Any idea on how to do so ?
Cheers,
Flo
So, I've looked into what trashgod offered me and came with this code:
public class PolarTest extends JFrame {
public PolarTest(double[][] dipaz, double[][] val){
JFrame f = new JFrame("Title");
ChartPanel panel = new ChartPanel(createChart(val, dipaz));
panel.setPreferredSize(new Dimension(500,500));
f.add(panel);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private JFreeChart createChart(double[][] val,double[][] dipaz){
XYSeriesCollection dataset = new XYSeriesCollection ();
double step, min, max;
min = val[0][2];
max = val[val.length-1][2];
step = (max-min)/10; //creation of 10 areas of similar heat range
dataset = (XYSeriesCollection) createDataset(val,step);
JFreeChart chart = ChartFactory.createPolarChart("test", dataset, true, true, true);
PolarPlot plot = (PolarPlot) chart.getPlot();
DefaultPolarItemRenderer r = (DefaultPolarItemRenderer) plot.getRenderer();
r.setFillComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,0.5f));
for(int i =0; i<dataset.getSeriesCount(); i++){
r.setSeriesFilled(i, true);
r.setShapesVisible(false);
r.setDrawOutlineWhenFilled(false);
}
NumberAxis rangeAxis = (NumberAxis) plot.getAxis();
rangeAxis.setTickLabelsVisible(false);
return chart;
}
private XYDataset createDataset(double[][] val, double step){
XYSeriesCollection result = new XYSeriesCollection();
double dpTmp, breakPoint;
int cpt=1;
boolean t;
t= true;
dpTmp = val[0][2];
breakPoint = dpTmp + step;
XYSeries series = null ;
for(int i = 0; i< val.length; i++){
if(val[i][2] < breakPoint){
if(t){
series = new XYSeries(String.valueOf(cpt));
t = false;
}
series.add(val[i][1],val[i][0]);
cpt++;
}else{
result.addSeries(series);
i--;
t=true;
breakPoint = val[i][2] + step;
}
}
return result;
}
The array dipaz contains my angle and dip (of X,Y dots I'd like to later plot on the polar representation), while val a 3 by N array:
val[][0] = dip
val[][1] = angle
val[][2] = value of "heat" , if we see that problem as a heatmap.
val is ascending sorted by the third column. My idea was to split the whole array in 10 (or more) areas of similar heat values.
if I run this code, I obtain the following output (cf pic). We can see that it's getting there, but not quite. I am not sure that this code is able to map correctly my heat on the polar plot>
How could I get closer to the picture I posted in my first post?
Thank you for your help.
Flo
i am use java to draw chart , and i want set background color for small area in xyplot . like: i want area from x axis (20 to 30) and y axis (10-20) set red color and do like this for the remaining, i am use valuemaker but not give me good solution because its fill long marker by color and i want only small area
this is my code:
private JFreeChart createChart(XYDataset dataset) {
/*JFreeChart chart = ChartFactory.createXYLineChart(
"Chart Index Sag",
"Sag Duration",
"Retained Voltage",
dataset,
PlotOrientation.VERTICAL,
false,
false,
false
);*/
XYLineAndShapeRenderer rr = new XYLineAndShapeRenderer();
rr.setSeriesLinesVisible(2, true);
rr.setSeriesShapesVisible(2, true);
rr.setPaint(Color.red);
// Point label
XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();
renderer.setBaseFillPaint(Color.black);
renderer.setSeriesLinesVisible(0, false);
renderer.setBaseItemLabelGenerator(new LabelGenerator());
renderer.setBaseItemLabelsVisible(true);
renderer.setBaseItemLabelFont(new Font("Arial", Font.BOLD, 12));
renderer.setPaint(Color.black);
//plot = (XYPlot) chart.getPlot();
SymbolAxis symbolaxis1 = new SymbolAxis("Sag Duration", new String[] { "0","0.02","0.2", "0.5", "10" });
symbolaxis1.setRange(0,6);
symbolaxis1.setGridBandsVisible(false);
SymbolAxis range = new SymbolAxis("Returned Voltage", new String[] { "0","0.2","0.4", "0.6", "0.8", "1" });
range.setRange(0,5);
range.setGridBandsVisible(false);
plot = new XYPlot(dataset, symbolaxis1, range, renderer);
plot.setDomainPannable(true);
plot.setRangePannable(true);
plot.setBackgroundPaint(Color.lightGray);
// Line curve
plot.setDataset(0, dataset);
plot.setDataset(1, dataset1);
final Marker originalEnd = new ValueMarker(1);
originalEnd.setPaint(Color.black);
originalEnd.setStroke(new BasicStroke(1));
plot.addDomainMarker(originalEnd);
final Marker v2 = new ValueMarker(2);
v2.setPaint(Color.black);
v2.setStroke(new BasicStroke(1));
plot.addDomainMarker(v2);
final Marker v3 = new ValueMarker(3);
v3.setPaint(Color.black);
v3.setStroke(new BasicStroke(1));
plot.addDomainMarker(v3);
final Marker v4 = new ValueMarker(4);
v4.setPaint(Color.black);
v4.setStroke(new BasicStroke(1));
plot.addDomainMarker(v4);
Marker r1 = new ValueMarker(1);
r1.setPaint(Color.black);
r1.setStroke(new BasicStroke(1));
plot.addRangeMarker(r1);
Marker r2 = new ValueMarker(2);
r2.setPaint(Color.black);
r2.setStroke(new BasicStroke(1));
plot.addRangeMarker(r2);
Marker r3 = new ValueMarker(3);
r3.setPaint(Color.black);
r3.setStroke(new BasicStroke(1));
plot.addRangeMarker(r3);
Marker r4 = new ValueMarker(4);
r4.setPaint(Color.black);
r4.setStroke(new BasicStroke(1));
plot.addRangeMarker(r4);
float dash[] = {1, 1};
float f1 = 1, f2 = 1, f3 = 10;
/*NumberAxis domainAxis = (NumberAxis) plot.getDomainAxis();
domainAxis.setRange(0, 2);
domainAxis.setTickUnit(new NumberTickUnit(0.2));*/
BasicStroke gridstroke = new BasicStroke(f1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, f2, dash, f3);
plot.setDomainGridlinePaint(Color.blue);
//plot.setRangeGridlinePaint(Color.blue);
plot.setDomainGridlineStroke(gridstroke);
plot.setRangeGridlineStroke(gridstroke);
final JFreeChart chart = new JFreeChart(plot);
chart.getXYPlot().setRenderer(0, rr);
chart.getXYPlot().setRenderer(1, renderer);
return chart;
}
You should try XYBoxAnnotation, maybe something like this:
XYPlot plot = chart.getXYPlot();
XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot.getRenderer();
XYBoxAnnotation xyboxannotation = new XYBoxAnnotation(
1, 1, 2, 2, new BasicStroke(0), new Color(0), new Color(0x30d0d0d0));
renderer.addAnnotation(xyboxannotation, Layer.BACKGROUND);
I am plotting a line chart using jFreeChart, which is a series of (x, y) value connected by a straight line.
But the problem is the shape, a circle or a rect that represents a data point is too big, since I have a lot of values in one series. You can see how it looks like in this screenshot:
Also, I learned the shapes that represent data point do not scale as the rest of the plot does when I resize the chart panel.
Question:
How to make the shape(the circles and rects that represent data point) smaller so that they won't clog together?
Here is my code to generate the chart, and I used a customized renderer to draw different color for different part of the line in one data series.
private JFreeChart createChart(XYDataset dataCollection) {
// create the chart...
JFreeChart chart = ChartFactory.createXYLineChart(
fileName, // chart title
"Count", // x axis label
"Price", // y axis label
dataCollection, // data
PlotOrientation.VERTICAL,
true, // include legend
true, // tooltips
false // urls
);
// customize chart
XYPlot plot = (XYPlot) chart.getPlot();
// find out the max and min value for price series
XYSeriesCollection collection = (XYSeriesCollection)plot.getDataset();
XYSeries priceSeries = collection.getSeries(0);
double maxY = priceSeries.getMaxY();
double minY = priceSeries.getMinY();
// set max and min for range axis (y axis)
NumberAxis rangeAxis = (NumberAxis)plot.getRangeAxis();
rangeAxis.setRange(minY, maxY);
XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer() {
public Color getItemColor(int series, int item) {
// modify code here to change color for different part of the line in one serie line
if(series == 1) {
System.out.println("getting color at: " + item);
int isBuy = 0;
if(item < kFilter.buySellSignal.size()) {
isBuy = kFilter.buySellSignal.get(item);
}
if(isBuy == 1) {
return Color.red;
} else {
return Color.green;
}
} else {
return Color.yellow;
}
}
#Override
protected void drawFirstPassShape(Graphics2D g2, int pass, int series, int item, Shape shape) {
super.drawFirstPassShape(g2, pass, series, item, shape);
//g2.setStroke(getItemStroke(series, item));
Color c1 = getItemColor(series, item - 1);
Color c2 = getItemColor(series, item);
GradientPaint linePaint = new GradientPaint(0, 0, c1, 0, 300, c2);
g2.setPaint(linePaint);
g2.draw(shape);
}
};
plot.setRenderer(renderer);
return chart;
}
You can override getItemShape() in your XYLineAndShapeRenderer to return any desired Shape, as shown here. Alternatively, invoke one of the abstract parent's methods, setSeriesShape(), setBaseShape() etc.
#Nicolas S.Xu reports using code similar to the following:
Rectangle rect = new Rectangle(2, 2);
renderer.setSeriesShape(1, rect);
See also ShapeUtilities.
I have created an application that show my data in jtable into a jfreechart. The version of my jfreechart is a line chart. The screenshot is like this :
How to make the label in line of type is vertical, so it will look neat or orderly
How to make a label of value in meetings axis values and axis type
This is my code
public class LineChartDemo1 extends ApplicationFrame {
/**
* Creates a new demo.
*
* #param title the frame title.
*/
List<ReportChart> theDatas;
public LineChartDemo1(final String title, List<ReportChart> chartData) {
super(title);
this.theDatas = chartData;
final CategoryDataset dataset = createDataset();
final JFreeChart chart = createChart(dataset);
final ChartPanel chartPanel = new ChartPanel(chart);
chartPanel.setPreferredSize(new Dimension(500, 270));
setContentPane(chartPanel);
Main_Menu.presentase.removeAll(); // My form
Main_Menu.presentase.setLayout(new java.awt.BorderLayout()); // My form
Main_Menu.presentase.add(chartPanel); // My form
}
/**
* Creates a sample dataset.
*
* #return The dataset.
*/
private CategoryDataset createDataset() {
final DefaultCategoryDataset dataset = new DefaultCategoryDataset();
String algorithm1 = "Levensthein";
String algoritma2 = "SmithWaterman";
for (int i = 0; i < Main_Menu.jTable3.getRowCount(); i++) {
Object fileName = Main_Menu.jTable3.getValueAt(i, 1);
String fileNameToString = namaFile.toString();
Object nilaiLevensthein = Main_Menu.jTable3.getValueAt(i, 2);
double value1 = Double.parseDouble(nilaiLevensthein.toString());
Object nilaiSmithWaterman = Main_Menu.jTable3.getValueAt(i, 3);
double value2 = Double.parseDouble(nilaiSmithWaterman.toString());
dataset.addValue(value1, algoritma1, fileNameToString);
dataset.addValue(value2, algoritma2, fileNameToString);
}
return dataset;
}
private JFreeChart createChart(final CategoryDataset dataset) {
Object namaFile = Main_Menu.jTable3.getValueAt(0, 0);
String namaFileKeString = namaFile.toString();
// create the chart...
final JFreeChart chart = ChartFactory.createLineChart(
"Persentase Kemiripan", // chart title
"File-file Pembanding", // domain axis label
namaFileKeString, // range axis label
dataset, // data
PlotOrientation.VERTICAL, // orientation
true, // include legend
true, // tooltips
false // urls
);
chart.setBackgroundPaint(Color.white);
final CategoryPlot plot = (CategoryPlot) chart.getPlot();
plot.setBackgroundPaint(Color.lightGray);
plot.setRangeGridlinePaint(Color.white);
// customise the range axis...
final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
rangeAxis.setAutoRangeIncludesZero(true);
final LineAndShapeRenderer renderer = (LineAndShapeRenderer) plot.getRenderer();
//renderer.setDrawShapes(true);
renderer.setSeriesStroke(
0, new BasicStroke(
2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
1.0f, new float[]{10.0f, 6.0f}, 0.0f
)
);
renderer.setSeriesStroke(
1, new BasicStroke(
2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
1.0f, new float[]{6.0f, 6.0f}, 0.0f
)
);
renderer.setSeriesStroke(
2, new BasicStroke(
2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
1.0f, new float[]{2.0f, 6.0f}, 0.0f
)
);
return chart;
}
}
For the help, thank you so much.
edit
I have success to make the label in x axis line to vertical
Here is the code
private JFreeChart createChart(final CategoryDataset dataset) {
Object fileName = Main_Menu.jTable3.getValueAt(0, 0);
String fileNameToString = fileName.toString();
// create the chart...
final JFreeChart chart = ChartFactory.createLineChart(
"Persentation", // chart title
"comparingFile", // domain axis label
fileNameToString , // range axis label
dataset, // data
PlotOrientation.VERTICAL, // orientation
true, // include legend
true, // tooltips
false // urls
);
chart.setBackgroundPaint(Color.white);
ChartFactory.setChartTheme(StandardChartTheme.createDarknessTheme());
ChartUtilities.applyCurrentTheme(chart);
final CategoryPlot plot = (CategoryPlot) chart.getPlot();
plot.setBackgroundPaint(Color.lightGray);
plot.setRangeGridlinePaint(Color.white);
final LineAndShapeRenderer renderer = (LineAndShapeRenderer) plot.getRenderer();
renderer.setShapesVisible(true);
renderer.setUseFillPaint(true);
renderer.setBaseItemLabelsVisible(true);
CategoryAxis catAxis = plot.getDomainAxis();
catAxis.setCategoryLabelPositions(CategoryLabelPositions.DOWN_90);
//catAxis.setCategoryLabelPositions(CategoryLabelPositions.createUpRotationLabelPositions(Math.PI / 16.0));
renderer.setSeriesStroke(
0, new BasicStroke(
2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
1.0f, new float[]{10.0f, 6.0f}, 0.0f
)
);
renderer.setSeriesStroke(
1, new BasicStroke(
2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
1.0f, new float[]{6.0f, 6.0f}, 0.0f
)
);
renderer.setSeriesStroke(
2, new BasicStroke(
2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
1.0f, new float[]{2.0f, 6.0f}, 0.0f
)
);
// OPTIONAL CUSTOMISATION COMPLETED.
return chart;
}
Now, the point 2 still mystery for me
"How to make a label of value in meetings axis values and axis type ?"
Invoke setVerticalTickLabels() on the domain axis, as shown here.
Create a custom XYItemLabelGenerator, as shown here, or a CategoryItemLabelGenerator, as shown here.