Workflows in napari#
For using napari and dask together to define and design workflows, we made a small library to make these things more convenient: napari-workflows. Goal was to allow the user to setup a workflow by clicking in napari. These workflows are then accessible as object, similar to a dictionary, that can be asked for results of given workflow steps. For example, in the workflow shown below, an input image is blurred using a Gaussian kernel and then thresholded using Otsu’s method and scikit-image.
from napari_workflows import Workflow
from skimage.io import imread
from skimage.filters import threshold_otsu, gaussian
from skimage.measure import label
from pyclesperanto_prototype import imshow
First, we define a workflow and add operations to it. E.g. an operation that takes an image named "input"
and produces a "denoised"
image out of it using the gaussian()
function and sigma=2
as parameter.
workflow = Workflow()
# define denoising
workflow.set("denoised", gaussian, "input", sigma=2)
We can also add custom function, which is for exmaple necessary to produce a binary image out of an intensity image directly with a single function call.
# define segmentation
def threshold(image):
return image > threshold_otsu(image)
workflow.set("binarized", threshold, "denoised")
We also apply connected component labeling to the binary image.
workflow.set("labeled", label, "binarized")
# Let's print out the whole workflow
print(str(workflow))
Workflow:
denoised <- (<function gaussian at 0x19b297940>, 'input', 2, None, 'nearest', 0, None, False, 4.0)
binarized <- (<function threshold at 0x19dbd8430>, 'denoised')
labeled <- (<function label at 0x19ba7c820>, 'binarized', None, False)
Executing workflows#
Until here, there were no images involved. We now load an image and store it in the workflow as "input"
.
workflow.set("input", imread("https://samples.fiji.sc/blobs.png"))
print(str(workflow))
Workflow:
denoised <- (<function gaussian at 0x19b297940>, 'input', 2, None, 'nearest', 0, None, False, 4.0)
binarized <- (<function threshold at 0x19dbd8430>, 'denoised')
labeled <- (<function label at 0x19ba7c820>, 'binarized', None, False)
input <- [[ 40 32 24 ... 216 200 200]
[ 56 40 24 ... 232 216 216]
[ 64 48 24 ... 240 232 232]
...
[ 72 80 80 ... 48 48 48]
[ 80 80 80 ... 48 48 48]
[ 96 88 80 ... 48 48 48]]
To actually execute computation, we call the workflow.get()
function that produces a single specified output. Under the hood, it will also execute all intermediate operations that are necessary to come to the final output.
result = workflow.get("labeled")
imshow(result, labels=True)