Channel shuffling and saving/adjusting channel names in the metadata

Dear community

I have to reshuffle channels and save combination of different channels as new images (ome.tif, using Bio-Formats). I need to do this for subsequent processing using a Matlab app, requires OME metadata with channel names.
Depending on how I do this, the metadata - specifically the channel names - in the output ome.tif is mixed up or absent.

My observations:

  1. Splitting and ImagePlus and exporting just one of the channels (or via duplicating an ImagePlus) , keeps the channel names with the same order after exporting with Bio-Formats, and excludes. E.g.:
    input: 3 channel ImagePlus, with channel names = RFP, GFP, DAPI
    → save only DAPI channel
    output: single image, with channel name = RFP
path = "someFilePath" + "ome.tif"
imp = IJ.getImage()
channels = ChannelSplitter.split(imp)[2] as ImagePlus, "Bio-Formats Exporter", "save=[$path] compression=Uncompressed")
  1. Merging channels after splitting removes all the metadata. (A similar question that was asked here but not answered).
    E.g. input = 3 channels [RFP, GFP, DAPI] → output = 2 channels [DAPI, RFP]
    Channel name information is lost.
path = "someFilePath" + "ome.tif"
imp = IJ.getImage()
cal = imp.getCalibration()
channels = ChannelSplitter.split(imp)
newImp = RGBStackMerge.mergeChannels([channels[2], channels[0]] as ImagePlus[], true)
newImp.setCalibration(cal), "Bio-Formats Exporter", "save=[$path] compression=Uncompressed")

Eventually, I found that the after opening an image (in my case .nd2 images) with Bio-Formats the OME metadata is stored within the ImagePlus in the “original file info” as xml-style string. This I copied and modified in a very dirty way…
Example code I use:

path = "someFilePath" + "ome.tif"
imp = IJ.getImage()
xmlOME = imp.getOriginalFileInfo().description
modifiedImp = ... // splitting & merging channels
adjustFileInfo(xmlOME, ["DAPI", "RFP"], modifiedImp), "Bio-Formats Exporter", "save=[$path] compression=Uncompressed")

// function to adjust the xml File
def adjustFileInfo(String xml, String[] chNames, ImagePlus impNew) {
    channelInfo = "<Channel Color=\"65535\" EmissionWavelength=\"440.0\" EmissionWavelengthUnit=\"nm\" ID=\"Channel:0:0\" Name=\"10xDAPI\" SamplesPerPixel=\"1\"><DetectorSettings ID=\"Detector:0:0\"/><LightPath/></Channel>"
    channelInfoArray = channelInfo.split("\"")
    // adjust the OME xml file info
    xmlFinal = xml.split("<Channel ")[0]

    // add the channel (name) information
    for (name in chNames) {
        channelInfoArray[1] = "65535" // or -7601921 or -939523841
        channelInfoArray[3] = "440.0" // or 607.0 or 708.0
        channelInfoArray[9] = name
        xmlFinal += channelInfoArray.join("\"")
    // "close" the xml file
    xmlFinal += "</Pixels></Image></OME>"

    // force the new file info into the imagePlus
    impNew.setFileInfo(new FileInfo())
    impNew.getOriginalFileInfo().description = xmlFinal

I am not super happy with this solution…
Does anyone know a easier, more elegant way to set metadata (channel names) to an ImagePlus, so that the Bio-Formats exporter will include those into the its (OME) metadata?
(Preferentially, avoiding writing the whole OME xml from scratch as exemplified here)

Thanks for your input and suggestions!

1 Like

To swap the channel metadata in a macro you would likely have to use a jython macro similar to bio-formats-examples/ at 7312b84159df3bbe83d8d99efb2c8a7e92c44b5e · dgault/bio-formats-examples · GitHub. In this example it is appending extra metadata before converting files, in your example it would be modifying the existing the metadata and then writing the planes in the desired order.

If it is an option to use the Bio-Formats command line tools (can be found at Bio-Formats Downloads | Open Microscopy Environment (OME)) then you could achieve the swap as below:

Convert and split the channels:
bfconvert path/to/input/myfile.nd2 path/to/output/myfile_C%c.ome.tiff
Rename the files so the channel indexes are in the desired order

Either import these files and they should be automatically grouped correctly or if preffered convert to a single file with:
bfconvert path/to/output/myfile_C0.ome.tiff path/to/output/myfile.ome.tiff

1 Like

Hi @dgault

Thanks for the suggestions!

The command line tools do work and save the channel names metadata correctly for the individual channel files (converted to a single file using the -nogroup option).
However, just renaming the files to have a different channel order does not swap the channel names in their metadata after import to Fiji…
Further, I did not see if the bftools also allow to create single files from a combination of channels that are less than the channel number of the input image?

Hence, I prefer your nice jython example:

This should give me more flexibility to combine and reorder the channels of choice, and adjusting the metadata fields from a copied metadata object rather than just some string operations.
I just need to get familiar with writing byte arrays instead of ImagePluses…

Thanks again!