home | lab | find me | science | publications | software | toolbox | site map

Jython for ImageJ by example

Example 1: defining a method to place ten copies of the current image in a new stack.

>>> img = WindowManager.getCurrentImage()
>>> def toStack(image):
...    stack = ImageStack(image.width, image.height)
...    for i in range(10):
...        stack.addSlice(image.getTitle(), image.getProcessor().crop())
...    ImagePlus("stack", stack).show()
>>> toStack(img)

Example 2: choose a file and try to open it as an image

>>> from java.awt import FileDialog
>>> fd = FileDialog(IJ.getInstance(), "Open", FileDialog.LOAD)
>>> fd.show()
>>> file_name = fd.getFile()
>>> if None != file_name:
...    Opener().openImage(fd.getDirectory(), file_name).show()

Perhaps it is better to use ImageJ's way of bringing up a file dialog, which may be a JFileChooser if the user ticked the right checkbox in the Edit - Options. It's also shorter:

>>> od = OpenDialog("Choose image file", None)
>>> file_name = od.getFileName()
>>> if None != file_name:
...    Opener().openImage(od.getDirectory(), file_name).show()

Example 3: running ImageJ commands from the jython interpreter.

Note that java methods whose return type is void print 'None'. Also note that doCommand will run in a separate thread.

>>> IJ.run("Select All")
>>> IJ.doCommand("Select All")

Example 4: put all tif images from a folder in a list named 'tifs', for further processing.

>>> from java.io import File, FilenameFilter
>>> import re
>>> class Filter(FilenameFilter):
...	def accept(self, dir, name):
...		reg = re.compile("\.tif$")
...		m = reg.search(name)
...		if m:
...			return 1
...		else:
...			return 0
>>> folder = "/images/art/"
>>> tifs = [Opener().openImage(folder, file.name) for file in File(folder).listFiles(Filter())]
>>> print tifs
[imp[image1.tif 600x900x1], imp[image2.tif 600x900x1], imp[image3.tif 600x900x1]]

Example 5: operator overloading.

In this case, it is used to make the '+' sign add together several copies of the currently active image into a single stack.

Note the usage of imp.title : despite 'title' being private to class ImagePlus, jython can read it automatically from the getTitle() method (this is called 'beans' functionality).

>>> class Stack(ImageStack):
...	def __init__(self, title, imp):
...		ImageStack.__init__(self, imp.width, imp.height)
...		self.title = title
...		self.addSlice(imp.title, imp.getProcessor())
...	def __add__(self, imp):
...		if imp.width == self.width and imp.height == self.height:
...			self.addSlice(imp.title, imp.getProcessor())
...		else:
...			print "image", imp.title, "has different dimensions. Ignoring."
...		return self
...	def show(self):
...		ImagePlus(self.title, self).show()
>>> img = WindowManager.getCurrentImage()
>>> stack = Stack("stack", img) + img + img + img
>>> stack.show()

Example 6: add all open images to a stack

Actually, only those of the same size as the first image in the list. Requires the class Stack defined in example 5.

>>> w = WindowManager
>>> stack = None
>>> for id in w.getIDList():
...	img = w.getImage(id)
...	if None == stack: stack = Stack("all", img)
...	else: stack += img
>>> stack.show()

Example 7: using java bean and event properties to show the current image in a new JFrame that will respond when closed.

>>> from javax.swing import JFrame
>>> from java.awt import Color, Dimension
>>> f = JFrame("Test", size=Dimension(400,400), \
...	windowClosing=lambda msg: IJ.showMessage("Closing the window!"), \
...	visible=1, background=Color.yellow)
>>> img = WindowManager.getCurrentImage()
>>> ic = img.getWindow().getCanvas()
>>> f.getContentPane().add(ic)

In pure java the above code would have taken lots of code lines. The only truly missing step is a way to check whether any image is open, but since this is a dynamic interpreter, if the 'img' var is null an error will show when trying to get the ImageCanvas 'ic', and thus it can be adjusted on the fly.

The above code could be even shorter, but then it may lose readability.

By java bean is understood the property/ies a class has such as, in JFrame, 'size', with its corresponding get and set methods. In jython any such bean can be specified within the constructor. See jython webpage on java bean properties and events.

For events, jython reads which listeners can be added to a class instance, and then which methods such listeners implement. Then any such method can be specified directly in the constructor such as the 'windowClosing' method of the WindowListener for the JFrame above, without having to generate subclasses or any redundant stuff.

Example 8: compiling jython code into pure java code, and then making an ImageJ plugin out of it

In your jython installation folder, there is a jython compiler that compiles jython code to both .java and .class files. Such .class files can be executed without the jython.jar present in the classpath.

The above means that you can create a jython ImageJ script, then compile it, and give it to people who don't even need to know that jython exists.

To compile a jython file named Add_Noise.py, using something like:

$ cd ImageJ/plugins/Jython/
$ jython-2.1/jythonc -J -classpath ij.jar -w . Add_Noise_1.py

The above creates Add_Noise.java and two .class files. Delete the .class files and adjust the Add_Noise.java to implement ij.plugin.PlugIn and to have a run(String) method that calls the main(String[]) present in Add_Noise.java. Then compile it as any other ImageJ plugin.

Voilà, you have now a pure java ImageJ plugin with can be executed without the jython jar present in the classpath.

Last updated: 2012-05-08 11:10 Zurich time. Copyright Albert Cardona.