Applet API¶
Workflow Concepts¶
A Workflow
combines a set of applets together to form an entire computational pipeline, along with the GUI to configure it.
A workflow is created when the user loads a project, and destroyed when the project is closed.
The workflow has three main responsibilities:
- Instantiate a set of applets, and expose them as a list for the ilastik shell to display.
- Build up a complete computational pipeline, one image lane at a time. This is done by connecting an individual image lane from each applet’s Top-Level Operator. (More on that in a bit.)
- Select a particular slot to serve as the “image name slot” for the shell. The shell uses this slot as the “master list” of all image lanes present in the workflow at any time.
Image Lanes¶
Note
This section explains how multi-image support is implemented in ilastik.
Most beginning developers don’t need to sweat the details here. Simple workflows can be designed with the assumption that only one image lane will be active.
The StandardApplet
base class handles multi-image support for you.
Workflows in ilastik are designed to work with an arbitrary number of input images. In the ilastik Applet/Workflow API, each image is said to occupy an image lane of the workflow. In the ilastik shell GUI, the user can view the results of only one lane at a time. He selects which lane to view using the shell’s “Current View” dropdown menu.
When the user adds a new input image to the workflow, the workflow creates a new image lane in each applet to process it.
This is done by calling addLane
on every applet’s topLevelOperator, and then calling connectLane
to connect together the lanes from each applet.
See MultiLaneOperatorABC
for more details.
Many applet GUIs can be written without regard to the fact that the applet’s top-level operator handles multiple image lanes at once. In fact, most applet GUIs are written to handle only a single lane of the applet’s top-level operator. Instead of manipulating the top-level operator directly, most GUIs manipulate a view of the top-level operator for a particular image lane.
For example, consider this top-level operator diagram (the Workflow Design page explains how to interpret operator diagrams).
If the Applet GUI is only interested in dealing with a single image (say, the second one), it can be written to use a view. In that case, the GUI is provided with an object that looks like this:
Notice that the view object has no multi-slots. As far as the GUI is concerned, there is only one image lane. (The dotted lines are just shown for comparison with the previous diagram. Click on the diagram and zoom in for better rendering.)
The Workflow Base Class¶
-
class
ilastik.workflow.
Workflow
(shell, headless=False, workflow_cmdline_args=(), project_creation_args=(), parent=None, graph=None)[source]¶ Base class for all workflows.
-
__init__
(shell, headless=False, workflow_cmdline_args=(), project_creation_args=(), parent=None, graph=None)[source]¶ Constructor. Subclasses MUST call this in their own
__init__
functions. The parent and graph parameters will be passed directly to the Operator base class. If both are None, a new Graph is instantiated internally.Parameters: - headless – Set to True if this workflow is being instantiated by a “headless” script, in which case the workflow should not attempt to access applet GUIs.
- workflow_cmdline_args – a (possibly empty) sequence of arguments to control the workflow from the command line
- project_creation_args – The original workflow_cmdline_args used when the project was first created.
- parent – The parent operator of the workflow or None (see also: Operator)
- graph – The graph instance the workflow is assigned to (see also: Operator)
-
applets
¶ Abstract property. Return the list of applets that are owned by this workflow.
-
imageNameListSlot
¶ Abstract property. Return the “image name list” slot, which lists the names of all image lanes (i.e. files) currently loaded by the workflow. This slot is typically provided by the DataSelection applet via its ImageName slot.
-
connectLane
(laneIndex)[source]¶ When a new image lane has been added to the workflow, this workflow base class does the following:
- Create room for the new image lane by adding a lane to each applet’s topLevelOperator
- Ask the subclass to hook up the new image lane by calling this function.
-
prepareForNewLane
(laneIndex)[source]¶ Workflows may override this method to prepare for a new lane, before the new lane is actually inserted.
For example they may copy cache states that will be invalidated by the insertion of the new lane, and restore those caches at the end of connectLane().
-
handleNewLanesAdded
()[source]¶ Called immediately after a new lane is fully initialized with data. If a workflow wants to restore state previously saved in prepareForNewLane(), this is the place to do it.
This function must be called by any code that can add new lanes to the workflow and initialize them. That happens in only two places: The DataSelectionGui, and the BatchProcessingApplet.
-
onProjectLoaded
(projectManager)[source]¶ Called by the project manager after the project is loaded (deserialized). Extra workflow initialization be done here.
-
handleAppletStateUpdateRequested
()[source]¶ Called when an applet has fired the
Applet.statusUpdateSignal
Workflow subclasses should reimplement this method to enable/disable applet gui’s
-
cleanUp
()[source]¶ The user closed the project, so this workflow is being destroyed. Tell the applet GUIs to stop processing data, and free any resources that are owned by this workflow or its applets.
Returns an iterable of QMenus to be added to the GUI
- Returns:
- iterable: QMenus to be added to the GUI
-
Applets¶
Applet classes do not have much functionality, but instead serve as a container for the main components of an applet:
- Top-level Operator
- GUI
- Serializer(s)
Applets must inherit from the Applet abstract base class. Subclasses should override the appropriate properties. The base class provides a few signals, which applets can use to communicate with the shell.
Applet Base Class¶
-
class
ilastik.applets.base.applet.
Applet
(name, syncWithImageIndex=True, interactive=True)[source]¶ Base class for all applets. The shell and workflow depend on this interface only. Applets can subclass from this class directly, but in most cases it is easier to subclass
StandardApplet
.-
__init__
(name, syncWithImageIndex=True, interactive=True)[source]¶ Constructor. Subclasses must call this base implementation in their own
__init__
methods. If they fail to do so, the shell raises an exception.Parameters: - name – The applet’s name, which will appear as the applet drawer title.
- syncWithImageIndex – If True, the shell/workflow will add an image lane to this applet for each image in the interactive workflow.
-
progressSignal
= None¶ Progress signal. When the applet is doing something time-consuming, this signal tells the shell to show a progress bar. Signature:
emit(percentComplete, canceled=false)
Note
To update the progress bar correctly, the shell expects that progress updates always begin with at least one zero update and end with at least one 100 update. That is:
self.progressSignal.emit(0)
... more updates ...self.progressSignal.emit(100)
-
shellRequestSignal
= None¶ Shell request signal is used to trigger certain shell actions. Signature:
emit(request)
whererequest
is an integer corresponding to the action the shell should take.The allowable actions are enumerated in the
ShellRequest
class. Example invocation:self.shellRequest.emit(ShellRequest.RequestSave)
-
appletStateUpdateRequested
= None¶ - This signal informs the workflow that something has changed that might
- affect the usability of various applets in the workflow.
Signature:
emit()
-
sendMessageToServer
= None¶ This signal tells the shell to send the dict ‘data’ to the (TCP) server ‘name’ (if connected) Signature:
emit(servername, data)
-
topLevelOperator
¶ Abstract property. The applet’s Top Level Operator, which is a single operator for all computation performed by the applet. Each applet has exactly one top-level operator for performing computations. Workflow managers can connect the top-level operator of one applet to others.
-
getMultiLaneGui
()[source]¶ Abstract method. Provides the applet’s GUI, which must be an instance of
AppletGuiInterface
.
-
dataSerializers
¶ A list of dataSerializer objects for loading/saving any project data the applet is responsible for. Each serializer must be an instance of
AppletSerializer
Subclasses should override this property. By default, returns [].
-
-
class
ilastik.applets.base.applet.
ShellRequest
[source]¶ This class enumerates the actions that applets can ask the shell to perform via
Applet.shellRequestSignal
. At the moment, there is only one supported action.-
RequestSave
= 0¶ Request that the shell perform a “save project” action.
-
StandardApplet Base Class¶
-
class
ilastik.applets.base.standardApplet.
StandardApplet
(name, workflow=None, interactive=True, *args, **kwargs)[source]¶ In most cases, it is easiest to use StandardApplet as a base class for your custom applet. StandardApplets are designed to simplify two tasks for most use-cases: Creating a top-level operator and creating a GUI.
StandardApplet subclasses may expose their top-level operator in one of two ways:
- (Advanced) Override the
Applet.topLevelOperator
property directly. - (Simple) Override BOTH
singleLaneOperatorClass
andbroadcastingSlots
, in which case a default implementation oftopLevelOperator
is provided for you.
StandardApplet subclasses may expose their GUI in one of three ways:
- (Advanced) Override
createMultiLaneGui()
. - (Simpler) Override
createSingleLaneGui()
, in which case a default implementation ofcreateMultiLaneGui()
is provided for you. - (Simplest) Override
singleLaneGuiClass
, in which case default implementations ofcreateSingleLaneGui()
andcreateMultiLaneGui()
are provided for you.
-
__init__
(name, workflow=None, interactive=True, *args, **kwargs)[source]¶ Constructor.
Parameters: - name – The applet’s name as it will appear in the GUI (e.g. the Applet Drawer title).
- workflow – The workflow this applet belongs to (not required if the subclass provides its own topLevelOperator).
-
singleLaneOperatorClass
¶ Return the operator class which handles a single image. Single-lane applets should override this property. (Multi-lane applets must override
topLevelOperator
directly.)
-
broadcastingSlots
¶ Slots that should be connected to all image lanes are referred to as “broadcasting” slots. Single-lane applets should override this property to return a list of the broadcasting slots’ names. (Multi-lane applets must override
topLevelOperator
directly.)
-
topLevelOperator
¶ Get the top-level (multi-image-lane) operator for the applet. This default implementation uses
singleLaneOperatorClass
andbroadcastingSlots
to generate the top-level operator. Applets that must be multi-image-lane-aware must override this property. Note that the top-level operator must adhere to theMultiLaneOperatorABC
interface.
-
singleLaneGuiClass
¶ Return the class that will be instantiated for each image lane the applet needs. The class constructor should accept a single parameter: a single-lane of the top-level operator.
-
createSingleLaneGui
(imageLaneIndex)[source]¶ This function is called to create new instances of single-lane applet GUIs. If your applet’s single-lane GUI requires special constructor arguments, then override this method. Otherwise, this default implementation generates instances of your
singleLaneGuiClass
.
- (Advanced) Override the
Top-level Operators¶
Everything an applet does is centered around the applet’s top-level operator.
It is typically the keeper of all state associated with the applet.
The top-level operators that the workflow and shell see must be capbable of handling multiple image lanes.
That is, they must adhere to the MultiLaneOperatorABC
.
If your applet inherits from StandardApplet
,
then your single-lane top-level operator can be automatically adapted to the multi-lane interface.
The applet GUI and the applet serializers both make changes to the top-level operator and listen for changes made to the top-level operator. Here’s an example timeline, showing a typical sequence of interactions.
- The shell is launched with a blank workflow
- All slots are connected, but none have any data
- The shell loads a project file
- Calls each serializer to read settings from the project file and apply them to the appropriate slots of the top-level operator
- The GUI responds to the changes made to the top-level operator by updating the GUI appearance.
- Widgets in the applet drawer for the applet are updated with the current operator slot values.
- The user changes a setting in the GUI, which in turn changes a slot value on the applet’s top-level operator.
- The changes are propagated downstream from the top-level operator, possibly resulting in an update in the central widget.
- The applet serializer also notices the change, and makes a note that the serializer is “dirty”.
Step 4 is repeated as the user experiments with the workflow options.
- The user selects “Save Project”
- The shell determines which serializers have work to do by calling isDirty()
- The shell calls serializeToHdf5 on the dirty serializers, causing them to save the current state of the corresponding top-level operators to the project file.
Repeat step 4 as the user experiments with more workflow options.
- The user attempts to close the project.
- The shell determines if any serializers have work to do by calling isDirty(). If any declare themselves dirty, the user is asked to confirm his decision to close the project.
Applet GUIs¶
An applet’s GUI object is responsible for providing the widgets that the shell displays when this applet is selected by the user.
Here’s a screenshot of the ilastik-shell gui:
In the following figure, the areas of the GUI are labeled according to the terminology used in the ilastik code base:
An applet GUI is responsible for providing the widgets for each of the areas labeled above except for the “Current Image Menu”, which is created by the shell. Additionally, Applet GUIs provide any menu items that should be shown when an applet is being viewed by the user.
-
class
ilastik.applets.base.appletGuiInterface.
AppletGuiInterface
(topLevelOperatorView)[source]¶ This is the abstract interface to which all applet GUI classes should adhere.
-
centralWidget
()[source]¶ Abstract method. Return the widget that will be displayed in the main viewer area.
Abstract method. Return a list of QMenu widgets to be shown in the menu bar when this applet is visible.
-
viewerControlWidget
()[source]¶ Abstract method. Return the widget that controls how the content of the central widget is displayed. Typically this consists of a layer list control.
-
setEnabled
(enabled)[source]¶ Abstract method. Enable or disable the gui, including applet drawer, central widget, menus, and viewer controls.
-
setImageIndex
(imageIndex)[source]¶ Abstract method. Called by the shell when the user has switched the input image he wants to view. The GUI should respond by updating the content of the central widget. Note: Single-image GUIs do not need to provide this function.
-
imageLaneAdded
(laneIndex)[source]¶ Abstract method. Called when a new image lane has been added to the workflow, and the GUI should respond appropriately. Note: The default GUI provided by StandardApplet overrides this for you.
-
imageLaneRemoved
(laneIndex, finalLength)[source]¶ Abstract method. Called when a new image lane is about to be removed from the workflow, and the GUI should respond appropriately. The GUI should clean up any resourecs it owns. Note: The default GUI provided by StandardApplet overrides this for you.
-
stopAndCleanUp
()[source]¶ Abstract method. Called when the GUI is about to be destroyed. The gui should stop updating all data views and should clean up any resources it created (e.g. orphan operators).
-
allowLaneSelectionChange
()[source]¶ Abstract method. Called by the shell to determine if the shell’s lane selection combobox should be displayed. Return False if your applet GUI handles switching between lanes itself (e.g. DataSelection, DataExport), or if the notion of lanes doesn’t apply to this applet (e.g. ProjectMetadata, BatchProcessing).
-
Applet Serializers¶
-
class
ilastik.applets.base.appletSerializer.
AppletSerializer
(topGroupName, slots=None, operator=None)[source]¶ Base class for all AppletSerializers.
-
_serializeToHdf5
(topGroup, hdf5File, projectFilePath)[source]¶ Child classes should override this function, if necessary.
-
_deserializeFromHdf5
(topGroup, groupVersion, hdf5File, projectFilePath, headless=False)[source]¶ Child classes should override this function, if necessary.
-
isDirty
()[source]¶ Returns true if the current state of this item (in memory) does not match the state of the HDF5 group on disk.
Subclasses only need override this method if ORing the flags is not enough.
-
progressIncrement
(group=None)[source]¶ Get the percentage progress for each slot.
Parameters: group – If None, all all slots are assumed to be processed. Otherwise, decides for each slot by calling slot.shouldSerialize(group).
-
serializeToHdf5
(hdf5File, projectFilePath)[source]¶ Serialize the current applet state to the given hdf5 file.
Subclasses should not override this method. Instead, subclasses override the ‘private’ version, _serializetoHdf5
Parameters: - hdf5File – An h5py.File handle to the project file, which should already be open
- projectFilePath – The path to the given file handle. (Most serializers do not use this parameter.)
-
deserializeFromHdf5
(hdf5File, projectFilePath, headless=False)[source]¶ Read the the current applet state from the given hdf5File handle, which should already be open.
Subclasses should not override this method. Instead, subclasses override the ‘private’ version, _deserializeFromHdf5
Parameters: - hdf5File – An h5py.File handle to the project file, which should already be open
- projectFilePath – The path to the given file handle. (Most serializers do not use this parameter.)
- headless – Are we called in headless mode? (in headless mode corrupted files cannot be fixed via the GUI)
-
Serializable Slots¶
-
class
ilastik.applets.base.appletSerializer.
SerialSlot
(slot, inslot=None, name=None, subname=None, default=None, depends=None, selfdepends=True)[source]¶ Implements the logic for serializing a slot.
-
__init__
(slot, inslot=None, name=None, subname=None, default=None, depends=None, selfdepends=True)[source]¶ Parameters: - slot – where to get data to save
- inslot – where to put loaded data. If None, it is the
same as ‘slot’.
Parameters: - name – name used for the group in the hdf5 file.
- subname – used for creating subgroups for multislots. should be able to call subname.format(i), where i is an integer.
- default – DEPRECATED
- depends – a list of slots which must be ready before this slot can be serialized. If None, defaults to [].
- selfdepends – whether ‘slot’ should be added to ‘depends’
-
_serialize
(group, name, slot)[source]¶ Parameters: - group (h5py.Group) – The parent group.
- name (string) – The name of the data or group
- slot (SerialSlot) – the slot to serialize
-
_deserialize
(subgroup, slot)[source]¶ Parameters: subgroup (h5py.Group) – not the parent group. This slot’s group.
-
serialize
(group)[source]¶ Performs tasks common to all serializations, like changing dirty status.
Do not override (unless for some reason this function does not do the right thing in your case). Instead override _serialize().
Parameters: group (h5py.Group) – The parent group in which to create this slot’s group.
-
-
class
ilastik.applets.base.appletSerializer.
SerialListSlot
(slot, inslot=None, name=None, subname=None, default=None, depends=None, selfdepends=True, transform=None, store_transform=None, iterable=<type 'list'>)[source]¶ As the name implies: used for serializing a list.
The only differences from the base class are:
- if deserializing fails, sets the slot value to [].
- if it succeeds, applies a transform to every element of the list (for instance, to convert it to the proper type).
-
class
ilastik.applets.base.appletSerializer.
SerialBlockSlot
(slot, inslot, blockslot, name=None, subname=None, default=None, depends=None, selfdepends=True, shrink_to_bb=False, compression_level=0)[source]¶ A slot which only saves nonzero blocks.
-
__init__
(slot, inslot, blockslot, name=None, subname=None, default=None, depends=None, selfdepends=True, shrink_to_bb=False, compression_level=0)[source]¶ Parameters: - blockslot – provides non-zero blocks.
- shrink_to_bb – If true, reduce each block of data from the slot to its nonzero bounding box before feeding saving it.
-
-
class
ilastik.applets.base.appletSerializer.
SerialClassifierSlot
(slot, cache, inslot=None, name=None, default=None, depends=None, selfdepends=True)[source]¶ For saving a classifier. Here we assume the classifier is stored in the .
Applet Library¶
Finally, the ilastik project serves as a library of applets that are useful for many workflows. In particular, the Layer Viewer applet is a base class that implements simple display of arbitrary slots from your top-level operator. It is intended to be used as a base class for almost all user-defined applets.