Lazyflow Developer Tutorial

I started out in my new position as student assistant to Dr. Anna Kreshuk at the Heidelberg Collaboratory for Image Processing this month, and was lucky to be able to dive into the coding directly during the hackathon held from April 8 to April 12. My task was testing the UI of the ilastik software and reporting any bugs I found, but later on I started fixing a few bugs myself. Therefore, I had to work my way through the developer documentation and other sources to get deeper understanding of how stuff works®. I thought the best way to handle this was to develop a short tutorial for myself and anyone else wanting to kick start with ilastik development. So here it is.

All of the code reviewed in this tutorial can be found at my github repo. I’m going to assume that you are familiar with python, git and github, and some knowledge of numpy would be fine (I’m not a numpy expert myself). Furthermore, you got to have a working development environment for ilastik. Basically this means that the following code does not lead to errors:

import numpy
import vigra
import lazyflow
import volumina
import ilastik

I will not go into the neccessary steps for this, mostly because this will be much easier in the future than it is right now, but also because I don’t really know how to myself.

So what do we want to do now? Let’s make clear what the software does in the first place: Ilastik stands for interactive learning and segmentation toolkit. It basically provides workflows for image processing tasks, like the classification of image regions. One such workflow consists of multiple operators that are chained together, providing a flexible approach to workflow designs. The terms workflow and operator are both specific elements of the software, and we will analyze them one by one.

The Operator class is defined in lazyflow. It represents some kind of operation being applied to the input data. The Operator interface is used so that the operator can be plugged into any Workflow. The Operator class is documented here, but I will go over the basics quickly. A regular operator has an input slot, an output slot and an execute method. The input slot can be hooked to another output slot or filled manually. The output slot is a required slot that can be hooked to by other operators. The execute method performs the actual operation. Take a look at the following example:

# ...
# we set the variable 'data' somewhere above
# instantiate the operator class
op = ExampleOperator()
# provide input
op.inputSlot.setValue(data) # inputSlot is an arbitrary attribute name, notice that input is a python keyword
# make an output request
request = op.output[:]
# wait for the request to complete
data = request.wait()

That is, in a nutshell, how an operator object will be used in a workflow. So let’s code a real example (just ignore the extra stuff in there): We will provide the OpInvert class later, let me just tell you now that it will invert a given grayscale image.