Skip to content

Commit

Permalink
2018.11.02 (1.52i24; Plot enhancements)
Browse files Browse the repository at this point in the history
  • Loading branch information
rasband committed Nov 2, 2018
1 parent e23b5ba commit 7f9ea90
Show file tree
Hide file tree
Showing 9 changed files with 334 additions and 201 deletions.
2 changes: 1 addition & 1 deletion ij/ImageJ.java
Expand Up @@ -79,7 +79,7 @@ public class ImageJ extends Frame implements ActionListener,

/** Plugins should call IJ.getVersion() or IJ.getFullVersion() to get the version string. */
public static final String VERSION = "1.52i";
public static final String BUILD = "21";
public static final String BUILD = "24";
public static Color backgroundColor = new Color(237,237,237);
/** SansSerif, 12-point, plain font. */
public static final Font SansSerif12 = new Font("SansSerif", Font.PLAIN, 12);
Expand Down
342 changes: 211 additions & 131 deletions ij/gui/Plot.java

Large diffs are not rendered by default.

85 changes: 62 additions & 23 deletions ij/gui/PlotContentsDialog.java
Expand Up @@ -14,15 +14,18 @@
import java.util.Vector;
import java.util.ArrayList;

/** This class implements the Plot Window's "Data>Add from Plot" and "More>Contents Style" dialogs */
/** This class implements the Plot Window's Data>"Add from Plot", "Add form Table", "Add Fit" and
* "More>Contents Style" dialogs
*/
public class PlotContentsDialog implements DialogListener {
/** Types of dialog (ERROR suppresses the dialog after an invalid call of a constructor) */
public final static int ERROR=-1, STYLE=0, ADD_FROM_PLOT=1, ADD_FROM_TABLE=2, ADD_FROM_ARRAYS=3, ADD_FIT=4;
/** Dialog headings for each dialogType >= 0 */
private static final String[] HEADINGS = new String[] {"Plot Contents Style", "Add From Plot", "Plot From Table", "Add Plot Data", "Add Fit"};
private Plot plot;
private int dialogType;
GenericDialog gd;
private Plot plot; // the plot we work on
private int dialogType; // determines what to do: ADD_FORM_PLOT, etc.
private double[] savedLimits; // previous plot range, for undo upon cancel
GenericDialog gd;
private int currentObjectIndex = -1;
private Choice objectChoice;
private Choice symbolChoice;
Expand Down Expand Up @@ -115,6 +118,7 @@ public void noErrorBars() {
/** Shows the dialog, with a given parent Frame (may be null) */
public void showDialog(Frame parent) {
if (dialogType == ERROR) return;
if (!creatingPlot) savedLimits = plot.getLimits();
plot.savePlotObjects();
String[] designations = plot.getPlotObjectDesignations();
if (dialogType == STYLE && designations.length==0) {
Expand Down Expand Up @@ -173,6 +177,8 @@ public void showDialog(Frame parent) {
columnChoice[i] = (Choice)(choices.get(choices.size()-1));
}
makeSourceColumns();
if (!creatingPlot)
suggestNewYColumn();
}
gd.addStringField("Color:", previousColor, 10);
gd.addStringField("Secondary (fill) color:", previousColor2, 10);
Expand Down Expand Up @@ -208,6 +214,7 @@ else if (dialogType == ADD_FIT)
}

gd.showDialog();

if (fittingThread != null) {
fittingThread.interrupt();
try {
Expand All @@ -220,6 +227,8 @@ else if (dialogType == ADD_FIT)
if (imp != null) imp.close();
} else {
plot.restorePlotObjects();
if (savedLimits != null)
plot.setLimits(savedLimits[0], savedLimits[1], savedLimits[2], savedLimits[3]);
plot.updateImage();
plot.killPlotObjectsSnapshot();
}
Expand Down Expand Up @@ -406,7 +415,10 @@ private void addObjectFromPlot() {
int plotIndex = plotChoice.getSelectedIndex();
int objectIndex = objectChoice.getSelectedIndex();
plot.restorePlotObjects();
if (savedLimits != null)
plot.setLimits(savedLimits);
currentObjectIndex = plot.addObjectFromPlot(allPlots[plotIndex], objectIndex); //no updateImage; will be done later
plot.fitRangeToLastPlotObject();
setDialogStyleFields(currentObjectIndex);
previousPlot = allPlots[plotIndex];
previousPlotObjectIndex = objectIndex;
Expand Down Expand Up @@ -473,7 +485,49 @@ private void makeSourceColumns() {
/** For "Add from Table" and "Add from Arrays" adds item to the plot according to the current Choice settings
* and sets the Style fields for it. */
private void addObjectFromTable() {
float data[][] = new float[N_COLUMNS][];
float[][] data = getDataArrays();
String label = columnChoice[1].getSelectedItem(); //take label from y
int shape = Plot.toShape(symbolChoice.getSelectedItem());
float lineWidth = (float)(Tools.parseDouble(widthField.getText()));
if (lineWidth > 0)
plot.setLineWidth(lineWidth);
plot.restorePlotObjects();
if (savedLimits != null)
plot.setLimits(savedLimits);
plot.setColor(colorField.getText(), color2Field.getText());
plot.addPoints(data[0], data[1], data[3], shape, label);
if (data[2] != null)
plot.addHorizontalErrorBars(data[2]);
if (creatingPlot) {
plot.setXYLabels(data[0]==null ? "x" : columnChoice[0].getSelectedItem(), columnChoice[1].getSelectedItem());
plot.setLimitsToFit(false);
} else
plot.fitRangeToLastPlotObject();
currentObjectIndex = plot.getNumPlotObjects()-1;
setDialogStyleFields(currentObjectIndex);
if (dialogType == ADD_FROM_TABLE)
previousTableName = allTableNames[tableChoice.getSelectedIndex()];
}

/** For "Add from Table" and "Add from Arrays", tries to set a 'y' data column that has not been plotted yet. */
private void suggestNewYColumn() {
int nYcolumns = columnChoice[1].getItemCount();
int currentIndex = columnChoice[1].getSelectedIndex();
for (int i=0; i<nYcolumns; i++) {
if (columnChoice[0].getSelectedIndex()==0 || //if x is a data column, don't suggest it as y
!columnChoice[1].getSelectedItem().equals(columnChoice[0].getSelectedItem())) {
float[][] data = getDataArrays();
data = new float[][] {data[0], data[1]}; //only compare x & y, not the error bars
if (plot.getPlotObjectIndex(data) < 0)
return; //current data are ok (not duplicate)
}
columnChoice[1].select((currentIndex+i+1)%nYcolumns); //try the next one
}
}

/** For "Add from Table" and "Add from Arrays", retrieves the data arrays according to the columnChoices */
private float[][] getDataArrays() {
float[][] data = new float[N_COLUMNS][];
if (dialogType == ADD_FROM_TABLE) {
ResultsTable rt = allTables[tableChoice.getSelectedIndex()];
for (int c=0; c<N_COLUMNS; c++) {
Expand All @@ -492,29 +546,14 @@ private void addObjectFromTable() {
previousColumns[c] = columnChoice[c].getSelectedIndex();
}
}
String label = columnChoice[1].getSelectedItem(); //take label from y
int shape = Plot.toShape(symbolChoice.getSelectedItem());
float lineWidth = (float)(Tools.parseDouble(widthField.getText()));
if (lineWidth > 0)
plot.setLineWidth(lineWidth);
plot.restorePlotObjects();
plot.setColor(colorField.getText(), color2Field.getText());
plot.addPoints(data[0], data[1], data[3], shape, label);
if (data[2] != null)
plot.addHorizontalErrorBars(data[2]);
if (creatingPlot) {
plot.setXYLabels(data[0]==null ? "x" : columnChoice[0].getSelectedItem(), columnChoice[1].getSelectedItem());
plot.setLimitsToFit(false);
}
currentObjectIndex = plot.getNumPlotObjects()-1;
setDialogStyleFields(currentObjectIndex);
if (dialogType == ADD_FROM_TABLE)
previousTableName = allTableNames[tableChoice.getSelectedIndex()];
return data;
}

/** Does the curve fit and adds the fit curve to the plot */
private void addFitCurve() {
plot.restorePlotObjects();
if (savedLimits != null)
plot.setLimits(savedLimits);
int dataIndex = fitDataChoice.getSelectedIndex();
float[][] data = plot.getDataObjectArrays(dataIndex);
String fitName = fitFunctionChoice.getSelectedItem();
Expand Down
6 changes: 1 addition & 5 deletions ij/gui/PlotDialog.java
Expand Up @@ -46,7 +46,7 @@ public void showDialog(Frame parent) {
GenericDialog gd = parent == null ? new GenericDialog(HEADINGS[dialogType]) :
new GenericDialog(HEADINGS[dialogType], parent);
if (dialogType == SET_RANGE) {
double[] currentMinMax = plot.currentMinMax;
double[] currentMinMax = plot.getLimits();
boolean livePlot = plot.plotMaker != null;
int xDigits = plot.logXAxis ? -2 : Plot.getDigits(currentMinMax[0], currentMinMax[1], 0.005*Math.abs(currentMinMax[1]-currentMinMax[0]), 6);
int yDigits = plot.logYAxis ? -2 : Plot.getDigits(currentMinMax[2], currentMinMax[3], 0.005*Math.abs(currentMinMax[3]-currentMinMax[2]), 6);
Expand Down Expand Up @@ -81,10 +81,6 @@ public void showDialog(Frame parent) {
linYMax = Double.NaN;
if (linXMin == linXMax || linYMin == linYMax)
return;
currentMinMax[0] = linXMin;
currentMinMax[1] = linXMax;
currentMinMax[2] = linYMin;
currentMinMax[3] = linYMax;

if (livePlot) plot.templateFlags = setFlag(plot.templateFlags, Plot.X_RANGE, gd.getNextBoolean());
boolean xLog = gd.getNextBoolean();
Expand Down
16 changes: 10 additions & 6 deletions ij/gui/PlotWindow.java
Expand Up @@ -457,8 +457,10 @@ public void mouseMoved(int x, int y) {
if (x < plot.leftMargin || y > plot.topMargin + plot.frameHeight) {
if (!rangeArrowsVisible && !plot.isFrozen())
showRangeArrows();
if (activeRangeArrow == 8)//it's the 'R' icon
if (activeRangeArrow == 8) //it's the 'R' icon
coordinates.setText("Reset Range");
else if (activeRangeArrow == 9) //it's the 'F' icon
coordinates.setText("Full Range (Fit All)");
if (activeRangeArrow >= 0 && !rangeArrowRois[activeRangeArrow].contains(x, y)) {
rangeArrowRois[activeRangeArrow].setFillColor(Color.GRAY);
ic.repaint(); //de-highlight arrow where cursor has moved out
Expand Down Expand Up @@ -515,7 +517,7 @@ void showRangeArrows() {
if (imp == null)
return;
hideRangeArrows(); //in case we have old arrows from a different plot size or so
rangeArrowRois = new Roi[4 * 2 + 1]; //4 arrows per axis plus 1 'Reset' icon
rangeArrowRois = new Roi[4 * 2 + 2]; //4 arrows per axis plus 'Reset' and 'Fit All' icons
int i = 0;
int height = imp.getHeight();
int arrowH = plot.topMargin < 14 ? 6 : 8; //height of arrows and distance between them; base is twice that value
Expand All @@ -536,16 +538,18 @@ void showRangeArrows() {
}
Font theFont = new Font("SansSerif", Font.BOLD, 13);

TextRoi txtRoi = new TextRoi(2, height - 20, 20, 18, " R ", theFont);
TextRoi txtRoi = new TextRoi(1, height - 19, "\u2009R\u2009", theFont); //thin spaces to make roi slightly wider
rangeArrowRois[8] = txtRoi;
TextRoi txtRoi2 = new TextRoi(20, height - 19, "\u2009F\u2009", theFont);
rangeArrowRois[9] = txtRoi2;

Overlay ovly = imp.getOverlay();
if (ovly == null)
ovly = new Overlay();
for (Roi roi : rangeArrowRois) {
if (roi instanceof TextRoi) {
txtRoi.setStrokeColor(Color.WHITE);
txtRoi.setFillColor(Color.GRAY);
roi.setStrokeColor(Color.WHITE);
roi.setFillColor(Color.GRAY);
} else
roi.setFillColor(Color.GRAY);
ovly.add(roi);
Expand Down Expand Up @@ -793,7 +797,7 @@ public void run() {
while (true) {
IJ.wait(50); //delay to make sure the roi has been updated
Plot plot = plotMaker!=null?plotMaker.getPlot():null;
if (doUpdate && plot!=null) {
if (doUpdate && plot!=null && plot.getNumPlotObjects()>0) {
plot.useTemplate(this.plot, this.plot.templateFlags);
plot.setPlotMaker(plotMaker);
this.plot = plot;
Expand Down
54 changes: 28 additions & 26 deletions ij/gui/PointRoi.java
Expand Up @@ -48,7 +48,7 @@ public class PointRoi extends PolygonRoi {
private boolean promptBeforeDeletingCalled;
private int nMarkers;
private boolean addToOverlay;

static {
setDefaultType((int)Prefs.get(TYPE_KEY, HYBRID));
setDefaultSize((int)Prefs.get(SIZE_KEY, 1));
Expand Down Expand Up @@ -76,10 +76,10 @@ public PointRoi(float[] ox, float[] oy) {
this(ox, oy, ox.length);
}

/** Creates a new PointRoi using the specified coordinates and properties. */
public PointRoi(float[] ox, float[] oy, String properties) {
/** Creates a new PointRoi using the specified coordinate arrays and options. */
public PointRoi(float[] ox, float[] oy, String options) {
this(ox, oy, ox.length);
setProps(properties);
setOptions(options);
}

/** Creates a new PointRoi from a FloatPolygon. */
Expand All @@ -92,12 +92,12 @@ public PointRoi(Polygon poly) {
this(itof(poly.xpoints), itof(poly.ypoints), poly.npoints);
}

/** Creates a new PointRoi using the specified coordinates and properties. */
public PointRoi(double ox, double oy, String properties) {
/** Creates a new PointRoi using the specified coordinates and options. */
public PointRoi(double ox, double oy, String options) {
super(makeXArray(ox, null), makeYArray(oy, null), 1, POINT);
width=1; height=1;
incrementCounter(null);
setProps(properties);
setOptions(options);
}

/** Creates a new PointRoi using the specified offscreen int coordinates. */
Expand Down Expand Up @@ -135,7 +135,9 @@ public PointRoi(int sx, int sy, ImagePlus imp) {
enlargeArrays(50);
if (Recorder.record) {
String add = Prefs.pointAddToOverlay?" add":"";
String properties = sizes[convertSizeToIndex(size)]+" "+Colors.colorToString(getColor())+" "+types[type]+add;
Overlay overlay = imp.getOverlay();
String label = overlay!=null&&overlay.getDrawLabels()?" label":"";
String properties = sizes[convertSizeToIndex(size)]+" "+Colors.colorToString(getColor())+" "+types[type]+add+label;
properties = properties.toLowerCase();
if (Recorder.scriptMode())
Recorder.recordCall("imp.setRoi(new PointRoi("+x+","+y+",\""+properties+"\"));");
Expand All @@ -144,28 +146,28 @@ public PointRoi(int sx, int sy, ImagePlus imp) {
}
}

private void setProps(String p) {
if (p==null)
private void setOptions(String options) {
if (options==null)
return;
if (p.contains("tiny")) size=TINY;
else if (p.contains("medium")) size=MEDIUM;
else if (p.contains("extra")) size=EXTRA_LARGE;
else if (p.contains("large")) size=LARGE;
if (p.contains("cross")) type=CROSSHAIR;
else if (p.contains("dot")) type=DOT;
else if (p.contains("circle")) type=CIRCLE;
if (options.contains("tiny")) size=TINY;
else if (options.contains("medium")) size=MEDIUM;
else if (options.contains("extra")) size=EXTRA_LARGE;
else if (options.contains("large")) size=LARGE;
if (options.contains("cross")) type=CROSSHAIR;
else if (options.contains("dot")) type=DOT;
else if (options.contains("circle")) type=CIRCLE;
Color c = null;
if (p.contains("yellow")) c = Color.yellow;
else if (p.contains("red")) c = Color.red;
else if (p.contains("black")) c = Color.black;
else if (p.contains("white")) c = Color.white;
else if (p.contains("geen")) c = Color.green;
else if (p.contains("blue")) c = Color.blue;
else if (p.contains("magenta")) c = Color.magenta;
else if (p.contains("cyan")) c = Color.cyan;
if (options.contains("yellow")) c = Color.yellow;
else if (options.contains("red")) c = Color.red;
else if (options.contains("black")) c = Color.black;
else if (options.contains("white")) c = Color.white;
else if (options.contains("geen")) c = Color.green;
else if (options.contains("blue")) c = Color.blue;
else if (options.contains("magenta")) c = Color.magenta;
else if (options.contains("cyan")) c = Color.cyan;
if (c!=null)
setStrokeColor(c);
addToOverlay = p.contains("add");
addToOverlay = options.contains("add");
}

static float[] itof(int[] arr) {
Expand Down
18 changes: 11 additions & 7 deletions ij/macro/Functions.java
Expand Up @@ -75,6 +75,7 @@ public class Functions implements MacroConstants, Measurements {
static WaitForUserDialog waitForUserDialog;
int pasteMode;
int lineWidth = 1;
boolean lineWidthSet;
boolean expandableArrays;
int plotWidth;
int plotHeight;
Expand Down Expand Up @@ -287,8 +288,11 @@ String getStringFunction(int type) {
}

private void setLineWidth(int width) {
if (overlayPath!=null && width!=lineWidth)
addDrawingToOverlay(getImage());
lineWidth = width;
getProcessor().setLineWidth(width);
lineWidthSet = true;
}

Variable[] getArrayFunction(int type) {
Expand Down Expand Up @@ -829,7 +833,7 @@ void resetImage() {
ImageProcessor getProcessor() {
if (defaultIP==null) {
defaultIP = getImage().getProcessor();
if (lineWidth!=1)
if (lineWidthSet)
defaultIP.setLineWidth(lineWidth);
}
return defaultIP;
Expand Down Expand Up @@ -5349,17 +5353,17 @@ String getProperties() {
void makePoint() {
double x = getFirstArg();
double y = getNextArg();
String properties = null;
String options = null;
if (interp.nextToken()==',')
properties = getNextString();
options = getNextString();
interp.getRightParen();
if (properties==null) {
if (options==null) {
if ((int)x==x && (int)y==y)
IJ.makePoint((int)x, (int)y);
else
IJ.makePoint(x, y);
} else
getImage().setRoi(new PointRoi(x, y, properties));
getImage().setRoi(new PointRoi(x, y, options));
resetImage();
shiftKeyDown = altKeyDown = false;
}
Expand Down Expand Up @@ -6406,8 +6410,8 @@ void addRoi(ImagePlus imp, Roi roi){
overlay = offscreenOverlay;
}
if (defaultColor!=null)
roi.setStrokeColor(defaultColor);
roi.setLineWidth(getProcessor().getLineWidth());
roi.setStrokeColor(defaultColor);
roi.setStrokeWidth(getProcessor().getLineWidth());
overlay.add(roi);
}

Expand Down

0 comments on commit 7f9ea90

Please sign in to comment.