package data_plot; import java.awt.*; import java.awt.image.*; import java.awt.event.*; import java.io.*; import java.awt.datatransfer.*; import java.util.*; import ij.*; import ij.gui.*; import ij.process.*; import ij.util.*; import ij.text.*; import ij.plugin.filter.*; import ij.gui.*; import ij.measure.*; import ij.io.SaveDialog; /* DataPlotWindowExt is largely based on the PlotWindow class and extends * its functionality towards accepting ArrayList data input and allowing to * display arrow plots, logarithmic (log in x and/or y) plots, minor ticks * (decimal and logarithmic), change of the label font, draw dotted lines... * * @version 1.0; 22 June 2012 * * @author Philippe CARL * @author University of Strasbourg * @author philippe.carl@unistra.fr * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /** This class implements the Analyze>Plot Profile command. * @authors Michael Schmid and Wayne Rasband */ public class DataPlotWindow extends ImageWindow implements ActionListener, ClipboardOwner, MouseListener, MouseMotionListener, KeyListener, ImageListener, Runnable { /** Display points using a circle 5 pixels in diameter. */ public static final int CIRCLE = 0; /** Display points using an X-shaped mark. */ public static final int X = 1; /** Display points using an box-shaped mark. */ public static final int BOX = 3; /** Display points using an tiangular mark. */ public static final int TRIANGLE = 4; /** Display points using an cross-shaped mark. */ public static final int CROSS = 5; /** Connect points with solid lines. */ public static final int LINE = 2; private static final int WIDTH = 450; private static final int HEIGHT = 200; private static final String MIN = "pp.min"; private static final String MAX = "pp.max"; private static final String PLOT_WIDTH = "pp.width"; private static final String PLOT_HEIGHT = "pp.height"; private static final String OPTIONS = "pp.options"; private static final int SAVE_X_VALUES = 1; private static final int AUTO_CLOSE = 2; private static final int LIST_VALUES = 4; private static final int INTERPOLATE = 8; private static final int NO_GRID_LINES = 16; private Button list, save, copy, live; private Label coordinates; private static String defaultDirectory = null; private static int options; private int defaultDigits = -1; private int markSize = 5; private static DataPlot staticPlot; private DataPlot plot; private String blankLabel = " "; private ImagePlus srcImp; // the source image for live plotting private Thread bgThread; // thread for plotting (in the background) private boolean doUpdate; // tells the background thread to update /** Save x-values only. To set, use Edit/Options/ Profile Plot Options. */ public static boolean saveXValues; /** Automatically close window after saving values. To set, use Edit/Options/Profile Plot Options. */ public static boolean autoClose; /** The width of the plot in pixels. */ public static int plotWidth = WIDTH; /** The height of the plot in pixels. */ public static int plotHeight = HEIGHT; /** Display the XY coordinates in a separate window. To set, use Edit/Options/Profile Plot Options. */ public static boolean listValues; /** Interpolate line profiles. To set, use Edit/Options/Profile Plot Options. */ public static boolean interpolate; /** Add grid lines to plots */ public static boolean noGridLines; // static initializer static { options = Prefs.getInt(OPTIONS, SAVE_X_VALUES); saveXValues = (options&SAVE_X_VALUES)!=0; autoClose = (options&AUTO_CLOSE)!=0; listValues = (options&LIST_VALUES)!=0; plotWidth = Prefs.getInt(PLOT_WIDTH, WIDTH); plotHeight = Prefs.getInt(PLOT_HEIGHT, HEIGHT); interpolate = (options&INTERPOLATE)==0; // 0=true, 1=false noGridLines = (options&NO_GRID_LINES)!=0; } /** * @deprecated * replaced by the Plot class. */ public DataPlotWindow(String title, String xLabel, String yLabel, float[] xValues, float[] yValues) { super(createImage(title, xLabel, yLabel, xValues, yValues)); plot = staticPlot; } /** * @deprecated * replaced by the Plot class. */ public DataPlotWindow(String title, String xLabel, String yLabel, double[] xValues, double[] yValues) { this(title, xLabel, yLabel, Tools.toFloat(xValues), Tools.toFloat(yValues)); } /** Creates a DataPlotWindow from a Plot object. */ DataPlotWindow(DataPlot plot) { super(plot.getImagePlus()); this.plot = plot; draw(); //addComponentListener(this); } /** Called by the constructor to generate the image the plot will be drawn on. This is a static method because constructors cannot call instance methods. */ static ImagePlus createImage(String title, String xLabel, String yLabel, float[] xValues, float[] yValues) { staticPlot = new DataPlot(title, xLabel, yLabel, xValues, yValues); return new ImagePlus(title, staticPlot.getBlankProcessor()); } /** Sets the x-axis and y-axis range. */ public void setLimits(double xMin, double xMax, double yMin, double yMax) { plot.setLimits(xMin, xMax, yMin, yMax); } /** Adds a set of points to the plot or adds a curve if shape is set to LINE. * @param x the x-coodinates * @param y the y-coodinates * @param shape CIRCLE, X, BOX, TRIANGLE, CROSS or LINE */ public void addPoints(float[] x, float[] y, int shape) { plot.addPoints(x, y, shape); } /** Adds a set of points to the plot using double arrays. Must be called before the plot is displayed. */ public void addPoints(double[] x, double[] y, int shape) { addPoints(Tools.toFloat(x), Tools.toFloat(y), shape); } /** Adds error bars to the plot. */ public void addErrorBars(float[] errorBars) { plot.addErrorBars(errorBars); } /** Draws a label. */ public void addLabel(double x, double y, String label) { plot.addLabel(x, y, label); } /** Changes the drawing color. The frame and labels are always drawn in black. */ public void setColor(Color c) { plot.setColor(c); } /** Changes the line width. */ public void setLineWidth(int lineWidth) { plot.setLineWidth(lineWidth); } /** Changes the font. */ public void changeFont(Font font) { plot.changeFont(font); } /** Displays the plot. */ public void draw() { Panel buttons = new Panel(); int hgap = IJ.isMacOSX()?1:5; buttons.setLayout(new FlowLayout(FlowLayout.RIGHT,hgap,0)); list = new Button(" List "); list.addActionListener(this); buttons.add(list); save = new Button("Save..."); save.addActionListener(this); buttons.add(save); copy = new Button("Copy..."); copy.addActionListener(this); buttons.add(copy); if (plot!=null && plot.getSourceImageID()!=0) { live = new Button("Live"); live.addActionListener(this); buttons.add(live); } coordinates = new Label("X=12345678, Y=12345678"); coordinates.setFont(new Font("Monospaced", Font.PLAIN, 12)); coordinates.setBackground(new Color(220, 220, 220)); buttons.add(coordinates); add(buttons); plot.draw(); pack(); coordinates.setText(blankLabel); ImageProcessor ip = plot.getProcessor(); if ((ip instanceof ColorProcessor) && (imp.getProcessor() instanceof ByteProcessor)) imp.setProcessor(null, ip); else imp.updateAndDraw(); if (listValues) showList(); } int getDigits(double n1, double n2) { if (Math.round(n1)==n1 && Math.round(n2)==n2) return 0; else { n1 = Math.abs(n1); n2 = Math.abs(n2); double n = n10.0?n1:n2; double diff = Math.abs(n2-n1); if (diff>0.0 && diff1) head += sets==1?"X\tY\t":"X0\tY0\t"; else head += sets==1?"Y0\t":"Y0\t"; if (plot.errorBars!=null) head += "ERR\t"; for (int j = 1; j1) head += "X" + j + "\tY" + j + "\t"; else head += "Y" + j + "\t"; } return head; } /** creates the data that fills the showList() function values */ private String createData(){ int max = 0; /** find the longest x-value data set */ float[] column; for(int i = 0; imax?s:max; } /** stores the values that will be displayed*/ ArrayList displayed = new ArrayList(plot.storedData); boolean eb_test = false; /** includes error bars.*/ if (plot.errorBars !=null) displayed.add(2, plot.errorBars); StringBuffer sb = new StringBuffer(); String v; int n = displayed.size(); for (int i = 0; i2) { column = (float[])displayed.get(j); xdigits = getPrecision(column); v = idigits) digits = setDigits; boolean realValues = false; for (int i=0; imax) max=column.length; } ResultsTable rt = new ResultsTable(); for (int row=0; row