Where to Start Plugin Development [Novice]

Hello all,
I should preface this by saying that it is likely a very novice-level question, but that I have experience working with FIJI, Java, and NetBeans. Currently, I am working on developing a plugin to perform a few actions on directories of images (Kirby-Bauer assays). I have thus far followed the Maven tutorial and have a working Gaussian Filter plugin, but this is where the wheels come off.

My intent is to perform edge detection and Hough Circle Transform upon these images, to measure inhibition zones, but I have stalled out. Can any of you recommend resources for undertaking such a project? Likewise, what about documentation on variable names and/or how to integrate the Java to FIJI?

My efforts searching the forums here have been fruitless, so I thank you all for your assistance.

1 Like

Hi ejnolaniv, @haesleinhuepf gave a really nice lesson about plugin development at Neubias TS11;
you could follow the the step by step tutorial he has done, looking at different branches to follow the modifications made to the code and their effects:

Hope this help,
best,
Rocco

3 Likes

Hey @ejnolaniv,

the repository @RoccoDAntuono mentioned can be a starting point accompanied by this video:

and these slides:

Let us know how it goes! We’re happy to help :nerd_face:

Cheers,
Robert

2 Likes

Thank you both. I am currently reading Burger & Burge’s text, “Digital Image Processing” and Werner Bailer’s “Writing ImageJ Plugins—A Tutorial”. I’ve already watched the video on pom.xml editing, and have a functional Gaussian blur plugin from the template.

I will provide updates as my progress and knowledge advance.
Again, thank you for the foundation!

1 Like

Hello Everyone,
So I have hit a wall. The resources discussed above heavily reference ImageJ 1.0 plugin development. My current endeavor is to generate a FIJI plugin, based upon the Maven project, which will load a directory of images, and perform a series of existing plugins upon these images. I intend to save the output to a table (.csv), but the tutorials are certainly at an intermediate level, when I am indeed an absolute beginner. I’ve had four semesters of Java experience (over the past 10 years), but I use it only a few times per year.

My questions are thus:

1.) How can a user load a directory of images? Using

image = datasetIOService.open(imageFile.getAbsolutePath());

only loads one image, yet I would ultimately like to apply to a whole directory. If a loop structure is inappropriate, I would gladly appreciate any feedback to the contrary.

2.) How can another plugin be called? I haven’t found an example yet which demonstrates this. Navigating the soup which is ImageJ2.0 documentation is surprisingly time consuming for a novice, so alas, I must implore to the community.

3.) If a table is returned by an existing plugin, will techniques employed in this tutorial work to capture and export them?

Thank you all in advance for your assistance and encouragement. I will not give up!

1 Like

Would some of the concepts in this slideshow (Haase, 2017) be useful?

1 Like

Hi

Which resources do you refer to? The slides and the video we provided actually tell about ImageJ2/Fiji plugin development.

I think a loop over all files is the way to go.

This depends on which plugin you would like to call. Calling an ImageJ1 plugin from ImageJ2 still works like back in the days:

IJ.run(filtered1, "Gaussian Blur...", "sigma=" + sigma1);

However, if you do know the plugin is an ImageJ2 command, you can call it like demonstrated here:

ij.command().run(DoGImageJOps.class, true, imglibParameters);

Alternatively, if the operations you want to use are part of imagej-ops, you can call them like this:

RandomAccessibleInterval<T> filtered1 = opService.filter().gauss(image, sigma1);

Sure. The only thing which is missing in the example you lionked is the way how to save tables. We discussed that some time ago in the forum as there was a bug with table-saving. But I think it’s fixed now.

If you have more specific questions, such as how to run a specific plugin, just let us know.

Good luck!

Cheers,
Robert

Robert,
Thank you so very much for your quick response! The resources which I have been utilizing are Werner Bailer’s (2016) Writing ImageJ Plugins—A Tuturial, and Burger & Burge’s (2016) Digital Image Processing. Although I feel Bailer’s tutorial is brilliant, I’m concerned that the ImageJ 1.0 methodologies are dated. My rationale is that if I’m going to learn how to do this process, I should learn the most current way. This parallels a historical issue I had when having to switch to Python 3, having learned Python 2; in hindsight, I would have much rather jumped into Python 3 head first.

1 Like

Hello Joe -

At the risk of my playing the fool (or token curmudgeon, or devil’s advocate, or russkii trollskii …):

If your focus is learning and you have some time to play around
and experiment, perhaps it would make sense to also try building
your plugin the ImageJ1 way, and see which approach better fits
your particular use case.

Thanks, mm

1 Like

Hey Mountain,
I’m currently using FIJI, which touts support for the 1.0 way, so you do have a valid point. I don’t exactly agree with it :wink: but ultimately, I may have to go that route.

