Example usage for org.jfree.data.xy XYSeriesCollection getSeries

List of usage examples for org.jfree.data.xy XYSeriesCollection getSeries

Introduction

In this page you can find the example usage for org.jfree.data.xy XYSeriesCollection getSeries.

Prototype

public XYSeries getSeries(Comparable key) 

Source Link

Document

Returns a series from the collection.

Usage

From source file:com.jtstand.swing.StatsPanel.java

public JFreeChart getChartDistribution(boolean horizontal) {
    //        System.out.println("Min: " + minValue());
    //        System.out.println("Max: " + maxValue());
    XYIntervalSeriesCollection datasetDistribution = createIntervalXYDatasetDistribution(horizontal);
    XYSeriesCollection dataset2 = createXYDatasetGauss(horizontal);
    // create the chart...
    NumberAxis xAxis = new NumberAxis(getValueString());
    xAxis.setAutoRangeIncludesZero(false);
    //        NumberAxis yAxis = new NumberAxis("Distribution");
    NumberAxis yAxis = new NumberAxis();
    yAxis.setAutoRangeIncludesZero(true);
    //XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();
    renderer = new MyBarRenderer();
    XYPlot plot = new XYPlot(datasetDistribution, xAxis, yAxis, renderer);
    plot.setOrientation(horizontal ? PlotOrientation.HORIZONTAL : PlotOrientation.VERTICAL);
    renderer.setBaseToolTipGenerator(new StandardXYToolTipGenerator());
    JFreeChart chart = new JFreeChart(null, JFreeChart.DEFAULT_TITLE_FONT, plot, isGrouping());
    chart.setBackgroundPaint((Paint) UIManager.get("Panel.background"));
    //        plot.setBackgroundPaint(Color.white);
    plot.setDomainAxisLocation(AxisLocation.BOTTOM_OR_LEFT);
    plot.setRangeAxisLocation(AxisLocation.BOTTOM_OR_LEFT);
    StandardXYItemLabelGenerator itemlabels = new StandardXYItemLabelGenerator();
    renderer.setBaseItemLabelGenerator(itemlabels);
    renderer.setBaseItemLabelsVisible(true);
    plot.setDataset(1, dataset2);/*from www  . ja v  a 2s.c o m*/
    plot.mapDatasetToRangeAxis(1, 1);
    //        ValueAxis domainAxis = plot.getDomainAxis();
    //domainAxis.setCategoryLabelPositions(horizontal?CategoryLabelPositions.STANDARD:CategoryLabelPositions.UP_90);
    ValueAxis axis2 = new NumberAxis("Gaussian");
    plot.setRangeAxis(1, axis2);
    axis2.setVisible(false);
    final XYLineAndShapeRenderer renderer2 = new XYLineAndShapeRenderer();
    //renderer2.setShapesVisible(false);
    //renderer2.setSeriesVisibleInLegend(false);
    renderer2.setBaseSeriesVisibleInLegend(false);
    //renderer2.setToolTipGenerator(new StandardCategoryToolTipGenerator());
    plot.setRenderer(1, renderer2);
    renderer.setUseYInterval(true);
    renderer.setBaseSeriesVisibleInLegend(false);
    /* coloring */
    Color c;
    if (isMultipleCategorization()) {
        //            TreeMap<String, Color> cmap = new TreeMap<String, Color>();
        int i = 0;
        for (Iterator<String> it = catstats.keySet().iterator(); it.hasNext(); i++) {
            String groupName = it.next();
            c = ChartCategories.getColor(i);
            for (int j = 0; j < datasetDistribution.getSeriesCount(); j++) {
                XYIntervalSeries s = datasetDistribution.getSeries(j);
                if (s.getKey().equals(groupName)) {
                    GradientPaint gp = new GradientPaint(0.0f, 0.0f, c, 0.0f, 0.0f, c.darker().darker());
                    renderer.setSeriesPaint(j, gp);
                }
            }
            for (int j = 0; j < dataset2.getSeriesCount(); j++) {
                XYSeries s = dataset2.getSeries(j);
                if (s.getKey().equals(groupName)) {
                    renderer2.setSeriesPaint(j, c);
                    renderer2.setSeriesShapesVisible(j, false);
                    renderer2.setSeriesStroke(j, myStroke);
                }
            }
        }
        c = Color.black;
    } else {
        c = ChartCategories.getColor(0);
        GradientPaint gp = new GradientPaint(0.0f, 0.0f, c, 0.0f, 0.0f, c.darker().darker());
        renderer.setSeriesPaint(0, gp);
    }
    renderer2.setSeriesPaint(0, c);
    renderer2.setSeriesShapesVisible(0, false);
    renderer2.setSeriesStroke(0, myStroke);

    placeLimitMarkers(plot, false);
    //        renderer.setAutoPopulateSeriesOutlinePaint(true);
    //        renderer.setBaseOutlinePaint(Color.black);
    //        renderer.setSeriesOutlinePaint(0, Color.black, true);
    //        renderer.setDrawBarOutline(true);

    renderer.setHighlightedItem(0, 0);
    yAxis.setAutoRange(false);
    yAxis.setAutoRange(true);
    xAxis.setRange(leftValue(0), rightValue(numberOfCategories - 1));
    chart.setTextAntiAlias(false);
    return chart;
}

