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);
Related
I have tried the following.
Am using the MP android charts specifically the combined chart
// draw bars behind lines
mChart.setDrawOrder(new CombinedChart.DrawOrder[]{
CombinedChart.DrawOrder.BAR,
CombinedChart.DrawOrder.LINE,
});
YAxis rightAxis = mChart.getAxisRight();
rightAxis.setDrawGridLines(false);
rightAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true)
YAxis leftAxis = mChart.getAxisLeft();
leftAxis.setDrawGridLines(false);
leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true)
XAxis xAxis = mChart.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTH_SIDED);
xAxis.setAxisMinimum(0f);
xAxis.setGranularity(1f);
CombinedData data = new CombinedData();
data.setData(generateLineData());
data.setData(setnewBarData());
mChart.setData(data);
So the above generates
As from the image above the values of bar chart are not centralized example the moles first bar is much to the center.
Also the line chart should be at the middle of each bar graph but it doesn't move to the middle
Where am i going wrong?
ADDITION
methods that set bar data
THe setnewBarData method is
public BarData setnewBarData() {
ArrayList<BarEntry> yVals1 = new ArrayList<BarEntry>();
for (int i = 0; i < itemcount + 1; i++) {
float mult = (itemcount + 1);
float val1 = (float) (Math.random() * mult) + mult / 3;
float val2 = (float) (Math.random() * mult) + mult / 3;
yVals1.add(new BarEntry(
i,
new float[]{val1, val2,},
getResources().getDrawable(R.drawable.back_arrow_white)));
}
BarDataSet set1;
set1 = new BarDataSet(yVals1, "Statistics Test 2018");
set1.setDrawIcons(false);
set1.setColors(new int[]{Color.rgb(61, 165, 255),Color.rgb(128, 133, 233)});
set1.setStackLabels(new String[]{"Births", "Divorces"});
set1.setAxisDependency(YAxis.AxisDependency.LEFT);
ArrayList<IBarDataSet> dataSets = new ArrayList<IBarDataSet>();
dataSets.add(set1);
BarData data = new BarData(dataSets);
data.setValueTextColor(Color.BLACK);
data.setBarWidth(0.5f);
return data;
}
THe method to generate line data is
private LineData generateLineData() {
LineData d = new LineData();
ArrayList<Entry> entries = new ArrayList<Entry>();
for (int index = 0; index < itemcount; index++)
entries.add(new Entry(index + 0.5f, getRandom(15, 5)));
LineDataSet set = new LineDataSet(entries, "Percentage Compliance");
set.setColor(Color.rgb(240, 238, 70));
set.setLineWidth(2.5f);
set.setCircleColor(Color.rgb(240, 238, 70));
set.setCircleRadius(5f);
set.setFillColor(Color.rgb(240, 238, 70));
set.setMode(LineDataSet.Mode.CUBIC_BEZIER);
set.setDrawValues(true);
set.setValueTextSize(10f);
set.setValueTextColor(Color.rgb(240, 238, 70));
set.setAxisDependency(YAxis.AxisDependency.LEFT);
d.addDataSet(set);
return d;
}
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);
This is my code at the moment (updated):
public DynamicTimeSeriesCollection dataset;
private static final String TITLE = "Stripchart";
private static final int COUNT = 3 * 60;
private static final int TEMP_MIN = -10;
private static final int TEMP_MAX = 50;
private static final int AIR_MIN = 0;
private static final int AIR_MAX = 20;
private static final int INSO_MIN = 0;
private static final int INSO_MAX = 1;
public void draw(Data data) {
float[] newData = new float[3];
newData[0] = (float) data.getTemp();
newData[1] = (float) data.getAir();
newData[2] = (float) data.getInso();
dataset.advanceTime();
dataset.appendData(newData);
}
private ChartPanel createChart() {
dataset = new DynamicTimeSeriesCollection(3, COUNT, new Second());
dataset.setTimeBase(new Second(0, 0, 0, 1, 1, 2016));
dataset.addSeries(new float[1], 0, "Temperature");
dataset.addSeries(new float[1], 1, "Air");
dataset.addSeries(new float[1], 2, "Insolation");
final JFreeChart result = ChartFactory.createTimeSeriesChart(
TITLE, "hh:mm:ss", " ", dataset, true, true, false);
final XYPlot plot = result.getXYPlot();
ValueAxis domain = plot.getDomainAxis();
domain.setAutoRange(true);
NumberAxis temp = new NumberAxis("Temperature");
NumberAxis air = new NumberAxis("Air");
NumberAxis inso = new NumberAxis("Insolation");
plot.setRangeAxis(0, temp);
plot.setRangeAxisLocation(0, AxisLocation.BOTTOM_OR_LEFT);
plot.setRangeAxis(1, air);
plot.setRangeAxisLocation(1, AxisLocation.BOTTOM_OR_LEFT);
plot.setRangeAxis(2, inso);
plot.setRangeAxisLocation(2, AxisLocation.BOTTOM_OR_LEFT);
List<Integer> axes = Arrays.asList(0, 1, 2);
plot.mapDatasetToRangeAxes(0, axes);
temp.setRange(TEMP_MIN, TEMP_MAX);
air.setRange(AIR_MIN, AIR_MAX);
inso.setRange(INSO_MIN, INSO_MAX);
ChartPanel chartPanel = new ChartPanel(result);
return chartPanel;
}
The units are °C , m/s and lux respectively.
Everything works fine but it does not map the series as exactly as I want.
As you can see, the blue line and green line are not mapped with the second and third axis.
Any ideas to get it working?
Your help will be appreciated.
// Updated :
I have tried using this but the result is the same:
List<Integer> axes = Arrays.asList(0, 1, 2);
plot.mapDatasetToRangeAxes(0, axes);
In your fragment, I see three axes and one dataset with three series. Your calls to mapDatasetToRangeAxis() appear to assume three distinct datasets. As suggested in this related example, you may want something like this:
List<Integer> axes = Arrays.asList(0, 1, 2);
plot.mapDatasetToRangeAxes(0, axes);
The approach assumes that the three series have linearly dependent scales, and you'll have to scale the individual axes accordingly, as shown here. You could try separate datasets, but I haven't tried it.
Addendum: Based on your update, it appears that the three datasets are not commensurate. Instead, create three individual datasets. Use the first in your chart factory, use setDataset() to establish the other two and map them accordingly:
final JFreeChart result = ChartFactory.createTimeSeriesChart(
TITLE, "hh:mm:ss", " ", createDatasetTemp(), true, true, false);
…
plot.setDataset(1, createDatasetAir());
plot.setDataset(2, createDatasetInso());
plot.setRangeAxis(0, temp);
plot.setRangeAxisLocation(0, AxisLocation.BOTTOM_OR_LEFT);
plot.setRangeAxis(1, air);
plot.setRangeAxisLocation(1, AxisLocation.BOTTOM_OR_LEFT);
plot.setRangeAxis(2, inso);
plot.setRangeAxisLocation(2, AxisLocation.BOTTOM_OR_LEFT);
plot.mapDatasetToRangeAxis(0, 0);
plot.mapDatasetToRangeAxis(1, 1);
plot.mapDatasetToRangeAxis(2, 2);
I have two data series with two different Y-axis and a single X-axis. I am trying to plot a Dual Y-Axis (or in Excel known as Secondary Y-Axis) so that the chart are scaled. But I only get a single Y-axis for both data series. Note: I am using AChartEngine 1.1.0
Can anyone please advise.
My code is given below with a screenshot.
public class LineChart {
public Intent getIntent(Context context){
int[] x = {1,2,3,4,5,6,7,8,9,10};
int[] y = {22,45,34,45,55,65,74,85,93,100};
TimeSeries series = new TimeSeries("Data1");
for(int i = 0; i<x.length; i++){
series.add(x[i], y[i]);
}
int[] x2 = {1,2,3,4,5,6,7,8,9,10};
int[] y2 = {223,454,334,454,554,655,745,855,935,510};
TimeSeries series2 = new TimeSeries("Data2");
for(int i = 0; i<x.length; i++){
series2.add(x2[i], y2[i]);
}
//Multiple Series Data Set
XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
dataset.addSeries(series); //First Data Series
dataset.addSeries(series2); //Second Data Series
//Multiple Series Renderer
XYMultipleSeriesRenderer mRenderer = new XYMultipleSeriesRenderer(2);
//Background
mRenderer.setApplyBackgroundColor(true);
mRenderer.setBackgroundColor(Color.BLACK);
//mRenderer.setMarginsColor(Color.parseColor("#F5F5F5"));
//Grid
mRenderer.setShowGridY(true);
mRenderer.setShowGridX(true);
mRenderer.setGridColor(Color.WHITE);
//Label
mRenderer.setLabelsTextSize(14);
mRenderer.setXLabelsColor(Color.GREEN);
//Min and Max
mRenderer.setXAxisMax(series.getMaxX());
mRenderer.setXAxisMin(series.getMinX());
//Dual yaxis
mRenderer.setYLabelsColor(0, Color.GREEN);
mRenderer.setYLabelsColor(1, Color.RED);
mRenderer.setYTitle("Y-AXIS1", 0);
mRenderer.setYTitle("Y-AXIS2", 1);
mRenderer.setYAxisAlign(Align.LEFT, 0);
mRenderer.setYAxisAlign(Align.RIGHT, 1);
mRenderer.setYLabelsAlign(Align.LEFT, 0);
mRenderer.setYLabelsAlign(Align.RIGHT, 1);
//First Series - Single Series Renderer
XYSeriesRenderer renderer = new XYSeriesRenderer();
renderer.setColor(Color.RED);
renderer.setPointStyle(PointStyle.CIRCLE);
renderer.setFillPoints(true);
//Second Series - Single Series Renderer
XYSeriesRenderer renderer2 = new XYSeriesRenderer();
renderer2.setColor(Color.GREEN);
renderer2.setPointStyle(PointStyle.CIRCLE);
renderer2.setFillPoints(true);
//Add renderers to multiple series Renderer
mRenderer.addSeriesRenderer(renderer);
mRenderer.addSeriesRenderer(renderer2);
Intent intent = ChartFactory.getLineChartIntent(context, dataset, mRenderer, "Line Graph Title");
return intent;
}
}
Finally, I have done it using this example - here
I'm trying to implement XYTextAnnotation in DynamicTimeSeriesCollection.
I have no idea how to find X value of series in DynamicTimeSeriesCollection. My code so far:
DynamicTimeSeriesCollection dataset = new DynamicTimeSeriesCollection(1, 60, new Minute());
final JFreeChart result = ChartFactory.createTimeSeriesChart(TITLE, "A", "B", dataset, true, true, false);
float[] series1Small = new float[10];
dataset.setTimeBase(new Minute(1, 1, 1, 1, 2013));
dataset.addSeries(series1Small,0,"1");
JFreeChart result = ChartFactory.createTimeSeriesChart(TITLE, "Время", "Платежи", dataset, true, true, false);
final XYPlot plot = result.getXYPlot();
-----------------------------------------------------------Below line doesn't work.
TimeSeriesDataItem item1 = series1.getDataItem(series1.getItemCount() - 1);
createAnnotation(item1,plot);
This is a function that used to work for annotation with TimeSeriesCollection.
public static void createAnnotation(TimeSeriesDataItem item,XYPlot plot)
{
double xAnnotation = item.getPeriod().getFirstMillisecond();
double yAnnotation = item.getValue().doubleValue();
XYTextAnnotation annotation = new XYTextAnnotation(item.getValue().toString(), xAnnotation, yAnnotation);
annotation.setFont(new Font("Arial",Font.BOLD,11));
plot.addAnnotation(annotation);
}
Starting form this example, I added the following lines in createChart() to obtain the image below:
double x = dataset.getXValue(0, COUNT - 1);
double y = dataset.getYValue(0, COUNT - 1);
String s = dataset.getY(0, COUNT - 1).toString();
XYTextAnnotation a = new XYTextAnnotation(s, x, y);
a.setFont(a.getFont().deriveFont(24f));
plot.addAnnotation(a);