External Plugins in PyImageJ

Hello,

I am trying to use XitoSBML plugin with pyimagej but am not able to understand how to use it in python.

import imagej
ij = imagej.init('sc.fiji:fiji')
ij.getVersion()
from skimage import io
import numpy as np
from jnius import autoclass
WindowManager = autoclass('ij.XitoSBML')
img = io.imread('image1.jpg')
img = np.mean(img[500:1000,300:850], axis=2)
ij.py.show(img, cmap = 'gray')

This is the code I tried but I cant figure out the error. Any help is appreciated

Welcome to the Image.sc Forum, @bhavay07!

Here’s a rundown of how I attacked this question:

  1. Firstly, I hadn’t heard of (or didn’t remember) what the XitoSBML plugin is. It’s not part of core ImageJ and it’s not part of Fiji. So I figured it must be a separate extension. Checking the list of update sites, I found the XitoSBML update site listed, which links to the XitoSBML repository on GitHub.

  2. From there, I see a pom.xml, so I know this is a Maven project. It extends pom-scijava, and has Maven artifact coordinate (groupId:artifactId) of jp.ac.keio.bio.fun:Xito_SBML. That’s good, because if you want to initialize pyimagej from Maven artifact coordinates, the plugins you want need to have Maven artifact coordinates!

  3. Next: is this artifact published to maven.scijava.org? Unfortunately, it’s not on maven.scijava.org. That’s unfortunate.

  4. Is there any way we can get this thing as a Maven coordinate? Yes, using Jitpack, which builds GitHub projects into Maven artifacts on demand in the cloud, we can access the latest release using coordinate com.github.spatialsimulator:XitoSBML:1.2.0. Great.

  5. We can try combining this coordinate with sc.fiji:fiji from the command line using jgo, one of the underlying technologies of pyimagej, with the command-line invocation jgo sc.fiji:fiji+com.github.spatialsimulator:XitoSBML:1.2.0:net.imagej.Main. The + concatenates the Maven artifacts, and the final :net.imagej.Main tells the name of the main class entry point, which in this case is just ImageJ’s usual launch class.

  6. OK, so Fiji comes up, but how do I know if XitoSBML is available? I can look for one of its commands in the menu. What commands does it have? Well, looking at the GitHub repository, this appears to be a suite of ImageJ 1.x plugins, so there is a plugins.config defining the commands. One of them is “run Spatial Image SBML Plugin” so we’ll try that.

  7. Press L for the search bar, type “run spatial”, and lo and behold: nothing. Right—because there was a long-standing issue with ImageJ 1.x plugins not being accessible from the normal Java classpath (it always wants to find them installed in a local ImageJ installation pointed at by plugins.dir property). But fortunately, I finally fixed that limitation late last year. We just need a newer imagej-legacy in the mix.

  8. How do we get a newer imagej-legacy? Well, a new Fiji release will happen very soon that includes it. But in the meantime, since we are impatient, we can tell jgo explicitly to include the latest version: jgo sc.fiji:fiji+net.imagej:imagej-legacy+com.github.spatialsimulator:XitoSBML:1.2.0:net.imagej.Main. The difference here from last time is the +net.imagej:imagej-legacy which is a shorthand for +net.imagej:imagej-legacy:RELEASE which means “please include the latest release of net.imagej:imagej-legacy in the environment.” This time, after Fiji pops up, typing “run spatial” into the search bar finds the plugin! Hooray! In theory, that means it’ll also work with pyimagej.

  9. Let’s try:

    $ python
    Python 3.7.3 | packaged by conda-forge | (default, Jul  1 2019, 14:38:56)
    [Clang 4.0.1 (tags/RELEASE_401/final)] :: Anaconda, Inc. on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import imagej
    >>> ij = imagej.init('sc.fiji:fiji+net.imagej:imagej-legacy+com.github.spatialsimulator:XitoSBML:1.2.0')
    SLF4J: Class path contains multiple SLF4J bindings.
    ... some warnings and stack traces here you can ignore ...
    >>> ij.getVersion()
    '2.0.0-rc-72/1.52r'
    >>> from jnius import autoclass
    >>> Spatial_Img_SBML = autoclass('jp.ac.keio.bio.fun.xitosbml.Spatial_Img_SBML')
    >>> Spatial_Img_SBML
    <class 'jnius.reflect.jp.ac.keio.bio.fun.xitosbml.Spatial_Img_SBML'>
    >>> sbml = Spatial_Img_SBML()
    >>> sbml.run("")
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "jnius/jnius_export_class.pxi", line 766, in jnius.JavaMethod.__call__
      File "jnius/jnius_export_class.pxi", line 860, in jnius.JavaMethod.call_method
      File "jnius/jnius_utils.pxi", line 91, in jnius.check_exception
    jnius.JavaException: JVM exception occurred: java.awt.HeadlessException
    >>>
    

    Ah, good old HeadlessException. Many ImageJ 1.x plugins have this problem. The plugin was designed to be run from inside the ImageJ 1.x user interface—not for reusable execution outside the context—and so it hardcodes use of GUI components.

At this point, we have a working pyimagej with the XitoSBML plugins available, but we need to ask ourselves: what are we trying to make this code do? For many ImageJ 1.x plugins you can use the Macro Recorder to generate code (e.g. in JavaScript) which can be pasted into a Python script mostly as-is, and it should work, as long as there were no hardcoded GUI usages. But your code above does not actually invoke XitoSBML to do anything in particular. Do you have a script that uses XitoSBML that works from inside Fiji, that you want to adapt to pyimagej? If so, reply here and paste it, and we can help further.

3 Likes

Hi @ctrueden,

Thanks for the help. I don’t have a script using XitoSBML at the moment as I am just trying to figure out what all things I can do using pyimagej and XitoSBML. Majority of the functions I have tried to call from python have thrown the Headless Exception.

Create_Img=autoclass('jp.ac.keio.bio.fun.xitosbml.xitosbml.MainImgSpatial')
Create_Img.run("run Spatial Image SBML Plugin")
>jnius.JavaException: JVM exception occurred: java.awt.HeadlessException

I am only able to run

Spatial_Img_SBML = autoclass('jp.ac.keio.bio.fun.xitosbml.Spatial_Img_SBML')
sbml = Spatial_Img_SBML()
sbml.showAbout()
>XitoSBML 1.2.0: Spatial SBML Plugin for ImageJ
Copyright (C) 2014-2019 Funahashi Lab. Keio University.

XitoSBML is an ImageJ plugin which creates Spatial SBML model
from segmented images. XitoSBML is not just a converter,
but also a spatial model editor so that users can add
molecules(species), reactions and advection/diffusion coefficients
to the converted Spatial SBML model.
More information is available at

    https://github.com/spatialsimulator/XitoSBML

So, I thought that I should try to access the inner level functions where some image processing is taking place but those functions have an ImagePlus object and some hash sets as their parameters and I am not so sure on how to get those.
Also, recording macros only gives this output and Im not sure what I can do with this.

open("C:/Users/Bhavay/Desktop/XitoSBML/examples/2D/example2D.tiff");
run("run Spatial Image SBML Plugin", "save=C:/Users/Bhavay/Desktop/XitoSBML/examples/2D/abcd.xml");
close();

I’d suggest reaching out to the XitoSBML authors asking if they can make the plugins macro recordable, and/or separate the core logic from the GUI logic, so things can be done headless programmatically. Otherwise, you probably won’t get too far with it via pyimagej.