Weka Segmentation Script on Linux Machine Headless

Dear all,

I want to run WekaSegmentation in headless mode without GUI on a Linux machine (connected via ssh). The Macro I wrote (ImageJ Macro language) should just open an Image file, apply a classifier and safe the result. I always get this error:

Loading Weka properties…
WARNING: core mtj jar files are not available as resources to this classloader (sun.misc.Launcher$AppClassLoader@764c12b6)
java.awt.HeadlessException
at java.awt.GraphicsEnvironment.checkHeadless(GraphicsEnvironment.java:204)
at java.awt.List.(List.java:233)
at java.awt.List.(List.java:205)
at trainableSegmentation.Weka_Segmentation.run(Weka_Segmentation.java:1253)
at ij.IJ.runUserPlugIn(IJ.java:217)
at ij.IJ.runPlugIn(IJ.java:181)
at ij.Executer.runCommand(Executer.java:137)
at ij.Executer.run(Executer.java:66)
at ij.IJ.run(IJ.java:297)
at ij.IJ.run(IJ.java:272)
at ij.macro.Functions.doRun(Functions.java:603)
at ij.macro.Functions.doFunction(Functions.java:96)
at ij.macro.Interpreter.doStatement(Interpreter.java:230)
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:1069)
at net.imagej.legacy.IJ1Helper$4.call(IJ1Helper.java:1065)
at net.imagej.legacy.IJ1Helper.runMacroFriendly(IJ1Helper.java:999)
at net.imagej.legacy.IJ1Helper.runMacroFile(IJ1Helper.java:1065)
at net.imagej.legacy.LegacyCommandline$Macro.handle(LegacyCommandline.java:187)
at org.scijava.console.DefaultConsoleService.processArgs(DefaultConsoleService.java:102)
at net.imagej.legacy.LegacyConsoleService.processArgs(LegacyConsoleService.java:81)
at org.scijava.AbstractGateway.launch(AbstractGateway.java:95)
at net.imagej.Main.main(Main.java:55)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.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)
No window with the title “Trainable Weka Segmentation v3.2.20” found.

The command to run my script in Putty is as follows:

$ /homeb/…/Fiji.app/ImageJ-linux64 --headless -macro /homeb/…/MacroTest2.ijm

My Macro called MacroTest2.ijm goes as follows:

input = "/work/…/ImagesIn/"
output = “/work/…/ImagesOut/”;
filename= "11611_2461_1_1-1.tif"
open(input + filename);
run(“Trainable Weka Segmentation”);
selectWindow(“Trainable Weka Segmentation v3.2.20”);
call(“trainableSegmentation.Weka_Segmentation.loadClassifier”, “/work/…/classifiertest.model”);
call(“trainableSegmentation.Weka_Segmentation.getResult”);
saveAs(“Tiff”, output + filename);
close();

What is going wrong? I have to admit I am neither an expert with linux nor with java.

Thank you!

best,
Lars

Hi @ladida

when using ij-macro commands I struggled too to get things running…
Also if you want to run it headless, you cannot use the open command, since it will want to create an image display.

My suggestion would be to go for something like groovy to script this. An outline would look like

import ij.IJ
import trainableSegmentation.WekaSegmentation

img = IJ.openImage('path/to/image.tif');

classifier = new WekaSegmentation()
classifier.loadClassifier('/path/to/classifier.model')
res = classifier.applyClassifier(img, 0, false)

...

For reference:

Sorry for not helping to debug, but I think switching the language will actually be easier.

Felix

2 Likes

Thank you @FelixM !

Writing the code in beanshell was indeed a good idea. It is working now!

Best,
Lars

1 Like

Hey guys, I have a similar/related topic. So maybe one of you can help me before I start a new thread:

Trying to use the "exact"code in beanshell as “apply classifier to all images in folder” as suggested by @FelixM. Doing this on an ubuntu platform via ssh. I just downloaded the latest Fiji-linux64.zip and unpacked it in my homefolder. I then run:

./ImageJ-linux64 --headless -macro ~/…path…/Macros/WEKA_P3.bsh

Return:

Cannot instantiate headless dialog except in macro mode
Error while executing the main() method of class ‘net.imagej.Main’:
… full text here:
Error1.txt (1.8 KB)

I wasn´t sure if this is the proper way to call the script, so I tried (with the basically same result):

./ImageJ-linux64 --ij2 --headless --run ~/…path…/Macros/WEKA_P3.bsh
return:
Java HotSpot™ 64-Bit Server VM warning: ignoring option PermSize=128m; support was removed in 8.0
Java HotSpot™ 64-Bit Server VM warning: Using incremental CMS is deprecated and will likely be removed in a future release
[INFO] Reading available sites from https://imagej.net/

