Thread/timing issues with the ImageJ ImageCalculator.run method in javascript

I an encountering several issues when calling the ImageCalculator run method in a javascript in Fiji. I would appreciate any feedback.

1. The following javascript completes without generating a Result window:

importClass(Packages.ij.gui.NewImage);
importClass(Packages.ij.plugin.ImageCalculator);
importClass(Packages.java.awt.Color);
		
var image1 = NewImage.createShortImage("image1", 500, 500, 100, NewImage.FILL_RANDOM);
var image2 = NewImage.createShortImage("image2", 500, 500, 100, NewImage.FILL_RANDOM);

var ic = new ImageCalculator();
ic.run("subtract create stack", image1, image2);

image1.close();
image2.close();

I don’t understand this behavior since I would expect the script execution to stop, until ic.run completes and shows a “Result of image1” window. It appears as if ic.run spawns a separate thread (like when one calls it in an ImageJ macro). Note that if I remove the last two lines a result window appears normally.

2. Even more bizarre, a result window does not appear in the following code variant, which should be harmless even if ic.run does spawn a separate thread:

importClass(Packages.ij.gui.NewImage);
importClass(Packages.ij.plugin.ImageCalculator);
importClass(Packages.java.awt.Color);
importClass(Packages.ij.IJ);
		
var image1 = NewImage.createShortImage("image1", 500, 500, 100, NewImage.FILL_RANDOM);
var image2 = NewImage.createShortImage("image2", 500, 500, 100, NewImage.FILL_RANDOM);

var ic = new ImageCalculator();
ic.run("subtract create stack", image1, image2);

IJ.wait(1000);

If I remove IJ.wait(1000) a result window appears normally.

3. Obviously my goal is to be able to further process the result of the stack subtraction. To do that I would adopt this strategy:

importClass(Packages.ij.gui.NewImage);
importClass(Packages.ij.plugin.ImageCalculator);
importClass(Packages.java.awt.Color);
importClass(Packages.ij.IJ);
importClass(Packages.ij.WindowManager);
		
var image1 = NewImage.createShortImage("image1", 500, 500, 100, NewImage.FILL_RANDOM);
var image2 = NewImage.createShortImage("image2", 500, 500, 100, NewImage.FILL_RANDOM);

var ic = new ImageCalculator();
ic.run("subtract create stack", image1, image2);

while(!WindowManager.getImage("Result of image1")) {
    IJ.wait(1000);
}

However, a result window is never shown!

The problem here is that you’re trying to rely on the user interface (i.e. an image window being shown) in a script that should be independent on any graphical UI.

From my experience, I’d suggest the following “rules”:

  • If you want (or need) to rely on the graphical user interface (GUI), stick to the IJ1 macro language. It makes sure that every command you run works on the currently active image.

  • If you use any of the more powerful script languages, you should make your script independent of any GUI events.

Have a look at the javadoc of ImageCalculator; its run() method returns an ImagePlus that you can use in your code, without ever calling WindowManager.getImage() or some such.

run

public ImagePlus run(String params, ImagePlus img1, ImagePlus img2)

Your can just get the result of your calculation like this:

var ic = new ImageCalculator();
var result = ic.run("subtract create stack", image1, image2);

EDIT:

Just to explain the behavior you describe above:

  • Your call to ic.run("subtract create stack", image1, image2); simply never shows an image window (it returns an ImagePlus object, but it’s your responsibility to call its show() method if you really want to have it displayed).
  • The fact the an image is displayed when you remove the last lines is due to the SciJava script post-processing: if the last line of any script has a return value (and ic.run does), SciJava/ImageJ will try to display it in the UI, once the script has finished.
1 Like

I must apologise here: I completely missed the fact that run returns an ImagePlus! Also, thanks for explaining the ‘apparently’ inconsistent behavior… It all makes sense now.