Retrieving indices of multiple selected ROIs in a macro

roi-manager
imagej
roimanager

#1

Hi,

I’m stumbling over what is hopefully a simple problem. I’ve defined multiple ROIs in a series of images. From within a macro I’d like be able to extract the indices of a subset (>1) that have been manually selected in the ROI Manager. I’d like to save these indices to an array that I can use later in the macro. The roiManager("index”) function only “returns the index of the first selected ROI if more than one is selected”.

I’ve come across online documentation for “ij.plugin.frame.RoiManager.getSelectedIndexes”, “ij.plugin.frame.RoiManager.getIndexes”, “ij.plugin.frame.RoiManager.getSelectedRoisAsArray” which all seem like they would accomplish this task, but I haven’t had any success getting these functions to work in a macro using call(), eval(), or run(). Could that result from the ij/plugin/frame/RoiManager.java not having been installed with the basic ImageJ program (I’m working in 1.50i)?

Any suggestions for a work around or a way to get these functions working in a macro?

Thanks,
Trevor


#2

Good day Trrevor,

please study the commented list of ImageJ macro functions:
https://imagej.nih.gov/ij/developer/macro/functions.html

especially those related to the ROI-manager and from those:

roiManager(“select”, index)
Selects an item in the ROI Manager list, where index must be greater than or equal zero and less than the value returned by roiManager(“count”). Note that macros that use this function sometimes run orders of magnitude faster in batch mode. Use roiManager(“deselect”) to deselect all items on the list. For an example, refer to the ROI Manager Stack Demo macro.

HTH

Herbie


#3

Hi Herbie,

Thanks for your quick feedback and apologies that my question wasn’t clear. Here’s a pared down reproducible example of the workflow I’m trying to build.

   // the user selects a subset of ROIs (using the ROI Manager GUI interface)
    
       roiManager(“select”, newArray(4,6,8))


   // then runs a macro that modifies those selected ROIs (indexes 4,6,8)

      macro "Change ROI colors [c]" {

      // using the built-in macro functions I've only been able to retrieve the first of the three selected indexes (i.e., 4)

          col_indexes = newArray(1);
          col_indexes[0] = roiManager("index")
 
       // ideally I would like to retrieve all three indices and store them in an array
     
          //col_indexes = call("ij.plugin.frame.RoiManager.getSelectedIndexes");
  
       // then run a loop that modifies each ROI 
       // (for reproducibility this is a trivial example of just changing colors, 
       // but there are more complex things that I would like to do with the selected ROIs)    
  
       for (i=0;i<col_indexes.length;i+=1){ 
          
          // Select col_indexes[i] in ROI Manager
 
              roiManager("select",col_indexes[i])
           
          // Change some property of that ROI (in this case color)

              Roi.setStrokeColor("red")       
             
        }
 
      // reset selection to include all three indices after applying loop

         roiManager(“select”, col_indexes)
              
    }

Currently this macro only modifies the first of the selected ROIs (e.g., 4). Is there a way to get it to loop through all three selected ROIs (e.g., 4,6,8)?

Thanks,
Trevor


#4

Does this thread not answer your question?


#5

Good day Trevor,

I think I understand now, but I see no possibility to access the array of selected ROIs by using macro calls.

Regards

Herbie


#6

Here is an older thread with a workaround which requires user interaction:

http://imagej.1557.x6.nabble.com/Getting-a-list-of-indexes-of-selected-ROIs-td5013762.html

A bit more tricky would be to use a scripting language in the macro to get the selected ROI’s in the ROI Manager with the command eval()


#7

yes I usually do it with user interaction as in the thread cited by @eljonco.


#8

Here is another workaround that might do the job. Its probably similar to the solution just referred to a few minutes ago by @Bio7 (haven´t checked).

run("Close All");
run("Blobs (25K)");
makeRectangle(12, 19, 28, 30); roiManager("Add");
makeRectangle(72, 22, 37, 29); roiManager("Add");
makeRectangle(147, 31, 47, 28); roiManager("Add");
makeRectangle(12, 102, 39, 25); roiManager("Add");
makeRectangle(93, 105, 18, 32); roiManager("Add");
makeRectangle(179, 108, 37, 28); roiManager("Add");
roiManager("Show All");

roiManager("select", newArray(1,3,5));


roiManager("Combine");
roiManager("Add");
indexarray = newArray;
roicount = roiManager("Count");
for (i=0;i<roicount-1;i++){
	roiManager("select", i);
  //get center of mass of selected ROI
		List.setMeasurements;
  		xm = List.getValue("XM");
  		ym = List.getValue("YM");

	roiManager("select", roicount-1);
	if (selectionContains(xm, ym)==true) {	
		//add index to array
		indexarray = Array.concat(indexarray, i);
	} 
}

roiManager("select", roicount-1);
roiManager("delete");

print("indices of selected ROIs: ");
Array.print(indexarray);

for (j=0;j<indexarray.length;j++){
	roiManager("select", indexarray[j]);
	roiManager("Set Color", "red");
}

#9

Adding to @MartinH’s suggestion:
Analyze > Set Measurements: tick ‘Bounding rectangle’.
Get the number of rows in the Results window if open.
Check if at least one roi in the manager was selected.
Perform roiManager("Measure");
This will add to the Results window only measurements of selected rows in roiManager.
Get the new number of rows in Results window.
For the added rows in the Results window, match BX,BY with Roi.getBounds(x, y, width, height) of every ROI in the manager, add [the index of the] matching ones to an array for later processing.


#10

Thanks @MartinH for your input! Your workaround solution gets the job done. FYI - for anyone else using this approach it gets fairly slow when you have a large number of ROIs in the RoiManager. Thanks again! - Trevor


#11

Good day Trevor!

[…] this approach it gets fairly slow when you have a large number of ROIs in the RoiManager.

That’s the reason why I didn’t take it into account.

Regards

Herbie


#12

Thanks @Bio7 I’ve used the approach from this thread in several other macros and it works well, although it didn’t quite apply in the function I was trying to build. Thanks for your input!


#13

I´m happy that this proved to be useful.
Probably things can be sped up in batch mode. You already might have tried this though.
https://imagej.nih.gov/ij/macros/RoiManagerSpeedTest.txt


#14

@Wayne I created a feature request on Github:


#15

I was able to get an eval() working for what you want. BTW the call() wouldn’t work for RoiManager.getSelectedIndexes because it is not a static method, it has to be run on an instance of the RoiManager. So the code below gets the RoiManager instance, then gets the array. Unfortunately the eval() command can only return a String so we have to convert the array to a string. You may have to parseInt() each indexes afterward. e.g. parseInt(indexes[0]);

a=eval("script","java.util.Arrays.toString(RoiManager.getInstance().getSelectedIndexes())");
indexes=split(substring(a,1,lengthOf(a)-1),",");

#16

The latest ImageJ daily build (1.52a59) adds this macro-callable method to the RoiManager:

 public static String getIndexesAsString() {
    RoiManager rm = RoiManager.getInstance();
    if (rm==null) return "";
    String str = Arrays.toString(rm.getSelectedIndexes());
    str = str.replaceAll(",", "");
    return str.substring(1,str.length()-1);
 }

This example macro shows how to use it:

  indexes = split(call("ij.plugin.frame.RoiManager.getIndexesAsString"));
  for (i=0; i<indexes.length; i++)
     print("ROI "+indexes[i] + " is selected");