How to create an image series OME-TIFF from python

Hi all,

inside my python code I have a loop processes 5d NumPy.Array. I managed to write every singe array incl metadata as an OME-TIFF, but it would be much more user-friendly to write let’ say one OME-TIFF with X series instead.

Has anyone a snippet etc. to get me started. Ideally I would like to avoid writing an 6D array into one OME-TIFF file with X -5d image series. In my imagination it would work like this:

  • open OME-TIFF file for writing
  • start loop
  • analyze 5D array
  • save 5D array to OME-TIFF as image series N

Or is a completely silly idea? Any thoughts are welcome.

Hi Sebastian,

recent versions of tifffile can write multi-series OME-TIFF files. There’s a short example in the docstring:

Write two numpy arrays to a multi-series OME-TIFF file:

>>> data0 = numpy.random.randint(0, 255, (32, 32, 3), 'uint8')
>>> data1 = numpy.random.randint(0, 1023, (4, 256, 256), 'uint16')
>>> with TiffWriter('temp.ome.tif') as tif:
...     tif.save(data0, compress=6, photometric='rgb')
...     tif.save(data1, photometric='minisblack',
...              metadata={'axes': 'ZYX', 'SignificantBits': 10,
...                        'Plane': {'PositionZ': [0.0, 1.0, 2.0, 3.0]}})
2 Likes

This is exactly what I tried, but I did not succeed. I think I am missing something here …

# -*- coding: utf-8 -*-

import sys
import os
import numpy as np
from aicsimageio import AICSImage, imread
import progressbar
import shutil
from apeer_ometiff_library import io, omexmlClass
import tifffile
from lxml import etree

filename = r"testdata\WP96_4Pos_B4-10_DAPI.czi"
savename = filename.split('.')[0] + '.ome.tiff'

# get AICSImageIO object using the python wrapper for libCZI
img = AICSImage(filename)

with tifffile.TiffWriter(savename, append=False) as tif:
    for s in progressbar.progressbar(range(img.shape[0]), redirect_stdout=True):

        # get the 5d image stack
        image5d = img.get_image_data("TZCYX", S=s)

        # write scene as OME-TIFF series
        tif.save(image5d,
                 photometric='minisblack',
                 contiguous=False,
                 metadata={'axes': 'TZCXY'})

    # close the AICSImage object at the end
    img.close()

When I open this one in Fiji it has 28 timepoints instead of 28 series …

Looks like you are using an older version of tifffile. The latest version (2020.9.3 on PyPI) will raise an exception for your code because the axes metadata should be 'TZCYX', not 'TZCXY'. Btw, contiguous=False, is no longer needed. To open the file in Fiji, use File > Import > Bio-Formats.

Cool, now it works as expected. Thank you so much. I might have mixed up my envs …

The code that works is now this:

# -*- coding: utf-8 -*-

import sys
import os
import numpy as np
from aicsimageio import AICSImage, imread
import progressbar
import shutil
from czitools import imgfileutils as imf
import tifffile
from lxml import etree

filename = r"testdata\WP96_4Pos_B4-10_DAPI.czi"
savename = filename.split('.')[0] + '.ome.tiff'

# get the metadata
md, additional_mdczi = imf.get_metadata(filename)

# get AICSImageIO object using the python wrapper for libCZI
img = AICSImage(filename)

with tifffile.TiffWriter(savename, append=False) as tif:

    for s in progressbar.progressbar(range(img.shape[0]), redirect_stdout=True):

        # get the 5d image stack
        image5d = img.get_image_data("TZCYX", S=s)

        # write scene as OME-TIFF series
        tif.save(image5d,
                 photometric='minisblack',
                 metadata={'axes': 'TZCYX',
                           'PhysicalSizeX': np.round(md['XScale'], 3),
                           'PhysicalSizeXUnit': md['XScaleUnit'],
                           'PhysicalSizeY': np.round(md['YScale'], 3),
                           'PhysicalSizeYUnit': md['YScaleUnit'],
                           'PhysicalSizeZ': np.round(md['ZScale'], 3),
                           'PhysicalSizeZUnit': md['ZScaleUnit']
                           }
                 )

    # close the AICSImage object at the end
    img.close()

print('Done')
1 Like