An unsorted list of hints that you might find useful.
Compile & Execute a Class
You do not need to call javac yourself with a long classpath:
and you can call its main() method just as easy:
Rapidly Prototype a Plugin
It is often easier to start out with a Jython, JRuby or BeanShell script, as you do not have to care about strict typing, exceptions or recompiling. Just place your script (with the correct extension – .py, .rb or .bsh) into the plugins/ folder and execute the script. Fiji will always execute the current version of the script, so you can edit and run the script without restarting Fiji.
Of course, it is even more convenient to use the Script Editor…
Once you have working code, you can turn it into a proper plugin (this is easiest with BeanShell, as its syntax is closest to Java already), adding strict typing and exception handling as needed.
Find the .jar File Containing a Certain Class
Sometimes, the compiler complains about a class not having a certain method or interface, but you know it must contain it. More often than not, that class exists in different versions in your classpath. Find out with
If you want to do that with an installed Fiji (i.e. when bin/ is missing), you can start the Script Editor and execute a BeanShell like this:
This will output the URL to the .class file, including the path to the enclosing .jar file.
Using ImageJ Effectively
ImageJ has a simple API, but it is also big, so here are a few pointers to some useful parts.
How to read a file into an ImagePlus
How to get the current image
Making a new image stack – quickly!
How to display an exception in a window
This is especially useful on Windows, where you usually do not see the console:
This is available since ImageJ 1.43g, as well as the option to set a different exception handler using
How to show a plot
ImageJ offers the ij.gui.Plot class to make a window showing a plot. Use it like this:
Instead of float arrays, you can also use double arrays.
If you need to update the plot at some stage, you need to save the return value of show():
To add another plot to the same window, use the addPoints() method:
The plots can be drawn in different colors like this:
You might need to adjust the bounding box if the second plot does not match the bounding box of the first one by using the setLimits() method before the call to plot.draw();
Duplicate, or convert between, ImageProcessor types
The ImageProcessor class has several useful methods: duplicate(), convertToByte(), convertToFloat(), convertToRGB(), and convertToShort().
This class also has some other goodies, such as methods for convolution.
How to store settings persistently
ImageJ (and therefore Fiji, too) has a way to store key/value pairs persistently, i.e. they are available even after a restart. The settings are stored in a file called IJ_Prefs.txt in the subdirectory called .imagej/ in your home directory (on Windows, directly in your home directory; on Mac, in ~/Library/Preferences).
The settings are only saved upon regular exit of Fiji; If you kill the process, or if the Java Runtime crashes, they are not saved. You can ask for the settings to be saved explicitly, though.
Example:
How to turn a number into a string, using a given number of decimal places
Use the d2s() method of the ij.IJ class:
How to abort a plugin completely
Sometimes, you want to abort a plugin without catching an exception at the highest level(s), without having ImageJ show an exception window. You can do that:
The special message Macro.MACRO_CANCELED will tell ImageJ not to show the exception message and stack trace in a text window.
Interact with the ROI manager
To add ROIs to the ROI manager, do something like this:
If you want to add the ROI with a slice label, you have to jump through a hoop:
To retrieve all ROIs from the ROI manager, do this:
If you need to preserve the order of the ROIs in the ROI manager, unfortunately you’ll have to access the AWT listbox:
To get just the selected ROIs, use code similar to this:
Show a results table
First you need to get the results table instance (or create one):
Then you can add a new row:
… and add entries by column label:
Finally make sure that the result table is displayed/updated:
How to find equivalent API commands between ImageJ 1.x and ImageJ2?
ImageJ1-ImageJ2 cheat sheet is available.
Tips for Graphical User Interface (GUI) programming
Programming with Swing components
When programming with Swing, beware that Swing is not thread safe. Swing’s golden rule states that:
Once a Swing component has been realized, all code that might affect or depend on the state of that component should be executed in the event-dispatching thread.
When has a Swing component been realized? When it is visible inside Window or JFrame that got a call to setVisible(true). This implies that its paint(Graphics) method has been called or will be called soon.
These are the methods that can realize a component, or rather, methods called on a Window or Frame or JFrame that will realize all its children components:
There is a class which helps you with all this: SwingUtilities. Example: to call pack() from within the constructor (which might or might not be called from the Event Dispatch Thread):
Information extracted from the Swing guide (now only available from via web.archive.org as Oracle removed the original docs), additional information can be found in the Concurrency in Swing lesson of The Java Tutorials.
Arcane Quirks
SoftReference and OutOfMemoryError
We have recently learned an interesting fact about Java’s SoftReference and the potential occurence of an OutOfMemoryError. The result first: An OutOfMemoryError may be thrown in a situation where SoftReferences can be released after which enough memory would be available. The reason is that normal garbage collection happens in an independent thread and does not halt other threads when they allocate memory. Only an explicit System.gc() waits until the memory is freed . The consequence is that whenever you allocate memory then you should do that with the following clause:
We found this by implementing a simple cache using a HashMap of SoftReferences to an object that on finalize removes the corresponding key in the HashMap. That cache is used to store image tiles for an ImgLib2 backend that uses a CATMAID stack (GitHub). It turned out that the painter thread in an interactive viewer was fetching new tiles quicker than the garbage collector would finalize SoftReferences and stopped with an OutOfMemoryError. We could solve that with the the above construct.