Page 1 of 1

Adding annotations to images

PostPosted: Wed May 30, 2012 1:10 pm
by ihs7
Hi there,

I have been working on making script for automatic tagging on import for the Omero client. I have been having trouble with one tiny problem which I think could easily be solved.

Code: Select all
def saveAndLinkAnnotation(updateService, parent, annotation, ns=None, description=None):
    """ Saves the Annotation and Links it to a Project, Dataset or Image """

    if ns:
        annotation.setNs(rstring(ns))
    if description:
        annotation.setDescription(rstring(description))
    annotation = updateService.saveAndReturnObject(annotation)
    if type(parent) == omero.model.DatasetI:
        l = omero.model.DatasetAnnotationLinkI()
    elif type(parent) == omero.model.ProjectI:
        l = omero.model.ProjectAnnotationLinkI()
    elif type(parent) == omero.model.ImageI:
        l = omero.model.ImageAnnotationLinkI()
    else:
        return
    parent = parent.__class__(parent.id.val, False)
    l.setParent(parent)
    l.setChild(annotation)
    return updateService.saveAndReturnObject(l)

    # Text Annotations
def addTag(updateService, parent, text, ns=None, description=None):
    """ Adds a Tag. """
    child = omero.model.TagAnnotationI()
    child.setTextValue(rstring(text))
    saveAndLinkAnnotation(updateService, parent, child, ns, description)


These are the functions I am using to add a tag, so far so good. Then I want to go through all the images in my dataset and tag them all.

Code: Select all
obs = conn.getObjects(dataType, ids)
    objects = list(obs)
       
    if len(objects) == 0:
        print "No %ss found for specified IDs" % dataType
        return
       
    images = []
   
    if dataType == 'Dataset':
        for ds in objects:
            print "Processing Images from Dataset: %s" % ds.getName()
            imgs = list(ds.listChildren())
            images.extend(imgs)
    else:
        print "Processing Images identified by ID"
        images = objects
   
    editedImgIds = []
   
    for i in images:
        print " Editing image ID: %d Name: %s" % (i.id, i.name)
        # i.name returns full name of file with .jpg ending
       
        #print conn.getObject("Dataset", 102)._obj
        #print conn.getObject("Image", i.id)._obj
        ### EXPERIMENTAL TAGGING
        addTag(updateService, i._obj, "Test_Tag", "test/omero/tag/ns", description=None)
        editedImgIds.append(i.id)

    return editedImgIds


When I select dataset when I am running the script I am only able to tag the datasets with given IDs and when I am running the scripts with selecting multiple images the script works fine and tags all the images.

I would though like to be able to select multiple datasets and be able to tag all images in these given datasets, not the datasets themselves. I don't want to select all the images as they could be thousands and would therefore make my automatic tagging useless.

There is also one slight problem, in the given example above I tagged multiple images with the "Test_Tag" tag and when I look at my tags the "Test_Tag" tag is shown multiple times in my tags, is there an easy way to solve this problem?

P.S. this is not the code as whole, if you are missing context I could show you all of the code.

Best regards,
Ívar

Re: Adding annotations to images

PostPosted: Wed May 30, 2012 1:35 pm
by wmoore
As far as I can see, if you pass in DataType of "Dataset", the images list you create should have all the images from all those Datasets. These should all get tagged. Is that not what's happening? Can you check what's in the images list when you pass in DataType "Dataset" and a couple of Dataset IDs, each Dataset containing a couple of images?

I can't see anywhere in that code that Datasets are getting tagged at all. Is that what you're seeing?

For the second question, you'd need to check whether a Tag of the given text already exists. If it does, you should use the existing Tag.

You can do this:
Code: Select all

>>> t = conn.getObjects("TagAnnotation", attributes={'textValue':'Test_Tag'})
>>> t = list(t)
>>> t
[<TagAnnotationWrapper id=151>]
>>> t[0]._obj


Then you can do:

Code: Select all
saveAndLinkAnnotation(updateService, parent, t[0]._obj, ns, description)

Re: Adding annotations to images

PostPosted: Wed May 30, 2012 2:03 pm
by ihs7
wmoore wrote:For the second question, you'd need to check whether a Tag of the given text already exists. If it does, you should use the existing Tag.

You can do this:
Code: Select all

>>> t = conn.getObjects("TagAnnotation", attributes={'textValue':'Test_Tag'})
>>> t = list(t)
>>> t
[<TagAnnotationWrapper id=151>]
>>> t[0]._obj


Then you can do:

Code: Select all
saveAndLinkAnnotation(updateService, parent, t[0]._obj, ns, description)


This is exactly what I had imagined and solves my second problem.

wmoore wrote:I can't see anywhere in that code that Datasets are getting tagged at all. Is that what you're seeing?


Code: Select all
for i in images:
        print " Editing image ID: %d Name: %s" % (i.id, i.name)
        # i.name returns full name of file with .jpg ending
       
        #print conn.getObject("Dataset", 102)._obj
        #print conn.getObject("Image", i.id)._obj
        ### EXPERIMENTAL TAGGING
        addTag(updateService, i._obj, "Test_Tag", "test/omero/tag/ns", description=None)
        editedImgIds.append(i.id)

    return editedImgIds


addTag is handling the tagging requests where i._obj is the current image which is being iterated. This works when I pass DataType of "Image".

When I pass DataType of "Dataset", none of the images being iterated are tagged.

There is no difference between the two methods and they are returning the same objects.

When I pass the DataType of "Image" I get:
Code: Select all
{'Project_ID': 'SH065', 'IDs': [1809L, 2047L, 1819L, 1993L], 'Data_Type': 'Image'}
Processing Images identified by ID
[<_ImageWrapper id=1993>, <_ImageWrapper id=1819>, <_ImageWrapper id=1809>, <_ImageWrapper id=2047>]
Editing image ID: 1993 Name: ch01_10x_EMP_fim0_10x_1-1-1_006.jpg
Editing image ID: 1819 Name: ch01_10x_EMP_fim0_10x_1-1-1_005.jpg
Editing image ID: 1809 Name: ch01_10x_EMP_fim0_10x_1-1-1_003.jpg
Editing image ID: 2047 Name: ch01_10x_EMP_fim0_10x_1-1-1_004.jpg


And the images get tagged.

When I pass the DataType of "Dataset" I get
Code: Select all
{'Project_ID': 'SH065', 'IDs': [102L], 'Data_Type': 'Dataset'}
Processing Images from Dataset: ch01
[<_ImageWrapper id=1993>, <_ImageWrapper id=1819>, <_ImageWrapper id=1809>, <_ImageWrapper id=2047>]
Editing image ID: 1809 Name: ch01_10x_EMP_fim0_10x_1-1-1_003.jpg
Editing image ID: 2047 Name: ch01_10x_EMP_fim0_10x_1-1-1_004.jpg
Editing image ID: 1819 Name: ch01_10x_EMP_fim0_10x_1-1-1_005.jpg
Editing image ID: 1993 Name: ch01_10x_EMP_fim0_10x_1-1-1_006.jpg


And the images won't get tagged.

The code as whole can be seen here: https://github.com/ihs7/Automated

Re: Adding annotations to images

PostPosted: Wed May 30, 2012 2:38 pm
by wmoore
I just downloaded and tried your script, passing it a single Dataset with 4 images. After running the script, I see all images are tagged, and I have 4 new tags

Code: Select all
$ psql omero
omero=# select discriminator, id, ns, textvalue from annotation order by id desc;
    discriminator     | id  |                      ns                       |                                  textvalue                                 
----------------------+-----+-----------------------------------------------+-----------------------------------------------------------------------------
/basic/text/tag/     | 269 | test/omero/tag/ns                             | Test_Tag
/basic/text/tag/     | 268 | test/omero/tag/ns                             | Test_Tag
/basic/text/tag/     | 267 | test/omero/tag/ns                             | Test_Tag
/basic/text/tag/     | 266 | test/omero/tag/ns                             | Test_Tag

Re: Adding annotations to images

PostPosted: Wed May 30, 2012 5:25 pm
by ihs7
Hmm.. interesting. The tags are being created but not linked to the images.

At least that is what OMERO.insight is showing me. I can view the tags but they are not linked to anything.

They are only being linked to image when DataType is "Image", but created and not linked when DataType is "Dataset".

Do you have any idea how I could sort that problem out?

Re: Adding annotations to images

PostPosted: Fri Jun 01, 2012 1:26 pm
by wmoore
A few things you can try:

- When you use DataType: "Image", use the same images that are in the Dataset, to be sure that you are attempting to Tag the same images in both cases - Then it shouldn't be a permissions or viewing the Tags in clients problem

- Print out the tag links as they're being created. E.g. in you addTag() do this:
Code: Select all
    link = saveAndLinkAnnotation(updateService, parent, child, ns, description)
    print link

This should print a load of data, including the image and tag associated with the link.

- Query the images for Tags just before and after you tag them in the script

Code: Select all
        for ann in i.listAnnotations():
            print "Anns on image %s BEFORE: %s" % (i.id, str(ann))

      # EXPERIMENTAL TAGGING
        addTag(updateService, i._obj, "Test_Tag", "test/omero/tag/ns", description=None)
       
        reloadImg = conn.getObject("Image", i.id)    # since image-tag links will be cached from above
        for ann in reloadImg.listAnnotations():
            print "Anns on image %s AFTER: %s" % (i.id, str(ann))


For me, running the script twice in succession, this printed out:

- First, using Dataset:
Code: Select all
{'IDs': [61L], 'Data_Type': 'Dataset'}
Processing Images from Dataset: dds
Editing image ID: 368 Name: IN-siRNAi02_R3D_D3D.dv_offsets
Anns on image 368 AFTER: <TagAnnotationWrapper id=282>
Editing image ID: 372 Name: IN-siRNAi02_R3D_D3D.dv_offsets
Anns on image 372 AFTER: <TagAnnotationWrapper id=283>


Again, with the same Images:
Code: Select all
{'IDs': [372L, 368L], 'Data_Type': 'Image'}
Processing Images identified by ID
Editing image ID: 372 Name: IN-siRNAi02_R3D_D3D.dv_offsets
Anns on image 372 BEFORE: <TagAnnotationWrapper id=283>
Anns on image 372 AFTER: <TagAnnotationWrapper id=283>
Anns on image 372 AFTER: <TagAnnotationWrapper id=284>
Editing image ID: 368 Name: IN-siRNAi02_R3D_D3D.dv_offsets
Anns on image 368 BEFORE: <TagAnnotationWrapper id=282>
Anns on image 368 AFTER: <TagAnnotationWrapper id=282>
Anns on image 368 AFTER: <TagAnnotationWrapper id=285>


- Are you seeing any stderr?

- Also, you could check your server logs dist/var/log/Blitz.0.log to see if there's any errors etc.

Re: Adding annotations to images

PostPosted: Fri Jun 01, 2012 3:50 pm
by ihs7
The problem has been sorted out.

images contained a list of _ImageWrapper objects
Code: Select all
images = [<_ImageWrapper id=2611>, <_ImageWrapper id=2590>, <_ImageWrapper id=2563>]


while editedImgIds contained a list of ImageI ids which I could use successfully for adding annotations
Code: Select all
editedImgIds = [2611L, 2590L, 2563L]


I have also added a function for looking for existing tags instead of creating duplicates which works perfectly.

I have updated the git for the project which includes fully working copy of the automatic import tagging based on logs made by our microscope, something I have envisaged to be an integrated function of the importer later on along with image analysis.

Thanks alot for the help wmoore!

Best regards,
Ívar

Re: Adding annotations to images

PostPosted: Wed Jun 06, 2012 4:03 pm
by ihs7
Another problem has occured. It seems like creating objects too fast might lead too constraint violations (my guess).

Here is the error output when I run my script on large amount of data (5 datasets containing 266 images each)

Code: Select all
Traceback (most recent call last):
  File "./script", line 215, in <module>
    editedImgIds = autoMated(conn, scriptParams)
  File "./script", line 73, in autoMated
    addTag(updateService, img[3], tagDatalist[0]._obj, ns=None, description=None)
  File "./script", line 173, in addTag
    saveAndLinkAnnotation(updateService, parent, text, ns, description)
  File "./script", line 167, in saveAndLinkAnnotation
    return updateService.saveAndReturnObject(l)
  File "/usr/local/bin/OMERO/OMERO.server/lib/python/omero_api_IUpdate_ice.py", line 97, in saveAndReturnObject
    return _M_omero.api.IUpdate._op_saveAndReturnObject.invoke(self, ((obj, ), _ctx))
