Working with microscopy data

Introduction

One of the main driving forces behind the development of jicbioimage has been the need to simplify programmatic analysis of microscopy data.

Microscopy data differ from normal images in that they can be multidimensional. For example a microscopy image can consist of several z-slices, creating something like a 3D object, as well as several time points, creating something like a movie.

What this means in practise is that a microscopy datum is in reality a collection of 2D images. What jicbioimage tries to do is to provide easy access to the individual 2D images in the microscopy datum. This is achieved by unzipping the content of the microscopy datum into a backend, which acts as a type of cache of the individual 2D images.

However, microscopy data comes in a multitude of differing formats and it is not the intention that jicbioimage should understand these formats natively. Particularly as this is something that the Open Microscopy team already does through its BioFormats project.

In order to be able to process microscopy data jicbioimage therefore depends on the BioFormats command line tools. In particular the bfconvert tool, which is used to populate the backend.

For more information on how to install jicbioimage and the BioFormats command line tools please see the Installation notes.

Image collection classes

There are two image collection classes:

These are used for managing access to the images stored within them. To this end the jicbioimage.core.image.ImageCollection class has got the functions below:

The jicbioimage.core.image.MicroscopyCollection class is more advanced in that individual images can be accessed by specifying the series, channel, zslice and timepoint of interest. For more information have a look at the API documentation of:

Obtaining image collections

One can obtain a basic jicbioimage.core.image.ImageCollection by loading a multipage TIFF file into a jicbioimage.core.io.DataManager. Let us therefore create a jicbioimage.core.io.DataManager.

>>> from jicbioimage.core.io import DataManager
>>> data_manager = DataManager()

Into which we can load the sample multipage.tif file.

>>> multipagetiff_fpath = "./tests/data/multipage.tif"

The jicbioimage.core.io.DataManager.load() function returns the image collection.

>>> image_collection = data_manager.load(multipagetiff_fpath)
>>> type(image_collection)
<class 'jicbioimage.core.image.ImageCollection'>

Which contains a number of jicbioimage.core.image.ProxyImage instances.

>>> image_collection  
[<ProxyImage object at ...>,
 <ProxyImage object at ...>,
 <ProxyImage object at ...>]

Accessing data from microscopy collections

Suppose instead that we had a microscopy file. Here we will use the z-series.ome.tif file.

>>> zseries_fpath = "z-series.ome.tif"

Let us now load a microscopy file instead.

>>> microscopy_collection = data_manager.load(zseries_fpath)
>>> type(microscopy_collection)
<class 'jicbioimage.core.image.MicroscopyCollection'>
>>> microscopy_collection  
[<MicroscopyImage(s=0, c=0, z=0, t=0) object at ...>,
 <MicroscopyImage(s=0, c=0, z=1, t=0) object at ...>,
 <MicroscopyImage(s=0, c=0, z=2, t=0) object at ...>,
 <MicroscopyImage(s=0, c=0, z=3, t=0) object at ...>,
 <MicroscopyImage(s=0, c=0, z=4, t=0) object at ...>]

One can now use a variety of methods to access the underlying microscopy images. For example to access the third z-slice one could use the code snipped below.

>>> microscopy_collection.proxy_image(z=2)  
<MicroscopyImage(s=0, c=0, z=2, t=0) object at ...>

Alternatively to access the raw underlying image data of the same z-slice one could use the code snippet below.

>>> microscopy_collection.image(z=2)  
<Image object at 0x..., dtype=uint8>

Similarly one could loop over all the slices in the z-stack using the code snippet below.

>>> for i in microscopy_collection.zstack_proxy_iterator():  
...     print(i)
...
<MicroscopyImage(s=0, c=0, z=0, t=0) object at ...>
<MicroscopyImage(s=0, c=0, z=1, t=0) object at ...>
<MicroscopyImage(s=0, c=0, z=2, t=0) object at ...>
<MicroscopyImage(s=0, c=0, z=3, t=0) object at ...>
<MicroscopyImage(s=0, c=0, z=4, t=0) object at ...>

One can also access the z-stack as a numpy.ndarray.

>>> microscopy_collection.zstack_array()  
array([[[ 0,  0,  0,  0,  0],
        [ 0,  0,  0,  0,  0],
        [ 0,  0,  0,  0,  0],
        ...
        [96, 96, 96, 96, 96],
        [96, 96, 96, 96, 96],
        [96, 96, 96, 96, 96]]], dtype=uint8)

However, it is often more convenient to access the z-stack as a jicbioimage.core.image.Image3D using the jicbioimage.core.image.MicroscopyCollection.zstack() method.

>>> microscopy_collection.zstack()  
<Image3D object at 0x..., dtype=uint8>