How to stop the results window from stealing focus during batch jobs

I have a macro in Fiji that shading corrects images, processes these, and performs other steps to count cells in stacks and output results as a.csv file. It is set up to work through the wells of a 96-well plate. I call setBatchMode(true) ;
at the beginning and
setBatchMode(false);
at the end.

In this macro, two Results windows are maintained. The first is created when Analyze Particles is called and the second is used to hold the tabulated results from each well. I use IJ.renameResults to maintain the contents of the results windows correctly.

The issue I am having is that, because Results windows are displayed, even in batch mode, the Results window grabs focus repeatedly while the macro runs, so that any key strokes I input into another application (like Chrome, or whatever) are trapped and applied to the Results window, often generating an error message in the macro.
This means that I cannot get any other work done on my computer while my macro runs.

This problem seems to cry out for running the macro in headless mode, which I have never done.
Instead of getting input from the user, I need to pass the following parameters in the command line: 1) the fully qualified name of a shading image; 2) the directory where the input files are; 3) the single letter string corresponding to the row of the 96 well plate that contains the control cells.

I have looked at the documentation for running a macro in headless mode, but can’t figure out a) how to pass parameters; b) how to link the parameters passed in the command line to the correct variables in the macro.

For example, instead of:
FlatFieldPath= File.openDialog(“Select the flat field image”);
open(FlatFieldPath) ;
flatfield = getTitle ;

How do I assign the fully qualified name of the flat field image that has been supplied in the command line to FlatFieldPath?

Many thanks to all for any help.

Hi @jmarks, welcome to the forum.

As you say, this is really crying out for running headless.

There’s an example on how to pass parameters from the command line to a macro here:


Let us know how it goes / if that’s what you’re looking for.

Good luck!

PS. This thread has some more details:

1 Like

Thanks so much for reading my very long post.

Before posting my question, I had already read the links you suggested, but remained confused.
I also found Running plugins/macros from the command line, which I quote:

With this macro saved as C:\Fiji.app\macros\Test.ijm:

filelist = getArgument();
file = split(filelist,’#’);
open(file[0]);
run(“Invert”);
saveAs(“Tiff”, file[1]);
close();
run(“Quit”);

and this command line:
> java -jar c:\Fiji.app\jars\ij-1.50b.jar -ijpath c:\Fiji.app -macro Test D:\In.tif#D:\Out2.tif

It runs the macro, which loads D:\In.tif, inverts it, saves it as D:\Out2.tif, and then closes ImageJ/Fiji.

However, the macro file and the syntax to pass parameters looks different from what you pointed me to.

To focus on what you suggested:

The example command line call to run IJ headless with parameters is (bolded emphasis on the parameter calling section):

./ImageJ-win64.exe -headless --console -macro ./RunBatch.ijm ‘folder=…/folder1 parameters=a.properties output=…/samples/Output’

My questions below about this example outline the depths of my confusion. Assume that my macro is called MyMacro.ijm:

  1. I don’t understand the mention of a RunBatch.ijm file. Is this a small macro that collects parameters and then passes them to MyMacro.ijm? Or is this a placeholder for MyMacro.ijm?

  2. In a command line call to run IJ headless, the 3 parameters I want to pass should be contained in a single string - with a variable assigned to whatever is after the = sign. Is this correct?

3a. I don’t understand the section parameters = a.properties. How is a.properties populated?

  1. The next questions concerns the code in the example RunBatch.ijm file

arg = getArgument()
print(“Running batch analysis with arguments:”)
print(arg)
run(“Batch process”, arg )
print(“Done.”)
eval(“script”, “System.exit(0);”);

I can see that

getArgument()

grabs the parameter string. However,

run(“Batch process”, arg)

passes the parameter string to “Batch process”. But where is MyMacro.ijm called?

You can see the pitiful depths of my confusion. My apologies for the request for the kindergarten explanation. In this case, Google has not been my friend.

Many, many thanks.

Always happy to help, but I wasn’t sure the level at which your misunderstandings were. Actually, I got confused myself looking at that example, so I’m going to forget it for now and we’ll work with a different example that I hope will clear things up.

Quick diversion: I would recommend that whatever your macro does, it assume that the image(s) it needs are already open, and also have it not worry about saving the results - we’ll write a “wrapper macro” that will do those things.

The arguments can be whatever you like, so long as the macro understands what to do with them.

Below is a macro that does the following:

  1. Loads an image according to the passed command line arguments
  2. Runs another (fixed) macro
  3. Saves the result at location specified by the command line arguments

Let’s call it ‘ReadWorkSave.ijm’

arg = getArgument()
args = split( arg, ",")
print( args[0] )
print( args[1] )
open( args[0] )
runMacro( "/Users/bogovicj/Documents/imagej/DoSomeWork.ijm" )
save( args[1] )
print( "done" )
eval("script", "System.exit(0);");

The split function breaks a String into substrings based on a delimiter you specify (I picked comma), meaning that you can pass one string and the macro will break it up for you. My plan was to give it the input and output file paths like this:

/Users/bogovicj/tmp/boats.tif,/Users/bogovicj/tmp/boats_edges.tif

After split

args[0]="/Users/bogovicj/tmp/boats.tif"
args[1]="/Users/bogovicj/tmp/boats_edges.tif"

Notice that the macro then just loads and saves to these paths ( we didn’t need the equal signs or any of the other formatting particulars that the other macro used ).

There, I’m assuming that the macro that does what you care about is called ‘DoSomeWork.ijm’ - for my testing it contains this:

run("Find Edges");

I ran this (I’m on a mac right now):

 /Applications/Fiji.app/Contents/MacOS/ImageJ-macosx --headless --console -macro `pwd`/ReadWorkSave.ijm '/Users/bogovicj/tmp/boats.tif,/Users/bogovicj/tmp/boats_edges.tif'

and it loaded boats.tif, found the edges, and saved it to boats_edges.tif

I hope this helps! Post back to let us know how it goes, and good luck :four_leaf_clover:

P.S. I assumed above that the macro you care about has one input and one output (if that’s not the case, its a bit more complicated, but not too much).

3 Likes

This is terrific! Very clear and seems very straightforward.
I will try your macro first to make sure that I get the command line syntax right on my windows machine (not sure that I need theconsole switch)

What is the pwd in the command line call? Is it a switch?

There is documentation on command line syntax for IJ1, but I can’t find a list of the switches (like --headless -macro)
Sure would be nice to have.

Glad to hear!

Oh, ‘pwd’ is a command to “print working directory” on Unix-like systems OS’s. It may not have been necessary for me to have that there.

Agree with you on the documentation front…

Well, I have made good headway, but have run into a road block.
I have made the following progress:

  1. successfully called simple macros in headless mode typing into the command line
  2. written a tiny macro that collects the parameters to be passed to the macro that I want to run in headless mode from the user, and generate a functioning batch file
  3. run the batch file that starts Fiji headless and runs the small macro.

Now, I have modified my complex macro to start with

arg = getArgument() ;

and then assigned the parameters to the correct variables.Using standard console print commands to the DOS window, I can see that the macro correctly opens and processes the files correctly. Hurray!:grinning:

Here is the problem:
the machine blows up with any call to roiManager, whether it is
roiManager("reset"), or
roiManager(("count"). or
roiManager("Select", j) ;

This is a complete game stopper for running this macro headless.

However, since I successfully call

run("Analyze Particles...", "size=10-Infinity pixel circularity=0.70-1.00 add);

the machine doesn’t seem to mind adding the particles to roiManager.

The error text follows. Any interpretation would be much appreciated. Perhaps I should start a new topic.

java.awt.HeadlessException
        at java.awt.GraphicsEnvironment.checkHeadless(GraphicsEnvironment.java:2
04)
        at java.awt.Window.<init>(Window.java:536)
        at java.awt.Frame.<init>(Frame.java:420)
        at ij.plugin.frame.PlugInFrame.<init>(PlugInFrame.java:13)
        at ij.plugin.frame.RoiManager.<init>(RoiManager.java:90)
        at ij.macro.Functions.roiManager(Functions.java:2748)
        at ij.macro.Functions.getFunctionValue(Functions.java:230)
        at ij.macro.Interpreter.getFactor(Interpreter.java:1385)
        at ij.macro.Interpreter.getTerm(Interpreter.java:1356)
        at ij.macro.Interpreter.getStringExpression(Interpreter.java:1496)
        at ij.macro.Interpreter.getStringTerm(Interpreter.java:1315)
        at ij.macro.Interpreter.getString(Interpreter.java:1272)
        at ij.macro.Interpreter.doStatement(Interpreter.java:281)
        at ij.macro.Interpreter.doBlock(Interpreter.java:608)
        at ij.macro.Interpreter.doStatement(Interpreter.java:272)
        at ij.macro.Interpreter.doFor(Interpreter.java:530)
        at ij.macro.Interpreter.doStatement(Interpreter.java:254)
        at ij.macro.Interpreter.doBlock(Interpreter.java:608)
        at ij.macro.Interpreter.doStatement(Interpreter.java:272)
        at ij.macro.Interpreter.doFor(Interpreter.java:530)
        at ij.macro.Interpreter.doStatement(Interpreter.java:254)
        at ij.macro.Interpreter.doBlock(Interpreter.java:608)
        at ij.macro.Interpreter.doStatement(Interpreter.java:272)
        at ij.macro.Interpreter.doFor(Interpreter.java:530)
        at ij.macro.Interpreter.doStatement(Interpreter.java:254)
        at ij.macro.Interpreter.doStatements(Interpreter.java:218)
        at ij.macro.Interpreter.run(Interpreter.java:115)
        at ij.macro.Interpreter.run(Interpreter.java:85)
        at ij.macro.Interpreter.run(Interpreter.java:96)
        at ij.plugin.Macro_Runner.runMacro(Macro_Runner.java:155)
        at ij.plugin.Macro_Runner.runMacroFile(Macro_Runner.java:139)
        at ij.IJ.runMacroFile(IJ.java:148)
        at net.imagej.legacy.IJ1Helper$4.call(IJ1Helper.java:1056)
        at net.imagej.legacy.IJ1Helper$4.call(IJ1Helper.java:1052)
        at net.imagej.legacy.IJ1Helper.runMacroFriendly(IJ1Helper.java:986)
        at net.imagej.legacy.IJ1Helper.runMacroFile(IJ1Helper.java:1052)
        at net.imagej.legacy.LegacyCommandline$Macro.handle(LegacyCommandline.ja
va:188)
        at org.scijava.console.DefaultConsoleService.processArgs(DefaultConsoleS
ervice.java:93)
        at net.imagej.legacy.LegacyConsoleService.processArgs(LegacyConsoleServi
ce.java:81)
        at org.scijava.AbstractGateway.launch(AbstractGateway.java:95)
        at net.imagej.Main.launch(Main.java:62)
        at net.imagej.Main.main(Main.java:68)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at net.imagej.launcher.ClassLauncher.launch(ClassLauncher.java:279)
        at net.imagej.launcher.ClassLauncher.run(ClassLauncher.java:186)
        at net.imagej.launcher.ClassLauncher.main(ClassLauncher.java:77)

Thanks so much!

1 Like

Thanks for the update and the detail - I can reproduce this behavior.

Thanks for checking so quickly. Should I post this issue as a new post to see if Curtis or others have a work-around?

Maybe, I’m not sure if this is an roi manager-specific issue, or something else.

@ctrueden, these roi-manager calls should be do-able while headless without this exception being thrown, right? :confused:

@bogovicj Very sorry for the delay in reply here. Just to tie things together for others who stumble across this thread:

The ROI Manager cannot work headless, since it extends PlugInFrame, and unlike GenericDialog, the ImageJ Legacy layer does not runtime patch it. This could potentially be added, but I have no bandwidth to do so myself this year.

See also these forum threads:

I have now filed an issue for this limitation:

3 Likes

A post was split to a new topic: How to batch process a directory of images