Search code examples
javaswingjfreecharttimeserieschart

Map dynamic dataset to different axis in JFreeChart


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.

enter image description here

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);

Solution

  • 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);