Package eas.plugins.standard.visualization.chartPlugin

Source Code of eas.plugins.standard.visualization.chartPlugin.AllroundChartPlugin

/*
* File name:        ChartPlugin.java (package eas.plugins.standard)
* Author(s):        Lukas König
* Java version:     6.0
* Generation date:  15.12.2011 (16:04:08)
*
* (c) This file and the EAS (Easy Agent Simulation) framework containing it
* is protected by Creative Commons by-nc-sa license. Any altered or
* further developed versions of this file have to meet the agreements
* stated by the license conditions.
*
* In a nutshell
* -------------
* You are free:
* - to Share -- to copy, distribute and transmit the work
* - to Remix -- to adapt the work
*
* Under the following conditions:
* - Attribution -- You must attribute the work in the manner specified by the
*   author or licensor (but not in any way that suggests that they endorse
*   you or your use of the work).
* - Noncommercial -- You may not use this work for commercial purposes.
* - Share Alike -- If you alter, transform, or build upon this work, you may
*   distribute the resulting work only under the same or a similar license to
*   this one.
*
* + Detailed license conditions (Germany):
*   http://creativecommons.org/licenses/by-nc-sa/3.0/de/
* + Detailed license conditions (unported):
*   http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en
*
* This header must be placed in the beginning of any version of this file.
*/

package eas.plugins.standard.visualization.chartPlugin;

import java.awt.BorderLayout;
import java.awt.Font;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.swing.JFrame;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.chart.renderer.xy.XYSplineRenderer;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.statistics.HistogramBin;
import org.jfree.data.statistics.HistogramDataset;
import org.jfree.data.xy.XYDataItem;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.RefineryUtilities;

import com.lowagie.text.pdf.DefaultFontMapper;

import eas.miscellaneous.StaticMethods;
import eas.plugins.AbstractDefaultPlugin;
import eas.simulation.Wink;
import eas.simulation.event.EASEvent;
import eas.simulation.event.EventFilter;
import eas.simulation.standardEnvironments.AbstractEnvironment;
import eas.startSetup.ParCollection;
import eas.startSetup.SingleParameter;
import eas.startSetup.parameterDatatypes.Datatypes;

/**
* @author Lukas König
*/
public class AllroundChartPlugin extends AbstractDefaultPlugin<AbstractEnvironment<?>> {

    private static final long serialVersionUID = -8043309759341640567L;
    private HashMap<String, XYSeriesCollection> lineDataSet = new HashMap<String, XYSeriesCollection>();
    private HashMap<String, JFrame> lineChartFrameList = new HashMap<String, JFrame>();

    private HashMap<String, HistogramDataset> histogramDataSet = new HashMap<String, HistogramDataset>();
    private HashMap<String, JFrame> histogramFrameList = new HashMap<String, JFrame>();

    private HashMap<String, DefaultPieDataset> pieDataSet = new HashMap<String, DefaultPieDataset>();
    private HashMap<String, JFrame> pieFrameList = new HashMap<String, JFrame>();
   
    // This list contains ALL charts (not just line charts)!
    private HashMap<String, JFreeChart> chartList = new HashMap<String, JFreeChart>();

    /**
     *
     * @param series
     * @param seriesName
     * @return  Positive number for position of the found item, negative if
     *          item was not found.
     */
    private int containsSeriesLinechart(List<?> series, String seriesName) {
        for (int i = 0; i < series.size(); i++) {
            if (((XYSeries) series.get(i)).getKey().equals(seriesName)) {
                return i;
            }
        }

        return -1;
    }
   
    private int containsSeriesHistogram(HistogramDataset dataset, String seriesName) {
        for (int i = 0; i < dataset.getSeriesCount(); i++) {
            if (dataset.getSeriesKey(i).equals(seriesName)) {
                return i;
            }
        }
       
        return -1;
    }
   
