Menu

Operator Development

Operator Development

This wiki page describes how to develop your own full-featured operator in IQM. This page is part of the [Plugin Development], since each plugin has to contain a single operator and extensibility in IQM is achieved using the plugin extensions.
You already may have checked out the plugin skeleton, so this wiki page focuses more on the composition of the operator.

Prerequisites

The same prerequisites apply as documented in [Plugin Development].

Structure

An IQM operator for both image and plot processing requires the following 4 classes to be implemented:

  1. Operator Descriptor
  2. Operator Validator
  3. Operator GUI
  4. Operator (Algorithm)

You are welcome to check out the simple-plugin-template skeleton for a simple example implementation of the entire operator.

Operator Descriptor

The operator descriptor contains all information on a specific operator ranging from accepted input data types to the number and types of parameters, number of sources and valid parameter ranges to stack processing types and a globally unique name.
This class is closely related to the Java Advanced Imaging OperationDescriptor, since we extend this class with our custom features.

In IQM, each descriptor has to extend at.mug.iqm.api.operator.AbstractOperatorDescriptor. The abstract class provides many methods and elements required for the integration in the IQM processing framework. The required resources are:

  1. at.mug.iqm.api.operator.OperatorType TYPE: The type of the operator determines whether or not the operator is enabled for loaded items of type IMAGE or PLOT in the application and is considered for enabling/disabling the menu items according to the current application state.
    • Example: public static final OperatorType TYPE = OperatorType.IMAGE;
  2. at.mug.iqm.api.operator.DataType[] OUTPUT_TYPES: An array of possible data types the operator may produce. This is coupled to some flags in the GUI, where the user separately can choose the items to be processed by this operator (see GUI description below).
    • Example: public static final DataType[] OUTPUT_TYPES = new DataType[] { DataType.PLOT };
  3. at.mug.iqm.api.operator.StackProcessingType[] STACK_PROCESSING_TYPE (optional): The stack processing type is set to DEFAULT in the abstract class. This means, that each item is processed separately within a stack using the same operator. Other stack processing types involve the processing of
    a. items or item pairs in a single manager lists (SINGLE_STACK_SEQUENTIAL),
    b. an even number of items in both manager lists (MULTI_STACK_EVEN), or
    c. an odd number of items in the manager lists, i.e. one item in one manager list and one or more items in the opposite manager list (MULTI_STACK_ODD).
    If you don't want any specific stack processing, simply omit this statement in your operator.
    Note: This list is continuously developed and extended, so always check the latest API for new types fitting your requirements.
    • Example: public static final StackProcessingType STACK_PROCESSING_TYPE = StackProcessingType.MULTI_STACK_EVEN;
  4. String[][] resources: A 2D string array of resources specified in key-value pairs. This array describes the most important part of the operator, the unique name (GlobalName). This name is used for every identification of the operator in the entire IQM system and must not match any other operator name. Furthermore, this array contains information on the documentation location, the vendor, operator version and a description of the parameters for this operator.
  5. String[] supportedModes: see the JAI documentation link above
  6. int numSources: the number of sources required by the operator
  7. String[] paramNames: the names of the parameters. The order of the items must correspond to paramClasses, paramDefaults, validParamValues. Parameters may be accessed via their names specified in this array.
  8. Class[] paramClasses´: the classes of parameters. Used for instantiation of parameters.
  9. Object[] paramDefaults: all default values of the parameters. Used for default creation of parameters.
  10. javax.media.util.Range[] validParamValues: a range of valid parameter values. This will be checked, when the operator is executed and may throw an exception, if the parameter is not properly set according to valid ranges.

Constructing the Descriptor and Registering the Operator

Choose one of the super constructors fitting your requirements in order to construct a new instance of this class.

A mandatory method in this class is public static IOperatorDescriptor register(). This method registers the operator with all its resources with the IQM operator registry.
Note: You may also implement operators using the default JAI system. Therefore, you will have to write a method public static IOperatorDescriptor registerWithJAI() and implement the entire operator according to the JAI specifications (which will not be part of this documentation).

Operator Validator

All operators have their own validator classes and implement the IOperatorValidator interface. The operator’s validator determines and implements the rules for approving an operator on a given set of input parameters (i.e. a work package). The validator is called before the GUI of an operator is opened. If validation is passed, the operator’s GUI is opened according to the information provided in the given work package (see GUI description below). If validation fails, the application displays an error message with custom information about what the operator needs as input types.

For convenience, we implemented default validators for both image and plot processing:

  • at.mug.iqm.api.operator.DefaultImageOperatorValidator: this validator checks for an image at the first position of the source vector, but does not perform any image-specific validations (e.g. checking the number of bands in the color model).
  • at.mug.iqm.api.operator.DefaultPlotOperatorValidator: this validator checks for a plot model at the first position of the source vector.

You are welcome to use them and override the validate(IWorkPackage) method using your custom validation rules. Most of the time you may be satisfied with the default implementations. If you don't want to perform any checks, simply override the aforementioned method and always return true. Nevertheless, we recommend implementing some restrictions in order to avoid unhandled usability errors.

Operator Graphical User Interface (GUI)

The most important part for controlling your operator's behaviour and its parameter for processing is the graphical user interface (GUI). Basically it should provide control elements for your parameters, e.g. spinners, buttons, text fields, and their corresponding labels. The main purpose of the GUI is setting of the parameter block in the operator according to the currently loaded item (e.g. an RGB image or a single-banded image).

Constructing the GUI

The entire GUI class with all possible control elements is assembled in the constructor. You may use custom subroutines for the assembly but every element is required to be created at instantiation. The standard signal flow when an operator is called is as follows:

  1. construct a work package and a default parameter block from the operator's descriptor (see above)
  2. validation check on the selected items and the work package
  3. on approval, call the GUI's update() method
  4. remove/alter control elements according to the information specified in the work package, e.g. remove sliders for single-band images, which are required for multi-band images.
  5. set the parameter block's values to the GUI elements, setParameterValuesToGUI() is called, where the first statement in this method MUST be the following line
    • this.pb = this.workPackage.getParameters();
  6. alter as many parameters as required
  7. execute the preview

On each event any control element receives, the parameter block has to be updated in order to reflect the current changes in the GUI. Depending on which operator you are constructing, you have to extend either

  • at.mug.iqm.api.operator.AbstractImageOperatorGUI or
  • at.mug.iqm.api.operator.AbstractPlotOperatorGUI.
Mandatory Elements

Constructor. Mandatory lines in the constructor are:

  1. this.setOpName(new MyOperatorDescriptor().getName());, where MyOperatorDescriptor is the name of your operator descriptor
  2. this.initialize();, initializes common behaviour
  3. this.setTitle("A title for the GUI frame");, set a custom title
  4. this.pack();, this has to be the last statement in the constructor

update(). The last statements in the update method must be:

  • this.updateParameterBlock();, sets the custom calculated parameters to the parameter block
  • this.setParameterValuesToGUI();, sets the custom calculated parameters to the control elements

Be advised that removing any event listeners avoids errors before setting values to control elements (e.g. JSpinners).

Resetting

Resetting is implemented in the super class and simply sets the default values of the parameter block specified in the operator's descriptor to the control elements.

Computing Custom Results

You may exclude some of the computations of the operator, if you don't want to produce all results. For example, if you are just interested in tables, and the operator computes tables and plots, simply un-tick the corresponding check box in the output options. The work package contains the information on whether to compute the selected items or all items.
If you want to remove this capability entirely, hide or remove the OutputOptionsPanel when you construct your GUI.

Auto Preview

Auto preview enables the execution of the operator in a preview mode each time a control element updates the parameter block. One has to make sure, that the call of this.showPreview() is implemented in the event handlers, if the check box for auto preview is selected.

Virtual Processing

Operators can store their results in serialized files on the hard drive after execution. The flag whether or not they should use memory or the disk can be set in the GUI. If the entire application is in virtual processing mode before the operator is launched, the flag is set automatically. The user may change this flag for the processing of a single operator, but as the GUI is closed, the application will go back in the state it was before the operator has been launched. The other way round, the user may set the application to virtual mode just for single executions, too.

Template Manager

Each operator in IQM is supporting parameter templates. The definition of the parameters is declared in the descriptor, thus, the template manager (preference manager) is a GUI front-end to a template file. The templates are generated automatically and integrate seamlessly into the operator's GUI.

Operator (Algorithm)

The operator has to extend the at.mug.iqm.api.operator.AbstractOperator or implement the IOperator interface. You are encouraged to use the abstract class for convenience. Every processing algorithm has to be implemented in run(IWorkPackage), subroutines are optional. The operator receives an at.mug.iqm.api.operator.IWorkPackage instance containing all information on the processing and produces an instance of at.mug.iqm.api.operator.IResult. Add all your single results to a at.mug.iqm.api.operator.Result and return the result object. This will display the results.

Mandatory Elements

Per default, each operator provides the ability to be cancelled. If you don't implement the cancellation statements (see next section), set the operator uncancellable via adding
this.setCancellable(false);
in the constructor.

Cancellation

Operators may be cancelled in the preview processing. In order to achieve that, simply add the following line at arbitrary positions in the run-method or anywhere else, where a reference to the operator object is available:
ìf (this.isCancelled(this.getParentTask()) return null;
This statement more or less checks a flag whether the executing thread/task has been cancelled by the user and exits the processing routine. You are encouraged to implement this statement in inner loops, if they are nested, loops in general, or before the return statement in the run-method. If you want to cancel sub routines, you have to check for cancellation yourselves. The operator does not display any results, if the run-method returns a null value.

Third Party Libraries. Every operator is open to use other java/native libraries, e.g. if you want to use OpenCV in your operator, put the java bindings in the lib folder of your installation and the plugin in the plugin folder. You may implement custom cancellation routines in these subroutines or right before and after calling them.
JAI is a special case, since we do not have control over its operational habits. So, we advise you to implement the cancellation statement before executing long running operations.

Progress Updates

Operators may have a determinable progress. For instance, if your operator loops 100 times, you may want to update the progress at each iteration. Therefore, add the following statement at meaningful positions in your code within the operator or the run-method:
this.fireProgressChanged(int p);, with p an integer value ranging from 0 to 100, indicating the progress in percent.
This updates a progress bar in the application's status panel.

If the progress of an operator is not really determinable, you may omit the statement and the progress bar is displayed in indeterminate mode.

Internationalization

Every operator's interface may be localized. Thus, a class managing the resource bundle has to be created in the package of your operator and manages a custom messages.properties file located in the operator's resources folder.
An example I18N.java class has been included in the simple-plugin-template skeleton.


Related

Wiki: Plugin Development

Discussion

Anonymous
Anonymous

Add attachments
Cancel





MongoDB Logo MongoDB