top bar

Version 2.0 Plugins

This page provides an overview of how to write new plugins in Version_2.0. While the basic concepts are similar to how they worked in previous versions, important details have changed.

Defining a Plugin

Version 2.0 uses the SciJavaPlugin framework for detecting and loading plugins at runtime. What this means for you as a plugin author is that your plugin class must do the following things to be detected and loaded:

  1. Its jar must be located in the mmplugins directory of your ImageJ installation.
  2. It must implement the MMPlugin interface, or one of the interfaces that inherits from MMPlugin (see the list further down the page)
  3. It must implement the org.scijava.plugin.SciJavaPlugin interface. This interface does not specify any methods (so all you need to do is add SciJavaPlugin to the list of interfaces implemented by your plugin class); it just marks the plugin class for later detection.
  4. It must have the org.scijava.plugin.Plugin annotation, with the "type" parameter matching the type of the plugin you wish to implement.

For example, if you want to add a new MenuPlugin to the Plugins menu, then you would need to have a plugin class that looks something like this:

@Plugin(type = MenuPlugin.class)
public class MyPlugin implements MenuPlugin, SciJavaPlugin {
...plugin implementation goes here...
}

Plugin instantiation

In µManager 2.0, all plugins are loaded and instantiated when µManager launches. This is different from prior versions, where plugins were instantiated on an as-needed basis. You will know your plugin has finished loading when its setContext() method is called. The Studio object passed as a parameter to that method provides the plugin with access to the µManager API.

Types of plugins

µManager 2.0 has a considerably expanded number of plugin types compared to 1.4, which are enumerated here.

MMPlugin

This is the most basic type of plugin. It is not explicitly exposed anywhere in the program, and thus should only be used by plugins that want to be fully in charge of their behavior and create their own UIs, largely independent of µManager itself. Be careful that your UI behaves sanely when closed (or has no mechanism to be closed), as once it is closed there will be no way to access it short of restarting the program.

MenuPlugin

MenuPlugin plugins are displayed in the Plugins menu. The getSubMenu() method allows them to declare where in the Plugins menu they appear, and the onPluginSelected() method is called when the user selects their entry from the menu.

Most plugins are MenuPlugins. One good example is the RecallPlugin.

ProcessorPlugin

ProcessorPlugin plugins are used in the data processing pipeline, which modifies images as they are acquired. They appear in the Plugins menu, under "On-The-Fly Image Processing". A ProcessorPlugin is really a gateway to two other objects. The first is the ProcessorConfigurator, which is a user interface that allows the user to configure how this plugin should process data. This configuration is output as a PropertyMap (effectively a key-value store). The second is the ProcessorFactory, which produces Processors based on the PropertyMap they have been provided.

This is a complicated mechanism, but the upshot is that a single ProcessorPlugin can create multiple independent ProcessorConfigurators, the configurations generated by those Configurators can be stored via PropertyMaps and restored later (e.g. in later sessions of the program), and each Processor is wholly independent of any others, allowing for multiple independent image processing pipelines.

Example ProcessorPlugins include the SplitView and ImageFlipper plugins.

OverlayPlugin

OverlayPlugin plugins are used to draw overlays on the image display window. They are made available via the "Overlays" section of any Inspector window. OverlayPlugins are primarily responsible for creating OverlayPanelFactories, which in turn create the OverlayPanels that are responsible for actually deciding what to draw and how to draw it. Copies of each OverlayPanel are embedded into each Inspector window, by way of the Factory.

An example OverlayPlugin is the TimestampPlugin, with the corresponding TimestampFactory and TimestampPanel classes.

AutofocusPlugin

AutofocusPlugin plugins are used to perform autofocus operations, typically in software. They are accessible via the autofocus UI in the main window and MDA window in the program. They remain largely unchanged from prior versions of µManager.

IntroPlugin

IntroPlugin plugins allow for some basic customization of the introductory dialog when µManager is launched. They can specify a list of config files that ought to always be available to users, and they can replace the "splash screen" image with their own image.

InspectorPlugin

InspectorPlugin plugins produce InspectorPanels that are displayed in the Inspector window(s). An InspectorPanel is simply a set of controls or informational displays related to the currently active DataViewer or DisplayWindow. Example InspectorPanels include HistogramsPanel, which displays the histograms, MetadataPanel, which shows image metadata, and OverlaysPanel, which draws overlays on the currently-displayed image.

QuickAccessPlugin

QuickAccessPlugin plugins create tools that can be embedded into the Quick Access Panel. They allow easy access to custom controls, so if your plugin has some simple controls that you want users to always be able to access (and that don't warrant a more fully-fledged GUI), you can use a QuickAccessPlugin to create those controls.

More specifically, you should create a SimpleButtonPlugin, ToggleButtonPlugin, or WidgetPlugin, depending on how complicated the usage logic is for your control. QuickAccessPlugin itself does not have any methods that get called when the control is interacted with, so the more specific child interfaces are necessary to do anything with the Quick Access Panel.

Providing an API for your plugin

If your plugin contains generally useful functionality that other code might want to call, it is a good idea to provide a stable programming interface (API) for it. Since classes in plugin JARs are not usually available on the classpath, you need to provide your API in a separate "library" JAR, to be included in the classpath. Your plugin will then be a wrapper around your library.

You can split the plugin and library in one of two ways:

  • Library = interface definitions only; Plugin = code that implements the interfaces, plus MMPlugin classes
  • Library = interface definitions, plus implementation code; Plugin = MMPlugin classes (thin wrappers that call the library)

If you use the latter scheme, it is important to make it clear which interfaces (and, possibly, classes) are part of the API (to be maintained stably to ensure compatibility) and which are implementation details (which the library author can change any time). We recommend following the MMStudio convention of placing implementation classes in packages that contain "internal" as an item in their fully qualified name.

© Micro-Manager : Vale Lab, UCSF 2006-2011 | All Rights Reserved | Contact