Skip to content

Commit 6f99400

Browse files
author
Nicolas Hervé
committed
feat: add kili export format for geospatial projects
2 parents b5f84a9 + 831d287 commit 6f99400

File tree

4 files changed

+77
-5
lines changed

4 files changed

+77
-5
lines changed

src/kili/adapters/authentification.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def is_api_key_valid(
2020
"""
2121
response = http_client.post(
2222
url=api_endpoint,
23-
data='{"query":"{ me { id email } }"}',
23+
data='{"query":"{ viewer { id email } }"}',
2424
timeout=30,
2525
headers={
2626
"Authorization": f"X-API-Key: {api_key}",

src/kili/adapters/kili_api_gateway/label/annotation_to_json_response.py

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from kili.domain.annotation import (
1010
ClassicAnnotation,
1111
ClassificationAnnotation,
12+
ObjectDetectionAnnotation,
1213
RankingAnnotation,
1314
TranscriptionAnnotation,
1415
Vertice,
@@ -55,7 +56,7 @@ def patch_label_json_response(
5556
5657
Modifies the input label.
5758
"""
58-
if self._project_input_type in {"VIDEO", "LLM_RLHF"}:
59+
if self._project_input_type in {"VIDEO", "LLM_RLHF", "GEOSPATIAL"}:
5960
if not annotations and self._label_has_json_response_data(label):
6061
return
6162

@@ -65,8 +66,11 @@ def patch_label_json_response(
6566
annotations=annotations, json_interface=self._project_json_interface
6667
)
6768
else:
69+
print("converting annotations")
6870
annotations = cast(List[ClassicAnnotation], annotations)
69-
converted_json_resp = _classic_annotations_to_json_response(annotations=annotations)
71+
converted_json_resp = _classic_annotations_to_json_response(
72+
annotations=annotations, json_interface=self._project_json_interface
73+
)
7074

7175
label["jsonResponse"] = converted_json_resp
7276

@@ -152,7 +156,7 @@ def _video_annotations_to_json_response(
152156

153157

154158
def _classic_annotations_to_json_response(
155-
annotations: List[ClassicAnnotation],
159+
annotations: List[ClassicAnnotation], json_interface: Dict
156160
) -> Dict[str, Dict[JobName, Dict]]:
157161
"""Convert label annotations to a json response."""
158162
json_resp = defaultdict(dict)
@@ -185,6 +189,18 @@ def _classic_annotations_to_json_response(
185189
for job_name, job_resp in ann_json_resp.items():
186190
json_resp.setdefault(job_name, {}).setdefault("text", job_resp["text"])
187191

192+
elif ann["__typename"] == "ObjectDetectionAnnotation":
193+
ann = cast(ObjectDetectionAnnotation, ann)
194+
ann_json_resp = _object_detection_annotation_to_json_response(
195+
ann,
196+
other_annotations,
197+
json_interface,
198+
)
199+
for job_name, job_resp in ann_json_resp.items():
200+
json_resp.setdefault(job_name, {}).setdefault("annotations", []).extend(
201+
job_resp["annotations"]
202+
)
203+
188204
else:
189205
raise NotImplementedError(f"Cannot convert classic annotation to json response: {ann}")
190206

@@ -352,6 +368,46 @@ def _transcription_annotation_to_json_response(
352368
return json_resp
353369

354370

371+
def _object_detection_annotation_to_json_response(
372+
annotation: ObjectDetectionAnnotation,
373+
other_annotations: List[ClassicAnnotation],
374+
json_interface: Dict,
375+
) -> Dict[JobName, Dict]:
376+
"""Convert object detection annotation to a json response."""
377+
child_annotations = _get_child_annotations(annotation, other_annotations)
378+
json_resp_child_jobs = (
379+
_compute_children_json_resp(child_annotations, other_annotations)
380+
if child_annotations
381+
else {}
382+
)
383+
384+
annotation_dict = {
385+
"children": json_resp_child_jobs,
386+
"categories": [{"name": annotation["category"]}],
387+
"mid": annotation["mid"],
388+
"type": json_interface["jobs"][annotation["job"]]["tools"][0],
389+
}
390+
391+
norm_vertices = annotation["annotationValue"]["vertices"]
392+
393+
if json_interface["jobs"][annotation["job"]]["tools"][0] == "marker":
394+
annotation_dict["point"] = norm_vertices[0][0][0]
395+
396+
elif json_interface["jobs"][annotation["job"]]["tools"][0] in {"polygon", "rectangle"}:
397+
annotation_dict["boundingPoly"] = [{"normalizedVertices": norm_vertices[0][0]}]
398+
399+
elif json_interface["jobs"][annotation["job"]]["tools"][0] == "semantic":
400+
annotation_dict["boundingPoly"] = [
401+
{"normalizedVertices": norm_vert} for norm_vert in norm_vertices[0]
402+
]
403+
404+
return {
405+
annotation["job"]: {
406+
"annotations": [annotation_dict],
407+
},
408+
}
409+
410+
355411
def _video_transcription_annotation_to_json_response(
356412
annotation: VideoTranscriptionAnnotation,
357413
) -> Dict[str, Dict[JobName, Dict]]:

src/kili/domain/annotation.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,21 @@ class Annotation(TypedDict):
9393
path: List[List[str]]
9494

9595

96+
class ObjectDetectionAnnotation(TypedDict):
97+
"""Object detection annotation."""
98+
99+
# pylint: disable=unused-private-member
100+
__typename: Literal["ObjectDetectionAnnotation"]
101+
id: AnnotationId
102+
labelId: LabelId
103+
job: JobName
104+
path: List[List[str]]
105+
annotationValue: ObjectDetectionAnnotationValue
106+
name: Optional[str]
107+
mid: str
108+
category: str
109+
110+
96111
class FrameInterval(TypedDict):
97112
"""Frame interval."""
98113

@@ -174,6 +189,7 @@ class VideoTranscriptionAnnotation(TypedDict):
174189

175190
ClassicAnnotation = Union[
176191
ClassificationAnnotation,
192+
ObjectDetectionAnnotation,
177193
RankingAnnotation,
178194
TranscriptionAnnotation,
179195
]

tests/unit/adapters/kili_api_gateway/label/test_label_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ def test_given_classic_label_annotations_when_converting_to_json_resp_it_works(
173173
_ = annotations
174174

175175
# When
176-
json_resp = _classic_annotations_to_json_response(annotations)
176+
json_resp = _classic_annotations_to_json_response(annotations, {})
177177

178178
# Then
179179
assert json_resp == expected_json_resp

0 commit comments

Comments
 (0)