diff --git a/labelbox/data/serialization/ndjson/converter.py b/labelbox/data/serialization/ndjson/converter.py index 0292d2bbd..a7c54b109 100644 --- a/labelbox/data/serialization/ndjson/converter.py +++ b/labelbox/data/serialization/ndjson/converter.py @@ -74,38 +74,37 @@ def serialize( ]] = [] # First pass to get all RelatiohnshipAnnotaitons # and update the UUIDs of the source and target annotations - for relationship_annotation in ( - annotation for annotation in label.annotations - if isinstance(annotation, RelationshipAnnotation)): - if relationship_annotation in uuid_safe_annotations: - relationship_annotation = copy.deepcopy( - relationship_annotation) - new_source_uuid = uuid.uuid4() - new_target_uuid = uuid.uuid4() - relationship_uuids[relationship_annotation.value.source. - _uuid].append(new_source_uuid) - relationship_uuids[relationship_annotation.value.target. - _uuid].append(new_target_uuid) - relationship_annotation.value.source._uuid = new_source_uuid - relationship_annotation.value.target._uuid = new_target_uuid - if relationship_annotation._uuid in used_uuids: - relationship_annotation._uuid = uuid.uuid4() - used_uuids.add(relationship_annotation._uuid) - uuid_safe_annotations.append(relationship_annotation) + for annotation in label.annotations: + if isinstance(annotation, RelationshipAnnotation): + annotation = copy.deepcopy(annotation) + new_source_uuid = uuid.uuid4() + new_target_uuid = uuid.uuid4() + relationship_uuids[annotation.value.source._uuid].append( + new_source_uuid) + relationship_uuids[annotation.value.target._uuid].append( + new_target_uuid) + annotation.value.source._uuid = new_source_uuid + annotation.value.target._uuid = new_target_uuid + if annotation._uuid in used_uuids: + annotation._uuid = uuid.uuid4() + used_uuids.add(annotation._uuid) + uuid_safe_annotations.append(annotation) # Second pass to update UUIDs for annotations referenced by RelationshipAnnotations for annotation in label.annotations: - if not isinstance(annotation, RelationshipAnnotation): - if hasattr(annotation, "_uuid"): - if annotation in uuid_safe_annotations: - annotation = copy.deepcopy(annotation) - next_uuids = relationship_uuids[annotation._uuid] - if len(next_uuids) > 0: - annotation._uuid = next_uuids.popleft() + if (not isinstance(annotation, RelationshipAnnotation) and + hasattr(annotation, "_uuid")): + annotation = copy.deepcopy(annotation) + next_uuids = relationship_uuids[annotation._uuid] + if len(next_uuids) > 0: + annotation._uuid = next_uuids.popleft() - if annotation._uuid in used_uuids: - annotation._uuid = uuid.uuid4() - used_uuids.add(annotation._uuid) + if annotation._uuid in used_uuids: + annotation._uuid = uuid.uuid4() + used_uuids.add(annotation._uuid) uuid_safe_annotations.append(annotation) + else: + if not isinstance(annotation, RelationshipAnnotation): + uuid_safe_annotations.append(annotation) label.annotations = uuid_safe_annotations for example in NDLabel.from_common([label]): annotation_uuid = getattr(example, "uuid", None) diff --git a/tests/data/assets/ndjson/relationship_import.json b/tests/data/assets/ndjson/relationship_import.json index bb4d905ff..76cb61988 100644 --- a/tests/data/assets/ndjson/relationship_import.json +++ b/tests/data/assets/ndjson/relationship_import.json @@ -38,5 +38,45 @@ "target": "d8813907-b15d-4374-bbe6-b9877fb42ccd", "type": "unidirectional" } + }, + { + "uuid": "d8813907-b15d-4374-bbe6-b9877fb42ccd", + "dataRow": { + "id": "clf98gj90000qp38ka34yhptl-DIFFERENT" + }, + "name": "cat", + "classifications": [], + "bbox": { + "top": 200.0, + "left": 100.0, + "height": 100.0, + "width": 100.0 + } + }, + { + "uuid": "9b1e1249-36b4-4665-b60a-9060e0d18660", + "dataRow": { + "id": "clf98gj90000qp38ka34yhptl-DIFFERENT" + }, + "name": "dog", + "classifications": [], + "bbox": { + "top": 500.0, + "left": 400.0, + "height": 200.0, + "width": 200.0 + } + }, + { + "uuid": "0e6354eb-9adb-47e5-8e52-217ed016d948", + "dataRow": { + "id": "clf98gj90000qp38ka34yhptl-DIFFERENT" + }, + "name": "is chasing", + "relationship": { + "source": "9b1e1249-36b4-4665-b60a-9060e0d18660", + "target": "d8813907-b15d-4374-bbe6-b9877fb42ccd", + "type": "unidirectional" + } } ] diff --git a/tests/data/serialization/ndjson/test_relationship.py b/tests/data/serialization/ndjson/test_relationship.py index 0f6f640df..9ede41d2c 100644 --- a/tests/data/serialization/ndjson/test_relationship.py +++ b/tests/data/serialization/ndjson/test_relationship.py @@ -14,9 +14,9 @@ def test_relationship(): res = list(NDJsonConverter.serialize(res)) assert len(res) == len(data) - res_relationship_annotation = [ + res_relationship_annotation, res_relationship_second_annotation = [ annot for annot in res if "relationship" in annot - ][0] + ] res_source_and_target = [ annot for annot in res if "relationship" not in annot ] @@ -29,6 +29,18 @@ def test_relationship(): annot["uuid"] for annot in res_source_and_target ] + assert res_relationship_second_annotation + assert res_relationship_second_annotation["relationship"][ + "source"] != res_relationship_annotation["relationship"]["source"] + assert res_relationship_second_annotation["relationship"][ + "target"] != res_relationship_annotation["relationship"]["target"] + assert res_relationship_second_annotation["relationship"]["source"] in [ + annot["uuid"] for annot in res_source_and_target + ] + assert res_relationship_second_annotation["relationship"]["target"] in [ + annot["uuid"] for annot in res_source_and_target + ] + def test_relationship_nonexistent_object(): with open("tests/data/assets/ndjson/relationship_import.json", "r") as file: