Abriendo archivos LIF#
Cuando se trabaja con datos de imágenes de microscopía, circulan muchos formatos de archivo, como el Formato de Imagen Leica (LIF). En este notebook, abriremos un archivo .lif usando la biblioteca readlif.
Nota: Se recomienda usar AICSImageIO para leer imágenes LIF como se muestra en este notebook.
La biblioteca readlif se puede instalar así desde la terminal:
pip install readlif
Después de instalarla, se puede importar.
from readlif.reader import LifFile
import os
import requests
from skimage.io import imshow
import numpy as np
Como conjunto de datos de ejemplo, utilizaremos una imagen compartida por Gregory Marquart y Harold Burgess bajo la licencia CC-BY 4.0. Primero necesitamos descargarla.
filename = "../../data/y293-Gal4_vmat-GFP-f01.lif"
url = 'https://zenodo.org/record/3382102/files/y293-Gal4_vmat-GFP-f01.lif?download=1'
if not os.path.isfile(filename):
# solo descargamos el archivo si aún no lo tenemos
response = requests.get(url)
open(filename, "wb").write(response.content)
En este punto, el archivo debería estar en nuestra computadora y se puede abrir así.
file = LifFile(filename)
file
'LifFile object with 1 image'
lif_image = file.get_image(0)
lif_image
'LifImage object with dimensions: Dims(x=616, y=500, z=86, t=1, m=1)'
De la LifImage, podemos obtener fotogramas individuales como imágenes PIL.
pil_image = lif_image.get_frame(z=0)
type(pil_image)
PIL.Image.Image
Finalmente, estas imágenes PIL 2D se pueden convertir en matrices numpy. Lo que nos permite eventualmente echar un vistazo a la imagen.
np_image = np.array(pil_image)
np_image.shape
(500, 616)
imshow(np_image)
/opt/miniconda3/envs/devbio-napari-env/lib/python3.9/site-packages/skimage/io/_plugins/matplotlib_plugin.py:149: UserWarning: Low image data range; displaying image with stretched contrast.
lo, hi, cmap = _get_display_range(image)
<matplotlib.image.AxesImage at 0x1378ab970>
Para acceder a todos los píxeles en nuestra imagen 3D, primero debemos echar un vistazo a los metadatos del archivo.
lif_image.info
{'dims': Dims(x=616, y=500, z=86, t=1, m=1),
'display_dims': (1, 2),
'dims_n': {1: 616, 2: 500, 3: 86},
'scale_n': {1: 2.1354804344851965,
2: 2.135480168493237,
3: 0.9929687300128537},
'path': 'Experiment_002/',
'name': 'Series011',
'channels': 2,
'scale': (2.1354804344851965, 2.135480168493237, 0.9929687300128537, None),
'bit_depth': (12, 12),
'mosaic_position': [],
'channel_as_second_dim': False,
'settings': {}}
Por ejemplo, podría ser útil más adelante conocer el tamaño del vóxel en orden z/y/x.
voxel_size = lif_image.info['scale'][2::-1]
voxel_size
(0.9929687300128537, 2.135480168493237, 2.1354804344851965)
También podemos leer cuántas secciones tiene la pila 3D.
num_slices = lif_image.info['dims'].z
num_slices
86
Esta información nos permite escribir una función de conveniencia que permite convertir la imagen LIF en una pila de imágenes numpy 3D.
def lif_to_numpy_stack(lif_image):
num_slices = lif_image.info['dims'].z
return np.asarray([np.array(lif_image.get_frame(z=z)) for z in range(num_slices)])
image_stack = lif_to_numpy_stack(lif_image)
image_stack.shape
(86, 500, 616)
Esta pila de imágenes puede usarse luego, por ejemplo, para visualizar una proyección de intensidad máxima a lo largo de Z.
imshow(np.max(image_stack, axis=0))
<matplotlib.image.AxesImage at 0x137a1c610>