Problem with Groovy Script

I am trying to write a groovy script to process a particle analysis workflow. I have run into two problems:

  1. I want to close any open Results and ROI manager windows at the beginning. The call on lines 44-47 work fine at the end where the windows are sure to be there. I want to run this at the beginning to get rid of any old windows from previous results and can’t figure out the syntax for the function to ignore cases where the windows are not there.

  2. I want to add the ROIs to the my final working image, “Blobs” and flatten to burn the overlay in before writing a .png file. I can’t get the call at line 39 right.

I am pasting the script file below:

import loci.formats.FormatTools
import loci.formats.ImageTools
import loci.common.DataTools

import ij.IJ
import ij.ImagePlus
import ij.ImageStack
import ij.process.ByteProcessor
import ij.process.ShortProcessor
import ij.plugin.frame.RoiManager
import ij.measure.ResultsTable
import ij.WindowManager

/*
 * For now be sure to close any open ROI Manager and Results windows before running
 */
 
IJ.log("\\Clear")
IJ.run("Close All")
IJ.run("Blobs (25K)")
imp = IJ.getImage()
imp.setTitle("Blobs")
imp.show()
IJ.run("8-bit")
IJ.run("Duplicate...", "title=work")
work = IJ.getImage()
work.setTitle("Work")
IJ.run(work, "Auto Threshold", "method=Default")
IJ.run("Convert to Mask")
IJ.run("Watershed")
IJ.run(work, "Analyze Particles...", "size=10-Infinity pixel display clear add summarize")

IJ.selectWindow("Summary")
IJ.run("Close")

IJ.selectWindow("Blobs")

/* 
roiManager("Show All with labels")
IJ.run("Flatten")



IJ.selectWindow("Results")
IJ.run("Close")
IJ.selectWindow("ROI Manager")
IJ.run("Close")

*/

Hi @John_Minter, sorry for the delayed reply.

Great to hear this!

I have a few comments:

You’re relying on the image that is currently open in the GUI here. A great feature of the scripting languages (other than IJ1 macro) is that they can keep references to images in variables, and therefore don’t have to rely on any “active image”, which makes them much less prone to race conditions (where e.g. the wrong image is picked up because some process producing an image is not yet finished, etc…).

If interacting with the active windows of the user interface (i.e. images, the ROI manager, the results table, etc.), I very much recommend using the IJ1 macro language. When using a full-fledged language (Python or Groovy alike), try to make yourself independent of UI calls like the one above.

Note that also the IJ.run("...") commands you’re using here act on the current image. If you use the macro recorder (e.g. in Beanshell mode, which records syntax mostly compatible with both Python and Groovy, because most commands are calls into the Java API anyhow), the recorded commands usually use a different IJ.run() method signature that includes your target image as an ImagePlus variable as first argument:

IJ.run(imp, "8-bit")
[...]
IJ.run(imp, "Convert to Mask")
IJ.run(imp, "Watershed")

(the recorded command for Duplicate is different, because in some cases you can better have direct calls to the Java API).

If you keep these points in mind, your scripts can get much more robust (and again, this is true for all scripting languages, including Groovy and Python).

You can achieve this in two steps:

The following script snippet illustrates this:

#@ RoiManager rm
#@ ResultsTable rt

rm.reset()
rt.reset()
rt.show("Results")

Again, using the RoiManager API, you can get a list of ROIs, then add these to an Overlay (not directly to an ImagePlus, because it can only have one ROI at a time), add the Overlay to your ImagePlus object, and flatten the overlay. (I’m running out of time now, but will follow up with a script example soon.)

Feel free to follow up with a description of the higher-level goal you’re trying to achieve with your script, and I am certain someone here on the forum will offer more help.

Thanks, Jan. I really like running the macro recorder in beanshell mode. This makes it a lot easier to prototype a script. I’ll come back as I have more questions. The use of RoiManager and ResultsTable script parameter was also key.

#@ RoiManager rm
#@ ResultsTable rt

I managed to construct groovy particle analysis script using the input you gave me that also cleans up at the end. I thought I would share it below… Any constructive criticism is welcome…

I do have one more question: Do you have any advice on how to keep a file of with groovy functions in a library directory that could be imported into working scripts. I was able to do this with python by putting the python file with the scripts in Fiji.app/jars/Lib directory and importing the function in python like

import jmFijiGen as jmg

Is there a similar ability in groovy?

Here is my working example goovy script:

#@ RoiManager rm
#@ ResultsTable rt
// start with imports
import ij.*
import ij.plugin.*

def fix_inverted_lut(imp){
	/* fix_inverted_lut(imp)
	 *  
	 *  Convert an image with an inverted LUT to a standard
	 *  8-bit grayscale image
	 *  
	 *  Parameters
	 *  ==========
	 *  imp		ImagePlus
	 *  	The 8 bit grayscale image with the inverted LUT
	 *  
	 *  Returns
	 *  =======
	 *  imp_new	ImagePlus
	 *  	The image with a standard 8-bit image w a gray LUT
	 * 
	 *
	 */
	title = imp.getTitle()
	imp_new = new Duplicator().run(imp)
	IJ.run(imp_new, "Grays", "")
	IJ.run(imp_new, "Invert", "")
	imp_new.setTitle(title)
	imp_new.show()
	return imp_new
}
// The main script
IJ.run("Close All")
imp = IJ.openImage("http://imagej.nih.gov/ij/images/blobs.gif")
imp = fix_inverted_lut(imp)
imp_new = new Duplicator().run(imp)
imp_new.setTitle("work")
IJ.run(imp_new, "Auto Threshold", "method=Default")
IJ.run(imp_new, "Watershed", "")
imp_new.show()
IJ.run("Set Measurements...", "area mean modal min centroid center perimeter bounding fit shape display redirect=None decimal=3")
IJ.run(imp_new, "Analyze Particles...", "size=100-100000 circularity=0.50-1.00 show=Overlay display exclude clear add")
rt.show("Results")
rm.show()
rm.moveRoisToOverlay(imp)
imp2 = imp.flatten()
imp2.show()
IJ.saveAs(imp2, "PNG", "/Users/jrminter/Desktop/blobs-segmented.png")
IJ.saveAs("Results", "/Users/jrminter/Desktop/blobs-results.csv")
imp.changes = false
imp.close()
imp2.changes = false
imp2.close()
imp_new.changes = false
imp_new.close()
rt.reset()
rm.reset()
IJ.selectWindow("Results")
IJ.run("Close")
IJ.selectWindow("ROI Manager")
IJ.run("Close")

1 Like