Saving Plugin / Command result from Jython script to file

imagej

#1

This is a follow up post, first part: Plugin not executed from Jython in headless mode

I am still having problems with the script syntax. The plugin returns an image that I want to save as a new file. I created a repository to demonstrate what I want to do:

I can save the image to the original location with this Jython code:

# @IOService io
# @CommandService command
# @ModuleService module

from my.test import TestPlugin

inpath = "/home/random/Development/imagej/plugins/fiji-plugin-script-example/script/blobs.tif"
myinput = io.open(inpath)
myfuture = command.run(TestPlugin, True, "input", myinput)
mymodule = module.waitFor(myfuture)
myoutput = mymodule.getOutput("output")
io.save(myoutput, inpath)

… but I cannot save it to a yet non existing file. Script code:

# @IOService io
# @CommandService command
# @ModuleService module

from my.test import TestPlugin

inpath = "/home/random/Development/imagej/plugins/fiji-plugin-script-example/script/blobs.tif"
outpath = "/home/random/Development/imagej/plugins/fiji-plugin-script-example/script/out.tif"
myinput = io.open(inpath)
myfuture = command.run(TestPlugin, True, "input", myinput)
mymodule = module.waitFor(myfuture)
myoutput = mymodule.getOutput("output")
io.save(myoutput, outpath)

Error message:

[ERROR] null
Traceback (most recent call last):
  File "/home/random/Development/imagej/plugins/fiji-plugin-script-example/script/run-plugin.py", line 15, in <module>
    io.save(myoutput, outpath)
	at io.scif.io.VirtualHandle.read(VirtualHandle.java:83)
	at io.scif.io.RandomAccessInputStream.read(RandomAccessInputStream.java:437)
	at io.scif.formats.KontronFormat$Checker.isFormat(KontronFormat.java:124)
	at io.scif.AbstractChecker.isFormat(AbstractChecker.java:93)
	at io.scif.services.DefaultFormatService.getFormatList(DefaultFormatService.java:342)
	at io.scif.services.DefaultFormatService.getFormat(DefaultFormatService.java:317)
	at io.scif.services.DefaultDatasetIOService.canOpen(DefaultDatasetIOService.java:83)
	at io.scif.io.DatasetIOPlugin.supportsSave(DatasetIOPlugin.java:70)
	at org.scijava.io.IOPlugin.supportsSave(IOPlugin.java:76)
	at org.scijava.io.IOService.getSaver(IOService.java:66)
	at org.scijava.io.DefaultIOService.save(DefaultIOService.java:80)
	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)

java.lang.UnsupportedOperationException: java.lang.UnsupportedOperationException: Attempting to read or write from a io.scif.io.VirtualHandle. There is no source to operate on.

	at org.python.core.Py.JavaError(Py.java:546)
	at org.python.core.Py.JavaError(Py.java:537)
	at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:188)
	at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:204)
	at org.python.core.PyObject.__call__(PyObject.java:496)
	at org.python.core.PyObject.__call__(PyObject.java:500)
	at org.python.core.PyMethod.__call__(PyMethod.java:156)
	at org.python.pycode._pyx0.f$0(/home/random/Development/imagej/plugins/fiji-plugin-script-example/script/run-plugin.py:15)
	at org.python.pycode._pyx0.call_function(/home/random/Development/imagej/plugins/fiji-plugin-script-example/script/run-plugin.py)
	at org.python.core.PyTableCode.call(PyTableCode.java:167)
	at org.python.core.PyCode.call(PyCode.java:18)
	at org.python.core.Py.runCode(Py.java:1386)
	at org.python.core.__builtin__.eval(__builtin__.java:497)
	at org.python.core.__builtin__.eval(__builtin__.java:501)
	at org.python.util.PythonInterpreter.eval(PythonInterpreter.java:259)
	at org.python.jsr223.PyScriptEngine.eval(PyScriptEngine.java:40)
	at org.python.jsr223.PyScriptEngine.eval(PyScriptEngine.java:31)
	at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)
	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:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.UnsupportedOperationException: Attempting to read or write from a io.scif.io.VirtualHandle. There is no source to operate on.
	at io.scif.io.VirtualHandle.read(VirtualHandle.java:83)
	at io.scif.io.RandomAccessInputStream.read(RandomAccessInputStream.java:437)
	at io.scif.formats.KontronFormat$Checker.isFormat(KontronFormat.java:124)
	at io.scif.AbstractChecker.isFormat(AbstractChecker.java:93)
	at io.scif.services.DefaultFormatService.getFormatList(DefaultFormatService.java:342)
	at io.scif.services.DefaultFormatService.getFormat(DefaultFormatService.java:317)
	at io.scif.services.DefaultDatasetIOService.canOpen(DefaultDatasetIOService.java:83)
	at io.scif.io.DatasetIOPlugin.supportsSave(DatasetIOPlugin.java:70)
	at org.scijava.io.IOPlugin.supportsSave(IOPlugin.java:76)
	at org.scijava.io.IOService.getSaver(IOService.java:66)
	at org.scijava.io.DefaultIOService.save(DefaultIOService.java:80)
	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 org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:186)
	... 24 more

I can fix that by first copying the input file to the output location…

from java.io import File
from java.nio.file import Files

infile = File(inpath)
outfile = File(outpath)
if not(outfile.exists()):
	Files.copy(infile.toPath(), outfile.toPath())

… but that is pretty bad.

What is the correct way to do this?

Also if someone could help out how to write a groovy script doing the same… or an IJ1 version… That could be added to the repository and be a useful resource to others as well. Op usage is documented very well in the Wiki and the tutorials, but I could not find too much on the CommandService. Maybe I looked at the wrong places…


#2

@maarzt helped me find a solution - if I use @DatasetIOService instead of @IOService in the script, it works and I don’t get this Exception. Any idea why? pinging @gab1one

EDIT @maarzt found the bug, I will create a PR :slight_smile:


#3

Ok it is already fixed in https://github.com/scifio/scifio/commit/2d5602534368a63be9d7e1d850a9fab563d03313 :slight_smile: