Skip to content

Commit

Permalink
Merge branch 'master' into aj/get-cloud-integrations-mark-deprecated
Browse files Browse the repository at this point in the history
  • Loading branch information
adam-encord authored Jan 11, 2025
2 parents b2165d3 + 6b9cbba commit 1ab677b
Show file tree
Hide file tree
Showing 12 changed files with 1,983 additions and 19 deletions.
5 changes: 3 additions & 2 deletions encord/objects/coordinates.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@
from __future__ import annotations

from dataclasses import dataclass
from enum import Flag, auto
from enum import auto
from typing import Any, Dict, List, Optional, Type, Union

from encord.exceptions import LabelRowError
from encord.objects.bitmask import BitmaskCoordinates
from encord.objects.common import Shape
from encord.orm.analytics import CamelStrEnum
from encord.orm.base_dto import BaseDTO


Expand Down Expand Up @@ -272,7 +273,7 @@ def to_dict(self) -> dict:
return {str(idx): {"x": value.x, "y": value.y} for idx, value in enumerate(self.values)}


class Visibility(Flag):
class Visibility(CamelStrEnum):
"""
An enumeration to represent the visibility state of an item.
Expand Down
14 changes: 13 additions & 1 deletion encord/objects/ontology_labels_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
PolylineCoordinates,
RotatableBoundingBoxCoordinates,
SkeletonCoordinates,
Visibility,
)
from encord.objects.frames import Frames, Range, Ranges, frames_class_to_frames_list, frames_to_ranges
from encord.objects.metadata import DICOMSeriesMetadata, DICOMSliceMetadata
Expand Down Expand Up @@ -2284,9 +2285,20 @@ def _get_coordinates(self, frame_object_label: dict) -> Coordinates:
elif "polyline" in frame_object_label:
return PolylineCoordinates.from_dict(frame_object_label)
elif "skeleton" in frame_object_label:

def _with_visibility_enum(point: dict):
if point.get(Visibility.INVISIBLE.value):
point["visibility"] = Visibility.INVISIBLE
elif point.get(Visibility.OCCLUDED.value):
point["visibility"] = Visibility.OCCLUDED
elif point.get(Visibility.VISIBLE.value):
point["visibility"] = Visibility.VISIBLE
return point

values = [_with_visibility_enum(pnt) for pnt in frame_object_label["skeleton"].values()]
skeleton_frame_object_label = {
"name": frame_object_label["name"],
"values": list(frame_object_label["skeleton"].values()),
"values": values,
}
return SkeletonCoordinates.from_dict(skeleton_frame_object_label)
elif "bitmask" in frame_object_label:
Expand Down
8 changes: 7 additions & 1 deletion encord/orm/cloud_integration.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import List
from typing import List, Optional
from uuid import UUID

from encord.orm.base_dto import BaseDTO
Expand All @@ -16,3 +16,9 @@ class CloudIntegrationV2(BaseDTO):

class GetCloudIntegrationsResponse(BaseDTO):
result: List[CloudIntegrationV2]


class GetCloudIntegrationsParams(BaseDTO):
filter_integration_uuids: Optional[List[UUID]] = None
filter_integration_titles: Optional[List[str]] = None
include_org_access: bool = False
39 changes: 39 additions & 0 deletions encord/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -1185,6 +1185,45 @@ def import_coco_labels(
branch_name=branch_name,
)

def export_coco_labels(
self,
label_hashes: Optional[List[str]] = None,
include_object_feature_hashes: Optional[Set[str]] = None,
include_classification_feature_hashes: Optional[Set[str]] = None,
branch_name: Optional[str] = None,
) -> Dict[str, Any]:
"""Export labels from the project to the COCO format.
This method requires the 'coco' extra to be installed. Install it using:
`pip install encord[coco]`.
Args:
label_hashes: List of label hashes to include. If not provided, all label rows will be included.
include_object_feature_hashes: If `None`, all objects will be included.
Otherwise, only objects with the specified feature hashes will be included.
include_classification_feature_hashes: If `None`, all classifications will be included.
Otherwise, only classifications with the specified feature hashes will be included.
branch_name: Optionally specify a branch name. Defaults to the `main` branch.
Returns:
Dict[str, Any]: A dictionary in the COCO format containing the exported labels,
including annotations and metadata conforming to COCO standards.
The dictionary also includes additional fields specific to Encord,
providing supplementary information not defined in the COCO standard.
Raises:
ImportError: If the 'coco' extra dependencies are not installed.
"""
from encord.utilities.coco.exporter import CocoExporter

label_rows = self.list_label_rows_v2(label_hashes=label_hashes, branch_name=branch_name)
with self.create_bundle() as bundle:
for row in label_rows:
row.initialise_labels(
include_object_feature_hashes=include_object_feature_hashes,
include_classification_feature_hashes=include_classification_feature_hashes,
bundle=bundle,
)
labels = [row.to_encord_dict() for row in label_rows]
coco_labels = CocoExporter(labels, ontology=self.ontology_structure).export()
return coco_labels

def get_collection(self, collection_uuid: Union[str, UUID]) -> ProjectCollection:
return ProjectCollection._get_collection(
project_client=self._client,
Expand Down
30 changes: 27 additions & 3 deletions encord/user_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
)
from encord.ontology import Ontology
from encord.orm.client_metadata_schema import ClientMetadataSchemaTypes
from encord.orm.cloud_integration import CloudIntegration, GetCloudIntegrationsResponse
from encord.orm.cloud_integration import CloudIntegration, GetCloudIntegrationsParams, GetCloudIntegrationsResponse
from encord.orm.dataset import (
DEFAULT_DATASET_ACCESS_SETTINGS,
CreateDatasetPayload,
Expand Down Expand Up @@ -865,15 +865,39 @@ def __upload_cvat_images(

return dataset_hash, image_title_to_image

def get_cloud_integrations(self) -> List[CloudIntegration]:
def get_cloud_integrations(
self,
filter_integration_uuids: Optional[Union[List[UUID], List[str], List[Union[UUID, str]]]] = None,
filter_integration_titles: Optional[List[str]] = None,
include_org_access: bool = False,
) -> List[CloudIntegration]:
"""
List either all (if called with no arguments) or matching cloud integrations the user has access to.
Args:
filter_integration_uuids: optional list of integration UUIDs to include.
filter_integration_titles: optional list of integration titles to include (exact match).
include_org_access: if set to true and the calling user is the organization admin, the
method will return all cloud integrations in the organization.
If `filter_integration_uuids` and `filter_integration_titles` are both provided, the method will return
the integrations that match both of the filters.
"""

if filter_integration_uuids is not None:
filter_integration_uuids = [UUID(x) if isinstance(x, str) else x for x in filter_integration_uuids]
return [
CloudIntegration(
id=str(x.integration_uuid),
title=x.title,
)
for x in self._api_client.get(
"cloud-integrations",
params=None,
params=GetCloudIntegrationsParams(
filter_integration_uuids=filter_integration_uuids,
filter_integration_titles=filter_integration_titles,
include_org_access=include_org_access,
),
result_type=GetCloudIntegrationsResponse,
).result
]
Expand Down
Loading

0 comments on commit 1ab677b

Please sign in to comment.