cgohlke / tifffile

Read and write TIFF files
https://pypi.org/project/tifffile
BSD 3-Clause "New" or "Revised" License
539 stars 155 forks source link

Write multi-file OME-TIFF #80

Closed lambdamoses closed 3 years ago

lambdamoses commented 3 years ago

I'm trying to reformat some regular TIFF images into a multi-series or multi-file OME-TIFF. Here each series should be a field of view (FOV), with x and y coordinates of stage position. I tried doing multi-series, but apparently I need to load all the images from all those FOVs into memory, into a numpy array one of whose dimensions is series to write with TiffWriter, and my computer doesn't have that much memory.

Then I tried writing multi-file, in which each file is a FOV, and the XML metadata contains information for all the files and Fiji will consider those files series when I load one file with Bio-Formats. However, it didn't quite work, as existing multi-file OME-TIFF has a UUID for each TiffData for each plane specifying the file name, like this:

image

I wrote all the metadata fields with code inspired by issue #16. However, I haven't figured out how to write the UUID and FileName part, say with python-bioformats. Is there any way to write the UUID and FileName under TiffData?

cgohlke commented 3 years ago

Tifffile doesn't support writing multi-file OME-TIFF. You'll have to save your own OME-XML as a description in the master file.

To write a large, single file OME-TIFF, you don't have to provide the data as a single numpy array to TiffWriter. Instead, pass the shape and dtype of the whole series, and a generator function of individual frames (or tiles) in the series to TiffWriter.write().

lambdamoses commented 3 years ago

Thank you for answering. I can load each z stack into memory and write them into the series. I made a dumb mistake when entering the metadata kwarg the first time I tried so I turned to xml, which didn't go well. This code worked:

with TiffWriter("test3.ome.tiff") as tw:
    for i,f in enumerate(fns):
        stack = [imread(fn) for fn in f]
        stack = np.stack(stack)
        tw.write(stack, metadata = {'axes': 'ZYX', 'SignificantBits': 16,
                                   'PhysicalSizeX': scalex, 'PhysicalSizeY': scaley,
                                   'PhysicalSizeZ': scalez, 
                                   'Plane': {'PositionX': [fov_coords[i,0] for j in range(SizeZ)], 
                                             'PositionY': [fov_coords[i,1] for j in range(SizeZ)], 
                                             'PositionZ': [1.5*n for n in range(SizeZ)]}})

where fns is a list of lists of file names for each FOV, and fov_coords is a matrix of FOV coordinates each row of which is for one FOV.