I would have expected an interactive dialogue to provide the directories for the script, as when I do in the windows GUI. I believe the Java should not be the problem, can you maybe help me figure out the problem? Feeling a bit … “headless” :sweat_smile:

java -version
openjdk version “1.8.0_222”
OpenJDK Runtime Environment (build 1.8.0_222-8u222-b10-1ubuntu1~16.04.1-b10)
OpenJDK 64-Bit Server VM (build 25.222-b10, mixed mode)

Best,

Adrian

Hi @Adrian_Schiefler

in case you have not a solution yet. The error message suggests, that it does not have the parameters for the script (first lines starting with ‘@’). But you can supply them in the command line: see notes on headless execution of scripts.

Hope that helps

Felix

Hi @FelixM,

thanks a lot for your reply and suggestion - looks rather “obvious” in hindsight :sweat_smile:

I tried and it seems I get the macro to run initially. But it breaks down when “getcanonicalpath” occurs:

Sourced file: inline evaluation of: ``inputDir = "/~/path/to/folder/...'' : Error in method invocation: Method getCanonicalPath() not found in class'java.lang.String' : at Line: 21 : in file: inline evaluation of: ``inputDir = "/~/path/to/folder/...'' : modelPath .getCanonicalPath ( )

So that looks like a java related problem after all. I’m sorry I understand still too little of Java and IJ2 vs Linux - do you maybe have another suggestion how to proceed - do I need to download some specific jars for the function to be understood?
The page you linked for headless considers IJ1 but I submit on IJ2 as follows, in case that changes the case:

./ImageJ-linux64 --ij2 --headless --run Macro.bsh

I also ran a general update on the command line and got the Imagscience jars for Weka:

~/Fiji.app$ ./ImageJ-linux64 --update update
~/Fiji.app$ ./ImageJ-linux64 --update update jars/imagescience.jar

Many thanks and kind regards,

Adrian

Hi @Adrian_Schiefler

Try to write the full path. Java/Groovy do not understand ~. The equivalent would be System.getProperty("user.home")

Thanks for the quick reply @FelixM - and for helping me with these basics!!!

So I get it to run when supplying the path as “user/path/to/folder/” initially, but it broke down at the “.getCanonicalPath” command when loading the model file.

Error in method invocation: Method getCanonicalPath() not found in class'java.lang.String' : at Line: 23 : in file: inline evaluation of: ``inputDir = "user/path/ . . . '' : modelPath .getCanonicalPath ( )

Guess that should actually not be, but simply scrapping it worked and the path variable defined for the model was sufficient to load it (script file at the bottom). However in the subsequent “ListOfFiles” loop I get unspecified errors and I’m not quite sure what the issue is here:

[ERROR] null
In file: inline evaluation of: ``inputDir = "user/path . . . '' Encountered "listOfFiles" at line 26, column 1.

        at bsh.Parser.generateParseException(Parser.java:6106)
        at bsh.Parser.jj_consume_token(Parser.java:5977)
        at bsh.Parser.Statement(Parser.java:2699)
        at bsh.Parser.BlockStatement(Parser.java:2819)
        at bsh.Parser.Line(Parser.java:172)
        at bsh.Interpreter.Line(Interpreter.java:1011)
        at bsh.Interpreter.eval(Interpreter.java:641)
        at bsh.Interpreter.eval(Interpreter.java:750)
        at bsh.Interpreter.eval(Interpreter.java:739)
        at org.scijava.plugins.scripting.beanshell.BeanshellScriptEngine.eval(BeanshellScriptEngine.java:68)
        at org.scijava.script.ScriptModule.run(ScriptModule.java:160)
        at org.scijava.module.ModuleRunner.run(ModuleRunner.java:168)
        at org.scijava.module.ModuleRunner.call(ModuleRunner.java:127)
        at org.scijava.module.ModuleRunner.call(ModuleRunner.java:66)
        at org.scijava.thread.DefaultThreadService$3.call(DefaultThreadService.java:238)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

.getCanonicalPath reoccurs but I couldn’t manage to replace it successfully. Guess it is some simple syntax/definition issue again and might be easily solved with rudimentary knowledge or a debugger interface(?) - which I both don’t have. Would be great if you could help me with it!

Adrian

The script as i tried to use below.
script.txt (1.9 KB)

if this above is the exact script you tried, you will need to edit the first three lines and give it paths to files that actually exist in your local filesystem.