How to setbigtiff true from python-bioformats javabridge?

saveimages

#1

Hi,

In python, when trying to write a tiff image stack I encountered the following error message:

File “/usr/local/lib/python2.7/dist-packages/javabridge/jutil.py”, line 392, in run_script
raise JavaException(call(e.throwable, “unwrap”, “()Ljava/lang/Object;”))
javabridge.jutil.JavaException: File is too large; call setBigTiff(true)

The message helpfully suggests I can write a larger file if I use a javbridge call to setBigTiff = True. But how is this done from python?

I guess it would be something like:

javabridge.call(???, “setBigTiff”, “True”, ???)

but don’t know what the arguments ‘???’ should be for accessing format writer.

Thanks for any help.


#2

I’ve used javabridge some, but not beyond the examples found in the documentation; so I’m not an expert. However, you might want to try using bioformats to read your images. The bioformats documentation says it can read BigTiff format. Goodluck!

Here is a snippet to setup bioformats in python.

import bioformats
import javabridge

javabridge.start_vm([], class_path=bioformats.JARS, max_heap_size="1G")

#3

Kyle, thanks for the quick reply.

I was already able to read and write using python-bioformats. The problem I encountered was in writing large Tiff files. I was looking for a simple approach to set the flag setBigTiff=true via javabridge.

I think I may now have solved the problem but not simply.

For writing a single bigtiff image, I amended a copy of the bioformats.write_image() function in formatwriter.py with the help of Delestro’s very useful stackoverflow code as follows:

import os
import bioformats.omexml as ome
import javabridge as jutil
import bioformats
import javabridge as javabridge

def write_tiff_image(pathname, pixels, pixel_type,
                 c = 0, z = 0, t = 0,
                 size_c = 1, size_z = 1, size_t = 1,
                 channel_names = None):
"""Write the image using bioformats.

:param filename: save to this filename

:param pixels: the image to save

:param pixel_type: save using this pixel type

:param c: the image's channel index

:param z: the image's `z` index

:param t: the image's `t` index

:param size_c: # of channels in the stack

:param size_z: # of z stacks

:param size_t: # of timepoints in the stack

:param channel_names: names of the channels (make up names if not present).

"""
omexml = ome.OMEXML()
omexml.image(0).Name = os.path.split(pathname)[1]
p = omexml.image(0).Pixels
assert isinstance(p, ome.OMEXML.Pixels)
p.SizeX = pixels.shape[1]
p.SizeY = pixels.shape[0]
p.SizeC = size_c
p.SizeT = size_t
p.SizeZ = size_z
p.DimensionOrder = ome.DO_XYCZT
p.PixelType = pixel_type
index = c + size_c * z + size_c * size_z * t
if pixels.ndim == 3:
    p.SizeC = pixels.shape[2]
    p.Channel(0).SamplesPerPixel = pixels.shape[2]
    omexml.structured_annotations.add_original_metadata(
        ome.OM_SAMPLES_PER_PIXEL, str(pixels.shape[2]))
elif size_c > 1:
    p.channel_count = size_c

pixel_buffer = bioformats.formatwriter.convert_pixels_to_buffer(pixels, pixel_type)

xml = omexml.to_xml()
script = """
importClass(Packages.loci.formats.services.OMEXMLService,
            Packages.loci.common.services.ServiceFactory,
            Packages.loci.formats.out.TiffWriter);
var service = new ServiceFactory().getInstance(OMEXMLService);
var metadata = service.createOMEXMLMetadata(xml);
var writer = new TiffWriter();
writer.setBigTiff(true);
writer.setMetadataRetrieve(metadata);
writer.setId(path);
writer.setInterleaved(true);
writer.saveBytes(index, buffer);
writer.close();
"""
jutil.run_script(script,
                 dict(path=pathname,
                 xml=xml,
                 index=index,
                 buffer=pixel_buffer))			

Here, the string script sent via javabridge creates a TiffWriter instance where I can set the crucial flag using:

writer.setBigTiff(true);

To solve my particular problem, I then call this function rather than biofromats.write_image() when writing the large image stack.

Regards,
FN


#4

Very cool! It might be possible to apply your solution to python-bioformats itself. Would you consider making a feature request here https://github.com/CellProfiler/python-bioformats/issues by filing an issue?


#5

Hi everyone,

great to see that this issue got resolved with a simple overriding of the bioformats.write_image() method. One alternative using the existing method worth trying would be to use a filename with a known BigTIFF extensions (.tf8, btf, tf2). Since Bio-Formats 5.1.3, this should internally force the TIFF writer to switch to BigTIFF when setId() is called.

Best,
Sébastien