The ability to extend the itools is one of their main strengths. This can be adding a button for an operation (like our example here), the capability to read/write new file types, new visualizations, or new ways to manipulate visualizations. Plus, the user interface can be customized to various levels. Toolbars and panels can be added to the standard configuration, but a totally custom interface can be created also. Capabilities can also be removed to provide a simpler interface for a specific task.
This example adds an adaptive histogram equalization operation to iimage.
There are two files for this demo program: mgitopadapthistequal__define.pro (doc) to define the operation and mg_dataop_demo.pro (doc) to setup using the operation. To run the demo, make sure both files are compiled or in your path and run mg_dataop_demo.
You'll probably want to look at the documentation for the parent classes of our class: IDLitComponent, IDLitIMessaging, IDLitOperation, and IDLitDataOperation during the course of this tutorial.
Define the member variables
The member variables will include all the properties of the operation, plus whatever else is needed to be stored during the life of the operation. The properties will be registered in the init method using the names defined here.
The init and cleanup methods
The init method has several jobs:
- call
IDLitDataOperation::initwith the proper keywords (typesand_extra), - register properties, and
- initialize member variables (properties).
As usual for a subclass' init method, the first task is to call the parent's init method:
name='Adaptive Histogram Equalization', $
icon='image', $
reversible_operation=0B, $
expensive_operation=0B, $
_extra=e)) then return, 0L
Note that it is important that it get passed _extra. The TYPES determines which itools data types the operation will act on. The REVERSIBLE_OPERATION and EXPENSIVE_OPERATION keywords relate to the undo/redo system. REVERSIBLE_OPERATION determines what happens when the user undo's the operation. If REVERSIBLE_OPERATION is set, then the undoExecute method is called. If REVERSIBLE_OPERATION is not set, then the itools will cache data before the operation is executed so that it can be restored when it is undone. EXPENSIVE_OPERATION determines the behavoir after the operation is undone. If EXPENSIVE_OPERATION is set, then the result of the operation is cached so it can be redone without having to calculate it again. If not set it must be calculated again via the execute method if it is redone.
description='Slope limit of histogram', $
name='Clip', $
sensitive=1
Register properties of the operation via IDLitComponent::registerProperty (IDLitComponent is a parent class of IDLitDataOperation). The positional parameter is the member variable name. The type is specified using the INTEGER and FLOAT keywords (others are available, though not corresponding to all the IDL types), but could be specifed via a code as the second positional parameter.
The cleanup method simply calls IDLitDataOperation::cleanup.
The setProperty and getProperty methods
The setProperty and getProperty methods are fairly standard. They must provide access to all registered properties and must pass keywords on to IDLitDataOperation::setProperty and IDLitDataOperation::getProperty.
The doExecuteUI, execute, and undoExecute methods
The doExecuteUI method is called to present a GUI for the user to modify properties, see
a preview, etc. before the operation is executed. It gets the tool object reference, does a quick sanity check, and does a UI service:
if (~otool) then return, 0L
return, otool->doUIService('OperationPreview', self)
Documented predefined choices for services are: 'PropertySheet' or 'OperationPreview'. You can also write your own UI service. Note that this method will not be called if the SHOW_EXECUTION_UI property of the operation is not set.
The execute method actually does the calculations of the operation. The function accepts a single positional parameter which is an input for the original data and an output for the operated upon data. This is the statement that actually does the adaptive histogram equalization:
clip=self.clip, $
nregions=self.nregions, $
top=self.top)
The status of the execution is returned (1 for success, 0 for failure).
The undoExecute method is not needed for this operation because REVERSIBLE_OPERATION is not set.
Using the operation
mg_dataop_demo puts MGitOpAdaptHistEqual into iimage and loads some default data. The itool is created with a data set in the standard way:
endo = read_image(f)
iimage, endo
id = itGetCurrent(tool=otool)
Here, itGetCurrent gets the itool identifier and object reference. We only need the object reference, but are required to get the identifier. Be sure to use itGetCurrent right after creating the itool, because if another itool is created or even becames the current window in the OS, it will be the current itool.
'MGitOpAdaptHistEqual', $
identifier='Operations/AdaptHistEqual', $
icon='image'
This registers the operation on our itool. The positional parameters give a name for our operation and the classname that defines the operation. The IDENTIFIER keyword locates the operation in the menu system. For instance, the identifier 'File/AdaptHistEqual' would put this in the File menu of the itool. More usefully, 'Operations/My Operations/AdaptHistEqual' would create a new submenu in the Operations menu and put this operation in it. The ICON keyword specifies an icon for the operation in the operation browser. In this case, icon='image' is equivalent to
Hopefully, this will provide a template for further operations. I hope to provide more demos/templates/tutorials for other methods of extending the itools including file readers, file writers, general operations, manipulators, visualizations, UI services, user interface panels, and full-blown user interfaces.

June 20th, 2006 at 5:01 pm
[...] For simple operations, subclassing IDLitDataOperation is an easy way to quickly add an operation to the iTools system. See previous post “Creating an iTool data operation” for more information about IDLitDataOperation. If you want to do anything more complicated than a numeric operation on the dependent variable of the currently selected visualization, then you want to subclass IDLitOperation. We will examine a fairly simple subclass of IDLitOperation, MGitOpDerivative, which calculates the derivative of data in a plot visualization. [...]
July 17th, 2006 at 7:58 pm
[...] The iTools are easy to use interactively (O.K., easy once you learn some of the conventions and jargon). But they also have the ability to be extended and controlled programmatically. I have given a couple examples of extending an iTool with new operations (data operation, general operation). I’ll post more extending iTools visualizations, file readers/writers, manipulators, user interface services, and custom user interfaces in the weeks to follow. But programmatically controlling an iTool is both fairly easy and extremely useful, especially in situations where a visualization needs to be created which further needs to be explored interactively. [...]