Setting LightSource in ome-tiff

Hi all,
I am using a script adapted from a previous thread which works great :stuck_out_tongue:

I’m just struggling to set the LightSource element to appear, eventhough I set the required LightSourceID.
Also for the channel element, I managed to have most metadata but could not manage to set a custom channelID. I think I follow the convention advised here

I use the methods for the metadataStore class, from the Fiji editor with the latest version of available packages.

Importing the file in Fiji with bioformat I get what seems like proper metadata

Here a minimal Jython example taking a tiff file, populating some metadata and saving the resulting file next to the original one. And the image file I used
crop.tif (13.0 KB)

Sorry it’s a bit lengthy

#@ File (label='Path to image') path
This macro requests an image tif file, add metadata and write a new file in the image folder with the same name but extension .ome.tif
from loci.formats import MetadataTools, ImageReader, ImageWriter, FormatTools
from ome.xml.model.primitives import NonNegativeInteger, PositiveInteger, PercentFraction, Color
from ome.xml.model.enums 	  import DimensionOrder, PixelType, AcquisitionMode
import os

# Get path to image
filePath = path.getPath()

# Initiate the reader
reader = ImageReader()
m = MetadataTools.createOMEXMLMetadata() # returns metadataStore

# Read initial image

# Set metadata in metadataStore m
## Pixels metadata
m.setPixelsBigEndian(False, 0)
m.setPixelsSignificantBits(PositiveInteger(16), 0)
m.setPixelsType(PixelType.UINT16, 0)
m.setPixelsInterleaved(False, 0)
m.setPixelsDimensionOrder(DimensionOrder.XYCZT, 0)

## Image dimensions (called PixelSize, different than physical size)
zero = NonNegativeInteger(0) # requires where the methods requie a NonNegativeInteger variable
one  = PositiveInteger(1)
width = PositiveInteger(90)
height = PositiveInteger(72)

m.setPixelsSizeC(one, 0)
m.setPixelsSizeT(one, 0)
m.setPixelsSizeX(width, 0)
m.setPixelsSizeY(height, 0)
m.setPixelsSizeZ(one, 0)    # number of slices

## Channel # partly working
m.setChannelID("Channel:1", 0, 0) # this does not work
m.setChannelName("Test", 0, 0) # this works
m.setChannelColor(Color(1), 0, 0) # this works
m.setChannelAcquisitionMode(AcquisitionMode.WIDEFIELD, 0, 0) # this works

## Light source # not working
m.setChannelLightSourceSettingsID("LightSource:1", 0, 0) 
percent = PercentFraction(0.5)
m.setChannelLightSourceSettingsAttenuation(percent, 0, 0)

# Create a new image with metadata
writer = ImageWriter()            # Create image writer
writer.setMetadataRetrieve(m)     # Associate metadata to writer
outPath = os.path.splitext(filePath)[0] + '.ome.tif'     # Create path to new file (apparently .tif is fine too)
writer.setId(outPath)             # Give path to writer 

 # Copy the pixel data to the new edited file
for series in range(reader.getSeriesCount()):
  for image in range(reader.getImageCount()):
    writer.saveBytes(0, reader.openBytes(0))

print 'Done'

Hi @LThomas, from running your script there are 2 different issues for the channel and the lightsource. The output file actually has the metadata and IDs which you set, however the reader is overriding these when opening the file.

The LightSourceSettings are being ignored as the reader could not find a matching Instrument, adding an Instrument with a matching ID should resolve this. For example below I am creating a Laser as the LightSource:

m.setInstrumentID("Instrument:1", 0) 
m.setLaserID("LightSource:1", 0, 0) 
m.setChannelLightSourceSettingsID("LightSource:1", 0, 0) 
percent = PercentFraction(0.5)
m.setChannelLightSourceSettingsAttenuation(percent, 0, 0)

The LightSource doesn’t have to be a Laser but can be any of Arc, Filament, GenericExcitationSource, Laser or LightEmittingDiode (see

In the case of the channel ID however this appears to be a bug in Bio-Formats and the original ID is getting overridden. I will create a GitHub Issue for this issue.


Hi David, thanks for the renewed help ! That did the trick !

I realized that I actually never declared a light source in my original script :sweat_smile:
I though I was doing so with
m.setChannelLightSourceSettingsID("LightSource:1", 0, 0)
but now I understood that it expects a reference to a lightsource ID and does not declare a light source.

Glad I could help spotting a bug for the channel !