  @Override
  public List<SingleParameter> getParameters() {
      LinkedList<SingleParameter> list = new LinkedList<SingleParameter>();
     
      list.add(new SingleParameter(
              "showLiveCharts?",
              Datatypes.BOOLEAN,
              true,
              "If the charts are visualized in a frame during simulation. If not, charts are accessible by sending ChartEventStoreAsPDF events.",
              this.id().toUpperCase()));
     
    return list;
  }

  @Override
  public String id() {
    return AbstractDefaultPlugin.ALLROUND_PLUGIN_PREFIX + "-chartplugin";
  }
 
    @Override
  public void runBeforeSimulation(final AbstractEnvironment<?> env, final ParCollection params) {
      params.log(StaticMethods.LOG_INFO, "\n"
              + "***********************************************************************\n"
              + "This is '" + this.id().toUpperCase() + "':\n"
              + "To create a chart or add data to an existing chart "
              + "simply broadcast a 'ChartEvent' to the SimulationTime, e.g.,\n"
              + "*environment*.getSimTime().broadcastEvent(new ChartEvent(*...*));\n"
              + "To store an existing chart as PDF you can broadcast a 'ChartEventStoreAsPDF', e.g.,\n"
              + "*environment*.getSimTime().broadcastEvent(new ChartEventStoreAsPDF(*chartName*, *File*));\n"
              + "***********************************************************************\n");
     
      env.getSimTime().requestEvents(this, new EventFilter() {
            private static final long serialVersionUID = 3719917006278896507L;

            @Override
            public boolean isAcceptable(EASEvent event) {
                return event.getClass().isAssignableFrom(ChartEvent.class);
            }
        });
  }

  @Override
  public void runAfterSimulation(AbstractEnvironment<?> env, ParCollection params) {}
 
    @Override
    public void runDuringSimulation(AbstractEnvironment<?> env, Wink currentSimTime,
            ParCollection params) {
    }

    private void resetVisibilityOfFrames() {
        for (JFrame frame : this.lineChartFrameList.values()) {
            frame.setVisible(true);
        }
        for (JFrame frame : this.pieFrameList.values()) {
            frame.setVisible(true);
        }
        for (JFrame frame : this.histogramFrameList.values()) {
            frame.setVisible(true);
        }
    }
 
    private void handleChartEvent(ChartEvent event, Wink lastSimTime, ParCollection params) {
        JFrame frame = null;
       
        if (event.getChartType().equals(ChartEvent.LINE_CHART_NAME)) {
            addDataToLineChart(event, lastSimTime, params);
            frame = this.lineChartFrameList.get(event.getChartName());
        } else if (event.getChartType().equals(ChartEvent.HISTOGRAM_CHART_NAME)) {
            addDataToHistogramChart(event, params);
            frame = this.histogramFrameList.get(event.getChartName());
        } else if (event.getChartType().equals(ChartEvent.PIE_CHART_NAME)) {
          addDataToPieChart(event, params);
        } else if (event.getChartType().equals(ChartEvent.DELETE_CHART_NAME)) {
            removeChart(event);
            return;
        }

        // Set general chart frame settings.
        if (event.getChartDim() != null) {
            int x = (int) event.getChartDim().x;
            int y = (int) event.getChartDim().y;
            if (frame.getSize().width != x || frame.getSize().height != y) {
                frame.setSize(x, y);
            }
        }
       
        if (event.getChartPos() != null) {
            int x = (int) event.getChartPos().x;
            int y = (int) event.getChartPos().y;
            if (frame.getLocation().x != x || frame.getLocation().y != y) {
                frame.setLocation(x, y);
            }
        }
    }

