x4d-devkit 0.46.0rc3__tar.gz → 0.47.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {x4d_devkit-0.46.0rc3/x4d_devkit.egg-info → x4d_devkit-0.47.0}/PKG-INFO +1 -1
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/pyproject.toml +1 -1
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_clean_basemap.py +74 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_sdk_api.py +1 -1
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/clean_basemap.py +64 -5
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/client/reconstruction.py +9 -1
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0/x4d_devkit.egg-info}/PKG-INFO +1 -1
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/LICENSE +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/README.md +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/setup.cfg +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_annotation_contract.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_annotation_reference.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_assets_client.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_boundary.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_box.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_build_info.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_clean_basemap_client.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_cli_auth.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_client_json_contract.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_client_projects.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_clip_archives.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_contract_validation.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_coordinate_frames.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_current_state.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_current_state_identity_consumers_example.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_dataset_contract.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_dataset_identity.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_detection_eval.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_evaluate.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_export_bundle.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_image_review.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_inference_input.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_inference_schemas.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_inference_service.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_label_schemas.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_lidar_materialization.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_loader.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_matching.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_metrics.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_models.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_platform_pose.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_preannotation_client.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_reconstruction_client.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_release_gate.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_roadmark_preview.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_semantic_scene_authoring.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_semantic_scene_client.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_semantic_scene_contract.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_semantic_scene_independent.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_semantic_scene_native_clip.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_source_attributes.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_time_contract.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_token.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_tracking_eval.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_training_identity.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_transform.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_transform_chain.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_validation.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_vector_map.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_vector_map_geometry.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_vector_map_session.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_work_session.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_work_session_validation_reuse.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/__init__.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/annotation_contract.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/annotation_reference.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/build_info.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/cli.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/client/__init__.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/client/_origin.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/client/annotation_reference.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/client/assets.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/client/bags.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/client/capabilities.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/client/checkpoints.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/client/clean_basemap.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/client/client.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/client/clip_work_sessions.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/client/clips.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/client/dataset_identity.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/client/image_review.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/client/label_schemas.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/client/preannotation.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/client/projects.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/client/semantic_scene.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/client/semantic_scene_authoring.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/client/services.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/client/test_sets.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/consumer_identity.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/coordinate_contract.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/core/__init__.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/core/loader.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/core/models.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/core/token.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/core/transform.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/current_state.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/dataset_contract.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/dataset_identity.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/eval/__init__.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/eval/api.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/eval/box.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/eval/detection.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/eval/matching.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/eval/metrics.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/eval/tracking.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/export_bundle.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/image_review.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/inference/__init__.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/inference/input.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/inference/models.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/inference/schemas.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/inference/service.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/inference/tasks.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/json_contract.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/label_schema.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/lidar_materialization.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/materialize.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/roadmark_preview.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/semantic_scene_authoring.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/semantic_scene_contract.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/time_contract.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/training_identity.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/validation/__init__.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/validation/contract.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/validation/platform_pose.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/validation/report.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/validation/validator.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/vector_map.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/vector_map_geometry.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit/work_session.py +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit.egg-info/SOURCES.txt +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit.egg-info/dependency_links.txt +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit.egg-info/entry_points.txt +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit.egg-info/requires.txt +0 -0
- {x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/x4d_devkit.egg-info/top_level.txt +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "x4d-devkit"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.47.0"
|
|
8
8
|
description = "Official X-4D external SDK and CLI for datasets, platform APIs, training bridges, and automation"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "Apache-2.0"
|
|
@@ -54,6 +54,7 @@ def fixture():
|
|
|
54
54
|
raw_point_ordinals=[0, 1, 2],
|
|
55
55
|
timestamps_ns=[100, 100, 100],
|
|
56
56
|
decisions=decisions[:3],
|
|
57
|
+
intensities=[2.5, 19.0, 240.0],
|
|
57
58
|
)
|
|
58
59
|
profile = {
|
|
59
60
|
"algorithm": {"id": "clean_static_basemap", "version": "0.6.0"},
|
|
@@ -102,6 +103,7 @@ def fixture():
|
|
|
102
103
|
"bounds": bounds,
|
|
103
104
|
"geometry": descriptor,
|
|
104
105
|
"mapping": mapping.descriptor("mapping"),
|
|
106
|
+
"intensity_range": [2.5, 240.0],
|
|
105
107
|
}
|
|
106
108
|
],
|
|
107
109
|
"diagnostics": {
|
|
@@ -139,6 +141,9 @@ def validate(manifest, assets):
|
|
|
139
141
|
manifest,
|
|
140
142
|
read_asset=assets.__getitem__,
|
|
141
143
|
observation_to_world=lambda sweep, ordinals, times: original[ordinals],
|
|
144
|
+
observation_intensity=lambda sweep, ordinals, times: np.asarray(
|
|
145
|
+
[2.5, 19.0, 240.0], dtype=np.float32
|
|
146
|
+
)[ordinals],
|
|
142
147
|
)
|
|
143
148
|
|
|
144
149
|
|
|
@@ -155,6 +160,7 @@ def remap(manifest, assets, **overrides):
|
|
|
155
160
|
"raw_point_ordinals": mapping["raw_point_ordinal"],
|
|
156
161
|
"timestamps_ns": mapping["timestamp_ns"],
|
|
157
162
|
"decisions": mapping["decision"],
|
|
163
|
+
"intensities": mapping["intensity"],
|
|
158
164
|
}
|
|
159
165
|
encoded = encode_clean_basemap_mapping(
|
|
160
166
|
geometry_raw_sha256=chunk["geometry"]["raw_sha256"], **(arguments | overrides)
|
|
@@ -190,6 +196,67 @@ def test_complete_scene_and_exact_original_observation_roundtrip():
|
|
|
190
196
|
parsed.data["profile"]["voxel_size_m"] = 1
|
|
191
197
|
|
|
192
198
|
|
|
199
|
+
def test_intensity_is_original_float32_and_does_not_change_geometry():
|
|
200
|
+
manifest, assets, _ = fixture()
|
|
201
|
+
before = copy.deepcopy(manifest["scene_source"])
|
|
202
|
+
assert MAPPING_DTYPE.itemsize == 24
|
|
203
|
+
remap(manifest, assets, intensities=[2.5, 20.0, 240.0])
|
|
204
|
+
assert manifest["scene_source"] == before
|
|
205
|
+
with pytest.raises(ValueError, match="intensity differs from its original"):
|
|
206
|
+
validate(manifest, assets)
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
@pytest.mark.parametrize(
|
|
210
|
+
"values",
|
|
211
|
+
[
|
|
212
|
+
[1, 2],
|
|
213
|
+
[True, False, True],
|
|
214
|
+
[1, float("nan"), 3],
|
|
215
|
+
[1, float("inf"), 3],
|
|
216
|
+
[1, 1e100, 3],
|
|
217
|
+
],
|
|
218
|
+
)
|
|
219
|
+
def test_invalid_intensity_cannot_be_encoded(values):
|
|
220
|
+
manifest, assets, _ = fixture()
|
|
221
|
+
with pytest.raises(ValueError, match="intensit"):
|
|
222
|
+
remap(manifest, assets, intensities=values)
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def test_intensity_range_cannot_hide_wrong_values():
|
|
226
|
+
manifest, assets, _ = fixture()
|
|
227
|
+
manifest["chunks"][0]["intensity_range"] = [0.0, 255.0]
|
|
228
|
+
manifest["basemap_revision"] = compute_clean_basemap_revision(manifest)
|
|
229
|
+
with pytest.raises(ValueError, match="intensity range"):
|
|
230
|
+
validate(manifest, assets)
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def test_old_manifest_and_mapping_are_rejected():
|
|
234
|
+
manifest, assets, _ = fixture()
|
|
235
|
+
manifest["contract_version"] = "x4d-clean-static-basemap-v4"
|
|
236
|
+
manifest["basemap_revision"] = compute_clean_basemap_revision(manifest)
|
|
237
|
+
with pytest.raises(ValueError):
|
|
238
|
+
parse_clean_basemap_manifest(manifest)
|
|
239
|
+
chunk = manifest["chunks"][0]
|
|
240
|
+
descriptor = chunk["mapping"]
|
|
241
|
+
raw = bytearray(zstandard.ZstdDecompressor().decompress(assets[descriptor["path"]]))
|
|
242
|
+
raw[:8] = b"X4DCBM2\0"
|
|
243
|
+
payload = zstandard.ZstdCompressor().compress(raw)
|
|
244
|
+
descriptor = dict(
|
|
245
|
+
descriptor,
|
|
246
|
+
path=f"generated/reconstruction/clean_basemap/mapping/{sha256_bytes(payload)[7:]}.zst",
|
|
247
|
+
sha256=sha256_bytes(payload),
|
|
248
|
+
raw_sha256=sha256_bytes(bytes(raw)),
|
|
249
|
+
size_bytes=len(payload),
|
|
250
|
+
)
|
|
251
|
+
with pytest.raises(ValueError):
|
|
252
|
+
decode_clean_basemap_mapping(
|
|
253
|
+
payload,
|
|
254
|
+
descriptor=descriptor,
|
|
255
|
+
geometry_raw_sha256=chunk["geometry"]["raw_sha256"],
|
|
256
|
+
point_count=chunk["point_count"],
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
|
|
193
260
|
def test_decision_proof_reuse_is_within_one_validation_call(monkeypatch):
|
|
194
261
|
manifest, assets, _ = fixture()
|
|
195
262
|
decoded = []
|
|
@@ -229,6 +296,9 @@ def test_cached_decision_proof_still_checks_every_carrier_read(changed):
|
|
|
229
296
|
manifest,
|
|
230
297
|
read_asset=read_asset,
|
|
231
298
|
observation_to_world=lambda sweep, ordinals, times: original[ordinals],
|
|
299
|
+
observation_intensity=lambda sweep, ordinals, times: np.asarray(
|
|
300
|
+
[2.5, 19.0, 240.0], dtype=np.float32
|
|
301
|
+
)[ordinals],
|
|
232
302
|
)
|
|
233
303
|
|
|
234
304
|
|
|
@@ -319,6 +389,9 @@ def test_original_observation_projection_is_required(kind):
|
|
|
319
389
|
manifest,
|
|
320
390
|
read_asset=assets.__getitem__,
|
|
321
391
|
observation_to_world=lambda *args: result,
|
|
392
|
+
observation_intensity=lambda sweep, ordinals, times: np.asarray(
|
|
393
|
+
[2.5, 19.0, 240.0], dtype=np.float32
|
|
394
|
+
)[ordinals],
|
|
322
395
|
)
|
|
323
396
|
|
|
324
397
|
|
|
@@ -387,6 +460,7 @@ def test_every_byte_in_last_record_obeys_exact_decision_domain(family):
|
|
|
387
460
|
raw_point_ordinals=np.arange(count),
|
|
388
461
|
timestamps_ns=np.full(count, 100),
|
|
389
462
|
decisions=np.full(count, KEEP_GROUND),
|
|
463
|
+
intensities=np.arange(count, dtype=np.float32),
|
|
390
464
|
)
|
|
391
465
|
domain, decode = KEEP_CODES, decode_clean_basemap_mapping
|
|
392
466
|
arguments = dict(geometry_raw_sha256=anchor, point_count=count)
|
|
@@ -11,7 +11,7 @@ from x4d_devkit.eval.matching import MetricData
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def test_package_version_is_current_release():
|
|
14
|
-
assert x4d_devkit.__version__ == "0.
|
|
14
|
+
assert x4d_devkit.__version__ == "0.47.0"
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
def test_loader_exposes_and_enforces_only_current_schema(tmp_path):
|
|
@@ -36,9 +36,9 @@ from x4d_devkit.semantic_scene_contract import (
|
|
|
36
36
|
)
|
|
37
37
|
from x4d_devkit.time_contract import parse_time_ns
|
|
38
38
|
|
|
39
|
-
CLEAN_BASEMAP_CONTRACT_VERSION = "x4d-clean-static-basemap-
|
|
39
|
+
CLEAN_BASEMAP_CONTRACT_VERSION = "x4d-clean-static-basemap-v5"
|
|
40
40
|
CLEAN_BASEMAP_OPERATION = "reconstruction.prepare_clean_static_basemap"
|
|
41
|
-
CLEAN_BASEMAP_MAPPING_FORMAT = "x4d-clean-static-basemap-mapping-
|
|
41
|
+
CLEAN_BASEMAP_MAPPING_FORMAT = "x4d-clean-static-basemap-mapping-v3"
|
|
42
42
|
CLEAN_BASEMAP_DECISION_FORMAT = "x4d-clean-static-basemap-decisions-v3"
|
|
43
43
|
_DECISION_CACHE_BYTES = 128 << 20
|
|
44
44
|
CLEAN_BASEMAP_INPUT_FIELDS = frozenset(
|
|
@@ -55,7 +55,7 @@ DECISION_CODES = frozenset({0, 1, 3, 18, 32, 33, 34})
|
|
|
55
55
|
KEEP_CODES = frozenset({0, 1, 3})
|
|
56
56
|
_HASH = re.compile(r"^sha256:[0-9a-f]{64}$")
|
|
57
57
|
_HEADER = struct.Struct("<8sI32s")
|
|
58
|
-
_MAPPING_MAGIC = b"
|
|
58
|
+
_MAPPING_MAGIC = b"X4DCBM3\0"
|
|
59
59
|
_DECISION_MAGIC = b"X4DCBD3\0"
|
|
60
60
|
MAPPING_DTYPE = np.dtype(
|
|
61
61
|
[
|
|
@@ -63,7 +63,8 @@ MAPPING_DTYPE = np.dtype(
|
|
|
63
63
|
("raw_point_ordinal", "<u4"),
|
|
64
64
|
("timestamp_ns", "<u8"),
|
|
65
65
|
("decision", "u1"),
|
|
66
|
-
("
|
|
66
|
+
("intensity", "<f4"),
|
|
67
|
+
("reserved", "u1", (3,)),
|
|
67
68
|
]
|
|
68
69
|
)
|
|
69
70
|
_MAX_U32 = (1 << 32) - 1
|
|
@@ -108,6 +109,21 @@ def _bounds(value: Any, path: str) -> None:
|
|
|
108
109
|
raise ValueError(f"{path} is inverted")
|
|
109
110
|
|
|
110
111
|
|
|
112
|
+
def _intensity_range(value: Any, path: str) -> None:
|
|
113
|
+
if (
|
|
114
|
+
not isinstance(value, list)
|
|
115
|
+
or len(value) != 2
|
|
116
|
+
or any(
|
|
117
|
+
isinstance(v, bool)
|
|
118
|
+
or not isinstance(v, (int, float))
|
|
119
|
+
or not math.isfinite(v)
|
|
120
|
+
for v in value
|
|
121
|
+
)
|
|
122
|
+
or value[0] > value[1]
|
|
123
|
+
):
|
|
124
|
+
raise ValueError(f"{path} must contain finite ordered intensity bounds")
|
|
125
|
+
|
|
126
|
+
|
|
111
127
|
def _freeze(value: Any) -> Any:
|
|
112
128
|
if isinstance(value, Mapping):
|
|
113
129
|
return MappingProxyType({k: _freeze(v) for k, v in value.items()})
|
|
@@ -349,7 +365,16 @@ def parse_clean_basemap_manifest(
|
|
|
349
365
|
for i, chunk in enumerate(chunks):
|
|
350
366
|
path = f"chunks[{i}]"
|
|
351
367
|
_object(
|
|
352
|
-
chunk,
|
|
368
|
+
chunk,
|
|
369
|
+
{
|
|
370
|
+
"ordinal",
|
|
371
|
+
"point_count",
|
|
372
|
+
"bounds",
|
|
373
|
+
"intensity_range",
|
|
374
|
+
"geometry",
|
|
375
|
+
"mapping",
|
|
376
|
+
},
|
|
377
|
+
path,
|
|
353
378
|
)
|
|
354
379
|
if chunk["ordinal"] != i or type(chunk["ordinal"]) is not int:
|
|
355
380
|
raise ValueError("chunk ordinals must be contiguous in canonical order")
|
|
@@ -360,6 +385,7 @@ def parse_clean_basemap_manifest(
|
|
|
360
385
|
f"{path}.point_count",
|
|
361
386
|
)
|
|
362
387
|
_bounds(chunk["bounds"], f"{path}.bounds")
|
|
388
|
+
_intensity_range(chunk["intensity_range"], f"{path}.intensity_range")
|
|
363
389
|
bounds.append(chunk["bounds"])
|
|
364
390
|
_descriptor(chunk["geometry"], "geometry", f"{path}.geometry")
|
|
365
391
|
_descriptor(chunk["mapping"], "mapping", f"{path}.mapping")
|
|
@@ -467,6 +493,7 @@ def encode_clean_basemap_mapping(
|
|
|
467
493
|
raw_point_ordinals: Any,
|
|
468
494
|
timestamps_ns: Any,
|
|
469
495
|
decisions: Any,
|
|
496
|
+
intensities: Any,
|
|
470
497
|
) -> CleanBasemapPayload:
|
|
471
498
|
vectors = {
|
|
472
499
|
"sweep_index": _vector(sweep_indices, _MAX_U32, "sweep_indices"),
|
|
@@ -487,6 +514,19 @@ def encode_clean_basemap_mapping(
|
|
|
487
514
|
records = np.zeros(count, dtype=MAPPING_DTYPE)
|
|
488
515
|
for key, vector in vectors.items():
|
|
489
516
|
records[key] = vector
|
|
517
|
+
intensity = np.asarray(intensities)
|
|
518
|
+
if (
|
|
519
|
+
intensity.shape != (count,)
|
|
520
|
+
or intensity.dtype.kind not in "iuf"
|
|
521
|
+
or not np.isfinite(intensity).all()
|
|
522
|
+
):
|
|
523
|
+
raise ValueError(
|
|
524
|
+
"intensities must contain one finite numeric value per geometry point"
|
|
525
|
+
)
|
|
526
|
+
with np.errstate(over="ignore", invalid="ignore"):
|
|
527
|
+
records["intensity"] = intensity
|
|
528
|
+
if not np.isfinite(records["intensity"]).all():
|
|
529
|
+
raise ValueError("intensities must be representable as finite float32")
|
|
490
530
|
return _encode(_MAPPING_MAGIC, geometry_raw_sha256, records)
|
|
491
531
|
|
|
492
532
|
|
|
@@ -511,6 +551,7 @@ def decode_clean_basemap_mapping(
|
|
|
511
551
|
np.any(records["reserved"] != 0)
|
|
512
552
|
or np.any(~np.isin(records["decision"], tuple(KEEP_CODES)))
|
|
513
553
|
or np.any(records["timestamp_ns"] > _MAX_I64)
|
|
554
|
+
or not np.isfinite(records["intensity"]).all()
|
|
514
555
|
):
|
|
515
556
|
raise ValueError(
|
|
516
557
|
"mapping records are noncanonical or contain removed observations"
|
|
@@ -604,6 +645,9 @@ def validate_clean_basemap_resource(
|
|
|
604
645
|
observation_to_world: Callable[
|
|
605
646
|
[Mapping[str, Any], np.ndarray, np.ndarray], np.ndarray
|
|
606
647
|
],
|
|
648
|
+
observation_intensity: Callable[
|
|
649
|
+
[Mapping[str, Any], np.ndarray, np.ndarray], np.ndarray
|
|
650
|
+
],
|
|
607
651
|
) -> CleanBasemapManifest:
|
|
608
652
|
"""Verify exact original observations and byte-exact complete scene correspondence."""
|
|
609
653
|
parsed = parse_clean_basemap_manifest(manifest)
|
|
@@ -681,6 +725,11 @@ def validate_clean_basemap_resource(
|
|
|
681
725
|
geometry_raw_sha256=descriptor["raw_sha256"],
|
|
682
726
|
point_count=chunk["point_count"],
|
|
683
727
|
)
|
|
728
|
+
if [
|
|
729
|
+
float(mapping["intensity"].min()),
|
|
730
|
+
float(mapping["intensity"].max()),
|
|
731
|
+
] != chunk["intensity_range"]:
|
|
732
|
+
raise ValueError("basemap intensity range differs from its actual points")
|
|
684
733
|
if np.any(mapping["sweep_index"] >= len(data["sweep_sources"])):
|
|
685
734
|
raise ValueError("mapping source index is outside the pinned source tables")
|
|
686
735
|
for index in np.unique(mapping["sweep_index"]):
|
|
@@ -715,6 +764,16 @@ def validate_clean_basemap_resource(
|
|
|
715
764
|
raise ValueError(
|
|
716
765
|
"basemap geometry differs from its original observations"
|
|
717
766
|
)
|
|
767
|
+
intensity = np.asarray(observation_intensity(sweep, ordinals, times))
|
|
768
|
+
if (
|
|
769
|
+
intensity.shape != ordinals.shape
|
|
770
|
+
or intensity.dtype.kind not in "iuf"
|
|
771
|
+
or not np.isfinite(intensity).all()
|
|
772
|
+
or not np.array_equal(intensity, mapping["intensity"][selected])
|
|
773
|
+
):
|
|
774
|
+
raise ValueError(
|
|
775
|
+
"basemap intensity differs from its original observations"
|
|
776
|
+
)
|
|
718
777
|
return parsed
|
|
719
778
|
|
|
720
779
|
|
|
@@ -307,7 +307,7 @@ class ReconstructionAPI:
|
|
|
307
307
|
"clean basemap chunk ordinal is outside the exact resource"
|
|
308
308
|
)
|
|
309
309
|
chunk = chunks[chunk_ordinal]
|
|
310
|
-
|
|
310
|
+
mapping = decode_clean_basemap_mapping(
|
|
311
311
|
self._client.assets.fetch(
|
|
312
312
|
state.asset_urls[chunk["mapping"]["path"]]
|
|
313
313
|
).content,
|
|
@@ -315,6 +315,14 @@ class ReconstructionAPI:
|
|
|
315
315
|
geometry_raw_sha256=chunk["geometry"]["raw_sha256"],
|
|
316
316
|
point_count=chunk["point_count"],
|
|
317
317
|
)
|
|
318
|
+
if [
|
|
319
|
+
float(mapping["intensity"].min()),
|
|
320
|
+
float(mapping["intensity"].max()),
|
|
321
|
+
] != list(chunk["intensity_range"]):
|
|
322
|
+
raise ValueError(
|
|
323
|
+
"clean basemap intensity range differs from its descriptor"
|
|
324
|
+
)
|
|
325
|
+
return mapping
|
|
318
326
|
|
|
319
327
|
def cancel_clean_basemap_task(
|
|
320
328
|
self, *, project_id: int, task_id: str
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{x4d_devkit-0.46.0rc3 → x4d_devkit-0.47.0}/tests/test_current_state_identity_consumers_example.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|