Skip to content

5.1 Workflows (Custom workflow)

Pradeep Rajasekhar edited this page Sep 12, 2022 · 12 revisions

This section follows on from workflows and will demonstrate how you can generate custom workflows and apply it to your deskewed data within napari-lattice!

We will use examples to demonstrate this.

Classical Segmentation

Image analysis workflows are usually bespoke and although we can generate segmented objects using pyclesperanto-assistant, what if we'd like to perform shape measurements as well?

In the previous section, we performed segmentation using:

  • gaussian blur
  • voronoi-otsu labelling

Now, we need to measure the shape properties of every label object across time. We will use napari-workflow API to design a workflow where we can call scikit-image regionprops at the end to perform measurements.

For executable code and more notes, please refer to this notebook.

We will create a workflow to perform the above segmentation:

#import workflow
from napari_workflows import Workflow

#We initialise a workflow
segmentation_workflow = Workflow()

#Set task for gaussian blur first 
input_image = "input_img"

 #To set a task, we use the set method
 segmentation_workflow.set("gaussian",
                      cle.gaussian_blur,
                      source = input_image,
                      sigma_x = 1, 
                      sigma_y= 1,
                      sigma_z= 0)

 #The second task will use input from above. so set the task name 'gaussian' as input 
 segmentation_workflow.set("voronoi-otsu",
                      cle.voronoi_otsu_labeling,
                      source = "gaussian",
                      spot_sigma = 14,
                      outline_sigma=0)

This only gives the images. To extract regionprops, we can write a custom function and save it as a .py file

from skimage.measure import regionprops_table
import numpy as np

def measure_region_properties(label_img):
    label_np = np.array(label_img)
     measurements = regionprops_table(label_np, properties=( 'area',
                                             'centroid',
                                             'axis_major_length',
                                             'axis_minor_length'))
     return measurements,label_np

This is saved as measure_regionprops.py. Now, we can import it within our workflow and set it as a task, where the output from voronoi-otsum which is a label image is the input for regionprops:

 segmentation_workflow.set("region_props",
                      measure_regionprops.measure_region_properties,
                      "voronoi-otsu"
                      )

Save this workflow:

from napari_workflows import _io_yaml_v1

_io_yaml_v1.save_workflow("regionprops_workflow.yml", segmentation_workflow)

To use the segmentation workflow with the custom python module regionprops, we need to ensure both the regionprops_workflow.yml file and measure_regionprops.py are in the same folder. This is ready to be used within napari-lattice.

To apply channel-specific operations, refer to this section.

Open napari-lattice and initialize your plugin. You can try with test dataset from here. You can use an ROI from the Crop and Deskew or just test it on the whole image. To learn how to import workflows and apply it on your data, instructions can be found here. If Previewing the workflow napari-lattice will perform the segmentation and save the regionprops table as a csv file in the same folder as the workflow. If you are Applying and Saving using a channel and time range, it will save the images and the table as a csv file in the specified output folder.

Cellpose

Cellpose is a very popular generalist cell segmentation algorithm. It now has a 'human-in-the-loop' training feature making it relatively easier to generate custom models.

Let us generate cell segmentation workflows using Cellpose for LLS data. You can install cellpose using its napari plugin, via Plugins -> Install/Uninstall Plugins and searching for cellpose. The installation may take a while. Once installed, to use the GPU for prediction, exit napari and then follow the GPU configuration instructions at the cellpose github page.

Link to Cellpose workflow notebook

For using cellpose in workflows, create a python file like the following and save it as cellpose_1.py. You can use any name, but make sure to use that name when calling the module from your workflow:

### cellpose_1.py
import numpy as np
from cellpose import models


def predict_cellpose(img,model_type:str="cyto"):
    model = models.Cellpose(gpu=True, model_type=model_type)
    channels = [0,0]
    img =np.array(img)
    masks, flows, styles, diams = model.eval(img, flow_threshold=None, channels=channels, diameter=25, do_3D=True)
    return masks

For details on how to use the cellpose API, refer to their https://cellpose.readthedocs.io/en/latest/index.html.

We define a workflow using the predict_cellpose function from cellpose_1.py module.

from napari_workflows import Workflow
from cellpose_1 import predict_cellpose

#We initialise a workflow
cellpose_workflow = Workflow()

#define cellpose prediction

input_arg = "input"
task_name = "cellpose"
cellpose_workflow.set(task_name,predict_cellpose,input_arg,model_type="cyto")

We use the cyto model here, but we can pass any model we like. Save the workflow:

from napari_workflows import _io_yaml_v1
_io_yaml_v1.save_workflow("cellpose_1_workflow.yml",cellpose_workflow)

To use different model or parameter for each channel, refer to this section.

Start napari-lattice and import your LLS data. To learn how to import workflows and apply it on your data, instructions can be found here.

ilastik

This section is in progress. It will showcase how to use ilastik python API in combination with models generated interactively within the ilastik software.

Channel-specific operations

More than often, the image processing algorithm, be it classical thresholding or an AI model is optimised for a specific protein/image channel within the microscopy image. It is possible to design flexible workflows that can use different software/settings based on the active channel or even timepoint'. Here, active channelortimepoint` refers to the channel or timepoint that is being deskewed/deconvolved and processed through the workflow. This is particularly useful for batch operations.

napari-lattice has a module named: config

from napari-lattice import config

Within your custom function, you can access the channel/time by calling config.channel or config.time respectively.

For channel:

#indexing starts at zero
if config.channel==0:
   #APPLY channel 0 specific function here
elif config.channel==1:
   #APPLY channel 1 specific function here

For time:

if config.time==x:
   #APPLY time x specific function here
elif config.time==y:
   #APPLY time y specific function here

Examples notebooks for designing multi-channel workflows are provided for thresholding and cellpose here.