Skip to content

Commit ccd0b31

Browse files
committed
2024.09.04 (1.54k16; Multi-point ROIs)
1 parent 7746fcb commit ccd0b31

File tree

12 files changed

+138
-37
lines changed

12 files changed

+138
-37
lines changed

ij/ImageJ.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public class ImageJ extends Frame implements ActionListener,
7979

8080
/** Plugins should call IJ.getVersion() or IJ.getFullVersion() to get the version string. */
8181
public static final String VERSION = "1.54k";
82-
public static final String BUILD = "12";
82+
public static final String BUILD = "16";
8383
public static Color backgroundColor = new Color(237,237,237);
8484
/** SansSerif, 12-point, plain font. */
8585
public static final Font SansSerif12 = new Font("SansSerif", Font.PLAIN, 12);

ij/gui/ImageCanvas.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,11 @@ else if (t==1)
359359
position = getSliceNumber(roi.getName());
360360
if (position>0 && imp.getCompositeMode()==IJ.COMPOSITE)
361361
position = 0;
362+
if (position == PointRoi.POINTWISE_POSITION)
363+
position = 0;
364+
if ((roi instanceof PointRoi) && Prefs.showAllPoints)
365+
position = 0;
366+
//IJ.log(c+" "+z+" "+t+" p="+position+"getP="+roi.getPosition()+" "+roiManagerShowAllMode);
362367
if (position==0 || position==currentImage || roiManagerShowAllMode)
363368
drawRoi(g, roi, drawLabels?i+LIST_OFFSET:-1);
364369
}

ij/gui/PointRoi.java

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import ij.plugin.PointToolOptions;
77
import ij.plugin.filter.Analyzer;
88
import ij.plugin.frame.Recorder;
9+
import ij.util.Tools;
910
import ij.util.Java2;
1011
import java.awt.*;
1112
import java.awt.image.*;
@@ -22,6 +23,8 @@ public class PointRoi extends PolygonRoi {
2223
public static final String[] sizes = {"Tiny", "Small", "Medium", "Large", "Extra Large", "XXL", "XXXL"};
2324
public static final String[] types = {"Hybrid", "Cross", "Dot", "Circle"};
2425
public static final int HYBRID=0, CROSS=1, CROSSHAIR=1, DOT=2, CIRCLE=3;
26+
/** Returned by getPosition if point stack positions are different */
27+
public static final int POINTWISE_POSITION = -2;
2528
private static final String TYPE_KEY = "point.type";
2629
private static final String SIZE_KEY = "point.size";
2730
private static final String CROSS_COLOR_KEY = "point.cross.color";
@@ -215,12 +218,13 @@ public void draw(Graphics g) {
215218
if (fontSize>9)
216219
Java2.setAntialiasedText(g, true);
217220
}
218-
int slice = imp!=null&&positions!=null&&imp.getStackSize()>1?imp.getCurrentSlice():0;
221+
int[] positions = this.positions; //use a copy to avoid NullPointerException on asynchronous change to null
222+
int slice = imp!=null && positions!=null && imp.getStackSize()>1?imp.getCurrentSlice():0;
219223
ImageCanvas ic = imp!=null?imp.getCanvas():null;
220224
if (ic!=null && overlay && ic.getShowAllList()!=null && ic.getShowAllList().contains(this) && !Prefs.showAllSliceOnly)
221-
slice = 0; // draw point irrespective of currently selected slice
225+
slice = 0; // In RoiManager's "show all" mode and not "associate with slice", draw point irrespective of currently selected slice
222226
if (Prefs.showAllPoints)
223-
slice = 0;
227+
slice = 0; // "Show on all slices" in Point tool options
224228
//IJ.log("draw: "+positions+" "+imp.getCurrentSlice());
225229
for (int i=0; i<nPoints; i++) {
226230
//IJ.log(i+" "+slice+" "+(positions!=null?positions[i]:-1)+" "+getPosition());
@@ -690,6 +694,52 @@ public void updateCounts() {
690694
counts[(counters==null || counters[i]>=counts.length) ? 0 : counters[i]] ++;
691695
}
692696

697+
/** Sets the stack position (image number) of all points in this Roi.
698+
* The points are only displayed when the stack is at the specified position.
699+
* Set to zero to have the points displayed on all images in the stack.
700+
* The stack position, when set, determines the visibility of this Roi
701+
* (i) if it is part of an overlay (normal overlay or the RoiManager's
702+
* 'Show All' overlay), or
703+
* (ii) if it is the currently active Roi and Prefs.showAllPoints
704+
* ('Show an all slices' in the Point Tool Options dialog) is off.
705+
* Clears any association of this Roi to a hyperstack position.
706+
*
707+
* Note that the behavior differs from that of the other Roi types:
708+
* For the other Roi types, setPosition does not restrict the visibility
709+
* to stack slice 'n' if that roi is the currently active Roi; it only
710+
* affects the visibility if that Roi is part of an overlay.
711+
*/
712+
public void setPosition(int n) {
713+
if (n<0 && n!=POINTWISE_POSITION)
714+
n = 0;
715+
if (n == 0) {
716+
positions = null;
717+
} else {
718+
if (positions == null)
719+
positions = new int[counters == null ? nPoints*2 : counters.length];
720+
if (n != POINTWISE_POSITION)
721+
Arrays.fill(positions, n);
722+
}
723+
hyperstackPosition = false;
724+
}
725+
726+
/** Returns the stack position (image number) of the points in this Roi, if
727+
* all points have the same position. Returns 0 if none of the points is
728+
* associated with a particular stack image, and PointRoi.POINTWISE_POSITION = -2
729+
* if there are different stack positions for different points.
730+
*/
731+
public int getPosition() {
732+
if (positions == null || nPoints < 1) {
733+
return 0;
734+
} else {
735+
int position = positions[0];
736+
for (int i=1; i<nPoints; i++)
737+
if (positions[i] != position)
738+
return POINTWISE_POSITION;
739+
return position;
740+
}
741+
}
742+
693743
/** Returns the stack slice of the point with the given index, or 0 if no slice defined for this point */
694744
public int getPointPosition(int index) {
695745
if (positions!=null && index<nPoints)
@@ -698,6 +748,18 @@ public int getPointPosition(int index) {
698748
return 0;
699749
}
700750

751+
/** Returns whether this Roi contains a point associated to the given stack slice.
752+
* Returns true for (non-existant) slice 0.
753+
* Does not care whether points would be shown irrespective of the slice number
754+
* (as given by the Point Tool options "Show on all slices", Prefs.showAllPoints).
755+
*/
756+
public boolean hasPointPosition(int slice) {
757+
if (slice < 0) return false;
758+
if (slice == 0) return true;
759+
if (positions == null) return true;
760+
return Tools.indexOf(positions, slice) >= 0;
761+
}
762+
701763
public void displayCounts() {
702764
ImagePlus imp = getImage();
703765
String firstColumnHdr = "Slice";

ij/gui/Roi.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ public class Roi extends Object implements Cloneable, java.io.Serializable, Iter
114114
private String name;
115115
private int position;
116116
private int channel, slice, frame;
117-
private boolean hyperstackPosition;
117+
protected boolean hyperstackPosition;
118118
private Overlay prototypeOverlay;
119119
private boolean subPixel;
120120
private boolean activeOverlayRoi;
@@ -2186,6 +2186,7 @@ public int getRoundRectArcSize() {
21862186
/** Sets the stack position (image number) of this ROI. In an overlay, this
21872187
* ROI is only displayed when the stack is at the specified position.
21882188
* Set to zero to have the ROI displayed on all images in the stack.
2189+
* Clears the hyperStackPosition, if there was one.
21892190
* @see ij.gui.Overlay
21902191
*/
21912192
public void setPosition(int n) {
@@ -2195,8 +2196,10 @@ public void setPosition(int n) {
21952196
hyperstackPosition = false;
21962197
}
21972198

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

22462249
/** Returns the slice position of this ROI, or zero
2247-
* if this ROI is not associated with a particular slice.
2250+
* if this ROI is not associated with a particular slice.
22482251
*/
22492252
public final int getZPosition() {
2250-
return slice==0&&!hyperstackPosition?position:slice;
2253+
return slice==0&&!hyperstackPosition ? position : slice;
22512254
}
22522255

22532256
/** Returns the frame position of this ROI, or zero
2254-
* if this ROI is not associated with a particular frame.
2257+
* if this ROI is not associated with a particular frame.
22552258
*/
22562259
public final int getTPosition() {
22572260
return frame;

ij/gui/RoiProperties.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ public class RoiProperties implements TextListener, WindowListener {
3131
private TextField groupField, colorField;
3232
private Label groupName;
3333

34-
/** Constructs a ColorChooser using the specified title and initial color. */
34+
/** Constructs a RoiProperties using the specified title for a given roi;
35+
* call showDialog for the actual dialog.
36+
* Note that the title determines which fields will be shown in the dialog. */
3537
public RoiProperties(String title, Roi roi) {
3638
if (roi==null)
3739
throw new IllegalArgumentException("ROI is null");
@@ -81,6 +83,8 @@ public boolean showDialog() {
8183
position = roi.getCPosition() +","+roi.getZPosition()+","+ roi.getTPosition();
8284
if (position.equals("0"))
8385
position = "none";
86+
else if (position.equals(""+PointRoi.POINTWISE_POSITION))
87+
position = "point-specific";
8488
String group = ""+roi.getGroup();
8589
if (group.equals("0"))
8690
group = "none";
@@ -97,8 +101,8 @@ public boolean showDialog() {
97101
String label = "Position:";
98102
ImagePlus imp = WindowManager.getCurrentImage();
99103
if (position.contains(",") || (imp!=null&&imp.isHyperStack()))
100-
label = "Position (c,s,f):";
101-
gd.addStringField(label, position);
104+
label = "Position (c,z,t):";
105+
gd.addStringField(label, position, 20);
102106
gd.addStringField("Group:", group);
103107
gd.addToSameRow(); gd.addMessage("wwwwwwwwwwww");
104108
}
@@ -125,7 +129,6 @@ public boolean showDialog() {
125129
colorField = (TextField)v.elementAt(v.size()-1);
126130
}
127131

128-
129132
if (!isLine) {
130133
if (isPoint) {
131134
int index = ((PointRoi)roi).getPointType();

ij/io/RoiDecoder.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -376,19 +376,20 @@ else if (type==angle)
376376
roi.setProperties(props);
377377
}
378378

379+
roi.setPosition(position);
380+
if (channel>0 || slice>0 || frame>0)
381+
roi.setPosition(channel, slice, frame);
382+
379383
if (version>=227) {
380384
int[] counters = getPointCounters(n);
381385
if (counters!=null && (roi instanceof PointRoi))
382-
((PointRoi)roi).setCounters(counters);
386+
((PointRoi)roi).setCounters(counters); //must be after roi.setPosition()
383387
}
384388

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

389-
roi.setPosition(position);
390-
if (channel>0 || slice>0 || frame>0)
391-
roi.setPosition(channel, slice, frame);
392393
decodeOverlayOptions(roi, version, options, overlayLabelColor, overlayFontSize);
393394
return roi;
394395
}

ij/measure/Calibration.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import ij.plugin.filter.Analyzer;
44

55
/** Calibration objects contain an image's spatial and density calibration data. */
6-
76
public class Calibration implements Cloneable {
87

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

77+
7878
/** Constructs a new Calibration object using the default values. */
79+
public Calibration() {
80+
}
81+
82+
/* Obsolete */
7983
public Calibration(ImagePlus imp) {
8084
if (imp!=null) {
8185
bitDepth = imp.getBitDepth();
8286
if (bitDepth!=UNKNOWN)
8387
invertedLut=imp.isInvertedLut();
8488
}
8589
}
86-
87-
/** Constructs a new Calibration object using the default values.
88-
For density calibration, the image is assumed to be 8-bits. */
89-
public Calibration() {
90-
}
91-
90+
9291
/** Returns 'true' if this image is spatially calibrated. */
9392
public boolean scaled() {
9493
return pixelWidth!=1.0 || pixelHeight!=1.0 || pixelDepth!=1.0 || !unit.equals("pixel");

ij/plugin/Resizer.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,10 @@ else if (z1>1 && z1<stackSize)
127127
interpolationMethod = gd.getNextChoiceIndex();
128128
if (constrain && newWidth==0)
129129
sizeToHeight = true;
130+
String options = Macro.getOptions();
131+
if (options != null && options.contains("constrain")
132+
&& options.contains("height=") && !options.contains("width="))
133+
sizeToHeight = true;
130134
if (newWidth<=0.0 && !constrain) newWidth = 50;
131135
if (newHeight<=0.0) newHeight = 50;
132136
}

ij/plugin/filter/ParticleAnalyzer.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -346,8 +346,8 @@ public boolean showDialog() {
346346
}
347347
gd.addStringField("Circularity:", IJ.d2s(minCircularity)+"-"+IJ.d2s(maxCircularity), 12);
348348
gd.addChoice("Show:", showStrings2, showStrings[showChoice]);
349-
String[] labels = new String[8];
350-
boolean[] states = new boolean[8];
349+
String[] labels = new String[10];
350+
boolean[] states = new boolean[10];
351351
labels[0]="Display results"; states[0] = (options&SHOW_RESULTS)!=0;
352352
labels[1]="Exclude on edges"; states[1]=(options&EXCLUDE_EDGE_PARTICLES)!=0;
353353
labels[2]="Clear results"; states[2]=(options&CLEAR_WORKSHEET)!=0;
@@ -356,7 +356,8 @@ public boolean showDialog() {
356356
labels[5]="Overlay"; states[5]=(options&OVERLAY)!=0;
357357
labels[6]="Add to Manager"; states[6]=(options&ADD_TO_MANAGER)!=0;
358358
labels[7]="Composite ROIs"; states[7]=(options&COMPOSITE_ROIS)!=0;
359-
gd.addCheckboxGroup(4, 2, labels, states);
359+
labels[8]="Record starts"; states[8]=(options&RECORD_STARTS)!=0;
360+
gd.addCheckboxGroup(5, 2, labels, states);
360361
gd.addHelp(IJ.URL2+"/docs/menus/analyze.html#ap");
361362
gd.showDialog();
362363
if (gd.wasCanceled())
@@ -419,6 +420,8 @@ public boolean showDialog() {
419420
options |= ADD_TO_MANAGER; else options &= ~ADD_TO_MANAGER;
420421
if (gd.getNextBoolean())
421422
options |= COMPOSITE_ROIS; else options &= ~COMPOSITE_ROIS;
423+
if (gd.getNextBoolean())
424+
options |= RECORD_STARTS; else options &= ~RECORD_STARTS;
422425
staticOptions = options;
423426
options |= SHOW_PROGRESS;
424427
if ((options&DISPLAY_SUMMARY)!=0)

ij/plugin/frame/RoiManager.java

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ else if (color==null && defaultColor!=null)
413413
listModel.addElement(label);
414414
roi.setName(label);
415415
Roi roiCopy = (Roi)roi.clone();
416-
boolean hasPosition = roiCopy.getPosition()>0 || roiCopy.hasHyperStackPosition();
416+
boolean hasPosition = roiCopy.getPosition()>0 || roiCopy.getPosition()==PointRoi.POINTWISE_POSITION || roiCopy.hasHyperStackPosition();
417417
if (!hasPosition && imp!=null && imp.getStackSize()>1)
418418
roiCopy.setPosition(imp); // set ROI position to current stack position
419419
if (lineWidth>1)
@@ -626,7 +626,8 @@ boolean update(boolean clone) {
626626
if (clone) {
627627
String name = (String)listModel.getElementAt(index);
628628
Roi roi2 = (Roi)roi.clone();
629-
roi2.setPosition(imp);
629+
if (roi2.getPosition() != PointRoi.POINTWISE_POSITION)
630+
roi2.setPosition(imp);
630631
roi.setName(name);
631632
roi2.setName(name);
632633
rois.set(index, roi2);
@@ -705,6 +706,8 @@ else if (roi.getZPosition()>0 && imp.getNSlices()==imp.getStackSize())
705706
imp.setSlice(roi.getZPosition());
706707
else if (position>0 && position<=imp.getStackSize())
707708
imp.setSlice(position);
709+
else if ((roi instanceof PointRoi) && !Prefs.showAllPoints && !((PointRoi)roi).hasPointPosition(imp.getSlice()))
710+
imp.setSlice(((PointRoi)roi).getPointPosition(0));
708711
else {
709712
String label = (String)listModel.getElementAt(index);
710713
int n = getSliceNumber(roi, label);
@@ -1559,6 +1562,7 @@ void setProperties(Color color, int lineWidth, Color fillColor) {
15591562
if (group>=0)
15601563
roi.setGroup(group);
15611564
if (rpRoi!=null) {
1565+
//IJ.log("new pos="+rpRoi.getPosition());
15621566
if (rpRoi.hasHyperStackPosition())
15631567
roi.setPosition(rpRoi.getCPosition(), rpRoi.getZPosition(), rpRoi.getTPosition());
15641568
else
@@ -1806,7 +1810,7 @@ void specify() {
18061810
runCommand("add");
18071811
}
18081812

1809-
private static boolean channel=false, slice=true, frame=false;
1813+
private static boolean channel=false, slice=true, frame=false; //remembers checkbox states for removePositions
18101814

18111815
private void removePositions(int position) {
18121816
int[] indexes = getIndexes();
@@ -1832,11 +1836,11 @@ private void removePositions(int position) {
18321836
gd.setInsets(5,15,0);
18331837
gd.addMessage("Remove positions for: ", font);
18341838
gd.setInsets(6,25,0);
1835-
gd.addCheckbox("Channels:", channel);
1839+
gd.addCheckbox("Channels c:", channel);
18361840
gd.setInsets(0,25,0);
1837-
gd.addCheckbox("Slices:", slice);
1841+
gd.addCheckbox("Slices z:", slice);
18381842
gd.setInsets(0,25,0);
1839-
gd.addCheckbox("Frames:", frame);
1843+
gd.addCheckbox("Frames t:", frame);
18401844
gd.showDialog();
18411845
if (gd.wasCanceled())
18421846
return;
@@ -1862,12 +1866,12 @@ private void removePositions(int position) {
18621866
int c = roi.getCPosition();
18631867
int z = roi.getZPosition();
18641868
int t = roi.getTPosition();
1865-
if (c>0 || t>0) {
1869+
if (roi.hasHyperStackPosition()) {
18661870
if (removeChannels) c = 0;
18671871
if (removeSlices) z = 0;
18681872
if (removeFrames) t = 0;
18691873
roi.setPosition(c, z, t);
1870-
} else
1874+
} else if (removeSlices)
18711875
roi.setPosition(0);
18721876
}
18731877
if (imp!=null)

0 commit comments

Comments
 (0)