Skip to content

Commit 18c42c3

Browse files
Drew KaulDrew Kaul
authored andcommitted
finally got scene integration test working
1 parent 58811cf commit 18c42c3

File tree

7 files changed

+107
-63
lines changed

7 files changed

+107
-63
lines changed

nucleus/annotation.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ def from_json(cls, payload: dict):
289289
dimensions=Point3D.from_json(geometry.get(DIMENSIONS_KEY, {})),
290290
yaw=payload.get(YAW_KEY, 0),
291291
reference_id=payload.get(REFERENCE_ID_KEY, None),
292-
item_id=payload.get(ITEM_ID_KEY, None),
292+
item_id=payload.get(DATASET_ITEM_ID_KEY, None),
293293
annotation_id=payload.get(ANNOTATION_ID_KEY, None),
294294
metadata=payload.get(METADATA_KEY, {}),
295295
)
@@ -310,6 +310,15 @@ def to_payload(self) -> dict:
310310
}
311311

312312

313+
def check_all_frame_paths_remote(frames: List[str]):
314+
for frame_url in frames:
315+
if is_local_path(frame_url):
316+
raise ValueError(
317+
f"All paths must be remote, but {frame_url} is either "
318+
"local, or a remote URL type that is not supported."
319+
)
320+
321+
313322
def check_all_mask_paths_remote(
314323
annotations: Sequence[Union[Annotation]],
315324
):

