diff --git a/darwin/datatypes.py b/darwin/datatypes.py index 56ccf2a73..44b954c98 100644 --- a/darwin/datatypes.py +++ b/darwin/datatypes.py @@ -22,6 +22,7 @@ except ImportError: NDArray = Any # type:ignore +from darwin.future.data_objects.properties import SelectedProperty from darwin.path_utils import construct_full_path, is_properties_enabled, parse_metadata # Utility types @@ -215,6 +216,9 @@ class Annotation: # The darwin ID of this annotation. id: Optional[str] = None + # Properties of this annotation. + properties: Optional[list[SelectedProperty]] = None + def get_sub(self, annotation_type: str) -> Optional[SubAnnotation]: """ Returns the first SubAnnotation that matches the given type. @@ -269,6 +273,9 @@ class VideoAnnotation: # The darwin ID of this annotation. id: Optional[str] = None + # Properties of this annotation. + properties: Optional[list[SelectedProperty]] = None + def get_data( self, only_keyframes: bool = True, @@ -1272,6 +1279,7 @@ def make_video_annotation( segments: List[Segment], interpolated: bool, slot_names: List[str], + properties: Optional[list[SelectedProperty]] = None, ) -> VideoAnnotation: """ Creates and returns a ``VideoAnnotation``. @@ -1308,6 +1316,7 @@ def make_video_annotation( segments, interpolated, slot_names=slot_names or [], + properties=properties, ) diff --git a/darwin/utils/utils.py b/darwin/utils/utils.py index 02ce6d3e8..721a0c8f6 100644 --- a/darwin/utils/utils.py +++ b/darwin/utils/utils.py @@ -38,6 +38,7 @@ UnrecognizableFileEncoding, UnsupportedFileType, ) +from darwin.future.data_objects.properties import SelectedProperty from darwin.version import __version__ if TYPE_CHECKING: @@ -839,6 +840,9 @@ def _parse_darwin_annotation(annotation: Dict[str, Any]) -> Optional[dt.Annotati if annotation.get("reviewers") is not None: main_annotation.reviewers = _parse_annotators(annotation["reviewers"]) + if "properties" in annotation: + main_annotation.properties = _parse_properties(annotation["properties"]) + return main_annotation @@ -861,6 +865,7 @@ def _parse_darwin_video_annotation(annotation: dict) -> Optional[dt.VideoAnnotat annotation.get("ranges", annotation.get("segments", [])), annotation.get("interpolated", False), slot_names=parse_slot_names(annotation), + properties=_parse_properties(annotation.get("properties", [])), ) if "id" in annotation: @@ -941,6 +946,21 @@ def _parse_annotators(annotators: List[Dict[str, Any]]) -> List[dt.AnnotationAut return [dt.AnnotationAuthor(annotator["full_name"], annotator["email"]) for annotator in annotators] +def _parse_properties(properties: List[Dict[str, Any]]) -> Optional[List[SelectedProperty]]: + selected_properties = [] + for property in properties: + selected_properties.append( + SelectedProperty( + frame_index=property.get("frame_index", None), + name=property.get("name", None), + type=property.get("type", None), + value=property.get("value", None), + ) + ) + + return selected_properties or None + + def split_video_annotation(annotation: dt.AnnotationFile) -> List[dt.AnnotationFile]: """ Splits the given video ``AnnotationFile`` into several video ``AnnotationFile``s, one for each