| 1 | package de.uka.ipd.sdq.sensorframework.visualisation.jfreechartvisualisation; |
| 2 | |
| 3 | import java.text.DecimalFormat; |
| 4 | import java.util.Collection; |
| 5 | |
| 6 | import org.eclipse.jface.action.MenuManager; |
| 7 | import org.eclipse.swt.widgets.Composite; |
| 8 | import org.jfree.chart.ChartFactory; |
| 9 | import org.jfree.chart.axis.NumberAxis; |
| 10 | import org.jfree.chart.axis.NumberTickUnit; |
| 11 | import org.jfree.chart.axis.TickUnitSource; |
| 12 | import org.jfree.chart.axis.TickUnits; |
| 13 | import org.jfree.chart.plot.PlotOrientation; |
| 14 | import org.jfree.data.xy.DefaultTableXYDataset; |
| 15 | import org.jfree.data.xy.XYSeries; |
| 16 | |
| 17 | import de.uka.ipd.sdq.codegen.simudatavisualisation.datatypes.TimeSeries; |
| 18 | import de.uka.ipd.sdq.codegen.simudatavisualisation.datatypes.TimeSeriesEntity; |
| 19 | |
| 20 | public class JFreeChartTimeSeriesViewer extends AbstractJFreeChartChart<TimeSeries> implements ISeriesExporter { |
| 21 | |
| 22 | DefaultTableXYDataset dataset = new DefaultTableXYDataset(); |
| 23 | |
| 24 | public JFreeChartTimeSeriesViewer(Composite parent, int style) { |
| 25 | super(parent, style); |
| 26 | } |
| 27 | |
| 28 | @Override |
| 29 | protected void initializeContextMenu(MenuManager menu_manager) { |
| 30 | super.initializeContextMenu(menu_manager); |
| 31 | menu_manager.add(new ExportCSV(this)); |
| 32 | menu_manager.add(new CopyClipboardAsR(this)); |
| 33 | } |
| 34 | |
| 35 | protected void initChart() { |
| 36 | chart = ChartFactory.createScatterPlot("Time Series", "Number of Measurement", "Time", dataset, PlotOrientation.VERTICAL, true, true, true); |
| 37 | NumberAxis yAxis = (NumberAxis) chart.getXYPlot().getRangeAxis(); |
| 38 | yAxis.setAutoRangeIncludesZero(false); |
| 39 | // adjusted to work with values with an accuracy of tick units (y-Axis labels) of up to 1e-16. |
| 40 | yAxis.setAutoRangeMinimumSize(1e-16); |
| 41 | yAxis.setStandardTickUnits(createAdvancedTickUnits()); |
| 42 | } |
| 43 | |
| 44 | /**Creates an advanced version of tick units. |
| 45 | * Works with up to 16 digits. Necessary to enable ticks by the auto range feature for values like 1/3. |
| 46 | * @return |
| 47 | */ |
| 48 | private static final TickUnitSource createAdvancedTickUnits() { |
| 49 | TickUnits tu = (TickUnits) NumberAxis.createStandardTickUnits(); |
| 50 | DecimalFormat df16 = new DecimalFormat("0.0000000000000000"); |
| 51 | DecimalFormat df15 = new DecimalFormat("0.000000000000000"); |
| 52 | DecimalFormat df14 = new DecimalFormat("0.00000000000000"); |
| 53 | DecimalFormat df13 = new DecimalFormat("0.0000000000000"); |
| 54 | DecimalFormat df12 = new DecimalFormat("0.000000000000"); |
| 55 | DecimalFormat df11 = new DecimalFormat("0.00000000000"); |
| 56 | DecimalFormat df10 = new DecimalFormat("0.0000000000"); |
| 57 | DecimalFormat df9 = new DecimalFormat("0.000000000"); |
| 58 | DecimalFormat df8 = new DecimalFormat("0.00000000"); |
| 59 | |
| 60 | tu.add(new NumberTickUnit(0.0000000000000001, df16)); |
| 61 | tu.add(new NumberTickUnit(0.000000000000001, df15)); |
| 62 | tu.add(new NumberTickUnit(0.00000000000001, df14)); |
| 63 | tu.add(new NumberTickUnit(0.0000000000001, df13)); |
| 64 | tu.add(new NumberTickUnit(0.000000000001, df12)); |
| 65 | tu.add(new NumberTickUnit(0.00000000001, df11)); |
| 66 | tu.add(new NumberTickUnit(0.0000000001, df10)); |
| 67 | tu.add(new NumberTickUnit(0.000000001, df9)); |
| 68 | tu.add(new NumberTickUnit(0.00000001, df8)); |
| 69 | |
| 70 | tu.add(new NumberTickUnit(0.0000000000000005, df16)); |
| 71 | tu.add(new NumberTickUnit(0.000000000000005, df15)); |
| 72 | tu.add(new NumberTickUnit(0.00000000000005, df14)); |
| 73 | tu.add(new NumberTickUnit(0.0000000000005, df13)); |
| 74 | tu.add(new NumberTickUnit(0.000000000005, df12)); |
| 75 | tu.add(new NumberTickUnit(0.00000000005, df11)); |
| 76 | tu.add(new NumberTickUnit(0.0000000005, df10)); |
| 77 | tu.add(new NumberTickUnit(0.000000005, df9)); |
| 78 | tu.add(new NumberTickUnit(0.00000005, df8)); |
| 79 | |
| 80 | tu.add(new NumberTickUnit(0.0000000000000025, df16)); |
| 81 | tu.add(new NumberTickUnit(0.000000000000025, df15)); |
| 82 | tu.add(new NumberTickUnit(0.00000000000025, df14)); |
| 83 | tu.add(new NumberTickUnit(0.0000000000025, df13)); |
| 84 | tu.add(new NumberTickUnit(0.000000000025, df12)); |
| 85 | tu.add(new NumberTickUnit(0.00000000025, df11)); |
| 86 | tu.add(new NumberTickUnit(0.0000000025, df10)); |
| 87 | tu.add(new NumberTickUnit(0.000000025, df9)); |
| 88 | |
| 89 | return tu; |
| 90 | } |
| 91 | |
| 92 | public void setData(Collection<TimeSeries> data){ |
| 93 | dataset.removeAllSeries(); |
| 94 | |
| 95 | for (TimeSeries timeSeries : data) |
| 96 | dataset.addSeries(getSeries(timeSeries)); |
| 97 | initChart(); |
| 98 | this.setChart(chart); |
| 99 | this.forceRedraw(); |
| 100 | } |
| 101 | |
| 102 | private XYSeries getSeries(TimeSeries ts) { |
| 103 | XYSeries series = new XYSeries(ts.getLabel(),true, false); |
| 104 | // patched to show ascending number of measurements, starting by 1 |
| 105 | long number = 1; |
| 106 | for (TimeSeriesEntity te : ts.getValues()) { |
| 107 | //series.add(te.getXValue(), te.getYValue()); |
| 108 | series.add(number++, te.getYValue()); |
| 109 | } |
| 110 | return series; |
| 111 | } |
| 112 | |
| 113 | public XYSeries getSeries() { |
| 114 | return dataset.getSeries(0); |
| 115 | } |
| 116 | |
| 117 | } |