Carga de carpetas de archivos tif multicanal / multiposición#

Algunos microscopios escriben datos de imagen en el disco como archivos tif corte por corte. Entonces encuentras muchos archivos nombrados por ejemplo image_z03_ch01.tif en estas carpetas. Para cargar estas carpetas, típicamente necesitas conocer detalles como cuántos cortes z y cuántos canales se fotografiaron, o si los datos de imagen tienen múltiples puntos de tiempo o no.

Ver también esta discusión.

from skimage import io
import matplotlib.pyplot as plt
import tifffile as tif
import numpy as np

import shutil
import os

path = "../../data/tif_folder/"

Para fines de demostración, simplemente creamos dicha carpeta con datos de imagen ficticios.

if not os.path.exists(path):
    os.mkdir(path)
for z in range(1,7):
    for c in range(1,5):
        #image = io.imread("c:/structure/data/blobs.tif")
        #io.imsave(f"c:/structure/data/images/r01c01f34p0{z}-ch0{c}t01.tiff", image)
        
        shutil.copy("../../data/blobs.tif",
                    path + f"image_z{str(z).zfill(2)}-ch{str(c).zfill(2)}.tiff")

Para obtener una visión general, podemos imprimir los nombres de los archivos en la carpeta.

for file in os.listdir(path):
    print(file)
image_z01-ch01.tiff
image_z01-ch02.tiff
image_z01-ch03.tiff
image_z01-ch04.tiff
image_z02-ch01.tiff
image_z02-ch02.tiff
image_z02-ch03.tiff
image_z02-ch04.tiff
image_z03-ch01.tiff
image_z03-ch02.tiff
image_z03-ch03.tiff
image_z03-ch04.tiff
image_z04-ch01.tiff
image_z04-ch02.tiff
image_z04-ch03.tiff
image_z04-ch04.tiff
image_z05-ch01.tiff
image_z05-ch02.tiff
image_z05-ch03.tiff
image_z05-ch04.tiff
image_z06-ch01.tiff
image_z06-ch02.tiff
image_z06-ch03.tiff
image_z06-ch04.tiff

scikit-image ofrece un imread_collection para cargar archivos que coincidan con un patrón, por ejemplo, que contengan *.

im_collection = io.imread_collection(path + "*")
im_collection
<skimage.io.collection.ImageCollection at 0x2244cd228e0>

Puedes convertir esta colección de imágenes en una pila de imágenes basada en un array de numpy. Desafortunadamente, el número de cortes z y canales es desconocido en este punto.

image_stack = im_collection.concatenate()
image_stack.shape
(24, 254, 256)

Si conoces el número de cortes z y canales, puedes reshape la imagen a una imagen 3D+ch o 4D.

num_channels = 4
num_z_slices = 6
image4d = np.reshape(image_stack, (num_channels, num_z_slices, image_stack.shape[-2], image_stack.shape[-1]))
image4d.shape
(4, 6, 254, 256)

Alternativamente, también puedes construir tus propios bucles for para cargar los datos desde el disco. Esto te da un poco más de libertad, por ejemplo, para ordenar cortes y canales en las dimensiones utilizadas.

num_channels = 4
num_z_slices = 6

image4d_loaded = np.asarray([
    [io.imread(path + f"image_z{str(z).zfill(2)}-ch{str(c).zfill(2)}.tiff") for c in range(1, 5)]
    for z in range(1, 7)
])
image4d_loaded.shape
(6, 4, 254, 256)