Plugin not executed from Jython in headless mode


#1

Hey all,

please help me, I have tried endless variations to call my Plugin from Jython in headless mode and it just won’t execute. The Plugin is supposed to modify a Dataset, this is just a minimized example.

This is the Plugin code:

package mpicbg.csbd.commands;

import net.imagej.Dataset;
import org.scijava.command.Command;
import org.scijava.plugin.Parameter;
import org.scijava.plugin.Plugin;

@Plugin( type = Command.class, menuPath = "Plugins>Debug>LogTest" )
public class TestPlugin implements Command {

	@Parameter
	private Dataset imp;

	@Override
	public void run() {
		System.out.println("LOGTEST");
	}
}

This is the Jython script:

from ij import IJ
path = "input.tif"
IJ.open(path)
IJ.run("LogTest", "")
IJ.save(path)

This Terminal command prints the expected LOGTEST output ( = executes the Plugin)…

./ImageJ-linux64 --ij2 --run script.py

… whereas this command doesn’t execute the command:

./ImageJ-linux64 --ij2 --headless --run script.py

I also tried the IJ2 approach:

# @IOService io
# @OpService op

from ij import IJ
path = "input.tif"
imp = io.open(path)
op.run("LogTest", imp)
io.save(imp, path)

… leading to this:

java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: No candidate 'LogTest' ops`

Do I have to register the Plugin somehow? Also tried CommandService but that also wasn’t successful.

Any ideas?


Saving Plugin / Command result from Jython script to file
#2

The command you’re using here all rely on a current image being open and active. While I would have expected it to still run in headless mode, this might be a reason why it doesn’t work as expected.

You could try:

imp = IJ.openImage(path)
IJ.run(imp, "LogTest", "")
...

Note that your plugin is a Command, not an Op. In order to run it, you should use the CommandService:

commandService.run(TestPlugin.class, true, "imp", imp).get()

BTW, it’s a bit confusing that you name this parameter imp, as this identifier is used throughout the IJ1 universe to specify an ImagePlus. How about using dataset, input or img instead? :wink:


#3

Thanks @imagejan, still not able to run it, I’m sorry.

Tried it, doesn’t execute the command either.

Looks good, but how do I tell it where to look for TestPlugin? I get NameError: name 'TestPlugin' is not defined and I cannot find a way to add my package path there. It’s located under mpicbg.csbd.commands.TestPlugin and tried these variations:

from mpicbg.csbd.commands import LogTest
import mpicbg.csbd.commands.LogTest

which results in ImportError: No module named mpicbg.

I build my Plugin like this:

mvn -Dimagej.app.directory=/home/user/Programs/Fiji.app -Ddelete.other.versions=true

…which puts the jar into the jars folder, but I also copied it to plugins to test if that helps. The module is still not found.

Btw. the naming of the Dataset is just temporary, not what I call it in my real Plugin, but good to know :wink:


#4

Does TestPlugin have a proper package declaration (it’s missing in the excerpt above)?

Also, you can (for additional safety) declare @Plugin( headless = true, ...) on TestPlugin.


#5

That looks to me like a classpath issue then…

What puzzles me is the fact that it runs fine for you when not using the --headless flag, right?


What’s the output of the command below on your system?

./ImageJ-linux64 --ij2 --headless --console --dry-run

The plugins directory is only needed for IJ1-style plugins, containing a plugins.config file inside the jar. Both jars and plugins are on the classpath if you use the launcher to start ImageJ.


#6

Thanks! It has a package declaration (will update the code, sorry, forgot to copy) and I added the headless attribute, no difference.


#7
java -Dpython.cachedir.skip=true -Dplugins.dir=/media/data_ssd/Programs/Fiji.app -Xmx20984m -Djava.awt.headless=true -Dapple.awt.UIElement=true -Djava.class.path=/media/data_ssd/Programs/Fiji.app/jars/imagej-launcher-4.0.5.jar -Dimagej.dir=/media/data_ssd/Programs/Fiji.app -Dij.dir=/media/data_ssd/Programs/Fiji.app -Dfiji.dir=/media/data_ssd/Programs/Fiji.app -Dfiji.defaultLibPath=lib/amd64/server/libjvm.so -Dfiji.executable=./ImageJ-linux64 -Dij.executable=./ImageJ-linux64 -Djava.library.path=/usr/local/cuda-8.0/lib64/:/media/data_ssd/Programs/Fiji.app/lib/linux64:/media/data_ssd/Programs/Fiji.app/mm/linux64 -Dscijava.context.strict=false net.imagej.launcher.ClassLauncher -ijjarpath jars -ijjarpath plugins net.imagej.Main

Without headless flag it runs in one scenario, in the others not, sorry, wasn’t precise here.
These are the different scenarios without headless flag:

path = "input.tif"
IJ.open(path)
IJ.run("LogTest", "")
IJ.save(path)

-> works (launches ImageJ, opens image, prints LOGTEST)

path = "input.tif"
imp = IJ.openImage(path)
IJ.run(imp, "LogTest", "")
IJ.save(imp, path)

-> results in ImageJ launching and a Popup saying "imp" is required but unset.

# @CommandService command
path = "input.tif"
imp = io.open(path)
imp = command.run(TestPlugin.class, true, "imp", imp).get()
io.save(imp, path)

-> same ImportError: No module named mpicbg


#8

Just out of curiosity: can you import in a Groovy script?

import mpicbg.csbd.commands.LogTest;

If so, that points to a general issue with your classpath and not Jython per se.

Also:

from mpicbg.csbd.commands import TestPlugin;
command.run(TestPlugin.class, true, "imp", imp).get(); # syntax wrong
command.run(TestPlugin, True, "imp", imp).get(); # works for me (but that's the next step)

#9

I’d say that’s good news, because it actually started your plugin :slight_smile: the problem is just that then your variable imp doesn’t contain an image :worried:
so just to be sure: is the image path correct in your tests? what does print imp say?

Thanks @stelfrich for pointing out the correct Python syntax. I’ve been using too much Groovy these days… but then you should leave away the semicolons, to be picky : )


#10

Just had a look at it now… The import class had indeed the wrong name and the command call now also works with this syntax. I still don’t completely understand why the IJ1 version does not work in headless mode, but I got a running script. Thank you!! :slight_smile: