Page 1 of 1

Default rendering settings when script creates an image

PostPosted: Thu Aug 04, 2011 11:08 am
by a.herbert
Hi,

I am using the Gateway API to create new images. I have scripts that work on multi-channel images and create new images using createImageFromNumpySeq().

I would like to know the best way to set up the default rendering settings for the image. I have managed to do this using the following code:

Code: Select all
def cloneImage(conn, img):
    """
    Clone the image into the same dataset in OMERO.
   
    @param conn:   The BlitzGateway connection
    @param img:    The OMERO ImageWrapper object
    """
    imageName = os.path.basename(img.getName())
    print "Image Id = %s" % img.getId()
    print "Image name = %s" % imageName
    print "Dimensions = x%s,y%s,z%s,c%s,t%s" % (
        img.getSizeX(), img.getSizeY(), img.getSizeZ(), img.getSizeC(), img.getSizeT() )

    renderingEngine = conn.createRenderingEngine()
    updateService = conn.getUpdateService()

    pixels = img.getPrimaryPixels()
   
    Z = range(img.getSizeZ())
    C = range(img.getSizeC())
    T = range(img.getSizeT())

    # Store original channel colours and names
    colors = []
    cNames = []
    for index, c in enumerate(img.getChannels()):
        colors.append(c.getColor().getRGB())
        cNames.append(str(c.getLabel()))

    # Use a tile generator to join up multiple frame image and upload to OMERO
    def tileGen():
        for z in Z:
            for c in C:
                for t in T:
                    # ACTUAL PROCESSING WOULD BE DONE HERE
                    yield pixels.getPlane(z, c, t)
   
    newImg = conn.createImageFromNumpySeq(tileGen(),
        img.getName(), len(Z), len(C), len(T),
        img.getDescription(), dataset=img.getDataset())

    print "New Image Id = %s" % newImg.getId()
   
    # Apply colors from the original image to the new one
    newImg._prepareRenderingEngine()
    for c, color in enumerate(colors):
        r,g,b = color
        newImg._re.setRGBA(c, r, g, b, 255)
    newImg._re.saveCurrentSettings()
    newImg._re.close()

    # Apply the original channel names
    pixelsId = newImg.getId()
    renderingEngine.lookupPixels(pixelsId)
    if not renderingEngine.lookupRenderingDef(pixelsId):
        renderingEngine.resetDefaults() 
    renderingEngine.load()
    pixels = renderingEngine.getPixels()
    for i, c in enumerate(pixels.iterateChannels()):
        lc = c.getLogicalChannel()
        lc.setName(rstring(cNames[i]))
        updateService.saveObject(lc)
       
    # Apply the original pixel size - Need to get the object again to refresh state
    newImg = conn.getObject("Image", newImg.getId())
    pixels = newImg.getPrimaryPixels()
    pixels.setPhysicalSizeX(rdouble(img.getPixelSizeX()))
    pixels.setPhysicalSizeY(rdouble(img.getPixelSizeY()))
    pixels.setPhysicalSizeZ(rdouble(img.getPixelSizeZ()))
    pixels.save()


This sets the rendering colours, channel names and physical size using the original image.

However the colours are not set as the defaults and are only applied to the user who owns the connection object:

  • If the owner opens the image in OMERO Insight and, using the rendering controls, resets the image to defaults the channel colours get reset
  • Other users do not see the applied colours

Is there a way to set the default channel colours for all users?

Thanks,

Alex

Re: Default rendering settings when script creates an image

PostPosted: Thu Aug 04, 2011 12:45 pm
by wmoore
Hi Alex,

There are a couple of things going on here:

If you view another user's images in a "collaborative" group, you will see the 'default' rendering settings on the image (not the owners settings). In Insight, under the right-hand "Preview" tab, the 'viewed by' button will let you browse and apply other user's rendering settings.
In a "read-only" group, where you can't save your own rendering settings, all users will only see the owner's settings. We could extend this approach to "collaborative" groups too, but we'd need to be sure this was behavior that most users would want.

Having just asked Chris about this...
It seems the right solution would be to set the colors on the Channels of the new image.
E.g. channel.red, green, blue are 0-255.
Most images don't have these values set - we use wavelength metadata to choose 'default' rendering settings. But if set, then by default, these colors should be used for all users.

I haven't tried this myself just now, but should be something like
Code: Select all
    for i, c in enumerate(pixels.iterateChannels()):
        c.red = 255
        c.green = 0
        c.blue = 0
        updateService.saveObject(c)


Hope that works!

Will.

Re: Default rendering settings when script creates an image

PostPosted: Thu Aug 04, 2011 2:10 pm
by a.herbert
Hi Will,

I tried setting the RGB colour values directly into the channel. This did not work. So I tried settings the metadata instead. I was already setting the channel name into the logical channel object. I just added the emission and excitation wavelength from the original image. The new image then renders as expected.

Here is my modified code:

Code: Select all
def cloneImage(conn, img):
    """
    Clone the image into the same dataset in OMERO.
   
    @param conn:   The BlitzGateway connection
    @param img:    The OMERO ImageWrapper object
    """
    imageName = os.path.basename(img.getName())
    print "Image Id = %s" % img.getId()
    print "Image name = %s" % imageName
    print "Dimensions = x%s,y%s,z%s,c%s,t%s" % (
        img.getSizeX(), img.getSizeY(), img.getSizeZ(), img.getSizeC(), img.getSizeT() )

    renderingEngine = conn.createRenderingEngine()
    updateService = conn.getUpdateService()

    pixels = img.getPrimaryPixels()
   
    Z = range(img.getSizeZ())
    C = range(img.getSizeC())
    T = range(img.getSizeT())

    # Store original channel details
    cNames = []
    emWave = []
    exWave = []
    for index, c in enumerate(img.getChannels()):
        lc = c.getLogicalChannel()
        cNames.append(str(c.getLabel()))
        emWave.append(lc.getEmissionWave())
        exWave.append(lc.getExcitationWave())
        print "Label = %s " % cNames[-1]
        print "ExW   = %s " % exWave[-1]
        print "EmW   = %s " % emWave[-1]

    # Use a tile generator to join up multiple frame image and upload to OMERO
    def tileGen():
        for z in Z:
            for c in C:
                for t in T:
                    yield pixels.getPlane(z, c, t)
   
    newImg = conn.createImageFromNumpySeq(tileGen(),
        img.getName(), len(Z), len(C), len(T),
        img.getDescription(), dataset=img.getDataset())

    print "New Image Id = %s" % newImg.getId()
   
    # Apply settings from the original image to the new one
    newImg._prepareRenderingEngine()

    pixelsId = newImg.getId()
    renderingEngine.lookupPixels(pixelsId)
    if not renderingEngine.lookupRenderingDef(pixelsId):
        renderingEngine.resetDefaults() 
    renderingEngine.load()
    pixels = renderingEngine.getPixels()
   
    for i, c in enumerate(pixels.iterateChannels()):
        lc = c.getLogicalChannel()
        lc.setEmissionWave(rint(emWave[i]))
        lc.setExcitationWave(rint(exWave[i]))
        lc.setName(rstring(cNames[i]))
        updateService.saveObject(lc)

    renderingEngine.resetDefaults() 

    # Apply the original pixel size - Need to get the object again to refresh state
    newImg = conn.getObject("Image", newImg.getId())
    pixels = newImg.getPrimaryPixels()
    pixels.setPhysicalSizeX(rdouble(img.getPixelSizeX()))
    pixels.setPhysicalSizeY(rdouble(img.getPixelSizeY()))
    pixels.setPhysicalSizeZ(rdouble(img.getPixelSizeZ()))
    pixels.save()


Regards,

Alex

Re: Default rendering settings when script creates an image

PostPosted: Thu Aug 04, 2011 2:36 pm
by wmoore
Hi Alex,

Glad you got it working.
I'll look into this a bit more when I have time. It gets more complex if the images don't have channel wavelengths set, since we then use excitation and emission filters on channels!

Cheers,

Will.

Re: Default rendering settings when script creates an image

PostPosted: Thu Aug 04, 2011 3:44 pm
by a.herbert
Hi Will,

If you can let me know the order in which OMERO goes through the meta data to assign colours that would be useful. I can then make sure my script copies all the meta-data that is needed to make the new images 'appear' normal to the user.

So far all my test images have worked since they have the wavelength data. If I find one without then that is when I'll need to add more to my script.

Regards,

Alex

Re: Default rendering settings when script creates an image

PostPosted: Thu Aug 04, 2011 4:06 pm
by wmoore
I can't remember the exact code/order, but I believe it's something like

* Emission Wavelength
* Excitation Wavelength
* LightPath/Emission Filter/CutIn
* LightPath/Excitation Filter/CutIn & CutOut
* Possibly also use Laser wavelength?? Channel/LightSourceSettings/LightSource ?

Also, if we have emission data for some channels and not for others, then we assume those are grey (transmitted light).

Will.

Re: Default rendering settings when script creates an image

PostPosted: Thu Aug 11, 2011 7:50 am
by cxallan
wmoore wrote:...

I haven't tried this myself just now, but should be something like
Code: Select all
    for i, c in enumerate(pixels.iterateChannels()):
        c.red = 255
        c.green = 0
        c.blue = 0
        updateService.saveObject(c)


Hope that works!

Will.


The channel colours have the highest priority but all four values (red, green, blue and alpha) must be set, so you will need something like:

Code: Select all
    for i, c in enumerate(pixels.iterateChannels()):
        c.red = 255
        c.green = 0
        c.blue = 0
        c.alpha = 255
        updateService.saveObject(c)