Set Bioformats metadata on existing TIFF

bio-formats
imagej
metadata
bioformats

#1

Hi,
I am looking for a simple way to set the image metadata according to the bioformat standard, for existing tiff images.
I know that there is the python-bioformats package, but some hint would be very welcome.

I am also interested by a solution within ImageJ possibly with Jython scripting, that would be great especially precising the packages to import.
Looking forward to your proposal…
Thanks


#2

Hi,

There is a script below which shows some of the basics of importing an image and reading metadata using Jython and the Bio-Formats API. From that you would additionally need to set the metadata values you want and write the image.

If you let me know what types of metadata values you are looking to set I can try and help you with the API calls required.

David Gault


#3

Hello David,
Thank you for your answer. I would like for instance to set the pixel size, exposure time, illumination intensity…
I found this demo script in java on the bioformat github repository :

It shows how to save an image with the metadata.
Consequently I have tried to set the pixel size for instance. So far I have something like this :

#@ File (label='Path to image') Path
from loci.formats import MetadataTools, ImageWriter, FormatTools
from ome.units import UNITS # https://static.javadoc.io/org.openmicroscopy/ome-xml/5.5.4/ome/units/UNITS.html
from ij import IJ

# Create a "metadata collection" object
Metadata = MetadataTools.createOMEXMLMetadata()
#print dir(omeMeta) # see all possible setters

# ex : setting pixel size
PixelSize = 1000 # whatever...

# convert pixel size to a length object
Length  = FormatTools.createLength(PixelSize,UNITS.MICROMETRE)

# Add pixel size to metadata
Metadata.setPixelsPhysicalSizeX(Length,0)


# Open image for which to set metadata
FilePath = Path.absolutePath
imp      = IJ.openImage(FilePath)

# Try converting to byte 
imProc = imp.getProcessor()
#imByte = imProc.convertToByte()
imByte = imProc.convertToByteProcessor()

# Save image with edited metadata
writer = ImageWriter()
writer.setMetadataRetrieve(Metadata)
NewPath = FilePath[:-4] + '-bis.tif'
writer.setId(NewPath)       # https://downloads.openmicroscopy.org/bio-formats/5.1.8/api/loci/formats/ImageWriter.html#setId(java.lang.String)
writer.saveBytes(0, imByte) # imByte must be a byte object... directly the image matrix ? 
writer.close()

But the line writer.setId(NewPath) always return a null pointer exception. I have tried to give a path pointing to an existing blank image, or to a filepath previously opened in the script with open(PathToNewFile,'w') but it did not work.
Any suggestion ?


#4

The code you have to edit the metadata looks to be correct. Im unsure why you are seeing a NullPointerException, writing to a new file should not be an issue (modifying the file name as you have done is fine). The one thing you are missing is the copying of the pixel data. Generally speaking the steps for conversion should be as below:

  • Create and setup a reader
  • Read the metadata to be modified
  • Modify the metadata
  • Create a writer and set the modified metadata
  • Copy the pixel data from the original file to the newly modified file

I have modified the example code you provided to show a working conversion which reads in a file, modifies the pixel size and writes out the new metadata with the existing pixel data:

    # read in and display ImagePlus object(s)
    from loci.plugins import BF
    from loci.formats import ImageReader, MetadataTools, ImageWriter, FormatTools
    from ij import IJ
    from ome.units import UNITS

    file = "/Users/dgault/Documents/Sample Images/ome_tiff/time-series.ome.tif"

    # Initiate the reader
    reader = ImageReader()
    omeMeta = MetadataTools.createOMEXMLMetadata()
    reader.setMetadataStore(omeMeta)
    reader.setId(file)

    # ex : setting pixel size
    PixelSize = 1000 # whatever...

    # convert pixel size to a length object
    Length  = FormatTools.createLength(PixelSize,UNITS.MICROMETRE)

    # Add pixel size to metadata
    omeMeta.setPixelsPhysicalSizeX(Length,0)

    # Create a new writer
    writer = ImageWriter()

    # Set the edited metadata
    writer.setMetadataRetrieve(omeMeta)
    NewPath = file[:-4] + '-bis.tif'
    writer.setId(NewPath)       # https://downloads.openmicroscopy.org/bio-formats/5.1.8/api/loci/formats/ImageWriter.html#setId(java.lang.String)

    # Copy the pixel data to the new edited file
    for series in range(reader.getSeriesCount()):
      reader.setSeries(series);
      writer.setSeries(series);
      for image in range(reader.getImageCount()):
        writer.saveBytes(0, reader.openBytes(0)) # imByte must be a byte object... directly the image matrix ? 

    # Close the reader and writer
    reader.close()
    writer.close()

A useful link for the steps on converting files can be found at https://docs.openmicroscopy.org/bio-formats/5.8.2/developers/export.html


#5

Works like a charm thanks !
For the new file I only changed the extension to .ome.tif , rather than the -bis.tif.
The SetID somehow recognises the extension for the encoding but actually both .tif or .ome.tif works the same. Maybe it is just a convention they use, and the extension is actually just .tifin both cases.

I also added a small print 'Done' at the end as the execution is not so instantaneous, like 1sec maybe :grin: