Cytomine-python-client icon indicating copy to clipboard operation
Cytomine-python-client copied to clipboard

Make AnnotationCollection.save return its results

Open schwobr opened this issue 4 years ago • 1 comments

Hi !

I noticed trying to work with the python client while understanding what happens behind the scenes that an AnnotationCollection doesn't quite behave like a collection of Annotation objects. Specifically, while using Annotation.save() populates the object, most importantly its id, and returns itself, AnnotationCollection.save() does not change the underlying Annotation objects ids and returns a boolean. This is not very handy, as it is impossible to get information from uploaded annotations, for instance their ids that could be later used to upload AnnotationTerm objects.

There are some workarounds, the main one being overwriting some of the source code at runtime but it is not very handy. We could also catch stdout as the response is logged by cytomine. However, I feel like it should be the default behaviour of the API to somehow give us access to annotations ids, that is why I would suggest making one of these changes:

  • The easiest one: make Cytomine.post_collection return the output of self._post and have AnnotationCollection.save return the results instead of a boolean as well. It is however not the most user friendly behaviour.
  • Make Cytomine.post_collection return a list of uploaded ids. This could be more readable and allow for easily checking upload success using the length of the list.
  • Make AnnotationCollection.save populate the underlying annotations and make it return the collection. This would be the most user friendly as it would be consistent with the single element upload behaviour. However it seems that it would also require to change the REST API to make it return a similar response as Annotation.save. It would also potentially be quite slow as the response would be heavy, which I guess is why it does not work like this. We could also have only the ids be populated, which would be enough for most use cases and would not add any weight to the response.

Whatever suits you best, but I think it is important to change the collection API. For anything that does not imply changing the REST API I can help with a PR if you'd like.

schwobr avatar Jan 17 '22 10:01 schwobr

Or maybe you can just try something similar:

 for class_id, polygons in tqdm(results.items(), desc="uploading results"):
            term_id = terms[labels[class_id]] # from ontology
            for idx, polygon in enumerate(polygons):
                annotation = Annotation(location=polygon.wkt, id_image=cytom_image.id, id_project=TARGET_PROJECT_ID, term=[term_id])
                annotations.append(annotation)
                
annotations.save() 

Ceachi avatar Oct 10 '23 18:10 Ceachi