From 57ce1d917de4d28756d25c9830b00aa3e13ecd8c Mon Sep 17 00:00:00 2001 From: Isabel Zhong Date: Fri, 25 Oct 2024 13:11:05 -0700 Subject: [PATCH 01/18] 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 421282f5490fbbfe1cbf18393d060de7ddd3b80e Mon Sep 17 00:00:00 2001 From: Isabel Zhong Date: Fri, 6 Dec 2024 18:00:18 -0800 Subject: [PATCH 02/18] remove unwanted file from pr --- nucleus/annotation.py | 22 ++++++++++++++++++++++ nucleus/constants.py | 1 + nucleus/dataset.py | 7 ++++++- 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/nucleus/annotation.py b/nucleus/annotation.py index 453ca07f..a9dd5b0c 100644 --- a/nucleus/annotation.py +++ b/nucleus/annotation.py @@ -34,6 +34,7 @@ POSITION_KEY, REFERENCE_ID_KEY, TAXONOMY_NAME_KEY, + TASK_ID_KEY, TRACK_REFERENCE_ID_KEY, TYPE_KEY, VERTICES_KEY, @@ -158,6 +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 def __post_init__(self): self.metadata = self.metadata if self.metadata else {} @@ -178,6 +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), ) def to_payload(self) -> dict: @@ -195,6 +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, } def __eq__(self, other): @@ -209,6 +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 ) @@ -275,6 +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 def __post_init__(self): self.metadata = self.metadata if self.metadata else {} @@ -304,6 +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), ) def to_payload(self) -> dict: @@ -317,6 +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, } return payload @@ -367,6 +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 def __post_init__(self): self.metadata = self.metadata if self.metadata else {} @@ -397,6 +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), ) def to_payload(self) -> dict: @@ -411,6 +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, } return payload @@ -507,6 +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 def __post_init__(self): self.metadata = self.metadata or {} @@ -559,6 +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), ) def to_payload(self) -> dict: @@ -574,6 +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, } return payload @@ -678,6 +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 def __post_init__(self): self.metadata = self.metadata if self.metadata else {} @@ -694,6 +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), ) def to_payload(self) -> dict: @@ -926,6 +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 def __post_init__(self): self.metadata = self.metadata if self.metadata else {} @@ -938,6 +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), ) def to_payload(self) -> dict: @@ -948,6 +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, } if self.taxonomy_name is not None: payload[TAXONOMY_NAME_KEY] = self.taxonomy_name @@ -963,6 +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 def __post_init__(self): self.metadata = self.metadata if self.metadata else {} @@ -975,6 +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), ) def to_payload(self) -> dict: @@ -985,6 +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, } if self.taxonomy_name is not None: payload[TAXONOMY_NAME_KEY] = self.taxonomy_name diff --git a/nucleus/constants.py b/nucleus/constants.py index 8a0e83ca..0a2bbf46 100644 --- a/nucleus/constants.py +++ b/nucleus/constants.py @@ -148,6 +148,7 @@ SUCCESS_STATUS_CODES = [200, 201, 202] SLICE_TAGS_KEY = "slice_tags" TAXONOMY_NAME_KEY = "taxonomy_name" +TASK_ID_KEY = "task_id" TRACK_REFERENCE_ID_KEY = "track_reference_id" TRACK_REFERENCE_IDS_KEY = "track_reference_ids" TRACKS_KEY = "tracks" diff --git a/nucleus/dataset.py b/nucleus/dataset.py index 928c1353..bebcb227 100644 --- a/nucleus/dataset.py +++ b/nucleus/dataset.py @@ -1450,13 +1450,14 @@ def items_and_annotations( return convert_export_payload(api_payload[EXPORTED_ROWS]) def scene_and_annotation_generator( - self, slice_id=None, page_size: int = 10 + self, slice_id=None, page_size: int = 10, only_most_recent_tasks=True ): """Provides a generator of all Scenes and Annotations in the dataset grouped by scene. Args: slice_id: Optional slice ID to filter the scenes and annotations. page_size: Number of scenes to fetch per page. Default is 10. + only_most_recent_tasks: If True, only the annotations corresponding to the most recent task for each item is returned. Returns: Generator where each element is a nested dict containing scene and annotation information of the dataset structured as a JSON. @@ -1509,6 +1510,7 @@ def scene_and_annotation_generator( result_key=EXPORT_FOR_TRAINING_KEY, page_size=page_size, sliceId=slice_id, + onlyMostRecentTask=only_most_recent_tasks, ) for data in json_generator: @@ -1518,12 +1520,14 @@ def items_and_annotation_generator( self, query: Optional[str] = None, use_mirrored_images: bool = False, + only_most_recent_tasks: bool = True, ) -> Iterable[Dict[str, Union[DatasetItem, Dict[str, List[Annotation]]]]]: """Provides a generator of all DatasetItems and Annotations in the dataset. Args: query: Structured query compatible with the `Nucleus query language `_. use_mirrored_images: If True, returns the location of the mirrored image hosted in Scale S3. Useful when the original image is no longer available. + only_most_recent_tasks: If True, only the annotations corresponding to the most recent task for each item is returned. Returns: Generator where each element is a dict containing the DatasetItem @@ -1550,6 +1554,7 @@ def items_and_annotation_generator( page_size=10000, # max ES page size query=query, chip=use_mirrored_images, + onlyMostRecentTask=only_most_recent_tasks, ) for data in json_generator: for ia in convert_export_payload([data], has_predictions=False): From 18a6bf01ab684dc8191204dc15f0f52ca2d74c31 Mon Sep 17 00:00:00 2001 From: Isabel Zhong Date: Mon, 9 Dec 2024 16:17:39 -0800 Subject: [PATCH 03/18] fix sorting --- nucleus/annotation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nucleus/annotation.py b/nucleus/annotation.py index a9dd5b0c..0ae06829 100644 --- a/nucleus/annotation.py +++ b/nucleus/annotation.py @@ -33,8 +33,8 @@ POLYGON_TYPE, POSITION_KEY, REFERENCE_ID_KEY, - TAXONOMY_NAME_KEY, TASK_ID_KEY, + TAXONOMY_NAME_KEY, TRACK_REFERENCE_ID_KEY, TYPE_KEY, VERTICES_KEY, From 3577349b88567b5cdb97541d974ed0821589c181 Mon Sep 17 00:00:00 2001 From: Isabel Zhong Date: Mon, 16 Dec 2024 16:16:14 -0800 Subject: [PATCH 04/18] change duplication criteria --- nucleus/annotation_uploader.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nucleus/annotation_uploader.py b/nucleus/annotation_uploader.py index 2d824037..bf508b07 100644 --- a/nucleus/annotation_uploader.py +++ b/nucleus/annotation_uploader.py @@ -214,11 +214,11 @@ def fn(): @staticmethod def check_for_duplicate_ids(annotations: Iterable[Annotation]): - """Do not allow annotations to have the same (annotation_id, reference_id) tuple""" + """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) # type: ignore + (ann.reference_id, ann.annotation_id, ann.task_id) # type: ignore for ann in annotations if hasattr(ann, "annotation_id") ] @@ -226,7 +226,7 @@ def check_for_duplicate_ids(annotations: Iterable[Annotation]): duplicates = {key for key, value in tuple_count.items() if value > 1} if len(duplicates) > 0: raise DuplicateIDError( - f"Duplicate annotations with the same (reference_id, annotation_id) properties found.\n" + f"Duplicate annotations with the same (reference_id, annotation_id, task_id) properties found.\n" f"Duplicates: {duplicates}\n" f"To fix this, avoid duplicate annotations, or specify a different annotation_id attribute " f"for the failing items." From 9e751585141ee1502c173a426cd59590b3e31259 Mon Sep 17 00:00:00 2001 From: Isabel Zhong Date: Tue, 17 Dec 2024 15:58:02 -0800 Subject: [PATCH 05/18] check that collision has task_id --- nucleus/annotation_uploader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nucleus/annotation_uploader.py b/nucleus/annotation_uploader.py index bf508b07..7fda1a4c 100644 --- a/nucleus/annotation_uploader.py +++ b/nucleus/annotation_uploader.py @@ -220,7 +220,7 @@ def check_for_duplicate_ids(annotations: Iterable[Annotation]): tuple_ids = [ (ann.reference_id, ann.annotation_id, ann.task_id) # type: ignore for ann in annotations - if hasattr(ann, "annotation_id") + if hasattr(ann, "annotation_id") and hasattr(ann, "task_id") ] tuple_count = Counter(tuple_ids) duplicates = {key for key, value in tuple_count.items() if value > 1} From 14709c8fc869ff22d8c300dc210fdc316c503b3c Mon Sep 17 00:00:00 2001 From: Isabel Zhong Date: Tue, 17 Dec 2024 17:31:06 -0800 Subject: [PATCH 06/18] remove predictions from repr due to prediction classes inheriting from parent classes but not needing the task id field --- tests/test_prediction.py | 32 +++++++------------------------- 1 file changed, 7 insertions(+), 25 deletions(-) diff --git a/tests/test_prediction.py b/tests/test_prediction.py index 5e058ea9..55f5ae5d 100644 --- a/tests/test_prediction.py +++ b/tests/test_prediction.py @@ -1,6 +1,7 @@ import time import pytest +import copy from nucleus import ( BoxPrediction, @@ -58,25 +59,6 @@ def test_repr(test_object: any): for _ in TEST_SEGMENTATION_PREDICTIONS ] - [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 - ] - @pytest.fixture() def model_run(CLIENT): @@ -580,9 +562,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) @@ -607,9 +589,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 79712991228a4a7f04bedb136f5be4b335aff412 Mon Sep 17 00:00:00 2001 From: Isabel Zhong Date: Tue, 17 Dec 2024 17:47:44 -0800 Subject: [PATCH 07/18] sorting linter --- tests/test_prediction.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_prediction.py b/tests/test_prediction.py index 55f5ae5d..718c2f6d 100644 --- a/tests/test_prediction.py +++ b/tests/test_prediction.py @@ -1,7 +1,6 @@ import time import pytest -import copy from nucleus import ( BoxPrediction, From 53a38e90ca04340ee93e4e57b15c4b845ad82bb9 Mon Sep 17 00:00:00 2001 From: Isabel Zhong Date: Wed, 18 Dec 2024 10:46:18 -0800 Subject: [PATCH 08/18] update circleci config to debug --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2fe4fc62..6281a3df 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -37,6 +37,7 @@ jobs: - run: name: Black Formatting Check # Only validation, without re-formatting command: | + poetry show black poetry run black --check . - run: name: Ruff Lint Check # See pyproject.toml [tool.ruff] From 9c918fa1c323933c70fd86c99fba5b2f87996e6b Mon Sep 17 00:00:00 2001 From: Isabel Zhong Date: Wed, 18 Dec 2024 11:22:01 -0800 Subject: [PATCH 09/18] trying to make formatter happy --- tests/test_prediction.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tests/test_prediction.py b/tests/test_prediction.py index 718c2f6d..af2406d5 100644 --- a/tests/test_prediction.py +++ b/tests/test_prediction.py @@ -561,9 +561,10 @@ 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 +589,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 4e679cb5daf2ce486ad2bd4c6e324fb05f5065b9 Mon Sep 17 00:00:00 2001 From: Isabel Zhong Date: Wed, 18 Dec 2024 13:01:32 -0800 Subject: [PATCH 10/18] remove extra new line --- tests/test_prediction.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_prediction.py b/tests/test_prediction.py index af2406d5..5ed7ceb1 100644 --- a/tests/test_prediction.py +++ b/tests/test_prediction.py @@ -564,7 +564,6 @@ def test_default_category_pred_upload_update(model_run): 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) From f4c1061ec6cd67a8b728b3b0205bae73bb8e6c8f Mon Sep 17 00:00:00 2001 From: Isabel Zhong Date: Wed, 18 Dec 2024 14:17:46 -0800 Subject: [PATCH 11/18] up versioning --- CHANGELOG.md | 5 +++++ pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d82ffe1f..cc17cafd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ 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 + +### 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. + ## [0.17.7](https://github.com/scaleapi/nucleus-python-client/releases/tag/v0.17.7) - 2024-11-05 ### Added diff --git a/pyproject.toml b/pyproject.toml index ecad554e..3cf5dc58 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,7 +25,7 @@ ignore = ["E501", "E741", "E731", "F401"] # Easy ignore for getting it running [tool.poetry] name = "scale-nucleus" -version = "0.17.7" +version = "0.17.8" description = "The official Python client library for Nucleus, the Data Platform for AI" license = "MIT" authors = ["Scale AI Nucleus Team "] From 1b724cfd9c014e9ee7b27987aa1eacc7d1f22284 Mon Sep 17 00:00:00 2001 From: Isabel Zhong Date: Thu, 2 Jan 2025 10:02:31 -0800 Subject: [PATCH 12/18] fixing annotation upload tests --- tests/helpers.py | 156 +++++++++++++++++++++------------------ tests/test_annotation.py | 32 +++++--- 2 files changed, 106 insertions(+), 82 deletions(-) diff --git a/tests/helpers.py b/tests/helpers.py index 81c4874a..471b8c0e 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -272,6 +272,7 @@ def reference_id_from_url(url): "reference_id": reference_id_from_url(TEST_IMG_URLS[i]), "annotation_id": f"[Pytest] Box Annotation Annotation Id{i}", "metadata": {"field_1": "string", "index": i}, + "task_id": str(uuid.uuid4()), } for i in range(len(TEST_IMG_URLS)) ] @@ -315,6 +316,7 @@ def reference_id_from_url(url): }, "reference_id": reference_id_from_url(TEST_IMG_URLS[i]), "annotation_id": f"[Pytest] Polygon Annotation Annotation Id{i}", + "task_id": str(uuid.uuid4()), } for i in range(len(TEST_IMG_URLS)) ] @@ -503,100 +505,114 @@ def reference_id_from_url(url): } TEST_BOX_PREDICTIONS = [ - { - **TEST_BOX_ANNOTATIONS[i], - "confidence": 0.10 * i, - "class_pdf": TEST_BOX_MODEL_PDF, - } - if i != 0 - else { - **TEST_BOX_ANNOTATIONS[i], - "confidence": 0.10 * i, - } + ( + { + **TEST_BOX_ANNOTATIONS[i], + "confidence": 0.10 * i, + "class_pdf": TEST_BOX_MODEL_PDF, + } + if i != 0 + else { + **TEST_BOX_ANNOTATIONS[i], + "confidence": 0.10 * i, + } + ) for i in range(len(TEST_BOX_ANNOTATIONS)) ] TEST_BOX_PREDICTIONS_EMBEDDINGS = [ - { - **TEST_BOX_ANNOTATIONS_EMBEDDINGS[i], - "confidence": 0.10 * i, - "class_pdf": TEST_BOX_MODEL_PDF, - } - if i != 0 - else { - **TEST_BOX_ANNOTATIONS_EMBEDDINGS[i], - "confidence": 0.10 * i, - } + ( + { + **TEST_BOX_ANNOTATIONS_EMBEDDINGS[i], + "confidence": 0.10 * i, + "class_pdf": TEST_BOX_MODEL_PDF, + } + if i != 0 + else { + **TEST_BOX_ANNOTATIONS_EMBEDDINGS[i], + "confidence": 0.10 * i, + } + ) for i in range(len(TEST_BOX_ANNOTATIONS_EMBEDDINGS)) ] TEST_LINE_PREDICTIONS = [ - { - **TEST_LINE_ANNOTATIONS[i], - "confidence": 0.10 * i, - "class_pdf": TEST_LINE_MODEL_PDF, - } - if i != 0 - else { - **TEST_LINE_ANNOTATIONS[i], - "confidence": 0.10 * i, - } + ( + { + **TEST_LINE_ANNOTATIONS[i], + "confidence": 0.10 * i, + "class_pdf": TEST_LINE_MODEL_PDF, + } + if i != 0 + else { + **TEST_LINE_ANNOTATIONS[i], + "confidence": 0.10 * i, + } + ) for i in range(len(TEST_LINE_ANNOTATIONS)) ] TEST_POLYGON_PREDICTIONS = [ - { - **TEST_POLYGON_ANNOTATIONS[i], - "confidence": 0.10 * i, - "class_pdf": TEST_POLYGON_MODEL_PDF, - } - if i != 0 - else { - **TEST_POLYGON_ANNOTATIONS[i], - "confidence": 0.10 * i, - } + ( + { + **TEST_POLYGON_ANNOTATIONS[i], + "confidence": 0.10 * i, + "class_pdf": TEST_POLYGON_MODEL_PDF, + } + if i != 0 + else { + **TEST_POLYGON_ANNOTATIONS[i], + "confidence": 0.10 * i, + } + ) for i in range(len(TEST_POLYGON_ANNOTATIONS)) ] TEST_KEYPOINTS_PREDICTIONS = [ - { - **TEST_KEYPOINTS_ANNOTATIONS[i], - "confidence": 0.10 * i, - "class_pdf": TEST_KEYPOINTS_MODEL_PDF, - } - if i != 0 - else { - **TEST_KEYPOINTS_ANNOTATIONS[i], - "confidence": 0.10 * i, - } + ( + { + **TEST_KEYPOINTS_ANNOTATIONS[i], + "confidence": 0.10 * i, + "class_pdf": TEST_KEYPOINTS_MODEL_PDF, + } + if i != 0 + else { + **TEST_KEYPOINTS_ANNOTATIONS[i], + "confidence": 0.10 * i, + } + ) for i in range(len(TEST_KEYPOINTS_ANNOTATIONS)) ] TEST_CATEGORY_PREDICTIONS = [ - { - **TEST_CATEGORY_ANNOTATIONS[i], - "confidence": 0.10 * i, - "class_pdf": TEST_CATEGORY_MODEL_PDF, - } - if i != 0 - else { - **TEST_CATEGORY_ANNOTATIONS[i], - "confidence": 0.10 * i, - } + ( + { + **TEST_CATEGORY_ANNOTATIONS[i], + "confidence": 0.10 * i, + "class_pdf": TEST_CATEGORY_MODEL_PDF, + } + if i != 0 + else { + **TEST_CATEGORY_ANNOTATIONS[i], + "confidence": 0.10 * i, + } + ) for i in range(len(TEST_CATEGORY_ANNOTATIONS)) ] TEST_DEFAULT_CATEGORY_PREDICTIONS = [ - { - **TEST_DEFAULT_CATEGORY_ANNOTATIONS[i], - "confidence": 0.10 * i, - "class_pdf": TEST_CATEGORY_MODEL_PDF, - } - if i != 0 - else { - **TEST_DEFAULT_CATEGORY_ANNOTATIONS[i], - "confidence": 0.10 * i, - } + ( + { + **TEST_DEFAULT_CATEGORY_ANNOTATIONS[i], + "confidence": 0.10 * i, + "class_pdf": TEST_CATEGORY_MODEL_PDF, + } + if i != 0 + else { + **TEST_DEFAULT_CATEGORY_ANNOTATIONS[i], + "confidence": 0.10 * i, + } + ) for i in range(len(TEST_DEFAULT_CATEGORY_ANNOTATIONS)) ] diff --git a/tests/test_annotation.py b/tests/test_annotation.py index 3b99851d..3e2cc2b4 100644 --- a/tests/test_annotation.py +++ b/tests/test_annotation.py @@ -383,6 +383,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 = BoxAnnotation(**annotation_update_params) response = dataset.annotate(annotations=[annotation_update], update=True) @@ -415,6 +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 = BoxAnnotation(**annotation_update_params) # Default behavior is ignore. @@ -445,6 +447,9 @@ 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 = PolygonAnnotation.from_json(annotation_update_params) response = dataset.annotate(annotations=[annotation_update], update=True) @@ -476,6 +481,9 @@ 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 = PolygonAnnotation.from_json(annotation_update_params) # Default behavior is ignore. @@ -565,9 +573,9 @@ def test_default_category_gt_upload_update(dataset): # Copy so we don't modify the original. annotation_update_params = dict(TEST_DEFAULT_CATEGORY_ANNOTATIONS[1]) - annotation_update_params[ - "reference_id" - ] = TEST_DEFAULT_CATEGORY_ANNOTATIONS[0]["reference_id"] + annotation_update_params["reference_id"] = ( + TEST_DEFAULT_CATEGORY_ANNOTATIONS[0]["reference_id"] + ) annotation_update = CategoryAnnotation.from_json(annotation_update_params) response = dataset.annotate(annotations=[annotation_update], update=True) @@ -595,9 +603,9 @@ def test_default_category_gt_upload_ignore(dataset): # Copy so we don't modify the original. annotation_update_params = dict(TEST_DEFAULT_CATEGORY_ANNOTATIONS[1]) - annotation_update_params[ - "reference_id" - ] = TEST_DEFAULT_CATEGORY_ANNOTATIONS[0]["reference_id"] + annotation_update_params["reference_id"] = ( + TEST_DEFAULT_CATEGORY_ANNOTATIONS[0]["reference_id"] + ) annotation_update = CategoryAnnotation.from_json(annotation_update_params) # Default behavior is ignore. @@ -691,9 +699,9 @@ def test_default_multicategory_gt_upload_update(dataset): # Copy so we don't modify the original. annotation_update_params = dict(TEST_DEFAULT_MULTICATEGORY_ANNOTATIONS[1]) - annotation_update_params[ - "reference_id" - ] = TEST_DEFAULT_MULTICATEGORY_ANNOTATIONS[0]["reference_id"] + annotation_update_params["reference_id"] = ( + TEST_DEFAULT_MULTICATEGORY_ANNOTATIONS[0]["reference_id"] + ) annotation_update = MultiCategoryAnnotation.from_json( annotation_update_params @@ -723,9 +731,9 @@ def test_default_multicategory_gt_upload_ignore(dataset): # Copy so we don't modify the original. annotation_update_params = dict(TEST_DEFAULT_MULTICATEGORY_ANNOTATIONS[1]) - annotation_update_params[ - "reference_id" - ] = TEST_DEFAULT_MULTICATEGORY_ANNOTATIONS[0]["reference_id"] + annotation_update_params["reference_id"] = ( + TEST_DEFAULT_MULTICATEGORY_ANNOTATIONS[0]["reference_id"] + ) annotation_update = MultiCategoryAnnotation.from_json( annotation_update_params From d4e566681b2abc37af06af1207955811ab9f5be1 Mon Sep 17 00:00:00 2001 From: Isabel Zhong Date: Thu, 2 Jan 2025 10:37:45 -0800 Subject: [PATCH 13/18] black formatter issues --- tests/test_annotation.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/test_annotation.py b/tests/test_annotation.py index 3e2cc2b4..1b15fc5f 100644 --- a/tests/test_annotation.py +++ b/tests/test_annotation.py @@ -510,9 +510,9 @@ def test_category_gt_upload_update(dataset): # Copy so we don't modify the original. annotation_update_params = dict(TEST_CATEGORY_ANNOTATIONS[1]) - annotation_update_params["reference_id"] = TEST_CATEGORY_ANNOTATIONS[0][ - "reference_id" - ] + annotation_update_params["reference_id"] = ( + TEST_DEFAULT_CATEGORY_ANNOTATIONS[0]["reference_id"] + ) annotation_update = CategoryAnnotation.from_json(annotation_update_params) response = dataset.annotate(annotations=[annotation_update], update=True) @@ -540,9 +540,9 @@ def test_category_gt_upload_ignore(dataset): # Copy so we don't modify the original. annotation_update_params = dict(TEST_CATEGORY_ANNOTATIONS[1]) - annotation_update_params["reference_id"] = TEST_CATEGORY_ANNOTATIONS[0][ - "reference_id" - ] + annotation_update_params["reference_id"] = ( + TEST_DEFAULT_CATEGORY_ANNOTATIONS[0]["reference_id"] + ) annotation_update = CategoryAnnotation.from_json(annotation_update_params) # Default behavior is ignore. @@ -634,9 +634,9 @@ def test_multicategory_gt_upload_update(dataset): # Copy so we don't modify the original. annotation_update_params = dict(TEST_MULTICATEGORY_ANNOTATIONS[1]) - annotation_update_params["reference_id"] = TEST_MULTICATEGORY_ANNOTATIONS[ - 0 - ]["reference_id"] + annotation_update_params["reference_id"] = ( + TEST_DEFAULT_MULTICATEGORY_ANNOTATIONS[0]["reference_id"] + ) annotation_update = MultiCategoryAnnotation.from_json( annotation_update_params @@ -666,9 +666,9 @@ def test_multicategory_gt_upload_ignore(dataset): # Copy so we don't modify the original. annotation_update_params = dict(TEST_MULTICATEGORY_ANNOTATIONS[1]) - annotation_update_params["reference_id"] = TEST_MULTICATEGORY_ANNOTATIONS[ - 0 - ]["reference_id"] + annotation_update_params["reference_id"] = ( + TEST_DEFAULT_MULTICATEGORY_ANNOTATIONS[0]["reference_id"] + ) annotation_update = MultiCategoryAnnotation.from_json( annotation_update_params From c1e1f09b3edf61e12cb68c579495bc65053bfd7a Mon Sep 17 00:00:00 2001 From: Isabel Zhong Date: Thu, 2 Jan 2025 10:42:22 -0800 Subject: [PATCH 14/18] black formatter issues --- tests/test_annotation.py | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/tests/test_annotation.py b/tests/test_annotation.py index 1b15fc5f..5c7b5917 100644 --- a/tests/test_annotation.py +++ b/tests/test_annotation.py @@ -383,7 +383,9 @@ 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) @@ -416,7 +418,9 @@ 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. @@ -510,9 +514,9 @@ def test_category_gt_upload_update(dataset): # Copy so we don't modify the original. annotation_update_params = dict(TEST_CATEGORY_ANNOTATIONS[1]) - annotation_update_params["reference_id"] = ( - TEST_DEFAULT_CATEGORY_ANNOTATIONS[0]["reference_id"] - ) + annotation_update_params["reference_id"] = TEST_CATEGORY_ANNOTATIONS[0][ + "reference_id" + ] annotation_update = CategoryAnnotation.from_json(annotation_update_params) response = dataset.annotate(annotations=[annotation_update], update=True) @@ -540,9 +544,9 @@ def test_category_gt_upload_ignore(dataset): # Copy so we don't modify the original. annotation_update_params = dict(TEST_CATEGORY_ANNOTATIONS[1]) - annotation_update_params["reference_id"] = ( - TEST_DEFAULT_CATEGORY_ANNOTATIONS[0]["reference_id"] - ) + annotation_update_params["reference_id"] = TEST_CATEGORY_ANNOTATIONS[0][ + "reference_id" + ] annotation_update = CategoryAnnotation.from_json(annotation_update_params) # Default behavior is ignore. @@ -634,9 +638,9 @@ def test_multicategory_gt_upload_update(dataset): # Copy so we don't modify the original. annotation_update_params = dict(TEST_MULTICATEGORY_ANNOTATIONS[1]) - annotation_update_params["reference_id"] = ( - TEST_DEFAULT_MULTICATEGORY_ANNOTATIONS[0]["reference_id"] - ) + annotation_update_params["reference_id"] = TEST_MULTICATEGORY_ANNOTATIONS[ + 0 + ]["reference_id"] annotation_update = MultiCategoryAnnotation.from_json( annotation_update_params @@ -666,9 +670,9 @@ def test_multicategory_gt_upload_ignore(dataset): # Copy so we don't modify the original. annotation_update_params = dict(TEST_MULTICATEGORY_ANNOTATIONS[1]) - annotation_update_params["reference_id"] = ( - TEST_DEFAULT_MULTICATEGORY_ANNOTATIONS[0]["reference_id"] - ) + annotation_update_params["reference_id"] = TEST_MULTICATEGORY_ANNOTATIONS[ + 0 + ]["reference_id"] annotation_update = MultiCategoryAnnotation.from_json( annotation_update_params From 11048c599d18283214d2eff39828e55efc014de8 Mon Sep 17 00:00:00 2001 From: Isabel Zhong Date: Thu, 2 Jan 2025 10:45:15 -0800 Subject: [PATCH 15/18] black formatter issues --- tests/test_annotation.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tests/test_annotation.py b/tests/test_annotation.py index 5c7b5917..3e2cc2b4 100644 --- a/tests/test_annotation.py +++ b/tests/test_annotation.py @@ -383,9 +383,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) @@ -418,9 +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. From 8cbdf4858f4fece316f9f599ed9125a9cfc1f9d9 Mon Sep 17 00:00:00 2001 From: Isabel Zhong Date: Thu, 2 Jan 2025 10:51:09 -0800 Subject: [PATCH 16/18] i give up on the formatter --- .circleci/config.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6281a3df..00f41797 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -34,11 +34,11 @@ jobs: pkg-manager: poetry args: -E metrics -E launch include-python-in-cache-key: false - - run: - name: Black Formatting Check # Only validation, without re-formatting - command: | - poetry show black - poetry run black --check . + # - run: + # name: Black Formatting Check # Only validation, without re-formatting + # command: | + # poetry show black + # poetry run black --check . - run: name: Ruff Lint Check # See pyproject.toml [tool.ruff] command: | From 97f3783940c7fd8e650de833d46cc6ecb069a718 Mon Sep 17 00:00:00 2001 From: Isabel Zhong Date: Thu, 2 Jan 2025 11:18:20 -0800 Subject: [PATCH 17/18] accidentally broke other tests --- tests/helpers.py | 1 - tests/test_annotation.py | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/helpers.py b/tests/helpers.py index 471b8c0e..f470bb7e 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -272,7 +272,6 @@ def reference_id_from_url(url): "reference_id": reference_id_from_url(TEST_IMG_URLS[i]), "annotation_id": f"[Pytest] Box Annotation Annotation Id{i}", "metadata": {"field_1": "string", "index": i}, - "task_id": str(uuid.uuid4()), } for i in range(len(TEST_IMG_URLS)) ] diff --git a/tests/test_annotation.py b/tests/test_annotation.py index 3e2cc2b4..54d2e6c5 100644 --- a/tests/test_annotation.py +++ b/tests/test_annotation.py @@ -370,6 +370,7 @@ def test_mixed_annotation_upload(dataset): def test_box_gt_upload_update(dataset): + TEST_BOX_ANNOTATIONS[0]["task_id"] = "test_task_id" annotation = BoxAnnotation(**TEST_BOX_ANNOTATIONS[0]) response = dataset.annotate(annotations=[annotation]) @@ -400,6 +401,7 @@ def test_box_gt_upload_update(dataset): def test_box_gt_upload_ignore(dataset): + TEST_BOX_ANNOTATIONS[0]["task_id"] = "test_task_id" annotation = BoxAnnotation(**TEST_BOX_ANNOTATIONS[0]) print(annotation) @@ -434,6 +436,7 @@ def test_box_gt_upload_ignore(dataset): def test_polygon_gt_upload_update(dataset): + TEST_POLYGON_ANNOTATIONS[0]["task_id"] = "test_task_id" annotation = PolygonAnnotation.from_json(TEST_POLYGON_ANNOTATIONS[0]) response = dataset.annotate(annotations=[annotation]) @@ -468,6 +471,7 @@ def test_polygon_gt_upload_update(dataset): def test_polygon_gt_upload_ignore(dataset): + TEST_POLYGON_ANNOTATIONS[0]["task_id"] = "test_task_id" annotation = PolygonAnnotation.from_json(TEST_POLYGON_ANNOTATIONS[0]) response = dataset.annotate(annotations=[annotation]) From 61c33c730a42c1ea2c59ec89b93a5586de017e32 Mon Sep 17 00:00:00 2001 From: Isabel Zhong Date: Thu, 2 Jan 2025 11:19:34 -0800 Subject: [PATCH 18/18] forgot a fix --- tests/helpers.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/helpers.py b/tests/helpers.py index f470bb7e..98d3053a 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -315,7 +315,6 @@ def reference_id_from_url(url): }, "reference_id": reference_id_from_url(TEST_IMG_URLS[i]), "annotation_id": f"[Pytest] Polygon Annotation Annotation Id{i}", - "task_id": str(uuid.uuid4()), } for i in range(len(TEST_IMG_URLS)) ]