My only concern is that if I endeavor to call and use 2.0 style plugins from a 1.0 format, would it be possible, or perhaps unnecessarily difficult? I’m presuming there is some underlying merit to the 2.0 way of doing things, and that even as a complete noob, I should embrace this and power through the learning curve. Do you foresee merits to learning the 1.0 methodology prior to jumping into the 2.0 realm?

1 Like

Yes, calling ImageJ2 stuff from ImageJ1 is kind of impossible. But the other way around is basically no issue and I walk down this road every day. Check out the video linked above and start programming an ImageJ2/Fiji plugin with maven and Commands. As soon as you hit a wall, switch to ImageJ1-way of doing things. Example: Use ImageJ2 for loading images, blurring them, thresholding, connected components. When you then try to visualise your object segmentation with outlined regions of interest (ROI) on top of your original image, you may have a hard time trying to avoid ImageJ1. :wink:

Esteemed community members,
I have not been able to progress with IJ2/Fiji plugin generation; the learning curve is too steep.
I can not even comprehend how to open Fiji instead of ImageJ when testing in NetBeans.
I have a pom.xml file which I have modified, and I am attempting to modify the Gaussian blur template to perform a series of modifications to an image.
As I am trying to detect and measure inhibition zones in Kirby-Bauer assays, I know I will need to filter, reduce to 8-bit, perform edge detection, and then use some implementation of circle detection…within a loop structure, in order to process a directory full of images.
At present, I do not comprehend how to even load Fiji when testing.
Concurrently, I can’t figure out how to instantiate or call other classes/plugins to perform any steps beyond the very first step of simply loading an image.
My thoughts are leading toward the need to perform multiple Commands, but I’m dead in the water, and I doubt I can leverage IJ 1.x (even for learning) because of the need to call IJ2 plugins for circle detection.
Does anyone have an actual tutorial on IJ2 development? The wiki suggests modifying existing plugins, but this is beyond my comprehension, since the examples do not load directories of images.
TL;DR — I’m completely lost, and can’t even modify a template to do anything.

Thank you for suggestions in advance.

2 Likes

Hey @ejnolaniv,

I’m sorry to hear that. However, don’t give up - if you have the project running in your IDE, the rest is totally doable! :muscle:

I never opened Fiji from my IDE either. As far as I know that’s normal and nobody does that. (Fiji Is Just ImageJ :wink: ) We develop ImageJ and ImageJ2 plugins and then put them into Fiji. As you can see in this presentation on slide 48/49, we only make a decision on using ImageJ2 or ImageJ-legacy user interface. May I ask, why do you think you need to run Fiji?

There are some Jupyter notebooks provided by @ctrueden which can help you here with getting started. The modern way of calling filters is called ImageJ-Ops. So conversion to 8 bit, you find under ij.op().convert(). Edge detection might only be available in ImageJ1 (not sure), but you can always convert the image to an ImagePlus and run a particular plugin via IJ.run(); as it was done in ImageJ1. Afterwards, you convert back to ImageJ2.

Would you mind sharing more details on which plugins you would like to run? Depending on from when/where/who these plugins are, they may be called differently. I’d like to know which plugins and would then check out their documentation and maybe (worst case) their source code.

Which one? :slight_smile:

So aside from the Jupyter notebooks linked above (there are more in the same respository), you find more code examples here.

Unfortunately, we haven’t managed yet to write a book about ImageJ2-development comparable to all the books around for ImageJ1-development. I hope we will come there at some point.

In the meantime THANK YOU for staying with us. We are aware that our documentation is sub-optimally organised and you are reminding us to keep improving. So thanks a lot for this feedback.

Furthermore, you are almost there. Feel free to ask further detailed questions. We’re happy to help.

Also consider sharing your code, some example data and/or screenshots so that we can take a look on what you are trying to achieve and point you in the right direction.

Cheers,
Robert

2 Likes

Sorry the journey has been so frustrating.

My first question for you is: why are you writing a plugin? You could use a script and write in e.g. Jython or Groovy, and save yourself a lot of pain relating to Java (e.g. static typing).

How could it be better? We need to know concrete concerns and suggestions to improve it.

It all comes down to what is on your classpath. If you add sc.fiji:fiji as a dependency, then you’ll get Fiji when you do new ImageJ().launch(). Or if you write code from the Script Editor, you’re already inside Fiji and have access to everything, including plugins installed from third-party update sites.

This sounds like a perfect use for a script or macronot a new Java plugin. Do you know about the Macro Recorder? Do you know about the script templates of the Script Editor? Have you read the Batch Processing page, which describes how to loop over images en masse?

