Flujos de trabajo en napari#

Para usar napari y dask juntos para definir y diseñar flujos de trabajo, hemos creado una pequeña biblioteca para hacer estas cosas más convenientes: napari-workflows. El objetivo era permitir al usuario configurar flujos de trabajo haciendo clic en napari. Estos flujos de trabajo son luego accesibles como objetos, similares a un diccionario, a los que se puede solicitar resultados de pasos específicos del flujo de trabajo. Por ejemplo, en el flujo de trabajo que se muestra a continuación, una imagen de entrada se desenfoca utilizando un kernel gaussiano y luego se aplica un umbral utilizando el método de Otsu y 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

Primero, definimos un flujo de trabajo y le agregamos operaciones. Por ejemplo, una operación que toma una imagen llamada "input" y produce una imagen "denoised" a partir de ella utilizando la función gaussian() y sigma=2 como parámetro.

workflow = Workflow()

# define denoising
workflow.set("denoised", gaussian, "input", sigma=2)

También podemos agregar funciones personalizadas, lo cual es necesario, por ejemplo, para producir una imagen binaria a partir de una imagen de intensidad directamente con una sola llamada de función.

# define segmentation
def threshold(image):
    return image > threshold_otsu(image)
workflow.set("binarized", threshold, "denoised")

También aplicamos etiquetado de componentes conectados a la imagen binaria.

workflow.set("labeled", label, "binarized")

# Imprimamos todo el flujo de trabajo
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)

Ejecutando flujos de trabajo#

Hasta aquí, no se han involucrado imágenes. Ahora cargamos una imagen y la almacenamos en el flujo de trabajo como "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]]

Para ejecutar realmente el cálculo, llamamos a la función workflow.get() que produce una única salida especificada. Internamente, también ejecutará todas las operaciones intermedias necesarias para llegar a la salida final.

result = workflow.get("labeled")

imshow(result, labels=True)
../_images/b46f00c2a30b6b117eb2e39466aeb14acc0b44b46a27ed2c5f2e130939bad9ac.png