Skip to content

Commit

Permalink
2024.09.04 (1.54k16; Multi-point ROIs)
Browse files Browse the repository at this point in the history
  • Loading branch information
rasband committed Sep 4, 2024
1 parent 7746fcb commit ccd0b31
Show file tree
Hide file tree
Showing 12 changed files with 138 additions and 37 deletions.
2 changes: 1 addition & 1 deletion ij/ImageJ.java
Original file line number Diff line number Diff line change
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.54k";
public static final String BUILD = "12";
public static final String BUILD = "16";
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
5 changes: 5 additions & 0 deletions ij/gui/ImageCanvas.java
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,11 @@ else if (t==1)
position = getSliceNumber(roi.getName());
if (position>0 && imp.getCompositeMode()==IJ.COMPOSITE)
position = 0;
if (position == PointRoi.POINTWISE_POSITION)
position = 0;
if ((roi instanceof PointRoi) && Prefs.showAllPoints)
position = 0;
//IJ.log(c+" "+z+" "+t+" p="+position+"getP="+roi.getPosition()+" "+roiManagerShowAllMode);
if (position==0 || position==currentImage || roiManagerShowAllMode)
drawRoi(g, roi, drawLabels?i+LIST_OFFSET:-1);
}
Expand Down
68 changes: 65 additions & 3 deletions ij/gui/PointRoi.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import ij.plugin.PointToolOptions;
import ij.plugin.filter.Analyzer;
import ij.plugin.frame.Recorder;
import ij.util.Tools;
import ij.util.Java2;
import java.awt.*;
import java.awt.image.*;
Expand All @@ -22,6 +23,8 @@ public class PointRoi extends PolygonRoi {
public static final String[] sizes = {"Tiny", "Small", "Medium", "Large", "Extra Large", "XXL", "XXXL"};
public static final String[] types = {"Hybrid", "Cross", "Dot", "Circle"};
public static final int HYBRID=0, CROSS=1, CROSSHAIR=1, DOT=2, CIRCLE=3;
/** Returned by getPosition if point stack positions are different */
public static final int POINTWISE_POSITION = -2;
private static final String TYPE_KEY = "point.type";
private static final String SIZE_KEY = "point.size";
private static final String CROSS_COLOR_KEY = "point.cross.color";
Expand Down Expand Up @@ -215,12 +218,13 @@ public void draw(Graphics g) {
if (fontSize>9)
Java2.setAntialiasedText(g, true);
}
int slice = imp!=null&&positions!=null&&imp.getStackSize()>1?imp.getCurrentSlice():0;
int[] positions = this.positions; //use a copy to avoid NullPointerException on asynchronous change to null
int slice = imp!=null && positions!=null && imp.getStackSize()>1?imp.getCurrentSlice():0;
ImageCanvas ic = imp!=null?imp.getCanvas():null;
if (ic!=null && overlay && ic.getShowAllList()!=null && ic.getShowAllList().contains(this) && !Prefs.showAllSliceOnly)
slice = 0; // draw point irrespective of currently selected slice
slice = 0; // In RoiManager's "show all" mode and not "associate with slice", draw point irrespective of currently selected slice
if (Prefs.showAllPoints)
slice = 0;
slice = 0; // "Show on all slices" in Point tool options
//IJ.log("draw: "+positions+" "+imp.getCurrentSlice());
for (int i=0; i<nPoints; i++) {
//IJ.log(i+" "+slice+" "+(positions!=null?positions[i]:-1)+" "+getPosition());
Expand Down Expand Up @@ -690,6 +694,52 @@ public void updateCounts() {
counts[(counters==null || counters[i]>=counts.length) ? 0 : counters[i]] ++;
}

/** Sets the stack position (image number) of all points in this Roi.
* The points are only displayed when the stack is at the specified position.
* Set to zero to have the points displayed on all images in the stack.
* The stack position, when set, determines the visibility of this Roi
* (i) if it is part of an overlay (normal overlay or the RoiManager's
* 'Show All' overlay), or
* (ii) if it is the currently active Roi and Prefs.showAllPoints
* ('Show an all slices' in the Point Tool Options dialog) is off.
* Clears any association of this Roi to a hyperstack position.
*
* Note that the behavior differs from that of the other Roi types:
* For the other Roi types, setPosition does not restrict the visibility
* to stack slice 'n' if that roi is the currently active Roi; it only
* affects the visibility if that Roi is part of an overlay.
*/
public void setPosition(int n) {
if (n<0 && n!=POINTWISE_POSITION)
n = 0;
if (n == 0) {
positions = null;
} else {
if (positions == null)
positions = new int[counters == null ? nPoints*2 : counters.length];
if (n != POINTWISE_POSITION)
Arrays.fill(positions, n);
}
hyperstackPosition = false;
}

/** Returns the stack position (image number) of the points in this Roi, if
* all points have the same position. Returns 0 if none of the points is
* associated with a particular stack image, and PointRoi.POINTWISE_POSITION = -2
* if there are different stack positions for different points.
*/
public int getPosition() {
if (positions == null || nPoints < 1) {
return 0;
} else {
int position = positions[0];
for (int i=1; i<nPoints; i++)
if (positions[i] != position)
return POINTWISE_POSITION;
return position;
}
}

/** Returns the stack slice of the point with the given index, or 0 if no slice defined for this point */
public int getPointPosition(int index) {
if (positions!=null && index<nPoints)
Expand All @@ -698,6 +748,18 @@ public int getPointPosition(int index) {
return 0;
}

/** Returns whether this Roi contains a point associated to the given stack slice.
* Returns true for (non-existant) slice 0.
* Does not care whether points would be shown irrespective of the slice number
* (as given by the Point Tool options "Show on all slices", Prefs.showAllPoints).
*/
public boolean hasPointPosition(int slice) {
if (slice < 0) return false;
if (slice == 0) return true;
if (positions == null) return true;
return Tools.indexOf(positions, slice) >= 0;
}

public void displayCounts() {
ImagePlus imp = getImage();
String firstColumnHdr = "Slice";
Expand Down
15 changes: 9 additions & 6 deletions ij/gui/Roi.java
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ public class Roi extends Object implements Cloneable, java.io.Serializable, Iter
private String name;
private int position;
private int channel, slice, frame;
private boolean hyperstackPosition;
protected boolean hyperstackPosition;
private Overlay prototypeOverlay;
private boolean subPixel;
private boolean activeOverlayRoi;
Expand Down Expand Up @@ -2186,6 +2186,7 @@ public int getRoundRectArcSize() {
/** Sets the stack position (image number) of this ROI. In an overlay, this
* ROI is only displayed when the stack is at the specified position.
* Set to zero to have the ROI displayed on all images in the stack.
* Clears the hyperStackPosition, if there was one.
* @see ij.gui.Overlay
*/
public void setPosition(int n) {
Expand All @@ -2195,8 +2196,10 @@ public void setPosition(int n) {
hyperstackPosition = false;
}

/** Returns the stack position (image number) of this ROI, or
* zero if the ROI is not associated with a particular stack image.
/** Returns the stack position (image number) for displaying this ROI,
* in an overlay (or the RoiManager's 'Show All'. Returns zero if the
* ROI is not associated with a particular stack image.
* PointRois can also return PointRoi.POINTWISE_POSITION.
* @see ij.gui.Overlay
*/
public int getPosition() {
Expand Down Expand Up @@ -2244,14 +2247,14 @@ public final int getCPosition() {
}

/** Returns the slice position of this ROI, or zero
* if this ROI is not associated with a particular slice.
* if this ROI is not associated with a particular slice.
*/
public final int getZPosition() {
return slice==0&&!hyperstackPosition?position:slice;
return slice==0&&!hyperstackPosition ? position : slice;
}

/** Returns the frame position of this ROI, or zero
* if this ROI is not associated with a particular frame.
* if this ROI is not associated with a particular frame.
*/
public final int getTPosition() {
return frame;
Expand Down
11 changes: 7 additions & 4 deletions ij/gui/RoiProperties.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ public class RoiProperties implements TextListener, WindowListener {
private TextField groupField, colorField;
private Label groupName;

/** Constructs a ColorChooser using the specified title and initial color. */
/** Constructs a RoiProperties using the specified title for a given roi;
* call showDialog for the actual dialog.
* Note that the title determines which fields will be shown in the dialog. */
public RoiProperties(String title, Roi roi) {
if (roi==null)
throw new IllegalArgumentException("ROI is null");
Expand Down Expand Up @@ -81,6 +83,8 @@ public boolean showDialog() {
position = roi.getCPosition() +","+roi.getZPosition()+","+ roi.getTPosition();
if (position.equals("0"))
position = "none";
else if (position.equals(""+PointRoi.POINTWISE_POSITION))
position = "point-specific";
String group = ""+roi.getGroup();
if (group.equals("0"))
group = "none";
Expand All @@ -97,8 +101,8 @@ public boolean showDialog() {
String label = "Position:";
ImagePlus imp = WindowManager.getCurrentImage();
if (position.contains(",") || (imp!=null&&imp.isHyperStack()))
label = "Position (c,s,f):";
gd.addStringField(label, position);
label = "Position (c,z,t):";
gd.addStringField(label, position, 20);
gd.addStringField("Group:", group);
gd.addToSameRow(); gd.addMessage("wwwwwwwwwwww");
}
Expand All @@ -125,7 +129,6 @@ public boolean showDialog() {
colorField = (TextField)v.elementAt(v.size()-1);
}


if (!isLine) {
if (isPoint) {
int index = ((PointRoi)roi).getPointType();
Expand Down
9 changes: 5 additions & 4 deletions ij/io/RoiDecoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -376,19 +376,20 @@ else if (type==angle)
roi.setProperties(props);
}

roi.setPosition(position);
if (channel>0 || slice>0 || frame>0)
roi.setPosition(channel, slice, frame);

if (version>=227) {
int[] counters = getPointCounters(n);
if (counters!=null && (roi instanceof PointRoi))
((PointRoi)roi).setCounters(counters);
((PointRoi)roi).setCounters(counters); //must be after roi.setPosition()
}

// set group (1.52t or later)
if (version>=228 && group>0)
roi.setGroup(group);

roi.setPosition(position);
if (channel>0 || slice>0 || frame>0)
roi.setPosition(channel, slice, frame);
decodeOverlayOptions(roi, version, options, overlayLabelColor, overlayFontSize);
return roi;
}
Expand Down
13 changes: 6 additions & 7 deletions ij/measure/Calibration.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import ij.plugin.filter.Analyzer;

/** Calibration objects contain an image's spatial and density calibration data. */

public class Calibration implements Cloneable {

public static final int STRAIGHT_LINE=0,POLY2=1,POLY3=2,POLY4=3,
Expand Down Expand Up @@ -75,20 +74,20 @@ public class Calibration implements Cloneable {
private boolean zeroClip;
private boolean invertY;


/** Constructs a new Calibration object using the default values. */
public Calibration() {
}

/* Obsolete */
public Calibration(ImagePlus imp) {
if (imp!=null) {
bitDepth = imp.getBitDepth();
if (bitDepth!=UNKNOWN)
invertedLut=imp.isInvertedLut();
}
}

/** Constructs a new Calibration object using the default values.
For density calibration, the image is assumed to be 8-bits. */
public Calibration() {
}


/** Returns 'true' if this image is spatially calibrated. */
public boolean scaled() {
return pixelWidth!=1.0 || pixelHeight!=1.0 || pixelDepth!=1.0 || !unit.equals("pixel");
Expand Down
4 changes: 4 additions & 0 deletions ij/plugin/Resizer.java
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ else if (z1>1 && z1<stackSize)
interpolationMethod = gd.getNextChoiceIndex();
if (constrain && newWidth==0)
sizeToHeight = true;
String options = Macro.getOptions();
if (options != null && options.contains("constrain")
&& options.contains("height=") && !options.contains("width="))
sizeToHeight = true;
if (newWidth<=0.0 && !constrain) newWidth = 50;
if (newHeight<=0.0) newHeight = 50;
}
Expand Down
9 changes: 6 additions & 3 deletions ij/plugin/filter/ParticleAnalyzer.java
Original file line number Diff line number Diff line change
Expand Up @@ -346,8 +346,8 @@ public boolean showDialog() {
}
gd.addStringField("Circularity:", IJ.d2s(minCircularity)+"-"+IJ.d2s(maxCircularity), 12);
gd.addChoice("Show:", showStrings2, showStrings[showChoice]);
String[] labels = new String[8];
boolean[] states = new boolean[8];
String[] labels = new String[10];
boolean[] states = new boolean[10];
labels[0]="Display results"; states[0] = (options&SHOW_RESULTS)!=0;
labels[1]="Exclude on edges"; states[1]=(options&EXCLUDE_EDGE_PARTICLES)!=0;
labels[2]="Clear results"; states[2]=(options&CLEAR_WORKSHEET)!=0;
Expand All @@ -356,7 +356,8 @@ public boolean showDialog() {
labels[5]="Overlay"; states[5]=(options&OVERLAY)!=0;
labels[6]="Add to Manager"; states[6]=(options&ADD_TO_MANAGER)!=0;
labels[7]="Composite ROIs"; states[7]=(options&COMPOSITE_ROIS)!=0;
gd.addCheckboxGroup(4, 2, labels, states);
labels[8]="Record starts"; states[8]=(options&RECORD_STARTS)!=0;
gd.addCheckboxGroup(5, 2, labels, states);
gd.addHelp(IJ.URL2+"/docs/menus/analyze.html#ap");
gd.showDialog();
if (gd.wasCanceled())
Expand Down Expand Up @@ -419,6 +420,8 @@ public boolean showDialog() {
options |= ADD_TO_MANAGER; else options &= ~ADD_TO_MANAGER;
if (gd.getNextBoolean())
options |= COMPOSITE_ROIS; else options &= ~COMPOSITE_ROIS;
if (gd.getNextBoolean())
options |= RECORD_STARTS; else options &= ~RECORD_STARTS;
staticOptions = options;
options |= SHOW_PROGRESS;
if ((options&DISPLAY_SUMMARY)!=0)
Expand Down
20 changes: 12 additions & 8 deletions ij/plugin/frame/RoiManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ else if (color==null && defaultColor!=null)
listModel.addElement(label);
roi.setName(label);
Roi roiCopy = (Roi)roi.clone();
boolean hasPosition = roiCopy.getPosition()>0 || roiCopy.hasHyperStackPosition();
boolean hasPosition = roiCopy.getPosition()>0 || roiCopy.getPosition()==PointRoi.POINTWISE_POSITION || roiCopy.hasHyperStackPosition();
if (!hasPosition && imp!=null && imp.getStackSize()>1)
roiCopy.setPosition(imp); // set ROI position to current stack position
if (lineWidth>1)
Expand Down Expand Up @@ -626,7 +626,8 @@ boolean update(boolean clone) {
if (clone) {
String name = (String)listModel.getElementAt(index);
Roi roi2 = (Roi)roi.clone();
roi2.setPosition(imp);
if (roi2.getPosition() != PointRoi.POINTWISE_POSITION)
roi2.setPosition(imp);
roi.setName(name);
roi2.setName(name);
rois.set(index, roi2);
Expand Down Expand Up @@ -705,6 +706,8 @@ else if (roi.getZPosition()>0 && imp.getNSlices()==imp.getStackSize())
imp.setSlice(roi.getZPosition());
else if (position>0 && position<=imp.getStackSize())
imp.setSlice(position);
else if ((roi instanceof PointRoi) && !Prefs.showAllPoints && !((PointRoi)roi).hasPointPosition(imp.getSlice()))
imp.setSlice(((PointRoi)roi).getPointPosition(0));
else {
String label = (String)listModel.getElementAt(index);
int n = getSliceNumber(roi, label);
Expand Down Expand Up @@ -1559,6 +1562,7 @@ void setProperties(Color color, int lineWidth, Color fillColor) {
if (group>=0)
roi.setGroup(group);
if (rpRoi!=null) {
//IJ.log("new pos="+rpRoi.getPosition());
if (rpRoi.hasHyperStackPosition())
roi.setPosition(rpRoi.getCPosition(), rpRoi.getZPosition(), rpRoi.getTPosition());
else
Expand Down Expand Up @@ -1806,7 +1810,7 @@ void specify() {
runCommand("add");
}

private static boolean channel=false, slice=true, frame=false;
private static boolean channel=false, slice=true, frame=false; //remembers checkbox states for removePositions

private void removePositions(int position) {
int[] indexes = getIndexes();
Expand All @@ -1832,11 +1836,11 @@ private void removePositions(int position) {
gd.setInsets(5,15,0);
gd.addMessage("Remove positions for: ", font);
gd.setInsets(6,25,0);
gd.addCheckbox("Channels:", channel);
gd.addCheckbox("Channels c:", channel);
gd.setInsets(0,25,0);
gd.addCheckbox("Slices:", slice);
gd.addCheckbox("Slices z:", slice);
gd.setInsets(0,25,0);
gd.addCheckbox("Frames:", frame);
gd.addCheckbox("Frames t:", frame);
gd.showDialog();
if (gd.wasCanceled())
return;
Expand All @@ -1862,12 +1866,12 @@ private void removePositions(int position) {
int c = roi.getCPosition();
int z = roi.getZPosition();
int t = roi.getTPosition();
if (c>0 || t>0) {
if (roi.hasHyperStackPosition()) {
if (removeChannels) c = 0;
if (removeSlices) z = 0;
if (removeFrames) t = 0;
roi.setPosition(c, z, t);
} else
} else if (removeSlices)
roi.setPosition(0);
}
if (imp!=null)
Expand Down
Loading

0 comments on commit ccd0b31

Please sign in to comment.