omero.ValidationException: exception ::omero::ValidationException
{
    serverStackTrace = ome.conditions.ValidationException: could not insert: [ome.model.annotations.ImageAnnotationLink]; SQL [insert into imageannotationlink (child, creation_id, external_id, group_id, owner_id, permissions, update_id, parent, version, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)]; constraint [imageannotationlink_parent_key]; nested exception is org.hibernate.exception.ConstraintViolationException: could not insert: [ome.model.annotations.ImageAnnotationLink]
   at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:637)
   at org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:412)
   at org.springframework.orm.hibernate3.HibernateInterceptor.invoke(HibernateInterceptor.java:117)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
   at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:108)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
   at ome.tools.hibernate.ProxyCleanupFilter$Interceptor.invoke(ProxyCleanupFilter.java:231)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
   at ome.services.util.ServiceHandler.invoke(ServiceHandler.java:116)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
   at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
   at $Proxy85.saveAndReturnObject(Unknown Source)
   at sun.reflect.GeneratedMethodAccessor1223.invoke(Unknown Source)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
   at java.lang.reflect.Method.invoke(Method.java:616)
   at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
   at ome.security.basic.BasicSecurityWiring.invoke(BasicSecurityWiring.java:83)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
   at ome.services.blitz.fire.AopContextInitializer.invoke(AopContextInitializer.java:43)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
   at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
   at $Proxy85.saveAndReturnObject(Unknown Source)
   at sun.reflect.GeneratedMethodAccessor1246.invoke(Unknown Source)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
   at java.lang.reflect.Method.invoke(Method.java:616)
   at ome.services.blitz.util.IceMethodInvoker.invoke(IceMethodInvoker.java:179)
   at ome.services.throttling.Callback.run(Callback.java:56)
   at ome.services.throttling.InThreadThrottlingStrategy.callInvokerOnRawArgs(InThreadThrottlingStrategy.java:56)
   at ome.services.blitz.impl.AbstractAmdServant.callInvokerOnRawArgs(AbstractAmdServant.java:136)
   at ome.services.blitz.impl.UpdateI.saveAndReturnObject_async(UpdateI.java:64)
   at omero.api._IUpdateTie.saveAndReturnObject_async(_IUpdateTie.java:92)
   at omero.api._IUpdateDisp.___saveAndReturnObject(_IUpdateDisp.java:185)
   at omero.api._IUpdateDisp.__dispatch(_IUpdateDisp.java:365)
   at IceInternal.Incoming.invoke(Incoming.java:159)
   at Ice.ConnectionI.invokeAll(ConnectionI.java:2037)
   at Ice.ConnectionI.message(ConnectionI.java:972)
   at IceInternal.ThreadPool.run(ThreadPool.java:577)
   at IceInternal.ThreadPool.access$100(ThreadPool.java:12)
   at IceInternal.ThreadPool$EventHandlerThread.run(ThreadPool.java:971)

    serverExceptionClass = ome.conditions.ValidationException
    message = could not insert: [ome.model.annotations.ImageAnnotationLink]; SQL [insert into imageannotationlink (child, creation_id, external_id, group_id, owner_id, permissions, update_id, parent, version, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)]; constraint [imageannotationlink_parent_key]; nested exception is org.hibernate.exception.ConstraintViolationException: could not insert: [ome.model.annotations.ImageAnnotationLink]
}


Is this something that could be solved?

Newest version of my script has been uploaded github.

Re: Adding annotations to images

PostPosted: Wed Jun 06, 2012 4:15 pm
by cxallan
The only thing I can think of is that your collections are getting out of sync. Can you try using an unloaded child as well as your unloaded parent when you are saving your links in saveAndLinkAnnotation(...)?

Re: Adding annotations to images

PostPosted: Wed Jun 06, 2012 8:45 pm
by wmoore
This looks like you're simply trying to attach a Tag to an Image that already has that Tag linked. You can't add the same Tag to an Image more than once.

You can either just ignore the error by using try / except.

Code: Select all
try:
    # add tag
except omero.ValidationException
    pass


OR, you can check whether a Tag is already linked to a particular image

Code: Select all
links = conn.getAnnotationLinks ("Image", parent_ids=[imgId], ann_ids=[tagId])
if len ( list(links) ) == 0:
    # add link


-Ooops, just saw Chris' post. You've already got an unloaded parent, so you just need:

Code: Select all
unloadedAnn = annotation.__class__(annotation.id.val, False)
l.setChild(unloadedAnn)