Silly Question

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Silly Question

Philip Ershler
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
Reply | Threaded
Open this post in threaded view
|

scaling ROI list

Aryeh Weiss
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
Reply | Threaded
Open this post in threaded view
|

Re: scaling ROI list

dscho
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);
Reply | Threaded
Open this post in threaded view
|

Re: scaling ROI list

Aryeh Weiss
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
Reply | Threaded
Open this post in threaded view
|

Re: scaling ROI list

dscho
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);
Reply | Threaded
Open this post in threaded view
|

Re: scaling ROI list

Aryeh Weiss
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++)
// 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.
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
Reply | Threaded
Open this post in threaded view
|

Re: scaling ROI list

dscho
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
Reply | Threaded
Open this post in threaded view
|

Re: scaling ROI list

Aryeh Weiss
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