diff --git a/webknossos/webknossos/annotation/annotation.py b/webknossos/webknossos/annotation/annotation.py index c7f8f44cc..920540798 100644 --- a/webknossos/webknossos/annotation/annotation.py +++ b/webknossos/webknossos/annotation/annotation.py @@ -1520,6 +1520,7 @@ def _set_annotation_info( modified=annotation_info.modified, data_store=annotation_info.data_store, tracing_time=annotation_info.tracing_time, + annotation_layers=None, ), ) @@ -1528,6 +1529,36 @@ def save(self, path: str | PathLike) -> None: "Remote annotations cannot be saved. Changes are applied ." ) + def get_segments_for_agglomerate(self, agglomerate_id: int) -> list[int] | None: + """Get the segment ids for a given agglomerate id. + + Args: + agglomerate_id (int): The agglomerate id. + + Returns: + List[int] | None: The segment ids if the agglomerate was edited, None otherwise. + """ + from ..client.context import _get_context + + context = _get_context() + annotation_info = self._get_annotation_info() + assert annotation_info.annotation_layers is not None, "Annotation has no layers" + tracingstore_client = context.get_tracingstore_api_client() + volume_layer = [ + layer + for layer in annotation_info.annotation_layers + if layer.typ == "Volume" + ] + assert len(volume_layer) == 1, "Expected exactly one volume layer" + segment_list_result = tracingstore_client.get_segments_for_agglomerate( + volume_layer[0].tracing_id, agglomerate_id + ) + segment_list = segment_list_result.segmentIds + if segment_list_result.agglomerateIdIsPresent: + return segment_list + else: + return None + def download_mesh( self, segment_id: int, diff --git a/webknossos/webknossos/client/api_client/models.py b/webknossos/webknossos/client/api_client/models.py index 299056fc6..049b60a7d 100644 --- a/webknossos/webknossos/client/api_client/models.py +++ b/webknossos/webknossos/client/api_client/models.py @@ -357,6 +357,19 @@ class ApiProjectCreate: owner: str | None = None +@attr.s(auto_attribs=True) +class ApiAnnotationLayer: + tracing_id: str + typ: str + name: str + + +@attr.s(auto_attribs=True) +class ApiEditableMappingSegmentListResult: + segmentIds: list[int] + agglomerateIdIsPresent: bool + + @attr.s(auto_attribs=True) class ApiAnnotation: id: str @@ -366,6 +379,7 @@ class ApiAnnotation: description: str state: str modified: int + annotation_layers: list[ApiAnnotationLayer] | None data_store: ApiDataStore | None = None tracing_time: int | None = None # millis diff --git a/webknossos/webknossos/client/api_client/tracingstore_api_client.py b/webknossos/webknossos/client/api_client/tracingstore_api_client.py index 103d19e76..8b22be557 100644 --- a/webknossos/webknossos/client/api_client/tracingstore_api_client.py +++ b/webknossos/webknossos/client/api_client/tracingstore_api_client.py @@ -2,6 +2,7 @@ from webknossos.client.api_client.models import ( ApiAdHocMeshInfo, + ApiEditableMappingSegmentListResult, ApiPrecomputedMeshInfo, ) @@ -26,6 +27,16 @@ def __init__( def url_prefix(self) -> str: return f"{self.base_url}/tracings" + def get_segments_for_agglomerate( + self, tracing_id: str, agglomerate_id: int + ) -> ApiEditableMappingSegmentListResult: + route = f"/mapping/{tracing_id}/segmentsForAgglomerate" + query: Query = {"agglomerateId": agglomerate_id} + + return self._get_json( + route, query=query, response_type=ApiEditableMappingSegmentListResult + ) + def annotation_download_mesh( self, mesh: ApiPrecomputedMeshInfo | ApiAdHocMeshInfo,