From source file:org.pf.midea.SimulationController.java

@Override
public void run() {
    textAreaNumeric.setText("");
    XYSeriesCollection xySeriesCollection = new XYSeriesCollection();
    double progress = 0;
    double progressStep = 100.0 / (planCells.length * (hSquareHigh - hSquareLow + hSquareStep) / hSquareStep);
    progressBar.setValue(0);//from   w  ww .ja v a2  s . co  m
    for (int i = 0; i < planCells.length; i++) {
        XYSeries xySeries;
        if (showLineNumbers)
            xySeries = new XYSeries(String.valueOf(i + 1) + ") " + planCells[i].getShortDescription());
        else
            xySeries = new XYSeries(planCells[i].getShortDescription());
        textAreaNumeric.append(planCells[i].getDescription() + "\n");
        textAreaNumeric.setCaretPosition(textAreaNumeric.getDocument().getLength());

        PlanStates.SourceType currentSourceType = planCells[i].getSourceCell().getSourceType();
        PlanStates.CodeType currentCodeType = planCells[i].getCodeCell().getCodeType();
        PlanStates.ModulationType currentModulationType = planCells[i].getModulationCell().getModulationType();
        PlanStates.ChannelType currentChannelType = planCells[i].getChannelCell().getChannelType();
        PlanStates.ErrorsType currentErrorsType = planCells[i].getErrorsCell().getErrorsType();

        BinaryNumber[] sourcePoints = null;
        switch (currentSourceType) {
        case ST_TEST:
            sourcePoints = ConstellationPointsGenerator.getTestPoints(currentModulationType, iterationsCount);
            break;
        case ST_RANDOM:
            sourcePoints = ConstellationPointsGenerator.getRandomPoints(currentModulationType, iterationsCount);
            break;
        }

        Coder coder = null;
        Decoder decoder = null;
        switch (currentCodeType) {
        case CT_NONE:
            coder = new CoderNone();
            decoder = new DecoderNone();
            break;
        case CT_HAMMING74:
            coder = new CoderHamming74();
            decoder = new DecoderHamming74();
            break;
        case CT_CYCLIC:
            coder = new CoderCyclic85();
            decoder = new DecoderCyclic85();
            break;
        case CT_BCH155:
            coder = new CoderBCH155();
            decoder = new DecoderBCH155();
            break;
        }

        Modulator modulator = null;
        Demodulator demodulator = null;
        switch (currentModulationType) {
        case MT_ASK:
            modulator = new ModulatorASK();
            demodulator = new DemodulatorASK();
            break;
        case MT_FSK:
            modulator = new ModulatorFSK();
            demodulator = new DemodulatorFSK();
            break;
        case MT_BPSK:
            modulator = new ModulatorBPSK();
            demodulator = new DemodulatorBPSK();
            break;
        case MT_QPSK:
            modulator = new ModulatorQPSK();
            demodulator = new DemodulatorQPSK();
            break;
        case MT_8PSK:
            modulator = new Modulator8PSK();
            demodulator = new Demodulator8PSK();
            break;
        case MT_16PSK:
            modulator = new Modulator16PSK();
            demodulator = new Demodulator16PSK();
            break;
        case MT_32PSK:
            modulator = new Modulator32PSK();
            demodulator = new Demodulator32PSK();
            break;
        case MT_16QAM:
            modulator = new Modulator16QAM();
            demodulator = new Demodulator16QAM();
            break;
        case MT_32QAM:
            modulator = new Modulator32QAM();
            demodulator = new Demodulator32QAM();
            break;
        case MT_64QAM:
            modulator = new Modulator64QAM();
            demodulator = new Demodulator64QAM();
            break;
        case MT_256QAM:
            modulator = new Modulator256QAM();
            demodulator = new Demodulator256QAM();
            break;
        }

        Channel channel = null;
        switch (currentChannelType) {
        case CHT_AWGN:
            channel = new ChannelAWGN();
            break;
        case CHT_RAYLEIGH:
            channel = new ChannelRayleigh();
            break;
        }

        BinaryNumber[] encoded = coder.encode(sourcePoints);
        Signal[] modulated = modulator.modulate(encoded);

        double error = 0;

        for (double h = hSquareLow; h <= hSquareHigh; h += hSquareStep) {
            double realH;
            if (dBs)
                realH = StatisticsTools.decibelsToTimes(h);
            else
                realH = h;

            Signal[] noised = channel.noise(realH, modulated);
            BinaryNumber[] demodulated = demodulator.demodulate(noised);
            noised = null;
            System.gc();
            BinaryNumber[] decoded = decoder.decode(demodulated);
            demodulated = null;
            System.gc();
            switch (currentErrorsType) {
            case ET_SER:
                error = StatisticsTools.getSER(sourcePoints, decoded);
                break;
            case ET_BER:
                error = StatisticsTools.getBER(sourcePoints, decoded);
                break;
            }
            decoded = null;
            System.gc();

            if (error > 0) {
                xySeries.add(h, error);
                textAreaNumeric.append(String.valueOf(h) + "\t" + String.valueOf(error) + "\n");
                textAreaNumeric.setCaretPosition(textAreaNumeric.getDocument().getLength());
            }

            progress += progressStep;
            progressBar.setValue((int) Math.round(progress));
        }
        xySeriesCollection.addSeries(xySeries);
        textAreaNumeric.append("\n");
        textAreaNumeric.setCaretPosition(textAreaNumeric.getDocument().getLength());
    }

    JFreeChart chart = ChartFactory.createXYLineChart("", dBs ? "" : "", "?",
            xySeriesCollection, PlotOrientation.VERTICAL, true, true, false);
    chart.getLegend().setPosition(RectangleEdge.RIGHT);
    XYPlot xyPlot = chart.getXYPlot();

    for (int i = 0; i < planCells.length; i++) {
        xyPlot.getRenderer().setSeriesStroke(i, new BasicStroke(planCells[i].getLineWidth()));
        if (planCells[i].getLineColor() != null)
            xyPlot.getRenderer().setSeriesPaint(i, planCells[i].getLineColor());

        if (showLineNumbers) {
            XYSeries currentSeries = xySeriesCollection.getSeries(i);
            double annotationY = currentSeries.getY(0).doubleValue();
            double annotationX = currentSeries.getX(0).doubleValue();
            for (int j = 1; j < currentSeries.getItemCount(); j++)
                if (currentSeries.getY(j).doubleValue() == 0) {
                    annotationY = currentSeries.getY(j - 1).doubleValue();
                    annotationX = currentSeries.getX(j - 1).doubleValue();
                    break;
                } else {
                    annotationY = currentSeries.getY(j).doubleValue();
                    annotationX = currentSeries.getX(j).doubleValue();
                }
            XYTextAnnotation annotation = new XYTextAnnotation(String.valueOf(i + 1), annotationX, annotationY);
            annotation.setBackgroundPaint(Color.WHITE);
            annotation.setFont(new Font("Dialog", 0, 14));
            xyPlot.addAnnotation(annotation);
        }
    }

    xyPlot.setBackgroundPaint(Color.WHITE);
    xyPlot.setDomainGridlinePaint(Color.GRAY);
    xyPlot.setRangeGridlinePaint(Color.GRAY);
    NumberAxis domainAxis = new NumberAxis("h, " + (dBs ? "" : ""));
    LogAxis rangeAxis = new LogAxis("?");
    rangeAxis.setNumberFormatOverride(new HumanNumberFormat(1));
    domainAxis.setTickLabelFont(new Font("Dialog", 0, 14));
    rangeAxis.setTickLabelFont(new Font("Dialog", 0, 14));
    xyPlot.setDomainAxis(domainAxis);
    xyPlot.setRangeAxis(rangeAxis);

    ChartPanel nestedPanel = new ChartPanel(chart);
    chartPanel.removeAll();
    chartPanel.add(nestedPanel, new CellConstraints());
    chartPanel.updateUI();
}

