Traitement des données de time-lapse#

Ce notebook démontre comment traiter les données de time-lapse image par image.

from skimage.io import imread, imsave
import pyclesperanto_prototype as cle
import numpy as np

Tout d’abord, nous devons définir l’origine des données que nous voulons traiter et où les résultats doivent être sauvegardés.

input_file = "../../data/CalibZAPWfixed_000154_max.tif"
output_file = "../../data/CalibZAPWfixed_000154_max_labels.tif"

Ensuite, nous ouvrons le jeu de données et voyons quelles dimensions d’image il possède.

timelapse = imread(input_file)
timelapse.shape
(100, 235, 389)

S’il n’est pas évident de savoir quelle dimension est la dimension temporelle, il est recommandé de découper le jeu de données dans différentes directions.

cle.imshow(timelapse[:,:,150])
../_images/442b86f3596c139e62135602bdaac281bfc4ff584cf7186cb7c43320f2364a8e.png
cle.imshow(timelapse[50,:,:])
../_images/ec9eeb7a9de6d9f80660d6ccb54ce388278033abab502f313884091c6179f125.png

Évidemment, la dimension temporelle est la première dimension (index 0).

Ensuite, nous définissons le flux de traitement d’image que nous voulons appliquer à notre jeu de données. Il est recommandé de le faire dans une fonction pour que nous puissions la réutiliser plus tard sans tout copier-coller.

def process_image(image, 
                  # define default parameters for the procedure
                  background_subtraction_radius=10, 
                  spot_sigma=1, 
                  outline_sigma=1):
    """Segment nuclei in an image and return labels"""
    # pre-process image
    background_subtracted = cle.top_hat_box(image, 
                  radius_x=background_subtraction_radius, 
                  radius_y=background_subtraction_radius)
    
    # segment nuclei
    labels = cle.voronoi_otsu_labeling(background_subtracted,
                  spot_sigma=spot_sigma,
                  outline_sigma=outline_sigma)

    return labels

# Try out the function
single_timepoint = timelapse[50]
segmented = process_image(single_timepoint)

# Visualize result
cle.imshow(segmented, labels=True)
../_images/ce59c91bb9c93b4882f2dc7c145ab7e13a8b4d46c58793967833f7388be507d1.png

Après avoir fait fonctionner cette fonction sur un seul point temporel, nous devrions programmer une boucle for qui parcourt le time-lapse, applique la procédure à quelques images et visualise les résultats. Note : Nous parcourons le time-lapse par pas de 10 images, pour avoir un aperçu.

max_t = timelapse.shape[0]
for t in range(0, max_t, 10):
    label_image = process_image(timelapse[t])
    cle.imshow(label_image, labels=True)
../_images/51c6a9e598304f16847f3f1dfa098cc73ac8ee7cc392437e3ff8dca75bab9b5d.png ../_images/ab3bcb4e330a3a2eb539f33bf994b3f49b2f28fbe65f8a9536b59154eb9d7af7.png ../_images/c7b5a1ab97a72cff10faab3b10775ab52170e3cdec6c3679bf095e3199fae549.png ../_images/eaeba58f06f14bcd20ed9acc8f1d120e95a15aafe5a33046c09671057ec8b456.png ../_images/da2a4535ff6354b5b969b5aa928862976ae89f852f8210a45173e5e9a1d57bed.png ../_images/ce59c91bb9c93b4882f2dc7c145ab7e13a8b4d46c58793967833f7388be507d1.png ../_images/782db570f2761bb79105d0bd8d09f1c006db76309e0f73198f731951b7a890f7.png ../_images/a67f022642078a4ad8366a1d480c9de82cc69d9b6d359394eecfca0f5a4a310b.png ../_images/cb912bd877a26a7d486345389c8be2a466864e5802172087952024f04f799539.png ../_images/3d0b815c7f235394fb18a80db92db9d3d309ca81049f0be54e4d677eef4d11c8.png

Lorsque nous sommes convaincus que la procédure fonctionne, nous pouvons l’appliquer à l’ensemble du time-lapse, collecter les résultats dans une liste et les sauvegarder sous forme de pile sur le disque.

label_timelapse = []
for t in range(0, max_t):
    label_image = process_image(timelapse[t])
    label_timelapse.append(label_image)
    
# convert list of 2D images to 3D stack
np_stack = np.asarray(label_timelapse)

# save result to disk
imsave(output_file, np_stack)
C:\Users\rober\AppData\Local\Temp\ipykernel_27924\219181406.py:10: UserWarning: ../../data/CalibZAPWfixed_000154_max_labels.tif is a low contrast image
  imsave(output_file, np_stack)

Juste pour être sûr que tout a bien fonctionné, nous rouvrons le jeu de données et affichons sa dimensionnalité. Elle est censée être identique à celle du jeu de données timelapse original.

result = imread(output_file)

result.shape
(100, 235, 389)
timelapse.shape
(100, 235, 389)