ImageJ 2.0 scripting - CellProfiler/CellProfiler GitHub Wiki

ImageJ 2.0 comes with several scripting languages that can be used to more fully take advantage of ImageJ's capabilities. This page documents how to use the Beanshell scripting language to write RunImageJ scripts for ImageJ 2.0.

Note that this functionality is only fully supported up to CP 2.1.1; use of it later is at your own risk. We hope to re-engineer this functionality for CP 3.0 and beyond- you can follow the efforts to do so here

Table of Contents

  1. Setting up to use Beanshell
  2. Basic ImageJ concepts
  3. The Beanshell language
  4. The ImageJ context
  5. Example: running a command

RunImageJ is initially configured to run ImageJ commands. To run Beanshell, select "Macro" in the "Run an ImageJ command or macro?" setting and select "Beanshell" as the programming language. You then write your script in the "Macro" setting. Your macro will probably take some image as input - if it does, check the box marked "Input the currently active image in ImageJ" and select the CellProfiler image that should be ImageJ's current image when the macro starts. If your macro produces an image after running, you can import that image into CellProfiler by checking the "Retrieve the currently active image from ImageJ".

You may find that image displays accumulate as your pipeline runs (press the "Show" button on the Run_ImageJ module to see the ImageJ UI and all open image displays to check this). You can close all image displays at the end of each cycle by placing a Run_ImageJ module that executes the "File > Close All" command after the last Run_ImageJ module in your pipeline.

ImageJ 2.0 has a modular, pluggable architecture. It has a base framework and structure for managing services and plugins and beyond this small base framework, everything is a plugin, including services. Examples of services are the command service which lets you run ImageJ commands and the display service which manages displays that hold ImageJ's images. The overall container of this is called the context - all of the pieces in ImageJ use the context to find the other pieces they need. CellProfiler does much the same; it uses the context to find the services it needs to find commands, find scripting languages and to run commands and scripts. As ImageJ 2.0 evolves on its way to post-beta release, functionality will be built into the scripting service to streamline writing scripts, but for now, some of what needs to be done may be difficult to understand and technical.

The Beanshell language is similar to both Java and Javascript. The Beanshell manual can be found here.

The ImageJ context is the container for your operating environment. It holds your images and your scripts change and reference only things within that context. CellProfiler automatically assigns the context to a variable called "ImageJ" before running script (this will soon be augmented with a second variable named "IJ", set by ImageJ itself which points to the ImageJ 2.0 service gateway). At a minimum, you can use the ImageJ object to get any service using the following boilerplate (the command service is shown as an example):
import imagej.command.CommandService;
cmdSvcClass = CommandService.class;
cmdSvc = ImageJ.getService(cmdSvcClass);

You need the command service to run a command. The command service has a run method that will run an ImageJ 2.0 plugin, chosen by class name. If you run the current version of the macro recorder, the recorder will display the class name as it's recording as well as the variable arguments for the plugin, for instance for the Invert... command:

Module: imagej.core.commands.assign.InvertDataValues
overlayService = imagej.data.display.DefaultOverlayService [priority = 0.0] {OverlayService}
imgDispService = imagej.data.display.DefaultImageDisplayService [priority = 0.0] {ImageDisplayService}
optionsService = imagej.options.DefaultOptionsService [priority = 0.0] {OptionsService}
display = imagej.data.display.DefaultImageDisplay@127208e4: type=interface imagej.data.display.DataView, name=DNA, objects={imagej.data.display.DefaultDatasetView@75db5427} {ImageDisplay}
allPlanes = true {boolean}
ImageJ 2.0 will fill in defaults for what it can, so we'll not specify the display (the image that will be processed) or any of the services, but we will set allPlanes which would otherwise prompt for a value.
import imagej.command.CommandService;
cmdSvcClass = CommandService.class;
cmdSvc = ImageJ.getService(cmdSvcClass);
result = cmdSvc.run("imagej.core.commands.assign.InvertDataValues", new Object [] {"allPlanes", true});
result.get();

The last line is the one that executes the module. The run method takes two inputs, the name of the command class to run, as a string, and an array of key/value pairs (the even elements, starting with element # 0 are the names of the arguments to be set and the odd elements are the values for the arguments). The run method returns a Future. There's a lot of (well thought out) technical hoo-ha about why a future has to be the output of run, but the upshot is that you can't be sure that the operation is complete unless you call get on the future that's returned.

⚠️ **GitHub.com Fallback** ⚠️