This is probably a dumb question but when using the Spot Enhancing 2D... plugin in a macro, how do automatically select the "Enhance" button in the dialog box? Or suppress the dialog box altogether? As in this short macro
run("SpotEnhancingFilter2D...","Diameter=4.0"); selectWindow("S.E.F. (4.0) of Untitled"); run("Find Maxima...", "noise=95 output=[Point Selection]"); run("Measure"); Thanks, Phil |
Is there a way to scale the entire ROI list. The idea is that I
have a set of ROIs defined for a certain image stack. If I scale the image stack (for example, by 0.5 in each dimension) I would to scale the ROI position and dimensions so that the ROIs correspond tothe scaled image. I know I can loop through the ROI list, get the ROI info, and create a new set of ROIs, but I was wondering if that function already exists. --aryeh -- Aryeh Weiss School of Engineering Bar Ilan University Ramat Gan 52900 Israel Ph: 972-3-5317638 FAX: 972-3-7384051 |
Hi Aryeh,
On Fri, 12 Aug 2011, Aryeh Weiss wrote: > Is there a way to scale the entire ROI list. The idea is that I have a > set of ROIs defined for a certain image stack. If I scale the image > stack (for example, by 0.5 in each dimension) I would to scale the ROI > position and dimensions so that the ROIs correspond tothe scaled image. > I know I can loop through the ROI list, get the ROI info, and create a > new set of ROIs, but I was wondering if that function already exists. This is similar to http://fiji.sc/Introduction_into_Macro_Programming#Resizing_to_a_given_width_of_the_selection_bounds The following is my attempt at a solution for your problem: -- snipsnap -- /* * This macro scales all ROIs in the ROI Manager * * Note: since the scaling is performed using integers, * upscaling leads to step artifacts. * * For technical reasons, this macro cannot handle composite * selections. */ function scaleROI(factor) { type = selectionType(); getSelectionCoordinates(x, y); for (i = 0; i < x.length; i++) { x[i] = x[i] * factor; y[i] = y[i] * factor; } makeSelection(type, x, y); } factor = getNumber("Factor", 0.5); count = roiManager("count"); current = roiManager("index"); for (i = 0; i < count; i++) { roiManager("select", i); scaleROI(factor); roiManager("update"); } if (current < 0) roiManager("deselect"); else roiManager("select", current); |
On 8/18/11 10:31 AM, Johannes Schindelin wrote:
> Hi Aryeh, > > On Fri, 12 Aug 2011, Aryeh Weiss wrote: > >> Is there a way to scale the entire ROI list. The idea is that I have a >> set of ROIs defined for a certain image stack. If I scale the image >> stack (for example, by 0.5 in each dimension) I would to scale the ROI >> position and dimensions so that the ROIs correspond tothe scaled image. >> I know I can loop through the ROI list, get the ROI info, and create a >> new set of ROIs, but I was wondering if that function already exists. > > This is similar to > > http://fiji.sc/Introduction_into_Macro_Programming#Resizing_to_a_given_width_of_the_selection_bounds > > The following is my attempt at a solution for your problem: > > -- snipsnap -- > /* > * This macro scales all ROIs in the ROI Manager > * > * Note: since the scaling is performed using integers, > * upscaling leads to step artifacts. > * > * For technical reasons, this macro cannot handle composite > * selections. > */ > > function scaleROI(factor) { > type = selectionType(); > getSelectionCoordinates(x, y); > for (i = 0; i< x.length; i++) { > x[i] = x[i] * factor; > y[i] = y[i] * factor; > } > makeSelection(type, x, y); > } > > factor = getNumber("Factor", 0.5); > > count = roiManager("count"); > current = roiManager("index"); > for (i = 0; i< count; i++) { > roiManager("select", i); > scaleROI(factor); > roiManager("update"); > } > if (current< 0) > roiManager("deselect"); > else > roiManager("select", current); > Hi Johannes, Thank you for your reply. This macro works, but I discovered something interesting. If I have an image smaller than the original image selected, and some of the ROIs are outside of the image area, then roiManager("select", i); will not select that ROI on the image. But, scaleROI depends on getSelectionCoordinates(x, y); to get the ROI coordinates. Therefore, the last valid ROI coordinates will be used instead. What is needed is a way to read the ROI coordinates without selecting them in the open image. I am looking for this. Meanwhile, I can use your macro, just being sure that the full size image is selected when it is run. Best regards, --aryeh -- Aryeh Weiss School of Engineering Bar Ilan University Ramat Gan 52900 Israel Ph: 972-3-5317638 FAX: 972-3-7384051 |
Hi Aryeh,
On Thu, 18 Aug 2011, Aryeh Weiss wrote: > On 8/18/11 10:31 AM, Johannes Schindelin wrote: > > > On Fri, 12 Aug 2011, Aryeh Weiss wrote: > > > > > Is there a way to scale the entire ROI list. The idea is that I have > > > a set of ROIs defined for a certain image stack. If I scale the > > > image stack (for example, by 0.5 in each dimension) I would to scale > > > the ROI position and dimensions so that the ROIs correspond tothe > > > scaled image. I know I can loop through the ROI list, get the ROI > > > info, and create a new set of ROIs, but I was wondering if that > > > function already exists. > > > > [...] > > Thank you for your reply. This macro works, but I discovered something > interesting. If I have an image smaller than the original image > selected, and some of the ROIs are outside of the image area, then > roiManager("select", i); will not select that ROI on the image. But, > scaleROI depends on getSelectionCoordinates(x, y); to get the ROI > coordinates. Therefore, the last valid ROI coordinates will be used > instead. What is needed is a way to read the ROI coordinates without > selecting them in the open image. I am looking for this. Meanwhile, I > can use your macro, just being sure that the full size image is selected > when it is run. That is unfortunate! So the only thing you could do is to write a script or plugin. Let me try. *clicketyclick* Wow, this was harder than I expected since the Macro API is so completely different from the Java API. Note that setSelectedIndexes() seems not to work correctly, and please note also that I did not import any classes because I wrote this in the Script Editor (obviously! :-) where the ImageJ classes are imported automatically. -- snipsnap -- /* * This script scales all ROIs in the ROI Manager * * Note: since the scaling is performed using integers, * upscaling leads to step artifacts. */ function cloneIntArray(array) { result = new java.lang.reflect.Array.newInstance(java.lang.Integer.TYPE, array.length); System.arraycopy(array, 0, result, 0, array.length); return result; } function scaleROI(roi, factor) { var type = roi.getType(); var bounds = roi.getBounds(); var n = 0; var x = null; var y = null; if (type == roi.RECTANGLE || type == roi.OVAL) { n = 2; x = [ 0, bounds.width ]; y = [ 0, bounds.height ]; } else if (type >= roi.FREEROI && type <= roi.FREELINE && type != roi.LINE) { n = roi.getNCoordinates(); x = cloneIntArray(roi.getXCoordinates()); y = cloneIntArray(roi.getYCoordinates()); } else { IJ.log("Unhandled ROI type: " + type); throw new Exception("Unhandled ROI type: " + type); } for (var i = 0; i < n; i++) { x[i] = (x[i] + bounds.x) * factor; y[i] = (y[i] + bounds.y) * factor; } if (type == roi.RECTANGLE) return new Roi(x[0], y[0], x[1] - x[0], y[1] - y[0]); else if (type == roi.OVAL) return new OvalRoi(x[0], y[0], x[1] - x[0], y[1] - y[0]); else if (type >= roi.FREEROI && type <= roi.FREELINE && type != roi.LINE) return new PolygonRoi(x, y, n, type); else throw new Exception("Unhandled ROI type: " + type); } var factor = IJ.getNumber("Factor", 0.5); var roiManager = RoiManager.getInstance(); if (roiManager == null) roiManager = new RoiManager(); var count = roiManager.getCount(); var list = roiManager.getList(); var rois = roiManager.getROIs(); var roiList = new Array(); for (var i = 0; i < count; i++) roiList[i] = scaleROI(rois.get(list.getItem(i)), factor); var selected = list.getSelectedIndexes(); IJ.log("selected: " + selected.length); roiManager.runCommand("Select All"); roiManager.runCommand("Delete"); for (var i = 0; i < count; i++) roiManager.addRoi(roiList[i]); if (selected != null) roiManager.setSelectedIndexes(selected); |
On 8/19/11 1:06 PM, Johannes Schindelin wrote:
> Hi Aryeh, > > On Thu, 18 Aug 2011, Aryeh Weiss wrote: > >> On 8/18/11 10:31 AM, Johannes Schindelin wrote: >> >>> On Fri, 12 Aug 2011, Aryeh Weiss wrote: >>> >>>> Is there a way to scale the entire ROI list. The idea is that I have >>>> a set of ROIs defined for a certain image stack. If I scale the >>>> image stack (for example, by 0.5 in each dimension) I would to scale >>>> the ROI position and dimensions so that the ROIs correspond tothe >>>> scaled image. I know I can loop through the ROI list, get the ROI >>>> info, and create a new set of ROIs, but I was wondering if that >>>> function already exists. >>> >>> [...] >> >> Thank you for your reply. This macro works, but I discovered something >> interesting. If I have an image smaller than the original image >> selected, and some of the ROIs are outside of the image area, then >> roiManager("select", i); will not select that ROI on the image. But, >> scaleROI depends on getSelectionCoordinates(x, y); to get the ROI >> coordinates. Therefore, the last valid ROI coordinates will be used >> instead. What is needed is a way to read the ROI coordinates without >> selecting them in the open image. I am looking for this. Meanwhile, I >> can use your macro, just being sure that the full size image is selected >> when it is run. > > That is unfortunate! So the only thing you could do is to write a script > or plugin. Let me try. > > *clicketyclick* > > Wow, this was harder than I expected since the Macro API is so completely > different from the Java API. > > Note that setSelectedIndexes() seems not to work correctly, and please > note also that I did not import any classes because I wrote this in the > Script Editor (obviously! :-) where the ImageJ classes are imported > automatically. > > -- snipsnap -- > /* > * This script scales all ROIs in the ROI Manager > * > * Note: since the scaling is performed using integers, > * upscaling leads to step artifacts. > */ > > function cloneIntArray(array) { > result = new java.lang.reflect.Array.newInstance(java.lang.Integer.TYPE, array.length); > System.arraycopy(array, 0, result, 0, array.length); > return result; > } > > function scaleROI(roi, factor) { > var type = roi.getType(); > var bounds = roi.getBounds(); > var n = 0; > var x = null; > var y = null; > if (type == roi.RECTANGLE || type == roi.OVAL) { > n = 2; > x = [ 0, bounds.width ]; > y = [ 0, bounds.height ]; > } > else if (type>= roi.FREEROI&& type<= roi.FREELINE&& type != roi.LINE) { > n = roi.getNCoordinates(); > x = cloneIntArray(roi.getXCoordinates()); > y = cloneIntArray(roi.getYCoordinates()); > } > else { > IJ.log("Unhandled ROI type: " + type); > throw new Exception("Unhandled ROI type: " + type); > } > > for (var i = 0; i< n; i++) { > x[i] = (x[i] + bounds.x) * factor; > y[i] = (y[i] + bounds.y) * factor; > } > > if (type == roi.RECTANGLE) > return new Roi(x[0], y[0], x[1] - x[0], y[1] - y[0]); > else if (type == roi.OVAL) > return new OvalRoi(x[0], y[0], x[1] - x[0], y[1] - y[0]); > else if (type>= roi.FREEROI&& type<= roi.FREELINE&& type != roi.LINE) > return new PolygonRoi(x, y, n, type); > else > throw new Exception("Unhandled ROI type: " + type); > } > > var factor = IJ.getNumber("Factor", 0.5); > > var roiManager = RoiManager.getInstance(); > if (roiManager == null) > roiManager = new RoiManager(); > > var count = roiManager.getCount(); > var list = roiManager.getList(); > var rois = roiManager.getROIs(); > var roiList = new Array(); > for (var i = 0; i< count; i++) roiSlice[i] = roiManager.getSliceNumber(RoiManager.getName(Integer.toString(i))); > roiList[i] = scaleROI(rois.get(list.getItem(i)), factor); > > var selected = list.getSelectedIndexes(); > IJ.log("selected: " + selected.length); > roiManager.runCommand("Select All"); > roiManager.runCommand("Delete"); > for (var i = 0; i< count; i++) // select the slice to which to write the new ROI IJ.getImage().setSlice(roiSlice[i]); > roiManager.addRoi(roiList[i]); > > if (selected != null) > roiManager.setSelectedIndexes(selected); > Hi Johannes and again, thank you for your reply and script. It had one problem, in that it wrote all of the ROIs back to the whatever slice was selected in the active image. I worked around this by adding the two lines of code interleaved into your script, above. These preserve the slice info, but of course they assume that there is a stack open with a sufficient number of slices. However, it would be better if the roimanager API allowed the slice info to be written to the roimanager without selection of the slice in the active image. Best regards, --aryeh -- Aryeh Weiss School of Engineering Bar Ilan University Ramat Gan 52900 Israel Ph: 972-3-5317638 FAX: 972-3-7384051 |
Hi,
On Fri, 19 Aug 2011, Aryeh Weiss wrote: > On 8/19/11 1:06 PM, Johannes Schindelin wrote: > > > /* > > * This script scales all ROIs in the ROI Manager > > * > > * Note: since the scaling is performed using integers, > > * upscaling leads to step artifacts. > > */ > > > > function cloneIntArray(array) { > > result = new java.lang.reflect.Array.newInstance(java.lang.Integer.TYPE, > > array.length); > > System.arraycopy(array, 0, result, 0, array.length); > > return result; > > } > > > > function scaleROI(roi, factor) { > > var type = roi.getType(); > > var bounds = roi.getBounds(); > > var n = 0; > > var x = null; > > var y = null; > > if (type == roi.RECTANGLE || type == roi.OVAL) { > > n = 2; > > x = [ 0, bounds.width ]; > > y = [ 0, bounds.height ]; > > } > > else if (type>= roi.FREEROI&& type<= roi.FREELINE&& type != roi.LINE) { > > n = roi.getNCoordinates(); > > x = cloneIntArray(roi.getXCoordinates()); > > y = cloneIntArray(roi.getYCoordinates()); > > } > > else { > > IJ.log("Unhandled ROI type: " + type); > > throw new Exception("Unhandled ROI type: " + type); > > } > > > > for (var i = 0; i< n; i++) { > > x[i] = (x[i] + bounds.x) * factor; > > y[i] = (y[i] + bounds.y) * factor; > > } > > > > if (type == roi.RECTANGLE) > > return new Roi(x[0], y[0], x[1] - x[0], y[1] - y[0]); > > else if (type == roi.OVAL) > > return new OvalRoi(x[0], y[0], x[1] - x[0], y[1] - y[0]); > > else if (type>= roi.FREEROI&& type<= roi.FREELINE&& type != roi.LINE) > > return new PolygonRoi(x, y, n, type); > > else > > throw new Exception("Unhandled ROI type: " + type); > > } > > > > var factor = IJ.getNumber("Factor", 0.5); > > > > var roiManager = RoiManager.getInstance(); > > if (roiManager == null) > > roiManager = new RoiManager(); > > > > var count = roiManager.getCount(); > > var list = roiManager.getList(); > > var rois = roiManager.getROIs(); > > var roiList = new Array(); > > for (var i = 0; i< count; i++) > // get slice info for the current ROI > roiSlice[i] = > roiManager.getSliceNumber(RoiManager.getName(Integer.toString(i))); > > > roiList[i] = scaleROI(rois.get(list.getItem(i)), factor); > > > > var selected = list.getSelectedIndexes(); > > IJ.log("selected: " + selected.length); > > roiManager.runCommand("Select All"); > > roiManager.runCommand("Delete"); > > for (var i = 0; i< count; i++) > // select the slice to which to write the new ROI > IJ.getImage().setSlice(roiSlice[i]); > > > roiManager.addRoi(roiList[i]); > > > > if (selected != null) > > roiManager.setSelectedIndexes(selected); > > > > Hi Johannes and again, thank you for your reply and script. > > It had one problem, in that it wrote all of the ROIs back to the > whatever slice was selected in the active image. I worked around this by > adding the two lines of code interleaved into your script, above. Yes, that works for the moment... > These preserve the slice info, but of course they assume that there is a > stack open with a sufficient number of slices. > > However, it would be better if the roimanager API allowed the slice info > to be written to the roimanager without selection of the slice in the > active image. Ah yes, probably a better way (which also preserves other names) would be to abuse the fact that you get the Hashtable and the List. So something like this should work: roiManager.getROIs().put(label, roi); roiManager.getList().setItem(roiManager.getCount() - 1, label); But actually, it would probably be easier to replace in-place. Rather than Select All followed by Delete and then addRoi(), this should work, too: roiManager.getROIs().put(roiManager.getList().getItem(index), roi); But I did not find a non-hacky way to force an update of what is displayed... :-( Ciao, Johannes |
On 8/19/11 4:49 PM, Johannes Schindelin wrote:
> Hi, > > On Fri, 19 Aug 2011, Aryeh Weiss wrote: > >> On 8/19/11 1:06 PM, Johannes Schindelin wrote: >> >>> /* >>> * This script scales all ROIs in the ROI Manager >>> * >>> * Note: since the scaling is performed using integers, >>> * upscaling leads to step artifacts. >>> */ >>> >>> function cloneIntArray(array) { >>> result = new java.lang.reflect.Array.newInstance(java.lang.Integer.TYPE, >>> array.length); >>> System.arraycopy(array, 0, result, 0, array.length); >>> return result; >>> } >>> >>> function scaleROI(roi, factor) { >>> var type = roi.getType(); >>> var bounds = roi.getBounds(); >>> var n = 0; >>> var x = null; >>> var y = null; >>> if (type == roi.RECTANGLE || type == roi.OVAL) { >>> n = 2; >>> x = [ 0, bounds.width ]; >>> y = [ 0, bounds.height ]; >>> } >>> else if (type>= roi.FREEROI&& type<= roi.FREELINE&& type != roi.LINE) { >>> n = roi.getNCoordinates(); >>> x = cloneIntArray(roi.getXCoordinates()); >>> y = cloneIntArray(roi.getYCoordinates()); >>> } >>> else { >>> IJ.log("Unhandled ROI type: " + type); >>> throw new Exception("Unhandled ROI type: " + type); >>> } >>> >>> for (var i = 0; i< n; i++) { >>> x[i] = (x[i] + bounds.x) * factor; >>> y[i] = (y[i] + bounds.y) * factor; >>> } >>> >>> if (type == roi.RECTANGLE) >>> return new Roi(x[0], y[0], x[1] - x[0], y[1] - y[0]); >>> else if (type == roi.OVAL) >>> return new OvalRoi(x[0], y[0], x[1] - x[0], y[1] - y[0]); >>> else if (type>= roi.FREEROI&& type<= roi.FREELINE&& type != roi.LINE) >>> return new PolygonRoi(x, y, n, type); >>> else >>> throw new Exception("Unhandled ROI type: " + type); >>> } >>> >>> var factor = IJ.getNumber("Factor", 0.5); >>> >>> var roiManager = RoiManager.getInstance(); >>> if (roiManager == null) >>> roiManager = new RoiManager(); >>> >>> var count = roiManager.getCount(); >>> var list = roiManager.getList(); >>> var rois = roiManager.getROIs(); >>> var roiList = new Array(); >>> for (var i = 0; i< count; i++) >> // get slice info for the current ROI >> roiSlice[i] = >> roiManager.getSliceNumber(RoiManager.getName(Integer.toString(i))); >> >>> roiList[i] = scaleROI(rois.get(list.getItem(i)), factor); >>> >>> var selected = list.getSelectedIndexes(); >>> IJ.log("selected: " + selected.length); >>> roiManager.runCommand("Select All"); >>> roiManager.runCommand("Delete"); >>> for (var i = 0; i< count; i++) >> // select the slice to which to write the new ROI >> IJ.getImage().setSlice(roiSlice[i]); >> >>> roiManager.addRoi(roiList[i]); >>> >>> if (selected != null) >>> roiManager.setSelectedIndexes(selected); >>> >> >> Hi Johannes and again, thank you for your reply and script. >> >> It had one problem, in that it wrote all of the ROIs back to the >> whatever slice was selected in the active image. I worked around this by >> adding the two lines of code interleaved into your script, above. > > Yes, that works for the moment... > >> These preserve the slice info, but of course they assume that there is a >> stack open with a sufficient number of slices. >> >> However, it would be better if the roimanager API allowed the slice info >> to be written to the roimanager without selection of the slice in the >> active image. > > Ah yes, probably a better way (which also preserves other names) would be > to abuse the fact that you get the Hashtable and the List. So something > like this should work: > > roiManager.getROIs().put(label, roi); > roiManager.getList().setItem(roiManager.getCount() - 1, label); > > But actually, it would probably be easier to replace in-place. Rather than > Select All followed by Delete and then addRoi(), this should work, too: > > roiManager.getROIs().put(roiManager.getList().getItem(index), roi); > > But I did not find a non-hacky way to force an update of what is > displayed... :-( > > Ciao, > Johannes > Yes -- this works. Here is the relevant modified section: var count = roiManager.getCount(); var list = roiManager.getList(); var rois = roiManager.getROIs(); var roiSlice; var currentROI; for (var i = 0; i < count; i++){ roiSlice = roiManager.getSliceNumber(RoiManager.getName(Integer.toString(i))); currentROI = scaleROI(rois.get(list.getItem(i)), factor); currentROI.setPosition(roiSlice); roiManager.getROIs().put(roiManager.getList().getItem(i), currentROI); } It would be more correct to use the getZPosition/getTPosition/getCPosition methods to properly handle hyperstacks, but the idea is clear. Thank you for pointing out this possibility. Best regards, --aryeh -- Aryeh Weiss School of Engineering Bar Ilan University Ramat Gan 52900 Israel Ph: 972-3-5317638 FAX: 972-3-7384051 |
Free forum by Nabble | Edit this page |