This is an archive of the old MediaWiki-based ImageJ wiki. The current website can be found at imagej.net.

Image Expression Parser

Image Expression Parser
Project Fiji
URL https://imagej.net/Image_Expression_Parser
Source on GitHub
License GPLv3
Release 3.0.1
Date Sat Apr 29 22:49:24 CDT 2017
Development status Stable
Support status Active
Team
Founders Jean-Yves Tinevez
Leads Jean-Yves Tinevez
Developers -
Debuggers Jean-Yves Tinevez
Reviewers Jean-Yves Tinevez
Support Jean-Yves Tinevez
Maintainers Jean-Yves Tinevez, Curtis Rueden
Contributors Johannes Schindelin, Albert Cardona, Jan Eglinger, Mark Hiner, Stephan Saalfeld

Usage

The plugin is located in Process  › Image Expression Parser.

This plugin parses arbitrary mathematical expressions and compute results using images as variables. For instance:

■ 2*A
■ A*(B+30)
■ sqrt(A^2+B^2)*cos(C)
■ A > B
■ gauss(A, 0.8)

where A,B and C are opened images of the same dimensions.

As of version 2.x, pixel per pixel based operations are supported and Imglib algorithm are supported.

The parsing ability is provided by the JEP library: Java Expression Parser v.jep-2.4.1-ext-1.1.1-gpl. This is the last version released under the GPL by its authors Nathan Funk and Richard Morris, see Singular System. Internally, this plugin uses Imglib to deal with images.

Internally, images are handled by copying them to a new float type image, so as to avoid clipping effect. The result image returned is of float type as well.


User interface

The interactive version (launched from ImageJ) uses a GUI.

When launched it displays a window allowing the user to enter a mathematical expression, with variables (capital single letters, so up to 26 variables) and canonical functions. The expression is checked by the parser of the JEP library (http://www.singularsys.com/jep/). If it is not valid, a hopefully useful error message is displayed.

Variables can be added using +/- buttons. They are matched to opened images in ImageJ.

When the images are RGB images, they are processed in a special way:

  • they are split in 3 RGB channels;
  • each channel is parsed and evaluated separately;
  • the 3 resulting images are put back together in a 3 channel composite image.

This GUI was built in part using Jigloo GUI builder http://www.cloudgarden.com/jigloo/.


Supported functions

Here is a list for supported functions and algorithms, as of version 2.1.


Supported ImgLib algorithms

Description Syntax
Gaussian convolution gauss(img, sigma)
Floyd-Steinberg dithering dither(img)
Image normalization (sum to 1) normalize(img)


Supported functions

Description Syntax
Euler constant e
π pi
Standard operators+, -, *, /, ^, %
Sinesin
Cosinecos
Tangenttan
Arc Sineasin
Arc Cosineacos
Arc Tangentatan
Arc Tangent 2 argsatan2(y,x)
Hyperbolic Sinesinh
Hyperbolic Cosinecosh
Hyperbolic Tangenttanh
Natural Logarithmlog
Exponentialexp
Powerpow
Square Rootsqrt
Absolute Valueabs
Roundround
Floorfloor
Ceilingceil
Boolean operators!, &&, ||, <, >, !=, ==, >=, <=



Extending the parser

It is relatively easy to extends the parser with new functions.

Basically, you must write a function that implements fiji.expressionparser.function.ImgLibFunction. Once done, it must be added to the parser class, so that it is aware of it. See in fiji.expressionparser.ImgLibParser the method addStandardFunctions() for an example.

However, in the fiji.expressionparser.function package lies a few abstract functions made to simplify the extension process:


fiji.expressionparser.function.TwoOperandsPixelBasedAbstractFunction

This is the mother class for functions that takes two arguments, and operate on pixel values only. That is: the pixel value on the result image will depend only the pixel values in the source images at the same location.

For instance, have a look at fiji.expressionparser.function.ImgLibArcTangent2 that extends it. New functions will basically just have to implement the actual operation on numbers, in the method evaluate(final R t1, final R t2).


fiji.expressionparser.function.SingleOperandPixelBasedAbstractFunction

The same thing, but for function with a single argument. For instance, see fiji.expressionparser.function.ImgLibAbs.


fiji.expressionparser.function.SingleOperandAbstractFunction

This is a more generic abstract class, allowing to handle whole image operation. There is two method to implement:

  • evaluate(Image<R> img) to specify what the function does on a whole image;
  • evaluate(R t) to specify what the function does on a scalar.

See ImgLibNormalize for an example.


fiji.expressionparser.function.TwoOperandsAbstractFunction

The same things, but for two arguments. There is more methods to implement, because of the singleton expansion that can be left or right, and not necessary yield identical results.

See ImgLibGaussConv for an example. In this example, you will also see how errors or invalid arguments are handled.



Calling the plugin from elsewhere

It is possible to call the plugin from another class or in a scripting language. For instance in Python:

from ij import WindowManager
from net.imglib2.img import ImagePlusAdapter
from net.imglib2.img.display.imagej import ImageJFunctions
from fiji.process import Image_Expression_Parser


# Make an ImgLib image from the current image
imp = WindowManager.getCurrentImage()
img = ImagePlusAdapter.wrap(imp)

# In python, the map can be a dictionary, relating 
# variable names to images
map = {'A': img}
expression = 'A^2'

# Instantiate plugin
parser = Image_Expression_Parser()

# Configure & execute
parser.setImageMap(map)
parser.setExpression(expression)
parser.process()
result = parser.getResult() # is an ImgLib image

# Copy result to an ImagePlus and display it
result_imp = ImageJFunctions.show(result)
result_imp.resetDisplayRange()
result_imp.updateAndDraw()


Here is another example in Javascript contributed by Jeff Hanson:


// This script was created as an javascript equivalent of the Python example here:
//   https://fiji.sc/Image_Expression_Parser#Calling_the_plugin_from_elsewhere

importClass(Packages.fiji.process.Image_Expression_Parser); 
importClass(java.util.HashMap);
importPackage(Packages.mpicbg.imglib);

expression = 'A^2';

imp = IJ.getImage();

img = Packages.mpicbg.imglib.image.ImagePlusAdapter.wrap(imp);

imgMap = new java.util.HashMap();
imgMap.put('A', img);
parser = new Packages.fiji.process.Image_Expression_Parser();
parser.setImageMap(imgMap);
parser.setExpression(expression);
parser.process();
result = parser.getResult();
resultImp = Packages.mpicbg.imglib.image.display.imagej.ImageJFunctions.copyToImagePlus(result);
IJ.run(resultImp, "Enhance Contrast", "saturated=0.35");
resultImp.show();

Version history

  • v1.0 - Feb 2010 - First working version.
  • v1.1 - Apr 2010 - Expression field now has a history.
  • v2.0 - May 2010 - Complete logic rewrite:
    • functions are now handled by code specific for ImgLib;
    • support for ImgLib algorithms and non pixel-based operations, such as gaussian convolution;
    • faster evaluation, thanks to dealing with ImgLib images as objects within the parser instead of pixel per pixel evaluation.
  • v2.1 - June 2010 - The GUI now generate a new separate thread for processing, freeing resources for the redraw of the GUI panel itself (thanks to Albert Cardona and the Fijiers input).
  • v2.2 - June 2010 - First version released publicly. RGB images are processed in a special way by the GUI: each of their channel is processed separately and put back together in a composite image.


Wish list for this plugin

We are interested into knowing how we should extend this plugin so that it suits your need. Tell us in the discussion page.