From 57ce1d917de4d28756d25c9830b00aa3e13ecd8c Mon Sep 17 00:00:00 2001 From: Isabel Zhong Date: Fri, 25 Oct 2024 13:11:05 -0700 Subject: [PATCH 01/10] optional slice param --- nucleus/dataset.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/nucleus/dataset.py b/nucleus/dataset.py index 6471a771..88b721a5 100644 --- a/nucleus/dataset.py +++ b/nucleus/dataset.py @@ -1449,10 +1449,13 @@ def items_and_annotations( ) return convert_export_payload(api_payload[EXPORTED_ROWS]) - def scene_and_annotation_generator(self, page_size: int = 10): + def scene_and_annotation_generator( + self, sliceId=None, page_size: int = 10 + ): """Provides a generator of all Scenes and Annotations in the dataset grouped by scene. Args: + sliceId: Optional slice ID to filter the scenes and annotations. page_size: Number of scenes to fetch per page. Default is 10. Returns: @@ -1505,6 +1508,7 @@ def scene_and_annotation_generator(self, page_size: int = 10): endpoint=f"dataset/{self.id}/{endpoint_name}", result_key=EXPORT_FOR_TRAINING_KEY, page_size=page_size, + sliceId=sliceId, ) for data in json_generator: From a0ef8463ab1b9e53a67b2093a77f80d39febfdcd Mon Sep 17 00:00:00 2001 From: Isabel Zhong Date: Mon, 24 Feb 2025 10:18:01 -0800 Subject: [PATCH 02/10] fix jean comments --- CHANGELOG.md | 2 +- nucleus/annotation.py | 46 +++++++++++++++++++--------------------- nucleus/constants.py | 3 ++- tests/test_prediction.py | 31 +++++++++++++++++++++------ 4 files changed, 50 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc17cafd..3a0a1463 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to the [Nucleus Python Client](https://github.com/scaleapi/n The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [0.17.8](https://github.com/scaleapi/nucleus-python-client/releases/tag/v0.17.7) - 2024-11-05 +## [0.17.8](https://github.com/scaleapi/nucleus-python-client/releases/tag/v0.17.8) - 2025-01-02 ### Added - Adding `only_most_recent_tasks` parameter for `dataset.scene_and_annotation_generator()` and `dataset.items_and_annotation_generator()` to accommodate for multiple sets of ground truth caused by relabeled tasks. Also returns the task_id in the annotation results. diff --git a/nucleus/annotation.py b/nucleus/annotation.py index 0ae06829..4c4961c5 100644 --- a/nucleus/annotation.py +++ b/nucleus/annotation.py @@ -159,7 +159,7 @@ class BoxAnnotation(Annotation): # pylint: disable=R0902 metadata: Optional[Dict] = None embedding_vector: Optional[list] = None track_reference_id: Optional[str] = None - task_id: Optional[str] = None + __task_id: Optional[str] = field(default=None, repr=False) def __post_init__(self): self.metadata = self.metadata if self.metadata else {} @@ -180,7 +180,7 @@ def from_json(cls, payload: dict): metadata=payload.get(METADATA_KEY, {}), embedding_vector=payload.get(EMBEDDING_VECTOR_KEY, None), track_reference_id=payload.get(TRACK_REFERENCE_ID_KEY, None), - task_id=payload.get(TASK_ID_KEY, None), + __task_id=payload.get(TASK_ID_KEY, None), ) def to_payload(self) -> dict: @@ -198,7 +198,7 @@ def to_payload(self) -> dict: METADATA_KEY: self.metadata, EMBEDDING_VECTOR_KEY: self.embedding_vector, TRACK_REFERENCE_ID_KEY: self.track_reference_id, - TASK_ID_KEY: self.task_id, + TASK_ID_KEY: self.__task_id, } def __eq__(self, other): @@ -213,7 +213,7 @@ def __eq__(self, other): and sorted(self.metadata.items()) == sorted(other.metadata.items()) and self.embedding_vector == other.embedding_vector and self.track_reference_id == other.track_reference_id - and self.task_id == other.task_id + and self.__task_id == other.__task_id ) @@ -280,7 +280,7 @@ class LineAnnotation(Annotation): annotation_id: Optional[str] = None metadata: Optional[Dict] = None track_reference_id: Optional[str] = None - task_id: Optional[str] = None + __task_id: Optional[str] = field(default=None, repr=False) def __post_init__(self): self.metadata = self.metadata if self.metadata else {} @@ -310,7 +310,7 @@ def from_json(cls, payload: dict): annotation_id=payload.get(ANNOTATION_ID_KEY, None), metadata=payload.get(METADATA_KEY, {}), track_reference_id=payload.get(TRACK_REFERENCE_ID_KEY, None), - task_id=payload.get(TASK_ID_KEY, None), + __task_id=payload.get(TASK_ID_KEY, None), ) def to_payload(self) -> dict: @@ -324,7 +324,7 @@ def to_payload(self) -> dict: ANNOTATION_ID_KEY: self.annotation_id, METADATA_KEY: self.metadata, TRACK_REFERENCE_ID_KEY: self.track_reference_id, - TASK_ID_KEY: self.task_id, + TASK_ID_KEY: self.__task.id, } return payload @@ -375,7 +375,7 @@ class PolygonAnnotation(Annotation): metadata: Optional[Dict] = None embedding_vector: Optional[list] = None track_reference_id: Optional[str] = None - task_id: Optional[str] = None + __task_id: Optional[str] = field(default=None, repr=False) def __post_init__(self): self.metadata = self.metadata if self.metadata else {} @@ -406,7 +406,7 @@ def from_json(cls, payload: dict): metadata=payload.get(METADATA_KEY, {}), embedding_vector=payload.get(EMBEDDING_VECTOR_KEY, None), track_reference_id=payload.get(TRACK_REFERENCE_ID_KEY, None), - task_id=payload.get(TASK_ID_KEY, None), + __task_id=payload.get(TASK_ID_KEY, None), ) def to_payload(self) -> dict: @@ -421,7 +421,7 @@ def to_payload(self) -> dict: METADATA_KEY: self.metadata, EMBEDDING_VECTOR_KEY: self.embedding_vector, TRACK_REFERENCE_ID_KEY: self.track_reference_id, - TASK_ID_KEY: self.task_id, + TASK_ID_KEY: self.__task.id, } return payload @@ -518,7 +518,7 @@ class KeypointsAnnotation(Annotation): annotation_id: Optional[str] = None metadata: Optional[Dict] = None track_reference_id: Optional[str] = None - task_id: Optional[str] = None + __task_id: Optional[str] = field(default=None, repr=False) def __post_init__(self): self.metadata = self.metadata or {} @@ -571,7 +571,7 @@ def from_json(cls, payload: dict): annotation_id=payload.get(ANNOTATION_ID_KEY, None), metadata=payload.get(METADATA_KEY, {}), track_reference_id=payload.get(TRACK_REFERENCE_ID_KEY, None), - task_id=payload.get(TASK_ID_KEY, None), + __task_id=payload.get(TASK_ID_KEY, None), ) def to_payload(self) -> dict: @@ -587,7 +587,7 @@ def to_payload(self) -> dict: ANNOTATION_ID_KEY: self.annotation_id, METADATA_KEY: self.metadata, TRACK_REFERENCE_ID_KEY: self.track_reference_id, - TASK_ID_KEY: self.task_id, + TASK_ID_KEY: self.__task.id, } return payload @@ -692,7 +692,7 @@ class CuboidAnnotation(Annotation): # pylint: disable=R0902 annotation_id: Optional[str] = None metadata: Optional[Dict] = None track_reference_id: Optional[str] = None - task_id: Optional[str] = None + __task_id: Optional[str] = field(default=None, repr=False) def __post_init__(self): self.metadata = self.metadata if self.metadata else {} @@ -709,7 +709,7 @@ def from_json(cls, payload: dict): annotation_id=payload.get(ANNOTATION_ID_KEY, None), metadata=payload.get(METADATA_KEY, {}), track_reference_id=payload.get(TRACK_REFERENCE_ID_KEY, None), - task_id=payload.get(TASK_ID_KEY, None), + __task_id=payload.get(TASK_ID_KEY, None), ) def to_payload(self) -> dict: @@ -942,7 +942,7 @@ class CategoryAnnotation(Annotation): taxonomy_name: Optional[str] = None metadata: Optional[Dict] = None track_reference_id: Optional[str] = None - task_id: Optional[str] = None + __task_id: Optional[str] = field(default=None, repr=False) def __post_init__(self): self.metadata = self.metadata if self.metadata else {} @@ -955,7 +955,7 @@ def from_json(cls, payload: dict): taxonomy_name=payload.get(TAXONOMY_NAME_KEY, None), metadata=payload.get(METADATA_KEY, {}), track_reference_id=payload.get(TRACK_REFERENCE_ID_KEY, None), - task_id=payload.get(TASK_ID_KEY, None), + __task_id=payload.get(TASK_ID_KEY, None), ) def to_payload(self) -> dict: @@ -966,7 +966,7 @@ def to_payload(self) -> dict: REFERENCE_ID_KEY: self.reference_id, METADATA_KEY: self.metadata, TRACK_REFERENCE_ID_KEY: self.track_reference_id, - TASK_ID_KEY: self.task_id, + TASK_ID_KEY: self.__task.id, } if self.taxonomy_name is not None: payload[TAXONOMY_NAME_KEY] = self.taxonomy_name @@ -982,7 +982,7 @@ class MultiCategoryAnnotation(Annotation): taxonomy_name: Optional[str] = None metadata: Optional[Dict] = None track_reference_id: Optional[str] = None - task_id: Optional[str] = None + __task_id: Optional[str] = field(default=None, repr=False) def __post_init__(self): self.metadata = self.metadata if self.metadata else {} @@ -995,7 +995,7 @@ def from_json(cls, payload: dict): taxonomy_name=payload.get(TAXONOMY_NAME_KEY, None), metadata=payload.get(METADATA_KEY, {}), track_reference_id=payload.get(TRACK_REFERENCE_ID_KEY, None), - task_id=payload.get(TASK_ID_KEY, None), + __task_id=payload.get(TASK_ID_KEY, None), ) def to_payload(self) -> dict: @@ -1006,7 +1006,7 @@ def to_payload(self) -> dict: REFERENCE_ID_KEY: self.reference_id, METADATA_KEY: self.metadata, TRACK_REFERENCE_ID_KEY: self.track_reference_id, - TASK_ID_KEY: self.task_id, + TASK_ID_KEY: self.__task.id, } if self.taxonomy_name is not None: payload[TAXONOMY_NAME_KEY] = self.taxonomy_name @@ -1079,9 +1079,7 @@ class AnnotationList: default_factory=list ) cuboid_annotations: List[CuboidAnnotation] = field(default_factory=list) - category_annotations: List[CategoryAnnotation] = field( - default_factory=list - ) + category_annotations: List[CategoryAnnotation] = field(default_factory=list) multi_category_annotations: List[MultiCategoryAnnotation] = field( default_factory=list ) diff --git a/nucleus/constants.py b/nucleus/constants.py index 0a2bbf46..190bf0e2 100644 --- a/nucleus/constants.py +++ b/nucleus/constants.py @@ -114,7 +114,8 @@ MODEL_PREDICTION_LABEL_KEY = "model_prediction_label" NAME_KEY = "name" NEW_ITEMS = "new_items" -NUCLEUS_ENDPOINT = "https://api.scale.com/v1/nucleus" +# NUCLEUS_ENDPOINT = "https://api.scale.com/v1/nucleus" +NUCLEUS_ENDPOINT = "http://localhost:3000/v1/nucleus" NUM_SENSORS_KEY = "num_sensors" ORIGINAL_IMAGE_URL_KEY = "original_image_url" PAGE_SIZE_KEY = "pageSize" diff --git a/tests/test_prediction.py b/tests/test_prediction.py index 5ed7ceb1..79d87670 100644 --- a/tests/test_prediction.py +++ b/tests/test_prediction.py @@ -53,6 +53,25 @@ def test_reprs(): def test_repr(test_object: any): assert eval(str(test_object)) == test_object + [test_repr(BoxPrediction.from_json(_)) for _ in TEST_BOX_PREDICTIONS] + + [test_repr(LinePrediction.from_json(_)) for _ in TEST_LINE_PREDICTIONS] + + [ + test_repr(PolygonPrediction.from_json(_)) + for _ in TEST_POLYGON_PREDICTIONS + ] + + [ + test_repr(CategoryPrediction.from_json(_)) + for _ in TEST_CATEGORY_PREDICTIONS + ] + + [ + test_repr(CategoryPrediction.from_json(_)) + for _ in TEST_DEFAULT_CATEGORY_PREDICTIONS + ] + [ test_repr(SegmentationPrediction.from_json(_)) for _ in TEST_SEGMENTATION_PREDICTIONS @@ -561,9 +580,9 @@ def test_default_category_pred_upload_update(model_run): # Copy so we don't modify the original. prediction_update_params = dict(TEST_DEFAULT_CATEGORY_PREDICTIONS[1]) - prediction_update_params[ - "reference_id" - ] = TEST_DEFAULT_CATEGORY_PREDICTIONS[0]["reference_id"] + prediction_update_params["reference_id"] = ( + TEST_DEFAULT_CATEGORY_PREDICTIONS[0]["reference_id"] + ) prediction_update = CategoryPrediction.from_json(prediction_update_params) response = model_run.predict(annotations=[prediction_update], update=True) @@ -588,9 +607,9 @@ def test_default_category_pred_upload_ignore(model_run): # Copy so we don't modify the original. prediction_update_params = dict(TEST_DEFAULT_CATEGORY_PREDICTIONS[1]) - prediction_update_params[ - "reference_id" - ] = TEST_DEFAULT_CATEGORY_PREDICTIONS[0]["reference_id"] + prediction_update_params["reference_id"] = ( + TEST_DEFAULT_CATEGORY_PREDICTIONS[0]["reference_id"] + ) prediction_update = CategoryPrediction.from_json(prediction_update_params) # Default behavior is ignore. From dea1283d355dc726448cccd91c061f890728eb7a Mon Sep 17 00:00:00 2001 From: Isabel Zhong Date: Mon, 24 Feb 2025 10:32:37 -0800 Subject: [PATCH 03/10] revert constants --- nucleus/constants.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/nucleus/constants.py b/nucleus/constants.py index 190bf0e2..0a2bbf46 100644 --- a/nucleus/constants.py +++ b/nucleus/constants.py @@ -114,8 +114,7 @@ MODEL_PREDICTION_LABEL_KEY = "model_prediction_label" NAME_KEY = "name" NEW_ITEMS = "new_items" -# NUCLEUS_ENDPOINT = "https://api.scale.com/v1/nucleus" -NUCLEUS_ENDPOINT = "http://localhost:3000/v1/nucleus" +NUCLEUS_ENDPOINT = "https://api.scale.com/v1/nucleus" NUM_SENSORS_KEY = "num_sensors" ORIGINAL_IMAGE_URL_KEY = "original_image_url" PAGE_SIZE_KEY = "pageSize" From 88622ed6b1790dc39ddeea1807c93d8914143d7d Mon Sep 17 00:00:00 2001 From: Isabel Zhong Date: Mon, 24 Feb 2025 10:43:03 -0800 Subject: [PATCH 04/10] fix pylint --- nucleus/annotation.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nucleus/annotation.py b/nucleus/annotation.py index 4c4961c5..7160bea7 100644 --- a/nucleus/annotation.py +++ b/nucleus/annotation.py @@ -213,7 +213,8 @@ def __eq__(self, other): and sorted(self.metadata.items()) == sorted(other.metadata.items()) and self.embedding_vector == other.embedding_vector and self.track_reference_id == other.track_reference_id - and self.__task_id == other.__task_id + and getattr(self, "_BoxAnnotation__task_id") + == getattr(other, "_BoxAnnotation__task_id") ) From 7ce3ffe9d7023aa83478bf0f9d0af5147f9befc3 Mon Sep 17 00:00:00 2001 From: Isabel Zhong Date: Mon, 24 Feb 2025 10:57:42 -0800 Subject: [PATCH 05/10] fix import issues --- nucleus/annotation.py | 86 +++++++++++++++++++++++++++++-------------- 1 file changed, 59 insertions(+), 27 deletions(-) diff --git a/nucleus/annotation.py b/nucleus/annotation.py index 7160bea7..4832a803 100644 --- a/nucleus/annotation.py +++ b/nucleus/annotation.py @@ -159,7 +159,7 @@ class BoxAnnotation(Annotation): # pylint: disable=R0902 metadata: Optional[Dict] = None embedding_vector: Optional[list] = None track_reference_id: Optional[str] = None - __task_id: Optional[str] = field(default=None, repr=False) + __task_id: Optional[str] = field(default=None, repr=False, init=False) def __post_init__(self): self.metadata = self.metadata if self.metadata else {} @@ -169,7 +169,7 @@ def __post_init__(self): @classmethod def from_json(cls, payload: dict): geometry = payload.get(GEOMETRY_KEY, {}) - return cls( + instance = cls( label=payload.get(LABEL_KEY, 0), x=geometry.get(X_KEY, 0), y=geometry.get(Y_KEY, 0), @@ -180,8 +180,11 @@ def from_json(cls, payload: dict): metadata=payload.get(METADATA_KEY, {}), embedding_vector=payload.get(EMBEDDING_VECTOR_KEY, None), track_reference_id=payload.get(TRACK_REFERENCE_ID_KEY, None), - __task_id=payload.get(TASK_ID_KEY, None), ) + setattr( + instance, "_BoxAnnotation__task_id", payload.get(TASK_ID_KEY, None) + ) + return instance def to_payload(self) -> dict: return { @@ -281,7 +284,7 @@ class LineAnnotation(Annotation): annotation_id: Optional[str] = None metadata: Optional[Dict] = None track_reference_id: Optional[str] = None - __task_id: Optional[str] = field(default=None, repr=False) + __task_id: Optional[str] = field(default=None, repr=False, init=False) def __post_init__(self): self.metadata = self.metadata if self.metadata else {} @@ -302,7 +305,7 @@ def __post_init__(self): @classmethod def from_json(cls, payload: dict): geometry = payload.get(GEOMETRY_KEY, {}) - return cls( + instance = cls( label=payload.get(LABEL_KEY, 0), vertices=[ Point.from_json(_) for _ in geometry.get(VERTICES_KEY, []) @@ -311,8 +314,11 @@ def from_json(cls, payload: dict): annotation_id=payload.get(ANNOTATION_ID_KEY, None), metadata=payload.get(METADATA_KEY, {}), track_reference_id=payload.get(TRACK_REFERENCE_ID_KEY, None), - __task_id=payload.get(TASK_ID_KEY, None), ) + setattr( + instance, "_LineAnnotation__task_id", payload.get(TASK_ID_KEY, None) + ) + return instance def to_payload(self) -> dict: payload = { @@ -325,7 +331,7 @@ def to_payload(self) -> dict: ANNOTATION_ID_KEY: self.annotation_id, METADATA_KEY: self.metadata, TRACK_REFERENCE_ID_KEY: self.track_reference_id, - TASK_ID_KEY: self.__task.id, + TASK_ID_KEY: self.__task_id, } return payload @@ -376,7 +382,7 @@ class PolygonAnnotation(Annotation): metadata: Optional[Dict] = None embedding_vector: Optional[list] = None track_reference_id: Optional[str] = None - __task_id: Optional[str] = field(default=None, repr=False) + __task_id: Optional[str] = field(default=None, repr=False, init=False) def __post_init__(self): self.metadata = self.metadata if self.metadata else {} @@ -397,7 +403,7 @@ def __post_init__(self): @classmethod def from_json(cls, payload: dict): geometry = payload.get(GEOMETRY_KEY, {}) - return cls( + instance = cls( label=payload.get(LABEL_KEY, 0), vertices=[ Point.from_json(_) for _ in geometry.get(VERTICES_KEY, []) @@ -407,8 +413,13 @@ def from_json(cls, payload: dict): metadata=payload.get(METADATA_KEY, {}), embedding_vector=payload.get(EMBEDDING_VECTOR_KEY, None), track_reference_id=payload.get(TRACK_REFERENCE_ID_KEY, None), - __task_id=payload.get(TASK_ID_KEY, None), ) + setattr( + instance, + "_PolygonAnnotation__task_id", + payload.get(TASK_ID_KEY, None), + ) + return instance def to_payload(self) -> dict: payload = { @@ -422,7 +433,7 @@ def to_payload(self) -> dict: METADATA_KEY: self.metadata, EMBEDDING_VECTOR_KEY: self.embedding_vector, TRACK_REFERENCE_ID_KEY: self.track_reference_id, - TASK_ID_KEY: self.__task.id, + TASK_ID_KEY: self.__task_id, } return payload @@ -519,7 +530,7 @@ class KeypointsAnnotation(Annotation): annotation_id: Optional[str] = None metadata: Optional[Dict] = None track_reference_id: Optional[str] = None - __task_id: Optional[str] = field(default=None, repr=False) + __task_id: Optional[str] = field(default=None, repr=False, init=False) def __post_init__(self): self.metadata = self.metadata or {} @@ -561,7 +572,7 @@ def from_json(cls, payload: dict): else None ) - return cls( + instance = cls( label=payload.get(LABEL_KEY, 0), keypoints=[ Keypoint.from_json(_) for _ in geometry.get(KEYPOINTS_KEY, []) @@ -572,8 +583,13 @@ def from_json(cls, payload: dict): annotation_id=payload.get(ANNOTATION_ID_KEY, None), metadata=payload.get(METADATA_KEY, {}), track_reference_id=payload.get(TRACK_REFERENCE_ID_KEY, None), - __task_id=payload.get(TASK_ID_KEY, None), ) + setattr( + instance, + "_KeypointsAnnotation__task_id", + payload.get(TASK_ID_KEY, None), + ) + return instance def to_payload(self) -> dict: payload = { @@ -588,7 +604,7 @@ def to_payload(self) -> dict: ANNOTATION_ID_KEY: self.annotation_id, METADATA_KEY: self.metadata, TRACK_REFERENCE_ID_KEY: self.track_reference_id, - TASK_ID_KEY: self.__task.id, + TASK_ID_KEY: self.__task_id, } return payload @@ -693,7 +709,7 @@ class CuboidAnnotation(Annotation): # pylint: disable=R0902 annotation_id: Optional[str] = None metadata: Optional[Dict] = None track_reference_id: Optional[str] = None - __task_id: Optional[str] = field(default=None, repr=False) + __task_id: Optional[str] = field(default=None, repr=False, init=False) def __post_init__(self): self.metadata = self.metadata if self.metadata else {} @@ -701,7 +717,7 @@ def __post_init__(self): @classmethod def from_json(cls, payload: dict): geometry = payload.get(GEOMETRY_KEY, {}) - return cls( + instance = cls( label=payload.get(LABEL_KEY, 0), position=Point3D.from_json(geometry.get(POSITION_KEY, {})), dimensions=Point3D.from_json(geometry.get(DIMENSIONS_KEY, {})), @@ -710,8 +726,13 @@ def from_json(cls, payload: dict): annotation_id=payload.get(ANNOTATION_ID_KEY, None), metadata=payload.get(METADATA_KEY, {}), track_reference_id=payload.get(TRACK_REFERENCE_ID_KEY, None), - __task_id=payload.get(TASK_ID_KEY, None), ) + setattr( + instance, + "_CuboidAnnotation__task_id", + payload.get(TASK_ID_KEY, None), + ) + return instance def to_payload(self) -> dict: payload = { @@ -730,7 +751,8 @@ def to_payload(self) -> dict: payload[METADATA_KEY] = self.metadata if self.track_reference_id: payload[TRACK_REFERENCE_ID_KEY] = self.track_reference_id - + if self.__task_id: + payload[TASK_ID_KEY] = self.__task_id return payload @@ -943,21 +965,26 @@ class CategoryAnnotation(Annotation): taxonomy_name: Optional[str] = None metadata: Optional[Dict] = None track_reference_id: Optional[str] = None - __task_id: Optional[str] = field(default=None, repr=False) + __task_id: Optional[str] = field(default=None, repr=False, init=False) def __post_init__(self): self.metadata = self.metadata if self.metadata else {} @classmethod def from_json(cls, payload: dict): - return cls( + instance = cls( label=payload[LABEL_KEY], reference_id=payload[REFERENCE_ID_KEY], taxonomy_name=payload.get(TAXONOMY_NAME_KEY, None), metadata=payload.get(METADATA_KEY, {}), track_reference_id=payload.get(TRACK_REFERENCE_ID_KEY, None), - __task_id=payload.get(TASK_ID_KEY, None), ) + setattr( + instance, + "_CategoryAnnotation__task_id", + payload.get(TASK_ID_KEY, None), + ) + return instance def to_payload(self) -> dict: payload = { @@ -967,7 +994,7 @@ def to_payload(self) -> dict: REFERENCE_ID_KEY: self.reference_id, METADATA_KEY: self.metadata, TRACK_REFERENCE_ID_KEY: self.track_reference_id, - TASK_ID_KEY: self.__task.id, + TASK_ID_KEY: self.__task_id, } if self.taxonomy_name is not None: payload[TAXONOMY_NAME_KEY] = self.taxonomy_name @@ -983,21 +1010,26 @@ class MultiCategoryAnnotation(Annotation): taxonomy_name: Optional[str] = None metadata: Optional[Dict] = None track_reference_id: Optional[str] = None - __task_id: Optional[str] = field(default=None, repr=False) + __task_id: Optional[str] = field(default=None, repr=False, init=False) def __post_init__(self): self.metadata = self.metadata if self.metadata else {} @classmethod def from_json(cls, payload: dict): - return cls( + instance = cls( labels=payload[LABELS_KEY], reference_id=payload[REFERENCE_ID_KEY], taxonomy_name=payload.get(TAXONOMY_NAME_KEY, None), metadata=payload.get(METADATA_KEY, {}), track_reference_id=payload.get(TRACK_REFERENCE_ID_KEY, None), - __task_id=payload.get(TASK_ID_KEY, None), ) + setattr( + instance, + "_MultiCategoryAnnotation__task_id", + payload.get(TASK_ID_KEY, None), + ) + return instance def to_payload(self) -> dict: payload = { @@ -1007,7 +1039,7 @@ def to_payload(self) -> dict: REFERENCE_ID_KEY: self.reference_id, METADATA_KEY: self.metadata, TRACK_REFERENCE_ID_KEY: self.track_reference_id, - TASK_ID_KEY: self.__task.id, + TASK_ID_KEY: self.__task_id, } if self.taxonomy_name is not None: payload[TAXONOMY_NAME_KEY] = self.taxonomy_name From 07ed72430cae50378dedda81299cee3c357c137c Mon Sep 17 00:00:00 2001 From: Isabel Zhong Date: Tue, 25 Feb 2025 15:54:48 -0800 Subject: [PATCH 06/10] fixing dup check --- nucleus/annotation.py | 74 ++++++++++++---------------------- nucleus/annotation_uploader.py | 33 +++++++++++---- 2 files changed, 51 insertions(+), 56 deletions(-) diff --git a/nucleus/annotation.py b/nucleus/annotation.py index 4832a803..db8d48c9 100644 --- a/nucleus/annotation.py +++ b/nucleus/annotation.py @@ -159,7 +159,7 @@ class BoxAnnotation(Annotation): # pylint: disable=R0902 metadata: Optional[Dict] = None embedding_vector: Optional[list] = None track_reference_id: Optional[str] = None - __task_id: Optional[str] = field(default=None, repr=False, init=False) + _task_id: Optional[str] = field(default=None, repr=False) def __post_init__(self): self.metadata = self.metadata if self.metadata else {} @@ -180,9 +180,7 @@ def from_json(cls, payload: dict): metadata=payload.get(METADATA_KEY, {}), embedding_vector=payload.get(EMBEDDING_VECTOR_KEY, None), track_reference_id=payload.get(TRACK_REFERENCE_ID_KEY, None), - ) - setattr( - instance, "_BoxAnnotation__task_id", payload.get(TASK_ID_KEY, None) + _task_id=payload.get(TASK_ID_KEY, None), ) return instance @@ -201,7 +199,7 @@ def to_payload(self) -> dict: METADATA_KEY: self.metadata, EMBEDDING_VECTOR_KEY: self.embedding_vector, TRACK_REFERENCE_ID_KEY: self.track_reference_id, - TASK_ID_KEY: self.__task_id, + TASK_ID_KEY: self._task_id, } def __eq__(self, other): @@ -216,8 +214,7 @@ def __eq__(self, other): and sorted(self.metadata.items()) == sorted(other.metadata.items()) and self.embedding_vector == other.embedding_vector and self.track_reference_id == other.track_reference_id - and getattr(self, "_BoxAnnotation__task_id") - == getattr(other, "_BoxAnnotation__task_id") + and self._task_id == other._task_id ) @@ -284,7 +281,7 @@ class LineAnnotation(Annotation): annotation_id: Optional[str] = None metadata: Optional[Dict] = None track_reference_id: Optional[str] = None - __task_id: Optional[str] = field(default=None, repr=False, init=False) + _task_id: Optional[str] = field(default=None, repr=False) def __post_init__(self): self.metadata = self.metadata if self.metadata else {} @@ -314,9 +311,7 @@ def from_json(cls, payload: dict): annotation_id=payload.get(ANNOTATION_ID_KEY, None), metadata=payload.get(METADATA_KEY, {}), track_reference_id=payload.get(TRACK_REFERENCE_ID_KEY, None), - ) - setattr( - instance, "_LineAnnotation__task_id", payload.get(TASK_ID_KEY, None) + _task_id=payload.get(TASK_ID_KEY, None), ) return instance @@ -331,7 +326,7 @@ def to_payload(self) -> dict: ANNOTATION_ID_KEY: self.annotation_id, METADATA_KEY: self.metadata, TRACK_REFERENCE_ID_KEY: self.track_reference_id, - TASK_ID_KEY: self.__task_id, + TASK_ID_KEY: self._task_id, } return payload @@ -382,7 +377,7 @@ class PolygonAnnotation(Annotation): metadata: Optional[Dict] = None embedding_vector: Optional[list] = None track_reference_id: Optional[str] = None - __task_id: Optional[str] = field(default=None, repr=False, init=False) + _task_id: Optional[str] = field(default=None, repr=False) def __post_init__(self): self.metadata = self.metadata if self.metadata else {} @@ -413,11 +408,7 @@ def from_json(cls, payload: dict): metadata=payload.get(METADATA_KEY, {}), embedding_vector=payload.get(EMBEDDING_VECTOR_KEY, None), track_reference_id=payload.get(TRACK_REFERENCE_ID_KEY, None), - ) - setattr( - instance, - "_PolygonAnnotation__task_id", - payload.get(TASK_ID_KEY, None), + _task_id=payload.get(TASK_ID_KEY, None), ) return instance @@ -433,7 +424,7 @@ def to_payload(self) -> dict: METADATA_KEY: self.metadata, EMBEDDING_VECTOR_KEY: self.embedding_vector, TRACK_REFERENCE_ID_KEY: self.track_reference_id, - TASK_ID_KEY: self.__task_id, + TASK_ID_KEY: self._task_id, } return payload @@ -530,7 +521,7 @@ class KeypointsAnnotation(Annotation): annotation_id: Optional[str] = None metadata: Optional[Dict] = None track_reference_id: Optional[str] = None - __task_id: Optional[str] = field(default=None, repr=False, init=False) + _task_id: Optional[str] = field(default=None, repr=False) def __post_init__(self): self.metadata = self.metadata or {} @@ -583,11 +574,7 @@ def from_json(cls, payload: dict): annotation_id=payload.get(ANNOTATION_ID_KEY, None), metadata=payload.get(METADATA_KEY, {}), track_reference_id=payload.get(TRACK_REFERENCE_ID_KEY, None), - ) - setattr( - instance, - "_KeypointsAnnotation__task_id", - payload.get(TASK_ID_KEY, None), + _task_id=payload.get(TASK_ID_KEY, None), ) return instance @@ -604,7 +591,7 @@ def to_payload(self) -> dict: ANNOTATION_ID_KEY: self.annotation_id, METADATA_KEY: self.metadata, TRACK_REFERENCE_ID_KEY: self.track_reference_id, - TASK_ID_KEY: self.__task_id, + TASK_ID_KEY: self._task_id, } return payload @@ -709,7 +696,7 @@ class CuboidAnnotation(Annotation): # pylint: disable=R0902 annotation_id: Optional[str] = None metadata: Optional[Dict] = None track_reference_id: Optional[str] = None - __task_id: Optional[str] = field(default=None, repr=False, init=False) + _task_id: Optional[str] = field(default=None, repr=False) def __post_init__(self): self.metadata = self.metadata if self.metadata else {} @@ -726,11 +713,7 @@ def from_json(cls, payload: dict): annotation_id=payload.get(ANNOTATION_ID_KEY, None), metadata=payload.get(METADATA_KEY, {}), track_reference_id=payload.get(TRACK_REFERENCE_ID_KEY, None), - ) - setattr( - instance, - "_CuboidAnnotation__task_id", - payload.get(TASK_ID_KEY, None), + _task_id=payload.get(TASK_ID_KEY, None), ) return instance @@ -751,8 +734,8 @@ def to_payload(self) -> dict: payload[METADATA_KEY] = self.metadata if self.track_reference_id: payload[TRACK_REFERENCE_ID_KEY] = self.track_reference_id - if self.__task_id: - payload[TASK_ID_KEY] = self.__task_id + if self._task_id: + payload[TASK_ID_KEY] = self._task_id return payload @@ -965,7 +948,7 @@ class CategoryAnnotation(Annotation): taxonomy_name: Optional[str] = None metadata: Optional[Dict] = None track_reference_id: Optional[str] = None - __task_id: Optional[str] = field(default=None, repr=False, init=False) + _task_id: Optional[str] = field(default=None, repr=False) def __post_init__(self): self.metadata = self.metadata if self.metadata else {} @@ -978,11 +961,7 @@ def from_json(cls, payload: dict): taxonomy_name=payload.get(TAXONOMY_NAME_KEY, None), metadata=payload.get(METADATA_KEY, {}), track_reference_id=payload.get(TRACK_REFERENCE_ID_KEY, None), - ) - setattr( - instance, - "_CategoryAnnotation__task_id", - payload.get(TASK_ID_KEY, None), + _task_id=payload.get(TASK_ID_KEY, None), ) return instance @@ -994,7 +973,7 @@ def to_payload(self) -> dict: REFERENCE_ID_KEY: self.reference_id, METADATA_KEY: self.metadata, TRACK_REFERENCE_ID_KEY: self.track_reference_id, - TASK_ID_KEY: self.__task_id, + TASK_ID_KEY: self._task_id, } if self.taxonomy_name is not None: payload[TAXONOMY_NAME_KEY] = self.taxonomy_name @@ -1010,7 +989,7 @@ class MultiCategoryAnnotation(Annotation): taxonomy_name: Optional[str] = None metadata: Optional[Dict] = None track_reference_id: Optional[str] = None - __task_id: Optional[str] = field(default=None, repr=False, init=False) + _task_id: Optional[str] = field(default=None, repr=False) def __post_init__(self): self.metadata = self.metadata if self.metadata else {} @@ -1023,11 +1002,7 @@ def from_json(cls, payload: dict): taxonomy_name=payload.get(TAXONOMY_NAME_KEY, None), metadata=payload.get(METADATA_KEY, {}), track_reference_id=payload.get(TRACK_REFERENCE_ID_KEY, None), - ) - setattr( - instance, - "_MultiCategoryAnnotation__task_id", - payload.get(TASK_ID_KEY, None), + _task_id=payload.get(TASK_ID_KEY, None), ) return instance @@ -1039,7 +1014,7 @@ def to_payload(self) -> dict: REFERENCE_ID_KEY: self.reference_id, METADATA_KEY: self.metadata, TRACK_REFERENCE_ID_KEY: self.track_reference_id, - TASK_ID_KEY: self.__task_id, + TASK_ID_KEY: self._task_id, } if self.taxonomy_name is not None: payload[TAXONOMY_NAME_KEY] = self.taxonomy_name @@ -1078,6 +1053,7 @@ class SceneCategoryAnnotation(Annotation): reference_id: str taxonomy_name: Optional[str] = None metadata: Optional[Dict] = field(default_factory=dict) + _task_id: Optional[str] = field(default=None, repr=False) @classmethod def from_json(cls, payload: dict): @@ -1086,6 +1062,7 @@ def from_json(cls, payload: dict): reference_id=payload[REFERENCE_ID_KEY], taxonomy_name=payload.get(TAXONOMY_NAME_KEY, None), metadata=payload.get(METADATA_KEY, {}), + _task_id=payload.get(TASK_ID_KEY, None), ) def to_payload(self) -> dict: @@ -1095,6 +1072,7 @@ def to_payload(self) -> dict: GEOMETRY_KEY: {}, REFERENCE_ID_KEY: self.reference_id, METADATA_KEY: self.metadata, + TASK_ID_KEY: self._task_id, } if self.taxonomy_name is not None: payload[TAXONOMY_NAME_KEY] = self.taxonomy_name diff --git a/nucleus/annotation_uploader.py b/nucleus/annotation_uploader.py index 7fda1a4c..9e248cec 100644 --- a/nucleus/annotation_uploader.py +++ b/nucleus/annotation_uploader.py @@ -176,9 +176,7 @@ def get_form_data_and_file_pointers_fn( """ def fn(): - request_json = construct_segmentation_payload( - segmentations, update - ) + request_json = construct_segmentation_payload(segmentations, update) form_data = [ FileFormField( name=SERIALIZED_REQUEST_KEY, @@ -212,15 +210,17 @@ def fn(): return fn - @staticmethod - def check_for_duplicate_ids(annotations: Iterable[Annotation]): + def check_for_duplicate_ids(self, annotations: Iterable[Annotation]): """Do not allow annotations to have the same (annotation_id, reference_id, task_id) tuple""" - # some annotations like CategoryAnnotation do not have annotation_id attribute, and as such, we allow duplicates tuple_ids = [ - (ann.reference_id, ann.annotation_id, ann.task_id) # type: ignore + ( + ann.reference_id, + ann.annotation_id, + getattr(ann, "_task_id", None), + ) for ann in annotations - if hasattr(ann, "annotation_id") and hasattr(ann, "task_id") + if hasattr(ann, "annotation_id") ] tuple_count = Counter(tuple_ids) duplicates = {key for key, value in tuple_count.items() if value > 1} @@ -255,3 +255,20 @@ def __init__( self._route = ( f"dataset/{dataset_id}/model/{model_id}/uploadPredictions" ) + + def check_for_duplicate_ids(self, predictions: Iterable[Annotation]): + """Do not allow predictions to have the same (annotation_id, reference_id) tuple""" + tuple_ids = [ + (pred.annotation_id, pred.reference_id) # type: ignore + for pred in predictions + if hasattr(pred, "annotation_id") and hasattr(pred, "reference_id") + ] + tuple_count = Counter(tuple_ids) + duplicates = {key for key, value in tuple_count.items() if value > 1} + if len(duplicates) > 0: + raise DuplicateIDError( + f"Duplicate predictions with the same (annotation_id, reference_id) properties found.\n" + f"Duplicates: {duplicates}\n" + f"To fix this, avoid duplicate predictions, or specify a different annotation_id attribute " + f"for the failing items." + ) From 05ab0298af8db46ce90720d0bbf6ed818585714f Mon Sep 17 00:00:00 2001 From: Isabel Zhong Date: Tue, 25 Feb 2025 15:59:52 -0800 Subject: [PATCH 07/10] fix bug --- nucleus/annotation.py | 21 +++++++-------------- nucleus/annotation_uploader.py | 4 ++-- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/nucleus/annotation.py b/nucleus/annotation.py index db8d48c9..ad352dd1 100644 --- a/nucleus/annotation.py +++ b/nucleus/annotation.py @@ -169,7 +169,7 @@ def __post_init__(self): @classmethod def from_json(cls, payload: dict): geometry = payload.get(GEOMETRY_KEY, {}) - instance = cls( + return cls( label=payload.get(LABEL_KEY, 0), x=geometry.get(X_KEY, 0), y=geometry.get(Y_KEY, 0), @@ -182,7 +182,6 @@ def from_json(cls, payload: dict): track_reference_id=payload.get(TRACK_REFERENCE_ID_KEY, None), _task_id=payload.get(TASK_ID_KEY, None), ) - return instance def to_payload(self) -> dict: return { @@ -302,7 +301,7 @@ def __post_init__(self): @classmethod def from_json(cls, payload: dict): geometry = payload.get(GEOMETRY_KEY, {}) - instance = cls( + return cls( label=payload.get(LABEL_KEY, 0), vertices=[ Point.from_json(_) for _ in geometry.get(VERTICES_KEY, []) @@ -313,7 +312,6 @@ def from_json(cls, payload: dict): track_reference_id=payload.get(TRACK_REFERENCE_ID_KEY, None), _task_id=payload.get(TASK_ID_KEY, None), ) - return instance def to_payload(self) -> dict: payload = { @@ -398,7 +396,7 @@ def __post_init__(self): @classmethod def from_json(cls, payload: dict): geometry = payload.get(GEOMETRY_KEY, {}) - instance = cls( + return cls( label=payload.get(LABEL_KEY, 0), vertices=[ Point.from_json(_) for _ in geometry.get(VERTICES_KEY, []) @@ -410,7 +408,6 @@ def from_json(cls, payload: dict): track_reference_id=payload.get(TRACK_REFERENCE_ID_KEY, None), _task_id=payload.get(TASK_ID_KEY, None), ) - return instance def to_payload(self) -> dict: payload = { @@ -563,7 +560,7 @@ def from_json(cls, payload: dict): else None ) - instance = cls( + return cls( label=payload.get(LABEL_KEY, 0), keypoints=[ Keypoint.from_json(_) for _ in geometry.get(KEYPOINTS_KEY, []) @@ -576,7 +573,6 @@ def from_json(cls, payload: dict): track_reference_id=payload.get(TRACK_REFERENCE_ID_KEY, None), _task_id=payload.get(TASK_ID_KEY, None), ) - return instance def to_payload(self) -> dict: payload = { @@ -704,7 +700,7 @@ def __post_init__(self): @classmethod def from_json(cls, payload: dict): geometry = payload.get(GEOMETRY_KEY, {}) - instance = cls( + return cls( label=payload.get(LABEL_KEY, 0), position=Point3D.from_json(geometry.get(POSITION_KEY, {})), dimensions=Point3D.from_json(geometry.get(DIMENSIONS_KEY, {})), @@ -715,7 +711,6 @@ def from_json(cls, payload: dict): track_reference_id=payload.get(TRACK_REFERENCE_ID_KEY, None), _task_id=payload.get(TASK_ID_KEY, None), ) - return instance def to_payload(self) -> dict: payload = { @@ -955,7 +950,7 @@ def __post_init__(self): @classmethod def from_json(cls, payload: dict): - instance = cls( + return cls( label=payload[LABEL_KEY], reference_id=payload[REFERENCE_ID_KEY], taxonomy_name=payload.get(TAXONOMY_NAME_KEY, None), @@ -963,7 +958,6 @@ def from_json(cls, payload: dict): track_reference_id=payload.get(TRACK_REFERENCE_ID_KEY, None), _task_id=payload.get(TASK_ID_KEY, None), ) - return instance def to_payload(self) -> dict: payload = { @@ -996,7 +990,7 @@ def __post_init__(self): @classmethod def from_json(cls, payload: dict): - instance = cls( + return cls( labels=payload[LABELS_KEY], reference_id=payload[REFERENCE_ID_KEY], taxonomy_name=payload.get(TAXONOMY_NAME_KEY, None), @@ -1004,7 +998,6 @@ def from_json(cls, payload: dict): track_reference_id=payload.get(TRACK_REFERENCE_ID_KEY, None), _task_id=payload.get(TASK_ID_KEY, None), ) - return instance def to_payload(self) -> dict: payload = { diff --git a/nucleus/annotation_uploader.py b/nucleus/annotation_uploader.py index 9e248cec..2b95bbdf 100644 --- a/nucleus/annotation_uploader.py +++ b/nucleus/annotation_uploader.py @@ -256,11 +256,11 @@ def __init__( f"dataset/{dataset_id}/model/{model_id}/uploadPredictions" ) - def check_for_duplicate_ids(self, predictions: Iterable[Annotation]): + def check_for_duplicate_ids(self, annotations: Iterable[Annotation]): """Do not allow predictions to have the same (annotation_id, reference_id) tuple""" tuple_ids = [ (pred.annotation_id, pred.reference_id) # type: ignore - for pred in predictions + for pred in annotations if hasattr(pred, "annotation_id") and hasattr(pred, "reference_id") ] tuple_count = Counter(tuple_ids) From 6d4e2952615e62ca3d34668d5c86bf3f129ad68e Mon Sep 17 00:00:00 2001 From: Isabel Zhong Date: Tue, 25 Feb 2025 16:18:34 -0800 Subject: [PATCH 08/10] more bugs --- tests/test_annotation.py | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/tests/test_annotation.py b/tests/test_annotation.py index 54d2e6c5..42c7ae2e 100644 --- a/tests/test_annotation.py +++ b/tests/test_annotation.py @@ -193,9 +193,7 @@ def test_polygon_gt_upload(dataset): assert response["annotations_processed"] == 1 assert response["annotations_ignored"] == 0 - response = dataset.refloc(annotation.reference_id)["annotations"][ - "polygon" - ] + response = dataset.refloc(annotation.reference_id)["annotations"]["polygon"] assert len(response) == 1 response_annotation = response[0] assert_polygon_annotation_matches_dict( @@ -370,7 +368,7 @@ def test_mixed_annotation_upload(dataset): def test_box_gt_upload_update(dataset): - TEST_BOX_ANNOTATIONS[0]["task_id"] = "test_task_id" + TEST_BOX_ANNOTATIONS[0]["_task_id"] = "test_task_id" annotation = BoxAnnotation(**TEST_BOX_ANNOTATIONS[0]) response = dataset.annotate(annotations=[annotation]) @@ -384,7 +382,7 @@ def test_box_gt_upload_update(dataset): annotation_update_params["reference_id"] = TEST_BOX_ANNOTATIONS[0][ "reference_id" ] - annotation_update_params["task_id"] = TEST_BOX_ANNOTATIONS[0]["task_id"] + annotation_update_params["_task_id"] = TEST_BOX_ANNOTATIONS[0]["_task_id"] annotation_update = BoxAnnotation(**annotation_update_params) response = dataset.annotate(annotations=[annotation_update], update=True) @@ -401,7 +399,7 @@ def test_box_gt_upload_update(dataset): def test_box_gt_upload_ignore(dataset): - TEST_BOX_ANNOTATIONS[0]["task_id"] = "test_task_id" + TEST_BOX_ANNOTATIONS[0]["_task_id"] = "test_task_id" annotation = BoxAnnotation(**TEST_BOX_ANNOTATIONS[0]) print(annotation) @@ -418,7 +416,7 @@ def test_box_gt_upload_ignore(dataset): annotation_update_params["reference_id"] = TEST_BOX_ANNOTATIONS[0][ "reference_id" ] - annotation_update_params["task_id"] = TEST_BOX_ANNOTATIONS[0]["task_id"] + annotation_update_params["_task_id"] = TEST_BOX_ANNOTATIONS[0]["_task_id"] annotation_update = BoxAnnotation(**annotation_update_params) # Default behavior is ignore. @@ -450,7 +448,7 @@ def test_polygon_gt_upload_update(dataset): annotation_update_params["reference_id"] = TEST_POLYGON_ANNOTATIONS[0][ "reference_id" ] - annotation_update_params["task_id"] = TEST_POLYGON_ANNOTATIONS[0][ + annotation_update_params["_task_id"] = TEST_POLYGON_ANNOTATIONS[0][ "task_id" ] @@ -460,9 +458,7 @@ def test_polygon_gt_upload_update(dataset): assert response["annotations_processed"] == 1 assert response["annotations_ignored"] == 0 - response = dataset.refloc(annotation.reference_id)["annotations"][ - "polygon" - ] + response = dataset.refloc(annotation.reference_id)["annotations"]["polygon"] assert len(response) == 1 response_annotation = response[0] assert_polygon_annotation_matches_dict( @@ -485,7 +481,7 @@ def test_polygon_gt_upload_ignore(dataset): annotation_update_params["reference_id"] = TEST_POLYGON_ANNOTATIONS[0][ "reference_id" ] - annotation_update_params["task_id"] = TEST_POLYGON_ANNOTATIONS[0][ + annotation_update_params["_task_id"] = TEST_POLYGON_ANNOTATIONS[0][ "task_id" ] @@ -496,9 +492,7 @@ def test_polygon_gt_upload_ignore(dataset): assert response["annotations_processed"] == 0 assert response["annotations_ignored"] == 1 - response = dataset.refloc(annotation.reference_id)["annotations"][ - "polygon" - ] + response = dataset.refloc(annotation.reference_id)["annotations"]["polygon"] assert len(response) == 1 response_annotation = response[0] assert_polygon_annotation_matches_dict( From 758979ca99a219a6c835e50438c160f3b2b3eb24 Mon Sep 17 00:00:00 2001 From: Isabel Zhong Date: Tue, 25 Feb 2025 17:20:01 -0800 Subject: [PATCH 09/10] fix another bug --- tests/test_annotation.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_annotation.py b/tests/test_annotation.py index 42c7ae2e..c656cc74 100644 --- a/tests/test_annotation.py +++ b/tests/test_annotation.py @@ -434,7 +434,7 @@ def test_box_gt_upload_ignore(dataset): def test_polygon_gt_upload_update(dataset): - TEST_POLYGON_ANNOTATIONS[0]["task_id"] = "test_task_id" + TEST_POLYGON_ANNOTATIONS[0]["_task_id"] = "test_task_id" annotation = PolygonAnnotation.from_json(TEST_POLYGON_ANNOTATIONS[0]) response = dataset.annotate(annotations=[annotation]) @@ -449,7 +449,7 @@ def test_polygon_gt_upload_update(dataset): "reference_id" ] annotation_update_params["_task_id"] = TEST_POLYGON_ANNOTATIONS[0][ - "task_id" + "_task_id" ] annotation_update = PolygonAnnotation.from_json(annotation_update_params) @@ -467,7 +467,7 @@ def test_polygon_gt_upload_update(dataset): def test_polygon_gt_upload_ignore(dataset): - TEST_POLYGON_ANNOTATIONS[0]["task_id"] = "test_task_id" + TEST_POLYGON_ANNOTATIONS[0]["_task_id"] = "test_task_id" annotation = PolygonAnnotation.from_json(TEST_POLYGON_ANNOTATIONS[0]) response = dataset.annotate(annotations=[annotation]) @@ -482,7 +482,7 @@ def test_polygon_gt_upload_ignore(dataset): "reference_id" ] annotation_update_params["_task_id"] = TEST_POLYGON_ANNOTATIONS[0][ - "task_id" + "_task_id" ] annotation_update = PolygonAnnotation.from_json(annotation_update_params) From c18d30008e9e7c06395ad49cd04c0364ad3976f9 Mon Sep 17 00:00:00 2001 From: Isabel Zhong Date: Wed, 26 Feb 2025 09:26:00 -0800 Subject: [PATCH 10/10] another fix --- tests/test_annotation.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/tests/test_annotation.py b/tests/test_annotation.py index c656cc74..64c56afd 100644 --- a/tests/test_annotation.py +++ b/tests/test_annotation.py @@ -434,7 +434,7 @@ def test_box_gt_upload_ignore(dataset): def test_polygon_gt_upload_update(dataset): - TEST_POLYGON_ANNOTATIONS[0]["_task_id"] = "test_task_id" + TEST_POLYGON_ANNOTATIONS[0]["task_id"] = "test_task_id" annotation = PolygonAnnotation.from_json(TEST_POLYGON_ANNOTATIONS[0]) response = dataset.annotate(annotations=[annotation]) @@ -448,9 +448,7 @@ def test_polygon_gt_upload_update(dataset): annotation_update_params["reference_id"] = TEST_POLYGON_ANNOTATIONS[0][ "reference_id" ] - annotation_update_params["_task_id"] = TEST_POLYGON_ANNOTATIONS[0][ - "_task_id" - ] + annotation_update_params["task_id"] = TEST_POLYGON_ANNOTATIONS[0]["task_id"] annotation_update = PolygonAnnotation.from_json(annotation_update_params) response = dataset.annotate(annotations=[annotation_update], update=True) @@ -467,7 +465,7 @@ def test_polygon_gt_upload_update(dataset): def test_polygon_gt_upload_ignore(dataset): - TEST_POLYGON_ANNOTATIONS[0]["_task_id"] = "test_task_id" + TEST_POLYGON_ANNOTATIONS[0]["task_id"] = "test_task_id" annotation = PolygonAnnotation.from_json(TEST_POLYGON_ANNOTATIONS[0]) response = dataset.annotate(annotations=[annotation]) @@ -481,9 +479,7 @@ def test_polygon_gt_upload_ignore(dataset): annotation_update_params["reference_id"] = TEST_POLYGON_ANNOTATIONS[0][ "reference_id" ] - annotation_update_params["_task_id"] = TEST_POLYGON_ANNOTATIONS[0][ - "_task_id" - ] + annotation_update_params["task_id"] = TEST_POLYGON_ANNOTATIONS[0]["task_id"] annotation_update = PolygonAnnotation.from_json(annotation_update_params) # Default behavior is ignore.