  private void addDataToPieChart(ChartEvent event, ParCollection params) {
    DefaultPieDataset dataset = this.pieDataSet.get(event.getChartName());
        JFreeChart chart = this.chartList.get(event.getChartName());
       
        if (dataset == null) {
            dataset = new DefaultPieDataset();
           
            if (event.isPaintChart3D()) {
                chart = ChartFactory.createPieChart3D(event.getChartName(), dataset, true, true, true);
            } else {
                chart = ChartFactory.createPieChart(event.getChartName(), dataset, true, true, true);
            }
           
            createFrame(event.getChartName(), event.getChartType(), params, chart);
           
            this.pieDataSet.put(event.getChartName(), dataset);
            this.chartList.put(event.getChartName(), chart);

            if (event.getSortOrderPieChartByKey() != null) {
                dataset.sortByKeys(event.getSortOrderPieChartByKey());
            }
            if (event.getSortOrderPieChartByValue() != null) {
                dataset.sortByKeys(event.getSortOrderPieChartByValue());
            }
           
            PiePlot plot = (PiePlot) chart.getPlot();
           
            if (event.isShowPercentages()) {
                plot.setLabelGenerator(new StandardPieSectionLabelGenerator("{0} = {2}"));
            } else {
                plot.setLabelGenerator(new StandardPieSectionLabelGenerator("{0} = {1}"));
            }
        }

        for (int i = 0; i < event.getPieData().length; i++) {
            dataset.setValue(event.getPieDataNames()[i], event.getPieData()[i]);
        }
       
        // Exploded segments.
        PiePlot plot = (PiePlot) chart.getPlot();
       
        for (String key : event.getExplodedSegmentsPie().keySet()) {
            plot.setExplodePercent(key, event.getExplodedSegmentsPie().get(key));
        }
       
        // Segment paints.
        for (String key : event.getPaintSegments().keySet()) {
            plot.setSectionPaint(key, event.getPaintSegments().get(key));
        }
  }

  private void removeChart(ChartEvent event) {
        try {this.chartList.remove(event.getChartName());} catch(Exception e) {}
        try {this.histogramDataSet.remove(event.getChartName());} catch(Exception e) {}
        try {this.lineDataSet.remove(event.getChartName());} catch(Exception e) {}
        try {this.histogramFrameList.get(event.getChartName()).dispose();} catch(Exception e) {}
        try {this.lineChartFrameList.get(event.getChartName()).dispose();} catch(Exception e) {}
        try {this.histogramFrameList.remove(event.getChartName());} catch(Exception e) {}
        try {this.lineChartFrameList.remove(event.getChartName());} catch(Exception e) {}
        try {this.pieDataSet.remove(event.getChartName());} catch (Exception e) {}
        try {this.pieFrameList.remove(event.getChartName());} catch (Exception e) {}
    }

    private void addDataToHistogramChart(ChartEvent event, ParCollection params) {
        // Histogram.
        HistogramDataset dataset = this.histogramDataSet.get(event.getChartName());
       
        JFreeChart chart = this.chartList.get(event.getChartName());
       
        if (dataset == null) {
            dataset = new HistogramDataset();
            dataset.setType(event.getHistType());
            dataset.addSeries(
                    event.getSeriesName(),
                    event.getHistogramValues(),
                    event.getHistogramBins(),
                    event.getHistogramMin(),
                    event.getHistogramMax());
           
            chart = ChartFactory.createHistogram(
                    event.getChartName(),
                    event.getxAxisLabel(),
                    event.getyAxisLabel(),
                    dataset,
                    PlotOrientation.VERTICAL,
                    true,
                    true,
                    true);
           
            createFrame(event.getChartName(), event.getChartType(), params, chart);
           
            this.histogramDataSet.put(event.getChartName(), dataset);
            this.chartList.put(event.getChartName(), chart);
        }

        if (!dataset.getType().equals(event.getHistType())) {
            dataset.setType(event.getHistType());
        }

        if (this.containsSeriesHistogram(dataset, event.getSeriesName()) >= 0) {
            /* Change existing series. This is done by awful reflections.
             */
           
            try {
                Field f = dataset.getClass().getDeclaredField("list"); //NoSuchFieldException
                f.setAccessible(true);
                @SuppressWarnings("unchecked")
                List<Map<String, Object>> list = (List<Map<String, Object>>) f.get(dataset);
                List<Map<String, Object>> list2 = new LinkedList<Map<String,Object>>();
                Map<String, Object> removeMap = null;
               
                for (Map<String, Object> map : list) {
                    String key = (String) map.get("key");
                    if (key != null && key.equals(event.getSeriesName())) {
                        removeMap = map;
                    }
                }
               
                list2.addAll(list);
                list2.remove(removeMap);
                this.addSeries(
                        list2,
                        event.getSeriesName(),
                        event.getHistogramValues(),
                        event.getHistogramBins(),
                        event.getHistogramMin(),
                        event.getHistogramMax());
                f.set(dataset, list2);
            } catch (Exception e) {
            } finally {
                dataset.setType(event.getHistType());
            }
        } else {
            // Add new series.
            dataset.addSeries(
                    event.getSeriesName(),
                    event.getHistogramValues(),
                    event.getHistogramBins(),
                    event.getHistogramMin(),
                    event.getHistogramMax());
            dataset.setType(event.getHistType());
        }
    }

    private void addDataToLineChart(ChartEvent event, Wink lastSimTime, ParCollection params) {
        // Line Chart.
        XYSeriesCollection dataset = this.lineDataSet.get(event.getChartName());
        XYItemRenderer renderer;
        XYPlot plot;
       
        if (dataset == null) {
            NumberAxis domain = new NumberAxis(event.getxAxisLabel());
            NumberAxis range = new NumberAxis(event.getyAxisLabel());
           
            if (event.isDrawSmoothSplinesInLineCharts()) {
                renderer = new XYSplineRenderer();
            } else {
                renderer = new XYLineAndShapeRenderer(event.isDrawLinesInLineCharts(), event.isDrawSymbolsInLineCharts());
            }
           
            dataset = new XYSeriesCollection();
            plot = new XYPlot(dataset, domain, range, renderer);
            domain.setAutoRange(true);
            domain.setLowerBound(lastSimTime.getCurrentTime());
            domain.setTickLabelsVisible(true);
            range.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
            JFreeChart chart = new JFreeChart(
                    event.getChartName(),
                    new Font("SansSerif", Font.BOLD, 24),
                    plot,
                    true);
           
            createFrame(event.getChartName(), event.getChartType(), params, chart);
           
            this.lineDataSet.put(event.getChartName(), dataset);
            this.chartList.put(event.getChartName(), chart);
        } else {
            plot = chartList.get(event.getChartName()).getXYPlot();
        }
       
        XYSeries series;
        int foundSeriesNum = this.containsSeriesLinechart(dataset.getSeries(), event.getSeriesName());
       
        if (foundSeriesNum < 0) {
            dataset.addSeries(new XYSeries(event.getSeriesName()));
            foundSeriesNum = this.containsSeriesLinechart(dataset.getSeries(), event.getSeriesName());
        }
       
        if (event.getLineStroke() != null) {
            plot.getRenderer().setSeriesStroke(foundSeriesNum, event.getLineStroke());
        }
        if (event.getLineColor() != null) {
            plot.getRenderer().setSeriesPaint(foundSeriesNum, event.getLineColor());
        }

        plot.getDomainAxis().setUpperBound(lastSimTime.getCurrentTime());
        series = dataset.getSeries(event.getSeriesName());

        if (event.getXValue() == ChartEvent.X_VALUE_NOT_SPECIFIED) {
            series.add(new XYDataItem(lastSimTime.getCurrentTime(), event.getValue()));
        } else {
            series.add(new XYDataItem(event.getXValue(), event.getValue()));
        }
    }

  private void createFrame(
      String chartName,
      String eventType,
      ParCollection params,
      JFreeChart chart) {
    ChartPanel chartPanel = new ChartPanel(chart);
    JFrame frame = new JFrame(eventType + " [" + chartName + "]");
    frame.getContentPane().add(chartPanel, BorderLayout.CENTER);
    frame.setBounds(200, 120, 600, 280);
    if (params.getParValueBoolean("showLiveCharts?")) {
        frame.setVisible(true);
        RefineryUtilities.centerFrameOnScreen(frame);
    }
    this.lineChartFrameList.put(chartName, frame);
  }
   
    private void handleChartEventStoreAsPDF(ChartEventStoreAsPDF event) {
        File file = event.getFile();
        try {
            StaticMethods.saveChartAsPDF(file, chartList.get(event.getChartNam()), 400, 300, new DefaultFontMapper());
        } catch (IOException e) {
            throw new RuntimeException(this.id().toUpperCase() + " - PDF not stored '" + event.getFile() + "'");
        }
    }

  @Override
  public void handleEvent(
          EASEvent e,
          AbstractEnvironment<?> env,
          Wink lastSimTime,
          ParCollection params) {
      try {
          ChartEvent event = (ChartEvent) e;
          this.handleChartEvent(event, lastSimTime, params);
        } catch (Exception e2) {}
     
        try {
            ChartEventStoreAsPDF event = (ChartEventStoreAsPDF) e;
            this.handleChartEventStoreAsPDF(event);
        } catch (Exception e2) {}
  }
 
  @Override
    public List<String> getRequiredPlugins() {return null;}

    @Override
    public List<String> getSupportedPlugins() {
        return null;
    }

    /**
     * This method comes directly from
     * {@link org.jfree.data.statistics.HistogramDataset}.
     *
     * @param liste    The list to add the series to.
     */
    private void addSeries(List<Map<String, Object>> liste, Comparable<?> key, double[] values, int bins,
            double minimum, double maximum) {

        if (key == null) {
            throw new IllegalArgumentException("Null 'key' argument.");
        }
        if (values == null) {
            throw new IllegalArgumentException("Null 'values' argument.");
        } else if (bins < 1) {
            throw new IllegalArgumentException(
                    "The 'bins' value must be at least 1.");
        }
        double binWidth = (maximum - minimum) / bins;

        double lower = minimum;
        double upper;
        List<HistogramBin> binList = new ArrayList<HistogramBin>(bins);
        for (int i = 0; i < bins; i++) {
            HistogramBin bin;
            // make sure bins[bins.length]'s upper boundary ends at maximum
            // to avoid the rounding issue. the bins[0] lower boundary is
            // guaranteed start from min
            if (i == bins - 1) {
                bin = new HistogramBin(lower, maximum);
            } else {
                upper = minimum + (i + 1) * binWidth;
                bin = new HistogramBin(lower, upper);
                lower = upper;
            }
            binList.add(bin);
        }
        // fill the bins
        for (int i = 0; i < values.length; i++) {
            int binIndex = bins - 1;
            if (values[i] < maximum) {
                double fraction = (values[i] - minimum) / (maximum - minimum);
                if (fraction < 0.0) {
                    fraction = 0.0;
                }
                binIndex = (int) (fraction * bins);
                // rounding could result in binIndex being equal to bins
                // which will cause an IndexOutOfBoundsException - see bug
                // report 1553088
                if (binIndex >= bins) {
                    binIndex = bins - 1;
                }
            }
            HistogramBin bin = binList.get(binIndex);
            bin.incrementCount();
        }
        // generic map for each series
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("key", key);
        map.put("bins", binList);
        map.put("values.length", new Integer(values.length));
        map.put("bin width", new Double(binWidth));
        liste.add(map);
    }

    @Override
    public void onSimulationResumed(AbstractEnvironment<?> env, Wink resumeTime,
            ParCollection params) {
        resetVisibilityOfFrames();
    }
}
TOP

Related Classes of eas.plugins.standard.visualization.chartPlugin.AllroundChartPlugin

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.