Java tutorial
/* Copyright 2009-2015 David Hadka * * This file is part of the MOEA Framework. * * The MOEA Framework is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or (at your * option) any later version. * * The MOEA Framework is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the MOEA Framework. If not, see <http://www.gnu.org/licenses/>. */ package iDynoOptimizer.MOEAFramework26.src.org.moeaframework.analysis.diagnostics; import java.awt.BasicStroke; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Paint; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.apache.commons.lang3.builder.CompareToBuilder; import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.LegendItem; import org.jfree.chart.LegendItemCollection; import org.jfree.chart.LegendItemSource; import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.block.LineBorder; import org.jfree.chart.plot.DatasetRenderingOrder; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.xy.DeviationRenderer; import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; import org.jfree.chart.title.LegendTitle; import org.jfree.data.xy.DefaultTableXYDataset; import org.jfree.data.xy.XYDataset; import org.jfree.data.xy.XYSeries; import org.jfree.data.xy.YIntervalSeries; import org.jfree.data.xy.YIntervalSeriesCollection; import org.jfree.ui.RectangleEdge; import org.jfree.ui.RectangleInsets; import iDynoOptimizer.MOEAFramework26.src.org.moeaframework.analysis.collector.Accumulator; import iDynoOptimizer.MOEAFramework26.src.org.moeaframework.util.Localization; /** * Displays a line plot of the runtime dynamics of a metric, displaying the * 25, 50, and 75 quantiles. */ public class LinePlot extends ResultPlot { private static final long serialVersionUID = -6265976590259977358L; /** * The localization instance for produce locale-specific strings. */ private static Localization localization = Localization.getLocalization(LinePlot.class); /** * The resolution of the line plot, controlling the number of collected * samples are included in each plotted point. */ private final int RESOLUTION = 500; /** * A data point, storing the NFE and corresponding metric value. */ private static class DataPoint implements Comparable<DataPoint> { /** * The number of evaluations of this data point. */ private final int NFE; /** * The metric value of this data point. */ private final double value; /** * Constructs a data point with the specified number of evaluations and * metric value. * * @param NFE the number of evaluations of this data point * @param value the metric value of this data point */ public DataPoint(int NFE, double value) { super(); this.NFE = NFE; this.value = value; } @Override public int compareTo(DataPoint rhs) { return new CompareToBuilder().append(NFE, rhs.NFE).toComparison(); } public int getNFE() { return NFE; } public double getValue() { return value; } } /** * Constructs a line plot for the specified metric. * * @param frame the {@code DiagnosticTool} instance containing this plot * @param metric the metric to display */ public LinePlot(DiagnosticTool frame, String metric) { super(frame, metric); setLayout(new BorderLayout()); } /** * Generate the individual series for the specified key. * * @param key the key identifying which result to plot * @param dataset the dataset to store the generated series */ protected void generateIndividualSeries(ResultKey key, DefaultTableXYDataset dataset) { for (Accumulator accumulator : controller.get(key)) { if (!accumulator.keySet().contains(metric)) { continue; } XYSeries series = new XYSeries(key, false, false); for (int i = 0; i < accumulator.size(metric); i++) { series.add((Number) accumulator.get("NFE", i), (Number) accumulator.get(metric, i)); } dataset.addSeries(series); } } /** * Generates the quantile series for the specified key. * * @param key the key identifying which result to plot * @param dataset the dataset to store the generated series */ protected void generateQuantileSeries(ResultKey key, YIntervalSeriesCollection dataset) { List<DataPoint> dataPoints = new ArrayList<DataPoint>(); for (Accumulator accumulator : controller.get(key)) { if (!accumulator.keySet().contains(metric)) { continue; } for (int i = 0; i < accumulator.size(metric); i++) { dataPoints.add(new DataPoint((Integer) accumulator.get("NFE", i), ((Number) accumulator.get(metric, i)).doubleValue())); } } Collections.sort(dataPoints); YIntervalSeries series = new YIntervalSeries(key); DescriptiveStatistics statistics = new DescriptiveStatistics(); int index = 0; int currentNFE = RESOLUTION; while (index < dataPoints.size()) { DataPoint point = dataPoints.get(index); if (point.getNFE() <= currentNFE) { statistics.addValue(point.getValue()); index++; } else { if (statistics.getN() > 0) { series.add(currentNFE, statistics.getPercentile(50), statistics.getPercentile(25), statistics.getPercentile(75)); } statistics.clear(); currentNFE += RESOLUTION; } } if (statistics.getN() > 0) { //if only entry, add extra point to display non-zero width if (series.isEmpty()) { series.add(currentNFE - RESOLUTION, statistics.getPercentile(50), statistics.getPercentile(25), statistics.getPercentile(75)); } series.add(currentNFE, statistics.getPercentile(50), statistics.getPercentile(25), statistics.getPercentile(75)); } dataset.addSeries(series); } @Override protected void update() { XYDataset dataset = null; //generate the plot data if (controller.getShowIndividualTraces()) { dataset = new DefaultTableXYDataset(); for (ResultKey key : frame.getSelectedResults()) { generateIndividualSeries(key, (DefaultTableXYDataset) dataset); } } else { dataset = new YIntervalSeriesCollection(); for (ResultKey key : frame.getSelectedResults()) { generateQuantileSeries(key, (YIntervalSeriesCollection) dataset); } } //create the chart JFreeChart chart = ChartFactory.createXYLineChart(metric, localization.getString("text.NFE"), localization.getString("text.value"), dataset, PlotOrientation.VERTICAL, false, true, false); final XYPlot plot = chart.getXYPlot(); //setup the series renderer if (controller.getShowIndividualTraces()) { XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer(true, false); for (int i = 0; i < dataset.getSeriesCount(); i++) { Paint paint = frame.getPaintHelper().get(dataset.getSeriesKey(i)); renderer.setSeriesStroke(i, new BasicStroke(1f, 1, 1)); renderer.setSeriesPaint(i, paint); } plot.setRenderer(renderer); } else { DeviationRenderer renderer = new DeviationRenderer(true, false); for (int i = 0; i < dataset.getSeriesCount(); i++) { Paint paint = frame.getPaintHelper().get(dataset.getSeriesKey(i)); renderer.setSeriesStroke(i, new BasicStroke(3f, 1, 1)); renderer.setSeriesPaint(i, paint); renderer.setSeriesFillPaint(i, paint); } plot.setRenderer(renderer); } //create the legend final LegendItemCollection items = plot.getLegendItems(); Iterator<?> iterator = items.iterator(); Set<ResultKey> uniqueKeys = new HashSet<ResultKey>(); while (iterator.hasNext()) { LegendItem item = (LegendItem) iterator.next(); if (uniqueKeys.contains(item.getSeriesKey())) { iterator.remove(); } else { uniqueKeys.add((ResultKey) item.getSeriesKey()); } } LegendItemSource source = new LegendItemSource() { @Override public LegendItemCollection getLegendItems() { return items; } }; LegendTitle legend = new LegendTitle(source); legend.setMargin(new RectangleInsets(1.0, 1.0, 1.0, 1.0)); legend.setFrame(new LineBorder()); legend.setBackgroundPaint(Color.WHITE); legend.setPosition(RectangleEdge.BOTTOM); chart.addLegend(legend); //scale the axes final NumberAxis domainAxis = new NumberAxis(); domainAxis.setAutoRange(true); plot.setDomainAxis(domainAxis); //add overlay if (controller.getShowLastTrace() && !controller.getShowIndividualTraces() && (controller.getLastAccumulator() != null) && controller.getLastAccumulator().keySet().contains(metric)) { DefaultTableXYDataset dataset2 = new DefaultTableXYDataset(); XYSeries series = new XYSeries(localization.getString("text.last"), false, false); for (int i = 0; i < controller.getLastAccumulator().size(metric); i++) { series.add((Number) controller.getLastAccumulator().get("NFE", i), (Number) controller.getLastAccumulator().get(metric, i)); } dataset2.addSeries(series); XYLineAndShapeRenderer renderer2 = new XYLineAndShapeRenderer(true, false); renderer2.setSeriesStroke(0, new BasicStroke(1f, 1, 1)); renderer2.setSeriesPaint(0, Color.BLACK); plot.setDataset(1, dataset2); plot.setRenderer(1, renderer2); plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD); } //update the chart in the GUI removeAll(); add(new ChartPanel(chart), BorderLayout.CENTER); revalidate(); repaint(); } }