Debugging multiple op error in scijava-jupyter-kernel

jupyter
Tags: #<Tag:0x00007fd542ac0750>

#1

For posterity:

If you are running scijava-jupyter-kernel and get an error saying there are multiple ops, then check your classpath for duplicate entries.

In some cases you can fix this problem by editing your scijava kernel’s JSON file by manually removing directories from the classpath.

e.g.

java.lang.IllegalArgumentException: Multiple 'net.imagej.ops.transform.zeroMinView.DefaultZeroMinView' ops of priority 0

#2

Thanks @kephale. Another reason this can happen is if you have a cell which defines a plugin as a new class, and you run that cell multiple times. Each time you run it, it registers a new “copy” of the plugin with the SciJava context. In the case of an op, you will then get multiple matches when trying to call the op subsequently. You can restart the kernel to fix this.


#3

Hi, did have a similar problem and I remove “/Applications/Fiji.app/jars” from json file, now I have “/Applications/Fiji.app/jars/bio-formats/*:/Applications/Fiji.app/plugins/”. So now I can load images in the notebook, however (and I’m not sure if it’s related), I can’t load czi or nd2 format file using ij.io().open(), am I doing something wrong? I never use the jupyter notebook with imageJ before.


#4

@cedrice Here is my kernel.json, pretty printed:

{
  "language":"groovy",
  "display_name":"SciJava",
  "argv":[
    "\/Users\/curtis\/anaconda3\/envs\/java_env\/bin\/java",
    "-classpath",
    "\/Users\/curtis\/anaconda3\/envs\/java_env\/opt\/scijava-jupyter-kernel\/*",
    "org.scijava.jupyter.kernel.ScijavaKernel",
    "-verbose",
    "info",
    "-connectionFile",
    "{connection_file}"
  ]
}

Note that JAR files from java_env/opt/scijava-jupyter-kernel/* are added to the classpath, but not anything from Fiji.

Alternately, you can add everything from Fiji’s jars and plugins and jars/bio-formats folders, but nothing else from anywhere else. In theory, all should be OK as long as each JAR is only included on the classpath once. If you include two different folders which contain the same (but maybe different versions) of the same JAR files, though, then you may have issues.

Can you please describe what goes wrong, post the error message, etc.? Note that I personally have not tested the SciJava Jupyter Kernel with Fiji, only with the base ImageJ2, so it may actually be the case that Bio-Formats does not work in the notebook for some reason. We can address it, but it may take some back and forth here.

Not too surprising since it has not been possible to do so prior to three weeks ago. :wink:


#5

@ctrueden thank you so much for getting back to me so quickly!

So I modified my JSON file to that:

{
  "language": "groovy",
  "display_name": "SciJava",
  "argv": [
    "/Users/ce/anaconda/envs/java_env/bin/java",
    "-classpath",
    "/Users/ce/anaconda/envs/java_env/opt/scijava-jupyter-kernel/*",
    "org.scijava.jupyter.kernel.ScijavaKernel",
    "-verbose",
    "info",
    "-connectionFile",
    "{connection_file}"
  ]
}

Then I do:

#!groovy
// @ImageJ ij
// @NotebookService nb 
img= ij.io().open("/path/to/img.tif")

It work nicely but:

img= ij.io().open("/path/to/img.nd2")

give me:

io.scif.FormatException:/path/to/img.nd2: No supported format found.
	at io.scif.services.DefaultFormatService.getFormatList(DefaultFormatService.java:351)
	at io.scif.services.DefaultFormatService.getFormat(DefaultFormatService.java:317)
	at io.scif.services.DefaultDatasetIOService.canOpen(DefaultDatasetIOService.java:83)
	at io.scif.io.DatasetIOPlugin.supportsOpen(DatasetIOPlugin.java:65)
	at org.scijava.io.IOService.getOpener(IOService.java:56)
	at org.scijava.io.DefaultIOService.open(DefaultIOService.java:65)
	at org.scijava.io.IOService$open.call(Unknown Source)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
	at Script2.run(Script2.groovy:1)
	at org.scijava.plugins.scripting.groovy.GroovyScriptEngine.eval(GroovyScriptEngine.java:303)
	at org.scijava.plugins.scripting.groovy.GroovyScriptEngine.eval(GroovyScriptEngine.java:122)
	at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)
	at org.scijava.script.ScriptModule.run(ScriptModule.java:159)
	at org.scijava.module.ModuleRunner.run(ModuleRunner.java:167)
	at org.scijava.jupyter.kernel.evaluator.Worker.run(Worker.java:109)
	at org.scijava.thread.DefaultThreadService$2.run(DefaultThreadService.java:220)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	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)

Thanks again for your help


#6

Right. Because Bio-Formats is not included with the base ImageJ2. The java_env/opt/scijava-jupyter-kernel/* says “please include all core ImageJ2 libraries in the default notebook configuration.”

There is good news and bad news!

The good news is that there is a “grab” mechanism for adding more libraries to your notebook dynamically.

The bad news it that right now, it is not as trivial as it should be to grab Bio-Formats into your notebook.

The other good news is that it can be done right now, as follows:

// -- Functions --
registerAndCreatePlugin = { pluginClass, pluginType ->
    info = new org.scijava.plugin.PluginInfo(pluginClass, pluginType)
    ij.plugin().addPlugin(info)
    ij.plugin().createInstance(info)
}
registerService = { serviceClass ->
    service = registerAndCreatePlugin(serviceClass, org.scijava.service.Service.class)
    ij.context().getServiceIndex().add(service)
}

// -- Add Bio-Formats support --
#@repository("https://maven.imagej.net/content/groups/public")
#@dependency(group = "io.scif", module = "scifio-bf-compat", version = "2.0.3")
#@dependency(group = "ome", module = "formats-gpl", version = "5.5.2")
registerService(io.scif.ome.services.DefaultOMEXMLService.class)
bff = registerAndCreatePlugin(io.scif.bf.BioFormatsFormat.class, io.scif.Format.class)
ij.scifio().format().addFormat(bff)

If you add the above snippet into your first #@ImageJ ij cell, it should then be possible to e.g. ij.io().open("/path/to/myImageWhichOnlyBioFormatsCanRead") later in the notebook.

We will make this easier in the future; it is still early days for this technology.

Edit: To make this solution more visible, I posted a gist, and linked it from the “Fundamentals of ImageJ” notebook.


#7

@ctrueden Thank you! It works very nicely.