Yes, there is a tutorial for that. From the front page, click on Development, which is the top-level portal into all Java coding topics. The table of contents at the top shows 6 Tutorials which if you click jumps down the page to the available tutorials. There are three boxes: Learning the ImageJ API, ImageJ plugins, and The Fiji distribution of ImageJ, the first two of which may be relevant here. The first bullet of “Learning the ImageJ API” is a link to the ImageJ tutorials, which house the motherlode of ImageJ2 API documentation. The first bullet of “ImageJ plugins” is a link to Writing ImageJ2 plugins, which covers what a “plugin” is in ImageJ2 terms and how to write one. If you learn better by example, the maven-projects folder of the ImageJ tutorials repository has many example projects illustrating various plugins.

What I’d like to know is:

  1. How could these resources be better structured?
  2. Are you sure you need to write Java code? I think a script would be easier for your needs.
3 Likes

Robert,

This is a great idea and I feel this will be a step forward. I’ll be spending the day scrutinizing these and making notes—but how does one translate the Python to Java, if the current literature on IJ2 is so sparse?

2 Likes

Hello Joe -

This is not an uncommon or illegitimate experience.

Briefly returning to IJ1:

There is an IJ1 Hough-transform circle detector (not shipped with
Fiji / ImageJ) here:

Hough Circles

I was able to run it on a Fiji sample image (Blobs). Here is the
result:

10%20Circles%20Found

Here is the complete, runnable* IJ1 Macro script that I used to
produce the above image:

run("Blobs (25K)");
run("Smooth");
setAutoThreshold("Default no-reset");
setOption("BlackBackground", false);
run("Convert to Mask");
run("Find Edges");
run("Hough Circles", "minimum=10 maximum=20 increment=2 number=10 threshold=60");
selectWindow("10 Circles Found");

*) You have to put the plugin class file, Hough_Circles.class, in
your Fiji plugins directory for this script to run.

Note, the script is a minor tweak of running the Macro Recorder,
Plugins > Macros > Record..., and then running the
various commands.

I don’t know whether (this implementation of) Hough-transform
circle detection is appropriate for your use case, but it does
appear to be sensible.

As an aside, my preferred language for IJ1 Fiji scripting is jython
(python), but there are several other choices, including IJM.

Also, I wouldn’t warn you off of writing a java plugin. If your
task is relatively small and self-contained – mostly running
ImageJ commands – then scripting tends to be (a bit) more
convenient. But if your task is larger and/or involves significant
“custom” computation, a java plugin might be the better choice.

Thanks, mm

2 Likes

Curtis,
I’m honored to have you respond to my posting. I’ll try to address some of the following:

Well, I’m not really writing one yet, but I sure am trying! Joking aside, this stems from my interest in Fiji and image analysis in general. I’ve performed some manual routines using Fiji before, and have a ton of projects from geometric morphometrics through fluorescence microscopy which I hope to tackle through some basic automation. As far as I know, macros and scripts run in the foreground, and are further away “from the iron” than a comparable Java plugin. Although difficult, the payoffs of developing an intimate understanding of—and the requisite skills working with—IJ2 plugins make this the ultimate goal. If I am mistaken in my presumptions and/or assumptions, please correct me freely.

I am currently reading through the Jupyter notebooks; and I am a HUGE proponent of markdown style tutorials. I use R Markdown heavily in the courses I teach because of the follow-the-leader type approach they allow. Translating the Python to Java will require some more research on my end, but I feel like this is a great start. I’m a biologist, and I realize that singular opinions aren’t going to shift development policy, but I would highly encourage these types of tutorials. One of the biggest obstacles I’ve faced on the imagej.net wiki is the jump from downloading a pom.xml file to actually modifying a .java file in any meaningful way. Explicitly, I don’t know how to start working with image objects. I would suppose a more kinesthetic tutorial is what I seek (at this time). Admittedly, I work in higher education, doing bioinformatics, but I can now confidently say my knowledge of software development norms and/or best-practices is completely inept—the whirlwind of Git, Maven, and advanced Java has been entirely disconnected from molecular biology, so I’m learning as I go, too…plus, I’m that outlier who uses NetBeans instead of Eclipse!

I’m hurling myself into de novo plugin development as a complete beginner, so this is surely my fault. However, I think a “here’s how to build a plugin from the ground up” bootcamp or Java-based markdown series would be immensely helpful. Reading across the imagej,net wiki, there are hundreds of links to either discuss ancillary topics or jump to different areas—which are overwhelming from a learner’s perspective, though not for a developer seeking a reference. Instead of being organized like an encyclopedia, something adopting more of a textbook format would be lovely. For example, I found Bailer’s IJ 1.x writing plugins tutorial (2006) to be a good read, and I’ve been trying to kludge together some functionality using that text (and appropriate dependencies), even if it’s not IJ2 compliant. Surely, asking for such a directed approach with practice problems and code snippets for IJ2 is a tall order. If I ever develop the comprehension necessary to assist, I would love to get involved in a project like that.

