Studying plugins: Where can I find a simple ImageJ2-style plugin in the current (1.51s) version of Fiji?

plugin
fiji
Tags: #<Tag:0x00007fb882c2ee48> #<Tag:0x00007fb882c2eab0>

#1

I am trying to learn how plugins work and how to develop them.
I assume that I should be focusing on ImageJ2-style (SciJava
plugin framework) plugins, and I would like to look at a real-world
example. I have been browsing my current Fiji installation, but
all of the plugins I happened to have looked at seem to be old-style
plugins.

So …

Could someone direct me to a new-style plugin distributed with the
current version of Fiji? (Preferably a relatively small plugin that
implements some simple end-user image manipulation.)

In more detail, I see, for example, that the command

Plugins->Stitching

is implemented by a plugin, apparently in:

./Fiji.app/plugins/Stitching_-3.1.5.jar

This jar contains the class file, Stitching_Pairwise.class, as
well as the plugins.config file that seems to indicate that the
Stitching plugin is an old-style plugin. Furthermore, the source
for Stitching_Pairwise.class:

https://github.com/fiji/Stitching/blob/cc96f5fdd6b8fefefe31710c6801dcd9213964b0/src/main/java/plugin/Stitching_Pairwise.java

contains:

public class Stitching_Pairwise implements PlugIn

indicating again, presumably, an old-style plugin.

I haven’t yet found anything that looks like a new-style plugin,
and I don’t really know a good way to search for one. So it would
be helpful if someone could direct me to a Fiji menu entry that is
hooked to a new-style plugin.

Thanks, mm.


#2

It’s true that there are many more IJ1-style plugins than IJ2-style ones. One reason is that IJ1 has been around a lot longer; another is that some of the IJ2 API is not yet fully stabilized.

Here is a Groovy script that prints out a list of available SciJava modules, excluding ImageJ Ops and the ApplyLookupTable command (since these dominate the output otherwise):

#@ ModuleService ms
scijavaCommands = ms.getModules().stream()
	.filter {
		info -> info.getIdentifier().startsWith("command:") &&
			!info.getIdentifier().contains("net.imagej.ops.") &&
			!info.getIdentifier().contains("ApplyLookupTable")
	}
	.map { info -> info.getIdentifier() }
	.collect().sort()
println(String.join("\n", scijavaCommands))

If you want a simple example to study, try the example-imagej-command, which exists to illustrate how ImageJ2 commands work.

Note that it is possible to use the SciJava plugin mechanism without actually declaring @Parameter fields or using ImgLib2 data structures. See e.g. BigDataViewerPlugin. This has the advantage of no longer needing the _ in the name nor the plugins.config in the JAR.


#3

Thank you, Curtis, this is very helpful.

I ran your script by pasting it into the Fiji script editor. Indeed, it lists many
IJ2-style plugins. For no particular reason I’ve decided to focus on

command:net.imagej.plugins.commands.assign.InvertDataValues

I’ve downloaded the source, InvertDataValues.java, and will start
monkeying around with it.

You do mention "that some of the IJ2 API is not yet fully stabilized."
Should this be a concern for me? Should I consider learning to
develop IJ1 plugins rather than IJ2 plugins?

Thanks again, mm.


#4

Hi @mountain_man

I have a simple plugin I am currently writing for a project with the Open Science Foundation attempting to replicate Gertz. etc. all a paper on biomechanical remodeling of the tumor environment. The project requires fiber measurements and the researchers were using a macro called FibriTool.

The plugin code has the original FibriTool code in the comments, so you can see how code from a macro is translated to ImageJ2 (imglib2 and imagej-ops).

The main reason we converted the Macro to ImageJ2 is to make is easy to use as a KNIME node, as we need to analyze a few hundred images and crunch statistics.


#5

There are tradeoffs. If you develop ImageJ 1.x, you accept the limitations of that framework. E.g. there many contexts where the code will not work. Whereas if you develop ImageJ2, you have code which can potentially be used in more scenarios (e.g. from within KNIME), but for which API breakages are likely in the future, necessitating future tweaks to the code. In short: it is not possible to write code which is totally “future-proof” right now.