nucleus/dataset.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from .annotation import (
1414
Annotation,
1515
check_all_mask_paths_remote,
16+
check_all_frame_paths_remote,
1617
)
1718
from .constants import (
1819
DATASET_ITEM_IDS_KEY,
@@ -246,6 +247,31 @@ def append(
246247
batch_size=batch_size,
247248
)
248249

250+
def upload_scene(
251+
self,
252+
payload: dict,
253+
update: Optional[bool] = False,
254+
asynchronous: bool = False,
255+
) -> Union[dict, AsyncJob]:
256+
"""TODO: add docstring here"""
257+
if asynchronous:
258+
check_all_frame_paths_remote(payload["frames"])
259+
request_id = serialize_and_write_to_presigned_url(
260+
[payload], self.id, self._client
261+
)
262+
response = self._client.make_request(
263+
payload={REQUEST_ID_KEY: request_id, UPDATE_KEY: update},
264+
route=f"{self.id}/upload_scene?async=1",
265+
)
266+
return AsyncJob(response["job_id"], self._client)
267+
268+
# TODO: create client method for sync scene upload
269+
response = self._client.make_request(
270+
payload=payload,
271+
route=f"{self.id}/upload_scene",
272+
)
273+
return response
274+
249275
def iloc(self, i: int) -> dict:
250276
"""
251277
Returns Dataset Item Info By Dataset Item Number.

nucleus/prediction.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ def from_json(cls, payload: dict):
198198
dimensions=Point3D.from_json(geometry.get(DIMENSIONS_KEY, {})),
199199
yaw=payload.get(YAW_KEY, 0),
200200
reference_id=payload.get(REFERENCE_ID_KEY, None),
201-
item_id=payload.get(ITEM_ID_KEY, None),
201+
item_id=payload.get(DATASET_ITEM_ID_KEY, None),
202202
confidence=payload.get(CONFIDENCE_KEY, None),
203203
annotation_id=payload.get(ANNOTATION_ID_KEY, None),
204204
metadata=payload.get(METADATA_KEY, {}),

nucleus/utils.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from collections import defaultdict
44
import io
55
import uuid
6+
import json
67
from typing import IO, Dict, List, Sequence, Union
78

89
import requests
@@ -120,11 +121,14 @@ def convert_export_payload(api_payload):
120121

121122

122123
def serialize_and_write(
123-
upload_units: Sequence[Union[DatasetItem, Annotation]], file_pointer
124+
upload_units: Sequence[Union[DatasetItem, Annotation, Dict]], file_pointer
124125
):
125126
for unit in upload_units:
126127
try:
127-
file_pointer.write(unit.to_json() + "\n")
128+
if isinstance(unit, (DatasetItem, Annotation)):
129+
file_pointer.write(unit.to_json() + "\n")
130+
else:
131+
file_pointer.write(json.dumps(unit) + "\n")
128132
except TypeError as e:
129133
type_name = type(unit).__name__
130134
message = (
@@ -151,7 +155,7 @@ def upload_to_presigned_url(presigned_url: str, file_pointer: IO):
151155

152156

153157
def serialize_and_write_to_presigned_url(
154-
upload_units: Sequence[Union["DatasetItem", Annotation]],
158+
upload_units: Sequence[Union[DatasetItem, Annotation, Dict]],
155159
dataset_id: str,
156160
client,
157161
):

tests/helpers.py

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@
2323
]
2424

2525
TEST_POINTCLOUD_URLS = [
26-
"https://scale-us-attachments.s3.us-west-2.amazonaws.com/select/examples/kitti_example_frame.json",
26+
"https://scaleapi-cust-lidar.s3.us-west-1.amazonaws.com/test-scale/frame-0.json",
2727
]
2828

29+
TEST_LIDAR_FRAMES = {"frames": TEST_POINTCLOUD_URLS}
30+
2931
TEST_DATASET_ITEMS = [
3032
DatasetItem(TEST_IMG_URLS[0], "1"),
3133
DatasetItem(TEST_IMG_URLS[1], "2"),
@@ -93,7 +95,6 @@ def reference_id_from_url(url):
9395
},
9496
"yaw": 5 * i,
9597
},
96-
"reference_id": reference_id_from_url(TEST_POINTCLOUD_URLS[i]),
9798
"annotation_id": f"[Pytest] Cuboid Annotation Annotation Id{i}",
9899
}
99100
for i in range(len(TEST_POINTCLOUD_URLS))
@@ -191,19 +192,19 @@ def assert_cuboid_annotation_matches_dict(
191192
assert (
192193
annotation_instance.annotation_id == annotation_dict["annotation_id"]
193194
)
194-
for instance_pt, dict_pt in zip(
195-
annotation_instance.position, annotation_dict["geometry"]["position"]
196-
):
197-
assert instance_pt.x == dict_pt["x"]
198-
assert instance_pt.y == dict_pt["y"]
199-
assert instance_pt.z == dict_pt["z"]
200-
for instance_pt, dict_pt in zip(
201-
annotation_instance.dimensions,
202-
annotation_dict["geometry"]["dimensions"],
203-
):
204-
assert instance_pt.x == dict_pt["x"]
205-
assert instance_pt.y == dict_pt["y"]
206-
assert instance_pt.z == dict_pt["z"]
195+
196+
instance_pos = annotation_instance.position
197+
dict_pos = annotation_dict["geometry"]["position"]
198+
assert instance_pos.x == dict_pos["x"]
199+
assert instance_pos.y == dict_pos["y"]
200+
assert instance_pos.z == dict_pos["z"]
201+
202+
instance_dim = annotation_instance.dimensions
203+
dict_dim = annotation_dict["geometry"]["dimensions"]
204+
assert instance_dim.x == dict_dim["x"]
205+
assert instance_dim.y == dict_dim["y"]
206+
assert instance_dim.z == dict_dim["z"]
207+
207208
assert annotation_instance.yaw == annotation_dict["geometry"]["yaw"]
208209

209210

tests/test_annotation.py

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,19 @@
22

33
from .helpers import (
44
TEST_DATASET_NAME,
5-
TEST_DATASET_3D_NAME,
65
TEST_IMG_URLS,
7-
TEST_POINTCLOUD_URLS,
86
TEST_BOX_ANNOTATIONS,
97
TEST_POLYGON_ANNOTATIONS,
10-
TEST_CUBOID_ANNOTATIONS,
118
TEST_SEGMENTATION_ANNOTATIONS,
129
reference_id_from_url,
1310
assert_box_annotation_matches_dict,
1411
assert_polygon_annotation_matches_dict,
15-
assert_cuboid_annotation_matches_dict,
1612
assert_segmentation_annotation_matches_dict,
1713
)
1814

1915
from nucleus import (
2016
BoxAnnotation,
2117
PolygonAnnotation,
22-
CuboidAnnotation,
2318
SegmentationAnnotation,
2419
DatasetItem,
2520
Segment,
@@ -66,26 +61,6 @@ def dataset(CLIENT):
6661
assert response == {"message": "Beginning dataset deletion..."}
6762

6863

69-
@pytest.fixture()
70-
def dataset_3d(CLIENT):
71-
ds = CLIENT.create_dataset(TEST_DATASET_3D_NAME)
72-
ds_items = []
73-
for url in TEST_POINTCLOUD_URLS:
74-
ds_items.append(
75-
DatasetItem(
76-
image_location=url,
77-
reference_id=reference_id_from_url(url),
78-
)
79-
)
80-
81-
response = ds.append(ds_items)
82-
assert ERROR_PAYLOAD not in response.json()
83-
yield ds
84-
85-
response = CLIENT.delete_dataset(ds.id)
86-
assert response == {"message": "Beginning dataset deletion..."}
87-
88-
8964
def test_box_gt_upload(dataset):
9065
annotation = BoxAnnotation(**TEST_BOX_ANNOTATIONS[0])
9166
response = dataset.annotate(annotations=[annotation])
@@ -120,24 +95,6 @@ def test_polygon_gt_upload(dataset):
12095
)
12196

12297

123-
def test_cuboid_gt_upload(dataset_3d):
124-
annotation = CuboidAnnotation.from_json(TEST_CUBOID_ANNOTATIONS[0])
125-
response = dataset_3d.annotate(annotations=[annotation])
126-
127-
assert response["dataset_id"] == dataset_3d.id
128-
assert response["annotations_processed"] == 1
129-
assert response["annotations_ignored"] == 0
130-
131-
response = dataset_3d.refloc(annotation.reference_id)["annotations"][
132-
"cuboid"
133-
]
134-
assert len(response) == 1
135-
response_annotation = response[0]
136-
assert_cuboid_annotation_matches_dict(
137-
response_annotation, TEST_CUBOID_ANNOTATIONS[0]
138-
)
139-
140-
14198
def test_single_semseg_gt_upload(dataset):
14299
annotation = SegmentationAnnotation.from_json(
143100
TEST_SEGMENTATION_ANNOTATIONS[0]

tests/test_scene.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import pytest
2+
3+
from .helpers import (
4+
TEST_DATASET_3D_NAME,
5+
TEST_CUBOID_ANNOTATIONS,
6+
TEST_LIDAR_FRAMES,
7+
assert_cuboid_annotation_matches_dict,
8+
)
9+
10+
from nucleus import (
11+
CuboidAnnotation,
12+
)
13+
14+
15+
@pytest.fixture()
16+
def dataset(CLIENT):
17+
ds = CLIENT.create_dataset(TEST_DATASET_3D_NAME)
18+
yield ds
19+
20+
response = CLIENT.delete_dataset(ds.id)
21+
assert response == {"message": "Beginning dataset deletion..."}
22+
23+
24+
@pytest.mark.integration
25+
def test_scene_upload_sync(dataset):
26+
payload = TEST_LIDAR_FRAMES
27+
response = dataset.upload_scene(payload)
28+
29+
assert response["dataset_id"] == dataset.id
30+
assert response["new_items"] == 1
31+
assert response["updated_items"] == 0
32+
assert response["ignored_items"] == 0
33+
34+
TEST_CUBOID_ANNOTATIONS[0]["dataset_item_id"] = dataset.items[0].item_id
35+
annotation = CuboidAnnotation.from_json(TEST_CUBOID_ANNOTATIONS[0])
36+
response = dataset.annotate(annotations=[annotation])
37+
38+
assert response["dataset_id"] == dataset.id
39+
assert response["annotations_processed"] == 1
40+
assert response["annotations_ignored"] == 0
41+
42+
response = dataset.loc(annotation.item_id)["annotations"]["cuboid"]
43+
assert len(response) == 1
44+
response_annotation = response[0]
45+
assert_cuboid_annotation_matches_dict(
46+
response_annotation, TEST_CUBOID_ANNOTATIONS[0]
47+
)

0 commit comments

Comments
 (0)