Nothing worth having is easy—but comprehension and developing plugins through Java are certainly worth having…so I’ve been chipping away for a month now, and I’ll get there eventually. I’m spending the day reading the entire Jupyter notebook series, and I’ll report back if this helps break through my stumbling blocks. On average, I devote 10–15 hours to this project per week, so it’s just a matter of time.

Thank you again for the response. I really do appreciate the support from the community.

2 Likes

Hey Mountain, you sure are the man!
That’s along the path of what I’m trying to achieve, although I have been learning toward incorporating IJ-OpenCV, since it has a version of the Circle Hough Transform (CHT) which has been used to create another package AntibiogramJ (Cuevas et al., 2015). I’m modeling my goal off of this existing “plugin”—although with much simpler goals (no GUI, multiple user/lab interface, automatic detection of codes…). So I have proof of concept using the IJ-OpenCV routines, I’ve now just got to start piecing the puzzle together. My ultimate end goal is to take a directory of input images, like this one, and perform the following:
KB2
* Warning: these future goals are way loftier than those of this thread*

  1. Given the known diameter of large Petri dishes (150mm) and diffusion disks (6mm), calibration will be incorporated.
  2. Disks will be identified, generically, and inhibitory zones will be measured around these.
  3. Whole directories of images will be processed via the plugin, since the medium (agar) will be identical.
  4. Different circle finding algorithms will be tested in future prototypes.

The CHT can get quite resource intensive, so I’ve been exploring other potential algorithms to try once I have a better understanding (and at least one working plugin). The burden of CHT is a major reason to target a plugin versus a script or macro.

I’m going to review your demonstration code after I finish reading the Jupyter notebooks today.
Thank you so much!

We have to be careful here when throwing around the term “plugin” because in ImageJ2 there are many kinds of plugins. If you mean “a piece of functionality that appears in the menu structure and performs some sequence of operations” that is a Command plugin (“command” for short), and what the example-imagej-command gives you a template for.

It’s true that macros are very limited in their intended scope. They can have problems running headless, problems running concurrently, and most importantly they do not support the full API available from Java. That is why historically, people have given the advice that “when you are getting serious with ImageJ, stop writing macros and start writing Java plugins.” However, that advice is no longer good as soon as you have access to full-fledged scripting languages like Groovy and Jython.

Scripts (in languages besides ImageJ Macro) are essentially just calls directly into the Java API, but with distinct (and typically very similar or even identical) syntax from Java. Since script languages are interpreted, it is possible there can be performance issues when doing things like for loops in the script language itself. But most image processing and analysis pipelines in ImageJ do not require looping over pixels. Rather, they tend to be linear or near-linear sequences of Java API calls, with zero performance impact between script vs. Java Command plugin. And scripts have many advantages: shorter and more concise; easier to understand since you can typically leave off the static types Java requires; and even more powerful in some ways since you can e.g. in Groovy dynamically add dependencies on additional third-party libraries to call seamlessly from your script.

If what you want to do is bioimage analysis, start by writing scripts. Do not go to plugins unless you need to do something unusual, such as:

  • focus completely on performance at the ImgLib2 level
  • implement a non-Command plugin—e.g. an IOPlugin adding support for a new data type to the File › Open… command.

And even in these cases, we are working to make it possible in more cases to use a scripting language, rather than the Java language, to do these things as well.

Please be aware that nearly all of those Jupyter notebooks are written in Groovy, not Python. The syntax is quite similar. And the ImageJ API is the same regardless of Java, Groovy or Python—so translating between those three languages should not typically end up being difficult.

I’m sorry—I don’t understand. Can you give me a specific process you followed that feels disjointed or disconnected? When you say “downloading a pom.xml file” do you mean cloning a repository from GitHub? Are we talking about the Writing plugins page? Or some other page?

Relatedly: if you decide to stick with Java: have you tried starting from the example-imagej-command template on GitHub? This is intended to be the central template from which you can springboard to a working Command plugin of your own.

From what you wrote above, it sounds like you did start from the example-imagej-command, and had it working in NetBeans, and then when you wanted to modify it to do something different, you just… didn’t know how? Right? I fully agree that that’s a difficult jump. It’s what the ImageJ Jupyter notebook tutorials are for, and at a lower level what the ImgLib2 Examples are for: learning ImageJ2 and ImgLib2 APIs.

That is the intent of the Jupyter notebooks. The toplevel “Introduction and Demo” notebook has a numbered table of contents at the top like that, with topics. Is this what you are talking about?

1 Like

Dear community members, I give up.
I’ve spent over 50 hours and one month’s time trying to make a dent. I’ll have to undertake some serious professional development on Maven, Java, and Groovy before entertaining the idea of such a simple Command plugin. At present, I can not continue this project until January. Please feel free to flag this post for removal.