How to correctly write Ij2 plugins?

Tags: #<Tag:0x00007fb8795f95e0> #<Tag:0x00007fb8795f94a0>


So I have a big question because I am quite confused about how plugins / services should work…

Here’s my problem :
I wrote a segmentation plugin “IJ1 style” with many static classes (so sad!). The MySeg class is a static class that contains the current state of my segmentation (meshes and point clouds, with some data attached). It also contains functions to work with a number of other static classes I wrote : an Optimizer class (actually doing the segmentation job), a Viewer class (3D), a GUI class, an Input/Output class.

SO. I want to rewrite all of this IJ2 style. How should I do ?

If that can clarify a bit, I’d like the user to be able to write scripts a bit like this :

ij.myseg.setOptimizerImage("myimage.tif"); // image to work with
ij.myseg.putSeed(x,y,z);	// seed for the segmentation
ij.myseg.optimize(numberOfSteps);	// processes a number of optimisation steps
ij.myseg.viewCurrentSegState();		// launch a 3D viewer with current meshes (maybe SciView!)
ij.myseg.saveState("myfile");		// saves the state into an output file

Should I write a MySeg service, and then commands for setOptimizerImage, putSeed, optimize, viewCurrentState, saveState ( that take a MySeg service as an input)?

I looked at this ( but I can’t relate easily with what I want to do… I also looked quickly at the TrackMate source code but it looks like IJ1 code if I’m not mistaken.

Thanks for your time!



Sorry, but I cannot really help you too much technically… in the process of learning myself. But I can point:

Hopefully a more adept individual (@imagejan @stelfrich @hadim @tinevez … ) here on the Forum can better assist you…

Thoughts from @awalter17: I don’t think a Service is what you want… I think what you want is a Command. If those methods are not more generally applicable and need to be carried out in a specific order… you could included them as private helper methods.



Hi @NicoKiaru,

I guess, you will not need to write any service. A single command plugin may do the job.

You may already know this example imageJ2 command plugin:

You can just download/copy and adapt the code from this repository. This is in fact just a proper ImageJ2 plugin doing simple stuff. If you never did such a maven/pom/eclipse/imagej2plugin thing before, you may want to watch this video:

To get your algorithm in this plugin I would recommend writing a separate Optimiser class for convenience. This class may take an image and a point as constructor parameters. Furthermore, it may have a function returning a binary (mask) image of type Img<BitType>, for example. Last but not least, to have potentially n-dimensional images, you should not work with x,y,z coordinates as integers or doubles but instead with an instance of RealPoint. For saving the state (which can just be represented by the binary image, the optimiser returns), you can use ImageJs io() service. You may not need an additional class or method for doing this.

If you do it for the first time and need some help, I would recommend you to put your initial version of the code on github, even though it may not have final functionality and put a link here. We can then have a look and discuss structure and architecture :wink:



Just to add a few thoughts to @haesleinhuepf’s excellent explanations:

This refers to a new plugin type, you don’t need that. As others pointed out above, a Plugin/Command is what you want.

Does that mean that you’d like to process a few steps, then check the result, then process further with the current state, then check again?
In this case (without knowing much about your actual use case), you could split the plugin into two commands:

  • a first one taking the actual inputs, and outputting your first “current state”:
private Img img;

private RealPoint seedPoint;

private YourCustomObject currentState;
  • and a second one that can advance the current state by n steps each time it runs:
private YourCustomObject currentState;

private int numberOfSteps;

Or maybe a Previewable command makes sense for you?

Just some ideas…

Another great example of an advanced IJ2 command is the Pendent Drop plugin by @daerr:


Nice screencast ;-)!
Awesome, thanks for all these feedbacks. I’ll take some time to think about it and I’ll probably get back to you.


Hi eveybody,
Short question : is this correct to set a default value for a parameter in java ?

@Parameter(label="equilibrium distance between surfels")
public float r_0=2f;

Because this

@Parameter(label="equilibrium distance between surfels", value=2f)
public float r_0;


As mentioned on a parallel discussion on Gitter:

Yes, in Java, you initialize the variable directly:

private int a = 0;

whereas in scripts, you have to go via value= because each line is parsed separately, and agnostic of the script language:

#@ int (value = 0) a

Also, you should make your parameters in Java be private, as the framework is taking care of setting and getting them.

(Beware of the default persist = true which causes default values to be overridden if you executed your plugin/script before, and there are different values stored in your prefs.)


Oki doki, thanks. Out of curiosity, if a command “command1” wants to access the value of a parameter of another command “command2”, is that doable ?


You need to instantiate a CommandModule using the CommandService, then you can query for the module inputs. Here’s an illustrative Groovy script (simply run it from the Script Editor after choosing Language > Groovy):

#@ CommandService commands

import org.scijava.command.Command
import org.scijava.plugin.Plugin
import org.scijava.plugin.Parameter
import org.scijava.log.LogService

@Plugin(type = Command.class)
class Command1 implements Command {
	int value1

	LogService log

	void run() {

@Plugin(type = Command.class)
class Command2 implements Command {
	String textInput;

	LogService log

	void run() {

commandModule1 =, true).get()
println "Input extracted from first command: ${commandModule1.getInput("value1")}"

commandModule2 =, true).get()
println "Input extracted from second command: ${commandModule2.getInput("textInput")}"


Just to give you an idea, I’ve uploaded two videos to show you how this works currently :

The first one shows the segmentation, initialized with a script that I execute:

The second one show a few basic manipulation of the “state” generated by the segmentation:

Notice there’s a GUI but actually all of this can be scripted currently in an IJ1 style.

I’m a bit reluctant to show the way I made these things work together (ugly static classes, some of you may have a heart attack) :sweat_smile: . But I’ll probably do it, because I do not want to start the wrong way if I do a rewrite. I’ll keep an IJ1 branch anyway, because it’s working, and then go to extensive rewrite tests in an IJ2 branch.


This is so awesome! Do you ship the (IJ1) plugin via update site already?

Do not worry about this. Seeing that it works so well, it cannot be all that crappy :wink:
And by the way, do you know about the CRAP license that was invented precisely to encourage academics to publish their (not so pretty) code?


CRAPL, nice ! :grinning:

Me and my colleagues we would like to at least submit a paper before sharing all this, which may take a few monthes.
Before submission, I wanted to “solve” two problems.
1 - I used dependencies without using Maven -> That was super annoying to install. But thanks to the learnathon, this part is solved :+1:.
2 - In an upsurge of bravery, I wanted to write it into a more IJ2 friendly way. But I now feel that it may be too much work at this point, or that the cost will not justify the delay.

I’ll keep you updated here.


I am going through the steps to deploy this plugin with an update site. Maybe I should create another thread in the forum but I think it is still related to this question.
I have these dependencies declared the pom files:


I first want to be able to run the plugin on a FIJI install. Currenlty it doesn’t work because some dependencies are missing. It seems that the dependencies from the ImageJ repository are there, but the one from Maven Central (glm, jcuda) are missing.
1 - How should I deal with these ? Should I put manually the missing jar in the jar folder ?
2 - When I will upload my plugin on the update site, should I add manually these “missing” jars ?



No, the maven-imagej-plugin takes care of copying all required dependencies to your ImageJ installation if you specify:


see the FAQ.

Also no: the ImageJ updater will be aware of your dependencies if you copied them to your installation using the method above.


Thank you! In fact I tried that but I was giving the wrong path for FIJI. By giving the correct path all the jars are handled correctly.

I launch my plugin (a command), and… I unfortunately got an error, even with an empty run() function in the command :

(Fiji Is Just) ImageJ 2.0.0-rc-61/1.51n; Java 1.8.0_66 [64-bit]; Linux 4.10.0-27-generic; 30MB of 765MB (4%)
	at java.util.ArrayList.addAll(
	at org.scijava.util.ClassUtils.getAnnotatedFields(
	at org.scijava.util.ClassUtils.getAnnotatedFields(
	at org.scijava.Context.getParameterFields(
	at org.scijava.Context.inject(
	at org.scijava.Context.inject(
	at org.scijava.Context.inject(
	at org.scijava.module.DefaultModuleService.createModule(
	at net.imagej.legacy.LegacyService.runLegacyCompatibleCommand(
	at net.imagej.legacy.DefaultLegacyHooks.interceptRunPlugIn(
	at ij.IJ.runPlugIn(
	at ij.Executer.runCommand(

I didn’t have time to figure out what could be the problem (maybe I need to declare one parameter ?). I’ll look at this in more detail next week.


Well, the error message suggests that some of the cached fields were null when trying to create a module from your command, see these lines:

To decide whether this is a bug in the framework or in your code, we’d have to see your code (ideally via gist or on github) :wink: or a minimal example that reproduces the issue.

At least nothing seems to be wrong with building and deploying to Fiji.



Some news on my side. The last problem seems to be linked with my JOGL dependencies.
Here are my jogl dependencies in pom.xml:


Let me detail step by step :
1 - First of all, everything works fine under eclipse (JOGL / CUDA). All works perfectly fine. The native libraries are somehow loaded and discovered correctly.
2 - I install my plugin to my local Fiji by using the mvn clean install command.
So far, so good.
3 - I launch Fiji.
4 - If I execute my plugin, I get the Null Pointer Exception mentioned above.
5 - I go to help > update. Here’s what I found:

My plugin wants to remove platform specific jars for the general ones.
6 - I apply the suggested changes and restart ImageJ.
7 - I execute my plugin and …
It works! (good, I don’t get the Null Pointer Exception and some parts of the plugin start). Except when it needs JOGL… in this case, this error shows up :

java.lang.UnsatisfiedLinkError: Can't load library: /home/nico/natives/linux-amd64//

Note that if I move the natives that are in the jar in>jars>linux64>jogl-all-2.3.2-natives-linux-amd64.jar to the indicated folder (/home/nico/natives/), then it works.
Of course, it would be better if there was a way to link my plugin directly to these natives.

How should I do that ?

PS1 : the source code of the plugin is here :
PS2 : I made an update site (NicoKiaru) with a benchmark that launches itself on the plugin call (if you want to repeat these steps)
PS3 : the topic is slightly drifting to a JOGL issue. I can open another thread if necessary.

Again, thanks for the nice support!

Fiji command unable to find JOGL library - minimal example