From d7f7c776e60749d95ee0ce400b1958db5f7966fd Mon Sep 17 00:00:00 2001 From: Alexandre Gobbo Date: Tue, 12 Aug 2014 16:40:57 +0200 Subject: [PATCH] Version 2: Abstraction of graphs & new implementations: JZY3D, JavaFX, JFreeChart --- ch.psi.plot/pom.xml | 40 +- .../src/main/java/ch/psi/plot/Axis.java | 72 + .../src/main/java/ch/psi/plot/LinePlot.java | 10 + .../main/java/ch/psi/plot/LinePlotBase.java | 155 ++ .../main/java/ch/psi/plot/LinePlotSeries.java | 180 +++ .../src/main/java/ch/psi/plot/MatrixPlot.java | 10 + .../main/java/ch/psi/plot/MatrixPlotBase.java | 160 ++ .../java/ch/psi/plot/MatrixPlotSeries.java | 160 ++ .../src/main/java/ch/psi/plot/Plot.java | 97 +- .../src/main/java/ch/psi/plot/PlotBase.java | 333 ++++ .../src/main/java/ch/psi/plot/PlotSeries.java | 54 + .../java/ch/psi/plot/javafx/LinePlot.java | 625 ++++++++ .../java/ch/psi/plot/jfree/ColorManager.java | 73 + .../{xy/tools => jfree}/CrossAnnotation.java | 24 +- .../main/java/ch/psi/plot/jfree/LinePlot.java | 544 +++++++ .../ch/psi/plot/jfree/ManualScaleDialog.java | 169 ++ .../java/ch/psi/plot/jfree/MatrixPlot.java | 490 ++++++ .../java/ch/psi/plot/jlchart/LinePlot.java | 242 +++ .../java/ch/psi/plot/jzy3d/MatrixPlot.java | 856 +++++++++++ .../src/main/java/ch/psi/plot/utils/IO.java | 60 + .../ch/psi/plot/utils/MonitoredPanel.java | 41 + .../java/ch/psi/plot/utils/SwingUtils.java | 69 + .../main/java/ch/psi/plot/xy/LinePlot.java | 472 ------ .../ch/psi/plot/xy/XYSeriesCollectionP.java | 626 -------- .../main/java/ch/psi/plot/xy/XYSeriesP.java | 454 ------ .../java/ch/psi/plot/xy/tools/Average.java | 61 - .../java/ch/psi/plot/xy/tools/Derivative.java | 80 - .../java/ch/psi/plot/xy/tools/Integral.java | 65 - .../java/ch/psi/plot/xy/tools/Maximum.java | 51 - .../java/ch/psi/plot/xy/tools/Minimum.java | 51 - .../java/ch/psi/plot/xyz/ColorManager.java | 86 -- .../ch/psi/plot/xyz/DynamicXYZDataset.java | 245 --- .../psi/plot/xyz/DynamicXYZDatasetList.java | 374 ----- .../psi/plot/xyz/DynamicXYZDatasetNumber.java | 378 ----- .../ch/psi/plot/xyz/ManualScaleDialog.java | 185 --- .../main/java/ch/psi/plot/xyz/MatrixPlot.java | 379 ----- .../java/ch/psi/plot/xyz/MatrixPlot2.java | 352 ----- .../java/ch/psi/plot/xyz/MatrixPlotData.java | 191 --- .../java/ch/psi/plot/xyz/XYZDatasetUtil.java | 71 - .../META-INF/services/ch.psi.plot.LinePlot | 1 + ch.psi.plot/src/test/java/LinePlotTest.java | 87 ++ ch.psi.plot/src/test/java/MatrixPlotTest.java | 112 ++ ch.psi.plot/src/test/java/TestJZY.java | 47 + .../java/ch/psi/plot/xy/LinePlotTest.java | 559 +++---- .../java/ch/psi/plot/xyz/MatrixPlot2Test.java | 212 --- .../java/ch/psi/plot/xyz/MatrixPlotTest.java | 211 --- .../psi/plot/xyz/generator/DataGenerator.java | 10 +- .../psi/plot/xyz/generator/XYZGenerator.java | 4 +- ch.psi.plot/tmp/done/Average.java | 76 - ch.psi.plot/tmp/done/CrossDrawer.java | 44 - ch.psi.plot/tmp/done/Derivatives.java | 82 - ch.psi.plot/tmp/done/Extrema.java | 56 - ch.psi.plot/tmp/done/GraphChooserFrame.form | 150 -- .../tmp/done/GraphPropertiesPanel.form | 112 -- ch.psi.plot/tmp/done/ImagePanel.java | 29 - ch.psi.plot/tmp/done/Integral.java | 60 - ch.psi.plot/tmp/done/LinePlot.java | 985 ------------ ch.psi.plot/tmp/done/LinePlotData.java | 46 - ch.psi.plot/tmp/done/LinePlotMetadata.java | 48 - ch.psi.plot/tmp/done/Maxs.java | 28 - ch.psi.plot/tmp/done/MenuLoader.java | 148 -- ch.psi.plot/tmp/done/MenuNodeType.java | 131 -- ch.psi.plot/tmp/done/MenuTreeType.java | 74 - ch.psi.plot/tmp/done/Mins.java | 28 - ch.psi.plot/tmp/done/ObjectFactory.java | 96 -- ch.psi.plot/tmp/done/PlugableUtil.java | 6 - ch.psi.plot/tmp/done/PlugableUtilXY.java | 8 - .../tmp/done/PluginExecutionException.java | 16 - ch.psi.plot/tmp/done/UtilityClassType.java | 65 - ch.psi.plot/tmp/done/XYPoint.java | 70 - ch.psi.plot/tmp/done/menuconfig.xsd | 28 - ch.psi.plot/tmp/done/menuconfigxy.xml | 36 - ch.psi.plot/tmp/done/menuconfigxyz.xml | 33 - .../tmp/util/CoordinateTransformer.java | 56 - ch.psi.plot/tmp/xy/GraphChooserFrame.java | 193 --- ch.psi.plot/tmp/xy/GraphPropertiesPanel.java | 358 ----- ch.psi.plot/tmp/xy/Interval.java | 70 - ch.psi.plot/tmp/xy/Marker.java | 97 -- ch.psi.plot/tmp/xyz/ExtremaFinder.java | 140 -- .../tmp/xyz/IndexOutOfBoundListener.java | 10 - ch.psi.plot/tmp/xyz/JFreeMatrixPlot.java | 1354 ----------------- ch.psi.plot/tmp/xyz/JFreeMatrixPlotData.java | 130 -- .../tmp/xyz/JFreeMatrixPlotMetadata.java | 198 --- ch.psi.plot/tmp/xyz/MatrixPlotData.java | 230 --- ch.psi.plot/tmp/xyz/PixelPlotData.java | 216 --- ch.psi.plot/tmp/xyz/Region.java | 109 -- ch.psi.plot/tmp/xyz/SectionPlotData.java | 75 - ch.psi.plot/tmp/xyz/StaticMatrixPlotter.java | 55 - .../tmp/xyz/StaticMatrixPlotterTest.java | 39 - ch.psi.plot/tmp/xyz/SurfacePlot.java | 122 -- ch.psi.plot/tmp/xyz/SurfacePlotData.java | 87 -- ch.psi.plot/tmp/xyz/SurfacePlotMetadata.java | 176 --- ch.psi.plot/tmp/xyz/plugable/BaryCenter.java | 103 -- ch.psi.plot/tmp/xyz/plugable/Filter.java | 41 - .../xyz/plugable/FilterTransformation.java | 79 - .../xyz/plugable/FourierTransformation.java | 106 -- ch.psi.plot/tmp/xyz/plugable/GaussFilter.java | 71 - .../tmp/xyz/plugable/GaussFilterMatrix.java | 61 - ch.psi.plot/tmp/xyz/plugable/Gradient.java | 113 -- .../tmp/xyz/plugable/GradientPlot.java | 62 - .../tmp/xyz/plugable/IntegratedXValues.java | 133 -- .../tmp/xyz/plugable/IntegratedYValues.java | 127 -- .../tmp/xyz/plugable/LaplaceFilter.java | 86 -- ch.psi.plot/tmp/xyz/plugable/Max.java | 39 - ch.psi.plot/tmp/xyz/plugable/Median.java | 92 -- ch.psi.plot/tmp/xyz/plugable/Min.java | 40 - .../tmp/xyz/plugable/PlugableUtilXYZ.java | 9 - 107 files changed, 4946 insertions(+), 12214 deletions(-) create mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/Axis.java create mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/LinePlot.java create mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/LinePlotBase.java create mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/LinePlotSeries.java create mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/MatrixPlot.java create mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/MatrixPlotBase.java create mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/MatrixPlotSeries.java create mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/PlotBase.java create mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/PlotSeries.java create mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/javafx/LinePlot.java create mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/jfree/ColorManager.java rename ch.psi.plot/src/main/java/ch/psi/plot/{xy/tools => jfree}/CrossAnnotation.java (74%) create mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/jfree/LinePlot.java create mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/jfree/ManualScaleDialog.java create mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/jfree/MatrixPlot.java create mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/jlchart/LinePlot.java create mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/jzy3d/MatrixPlot.java create mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/utils/IO.java create mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/utils/MonitoredPanel.java create mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/utils/SwingUtils.java delete mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/xy/LinePlot.java delete mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/xy/XYSeriesCollectionP.java delete mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/xy/XYSeriesP.java delete mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/xy/tools/Average.java delete mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/xy/tools/Derivative.java delete mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/xy/tools/Integral.java delete mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/xy/tools/Maximum.java delete mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/xy/tools/Minimum.java delete mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/xyz/ColorManager.java delete mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/xyz/DynamicXYZDataset.java delete mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/xyz/DynamicXYZDatasetList.java delete mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/xyz/DynamicXYZDatasetNumber.java delete mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/xyz/ManualScaleDialog.java delete mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/xyz/MatrixPlot.java delete mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/xyz/MatrixPlot2.java delete mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/xyz/MatrixPlotData.java delete mode 100644 ch.psi.plot/src/main/java/ch/psi/plot/xyz/XYZDatasetUtil.java create mode 100644 ch.psi.plot/src/main/resources/META-INF/services/ch.psi.plot.LinePlot create mode 100644 ch.psi.plot/src/test/java/LinePlotTest.java create mode 100644 ch.psi.plot/src/test/java/MatrixPlotTest.java create mode 100644 ch.psi.plot/src/test/java/TestJZY.java delete mode 100644 ch.psi.plot/src/test/java/ch/psi/plot/xyz/MatrixPlot2Test.java delete mode 100644 ch.psi.plot/src/test/java/ch/psi/plot/xyz/MatrixPlotTest.java delete mode 100644 ch.psi.plot/tmp/done/Average.java delete mode 100644 ch.psi.plot/tmp/done/CrossDrawer.java delete mode 100644 ch.psi.plot/tmp/done/Derivatives.java delete mode 100644 ch.psi.plot/tmp/done/Extrema.java delete mode 100644 ch.psi.plot/tmp/done/GraphChooserFrame.form delete mode 100644 ch.psi.plot/tmp/done/GraphPropertiesPanel.form delete mode 100644 ch.psi.plot/tmp/done/ImagePanel.java delete mode 100644 ch.psi.plot/tmp/done/Integral.java delete mode 100644 ch.psi.plot/tmp/done/LinePlot.java delete mode 100644 ch.psi.plot/tmp/done/LinePlotData.java delete mode 100644 ch.psi.plot/tmp/done/LinePlotMetadata.java delete mode 100644 ch.psi.plot/tmp/done/Maxs.java delete mode 100644 ch.psi.plot/tmp/done/MenuLoader.java delete mode 100644 ch.psi.plot/tmp/done/MenuNodeType.java delete mode 100644 ch.psi.plot/tmp/done/MenuTreeType.java delete mode 100644 ch.psi.plot/tmp/done/Mins.java delete mode 100644 ch.psi.plot/tmp/done/ObjectFactory.java delete mode 100644 ch.psi.plot/tmp/done/PlugableUtil.java delete mode 100644 ch.psi.plot/tmp/done/PlugableUtilXY.java delete mode 100644 ch.psi.plot/tmp/done/PluginExecutionException.java delete mode 100644 ch.psi.plot/tmp/done/UtilityClassType.java delete mode 100644 ch.psi.plot/tmp/done/XYPoint.java delete mode 100644 ch.psi.plot/tmp/done/menuconfig.xsd delete mode 100644 ch.psi.plot/tmp/done/menuconfigxy.xml delete mode 100644 ch.psi.plot/tmp/done/menuconfigxyz.xml delete mode 100644 ch.psi.plot/tmp/util/CoordinateTransformer.java delete mode 100644 ch.psi.plot/tmp/xy/GraphChooserFrame.java delete mode 100644 ch.psi.plot/tmp/xy/GraphPropertiesPanel.java delete mode 100644 ch.psi.plot/tmp/xy/Interval.java delete mode 100644 ch.psi.plot/tmp/xy/Marker.java delete mode 100644 ch.psi.plot/tmp/xyz/ExtremaFinder.java delete mode 100644 ch.psi.plot/tmp/xyz/IndexOutOfBoundListener.java delete mode 100644 ch.psi.plot/tmp/xyz/JFreeMatrixPlot.java delete mode 100644 ch.psi.plot/tmp/xyz/JFreeMatrixPlotData.java delete mode 100644 ch.psi.plot/tmp/xyz/JFreeMatrixPlotMetadata.java delete mode 100644 ch.psi.plot/tmp/xyz/MatrixPlotData.java delete mode 100644 ch.psi.plot/tmp/xyz/PixelPlotData.java delete mode 100644 ch.psi.plot/tmp/xyz/Region.java delete mode 100644 ch.psi.plot/tmp/xyz/SectionPlotData.java delete mode 100644 ch.psi.plot/tmp/xyz/StaticMatrixPlotter.java delete mode 100644 ch.psi.plot/tmp/xyz/StaticMatrixPlotterTest.java delete mode 100644 ch.psi.plot/tmp/xyz/SurfacePlot.java delete mode 100644 ch.psi.plot/tmp/xyz/SurfacePlotData.java delete mode 100644 ch.psi.plot/tmp/xyz/SurfacePlotMetadata.java delete mode 100644 ch.psi.plot/tmp/xyz/plugable/BaryCenter.java delete mode 100644 ch.psi.plot/tmp/xyz/plugable/Filter.java delete mode 100644 ch.psi.plot/tmp/xyz/plugable/FilterTransformation.java delete mode 100644 ch.psi.plot/tmp/xyz/plugable/FourierTransformation.java delete mode 100644 ch.psi.plot/tmp/xyz/plugable/GaussFilter.java delete mode 100644 ch.psi.plot/tmp/xyz/plugable/GaussFilterMatrix.java delete mode 100644 ch.psi.plot/tmp/xyz/plugable/Gradient.java delete mode 100644 ch.psi.plot/tmp/xyz/plugable/GradientPlot.java delete mode 100644 ch.psi.plot/tmp/xyz/plugable/IntegratedXValues.java delete mode 100644 ch.psi.plot/tmp/xyz/plugable/IntegratedYValues.java delete mode 100644 ch.psi.plot/tmp/xyz/plugable/LaplaceFilter.java delete mode 100644 ch.psi.plot/tmp/xyz/plugable/Max.java delete mode 100644 ch.psi.plot/tmp/xyz/plugable/Median.java delete mode 100644 ch.psi.plot/tmp/xyz/plugable/Min.java delete mode 100644 ch.psi.plot/tmp/xyz/plugable/PlugableUtilXYZ.java diff --git a/ch.psi.plot/pom.xml b/ch.psi.plot/pom.xml index 419c6d3..4085da2 100644 --- a/ch.psi.plot/pom.xml +++ b/ch.psi.plot/pom.xml @@ -2,8 +2,14 @@ 4.0.0 ch.psi plot - 1.1.31 - + 2.0-SNAPSHOT + + + jzy3d-releases + Jzy3d Snapshots + http://www.jzy3d.org/maven/releases + + org.jfree @@ -16,18 +22,29 @@ 4.8.2 test - + + fr.esrf.tangoatk.widget.util.chart + JLChart + 1.0.0 + + + org.jzy3d + jzy3d-api + 0.9.1 + + - + maven-compiler-plugin + 3.1 UTF-8 1.7 - 1.7 + 1.7 - + org.apache.maven.plugins @@ -39,6 +56,9 @@ jar + + -Xdoclint:none + @@ -55,7 +75,7 @@ - + @@ -71,4 +91,10 @@ http://yoke/artifactory/libs-releases-local + \ No newline at end of file diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/Axis.java b/ch.psi.plot/src/main/java/ch/psi/plot/Axis.java new file mode 100644 index 0000000..42fb516 --- /dev/null +++ b/ch.psi.plot/src/main/java/ch/psi/plot/Axis.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved. + */ +package ch.psi.plot; + +import ch.psi.plot.Plot.AxisId; + +/** + * + */ +public class Axis { + + PlotBase plot; + AxisId id; + + Axis(String label, PlotBase plot, AxisId id) { + this.plot = plot; + this.id = id; + if (label == null) { + label = ""; + } + this.label = label; + } + + String label = ""; + + public String getLabel() { + return label; + } + + public void setLabel(String value) { + label = value; + plot.onAxisLabelChanged(id); + } + + double min; + + public double getMin() { + return min; + } + + public void setMin(double value) { + min = value; + plot.onAxisRangeChanged(id); + } + + double max; + + public double getMax() { + return max; + } + + public void setMax(double value) { + max = value; + plot.onAxisRangeChanged(id); + } + + public void setRange(double min, double max) { + this.min = min; + this.max = max; + plot.onAxisRangeChanged(id); + } + + public boolean isAutoRange() { + return (max <= min); + } + + public void setAutoRange() { + setRange(0, 0); + } + +} diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/LinePlot.java b/ch.psi.plot/src/main/java/ch/psi/plot/LinePlot.java new file mode 100644 index 0000000..93c2cee --- /dev/null +++ b/ch.psi.plot/src/main/java/ch/psi/plot/LinePlot.java @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved. + */ +package ch.psi.plot; + +/** + * + */ +public interface LinePlot extends Plot { +} diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/LinePlotBase.java b/ch.psi.plot/src/main/java/ch/psi/plot/LinePlotBase.java new file mode 100644 index 0000000..76781fc --- /dev/null +++ b/ch.psi.plot/src/main/java/ch/psi/plot/LinePlotBase.java @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved. + */ +package ch.psi.plot; + +import ch.psi.plot.LinePlotSeries.LinePlotSeriesListener; +import ch.psi.plot.utils.IO; +import ch.psi.plot.utils.SwingUtils; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.IOException; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuItem; + +/** + * TODO: FDA calls to .update -> requestUpdate() + */ +abstract public class LinePlotBase extends PlotBase implements LinePlot { + + private String xAxisLabel = "X"; + private String yAxisLabel = "Y"; + + protected LinePlotBase() { + this(null); + } + + protected LinePlotBase(String title) { + super(LinePlotSeries.class, title); + createAxis(AxisId.X, "X"); + createAxis(AxisId.Y, "Y"); + + } + + //TODO: Improve it to share the same X rows + @Override + public void saveData(String filename) throws IOException { + StringBuilder str = new StringBuilder(1024); + + int numberSeries = getAllSeries().length; + + str.append(getAxis(AxisId.X).getLabel().isEmpty() ? "X" : getAxis(AxisId.X).getLabel()).append(FIELD_SEPARATOR); + for (LinePlotSeries series : getAllSeries()) { + str.append(series.getName()).append(FIELD_SEPARATOR); + } + str.append(LINE_SEPARATOR); + + int seriesIndex = 0; + for (LinePlotSeries series : getAllSeries()) { + double[][] data = getSeriesData(series); + for (int i = 0; i < data[0].length; i++) { + double x = data[0][i]; + double y = data[1][i]; + str.append(String.format("%1.6f", x)).append(FIELD_SEPARATOR); + for (int j = 0; j < seriesIndex; j++) { + str.append(String.format("NaN", x)).append(FIELD_SEPARATOR); + } + str.append(String.format("%1.6f", y)).append(FIELD_SEPARATOR); + for (int j = seriesIndex + 1; j < numberSeries; j++) { + str.append(String.format("NaN", x)).append(FIELD_SEPARATOR); + } + str.append(LINE_SEPARATOR); + } + seriesIndex++; + } + IO.writeStringToFile(filename, str.toString()); + } + + final LinePlotSeriesListener seriesListener = new LinePlotSeriesListener() { + @Override + public void onSeriesAppendData(LinePlotSeries series, double x, double y) { + onAppendData(series, x, y); + if (getRequireUpdateOnAppend() && isUpdatesEnabled()) { + requestSeriesUpdate(series); + } + } + + @Override + public void onSeriesSetData(LinePlotSeries series, double[] x, double[] y) { + if (y == null) { + y = new double[0]; + } + if ((x == null) || (y.length != x.length)) { + x = new double[y.length]; + for (int i = 0; i < x.length; i++) { + x[i] = i; + } + } + onSetData(series, x, y); + if (isUpdatesEnabled()) { + requestSeriesUpdate(series); + } + } + }; + + /** + * Returns a token to reference underlying data from LinePlotSeries + */ + abstract protected void onAppendData(LinePlotSeries series, double x, double y); + + abstract protected void onSetData(LinePlotSeries series, double[] x, double[] y); + + //Injecting specific entries in popup menu + @Override + protected void onCreatedPanel() { + addPopupMenuItem(null);//Separator + // Detach plot into a separate frame + JMenu detachPlotMenu = new JMenu("Detach"); + String[] implementations = getImplementations(); + JMenuItem[] detachPlotMenuItems = new JMenuItem[implementations.length]; + + ActionListener listener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + try { + LinePlot p = newPlot(e.getActionCommand()); + p.setTitle(getTitle()); + p.getAxis(AxisId.X).setLabel(getAxis(AxisId.X).getLabel()); + p.getAxis(AxisId.Y).setLabel(getAxis(AxisId.Y).getLabel()); + for (LinePlotSeries series : getAllSeries()) { + LinePlotSeries detachedSeries = new LinePlotSeries(series.getName(), series.getColor()); + p.addSeries(detachedSeries); + detachedSeries.setData(series.getX(), series.getY()); + } + + JFrame frame = new JFrame(getTitle()); + frame.setContentPane(p.getChartPanel()); + frame.pack(); + SwingUtils.centerOnScreen(frame); + frame.setVisible(true); + } catch (Exception ex) { + SwingUtils.showException(getChartPanel(), ex); + } + } + }; + + for (int i=0;i { + + public interface LinePlotSeriesListener { + + void onSeriesSetData(LinePlotSeries series, double[] x, double[] y); + + void onSeriesAppendData(LinePlotSeries series, double x, double y); + } + + public LinePlotSeries(String name) { + this(name, SwingUtils.generateRandomColor()); + } + + public LinePlotSeries(String name, Color color) { + super(name); + setColor(color); + } + + private Color color; + + void setColor(Color color) { + this.color = color; + } + + public Color getColor() { + return color; + } + + private int axisY = 1; + + void setAxisY(int axis) { + this.axisY = axisY; + } + + public int getAxisY() { + return axisY; + } + + public void setData(double[] x, double[] y) { + if (getPlot() != null) { + ((LinePlotBase) getPlot()).seriesListener.onSeriesSetData(this, x, y); + } + } + + public void appendData(double x, double y) { + if (getPlot() != null) { + ((LinePlotBase) getPlot()).seriesListener.onSeriesAppendData(this, x, y); + } + } + + @Override + public void clear() { + setData(new double[0], new double[0]); + } + + public double[] getX() { + if (getPlot() == null) { + return new double[0]; + } + return getPlot().getSeriesData(this)[0]; + } + + public double[] getY() { + if (getPlot() == null) { + return new double[0]; + } + return getPlot().getSeriesData(this)[1]; + } + + public int getCount() { + if (getPlot() == null) { + return 0; + } + return getPlot().getSeriesData(this)[0].length; + } + + //Tools + public double getAverage() { + double average = 0.0; + for (double y : getY()) { + average = average + y; + } + return average / getCount(); + } + + public double[] getMinimum() { + double min = Double.NaN; + double xmin = Double.NaN; + double[][] data = getPlot().getSeriesData(this); + double[] x = data[0]; + double[] y = data[1]; + + for (int i = 0; i < x.length; i++) { + if (Double.isNaN(min) || (y[i] < min)) { + min = y[i]; + xmin = x[i]; + } + } + return new double[]{xmin, min}; + } + + public double[] getMaximum() { + double max = Double.NaN; + double xmax = Double.NaN; + double[][] data = getPlot().getSeriesData(this); + double[] x = data[0]; + double[] y = data[1]; + + for (int i = 0; i < x.length; i++) { + if (Double.isNaN(max) || (y[i] > max)) { + max = y[i]; + xmax = x[i]; + } + } + return new double[]{xmax, max}; + } + + public double[][] getDerivative() { + if (getCount() <= 2) { + return new double[][]{new double[0], new double[0]}; + } + double[][] data = getPlot().getSeriesData(this); + double[] x = data[0]; + double[] y = data[1]; + + double[] dx = new double[getCount() - 2]; + double[] dy = new double[getCount() - 2]; + + for (int i = 1; i < getCount() - 1; i++) { // do not start at 0 but 1 - stop 1 before end + double xi = x[i]; + double ximinus1 = x[i - 1]; + double xiplus1 = x[i + 1]; + double yiminus1 = y[i - 1]; + double yiplus1 = y[i + 1]; + + if (xiplus1 - ximinus1 != 0.0) { + double di = (yiplus1 - yiminus1) / (xiplus1 - ximinus1); + dx[i - 1] = xi; + dy[i - 1] = di; + } else { + dx[i - 1] = xi; + dy[i - 1] = Double.NaN; + } + } + + return new double[][]{dx, dy}; + } + + public double[][] getIntegral() { + if (getCount() <= 1) { + return new double[][]{new double[0], new double[0]}; + } + double[][] data = getPlot().getSeriesData(this); + double[] x = data[0]; + double[] y = data[1]; + + double[] ix = new double[getCount() - 1]; + double[] iy = new double[getCount() - 1]; + double value = 0.0; + + for (int i = 1; i < getCount(); i++) { // Leave out 1. point + value += (x[i] - x[i - 1]) * (y[i] + y[i - 1]) / 2.0; + ix[i - 1] = x[i]; + iy[i - 1] = value; + } + return new double[][]{ix, iy}; + } + +} diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/MatrixPlot.java b/ch.psi.plot/src/main/java/ch/psi/plot/MatrixPlot.java new file mode 100644 index 0000000..20e7236 --- /dev/null +++ b/ch.psi.plot/src/main/java/ch/psi/plot/MatrixPlot.java @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved. + */ +package ch.psi.plot; + +/** + * + */ +public interface MatrixPlot extends Plot { +} diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/MatrixPlotBase.java b/ch.psi.plot/src/main/java/ch/psi/plot/MatrixPlotBase.java new file mode 100644 index 0000000..3790ae0 --- /dev/null +++ b/ch.psi.plot/src/main/java/ch/psi/plot/MatrixPlotBase.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved. + */ +package ch.psi.plot; + +import ch.psi.plot.MatrixPlotSeries.MatrixPlotSeriesListener; +import ch.psi.plot.utils.IO; +import ch.psi.plot.utils.SwingUtils; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.IOException; +import java.util.HashMap; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuItem; + +/** + * + */ +abstract public class MatrixPlotBase extends PlotBase implements MatrixPlot { + + protected MatrixPlotBase() { + this(null); + } + + protected MatrixPlotBase(String title) { + super(MatrixPlotSeries.class, title); + createAxis(AxisId.X, "X"); + createAxis(AxisId.Y, "Y"); + createAxis(AxisId.Z); + } + + //Only supporting one series for now so let's gain some speed + @Override + public void addSeries(MatrixPlotSeries series) { + if (getAllSeries().length > 0) { + removeSeries(getAllSeries()[0]); + } + super.addSeries(series); + + } + + final MatrixPlotSeriesListener seriesListener = new MatrixPlotSeriesListener() { + @Override + public void onSeriesAppendData(MatrixPlotSeries series, double x, double y, double z) { + + if ((series == null) || (getNumberOfSeries() == 0)) { + return; + } + final int indexX = ((int) ((x - series.getMinX()) / series.getBinWidthX())); + final int indexY = ((int) ((y - series.getMinY()) / series.getBinWidthY())); + if (!series.contains(indexX, indexY)) { + return; + } + onAppendData(series, indexX, indexY, x, y, z); + if (getRequireUpdateOnAppend() && isUpdatesEnabled()) { + requestSeriesUpdate(series); + } + } + + @Override + public void onSeriesSetData(MatrixPlotSeries series, double[][] data) { + if ((series == null) || (getNumberOfSeries() == 0)) { + return; + } + //TODO: Check consistency of z + onSetData(series, data); + if (isUpdatesEnabled()) { + requestSeriesUpdate(series); + } + } + }; + + public void saveData(String filename) throws IOException { + if (getAllSeries().length == 0) { + return; + } + MatrixPlotSeries series = getAllSeries()[0]; + StringBuilder str = new StringBuilder(1024); + + str.append(getAxis(AxisId.X).getLabel().isEmpty() ? "X" : getAxis(AxisId.X).getLabel()).append(FIELD_SEPARATOR); + str.append(getAxis(AxisId.Y).getLabel().isEmpty() ? "Y" : getAxis(AxisId.Y).getLabel()).append(FIELD_SEPARATOR); + str.append(getAxis(AxisId.Z).getLabel().isEmpty() ? "Z" : getAxis(AxisId.Z).getLabel()).append(LINE_SEPARATOR); + + double[][] data = getSeriesData(getAllSeries()[0]); + for (int i = 0; i < data.length; i++) { + for (int j = 0; j < data[0].length; j++) { + double y = series.getMinY() + i * series.getBinWidthY(); + double x = series.getMinX() + j * series.getBinWidthX(); + double z = data[i][j]; + str.append(String.format("%1.6f", x)).append(FIELD_SEPARATOR); + str.append(String.format("%1.6f", y)).append(FIELD_SEPARATOR); + str.append(String.format("%1.6f", z)).append(LINE_SEPARATOR); + } + } + IO.writeStringToFile(filename, str.toString()); + } + + //Injecting specific entries in popup menu + @Override + protected void onCreatedPanel() { + addPopupMenuItem(null);//Separator + // Detach plot into a separate frame + JMenu detachPlotMenu = new JMenu("Detach"); + String[] implementations = getImplementations(); + JMenuItem[] detachPlotMenuItems = new JMenuItem[implementations.length]; + + ActionListener listener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + try { + if (getAllSeries().length == 0) { + return; + } + MatrixPlotSeries s = getAllSeries()[0]; + MatrixPlot p = newPlot(e.getActionCommand()); + p.setTitle(getTitle()); + p.getAxis(AxisId.X).setLabel(getAxis(AxisId.X).getLabel()); + p.getAxis(AxisId.Y).setLabel(getAxis(AxisId.Y).getLabel()); + p.getAxis(AxisId.Z).setLabel(getAxis(AxisId.Z).getLabel()); + MatrixPlotSeries detachedSeries = new MatrixPlotSeries(null, s.getMinX(), s.getMaxX(), s.getNumberOfBinsX(), s.getMinY(), s.getMaxY(), s.getNumberOfBinsY()); + p.addSeries(detachedSeries); + detachedSeries.setData(s.getData()); + + JFrame frame = new JFrame(getTitle()); + frame.setContentPane(p.getChartPanel()); + frame.pack(); + SwingUtils.centerOnScreen(frame); + frame.setVisible(true); + } catch (Exception ex) { + SwingUtils.showException(getChartPanel(), ex); + } + } + }; + for (int i=0;i { + + public interface MatrixPlotSeriesListener { + + void onSeriesSetData(MatrixPlotSeries series, double[][] data); + + void onSeriesAppendData(MatrixPlotSeries series, double x, double y, double z); + } + + private static final Logger logger = Logger.getLogger(MatrixPlotSeries.class.getName()); + + private final double minX; + private final double maxX; + private final int numberOfBinsX; + private final double binWidthX; + + private final double minY; + private final double maxY; + private final int numberOfBinsY; + private final double binWidthY; + + public MatrixPlotSeries(String name, double minX, double maxX, int nX, double minY, double maxY, int nY) { + super(name); + + this.minX = minX; + this.maxX = maxX; + this.numberOfBinsX = nX; + + this.minY = minY; + this.maxY = maxY; + this.numberOfBinsY = nY; + + this.binWidthX = (maxX - minX) / (double) (numberOfBinsX - 1); + this.binWidthY = (maxY - minY) / (double) (numberOfBinsY - 1); + + } + + public void setData(double[][] data) { + if ((data == null) || (data.length != numberOfBinsY) || (data[0].length != numberOfBinsX)) { + data = new double[numberOfBinsY][numberOfBinsX]; + for (int i = 0; i < numberOfBinsY; i++) { + Arrays.fill(data[i], Double.NaN); + } + } + if (getPlot() != null) { + ((MatrixPlotBase) getPlot()).seriesListener.onSeriesSetData(this, data); + } + } + + public void appendData(double x, double y, double z) { + if (getPlot() != null) { + ((MatrixPlotBase) getPlot()).seriesListener.onSeriesAppendData(this, x, y, z); + } + + } + + public double[][] getData() { + if (getPlot() == null) { + return new double[0][0]; + } + return getPlot().getSeriesData(this); + } + + @Override + public void clear() { + setData(null); + } + + /** + * @return the binWidthX + */ + public double getBinWidthX() { + return binWidthX; + } + + /** + * @return the binWidthY + */ + public double getBinWidthY() { + return binWidthY; + } + + /** + * @return the minX + */ + public double getMinX() { + return minX; + } + + /** + * @return the maxX + */ + public double getMaxX() { + return maxX; + } + + /** + * @return the minY + */ + public double getMinY() { + return minY; + } + + /** + * @return the maxY + */ + public double getMaxY() { + return maxY; + } + + /** + * @return the numberOfBinsX + */ + public int getNumberOfBinsX() { + return numberOfBinsX; + } + + /** + * @return the numberOfBinsY + */ + public int getNumberOfBinsY() { + return numberOfBinsY; + } + + //Utilities + public boolean contains(int indexX, int indexY) { + return ((indexX <= numberOfBinsX) && (indexX >= 0) && (indexY <= numberOfBinsY) && (indexY >= 0)); + + } + + public double[] minMaxZValue() { + + double min = Double.NaN; + double max = Double.NaN; + + double[][] data = getData(); + for (int i = 0; i < data.length; i++) { + for (int j = 0; j < data[0].length; j++) { + if (data[i][j] != Double.NEGATIVE_INFINITY) { + if (Double.isNaN(min) || (data[i][j] < min)) { + min = data[i][j]; + } + if (Double.isNaN(max) || (data[i][j] > max)) { + max = data[i][j]; + } + } + } + } + return new double[]{min, max}; + } + +} diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/Plot.java b/ch.psi.plot/src/main/java/ch/psi/plot/Plot.java index f9dc7d9..f31c9e3 100644 --- a/ch.psi.plot/src/main/java/ch/psi/plot/Plot.java +++ b/ch.psi.plot/src/main/java/ch/psi/plot/Plot.java @@ -1,42 +1,65 @@ -/** - * - * Copyright 2010 Paul Scherrer Institute. All rights reserved. - * - * This code 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. - * - * This code 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 this code. If not, see . - * +/* + * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved. */ - package ch.psi.plot; -import org.jfree.chart.ChartPanel; -import org.jfree.chart.JFreeChart; +import java.awt.image.BufferedImage; +import java.io.IOException; +import javax.swing.JPanel; -public interface Plot { - /** - * Get the chart panel - * @return - */ - public ChartPanel getChartPanel(); - - /** - * Get chart of the plot (e.g. to be able to export the chart as an image) - * @return - */ - public JFreeChart getChart(); - - /** - * Update plot (notify all components of the plot) - */ - public void update(); +/** + * + */ +public interface Plot { + + public JPanel getChartPanel(); + + //Request update on event loop + public void update(boolean deferred); + + public void setUpdatesEnabled(boolean value); + + public boolean isUpdatesEnabled(); + + //Generic properties + public void setTitle(String title); + + public String getTitle(); + + //Generic operations + public void saveData(String filename) throws IOException; + + public BufferedImage getSnapshot(); + + public void saveSnapshot(String filename, String format) throws IOException; + + //Series list management + public void addSeries(T series); + + public void addSeries(T[] series); + + public void removeSeries(T series); + + public T getSeries(String name); + + public T getSeries(int index); + + public int getNumberOfSeries(); + + public void updateSeries(T series); + + public void requestSeriesUpdate(final T series); + + public double[][] getSeriesData(final T series); + + public T[] getAllSeries(); + + public void clear(); //remove all series + + //Axis + public enum AxisId { + X, Y, Z; + }; + + public Axis getAxis(AxisId id); } diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/PlotBase.java b/ch.psi.plot/src/main/java/ch/psi/plot/PlotBase.java new file mode 100644 index 0000000..9755d18 --- /dev/null +++ b/ch.psi.plot/src/main/java/ch/psi/plot/PlotBase.java @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved. + */ +package ch.psi.plot; + +import ch.psi.plot.utils.IO; +import ch.psi.plot.utils.SwingUtils; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.JFileChooser; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import javax.swing.filechooser.FileNameExtensionFilter; + +/** + * + */ +abstract public class PlotBase implements Plot { + static{ + javax.swing.JPopupMenu.setDefaultLightWeightPopupEnabled(false); + } + + final String LINE_SEPARATOR = System.lineSeparator(); + final String FIELD_SEPARATOR = "\t"; + + final Class seriesType; + + protected PlotBase(Class seriesType) { + this(seriesType, null); + + } + + protected PlotBase(Class seriesType, String title) { + if (title == null) { + title = "Plot"; + } + setTitle(title); + this.seriesType = seriesType; + } + + String title; + + public void setTitle(String title) { + this.title = title; + } + + public String getTitle() { + return title; + } + + volatile boolean bUpdating; + + public final void update(boolean deferred) { + if ((!deferred) && SwingUtilities.isEventDispatchThread()) { + bUpdating = false; + doUpdate(); + } else { + if (!bUpdating) { + bUpdating = true; + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + if (bUpdating) { + bUpdating = false; + try { + doUpdate(); + } catch (Exception ex) { + Logger.getLogger(PlotBase.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + }); + } + } + } + + boolean requireUpdateOnAppend = true; + + protected void setRequireUpdateOnAppend(boolean value) { + requireUpdateOnAppend = value; + } + + protected boolean getRequireUpdateOnAppend() { + return requireUpdateOnAppend; + } + + boolean updatesEnabled = true; + + public void setUpdatesEnabled(boolean value) { + updatesEnabled = value; + } + + public boolean isUpdatesEnabled() { + return updatesEnabled; + } + + /** + * Should be improved in implementations to make it independent of the + * window state; + */ + public BufferedImage getSnapshot() { + return SwingUtils.createImage(getChartPanel()); + } + + public void saveSnapshot(String filename, String format) throws IOException { + IO.writeImageToFile(getSnapshot(), filename, format); + } + + JPanel panel; + + public JPanel getChartPanel() { + if (panel == null) { + panel = createChartPanel(); + + addPopupMenuItem(null);//Separator + JMenuItem saveData = new JMenuItem("Save Data"); + saveData.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + JFileChooser chooser = new JFileChooser(); + FileNameExtensionFilter filter = new FileNameExtensionFilter("Text data files", "txt", "dat"); + chooser.setFileFilter(filter); + int returnVal = chooser.showSaveDialog(panel); + if (returnVal == JFileChooser.APPROVE_OPTION) { + String filename = chooser.getSelectedFile().getAbsolutePath(); + String type = IO.getExtension(chooser.getSelectedFile()); + if (type == null) { + type = "txt"; + filename += "." + type; + } + saveData(filename); + } + } catch (Exception ex) { + SwingUtils.showException(panel, ex); + } + } + }); + addPopupMenuItem(saveData); + JMenuItem saveSnapshot = new JMenuItem("Save Snapshot"); + saveSnapshot.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + JFileChooser chooser = new JFileChooser(); + FileNameExtensionFilter filter = new FileNameExtensionFilter("Image File", "png", "jpg", "bmp"); + chooser.setFileFilter(filter); + int returnVal = chooser.showSaveDialog(panel); + if (returnVal == JFileChooser.APPROVE_OPTION) { + String filename = chooser.getSelectedFile().getAbsolutePath(); + String type = IO.getExtension(chooser.getSelectedFile()); + if (type == null) { + type = "png"; + filename += "." + type; + } + saveSnapshot(filename, type); + } + } catch (Exception ex) { + SwingUtils.showException(panel, ex); + } + } + }); + addPopupMenuItem(saveSnapshot); + onCreatedPanel(); + } + return panel; + } + + //Overidables + protected void onCreatedPanel() { + } + + abstract protected JPanel createChartPanel(); + + /** + * null for separator + */ + abstract protected void addPopupMenuItem(JMenuItem item); + + //Series list support + final HashMap seriesList = new HashMap<>(); + + @Override + public void addSeries(T series) { + if (series.name == null) { + return; + } + T existingSeries = getSeries(series.name); + if (existingSeries == series) { + return; + } + if (existingSeries != null) { + removeSeries(existingSeries); + } + synchronized (seriesList) { + seriesList.put(series.name, series); + } + series.setPlot(this); + series.setToken(onAddedSeries(series)); + } + + @Override + public void addSeries(T[] series) { + for (T s : series) { + addSeries(s); + } + } + + @Override + public void removeSeries(T series) { + if (series.getPlot() == this) { + series.setPlot(null); + } + onRemovedSeries(series); + synchronized (seriesList) { + seriesList.remove(series.name); + } + } + + @Override + public T getSeries(String name) { + synchronized (seriesList) { + return seriesList.get(name); + } + } + + //TODO: Not respecting order + @Override + public T getSeries(int index) { + synchronized (seriesList) { + if ((index < 0) || (index >= seriesList.size())) { + return null; + } + return seriesList.get(getAllSeries()[index]); + } + } + + @Override + public int getNumberOfSeries() { + return seriesList.size(); + } + + @Override + public T[] getAllSeries() { + synchronized (seriesList) { + ArrayList list = new ArrayList(); + for (T series : seriesList.values()) { + list.add(series); + } + return list.toArray((T[]) Array.newInstance(seriesType, 0)); + } + } + + @Override + public void requestSeriesUpdate(final T series) { + if (!series.updating) { + series.updating = true; + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + series.updating = false; + try { + updateSeries(series); + } catch (Exception ex) { + Logger.getLogger(LinePlotBase.class.getName()).log(Level.SEVERE, null, ex); + } + } + }); + } + } + + abstract protected Object onAddedSeries(T series); + + abstract protected void onRemovedSeries(T series); + + /** + * These overridables can be optimised in implementations + */ + protected void onRemovedAllSeries() { + for (T s : getAllSeries()) { + removeSeries(s); + } + } + + protected void doUpdate() { + for (T s : getAllSeries()) { + updateSeries(s); + } + } + + @Override + public void clear() { + onRemovedAllSeries(); + synchronized (seriesList) { + seriesList.clear(); + } + update(true); + } + + //Axis + final HashMap axisList = new HashMap<>(); + + protected void createAxis(AxisId axis) { + createAxis(axis, null); + } + + protected void createAxis(AxisId axis, String label) { + axisList.put(axis, new Axis(label, this, axis)); + } + + public Axis getAxis(AxisId id) { + return axisList.get(id); + } + + //Axis Callbacks + protected void onAxisLabelChanged(AxisId axis) { + if (isUpdatesEnabled()) { + doUpdate(); + } + } + + protected void onAxisRangeChanged(AxisId axis) { + if (isUpdatesEnabled()) { + doUpdate(); + } + } +} diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/PlotSeries.java b/ch.psi.plot/src/main/java/ch/psi/plot/PlotSeries.java new file mode 100644 index 0000000..8f7f96e --- /dev/null +++ b/ch.psi.plot/src/main/java/ch/psi/plot/PlotSeries.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved. + */ +package ch.psi.plot; + +/** + * + */ +public abstract class PlotSeries { + + volatile boolean updating = false; + + protected PlotSeries() { + this(""); + } + + protected PlotSeries(String name) { + setName((name == null) ? "" : name); + } + + Object token; + + void setToken(Object token) { + this.token = token; + } + + public Object getToken() { + return token; + } + + private T plot; + + void setPlot(T plot) { + this.plot = plot; + } + + public T getPlot() { + return plot; + } + + String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public void clear(){ + + } +} diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/javafx/LinePlot.java b/ch.psi.plot/src/main/java/ch/psi/plot/javafx/LinePlot.java new file mode 100644 index 0000000..bc740cf --- /dev/null +++ b/ch.psi.plot/src/main/java/ch/psi/plot/javafx/LinePlot.java @@ -0,0 +1,625 @@ +/* + * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved. + */ +package ch.psi.plot.javafx; + +import ch.psi.plot.LinePlotSeries; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.text.DecimalFormat; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import javafx.animation.AnimationTimer; +import javafx.application.Platform; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.collections.ObservableList; +import javafx.embed.swing.JFXPanel; +import javafx.event.ActionEvent; +import javafx.event.EventHandler; +import javafx.geometry.Point2D; +import javafx.scene.Cursor; +import javafx.scene.Node; +import javafx.scene.Scene; +import javafx.scene.chart.Axis; +import javafx.scene.chart.LineChart; +import javafx.scene.chart.NumberAxis; +import javafx.scene.chart.XYChart; +import javafx.scene.chart.XYChart.Data; +import javafx.scene.chart.XYChart.Series; +import javafx.scene.control.CheckMenuItem; +import javafx.scene.control.ContextMenu; +import javafx.scene.control.Label; +import javafx.scene.control.Menu; +import javafx.scene.control.MenuItem; +import javafx.scene.control.SeparatorMenuItem; +import javafx.scene.input.MouseButton; +import javafx.scene.input.MouseEvent; +import javafx.scene.layout.StackPane; +import javafx.scene.paint.Color; +import javafx.scene.shape.Rectangle; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; + +/** + * + */ +public class LinePlot extends ch.psi.plot.LinePlotBase { + + final boolean HOVERING_SYMBOLS = true; + + public LinePlot() { + super(); + createChart(); + setRequireUpdateOnAppend(false); + } + + final LinkedHashMap>> seriesList = new LinkedHashMap<>(); + + @Override + protected Object onAddedSeries(final LinePlotSeries series) { + XYChart.Series chartSeries = new XYChart.Series(); + ConcurrentLinkedQueue> queue = new ConcurrentLinkedQueue<>(); + chartSeries.setName(series.getName()); + synchronized (seriesList) { + seriesList.put(chartSeries, queue); + } + update(true); + return chartSeries; + } + + @Override + protected void onRemovedSeries(LinePlotSeries series) { + XYChart.Series chartSeries = getChartSeries(series); + if (chartSeries != null) { + synchronized (seriesList) { + seriesList.remove(chartSeries); + } + update(true); + } + } + + @Override + protected void onAppendData(final LinePlotSeries series, final double x, final double y) { + XYChart.Series chartSeries = getChartSeries(series); + if (chartSeries != null) { + synchronized (seriesList) { + ConcurrentLinkedQueue> queue = seriesList.get(chartSeries); + Data dataPoint = new Data(x, y); + queue.add(dataPoint); + } + } + } + + @Override + protected void onSetData(LinePlotSeries series, double[] x, double[] y) { + XYChart.Series chartSeries = getChartSeries(series); + synchronized (seriesList) { + ConcurrentLinkedQueue> queue = seriesList.get(chartSeries); + for (int i = 0; i < x.length; i++) { + Data dataPoint = new Data(x[i], y[i]); + queue.add(dataPoint); + } + } + } + + @Override + public void updateSeries(LinePlotSeries series) { + } + + @Override + public double[][] getSeriesData(LinePlotSeries series) { + XYChart.Series s = getChartSeries(series); + ObservableList> list = s.getData(); + double[] x = new double[list.size()]; + double[] y = new double[list.size()]; + int index = 0; + for (Data item : list) { + x[index] = item.getXValue().doubleValue(); + y[index++] = item.getYValue().doubleValue(); + } + return new double[][]{x, y}; + + } + + XYChart.Series getChartSeries(LinePlotSeries series) { + return (XYChart.Series) (series.getToken()); + } + + @Override + public void doUpdate() { + if (mTimerFX != null) { + Platform.runLater(new Runnable() { + @Override + public void run() { + updateFX(); + } + }); + } + } + + private static JFXPanel fxContainer; + + @Override + protected JPanel createChartPanel() { + fxContainer.setPreferredSize(new Dimension(480, 240)); + JPanel panel = new JPanel(); + panel.setLayout(new BorderLayout()); + panel.add(fxContainer); + // create JavaFX scene + Platform.runLater(new Runnable() { + + @Override + public void run() { + createScene(); + } + }); + return panel; + } + + class MyLineChart extends LineChart { + + public MyLineChart(Axis axis, Axis axis1) { + super(axis, axis1); + } + + public void addNode(Node node) { + if (node != null) { + getPlotChildren().add(node); + } + } + + public void removeNode(Node node) { + if (node != null) { + getPlotChildren().remove(node); + } + } + + @Override + protected void requestChartLayout() { + super.requestChartLayout(); + } + } + + private MyLineChart chart; + + boolean drawSymbols = false; + + public void setDrawSymbols(boolean value) { + if (value != drawSymbols) { + drawSymbols = value; + if (chart != null) { + if (HOVERING_SYMBOLS) { + for (Iterator> it = chart.getData().iterator(); it.hasNext();) { + XYChart.Series series = it.next(); + ObservableList> list = series.getData(); + for (Data item : list) { + Node symbol = item.getNode(); + if (symbol != null) { + item.setNode(null); + chart.removeNode(symbol); + } + if (drawSymbols) { + symbol = new HoveredThresholdNode(series, item.getXValue(), item.getYValue()); + //symbol = chart.createSymbol(series,chart.getData().indexOf(series), item, itemIndex); + item.setNode(symbol); + chart.addNode(symbol); + } + } + } + } else { + chart.setCreateSymbols(getDrawSymbols()); + } + + chart.requestChartLayout(); + } + } + } + + public boolean getDrawSymbols() { + return drawSymbols; + } + + private void createChart() { + fxContainer = new JFXPanel(); //Must do bedore any JavaFX call + //xAxis = new NumberAxis(lower,upper,tick); + NumberAxis xAxis = new NumberAxis(); + xAxis.setForceZeroInRange(false); + xAxis.setAutoRanging(true); + + xAxis.setTickLabelsVisible(true); + xAxis.setTickMarkVisible(true); + xAxis.setMinorTickVisible(true); + + NumberAxis yAxis = new NumberAxis(); + yAxis.setForceZeroInRange(false); + yAxis.setAutoRanging(true); + + //-- Chart + chart = new MyLineChart<>(xAxis, yAxis); + chart.setAnimated(false); + chart.setCreateSymbols(false); + chart.setCursor(Cursor.CROSSHAIR); + } + + Rectangle zoomRect; + + private void createScene() { + /*Platform.runLater(new Runnable() { + @Override + public void run() {*/ + chart.setId(getTitle()); + chart.setTitle(getTitle()); + + + final StackPane chartContainer = new StackPane(); + chartContainer.getChildren().add(chart); + zoomRect = new Rectangle(); + zoomRect.setManaged(false); + zoomRect.setFill(Color.LIGHTSEAGREEN.deriveColor(0, 1, 1, 0.5)); + chartContainer.getChildren().add(zoomRect); + + setUpZooming(zoomRect, chart); + setUpContextMenu(); + fxContainer.setScene(new Scene(chartContainer)); + + synchronized (seriesList) { + addSeriesToChart(); + } + + // Every frame to take any data from queue and add to chart + mTimerFX = new AnimationTimer() { + @Override + public void handle(long now) { + onTimerFX(now); + } + }; + mTimerFX.start(); + + /* + mTimerFX = new Timeline(new KeyFrame(Duration.millis(200), new EventHandler() { + + @Override + public void handle(ActionEvent event) { + onTimerFX(System.nanoTime()); + } + })); + mTimerFX.setCycleCount(Timeline.INDEFINITE); + mTimerFX.play(); + */ + /* + } + });*/ + } + + //Timeline mTimerFX; + AnimationTimer mTimerFX; + + void onTimerFX(long start) { + + synchronized (seriesList) { + for (Iterator it = seriesList.keySet().iterator(); it.hasNext();) { + XYChart.Series series = it.next(); + if (isPlottingSeries(series)) { + ConcurrentLinkedQueue> queue = seriesList.get(series); + //int count=0; + //while (!queue.isEmpty() && (count++<1000)) { + // series.getData().add(queue.remove()); + //} + if (!queue.isEmpty()) { + + if (getDrawSymbols()) { + for (Data d : queue) { + d.setNode(new HoveredThresholdNode(series, d.getXValue(), d.getYValue())); + } + } + series.getData().addAll(queue); + queue.clear(); + + } + } + if (getElapsedMillis(start) > 200) { + return; + } + + //xAxis.setLowerBound(xSeriesData-MAX_DATA_POINTS); + //xAxis.setUpperBound(xSeriesData-1); + } + } + } + + long getElapsedMillis(long start) { + return (System.nanoTime() - start) / 1000000; + } + + void updateFX() { + synchronized (seriesList) { + addSeriesToChart(); + removeSeriesFromChart(); + } + } + + void addSeriesToChart() { + for (Iterator it = seriesList.keySet().iterator(); it.hasNext();) { + XYChart.Series series = it.next(); + if (!isPlottingSeries(series)) { + chart.getData().add(series); + +//Attempt to have a floating label that could speed up rendering of symbol coordinates +//Didn't manage to display the label. +/* + + final Label label = new Label(""); + label.setLabelFor(series.getNode()); + label.getStyleClass().addAll("chart-line-symbol"); + label.getStyleClass().addAll(series.getNode().getStyleClass()); + label.setStyle("-fx-font-size: 13; -fx-font-weight: normal;"); ; + label.setMinSize(Label.USE_PREF_SIZE, Label.USE_PREF_SIZE); + chart.addNode(label); + + series.getNode().setOnMouseEntered(new EventHandler() { + @Override public void handle(MouseEvent mouseEvent) { + final NumberAxis yAxis = (NumberAxis) chart.getYAxis(); + final NumberAxis xAxis = (NumberAxis) chart.getXAxis(); + Point2D xAxisInScene = xAxis.localToScene(0, 0); + double xOffset = mouseEvent.getSceneX() - xAxisInScene.getX(); + double yOffset = mouseEvent.getSceneY() - xAxisInScene.getY(); + double xAxisScale = xAxis.getScale(); + double yAxisScale = yAxis.getScale(); + double x = xAxis.getLowerBound() + xOffset / xAxisScale; + double y = yAxis.getLowerBound() + yOffset / yAxisScale; + String str="(" + format.format(x) + ", " + format.format(y) +")"; + + //System.out.println(str); + label.setText(str); + label.setVisible(true); + label.toFront(); + + + } + }); + series.getNode().setOnMouseExited(new EventHandler() { + @Override public void handle(MouseEvent mouseEvent) { + label.setVisible(false); + } + }); + + */ + } + } + } + + void removeSeriesFromChart() { + for (Iterator> it = chart.getData().iterator(); it.hasNext();) { + XYChart.Series series = it.next(); + if (!seriesList.keySet().contains(series)) { + chart.getData().remove(series); + } + } + } + + boolean isPlottingSeries(Series series) { + return chart.getData().contains(series); + } + + boolean zooming; + + private void setUpZooming(final Rectangle rect, final Node zoomingNode) { + final ObjectProperty mouseAnchor = new SimpleObjectProperty<>(); + zoomingNode.setOnMousePressed(new EventHandler() { + @Override + public void handle(MouseEvent event) { + if (event.isControlDown() && (event.getButton() == MouseButton.PRIMARY)) { + mouseAnchor.set(new Point2D(event.getX(), event.getY())); + zooming = true; + rect.setWidth(0); + rect.setHeight(0); + } else if (event.getButton() == MouseButton.SECONDARY) { + contextMenu.show(zoomingNode, event.getScreenX(), event.getScreenY()); + + } + } + }); + zoomingNode.setOnMouseDragged(new EventHandler() { + @Override + public void handle(MouseEvent event) { + if (event.isControlDown() && zooming) { + double x = event.getX(); + double y = event.getY(); + rect.setX(Math.min(x, mouseAnchor.get().getX())); + rect.setY(Math.min(y, mouseAnchor.get().getY())); + rect.setWidth(Math.abs(x - mouseAnchor.get().getX())); + rect.setHeight(Math.abs(y - mouseAnchor.get().getY())); + } + } + }); + + zoomingNode.setOnMouseReleased(new EventHandler() { + @Override + public void handle(MouseEvent event) { + if (event.isControlDown() && zooming) { + doZoom(zoomRect, chart); + } + rect.setWidth(0); + rect.setHeight(0); + zooming = false; + } + }); + + } + + private void doZoom(Rectangle zoomRect, LineChart chart) { + Point2D zoomTopLeft = new Point2D(zoomRect.getX(), zoomRect.getY()); + Point2D zoomBottomRight = new Point2D(zoomRect.getX() + zoomRect.getWidth(), zoomRect.getY() + zoomRect.getHeight()); + final NumberAxis yAxis = (NumberAxis) chart.getYAxis(); + Point2D yAxisInScene = yAxis.localToScene(0, 0); + final NumberAxis xAxis = (NumberAxis) chart.getXAxis(); + if (zoomTopLeft.getX() < yAxisInScene.getX() && zoomTopLeft.getY() < yAxisInScene.getY()) { + resetZoom(); + } else { + xAxis.setAutoRanging(false); + yAxis.setAutoRanging(false); + Point2D xAxisInScene = xAxis.localToScene(0, 0); + double xOffset = zoomTopLeft.getX() - yAxisInScene.getX(); + double yOffset = zoomBottomRight.getY() - xAxisInScene.getY(); + double xAxisScale = xAxis.getScale(); + double yAxisScale = yAxis.getScale(); + xAxis.setLowerBound(xAxis.getLowerBound() + xOffset / xAxisScale); + xAxis.setUpperBound(xAxis.getLowerBound() + zoomRect.getWidth() / xAxisScale); + yAxis.setLowerBound(yAxis.getLowerBound() + yOffset / yAxisScale); + yAxis.setUpperBound(yAxis.getLowerBound() - zoomRect.getHeight() / yAxisScale); + // System.out.println(xAxis.getLowerBound() + " " + xAxis.getUpperBound() + " " + yAxis.getLowerBound() + " " + yAxis.getUpperBound()); + } + + zoomRect.setWidth(0); + zoomRect.setHeight(0); + } + + private void resetZoom() { + + final NumberAxis yAxis = (NumberAxis) chart.getYAxis(); + final NumberAxis xAxis = (NumberAxis) chart.getXAxis(); + + if (getAxis(AxisId.Y).isAutoRange()) { + yAxis.setLowerBound(getAxis(AxisId.Y).getMin()); + yAxis.setUpperBound(getAxis(AxisId.Y).getMax()); + yAxis.setAutoRanging(true); + + } else { + yAxis.setAutoRanging(false); + yAxis.setLowerBound(getAxis(AxisId.Y).getMin()); + yAxis.setUpperBound(getAxis(AxisId.Y).getMax()); + } + + if (getAxis(AxisId.X).isAutoRange()) { + xAxis.setLowerBound(getAxis(AxisId.X).getMin()); + xAxis.setUpperBound(getAxis(AxisId.X).getMax()); + xAxis.setAutoRanging(true); + } else { + xAxis.setAutoRanging(false); + xAxis.setLowerBound(getAxis(AxisId.X).getMin()); + xAxis.setUpperBound(getAxis(AxisId.X).getMax()); + } + } + + @Override + protected void onAxisRangeChanged(AxisId axis_id) { + NumberAxis axis = null; + switch (axis_id) { + case X: + axis = (NumberAxis) chart.getXAxis(); + break; + case Y: + axis = (NumberAxis) chart.getYAxis(); + break; + default: + return; + } + axis.setAutoRanging(getAxis(axis_id).isAutoRange()); + axis.setLowerBound(getAxis(axis_id).getMin()); + axis.setUpperBound(getAxis(axis_id).getMax()); + } + + ContextMenu contextMenu; + + public void setUpContextMenu() { + contextMenu = new ContextMenu(); + final CheckMenuItem item1 = new CheckMenuItem("Draw Symbols"); + item1.setSelected(getDrawSymbols()); + item1.setOnAction(new EventHandler() { + public void handle(ActionEvent e) { + setDrawSymbols(item1.isSelected()); + } + }); + final CheckMenuItem item2 = new CheckMenuItem("Show Legend"); + item2.setSelected(chart.isLegendVisible()); + item2.setOnAction(new EventHandler() { + public void handle(ActionEvent e) { + chart.setLegendVisible(item2.isSelected()); + } + }); + MenuItem item3 = new MenuItem("Reset Zoom"); + item3.setOnAction(new EventHandler() { + public void handle(ActionEvent e) { + resetZoom(); + } + }); + contextMenu.getItems().addAll(item1, item2, item3); + } + + DecimalFormat format = new DecimalFormat("#.######"); + + class HoveredThresholdNode extends StackPane { + + HoveredThresholdNode(XYChart.Series series, Number x, Number y) { + setPrefSize(8, 8); + getStyleClass().addAll("chart-line-symbol"); + getStyleClass().addAll(series.getNode().getStyleClass()); + + final Label label = new Label("(" + format.format(x) + ", " + format.format(y) + ")"); + label.getStyleClass().addAll("chart-line-symbol"); + label.getStyleClass().addAll(series.getNode().getStyleClass()); + label.setStyle("-fx-font-size: 13; -fx-font-weight: normal;"); + //label.setTextFill(Color.FORESTGREEN); + label.setMinSize(Label.USE_PREF_SIZE, Label.USE_PREF_SIZE); + setOnMouseEntered(new EventHandler() { + @Override + public void handle(MouseEvent mouseEvent) { + getChildren().setAll(label); + setCursor(Cursor.NONE); + toFront(); + } + }); + setOnMouseExited(new EventHandler() { + @Override + public void handle(MouseEvent mouseEvent) { + getChildren().clear(); + setCursor(Cursor.CROSSHAIR); + } + }); + } + + } + + void addSwingMenuItem(final ObservableList menu, final JMenuItem item) { + if (item instanceof JMenu) { + Menu menu_fx = new Menu(item.getText()); + for (Component menuItem : ((JMenu) item).getMenuComponents()) { + if (menuItem instanceof JMenu) { + addSwingMenuItem(menu_fx.getItems(), ((JMenu) menuItem)); + } else if (menuItem instanceof JPopupMenu.Separator) { + menu_fx.getItems().add(new SeparatorMenuItem()); + } else if (menuItem instanceof JMenuItem) { + addSwingMenuItem(menu_fx.getItems(), ((JMenuItem) menuItem)); + } + } + menu.add(menu_fx); + } else if (item instanceof JMenuItem) { + MenuItem itemFX = new MenuItem(item.getText()); + itemFX.setOnAction(new EventHandler() { + public void handle(ActionEvent e) { + item.doClick(); + } + }); + menu.add(itemFX); + } + } + + protected void addPopupMenuItem(final JMenuItem item) { + Platform.runLater(new Runnable() { + @Override + public void run() { + if (item == null) { + contextMenu.getItems().add(new SeparatorMenuItem()); + } else { + addSwingMenuItem(contextMenu.getItems(), item); + } + } + }); + } + +} diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/jfree/ColorManager.java b/ch.psi.plot/src/main/java/ch/psi/plot/jfree/ColorManager.java new file mode 100644 index 0000000..e6bc2e6 --- /dev/null +++ b/ch.psi.plot/src/main/java/ch/psi/plot/jfree/ColorManager.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved. + */ +package ch.psi.plot.jfree; + +import java.awt.Color; + +/** + * Utility class for applying a color map + */ +public class ColorManager { + + /** + * Get color for a given value + * + * @param v Value to get the color for + * @param vmin Lower end value mapped to the lower end of the color map + * @param vmax Upper end value mapped to the upper end of the color map + * @return Mapped color for the specified value + */ + public static Color getColourForValue(double v, double vmin, double vmax) { + // Standard algorithm for hot-cold color gradient (copied from + // http://local.wasp.uwa.edu.au/~pbourke/texture_colour/colourramp/) + + //Init color to white + double r = 1.0; + double g = 1.0; + double b = 1.0; + + double dv; + + if (v < vmin) { + v = vmin; + } + if (v > vmax) { + v = vmax; + } + dv = vmax - vmin; + + if (v < (vmin + 0.25 * dv)) { + r = 0.0; + g = 4 * (v - vmin) / dv; + } else if (v < (vmin + 0.5 * dv)) { + r = 0.0; + b = 1 + 4 * (vmin + 0.25 * dv - v) / dv; + } else if (v < (vmin + 0.75 * dv)) { + r = 4 * (v - vmin - 0.5 * dv) / dv; + b = 0.0; + } else { + g = 1 + 4 * (vmin + 0.75 * dv - v) / dv; + b = 0.0; + } + + return new Color(new Double(255.0 * r).intValue(), new Double(255.0 * g).intValue(), new Double(255.0 * b).intValue()); + } + + /** + * Get a gray value for a given value + * + * @param value the value (must be within the range specified by the lower + * and upper bounds for the scale). + * + * @return a gray scale color. + */ + public static Color getGrayForValue(double value, double vmin, double vmax) { + double v = Math.max(value, vmin); + v = Math.min(v, vmax); + int g = (int) ((v - vmin) / (vmax - vmin) * 255.0); + // FIXME: it probably makes sense to allocate an array of 256 Colors + // and lazily populate this array... + return new Color(g, g, g); + } +} diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/xy/tools/CrossAnnotation.java b/ch.psi.plot/src/main/java/ch/psi/plot/jfree/CrossAnnotation.java similarity index 74% rename from ch.psi.plot/src/main/java/ch/psi/plot/xy/tools/CrossAnnotation.java rename to ch.psi.plot/src/main/java/ch/psi/plot/jfree/CrossAnnotation.java index ae8e9d7..f32342e 100644 --- a/ch.psi.plot/src/main/java/ch/psi/plot/xy/tools/CrossAnnotation.java +++ b/ch.psi.plot/src/main/java/ch/psi/plot/jfree/CrossAnnotation.java @@ -1,4 +1,4 @@ -package ch.psi.plot.xy.tools; +package ch.psi.plot.jfree; import java.awt.BasicStroke; import java.awt.Color; @@ -10,29 +10,31 @@ import org.jfree.ui.Drawable; /** * Class that draws an cross as annotation. - * - * This is an implementation of the {@link Drawable} interface, to illustrate the use of the - * {@link org.jfree.chart.annotations.XYDrawableAnnotation} class. + * + * This is an implementation of the {@link Drawable} interface, to illustrate + * the use of the {@link org.jfree.chart.annotations.XYDrawableAnnotation} + * class. */ public class CrossAnnotation implements Drawable { - private final Color color; - + private final Color color; + /** * Creates a new instance. */ public CrossAnnotation(Color color) { - this.color = color; + this.color = color; } /** * Draws cross - * @param g2 the graphics device. - * @param area the area in which to draw. + * + * @param g2 the graphics device. + * @param area the area in which to draw. */ public void draw(Graphics2D g2, Rectangle2D area) { - - // Draw red cross + + // Draw red cross g2.setPaint(color); g2.setStroke(new BasicStroke(2)); // Stroke width = 2 Line2D line1 = new Line2D.Double(area.getCenterX(), area.getMinY(), area.getCenterX(), area.getMaxY()); diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/jfree/LinePlot.java b/ch.psi.plot/src/main/java/ch/psi/plot/jfree/LinePlot.java new file mode 100644 index 0000000..a40c6c2 --- /dev/null +++ b/ch.psi.plot/src/main/java/ch/psi/plot/jfree/LinePlot.java @@ -0,0 +1,544 @@ +package ch.psi.plot.jfree; + +import ch.psi.plot.LinePlotBase; +import ch.psi.plot.LinePlotSeries; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.text.DecimalFormat; +import java.util.Collection; +import java.util.List; +import java.util.logging.Logger; +import javax.swing.AbstractAction; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; +import org.jfree.chart.ChartFactory; +import org.jfree.chart.ChartPanel; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.annotations.XYAnnotation; +import org.jfree.chart.annotations.XYDrawableAnnotation; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.entity.StandardEntityCollection; +import org.jfree.chart.labels.StandardXYToolTipGenerator; +import org.jfree.chart.labels.XYToolTipGenerator; +import org.jfree.chart.plot.Marker; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.plot.ValueMarker; +import org.jfree.chart.plot.XYPlot; +import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; +import org.jfree.data.Range; +import org.jfree.data.xy.XYDataItem; +import org.jfree.data.xy.XYSeries; +import org.jfree.data.xy.XYSeriesCollection; +import org.jfree.ui.Layer; +import org.jfree.ui.RectangleAnchor; +import org.jfree.ui.RefineryUtilities; +import org.jfree.ui.TextAnchor; + +public class LinePlot extends LinePlotBase { + + private static final Logger logger = Logger.getLogger(LinePlot.class.getName()); + + private ChartPanel chartPanel; + + private static final int chartPanelWidth = 500; + private static final int chartPanelHeight = 270; + + //Defining Context Menu Label + private static final String showLegendMenuLabel = "Show Legend"; + private static final String hideLegendMenuLabel = "Hide Legend"; + private static final String showTooltipsMenuLabel = "Show Tooltips"; + private static final String hideTooltipsMenuLabel = "Hide Tooltips"; + + private XYSeriesCollection data; + + JFreeChart chart; + + private boolean tooltips = false; + + /** + * @param title Title of plot + */ + public LinePlot() { + super(); + data = new XYSeriesCollection(); + } + + @Override + public void onAppendData(LinePlotSeries series, double x, double y) { + XYSeries s = getXYSeries(series); + s.add(new XYDataItem(x, y), false); + } + + @Override + protected void onSetData(LinePlotSeries series, double[] x, double[] y) { + XYSeries s = getXYSeries(series); + if (!s.isEmpty()) { + s.clear(); + } + for (int i = 0; i < y.length; i++) { + s.add(new XYDataItem(x[i], y[i]), false); + } + } + + @Override + protected Object onAddedSeries(LinePlotSeries series) { + final XYSeries s = new XYSeries(series.getName()); + data.addSeries(s); + + return s; + } + + @Override + protected void onRemovedSeries(LinePlotSeries series) { + /* + for (Object s : data.getSeries()) { + if (((XYSeries)s).getKey().equals(series.getName())) { + data.removeSeries(((XYSeries)s)); + } + } + */ + if ((series != null) && (series.getToken() != null)) { + data.removeSeries((XYSeries) (series.getToken())); + } + } + + @Override + public double[][] getSeriesData(final LinePlotSeries series) { + final XYSeries s = getXYSeries(series); + List items = s.getItems(); + double[] x = new double[items.size()]; + double[] y = new double[items.size()]; + for (int i = 0; i < y.length; i++) { + x[i] = items.get(i).getXValue(); + y[i] = items.get(i).getYValue(); + } + return new double[][]{x, y}; + } + + @Override + public void onRemovedAllSeries() { + data.removeAllSeries(); + } + + public void updateSeries(LinePlotSeries series) { + XYSeries s = getXYSeries(series); + s.fireSeriesChanged(); + } + + XYSeries getXYSeries(LinePlotSeries series) { + /* + for (Object s : data.getSeries()) { + if (((XYSeries)s).getKey().equals(series.getName())) { + return ((XYSeries)s); + } + } + return null; + */ + return (XYSeries) (series.getToken()); + } + + /** + * Get the chart panel of this plot. The chart panel will be lazily created + * the first time this function is called + * + * @return + */ + @Override + protected JPanel createChartPanel() { + // Create chart + chart = ChartFactory.createXYLineChart(getTitle(), getAxis(AxisId.X).getLabel(), getAxis(AxisId.Y).getLabel(), data, PlotOrientation.VERTICAL, true, tooltips, false); + + // Customize chart look and feel + // Customize background (gray: new Color(238,238,238)) + chart.setBackgroundPaint(null); + + // Customize legend + chart.getLegend().setVisible(false); + chart.getLegend().setBackgroundPaint(null); + chart.getLegend().setBorder(0, 0, 0, 0); + + // Customize plot area look and feel + XYPlot plot = (XYPlot) chart.getPlot(); + plot.setBackgroundPaint(Color.white); + plot.setDomainGridlinePaint(Color.gray); + plot.setRangeGridlinePaint(Color.gray); + + // Show data point + ((XYLineAndShapeRenderer) plot.getRenderer()).setBaseShapesVisible(true); + + // Include zeros in range (x) axis + ((NumberAxis) plot.getRangeAxis()).setAutoRangeIncludesZero(false); + + // Lazy creation of the chart panel + chartPanel = new ChartPanel(chart); + chartPanel.setName(getTitle()); + + // Remove border + chartPanel.getChart().setBorderVisible(false); + + // Set size of chart + chartPanel.setPreferredSize(new java.awt.Dimension(chartPanelWidth, chartPanelHeight)); + + // Add more items to the context menu + amendContextMenu(); + + //Activate (arrow) keys + addKeyBindings(); + return chartPanel; + } + + /** + * Change visible part of chart + * + * @param translationVector + */ + private void moverOverPlot(XYDataItem translationVector) { + double translatedDomainIntervalMin = chart.getXYPlot().getDomainAxis().getRange().getLowerBound() + translationVector.getX().doubleValue(); + double translatedDomainIntervalMax = chart.getXYPlot().getDomainAxis().getRange().getUpperBound() + translationVector.getX().doubleValue(); + double translatedRangeIntervalMin = chart.getXYPlot().getRangeAxis().getRange().getLowerBound() + translationVector.getY().doubleValue(); + double translatedRangeIntervalMax = chart.getXYPlot().getRangeAxis().getRange().getUpperBound() + translationVector.getY().doubleValue(); + + Range domainAxisRange = new Range(translatedDomainIntervalMin, translatedDomainIntervalMax); + Range rangeAxisRange = new Range(translatedRangeIntervalMin, translatedRangeIntervalMax); + //We set notify to false in the first call.. + chart.getXYPlot().getDomainAxis().setRange(domainAxisRange, true, false); + //...and true in the last + chart.getXYPlot().getRangeAxis().setRange(rangeAxisRange, true, true); + + } + + /** + * Add key bindings to chart panel + */ + private void addKeyBindings() { + final String moveUpKey = "move up"; + final String moveDownKey = "move down"; + final String moveRightKey = "move right"; + final String moveLeftKey = "move left"; + + // Up arrow + chartPanel.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), moveUpKey); + chartPanel.getActionMap().put(moveUpKey, new AbstractAction() { + // Default serial id + private static final long serialVersionUID = 1L; + + @Override + public void actionPerformed(ActionEvent e) { + moverOverPlot(new XYDataItem(0.0, ((NumberAxis) chart.getXYPlot().getRangeAxis()).getTickUnit().getSize())); + } + }); + + // Down arrow + chartPanel.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), moveDownKey); + chartPanel.getActionMap().put(moveDownKey, new AbstractAction() { + // Default serial id + private static final long serialVersionUID = 1L; + + @Override + public void actionPerformed(ActionEvent e) { + moverOverPlot(new XYDataItem(0.0, -((NumberAxis) chart.getXYPlot().getRangeAxis()).getTickUnit().getSize())); + } + }); + + // Right arrow + chartPanel.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), moveRightKey); + chartPanel.getActionMap().put(moveRightKey, new AbstractAction() { + // Default serial id + private static final long serialVersionUID = 1L; + + @Override + public void actionPerformed(ActionEvent e) { + moverOverPlot(new XYDataItem(((NumberAxis) chart.getXYPlot().getDomainAxis()).getTickUnit().getSize(), 0.0)); + } + }); + + // Left arrow + chartPanel.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), moveLeftKey); + chartPanel.getActionMap().put(moveLeftKey, new AbstractAction() { + // Default serial id + private static final long serialVersionUID = 1L; + + @Override + public void actionPerformed(ActionEvent e) { + moverOverPlot(new XYDataItem(-((NumberAxis) chart.getXYPlot().getDomainAxis()).getTickUnit().getSize(), 0.0)); + } + }); + } + + @Override + protected void onAxisRangeChanged(AxisId axis_id) { + ValueAxis axis = null; + + switch (axis_id) { + case X: + axis = chart.getXYPlot().getDomainAxis(); + break; + case Y: + axis = chart.getXYPlot().getRangeAxis(); + break; + default: + return; + } + if (getAxis(axis_id).isAutoRange()) { + axis.setAutoRange(true); + } else { + axis.setRange(new Range(getAxis(axis_id).getMin(), getAxis(axis_id).getMax()), true, true); + } + } + + /** + * Add additional items to the context menu of the plot + */ + public void amendContextMenu() { + + chartPanel.getPopupMenu().addSeparator(); + + JMenu toolsMenu = new JMenu("Tools"); + chartPanel.getPopupMenu().add(toolsMenu); + + // Mark average + JMenuItem averageMenuItem = new JMenuItem("Average"); + averageMenuItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + for (LinePlotSeries series : getAllSeries()) { + double a = series.getAverage(); + // Remove all range markers + Collection c = chartPanel.getChart().getXYPlot().getRangeMarkers(Layer.FOREGROUND); + if (c != null) { + for (final Object marker : c) { + SwingUtilities.invokeLater(new Runnable() { // Avoid concurrent modification exception + @Override + public void run() { + chartPanel.getChart().getXYPlot().removeRangeMarker((Marker) marker); + } + }); + + } + } + + final ValueMarker marker = new ValueMarker(a, Color.BLACK, new BasicStroke(1)); + marker.setLabel("Average [" + series.getName() + "]: " + String.format("%.6f", a)); + marker.setLabelAnchor(RectangleAnchor.CENTER); + marker.setLabelTextAnchor(TextAnchor.TOP_RIGHT); + + SwingUtilities.invokeLater(new Runnable() { // Avoid concurrent modification exception + @Override + public void run() { + chartPanel.getChart().getXYPlot().addRangeMarker(marker, Layer.FOREGROUND); + } + }); + } + } + }); + toolsMenu.add(averageMenuItem); + + // Mark minimum value + JMenuItem minimumMenuItem = new JMenuItem("Minimum"); + minimumMenuItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + for (LinePlotSeries series : getAllSeries()) { + double[] min = series.getMinimum(); +// System.out.println("Minimum: "+m.getXValue()); + // Remove all annotation for the series + for (Object o : chartPanel.getChart().getXYPlot().getAnnotations()) { + chartPanel.getChart().getXYPlot().removeAnnotation((XYAnnotation) o); + } + XYDrawableAnnotation cross = new XYDrawableAnnotation(min[0], min[1], 10.0, 10.0, new CrossAnnotation(Color.BLACK)); + cross.setToolTipText("Minimum: " + min[0] + " / " + min[1]); + chartPanel.getChart().getXYPlot().addAnnotation(cross); + } + } + }); + toolsMenu.add(minimumMenuItem); + + // Mark maximum value + JMenuItem maximumMenuItem = new JMenuItem("Maximum"); + maximumMenuItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + for (LinePlotSeries series : getAllSeries()) { + double[] max = series.getMaximum(); + // Remove all annotation for the series + for (Object o : chartPanel.getChart().getXYPlot().getAnnotations()) { + chartPanel.getChart().getXYPlot().removeAnnotation((XYAnnotation) o); + } + XYDrawableAnnotation cross = new XYDrawableAnnotation(max[0], max[1], 10.0, 10.0, new CrossAnnotation(Color.BLACK)); + cross.setToolTipText("Maximum: " + max[0] + " / " + max[1]); + chartPanel.getChart().getXYPlot().addAnnotation(cross); + } + } + }); + toolsMenu.add(maximumMenuItem); + + // Show derivative + JMenuItem derivativeMenuItem = new JMenuItem("Derivative"); + derivativeMenuItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + LinePlot p = new LinePlot(); + p.setTitle("Derivative - " + getTitle()); + for (LinePlotSeries series : getAllSeries()) { + double[][] derivative = series.getDerivative(); + LinePlotSeries dseries = new LinePlotSeries(series.getName() + "'"); + p.addSeries(dseries); + dseries.setData(derivative[0], derivative[1]); + } + JFrame frame = new JFrame(); + frame.setContentPane(p.getChartPanel()); + frame.pack(); + RefineryUtilities.centerFrameOnScreen(frame); + frame.setVisible(true); + } + }); + toolsMenu.add(derivativeMenuItem); + + // Show integral + JMenuItem integralMenuItem = new JMenuItem("Integral"); + integralMenuItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + // Show new frame + LinePlot p = new LinePlot(); + p.setTitle("Integral - " + getTitle()); + for (LinePlotSeries series : getAllSeries()) { + double[][] integral = series.getIntegral(); + LinePlotSeries dseries = new LinePlotSeries("integral-" + series.getName()); + p.addSeries(dseries); + dseries.setData(integral[0], integral[1]); + } + JFrame frame = new JFrame(); + frame.setContentPane(p.getChartPanel()); + frame.pack(); + RefineryUtilities.centerFrameOnScreen(frame); + frame.setVisible(true); + } + }); + toolsMenu.add(integralMenuItem); + + /* + chartPanel.getPopupMenu().addSeparator(); + // Detach plot into a separate frame + JMenuItem detachPlotMenuItem = new JMenuItem("Detach"); + detachPlotMenuItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + LinePlot p = new LinePlot(); + p.setTitle(getTitle()); + for (LinePlotSeries series : LinePlot.this.getAllSeries()) { + LinePlotSeries detachedSeries = new LinePlotSeries(series.getName(), series.getColor()); + p.addSeries(detachedSeries); + detachedSeries.setData(series.getX(), series.getY()); + } + + JFrame frame = new JFrame(); + frame.setContentPane(p.getChartPanel()); + frame.pack(); + RefineryUtilities.centerFrameOnScreen(frame); + frame.setVisible(true); + } + }); + chartPanel.getPopupMenu().add(detachPlotMenuItem); + */ + // Hide/Show legend + JMenuItem hideLegendMenuItem = new JMenuItem(showLegendMenuLabel); + hideLegendMenuItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + JMenuItem source = (JMenuItem) (e.getSource()); + + if (source.getText() == showLegendMenuLabel) { + chart.getLegend().setVisible(true); + source.setText(hideLegendMenuLabel); + } else if (source.getText() == hideLegendMenuLabel) { + chart.getLegend().setVisible(false); + source.setText(showLegendMenuLabel); + } + } + }); + chartPanel.getPopupMenu().add(hideLegendMenuItem); + + // Hide/Show tooltips + JMenuItem hideToolTipsMenuItem = new JMenuItem(hideTooltipsMenuLabel); + if (!tooltips) { + hideToolTipsMenuItem.setText(showTooltipsMenuLabel); + } + hideToolTipsMenuItem.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + JMenuItem source = (JMenuItem) (e.getSource()); + if (source.getText() == showTooltipsMenuLabel) { + showTooltips(); + source.setText(hideTooltipsMenuLabel); + } else if (source.getText() == hideTooltipsMenuLabel) { + hideTooltips(); + source.setText(showTooltipsMenuLabel); + } + } + }); + chartPanel.getPopupMenu().add(hideToolTipsMenuItem); + + } + + private void showTooltips() { + tooltips = true; + DecimalFormat dm = new DecimalFormat("0.##########"); + XYToolTipGenerator xYToolTipGenerator = new StandardXYToolTipGenerator("{1}/{2}", dm, dm); + chart.getXYPlot().getRenderer().setBaseToolTipGenerator(xYToolTipGenerator); + chartPanel.setDisplayToolTips(true); + chartPanel.getChartRenderingInfo().setEntityCollection(new StandardEntityCollection()); + } + + private void hideTooltips() { + tooltips = false; + // http://www.jfree.org/phpBB2/viewtopic.php?t=12788&highlight=redraw+speed+performance+problem + chartPanel.getChartRenderingInfo().setEntityCollection(null); + chart.getXYPlot().getRenderer().setBaseToolTipGenerator(null); + } + + protected void addPopupMenuItem(final JMenuItem item) { + if (item == null) { + chartPanel.getPopupMenu().addSeparator(); + } else { + chartPanel.getPopupMenu().add(item); + } + } + /* + @Override + protected void doUpdate() + if (data != null) { + SwingUtilities.invokeLater(new Runnable() { // Try to avoid concurrent modification exception + @Override + public void run() { + try { + for (XYSeries s : data.getSeries()) { + s.fireSeriesChanged(); + } + } catch (ConcurrentModificationException e) { + logger.log(Level.WARNING, "Series got modified concurrently: " + e.getMessage(), e); + } + } + }); + } + } + */ + /* + //Trash + @Override + public void setData(Object data) { + super.setData(data); + this.data = (XYSeriesCollection) data; + } + */ +} diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/jfree/ManualScaleDialog.java b/ch.psi.plot/src/main/java/ch/psi/plot/jfree/ManualScaleDialog.java new file mode 100644 index 0000000..172d237 --- /dev/null +++ b/ch.psi.plot/src/main/java/ch/psi/plot/jfree/ManualScaleDialog.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved. + */ +package ch.psi.plot.jfree; + +import ch.psi.plot.jfree.MatrixPlot; +import java.awt.BorderLayout; +import java.awt.FlowLayout; + +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.border.EmptyBorder; +import javax.swing.JTextField; +import javax.swing.JLabel; +import java.awt.Font; +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; + +/** + * + */ +public class ManualScaleDialog extends JDialog { + + // Default serial id + private static final long serialVersionUID = 1L; + + private final JPanel contentPanel = new JPanel(); + private JTextField textFieldHighValue; + private JTextField textFieldLowValue; + + private MatrixPlot plot; + + private int selectedOption; + + /** + * Launch the application. + */ + public static void main(String[] args) { + try { + ManualScaleDialog dialog = new ManualScaleDialog(); + dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); + dialog.setVisible(true); + System.out.println("HERE"); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Create the dialog. + */ + public ManualScaleDialog() { + setModal(true); // Block until dialog is disposed. + setBounds(100, 100, 450, 300); + getContentPane().setLayout(new BorderLayout()); + contentPanel.setLayout(new FlowLayout()); + contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5)); + getContentPane().add(contentPanel, BorderLayout.CENTER); + { + JLabel lblLowValue = new JLabel("Low Value:"); + lblLowValue.setFont(new Font("Lucida Grande", Font.BOLD, 13)); + contentPanel.add(lblLowValue); + } + { + textFieldLowValue = new JTextField(); + contentPanel.add(textFieldLowValue); + textFieldLowValue.setColumns(10); + } + { + JLabel lblHighValue = new JLabel("High Value:"); + lblHighValue.setFont(new Font("Lucida Grande", Font.BOLD, 13)); + contentPanel.add(lblHighValue); + } + { + textFieldHighValue = new JTextField(); + contentPanel.add(textFieldHighValue); + textFieldHighValue.setColumns(10); + } + { + JPanel buttonPane = new JPanel(); + buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT)); + getContentPane().add(buttonPane, BorderLayout.SOUTH); + { + JButton okButton = new JButton("OK"); + okButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent arg0) { + // set OK + selectedOption = JOptionPane.OK_OPTION; + dispose(); + } + }); + { + JButton btnApply = new JButton("Apply"); + btnApply.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent arg0) { + // TODO apply values + if (plot != null) { + plot.setColorScale(getLow(), getHigh()); + } + } + }); + buttonPane.add(btnApply); + } + okButton.setActionCommand("OK"); + buttonPane.add(okButton); + getRootPane().setDefaultButton(okButton); + } + { + JButton cancelButton = new JButton("Cancel"); + cancelButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent arg0) { + // set Cancel + selectedOption = JOptionPane.CANCEL_OPTION; + dispose(); + } + }); + cancelButton.setActionCommand("Cancel"); + buttonPane.add(cancelButton); + } + } + + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + pack(); + } + + public void showDialog() { + setVisible(true); + } + + public void setMatrixPlot(MatrixPlot p) { + plot = p; + } + + public void setLow(double low) { + textFieldLowValue.setText(String.format("%.4f", low)); + } + + public void setHigh(double high) { + textFieldHighValue.setText(String.format("%.4f", high)); + } + + public double getLow() { + double low = Double.NaN; + try { + low = Double.parseDouble(textFieldLowValue.getText()); + } catch (NumberFormatException e) { + } + return low; + } + + public double getHigh() { + double high = Double.NaN; + try { + high = Double.parseDouble(textFieldHighValue.getText()); + } catch (NumberFormatException e) { + } + return high; + } + + /** + * @return the selectedOption + */ + public int getSelectedOption() { + return selectedOption; + } + +} diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/jfree/MatrixPlot.java b/ch.psi.plot/src/main/java/ch/psi/plot/jfree/MatrixPlot.java new file mode 100644 index 0000000..fbff4c3 --- /dev/null +++ b/ch.psi.plot/src/main/java/ch/psi/plot/jfree/MatrixPlot.java @@ -0,0 +1,490 @@ +package ch.psi.plot.jfree; + +import ch.psi.plot.MatrixPlotBase; +import ch.psi.plot.MatrixPlotSeries; +import java.awt.Color; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.text.DecimalFormat; +import java.util.Arrays; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import org.jfree.chart.ChartPanel; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.event.AxisChangeEvent; +import org.jfree.chart.event.AxisChangeListener; +import org.jfree.chart.labels.StandardXYZToolTipGenerator; +import org.jfree.chart.labels.XYZToolTipGenerator; +import org.jfree.chart.plot.XYPlot; +import org.jfree.chart.renderer.LookupPaintScale; +import org.jfree.chart.renderer.PaintScale; +import org.jfree.chart.renderer.xy.XYBlockRenderer; +import org.jfree.chart.title.PaintScaleLegend; +import org.jfree.data.Range; +import org.jfree.data.xy.DefaultXYZDataset; +import org.jfree.ui.RectangleAnchor; +import org.jfree.ui.RectangleEdge; +import org.jfree.ui.RectangleInsets; + +/** + * Returns a matrix plot panel + */ +public class MatrixPlot extends MatrixPlotBase { + + private static final int chartPanelWidth = 500; + private static final int chartPanelHeight = 270; + + private boolean grayScale = false; + + private MatrixPlotSeries series; + private DefaultXYZDataset data; + private JFreeChart chart; + private ChartPanel chartPanel; + + double[] xvalues = new double[0]; + double[] yvalues = new double[0]; + double[] zvalues = new double[0]; + + /** + * Constructor + * + * @param title + * @param data + */ + XYPlot plot; + final NumberAxis xAxis, yAxis; + final XYBlockRenderer renderer; + + public MatrixPlot() { + super(); + // Create matrix chart + // Init size of plot area according to min and max set in the datas metadata + // Set axis: (plus half bin size on both sides), since we plot the bins centered. + xAxis = new NumberAxis(""); + yAxis = new NumberAxis(""); + + // Configure block renderer to have the blocks rendered in the correct size + renderer = new XYBlockRenderer(); + renderer.setBaseCreateEntities(false); + plot = new XYPlot(null, xAxis, yAxis, renderer); + + // Remove background paint/color + plot.setBackgroundPaint(null); + + // Set the maximum zoom out to the initial zoom rate This also + // provides a workaround for dynamic plots because there zoom out does not work correctly (zoom out to infinity) + plot.getRangeAxis().addChangeListener(new AxisChangeListener() { + @Override + public void axisChanged(AxisChangeEvent event) { + if (series == null) { + return; + } + ValueAxis axis = ((ValueAxis) event.getAxis()); + if (axis.getLowerBound() < yMin || axis.getUpperBound() > yMax) { + Range range = new Range(yMin, yMax); + axis.setRange(range, true, false); + } + } + }); + plot.getDomainAxis().addChangeListener(new AxisChangeListener() { + @Override + public void axisChanged(AxisChangeEvent event) { + if (series == null) { + return; + } + ValueAxis axis = ((ValueAxis) event.getAxis()); + if (axis.getLowerBound() < xMin || axis.getUpperBound() > xMax) { + Range range = new Range(xMin, xMax); + axis.setRange(range, true, false); + } + } + }); + + } + + double xMin, xMax, yMin, yMax; + + @Override + protected Object onAddedSeries(MatrixPlotSeries series) { + this.series = series; + int arraylength = series.getNumberOfBinsX() * series.getNumberOfBinsY(); + xvalues = new double[arraylength]; + yvalues = new double[arraylength]; + zvalues = new double[arraylength]; + Arrays.fill(xvalues, Double.NEGATIVE_INFINITY); + Arrays.fill(yvalues, Double.NEGATIVE_INFINITY); + Arrays.fill(zvalues, Double.NEGATIVE_INFINITY); + double[][] dataArray = new double[][]{xvalues, yvalues, zvalues}; + //Create the XYDataset (org.jfree), not to be confused with the ch.psi dataSet) + data = new DefaultXYZDataset(); + data.addSeries("Data", dataArray); + + onAxisRangeChanged(AxisId.X); + onAxisRangeChanged(AxisId.Y); + xAxis.setLabel(getAxis(AxisId.X).getLabel()); + yAxis.setLabel(getAxis(AxisId.Y).getLabel()); + + renderer.setBlockWidth(series.getBinWidthX()); // If this is not set the default block size is 1 + renderer.setBlockHeight(series.getBinWidthY()); // If this is not set the default block size is 1 + renderer.setBlockAnchor(RectangleAnchor.CENTER); + + // Remove background paint/color + plot.setBackgroundPaint(null); + + plot.setDataset(data); + + return data; + } + + @Override + protected void onAxisRangeChanged(AxisId axis_id) { + // The axis min and max values need to be half a bin larger. Otherwise the outer pixels + // will not be plotted correctly (half of the pixel is missing) + if (axis_id == AxisId.X) { + if (getAxis(AxisId.X).isAutoRange()) { + xMin = series.getMinX() - 0.5 * series.getBinWidthX(); + xMax = series.getMaxX() + 0.5 * series.getBinWidthX(); + } else { + xMin = getAxis(AxisId.X).getMin(); + xMax = getAxis(AxisId.X).getMax(); + } + xAxis.setLowerBound(xMin); + xAxis.setUpperBound(xMax); + } + if (axis_id == AxisId.Y) { + if (getAxis(AxisId.Y).isAutoRange()) { + yMin = series.getMinY() - 0.5 * series.getBinWidthY(); + yMax = series.getMaxY() + 0.5 * series.getBinWidthY(); + } else { + yMin = getAxis(AxisId.Y).getMin(); + yMax = getAxis(AxisId.Y).getMax(); + } + yAxis.setLowerBound(yMin); + yAxis.setUpperBound(yMax); + } + } + + @Override + protected void onRemovedSeries(MatrixPlotSeries s) { + series = null; + doUpdate(); + } + + @Override + protected void onAppendData(MatrixPlotSeries series, int indexX, int indexY, double x, double y, double z) { + final int index = indexY * series.getNumberOfBinsX() + indexX; + //x Value is column, y value is row + xvalues[index] = x; + yvalues[index] = y; + zvalues[index] = z; + } + + @Override + protected void onSetData(MatrixPlotSeries series, double[][] data) { + int index = 0; + for (int y = 0; y < data.length; y++) { + for (int x = 0; x < data[0].length; x++) { + //final int index = y * series.getNumberOfBinsX() + x; + xvalues[index] = series.getMinX() + series.getBinWidthX() * x; + yvalues[index] = series.getMinY() + series.getBinWidthY() * y; + zvalues[index++] = data[y][x]; + } + } + } + + @Override + public void clear() { + if (series != null) { + removeSeries(series); + doUpdate(); + } + } + + @Override + public double[][] getSeriesData(MatrixPlotSeries s) { + int x = series.getNumberOfBinsX(); + int y = series.getNumberOfBinsY(); + double[][] ret = new double[y][x]; + int index = 0; + for (int i = 0; i < y; i++) { + for (int j = 0; j < x; j++) { + ret[i][j] = data.getZValue(0, index++); + } + } + return ret; + } + + // Action Classes that implement methods called after keyboard input + /** + * Adapt the context menu of the chart panel + */ + private void adaptContextMenu(final ChartPanel chartPanel) { + + // Show hide tooltips + final String tooltipsMenuLabel = "Tooltips"; + final String hideTooltipsMenuLabel = "Hide Tooltips"; + JMenuItem contextMenuItemToolTip = new JMenuItem(tooltipsMenuLabel); + contextMenuItemToolTip.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + JMenuItem source = (JMenuItem) (e.getSource()); + if (source.getText() == tooltipsMenuLabel) { + showTooltip(); + source.setText(hideTooltipsMenuLabel); + } else if (source.getText() == hideTooltipsMenuLabel) { + hideTooltip(); + source.setText(tooltipsMenuLabel); + } + } + }); + chartPanel.getPopupMenu().add(contextMenuItemToolTip); + + // Update colormap + JMenuItem contextMenuItemAdaptScale = new JMenuItem("Update Scale"); + contextMenuItemAdaptScale.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + adaptColorMapScale(); + } + }); + + // Set gray scale colormap + JMenuItem contextMenuItemGrayScale = new JMenuItem("Gray Scale"); + contextMenuItemGrayScale.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + grayScale = true; + adaptColorMapScale(); + } + }); + + // Set color colormap + JMenuItem contextMenuItemTemperatureColor = new JMenuItem("Color Scale"); + contextMenuItemTemperatureColor.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + grayScale = false; + adaptColorMapScale(); + } + }); + + // Set color colormap + JMenuItem menuItemScale = new JMenuItem("Manual Scale"); + menuItemScale.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + ManualScaleDialog d = new ManualScaleDialog(); + d.setLocationRelativeTo(chartPanel); + d.setLow(((PaintScaleLegend) chart.getSubtitles().get(0)).getScale().getLowerBound()); + d.setHigh(((PaintScaleLegend) chart.getSubtitles().get(0)).getScale().getUpperBound()); + d.setMatrixPlot(MatrixPlot.this); + + d.showDialog(); + if (d.getSelectedOption() == JOptionPane.OK_OPTION) { + setColorScale(d.getLow(), d.getHigh()); + } + } + }); + + // Group colormap related menu items + JMenuItem contextMenuChooseColorMap = new JMenu("ColorMap"); + contextMenuChooseColorMap.add(contextMenuItemAdaptScale); + contextMenuChooseColorMap.add(menuItemScale); + contextMenuChooseColorMap.add(contextMenuItemGrayScale); + contextMenuChooseColorMap.add(contextMenuItemTemperatureColor); + chartPanel.getPopupMenu().add(contextMenuChooseColorMap); + /* + // Add separator + chartPanel.getPopupMenu().addSeparator(); + + + // Detach plot into an own frame + JMenuItem contextMenuItemDetach = new JMenuItem("Detach Plot"); + contextMenuItemDetach.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + MatrixPlot p = new MatrixPlot(); + p.setTitle(title); + p.setSeries(series); + + final JFrame frame = new JFrame(title); + frame.getContentPane(); + frame.setContentPane(p.getChartPanel()); + frame.pack(); + frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); // Close application if frame is closed + + // Set color scale + p.adaptColorMapScale(); + + java.awt.EventQueue.invokeLater(new Runnable() { + public void run() { + frame.setVisible(true); + } + }); + } + }); + chartPanel.getPopupMenu().add(contextMenuItemDetach); + */ + } + + /** + * Show Tooltips. This is not done per default since it makes the app slow + * for datasize >= 1M + */ + private void showTooltip() { + //Tooltips are quit expensive + DecimalFormat dm = new DecimalFormat("0.##########"); + XYZToolTipGenerator xYZToolTipGenerator = new StandardXYZToolTipGenerator("{0}: ({1} / {2} / {3})", dm, dm, dm); + + chart.getXYPlot().getRenderer().setBaseToolTipGenerator(xYZToolTipGenerator); + ((XYBlockRenderer) chart.getXYPlot().getRenderer()).setBaseCreateEntities(true); + } + + /** + * Clear Tooltips + */ + private void hideTooltip() { + //Tooltips are quit expensive + ((XYBlockRenderer) chart.getXYPlot().getRenderer()).setBaseToolTipGenerator(null); + ((XYBlockRenderer) chart.getXYPlot().getRenderer()).setBaseCreateEntities(false); + + } + + /** + * Adapt the lower and upper color map scale to the min and max data values + * of the currently selected region Need to be called AFTER the chart panel + * is created + */ + public void adaptColorMapScale() { + double[] v = series.minMaxZValue(); + if (v[0] != Double.NaN && v[1] != Double.NaN && v[0] < v[1]) { + setColorScale(v[0], v[1]); + } + } + + /** + * Set the min and max of color map scale to scaleMin and scaleMax + * + * @param scaleMin min value of scale + * @param scaleMax max value of scale + */ + public void setColorScale(double scaleMin, double scaleMax) { + + // Create scale for legend + LookupPaintScale legendScale = new LookupPaintScale(scaleMin, scaleMax, Color.GRAY); + setScaleColors(legendScale, scaleMin, scaleMax); + + // Create legend + PaintScaleLegend legend = new PaintScaleLegend(legendScale, new NumberAxis()); + legend.setPadding(new RectangleInsets(5, 5, 5, 5)); + // Width of the legend (colorbar) + legend.setStripWidth(20); + // Position of the legend + legend.setPosition(RectangleEdge.RIGHT); + // Remove background paint/color + legend.setBackgroundPaint(null); + + // Add legend to plot panel + chart.clearSubtitles(); + chart.addSubtitle(legend); + + //We need a second scale for rendering only, where the 'infinities' are in correct color + LookupPaintScale rendererScale = new LookupPaintScale(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Color.GRAY); + setScaleColors(rendererScale, scaleMin, scaleMax); + // Make the paint scale range from - to + infinity + if (grayScale) { + rendererScale.add(Double.NEGATIVE_INFINITY, ColorManager.getGrayForValue(scaleMin, scaleMin, scaleMax)); + rendererScale.add(Double.POSITIVE_INFINITY, ColorManager.getGrayForValue(scaleMax, scaleMin, scaleMax)); + } else { + rendererScale.add(Double.NEGATIVE_INFINITY, ColorManager.getColourForValue(scaleMin, scaleMin, scaleMax)); + rendererScale.add(Double.POSITIVE_INFINITY, ColorManager.getColourForValue(scaleMax, scaleMin, scaleMax)); + } + ((XYBlockRenderer) chart.getXYPlot().getRenderer()).setPaintScale(rendererScale); + } + + /** + * Set the colors for the colored Paint Scale (either single color or + * temperature color) + * + * @param paintScale + * @param scaleMin + * @param scaleMax + */ + private void setScaleColors(PaintScale paintScale, double scaleMin, double scaleMax) { + if (grayScale) { + for (int i = 0; i < 256; i++) { + double value = scaleMin + (i / 255.0) * (scaleMax - scaleMin); + ((LookupPaintScale) paintScale).add(value, ColorManager.getGrayForValue(value, scaleMin, scaleMax)); + } + } else { + for (int i = 0; i < 256; i++) { + double value = scaleMin + (i / 255.0) * (scaleMax - scaleMin); + ((LookupPaintScale) paintScale).add(value, ColorManager.getColourForValue(value, scaleMin, scaleMax)); + } + } + } + + /** + * Get the chart panel + * + * @return + */ + @Override + protected JPanel createChartPanel() { + chart = new JFreeChart(getTitle(), plot); + + //Remove the series label (also called legend) + chart.removeLegend(); + //AntiAliasing is used to speed up rendering +// chart.setAntiAlias(false); + + // Init PaintScale + setColorScale(0, 1); + + //Create the Chartpanel where the chart will be plotted + chartPanel = new ChartPanel(chart); + + chartPanel.setPreferredSize(new java.awt.Dimension(chartPanelWidth, chartPanelHeight)); + + //All interactive menu items + adaptContextMenu(chartPanel); + return chartPanel; + } + + /* (non-Javadoc) + * @see ch.psi.plot.Plot#update() + */ + @Override + public void doUpdate() { + if (chart != null) { + chart.fireChartChanged(); + adaptColorMapScale(); + } + } + + @Override + public void updateSeries(MatrixPlotSeries series) { + doUpdate(); + } + + protected void addPopupMenuItem(final JMenuItem item) { + if (item == null) { + chartPanel.getPopupMenu().addSeparator(); + } else { + chartPanel.getPopupMenu().add(item); + } + } + + //public JFreeChart getChart() { + // return chart; + //} + //@Override + //public void setData(Object data){ + // super.setData(data); + // this.data=(MatrixPlotSeries) data; + //} +} diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/jlchart/LinePlot.java b/ch.psi.plot/src/main/java/ch/psi/plot/jlchart/LinePlot.java new file mode 100644 index 0000000..56df9c7 --- /dev/null +++ b/ch.psi.plot/src/main/java/ch/psi/plot/jlchart/LinePlot.java @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved. + */ +package ch.psi.plot.jlchart; + +import ch.psi.plot.LinePlotBase; +import ch.psi.plot.LinePlotSeries; +import ch.psi.plot.utils.MonitoredPanel; +import fr.esrf.tangoatk.widget.util.chart.DataList; +import fr.esrf.tangoatk.widget.util.chart.JLAxis; +import fr.esrf.tangoatk.widget.util.chart.JLChart; +import fr.esrf.tangoatk.widget.util.chart.JLDataView; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.util.ArrayList; +import javax.swing.JMenuItem; +import javax.swing.JPanel; + +/** + * + */ +public class LinePlot extends LinePlotBase { + + final JLChart plot; + + final ArrayList views = new ArrayList<>(); + + public LinePlot() { + super(); + plot = new JLChart(); + plot.getXAxis().setAnnotation(JLAxis.VALUE_ANNO); + //plot.getXAxis().setLabelFormat(JLAxis.SCIENTIFIC_FORMAT); + plot.getY1Axis().setAutoScale(true); + plot.getY2Axis().setAutoScale(true); + plot.getXAxis().setAutoScale(true); + plot.getY1Axis().setGridVisible(true); + plot.getXAxis().setGridVisible(true); + + /* + plot.getY1Axis().setAutoScale(false); + plot.getY2Axis().setAutoScale(false); + plot.getXAxis().setAutoScale(false); + plot.getY1Axis().setMinimum(0); + plot.getY1Axis().setMaximum(10); + plot.getY2Axis().setMinimum(0); + plot.getY2Axis().setMaximum(10); + plot.getXAxis().setMinimum(0); + plot.getXAxis().setMaximum(10); + */ + plot.setLabelVisible(false); + plot.setBackground(new Color(240, 240, 240)); + setRequireUpdateOnAppend(false); + } + + @Override + protected void onAxisRangeChanged(AxisId axis_id) { + JLAxis axis = null; + switch (axis_id) { + case X: + axis = plot.getXAxis(); + break; + case Y: + axis = plot.getY1Axis(); + break; + default: + return; + } + axis.setAutoScale(getAxis(axis_id).isAutoRange()); + axis.setMinimum(getAxis(axis_id).getMin()); + axis.setMaximum(getAxis(axis_id).getMax()); + update(true); + } + + @Override + protected Object onAddedSeries(LinePlotSeries series) { + JLDataView view = new JLDataView(); + + view.setColor(series.getColor()); + //view.setLineWidth(1); + + int markerSize = 4; + view.setName(series.getName()); + view.setMarkerSize(markerSize); + view.setMarkerColor(series.getColor()); + + view.setViewType(JLDataView.TYPE_LINE); + + if (markerSize > 0) { + view.setMarker(JLDataView.MARKER_DOT); + } else { + view.setMarker(JLDataView.MARKER_NONE); + } + + if (series.getAxisY() == 2) { + plot.getY2Axis().addDataView(view); + } else { + plot.getY1Axis().addDataView(view); + } + return view; + } + + JLDataView getDataView(LinePlotSeries series) { + return (JLDataView) (series.getToken()); + } + + @Override + protected void onRemovedSeries(LinePlotSeries series) { + JLDataView view = getDataView(series); + for (int i = 0; i < plot.getY1Axis().getViewNumber(); i++) { + if (view.getName().equals(plot.getY1Axis().getDataView(i).getName())) { + plot.getY1Axis().removeDataView(view); + } + + } + for (int i = 0; i < plot.getY2Axis().getViewNumber(); i++) { + if (view.getName().equals(plot.getY2Axis().getDataView(i).getName())) { + plot.getY2Axis().removeDataView(view); + } + } + } + + @Override + protected void onAppendData(LinePlotSeries series, double x, double y) { + JLDataView view = getDataView(series); + if (view != null) //view.add(x, y); + { + plot.addData(view, x, y); + } + } + + @Override + protected void onSetData(LinePlotSeries series, double[] x, double[] y) { + JLDataView view = getDataView(series); + if (view != null) { + view.setData(x, y); + } + } + + @Override + public double[][] getSeriesData(LinePlotSeries series) { + JLDataView view = getDataView(series); + double[] x = new double[view.getDataLength()]; + double[] y = new double[x.length]; + int index = 0; + DataList data = view.getData(); + while (data != null) { + if (index >= x.length) { + break; + } + x[index] = data.x; + y[index] = data.y; + index++; + data = data.next; + } + return new double[][]{x, y}; + } + + JPanel chartPanel; + + @Override + protected JPanel createChartPanel() { + JPanel chartPanel = new MonitoredPanel() { + protected void onShown() { + addKeyBindings(); + } + }; + + chartPanel.setLayout(new BorderLayout()); + chartPanel.add(plot); + chartPanel.setPreferredSize(new Dimension(480, 240)); + + plot.setHeader(getTitle()); + plot.getY1Axis().setName(getAxis(AxisId.Y).getLabel()); + plot.getXAxis().setName(getAxis(AxisId.Y).getLabel()); + return chartPanel; + } + + @Override + public void updateSeries(LinePlotSeries series) { + doUpdate();//TODO + } + + @Override + public void doUpdate() { + plot.repaint(); + } + + private void addKeyBindings() { + //The zoom method ois not doing what I expecte, and no documentation... + /* + plot.setFocusable( true ); + plot.requestFocusInWindow(); + plot.addKeyListener(new KeyListener() { + + @Override + public void keyTyped(KeyEvent e) { + } + + @Override + public void keyPressed(KeyEvent e) { + doUpdate(); + System.out.println("Total " + plot.getXAxis().getMinimum() + "->" + plot.getXAxis().getMaximum()); + System.out.println("Zoom " + plot.getXAxis().getMin() + "->" + plot.getXAxis().getMax()); + if (plot.isZoomed()){ + if (e.getKeyCode()==KeyEvent.VK_RIGHT){ + double w = plot.getXAxis().getMax()-plot.getXAxis().getMin(); + double r = plot.getXAxis().getMax() + w/10; + //r = Math.min(r,plot.getXAxis().getMaximum()); + plot.getXAxis().zoom((int)(r-w),(int)r); + System.out.println("Zooming to " + ((int)(r-w)) + "-" + ((int)r)); + requestUpdate(); + + } + else if (e.getKeyCode()==KeyEvent.VK_LEFT){ + double w = plot.getXAxis().getMax()-plot.getXAxis().getMin(); + double l = plot.getXAxis().getMin() - w/10; + //l = Math.max(l,plot.getXAxis().getMinimum()); + plot.getXAxis().zoom((int)l,(int)(l+w)); + System.out.println("Zooming to " + ((int)l) + "-" + ((int)(l+w))); + requestUpdate(); + } + } + } + + @Override + public void keyReleased(KeyEvent e) { + + } + }); + */ + } + + protected void addPopupMenuItem(final JMenuItem item) { + if (item == null) { + plot.addSeparator(); + } else { + plot.addMenuItem(item); + } + } + +} diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/jzy3d/MatrixPlot.java b/ch.psi.plot/src/main/java/ch/psi/plot/jzy3d/MatrixPlot.java new file mode 100644 index 0000000..eba2bd9 --- /dev/null +++ b/ch.psi.plot/src/main/java/ch/psi/plot/jzy3d/MatrixPlot.java @@ -0,0 +1,856 @@ +/* + * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved. + */ +package ch.psi.plot.jzy3d; + +import ch.psi.plot.MatrixPlotBase; +import ch.psi.plot.MatrixPlotSeries; +import ch.psi.plot.utils.IO; +import ch.psi.plot.utils.MonitoredPanel; +import ch.psi.plot.utils.SwingUtils; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.ButtonGroup; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.SwingUtilities; +import org.jzy3d.chart.Chart; +import org.jzy3d.chart.Settings; +import org.jzy3d.colors.Color; +import org.jzy3d.colors.ColorMapper; +import org.jzy3d.colors.colormaps.ColorMapGrayscale; +import org.jzy3d.colors.colormaps.ColorMapRainbow; +import org.jzy3d.contour.DefaultContourColoringPolicy; +import org.jzy3d.contour.IContourColoringPolicy; +import org.jzy3d.contour.MapperContourPictureGenerator; +import org.jzy3d.maths.BoundingBox3d; +import org.jzy3d.maths.Coord3d; +import org.jzy3d.maths.Range; +import org.jzy3d.plot3d.builder.Builder; +import org.jzy3d.plot3d.builder.Mapper; +import org.jzy3d.plot3d.builder.concrete.OrthonormalGrid; +import org.jzy3d.plot3d.primitives.AbstractDrawable; +import org.jzy3d.plot3d.primitives.Point; +import org.jzy3d.plot3d.primitives.Polygon; +import org.jzy3d.plot3d.primitives.ScatterMultiColor; +import org.jzy3d.plot3d.primitives.Shape; +import org.jzy3d.plot3d.primitives.axes.ContourAxeBox; +import org.jzy3d.plot3d.rendering.legends.colorbars.AWTColorbarLegend; +import org.jzy3d.plot3d.rendering.view.modes.ViewBoundMode; + +/** + * + */ +public class MatrixPlot extends MatrixPlotBase { + + JPanel panel; + private Chart chart; + private Mapper mapper; + private Shape surface; + private MatrixPlotSeries series; + private double[][] data; + + public MatrixPlot() { + super(); + panel = new MonitoredPanel() { + protected void onShown() { + checkBounds(true); + } + }; + panel.setLayout(new BorderLayout()); + //panel.setLayout(new GridLayout(1,1)); + setColormap(Colormap.TEMPERATURE); + Settings.getInstance().setHardwareAccelerated(true); + panel.setPreferredSize(new Dimension(640, 480)); + setupPopupMenu(); + } + + @Override + protected Object onAddedSeries(final MatrixPlotSeries s) { + if (!SwingUtilities.isEventDispatchThread()) { + try { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + onAddedSeries(s); + } + }); + } catch (Exception ex) { + Logger.getLogger(MatrixPlot.class.getName()).log(Level.SEVERE, null, ex); + } + return this; + } + + synchronized (chartLock) { + if (s != null) { + if (chart != null) { + chart.clear(); + } + } + + if (s == null) { + //if (chart != null) { + //chart.clear(); + //} + series = null; + data = null; + } else { + if (getAxis(AxisId.X).isAutoRange()) { + rangeX = new Range(s.getMinX(), s.getMaxX()); + } else { + rangeX = new Range(getAxis(AxisId.X).getMin(), getAxis(AxisId.X).getMax()); + } + if (getAxis(AxisId.Y).isAutoRange()) { + rangeY = new Range(s.getMinY(), s.getMaxY()); + } else { + rangeY = new Range(getAxis(AxisId.Y).getMin(), getAxis(AxisId.Y).getMax()); + } + //If same series & same dimensions then preserve data + if ((data == null) || (series != s) || (s.getNumberOfBinsY() != data.length) || (s.getNumberOfBinsX() != data[0].length)) { + data = new double[s.getNumberOfBinsY()][s.getNumberOfBinsX()]; + for (int i = 0; i < data.length; i++) { + Arrays.fill(data[i], Double.NaN); + } + } + series = s; + } + } + createGraph(); + return this; + } + + @Override + protected void onAxisRangeChanged(AxisId axis_id) { + if (series != null) { + updateGraph(true); + } + } + + @Override + protected void onRemovedSeries(MatrixPlotSeries s) { + series = null; + if (chart != null) { + chart.clear(); + } + } + + @Override + protected void onAppendData(MatrixPlotSeries s, int indexX, int indexY, double x, double y, double z) { + data[indexY][indexX] = z; + } + + @Override + protected void onSetData(MatrixPlotSeries s, double[][] data) { + this.data = data; + } + + @Override + public void doUpdate() { + updateGraph(false); + } + + public void updateSeries(MatrixPlotSeries s) { + updateGraph(false); + } + + @Override + public double[][] getSeriesData(MatrixPlotSeries s) { + return data; + } + + @Override + protected JPanel createChartPanel() { + return panel; + } + + private Range rangeX; + private Range rangeY; + double[] rangeZ = null; + + boolean showLegend = true; + + public void setShowLegend(boolean value) { + if (value != showLegend) { + showLegend = value; + if ((panel != null) && (panel.isShowing())) { + updateGraph(true); + } + } + } + + public boolean getShowLegend() { + return showLegend; + } + + boolean showFace = true; + + public void setShowFace(boolean value) { + if (value != showFace) { + showFace = value; + if ((panel != null) && (panel.isShowing())) { + updateGraph(true); + } + } + } + + public boolean getShowFace() { + return showFace; + } + + boolean showFrame = false; + + public void setShowFrame(boolean value) { + if (value != showFrame) { + showFrame = value; + if ((panel != null) && (panel.isShowing())) { + updateGraph(true); + } + } + } + + public boolean getShowFrame() { + return showFrame; + } + + boolean showAxis = true; + + public void setShowAxis(boolean value) { + if (value != showAxis) { + showAxis = value; + if ((panel != null) && (panel.isShowing())) { + updateGraph(true); + } + } + } + + public boolean getShowAxis() { + return showAxis; + } + + public enum Colormap { + + GRAYSCALE, + TEMPERATURE, + } + Colormap colormap = Colormap.TEMPERATURE; + + public void setColormap(Colormap value) { + if (value != colormap) { + colormap = value; + if ((panel != null) && (panel.isShowing())) { + updateGraph(true); + } + } + } + + public Colormap getColormap() { + return colormap; + } + + public enum Quality { + + LOW, + MEDIUM, + HIGH, + HIGHEST; + + private org.jzy3d.plot3d.rendering.canvas.Quality toJzy3dQuality() { + switch (this) { + case LOW: + return org.jzy3d.plot3d.rendering.canvas.Quality.Fastest; + case MEDIUM: + return org.jzy3d.plot3d.rendering.canvas.Quality.Intermediate; + case HIGH: + return org.jzy3d.plot3d.rendering.canvas.Quality.Advanced; + case HIGHEST: + return org.jzy3d.plot3d.rendering.canvas.Quality.Nicest; + } + return null; + } + } + Quality quality = Quality.HIGH; + + public void setQuality(Quality quality) { + this.quality = quality; + if (series != null) { + createGraph(); + } + } + + public Quality getQuality() { + return quality; + } + + public enum Mode { + + TOP, + PROFILE, + FREE; + + private org.jzy3d.plot3d.rendering.view.modes.ViewPositionMode toJzy3dMode() { + switch (this) { + case TOP: + return org.jzy3d.plot3d.rendering.view.modes.ViewPositionMode.TOP; + case PROFILE: + return org.jzy3d.plot3d.rendering.view.modes.ViewPositionMode.PROFILE; + case FREE: + return org.jzy3d.plot3d.rendering.view.modes.ViewPositionMode.FREE; + } + return null; + } + } + Mode mode = Mode.FREE; + + public void setMode(Mode mode) { + this.mode = mode; + if (series != null) { + updateGraph(true); + } + } + + public Mode getMode() { + return mode; + } + + public enum Contour { + + NONE, + NORMAL, + FILLED, + HEIGHT_MAP, + CONTOUR_3D + + } + Contour contour = Contour.NONE; + + public void setContour(Contour contour) { + this.contour = contour; + if (series != null) { + createGraph(); + } + } + + public Contour getContour() { + return contour; + } + + int contourLevels = 10; + + public void setContourLevels(int value) { + contourLevels = value; + updateGraph(true); + } + + public int getContourLevels() { + return contourLevels; + } + + int contourDensity = 400; + + public void setContourDensity(int value) { + contourDensity = value; + updateGraph(true); + } + + public int getContourDensity() { + return contourDensity; + } + + java.awt.Color frameColor = java.awt.Color.BLACK; + + public void setFrameColor(java.awt.Color value) { + frameColor = value; + updateGraph(true); + } + + public java.awt.Color getFrameColor() { + return frameColor; + } + + JPopupMenu menuPopup; + + void setupPopupMenu() { + menuPopup = new JPopupMenu(); + JMenuItem menuUpdate = new JMenuItem("Update"); + final JCheckBoxMenuItem menuShowAxis = new JCheckBoxMenuItem("Show Axis"); + final JCheckBoxMenuItem menuShowLegend = new JCheckBoxMenuItem("Show Legend"); + final JCheckBoxMenuItem menuShowFace = new JCheckBoxMenuItem("Show Face"); + final JCheckBoxMenuItem menuShowFrame = new JCheckBoxMenuItem("Show Frame"); + JMenuItem frameColor = new JMenuItem("Set Frame Color"); + + final JMenu menuColormap = new JMenu("Colormap"); + final JMenu menuMode = new JMenu("Mode"); + final JMenu menuContour = new JMenu("Contour"); + final JMenu menuQuality = new JMenu("Quality"); + menuPopup.add(menuShowAxis); + menuPopup.add(menuShowLegend); + menuPopup.add(menuShowFace); + menuPopup.add(menuShowFrame); + menuPopup.add(frameColor); + menuPopup.add(menuColormap); + menuPopup.add(menuMode); + menuPopup.add(menuContour); + menuPopup.add(menuQuality); + menuPopup.add(menuUpdate); + menuUpdate.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + updateGraph(true); + } catch (Exception ex) { + } + } + }); + + frameColor.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + String ret = SwingUtils.getString(panel, "Enter frame color (name or R,G,B):", getFrameColor().getRed() + "," + getFrameColor().getGreen() + "," + getFrameColor().getBlue()); + if (ret != null) { + java.awt.Color color = null; + if (ret.contains(",")) { + String[] tokens = ret.split(","); + color = new java.awt.Color(Integer.valueOf(tokens[0]), Integer.valueOf(tokens[1]), Integer.valueOf(tokens[2])); + } else { + Field field = java.awt.Color.class.getField(ret); + color = (java.awt.Color) field.get(null); + } + setFrameColor(color); + updateGraph(true); + } + } catch (Exception ex) { + SwingUtils.showException(panel, ex); + } + } + }); + + menuShowFrame.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + setShowFrame(!getShowFrame()); + menuShowFrame.setSelected(getShowFrame()); + } + }); + menuShowFrame.setSelected(getShowFrame()); + + menuShowLegend.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + setShowLegend(!getShowLegend()); + menuShowLegend.setSelected(getShowLegend()); + } + }); + menuShowLegend.setSelected(getShowLegend()); + + menuShowFace.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + setShowFace(!getShowFace()); + menuShowLegend.setSelected(getShowFace()); + } + }); + menuShowFace.setSelected(getShowFace()); + + menuShowAxis.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + setShowAxis(!getShowAxis()); + menuShowAxis.setSelected(getShowAxis()); + } + }); + menuShowAxis.setSelected(getShowAxis()); + + ButtonGroup colormapGroup = new ButtonGroup(); + for (Colormap c : Colormap.values()) { + final JRadioButtonMenuItem menuItem = new JRadioButtonMenuItem(c.toString()); + colormapGroup.add(menuItem); + menuItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + setColormap(Colormap.valueOf(e.getActionCommand())); + } + }); + menuItem.setSelected(getColormap().toString().equals(menuItem.getText())); + menuColormap.add(menuItem); + } + + ButtonGroup modeGroup = new ButtonGroup(); + for (Mode q : Mode.values()) { + final JRadioButtonMenuItem menuItem = new JRadioButtonMenuItem(q.toString()); + modeGroup.add(menuItem); + menuItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + setMode(Mode.valueOf(e.getActionCommand())); + } + }); + menuItem.setSelected(getMode().toString().equals(menuItem.getText())); + menuMode.add(menuItem); + } + + ButtonGroup contourGroup = new ButtonGroup(); + for (Contour q : Contour.values()) { + final JRadioButtonMenuItem menuItem = new JRadioButtonMenuItem(q.toString()); + contourGroup.add(menuItem); + menuItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + setContour(Contour.valueOf(e.getActionCommand())); + } + }); + menuItem.setSelected(getContour().toString().equals(menuItem.getText())); + menuContour.add(menuItem); + } + menuContour.addSeparator(); + JMenuItem levels = new JMenuItem("Set Levels"); + levels.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + String ret = SwingUtils.getString(panel, "Enter number of contour levels:", getContourLevels()); + if (ret != null) { + Integer levels = Integer.valueOf(ret); + setContourLevels(levels); + } + } catch (Exception ex) { + SwingUtils.showException(panel, ex); + } + } + }); + menuContour.add(levels); + + JMenuItem density = new JMenuItem("Set Density"); + density.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + String ret = SwingUtils.getString(panel, "Enter contour density:", getContourDensity()); + if (ret != null) { + Integer density = Integer.valueOf(ret); + setContourDensity(density); + } + } catch (Exception ex) { + SwingUtils.showException(panel, ex); + } + } + }); + menuContour.add(density); + + ButtonGroup qualityGroup = new ButtonGroup(); + for (Quality q : Quality.values()) { + final JRadioButtonMenuItem menuItem = new JRadioButtonMenuItem(q.toString()); + qualityGroup.add(menuItem); + menuItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + setQuality(Quality.valueOf(e.getActionCommand())); + } + }); + menuItem.setSelected(getQuality().toString().equals(menuItem.getText())); + menuQuality.add(menuItem); + } + } + + protected static void remap(Shape shape, Mapper mapper) { + List polygons = shape.getDrawables(); + for (AbstractDrawable d : polygons) { + if (d instanceof Polygon) { + Polygon p = (Polygon) d; + for (int i = 0; i < p.size(); i++) { + Point pt = p.get(i); + Coord3d c = pt.xyz; + c.z = (float) mapper.f(c.x, c.y); + } + } + } + } + + final Object chartLock = new Object(); + + void createGraph() { /* + if (!SwingUtilities.isEventDispatchThread()) { + try { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + createGraph(); + } + }); + } catch (Exception ex) { + Logger.getLogger(MatrixPlot.class.getName()).log(Level.SEVERE, null, ex); + } + } + */ + + synchronized (chartLock) { + if (series != null) { + if ((getContour() == Contour.NONE) || (getContour() == Contour.CONTOUR_3D)) { + chart = org.jzy3d.chart.factories.ContourChartComponentFactory.chart(getQuality().toJzy3dQuality(), "awt"); + } else { + chart = new org.jzy3d.chart.factories.ContourChartComponentFactory().newChart(getQuality().toJzy3dQuality(), "awt"); + } + + if (rangeY == null) { + rangeY = new Range(0, data.length - 1); + } + if (rangeX == null) { + rangeX = new Range(0, data[0].length - 1); + } + mapper = new Mapper() { + @Override + public double f(double x, double y) { + if (data == null) { + return Double.NaN; + } + return data[(int) Math.round((y - rangeY.getMin()) / ((rangeY.getMax() - rangeY.getMin()) / (data.length - 1)))][(int) Math.round((x - rangeX.getMin()) / ((rangeX.getMax() - rangeX.getMin()) / (data[0].length - 1)))]; + + } + }; + Component canvas = (Component) chart.getCanvas(); + panel.removeAll(); + panel.add(canvas); + + //Todo: why it is not displyed if I don'r pack the Window? + if (panel.isVisible()) { + panel.validate(); + } + + chart.addMouseController(); + chart.getAxeLayout().setXAxeLabel(getAxis(AxisId.X).getLabel()); + chart.getAxeLayout().setYAxeLabel(getAxis(AxisId.Y).getLabel()); + chart.getAxeLayout().setZAxeLabel(getAxis(AxisId.Z).getLabel()); + + chart.getCanvas().addMouseController(new MouseAdapter() { + @Override + public void mouseReleased(MouseEvent e) { + checkPopup(e); + } + + @Override + public void mousePressed(MouseEvent e) { + checkPopup(e); + } + + private void checkPopup(MouseEvent e) { + if (e.isPopupTrigger()) { + menuPopup.show(e.getComponent(), e.getX(), e.getY()); + } + } + }); + } + + updateGraph(true); + } + + } + + private void updateGraph(final boolean newSeries) { + if (!SwingUtilities.isEventDispatchThread()) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + updateGraph(newSeries); + } + }); + return; + } +//long start = System.currentTimeMillis(); + synchronized (chartLock) { + Shape former = surface; + if (series == null) { + if (surface != null) { + chart.getScene().getGraph().remove(former, false); + } + surface = null; + } else { + + //TODO: Not succeding having the partial updates - and they are not performing much better neither + boolean changedBoundsZ = checkBounds(false); + if ((surface == null) || (newSeries) || getAxis(AxisId.Z).isAutoRange() || changedBoundsZ) { + //if (true) { + surface = (Shape) Builder.buildOrthonormal( + new OrthonormalGrid(rangeX, series.getNumberOfBinsX(), rangeY, series.getNumberOfBinsY()), mapper); + ColorMapper colorMapper = new ColorMapper((colormap == Colormap.TEMPERATURE) ? new ColorMapRainbow() : new ColorMapGrayscale(), + (float) ((getAxis(AxisId.Z).isAutoRange()) ? surface.getBounds().getZmin() : getAxis(AxisId.Z).getMin()), + (float) ((getAxis(AxisId.Z).isAutoRange()) ? surface.getBounds().getZmax() : getAxis(AxisId.Z).getMax()), + new Color(1, 1, 1, .5f)); + surface.setColorMapper(colorMapper); + surface.setFaceDisplayed(true); + surface.setWireframeDisplayed(getShowFrame()); + + surface.setWireframeColor(new Color(frameColor.getRed(), frameColor.getGreen(), frameColor.getBlue(), frameColor.getAlpha())); + surface.setFaceDisplayed(getShowFace()); + if (getShowLegend()) { + AWTColorbarLegend cbar = new AWTColorbarLegend(surface, chart.getView().getAxe().getLayout()); + surface.setLegend(cbar); + } + + if (getContour() != Contour.NONE) { + int xRes = getContourDensity(); + int yRes = getContourDensity(); + + MapperContourPictureGenerator contour = new MapperContourPictureGenerator(mapper, rangeX, rangeY); + IContourColoringPolicy policy = new DefaultContourColoringPolicy(colorMapper); + ContourAxeBox cab = (getContour() == Contour.CONTOUR_3D) ? null : (ContourAxeBox) chart.getView().getAxe(); + + switch (getContour()) { + case NORMAL: + cab.setContourImg(contour.getContourImage(policy, xRes, yRes, getContourLevels()), rangeX, rangeY); + break; + case FILLED: + cab.setContourImg(contour.getFilledContourImage(policy, xRes, yRes, getContourLevels()), rangeX, rangeY); + break; + case HEIGHT_MAP: + cab.setContourImg(contour.getHeightMap(policy, xRes, yRes, getContourLevels()), rangeX, rangeY); + break; + case CONTOUR_3D: + //int nx=series.getNumberOfBinsX(); + //int ny=series.getNumberOfBinsY(); + + float dx = ((float) series.getNumberOfBinsX()) / xRes; + float dy = ((float) series.getNumberOfBinsY()) / yRes; + double[][] contours = contour.getContourMatrix(xRes, yRes, getContourLevels()); + // Create the dot cloud scene and fill with data + int size = xRes * yRes; + Coord3d[] points = new Coord3d[size]; + for (int x = 0; x < xRes; x++) { + for (int y = 0; y < yRes; y++) { + float px = (float) ((float) x * dx * series.getBinWidthX() + series.getMinX()); + float py = (float) ((float) y * dy * series.getBinWidthY() + series.getMinY()); + + if (contours[x][y] > -Double.MAX_VALUE) { // Non contours points are -Double.MAX_VALUE and are not painted + points[x * yRes + y] = new Coord3d(px, py, (float) contours[x][y]); + } else { + points[x * yRes + y] = new Coord3d(px, py, Float.NaN); + //points[x*ny+y] = new Coord3d((float)x * series.getBinWidthX()+ series.getMinX(),(float)y* series.getBinWidthY()+ series.getMinY(),(float)0.0); + + //points[x*ny+y] = new Coord3d((float)x * series.getBinWidthX()+ series.getMinX(),(float)y* series.getBinWidthY()+ series.getMinY(),(float)mapper.f((float)x * series.getBinWidthX()+ series.getMinX(), (float)y* series.getBinWidthY()+ series.getMinY())); + } + } + } + //ScatterMultiColor scatter = new ScatterMultiColor( points, new ColorMapper( new ColorMapRainbow(), -600.0f, 600.0f ) ); + ScatterMultiColor scatter = new ScatterMultiColor(points, colorMapper); + surface.add(scatter); + //chart.getScene().add(scatter); + break; + } + } + chart.setViewMode(getMode().toJzy3dMode()); + chart.setAxeDisplayed(getShowAxis()); + } + + if (surface == former) { + remap(surface, mapper); + chart.render(); + } else { + + chart.getScene().getGraph().add(surface, false); + if (former != null) { + chart.getScene().getGraph().remove(former, false); + } + boolean changed = checkBounds(true); + //if (!changed) + // chart.getView().updateBounds(); + + } + } +//System.out.println(System.currentTimeMillis()-start); + } + } + + protected boolean checkBounds(boolean updateBounds) { + if (chart == null) { + return false; + } + boolean changed = false; + //If manual bounds + if (!getAxis(AxisId.X).isAutoRange() || !getAxis(AxisId.Y).isAutoRange() || !getAxis(AxisId.Z).isAutoRange()) { + //Deferring setting bounds untiul the panel is displayed + if (panel.isShowing() && (chart != null)) { + if (chart.getView().getBoundsMode() != ViewBoundMode.MANUAL) { + changed = true; + } + BoundingBox3d bounds = chart.getView().getBounds(); + if (!getAxis(AxisId.X).isAutoRange()) { + if (bounds.getXmin() != getAxis(AxisId.X).getMin()) { + bounds.setXmin((float) getAxis(AxisId.X).getMin()); + changed = true; + } + if (bounds.getXmax() != getAxis(AxisId.X).getMax()) { + bounds.setXmax((float) getAxis(AxisId.X).getMax()); + changed = true; + } + } + if (!getAxis(AxisId.Y).isAutoRange()) { + if (bounds.getYmin() != getAxis(AxisId.Y).getMin()) { + bounds.setYmin((float) getAxis(AxisId.Y).getMin()); + changed = true; + } + if (bounds.getYmax() != getAxis(AxisId.Y).getMax()) { + bounds.setYmax((float) getAxis(AxisId.Y).getMax()); + changed = true; + } + } + if (!getAxis(AxisId.Z).isAutoRange()) { + if (bounds.getZmin() != getAxis(AxisId.Z).getMin()) { + bounds.setZmin((float) getAxis(AxisId.Z).getMin()); + changed = true; + } + if (bounds.getZmax() != getAxis(AxisId.Z).getMax()) { + bounds.setZmax((float) getAxis(AxisId.Z).getMax()); + changed = true; + } + } + if (changed && updateBounds) { + chart.getView().setBoundManual(bounds); + } + } + } else if (chart.getView().getBoundsMode() != ViewBoundMode.AUTO_FIT) { + if (updateBounds) { + chart.getView().setBoundMode(ViewBoundMode.AUTO_FIT); + } + changed = true; + } + + return changed; + } + + protected void addPopupMenuItem(final JMenuItem item) { + if (item == null) { + menuPopup.addSeparator(); + } else { + menuPopup.add(item); + } + } + + @Override + public BufferedImage getSnapshot() { + + File temp=null; + try{ + temp = File.createTempFile("snapshot", ".bmp"); + chart.screenshot(temp); + return IO.readImageFromFile(temp.getAbsolutePath()); + } + catch (Exception ex){ + return null; + } + finally{ + if (temp!=null) + temp.delete(); + } + } + + public void saveSnapshot(String filename, String format) throws IOException { + if (chart!=null){ + chart.screenshot(new File(filename)); + } + } + +} diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/utils/IO.java b/ch.psi.plot/src/main/java/ch/psi/plot/utils/IO.java new file mode 100644 index 0000000..17664ae --- /dev/null +++ b/ch.psi.plot/src/main/java/ch/psi/plot/utils/IO.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved. + */ +package ch.psi.plot.utils; + +import java.awt.image.BufferedImage; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; +import javax.imageio.ImageIO; + +/** + * + */ +public class IO { + + public static void writeArrayToFile(String filename, byte arr[]) throws IOException { + + OutputStream fout = null; + try { + fout = new BufferedOutputStream(new FileOutputStream(filename, false)); + if (arr != null) { + new PrintStream(fout).write(arr, 0, arr.length); + } + fout.flush(); + } finally { + if (fout != null) { + fout.close(); + } + } + } + + public static void writeStringToFile(String filename, String str) throws IOException { + writeArrayToFile(filename, str.getBytes("UTF-8")); + } + + public static void writeImageToFile(BufferedImage image, String filename, String format) throws IOException { + if (image != null) { + ImageIO.write(image, format, new File(filename)); + } + } + + public static BufferedImage readImageFromFile(String filename) throws IOException { + return ImageIO.read(new File(filename)); + } + + public static String getExtension(File f) { + String ext = null; + String s = f.getName(); + int i = s.lastIndexOf('.'); + + if (i > 0 && i < s.length() - 1) { + ext = s.substring(i + 1).toLowerCase(); + } + return ext; + } +} diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/utils/MonitoredPanel.java b/ch.psi.plot/src/main/java/ch/psi/plot/utils/MonitoredPanel.java new file mode 100644 index 0000000..ccb8e19 --- /dev/null +++ b/ch.psi.plot/src/main/java/ch/psi/plot/utils/MonitoredPanel.java @@ -0,0 +1,41 @@ +package ch.psi.plot.utils; + +/* + * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved. + */ +import java.awt.event.HierarchyEvent; +import java.awt.event.HierarchyListener; +import javax.swing.JPanel; + +/** + * + */ +public class MonitoredPanel extends JPanel { + + public MonitoredPanel() { + addHierarchyListener(new HierarchyListener() { + @Override + public void hierarchyChanged(HierarchyEvent e) { + if ((HierarchyEvent.SHOWING_CHANGED & e.getChangeFlags()) != 0) { + if (isShowing()) { + try { + onShown(); + } catch (Exception ex) { + } + } else { + try { + onHidden(); + } catch (Exception ex) { + } + } + } + } + }); + } + + protected void onShown() { + } + + protected void onHidden() { + } +} diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/utils/SwingUtils.java b/ch.psi.plot/src/main/java/ch/psi/plot/utils/SwingUtils.java new file mode 100644 index 0000000..bc86eaa --- /dev/null +++ b/ch.psi.plot/src/main/java/ch/psi/plot/utils/SwingUtils.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved. + */ +package ch.psi.plot.utils; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.Toolkit; +import java.awt.image.BufferedImage; +import java.util.Random; +import javax.swing.JOptionPane; + +/** + * + */ +public class SwingUtils { + + public static void centerOnParent(Component parent, Component component) { + Rectangle r = parent.getBounds(); + Dimension w = component.getSize(); + int x = Math.max(r.x + (r.width - w.width) / 2, 4); + int y = Math.max(r.y + (r.height - w.height) / 2, 4); + component.setLocation(x, y); + } + + public static void centerOnScreen(Component component) { + Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); + component.setLocation(dim.width / 2 - component.getSize().width / 2, dim.height / 2 - component.getSize().height / 2); + } + + public static Color generateRandomColor() { + Random random = new Random(); + + Color mix = Color.WHITE; + int red = (random.nextInt(256) + mix.getRed()) / 2; + int green = (random.nextInt(256) + mix.getGreen()) / 2; + int blue = (random.nextInt(256) + mix.getBlue()) / 2; + + Color color = new Color(red, green, blue); + return color; + } + + public static void showMessage(Component parent, String title, String msg) { + JOptionPane.showMessageDialog(parent, msg, title, JOptionPane.INFORMATION_MESSAGE, null); + } + + public static void showException(Component parent, Exception ex) { + JOptionPane.showMessageDialog(parent, ex.getMessage(), "Exception", JOptionPane.WARNING_MESSAGE, null); + } + + public static String getString(Component parent, String msg, Object current_value) { + return JOptionPane.showInputDialog(parent, msg, String.valueOf(current_value)); + } + + public static BufferedImage createImage(Component panel) { + if (panel == null) { + return null; + } + Dimension size = panel.getSize(); + BufferedImage image = new BufferedImage( + size.width, size.height, BufferedImage.TYPE_INT_RGB); + Graphics2D g2 = image.createGraphics(); + panel.paint(g2); + return image; + } +} diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/xy/LinePlot.java b/ch.psi.plot/src/main/java/ch/psi/plot/xy/LinePlot.java deleted file mode 100644 index b77ae1f..0000000 --- a/ch.psi.plot/src/main/java/ch/psi/plot/xy/LinePlot.java +++ /dev/null @@ -1,472 +0,0 @@ -package ch.psi.plot.xy; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.KeyEvent; -import java.text.DecimalFormat; -import java.util.Collection; -import java.util.ConcurrentModificationException; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.swing.AbstractAction; -import javax.swing.JComponent; -import javax.swing.JFrame; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.KeyStroke; -import javax.swing.SwingUtilities; - -import org.jfree.chart.ChartFactory; -import org.jfree.chart.ChartPanel; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.annotations.XYAnnotation; -import org.jfree.chart.annotations.XYDrawableAnnotation; -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.entity.StandardEntityCollection; -import org.jfree.chart.labels.StandardXYToolTipGenerator; -import org.jfree.chart.labels.XYToolTipGenerator; -import org.jfree.chart.plot.Marker; -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.chart.plot.ValueMarker; -import org.jfree.chart.plot.XYPlot; -import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; -import org.jfree.data.Range; -import org.jfree.data.xy.XYDataItem; -import org.jfree.ui.Layer; -import org.jfree.ui.RectangleAnchor; -import org.jfree.ui.RefineryUtilities; -import org.jfree.ui.TextAnchor; - -import ch.psi.plot.Plot; -import ch.psi.plot.xy.tools.Average; -import ch.psi.plot.xy.tools.CrossAnnotation; -import ch.psi.plot.xy.tools.Derivative; -import ch.psi.plot.xy.tools.Integral; -import ch.psi.plot.xy.tools.Maximum; -import ch.psi.plot.xy.tools.Minimum; - -public class LinePlot implements Plot { - - private static final Logger logger = Logger.getLogger(LinePlot.class.getName()); - - private ChartPanel chartPanel; - - private static final int chartPanelWidth = 500; - private static final int chartPanelHeight = 270; - - //Defining Context Menu Label - private static final String showLegendMenuLabel = "Show Legend"; - private static final String hideLegendMenuLabel = "Hide Legend"; - private static final String showTooltipsMenuLabel = "Show Tooltips"; - private static final String hideTooltipsMenuLabel = "Hide Tooltips"; - - - private XYSeriesCollectionP data; - - JFreeChart chart; - - private String title; - private String xAxisLabel = "X"; - private String yAxisLabel = "Y"; - - private boolean tooltips = false; - - /** - * @param title Title of plot - */ - public LinePlot(String title){ - this(title, new XYSeriesCollectionP()); - } - - - /** - * @param title Title of plot - * @param data Data of plot - */ - public LinePlot(String title, XYSeriesCollectionP data){ - this.title = title; - this.data = data; - } - - - /** - * Get the chart panel of this plot. The chart panel will be lazily created - * the first time this function is called - * @return - */ - @Override - public ChartPanel getChartPanel() { - if(chartPanel == null){ - - // Create chart - chart = ChartFactory.createXYLineChart(this.title, xAxisLabel, yAxisLabel, data, PlotOrientation.VERTICAL, true, tooltips, false); - - // Customize chart look and feel - // Customize background (gray: new Color(238,238,238)) - chart.setBackgroundPaint(null); - - // Customize legend - chart.getLegend().setVisible(false); - chart.getLegend().setBackgroundPaint(null); - chart.getLegend().setBorder(0, 0, 0, 0); - - // Customize plot area look and feel - XYPlot plot = (XYPlot) chart.getPlot(); - plot.setBackgroundPaint(Color.white); - plot.setDomainGridlinePaint(Color.gray); - plot.setRangeGridlinePaint(Color.gray); - - // Show data point - ((XYLineAndShapeRenderer)plot.getRenderer()).setBaseShapesVisible(true); - - // Include zeros in range (x) axis - ((NumberAxis) plot.getRangeAxis()).setAutoRangeIncludesZero(false); - - // Lazy creation of the chart panel - chartPanel = new ChartPanel(chart); - chartPanel.setName(title); - - // Remove border - chartPanel.getChart().setBorderVisible(false); - - // Set size of chart - chartPanel.setPreferredSize(new java.awt.Dimension(chartPanelWidth, chartPanelHeight)); - - // Add more items to the context menu - amendContextMenu(); - - //Activate (arrow) keys - addKeyBindings(); - } - return chartPanel; - } - - /** - * Change visible part of chart - * @param translationVector - */ - private void moverOverPlot(XYDataItem translationVector) { - double translatedDomainIntervalMin = chart.getXYPlot().getDomainAxis().getRange().getLowerBound() + translationVector.getX().doubleValue(); - double translatedDomainIntervalMax = chart.getXYPlot().getDomainAxis().getRange().getUpperBound() + translationVector.getX().doubleValue(); - double translatedRangeIntervalMin = chart.getXYPlot().getRangeAxis().getRange().getLowerBound() + translationVector.getY().doubleValue(); - double translatedRangeIntervalMax = chart.getXYPlot().getRangeAxis().getRange().getUpperBound() + translationVector.getY().doubleValue(); - - Range domainAxisRange = new Range(translatedDomainIntervalMin, translatedDomainIntervalMax); - Range rangeAxisRange = new Range(translatedRangeIntervalMin, translatedRangeIntervalMax); - //We set notify to false in the first call.. - chart.getXYPlot().getDomainAxis().setRange(domainAxisRange, true, false); - //...and true in the last - chart.getXYPlot().getRangeAxis().setRange(rangeAxisRange, true, true); - - } - - /** - * Add key bindings to chart panel - */ - private void addKeyBindings(){ - final String moveUpKey = "move up"; - final String moveDownKey = "move down"; - final String moveRightKey = "move right"; - final String moveLeftKey = "move left"; - - // Up arrow - chartPanel.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), moveUpKey); - chartPanel.getActionMap().put(moveUpKey, new AbstractAction() { - // Default serial id - private static final long serialVersionUID = 1L; - @Override - public void actionPerformed(ActionEvent e) { - moverOverPlot(new XYDataItem(0.0, ((NumberAxis)chart.getXYPlot().getRangeAxis()).getTickUnit().getSize())); - } - }); - - // Down arrow - chartPanel.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0),moveDownKey); - chartPanel.getActionMap().put(moveDownKey, new AbstractAction() { - // Default serial id - private static final long serialVersionUID = 1L; - @Override - public void actionPerformed(ActionEvent e) { - moverOverPlot(new XYDataItem(0.0, - ((NumberAxis)chart.getXYPlot().getRangeAxis()).getTickUnit().getSize())); - } - }); - - // Right arrow - chartPanel.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0),moveRightKey); - chartPanel.getActionMap().put(moveRightKey, new AbstractAction() { - // Default serial id - private static final long serialVersionUID = 1L; - @Override - public void actionPerformed(ActionEvent e) { - moverOverPlot(new XYDataItem(((NumberAxis)chart.getXYPlot().getDomainAxis()).getTickUnit().getSize(), 0.0)); - } - }); - - // Left arrow - chartPanel.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0),moveLeftKey); - chartPanel.getActionMap().put(moveLeftKey, new AbstractAction() { - // Default serial id - private static final long serialVersionUID = 1L; - @Override - public void actionPerformed(ActionEvent e) { - moverOverPlot(new XYDataItem(- ((NumberAxis)chart.getXYPlot().getDomainAxis()).getTickUnit().getSize(), 0.0)); - } - }); - } - - /** - * Add additional items to the context menu of the plot - */ - public void amendContextMenu(){ - - chartPanel.getPopupMenu().addSeparator(); - - JMenu toolsMenu = new JMenu("Tools"); - chartPanel.getPopupMenu().add(toolsMenu); - - // Mark average - JMenuItem averageMenuItem = new JMenuItem("Average"); - averageMenuItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - Average average = new Average(); - for (XYSeriesP series : data.getSeries()) { - double a = average.average(series); - // Remove all range markers - Collection c = chartPanel.getChart().getXYPlot().getRangeMarkers(Layer.FOREGROUND); - if(c!=null){ - for(final Object marker: c){ - SwingUtilities.invokeLater(new Runnable() { // Avoid concurrent modification exception - @Override - public void run() { - chartPanel.getChart().getXYPlot().removeRangeMarker((Marker) marker); - } - }); - - } - } - - final ValueMarker marker = new ValueMarker(a, Color.BLACK, new BasicStroke(1)); - marker.setLabel("Average ["+series.getKey()+"]: "+String.format("%.6f", a)); - marker.setLabelAnchor(RectangleAnchor.CENTER); - marker.setLabelTextAnchor(TextAnchor.TOP_RIGHT); - - SwingUtilities.invokeLater(new Runnable() { // Avoid concurrent modification exception - @Override - public void run() { - chartPanel.getChart().getXYPlot().addRangeMarker(marker, Layer.FOREGROUND); - } - }); - } - } - }); - toolsMenu.add(averageMenuItem); - - - // Mark minimum value - JMenuItem minimumMenuItem = new JMenuItem("Minimum"); - minimumMenuItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - Minimum minimum = new Minimum(); - for (XYSeriesP series : data.getSeries()) { - XYDataItem m = minimum.minimum(series); -// System.out.println("Minimum: "+m.getXValue()); - // Remove all annotation for the series - for(Object o: chartPanel.getChart().getXYPlot().getAnnotations()){ - chartPanel.getChart().getXYPlot().removeAnnotation((XYAnnotation) o); - } - XYDrawableAnnotation cross = new XYDrawableAnnotation(m.getXValue(), m.getYValue(), 10.0, 10.0, new CrossAnnotation(Color.BLACK)); - cross.setToolTipText("Minimum: "+m.getXValue() +" / "+ m.getYValue()); - chartPanel.getChart().getXYPlot().addAnnotation(cross); - } - } - }); - toolsMenu.add(minimumMenuItem); - - - // Mark maximum value - JMenuItem maximumMenuItem = new JMenuItem("Maximum"); - maximumMenuItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - Maximum maximum = new Maximum(); - for (XYSeriesP series : data.getSeries()) { - XYDataItem m = maximum.maximum(series); - // Remove all annotation for the series - for(Object o: chartPanel.getChart().getXYPlot().getAnnotations()){ - chartPanel.getChart().getXYPlot().removeAnnotation((XYAnnotation) o); - } - XYDrawableAnnotation cross = new XYDrawableAnnotation(m.getXValue(), m.getYValue(), 10.0, 10.0, new CrossAnnotation(Color.BLACK)); - cross.setToolTipText("Maximum: "+m.getXValue() +" / "+ m.getYValue()); - chartPanel.getChart().getXYPlot().addAnnotation(cross); - } - } - }); - toolsMenu.add(maximumMenuItem); - - - // Show derivative - JMenuItem derivativeMenuItem = new JMenuItem("Derivative"); - derivativeMenuItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - Derivative derivative = new Derivative(); - LinePlot p = new LinePlot("Derivative - " + title, derivative.derivative(data)); - - JFrame frame = new JFrame(); - frame.setContentPane(p.getChartPanel()); - frame.pack(); - RefineryUtilities.centerFrameOnScreen(frame); - frame.setVisible(true); - } - }); - toolsMenu.add(derivativeMenuItem); - - // Show integral - JMenuItem integralMenuItem = new JMenuItem("Integral"); - integralMenuItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - Integral integral = new Integral(); - - // Show new frame - LinePlot p = new LinePlot("Integral - "+title, integral.integral(data)); - - JFrame frame = new JFrame(); - frame.setContentPane(p.getChartPanel()); - frame.pack(); - RefineryUtilities.centerFrameOnScreen(frame); - frame.setVisible(true); - } - }); - toolsMenu.add(integralMenuItem); - - chartPanel.getPopupMenu().addSeparator(); - - // Detach plot into a separate frame - JMenuItem detachPlotMenuItem = new JMenuItem("Detach"); - detachPlotMenuItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - LinePlot p = new LinePlot(title, data); - - JFrame frame = new JFrame(); - frame.setContentPane(p.getChartPanel()); - frame.pack(); - RefineryUtilities.centerFrameOnScreen(frame); - frame.setVisible(true); - } - }); - chartPanel.getPopupMenu().add(detachPlotMenuItem); - - // Hide/Show legend - JMenuItem hideLegendMenuItem = new JMenuItem(showLegendMenuLabel); - hideLegendMenuItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - JMenuItem source = (JMenuItem)(e.getSource()); - - if(source.getText() == showLegendMenuLabel){ - chart.getLegend().setVisible(true); - source.setText(hideLegendMenuLabel); - } - - else if(source.getText() == hideLegendMenuLabel){ - chart.getLegend().setVisible(false); - source.setText(showLegendMenuLabel); - } - } - }); - chartPanel.getPopupMenu().add(hideLegendMenuItem); - - // Hide/Show tooltips - JMenuItem hideToolTipsMenuItem = new JMenuItem(hideTooltipsMenuLabel); - if(!tooltips){ - hideToolTipsMenuItem.setText(showTooltipsMenuLabel); - } - hideToolTipsMenuItem.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - JMenuItem source = (JMenuItem)(e.getSource()); - if(source.getText() == showTooltipsMenuLabel){ - showTooltips(); - source.setText(hideTooltipsMenuLabel); - } - - else if(source.getText() == hideTooltipsMenuLabel){ - hideTooltips(); - source.setText(showTooltipsMenuLabel); - } - } - }); - chartPanel.getPopupMenu().add(hideToolTipsMenuItem); - - - - } - - private void showTooltips(){ - tooltips = true; - DecimalFormat dm = new DecimalFormat("0.##########"); - XYToolTipGenerator xYToolTipGenerator = new StandardXYToolTipGenerator( "{1}/{2}", dm, dm); - chart.getXYPlot().getRenderer().setBaseToolTipGenerator(xYToolTipGenerator); - chartPanel.setDisplayToolTips(true); - chartPanel.getChartRenderingInfo().setEntityCollection(new StandardEntityCollection()); - } - - private void hideTooltips(){ - tooltips = false; - // http://www.jfree.org/phpBB2/viewtopic.php?t=12788&highlight=redraw+speed+performance+problem - chartPanel.getChartRenderingInfo().setEntityCollection(null); - chart.getXYPlot().getRenderer().setBaseToolTipGenerator(null); - } - - - @Override - public void update() { - if(data != null){ - SwingUtilities.invokeLater(new Runnable() { // Try to avoid concurrent modification exception - @Override - public void run() { - try{ - for(XYSeriesP s:data.getSeries()){ - s.fireSeriesChanged(); - } - } - catch(ConcurrentModificationException e){ - logger.log(Level.WARNING, "Series got modified concurrently: "+e.getMessage(), e); - } - } - }); - } - - } - - @Override - public JFreeChart getChart() { - return chart; - } - - // Getter and setter - public XYSeriesCollectionP getData() { - return data; - } - public String getxAxisLabel() { - return xAxisLabel; - } - public void setxAxisLabel(String xAxisLabel) { - this.xAxisLabel = xAxisLabel; - } - public String getyAxisLabel() { - return yAxisLabel; - } - public void setyAxisLabel(String yAxisLabel) { - this.yAxisLabel = yAxisLabel; - } -} - diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/xy/XYSeriesCollectionP.java b/ch.psi.plot/src/main/java/ch/psi/plot/xy/XYSeriesCollectionP.java deleted file mode 100644 index 53a4eab..0000000 --- a/ch.psi.plot/src/main/java/ch/psi/plot/xy/XYSeriesCollectionP.java +++ /dev/null @@ -1,626 +0,0 @@ -/* =========================================================== - * JFreeChart : a free chart library for the Java(tm) platform - * =========================================================== - * - * (C) Copyright 2000-2009, by Object Refinery Limited and Contributors. - * - * Project Info: http://www.jfree.org/jfreechart/index.html - * - * This library 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 2.1 of the License, or - * (at your option) any later version. - * - * This library 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 this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. - * - * [Java is a trademark or registered trademark of Sun Microsystems, Inc. - * in the United States and other countries.] - * - * ----------------------- - * XYSeriesCollection.java - * ----------------------- - * (C) Copyright 2001-2009, by Object Refinery Limited and Contributors. - * - * Original Author: David Gilbert (for Object Refinery Limited); - * Contributor(s): Aaron Metzger; - * - * Changes - * ------- - * 15-Nov-2001 : Version 1 (DG); - * 03-Apr-2002 : Added change listener code (DG); - * 29-Apr-2002 : Added removeSeries, removeAllSeries methods (ARM); - * 07-Oct-2002 : Fixed errors reported by Checkstyle (DG); - * 26-Mar-2003 : Implemented Serializable (DG); - * 04-Aug-2003 : Added getSeries() method (DG); - * 31-Mar-2004 : Modified to use an XYIntervalDelegate. - * 05-May-2004 : Now extends AbstractIntervalXYDataset (DG); - * 18-Aug-2004 : Moved from org.jfree.data --> org.jfree.data.xy (DG); - * 17-Nov-2004 : Updated for changes to DomainInfo interface (DG); - * 11-Jan-2005 : Removed deprecated code in preparation for 1.0.0 release (DG); - * 28-Mar-2005 : Fixed bug in getSeries(int) method (1170825) (DG); - * 05-Oct-2005 : Made the interval delegate a dataset listener (DG); - * ------------- JFREECHART 1.0.x --------------------------------------------- - * 27-Nov-2006 : Added clone() override (DG); - * 08-May-2007 : Added indexOf(XYSeries) method (DG); - * 03-Dec-2007 : Added getSeries(Comparable) method (DG); - * 22-Apr-2008 : Implemented PublicCloneable (DG); - * 27-Feb-2009 : Overridden getDomainOrder() to detect when all series are - * sorted in ascending order (DG); - * 06-Mar-2009 : Implemented RangeInfo (DG); - * 06-Mar-2009 : Fixed equals() implementation (DG); - * - */ - -package ch.psi.plot.xy; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.jfree.data.DomainInfo; -import org.jfree.data.DomainOrder; -import org.jfree.data.Range; -import org.jfree.data.RangeInfo; -import org.jfree.data.UnknownKeyException; -import org.jfree.data.general.DatasetChangeEvent; -import org.jfree.data.xy.AbstractIntervalXYDataset; -import org.jfree.data.xy.IntervalXYDataset; -import org.jfree.data.xy.IntervalXYDelegate; -import org.jfree.data.xy.XYDataItem; - -/** - * Represents a collection of {@link XYSeries} objects that can be used as a - * dataset. - */ -public class XYSeriesCollectionP extends AbstractIntervalXYDataset - implements IntervalXYDataset, DomainInfo, RangeInfo, - Serializable { - - /** For serialization. */ - private static final long serialVersionUID = -7590013825931496766L; - - /** The series that are included in the collection. */ - private List data; - - /** The interval delegate (used to calculate the start and end x-values). */ - private IntervalXYDelegate intervalDelegate; - - /** - * Constructs an empty dataset. - */ - public XYSeriesCollectionP() { - this(null); - } - - /** - * Constructs a dataset and populates it with a single series. - * - * @param series the series (null ignored). - */ - public XYSeriesCollectionP(XYSeriesP series) { - this.data = new ArrayList(); - this.intervalDelegate = new IntervalXYDelegate(this, false); - addChangeListener(this.intervalDelegate); - if (series != null) { - this.data.add(series); - series.addChangeListener(this); - } - } - - /** - * Returns the order of the domain (X) values, if this is known. - * - * @return The domain order. - */ - public DomainOrder getDomainOrder() { - return DomainOrder.NONE; // No specific order -// return DomainOrder.ASCENDING; - } - - /** - * Adds a series to the collection and sends a {@link DatasetChangeEvent} - * to all registered listeners. - * - * @param series the series (null not permitted). - */ - public void addSeries(XYSeriesP series) { - if (series == null) { - throw new IllegalArgumentException("Null 'series' argument."); - } - this.data.add(series); - series.addChangeListener(this); - fireDatasetChanged(); - } - - /** - * Removes a series from the collection and sends a - * {@link DatasetChangeEvent} to all registered listeners. - * - * @param series the series index (zero-based). - */ - public void removeSeries(int series) { - if ((series < 0) || (series >= getSeriesCount())) { - throw new IllegalArgumentException("Series index out of bounds."); - } - - // fetch the series, remove the change listener, then remove the series. - XYSeriesP ts = (XYSeriesP) this.data.get(series); - ts.removeChangeListener(this); - this.data.remove(series); - fireDatasetChanged(); - } - - /** - * Removes a series from the collection and sends a - * {@link DatasetChangeEvent} to all registered listeners. - * - * @param series the series (null not permitted). - */ - public void removeSeries(XYSeriesP series) { - if (series == null) { - throw new IllegalArgumentException("Null 'series' argument."); - } - if (this.data.contains(series)) { - series.removeChangeListener(this); - this.data.remove(series); - fireDatasetChanged(); - } - } - - /** - * Removes all the series from the collection and sends a - * {@link DatasetChangeEvent} to all registered listeners. - */ - public void removeAllSeries() { - // Unregister the collection as a change listener to each series in - // the collection. - for (int i = 0; i < this.data.size(); i++) { - XYSeriesP series = (XYSeriesP) this.data.get(i); - series.removeChangeListener(this); - } - - // Remove all the series from the collection and notify listeners. - this.data.clear(); - fireDatasetChanged(); - } - - /** - * Returns the number of series in the collection. - * - * @return The series count. - */ - public int getSeriesCount() { - return this.data.size(); - } - - /** - * Returns a list of all the series in the collection. - * - * @return The list (which is unmodifiable). - */ - public List getSeries() { - return Collections.unmodifiableList(this.data); - } - - /** - * Returns the index of the specified series, or -1 if that series is not - * present in the dataset. - * - * @param series the series (null not permitted). - * - * @return The series index. - * - * @since 1.0.6 - */ - public int indexOf(XYSeriesP series) { - if (series == null) { - throw new IllegalArgumentException("Null 'series' argument."); - } - return this.data.indexOf(series); - } - - /** - * Returns a series from the collection. - * - * @param series the series index (zero-based). - * - * @return The series. - * - * @throws IllegalArgumentException if series is not in the - * range 0 to getSeriesCount() - 1. - */ - public XYSeriesP getSeries(int series) { - if ((series < 0) || (series >= getSeriesCount())) { - throw new IllegalArgumentException("Series index out of bounds"); - } - return (XYSeriesP) this.data.get(series); - } - - /** - * Returns a series from the collection. - * - * @param key the key (null not permitted). - * - * @return The series with the specified key. - * - * @throws UnknownKeyException if key is not found in the - * collection. - * - * @since 1.0.9 - */ - public XYSeriesP getSeries(Comparable key) { - if (key == null) { - throw new IllegalArgumentException("Null 'key' argument."); - } - for (XYSeriesP series: this.data) { - if (key.equals(series.getKey())) { - return series; - } - } - throw new UnknownKeyException("Key not found: " + key); - } - - /** - * Returns the key for a series. - * - * @param series the series index (in the range 0 to - * getSeriesCount() - 1). - * - * @return The key for a series. - * - * @throws IllegalArgumentException if series is not in the - * specified range. - */ - public Comparable getSeriesKey(int series) { - // defer argument checking - return getSeries(series).getKey(); - } - - /** - * Returns the number of items in the specified series. - * - * @param series the series (zero-based index). - * - * @return The item count. - * - * @throws IllegalArgumentException if series is not in the - * range 0 to getSeriesCount() - 1. - */ - public int getItemCount(int series) { - // defer argument checking - return getSeries(series).getItemCount(); - } - - /** - * Returns the x-value for the specified series and item. - * - * @param series the series (zero-based index). - * @param item the item (zero-based index). - * - * @return The value. - */ - public Number getX(int series, int item) { - XYSeriesP ts = (XYSeriesP) this.data.get(series); - XYDataItem xyItem = ts.getDataItem(item); - return xyItem.getX(); - } - - /** - * Returns the starting X value for the specified series and item. - * - * @param series the series (zero-based index). - * @param item the item (zero-based index). - * - * @return The starting X value. - */ - public Number getStartX(int series, int item) { - return this.intervalDelegate.getStartX(series, item); - } - - /** - * Returns the ending X value for the specified series and item. - * - * @param series the series (zero-based index). - * @param item the item (zero-based index). - * - * @return The ending X value. - */ - public Number getEndX(int series, int item) { - return this.intervalDelegate.getEndX(series, item); - } - - /** - * Returns the y-value for the specified series and item. - * - * @param series the series (zero-based index). - * @param index the index of the item of interest (zero-based). - * - * @return The value (possibly null). - */ - public Number getY(int series, int index) { - XYSeriesP ts = (XYSeriesP) this.data.get(series); - XYDataItem xyItem = ts.getDataItem(index); - return xyItem.getY(); - } - - /** - * Returns the starting Y value for the specified series and item. - * - * @param series the series (zero-based index). - * @param item the item (zero-based index). - * - * @return The starting Y value. - */ - public Number getStartY(int series, int item) { - return getY(series, item); - } - - /** - * Returns the ending Y value for the specified series and item. - * - * @param series the series (zero-based index). - * @param item the item (zero-based index). - * - * @return The ending Y value. - */ - public Number getEndY(int series, int item) { - return getY(series, item); - } - - /** - * Returns the minimum x-value in the dataset. - * - * @param includeInterval a flag that determines whether or not the - * x-interval is taken into account. - * - * @return The minimum value. - */ - public double getDomainLowerBound(boolean includeInterval) { - if (includeInterval) { - return this.intervalDelegate.getDomainLowerBound(includeInterval); - } - else { - double result = Double.NaN; - int seriesCount = getSeriesCount(); - for (int s = 0; s < seriesCount; s++) { - XYSeriesP series = getSeries(s); - double lowX = series.getMinX(); - if (Double.isNaN(result)) { - result = lowX; - } - else { - if (!Double.isNaN(lowX)) { - result = Math.min(result, lowX); - } - } - } - return result; - } - } - - /** - * Returns the maximum x-value in the dataset. - * - * @param includeInterval a flag that determines whether or not the - * x-interval is taken into account. - * - * @return The maximum value. - */ - public double getDomainUpperBound(boolean includeInterval) { - if (includeInterval) { - return this.intervalDelegate.getDomainUpperBound(includeInterval); - } - else { - double result = Double.NaN; - int seriesCount = getSeriesCount(); - for (int s = 0; s < seriesCount; s++) { - XYSeriesP series = getSeries(s); - double hiX = series.getMaxX(); - if (Double.isNaN(result)) { - result = hiX; - } - else { - if (!Double.isNaN(hiX)) { - result = Math.max(result, hiX); - } - } - } - return result; - } - } - - /** - * Returns the range of the values in this dataset's domain. - * - * @param includeInterval a flag that determines whether or not the - * x-interval is taken into account. - * - * @return The range (or null if the dataset contains no - * values). - */ - public Range getDomainBounds(boolean includeInterval) { - if (includeInterval) { - return this.intervalDelegate.getDomainBounds(includeInterval); - } - else { - double lower = Double.POSITIVE_INFINITY; - double upper = Double.NEGATIVE_INFINITY; - int seriesCount = getSeriesCount(); - for (int s = 0; s < seriesCount; s++) { - XYSeriesP series = getSeries(s); - double minX = series.getMinX(); - if (!Double.isNaN(minX)) { - lower = Math.min(lower, minX); - } - double maxX = series.getMaxX(); - if (!Double.isNaN(maxX)) { - upper = Math.max(upper, maxX); - } - } - if (lower > upper) { - return null; - } - else { - return new Range(lower, upper); - } - } - } - - /** - * Returns the interval width. This is used to calculate the start and end - * x-values, if/when the dataset is used as an {@link IntervalXYDataset}. - * - * @return The interval width. - */ - public double getIntervalWidth() { - return this.intervalDelegate.getIntervalWidth(); - } - - /** - * Sets the interval width and sends a {@link DatasetChangeEvent} to all - * registered listeners. - * - * @param width the width (negative values not permitted). - */ - public void setIntervalWidth(double width) { - if (width < 0.0) { - throw new IllegalArgumentException("Negative 'width' argument."); - } - this.intervalDelegate.setFixedIntervalWidth(width); - fireDatasetChanged(); - } - - /** - * Returns the interval position factor. - * - * @return The interval position factor. - */ - public double getIntervalPositionFactor() { - return this.intervalDelegate.getIntervalPositionFactor(); - } - - /** - * Sets the interval position factor. This controls where the x-value is in - * relation to the interval surrounding the x-value (0.0 means the x-value - * will be positioned at the start, 0.5 in the middle, and 1.0 at the end). - * - * @param factor the factor. - */ - public void setIntervalPositionFactor(double factor) { - this.intervalDelegate.setIntervalPositionFactor(factor); - fireDatasetChanged(); - } - - /** - * Returns whether the interval width is automatically calculated or not. - * - * @return Whether the width is automatically calculated or not. - */ - public boolean isAutoWidth() { - return this.intervalDelegate.isAutoWidth(); - } - - /** - * Sets the flag that indicates wether the interval width is automatically - * calculated or not. - * - * @param b a boolean. - */ - public void setAutoWidth(boolean b) { - this.intervalDelegate.setAutoWidth(b); - fireDatasetChanged(); - } - - /** - * Returns the range of the values in this dataset's range. - * - * @param includeInterval ignored. - * - * @return The range (or null if the dataset contains no - * values). - */ - public Range getRangeBounds(boolean includeInterval) { - double lower = Double.POSITIVE_INFINITY; - double upper = Double.NEGATIVE_INFINITY; - int seriesCount = getSeriesCount(); - for (int s = 0; s < seriesCount; s++) { - XYSeriesP series = getSeries(s); - double minY = series.getMinY(); - if (!Double.isNaN(minY)) { - lower = Math.min(lower, minY); - } - double maxY = series.getMaxY(); - if (!Double.isNaN(maxY)) { - upper = Math.max(upper, maxY); - } - } - if (lower > upper) { - return null; - } - else { - return new Range(lower, upper); - } - } - - /** - * Returns the minimum y-value in the dataset. - * - * @param includeInterval a flag that determines whether or not the - * y-interval is taken into account. - * - * @return The minimum value. - */ - public double getRangeLowerBound(boolean includeInterval) { - double result = Double.NaN; - int seriesCount = getSeriesCount(); - for (int s = 0; s < seriesCount; s++) { - XYSeriesP series = getSeries(s); - double lowY = series.getMinY(); - if (Double.isNaN(result)) { - result = lowY; - } - else { - if (!Double.isNaN(lowY)) { - result = Math.min(result, lowY); - } - } - } - return result; - } - - /** - * Returns the maximum y-value in the dataset. - * - * @param includeInterval a flag that determines whether or not the - * y-interval is taken into account. - * - * @return The maximum value. - */ - public double getRangeUpperBound(boolean includeInterval) { - double result = Double.NaN; - int seriesCount = getSeriesCount(); - for (int s = 0; s < seriesCount; s++) { - XYSeriesP series = getSeries(s); - double hiY = series.getMaxY(); - if (Double.isNaN(result)) { - result = hiY; - } - else { - if (!Double.isNaN(hiY)) { - result = Math.max(result, hiY); - } - } - } - return result; - } - -} diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/xy/XYSeriesP.java b/ch.psi.plot/src/main/java/ch/psi/plot/xy/XYSeriesP.java deleted file mode 100644 index a965492..0000000 --- a/ch.psi.plot/src/main/java/ch/psi/plot/xy/XYSeriesP.java +++ /dev/null @@ -1,454 +0,0 @@ -package ch.psi.plot.xy; - -/* =========================================================== - * JFreeChart : a free chart library for the Java(tm) platform - * =========================================================== - * - * (C) Copyright 2000-2009, by Object Refinery Limited and Contributors. - * - * Project Info: http://www.jfree.org/jfreechart/index.html - * - * This library 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 2.1 of the License, or - * (at your option) any later version. - * - * This library 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 this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. - * - * [Java is a trademark or registered trademark of Sun Microsystems, Inc. - * in the United States and other countries.] - * - * ------------- - * XYSeries.java - * ------------- - * (C) Copyright 2001-2009, Object Refinery Limited and Contributors. - * - * Original Author: David Gilbert (for Object Refinery Limited); - * Contributor(s): Aaron Metzger; - * Jonathan Gabbai; - * Richard Atkinson; - * Michel Santos; - * Ted Schwartz (fix for bug 1955483); - * - * Changes - * ------- - * 15-Nov-2001 : Version 1 (DG); - * 03-Apr-2002 : Added an add(double, double) method (DG); - * 29-Apr-2002 : Added a clear() method (ARM); - * 06-Jun-2002 : Updated Javadoc comments (DG); - * 29-Aug-2002 : Modified to give user control over whether or not duplicate - * x-values are allowed (DG); - * 07-Oct-2002 : Fixed errors reported by Checkstyle (DG); - * 11-Nov-2002 : Added maximum item count, code contributed by Jonathan - * Gabbai (DG); - * 26-Mar-2003 : Implemented Serializable (DG); - * 04-Aug-2003 : Added getItems() method (DG); - * 15-Aug-2003 : Changed 'data' from private to protected, added new add() - * methods with a 'notify' argument (DG); - * 22-Sep-2003 : Added getAllowDuplicateXValues() method (RA); - * 29-Jan-2004 : Added autoSort attribute, based on a contribution by - * Michel Santos - see patch 886740 (DG); - * 03-Feb-2004 : Added indexOf() method (DG); - * 16-Feb-2004 : Added remove() method (DG); - * 18-Aug-2004 : Moved from org.jfree.data --> org.jfree.data.xy (DG); - * 21-Feb-2005 : Added update(Number, Number) and addOrUpdate(Number, Number) - * methods (DG); - * 03-May-2005 : Added a new constructor, fixed the setMaximumItemCount() - * method to remove items (and notify listeners) if necessary, - * fixed the add() and addOrUpdate() methods to handle unsorted - * series (DG); - * ------------- JFreeChart 1.0.x --------------------------------------------- - * 11-Jan-2005 : Renamed update(int, Number) --> updateByIndex() (DG); - * 15-Jan-2007 : Added toArray() method (DG); - * 31-Oct-2007 : Implemented faster hashCode() (DG); - * 22-Nov-2007 : Reimplemented clone() (DG); - * 01-May-2008 : Fixed bug 1955483 in addOrUpdate() method, thanks to - * Ted Schwartz (DG); - * 24-Nov-2008 : Further fix for 1955483 (DG); - * 06-Mar-2009 : Added minX, maxX, minY and maxY fields (DG); - * - */ - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.jfree.data.general.Series; -import org.jfree.data.general.SeriesChangeEvent; -import org.jfree.data.general.SeriesException; -import org.jfree.data.xy.XYDataItem; - -/** - * Represents a sequence of zero or more data items in the form (x, y). By - * default, items in the series will be sorted into ascending order by x-value, - * and duplicate x-values are permitted. Both the sorting and duplicate - * defaults can be changed in the constructor. Y-values can be - * null to represent missing values. - */ -public class XYSeriesP extends Series implements Cloneable, Serializable { - - /** For serialization. */ - static final long serialVersionUID = -5908509288197150436L; - - // In version 0.9.12, in response to several developer requests, I changed - // the 'data' attribute from 'private' to 'protected', so that others can - // make subclasses that work directly with the underlying data structure. - - /** Storage for the data items in the series. */ - protected List data; - - /** The maximum number of items for the series. */ - private int maximumItemCount = Integer.MAX_VALUE; - - /** - * A flag that controls whether the items are automatically sorted - * (by x-value ascending). - */ - - /** The lowest x-value in the series, excluding Double.NaN values. */ - private double minX; - - /** The highest x-value in the series, excluding Double.NaN values. */ - private double maxX; - - /** The lowest y-value in the series, excluding Double.NaN values. */ - private double minY; - - /** The highest y-value in the series, excluding Double.NaN values. */ - private double maxY; - - /** - * Creates a new empty series. By default, items added to the series will - * be sorted into ascending order by x-value, and duplicate x-values will - * be allowed (these defaults can be modified with another constructor. - * - * @param key the series key (null not permitted). - */ - public XYSeriesP(Comparable key) { - this(key, true, true); - } - - /** - * Constructs a new empty series, with the auto-sort flag set as requested, - * and duplicate values allowed. - * - * @param key the series key (null not permitted). - * @param autoSort a flag that controls whether or not the items in the - * series are sorted. - */ - public XYSeriesP(Comparable key, boolean autoSort) { - this(key, autoSort, true); - } - - /** - * Constructs a new xy-series that contains no data. You can specify - * whether or not duplicate x-values are allowed for the series. - * - * @param key the series key (null not permitted). - * @param autoSort a flag that controls whether or not the items in the - * series are sorted. - * @param allowDuplicateXValues a flag that controls whether duplicate - * x-values are allowed. - */ - public XYSeriesP(Comparable key, boolean autoSort, - boolean allowDuplicateXValues) { - super(key); - this.data = new ArrayList(1000); // allocate memory already for 1000 items - this.minX = Double.NaN; - this.maxX = Double.NaN; - this.minY = Double.NaN; - this.maxY = Double.NaN; - } - - /** - * Returns the smallest x-value in the series, ignoring any Double.NaN - * values. This method returns Double.NaN if there is no smallest x-value - * (for example, when the series is empty). - * - * @return The smallest x-value. - * - * @see #getMaxX() - * - * @since 1.0.13 - */ - public double getMinX() { - return this.minX; - } - - /** - * Returns the largest x-value in the series, ignoring any Double.NaN - * values. This method returns Double.NaN if there is no largest x-value - * (for example, when the series is empty). - * - * @return The largest x-value. - * - * @see #getMinX() - * - * @since 1.0.13 - */ - public double getMaxX() { - return this.maxX; - } - - /** - * Returns the smallest y-value in the series, ignoring any null and - * Double.NaN values. This method returns Double.NaN if there is no - * smallest y-value (for example, when the series is empty). - * - * @return The smallest y-value. - * - * @see #getMaxY() - * - * @since 1.0.13 - */ - public double getMinY() { - return this.minY; - } - - /** - * Returns the largest y-value in the series, ignoring any Double.NaN - * values. This method returns Double.NaN if there is no largest y-value - * (for example, when the series is empty). - * - * @return The largest y-value. - * - * @see #getMinY() - * - * @since 1.0.13 - */ - public double getMaxY() { - return this.maxY; - } - - /** - * Updates the cached values for the minimum and maximum data values. - * - * @param item the item added (null not permitted). - * - * @since 1.0.13 - */ - private void updateBoundsForAddedItem(XYDataItem item) { - double x = item.getXValue(); - this.minX = minIgnoreNaN(this.minX, x); - this.maxX = maxIgnoreNaN(this.maxX, x); - if (item.getY() != null) { - double y = item.getYValue(); - this.minY = minIgnoreNaN(this.minY, y); - this.maxY = maxIgnoreNaN(this.maxY, y); - } - } - - /** - * Finds the bounds of the x and y values for the series, by iterating - * through all the data items. - * - * @since 1.0.13 - */ - private void findBoundsByIteration() { - this.minX = Double.NaN; - this.maxX = Double.NaN; - this.minY = Double.NaN; - this.maxY = Double.NaN; - for(XYDataItem item: data){ - updateBoundsForAddedItem(item); - } - } - - /** - * Returns the number of items in the series. - * - * @return The item count. - * - * @see #getItems() - */ - public int getItemCount() { - return this.data.size(); - } - - /** - * Returns the list of data items for the series (the list contains - * {@link XYDataItem} objects and is unmodifiable). - * - * @return The list of data items. - */ - public List getItems() { - return Collections.unmodifiableList(this.data); - } - - /** - * Returns the maximum number of items that will be retained in the series. - * The default value is Integer.MAX_VALUE. - * - * @return The maximum item count. - * - * @see #setMaximumItemCount(int) - */ - public int getMaximumItemCount() { - return this.maximumItemCount; - } - - /** - * Sets the maximum number of items that will be retained in the series. - * If you add a new item to the series such that the number of items will - * exceed the maximum item count, then the first element in the series is - * automatically removed, ensuring that the maximum item count is not - * exceeded. - *

- * Typically this value is set before the series is populated with data, - * but if it is applied later, it may cause some items to be removed from - * the series (in which case a {@link SeriesChangeEvent} will be sent to - * all registered listeners). - * - * @param maximum the maximum number of items for the series. - */ - public void setMaximumItemCount(int maximum) { - this.maximumItemCount = maximum; - int remove = this.data.size() - maximum; - if (remove > 0) { - this.data.subList(0, remove).clear(); - findBoundsByIteration(); - fireSeriesChanged(); - } - } - - /** - * Adds a new data item to the series (in the correct position if the - * autoSort flag is set for the series) and sends a - * {@link SeriesChangeEvent} to all registered listeners. - *

- * Throws an exception if the x-value is a duplicate AND the - * allowDuplicateXValues flag is false. - * - * @param x the x-value (null not permitted). - * @param y the y-value (null permitted). - * - * @throws SeriesException if the x-value is a duplicate and the - * allowDuplicateXValues flag is not set for this series. - */ - public void add(Number x, Number y) { - // argument checking delegated... - add(new XYDataItem(x, y), true); - } - - /** - * Adds new data to the series and, if requested, sends a - * {@link SeriesChangeEvent} to all registered listeners. - *

- * Throws an exception if the x-value is a duplicate AND the - * allowDuplicateXValues flag is false. - * - * @param x the x-value (null not permitted). - * @param y the y-value (null permitted). - * @param notify a flag the controls whether or not a - * {@link SeriesChangeEvent} is sent to all registered - * listeners. - */ - public void add(Number x, Number y, boolean notify) { - // delegate argument checking to XYDataItem... - XYDataItem item = new XYDataItem(x, y); - add(item, notify); - } - - /** - * Adds a data item to the series and, if requested, sends a - * {@link SeriesChangeEvent} to all registered listeners. - * - * @param item the (x, y) item (null not permitted). - * @param notify a flag that controls whether or not a - * {@link SeriesChangeEvent} is sent to all registered - * listeners. - */ - public void add(XYDataItem item, boolean notify) { - if (item == null) { - throw new IllegalArgumentException("Null 'item' argument."); - } - - this.data.add(item); - - if (notify) { - fireSeriesChanged(); - } - } - - /** - * Removes all data items from the series and sends a - * {@link SeriesChangeEvent} to all registered listeners. - */ - public void clear() { - if (this.data.size() > 0) { - this.data.clear(); - this.minX = Double.NaN; - this.maxX = Double.NaN; - this.minY = Double.NaN; - this.maxY = Double.NaN; - fireSeriesChanged(); - } - } - - /** - * Return the data item with the specified index. - * - * @param index the index. - * - * @return The data item with the specified index. - */ - public XYDataItem getDataItem(int index) { - return (XYDataItem) this.data.get(index); - } - - /** - * A function to find the minimum of two values, but ignoring any - * Double.NaN values. - * - * @param a the first value. - * @param b the second value. - * - * @return The minimum of the two values. - */ - private double minIgnoreNaN(double a, double b) { - if (Double.isNaN(a)) { - return b; - } - else { - if (Double.isNaN(b)) { - return a; - } - else { - return Math.min(a, b); - } - } - } - - /** - * A function to find the maximum of two values, but ignoring any - * Double.NaN values. - * - * @param a the first value. - * @param b the second value. - * - * @return The maximum of the two values. - */ - private double maxIgnoreNaN(double a, double b) { - if (Double.isNaN(a)) { - return b; - } - else { - if (Double.isNaN(b)) { - return a; - } - else { - return Math.max(a, b); - } - } - } -} - diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/xy/tools/Average.java b/ch.psi.plot/src/main/java/ch/psi/plot/xy/tools/Average.java deleted file mode 100644 index 3d63bcf..0000000 --- a/ch.psi.plot/src/main/java/ch/psi/plot/xy/tools/Average.java +++ /dev/null @@ -1,61 +0,0 @@ -/** - * - * Copyright 2010 Paul Scherrer Institute. All rights reserved. - * - * This code 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. - * - * This code 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 this code. If not, see . - * - */ - -package ch.psi.plot.xy.tools; - -import org.jfree.data.xy.XYDataItem; - -import ch.psi.plot.xy.XYSeriesCollectionP; -import ch.psi.plot.xy.XYSeriesP; - - -/** - * Calculate average of series - */ -public class Average { - - /** - * Calculate average of the passed series collection - * - * @param collection - * @return Average value of the collection - */ - public double average(XYSeriesCollectionP collection){ - double average = 0.0; - for (XYSeriesP series : collection.getSeries()) { - average = average + average(series); - } - - return average/collection.getSeriesCount(); - } - - /** - * Calculate average value for a series - * @param series - * @return - */ - public double average(XYSeriesP series){ - double average = 0.0; - for(XYDataItem item: series.getItems()){ - average = average+item.getYValue(); - } - - return average/series.getItemCount(); - } -} diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/xy/tools/Derivative.java b/ch.psi.plot/src/main/java/ch/psi/plot/xy/tools/Derivative.java deleted file mode 100644 index 68a5f6f..0000000 --- a/ch.psi.plot/src/main/java/ch/psi/plot/xy/tools/Derivative.java +++ /dev/null @@ -1,80 +0,0 @@ -/** - * - * Copyright 2010 Paul Scherrer Institute. All rights reserved. - * - * This code 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. - * - * This code 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 this code. If not, see . - * - */ - -package ch.psi.plot.xy.tools; - -import org.jfree.data.xy.XYDataItem; - -import ch.psi.plot.xy.XYSeriesCollectionP; -import ch.psi.plot.xy.XYSeriesP; - -/** - * Calculate derivative of series - */ -public class Derivative { - - /** - * Calculate derivatives for all series in the passed collection - * @param collection - * @return Collection of series holding the derivatives - */ - public XYSeriesCollectionP derivative(XYSeriesCollectionP collection){ - XYSeriesCollectionP dcollection = new XYSeriesCollectionP(); - for (XYSeriesP series : collection.getSeries()) { - dcollection.addSeries(derivative(series)); - } - - return dcollection; - } - - /** - * Calculate derivative (first and/or second order) of a given function. - * derivative is based upon 3 points. - * - * @param series - * @return - */ - public XYSeriesP derivative(XYSeriesP series){ - - XYSeriesP derivative = new XYSeriesP(series.getKey() + "'"); - - for (int i = 1; i < series.getItemCount() - 1; i++) { // do not start at 0 but 1 - stop 1 before end - XYDataItem m = series.getDataItem(i - 1); - XYDataItem p = series.getDataItem(i + 1); - - double xi = series.getDataItem(i).getXValue(); - - double ximinus1 = m.getXValue(); - double xiplus1 = p.getXValue(); - - double yiminus1 = m.getYValue(); - double yiplus1 = p.getYValue(); - - if (xiplus1-ximinus1 != 0.0) { - double di = (yiplus1 - yiminus1) / (xiplus1-ximinus1); - derivative.add(xi, di); - } - else{ - derivative.add(xi, Double.NaN); - } - } - - return derivative; - } -} diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/xy/tools/Integral.java b/ch.psi.plot/src/main/java/ch/psi/plot/xy/tools/Integral.java deleted file mode 100644 index d4014b0..0000000 --- a/ch.psi.plot/src/main/java/ch/psi/plot/xy/tools/Integral.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * - * Copyright 2010 Paul Scherrer Institute. All rights reserved. - * - * This code 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. - * - * This code 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 this code. If not, see . - * - */ - -package ch.psi.plot.xy.tools; - -import org.jfree.data.xy.XYDataItem; - -import ch.psi.plot.xy.XYSeriesCollectionP; -import ch.psi.plot.xy.XYSeriesP; - -/** - * Calculate integral of series - */ -public class Integral { - - /** - * Calculate integral for all series in passed collection - * @param collection - * @return Collection of series - */ - public XYSeriesCollectionP integral(XYSeriesCollectionP collection){ - XYSeriesCollectionP icollection = new XYSeriesCollectionP(); - for (XYSeriesP series : collection.getSeries()) { - icollection.addSeries(integral(series)); - } - - return icollection; - } - - /** - * Calculate integral of the function - * @param series - * @return - */ - public XYSeriesP integral(XYSeriesP series) { - XYSeriesP integral = new XYSeriesP("integral-" + series.getKey()); - - double value = 0.0; - for (int i = 1; i < series.getItemCount(); i++) { // Leave out 1. point - XYDataItem item = series.getDataItem(i); - XYDataItem itemM = series.getDataItem(i - 1); - - value += (item.getXValue() - itemM.getXValue()) * (item.getYValue() + itemM.getYValue()) / 2.0; - - integral.add(item.getXValue(), value); - } - return integral; - } -} diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/xy/tools/Maximum.java b/ch.psi.plot/src/main/java/ch/psi/plot/xy/tools/Maximum.java deleted file mode 100644 index 1f60676..0000000 --- a/ch.psi.plot/src/main/java/ch/psi/plot/xy/tools/Maximum.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * - * Copyright 2010 Paul Scherrer Institute. All rights reserved. - * - * This code 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. - * - * This code 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 this code. If not, see . - * - */ - -package ch.psi.plot.xy.tools; - -import org.jfree.data.xy.XYDataItem; -import ch.psi.plot.xy.XYSeriesP; - -/** - * Find maximum of series - */ -public class Maximum { - - /** - * Find maximum in series - * @param series - * @return maximum data point - */ - public XYDataItem maximum(XYSeriesP series){ - XYDataItem maximum = null; - for(XYDataItem item: series.getItems()){ - if(maximum==null){ // set first item as maximum - maximum = item; - } - else{ - if(item.getYValue()>maximum.getYValue()){ - maximum = item; - } - } - } - return maximum; - } - - -} diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/xy/tools/Minimum.java b/ch.psi.plot/src/main/java/ch/psi/plot/xy/tools/Minimum.java deleted file mode 100644 index 50c49ce..0000000 --- a/ch.psi.plot/src/main/java/ch/psi/plot/xy/tools/Minimum.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * - * Copyright 2010 Paul Scherrer Institute. All rights reserved. - * - * This code 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. - * - * This code 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 this code. If not, see . - * - */ - -package ch.psi.plot.xy.tools; - -import org.jfree.data.xy.XYDataItem; -import ch.psi.plot.xy.XYSeriesP; - -/** - * Find minimum of series - */ -public class Minimum { - - /** - * Find minimum in series - * @param series - * @return minimum data point - */ - public XYDataItem minimum(XYSeriesP series){ - XYDataItem minimum = null; - for(XYDataItem item: series.getItems()){ - if(minimum == null){ - minimum = item; - } - else{ - if(item.getYValue(). - * - */ - -package ch.psi.plot.xyz; - -import java.awt.Color; - -/** - * Utility class for applying a color map - */ -public class ColorManager { - - /** - * Get color for a given value - * @param v Value to get the color for - * @param vmin Lower end value mapped to the lower end of the color map - * @param vmax Upper end value mapped to the upper end of the color map - * @return Mapped color for the specified value - */ - public static Color getColourForValue(double v, double vmin, double vmax) - { - // Standard algorithm for hot-cold color gradient (copied from - // http://local.wasp.uwa.edu.au/~pbourke/texture_colour/colourramp/) - - //Init color to white - double r = 1.0; - double g = 1.0; - double b = 1.0; - - double dv; - - if (v < vmin) - v = vmin; - if (v > vmax) - v = vmax; - dv = vmax - vmin; - - if (v < (vmin + 0.25 * dv)) { - r = 0.0; - g = 4 * (v - vmin) / dv; - } else if (v < (vmin + 0.5 * dv)) { - r = 0.0; - b = 1 + 4 * (vmin + 0.25 * dv - v) / dv; - } else if (v < (vmin + 0.75 * dv)) { - r = 4 * (v - vmin - 0.5 * dv) / dv; - b = 0.0; - } else { - g = 1 + 4 * (vmin + 0.75 * dv - v) / dv; - b = 0.0; - } - - return new Color( new Double(255.0*r).intValue(), new Double(255.0*g).intValue(), new Double(255.0*b).intValue()); - } - - /** - * Get a gray value for a given value - * @param value the value (must be within the range specified by the - * lower and upper bounds for the scale). - * - * @return a gray scale color. - */ - public static Color getGrayForValue(double value, double vmin, double vmax) { - double v = Math.max(value, vmin); - v = Math.min(v, vmax); - int g = (int) ((v - vmin) / (vmax- vmin) * 255.0); - // FIXME: it probably makes sense to allocate an array of 256 Colors - // and lazily populate this array... - return new Color(g, g, g); - } -} diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/xyz/DynamicXYZDataset.java b/ch.psi.plot/src/main/java/ch/psi/plot/xyz/DynamicXYZDataset.java deleted file mode 100644 index a101356..0000000 --- a/ch.psi.plot/src/main/java/ch/psi/plot/xyz/DynamicXYZDataset.java +++ /dev/null @@ -1,245 +0,0 @@ -/** - * - * Copyright 2011 Paul Scherrer Institute. All rights reserved. - * - * This code 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. - * - * This code 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 this code. If not, see . - * - */ -package ch.psi.plot.xyz; - -import java.util.ArrayList; -import java.util.List; - -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.renderer.xy.XYBlockRenderer; -import org.jfree.data.DomainOrder; -import org.jfree.data.general.DatasetChangeListener; -import org.jfree.data.general.DatasetGroup; -import org.jfree.data.xy.XYZDataset; -import org.jfree.ui.RectangleAnchor; - -/** - * Dynamic dataset - */ -public class DynamicXYZDataset implements XYZDataset{ - - private final double xResolution; - private final double yResolution; - - private final NumberAxis xAxis = new NumberAxis(); - private double xLowerBound = Double.NaN; - private double xUpperBound = Double.NaN; - private final NumberAxis yAxis = new NumberAxis(); - private double yLowerBound = Double.NaN; - private double yUpperBound = Double.NaN; - private double zLowerBound = Double.NaN; - - - private double zUpperBound = Double.NaN; - - private final XYBlockRenderer renderer = new XYBlockRenderer(); - - - private List items = new ArrayList(); - - /** - * Default constructor - */ - public DynamicXYZDataset(){ - xResolution = 1.0; - yResolution = 1.0; - - xAxis.setRange(xLowerBound, xUpperBound); - yAxis.setRange(yLowerBound, yUpperBound); - - renderer.setBlockWidth(xResolution); // If this is not set the default block size is 1 - renderer.setBlockHeight(yResolution); // If this is not set the default block size is 1 - renderer.setBlockAnchor(RectangleAnchor.CENTER); - renderer.setBaseCreateEntities(false); - } - - public void addData(double x, double y, double z){ - items.add(new DynamicXYZDataset.Vector(x,y,z)); - } - - @Override - public int getItemCount(int series) { - return items.size(); - } - - @Override - public Number getX(int series, int item) { - return items.get(item).getX(); - } - - @Override - public double getXValue(int series, int item) { - return items.get(item).getX(); - } - - @Override - public Number getY(int series, int item) { - return items.get(item).getY(); - } - - @Override - public double getYValue(int series, int item) { - return items.get(item).getY(); - } - - @Override - public Number getZ(int series, int item) { - return items.get(item).getZ(); - } - - @Override - public double getZValue(int series, int item) { - return items.get(item).getZ(); - } - - @Override - public DomainOrder getDomainOrder() { - return DomainOrder.NONE; - } - - @Override - public int getSeriesCount() { - // Series not implemented/used - dataset only holds one series - return 1; - } - - @SuppressWarnings("rawtypes") - @Override - public Comparable getSeriesKey(int series) { - // Series not implemented/used - return ""; - } - - @SuppressWarnings("rawtypes") - @Override - public int indexOf(Comparable seriesKey) { - // Series not implemented/used - return 0; - } - - @Override - public DatasetGroup getGroup() { - // Not implemented/used - return null; - } - - @Override - public void setGroup(DatasetGroup group) { - // Not implemented/used - } - - @Override - public void addChangeListener(DatasetChangeListener listener) { - } - - @Override - public void removeChangeListener(DatasetChangeListener listener) { - } - - // Convenient methods - - public double getzLowerBound() { - return zLowerBound; - } - public double getzUpperBound() { - return zUpperBound; - } - public NumberAxis getxAxis() { - return xAxis; - } - public NumberAxis getyAxis() { - return yAxis; - } - public XYBlockRenderer getRenderer() { - return renderer; - } - public double getxLowerBound() { - return xLowerBound; - } - public double getxUpperBound() { - return xUpperBound; - } - public double getyLowerBound() { - return yLowerBound; - } - public double getyUpperBound() { - return yUpperBound; - } - - - class Vector{ - private double x; - private double y; - private double z; - - /** - * Default constructor - */ - public Vector(){ - } - - /** - * @param x2 - * @param y2 - * @param z2 - */ - public Vector(double x, double y, double z) { - // Right now x and xvalue are the same. This might change if we introduce a virtual grid ... - this.x = x; - this.y = y; - this.z = z; - } - /** - * @return the x - */ - public double getX() { - return x; - } - /** - * @param x the x to set - */ - public void setX(double x) { - this.x = x; - } - /** - * @return the y - */ - public double getY() { - return y; - } - /** - * @param y the y to set - */ - public void setY(double y) { - this.y = y; - } - /** - * @return the z - */ - public double getZ() { - return z; - } - /** - * @param z the z to set - */ - public void setZ(double z) { - this.z = z; - } - } -} diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/xyz/DynamicXYZDatasetList.java b/ch.psi.plot/src/main/java/ch/psi/plot/xyz/DynamicXYZDatasetList.java deleted file mode 100644 index f46e68b..0000000 --- a/ch.psi.plot/src/main/java/ch/psi/plot/xyz/DynamicXYZDatasetList.java +++ /dev/null @@ -1,374 +0,0 @@ -/** - * - * Copyright 2011 Paul Scherrer Institute. All rights reserved. - * - * This code 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. - * - * This code 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 this code. If not, see . - * - */ -package ch.psi.plot.xyz; - -import java.util.ArrayList; -import java.util.List; - -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.renderer.xy.XYBlockRenderer; -import org.jfree.data.DomainOrder; -import org.jfree.data.general.DatasetChangeListener; -import org.jfree.data.general.DatasetGroup; -import org.jfree.data.xy.XYZDataset; -import org.jfree.ui.RectangleAnchor; - -/** - * Dynamic dataset - * @author ebner - * - */ -public class DynamicXYZDatasetList implements XYZDataset{ - - private final double xResolution; - private final double yResolution; - - private final NumberAxis xAxis = new NumberAxis(); - private final NumberAxis yAxis = new NumberAxis(); - private double zLowerBound = Double.NaN; - private double zUpperBound = Double.NaN; - - private final XYBlockRenderer renderer = new XYBlockRenderer(); - - - private final List listeners = new ArrayList(); - private List xitems = new ArrayList(100000); - private List yitems = new ArrayList(100000); - private List zitems = new ArrayList(100000); - - /** - * Default constructor - */ - public DynamicXYZDatasetList(){ - xResolution = 1.0; - yResolution = 1.0; - xAxis.setRange(0, 100); - yAxis.setRange(0, 100); - - renderer.setBlockWidth(xResolution); // If this is not set the default block size is 1 - renderer.setBlockHeight(yResolution); // If this is not set the default block size is 1 - renderer.setBlockAnchor(RectangleAnchor.CENTER); - } - - /** - * Add datapoint - * @param x - * @param y - * @param z - */ - public void addData(Double x, Double y, Double z){ - System.out.println(x +" "+ y +" "+ z); - xitems.add(x); - yitems.add(y); - zitems.add(z); -// items.add(new DynamicXYZDatasetList.Vector(x,y,z)); - - // Update axis - -// final double xv = x.doubleValue(); -// final double yv = y.doubleValue(); -// final double zv = z.doubleValue(); -// -// if(Double.isNaN(xLowerBound) && Double.isNaN(xUpperBound)){ -// xLowerBound = xv-incX; -// xUpperBound = xv+incX; -// xAxis.setRange(xLowerBound, xUpperBound); -// } -// else{ -// if(xv>(xUpperBound+incX)){ -// xUpperBound = xv+incX; -// xAxis.setUpperBound(xUpperBound); -// } -// else if(xv(yUpperBound+incY)){ -// yUpperBound = yv+incY; -// yAxis.setUpperBound(yUpperBound); -// } -// else if(yvzUpperBound){ -// zUpperBound = zv; -// } -// else if(zv. - * - */ -package ch.psi.plot.xyz; - -import java.util.ArrayList; -import java.util.List; - -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.renderer.xy.XYBlockRenderer; -import org.jfree.data.DomainOrder; -import org.jfree.data.general.DatasetChangeListener; -import org.jfree.data.general.DatasetGroup; -import org.jfree.data.xy.XYZDataset; -import org.jfree.ui.RectangleAnchor; - -/** - * Dynamic dataset - */ -public class DynamicXYZDatasetNumber implements XYZDataset{ - - private final double xResolution; - private final double yResolution; - private final double incX; - private final double incY; - - private final NumberAxis xAxis = new NumberAxis(); - private double xLowerBound = Double.NaN; - private double xUpperBound = Double.NaN; - private final NumberAxis yAxis = new NumberAxis(); - private double yLowerBound = Double.NaN; - private double yUpperBound = Double.NaN; - private double zLowerBound = Double.NaN; - - - private double zUpperBound = Double.NaN; - - private final XYBlockRenderer renderer = new XYBlockRenderer(); - - - private final List listeners = new ArrayList(); - private List items = new ArrayList(); - - /** - * Default constructor - */ - public DynamicXYZDatasetNumber(){ - xResolution = 1.0; - yResolution = 1.0; - incX = xResolution/2; - incY = yResolution/2; - - xAxis.setRange(xLowerBound, xUpperBound); - yAxis.setRange(yLowerBound, yUpperBound); - - renderer.setBlockWidth(xResolution); // If this is not set the default block size is 1 - renderer.setBlockHeight(yResolution); // If this is not set the default block size is 1 - renderer.setBlockAnchor(RectangleAnchor.CENTER); - renderer.setBaseCreateEntities(false); - } - - /** - * Add datapoint - * @param x - * @param y - * @param z - */ - public void addData(Number x, Number y, Number z){ - items.add(new DynamicXYZDatasetNumber.Vector(x,y,z)); - - // Update axis - - final double xv = x.doubleValue(); - final double yv = y.doubleValue(); - final double zv = z.doubleValue(); - - if(Double.isNaN(xLowerBound) && Double.isNaN(xUpperBound)){ - xLowerBound = xv-incX; - xUpperBound = xv+incX; - xAxis.setRange(xLowerBound, xUpperBound); - } - else{ - if(xv>(xUpperBound+incX)){ - xUpperBound = xv+incX; - xAxis.setUpperBound(xUpperBound); - } - else if(xv(yUpperBound+incY)){ - yUpperBound = yv+incY; - yAxis.setUpperBound(yUpperBound); - } - else if(yvzUpperBound){ - zUpperBound = zv; - } - else if(zv. - * - */ - -package ch.psi.plot.xyz; - -import java.awt.BorderLayout; -import java.awt.FlowLayout; - -import javax.swing.JButton; -import javax.swing.JDialog; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.border.EmptyBorder; -import javax.swing.JTextField; -import javax.swing.JLabel; -import java.awt.Font; -import java.awt.event.ActionListener; -import java.awt.event.ActionEvent; - -/** - * @author ebner - * - */ -public class ManualScaleDialog extends JDialog { - // Default serial id - private static final long serialVersionUID = 1L; - - private final JPanel contentPanel = new JPanel(); - private JTextField textFieldHighValue; - private JTextField textFieldLowValue; - - private MatrixPlot plot; - - private int selectedOption; - - /** - * Launch the application. - */ - public static void main(String[] args) { - try { - ManualScaleDialog dialog = new ManualScaleDialog(); - dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); - dialog.setVisible(true); - System.out.println("HERE"); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * Create the dialog. - */ - public ManualScaleDialog() { - setModal(true); // Block until dialog is disposed. - setBounds(100, 100, 450, 300); - getContentPane().setLayout(new BorderLayout()); - contentPanel.setLayout(new FlowLayout()); - contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5)); - getContentPane().add(contentPanel, BorderLayout.CENTER); - { - JLabel lblLowValue = new JLabel("Low Value:"); - lblLowValue.setFont(new Font("Lucida Grande", Font.BOLD, 13)); - contentPanel.add(lblLowValue); - } - { - textFieldLowValue = new JTextField(); - contentPanel.add(textFieldLowValue); - textFieldLowValue.setColumns(10); - } - { - JLabel lblHighValue = new JLabel("High Value:"); - lblHighValue.setFont(new Font("Lucida Grande", Font.BOLD, 13)); - contentPanel.add(lblHighValue); - } - { - textFieldHighValue = new JTextField(); - contentPanel.add(textFieldHighValue); - textFieldHighValue.setColumns(10); - } - { - JPanel buttonPane = new JPanel(); - buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT)); - getContentPane().add(buttonPane, BorderLayout.SOUTH); - { - JButton okButton = new JButton("OK"); - okButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent arg0) { - // set OK - selectedOption = JOptionPane.OK_OPTION; - dispose(); - } - }); - { - JButton btnApply = new JButton("Apply"); - btnApply.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent arg0) { - // TODO apply values - if(plot!=null){ - plot.setColorScale(getLow(), getHigh()); - } - } - }); - buttonPane.add(btnApply); - } - okButton.setActionCommand("OK"); - buttonPane.add(okButton); - getRootPane().setDefaultButton(okButton); - } - { - JButton cancelButton = new JButton("Cancel"); - cancelButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent arg0) { - // set Cancel - selectedOption = JOptionPane.CANCEL_OPTION; - dispose(); - } - }); - cancelButton.setActionCommand("Cancel"); - buttonPane.add(cancelButton); - } - } - - setDefaultCloseOperation(DISPOSE_ON_CLOSE); - pack(); - } - - public void showDialog(){ - setVisible(true); - } - - public void setMatrixPlot(MatrixPlot p){ - plot = p; - } - - public void setLow(double low){ - textFieldLowValue.setText(String.format("%.4f", low)); - } - public void setHigh(double high){ - textFieldHighValue.setText(String.format("%.4f", high)); - } - - public double getLow(){ - double low = Double.NaN; - try{ - low = Double.parseDouble(textFieldLowValue.getText()); - } - catch(NumberFormatException e){ - } - return low; - } - - public double getHigh(){ - double high = Double.NaN; - try{ - high = Double.parseDouble(textFieldHighValue.getText()); - } - catch(NumberFormatException e){ - } - return high; - } - - /** - * @return the selectedOption - */ - public int getSelectedOption() { - return selectedOption; - } - -} diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/xyz/MatrixPlot.java b/ch.psi.plot/src/main/java/ch/psi/plot/xyz/MatrixPlot.java deleted file mode 100644 index 441daf3..0000000 --- a/ch.psi.plot/src/main/java/ch/psi/plot/xyz/MatrixPlot.java +++ /dev/null @@ -1,379 +0,0 @@ -package ch.psi.plot.xyz; - -import java.awt.Color; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.text.DecimalFormat; - -import javax.swing.JFrame; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.WindowConstants; - -import org.jfree.chart.ChartPanel; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.axis.ValueAxis; -import org.jfree.chart.event.AxisChangeEvent; -import org.jfree.chart.event.AxisChangeListener; -import org.jfree.chart.labels.StandardXYZToolTipGenerator; -import org.jfree.chart.labels.XYZToolTipGenerator; -import org.jfree.chart.plot.XYPlot; -import org.jfree.chart.renderer.LookupPaintScale; -import org.jfree.chart.renderer.PaintScale; -import org.jfree.chart.renderer.xy.XYBlockRenderer; -import org.jfree.chart.title.PaintScaleLegend; -import org.jfree.data.Range; -import org.jfree.ui.RectangleAnchor; -import org.jfree.ui.RectangleEdge; -import org.jfree.ui.RectangleInsets; - -import ch.psi.plot.Plot; - - -/** - * Returns a matrix plot panel - */ -public class MatrixPlot implements Plot { - - private static final int chartPanelWidth = 500; - private static final int chartPanelHeight = 270; - - private String title; - private String xAxisLabel = "X"; - private String yAxisLabel = "Y"; - - private boolean grayScale = false; - - private MatrixPlotData data; - private JFreeChart chart; - private ChartPanel chartPanel; - - /** - * Constructor - * @param title - * @param data - */ - public MatrixPlot(String title, final MatrixPlotData data) { - this.title = title; - this.data = data; - } - - // Action Classes that implement methods called after keyboard input - - /** - * Adapt the context menu of the chart panel - */ - private void adaptContextMenu(final ChartPanel chartPanel){ - - // Show hide tooltips - final String tooltipsMenuLabel = "Tooltips"; - final String hideTooltipsMenuLabel = "Hide Tooltips"; - JMenuItem contextMenuItemToolTip = new JMenuItem(tooltipsMenuLabel); - contextMenuItemToolTip.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - JMenuItem source = (JMenuItem)(e.getSource()); - if (source.getText() == tooltipsMenuLabel){ - showTooltip(); - source.setText(hideTooltipsMenuLabel); - } - - else if (source.getText() == hideTooltipsMenuLabel){ - hideTooltip(); - source.setText(tooltipsMenuLabel); - } - } - }); - chartPanel.getPopupMenu().add(contextMenuItemToolTip); - - // Update colormap - JMenuItem contextMenuItemAdaptScale = new JMenuItem("Update Scale"); - contextMenuItemAdaptScale.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - adaptColorMapScale(); - } - }); - - // Set gray scale colormap - JMenuItem contextMenuItemGrayScale = new JMenuItem("Gray Scale"); - contextMenuItemGrayScale.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - grayScale = true; - adaptColorMapScale(); - } - }); - - // Set color colormap - JMenuItem contextMenuItemTemperatureColor = new JMenuItem("Color Scale"); - contextMenuItemTemperatureColor.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - grayScale = false; - adaptColorMapScale(); - } - }); - - // Set color colormap - JMenuItem menuItemScale = new JMenuItem("Manual Scale"); - menuItemScale.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - ManualScaleDialog d = new ManualScaleDialog(); - d.setLocationRelativeTo(chartPanel); - d.setLow(((PaintScaleLegend) chart.getSubtitles().get(0)).getScale().getLowerBound()); - d.setHigh(((PaintScaleLegend) chart.getSubtitles().get(0)).getScale().getUpperBound()); - d.setMatrixPlot(MatrixPlot.this); - - d.showDialog(); - if(d.getSelectedOption()==JOptionPane.OK_OPTION){ - setColorScale(d.getLow(), d.getHigh()); - } - } - }); - - // Group colormap related menu items - JMenuItem contextMenuChooseColorMap = new JMenu("ColorMap"); - contextMenuChooseColorMap.add(contextMenuItemAdaptScale); - contextMenuChooseColorMap.add(menuItemScale); - contextMenuChooseColorMap.add(contextMenuItemGrayScale); - contextMenuChooseColorMap.add(contextMenuItemTemperatureColor); - chartPanel.getPopupMenu().add(contextMenuChooseColorMap); - - // Add separator - chartPanel.getPopupMenu().addSeparator(); - - // Detach plot into an own frame - JMenuItem contextMenuItemDetach = new JMenuItem("Detach Plot"); - contextMenuItemDetach.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - MatrixPlot p = new MatrixPlot(title, data); - - final JFrame frame = new JFrame(title); - frame.getContentPane(); - frame.setContentPane(p.getChartPanel()); - frame.pack(); - frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); // Close application if frame is closed - - // Set color scale - p.adaptColorMapScale(); - - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - frame.setVisible(true); - } - }); - } - }); - chartPanel.getPopupMenu().add(contextMenuItemDetach); - - } - - - /** - * Show Tooltips. This is not done per default since it makes the app slow for datasize >= 1M - */ - private void showTooltip(){ - //Tooltips are quit expensive - DecimalFormat dm = new DecimalFormat("0.##########"); - XYZToolTipGenerator xYZToolTipGenerator = new StandardXYZToolTipGenerator("{0}: ({1} / {2} / {3})", dm, dm, dm); - - chart.getXYPlot().getRenderer().setBaseToolTipGenerator(xYZToolTipGenerator); - ((XYBlockRenderer)chart.getXYPlot().getRenderer()).setBaseCreateEntities(true); - } - - /** - * Clear Tooltips - */ - private void hideTooltip(){ - //Tooltips are quit expensive - ((XYBlockRenderer)chart.getXYPlot().getRenderer()).setBaseToolTipGenerator(null); - ((XYBlockRenderer)chart.getXYPlot().getRenderer()).setBaseCreateEntities(false); - - } - - - /** - * Adapt the lower and upper color map scale to the min and max data values of the currently selected region - * Need to be called AFTER the chart panel is created - */ - public void adaptColorMapScale(){ - double[] v = XYZDatasetUtil.minMaxZValue(data.getData()); - if(v[0]!=Double.NaN && v[1]!=Double.NaN && v[0] data.getAxisMaxY()){ - Range range = new Range(data.getAxisMinY(), data.getAxisMaxY()); - axis.setRange(range, true, false); - } - } - }); - plot.getDomainAxis().addChangeListener(new AxisChangeListener() { - @Override - public void axisChanged(AxisChangeEvent event) { - ValueAxis axis = ((ValueAxis)event.getAxis()); - if(axis.getLowerBound() < data.getAxisMinX() || axis.getUpperBound() > data.getAxisMaxX()){ - Range range = new Range(data.getAxisMinX(), data.getAxisMaxX()); - axis.setRange(range, true, false); - } - } - }); - - - - chart = new JFreeChart(title, plot); - - //Remove the series label (also called legend) - chart.removeLegend(); - //AntiAliasing is used to speed up rendering -// chart.setAntiAlias(false); - - // Init PaintScale - setColorScale(0,1); - - - - //Create the Chartpanel where the chart will be plotted - chartPanel = new ChartPanel(chart); - - chartPanel.setPreferredSize(new java.awt.Dimension(chartPanelWidth, chartPanelHeight)); - - //All interactive menu items - adaptContextMenu(chartPanel); - } - - - return chartPanel; - } - - /* (non-Javadoc) - * @see ch.psi.plot.Plot#update() - */ - @Override - public void update() { - chart.fireChartChanged(); - adaptColorMapScale(); - } - - /* (non-Javadoc) - * @see ch.psi.plot.Plot#getChart() - */ - @Override - public JFreeChart getChart() { - return chart; - } -} diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/xyz/MatrixPlot2.java b/ch.psi.plot/src/main/java/ch/psi/plot/xyz/MatrixPlot2.java deleted file mode 100644 index c9d8277..0000000 --- a/ch.psi.plot/src/main/java/ch/psi/plot/xyz/MatrixPlot2.java +++ /dev/null @@ -1,352 +0,0 @@ -package ch.psi.plot.xyz; - -import java.awt.Color; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.text.DecimalFormat; - -import javax.swing.JFrame; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.WindowConstants; - -import org.jfree.chart.ChartPanel; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.labels.StandardXYZToolTipGenerator; -import org.jfree.chart.labels.XYZToolTipGenerator; -import org.jfree.chart.plot.XYPlot; -import org.jfree.chart.renderer.LookupPaintScale; -import org.jfree.chart.renderer.PaintScale; -import org.jfree.chart.renderer.xy.XYBlockRenderer; -import org.jfree.chart.title.PaintScaleLegend; -import org.jfree.ui.RectangleEdge; -import org.jfree.ui.RectangleInsets; - -import ch.psi.plot.Plot; - - -/** - * Returns a matrix plot panel - */ -public class MatrixPlot2 implements Plot { - - private static final int chartPanelWidth = 500; - private static final int chartPanelHeight = 270; - - private String title; - - private boolean grayScale = false; - - private DynamicXYZDatasetList data; - private JFreeChart chart; - private ChartPanel chartPanel; - - /** - * @param title - * @param data - */ - public MatrixPlot2(String title, final DynamicXYZDatasetList data) { - this.title = title; - this.data = data; - } - - // Action Classes that implement methods called after keyboard input - - /** - * Adapt the context menu of the chart panel - */ - private void adaptContextMenu(final ChartPanel chartPanel){ - - // Show hide tooltips - final String tooltipsMenuLabel = "Tooltips"; - final String hideTooltipsMenuLabel = "Hide Tooltips"; - JMenuItem contextMenuItemToolTip = new JMenuItem(tooltipsMenuLabel); - contextMenuItemToolTip.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - JMenuItem source = (JMenuItem)(e.getSource()); - if (source.getText() == tooltipsMenuLabel){ - showTooltip(); - source.setText(hideTooltipsMenuLabel); - } - - else if (source.getText() == hideTooltipsMenuLabel){ - hideTooltip(); - source.setText(tooltipsMenuLabel); - } - } - }); - chartPanel.getPopupMenu().add(contextMenuItemToolTip); - - // Update colormap - JMenuItem contextMenuItemAdaptScale = new JMenuItem("Update Scale"); - contextMenuItemAdaptScale.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - adaptColorMapScale(); - } - }); - - // Set gray scale colormap - JMenuItem contextMenuItemGrayScale = new JMenuItem("Gray Scale"); - contextMenuItemGrayScale.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - grayScale = true; - adaptColorMapScale(); - } - }); - - // Set color colormap - JMenuItem contextMenuItemTemperatureColor = new JMenuItem("Color Scale"); - contextMenuItemTemperatureColor.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - grayScale = false; - adaptColorMapScale(); - } - }); - -// // Set color colormap -// JMenuItem menuItemScale = new JMenuItem("Manual Scale"); -// menuItemScale.addActionListener(new ActionListener() { -// @Override -// public void actionPerformed(ActionEvent e) { -// ManualScaleDialog d = new ManualScaleDialog(); -// d.setLocationRelativeTo(chartPanel); -// d.setLow(((PaintScaleLegend) chart.getSubtitles().get(0)).getScale().getLowerBound()); -// d.setHigh(((PaintScaleLegend) chart.getSubtitles().get(0)).getScale().getUpperBound()); -// d.setMatrixPlot(MatrixPlot2.this); -// -// d.showDialog(); -// if(d.getSelectedOption()==JOptionPane.OK_OPTION){ -// setColorScale(d.getLow(), d.getHigh()); -// } -// } -// }); - - // Group colormap related menu items - JMenuItem contextMenuChooseColorMap = new JMenu("ColorMap"); - contextMenuChooseColorMap.add(contextMenuItemAdaptScale); -// contextMenuChooseColorMap.add(menuItemScale); - contextMenuChooseColorMap.add(contextMenuItemGrayScale); - contextMenuChooseColorMap.add(contextMenuItemTemperatureColor); - chartPanel.getPopupMenu().add(contextMenuChooseColorMap); - - // Add separator - chartPanel.getPopupMenu().addSeparator(); - - // Detach plot into an own frame - JMenuItem contextMenuItemDetach = new JMenuItem("Detach Plot"); - contextMenuItemDetach.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - MatrixPlot2 p = new MatrixPlot2(title, data); - - final JFrame frame = new JFrame(title); - frame.getContentPane(); - frame.setContentPane(p.getChartPanel()); - frame.pack(); - frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); // Close application if frame is closed - - // Set color scale - p.adaptColorMapScale(); - - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - frame.setVisible(true); - } - }); - } - }); - chartPanel.getPopupMenu().add(contextMenuItemDetach); - - } - - - /** - * Show Tooltips. This is not done per default since it makes the app slow for datasize >= 1M - */ - private void showTooltip(){ - //Tooltips are quit expensive - DecimalFormat dm = new DecimalFormat("0.##########"); - XYZToolTipGenerator xYZToolTipGenerator = new StandardXYZToolTipGenerator("{0}: ({1} / {2} / {3})", dm, dm, dm); - - chart.getXYPlot().getRenderer().setBaseToolTipGenerator(xYZToolTipGenerator); - ((XYBlockRenderer)chart.getXYPlot().getRenderer()).setBaseCreateEntities(true); - } - - /** - * Clear Tooltips - */ - private void hideTooltip(){ - //Tooltips are quit expensive - ((XYBlockRenderer)chart.getXYPlot().getRenderer()).setBaseToolTipGenerator(null); - ((XYBlockRenderer)chart.getXYPlot().getRenderer()).setBaseCreateEntities(false); - - } - - - /** - * Adapt the lower and upper color map scale to the min and max data values of the currently selected region - * Need to be called AFTER the chart panel is created - */ - public void adaptColorMapScale(){ - if(!Double.isNaN(data.getzLowerBound()) && !Double.isNaN(data.getzUpperBound())){ - setColorScale(data.getzLowerBound(),data.getzUpperBound()); - } - } - - /** - * Set the min and max of color map scale to scaleMin and scaleMax - * @param scaleMin min value of scale - * @param scaleMax max value of scale - */ - public void setColorScale(double scaleMin, double scaleMax){ - - // Create scale for legend - LookupPaintScale legendScale = new LookupPaintScale(scaleMin, scaleMax, Color.GRAY); - setScaleColors(legendScale, scaleMin, scaleMax); - - // Create legend - PaintScaleLegend legend = new PaintScaleLegend(legendScale, new NumberAxis()); - legend.setPadding(new RectangleInsets(5, 5, 5, 5)); - // Width of the legend (colorbar) - legend.setStripWidth(20); - // Position of the legend - legend.setPosition(RectangleEdge.RIGHT); - // Remove background paint/color - legend.setBackgroundPaint(null); - - // Add legend to plot panel - chart.clearSubtitles(); - chart.addSubtitle(legend); - - - //We need a second scale for rendering only, where the 'infinities' are in correct color - LookupPaintScale rendererScale = new LookupPaintScale(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Color.GRAY); - setScaleColors(rendererScale, scaleMin, scaleMax); - // Make the paint scale range from - to + infinity - if (grayScale) { - rendererScale.add(Double.NEGATIVE_INFINITY, ColorManager.getGrayForValue(scaleMin, scaleMin, scaleMax)); - rendererScale.add(Double.POSITIVE_INFINITY, ColorManager.getGrayForValue(scaleMax, scaleMin, scaleMax)); - } else { - rendererScale.add(Double.NEGATIVE_INFINITY, ColorManager.getColourForValue(scaleMin, scaleMin, scaleMax)); - rendererScale.add(Double.POSITIVE_INFINITY, ColorManager.getColourForValue(scaleMax, scaleMin, scaleMax)); - } - ((XYBlockRenderer) chart.getXYPlot().getRenderer()).setPaintScale(rendererScale); - } - - /** - * Set the colors for the colored Paint Scale (either single color or temperature color) - * @param paintScale - * @param scaleMin - * @param scaleMax - */ - private void setScaleColors(PaintScale paintScale, double scaleMin, double scaleMax){ - if (grayScale) { - for (int i = 0; i < 256; i++) { - double value = scaleMin + (i / 255.0) * (scaleMax - scaleMin); - ((LookupPaintScale) paintScale).add(value, ColorManager.getGrayForValue(value, scaleMin, scaleMax)); - } - } - else { - for (int i = 0; i < 256; i++) { - double value = scaleMin + (i / 255.0) * (scaleMax - scaleMin); - ((LookupPaintScale) paintScale).add(value, ColorManager.getColourForValue(value, scaleMin, scaleMax)); - } - } - } - - - - /** - * Get plot data - * @return - */ - public DynamicXYZDatasetList getData() { - return data; - } - - /** - * Get the chart panel - * @return - */ - @Override - public ChartPanel getChartPanel() { - if(chartPanel == null){ - - XYPlot plot = new XYPlot(data, data.getxAxis(), data.getyAxis(), data.getRenderer()); - - - // Remove background paint/color - plot.setBackgroundPaint(null); - - // Set the maximum zoom out to the initial zoom rate This also - // provides a workaround for dynamic plots because there zoom out does not work correctly (zoom out to infinity) -// plot.getRangeAxis().addChangeListener(new AxisChangeListener() { -// @Override -// public void axisChanged(AxisChangeEvent event) { -// ValueAxis axis = ((ValueAxis)event.getAxis()); -// if(axis.getLowerBound() < data.getyLowerBound() || axis.getUpperBound() > data.getyUpperBound()){ -// Range range = new Range(data.getyLowerBound(), data.getyUpperBound()); -// axis.setRange(range, true, false); -// } -// } -// }); -// plot.getDomainAxis().addChangeListener(new AxisChangeListener() { -// @Override -// public void axisChanged(AxisChangeEvent event) { -// ValueAxis axis = ((ValueAxis)event.getAxis()); -// if(axis.getLowerBound() < data.getxLowerBound() || axis.getUpperBound() > data.getxUpperBound()){ -// Range range = new Range(data.getxLowerBound(), data.getxUpperBound()); -// axis.setRange(range, true, false); -// } -// } -// }); - - - - chart = new JFreeChart(title, plot); - - //Remove the series label (also called legend) - chart.removeLegend(); - //AntiAliasing is used to speed up rendering -// chart.setAntiAlias(false); - - // Init PaintScale - setColorScale(0,1); - - - - //Create the Chartpanel where the chart will be plotted - chartPanel = new ChartPanel(chart); - - chartPanel.setPreferredSize(new java.awt.Dimension(chartPanelWidth, chartPanelHeight)); - - //All interactive menu items - adaptContextMenu(chartPanel); - } - - - return chartPanel; - } - - /* (non-Javadoc) - * @see ch.psi.plot.Plot#update() - */ - @Override - public void update() { - chart.fireChartChanged(); - adaptColorMapScale(); - } - - /* (non-Javadoc) - * @see ch.psi.plot.Plot#getChart() - */ - @Override - public JFreeChart getChart() { - return chart; - } -} diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/xyz/MatrixPlotData.java b/ch.psi.plot/src/main/java/ch/psi/plot/xyz/MatrixPlotData.java deleted file mode 100644 index fd00e06..0000000 --- a/ch.psi.plot/src/main/java/ch/psi/plot/xyz/MatrixPlotData.java +++ /dev/null @@ -1,191 +0,0 @@ -package ch.psi.plot.xyz; - -import java.util.Arrays; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.jfree.data.xy.DefaultXYZDataset; -import org.jfree.data.xy.XYZDataset; - -/** - * PlotData implementation optimized for matrix data. - * ... - */ -public class MatrixPlotData { - - private static final Logger logger = Logger.getLogger(MatrixPlotData.class.getName()); - - private final double minX; - private final double maxX; - private final int numberOfBinsX; - private final double binWidthX; - - private final double minY; - private final double maxY; - private final int numberOfBinsY; - private final double binWidthY; - - private final double axisMinX; - private final double axisMaxX; - private final double axisMinY; - private final double axisMaxY; - - - double[] xvalues; - double[] yvalues; - double[] zvalues; - - private XYZDataset data; - - public MatrixPlotData(double minX, double maxX, int nX, double minY, double maxY, int nY){ - - this.minX = minX; - this.maxX = maxX; - this.numberOfBinsX = nX; - - this.minY = minY; - this.maxY = maxY; - this.numberOfBinsY = nY; - - this.binWidthX = (maxX - minX)/(double) (numberOfBinsX - 1); - this.binWidthY = (maxY - minY)/(double) (numberOfBinsY - 1); - - // The axis min and max values need to be half a bin larger. Otherwise the outer pixels - // will not be plotted correctly (half of the pixel is missing) - this.axisMinX = minX - 0.5*binWidthX; - this.axisMaxX = maxX + 0.5*binWidthX; - - this.axisMinY = minY - 0.5*binWidthY; - this.axisMaxY = maxY + 0.5*binWidthY; - - int arraylength = numberOfBinsX*numberOfBinsY; - xvalues = new double[arraylength]; - yvalues = new double[arraylength]; - zvalues = new double[arraylength]; - - Arrays.fill(xvalues, Double.NEGATIVE_INFINITY); - Arrays.fill(yvalues, Double.NEGATIVE_INFINITY); - Arrays.fill(zvalues, Double.NEGATIVE_INFINITY); - - double[][] dataArray = new double[][] {xvalues, yvalues, zvalues}; - - - //Create the XYDataset (org.jfree), not to be confused with the ch.psi dataSet) - data = new DefaultXYZDataset(); - ((DefaultXYZDataset)data).addSeries("Data" , dataArray); - } - - public XYZDataset getData() { - return data; - } - - public void addData(final double x, final double y, final double z) { - final int xBin = ((int) ((x - axisMinX)/binWidthX)); - final int yBin = ((int) ((y - axisMinY)/binWidthY)); - final int index = yBin * numberOfBinsX + xBin; - - try{ - //x Value is column, y value is row - xvalues[index] = x; - yvalues[index] = y; - zvalues[index] = z; - } - catch(ArrayIndexOutOfBoundsException e){ - logger.log(Level.WARNING, "Unable to add data point at index "+index+" [x: "+x+" y: "+y+"]", e); - } - } - - public void clear(){ - Arrays.fill(xvalues, Double.NEGATIVE_INFINITY); - Arrays.fill(yvalues, Double.NEGATIVE_INFINITY); - Arrays.fill(zvalues, Double.NEGATIVE_INFINITY); - } - - /** - * @return the axisMinX - */ - public double getAxisMinX() { - return axisMinX; - } - - /** - * @return the axisMinY - */ - public double getAxisMinY() { - return axisMinY; - } - - /** - * @return the binWidthX - */ - public double getBinWidthX() { - return binWidthX; - } - - /** - * @return the binWidthY - */ - public double getBinWidthY() { - return binWidthY; - } - - /** - * @return the minX - */ - public double getMinX() { - return minX; - } - - /** - * @return the maxX - */ - public double getMaxX() { - return maxX; - } - - /** - * @return the minY - */ - public double getMinY() { - return minY; - } - - /** - * @return the maxY - */ - public double getMaxY() { - return maxY; - } - - /** - * @return the axisMaxX - */ - public double getAxisMaxX() { - return axisMaxX; - } - - /** - * @return the axisMaxY - */ - public double getAxisMaxY() { - return axisMaxY; - } - - /** - * @return the numberOfBinsX - */ - public int getNumberOfBinsX() { - return numberOfBinsX; - } - - /** - * @return the numberOfBinsY - */ - public int getNumberOfBinsY() { - return numberOfBinsY; - } - -} - - - diff --git a/ch.psi.plot/src/main/java/ch/psi/plot/xyz/XYZDatasetUtil.java b/ch.psi.plot/src/main/java/ch/psi/plot/xyz/XYZDatasetUtil.java deleted file mode 100644 index 1533e23..0000000 --- a/ch.psi.plot/src/main/java/ch/psi/plot/xyz/XYZDatasetUtil.java +++ /dev/null @@ -1,71 +0,0 @@ -/** - * - * Copyright 2010 Paul Scherrer Institute. All rights reserved. - * - * This code 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. - * - * This code 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 this code. If not, see . - * - */ - -package ch.psi.plot.xyz; - -import org.jfree.data.xy.XYZDataset; - -/** - */ -public class XYZDatasetUtil { - - /** - * Find the minimum and maximum value of the dataset - * @param dataset Dataset to find the min and max value - * @return Double array with min in element 0 and max in element 1 - */ - public static double[] minMaxZValue(XYZDataset dataset){ - - double min = Double.NaN; - double max = Double.NaN; - - if(dataset != null){ - int seriesCount = dataset.getSeriesCount(); - for(int s=0;smax){ - max=v; - } - if(v. - * + * */ - package ch.psi.plot.xy; +import ch.psi.plot.LinePlot; +import ch.psi.plot.LinePlotSeries; +import ch.psi.plot.utils.SwingUtils; +import ch.psi.plot.xy.generator.Sinus; +import ch.psi.plot.xy.generator.XYGenerator; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.LineNumberReader; - +import java.util.logging.Level; +import java.util.logging.Logger; import javax.swing.JFrame; - -import org.jfree.chart.ChartPanel; -import org.jfree.ui.RefineryUtilities; +import javax.swing.JPanel; import org.junit.After; import org.junit.Before; import org.junit.Test; -import ch.psi.plot.xy.LinePlot; -import ch.psi.plot.xy.generator.Sinus; -import ch.psi.plot.xy.generator.XYGenerator; - /** * Test for the LinePlot class - * @author ebner * */ public class LinePlotTest { - private final File file = new File("../ch.psi.sls.xasec/testfiles/text/beamCurrent.txt"); - private final long timeToClose = 7200000; // 2 hours - - @Before - public void setUp() throws Exception { - } + private final File file = new File("../ch.psi.sls.xasec/testfiles/text/beamCurrent.txt"); + private final long timeToClose = 7200000; // 2 hours + static LinePlot linePlot; - @After - public void tearDown() throws Exception { - } - - /** - * Test LinePlot rendering point by point (getting data from a generator) - * @throws IOException - * @throws InterruptedException - */ - @Test - public void testLinePlotGeneratorPerformance() throws IOException, InterruptedException { - - for(int i=0;i<10;i++){ - LinePlot linePlot = new LinePlot("Title ", getDataFromGenerator(1)) ; -// linePlot.plot(); - - JFrame frame = new JFrame(); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.setContentPane(linePlot.getChartPanel()); - frame.pack(); - RefineryUtilities.centerFrameOnScreen(frame); - frame.setVisible(true); - } - - Thread.sleep(timeToClose); - } - - /** - * Test LinePlot rendering point by point (getting data from a generator) - * @throws IOException - * @throws InterruptedException - */ - @Test - public void testLinePlotAllDataAvailable() throws IOException, InterruptedException { - - for(int i=0;i<1;i++){ - XYSeriesCollectionP d = loadDataFromGenerator(); - LinePlot linePlot = new LinePlot("Title ", d) ; - - ChartPanel chartPanel = linePlot.getChartPanel(); - JFrame frame = new JFrame(); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.setContentPane(chartPanel); - frame.pack(); - RefineryUtilities.centerFrameOnScreen(frame); - frame.setVisible(true); - frame.setContentPane(chartPanel); - } - - Thread.sleep(timeToClose); - } - - /** - * Test LinePlot rendering point by point (getting data from a generator) - * @throws IOException - * @throws InterruptedException - */ - @Test - public void testLinePlotGenerator() throws IOException, InterruptedException { - - for(int i=0;i<1;i++){ - LinePlot linePlot = new LinePlot("Title ", getDataFromGenerator(1)) ; -// linePlot.plot(); - JFrame frame = new JFrame(); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.setContentPane(linePlot.getChartPanel()); - frame.pack(); - RefineryUtilities.centerFrameOnScreen(frame); - frame.setVisible(true); - } - - Thread.sleep(timeToClose); - } - - @Test - public void testLinePlotGeneratorOne() throws IOException, InterruptedException { + @Before + public void setUp() throws Exception { + linePlot = new ch.psi.plot.jfree.LinePlot(); + //linePlot = new ch.psi.plot.jlchart.LinePlot() ; + linePlot.setTitle("Title"); + } - XYSeriesCollectionP data = new XYSeriesCollectionP(); - XYGenerator generator = new XYGenerator(new Sinus(0.01), 0, 1, 1000, false); + @After + public void tearDown() throws Exception { + } - generator.reset(); + /** + * Test LinePlot rendering point by point (getting data from a generator) + * + * @throws IOException + * @throws InterruptedException + */ + @Test + public void testLinePlotGeneratorPerformance() throws IOException, InterruptedException { + linePlot.clear(); + //for(int i=0;i<10;i++) + { + LinePlotSeries[] series = getDataFromGenerator(0, linePlot); + //linePlot.addSeries(series); - String seriesName = "test"; - XYSeriesP serie = new XYSeriesP(seriesName); - data.addSeries(serie); +//addDataFromGenerator(0, 10, 1000, linePlot); + JFrame frame = new JFrame(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setContentPane(linePlot.getChartPanel()); + frame.pack(); + SwingUtils.centerOnScreen(frame); + frame.setVisible(true); + } - double[] xy; - while ((xy = generator.getNewPoint()) != null) { - serie.add(xy[0], xy[1]); // Add t to the y value to see the plotted line - } + Thread.sleep(timeToClose); + } - LinePlot linePlot = new LinePlot("Title ", data); - JFrame frame = new JFrame(); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.setContentPane(linePlot.getChartPanel()); - frame.pack(); - RefineryUtilities.centerFrameOnScreen(frame); - frame.setVisible(true); + /** + * Test LinePlot rendering point by point (getting data from a generator) + * + * @throws IOException + * @throws InterruptedException + */ + @Test + public void testLinePlotAllDataAvailable() throws IOException, InterruptedException { + linePlot.clear(); + for (int i = 0; i < 1; i++) { + LinePlotSeries[] d = loadDataFromGenerator(linePlot); + //linePlot.addSeries(d); + JPanel chartPanel = linePlot.getChartPanel(); + JFrame frame = new JFrame(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setContentPane(chartPanel); + frame.pack(); + SwingUtils.centerOnScreen(frame); + frame.setVisible(true); + frame.setContentPane(chartPanel); + } - Thread.sleep(timeToClose); - } - - - /** - * Test LinePlot rendering point by point (getting data from a generator) - * @throws IOException - * @throws InterruptedException - */ - @Test - public void testLinePlotGenerator65536() throws IOException, InterruptedException { - - LinePlot linePlot = new LinePlot("Title ", loadDataFromGenerator65536(0)) ; + Thread.sleep(timeToClose); + } - JFrame frame = new JFrame(); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.setContentPane(linePlot.getChartPanel()); - frame.pack(); - RefineryUtilities.centerFrameOnScreen(frame); - frame.setVisible(true); - - int cnt = 1; - while(true){ - Thread.sleep(5000); - linePlot.getData().removeAllSeries(); - linePlot.getData().addSeries(loadDataFromGenerator65536(cnt).getSeries(0)); - cnt++; - } - } - - - /** - * Test LinePlot rendering point by point (getting data from a file) - * @throws IOException - * @throws InterruptedException - */ - @Test - public void testLinePlotFile() throws IOException, InterruptedException { - LinePlot linePlot = new LinePlot("Title ", getDataFromFile()) ; -// linePlot.plot(); - JFrame frame = new JFrame(); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.setContentPane(linePlot.getChartPanel()); - frame.pack(); - RefineryUtilities.centerFrameOnScreen(frame); - frame.setVisible(true); - - Thread.sleep(timeToClose); - } + /** + * Test LinePlot rendering point by point (getting data from a generator) + * + * @throws IOException + * @throws InterruptedException + */ + @Test + public void testLinePlotGenerator() throws IOException, InterruptedException { + linePlot.clear(); + for (int i = 0; i < 1; i++) { + linePlot.addSeries(getDataFromGenerator(1, linePlot)); + JFrame frame = new JFrame(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setContentPane(linePlot.getChartPanel()); + frame.pack(); + SwingUtils.centerOnScreen(frame); + frame.setVisible(true); + } - - /** - * Get data from file - * @return - * @throws IOException - */ - private XYSeriesCollectionP getDataFromFile() throws IOException{ - String seriesName = "File Data"; - XYSeriesCollectionP data = new XYSeriesCollectionP(); - LineNumberReader in = new LineNumberReader(new FileReader(file)); - - // Update data - data.addSeries(new XYSeriesP(seriesName)); - - // Read data - String s; - while ((s = in.readLine()) != null) { - double x = (double) in.getLineNumber(); - double y = Double.parseDouble(s); - - data.getSeries(seriesName).add(x, y); - } - in.close(); - return(data); - } - - /** - * Get data from a generator - * @param sleeptime Time between data points - * @return - */ - private XYSeriesCollectionP getDataFromGenerator(final long sleeptime){ - final String seriesBaseName = "Generator Data"; - final XYSeriesCollectionP data = new XYSeriesCollectionP(); - final XYGenerator generator = new XYGenerator(new Sinus(0.01), 0, 1, 1000, false); - - - - Thread t = new Thread(new Runnable() { - - @Override - public void run() { - for(int t=0;t<1000;t++){ - // Reset generator - generator.reset(); - - String seriesName = seriesBaseName+" - "+t; - XYSeriesP serie = new XYSeriesP(seriesName); - data.addSeries(serie); - - double[] xy; - while((xy=generator.getNewPoint())!=null){ - serie.add(xy[0], xy[1]+t); // Add t to the y value to see the plotted line -// data.getSeries(seriesName).add(xy[0], xy[1]+t,false); // No notification send - Update of GUI will be performed periodically - - try { - Thread.sleep(sleeptime); - } catch (InterruptedException e) { - } - } - } - - System.out.println("DONE"); - } - }); - t.start(); - - return data; - } - - private XYSeriesCollectionP loadDataFromGenerator() { - final String seriesBaseName = "Generator Data"; - final XYSeriesCollectionP data = new XYSeriesCollectionP(); - final XYGenerator generator = new XYGenerator(new Sinus(0.01), 0, 1, 1000, false); + Thread.sleep(timeToClose); + } - for (int t = 0; t < 1000; t++) { - // Reset generator - generator.reset(); + @Test + public void testLinePlotGeneratorOne() throws IOException, InterruptedException { - String seriesName = seriesBaseName + " - " + t; - final XYSeriesP f = new XYSeriesP(seriesName); - data.addSeries(f); + XYGenerator generator = new XYGenerator(new Sinus(0.01), 0, 1, 1000, false); - double[] xy; - while ((xy = generator.getNewPoint()) != null) { -// f.add(xy[0], xy[1] + t); // Add t to the y value to see the plotted line - f.add(xy[0], xy[1] + t, false); // No notification send - use this if all data is available before plotting - } - } + generator.reset(); - System.out.println("DONE"); + String seriesName = "test"; + LinePlotSeries series = new LinePlotSeries(seriesName); - return data; - } - - private XYSeriesCollectionP loadDataFromGenerator65536(int count) { - final String seriesBaseName = "Generator Data"; - final XYSeriesCollectionP data = new XYSeriesCollectionP(); - - final XYGenerator generator = new XYGenerator(new Sinus(0.01), 0, 1, 65536, false); - - String seriesName = seriesBaseName; - final XYSeriesP f = new XYSeriesP(seriesName); - data.addSeries(f); + double[] xy; + while ((xy = generator.getNewPoint()) != null) { + series.appendData(xy[0], xy[1]); // Add t to the y value to see the plotted line + } - double[] xy; - while ((xy = generator.getNewPoint()) != null) { - f.add(xy[0], xy[1]+count, false); // No notification send - use this if all data is available before plotting - } + linePlot.clear(); + linePlot.addSeries(series); - System.out.println("DONE"); + JFrame frame = new JFrame(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setContentPane(linePlot.getChartPanel()); + frame.pack(); + SwingUtils.centerOnScreen(frame); + frame.setVisible(true); + + Thread.sleep(timeToClose); + } + + /** + * Test LinePlot rendering point by point (getting data from a generator) + * + * @throws IOException + * @throws InterruptedException + */ + @Test + public void testLinePlotGenerator65536() throws IOException, InterruptedException { + linePlot.clear(); + linePlot.addSeries(loadDataFromGenerator65536(0, linePlot)); + + JFrame frame = new JFrame(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setContentPane(linePlot.getChartPanel()); + frame.pack(); + SwingUtils.centerOnScreen(frame); + frame.setVisible(true); + + int cnt = 1; + while (true) { + Thread.sleep(5000); + linePlot.clear(); + linePlot.addSeries(loadDataFromGenerator65536(cnt, linePlot)); + cnt++; + } + + } + + /** + * Test LinePlot rendering point by point (getting data from a file) + * + * @throws IOException + * @throws InterruptedException + */ + @Test + public void testLinePlotFile() throws IOException, InterruptedException { + linePlot.clear(); + linePlot.addSeries(getDataFromFile()); + JFrame frame = new JFrame(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setContentPane(linePlot.getChartPanel()); + frame.pack(); + SwingUtils.centerOnScreen(frame); + frame.setVisible(true); + + Thread.sleep(timeToClose); + } + + /** + * Get data from file + * + * @return + * @throws IOException + */ + private LinePlotSeries getDataFromFile() throws IOException { + String seriesName = "File Data"; + LineNumberReader in = new LineNumberReader(new FileReader(file)); + + // Update data + LinePlotSeries series = new LinePlotSeries(seriesName); + + // Read data + String s; + while ((s = in.readLine()) != null) { + double x = (double) in.getLineNumber(); + double y = Double.parseDouble(s); + + series.appendData(x, y); + } + in.close(); + return (series); + } + + /** + * Get data from a generator + * + * @param sleeptime Time between data points + * @return + */ + private LinePlotSeries[] getDataFromGenerator(final long sleeptime, final LinePlot plot) { + final String seriesBaseName = "Generator Data"; + final LinePlotSeries[] series = new LinePlotSeries[100]; + for (int i = 0; i < series.length; i++) { + String seriesName = seriesBaseName + " - " + i; + series[i] = new LinePlotSeries(seriesName); + } + plot.addSeries(series); + final XYGenerator generator = new XYGenerator(new Sinus(0.01), 0, 1, 1000, false); + + Thread t = new Thread(new Runnable() { + + @Override + public void run() { + long start = System.currentTimeMillis(); + for (int i = 0; i < series.length; i++) { + // Reset generator + generator.reset(); + double[] xy; + while ((xy = generator.getNewPoint()) != null) { + series[i].appendData(xy[0], xy[1] + i); // Add t to the y value to see the plotted line + + try { + Thread.sleep(sleeptime); + } catch (InterruptedException e) { + } + } + } + + System.out.println("DONE: " + (System.currentTimeMillis() - start)); + } + }); + t.start(); + + return series; + } + + private LinePlotSeries[] loadDataFromGenerator(final LinePlot plot) { + final String seriesBaseName = "Generator Data"; + final LinePlotSeries[] series = new LinePlotSeries[10]; + for (int i = 0; i < series.length; i++) { + String seriesName = seriesBaseName + " - " + i; + series[i] = new LinePlotSeries(seriesName); + } + plot.addSeries(series); + + final XYGenerator generator = new XYGenerator(new Sinus(0.01), 0, 1, 1000, false); + + plot.setUpdatesEnabled(false); + for (int t = 0; t < 1000; t++) { + // Reset generator + generator.reset(); + double[] xy; + while ((xy = generator.getNewPoint()) != null) { + series[t].appendData(xy[0], xy[1] + t); // Add t to the y value to see the plotted line + } + plot.requestSeriesUpdate(series[t]); + } + plot.setUpdatesEnabled(true); + + System.out.println("DONE"); + + return series; + } + + private LinePlotSeries loadDataFromGenerator65536(int count, final LinePlot plot) { + final String seriesBaseName = "Generator Data"; + LinePlotSeries series = new LinePlotSeries(seriesBaseName); + + final XYGenerator generator = new XYGenerator(new Sinus(0.01), 0, 1, 65536, false); + + plot.setUpdatesEnabled(false); + double[] xy; + plot.setUpdatesEnabled(false); + while ((xy = generator.getNewPoint()) != null) { + series.appendData(xy[0], xy[1] + count); // No notification send - use this if all data is available before plotting + } + plot.setUpdatesEnabled(true); + plot.update(true); + System.out.println("DONE"); + + return series; + } - return data; - } } diff --git a/ch.psi.plot/src/test/java/ch/psi/plot/xyz/MatrixPlot2Test.java b/ch.psi.plot/src/test/java/ch/psi/plot/xyz/MatrixPlot2Test.java deleted file mode 100644 index bd449b3..0000000 --- a/ch.psi.plot/src/test/java/ch/psi/plot/xyz/MatrixPlot2Test.java +++ /dev/null @@ -1,212 +0,0 @@ -/** - * - * Copyright 2010 Paul Scherrer Institute. All rights reserved. - * - * This code 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. - * - * This code 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 this code. If not, see . - * - */ - -package ch.psi.plot.xyz; - -import java.util.Random; -import java.util.logging.Logger; - -import javax.swing.JFrame; -import javax.swing.WindowConstants; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -//import ch.psi.sls.xasec.data.DataSet; -//import ch.psi.sls.xasec.data.DataSetUtils; -import ch.psi.plot.xyz.MatrixPlot; -import ch.psi.plot.xyz.MatrixPlotData; -import ch.psi.plot.xyz.generator.DataGenerator; -import ch.psi.plot.xyz.generator.Sinus2D; -import ch.psi.plot.xyz.generator.XYZGenerator; - - -/** - * Test case for MatrixPlot class - * @author ebner - * - */ -public class MatrixPlot2Test { - - // Get Logger - private static final Logger logger = Logger.getLogger(MatrixPlot2Test.class.getName()); - - private final long timeToClose = 7200000; // 2 hours - - @Before - public void setUp() throws Exception { - } - - @After - public void tearDown() throws Exception { - } - - /** - * Test case for MatrixPlot (getting data from a generator) - * @throws InterruptedException - */ - @Test - public void testMatrixPlot() throws InterruptedException { - double startX = 0; - double stepSizeX = 1; - int stepsX = 50; - double startY = 0; - double stepSizeY = 1; - int stepsY = 50; - - final DynamicXYZDatasetList data = new DynamicXYZDatasetList(); - - final XYZGenerator generator = new XYZGenerator(new Sinus2D(2,4), startX, stepSizeX, stepsX, startY, stepSizeY, stepsY, false); - final MatrixPlot2 plot = new MatrixPlot2("Matrix Plot Test", data); - - final JFrame frame = new JFrame(""); - frame.setContentPane(plot.getChartPanel()); - frame.pack(); - frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); // Close application if frame is closed - - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - frame.setVisible(true); - } - }); - - Thread t = new Thread(new Runnable() { - - @Override - public void run() { -// for(int t=0;t<200;t++){ -// // Reset generator -// generator.reset(); - -// int count = 0; - double[] xyz; - while((xyz=generator.getNewPoint())!=null){ - data.addData(xyz[0], xyz[1], xyz[2]); - - try { - Thread.sleep(10); - } catch (InterruptedException e) { - } - - // or set matrixChart.setNotify(false); in MatrixPlot Line 431 ... -// if(count==10){ -// plot.update(); -// count=0; -// } -// else{ -// count++; -// } - } - System.out.println("Generator done"); - -// } - - } - }); - t.start(); - - Thread.sleep(timeToClose); - } - - @Test - public void testPlotConverterGeneratorMatrixPlot() throws InterruptedException { - DataGenerator generator = new DataGenerator(new Sinus2D(2,4)); - generator.generateData(); - - MatrixPlot plot = new MatrixPlot("Matrix Plot Test", generator.getData()); - -// converter.generateData(); -//// Thread t = new Thread(converter); -//// t.start(); - - final JFrame frame = new JFrame(""); - frame.setContentPane(plot.getChartPanel()); - frame.pack(); - frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); // Close application if frame is closed - - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - frame.setVisible(true); - } - }); - - - Thread.sleep(timeToClose); - } - - @Test - public void testPlotMatrixPlot() throws InterruptedException { - MatrixPlotData data = new MatrixPlotData(-10, -1, 10, -10, -1, 10); - - Random r = new Random(); - - for (double i = data.getMinX(); i <= data.getMaxX(); i++) { - for (double t = data.getMinY(); t <= data.getMaxY(); t++) { - data.addData(i, t, r.nextDouble() * 10); - } - } - - MatrixPlot plot = new MatrixPlot("Matrix Plot Test", data); - final JFrame frame = new JFrame(""); - frame.setContentPane(plot.getChartPanel()); - frame.pack(); - frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); // Close application if frame is closed - - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - frame.setVisible(true); - } - }); - - Thread.sleep(timeToClose); - } - - - @Test - public void testPlotMatrixPlot2() throws InterruptedException { - MatrixPlotData data = new MatrixPlotData(-11.5, -11.0, 6, -10.5, -10.0, 6); - - Random r = new Random(); - - for (double i = data.getMinX(); i <= data.getMaxX(); i=i+0.1) { - for (double t = data.getMinY(); t <= data.getMaxY(); t=t+0.1) { - logger.info("Add data: "+i+" "+t); - if(t==data.getMinY()){ - continue; - } - data.addData(i, t, r.nextDouble() * 10); - } - } - - MatrixPlot plot = new MatrixPlot("Matrix Plot Test", data); - final JFrame frame = new JFrame(""); - frame.setContentPane(plot.getChartPanel()); - frame.pack(); - frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); // Close application if frame is closed - - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - frame.setVisible(true); - } - }); - - Thread.sleep(timeToClose); - } -} diff --git a/ch.psi.plot/src/test/java/ch/psi/plot/xyz/MatrixPlotTest.java b/ch.psi.plot/src/test/java/ch/psi/plot/xyz/MatrixPlotTest.java deleted file mode 100644 index 7793804..0000000 --- a/ch.psi.plot/src/test/java/ch/psi/plot/xyz/MatrixPlotTest.java +++ /dev/null @@ -1,211 +0,0 @@ -/** - * - * Copyright 2010 Paul Scherrer Institute. All rights reserved. - * - * This code 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. - * - * This code 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 this code. If not, see . - * - */ - -package ch.psi.plot.xyz; - -import java.util.Random; -import java.util.logging.Logger; - -import javax.swing.JFrame; -import javax.swing.WindowConstants; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -//import ch.psi.sls.xasec.data.DataSet; -//import ch.psi.sls.xasec.data.DataSetUtils; -import ch.psi.plot.xyz.MatrixPlot; -import ch.psi.plot.xyz.MatrixPlotData; -import ch.psi.plot.xyz.generator.DataGenerator; -import ch.psi.plot.xyz.generator.Sinus2D; -import ch.psi.plot.xyz.generator.XYZGenerator; - - -/** - * Test case for MatrixPlot class - * @author ebner - * - */ -public class MatrixPlotTest { - - // Get Logger - private static final Logger logger = Logger.getLogger(MatrixPlotTest.class.getName()); - - private final long timeToClose = 7200000; // 2 hours - - @Before - public void setUp() throws Exception { - } - - @After - public void tearDown() throws Exception { - } - - /** - * Test case for MatrixPlot (getting data from a generator) - * @throws InterruptedException - */ - @Test - public void testMatrixPlot() throws InterruptedException { - double startX = 10; - double stepSizeX = 1; - int stepsX = 1000; - double startY = 10; - double stepSizeY = 1; - int stepsY = 1000; - - final MatrixPlotData data = new MatrixPlotData(startX, startX+stepsX*stepSizeX, stepsX, startY, startY+stepsY*stepSizeY, stepsY); - - final XYZGenerator generator = new XYZGenerator(new Sinus2D(2,4), startX, stepSizeX, stepsX, startY, stepSizeY, stepsY, false); - final MatrixPlot plot = new MatrixPlot("Matrix Plot Test", data); - - final JFrame frame = new JFrame(""); - frame.setContentPane(plot.getChartPanel()); - frame.pack(); - frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); // Close application if frame is closed - - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - frame.setVisible(true); - } - }); - - Thread t = new Thread(new Runnable() { - - @Override - public void run() { -// for(int t=0;t<200;t++){ -// // Reset generator -// generator.reset(); - -// int count = 0; - double[] xyz; - while((xyz=generator.getNewPoint())!=null){ - data.addData(xyz[0], xyz[1], xyz[2]); - - try { - Thread.sleep(1); - } catch (InterruptedException e) { - } - - // or set matrixChart.setNotify(false); in MatrixPlot Line 431 ... -// if(count==10){ -// plot.update(); -// count=0; -// } -// else{ -// count++; -// } - } - -// } - - } - }); - t.start(); - - Thread.sleep(timeToClose); - } - - @Test - public void testPlotConverterGeneratorMatrixPlot() throws InterruptedException { - DataGenerator generator = new DataGenerator(new Sinus2D(2,4)); - generator.generateData(); - - MatrixPlot plot = new MatrixPlot("Matrix Plot Test", generator.getData()); - -// converter.generateData(); -//// Thread t = new Thread(converter); -//// t.start(); - - final JFrame frame = new JFrame(""); - frame.setContentPane(plot.getChartPanel()); - frame.pack(); - frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); // Close application if frame is closed - - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - frame.setVisible(true); - } - }); - - - Thread.sleep(timeToClose); - } - - @Test - public void testPlotMatrixPlot() throws InterruptedException { - MatrixPlotData data = new MatrixPlotData(-10, -1, 10, -10, -1, 10); - - Random r = new Random(); - - for (double i = data.getMinX(); i <= data.getMaxX(); i++) { - for (double t = data.getMinY(); t <= data.getMaxY(); t++) { - data.addData(i, t, r.nextDouble() * 10); - } - } - - MatrixPlot plot = new MatrixPlot("Matrix Plot Test", data); - final JFrame frame = new JFrame(""); - frame.setContentPane(plot.getChartPanel()); - frame.pack(); - frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); // Close application if frame is closed - - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - frame.setVisible(true); - } - }); - - Thread.sleep(timeToClose); - } - - - @Test - public void testPlotMatrixPlot2() throws InterruptedException { - MatrixPlotData data = new MatrixPlotData(-11.5, -11.0, 6, -10.5, -10.0, 6); - - Random r = new Random(); - - for (double i = data.getMinX(); i <= data.getMaxX(); i=i+0.1) { - for (double t = data.getMinY(); t <= data.getMaxY(); t=t+0.1) { - logger.info("Add data: "+i+" "+t); - if(t==data.getMinY()){ - continue; - } - data.addData(i, t, r.nextDouble() * 10); - } - } - - MatrixPlot plot = new MatrixPlot("Matrix Plot Test", data); - final JFrame frame = new JFrame(""); - frame.setContentPane(plot.getChartPanel()); - frame.pack(); - frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); // Close application if frame is closed - - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - frame.setVisible(true); - } - }); - - Thread.sleep(timeToClose); - } -} diff --git a/ch.psi.plot/src/test/java/ch/psi/plot/xyz/generator/DataGenerator.java b/ch.psi.plot/src/test/java/ch/psi/plot/xyz/generator/DataGenerator.java index 9461b61..c7de3f9 100644 --- a/ch.psi.plot/src/test/java/ch/psi/plot/xyz/generator/DataGenerator.java +++ b/ch.psi.plot/src/test/java/ch/psi/plot/xyz/generator/DataGenerator.java @@ -3,7 +3,7 @@ package ch.psi.plot.xyz.generator; import java.util.logging.Logger; import ch.psi.plot.xy.generator.Noise; -import ch.psi.plot.xyz.MatrixPlotData; +import ch.psi.plot.MatrixPlotSeries; /** * Converter object converting a file into PixelPlot data @@ -12,7 +12,7 @@ public class DataGenerator implements Runnable { private static Logger logger = Logger.getLogger(DataGenerator.class.getName()); - private final MatrixPlotData data; + private final MatrixPlotSeries data; private XYZGeneratorFunction function; double xMin = 0; @@ -38,7 +38,7 @@ public class DataGenerator implements Runnable { public DataGenerator(XYZGeneratorFunction function, boolean noise, boolean metaDataAvailable){ this.function = function; - data = new MatrixPlotData(xMin,xMax,xNStep,yMin,yMax,yNStep); + data = new MatrixPlotSeries(null, xMin,xMax,xNStep,yMin,yMax,yNStep); if(noise){ noiseFunctionX = new Noise(data.getBinWidthX()); @@ -70,7 +70,7 @@ public class DataGenerator implements Runnable { } logger.fine("x: "+x+" y: "+y+" z: "+function.generate(x, y)); - data.addData(x, y, function.generate(x, y)); + data.appendData(x, y, function.generate(x, y)); // try { // Thread.sleep(1); // } catch (InterruptedException e1) { @@ -80,7 +80,7 @@ public class DataGenerator implements Runnable { } } - public MatrixPlotData getData() { + public MatrixPlotSeries getData() { return data; } diff --git a/ch.psi.plot/src/test/java/ch/psi/plot/xyz/generator/XYZGenerator.java b/ch.psi.plot/src/test/java/ch/psi/plot/xyz/generator/XYZGenerator.java index 8963219..534aa53 100644 --- a/ch.psi.plot/src/test/java/ch/psi/plot/xyz/generator/XYZGenerator.java +++ b/ch.psi.plot/src/test/java/ch/psi/plot/xyz/generator/XYZGenerator.java @@ -43,12 +43,12 @@ public class XYZGenerator { this.startX = startX; this.stepSizeX = stepSizeX; this.stepsX = stepsX; - this.currentStepX = startX; + this.currentStepX = 0; this.startY = startY; this.stepSizeY = stepSizeY; this.stepsY = stepsY; - this.currentStepY = startY; + this.currentStepY = 0; if(noise){ this.noiseGeneratorX = new Noise(stepSizeX); diff --git a/ch.psi.plot/tmp/done/Average.java b/ch.psi.plot/tmp/done/Average.java deleted file mode 100644 index 5e8d773..0000000 --- a/ch.psi.plot/tmp/done/Average.java +++ /dev/null @@ -1,76 +0,0 @@ -package ch.psi.plot.plot.done; - -import java.awt.Color; -import org.jfree.chart.plot.Marker; -import org.jfree.chart.plot.ValueMarker; -import org.jfree.data.xy.XYSeries; -import org.jfree.data.xy.XYSeriesCollection; -import org.jfree.ui.Layer; -import org.jfree.ui.RectangleAnchor; -import org.jfree.ui.TextAnchor; - -import ch.psi.plot.util.PluginExecutionException; -import ch.psi.plot.xy.LinePlot; -import ch.psi.plot.xy.LinePlotData; -import ch.psi.plot.xy.plugable.PlugableUtilXY; - -public class Average implements PlugableUtilXY{ - - private final static String averageLabel = "average"; - - @Override - public void execute(LinePlot lineplot) throws PluginExecutionException { - double average = calculateAverage(lineplot.getData()); - // add a labelled marker for the average - final Marker start = new ValueMarker(average); - start.setPaint(Color.blue); - start.setLabel(averageLabel); - start.setLabelAnchor(RectangleAnchor.BOTTOM_RIGHT); - start.setLabelTextAnchor(TextAnchor.TOP_RIGHT); - - if(lineplot.getChartPanel().getChart().getXYPlot().getRangeMarkers(Layer.FOREGROUND) != null){ - //remove the previous marker - Marker previousAverageMarker = null; - for (Object o: lineplot.getChartPanel().getChart().getXYPlot().getRangeMarkers(Layer.FOREGROUND)){ - if(o instanceof Marker){ - if( ((Marker) o).getLabel().equals(averageLabel) ){ - previousAverageMarker = (Marker) o; - } - } - } - - lineplot.getChartPanel().getChart().getXYPlot().removeRangeMarker(previousAverageMarker); - } - - lineplot.getChartPanel().getChart().getXYPlot().addRangeMarker(start); - - } - - @Override - public String getLabel() { - return this.getClass().getSimpleName(); - } - - /** - * Calculate average of all graphs - * @param data - * @return - */ - private double calculateAverage(LinePlotData data){ - XYSeriesCollection inputSeriesCollection = (XYSeriesCollection) data.getData(); - - double average = 0.0; - int numberOfValues = 0; - - for (Object xySeries : inputSeriesCollection.getSeries()) { - for (int i = 1; i < inputSeriesCollection.getSeries(((XYSeries) xySeries).getKey()).getItemCount(); i++) { - double yi = inputSeriesCollection.getSeries(((XYSeries) xySeries).getKey()).getDataItem(i).getYValue(); - average += yi; - } - numberOfValues += inputSeriesCollection.getSeries(((XYSeries) xySeries).getKey()).getItemCount(); - } - - return average/numberOfValues; - } - -} diff --git a/ch.psi.plot/tmp/done/CrossDrawer.java b/ch.psi.plot/tmp/done/CrossDrawer.java deleted file mode 100644 index 0382392..0000000 --- a/ch.psi.plot/tmp/done/CrossDrawer.java +++ /dev/null @@ -1,44 +0,0 @@ -package ch.psi.plot.xyz; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.geom.Line2D; -import java.awt.geom.Rectangle2D; - -import org.jfree.ui.Drawable; - -/** - * Class that draws an Red cross as annotation. - * - * This is an implementation of the {@link Drawable} interface, to illustrate the use of the - * {@link org.jfree.chart.annotations.XYDrawableAnnotation} class. - */ -public class CrossDrawer implements Drawable { - - private Color color; //= Color.orange; - private float strokeWidth = 1; - - /** - * Creates a new instance. - */ - public CrossDrawer(Color color) { - this.color = color; - } - - /** - * Draws cross - * @param g2 the graphics device. - * @param area the area in which to draw. - */ - public void draw(Graphics2D g2, Rectangle2D area) { - - // Draw red cross - g2.setPaint(color); - g2.setStroke(new BasicStroke(strokeWidth)); - Line2D line1 = new Line2D.Double(area.getCenterX(), area.getMinY(), area.getCenterX(), area.getMaxY()); - Line2D line2 = new Line2D.Double(area.getMinX(), area.getCenterY(), area.getMaxX(), area.getCenterY()); - g2.draw(line1); - g2.draw(line2); - } -} diff --git a/ch.psi.plot/tmp/done/Derivatives.java b/ch.psi.plot/tmp/done/Derivatives.java deleted file mode 100644 index ac4b3d5..0000000 --- a/ch.psi.plot/tmp/done/Derivatives.java +++ /dev/null @@ -1,82 +0,0 @@ -package ch.psi.plot.plot.done; - -import org.jfree.data.xy.XYSeries; -import org.jfree.data.xy.XYSeriesCollection; - -import ch.psi.plot.util.XYPoint; -import ch.psi.plot.xy.LinePlot; -import ch.psi.plot.xy.LinePlotData; - - -public class Derivatives implements PlugableUtilXY{ - - /** - * Calculate derivative (first and/or second order) of a given function. - * derivative is based upon 3 points. - * @param data - * @param inclusiveSecondOrder - * @return - */ - public LinePlotData calculateDerivative(LinePlotData data){ - XYSeriesCollection inputSeriesCollection = (XYSeriesCollection) data.getData(); - - XYSeriesCollection derivativeCollection = new XYSeriesCollection(); - - for (Object xySeries : inputSeriesCollection.getSeries()) { - XYSeries derivative = new XYSeries(((XYSeries) xySeries).getKey() + "'"); - XYSeries secondDerivative = new XYSeries(((XYSeries) xySeries).getKey() + "''"); - - for (int i = 1; i < inputSeriesCollection.getSeries(((XYSeries) xySeries).getKey()).getItemCount() - 1; i++) { - double xi = inputSeriesCollection.getSeries(((XYSeries) xySeries).getKey()).getDataItem(i).getXValue(); - double xiplus1 = inputSeriesCollection.getSeries(((XYSeries) xySeries).getKey()).getDataItem(i+1).getXValue(); - double ximinus1 = inputSeriesCollection.getSeries(((XYSeries) xySeries).getKey()).getDataItem(i-1).getXValue(); - double h1 = xi - ximinus1; - double h2 = xiplus1 - xi; - //double yiminus2 = inputSeriesCollection.getSeries(((XYSeries) xySeries).getKey()).getDataItem(i-2).getYValue(); - double yiminus1 = inputSeriesCollection.getSeries(((XYSeries) xySeries).getKey()).getDataItem(i-1).getYValue(); - double yiplus1 = inputSeriesCollection.getSeries(((XYSeries) xySeries).getKey()).getDataItem(i+1).getYValue(); - //double yiplus2 = inputSeriesCollection.getSeries(((XYSeries) xySeries).getKey()).getDataItem(i+2).getYValue(); - //5 point stencil (order h^4) - //double di = (-yiplus2 + 8*yiplus1 -8*yiminus1 + yiminus2)/12.0*h; - //* Point estimation - if(!(h1 + h2 == 0.0)){ - double di = (yiplus1 - yiminus1)/(h1 + h2); - derivative.add(xi, di); - } - double yi = inputSeriesCollection.getSeries(((XYSeries) xySeries).getKey()).getDataItem(i).getYValue(); - if (!(h1 == 0.0 || h2 == 0.0)){ - double d2i = (h1*yiplus1 - (h1+h2)*yi + h2*yiminus1)/(h1*h2*(h1+h2)); - secondDerivative.add(xi, d2i); - } - } - - derivativeCollection.addSeries(derivative); - derivativeCollection.addSeries(secondDerivative); - } - LinePlotData d = new LinePlotData(); - d.setData(derivativeCollection); - return d; - } - - - public XYPoint findMaximumDerivative(LinePlotData data){ - LinePlotData derivative = calculateDerivative(data); - XYPoint minimum = Extrema.findExtrema(derivative, true).get(0); - return minimum; - } - - @Override - public void execute(LinePlot lineplot) { - LinePlotData d = null; - d = calculateDerivative(lineplot.getData()); - LinePlot p = new LinePlot("Derivatives" , d); - p.plot(false); - - } - - @Override - public String getLabel() { - return this.getClass().getSimpleName(); - } - -} diff --git a/ch.psi.plot/tmp/done/Extrema.java b/ch.psi.plot/tmp/done/Extrema.java deleted file mode 100644 index 4b6ffef..0000000 --- a/ch.psi.plot/tmp/done/Extrema.java +++ /dev/null @@ -1,56 +0,0 @@ -package ch.psi.plot.plot.done; - -import java.util.ArrayList; -import java.util.List; - -import org.jfree.data.xy.XYSeries; -import org.jfree.data.xy.XYSeriesCollection; - -import ch.psi.plot.util.XYPoint; -import ch.psi.plot.xy.LinePlotData; - - -public class Extrema { - - public static List findExtrema(LinePlotData data, boolean returnMins){ - - ArrayList mins = new ArrayList(); - ArrayList maxs = new ArrayList(); - - XYSeriesCollection inputSeriesCollection = (XYSeriesCollection) data.getData(); - for (Object xySeries : inputSeriesCollection.getSeries()) { - double max = Double.NEGATIVE_INFINITY; - double min = Double.POSITIVE_INFINITY; - double xmax = 0.0; - double xmin = 0.0; - for (int i = 0; i < inputSeriesCollection.getSeries(((XYSeries) xySeries).getKey()).getItemCount(); i++) { - double xi = inputSeriesCollection.getSeries(((XYSeries) xySeries).getKey()).getDataItem(i).getXValue(); - double yi = inputSeriesCollection.getSeries(((XYSeries) xySeries).getKey()).getDataItem(i).getYValue(); - if(yi > max){ - max = yi; - xmax = xi; - } - if(yi < min){ - min = yi; - xmin = xi; - } - } - XYPoint minPoint = new XYPoint(xmin, min); - XYPoint maxPoint = new XYPoint(xmax, max); - - mins.add(minPoint); - maxs.add(maxPoint); - } - if (returnMins){ - return mins; - } - else{ - return maxs; - } - - } - - - - -} \ No newline at end of file diff --git a/ch.psi.plot/tmp/done/GraphChooserFrame.form b/ch.psi.plot/tmp/done/GraphChooserFrame.form deleted file mode 100644 index bbe3040..0000000 --- a/ch.psi.plot/tmp/done/GraphChooserFrame.form +++ /dev/null @@ -1,150 +0,0 @@ - - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/ch.psi.plot/tmp/done/GraphPropertiesPanel.form b/ch.psi.plot/tmp/done/GraphPropertiesPanel.form deleted file mode 100644 index 00380f1..0000000 --- a/ch.psi.plot/tmp/done/GraphPropertiesPanel.form +++ /dev/null @@ -1,112 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/ch.psi.plot/tmp/done/ImagePanel.java b/ch.psi.plot/tmp/done/ImagePanel.java deleted file mode 100644 index d691622..0000000 --- a/ch.psi.plot/tmp/done/ImagePanel.java +++ /dev/null @@ -1,29 +0,0 @@ -package ch.psi.plot.plot.done; - -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.image.BufferedImage; - -import javax.swing.JPanel; - -class ImagePanel extends JPanel - { - private static final long serialVersionUID = 1L; - private BufferedImage image; - - public ImagePanel( BufferedImage image ) - { - this.image = image; - - setPreferredSize( new Dimension(image.getWidth(), image.getHeight()) ); -// repaint(); -// invalidate(); - } - - @Override - protected void paintComponent(Graphics g) - { - if ( image != null ) - g.drawImage( image, 0, 0, this ); - } - } \ No newline at end of file diff --git a/ch.psi.plot/tmp/done/Integral.java b/ch.psi.plot/tmp/done/Integral.java deleted file mode 100644 index 3d148d2..0000000 --- a/ch.psi.plot/tmp/done/Integral.java +++ /dev/null @@ -1,60 +0,0 @@ -package ch.psi.plot.plot.done; - -import org.jfree.data.xy.XYSeries; -import org.jfree.data.xy.XYSeriesCollection; - -import ch.psi.plot.xy.LinePlot; -import ch.psi.plot.xy.LinePlotData; - - -public class Integral implements PlugableUtilXY{ - - @Override - public void execute(LinePlot lineplot) { - LinePlotData d = null; - d = calculateIntegral(lineplot.getData()); - if(d != null){ - LinePlot p = new LinePlot("Integral" , d); - p.plot(false); - } - - } - - @Override - public String getLabel() { - return this.getClass().getSimpleName(); - } - - /** - * Calculate Integral of function (trapezoidal) - * @param data - * @return - */ - private LinePlotData calculateIntegral(LinePlotData data){ - XYSeriesCollection inputSeriesCollection = (XYSeriesCollection) data.getData(); - - XYSeriesCollection integralCollection = new XYSeriesCollection(); - - for (Object xySeries : inputSeriesCollection.getSeries()) { - XYSeries integral = new XYSeries("int " + ((XYSeries) xySeries).getKey()); - - double intXi = 0.0; - for (int i = 1; i < inputSeriesCollection.getSeries(((XYSeries) xySeries).getKey()).getItemCount(); i++) { - double xi = inputSeriesCollection.getSeries(((XYSeries) xySeries).getKey()).getDataItem(i).getXValue(); - double ximinus1 = inputSeriesCollection.getSeries(((XYSeries) xySeries).getKey()).getDataItem(i-1).getXValue(); - double h1 = xi - ximinus1; - double yiminus1 = inputSeriesCollection.getSeries(((XYSeries) xySeries).getKey()).getDataItem(i-1).getYValue(); - double yi = inputSeriesCollection.getSeries(((XYSeries) xySeries).getKey()).getDataItem(i).getYValue(); - intXi += h1*(yi + yiminus1)/2.0; - integral.add(xi, intXi); - } - - integralCollection.addSeries(integral); - } - - LinePlotData d = new LinePlotData(); - d.setData(integralCollection); - return d; - } - -} diff --git a/ch.psi.plot/tmp/done/LinePlot.java b/ch.psi.plot/tmp/done/LinePlot.java deleted file mode 100644 index 8fc76fd..0000000 --- a/ch.psi.plot/tmp/done/LinePlot.java +++ /dev/null @@ -1,985 +0,0 @@ -package ch.psi.plot.plot.done; - -import java.awt.Color; -import java.awt.Paint; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.event.MouseMotionListener; -import java.awt.image.BufferedImage; -import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.ServiceLoader; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.swing.AbstractAction; -import javax.swing.JComponent; -import javax.swing.JFrame; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.KeyStroke; -import javax.swing.WindowConstants; - -import org.jfree.chart.ChartFactory; -import org.jfree.chart.ChartMouseEvent; -import org.jfree.chart.ChartMouseListener; -import org.jfree.chart.ChartPanel; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.annotations.XYAnnotation; -import org.jfree.chart.annotations.XYDrawableAnnotation; -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.entity.StandardEntityCollection; -import org.jfree.chart.labels.StandardXYToolTipGenerator; -import org.jfree.chart.labels.XYToolTipGenerator; -import org.jfree.chart.plot.IntervalMarker; -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.chart.plot.ValueMarker; -import org.jfree.chart.plot.XYPlot; -import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; -import org.jfree.data.Range; -import org.jfree.data.xy.XYDataset; -import org.jfree.data.xy.XYSeries; -import org.jfree.data.xy.XYSeriesCollection; -import org.jfree.ui.Layer; -import org.jfree.ui.RectangleInsets; -import org.jfree.ui.RefineryUtilities; - -import ch.psi.plot.plot.EventActionListener; -import ch.psi.plot.plot.Plot; -import ch.psi.plot.plot.util.CoordinateTransformer; -import ch.psi.plot.plot.xy.GraphChooserFrame; -import ch.psi.plot.plot.xy.Interval; -import ch.psi.plot.plot.xy.Marker; -import ch.psi.plot.plot.xyz.CrossDrawer; - - -//Removed interfaces: AxisChangeListener -public class LinePlot implements Plot, ChartMouseListener, MouseListener, MouseMotionListener, ActionListener { - - private static Logger logger = Logger.getLogger(LinePlot.class.getName()); - - private List eventActionListener = new ArrayList(); - private List plugableUtils; - - private ChartPanel chartPanel; - - private List markers; - - private boolean notification = true; - - private boolean dragging; - private boolean rescaleAxis = false; - private XYPoint difference = new XYPoint(0.0,0.0); - - //Defining Context Menu Label - private static final String pauseMenuLabel = "Pause Conversion"; - private static final String continueMenuLabel = "Continue Conversion"; - private static final String clearAnnotationsMenuLabel = "Clear Annotations"; - private static final String resetPlotMenuLabel = "Reset Plot"; - private static final String splitPlotMenuLabel = "Split Plot"; - private static final String detachPlotMenuLabel = "Detach Plot"; - private static final String showLegendMenuLabel = "Show Legend"; - private static final String hideLegendMenuLabel = "Hide Legend"; - private static final String hideGraphPlotMenuLabel = "Hide/Show Graph"; - private static final String dataPointsMarkersMenuLabel = "Hide/Show datapoint markers"; - private static final String showTooltipsMenuLabel = "Show Tooltips"; - private static final String hideTooltipsMenuLabel = "Hide Tooltips"; - private static final String disableGraphChooserMenuLabel = "Disable GraphChooser"; - private static final String enableGraphChooserMenuLabel = "Enable GraphChooser"; - - - - private static final int chartPanelWidth = 500; - private static final int chartPanelHeight = 270; - - - private JMenu hideGraphMenu; - private JMenuItem hideLegendMenuItem; - - - //Action Map keys (Input Map values) - - - - private LinePlotData data; - private String title; - private boolean tooltipVisible = false; - private boolean enableGraphChooser = false; - - - /** - * Constructor - * @param title Title of plot - */ - public LinePlot(String title){ - this(title, new LinePlotData(), true); - } - - /** - * Constructor - * @param title Title of plot - * @param data Data of plot - */ - public LinePlot(String title, LinePlotData data){ - this(title, data, true); - } - - /** - * Constructor - * @param title Title of plot - * @param data Plot data - * @param notification Flag whether adding a point will create a notification - * @param useFastRenderer Flag to decide whether a fast renderer is used - */ - public LinePlot(String title, LinePlotData data, boolean notification){ - this.title = title; - this.data = data; - this.notification = notification; - - - this.markers = new ArrayList(); - - setUpPlotPanel(); - } - - /** - * Change visible part of chart - * @param translationVector - */ - private void moverOverPlot(XYPoint translationVector) { - double translatedDomainIntervalMin = chartPanel.getChart().getXYPlot().getDomainAxis().getRange().getLowerBound() + translationVector.getX(); - double translatedDomainIntervalMax = chartPanel.getChart().getXYPlot().getDomainAxis().getRange().getUpperBound() + translationVector.getX(); - double translatedRangeIntervalMin = chartPanel.getChart().getXYPlot().getRangeAxis().getRange().getLowerBound() + translationVector.getY(); - double translatedRangeIntervalMax = chartPanel.getChart().getXYPlot().getRangeAxis().getRange().getUpperBound() + translationVector.getY(); - - Range domainAxisRange = new Range(translatedDomainIntervalMin, translatedDomainIntervalMax); - Range rangeAxisRange = new Range(translatedRangeIntervalMin, translatedRangeIntervalMax); - //We set notify to false in the first call.. - chartPanel.getChart().getXYPlot().getDomainAxis().setRange(domainAxisRange, true, false); - //...and true in the last - chartPanel.getChart().getXYPlot().getRangeAxis().setRange(rangeAxisRange, true, true); - - } - - /** - * Add key bindings to chart panel - */ - private void addKeyBindings(){ - final String moveUpKey = "move up"; - final String moveDownKey = "move down"; - final String moveRightKey = "move right"; - final String moveLeftKey = "move left"; - - // Up arrow - chartPanel.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), moveUpKey); - chartPanel.getActionMap().put(moveUpKey, new AbstractAction() { - @Override - public void actionPerformed(ActionEvent e) { - XYPoint translationVector = new XYPoint(0.0, ((NumberAxis)chartPanel.getChart().getXYPlot().getRangeAxis()).getTickUnit().getSize()); - moverOverPlot(translationVector); - } - }); - - // Down arrow - chartPanel.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0),moveDownKey); - chartPanel.getActionMap().put(moveDownKey, new AbstractAction() { - @Override - public void actionPerformed(ActionEvent e) { - XYPoint translationVector = new XYPoint(0.0, - ((NumberAxis)chartPanel.getChart().getXYPlot().getRangeAxis()).getTickUnit().getSize()); - moverOverPlot(translationVector); - } - }); - - // Right arrow - chartPanel.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0),moveRightKey); - chartPanel.getActionMap().put(moveRightKey, new AbstractAction() { - @Override - public void actionPerformed(ActionEvent e) { - XYPoint translationVector = new XYPoint(((NumberAxis)chartPanel.getChart().getXYPlot().getDomainAxis()).getTickUnit().getSize(), 0.0); - moverOverPlot(translationVector); - } - }); - - // Left arrow - chartPanel.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0),moveLeftKey); - chartPanel.getActionMap().put(moveLeftKey, new AbstractAction() { - @Override - public void actionPerformed(ActionEvent e) { - XYPoint translationVector = new XYPoint(- ((NumberAxis)chartPanel.getChart().getXYPlot().getDomainAxis()).getTickUnit().getSize(), 0.0); - moverOverPlot(translationVector); - } - }); - } - - - @Override - public JPanel getPlotPanel(){ - chartPanel.setName(title); - return this.chartPanel; - } - - public BufferedImage getImage(){ - return(chartPanel.getChart().createBufferedImage(chartPanelWidth, chartPanelHeight, null)); - } - - - public void plotByRenderingToScreen(boolean terminateOnExit, Integer x, Integer y, Integer width, Integer height){ - JFrame frame = new JFrame(title); - // Add panel to frame - frame.setContentPane(getPlotPanel()); - - frame.pack(); - if(terminateOnExit){ - frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); // Close application if frame is closed - } - - // Set frame size and position - if(height != null && width != null){ - frame.setSize(width, height); - } - - if(x != null && y != null){ - frame.setLocation(x, y); - } - - else{ - // Center the frame - RefineryUtilities.centerFrameOnScreen(frame); - } - frame.setVisible(true); - - } - - - - @Override - public void plot(){ - plot(true); - } - - - @Override - public void plot(boolean terminateOnExit){ - plotByRenderingToScreen(terminateOnExit, null, null, null, null); - } - - @Override - public void plot(boolean terminateOnExit, int x, int y){ - plotByRenderingToScreen(terminateOnExit, new Integer(x), new Integer(y), null, null); - } - - @Override - public void plot(boolean terminateOnExit, int x, int y, int width, int height){ - plotByRenderingToScreen(terminateOnExit, new Integer(x), new Integer(y), new Integer(width), new Integer(height)); - } - - @Override - public void addEventActionListener(EventActionListener listener){ - eventActionListener.add(listener); - } - - @Override - public void removeEventActionListener(EventActionListener listener){ - eventActionListener.remove(listener); - } - - /** - * Setup plot - */ - public void setUpPlotPanel() { - // Create chart - JFreeChart chart = createChart(data.getData(), data.getMetadata().getxAxisLabel(), data.getMetadata().getyAxisLabel()); - - chartPanel = new ChartPanel(chart); - - if(tooltipVisible){ - showTooltips(); - } - else{ - hideTooltips(); - } - - - // Adapt chart panel - chartPanel.addChartMouseListener(this); - chartPanel.addMouseListener(this); - chartPanel.addMouseMotionListener(this); - - chartPanel.getChart().setBorderVisible(false); - chartPanel.getChart().setNotify(notification); - - chartPanel.setPreferredSize(new java.awt.Dimension(chartPanelWidth, chartPanelHeight)); - - - // Add more items to the context menu - amendContextMenu(); - amendPlugableContextMenu(); - //Activate (arrow) keys - addKeyBindings(); - - } - - - /** - * Show Legend of chart - * @param enable - */ - public void showLegend(boolean enable){ - chartPanel.getChart().getLegend().setVisible(enable); - } - - /** - * Add additional items to the context menu of the frame - */ - public void amendContextMenu(){ - - JMenuItem pauseMenuItem = new JMenuItem(pauseMenuLabel); - pauseMenuItem.addActionListener(this); - chartPanel.getPopupMenu().add(pauseMenuItem); - - JMenuItem resetPlotMenuItem = new JMenuItem(resetPlotMenuLabel); - resetPlotMenuItem.addActionListener(this); - chartPanel.getPopupMenu().add(resetPlotMenuItem); - - - hideGraphMenu = new JMenu(hideGraphPlotMenuLabel); - hideGraphMenu.addActionListener(this); - chartPanel.getPopupMenu().add(hideGraphMenu); - - JMenuItem clearAnnotationsMenuItem = new JMenuItem(clearAnnotationsMenuLabel); - clearAnnotationsMenuItem.addActionListener(this); - chartPanel.getPopupMenu().add(clearAnnotationsMenuItem); - - - JMenuItem dataPointsMarkersMenuItem = new JMenuItem(dataPointsMarkersMenuLabel); - dataPointsMarkersMenuItem.addActionListener(this); - chartPanel.getPopupMenu().add(dataPointsMarkersMenuItem); - - JMenuItem splitPlotMenuItem = new JMenuItem(splitPlotMenuLabel); - splitPlotMenuItem.addActionListener(this); - chartPanel.getPopupMenu().add(splitPlotMenuItem); - - JMenuItem detachPlotMenuItem = new JMenuItem(detachPlotMenuLabel); - detachPlotMenuItem.addActionListener(this); - chartPanel.getPopupMenu().add(detachPlotMenuItem); - - hideLegendMenuItem = new JMenuItem(hideLegendMenuLabel); - hideLegendMenuItem.addActionListener(this); - chartPanel.getPopupMenu().add(hideLegendMenuItem); - - JMenuItem hideToolTipsMenuItem = new JMenuItem(hideTooltipsMenuLabel); - if(!tooltipVisible){ - hideToolTipsMenuItem.setText(showTooltipsMenuLabel); - } - hideToolTipsMenuItem.addActionListener(this); - chartPanel.getPopupMenu().add(hideToolTipsMenuItem); - - JMenuItem enableGraphChooserMenuItem = new JMenuItem(disableGraphChooserMenuLabel); - if(!enableGraphChooser){ - enableGraphChooserMenuItem.setText(enableGraphChooserMenuLabel); - } - enableGraphChooserMenuItem.addActionListener(this); - chartPanel.getPopupMenu().add(enableGraphChooserMenuItem); - - - for (Object xySeries : data.getData().getSeries()) { - JMenuItem graphMenuItem = new JMenuItem((String)((XYSeries) xySeries).getKey()); - graphMenuItem.addActionListener(this); - hideGraphMenu.add(graphMenuItem); - } - - chartPanel.getPopupMenu().addSeparator(); - //FFT Menu Items - - - - } - - /** - * amend additional menu entries to the default context menu - */ - public void amendPlugableContextMenu(){ - //Add analysis menu items (created according xml) - MenuLoader menuLoader = new MenuLoader(PlotType.oneDim, "menuconfigxy.xml","ch.psi.plot.xy.plugable.", this); - menuLoader.initUtils(chartPanel.getPopupMenu()); - //load the predifined menu entries - plugableUtils = menuLoader.getPlugableUtils(); - //load the user defined plugins - loadServices(); - } - - - /** - * load services if there are and add them to the plugableUtils List - */ - private void loadServices() { - ServiceLoader plugableUtilXYServices = ServiceLoader.load(PlugableUtilXY.class); - for ( PlugableUtilXY plugableUtilXYService : plugableUtilXYServices){ - plugableUtils.add(plugableUtilXYService); - JMenuItem serviceLoadedMenuItem = new JMenuItem(plugableUtilXYService.getLabel()); - serviceLoadedMenuItem.addActionListener(this); - chartPanel.getPopupMenu().add(serviceLoadedMenuItem); - } - } - - /** - * Creates a JFreeChart. - * @param dataset the data for the chart. - * @return a chart. - */ - private JFreeChart createChart(XYDataset dataset, String xLabel, String yLabel) { - - // Create chart - JFreeChart chart = ChartFactory.createXYLineChart(this.title, xLabel, yLabel, dataset, PlotOrientation.VERTICAL, true, false, false); - - // Customize chart look and feel - chart.setBackgroundPaint(new Color(238,238,238)); - chart.getLegend().setBackgroundPaint(new Color(238,238,238)); - chart.getLegend().setBorder(0, 0, 0, 0); - - // Customize plot area look and feel - XYPlot plot = (XYPlot) chart.getPlot(); - plot.setBackgroundPaint(Color.white); - plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0)); - plot.setDomainGridlinePaint(Color.gray); - plot.setRangeGridlinePaint(Color.gray); - - // Show data point - ((XYLineAndShapeRenderer)plot.getRenderer()).setBaseShapesVisible(true); - - - ((NumberAxis) plot.getRangeAxis()).setAutoRangeIncludesZero(false); - - return chart; - } - - /** - * Show tooltips - */ - public void showTooltips(){ - DecimalFormat dm = new DecimalFormat("0.##########"); - XYToolTipGenerator xYToolTipGenerator = new StandardXYToolTipGenerator( "{1}/{2}", dm, dm); - chartPanel.getChart().getXYPlot().getRenderer().setBaseToolTipGenerator(xYToolTipGenerator); - chartPanel.setDisplayToolTips(true); - chartPanel.getChartRenderingInfo().setEntityCollection(new StandardEntityCollection()); - } - - /** - * Hide tooltips - */ - public void hideTooltips(){ - chartPanel.getChartRenderingInfo().setEntityCollection(null); // TODO verify (http://www.jfree.org/phpBB2/viewtopic.php?t=12788&highlight=redraw+speed+performance+problem) - chartPanel.getChart().getXYPlot().getRenderer().setBaseToolTipGenerator(null); - } - - /** - * Receives chart mouse click events. - * @param event the event. - */ - @Override - public void chartMouseClicked(ChartMouseEvent event) { - - //calculate x and y value in chart at mouse position - XYPoint chartPoint = new XYPoint(0.0,0.0); - if (!CoordinateTransformer.chartCoordinates(chartPanel, event.getTrigger().getX(),event.getTrigger().getY(), chartPoint)){; - return; - } - double chartX = chartPoint.getX().doubleValue(); - - if ((event.getTrigger().getModifiers() & InputEvent.BUTTON1_MASK) == InputEvent.BUTTON1_MASK ){ - //remove marker if exists - //Lazy evaluation of the 'and' is needed here - if(chartPanel.getChart().getXYPlot().getDomainMarkers(Layer.FOREGROUND) != null && getValueMarker(chartX) != null){ - chartPanel.getChart().getXYPlot().removeDomainMarker(getValueMarker(chartX)); - } - else{ - //Now use data to set marker: - ValueMarker valuemarker = new ValueMarker(chartX); - valuemarker.setPaint(Color.green); - //valuemarker.setLabel("Start"); - //valuemarker.setLabelAnchor(RectangleAnchor.TOP_LEFT); - //valuemarker.setLabelTextAnchor(TextAnchor.TOP_RIGHT); - chartPanel.getChart().getXYPlot().addDomainMarker(valuemarker); - } - } - else if ((event.getTrigger().getModifiers() & InputEvent.BUTTON2_MASK) == InputEvent.BUTTON2_MASK ){ - //Lazy evaluation of the 'and' is needed here - if(chartPanel.getChart().getXYPlot().getDomainMarkers(Layer.BACKGROUND) != null && isClickInSelectedInterval(chartX) != null){ - //It could be that valuemarker are allready removed, but there is no danger here - chartPanel.getChart().getXYPlot().removeDomainMarker(getValueMarker(isClickInSelectedInterval(chartX).getStartValue()),Layer.FOREGROUND); - chartPanel.getChart().getXYPlot().removeDomainMarker(getValueMarker(isClickInSelectedInterval(chartX).getEndValue()),Layer.FOREGROUND); - chartPanel.getChart().getXYPlot().removeDomainMarker(isClickInSelectedInterval(chartX),Layer.BACKGROUND); - } - // else if condition is for security (should not happen that someone clicks to mark interval before interval exists, but can happen. - else if(chartPanel.getChart().getXYPlot().getDomainMarkers(Layer.FOREGROUND) != null){ - Double leftIntervalBorder = calculateInfimum(chartPanel.getChart().getXYPlot().getDomainAxis().getLowerBound(),chartX); - Double rightIntervalBorder = calculateSupremum(chartPanel.getChart().getXYPlot().getDomainAxis().getUpperBound(),chartX); - IntervalMarker intervalmarker = new IntervalMarker(leftIntervalBorder,rightIntervalBorder); - // getBackground(); // TODO commenting out of this need to be verified - intervalmarker.setPaint(Color.LIGHT_GRAY); - chartPanel.getChart().getXYPlot().addDomainMarker(intervalmarker,Layer.BACKGROUND); - - } - } - - } - - /** - * Get the Value marker at the position chartX - * @param chartX - * @return valueMarker - */ - public ValueMarker getValueMarker(Double chartX){ - //Layer.ForeGround returns ValueMarkers make sure that ALL value markers are set foreground - for (Object o: chartPanel.getChart().getXYPlot().getDomainMarkers(Layer.FOREGROUND)){ - ValueMarker valueMarker = (ValueMarker) o; - if (valueMarker.getValue() == chartX){ - return valueMarker; - } - - } - return null; - } - - /** - * get the Interval bounded by start/end - * @param start - * @param end - * @return - */ - public IntervalMarker getIntervalMarker(Double start, Double end){ - - //Layer.BACKGROUND returns IntervalMarkers. make sure that ALL interval markers are set background - for (Object o: chartPanel.getChart().getXYPlot().getDomainMarkers(Layer.BACKGROUND)){ - IntervalMarker intervalMarker = (IntervalMarker) o; - if (intervalMarker.getStartValue() == start && intervalMarker.getEndValue() == end){ - return intervalMarker; - } - } - return null; - } - - /** - * Get interval markers - */ - public List getIntervalMarkers(){ - List intervals = new ArrayList(); - for (Object o: chartPanel.getChart().getXYPlot().getDomainMarkers(Layer.BACKGROUND)){ - IntervalMarker intervalMarker = (IntervalMarker) o; - intervals.add(new Interval(intervalMarker.getStartValue(), intervalMarker.getEndValue())); - } - return(intervals); - } - - - /** - * calculate the infimum of value chartX that is not smaller than leftBound - * @param leftBound - * @param chartX - * @return - */ - public Double calculateInfimum(Double leftBound, Double chartX){ - Set lower = new HashSet(); - lower.add(leftBound); - for (Object o: chartPanel.getChart().getXYPlot().getDomainMarkers(Layer.FOREGROUND)){ - ValueMarker valueMarker = (ValueMarker) o; - if (valueMarker.getValue() < chartX){ - lower.add(valueMarker.getValue()); - } - } - return (Double) Collections.max(lower); - - } - - /** - * calculate the supremum of value chartX that is not bigger than rightBound - * @param leftBound - * @param chartX - * @return - */ - public Double calculateSupremum(Double rightBound, Double chartX){ - Set upper = new HashSet(); - upper.add(rightBound); - for (Object o: chartPanel.getChart().getXYPlot().getDomainMarkers(Layer.FOREGROUND)){ - ValueMarker valueMarker = (ValueMarker) o; - if (valueMarker.getValue() > chartX){ - upper.add(valueMarker.getValue()); - } - } - return (Double) Collections.min(upper); - - } - - /** - * Find the clicked interval - * @param chartX - * @return - */ - public IntervalMarker isClickInSelectedInterval(Double chartX){ - for (Object o: chartPanel.getChart().getXYPlot().getDomainMarkers(Layer.BACKGROUND)){ - IntervalMarker intervalMarker = (IntervalMarker) o; - if (intervalMarker.getStartValue() <= chartX && chartX <= intervalMarker.getEndValue()){ - return intervalMarker; - } - } - return null; - } - - - /** - * Receives events if mouse moved on the chart - * @param event the event. - */ - @Override - public void chartMouseMoved(ChartMouseEvent event) { - //TODO To be implemented or removed - } - - /** - * Event reciever if mouse is clicked - */ - @Override - public void mouseClicked(MouseEvent e) { - - //either: extract tooltip - if (e.getSource().equals(chartPanel)){ - // Parse coordinates out of tooltip - double x,y; - String label; - String ttip = chartPanel.getToolTipText(e); - if (ttip != null){ - String floatingPointRegex = "[-+]?[0-9]*\\.?[0-9]+"; - String regex = "(\\w*):{1}\\s*\\(" + "(" + floatingPointRegex + ")" + ",{1}\\s*" + "(" + floatingPointRegex + ")"; - Pattern pattern = Pattern.compile(regex); - Matcher matcher = pattern.matcher(ttip); - - while (matcher.find()) { - label = matcher.group(1); - x = Double.parseDouble(matcher.group(2).toString()); - y = Double.parseDouble(matcher.group(3).toString()); - logger.fine("Label:"+ label +" x=" + x + "y=" + y); - markers.add(new Marker(label, x, y)); - } - } - } - - //or: open graph properties context menu - boolean clickInChart = CoordinateTransformer.chartCoordinates(chartPanel, e.getX(), e.getY(), new XYPoint(0.0, 0.0)); - if((!clickInChart) && enableGraphChooser){ - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - new GraphChooserFrame(data, chartPanel.getChart().getXYPlot()).setVisible(true); - } - }); - } - - } - - /** - * Event receiver if mouse entered chart - */ - @Override - public void mouseEntered(MouseEvent e) { - //TODO To be implemented or removed - } - - /** - * Event receiver if mouse exited chart - */ - @Override - public void mouseExited(MouseEvent e) { - //TODO To be implemented or removed - } - - /** - * Event receiver mouse pressed - */ - @Override - public void mousePressed(MouseEvent e) { - dragging = false; - } - - /** - * Event receiver mouse released - */ - @Override - //Change scale via drag and drop - public void mouseReleased(MouseEvent e) { - if(dragging == true && rescaleAxis == true){ - if(this.difference.getX() > 0.0){ - chartPanel.getChart().getXYPlot().getDomainAxis().setUpperBound( - chartPanel.getChart().getXYPlot().getDomainAxis().getUpperBound() + difference.getX()); - } - else{ - chartPanel.getChart().getXYPlot().getDomainAxis().setLowerBound( - chartPanel.getChart().getXYPlot().getDomainAxis().getLowerBound() - difference.getX()); - - } - - if(this.difference.getY() > 0.0){ - chartPanel.getChart().getXYPlot().getRangeAxis().setUpperBound( - chartPanel.getChart().getXYPlot().getRangeAxis().getUpperBound() + difference.getY()); - } - else{ - chartPanel.getChart().getXYPlot().getRangeAxis().setLowerBound( - chartPanel.getChart().getXYPlot().getRangeAxis().getLowerBound() - difference.getY()); - - } - } - dragging = false; - - } - - /** - * Event receiver mouse dragged - */ - @Override - public void mouseDragged(MouseEvent e) { - XYPoint startPoint = new XYPoint(0.0,0.0); - XYPoint endPoint = new XYPoint(0.0,0.0); - - if (dragging == false){ - //startPoint of dragging must lie outside plot coordinate system to rescale Axis. - rescaleAxis = !CoordinateTransformer.chartCoordinates(chartPanel, e.getX(), e.getY(),startPoint); - dragging = true; - } - CoordinateTransformer.chartCoordinates(chartPanel, e.getX(), e.getY(), endPoint); - difference.setX(endPoint.getX() - startPoint.getX()); - difference.setY(endPoint.getY() - startPoint.getY()); - - } - - public void showMins(){ - for (XYPoint min : Extrema.findExtrema(data, true)){ - XYAnnotation cross = new XYDrawableAnnotation(min.getX(), min.getY(), 10.0, 10.0, new CrossAnnotation(Color.BLACK)); - chartPanel.getChart().getXYPlot().addAnnotation(cross); - } - } - public void showMaxs(){ - for (XYPoint max : Extrema.findExtrema(data, false)){ - XYAnnotation cross = new XYDrawableAnnotation(max.getX(), max.getY(), 10.0, 10.0, new CrossAnnotation(Color.BLACK)); - chartPanel.getChart().getXYPlot().addAnnotation(cross); - } - } - - /** - * Event receiver mouse moved - */ - @Override - public void mouseMoved(MouseEvent e) { - //TODO To be implemented or removed - } - - - /** - * Event receiver action performed - */ - @Override - public void actionPerformed(ActionEvent e) { - JMenuItem source = (JMenuItem)(e.getSource()); - JMenu parent = null; - try { - parent = (JMenu)((JPopupMenu) source.getParent()).getInvoker(); - } catch (ClassCastException c) { - } - - - logger.finest( source.getText()); - for (PlugableUtil plugableUtil : plugableUtils) { - if(source.getText().equals(plugableUtil.getLabel())){ - try{ - ((PlugableUtilXY)plugableUtil).execute(this); - } - catch (ClassCastException pe) { - logger.log(Level.SEVERE, "Unable to execute plugin " + ((PlugableUtilXY)plugableUtil).getLabel(), pe); - } catch (PluginExecutionException pe) { - logger.log(Level.SEVERE, "Unable to execute plugin " + ((PlugableUtilXY)plugableUtil).getLabel(), pe); - } - return; - } - } - - // TODO Need to reimplement this functions - // no update() function needed as plot changes automatically if data changes - if(source.getText() == pauseMenuLabel){ - for(EventActionListener listener: eventActionListener){ - listener.performAction(EventActionListener.Actions.PAUSE); - } - source.setText(continueMenuLabel); - } - else if(source.getText() == continueMenuLabel){ - for(EventActionListener listener: eventActionListener){ - listener.performAction(EventActionListener.Actions.CONTINUE); - } - source.setText(pauseMenuLabel); - } - - else if(source.getText() == dataPointsMarkersMenuLabel){ - boolean shapesFilled = ((XYLineAndShapeRenderer)chartPanel.getChart().getXYPlot().getRenderer()).getBaseShapesVisible(); - ((XYLineAndShapeRenderer)chartPanel.getChart().getXYPlot().getRenderer()).setBaseShapesVisible(!shapesFilled); - - } - - else if(source.getText() == clearAnnotationsMenuLabel){ - chartPanel.getChart().getXYPlot().clearRangeMarkers(); - chartPanel.getChart().getXYPlot().clearDomainMarkers(); - chartPanel.getChart().getXYPlot().clearAnnotations(); - } - - else if(source.getText() == showLegendMenuLabel){ - showLegend(true); - source.setText(hideLegendMenuLabel); - } - - else if(source.getText() == hideLegendMenuLabel){ - showLegend(false); - source.setText(showLegendMenuLabel); - } - - else if(source.getText() == showTooltipsMenuLabel){ - showTooltips(); - source.setText(hideTooltipsMenuLabel); - setTooltipVisible(true); - } - - else if(source.getText() == hideTooltipsMenuLabel){ - hideTooltips(); - source.setText(showTooltipsMenuLabel); - setTooltipVisible(false); - } - - // - else if(source.getText() == enableGraphChooserMenuLabel){ - enableGraphChooser=true; - source.setText(disableGraphChooserMenuLabel); - } - - else if(source.getText() == disableGraphChooserMenuLabel){ - enableGraphChooser=false; - source.setText(enableGraphChooserMenuLabel); - } - // - else if(source.getText() == resetPlotMenuLabel){ - // TODO to be defined - // dataListenerAndConverter.resetPlot(); - } - - else if(source.getText() == splitPlotMenuLabel){ - for (Object xySeries : ((XYSeriesCollection) data.getData()).getSeries()) { - LinePlotData d = new LinePlotData(); - ((XYSeriesCollection) d.getData()).addSeries(((XYSeries) xySeries)); - int index = data.getData().indexOf((XYSeries) xySeries); - //The right colors are not automatically assigned - Paint paint = chartPanel.getChart().getXYPlot().getRenderer().getSeriesPaint(index); - LinePlot p = new LinePlot((String) ((XYSeries) xySeries).getKey(), d); - // there is only one series in this plot, so we choose index 0 to assign paint - p.getChartPanel().getChart().getXYPlot().getRenderer().setSeriesPaint(0, paint); - p.plot(false); - } - - } - - else if(source.getText() == detachPlotMenuLabel){ - LinePlotData d = data; - LinePlot p = new LinePlot(this.title, d); - p.plot(false); - } - - - //the following cast may throw a ClasscastException - else if (parent != null){ - if(parent.getText().equals(hideGraphPlotMenuLabel ) ){ - int index = -1; - for (Object xySeries : ((XYSeriesCollection) data.getData()).getSeries()) { - if( ((XYSeries) xySeries).getKey() == source.getText()){ - index = data.getData().indexOf((XYSeries) xySeries); - } - } - boolean visible = chartPanel.getChart().getXYPlot().getRenderer().isSeriesVisible(index); - chartPanel.getChart().getXYPlot().getRenderer().setSeriesVisible(index, !visible); - //logger.fine(chartPanel.getChart().getLegend(index).getFrame().getInsets().getLeft()); - } - } - - else{ - logger.severe("Unknown source " + source.getName()); - } - } - - - - - @Override - public void update() { - - // Update menu structure ... - logger.fine("Update triggered in LinePlot ["+title+"]"); - hideGraphMenu.removeAll(); - for (Object xySeries : data.getData().getSeries()) { - JMenuItem graphMenuItem = new JMenuItem((String)((XYSeries) xySeries).getKey()); - graphMenuItem.addActionListener(this); - hideGraphMenu.add(graphMenuItem); - } - - // If there are more than 10 xySeries, hide legend - // Only check == 10 because if legend is manually set to true afterwards that this does - // not get overwritten each time this function is called - if(data.getData().getSeries().size()==10){ - showLegend(false); - hideLegendMenuItem.setText(showLegendMenuLabel); - } - - chartPanel.getChart().setNotify(!notification); - chartPanel.getChart().setNotify(notification); - - } - - //getter and setter - public LinePlotData getData() { - return data; - } - - public void setData(LinePlotData data) { - this.data = data; - } - - public ChartPanel getChartPanel() { - return chartPanel; - } - - public void setChartPanel(ChartPanel chartPanel) { - this.chartPanel = chartPanel; - } - - public List getMarkers(){ - return(markers); - } - - public boolean isTooltipVisible() { - return tooltipVisible; - } - - private void setTooltipVisible(boolean tooltipVisible) { - this.tooltipVisible = tooltipVisible; - } - - public XYSeries newSeries(String key){ - XYSeries s = new XYSeries(key); - getData().getData().addSeries(s); - return(s); - } - -} - diff --git a/ch.psi.plot/tmp/done/LinePlotData.java b/ch.psi.plot/tmp/done/LinePlotData.java deleted file mode 100644 index c5677f2..0000000 --- a/ch.psi.plot/tmp/done/LinePlotData.java +++ /dev/null @@ -1,46 +0,0 @@ -package ch.psi.plot.plot.done; - -import org.jfree.data.xy.XYSeriesCollection; - -import ch.psi.plot.PlotData; - -/** - * Bean holding a line plot data/metadata - */ -public class LinePlotData implements PlotData { - - private XYSeriesCollection data = new XYSeriesCollection(); - private LinePlotMetadata metadata = new LinePlotMetadata(); - - /** - * Get plottable XYDataSet - * @return Data in an XYDataset object - */ - public XYSeriesCollection getData(){ - return(data); - } - - /** - * Set line plot data - * @param data Data in a XYDataset - */ - public void setData(XYSeriesCollection data){ - this.data = data; - } - - /** - * Get data related metadata - * @return - */ - public LinePlotMetadata getMetadata(){ - return(metadata); - } - - /** - * Set line plot metadata - * @param metadata - */ - public void setMetadata(LinePlotMetadata metadata){ - this.metadata = metadata; - } -} diff --git a/ch.psi.plot/tmp/done/LinePlotMetadata.java b/ch.psi.plot/tmp/done/LinePlotMetadata.java deleted file mode 100644 index a40636e..0000000 --- a/ch.psi.plot/tmp/done/LinePlotMetadata.java +++ /dev/null @@ -1,48 +0,0 @@ -package ch.psi.plot.plot.done; - -/** - * Class holding metadata of a line plot - */ -public class LinePlotMetadata { - - /** - * X Axis label - */ - private String xAxisLabel = "X"; - - /** - * Y Axis label - */ - private String yAxisLabel = "Y"; - - // Getter and setter functions - - /** - * @return the xAxisLabel - */ - public String getxAxisLabel() { - return xAxisLabel; - } - - /** - * @param xAxisLabel the xAxisLabel to set - */ - public void setxAxisLabel(String xAxisLabel) { - this.xAxisLabel = xAxisLabel; - } - - /** - * @return the yAxisLabel - */ - public String getyAxisLabel() { - return yAxisLabel; - } - - /** - * @param yAxisLabel the yAxisLabel to set - */ - public void setyAxisLabel(String yAxisLabel) { - this.yAxisLabel = yAxisLabel; - } - -} diff --git a/ch.psi.plot/tmp/done/Maxs.java b/ch.psi.plot/tmp/done/Maxs.java deleted file mode 100644 index 5bc7c7f..0000000 --- a/ch.psi.plot/tmp/done/Maxs.java +++ /dev/null @@ -1,28 +0,0 @@ -package ch.psi.plot.plot.done; - -import java.awt.Color; - -import org.jfree.chart.annotations.XYAnnotation; -import org.jfree.chart.annotations.XYDrawableAnnotation; - -import ch.psi.plot.util.XYPoint; -import ch.psi.plot.xy.LinePlot; -import ch.psi.plot.xyz.CrossDrawer; - -public class Maxs implements PlugableUtilXY{ - - @Override - public void execute(LinePlot lineplot) { - for (XYPoint max : Extrema.findExtrema(lineplot.getData(), false)){ - CrossDrawer cd = new CrossDrawer(Color.BLACK); - XYAnnotation cross = new XYDrawableAnnotation(max.getX(), max.getY(), 10.0, 10.0, cd); - lineplot.getChartPanel().getChart().getXYPlot().addAnnotation(cross); - } - } - - @Override - public String getLabel() { - return this.getClass().getSimpleName(); - } - -} diff --git a/ch.psi.plot/tmp/done/MenuLoader.java b/ch.psi.plot/tmp/done/MenuLoader.java deleted file mode 100644 index 1873eed..0000000 --- a/ch.psi.plot/tmp/done/MenuLoader.java +++ /dev/null @@ -1,148 +0,0 @@ -package ch.psi.plot.plot.done; - -import java.awt.event.ActionListener; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.swing.JComponent; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBElement; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Unmarshaller; - -import ch.psi.plot.menuconfig.MenuNodeType; -import ch.psi.plot.menuconfig.MenuTreeType; -import ch.psi.plot.util.PlugableUtil.PlotType; -import ch.psi.plot.xy.plugable.PlugableUtilXY; -import ch.psi.plot.xyz.plugable.PlugableUtilXYZ; - -/** - * Class which generates a menu according to an xml file - * - */ -public class MenuLoader { - - private static Logger logger = Logger.getLogger(MenuLoader.class.getName()); - - private PlotType plotType; - private String xmlFileName; - private String utilityClassPackageName; - private ActionListener listener; - private List plugableUtils = new ArrayList(); - - /** - * Constructor - * @param plotType - * @param xmlFileName - * @param utilityClassPackageName - * @param listener - */ - public MenuLoader(PlotType plotType, String xmlFileName, - String utilityClassPackageName, ActionListener listener) { - this.plotType = plotType; - this.xmlFileName = xmlFileName; - this.utilityClassPackageName = utilityClassPackageName; - this.listener = listener; - } - - /** - * Adds menu entries and submenus to the basis menu according to the xmlFileName - * @param basisMenu - */ - public void initUtils(JComponent basisMenu){ - - JAXBContext jc; - Unmarshaller um; - JAXBElement rootMenuElement = null; - - try { - jc = JAXBContext.newInstance("ch.psi.plot.menuconfig"); - um = jc.createUnmarshaller(); - InputStream xmlResource = this.getClass().getResourceAsStream(xmlFileName); - if(xmlResource == null){ - logger.log(Level.WARNING, "Resource '" + xmlFileName + "' is null "); - return; - } - - rootMenuElement = (JAXBElement) um.unmarshal(xmlResource); - - } catch (JAXBException e) { - e.printStackTrace(); - } - - MenuTreeType rootMenu = (MenuTreeType)rootMenuElement.getValue(); - - List rootMenuEntries = rootMenu.getMenuNode(); - //We start with the rootMenu entries for parsing, they are added to the popupmenu - addMenuItem(basisMenu, rootMenuEntries); - } - - /** - * Adds (recursively) menuEntries to menu. (an element of menuEntries is either a - * item (command) or a submenu). - * @param menu - * @param menuEntries - */ - private void addMenuItem(JComponent menu, List menuEntries){ - - //Check for all menu entries if they are a feature or a submenu - for (MenuNodeType menuNodeEntry : menuEntries) { - if(menuNodeEntry.getUtilityClass() != null){ - Class pluginClass = null; - try {//Load class according to its name - pluginClass = Class.forName( utilityClassPackageName + menuNodeEntry.getUtilityClass().getName()); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - continue; - } - try {//add loaded class to List of plugable Utils (properly casted) - switch (plotType) { - case oneDim: - plugableUtils.add((PlugableUtilXY) pluginClass.newInstance()); - break; - case twoDim: - plugableUtils.add((PlugableUtilXYZ) pluginClass.newInstance()); - break; - default: - break; - } - } catch (InstantiationException e) { - e.printStackTrace(); - continue; - } catch (IllegalAccessException e) { - e.printStackTrace(); - continue; - } - - int indexTop = plugableUtils.size() - 1; - JMenuItem menuItem = new JMenuItem(plugableUtils.get(indexTop).getLabel()); - menuItem.addActionListener(listener); - menu.add(menuItem); - } - else{//If it is not a menu entry, it must be a submenu - //so we call the function recursively - //First we create the new Menu.. - JMenu submenu = new JMenu(menuNodeEntry.getName()); - menu.add(submenu); - //..then we call the function again with the newly created menu and the submenulist - addMenuItem(submenu, menuNodeEntry.getSubmenu()); - } - } - } - - //getter and setter - public List getPlugableUtils() { - return plugableUtils; - } - - public void setPlugableUtils(List plugableUtils) { - this.plugableUtils = plugableUtils; - } - - -} diff --git a/ch.psi.plot/tmp/done/MenuNodeType.java b/ch.psi.plot/tmp/done/MenuNodeType.java deleted file mode 100644 index e4c68a7..0000000 --- a/ch.psi.plot/tmp/done/MenuNodeType.java +++ /dev/null @@ -1,131 +0,0 @@ -// -// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6 -// See http://java.sun.com/xml/jaxb -// Any modifications to this file will be lost upon recompilation of the source schema. -// Generated on: 2009.12.07 at 03:37:39 PM CET -// - - -package ch.psi.plot.plot.done; - -import java.util.ArrayList; -import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for menuNodeType complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="menuNodeType">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <choice>
- *         <sequence>
- *           <element name="submenu" type="{}menuNodeType" maxOccurs="unbounded" minOccurs="0"/>
- *         </sequence>
- *         <element name="utilityClass" type="{}utilityClassType"/>
- *       </choice>
- *       <attribute name="name" type="{http://www.w3.org/2001/XMLSchema}string" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "menuNodeType", propOrder = { - "submenu", - "utilityClass" -}) -public class MenuNodeType { - - protected List submenu; - protected UtilityClassType utilityClass; - @XmlAttribute - protected String name; - - /** - * Gets the value of the submenu property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the submenu property. - * - *

- * For example, to add a new item, do as follows: - *

-     *    getSubmenu().add(newItem);
-     * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link MenuNodeType } - * - * - */ - public List getSubmenu() { - if (submenu == null) { - submenu = new ArrayList(); - } - return this.submenu; - } - - /** - * Gets the value of the utilityClass property. - * - * @return - * possible object is - * {@link UtilityClassType } - * - */ - public UtilityClassType getUtilityClass() { - return utilityClass; - } - - /** - * Sets the value of the utilityClass property. - * - * @param value - * allowed object is - * {@link UtilityClassType } - * - */ - public void setUtilityClass(UtilityClassType value) { - this.utilityClass = value; - } - - /** - * Gets the value of the name property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getName() { - return name; - } - - /** - * Sets the value of the name property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setName(String value) { - this.name = value; - } - -} diff --git a/ch.psi.plot/tmp/done/MenuTreeType.java b/ch.psi.plot/tmp/done/MenuTreeType.java deleted file mode 100644 index d81bcd5..0000000 --- a/ch.psi.plot/tmp/done/MenuTreeType.java +++ /dev/null @@ -1,74 +0,0 @@ -// -// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6 -// See http://java.sun.com/xml/jaxb -// Any modifications to this file will be lost upon recompilation of the source schema. -// Generated on: 2009.12.07 at 03:37:39 PM CET -// - - -package ch.psi.plot.plot.done; - -import java.util.ArrayList; -import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for menuTreeType complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="menuTreeType">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="menuNode" type="{}menuNodeType" maxOccurs="unbounded" minOccurs="0"/>
- *       </sequence>
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "menuTreeType", propOrder = { - "menuNode" -}) -public class MenuTreeType { - - protected List menuNode; - - /** - * Gets the value of the menuNode property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the menuNode property. - * - *

- * For example, to add a new item, do as follows: - *

-     *    getMenuNode().add(newItem);
-     * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link MenuNodeType } - * - * - */ - public List getMenuNode() { - if (menuNode == null) { - menuNode = new ArrayList(); - } - return this.menuNode; - } - -} diff --git a/ch.psi.plot/tmp/done/Mins.java b/ch.psi.plot/tmp/done/Mins.java deleted file mode 100644 index 3c15fa7..0000000 --- a/ch.psi.plot/tmp/done/Mins.java +++ /dev/null @@ -1,28 +0,0 @@ -package ch.psi.plot.plot.done; - -import java.awt.Color; - -import org.jfree.chart.annotations.XYAnnotation; -import org.jfree.chart.annotations.XYDrawableAnnotation; - -import ch.psi.plot.util.XYPoint; -import ch.psi.plot.xy.LinePlot; -import ch.psi.plot.xyz.CrossDrawer; - -public class Mins implements PlugableUtilXY{ - - @Override - public void execute(LinePlot lineplot) { - for (XYPoint min : Extrema.findExtrema(lineplot.getData(), true)){ - CrossDrawer cd = new CrossDrawer(Color.BLACK); - XYAnnotation cross = new XYDrawableAnnotation(min.getX(), min.getY(), 10.0, 10.0, cd); - lineplot.getChartPanel().getChart().getXYPlot().addAnnotation(cross); - } - } - - @Override - public String getLabel() { - return this.getClass().getSimpleName(); - } - -} diff --git a/ch.psi.plot/tmp/done/ObjectFactory.java b/ch.psi.plot/tmp/done/ObjectFactory.java deleted file mode 100644 index 98d6e20..0000000 --- a/ch.psi.plot/tmp/done/ObjectFactory.java +++ /dev/null @@ -1,96 +0,0 @@ -// -// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6 -// See http://java.sun.com/xml/jaxb -// Any modifications to this file will be lost upon recompilation of the source schema. -// Generated on: 2009.12.07 at 03:37:39 PM CET -// - - -package ch.psi.plot.plot.done; - -import javax.xml.bind.JAXBElement; -import javax.xml.bind.annotation.XmlElementDecl; -import javax.xml.bind.annotation.XmlRegistry; -import javax.xml.namespace.QName; - - -/** - * This object contains factory methods for each - * Java content interface and Java element interface - * generated in the ch.psi.sls.xasec.plot.menuconfig package. - *

An ObjectFactory allows you to programatically - * construct new instances of the Java representation - * for XML content. The Java representation of XML - * content can consist of schema derived interfaces - * and classes representing the binding of schema - * type definitions, element declarations and model - * groups. Factory methods for each of these are - * provided in this class. - * - */ -@XmlRegistry -public class ObjectFactory { - - private final static QName _MenuNode_QNAME = new QName("", "menuNode"); - private final static QName _UtilityClass_QNAME = new QName("", "utilityClass"); - private final static QName _MenuTree_QNAME = new QName("", "menuTree"); - - /** - * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: ch.psi.sls.xasec.plot.menuconfig - * - */ - public ObjectFactory() { - } - - /** - * Create an instance of {@link MenuNodeType } - * - */ - public MenuNodeType createMenuNodeType() { - return new MenuNodeType(); - } - - /** - * Create an instance of {@link MenuTreeType } - * - */ - public MenuTreeType createMenuTreeType() { - return new MenuTreeType(); - } - - /** - * Create an instance of {@link UtilityClassType } - * - */ - public UtilityClassType createUtilityClassType() { - return new UtilityClassType(); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link MenuNodeType }{@code >}} - * - */ - @XmlElementDecl(namespace = "", name = "menuNode") - public JAXBElement createMenuNode(MenuNodeType value) { - return new JAXBElement(_MenuNode_QNAME, MenuNodeType.class, null, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link UtilityClassType }{@code >}} - * - */ - @XmlElementDecl(namespace = "", name = "utilityClass") - public JAXBElement createUtilityClass(UtilityClassType value) { - return new JAXBElement(_UtilityClass_QNAME, UtilityClassType.class, null, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link MenuTreeType }{@code >}} - * - */ - @XmlElementDecl(namespace = "", name = "menuTree") - public JAXBElement createMenuTree(MenuTreeType value) { - return new JAXBElement(_MenuTree_QNAME, MenuTreeType.class, null, value); - } - -} diff --git a/ch.psi.plot/tmp/done/PlugableUtil.java b/ch.psi.plot/tmp/done/PlugableUtil.java deleted file mode 100644 index 171e863..0000000 --- a/ch.psi.plot/tmp/done/PlugableUtil.java +++ /dev/null @@ -1,6 +0,0 @@ -package ch.psi.plot.plot.done; - -public interface PlugableUtil { - public enum PlotType {oneDim, twoDim}; - public String getLabel(); -} diff --git a/ch.psi.plot/tmp/done/PlugableUtilXY.java b/ch.psi.plot/tmp/done/PlugableUtilXY.java deleted file mode 100644 index e058c21..0000000 --- a/ch.psi.plot/tmp/done/PlugableUtilXY.java +++ /dev/null @@ -1,8 +0,0 @@ -package ch.psi.plot.plot.done; -import ch.psi.plot.util.PluginExecutionException; -import ch.psi.plot.util.PlugableUtil; -import ch.psi.plot.xy.LinePlot; - -public interface PlugableUtilXY extends PlugableUtil{ - public void execute(LinePlot lineplot) throws PluginExecutionException; -} diff --git a/ch.psi.plot/tmp/done/PluginExecutionException.java b/ch.psi.plot/tmp/done/PluginExecutionException.java deleted file mode 100644 index 866e616..0000000 --- a/ch.psi.plot/tmp/done/PluginExecutionException.java +++ /dev/null @@ -1,16 +0,0 @@ -package ch.psi.plot.plot.done; - -public class PluginExecutionException extends Throwable{ - - public PluginExecutionException() { - } - - public PluginExecutionException(String msg) { - super(msg); - } - /** - * - */ - private static final long serialVersionUID = 1L; - -} diff --git a/ch.psi.plot/tmp/done/UtilityClassType.java b/ch.psi.plot/tmp/done/UtilityClassType.java deleted file mode 100644 index 5375394..0000000 --- a/ch.psi.plot/tmp/done/UtilityClassType.java +++ /dev/null @@ -1,65 +0,0 @@ -// -// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6 -// See http://java.sun.com/xml/jaxb -// Any modifications to this file will be lost upon recompilation of the source schema. -// Generated on: 2009.12.07 at 03:37:39 PM CET -// - - -package ch.psi.plot.plot.done; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for utilityClassType complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="utilityClassType">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <attribute name="name" type="{http://www.w3.org/2001/XMLSchema}string" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "utilityClassType") -public class UtilityClassType { - - @XmlAttribute - protected String name; - - /** - * Gets the value of the name property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getName() { - return name; - } - - /** - * Sets the value of the name property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setName(String value) { - this.name = value; - } - -} diff --git a/ch.psi.plot/tmp/done/XYPoint.java b/ch.psi.plot/tmp/done/XYPoint.java deleted file mode 100644 index 8590e44..0000000 --- a/ch.psi.plot/tmp/done/XYPoint.java +++ /dev/null @@ -1,70 +0,0 @@ -/** - * - * Copyright 2010 Paul Scherrer Institute. All rights reserved. - * - * This code 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. - * - * This code 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 this code. If not, see . - * - */ - -package ch.psi.plot.plot.done; - -/** - * XY Point - * @author ebner - * - */ -public class XYPoint { - - private Double x; - private Double y; - - /** - * Constructor - * @param x - * @param y - */ - public XYPoint(double x, double y) { - this.x = new Double(x); - this.y = new Double(y); - } - - /** - * @return the x - */ - public Double getX() { - return x; - } - - /** - * @param x the x to set - */ - public void setX(Double x) { - this.x = x; - } - - /** - * @return the y - */ - public Double getY() { - return y; - } - - /** - * @param y the y to set - */ - public void setY(Double y) { - this.y = y; - } - -} diff --git a/ch.psi.plot/tmp/done/menuconfig.xsd b/ch.psi.plot/tmp/done/menuconfig.xsd deleted file mode 100644 index f63766a..0000000 --- a/ch.psi.plot/tmp/done/menuconfig.xsd +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ch.psi.plot/tmp/done/menuconfigxy.xml b/ch.psi.plot/tmp/done/menuconfigxy.xml deleted file mode 100644 index 189d02d..0000000 --- a/ch.psi.plot/tmp/done/menuconfigxy.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ch.psi.plot/tmp/done/menuconfigxyz.xml b/ch.psi.plot/tmp/done/menuconfigxyz.xml deleted file mode 100644 index 2ac592c..0000000 --- a/ch.psi.plot/tmp/done/menuconfigxyz.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ch.psi.plot/tmp/util/CoordinateTransformer.java b/ch.psi.plot/tmp/util/CoordinateTransformer.java deleted file mode 100644 index 5c2ebe1..0000000 --- a/ch.psi.plot/tmp/util/CoordinateTransformer.java +++ /dev/null @@ -1,56 +0,0 @@ -package ch.psi.plot.util; - - -import java.awt.Point; -import java.awt.geom.Point2D; -import java.awt.geom.Rectangle2D; - -import org.jfree.chart.ChartRenderingInfo; -import org.jfree.chart.axis.ValueAxis; -import org.jfree.chart.plot.XYPlot; -import org.jfree.chart.ChartPanel; -import org.jfree.ui.RectangleEdge; - -import ch.psi.plot.plot.done.XYPoint; - - -/** - * Helper class transforms window (frame) coordinates to chart coordinates. - * @param mouseX, mouseY position of mouse click - * @param xyPoint (useless so far) - * @return true if mouse click was in Chart, false else (if click was in Legend area, etc.) - */ - - -public class CoordinateTransformer { - - public static boolean chartCoordinates(ChartPanel chartPanel, int mouseX, int mouseY, XYPoint xyPoint) { - //calculate x and y value in chart at mouse position - Point2D p = chartPanel.translateScreenToJava2D(new Point(mouseX, mouseY)); - XYPlot plot = (XYPlot) chartPanel.getChart().getPlot(); - ChartRenderingInfo info = chartPanel.getChartRenderingInfo(); - Rectangle2D dataArea = info.getPlotInfo().getDataArea(); - - ValueAxis domainAxis = plot.getDomainAxis(); - RectangleEdge domainAxisEdge = plot.getDomainAxisEdge(); - ValueAxis rangeAxis = plot.getRangeAxis(); - RectangleEdge rangeAxisEdge = plot.getRangeAxisEdge(); - double chartX = domainAxis.java2DToValue(p.getX(), dataArea, domainAxisEdge); - double chartY = rangeAxis.java2DToValue(p.getY(), dataArea,rangeAxisEdge); - - // TODO need to remove this or make this as an return value - xyPoint.setX(chartX); - xyPoint.setY(chartY); - - //Check if the click occurred in the plot region - if (chartX < domainAxis.getLowerBound() || chartX > domainAxis.getUpperBound() || - chartY < rangeAxis.getLowerBound() || chartY > rangeAxis.getUpperBound()){ - return false; - } - else{ - return true; - } - } - - -} diff --git a/ch.psi.plot/tmp/xy/GraphChooserFrame.java b/ch.psi.plot/tmp/xy/GraphChooserFrame.java deleted file mode 100644 index d45dec4..0000000 --- a/ch.psi.plot/tmp/xy/GraphChooserFrame.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ - -/* - * GraphChoserFrame.java - * - * Created on Mar 16, 2010, 8:42:58 AM - */ - -package ch.psi.plot.plot.xy; - -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import javax.swing.JPanel; - -import org.jfree.chart.plot.XYPlot; -import org.jfree.data.xy.XYSeries; -import org.jfree.data.xy.XYSeriesCollection; - -import ch.psi.plot.plot.done.LinePlotData; - - - -/** - * - * @author studer_a1 - */ -public class GraphChooserFrame extends javax.swing.JFrame { - - /** - * - */ - private static final long serialVersionUID = 1L; - private XYPlot plot; - private LinePlotData data; - - - /** Creates new form GraphChoserFrame */ - public GraphChooserFrame(LinePlotData data, XYPlot plot) { - this.plot = plot; - this.data = data; - //this.renderer = (XYLineAndShapeRenderer) plot.getRenderer(); - initComponents(); - initGraphPanels(); - } - - - /** - * inits the graph panel. For every series a GraphPropertiesPanel is created and added to the Panel - */ - public void initGraphPanels(){ - - GridBagConstraints gbc = new GridBagConstraints(); - gbc.weightx = 1.0; - gbc.fill = GridBagConstraints.HORIZONTAL; - gbc.gridwidth = GridBagConstraints.REMAINDER; - - JPanel graphOptionsContainerPanel = new JPanel(new GridBagLayout()); - graphOptionScrollPane.setViewportView(graphOptionsContainerPanel); - - int seriesNumber = 0; - for (Object xySeriesObject: ((XYSeriesCollection) data.getData()).getSeries()) { - XYSeries xySeries = (XYSeries) xySeriesObject; - GraphPropertiesPanel gpPanel = new GraphPropertiesPanel(plot, xySeries, seriesNumber); - graphOptionsContainerPanel.add(gpPanel, gbc); - seriesNumber++; - } - - - } - - /** This method is called from within the constructor to - * initialize the form. - * WARNING: Do NOT modify this code. The content of this method is - * always regenerated by the Form Editor. - */ - private void initComponents() { - - graphOptionScrollPane = new javax.swing.JScrollPane(); - jPanel1 = new javax.swing.JPanel(); - nameLabel = new javax.swing.JLabel(); - colorLabel = new javax.swing.JLabel(); - plotLabel = new javax.swing.JLabel(); - singleLabel = new javax.swing.JLabel(); - logLabel = new javax.swing.JLabel(); - minLabel = new javax.swing.JLabel(); - maxLabel = new javax.swing.JLabel(); - rangeLabel = new javax.swing.JLabel(); - - setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); - - nameLabel.setText("Name"); - - colorLabel.setText("Color"); - - plotLabel.setText("Plot"); - - singleLabel.setText("Single"); - - logLabel.setText("Log"); - - minLabel.setText("Min"); - - maxLabel.setText("Max"); - - rangeLabel.setText("range"); - - javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); - jPanel1.setLayout(jPanel1Layout); - jPanel1Layout.setHorizontalGroup( - jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addContainerGap() - .addComponent(nameLabel) - .addGap(123, 123, 123) - .addComponent(colorLabel) - .addGap(32, 32, 32) - .addComponent(plotLabel) - .addGap(18, 18, 18) - .addComponent(singleLabel) - .addGap(18, 18, 18) - .addComponent(logLabel) - .addGap(18, 18, 18) - .addComponent(rangeLabel) - .addGap(55, 55, 55) - .addComponent(minLabel) - .addGap(73, 73, 73) - .addComponent(maxLabel) - .addContainerGap(119, Short.MAX_VALUE)) - ); - jPanel1Layout.setVerticalGroup( - jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addContainerGap() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(nameLabel) - .addComponent(logLabel) - .addComponent(singleLabel) - .addComponent(plotLabel) - .addComponent(colorLabel) - .addComponent(rangeLabel) - .addComponent(minLabel) - .addComponent(maxLabel)) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - ); - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); - getContentPane().setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGap(39, 39, 39) - .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(47, Short.MAX_VALUE)) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGap(36, 36, 36) - .addComponent(graphOptionScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 719, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(36, Short.MAX_VALUE))) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(249, Short.MAX_VALUE)) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGap(59, 59, 59) - .addComponent(graphOptionScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 182, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(59, Short.MAX_VALUE))) - ); - - pack(); - }// //GEN-END:initComponents - - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JLabel colorLabel; - private javax.swing.JScrollPane graphOptionScrollPane; - private javax.swing.JPanel jPanel1; - private javax.swing.JLabel logLabel; - private javax.swing.JLabel maxLabel; - private javax.swing.JLabel minLabel; - private javax.swing.JLabel nameLabel; - private javax.swing.JLabel plotLabel; - private javax.swing.JLabel rangeLabel; - private javax.swing.JLabel singleLabel; - // End of variables declaration//GEN-END:variables - -} diff --git a/ch.psi.plot/tmp/xy/GraphPropertiesPanel.java b/ch.psi.plot/tmp/xy/GraphPropertiesPanel.java deleted file mode 100644 index 5b19434..0000000 --- a/ch.psi.plot/tmp/xy/GraphPropertiesPanel.java +++ /dev/null @@ -1,358 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ - -/* - * GraphPropertiesPanel.java - * - * Created on Mar 16, 2010, 8:30:56 AM - */ - -package ch.psi.plot.plot.xy; - -import java.awt.Color; -import java.awt.Paint; -import java.util.logging.Logger; - -import org.jfree.chart.axis.LogarithmicAxis; -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.plot.XYPlot; -import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; -import org.jfree.data.xy.XYSeries; -import org.jfree.data.xy.XYSeriesCollection; - -import ch.psi.plot.plot.done.LinePlot; -import ch.psi.plot.plot.done.LinePlotData; - - - -/** - * - * @author studer_a1 - */ -public class GraphPropertiesPanel extends javax.swing.JPanel { - - /** - * - */ - private static final long serialVersionUID = 1L; - private static Logger logger = Logger.getLogger(GraphPropertiesPanel.class.getName()); - - private XYSeries xySeries; - private XYLineAndShapeRenderer renderer; - private XYPlot plot; - private int seriesNumber; - private int xyDataSetOffset; - LinePlot singlePlot = null; - - /** Creates new form GraphPropertiesPanel */ - public GraphPropertiesPanel(XYPlot plot, XYSeries xySeries, int seriesNumber) { - this.plot = plot; - this.xySeries = xySeries; - this.renderer = (XYLineAndShapeRenderer) plot.getRenderer(); - this.seriesNumber = seriesNumber; - this.xyDataSetOffset = plot.getDatasetCount(); - - initComponents(); - initFields(); - } - - public void initFields(){ - nameLabel.setText(xySeries.getKey().toString()); - colorLabel.setOpaque(true); - colorLabel.setBackground((Color) renderer.getSeriesPaint(seriesNumber)); - plotCheckBox.setSelected(renderer.isSeriesVisible(seriesNumber)); - singleCheckBox.setSelected(false); - logCheckBox.setSelected(false); - minTextField.setText(new Double(xySeries.getMinY()).toString()); - maxTextField.setText(new Double(xySeries.getMaxY()).toString()); - } - - /** - * Creates a single plot out of an xySeries, destroys the plot if singleCheckBox.isSelected() is false - */ - public void createSinglePlotUsingSeries(){ - LinePlotData d = new LinePlotData(); - ((XYSeriesCollection) d.getData()).addSeries(xySeries); - //use the same paint as in the original - Paint paint = renderer.getSeriesPaint(seriesNumber); - singlePlot = new LinePlot(xySeries.getKey().toString(), d); - // there is only one series in this plot, so we choose index 0 to assign paint - singlePlot.getChartPanel().getChart().getXYPlot().getRenderer().setSeriesPaint(0, paint); - singlePlot.plot(false); - //check whether we want a log scale - if(logCheckBox.isSelected()){ - final NumberAxis rangeAxis = new LogarithmicAxis("Log"); - ((LogarithmicAxis)rangeAxis).setAllowNegativesFlag(true); - singlePlot.getChartPanel().getChart().getXYPlot().setRangeAxis(rangeAxis); - } - } - - /** - * creates a dataset with a single xySerie - * @return - */ - public XYSeriesCollection wrapSeriesInDataSet(){ - XYSeriesCollection wrappedSeries = new XYSeriesCollection(); - wrappedSeries.addSeries(xySeries); - return wrappedSeries; - - } - - /** - * creates an additional range (y) scale for a series (identified by its name) - * lowerbound and upperbound are taken from user input. - * @param name - * @param lowerBound - * @param upperBound - * @return - */ - public NumberAxis createIndivdualRangeScale(String name, double lowerBound, double upperBound){ - NumberAxis individualRangeScale = new NumberAxis(name); - individualRangeScale.setLowerBound(lowerBound); - individualRangeScale.setUpperBound(upperBound); - return individualRangeScale; - - } - - /** - * makes the individual range scale visible - */ - public void applyIndividualRangeScale(){ - double lowerBound = 0.0; - double upperBound = 0.0; - try { - lowerBound = Double.parseDouble(minTextField.getText()); - upperBound = Double.parseDouble(maxTextField.getText()); - } catch (NumberFormatException e) { - logger.warning("invalid bounds"); - return; - } - - //create new dataset and axis - NumberAxis individualRangeScale = createIndivdualRangeScale( - xySeries.getKey().toString(),lowerBound, upperBound); - individualRangeScale.setLabelPaint(renderer.getSeriesPaint(seriesNumber)); - individualRangeScale.setTickLabelPaint(renderer.getSeriesPaint(seriesNumber)); - individualRangeScale.setAxisLinePaint(renderer.getSeriesPaint(seriesNumber)); - plot.setRangeAxis(seriesNumber + xyDataSetOffset, individualRangeScale); - plot.setDataset(seriesNumber + xyDataSetOffset, wrapSeriesInDataSet()); - plot.mapDatasetToRangeAxis(seriesNumber + xyDataSetOffset, seriesNumber + xyDataSetOffset); - XYLineAndShapeRenderer individualRenderer = new XYLineAndShapeRenderer(); - //StandardXYItemRenderer individualRenderer = new StandardXYItemRenderer(); - individualRenderer.setSeriesPaint(0, renderer.getSeriesPaint(seriesNumber)); - individualRenderer.setSeriesShape(0, renderer.getSeriesShape(seriesNumber)); - plot.setRenderer(seriesNumber + xyDataSetOffset, individualRenderer); - - //set original series invisible - renderer.setSeriesVisible(seriesNumber, false); - - } - - /** - * removes the individual range scale - */ - public void removeIndividualRangeScale(){ - //we remove axis and dataset and renderer - plot.setRangeAxis(seriesNumber + xyDataSetOffset, null); - plot.setDataset(seriesNumber + xyDataSetOffset, null); - plot.setRenderer(seriesNumber + xyDataSetOffset, null); - if(plotCheckBox.isSelected()){ - renderer.setSeriesVisible(seriesNumber, true); - //renderer.setSer - } - } - - private void initComponents() { - - nameLabel = new javax.swing.JLabel(); - colorLabel = new javax.swing.JLabel(); - plotCheckBox = new javax.swing.JCheckBox(); - singleCheckBox = new javax.swing.JButton(); - logCheckBox = new javax.swing.JCheckBox(); - minTextField = new javax.swing.JTextField(); - maxTextField = new javax.swing.JTextField(); - individualRangeScaleCheckBox = new javax.swing.JCheckBox(); - - singleCheckBox.setText("Show"); - nameLabel.setText("name"); - - colorLabel.setText(" "); - - plotCheckBox.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - plotCheckBoxActionPerformed(evt); - } - }); - - singleCheckBox.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - createSinglePlotUsingSeries(); - } - }); - - logCheckBox.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - logCheckBoxActionPerformed(evt); - } - }); - - minTextField.setText("min"); - minTextField.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - minTextFieldActionPerformed(evt); - } - }); - - maxTextField.setText("max"); - maxTextField.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - maxTextFieldActionPerformed(evt); - } - }); - - individualRangeScaleCheckBox.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - individualRangeScaleCheckBoxActionPerformed(evt); - } - }); - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addComponent(nameLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 103, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(58, 58, 58) - .addComponent(colorLabel) - .addGap(50, 50, 50) - .addComponent(plotCheckBox) - .addGap(30, 30, 30) - .addComponent(singleCheckBox) - .addGap(30, 30, 30) - .addComponent(logCheckBox) - .addGap(28, 28, 28) - .addComponent(individualRangeScaleCheckBox) - .addGap(49, 49, 49) - .addComponent(minTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 83, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(18, 18, 18) - .addComponent(maxTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 86, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(106, Short.MAX_VALUE)) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(logCheckBox) - .addComponent(singleCheckBox) - .addComponent(plotCheckBox) - .addComponent(nameLabel) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(minTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(maxTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGroup(layout.createSequentialGroup() - .addGap(6, 6, 6) - .addComponent(colorLabel)) - .addComponent(individualRangeScaleCheckBox)) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - ); - }// //GEN-END:initComponents - - private void plotCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_plotCheckBoxActionPerformed - if(plotCheckBox.isSelected()){ - //if an individual scale exists, set this one visible - //if(plot.getRenderer(seriesNumber + xyDataSetOffset) != null){ - if(individualRangeScaleCheckBox.isSelected()){ - //The following should always be true, if not, there is a (logical) problem - if(plot.getRenderer(seriesNumber + xyDataSetOffset) != null){ - plot.getRenderer(seriesNumber + xyDataSetOffset).setSeriesVisible(0, true); - } - } - else{ - //set the other one invisible - renderer.setSeriesVisible(seriesNumber, true); - } - } - else{ - //set individual range dataset and series invisible (if exists) - renderer.setSeriesVisible(seriesNumber, false); - if(plot.getRenderer(seriesNumber + xyDataSetOffset) != null){ - plot.getRenderer(seriesNumber + xyDataSetOffset).setSeriesVisible(0, false); - } - - } - }//GEN-LAST:event_plotCheckBoxActionPerformed - - - private void logCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_logCheckBoxActionPerformed - // TODO add your handling code here: - }//GEN-LAST:event_logCheckBoxActionPerformed - - private void minTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_minTextFieldActionPerformed - double lowerBound = 0.0; - - if(individualRangeScaleCheckBox.isSelected()){ - if(plot.getRangeAxis(seriesNumber + xyDataSetOffset) != null){ - try { - lowerBound = Double.parseDouble(minTextField.getText()); - } catch (NumberFormatException e) { - logger.warning("invalid lower bound"); - return; - } - if(lowerBound >= plot.getRangeAxis(seriesNumber + xyDataSetOffset).getUpperBound()){ - logger.warning("lower bound >= upper bound"); - } - else{ - plot.getRangeAxis(seriesNumber + xyDataSetOffset).setLowerBound(lowerBound); - } - } - } - }//GEN-LAST:event_minTextFieldActionPerformed - - private void maxTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_maxTextFieldActionPerformed - double upperBound = 0.0; - - if(individualRangeScaleCheckBox.isSelected()){ - if(plot.getRangeAxis(seriesNumber + xyDataSetOffset) != null){ - try { - upperBound = Double.parseDouble(maxTextField.getText()); - } catch (NumberFormatException e) { - logger.warning("invalid upper bound"); - return; - } - if(upperBound <= plot.getRangeAxis(seriesNumber + xyDataSetOffset).getLowerBound()){ - logger.warning("upper bound <= lower bound"); - } - else{ - plot.getRangeAxis(seriesNumber + xyDataSetOffset).setUpperBound(upperBound); - } - } - } - - }//GEN-LAST:event_maxTextFieldActionPerformed - - private void individualRangeScaleCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_individualRangeScaleCheckBoxActionPerformed - if(individualRangeScaleCheckBox.isSelected()){ - applyIndividualRangeScale(); - } - else{ - removeIndividualRangeScale(); - } - }//GEN-LAST:event_individualRangeScaleCheckBoxActionPerformed - - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JLabel colorLabel; - private javax.swing.JCheckBox individualRangeScaleCheckBox; - private javax.swing.JCheckBox logCheckBox; - private javax.swing.JTextField maxTextField; - private javax.swing.JTextField minTextField; - private javax.swing.JLabel nameLabel; - private javax.swing.JCheckBox plotCheckBox; - private javax.swing.JButton singleCheckBox; - // End of variables declaration//GEN-END:variables - -} diff --git a/ch.psi.plot/tmp/xy/Interval.java b/ch.psi.plot/tmp/xy/Interval.java deleted file mode 100644 index f03b58a..0000000 --- a/ch.psi.plot/tmp/xy/Interval.java +++ /dev/null @@ -1,70 +0,0 @@ -/** - * - * Copyright 2010 Paul Scherrer Institute. All rights reserved. - * - * This code 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. - * - * This code 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 this code. If not, see . - * - */ - -package ch.psi.plot.plot.xy; - -/** - * Bean holding information of an LinePlot interval - * @author ebner - * - */ -public class Interval { - - private Double leftBorder; - private Double rightBorder; - - /** - * Constructor - Default constructor - * @param leftBorder - * @param rightBorder - */ - public Interval(Double leftBorder, Double rightBorder) { - this.leftBorder = leftBorder; - this.rightBorder = rightBorder; - } - - /** - * @return the leftBorder - */ - public Double getLeftBorder() { - return leftBorder; - } - - /** - * @param leftBorder the leftBorder to set - */ - public void setLeftBorder(Double leftBorder) { - this.leftBorder = leftBorder; - } - - /** - * @return the rightBorder - */ - public Double getRightBorder() { - return rightBorder; - } - - /** - * @param rightBorder the rightBorder to set - */ - public void setRightBorder(Double rightBorder) { - this.rightBorder = rightBorder; - } - -} diff --git a/ch.psi.plot/tmp/xy/Marker.java b/ch.psi.plot/tmp/xy/Marker.java deleted file mode 100644 index 2acfd75..0000000 --- a/ch.psi.plot/tmp/xy/Marker.java +++ /dev/null @@ -1,97 +0,0 @@ -/** - * - * Copyright 2010 Paul Scherrer Institute. All rights reserved. - * - * This code 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. - * - * This code 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 this code. If not, see . - * - */ - -package ch.psi.plot.plot.xy; - -/** - * Bean for storing a LinePlot marker information - * @author ebner - * - */ -public class Marker { - - /** - * Label of the marker - */ - private String label; - /** - * X coordinate of the marker - */ - private Double x; - /** - * Y coordinate of the marker - */ - private Double y; - - - /** - * Constructor - * @param label - * @param x - * @param y - */ - public Marker(String label, Double x, Double y) { - this.label = label; - this.x = x; - this.y = y; - } - - /** - * @return the label - */ - public String getLabel() { - return label; - } - - /** - * @param label the label to set - */ - public void setLabel(String label) { - this.label = label; - } - - /** - * @return the x - */ - public Double getX() { - return x; - } - - /** - * @param x the x to set - */ - public void setX(Double x) { - this.x = x; - } - - /** - * @return the y - */ - public Double getY() { - return y; - } - - /** - * @param y the y to set - */ - public void setY(Double y) { - this.y = y; - } - -} diff --git a/ch.psi.plot/tmp/xyz/ExtremaFinder.java b/ch.psi.plot/tmp/xyz/ExtremaFinder.java deleted file mode 100644 index 82b01ce..0000000 --- a/ch.psi.plot/tmp/xyz/ExtremaFinder.java +++ /dev/null @@ -1,140 +0,0 @@ -package ch.psi.plot.xyz; - -import java.util.logging.Logger; - -import ch.psi.plot.util.XYPoint; - -public class ExtremaFinder { - - private static Logger logger = Logger.getLogger(ExtremaFinder.class.getName()); - - private enum Extrema {MIN, MAX, MIN_MAX_VALUE}; - - - /** - * Get the point of the minimum value - * @param plotData - * @param lowerLeft - * @param upperRight - * @return - */ - public static XYPoint getMinimum(JFreeMatrixPlotData plotData, XYPoint lowerLeft, XYPoint upperRight){ - return(findExtrema(plotData, lowerLeft, upperRight, Extrema.MIN, true)); - } - - /** - * Get the point of the maximum value - * @param plotData - * @param lowerLeft - * @param upperRight - * @return - */ - public static XYPoint getMaximum(JFreeMatrixPlotData plotData, XYPoint lowerLeft, XYPoint upperRight){ - return(findExtrema(plotData, lowerLeft, upperRight, Extrema.MAX, true)); - } - - /** - * Get the lowest and highest value of the data in the region - * - * TODO XYPoint need to be removed !!!!! - * - * @param plotData - * @param lowerLeft - * @param upperRight - * @return - */ - public static XYPoint getMinMaxValue(JFreeMatrixPlotData plotData, XYPoint lowerLeft, XYPoint upperRight){ - return(findExtrema(plotData, lowerLeft, upperRight, Extrema.MIN_MAX_VALUE, true)); - } - - /** - * Find extremas in the specified region - * @param plotData - * @param lowerLeft - * @param upperRight - * @param e - * @return - */ - private static XYPoint findExtrema(JFreeMatrixPlotData plotData, XYPoint lowerLeft, XYPoint upperRight, Extrema e, boolean binned){ - - double x; double y; double z; - double zmin = Double.POSITIVE_INFINITY; - double zmax = Double.NEGATIVE_INFINITY; - double minLocationX = 0.0; - double minLocationY = 0.0; - double maxLocationX = 0.0; - double maxLocationY = 0.0; - - - x = lowerLeft.getX(); - y = lowerLeft.getY(); - - if (binned){ - try{ - x = plotData.getXValueBinned(x); - y = plotData.getYValueBinned(y); - } - catch(Exception exc){ - logger.fine(exc.getMessage() + " Start values couldn't be binned"); - } - } - - while(x < upperRight.getX()){ - while(y < upperRight.getY()){ - try{ - z = plotData.getValue(x, y); - //we discard negative infinity, since this is related to init values - if (z < zmin && !(z == Double.NEGATIVE_INFINITY)){ - zmin = z; - minLocationX = x; - minLocationY = y; - } - if (z > zmax && !(z == Double.POSITIVE_INFINITY)){ - zmax = z; - maxLocationX = x; - maxLocationY = y; - } - } - catch(Exception exception){ - logger.severe(exception.getMessage()); - } - - y = y + plotData.getMetadata().getBinWidthY(); - } - y = lowerLeft.getY(); - x = x + plotData.getMetadata().getBinWidthX(); - } - - XYPoint extrema = null; - - if(binned){ - try{ - minLocationX = plotData.getXValueBinned(minLocationX); - minLocationY = plotData.getYValueBinned(minLocationY); - - maxLocationX = plotData.getXValueBinned(maxLocationX); - maxLocationY = plotData.getYValueBinned(maxLocationY); - } - catch(Exception exc){ - logger.fine(exc.getMessage() + " Extrema couldn't be binned"); - } - } - - if(e.equals(Extrema.MIN)){ - extrema = new XYPoint(minLocationX, minLocationY); - } - else if(e.equals(Extrema.MAX)){ - extrema = new XYPoint(maxLocationX, maxLocationY); - } - else if(e.equals(Extrema.MIN_MAX_VALUE)){ - extrema = new XYPoint(zmin, zmax); - } - - return(extrema); - } - - - - - -} diff --git a/ch.psi.plot/tmp/xyz/IndexOutOfBoundListener.java b/ch.psi.plot/tmp/xyz/IndexOutOfBoundListener.java deleted file mode 100644 index 671b7fc..0000000 --- a/ch.psi.plot/tmp/xyz/IndexOutOfBoundListener.java +++ /dev/null @@ -1,10 +0,0 @@ -package ch.psi.plot.xyz; - -public interface IndexOutOfBoundListener { - - /** - * If the initially allocated matrix is too small, we need to reallocate - * a new MatrixSeries and then tell matrix plot to replot - */ - public void redraw(); -} diff --git a/ch.psi.plot/tmp/xyz/JFreeMatrixPlot.java b/ch.psi.plot/tmp/xyz/JFreeMatrixPlot.java deleted file mode 100644 index 9597c01..0000000 --- a/ch.psi.plot/tmp/xyz/JFreeMatrixPlot.java +++ /dev/null @@ -1,1354 +0,0 @@ -package ch.psi.plot.xyz; - -import ij.ImageJ; -import ij.ImagePlus; -import ij.process.FloatProcessor; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.Insets; -import java.awt.Point; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.event.MouseMotionListener; -import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.ServiceLoader; -import java.util.logging.Logger; - -import javax.swing.AbstractAction; -import javax.swing.JComponent; -import javax.swing.JFrame; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JTextField; -import javax.swing.KeyStroke; -import javax.swing.WindowConstants; - -import org.jfree.chart.ChartPanel; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.annotations.XYAnnotation; -import org.jfree.chart.annotations.XYDrawableAnnotation; -import org.jfree.chart.annotations.XYPolygonAnnotation; -import org.jfree.chart.annotations.XYTextAnnotation; -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.event.AxisChangeEvent; -import org.jfree.chart.event.AxisChangeListener; -import org.jfree.chart.labels.StandardXYZToolTipGenerator; -import org.jfree.chart.labels.XYZToolTipGenerator; -import org.jfree.chart.plot.XYPlot; -import org.jfree.chart.renderer.LookupPaintScale; -import org.jfree.chart.renderer.PaintScale; -import org.jfree.chart.renderer.xy.XYBlockRenderer; -import org.jfree.chart.title.PaintScaleLegend; -import org.jfree.data.Range; -import org.jfree.data.xy.XYSeries; -import org.jfree.data.xy.XYSeriesCollection; -import org.jfree.ui.RectangleAnchor; -import org.jfree.ui.RectangleEdge; -import org.jfree.ui.RectangleInsets; -import org.jfree.ui.RefineryUtilities; - -import ch.psi.plot.EventActionListener; -import ch.psi.plot.Plot; -import ch.psi.plot.util.CoordinateTransformer; -import ch.psi.plot.util.MenuLoader; -import ch.psi.plot.util.PlugableUtil; -import ch.psi.plot.util.PluginExecutionException; -import ch.psi.plot.util.XYPoint; -import ch.psi.plot.util.PlugableUtil.PlotType; -import ch.psi.plot.xy.LinePlot; -import ch.psi.plot.xy.LinePlotData; -import ch.psi.plot.xyz.plugable.PlugableUtilXYZ; - - - -/** - * Returns a matrix plot panel - */ -public class JFreeMatrixPlot implements Plot, AxisChangeListener, MouseListener, MouseMotionListener, ActionListener, IndexOutOfBoundListener{ - - private static final long serialVersionUID = 1L; - - private static Logger logger = Logger.getLogger(JFreeMatrixPlot.class.getName()); - - private final int frameHeight = 500; - private final int frameWidth = 1200; - private final int frameUpperLeftX = 0; - private final int frameUpperLeftY = 500; - - private String title; - - //Menu labels - final String tooltipsMenuLabel = "Tooltips"; - final String hideTooltipsMenuLabel = "Hide Tooltips"; - - final String clearMarkersMenuLabel = "Clear Markers"; - final String originalRangeMenuLabel = "Original Range"; - final String originalColorMapScaleMenuLabel = "Original Colormap"; - final String adaptColorMapScaleMenuLabel = "Adapt Colormap"; - final String chooseColorMapMenuLabel = "Choose ColorMap"; - final String grayScaleMenuLabel = "No Color"; - final String singleColorScaleMenuLabel = "Single Color"; - final String temperatureColorScaleMenuLabel = "Temperature Color"; - final String detachMenuLabel = "Detach Plot"; - final String analyzeMenuLabel = "Analyze"; - final String pauseMenuLabel = "Pause"; - final String continueMenuLabel = "Continue"; - final String reloadDataMenulabel = "Reload Data"; - - //Action Map keys (Input Map values) - final String CtrlReleasedKey = "Ctrl released"; - final String moveUpKey = "move up"; - final String moveDownKey = "move down"; - final String moveRightKey = "move right"; - final String moveLeftKey = "move left"; - - //List of Event Listeners - private List eventActionListeners = new ArrayList(); - private List plugableUtils; - - private HashMap interestingSpots = new HashMap(); // List of interesting spots - private ArrayList anonymousInterstingSpots = new ArrayList(); // List of interesting spots without a key - private ArrayList regions = new ArrayList(); //Selected regions - - //Default is GrayScale - private boolean isGrayScale = false; - //If Scale is colored, then single color is default (not temperature color) - private boolean isSingleColorScale = false; - - //label for section plots - private String lineSectionPlotTitle = "Line Section Plot"; - private XYSeriesCollection lineSectionCollection; - - //GUI components - private JFrame frame; - private ChartPanel matrixPlotPanel; - private JPanel jPanel; - private JPanel textFieldPanel; - private JTextField upperBoundTextField; - private JTextField lowerBoundTextField; - - - //We need a reference to paintScaleLegend to be able to change the scale - //private PaintScaleLegend paintScaleLegend; - - private Point startPoint = new Point(); //StartPoint of Line Diagram - private Point endPoint = new Point(); - private XYPoint chartStartPoint = new XYPoint(0.0, 0.0); - private XYPoint chartEndPoint = new XYPoint(0.0, 0.0); - - //Coordinates of rectangle if zoomed (AxisChangedListener is notified) - private XYPoint lowerLeftChartCorner = new XYPoint(0.0, 0.0); - private XYPoint upperRightChartCorner = new XYPoint(0.0, 0.0); - - private XYPoint zRange = new XYPoint(0.0, 0.0); - - private boolean isDragging = false; - private boolean isCTRLReleased = true; - - private JFreeMatrixPlotData data; - - - - /** - * Constructor - * @param title - * @param data - */ - public JFreeMatrixPlot(String title, JFreeMatrixPlotData data) { - createPanel(title, data); - } - - public void createPanel(String title, JFreeMatrixPlotData data ){ - this.title = title; - this.data = data; - - // Init size of plot area according to min and max set in the datas metadata - initChartRectangle(); - - //Create the Chartpanel where the chart will be plotted - - this.matrixPlotPanel = new ChartPanel(createMatrixChart()); - //This is for speed up - //matrixPlotPanel.getChartRenderingInfo().setEntityCollection(null); - this.jPanel = new JPanel(new BorderLayout()); - jPanel.add(matrixPlotPanel); - - addListeners(); - // Add bindings that handle keyboard input - addBindings(); - //add the text fields for editing lower an upper Bounds - addTextFields(); - // Init PaintScale - setOriginalColorMapScale(); - // Customize context Menu - //All interactive menu items - adaptContextMenu(); - //All analysis related menu items - amendPlugableContextMenu(); - - } - - - // Action Classes that implement methods called after keyboard input - - // Only needed for the action after shift is released (shift needs to be pressed for drawing a polygon) - public class ReleasedPolygonAction extends AbstractAction{ - private static final long serialVersionUID = 1L; - @Override - public void actionPerformed(ActionEvent e) { - redrawSelectedRegions(); - isCTRLReleased = true; - } - } - - // Arrow key actions - public class MoveUpAction extends AbstractAction{ - private static final long serialVersionUID = 1L; - @Override - public void actionPerformed(ActionEvent e) { - XYPoint translationVector = new XYPoint(0.0, data.getMetadata().getBinWidthY()); - moverOverPlot(translationVector); - } - } - - public class MoveDownAction extends AbstractAction{ - private static final long serialVersionUID = 1L; - @Override - public void actionPerformed(ActionEvent e) { - XYPoint translationVector = new XYPoint(0.0, - data.getMetadata().getBinWidthY()); - moverOverPlot(translationVector); - } - } - - public class MoveRightAction extends AbstractAction{ - private static final long serialVersionUID = 1L; - @Override - public void actionPerformed(ActionEvent e) { - XYPoint translationVector = new XYPoint(data.getMetadata().getBinWidthX(), 0.0); - moverOverPlot(translationVector); - } - } - - public class MoveLeftAction extends AbstractAction{ - private static final long serialVersionUID = 1L; - @Override - public void actionPerformed(ActionEvent e) { - XYPoint translationVector = new XYPoint(- data.getMetadata().getBinWidthX(), 0.0); - moverOverPlot(translationVector); - } - } - - - public void addTextFields(){ - textFieldPanel = new JPanel(new BorderLayout()); - textFieldPanel.add(addLowerBoundTextField(), BorderLayout.SOUTH); - textFieldPanel.add(addUpperBoundTextField(), BorderLayout.NORTH); - - jPanel.add(textFieldPanel, BorderLayout.EAST); - } - - public JTextField addLowerBoundTextField(){ - this.lowerBoundTextField = new JTextField(zRange.getX().toString(), 5); - lowerBoundTextField.addActionListener( new ActionListener() { - @Override public void actionPerformed( ActionEvent e ) { - double lb; - try { - lb = Double.parseDouble(((JTextField) e.getSource()).getText()); - zRange.setX(lb); - setScale(zRange.getX(), zRange.getY()); - } catch (NumberFormatException e1) { - e1.printStackTrace(); - } - } - } ); - return lowerBoundTextField; - } - - public JTextField addUpperBoundTextField(){ - upperBoundTextField = new JTextField(zRange.getY().toString(), 5); - upperBoundTextField.addActionListener( new ActionListener() { - @Override public void actionPerformed( ActionEvent e ) { - double ub; - try { - ub = Double.parseDouble(((JTextField) e.getSource()).getText()); - zRange.setY(ub); - setScale(zRange.getX(), zRange.getY()); - } catch (NumberFormatException e1) { - e1.printStackTrace(); - } - } - } ); - return upperBoundTextField; - } - - - public void amendPlugableContextMenu(){ - MenuLoader menuLoader = new MenuLoader(PlotType.twoDim, "menuconfigxyz.xml", "ch.psi.plot.xyz.plugable.", this); - menuLoader.initUtils(matrixPlotPanel.getPopupMenu()); - //add predefined actions - plugableUtils = menuLoader.getPlugableUtils(); - //add user defined actions loaded via services - loadServices(); - } - - private void loadServices() { - ServiceLoader plugableUtilXYZServices = ServiceLoader.load(PlugableUtilXYZ.class); - for ( PlugableUtilXYZ plugableUtilXYZService : plugableUtilXYZServices){ - plugableUtils.add(plugableUtilXYZService); - JMenuItem serviceLoadedMenuItem = new JMenuItem(plugableUtilXYZService.getLabel()); - serviceLoadedMenuItem.addActionListener(this); - matrixPlotPanel.getPopupMenu().add(serviceLoadedMenuItem); - } - } - - - private void adaptContextMenu(){ - JMenuItem contextMenuItemToolTip = new JMenuItem(tooltipsMenuLabel); - JMenuItem contextMenuItemClearMarkers = new JMenuItem(clearMarkersMenuLabel); - JMenuItem contextMenuItemOriginalRange = new JMenuItem(originalRangeMenuLabel); - JMenuItem contextMenuItemAdaptScale = new JMenuItem(adaptColorMapScaleMenuLabel); - JMenuItem contextMenuItemOriginalScale = new JMenuItem(originalColorMapScaleMenuLabel); - JMenuItem contextMenuChooseColorMap = new JMenu(chooseColorMapMenuLabel); - JMenuItem contextMenuItemGrayScale = new JMenuItem(grayScaleMenuLabel); - JMenuItem contextMenuItemSingleColor = new JMenuItem(singleColorScaleMenuLabel); - JMenuItem contextMenuItemTemperatureColor = new JMenuItem(temperatureColorScaleMenuLabel); - JMenuItem contextMenuItemPause = new JMenuItem(pauseMenuLabel); - JMenuItem contextMenuItemReloadData = new JMenuItem(reloadDataMenulabel); - JMenuItem contextMenuItemDetach = new JMenuItem(detachMenuLabel); - contextMenuItemDetach.addActionListener(this); - - JMenuItem contextMenuItemAnalyze = new JMenuItem(analyzeMenuLabel); - contextMenuItemAnalyze.addActionListener(this); - - // Add action listeners - contextMenuItemToolTip.addActionListener(this); - contextMenuItemClearMarkers.addActionListener(this); - contextMenuItemOriginalRange.addActionListener(this); - contextMenuItemAdaptScale.addActionListener(this); - contextMenuItemOriginalScale.addActionListener(this); - contextMenuItemGrayScale.addActionListener(this); - contextMenuItemSingleColor.addActionListener(this); - contextMenuItemTemperatureColor.addActionListener(this); - contextMenuItemPause.addActionListener(this); - contextMenuItemReloadData.addActionListener(this); - - // Group menus - contextMenuChooseColorMap.add(contextMenuItemGrayScale); - contextMenuChooseColorMap.add(contextMenuItemSingleColor); - contextMenuChooseColorMap.add(contextMenuItemTemperatureColor); - - // Add menus to popup panel - matrixPlotPanel.getPopupMenu().add(contextMenuItemToolTip); - matrixPlotPanel.getPopupMenu().add(contextMenuItemClearMarkers); - matrixPlotPanel.getPopupMenu().add(contextMenuItemOriginalRange); - matrixPlotPanel.getPopupMenu().add(contextMenuItemAdaptScale); - matrixPlotPanel.getPopupMenu().add(contextMenuItemOriginalScale); - matrixPlotPanel.getPopupMenu().add(contextMenuChooseColorMap); - matrixPlotPanel.getPopupMenu().addSeparator(); - matrixPlotPanel.getPopupMenu().add(contextMenuItemDetach); - matrixPlotPanel.getPopupMenu().add(contextMenuItemAnalyze); - matrixPlotPanel.getPopupMenu().addSeparator(); - matrixPlotPanel.getPopupMenu().add(contextMenuItemPause); - matrixPlotPanel.getPopupMenu().add(contextMenuItemReloadData); - matrixPlotPanel.getPopupMenu().addSeparator(); - - - //Deactivate some unused features - matrixPlotPanel.getPopupMenu().getComponent(7).setEnabled(false); - matrixPlotPanel.getPopupMenu().getComponent(8).setEnabled(false); - matrixPlotPanel.getPopupMenu().getComponent(10).setEnabled(false); - } - - private void addListeners(){ - // Add mouse listener - matrixPlotPanel.addMouseListener(this); - matrixPlotPanel.addMouseMotionListener(this); - // Both DomainAxis Listener and Range Axis Listener are needed - matrixPlotPanel.getChart().getXYPlot().getDomainAxis().addChangeListener(this); - matrixPlotPanel.getChart().getXYPlot().getRangeAxis().addChangeListener(this); - } - - private void addBindings(){ - //Control released finishes Polygon definition (and plots polygon) - this.matrixPlotPanel.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke("released CONTROL"), CtrlReleasedKey); - //up arrow - this.matrixPlotPanel.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), moveUpKey); - //down arrow - this.matrixPlotPanel.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0),moveDownKey); - //right arrow - this.matrixPlotPanel.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0),moveRightKey); - //left arrow - this.matrixPlotPanel.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0),moveLeftKey); - - matrixPlotPanel.getActionMap().put(CtrlReleasedKey, new ReleasedPolygonAction()); - matrixPlotPanel.getActionMap().put(moveUpKey, new MoveUpAction()); - matrixPlotPanel.getActionMap().put(moveDownKey, new MoveDownAction()); - matrixPlotPanel.getActionMap().put(moveRightKey, new MoveRightAction()); - matrixPlotPanel.getActionMap().put(moveLeftKey, new MoveLeftAction()); - } - - /** - * Inits the opposite points of the data and plot frame, the plot frame is larger - * (plus half bin size on both sides), since we plot the bins centered. - */ - private void initChartRectangle(){ - - lowerLeftChartCorner.setX(data.getMetadata().getMinX()- 0.5* data.getMetadata().getBinWidthX()); - lowerLeftChartCorner.setY(data.getMetadata().getMinY()- 0.5* data.getMetadata().getBinWidthY()); - upperRightChartCorner.setX(data.getMetadata().getMaxX()+ 0.5* data.getMetadata().getBinWidthX()); - upperRightChartCorner.setY(data.getMetadata().getMaxY()+ 0.5* data.getMetadata().getBinWidthY()); - } - - /** - * Creates a matrix chart. - * - * @return chart. - */ - private JFreeChart createMatrixChart() { - - NumberAxis xAxis = new NumberAxis(data.getMetadata().getxAxisLabel()); - xAxis.setLowerBound(lowerLeftChartCorner.getX()); - xAxis.setUpperBound(upperRightChartCorner.getX()); - - NumberAxis yAxis = new NumberAxis(data.getMetadata().getyAxisLabel()); - yAxis.setLowerBound(lowerLeftChartCorner.getY()); - yAxis.setUpperBound(upperRightChartCorner.getY()); - - XYBlockRenderer renderer = new XYBlockRenderer(); - renderer.setBlockWidth(data.getMetadata().getBinWidthX()); - renderer.setBlockHeight(data.getMetadata().getBinWidthY()); - renderer.setBlockAnchor(RectangleAnchor.CENTER); - - renderer.setBaseCreateEntities(false); - XYPlot matrixPlot = new XYPlot(data.getData(), xAxis, yAxis, renderer); - matrixPlot.setBackgroundPaint(Color.lightGray); - //matrixPlot.setRangeGridlinePaint(Color.white); - JFreeChart matrixChart = new JFreeChart(title, matrixPlot); - - //Remove the series label (also called legend) - matrixChart.removeLegend(); - //matrixChart.setBackgroundPaint(Color.green); - //Antialiasing is used to speed up rendering - matrixChart.setAntiAlias(false); - // Only accept manual updates -// matrixChart.setNotify(false); - - return matrixChart; - } - - - //Implementation of interfaces, interactive stuff - - /** - * Axis Change Listener, lower leftchart and upper right chart corner - * needs to be updated (if valid) - */ - @Override - public void axisChanged(AxisChangeEvent arg0) { - if(matrixPlotPanel.getChart().getXYPlot().getDomainAxis().getLowerBound() < data.getMetadata().getMinX() - 0.5*data.getMetadata().getBinWidthX() - || matrixPlotPanel.getChart().getXYPlot().getDomainAxis().getUpperBound() > data.getMetadata().getMaxX() + 0.5*data.getMetadata().getBinWidthX() - || matrixPlotPanel.getChart().getXYPlot().getRangeAxis().getLowerBound() < data.getMetadata().getMinY() - 0.5*data.getMetadata().getBinWidthY() - || matrixPlotPanel.getChart().getXYPlot().getRangeAxis().getUpperBound() > data.getMetadata().getMaxY() + 0.5*data.getMetadata().getBinWidthY()) - { - setOriginalPlotRegion(false); - return; - } - - lowerLeftChartCorner.setX(matrixPlotPanel.getChart().getXYPlot().getDomainAxis().getLowerBound()); - lowerLeftChartCorner.setY(matrixPlotPanel.getChart().getXYPlot().getRangeAxis().getLowerBound()); - upperRightChartCorner.setX(matrixPlotPanel.getChart().getXYPlot().getDomainAxis().getUpperBound()); - upperRightChartCorner.setY(matrixPlotPanel.getChart().getXYPlot().getRangeAxis().getUpperBound()); - - - if(lowerLeftChartCorner.getX() > upperRightChartCorner.getX() - || lowerLeftChartCorner.getY() > upperRightChartCorner.getY()){ - setOriginalPlotRegion(false); - } - } - - @Override - public void mouseClicked(MouseEvent e) { - // When mouse wheel is pressed, visible rectangle is selected, unless the click occurs in a already - // selected region, then the region will be unmarked - - if ((e.getModifiers() & InputEvent.BUTTON2_MASK) == InputEvent.BUTTON2_MASK){ - XYPoint chartClickPoint = new XYPoint(0.0,0.0); - - // If click is outside chart we return - if(!CoordinateTransformer.chartCoordinates(getMatrixPlotPanel(), e.getX(), e.getY(), chartClickPoint)){ - return; - } - - // If the click occurred in an allready marked region, we return (after deleting an redrawing) - if(removeSelectedRegion(chartClickPoint)){ - this.redrawSelectedRegions(); - return; - } - - double x1 = matrixPlotPanel.getChart().getXYPlot().getDomainAxis().getLowerBound(); - double y1 = matrixPlotPanel.getChart().getXYPlot().getRangeAxis().getLowerBound(); - double x3 = matrixPlotPanel.getChart().getXYPlot().getDomainAxis().getUpperBound(); - double y3 = matrixPlotPanel.getChart().getXYPlot().getRangeAxis().getUpperBound(); - - double x2 = x1; - double y2 = y3; - double x4 = x3; - double y4 = y1; - - // Don't do anything if original frame is selected - //Original Frame is different for Matrix and PixelPlot - - if(data instanceof MatrixPlotData){ - if (x1 == data.getMetadata().getMinX() - 0.5* data.getMetadata().getBinWidthX() && - x3 == data.getMetadata().getMaxX() + 0.5* data.getMetadata().getBinWidthX() && - y1 == data.getMetadata().getMinY()- 0.5* data.getMetadata().getBinWidthY() && - y3 == data.getMetadata().getMaxY()+ 0.5* data.getMetadata().getBinWidthY()){ - return; - } - } - else if(data instanceof PixelPlotData){ - if (x1 == data.getMetadata().getMinX() && - x3 == data.getMetadata().getMaxX() && - y1 == data.getMetadata().getMinY() && - y3 == data.getMetadata().getMaxY()){ - return; - } - } - - // TODO NEED TO BE VERIFIED - Region selectedRegion = new Region(); - regions.add(selectedRegion); - - int indexOfLastRegion = regions.size() - 1; - XYPoint xyPoint1 = new XYPoint(x1, y1); - regions.get(indexOfLastRegion).getPointList().add(xyPoint1); - XYPoint xyPoint2 = new XYPoint(x2, y2); - regions.get(indexOfLastRegion).getPointList().add(xyPoint2); - XYPoint xyPoint3 = new XYPoint(x3, y3); - regions.get(indexOfLastRegion).getPointList().add(xyPoint3); - XYPoint xyPoint4 = new XYPoint(x4, y4); - regions.get(indexOfLastRegion).getPointList().add(xyPoint4); - - redrawSelectedRegions(); - } - - // Mark spot / add pointer - if (e.isShiftDown()){ - XYPoint xyPoint = new XYPoint(0.0, 0.0); - //Check if coordinate is in chart - if (CoordinateTransformer.chartCoordinates(getMatrixPlotPanel(), e.getX(), e.getY(), xyPoint)){ - //Add pointer to HashMap - String key = JOptionPane.showInputDialog("Enter marker Id"); - if(key == null){ - return; - } - if (key.isEmpty()){ - anonymousInterstingSpots.add(xyPoint); - } - else{ - interestingSpots.put(key, xyPoint); - } - redrawSelectedRegions(); - } - else{ - return; - } - } - - // Add a region - else if (e.isControlDown()){ - logger.fine("Add region"); - - if(isCTRLReleased){ - //If control is released, start with a new region - Region selectedRegion = new Region(); - regions.add(selectedRegion); - isCTRLReleased = false; - } - - XYPoint xyPoint = new XYPoint(0.0, 0.0); - //Check if Point is inside chart - int indexOfLastRegion = regions.size() - 1; - if (CoordinateTransformer.chartCoordinates(getMatrixPlotPanel(), e.getX(), e.getY(), xyPoint)){ - //if so, add valid point to the last Region in list - regions.get(indexOfLastRegion).getPointList().add(xyPoint); - } - else - { - //TODO: check if this works - regions.remove(indexOfLastRegion); - return; - } - } - } - - @Override - public void mouseEntered(MouseEvent e) { - } - - @Override - public void mouseExited(MouseEvent e) { - } - - @Override - public void mousePressed(MouseEvent e) { - - // This is responsible only for plotting section plots. - if(!(e.isAltDown() && e.isShiftDown())){ - return; - } - - isDragging = false; - matrixPlotPanel.setMouseZoomable(false); - startPoint.setLocation(e.getX(), e.getY()); - } - - @Override - public void mouseReleased(MouseEvent e) { - - //This is responsible only for plotting section plots. - if(!(e.isAltDown()&&e.isShiftDown())){ - return; - } - - if(isDragging == true){ - isDragging = false; - matrixPlotPanel.setMouseZoomable(true); - // TODO NEED TO VERIFY - SEAMS TO BE CONFUSE CODE - endPoint.setLocation(e.getX(), e.getY()); - // lineSectionPlots.get(lineSectionPlots.size() - 1).getChart().setTitle("(" + round(chartStartPoint.getX(),2) + ", " + round(chartStartPoint.getY(),2) + ")" + - // " -> " +" (" + round(chartEndPoint.getX(),2) + ", " + round(chartEndPoint.getY(),2) + ")"); - // Prevent line from being redrawn - startPoint.setLocation(0.0, 0.0); - endPoint.setLocation(0.0, 0.0); - // Clear the last line from the line section: - redrawSelectedRegions(); - } - } - - @Override - public void mouseDragged(MouseEvent e) { - //This is responsible only for plotting section plots. - if(!(e.isAltDown() && e.isShiftDown())){ - return; - } - - if (isDragging == false){ - //If dragging is false we are new in drag mode, so we create new chart and XYdataset - lineSectionCollection = new XYSeriesCollection(); - lineSectionCollection.addSeries(new XYSeries(lineSectionPlotTitle + " " + getMatrixPlotPanel().getChart().getTitle().getText())); - - LinePlotData d = new LinePlotData(); - d.setData(lineSectionCollection); - LinePlot p = new LinePlot(lineSectionPlotTitle, d); - p.plot(false); - - startPoint.setLocation(e.getX(), e.getY()); - isDragging = true; - } - else{ - endPoint.setLocation(e.getX(), e.getY()); - if (!CoordinateTransformer.chartCoordinates(getMatrixPlotPanel(), startPoint.x, startPoint.y, chartStartPoint)){ - return; - } - if (!CoordinateTransformer.chartCoordinates(getMatrixPlotPanel(), endPoint.x, endPoint.y, chartEndPoint)){ - logger.fine("Endpoint must be within chart area"); - return; - } - - SectionPlotData.calculateSectionPlotData(data, chartStartPoint, chartEndPoint, lineSectionCollection, lineSectionPlotTitle + " " + getMatrixPlotPanel().getChart().getTitle().getText()); - - //The following lines are used if line is plotted in jfree - // XYLineAnnotation lineAnnotation = new XYLineAnnotation(chartStartPoint.getX(), chartStartPoint.getY(), chartEndPoint.getX(), chartEndPoint.getY(), new BasicStroke(1.5f), Color.BLUE); - // matrixPlotPanel.getChart().getXYPlot().addAnnotation(lineAnnotation); - //redraw selected regions the clear annotations (last line Annotations) - //Since the Information about selected regions is kept separately, we can use redraw. - // redrawSelectedRegions(); - //The following line is used if drawing within native javax (which is much faster in case of a huge dataset - Graphics2D g = (Graphics2D) frame.getGraphics(); - g.setColor( Color.blue ); - Insets insets = frame.getInsets(); - g.drawLine(startPoint.x + insets.left, startPoint.y + insets.top, endPoint.x + insets.left, endPoint.y + insets.top); - - } - } - - - - @Override - public void mouseMoved(MouseEvent e) { - } - - @Override - public void actionPerformed(ActionEvent e) { - - JMenuItem source = (JMenuItem)(e.getSource()); - for (PlugableUtil plugableUtil : plugableUtils) { - if(source.getText().equals(plugableUtil.getLabel())){ - try{ - ((PlugableUtilXYZ)plugableUtil).execute(this); - } - catch (ClassCastException cce) { - logger.severe(cce.getMessage()); - } catch (PluginExecutionException pe) { - logger.severe("unable to execute plugin " + ((PlugableUtilXYZ)plugableUtil).getLabel()); - logger.info(pe.getMessage()); - } - return; - } - } - - - if(source.getText() == originalRangeMenuLabel){ - setOriginalPlotRegion(); - } - - else if (source.getText() == tooltipsMenuLabel){ - showTooltip(); - source.setText(hideTooltipsMenuLabel); - } - - else if (source.getText() == clearMarkersMenuLabel){ - clearMarkers(); - } - - else if (source.getText() == hideTooltipsMenuLabel){ - hideTooltip(); - source.setText(tooltipsMenuLabel); - } - - else if (source.getText() == originalColorMapScaleMenuLabel){ - setOriginalColorMapScale(); - } - else if (source.getText() == adaptColorMapScaleMenuLabel){ - adaptColorMapScale(); - } - else if (source.getText() == grayScaleMenuLabel){ - isGrayScale = true; - isSingleColorScale = false; - setOriginalColorMapScale(); - } - else if (source.getText() == singleColorScaleMenuLabel){ - isGrayScale = false; - isSingleColorScale = true; - setOriginalColorMapScale(); - } - else if (source.getText() == temperatureColorScaleMenuLabel){ - isGrayScale = false; - isSingleColorScale = false; - setOriginalColorMapScale(); - } - else if(source.getText() == pauseMenuLabel){ - pauseConverting(); - source.setText(continueMenuLabel); - } - else if(source.getText() == continueMenuLabel){ - continueConverting(); - source.setText(pauseMenuLabel); - } - else if(source.getText() == reloadDataMenulabel){ - reloadData(); - } - else if(source.getText() == detachMenuLabel){ - // Detach plot into own frame - JFreeMatrixPlot p = new JFreeMatrixPlot(this.title, data); - p.adaptColorMapScale(); - p.plot(false); - } - else if(source.getText() == analyzeMenuLabel){ - // Analyze image with ImageJ - new ImageJ(null, ImageJ.EMBEDDED); - - FloatProcessor fp = new FloatProcessor(data.getXSize(), data.getYSize(), data.getDataArray()); - ImagePlus imp = new ImagePlus(this.title, fp); - imp.show(); - } - } - - /** - * Pause the data conversion process - */ - private void pauseConverting(){ - for(EventActionListener listener: eventActionListeners){ - listener.performAction(EventActionListener.Actions.PAUSE); - } - } - - /** - * Continue the data conversion process - */ - private void continueConverting(){ - for(EventActionListener listener: eventActionListeners){ - listener.performAction(EventActionListener.Actions.CONTINUE); - } - } - - /** - * Reload data - */ - private void reloadData(){ - for(EventActionListener listener: eventActionListeners){ - listener.performAction(EventActionListener.Actions.RELOAD); - } - adaptColorMapScale(); - } - - - private void clearMarkers(){ - clearSelectedRegions(); - } - - /** - * Show Tooltips. This is not done per default since it makes the app slow for datasize >= 1M - */ - private void showTooltip(){ - //Tooltips are quit expensive - Thread t = new Thread( new Runnable(){ - public void run(){ - DecimalFormat dm = new DecimalFormat("0.##########"); - XYZToolTipGenerator xYZToolTipGenerator = new StandardXYZToolTipGenerator( - "{0}: ({1} / {2} / {3})", dm, dm, dm - ); - - matrixPlotPanel.getChart().getXYPlot().getRenderer().setBaseToolTipGenerator(xYZToolTipGenerator); - ((XYBlockRenderer)matrixPlotPanel.getChart().getXYPlot().getRenderer()).setBaseCreateEntities(true); - }}); - t.start(); - - } - - /** - * Clear Tooltips - */ - private void hideTooltip(){ - //Tooltips are quit expensive - ((XYBlockRenderer)matrixPlotPanel.getChart().getXYPlot().getRenderer()).setBaseToolTipGenerator(null); - ((XYBlockRenderer)matrixPlotPanel.getChart().getXYPlot().getRenderer()).setBaseCreateEntities(false); - - } - - private void setOriginalPlotRegion(boolean notify){ - // Make sure that notify is false, otherwise the registered axis changelistener will restore the - // LowerLeftChartCorner and upperRightChartCorner with the original values after the first call - // (e.g matrixPlotPanel.getChart().getXYPlot().getDomainAxis().setLowerBound...) - Range domainAxisRange = new Range(data.getMetadata().getMinX() - 0.5*data.getMetadata().getBinWidthX(), - data.getMetadata().getMaxX() + 0.5*data.getMetadata().getBinWidthX()); - Range rangeAxisRange = new Range(data.getMetadata().getMinY() - 0.5*data.getMetadata().getBinWidthY(), - data.getMetadata().getMaxY() + 0.5*data.getMetadata().getBinWidthY()); - //We set notify to false in the first call.. - matrixPlotPanel.getChart().getXYPlot().getDomainAxis().setRange(domainAxisRange, true, notify); - //...and true in the last - matrixPlotPanel.getChart().getXYPlot().getRangeAxis().setRange(rangeAxisRange, true, true); - } - - /** - * Set the region of the plot as specified in the data metadata - */ - private void setOriginalPlotRegion(){ - matrixPlotPanel.getChart().getXYPlot().getDomainAxis().setLowerBound(data.getMetadata().getMinX() - 0.5*data.getMetadata().getBinWidthX()); - matrixPlotPanel.getChart().getXYPlot().getDomainAxis().setUpperBound(data.getMetadata().getMaxX() + 0.5*data.getMetadata().getBinWidthX()); - matrixPlotPanel.getChart().getXYPlot().getRangeAxis().setLowerBound(data.getMetadata().getMinY() - 0.5*data.getMetadata().getBinWidthY()); - matrixPlotPanel.getChart().getXYPlot().getRangeAxis().setUpperBound(data.getMetadata().getMaxY() + 0.5*data.getMetadata().getBinWidthY()); - } - - /** - * Set the region of the plot according to the values of lowerLeftChartCorner and upperRightChartCorner - */ - private void setActualPlotRegion(){ - // Make sure that notify is false, otherwise the registered axis changelistener will restore the - // LowerLeftChartCorner and upperRightChartCorner with the original values after the first call - // (e.g matrixPlotPanel.getChart().getXYPlot().getDomainAxis().setLowerBound...) - Range domainAxisRange = new Range(lowerLeftChartCorner.getX().doubleValue(),upperRightChartCorner.getX().doubleValue()); - Range rangeAxisRange = new Range(lowerLeftChartCorner.getY().doubleValue(), upperRightChartCorner.getY().doubleValue()); - //We set notify to false in the first call.. - matrixPlotPanel.getChart().getXYPlot().getDomainAxis().setRange(domainAxisRange, true, false); - //...and true in the last - matrixPlotPanel.getChart().getXYPlot().getRangeAxis().setRange(rangeAxisRange, true, true); - - } - - /** - * Move the visible part of the plot in direction translationVector - * @param translationVector - */ - private void moverOverPlot(XYPoint translationVector){ - //lowerLeftChartCorner.setX(Math.max(lowerLeftChartCorner.getX().doubleValue() + translationVector.getX().doubleValue(), matrixPlotData.getXmin())); - lowerLeftChartCorner.setX(lowerLeftChartCorner.getX().doubleValue() + translationVector.getX().doubleValue()); - //lowerLeftChartCorner.setY(Math.max(lowerLeftChartCorner.getY().doubleValue() + translationVector.getY().doubleValue(), matrixPlotData.getYmin())); - lowerLeftChartCorner.setY(lowerLeftChartCorner.getY().doubleValue() + translationVector.getY().doubleValue()); - //upperRightChartCorner.setX(Math.min(upperRightChartCorner.getX().doubleValue() + translationVector.getX().doubleValue(), matrixPlotData.getXmax())); - upperRightChartCorner.setX(upperRightChartCorner.getX().doubleValue() + translationVector.getX().doubleValue()); - //upperRightChartCorner.setY(Math.min(upperRightChartCorner.getY().doubleValue() + translationVector.getY().doubleValue(), matrixPlotData.getYmax())); - upperRightChartCorner.setY(upperRightChartCorner.getY().doubleValue() + translationVector.getY().doubleValue()); - - setActualPlotRegion(); - } - - public void updateZRangeTextFields(){ - DecimalFormat df = new DecimalFormat("###.###"); - lowerBoundTextField.setText(df.format(zRange.getX())); - upperBoundTextField.setText(df.format(zRange.getY())); - - } - - /** - * Set lower and upper color scale value to min and max value of the underlying data - */ - private void setOriginalColorMapScale(){ - setScale(data.getMetadata().getMinValue(), data.getMetadata().getMaxValue()); - zRange.setX(data.getMetadata().getMinValue()); - zRange.setY(data.getMetadata().getMaxValue()); - updateZRangeTextFields(); - } - - /** - * Adapt the lower and upper color map scale to the min and max data values of the currently selected region - */ - public void adaptColorMapScale(){ - XYPoint zMinAndMax = new XYPoint(0.0,0.0); - XYPoint validLowerLeftChartCorner = new XYPoint(Math.max(lowerLeftChartCorner.getX(), data.getMetadata().getMinX() -0.5 *data.getMetadata().getBinWidthX()), - Math.max(lowerLeftChartCorner.getY(), data.getMetadata().getMinY()-0.5 *data.getMetadata().getBinWidthY())); - XYPoint validUpperRightChartCorner = new XYPoint(Math.min(upperRightChartCorner.getX(), data.getMetadata().getMaxX() + 0.5 *data.getMetadata().getBinWidthX()), - Math.min(upperRightChartCorner.getY(), data.getMetadata().getMaxY()+ 0.5 *data.getMetadata().getBinWidthY())); - - zMinAndMax = ExtremaFinder.getMinMaxValue(data, validLowerLeftChartCorner, validUpperRightChartCorner); - if(zMinAndMax.getY() > zMinAndMax.getX()){ - setScale(zMinAndMax.getX(),zMinAndMax.getY()); - zRange.setX(zMinAndMax.getX()); - zRange.setY(zMinAndMax.getY()); - updateZRangeTextFields(); - } - } - - /** - * Set the min and max of color map scale to scaleMin and scaleMax - */ - - private void setScale(double scaleMin, double scaleMax){ - - - PaintScale paintScaleForLegend; - PaintScale paintScaleForRenderer; - - paintScaleForLegend = new LookupPaintScale(scaleMin, scaleMax, Color.GRAY); - setPaintScaleColors(paintScaleForLegend, scaleMin, scaleMax); - //We need a second scale for rendering only, where the 'infinities' are in correct color - - paintScaleForRenderer = new LookupPaintScale(-Math.pow(2,Double.MAX_EXPONENT), Double.POSITIVE_INFINITY, Color.GRAY); - setPaintScaleColors(paintScaleForRenderer, scaleMin, scaleMax); - - //Don't know why the following line didn't work - //((PaintScaleLegend) matrixPlotPanel.getChart().getSubtitles().get(matrixPlotPanel.getChart().getSubtitles().size()-1)).setScale(gs); - - matrixPlotPanel.getChart().clearSubtitles(); - NumberAxis scaleAxis = new NumberAxis("Scale"); - PaintScaleLegend paintScaleLegend = new PaintScaleLegend(paintScaleForLegend, scaleAxis); - paintScaleLegend.setPadding(new RectangleInsets(5, 5, 5, 5)); - paintScaleLegend.setStripWidth(50); - paintScaleLegend.setPosition(RectangleEdge.RIGHT); - matrixPlotPanel.getChart().addSubtitle(paintScaleLegend); - paintScaleLegend.setBackgroundPaint(new Color(238,238,238)); - - addInfinityToPaintScale(paintScaleForRenderer, scaleMin, scaleMax); - ((XYBlockRenderer) matrixPlotPanel.getChart().getXYPlot().getRenderer()).setPaintScale(paintScaleForRenderer); - - } - - - /** - * Make the paint scale range from - to + infinity - * @param paintScale - * @param scaleMin - * @param scaleMax - */ - private void addInfinityToPaintScale(PaintScale paintScale, double scaleMin, double scaleMax){ - if(!(paintScale.getClass() == LookupPaintScale.class)){ - return; - } - - if (isGrayScale){ - ((LookupPaintScale) paintScale).add(Double.NEGATIVE_INFINITY, getGrayValue(scaleMin, scaleMin, scaleMax)); - ((LookupPaintScale) paintScale).add(Double.POSITIVE_INFINITY, getGrayValue(scaleMax, scaleMin, scaleMax)); - - } - - else{ - - if(isSingleColorScale){ - ((LookupPaintScale) paintScale).add(Double.NEGATIVE_INFINITY, new Color(255,255,255)); - ((LookupPaintScale) paintScale).add(Double.POSITIVE_INFINITY, new Color(0,0,0)); - } - else{ - ((LookupPaintScale) paintScale).add(Double.NEGATIVE_INFINITY, getColour(scaleMin, scaleMin, scaleMax)); - ((LookupPaintScale) paintScale).add(Double.POSITIVE_INFINITY, getColour(scaleMax, scaleMin, scaleMax)); - } - } - } - - /** - * Set the colors for the colored Paint Scale (either single color or temperature color) - * @param paintScale - * @param scaleMin - * @param scaleMax - */ - private void setPaintScaleColors(PaintScale paintScale, double scaleMin, double scaleMax){ - //Single color mapping (blue) - if (isGrayScale){ - for(int i = 0; i<256; i++){ - double value = scaleMin + (i/255.0)*(scaleMax - scaleMin); - ((LookupPaintScale) paintScale).add(value, getGrayValue(value, scaleMin, scaleMax)); - } - } - - else{ - if(isSingleColorScale){ - for(int i = 0; i<256; i++){ - double value = scaleMin + (i/255.0)*0.5*(scaleMax - scaleMin); - ((LookupPaintScale) paintScale).add(value, new Color(255-i,255-i,255)); - } - for(int i = 0; i<256; i++){ - double value = scaleMin + 0.5*(scaleMax - scaleMin) + (i/255.0)*0.5*(scaleMax - scaleMin); - ((LookupPaintScale) paintScale).add(value, new Color(0,0,255-i)); - } - } - else{ - //Hot-cold color mapping - for(int i = 0; i<256; i++){ - double value = scaleMin + (i/255.0)*(scaleMax - scaleMin); - ((LookupPaintScale) paintScale).add(value, getColour(value, scaleMin, scaleMax)); - } - } - } - } - - /** - * Get a gray value for a given value - * @param value the value (must be within the range specified by the - * lower and upper bounds for the scale). - * - * @return a gray scale color. - */ - public Color getGrayValue(double value, double vmin, double vmax) { - double v = Math.max(value, vmin); - v = Math.min(v, vmax); - int g = (int) ((v - vmin) / (vmax- vmin) * 255.0); - // FIXME: it probably makes sense to allocate an array of 256 Colors - // and lazily populate this array... - return new Color(g, g, g); - } - - - /** - * Get color for a given value - * @param v Value to get the color for - * @param vmin Lower end value mapped to the lower end of the color map - * @param vmax Upper end value mapped to the upper end of the color map - * @return Mapped color for the specified value - */ - private Color getColour(double v, double vmin, double vmax) - { - // Standard algorithm for hot-cold color gradient (copied from - // http://local.wasp.uwa.edu.au/~pbourke/texture_colour/colourramp/) - - //Init color to white - double r = 1.0; - double g = 1.0; - double b = 1.0; - - double dv; - - if (v < vmin) - v = vmin; - if (v > vmax) - v = vmax; - dv = vmax - vmin; - - if (v < (vmin + 0.25 * dv)) { - r = 0.0; - g = 4 * (v - vmin) / dv; - } else if (v < (vmin + 0.5 * dv)) { - r = 0.0; - b = 1 + 4 * (vmin + 0.25 * dv - v) / dv; - } else if (v < (vmin + 0.75 * dv)) { - r = 4 * (v - vmin - 0.5 * dv) / dv; - b = 0.0; - } else { - g = 1 + 4 * (vmin + 0.75 * dv - v) / dv; - b = 0.0; - } - - return new Color( new Double(255.0*r).intValue(), new Double(255.0*g).intValue(), new Double(255.0*b).intValue()); - } - - - /** - * Redraw selected regions - */ - public void redrawSelectedRegions(){ - clearSelectedRegions(); - drawSelectedRegions(); - } - - /** - * Clear selected regions - */ - private void clearSelectedRegions(){ - matrixPlotPanel.getChart().getXYPlot().clearAnnotations(); - } - - /** - * Draw selected regions - */ - private void drawSelectedRegions(){ - for (Region region : regions){ - double[] polygon = new double[2*region.getPointList().size()]; - int i = 0; - for (XYPoint xyPoint : region.getPointList()){ - polygon[i] = xyPoint.getX(); - i=i+1; - polygon[i] = xyPoint.getY(); - i=i+1; - } - XYPolygonAnnotation annotation = new XYPolygonAnnotation(polygon, null, null, new Color(0, 0, 255, 90)); - matrixPlotPanel.getChart().getXYPlot().addAnnotation(annotation); - } - - double crossSize = 10.0; - double scalefactor = (upperRightChartCorner.getY() - lowerLeftChartCorner.getY())/(matrixPlotPanel.getSize().getHeight() - (double)matrixPlotPanel.getInsets().top - (double)matrixPlotPanel.getInsets().bottom); - double magnificationY = (upperRightChartCorner.getY() - lowerLeftChartCorner.getY())/(data.getMetadata().getMaxY() - data.getMetadata().getMinY()); - double distanceFromCross = crossSize * scalefactor/magnificationY; - - - for (String key : interestingSpots.keySet()){ - CrossAnnotation cd = new CrossAnnotation(Color.RED); - XYAnnotation bestBid = new XYDrawableAnnotation(interestingSpots.get(key).getX(), interestingSpots.get(key).getY(), crossSize, crossSize, cd); - matrixPlotPanel.getChart().getXYPlot().addAnnotation(bestBid); - XYAnnotation textAnnotation = new XYTextAnnotation(key, interestingSpots.get(key).getX(), interestingSpots.get(key).getY() - distanceFromCross); - - matrixPlotPanel.getChart().getXYPlot().addAnnotation(textAnnotation); - } - - for (XYPoint anonymousSpot :anonymousInterstingSpots){ - CrossAnnotation cd = new CrossAnnotation(Color.RED); - XYAnnotation bestBid = new XYDrawableAnnotation(anonymousSpot.getX(), anonymousSpot.getY(), crossSize, crossSize, cd); - matrixPlotPanel.getChart().getXYPlot().addAnnotation(bestBid); - } - } - - /** - * Remove the region of the given point - * @param xyPoint - * @return - */ - public boolean removeSelectedRegion(XYPoint xyPoint){ - boolean isAtLeastOneFoundToBeDeleted = false; - for(int i=0;i getEventActionListeners() { - return eventActionListeners; - } - - public void setEventActionListeners( - List eventActionListeners) { - this.eventActionListeners = eventActionListeners; - } - - public JFreeMatrixPlotData getData() { - return data; - } - - public void setData(JFreeMatrixPlotData data) { - this.data = data; - } - - public void setMatrixPlotPanel(ChartPanel matrixPlotPanel) { - this.matrixPlotPanel = matrixPlotPanel; - } - - public HashMap getInterestingSpots() { - return interestingSpots; - } - - public void setInterestingSpots(HashMap interestingSpots) { - this.interestingSpots = interestingSpots; - } - public JPanel getjPanel() { - return this.jPanel; - } - public void setjPanel(JPanel jPanel) { - this.jPanel = jPanel; - } - - public ArrayList getRegions() { - return regions; - } - - public void setRegions(ArrayList regions) { - this.regions = regions; - } - - - -} - - - diff --git a/ch.psi.plot/tmp/xyz/JFreeMatrixPlotData.java b/ch.psi.plot/tmp/xyz/JFreeMatrixPlotData.java deleted file mode 100644 index f4e5792..0000000 --- a/ch.psi.plot/tmp/xyz/JFreeMatrixPlotData.java +++ /dev/null @@ -1,130 +0,0 @@ - -package ch.psi.plot.xyz; - -import org.jfree.data.xy.XYZDataset; - -import ch.psi.plot.PlotData; - -public interface JFreeMatrixPlotData extends PlotData{ - - public enum DataType {MATRIX, PIXEL}; - - /** - * Get data object - * @return - */ - public XYZDataset getData(); - - /** - * Get metadata related to the data - * @return - */ - public JFreeMatrixPlotMetadata getMetadata(); - - /** - * Set metadata related to the data - * @param metadata - */ - public void setMetadata(JFreeMatrixPlotMetadata metadata); - - /** - * Add data to data object - * @param x - * @param y - * @param z - */ - public void addData(Number x, Number y, Number z); - - /** - * Add data binned to data object (x and y positions are modified such that - * they lie in the middle of their respective bin) |--*--------| -> |-----*-----| - * @param x - * @param y - * @param z - */ - public void addDataBinned(Number x, Number y, Number z); - - /** - * Add data to data object, position in array (matrix) is independent of x, y value. - * @param i Corresponds to y position - * @param j Corresponds to x position - * @param x - * @param y - * @param z - */ - public void addData(int i, int j, Number x, Number y, Number z); - - /** - * Get value of coordinates x / y - * @param x - * @param y - * @return - */ - public double getValue(double x, double y); - - /** - * Get value of bin i, j (i row, j column, starting point is lower left - * @param i - * @param j - * @return - */ - public double getValue(int i, int j); - - /** - * Set value at position i/j (i row, j column) - * @param x - * @param y - * @param value - */ - public void setValue(int i, int j, double value); - - - /** - * Returns value X according to array position (i row, j column) - * @param x - * @param y - * @return - */ - public double getXValue(int i, int j); - - /** - * Returns the Y according to array position (i row, j column) - * @param x - * @param y - * @return - */ - public double getYValue(int i, int j); - - /** - * returns the X value of data - * @param x - * @return - */ - public double getXValueBinned(double x); - - /** - * returns the Y value of data - * @param y - * @return - */ - public double getYValueBinned(double y); - - /** - * Returns the bin number in which x lies - * @param x - * @return - */ - public int getXBin(double x); - - /** - * Returns the bin number in which y lies - * @param y - * @return - */ - public int getYBin(double y); - - - public double[] getDataArray(); - public int getXSize(); - public int getYSize(); -} diff --git a/ch.psi.plot/tmp/xyz/JFreeMatrixPlotMetadata.java b/ch.psi.plot/tmp/xyz/JFreeMatrixPlotMetadata.java deleted file mode 100644 index 7c57bf1..0000000 --- a/ch.psi.plot/tmp/xyz/JFreeMatrixPlotMetadata.java +++ /dev/null @@ -1,198 +0,0 @@ -package ch.psi.plot.xyz; - -/** - * Bean class to holding metadata for matrix plots - */ -public class JFreeMatrixPlotMetadata { - - private double minX; - private double maxX; - private int numberOfBinsX; - private double minY; - private double maxY; - private int numberOfBinsY; - private double minValue; - private double maxValue; - private String xAxisLabel = "X"; - private String yAxisLabel = "Y"; - - /** - * Get the minimum value of the x-axis - * @return - */ - public double getMinX() { - return minX; - } - - /** - * Set the minimum value of the x-axis - * @param minX - */ - public void setMinX(double minX) { - this.minX = minX; - } - - /** - * Get the maximum value of the x-axis - * @return - */ - public double getMaxX() { - return maxX; - } - - /** - * Set the maximum value of the x-axis - * @param maxX - */ - public void setMaxX(double maxX) { - this.maxX = maxX; - } - - /** - * Get the number of bins of the x-axis - * @return - */ - public int getNumberOfBinsX() { - return numberOfBinsX; - } - - /** - * Set the number of bins of the x-axis - * @param numberOfBinsX - */ - public void setNumberOfBinsX(int numberOfBinsX) { - this.numberOfBinsX = numberOfBinsX; - } - - /** - * Get the minimum value of the y-axis - * @return - */ - public double getMinY() { - return minY; - } - - /** - * Set the minimum value of the y-axis - * @param minY - */ - public void setMinY(double minY) { - this.minY = minY; - } - - /** - * Get the maximum value of the y-axis - * @return - */ - public double getMaxY() { - return maxY; - } - - /** - * Set the maximum value of the y-axis - * @param maxY - */ - public void setMaxY(double maxY) { - this.maxY = maxY; - } - - /** - * Get the number of bins of the y-axis - * @return - */ - public int getNumberOfBinsY() { - return numberOfBinsY; - } - - /** - * Set the number of bins of the y-axis - * @param numberOfBinsY - */ - public void setNumberOfBinsY(int numberOfBinsY) { - this.numberOfBinsY = numberOfBinsY; - } - - /** - * Get the minimum value of the value - * @return - */ - public double getMinValue() { - return minValue; - } - - /** - * Set the minimum value of the value - * @param minValue - */ - public void setMinValue(double minValue) { - this.minValue = minValue; - } - - /** - * Get the maximum value of the value - * @return - */ - public double getMaxValue() { - return maxValue; - } - - /** - * Set the maximum value of the value - * @param maxValue - */ - public void setMaxValue(double maxValue) { - this.maxValue = maxValue; - } - - /** - * Get the bin width of the x-axis - * maxX and minX values are the values in the middle of the first and last bin - * therefore numberofXBins is reduced by 1. - * @return - */ - public double getBinWidthX(){ - return (maxX - minX)/(double) (numberOfBinsX - 1); - } - - /** - * Get the bin width of the y-axis - * maxY and minY values are the values in the middle of the first and last bin - * therefore numberofYBins is reduced by 1. - * @return - */ - public double getBinWidthY(){ - return (maxY - minY)/(double) (numberOfBinsY - 1); - } - - /** - * Get the x-axis label - * @return - */ - public String getxAxisLabel() { - return xAxisLabel; - } - - /** - * Set the x-axis label - * @param xAxisLabel - */ - public void setxAxisLabel(String xAxisLabel) { - this.xAxisLabel = xAxisLabel; - } - - /** - * Get the y-axis label - * @return - */ - public String getyAxisLabel() { - return yAxisLabel; - } - - /** - * Set the y-axis label - * @param yAxisLabel - */ - public void setyAxisLabel(String yAxisLabel) { - this.yAxisLabel = yAxisLabel; - } -} diff --git a/ch.psi.plot/tmp/xyz/MatrixPlotData.java b/ch.psi.plot/tmp/xyz/MatrixPlotData.java deleted file mode 100644 index 48dc746..0000000 --- a/ch.psi.plot/tmp/xyz/MatrixPlotData.java +++ /dev/null @@ -1,230 +0,0 @@ -package ch.psi.plot.xyz; - -import java.util.Arrays; -import java.util.logging.Logger; - -import org.jfree.data.xy.DefaultXYZDataset; -import org.jfree.data.xy.XYZDataset; - -/** - * PlotData implementation optimized for matrix data. - * ... - */ -public class MatrixPlotData implements JFreeMatrixPlotData{ - - private static Logger logger = Logger.getLogger(MatrixPlotData.class.getName()); - - private int numberOfXBins; - private int numberOfYBins; - - private double[][] dataArray; - Boolean[] occupiedBin; - - private XYZDataset data; - private JFreeMatrixPlotMetadata metadata; - - - public MatrixPlotData(){ - this(new JFreeMatrixPlotMetadata()); - } - - - public MatrixPlotData(JFreeMatrixPlotMetadata metadata) { - - this.metadata = metadata; - - numberOfXBins = metadata.getNumberOfBinsX(); - numberOfYBins = metadata.getNumberOfBinsY(); - - int arraylength = numberOfXBins*numberOfYBins; - double[] xvalues = new double[arraylength]; - double[] yvalues = new double[arraylength]; - double[] zvalues = new double[arraylength]; - - Arrays.fill(xvalues, Double.NEGATIVE_INFINITY); - Arrays.fill(yvalues, Double.NEGATIVE_INFINITY); - Arrays.fill(zvalues, Double.NEGATIVE_INFINITY); - logger.fine("Number of X values: "+numberOfXBins+" Number of Y values: "+numberOfYBins+" Array size: "+arraylength); - - dataArray = new double[][] {xvalues, yvalues, zvalues}; - - occupiedBin = new Boolean[arraylength]; - Arrays.fill(occupiedBin, false); - - //Create the XYDataset (org.jfree), not to be confused with the ch.psi dataSet) - data = new DefaultXYZDataset(); - ((DefaultXYZDataset)data).addSeries("Series Name" , dataArray); - } - - @Override - public void addData(Number x, Number y, Number z) { - int xBin = getXBin(x.doubleValue()); - int yBin = getYBin(y.doubleValue()); - - //x Value is column, y value is row - dataArray[0][yBin * numberOfXBins + xBin] = x.doubleValue(); - dataArray[1][yBin * numberOfXBins + xBin] = y.doubleValue(); - dataArray[2][yBin * numberOfXBins + xBin] = z.doubleValue(); - } - - @Override - public void addDataBinned(Number x, Number y, Number z) { - int xBin = getXBin(x.doubleValue()); - int yBin = getYBin(y.doubleValue()); - - dataArray[0][yBin * numberOfXBins + xBin] = getXValueBinned(xBin, yBin); - dataArray[1][yBin * numberOfXBins + xBin] = getYValueBinned(xBin, yBin); - dataArray[2][yBin * numberOfXBins + xBin] = z.doubleValue(); - - if (occupiedBin[yBin * numberOfXBins + xBin]){ - logger.finest("Bin (" + xBin + " " + yBin + ") is allready filled" ); - } - else{ - occupiedBin[yBin * numberOfXBins + xBin] = true; - } - - } - - //Not part of interface - public double getXValueBinned(int i, int j){ - return metadata.getMinX() + i*metadata.getBinWidthX(); - } - - //Not part of interface - public double getYValueBinned(int i, int j){ - return metadata.getMinY() + j*metadata.getBinWidthY(); - } - - @Override - public void addData(int i, int j, Number x, Number y, Number z) { - //The array is filled 'horizontally' (row (=yAxis) kept constant, columns++ , - //then row++ etc) - - dataArray[0][i * numberOfXBins + j] = x.doubleValue(); - dataArray[1][i * numberOfXBins + j] = y.doubleValue(); - dataArray[2][i * numberOfXBins + j] = z.doubleValue(); - } - - - @Override - public XYZDataset getData() { - return data; - } - - @Override - public JFreeMatrixPlotMetadata getMetadata() { - return metadata; - } - - @Override - public void setMetadata(JFreeMatrixPlotMetadata metadata) { - this.metadata = metadata; - } - - @Override - public double getXValue(int i, int j){ - return dataArray[0][i * numberOfXBins + j]; - } - - @Override - public double getYValue(int i, int j){ - return dataArray[1][i * numberOfXBins + j]; - } - - @Override - public double getXValueBinned(double x){ - return metadata.getMinX() + getXBin(x)*metadata.getBinWidthX(); - } - - @Override - public double getYValueBinned(double y){ - return metadata.getMinY() + getYBin(y)*metadata.getBinWidthY(); - } - - - - @Override - public double getValue(double x, double y){ - int column = getXBin(x); - int row = getYBin(y); - //int column = (int)x; - //int row = (int)y; - return dataArray[2][row * numberOfXBins + column]; - } - - @Override - public double getValue(int i, int j) { - return dataArray[2][i * numberOfXBins + j]; - } - - /** - * The array is filled 'horizontally' (row kept constant, columns++ , - * then row++ etc. where row = i = yAxis and column = j = xAxis) - */ - @Override - public void setValue(int i, int j, double value) { - dataArray[2][i * numberOfXBins + j] = value; - } - - /** - * get the bin in which x lies - * maxX and minX values are the values in the middle of the first and last bin - * therefore we need to subtract 1/2 of binWidth - * @return - */ - @Override - public int getXBin(double x) { - return ((int) ((x - ( metadata.getMinX() - 0.5*metadata.getBinWidthX()))/metadata.getBinWidthX())); - } - - /** - * get the bin in which y lies - * maxY and minY values are the values in the middle of the first and last bin - * therefore we need to subtract 1/2 of binWidth - * @return - */ - @Override - public int getYBin(double y) { - return ((int) ((y - (metadata.getMinY() - 0.5*metadata.getBinWidthY()))/metadata.getBinWidthY())); - } - - - /* (non-Javadoc) - * @see ch.psi.plot.xyz.JFreeMatrixPlotData#getDataArray() - */ - @Override - public double[] getDataArray() { - return dataArray[2]; - } - - - /* (non-Javadoc) - * @see ch.psi.plot.xyz.JFreeMatrixPlotData#getXSize() - */ - @Override - public int getXSize() { - // TODO Auto-generated method stub - return numberOfXBins; - } - - - /* (non-Javadoc) - * @see ch.psi.plot.xyz.JFreeMatrixPlotData#getYSize() - */ - @Override - public int getYSize() { - // TODO Auto-generated method stub - return numberOfYBins; - } - - - public void clear(){ - Arrays.fill(dataArray[0], Double.NEGATIVE_INFINITY); - Arrays.fill(dataArray[1], Double.NEGATIVE_INFINITY); - Arrays.fill(dataArray[2], Double.NEGATIVE_INFINITY); - } - -} - - - diff --git a/ch.psi.plot/tmp/xyz/PixelPlotData.java b/ch.psi.plot/tmp/xyz/PixelPlotData.java deleted file mode 100644 index 2b2b7dd..0000000 --- a/ch.psi.plot/tmp/xyz/PixelPlotData.java +++ /dev/null @@ -1,216 +0,0 @@ -package ch.psi.plot.xyz; - -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.jfree.data.xy.MatrixSeries; -import org.jfree.data.xy.MatrixSeriesCollection; -import org.jfree.data.xy.XYZDataset; - -public class PixelPlotData implements JFreeMatrixPlotData { - - private static Logger logger = Logger.getLogger(PixelPlotData.class.getName()); - - private MatrixSeries matrixData; - private JFreeMatrixPlotMetadata metadata = null; - - /** - * Constructor using metadata - * @param metadata - */ - public PixelPlotData(JFreeMatrixPlotMetadata metadata){ - this.metadata = metadata; - matrixData = new MatrixSeries("Matrix Series Name", metadata.getNumberOfBinsY(), metadata.getNumberOfBinsX()); - matrixData.zeroAll(); - } - - - /** - * Constructor without metadata (no metadata available, default values are used) - */ - public PixelPlotData(){ - int defaultNumberOfXBins = 5; - int defaultNumberOfYBins = 5; - - this.metadata = new JFreeMatrixPlotMetadata(); - metadata.setMinX(0.0); - metadata.setMaxX(defaultNumberOfXBins - 1.0); - metadata.setMinY(0.0); - metadata.setMaxY(defaultNumberOfYBins - 1.0); - metadata.setMinValue(0.0); - metadata.setMaxValue(100.0); - metadata.setNumberOfBinsX(defaultNumberOfXBins); - metadata.setNumberOfBinsY(defaultNumberOfYBins); - matrixData = new MatrixSeries("Matrix Series Name", defaultNumberOfYBins, defaultNumberOfXBins); - matrixData.zeroAll(); - } - - /** - * If the matrix sized is exceeded, we need a way to enlarge the matrix - * @param numberOfXBins - * @param numberOfYBins - */ - public void rescaleMatrix(int rescaledNumberOfXBins, int rescaledNumberOfYBins){ - MatrixSeries newMatrixData = new MatrixSeries("Matrix Series Name", rescaledNumberOfYBins, rescaledNumberOfXBins); - //copy the data first - for (int k = 0; k < metadata.getNumberOfBinsY(); k++) { - for (int l = 0; l < metadata.getNumberOfBinsX(); l++) { - newMatrixData.update(k, l, matrixData.get(k, l)); - } - } - - this.metadata.setNumberOfBinsX(rescaledNumberOfXBins); - this.metadata.setNumberOfBinsY(rescaledNumberOfYBins); - this.metadata.setMaxX(rescaledNumberOfXBins - 1.0); - this.metadata.setMaxY(rescaledNumberOfYBins - 1.0); - - this.matrixData = newMatrixData; - } - - //The following convention holds: any function called with int assumes - //Matrix like access, i.e (0, 0) is in upper left corner. - //functions called with double assume cartesian like access. - //i.e (0, 0) is in lower left corner - - @Override - public void addData(Number x, Number y, Number z){ - //Remember that fillBin is called as column, row - int j = x.intValue(); - int i = y.intValue(); - - - try { - matrixData.update(i, j, z.doubleValue()); - } catch (IndexOutOfBoundsException e) { - logger.log(Level.INFO, "Index out of bound, pixel plot array is resized dynamically" ,e.getMessage()); - - int scaleFactor = 2; - int rescaledNumberOfXBins = metadata.getNumberOfBinsX(); - int rescaledNumberOfYBins = metadata.getNumberOfBinsY(); - - if(j >= metadata.getNumberOfBinsX()){ - rescaledNumberOfXBins = scaleFactor*metadata.getNumberOfBinsX(); - logger.log(Level.INFO, "X Size exceeded"); - } - - else if(i >= metadata.getNumberOfBinsY()){ - rescaledNumberOfYBins = scaleFactor*metadata.getNumberOfBinsY(); - logger.log(Level.INFO, "Y Size exceeded"); - - } - - rescaleMatrix(rescaledNumberOfXBins, rescaledNumberOfYBins); - throw new IndexOutOfBoundsException(); - } - - } - - @Override - public void addDataBinned(Number x, Number y, Number z) { - addData(x,y,z); - } - - @Override - public void addData(int i, int j, Number x, Number y, Number z) { - //x, y are discarded - //matrixData.update(i, j, z.doubleValue()); - addData(j, i, z); - } - - @Override - public XYZDataset getData() { - return new MatrixSeriesCollection(matrixData); - } - - @Override - public JFreeMatrixPlotMetadata getMetadata() { - return metadata; - } - - @Override - public double getXValue(int i, int j) { - //Remember that x is column and y is row - return (double) j; - } - - @Override - public double getYValue(int i, int j) { - //Remember that x is column and y is row - return (double) i; - } - - @Override - public double getValue(double x, double y) { - //Remember that x is column and y is row - return matrixData.get((int) y, (int) x); - } - - @Override - public double getValue(int i, int j) { - //called with ints we assume matrix like access - return matrixData.get(i, j); - } - - @Override - public void setValue(int i, int j, double value) { - matrixData.update(i, j, value); - } - - @Override - public int getXBin(double x) { - return (int) x; - } - - @Override - public int getYBin(double y) { - return (int) y; - } - - @Override - public void setMetadata(JFreeMatrixPlotMetadata metadata) { - this.metadata = metadata; - } - - @Override - public double getXValueBinned(double x) { - return (double) ((int)x); - } - - @Override - public double getYValueBinned(double y) { - return (double) ((int)y); - } - - - /* (non-Javadoc) - * @see ch.psi.plot.xyz.JFreeMatrixPlotData#getDataArray() - */ - @Override - public double[] getDataArray() { - // TODO Auto-generated method stub - return null; - } - - - /* (non-Javadoc) - * @see ch.psi.plot.xyz.JFreeMatrixPlotData#getXSize() - */ - @Override - public int getXSize() { - // TODO Auto-generated method stub - return 0; - } - - - /* (non-Javadoc) - * @see ch.psi.plot.xyz.JFreeMatrixPlotData#getYSize() - */ - @Override - public int getYSize() { - // TODO Auto-generated method stub - return 0; - } - - - -} diff --git a/ch.psi.plot/tmp/xyz/Region.java b/ch.psi.plot/tmp/xyz/Region.java deleted file mode 100644 index 1dedd27..0000000 --- a/ch.psi.plot/tmp/xyz/Region.java +++ /dev/null @@ -1,109 +0,0 @@ -package ch.psi.plot.xyz; - -import java.util.ArrayList; - -import ch.psi.plot.util.XYPoint; - -/** - * Object describing a region inside a 2D matrix plot - */ -public class Region{ - - private ArrayList pointList = new ArrayList(); // List of points - - /** - * Check if point is inside the Region/Polygon - * Use of a implementation of Point in Polygon algorithm (Ray Casting). This algorithm only works for simple - * polygons (no line intersection) - * @param xyPoint - * @return - */ - public boolean isInside(XYPoint xyPoint){ - int numberOfFoundYValues = 0; - - // We init the before Point with the first polygon point, so nothing (wrong) will happen in the first loop - XYPoint xyPolygonVertexBefore = new XYPoint(pointList.get(0).getX(), pointList.get(0).getY()); - XYPoint xyPolygonVertex = new XYPoint(0.0, 0.0); - for (int i=1; i< pointList.size(); i++){ - xyPolygonVertex.setX(pointList.get(i).getX()); - xyPolygonVertex.setY(pointList.get(i).getY()); - if (isInInterval(xyPolygonVertex.getX(), xyPolygonVertexBefore.getX(), xyPoint.getX())){ - //FoundYValues.add(new Double(calculateYValue(xyPolygonVertexBefore, xyPolygonVertex, xyPoint.getX()))); - if(calculateYValue(xyPolygonVertexBefore, xyPolygonVertex, xyPoint.getX()) < xyPoint.getY()){ - numberOfFoundYValues++; - } - } - xyPolygonVertexBefore.setX(xyPolygonVertex.getX()); xyPolygonVertexBefore.setY(xyPolygonVertex.getY()); - } - //Don't forget to close the polygon (check the last closing line). - xyPolygonVertex.setX(pointList.get(0).getX()); - xyPolygonVertex.setY(pointList.get(0).getY()); - //PolygonVertexBefore contains the last element in list. - if (isInInterval(xyPolygonVertex.getX(), xyPolygonVertexBefore.getX(), xyPoint.getX())){ - if(calculateYValue(xyPolygonVertexBefore, xyPolygonVertex, xyPoint.getX()) < xyPoint.getY()){ - numberOfFoundYValues++; - } - } - - //Odd number of found yvalues indicates that point lays outside of polygon - if(numberOfFoundYValues % 2 == 0){ - return false; - } - else{ - return true; - } - } - - /** - * Get the point list of the region/polygon - * @return - */ - public ArrayList getPointList() { - return pointList; - } - - /** - * Set the point list of the region/polygon - * @param pointList - */ - public void setPointList(ArrayList pointList) { - this.pointList = pointList; - } - - /** - * Check whether x is within the interval of x1 and x2 - * @param x1 - * @param x2 - * @param x - * @return - */ - private boolean isInInterval(double x1, double x2, double x){ - //In case x1 > x2 we interchange them with min, max - if (x > Math.min(x1, x2) && x < Math.max(x1,x2)){ - return true; - } - else{ - return false; - } - } - - /** - * Calculate y value - * @param xyStartPoint - * @param xyEndPoint - * @param x - * @return - */ - private double calculateYValue(XYPoint xyStartPoint, XYPoint xyEndPoint, double x){ - //This is just for security sake, ask first if x is inInterval before calling - if (!isInInterval(xyStartPoint.getX(), xyEndPoint.getX(), x)){ - return 0.0; - } - else{ - //Evaluate y= a*(x - x_start) + y_start at the point x - //Note that delta x cannot be zero since in that case x cannot be in interval - double a = (xyEndPoint.getY() - xyStartPoint.getY())/(xyEndPoint.getX() - xyStartPoint.getX()); - return a*(x- xyStartPoint.getX()) + xyStartPoint.getY(); - } - } -} diff --git a/ch.psi.plot/tmp/xyz/SectionPlotData.java b/ch.psi.plot/tmp/xyz/SectionPlotData.java deleted file mode 100644 index 0ff7929..0000000 --- a/ch.psi.plot/tmp/xyz/SectionPlotData.java +++ /dev/null @@ -1,75 +0,0 @@ -package ch.psi.plot.xyz; - -import org.jfree.data.xy.XYSeriesCollection; - -import ch.psi.plot.util.XYPoint; - -public class SectionPlotData { - - /** - * Calculates the line section plot data for a xyz plot (the line is typically drawn with mouse) - * @param plotData - * @param startPoint - * @param endPoint - * @param lineSectionCollection - * @param lineSectionPlotLabel - */ - public static void calculateSectionPlotData(JFreeMatrixPlotData plotData, XYPoint startPoint, XYPoint endPoint, XYSeriesCollection lineSectionCollection, String lineSectionPlotLabel){ - - lineSectionCollection.getSeries(lineSectionPlotLabel).clear(); - XYPoint difference = new XYPoint(endPoint.getX() - startPoint.getX(), endPoint.getY() - startPoint.getY()); - - double angleWithHorizontal; - double slope; - - if(difference.getX() == 0.0){ - slope = Double.MAX_VALUE; - angleWithHorizontal = Math.PI/2.0; - } - else{ - slope = difference.getY()/difference.getX(); - angleWithHorizontal = Math.atan(slope); - } - double x = startPoint.getX(); - double deltax; - double y = startPoint.getY(); - double deltay; - double z; - double lineSegmentlength; - - if((angleWithHorizontal >= -Math.PI/4.0 ) && (angleWithHorizontal <= Math.PI/4.0)){ - //Be aware of signum of delta x (can be negative) - deltax = Math.signum(difference.getX())*plotData.getMetadata().getBinWidthX(); - //Cover both cases (deltax > 0 and deltax < 0) - while (Math.signum(difference.getX())*(endPoint.getX() - x) >= 0.0){ - //z value at the line position - z = plotData.getValue(x, y); - lineSegmentlength = Math.sqrt(Math.pow(x-startPoint.getX(),2.0) + Math.pow(y-startPoint.getY(),2.0)); - lineSectionCollection.getSeries(lineSectionPlotLabel).add(lineSegmentlength, z); - //y value of the Line - y = y + slope*deltax; - //update x value - x = x + deltax; - } - } - else{ - //If the slope is steeper than +- 45 degrees, we choose y Axis as independent variable, in order not to miss points - if(slope == 0.0){ - //We should never end here, just for security's sake (if slope = 0 were in x section) - } - else{ - slope = 1.0/slope; - } - //Be aware of signum of delta y (can be negative) - deltay = Math.signum(difference.getY())*plotData.getMetadata().getBinWidthY(); - while (Math.signum(difference.getY())*(endPoint.getY() - y) >= 0.0){ - z = plotData.getValue(x, y); - lineSegmentlength = Math.sqrt(Math.pow(x-startPoint.getX(),2.0) + Math.pow(y-startPoint.getY(),2.0)); - lineSectionCollection.getSeries(lineSectionPlotLabel).add(lineSegmentlength, z); - x = x + slope*deltay; - y = y + deltay; - } - } - } - -} diff --git a/ch.psi.plot/tmp/xyz/StaticMatrixPlotter.java b/ch.psi.plot/tmp/xyz/StaticMatrixPlotter.java deleted file mode 100644 index 20da2ab..0000000 --- a/ch.psi.plot/tmp/xyz/StaticMatrixPlotter.java +++ /dev/null @@ -1,55 +0,0 @@ -package ch.psi.plot.xyz; - -import ch.psi.plot.EventActionListener; -import ch.psi.plot.xyz.JFreeMatrixPlot; -import ch.psi.plot.xyz.JFreeMatrixPlotMetadata; -import ch.psi.plot.xyz.MatrixPlotData; - -public class StaticMatrixPlotter { - - public static void convert(double[][] data, MatrixPlotData matrixPlotData){ - for (int i = 0; i < data.length; i++) { - for (int j = 0; j < data[0].length; j++) { - matrixPlotData.addData(matrixPlotData.getXValueBinned(i, j), matrixPlotData.getYValueBinned(i, j), data[i][j]); - } - } - } - - public static void plot(String name, double minX, double maxX, double minY, double maxY, double minZ, double maxZ, final double[][] data){ - JFreeMatrixPlotMetadata md = new JFreeMatrixPlotMetadata(); - md.setNumberOfBinsX(data.length); - md.setNumberOfBinsY(data[0].length); - md.setMinX(minX); - md.setMaxX(maxX); - md.setMinY(minY); - md.setMaxY(maxY); - md.setMinValue(minZ); - md.setMaxValue(maxZ); - - final MatrixPlotData matrixPlotData = new MatrixPlotData(md); - - convert(data, matrixPlotData); - JFreeMatrixPlot plot = new JFreeMatrixPlot(name, matrixPlotData); - plot.plot(); - plot.adaptColorMapScale(); - - class LocalEventActionListener implements EventActionListener{ - @Override - public void performAction(Actions action) { - convert(data, matrixPlotData); - } - } - - plot.addEventActionListener(new LocalEventActionListener()); - - } - - public static void plot(String name, double[][] data){ - plot(name, 0.0, (double)data.length, 0.0, (double)data[0].length, 0.0, 100.0, data ); - } - - public static void plot(double[][] data){ - plot("test matrix plot", 0.0, data.length, 0.0, data[0].length, 0.0, 100.0, data ); - } - -} diff --git a/ch.psi.plot/tmp/xyz/StaticMatrixPlotterTest.java b/ch.psi.plot/tmp/xyz/StaticMatrixPlotterTest.java deleted file mode 100644 index 5fad096..0000000 --- a/ch.psi.plot/tmp/xyz/StaticMatrixPlotterTest.java +++ /dev/null @@ -1,39 +0,0 @@ -package ch.psi.plot.xyz; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - - - -public class StaticMatrixPlotterTest { - @Before - public void setUp() throws Exception { - } - - @After - public void tearDown() throws Exception { - } - - - @Test - public void testMatrixPlotStatic(){ - - int ni = 11; - int nj = 19; - double[][] data = new double[ni][nj]; - for (int i = 0; i < ni; i++) { - for (int j = 0; j < nj; j++) { - data[i][j] = i*j; - } - } - StaticMatrixPlotter.plot("test matrix plot", data); - try { - Thread.sleep(100000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - } - -} diff --git a/ch.psi.plot/tmp/xyz/SurfacePlot.java b/ch.psi.plot/tmp/xyz/SurfacePlot.java deleted file mode 100644 index e39a09f..0000000 --- a/ch.psi.plot/tmp/xyz/SurfacePlot.java +++ /dev/null @@ -1,122 +0,0 @@ -package ch.psi.plot.xyz; - -import java.util.List; - -import javax.swing.JPanel; -import javax.swing.WindowConstants; - -import org.jfree.ui.RefineryUtilities; - -import ch.psi.plot.EventActionListener; -import ch.psi.plot.Plot; -import jhplot.HPlot3D; - -public class SurfacePlot implements Plot { - - private HPlot3D hPlot3D; - private final int frameHeight = 500; - private final int frameWidth = 1200; - - private List datalist; - private String title; - - public SurfacePlot(String title, List datalist){ - this.datalist = datalist; - } - - /** - * Setup of the surface plot(s) - */ - public void setUpFrame(boolean terminateOnExit){ - - hPlot3D = new HPlot3D(title, frameWidth, frameHeight, datalist.size(), 1); - - hPlot3D.visible(true); - - hPlot3D.setGTitle("Surface Plot"); - - if(terminateOnExit){ - hPlot3D.getFrame().setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); // Close application if frame is closed - } - - int histogramPosition = 1; - // Init the plots histograms and add them to the plot - for(SurfacePlotData data: datalist){ - hPlot3D.cd(histogramPosition, 1); - - hPlot3D.setLabelOffsetZ(5.0); - - hPlot3D.setNameX(data.getMetadata().getxAxisLabel()); - hPlot3D.setNameY(data.getMetadata().getyAxisLabel()); - hPlot3D.setNameZ(data.getMetadata().getzAxisLabel()); - - hPlot3D.draw(data.getData()); - hPlot3D.setScaling(data.getMetadata().getScaling()); - hPlot3D.setRotationAngle(data.getMetadata().getRotationAngle()); - hPlot3D.setElevationAngle(data.getMetadata().getElevationAngle()); - histogramPosition++; - } - - } - - @Override - public JPanel getPlotPanel(){ - hPlot3D.getCanvasPanel().setName(title); - return hPlot3D.getCanvasPanel(); - } - - @Override - public void plot(){ - plot(true); - } - - @Override - public void plot(boolean terminateOnExit) { - setUpFrame(terminateOnExit); - //We don't explicitly plot here, the plotting is triggered by the converter - //via calling update function of all registered classes that implement - //DataUpdateListener - - // Center the frame - RefineryUtilities.centerFrameOnScreen(hPlot3D.getFrame()); - } - - @Override - public void plot(boolean terminateOnExit, int x, int y){ - setUpFrame(terminateOnExit); - - // Set frame position - hPlot3D.getFrame().setLocation(x, y); - - } - - @Override - public void plot(boolean terminateOnExit, int x, int y, int width, int height){ - setUpFrame(terminateOnExit); - - // Set frame size and position - hPlot3D.getFrame().setSize(width, height); - hPlot3D.getFrame().setLocation(x, y); - - } - - @Override - public void update() { - // Update panels - for (int p = 1; p <= datalist.size(); p++) { // p is plot position - hPlot3D.cd(p, 1); - hPlot3D.updateData(); - } - } - - @Override - public void addEventActionListener(EventActionListener listener) { - // TODO Auto-generated method stub - } - - @Override - public void removeEventActionListener(EventActionListener listener) { - // TODO Auto-generated method stub - } - -} diff --git a/ch.psi.plot/tmp/xyz/SurfacePlotData.java b/ch.psi.plot/tmp/xyz/SurfacePlotData.java deleted file mode 100644 index 26a85ed..0000000 --- a/ch.psi.plot/tmp/xyz/SurfacePlotData.java +++ /dev/null @@ -1,87 +0,0 @@ -package ch.psi.plot.xyz; - -import ch.psi.plot.PlotData; -import jhplot.H2D; - -/** - * Class to hold Surface Plot specific data and metadata. - */ -public class SurfacePlotData implements PlotData { - - private H2D data; - private SurfacePlotMetadata metadata; - - /** - * Instantiate Surface Plot Data. All required parameters are parameters of the constructor. - * @param title - * @param binsX - * @param minX - * @param maxX - * @param binsY - * @param minY - * @param maxY - */ - public SurfacePlotData(String title, int binsX, double minX, double maxX, int binsY, double minY, double maxY){ - metadata = new SurfacePlotMetadata(); - data = new H2D(title, binsX, minX, maxX, binsY, minY, maxY); - } - - /** - * Add data to data object - * @param x - * @param y - * @param z - */ - public void addData(Number x, Number y, Number z) { - int xBin = data.findBinX(x.doubleValue()); - int yBin = data.findBinY(y.doubleValue()); - //Non additive mode - if (data.binEntries(xBin, yBin) == 0){ - data.fill(x.doubleValue(), y.doubleValue(), z.doubleValue()); - } - } - - /** - * Add data to data object, bin is not derived from x,y value - * @param i - * @param j - * @param x - * @param y - * @param z - */ - public void addData(int i, int j, Number x, Number y, Number z) { - //Non additive mode, skip x,y - double xj = ((double)j/(double)data.getBinsX()) * (data.getMaxX() - data.getMinX()); - double yi = ((double)i/(double)data.getBinsY()) * (data.getMaxY() - data.getMinY()); - int xBin = data.findBinX(xj); - int yBin = data.findBinY(yi); - - if (data.binEntries(xBin, yBin) == 0){ - data.fill(xj, yi, z.doubleValue()); - } - } - - /** - * Get SurfacePlot specific data - * @return - */ - public H2D getData() { - return data; - } - - /** - * Get metadata - * @return Metadata object - */ - public SurfacePlotMetadata getMetadata(){ - return(metadata); - } - - /** - * Set metadata - * @param metadata - */ - public void setMetadata(SurfacePlotMetadata metadata){ - this.metadata = metadata; - } -} diff --git a/ch.psi.plot/tmp/xyz/SurfacePlotMetadata.java b/ch.psi.plot/tmp/xyz/SurfacePlotMetadata.java deleted file mode 100644 index e6c06e1..0000000 --- a/ch.psi.plot/tmp/xyz/SurfacePlotMetadata.java +++ /dev/null @@ -1,176 +0,0 @@ -package ch.psi.plot.xyz; - -/** - * Bean to hold surface plot metadata - */ -public class SurfacePlotMetadata { - - private String xAxisLabel = ""; - private String yAxisLabel = ""; - private String zAxisLabel = ""; - - private int numberOfBinsX; - private double minValueX; - private double maxValueX; - - private int numberOfBinsY; - private double minValueY; - private double maxValueY; - - private double scaling = 15; // Default value - private double rotationAngle = 220; // Default value - private double elevationAngle = 20; // Default value - - public SurfacePlotMetadata(){ - } - - public SurfacePlotMetadata(String xAxisLabel, String yAxisLabel, String zAxisLabel){ - this.xAxisLabel = xAxisLabel; - this.yAxisLabel = yAxisLabel; - this.zAxisLabel = zAxisLabel; - } - - /** - * Get x-axis label - * @return Label x-axis - */ - public String getxAxisLabel() { - return xAxisLabel; - } - - public void setxAxisLabel(String xAxisLabel) { - this.xAxisLabel = xAxisLabel; - } - - /** - * Get y-axis label - * @return Label y-axis - */ - public String getyAxisLabel() { - return yAxisLabel; - } - - public void setyAxisLabel(String yAxisLabel) { - this.yAxisLabel = yAxisLabel; - } - - /** - * Get z-axis label - * @return Label z-axis - */ - public String getzAxisLabel() { - return zAxisLabel; - } - - public void setzAxisLabel(String zAxisLabel) { - this.zAxisLabel = zAxisLabel; - } - - /** - * Get scaling - * @return Scaling factor - */ - public double getScaling() { - return scaling; - } - - public void setScaling(double scaling) { - this.scaling = scaling; - } - - /** - * Get rotation angle - * @return Rotation angle - */ - public double getRotationAngle() { - return rotationAngle; - } - - public void setRotationAngle(double rotationAngle) { - this.rotationAngle = rotationAngle; - } - - /** - * Get elevation angle - * @return Elevation angle - */ - public double getElevationAngle() { - return elevationAngle; - } - - public void setElevationAngle(double elevationAngle) { - this.elevationAngle = elevationAngle; - } - - /** - * Get number of bins of the x-axis - * @return Number of bins of the x-axis - */ - public int getNumberOfBinsX() { - return numberOfBinsX; - } - - public void setNumberOfBinsX(int numberOfBinsX) { - this.numberOfBinsX = numberOfBinsX; - } - - /** - * Get lowest x-axis value - * @return - */ - public double getMinValueX() { - return minValueX; - } - - public void setMinValueX(double minValueX) { - this.minValueX = minValueX; - } - - /** - * Get highest x-axis value - * @return - */ - public double getMaxValueX() { - return maxValueX; - } - - public void setMaxValueX(double maxValueX) { - this.maxValueX = maxValueX; - } - - /** - * Get number of bins of the y-axis - * @return - */ - public int getNumberOfBinsY() { - return numberOfBinsY; - } - - public void setNumberOfBinsY(int numberOfBinsY) { - this.numberOfBinsY = numberOfBinsY; - } - - /** - * Get lowest number of the y-axis - * @return - */ - public double getMinValueY() { - return minValueY; - } - - public void setMinValueY(double minValueY) { - this.minValueY = minValueY; - } - - /** - * Get highest y-axis value - * @return - */ - public double getMaxValueY() { - return maxValueY; - } - - public void setMaxValueY(double maxValueY) { - this.maxValueY = maxValueY; - } -} diff --git a/ch.psi.plot/tmp/xyz/plugable/BaryCenter.java b/ch.psi.plot/tmp/xyz/plugable/BaryCenter.java deleted file mode 100644 index 0b8945f..0000000 --- a/ch.psi.plot/tmp/xyz/plugable/BaryCenter.java +++ /dev/null @@ -1,103 +0,0 @@ -package ch.psi.plot.xyz.plugable; - -import java.util.logging.Level; -import java.util.logging.Logger; - -import ch.psi.plot.util.XYPoint; -import ch.psi.plot.xyz.JFreeMatrixPlot; -import ch.psi.plot.xyz.JFreeMatrixPlotData; - -public class BaryCenter implements PlugableUtilXYZ{ - - private static Logger logger = Logger.getLogger(BaryCenter.class.getName()); - - /** - * Find the Barycenter of the passed matrix plot data - * @param plotData - * @param lowerLeft - * @param upperRight - * @return - */ - private XYPoint findBarycenter(JFreeMatrixPlotData plotData, XYPoint lowerLeft, XYPoint upperRight, boolean binned){ - XYPoint barycenter; - - double x; double y;double z; - x = lowerLeft.getX(); - y = lowerLeft.getY(); - - if (binned){ - try{ - x = plotData.getXValueBinned(x); - y = plotData.getYValueBinned(y); - } - catch(Exception e){ - logger.fine(e.getMessage() + " Start values couldn't be binned"); - } - } - - double barycenterX = 0.0; double barycenterY = 0.0; - double norm = 0.0; - - while(x < upperRight.getX()){ - while(y < upperRight.getY()){ - try{ - z = plotData.getValue(x, y); - barycenterX += z*x; - barycenterY += z*y; - norm += z; - } - catch(Exception e){ - logger.severe(e.getMessage()); - } - - y = y + plotData.getMetadata().getBinWidthY(); - } - y = lowerLeft.getY(); - x = x + plotData.getMetadata().getBinWidthX(); - } - - if(binned){ - try{ - barycenter = new XYPoint(plotData.getXValueBinned(barycenterX/norm), - plotData.getYValueBinned(barycenterY/norm)); - } - catch(Exception e){ - logger.log(Level.SEVERE, "Barycenter couldn't be binned", e); - //return unbinned version if binned failed - barycenter = new XYPoint(barycenterX/norm, barycenterY/norm); - } - } - else{ - barycenter = new XYPoint(barycenterX/norm, barycenterY/norm); - } - - return barycenter; - } - - /** - * Add marker to barycenter value - */ - @Override - public void execute(final JFreeMatrixPlot jFreeMatrixPlot) { - - Thread t = new Thread( new Runnable(){ - public void run(){ - - try { - XYPoint bc = findBarycenter(jFreeMatrixPlot.getData(), jFreeMatrixPlot.getLowerLeftChartCorner(), jFreeMatrixPlot.getUpperRightChartCorner(), true); - jFreeMatrixPlot.getInterestingSpots().put(getLabel(), bc); - jFreeMatrixPlot.redrawSelectedRegions(); - } catch (Exception e) { - logger.warning(e.getMessage()); - } - }}); - t.start(); - - } - - @Override - public String getLabel() { - return this.getClass().getSimpleName(); - } - -} diff --git a/ch.psi.plot/tmp/xyz/plugable/Filter.java b/ch.psi.plot/tmp/xyz/plugable/Filter.java deleted file mode 100644 index dda0b2f..0000000 --- a/ch.psi.plot/tmp/xyz/plugable/Filter.java +++ /dev/null @@ -1,41 +0,0 @@ -package ch.psi.plot.xyz.plugable; - -/** - * Abstract filter class - */ -public abstract class Filter { - - /** - * Get the filter data entry of filter row i and column j - * @param i Row of the filter - * @param j Column of the filter - * @return Filter entry - */ - public abstract double getDataEntry(int i, int j); - - /** - * Get the number of rows of the filter - * @return Number of rows - */ - public abstract int getNumberOfRows(); - - /** - * Get the number of columns of the filter - * @return Number of columns - */ - public abstract int getNumberOfColumns(); - - /** - * Get whether filter dimensions are odd or even - * @return True if either the number of rows or the number of columns is odd, False otherwise - */ - public boolean isDimensionOdd(){ - if( (getNumberOfRows() % 2 == 0) || (getNumberOfColumns() % 2 == 0)){ - return false; - } - else{ - return true; - } - } - -} diff --git a/ch.psi.plot/tmp/xyz/plugable/FilterTransformation.java b/ch.psi.plot/tmp/xyz/plugable/FilterTransformation.java deleted file mode 100644 index f41cfee..0000000 --- a/ch.psi.plot/tmp/xyz/plugable/FilterTransformation.java +++ /dev/null @@ -1,79 +0,0 @@ -package ch.psi.plot.xyz.plugable; - -import java.util.LinkedList; -import java.util.Queue; -import java.util.logging.Logger; - -import ch.psi.plot.xyz.JFreeMatrixPlotData; - -public class FilterTransformation { - - private static Logger logger = Logger.getLogger(FilterTransformation.class.getName()); - - /** - * Apply specified filter to the passed data object - * @param plotData - * @param filter - */ - public static void applyFilter(JFreeMatrixPlotData plotData, Filter filter){ - - int numberOfXBins = plotData.getMetadata().getNumberOfBinsX(); - int numberOfYBins = plotData.getMetadata().getNumberOfBinsY(); - - logger.fine("Number of X bins: "+ numberOfXBins); - logger.fine("Number of Y bins: "+ numberOfYBins); - - if(!filter.isDimensionOdd()){ - logger.severe("Dimension of Filter Matrix must be odd"); - return; - } - - //We need a queue to store the transformed values since we don't want the old values to - //be overwritten. (not before their not used anymore for a later row) - Queue queue = new LinkedList(); - int requiredQueueSize = (filter.getNumberOfRows() - 1)/2; - int rowEdges = requiredQueueSize; - int columnEdges = (filter.getNumberOfColumns() - 1)/2; - - for (int i = rowEdges; i < numberOfYBins - rowEdges; i++) { - double[] filteredPointsQueuing = new double[numberOfXBins - 2*columnEdges]; - for (int j = columnEdges; j < numberOfXBins - columnEdges; j++) { - double filteredPoint = 0.0; - for (int f = 0; f < filter.getNumberOfRows(); f++) { - for (int g = 0; g < filter.getNumberOfColumns(); g++) { - int positionOfFilterPointInMatrixRow = i - rowEdges + f; - int positionOfFilterPointInMatrixColumn = j - columnEdges + g; - //getValue is called (row, column) - filteredPoint += filter.getDataEntry(f, g) * plotData.getValue(positionOfFilterPointInMatrixRow, positionOfFilterPointInMatrixColumn ); - - } - }//filtered point is calculated - filteredPointsQueuing[j - columnEdges] = filteredPoint; - } - - queue.add(filteredPointsQueuing); - - if(queue.size() > requiredQueueSize){ - double[] filteredPointsPolled = new double[numberOfXBins - 2*columnEdges]; - filteredPointsPolled = queue.poll(); - //Write the polled data back - for (int j = columnEdges; j < numberOfXBins - columnEdges; j++) { - plotData.setValue(i - requiredQueueSize, j, filteredPointsPolled[j - columnEdges]); - } - } - } - - //empty stack if last line is reached - while(queue.size() > 0){ - double[] filteredPointsPolled = new double[numberOfXBins - 2*columnEdges]; - filteredPointsPolled = queue.poll(); - //Write the polled data back - for (int j = columnEdges; j < numberOfXBins - columnEdges; j++) { - //setZValue is called (column, row, value) - plotData.setValue(numberOfYBins - 1 - rowEdges - queue.size(), j, filteredPointsPolled[j - columnEdges]); - - } - } - } - -} diff --git a/ch.psi.plot/tmp/xyz/plugable/FourierTransformation.java b/ch.psi.plot/tmp/xyz/plugable/FourierTransformation.java deleted file mode 100644 index 8264f15..0000000 --- a/ch.psi.plot/tmp/xyz/plugable/FourierTransformation.java +++ /dev/null @@ -1,106 +0,0 @@ -package ch.psi.plot.xyz.plugable; - -import java.util.ArrayList; -import java.util.logging.Logger; - -import org.apache.commons.math.complex.Complex; -import org.apache.commons.math.transform.FastFourierTransformer; - -import ch.psi.plot.xy.plugable.FourierTransformer; -import ch.psi.plot.xyz.JFreeMatrixPlot; -import ch.psi.plot.xyz.JFreeMatrixPlotData; -import ch.psi.plot.xyz.JFreeMatrixPlotMetadata; -import ch.psi.plot.xyz.MatrixPlotData; - -public class FourierTransformation implements PlugableUtilXYZ{ - - private static Logger logger = Logger.getLogger(FourierTransformation.class.getName()); - - - /** - * Apply fourier transformation to the data and return a new data matrix - * TODO to be checked - * @param plotData - * @return - */ - private JFreeMatrixPlotData calculateFFT(JFreeMatrixPlotData plotData){ - - int powerOf2InputDataLengthX = FourierTransformer.getPreviousPowerOf2(plotData.getMetadata().getNumberOfBinsX()); - int powerOf2InputDataLengthY = FourierTransformer.getPreviousPowerOf2(plotData.getMetadata().getNumberOfBinsY()); - //Allocate input for FFT - Complex[][] inputData = new Complex[powerOf2InputDataLengthY][powerOf2InputDataLengthX]; - //define Input for FFT - for (int i = 0; i < powerOf2InputDataLengthY; i++) { - for (int j = 0; j < powerOf2InputDataLengthX; j++) { - //Imaginary part of InputData is zero - inputData[i][j] = new Complex(plotData.getValue(i, j), 0.0); - } - } - //Do 2D FFT - FastFourierTransformer fastFourierTransformer = new FastFourierTransformer(); - Complex[][] fourierTransformedData = (Complex[][]) fastFourierTransformer.mdfft(inputData,true); - - //calculate interval in fourier space - double fourierSpaceScaleFaktorX = (2*Math.PI)/(plotData.getMetadata().getBinWidthX()*powerOf2InputDataLengthX); - double fourierSpaceScaleFaktorY = (2*Math.PI)/(plotData.getMetadata().getBinWidthY()*powerOf2InputDataLengthY); - - //Now we know all metadata - - // New FourierPlotDataInstance - JFreeMatrixPlotMetadata metadata = new JFreeMatrixPlotMetadata(); - metadata.setMinX(0.0); - metadata.setMaxX(fourierSpaceScaleFaktorX*powerOf2InputDataLengthX); - metadata.setNumberOfBinsX(powerOf2InputDataLengthX); - metadata.setMinY(0.0); - metadata.setMaxY(fourierSpaceScaleFaktorY*powerOf2InputDataLengthY); - metadata.setNumberOfBinsY(powerOf2InputDataLengthY); - metadata.setMinValue(Double.NEGATIVE_INFINITY); - metadata.setMaxValue(Double.POSITIVE_INFINITY); - MatrixPlotData fourierPlotData = new MatrixPlotData(metadata); - - //Fill the data of the new instance with the fourier transform - ArrayList powerSpectrumValues = new ArrayList(powerOf2InputDataLengthX*powerOf2InputDataLengthY); - - for (int i = 0; i < powerOf2InputDataLengthY; i++) { - for (int j = 0; j < powerOf2InputDataLengthX; j++) { - double kx = fourierSpaceScaleFaktorX*j + fourierSpaceScaleFaktorX/2.0; - double ky = fourierSpaceScaleFaktorY*i + fourierSpaceScaleFaktorY/2.0; - //Only Power Spectrum - double powerSpectrumValue = fourierTransformedData[i][j].abs(); - //double imagPartValue = fourierTransformedData[i][j].getImaginary(); - //double realPartValue = fourierTransformedData[i][j].getReal(); - fourierPlotData.addData(kx,ky,powerSpectrumValue); - powerSpectrumValues.add(new Double(powerSpectrumValue)); - } - } - return fourierPlotData; - } - - /** - * Show Fourier transformation of the underlying data - */ - @Override - public void execute(final JFreeMatrixPlot jFreeMatrixPlot) { - Thread t = new Thread( new Runnable(){ - public void run(){ - try { - JFreeMatrixPlot plot = new JFreeMatrixPlot("Fourier Transformation", calculateFFT(jFreeMatrixPlot.getData())); - plot.adaptColorMapScale(); - plot.plot(false); - - } catch (Exception e) { - logger.warning(e.getMessage()); - } - - }}); - t.start(); - - - } - - @Override - public String getLabel() { - return this.getClass().getSimpleName(); - } - -} diff --git a/ch.psi.plot/tmp/xyz/plugable/GaussFilter.java b/ch.psi.plot/tmp/xyz/plugable/GaussFilter.java deleted file mode 100644 index 8c1ca39..0000000 --- a/ch.psi.plot/tmp/xyz/plugable/GaussFilter.java +++ /dev/null @@ -1,71 +0,0 @@ -package ch.psi.plot.xyz.plugable; - -import java.util.logging.Logger; - -import ch.psi.plot.xyz.JFreeMatrixPlot; - -public class GaussFilter implements PlugableUtilXYZ{ - - private static Logger logger = Logger.getLogger(GaussFilter.class.getName()); - - @Override - public void execute(final JFreeMatrixPlot jFreeMatrixPlot) { - - - Thread t = new Thread( new Runnable(){ - public void run(){ - - Class pluginClass = null; - - String classname = "ch.psi.plot.xyz.plugable.IntegratedXValues"; - try {//Load class according to its name - pluginClass = Class.forName(classname); - - } catch (ClassNotFoundException e) { - logger.warning("Class " + classname + " not found " + e.getMessage()); - } - - IntegratedXValues integratedXValues = null; - - try { - integratedXValues = (IntegratedXValues) pluginClass.newInstance(); - } catch (InstantiationException e) { - logger.warning("Unable to instantiate " + classname + " : " + e.getMessage()); - } catch (IllegalAccessException e) { - logger.warning("Unable to access " + classname + " : " + e.getMessage()); - } - - - try { - final int sizeMin = 3; - final double filteringRange = 0.02; - int n = (int) (filteringRange*jFreeMatrixPlot.getData().getMetadata().getNumberOfBinsY()); - int m = (int) (filteringRange*jFreeMatrixPlot.getData().getMetadata().getNumberOfBinsX()); - - int nOdd = n + (n+1) % 2; - int mOdd = m + (m+1) % 2; - - final int nFilter = Math.max(nOdd, sizeMin); - final int mFilter = Math.max(mOdd, sizeMin); - - - logger.info("Total Integral before smoothing: " + integratedXValues.integrate(jFreeMatrixPlot.getData(), jFreeMatrixPlot.getLowerLeftChartCorner(), jFreeMatrixPlot.getUpperRightChartCorner())); - FilterTransformation.applyFilter(jFreeMatrixPlot.getData(), new GaussFilterMatrix(nFilter, mFilter)); - logger.info("Total Integral after smoothing: " + integratedXValues.integrate(jFreeMatrixPlot.getData(), jFreeMatrixPlot.getLowerLeftChartCorner(), jFreeMatrixPlot.getUpperRightChartCorner())); - jFreeMatrixPlot.getMatrixPlotPanel().getChart().fireChartChanged(); - - } catch (Exception e) { - logger.warning(e.getMessage()); - } - - }}); - t.start(); - - } - - @Override - public String getLabel() { - return this.getClass().getSimpleName(); - } - -} diff --git a/ch.psi.plot/tmp/xyz/plugable/GaussFilterMatrix.java b/ch.psi.plot/tmp/xyz/plugable/GaussFilterMatrix.java deleted file mode 100644 index cd2809c..0000000 --- a/ch.psi.plot/tmp/xyz/plugable/GaussFilterMatrix.java +++ /dev/null @@ -1,61 +0,0 @@ -package ch.psi.plot.xyz.plugable; - -/** - * Gauss filter implementation 5x5 - */ -public class GaussFilterMatrix extends Filter { - - private int numberOfRows; - private int numberOfColumns; - private double[][] data; - private double weight = 0.0; - private double sigma = 1.0; - - - /** - * Create Gauss Filter - */ - public GaussFilterMatrix(int n, int m) { - - this.numberOfRows = n; - this.numberOfColumns = m; - - data = new double[numberOfRows][numberOfColumns]; - - sigma = (double) 2.0*Math.PI*Math.sqrt(n*n + m*m); - //The entry 0,0 is lower left edge! (not upper left edge) - //(doesn't matter for symmetric matrices) - - for (int i = 0; i < numberOfRows; i++) { - for (int j = 0; j < numberOfColumns; j++) { - data[i][j] = Math.exp(-Math.pow(1.0/sigma,2.0)* - (Math.pow((i-(numberOfRows-1)/2.0),2.0) + - Math.pow((j-(numberOfColumns-1)/2),2.0))); - weight += data[i][j]; - } - } - - for (int i = 0; i < numberOfRows; i++) { - for (int j = 0; j < numberOfColumns; j++) { - data[i][j] *= 1.0/weight; - } - } - - } - - @Override - public double getDataEntry(int i, int j) { - return data[i][j]; - } - - @Override - public int getNumberOfColumns() { - return numberOfColumns; - } - - @Override - public int getNumberOfRows() { - return numberOfRows; - } - -} diff --git a/ch.psi.plot/tmp/xyz/plugable/Gradient.java b/ch.psi.plot/tmp/xyz/plugable/Gradient.java deleted file mode 100644 index 49ed99f..0000000 --- a/ch.psi.plot/tmp/xyz/plugable/Gradient.java +++ /dev/null @@ -1,113 +0,0 @@ -package ch.psi.plot.xyz.plugable; - -import java.util.logging.Logger; - -import org.jfree.data.xy.VectorSeries; -import org.jfree.data.xy.VectorSeriesCollection; - -import ch.psi.plot.util.XYPoint; -import ch.psi.plot.xyz.JFreeMatrixPlot; -import ch.psi.plot.xyz.JFreeMatrixPlotData; - -public class Gradient implements PlugableUtilXYZ{ - - private static Logger logger = Logger.getLogger(Gradient.class.getName()); - - /** - * Calculates the normalized gradient field of the visible part of the scalar field - * @param plotData - * @param lowerLeftChartCorner - * @param upperRightChartCorner - * @return - */ - private VectorSeriesCollection calculateGradientField(JFreeMatrixPlotData plotData, XYPoint lowerLeftChartCorner, XYPoint upperRightChartCorner){ - double xBinWidth = plotData.getMetadata().getBinWidthX(); - double yBinWidth = plotData.getMetadata().getBinWidthY(); - - logger.fine("x-width: "+xBinWidth+" y-width: "+yBinWidth); - - VectorSeriesCollection gradientField = new VectorSeriesCollection(); - VectorSeries vectorSeries = new VectorSeries("gradient field of detector"); - gradientField.addSeries(vectorSeries); - //calculate gradient, except at the borders. - //the borders are either given by selection, or - if plot is still being updated, by the current XBin value - int selectedXminBin = plotData.getXBin(lowerLeftChartCorner.getX()); - int selectedYminBin = plotData.getYBin(lowerLeftChartCorner.getY()); - - int selectedXmaxBin = plotData.getXBin(upperRightChartCorner.getX()); - int selectedYmaxBin = plotData.getYBin(upperRightChartCorner.getY()); - - int numberOfSelectedXBins = selectedXmaxBin - selectedXminBin; - int numberOfSelectedYBins = selectedYmaxBin - selectedYminBin; - - logger.fine("no x bins: "+numberOfSelectedXBins+" no y bins: "+numberOfSelectedYBins); - - double[][] gradientXField = new double[numberOfSelectedYBins][numberOfSelectedXBins]; - double[][] gradientYField = new double[numberOfSelectedYBins][numberOfSelectedXBins]; - - double maxGradientNorm = 0.0; - - double binDiagonalLength = Math.sqrt(xBinWidth*xBinWidth + yBinWidth*yBinWidth); - //calculate gradient, except at the borders and beyond - for (int i = 1; i < numberOfSelectedYBins - 1; i++) { - for (int j = 1 ; j < numberOfSelectedXBins - 1; j++) { - //Remember that x Axis defines column (y Axis row) - //such that gradientX = d/d(column) and gradientY = d/ d(row) - gradientXField[i][j] = (plotData.getValue(i + selectedYminBin, j + selectedXminBin + 1) - - plotData.getValue(i + selectedYminBin, j + selectedXminBin - 1))/2*xBinWidth; - gradientYField[i][j] = (plotData.getValue(i + selectedYminBin + 1, j + selectedXminBin) - - plotData.getValue(i + selectedYminBin -1, j + selectedXminBin))/2*yBinWidth; - double gradientNorm = Math.sqrt(Math.pow(gradientXField[i][j], 2.0) + Math.pow(gradientYField[i][j], 2.0)); - maxGradientNorm = Math.max(maxGradientNorm, gradientNorm); - } - } - - double scaleFactor; - if (maxGradientNorm != 0.0){ - scaleFactor = 1.0/maxGradientNorm; - } - else{ - scaleFactor = 0.0; - } - - for (int i = 0; i < numberOfSelectedYBins - 1; i++) { - for (int j = 0; j < numberOfSelectedXBins - 1; j++) { - double scaledGradientX = binDiagonalLength * scaleFactor * gradientXField[i][j]; - double scaledGradientY = binDiagonalLength * scaleFactor * gradientYField[i][j]; - vectorSeries.add(plotData.getXValue(i + selectedYminBin, j + selectedXminBin), plotData.getYValue(i + selectedYminBin, j + selectedXminBin), scaledGradientX, scaledGradientY); - } - } - return gradientField; - } - - - - /** - * Show gradient field of the underlying data - */ - @Override - public void execute(final JFreeMatrixPlot jFreeMatrixPlot) { - Thread t = new Thread( new Runnable(){ - public void run(){ - - try { - GradientPlot plot = new GradientPlot("Gradient Field", - calculateGradientField(jFreeMatrixPlot.getData(), jFreeMatrixPlot.getLowerLeftChartCorner(), jFreeMatrixPlot.getUpperRightChartCorner()), - jFreeMatrixPlot.getLowerLeftChartCorner(), jFreeMatrixPlot.getUpperRightChartCorner()); - plot.pack(); - plot.setVisible(true); - } catch (Exception e) { - logger.warning(e.getMessage()); - } - - }}); - t.start(); - - } - - @Override - public String getLabel() { - return this.getClass().getSimpleName(); - } - -} diff --git a/ch.psi.plot/tmp/xyz/plugable/GradientPlot.java b/ch.psi.plot/tmp/xyz/plugable/GradientPlot.java deleted file mode 100644 index 9515d2d..0000000 --- a/ch.psi.plot/tmp/xyz/plugable/GradientPlot.java +++ /dev/null @@ -1,62 +0,0 @@ -package ch.psi.plot.xyz.plugable; - -import java.awt.Dimension; - -import javax.swing.JFrame; -import org.jfree.chart.ChartPanel; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.plot.XYPlot; -import org.jfree.chart.renderer.xy.VectorRenderer; -import org.jfree.data.xy.VectorSeriesCollection; - -import ch.psi.plot.util.XYPoint; - - -public class GradientPlot extends JFrame{ - - private static final long serialVersionUID = 1L; - - /** - * Constructor - * Creates a ChartPanel that plots the gradientField - * @param title - * @param gradientField - * @param lowerLeft - * @param upperRight - */ - public GradientPlot(String title, VectorSeriesCollection gradientField, XYPoint lowerLeft, XYPoint upperRight) { - super(title); - JFreeChart chart = createChart(gradientField, lowerLeft, upperRight); - ChartPanel chartPanel = new ChartPanel(chart); - chartPanel.setPreferredSize(new Dimension(500, 270)); - setContentPane(chartPanel); - } - - /** - * Creates a chart that plots the gradientField in a specified range (lowerleft and upperright rectangle) - * @param gradientField - * @param lowerLeft - * @param upperRight - * @return - */ - private JFreeChart createChart(VectorSeriesCollection gradientField, XYPoint lowerLeft, XYPoint upperRight) { - // create the chart... - - NumberAxis xAxis = new NumberAxis("X"); - xAxis.setLowerBound(lowerLeft.getX()); - xAxis.setUpperBound(upperRight.getX()); - - NumberAxis yAxis = new NumberAxis("Y"); - yAxis.setLowerBound(lowerLeft.getY()); - yAxis.setUpperBound(upperRight.getY()); - - VectorRenderer renderer = new VectorRenderer(); - XYPlot vectorPlot = new XYPlot(gradientField, xAxis, yAxis, renderer); - JFreeChart chart = new JFreeChart("Gradient Field", vectorPlot); - - return chart; - } - - -} diff --git a/ch.psi.plot/tmp/xyz/plugable/IntegratedXValues.java b/ch.psi.plot/tmp/xyz/plugable/IntegratedXValues.java deleted file mode 100644 index 3242f60..0000000 --- a/ch.psi.plot/tmp/xyz/plugable/IntegratedXValues.java +++ /dev/null @@ -1,133 +0,0 @@ -package ch.psi.plot.xyz.plugable; - -import java.util.logging.Logger; - -import org.jfree.data.xy.XYSeries; - -import ch.psi.plot.util.XYPoint; -import ch.psi.plot.xy.LinePlot; -import ch.psi.plot.xy.LinePlotData; -import ch.psi.plot.xyz.JFreeMatrixPlot; -import ch.psi.plot.xyz.JFreeMatrixPlotData; - -public class IntegratedXValues implements PlugableUtilXYZ{ - - private static Logger logger = Logger.getLogger(IntegratedXValues.class.getName()); - - - /** - * Creates line plot data for the integrated X axis of the passed matrix plot data - * @param plotData - * @param lowerLeft - * @param upperRight - * @return - */ - private LinePlotData integrateAlongXAxis(JFreeMatrixPlotData plotData, XYPoint lowerLeft, XYPoint upperRight, boolean binned){ - - LinePlotData data = new LinePlotData(); - XYSeries integratedValues = new XYSeries("Integrated X Values"); - data.getData().addSeries(integratedValues); - - - double x; double y;double z; - - x = lowerLeft.getX(); - y = lowerLeft.getY(); - - if (binned){ - try{ - x = plotData.getXValueBinned(x); - y = plotData.getYValueBinned(y); - } - catch(Exception e){ - logger.fine(e.getMessage() + " Start values couldn't be binned"); - } - } - - double sumXDirection = 0.0; - double area = plotData.getMetadata().getBinWidthX()*plotData.getMetadata().getBinWidthY(); - - while(y < upperRight.getY()){ - while(x < upperRight.getX()){ - try{ - z = plotData.getValue(x, y); - sumXDirection += z*area; - } - catch(Exception e){ - logger.severe(e.getMessage()); - } - x = x + plotData.getMetadata().getBinWidthX(); - } - - //if binned, then write the y value according to the stored value in MatrixPlotData - if(binned){ - try{ - integratedValues.add(plotData.getYValueBinned(y), sumXDirection); - } - catch(Exception e){ - logger.fine(e.getMessage() + " Integration couldn't be binned"); - //We use unbinned version if binned failed - integratedValues.add(y, sumXDirection); - } - } - else{//just use the calculated y value - integratedValues.add(y, sumXDirection); - } - - sumXDirection = 0.0; - x = lowerLeft.getX(); - y = y + plotData.getMetadata().getBinWidthY(); - } - - return data; - } - - /** - * Calculate integral of visible plot (by first integrating along X-Axis) - * @param plotData - * @param lowerLeft - * @param upperRight - * @return - */ - public double integrate(JFreeMatrixPlotData plotData, XYPoint lowerLeft, XYPoint upperRight){ - LinePlotData integratedValues = integrateAlongXAxis(plotData, lowerLeft,upperRight, true); - - double integratedValue = 0.0; - for (int i = 1; i < integratedValues.getData().getSeries(0).getItemCount() - 1; i++) { - integratedValue += integratedValues.getData().getSeries(0).getDataItem(i).getYValue(); - } - return integratedValue; - } - - - /** - * Show the integrated X Axis value of the current view in a line plot - */ - - @Override - public void execute(final JFreeMatrixPlot jFreeMatrixPlot) { - Thread t = new Thread( new Runnable(){ - public void run(){ - - try { - LinePlotData lpData = integrateAlongXAxis(jFreeMatrixPlot.getData(), jFreeMatrixPlot.getLowerLeftChartCorner(), jFreeMatrixPlot.getUpperRightChartCorner(), true); - LinePlot p = new LinePlot("Integrated Data" , lpData); - p.plot(false); - //logger.debug("total = " + JFreeMatrixPlotUtil.integrate(data, lowerLeftChartCorner, upperRightChartCorner)); - - } catch (Exception e) { - logger.warning(e.getMessage()); - } - - }}); - t.start(); - - } - - @Override - public String getLabel() { - return this.getClass().getSimpleName(); - } - - -} diff --git a/ch.psi.plot/tmp/xyz/plugable/IntegratedYValues.java b/ch.psi.plot/tmp/xyz/plugable/IntegratedYValues.java deleted file mode 100644 index 319f0f8..0000000 --- a/ch.psi.plot/tmp/xyz/plugable/IntegratedYValues.java +++ /dev/null @@ -1,127 +0,0 @@ -package ch.psi.plot.xyz.plugable; - -import java.util.logging.Logger; - -import org.jfree.data.xy.XYSeries; - -import ch.psi.plot.util.XYPoint; -import ch.psi.plot.xy.LinePlot; -import ch.psi.plot.xy.LinePlotData; -import ch.psi.plot.xyz.JFreeMatrixPlot; -import ch.psi.plot.xyz.JFreeMatrixPlotData; - -public class IntegratedYValues implements PlugableUtilXYZ{ - - private static Logger logger = Logger.getLogger(IntegratedYValues.class.getName()); - - - /** - * Creates line plot data for the integrated y axis of the passed matrix plot data - * @param plotData - * @param lowerLeft - * @param upperRight - * @return - */ - public static LinePlotData integrateAlongYAxis(JFreeMatrixPlotData plotData, XYPoint lowerLeft, XYPoint upperRight, boolean binned){ - - LinePlotData data = new LinePlotData(); - XYSeries integratedValues = new XYSeries("Integrated Y Values"); - data.getData().addSeries(integratedValues); - - double x; double y;double z; - x = lowerLeft.getX(); - y = lowerLeft.getY(); - - if (binned){ - try{ - x = plotData.getXValueBinned(x); - y = plotData.getYValueBinned(y); - } - catch(Exception e){ - logger.fine(e.getMessage() + " Start values couldn't be binned"); - } - } - - double sumYDirection = 0.0; - double area = plotData.getMetadata().getBinWidthX()*plotData.getMetadata().getBinWidthY(); - - while(x < upperRight.getX()){ - while(y < upperRight.getY()){ - try{ - z = plotData.getValue(x, y); - sumYDirection += z*area; - } - catch(Exception e){ - logger.severe(e.getMessage()); - } - y = y + plotData.getMetadata().getBinWidthY(); - } - - - //if binned, then write the y value according to the stored value in MatrixPlotData - if(binned){ - try{ - integratedValues.add(plotData.getXValueBinned(x), sumYDirection); - } - catch(Exception e){ - logger.severe(e.getMessage() + " Integration couldn't be binned"); - //We use unbinned version if binned failed - integratedValues.add(x, sumYDirection); - } - } - else{//just use the calculated y value - integratedValues.add(x, sumYDirection); - } - sumYDirection = 0.0; - y = lowerLeft.getY(); - x = x + plotData.getMetadata().getBinWidthX(); - } - return data; - } - - - /** - * Calculate integral of visible plot (by first integrating along Y-Axis) - * @param plotData - * @param lowerLeft - * @param upperRight - * @return - */ - public double integrate(JFreeMatrixPlotData plotData, XYPoint lowerLeft, XYPoint upperRight){ - LinePlotData integratedValues = integrateAlongYAxis(plotData, lowerLeft,upperRight, true); - - double integratedValue = 0.0; - for (int i = 1; i < integratedValues.getData().getSeries(0).getItemCount() - 1; i++) { - integratedValue += integratedValues.getData().getSeries(0).getDataItem(i).getYValue(); - } - return integratedValue; - } - - - /** - * Show the integrated X Axis value of the current view in a line plot - */ - - @Override - public void execute(final JFreeMatrixPlot jFreeMatrixPlot) { - Thread t = new Thread( new Runnable(){ - public void run(){ - try { - LinePlotData lpData = integrateAlongYAxis(jFreeMatrixPlot.getData(), jFreeMatrixPlot.getLowerLeftChartCorner(), jFreeMatrixPlot.getUpperRightChartCorner(), true); - LinePlot p = new LinePlot("Integrated Data" , lpData); - p.plot(false); - //logger.debug("total = " + JFreeMatrixPlotUtil.integrate(data, lowerLeftChartCorner, upperRightChartCorner)); - } catch (Exception e) { - logger.warning(e.getMessage()); - } - - }}); - t.start(); - - } - - @Override - public String getLabel() { - return this.getClass().getSimpleName(); - } -} diff --git a/ch.psi.plot/tmp/xyz/plugable/LaplaceFilter.java b/ch.psi.plot/tmp/xyz/plugable/LaplaceFilter.java deleted file mode 100644 index 27fcfbd..0000000 --- a/ch.psi.plot/tmp/xyz/plugable/LaplaceFilter.java +++ /dev/null @@ -1,86 +0,0 @@ -package ch.psi.plot.xyz.plugable; - -import java.util.logging.Logger; - -import ch.psi.plot.xyz.JFreeMatrixPlot; - -public class LaplaceFilter implements PlugableUtilXYZ{ - - private static Logger logger = Logger.getLogger(LaplaceFilter.class.getName()); - - private class LaplaceFilter3x3 extends Filter{ - - private final int numberOfRows = 3; - private final int numberOfColumns = 3; - private double[][] data = new double[numberOfRows][numberOfColumns]; - private double weight = 1.0/4.0; - - /** - * Create 3x3 Laplace Filter - */ - public LaplaceFilter3x3() { - super(); - //The entry 0,0 is lower left edge! (not upper right edge) - //(doesn't matter for symmetric matrices) - data[0][0] = 1.0; - data[0][1] = 2.0; - data[0][2] = 1.0; - - data[1][0] = 2.0; - data[1][1] = -12.0; - data[1][2] = 2.0; - - data[2][0] = 1.0; - data[2][1] = 2.0; - data[2][2] = 1.0; - - for (int i = 0; i < numberOfRows; i++) { - for (int j = 0; j < numberOfColumns; j++) { - data[i][j] *= weight; - } - } - - } - - @Override - public double getDataEntry(int i, int j) { - return data[i][j]; - } - - @Override - public int getNumberOfColumns() { - return numberOfColumns; - } - - @Override - public int getNumberOfRows() { - return numberOfRows; - } - } - - /** - * Apply a Laplace filter to the data - */ - @Override - public void execute(final JFreeMatrixPlot jFreeMatrixPlot) { - Thread t = new Thread( new Runnable(){ - public void run(){ - - try { - FilterTransformation.applyFilter(jFreeMatrixPlot.getData(), new LaplaceFilter3x3()); - jFreeMatrixPlot.getMatrixPlotPanel().getChart().fireChartChanged(); - - } catch (Exception e) { - logger.warning(e.getMessage()); - } - - }}); - t.start(); - } - - @Override - public String getLabel() { - return this.getClass().getSimpleName(); - } - -} diff --git a/ch.psi.plot/tmp/xyz/plugable/Max.java b/ch.psi.plot/tmp/xyz/plugable/Max.java deleted file mode 100644 index a8ed9b3..0000000 --- a/ch.psi.plot/tmp/xyz/plugable/Max.java +++ /dev/null @@ -1,39 +0,0 @@ -package ch.psi.plot.xyz.plugable; - -import java.util.logging.Logger; - -import ch.psi.plot.util.XYPoint; -import ch.psi.plot.xyz.ExtremaFinder; -import ch.psi.plot.xyz.JFreeMatrixPlot; - -public class Max implements PlugableUtilXYZ{ - - private static Logger logger = Logger.getLogger(Max.class.getName()); - - /** - * Add marker to maximum value - */ - @Override - public void execute(final JFreeMatrixPlot jFreeMatrixPlot) { - Thread t = new Thread( new Runnable(){ - public void run(){ - - try { - XYPoint max = ExtremaFinder.getMaximum(jFreeMatrixPlot.getData(), jFreeMatrixPlot.getLowerLeftChartCorner(), jFreeMatrixPlot.getUpperRightChartCorner()); - jFreeMatrixPlot.getInterestingSpots().put(getLabel(), max); - jFreeMatrixPlot.redrawSelectedRegions(); - } catch (Exception e) { - logger.warning(e.getMessage()); - } - - }}); - t.start(); - - } - - @Override - public String getLabel() { - return this.getClass().getSimpleName(); - } - -} diff --git a/ch.psi.plot/tmp/xyz/plugable/Median.java b/ch.psi.plot/tmp/xyz/plugable/Median.java deleted file mode 100644 index 2ccf000..0000000 --- a/ch.psi.plot/tmp/xyz/plugable/Median.java +++ /dev/null @@ -1,92 +0,0 @@ -package ch.psi.plot.xyz.plugable; - -import java.util.Arrays; -import java.util.logging.Level; -import java.util.logging.Logger; - -import ch.psi.plot.xyz.JFreeMatrixPlot; -import ch.psi.plot.xyz.JFreeMatrixPlotData; -import ch.psi.plot.xyz.JFreeMatrixPlotMetadata; -import ch.psi.plot.xyz.MatrixPlotData; -import ch.psi.plot.xyz.PixelPlotData; -import ch.psi.plot.xyz.plugable.PlugableUtilXYZ; - -public class Median implements PlugableUtilXYZ{ - - private static Logger logger = Logger.getLogger(Median.class.getName()); - - @Override - public void execute(final JFreeMatrixPlot jFreeMatrixPlot){ - - Thread t = new Thread( new Runnable(){ - public void run(){ - - try { - double medianValue; - int numberOfDataPoints = jFreeMatrixPlot.getData().getData().getItemCount(0); - - int medianIndex = numberOfDataPoints/2; - //List zValues = new ArrayList(); - double[] zValues = new double[numberOfDataPoints]; - for (int j = 0; j < numberOfDataPoints; j++) { - //zValues.add(new Double(jFreeMatrixPlot.getData().getData().getZValue(0, j))); - //very slow if used with pixel plots, maybe due to the modulo access - zValues[j] = jFreeMatrixPlot.getData().getData().getZValue(0, j); - //System.out.println(zValues[j]); - } - - Arrays.sort(zValues); - //medianValue = zValues.get(medianIndex); - medianValue = zValues[medianIndex]; - - JFreeMatrixPlotMetadata medianMetaData = jFreeMatrixPlot.getData().getMetadata(); - medianMetaData.setMinValue(0.0); - medianMetaData.setMaxValue(1.0); - - JFreeMatrixPlotData medianData = null; - - if(jFreeMatrixPlot.getData() instanceof MatrixPlotData){ - medianData = new MatrixPlotData(medianMetaData); - } - else if(jFreeMatrixPlot.getData() instanceof PixelPlotData){ - medianData = new PixelPlotData(medianMetaData); - } - - if(medianData == null){ - logger.warning("unable to determine data type (neither MatrixPlotData nor PixelPlotData"); - return; - } - - for (int k = 0; k < medianMetaData.getNumberOfBinsY(); k++) { - for (int i = 0; i < medianMetaData.getNumberOfBinsX(); i++) { - double x = jFreeMatrixPlot.getData().getXValue(k, i); - double y = jFreeMatrixPlot.getData().getYValue(k, i); - double z = 0.0; - if( jFreeMatrixPlot.getData().getValue(k, i) > medianValue){ - z = 1.0; - } - medianData.addData(x, y, z); - } - - } - - JFreeMatrixPlot plot = new JFreeMatrixPlot("Binary Median Plot", medianData); - plot.plot(false); - - logger.log(Level.INFO,"median value = " + medianValue); - } catch (Exception e) { - logger.warning(e.getMessage()); - } - - }}); - t.start(); - - - } - - @Override - public String getLabel() { - return this.getClass().getSimpleName(); - } - -} diff --git a/ch.psi.plot/tmp/xyz/plugable/Min.java b/ch.psi.plot/tmp/xyz/plugable/Min.java deleted file mode 100644 index 312bd84..0000000 --- a/ch.psi.plot/tmp/xyz/plugable/Min.java +++ /dev/null @@ -1,40 +0,0 @@ -package ch.psi.plot.xyz.plugable; - -import java.util.logging.Logger; - -import ch.psi.plot.util.XYPoint; -import ch.psi.plot.xyz.ExtremaFinder; -import ch.psi.plot.xyz.JFreeMatrixPlot; - -public class Min implements PlugableUtilXYZ{ - - private static Logger logger = Logger.getLogger(Min.class.getName()); - - /** - * Add marker to minimum value - */ - @Override - public void execute(final JFreeMatrixPlot jFreeMatrixPlot) { - Thread t = new Thread( new Runnable(){ - public void run(){ - - try { - XYPoint max = ExtremaFinder.getMinimum(jFreeMatrixPlot.getData(), jFreeMatrixPlot.getLowerLeftChartCorner(), jFreeMatrixPlot.getUpperRightChartCorner()); - jFreeMatrixPlot.getInterestingSpots().put(getLabel(), max); - jFreeMatrixPlot.redrawSelectedRegions(); - } catch (Exception e) { - logger.warning(e.getMessage()); - } - - }}); - t.start(); - - } - - @Override - public String getLabel() { - return this.getClass().getSimpleName(); - } - - -} diff --git a/ch.psi.plot/tmp/xyz/plugable/PlugableUtilXYZ.java b/ch.psi.plot/tmp/xyz/plugable/PlugableUtilXYZ.java deleted file mode 100644 index 68cb5bd..0000000 --- a/ch.psi.plot/tmp/xyz/plugable/PlugableUtilXYZ.java +++ /dev/null @@ -1,9 +0,0 @@ -package ch.psi.plot.xyz.plugable; - -import ch.psi.plot.util.PlugableUtil; -import ch.psi.plot.util.PluginExecutionException; -import ch.psi.plot.xyz.JFreeMatrixPlot; - -public interface PlugableUtilXYZ extends PlugableUtil{ - public void execute(JFreeMatrixPlot jFreeMatrixPlot) throws PluginExecutionException; -}