From source file:mil.tatrc.physiology.utilities.csv.plots.ActionEventPlotter.java

public void createGraph(PlotJob job, List<List<Double>> timeData, List<List<Double>> data,
        List<LogEvent> events, List<SEAction> actions) {
    CSVPlotTool plotTool = new CSVPlotTool(); //to leverage existing functions
    String title = job.name + "_";
    XYSeriesCollection dataSet = new XYSeriesCollection();
    double maxY = 0;
    double minY = Double.MAX_VALUE;
    for (int i = 0; i < timeData.size(); i++) {
        if (timeData.get(i) == null || data.get(i) == null) {
            job.bgColor = Color.white; //This hits when we have Expected data but NOT computed data
            continue;
        }/*from   ww  w.  j  a  v a2  s. c o  m*/

        title = title + job.headers.get(i) + "_";
        XYSeries dataSeries;
        if (job.isComparePlot) {
            if (timeData.size() > 1)
                dataSeries = plotTool.createXYSeries(i == 0 ? "Expected" : "Computed", timeData.get(i),
                        data.get(i));
            else //If we're comparing but only have one data list, expected is missing, so rename to computed
            {
                dataSeries = plotTool.createXYSeries("Computed", timeData.get(i), data.get(i));
            }
        } else
            dataSeries = plotTool.createXYSeries(job.headers.get(i), timeData.get(i), data.get(i));
        dataSet.addSeries(dataSeries);
        maxY = maxY < dataSeries.getMaxY() ? dataSeries.getMaxY() : maxY;
        minY = minY > dataSeries.getMinY() ? dataSeries.getMinY() : minY;
    }
    title = title + "vs_Time_Action_Event_Plot";

    //Override the constructed title if desired (usually for compare plots)
    if (job.titleOverride != null && !job.titleOverride.isEmpty()
            && !job.titleOverride.equalsIgnoreCase("None"))
        title = job.titleOverride;

    double rangeLength = maxY - minY;
    if (Math.abs(rangeLength) < 1e-6) {
        rangeLength = .01;
    }

    class AEEntry implements Comparable<AEEntry> {
        public String name;
        public List<Double> times = new ArrayList<Double>();
        public List<Double> YVals = new ArrayList<Double>();
        public String type = "";

        public int compareTo(AEEntry entry) {
            return times.get(0) < entry.times.get(0) ? -1 : times.get(0) > entry.times.get(0) ? 1 : 0;
        }
    }

    List<AEEntry> allActionsAndEvents = new ArrayList<AEEntry>();

    if (!job.skipAllEvents) {
        //Make points for each event
        //Treat each event like two points on the same vertical line
        for (LogEvent event : events) {
            boolean skip = false;

            for (String eventToSkip : job.eventOmissions) {
                if (event.text.contains(eventToSkip))
                    skip = true;
            }
            if (skip)
                continue;
            AEEntry entry = new AEEntry();

            entry.times.add(event.time.getValue());
            if (job.logAxis)
                entry.YVals.add(maxY);
            else if (job.forceZeroYAxisBound && maxY < 0)
                entry.YVals.add(-.01);
            else
                entry.YVals.add(maxY + 0.15 * rangeLength);

            entry.times.add(event.time.getValue());
            if (job.logAxis)
                entry.YVals.add(minY);
            else if (job.forceZeroYAxisBound && minY > 0)
                entry.YVals.add(-.01);
            else
                entry.YVals.add(minY - 0.15 * rangeLength);

            entry.name = event.text + "\r\nt=" + event.time.getValue();
            entry.type = "EVENT:";

            allActionsAndEvents.add(entry);
        }
    }

    if (!job.skipAllActions) {
        //Make similar entries for actions
        for (SEAction action : actions) {
            boolean skip = false;

            for (String actionToSkip : job.actionOmissions) {
                if (action.toString().contains(actionToSkip))
                    skip = true;
            }
            if (skip)
                continue;

            if (action.toString().contains("Advance Time"))
                continue;

            AEEntry entry = new AEEntry();

            entry.times.add(action.getScenarioTime().getValue());
            if (job.logAxis)
                entry.YVals.add(maxY);
            else if (job.forceZeroYAxisBound && maxY < 0)
                entry.YVals.add(-.01);
            else
                entry.YVals.add(maxY + 0.15 * rangeLength);

            entry.times.add(action.getScenarioTime().getValue());
            if (job.logAxis)
                entry.YVals.add(minY);
            else if (job.forceZeroYAxisBound && minY > 0)
                entry.YVals.add(-.01);
            else
                entry.YVals.add(minY - 0.15 * rangeLength);

            entry.name = action.toString() + "\r\nt=" + action.getScenarioTime().getValue();
            entry.type = "ACTION:";

            allActionsAndEvents.add(entry);
        }
    }

    //Sort the list
    Collections.sort(allActionsAndEvents);

    //Add a series for each entry
    for (AEEntry entry : allActionsAndEvents) {
        dataSet.addSeries(plotTool.createXYSeries(entry.type + entry.name, entry.times, entry.YVals));
    }

    //If we have experimental data, try to load it and create a dataset for it
    XYSeriesCollection expDataSet = new XYSeriesCollection();
    if (job.experimentalData != null && !job.experimentalData.isEmpty()) {
        Map<String, List<Double>> expData = new HashMap<String, List<Double>>();
        List<String> expHeaders = new ArrayList<String>();

        try {
            CSVContents csv = new CSVContents(job.experimentalData);
            csv.abbreviateContents = 0;
            csv.readAll(expData);
            expHeaders = csv.getHeaders();
        } catch (Exception e) {
            Log.error("Unable to read experimental data");
        }

        if (!expData.isEmpty() && !expHeaders.isEmpty()) {
            List<Double> expTimeData = new ArrayList<Double>();
            expTimeData = expData.get("Time(s)");

            for (String h : expHeaders) //Will assume all headers from exp file will be on same Y axis vs time
            {
                if (h.equalsIgnoreCase("Time(s)"))
                    continue;

                expDataSet.addSeries(plotTool.createXYSeries("Experimental " + h, expTimeData, expData.get(h)));
            }
        }
    }

    //set labels
    String XAxisLabel = "Time(s)";
    String YAxisLabel = job.headers.get(0);

    JFreeChart chart = ChartFactory.createXYLineChart(
            job.titleOverride != null && job.titleOverride.equalsIgnoreCase("None") ? "" : title, // chart title
            XAxisLabel, // x axis label
            YAxisLabel, // y axis label
            dataSet, // data
            PlotOrientation.VERTICAL, // orientation
            true, // include legend
            true, // tooltips
            false // urls
    );

    Log.info("Creating Graph " + title);
    XYPlot plot = (XYPlot) chart.getPlot();

    if (!job.logAxis) {
        // Determine Y range
        double resMax0 = maxY;
        double resMin0 = minY;
        if (Double.isNaN(resMax0) || Double.isNaN(resMin0))
            plot.getDomainAxis().setLabel("Range is NaN");
        if (DoubleUtils.isZero(resMin0))
            resMin0 = -0.000001;
        if (DoubleUtils.isZero(resMax0))
            resMax0 = 0.000001;
        if (job.forceZeroYAxisBound && resMin0 >= 0)
            resMin0 = -.000001;
        if (job.forceZeroYAxisBound && resMax0 <= 0)
            resMax0 = .000001;
        rangeLength = resMax0 - resMin0;
        ValueAxis yAxis = plot.getRangeAxis();
        if (rangeLength != 0)
            yAxis.setRange(resMin0 - 0.15 * rangeLength, resMax0 + 0.15 * rangeLength);//15% buffer so we can see top and bottom clearly           

        //Add another Y axis to the right side for easier reading
        ValueAxis rightYAxis = new NumberAxis();
        rightYAxis.setRange(yAxis.getRange());
        rightYAxis.setLabel("");

        //Override the bounds if desired
        try {
            if (job.Y1LowerBound != null) {
                yAxis.setLowerBound(job.Y1LowerBound);
                rightYAxis.setLowerBound(job.Y1LowerBound);
            }
            if (job.Y1UpperBound != null) {
                yAxis.setUpperBound(job.Y1UpperBound);
                rightYAxis.setUpperBound(job.Y1UpperBound);
            }
        } catch (Exception e) {
            Log.error(
                    "Couldn't set Y bounds. You probably tried to set a bound on an axis that doesn't exist.");
        }
        plot.setRangeAxis(0, yAxis);
        plot.setRangeAxis(1, rightYAxis);

    } else {
        double resMin = minY;
        double resMax = maxY;
        if (resMin <= 0.0)
            resMin = .00001;
        LogarithmicAxis yAxis = new LogarithmicAxis("Log(" + YAxisLabel + ")");
        LogarithmicAxis rightYAxis = new LogarithmicAxis("");
        yAxis.setLowerBound(resMin);
        rightYAxis.setLowerBound(resMin);
        yAxis.setUpperBound(resMax);
        rightYAxis.setUpperBound(resMax);

        //Override the bounds if desired
        try {
            if (job.Y1LowerBound != null) {
                yAxis.setLowerBound(job.Y1LowerBound);
                rightYAxis.setLowerBound(job.Y1LowerBound);
            }
            if (job.Y1UpperBound != null) {
                yAxis.setUpperBound(job.Y1UpperBound);
                rightYAxis.setUpperBound(job.Y1UpperBound);
            }
        } catch (Exception e) {
            Log.error(
                    "Couldn't set Y bounds. You probably tried to set a bound on an axis that doesn't exist.");
        }
        plot.setRangeAxis(0, yAxis);
        plot.setRangeAxis(1, rightYAxis);
    }

    //Override X bounds if desired
    try {
        if (job.X1LowerBound != null)
            plot.getDomainAxis(0).setLowerBound(job.X1LowerBound);
        if (job.X1UpperBound != null)
            plot.getDomainAxis(0).setUpperBound(job.X1UpperBound);
    } catch (Exception e) {
        Log.error("Couldn't set X bounds. You probably tried to set a bound on an axis that doesn't exist.");
    }

    //Override labels if desired
    if (job.X1Label != null && !plot.getDomainAxis(0).getLabel().contains("NaN"))
        plot.getDomainAxis(0).setLabel(job.X1Label.equalsIgnoreCase("None") ? "" : job.X1Label);
    if (job.Y1Label != null)
        plot.getRangeAxis(0).setLabel(job.Y1Label.equalsIgnoreCase("None") ? "" : job.Y1Label);

    //If we have experimental data, set up the renderer for it and add to plot
    if (expDataSet.getSeriesCount() != 0) {
        XYItemRenderer renderer1 = new XYLineAndShapeRenderer(false, true); // Shapes only
        renderer1.setSeriesShape(0, ShapeUtilities.createDiamond(8));
        plot.setDataset(1, expDataSet);
        plot.setRenderer(1, renderer1);
        plot.mapDatasetToDomainAxis(1, 0);
        plot.mapDatasetToRangeAxis(1, 0);
    }

    formatAEPlot(job, chart);
    plot.setDomainGridlinesVisible(job.showGridLines);
    plot.setRangeGridlinesVisible(job.showGridLines);

    //Changing line widths and colors
    XYItemRenderer r = plot.getRenderer();
    BasicStroke wideLine = new BasicStroke(2.0f);
    Color[] AEcolors = { Color.red, Color.green, Color.black, Color.magenta, Color.orange };
    Color[] dataColors = { Color.blue, Color.cyan, Color.gray, Color.black, Color.red };
    for (int i = 0, cIndex = 0; i < dataSet.getSeriesCount(); i++, cIndex++) {
        r.setSeriesStroke(i, wideLine);
        XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot.getRenderer();
        renderer.setBaseShapesVisible(false);
        if (cIndex > 4)
            cIndex = 0;
        if (i < job.headers.size()) //Our actual data
        {
            renderer.setSeriesFillPaint(i, dataColors[cIndex]);
            renderer.setSeriesPaint(i, dataColors[cIndex]);
        } else //actions and events in procession of other colors
        {
            renderer.setSeriesFillPaint(i, AEcolors[cIndex]);
            renderer.setSeriesPaint(i, AEcolors[cIndex]);
        }
    }
    //Special color and format changes for compare plots
    if (job.isComparePlot) {
        XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot.getRenderer();

        for (int i = 0; i < dataSet.getSeriesCount(); i++) {
            if (dataSet.getSeries(i).getKey().toString().equalsIgnoreCase("Expected")) {
                renderer.setSeriesStroke(//makes a dashed line
                        i, //argument below float[]{I,K} -> alternates between solid and opaque (solid for I, opaque for K)
                        new BasicStroke(2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1.0f,
                                new float[] { 15.0f, 30.0f }, 0.0f));
                renderer.setDrawSeriesLineAsPath(true);
                renderer.setUseFillPaint(true);
                renderer.setBaseShapesVisible(false);
                renderer.setSeriesFillPaint(i, Color.black);
                renderer.setSeriesPaint(i, Color.black);
            }
            if (dataSet.getSeries(i).getKey().toString().equalsIgnoreCase("Computed")) {
                renderer.setSeriesFillPaint(i, Color.red);
                renderer.setSeriesPaint(i, Color.red);
            }
            if (dataSet.getSeries(i).getKey().toString().startsWith("ACTION")) {
                renderer.setSeriesFillPaint(i, Color.green);
                renderer.setSeriesPaint(i, Color.green);
            }
            if (dataSet.getSeries(i).getKey().toString().startsWith("EVENT")) {
                renderer.setSeriesFillPaint(i, Color.blue);
                renderer.setSeriesPaint(i, Color.blue);
            }
        }
    }

    //Split the auto-generated legend into two legends, one for data and one for actions and events
    LegendItemCollection originalLegendCollection = plot.getLegendItems();
    final LegendItemCollection dataLegendCollection = new LegendItemCollection();
    int i;
    for (i = 0; i < job.headers.size() && i < originalLegendCollection.getItemCount(); i++) {
        if (originalLegendCollection.get(i).getLabel().startsWith("ACTION")
                || originalLegendCollection.get(i).getLabel().startsWith("EVENT"))
            break;
        dataLegendCollection.add(originalLegendCollection.get(i));
    }
    final LegendItemCollection remainingLegendCollection = new LegendItemCollection();
    for (; i < originalLegendCollection.getItemCount(); i++) {
        remainingLegendCollection.add(originalLegendCollection.get(i));
    }
    chart.removeLegend();
    LegendItemSource source = new LegendItemSource() {
        LegendItemCollection lic = new LegendItemCollection();
        {
            lic.addAll(dataLegendCollection);
        }

        public LegendItemCollection getLegendItems() {
            return lic;
        }
    };
    LegendTitle dataLegend = new LegendTitle(source);
    dataLegend.setMargin(new RectangleInsets(1.0, 1.0, 1.0, 1.0));
    dataLegend.setBorder(2, 2, 2, 2);
    dataLegend.setBackgroundPaint(Color.white);
    dataLegend.setPosition(RectangleEdge.TOP);
    dataLegend.setItemFont(new Font("SansSerif", Font.PLAIN, 22));
    chart.addLegend(dataLegend);

    source = new LegendItemSource() {
        LegendItemCollection lic = new LegendItemCollection();
        {
            lic.addAll(remainingLegendCollection);
        }

        public LegendItemCollection getLegendItems() {
            return lic;
        }
    };
    LegendTitle actionEventsLegend = new LegendTitle(source);
    actionEventsLegend.setMargin(new RectangleInsets(1.0, 1.0, 1.0, 1.0));
    actionEventsLegend.setBorder(2, 2, 2, 2);
    actionEventsLegend.setBackgroundPaint(Color.white);
    actionEventsLegend.setPosition(RectangleEdge.BOTTOM);
    actionEventsLegend.setItemFont(new Font("SansSerif", Font.PLAIN, 22));
    if (!job.hideAELegend && !job.removeAllLegends)
        chart.addLegend(actionEventsLegend);

    if (job.removeAllLegends)
        chart.removeLegend();

    int verticalPixels = 800 + 170 * (allActionsAndEvents.size() / 5);

    //This is a little hacky, but if we want only the legend, just extend Plot() and remove the draw functionality so it makes a blank plot
    class legendPlot extends Plot {
        public void draw(Graphics2D arg0, Rectangle2D arg1, Point2D arg2, PlotState arg3,
                PlotRenderingInfo arg4) {

        }

        public String getPlotType() {
            return null;
        }
    }
    //Then add the legend to that and throw away the original plot
    if (job.legendOnly) {
        chart = new JFreeChart("", null, new legendPlot(), false);
        chart.addLegend(actionEventsLegend);
    }

    try {
        FileUtils.createDirectory(job.outputDir);
        String filename = job.outputFilename == null
                ? job.outputDir + "/" + plotTool.MakeFileName(title) + ".jpg"
                : job.outputDir + "/" + job.outputFilename;
        if (!filename.endsWith(".jpg"))
            filename = filename + ".jpg";
        File JPGFile = new File(filename);
        if (job.imageHeight != null && job.imageWidth != null)
            ChartUtilities.saveChartAsJPEG(JPGFile, chart, job.imageWidth, job.imageHeight);
        else if (!job.hideAELegend && !job.removeAllLegends)
            ChartUtilities.saveChartAsJPEG(JPGFile, chart, 1600, verticalPixels);
        else
            ChartUtilities.saveChartAsJPEG(JPGFile, chart, 1600, 800);
    } catch (IOException e) {
        Log.error(e.getMessage());
    }
}