Make AnnotationCollection.save return its results
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_collectionreturn the output ofself._postand haveAnnotationCollection.savereturn the results instead of a boolean as well. It is however not the most user friendly behaviour. - Make
Cytomine.post_collectionreturn 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.savepopulate 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 asAnnotation.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.
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()