perf(data): bound lidar readers and lab session loading
This commit is contained in:
@@ -113,6 +113,17 @@ class E10LidarFieldSource:
|
||||
"""Strict reader for the immutable, intensity-free RAVNOVES00 E10 pack."""
|
||||
|
||||
def __init__(self, root: Path) -> None:
|
||||
self._open(root, verify_content=True)
|
||||
|
||||
@classmethod
|
||||
def _restore_validated_generation(cls, root: Path) -> E10LidarFieldSource:
|
||||
"""Open a generation already admitted by the host validation cache."""
|
||||
|
||||
instance = cls.__new__(cls)
|
||||
instance._open(root, verify_content=False)
|
||||
return instance
|
||||
|
||||
def _open(self, root: Path, *, verify_content: bool) -> None:
|
||||
candidate = root.expanduser().absolute()
|
||||
if candidate.is_symlink():
|
||||
raise LidarGroundError("E10 LiDAR source cannot be a symlink")
|
||||
@@ -140,12 +151,16 @@ class E10LidarFieldSource:
|
||||
arrays_path.is_symlink()
|
||||
or not arrays_path.is_file()
|
||||
or arrays_path.stat().st_size != artifact.get("byte_length")
|
||||
or _sha256(arrays_path) != artifact.get("sha256")
|
||||
or (
|
||||
verify_content
|
||||
and _sha256(arrays_path) != artifact.get("sha256")
|
||||
)
|
||||
):
|
||||
raise LidarGroundError("E10 LiDAR source artifact is invalid")
|
||||
self.arrays = np.load(arrays_path, allow_pickle=False)
|
||||
try:
|
||||
self._validate_arrays()
|
||||
if verify_content:
|
||||
self._validate_arrays()
|
||||
except BaseException:
|
||||
self.close()
|
||||
raise
|
||||
|
||||
@@ -224,6 +224,17 @@ class K1LocalSurfaceV1:
|
||||
"""Strict reader for source-aligned, passive K1 local-surface evidence."""
|
||||
|
||||
def __init__(self, root: Path) -> None:
|
||||
self._open(root, verify_content=True)
|
||||
|
||||
@classmethod
|
||||
def _restore_validated_generation(cls, root: Path) -> K1LocalSurfaceV1:
|
||||
"""Open a generation already admitted by the host validation cache."""
|
||||
|
||||
instance = cls.__new__(cls)
|
||||
instance._open(root, verify_content=False)
|
||||
return instance
|
||||
|
||||
def _open(self, root: Path, *, verify_content: bool) -> None:
|
||||
candidate = root.expanduser().absolute()
|
||||
if candidate.is_symlink():
|
||||
raise LidarGroundError("K1 local-surface artifact cannot be a symlink")
|
||||
@@ -243,11 +254,18 @@ class K1LocalSurfaceV1:
|
||||
or self.manifest.get("model_id") != self.root.name
|
||||
):
|
||||
raise LidarGroundError("K1 local-surface identity is invalid")
|
||||
artifacts = _validate_artifacts(self.root, self.manifest.get("artifacts"))
|
||||
artifacts = _validate_artifacts(
|
||||
self.root,
|
||||
self.manifest.get("artifacts"),
|
||||
verify_digests=verify_content,
|
||||
)
|
||||
self.arrays = np.load(artifacts["local-surface"], allow_pickle=False)
|
||||
self.report = _read_json(artifacts["local-surface-report"])
|
||||
try:
|
||||
self._validate()
|
||||
if verify_content:
|
||||
self._validate()
|
||||
else:
|
||||
self._restore_capabilities()
|
||||
except BaseException:
|
||||
self.close()
|
||||
raise
|
||||
@@ -256,6 +274,34 @@ class K1LocalSurfaceV1:
|
||||
def close(self) -> None:
|
||||
self.arrays.close()
|
||||
|
||||
def _restore_capabilities(self) -> None:
|
||||
"""Restore derived reader flags without touching large array payloads."""
|
||||
|
||||
files = set(self.arrays.files)
|
||||
qualification = {
|
||||
"prediction_available",
|
||||
"prediction_cell_count",
|
||||
"prediction_residual_p50_m",
|
||||
"prediction_residual_p95_m",
|
||||
"prediction_inlier_fraction",
|
||||
"height_delta_m",
|
||||
"slope_delta_deg",
|
||||
"roughness_delta_m",
|
||||
"temporal_compared",
|
||||
"temporal_jump",
|
||||
"step_candidate_cell_count",
|
||||
"step_candidate_point_count",
|
||||
"point_step_candidate",
|
||||
}
|
||||
prediction_evidence = {
|
||||
"prediction_prior_plane_coefficients_map",
|
||||
"prediction_cell_offsets",
|
||||
"prediction_cell_points_map",
|
||||
"prediction_cell_signed_residual_m",
|
||||
}
|
||||
self.has_temporal_qualification = qualification <= files
|
||||
self.has_prediction_evidence = prediction_evidence <= files
|
||||
|
||||
def _validate(self) -> None:
|
||||
frame_count = _nonnegative_int(self.identity.get("frame_count"), "frame count")
|
||||
point_count = _nonnegative_int(self.identity.get("point_count"), "point count")
|
||||
@@ -835,21 +881,30 @@ class K1LocalSurfaceV1:
|
||||
height_threshold = float(criteria["surface_height_jump_m"])
|
||||
slope_threshold = float(criteria["surface_slope_jump_deg"])
|
||||
roughness_threshold = float(criteria["surface_roughness_jump_m"])
|
||||
prediction_available_values = self.arrays["prediction_available"]
|
||||
prediction_p50_values = self.arrays["prediction_residual_p50_m"]
|
||||
prediction_p95_values = self.arrays["prediction_residual_p95_m"]
|
||||
prediction_inlier_values = self.arrays["prediction_inlier_fraction"]
|
||||
temporal_compared_values = self.arrays["temporal_compared"]
|
||||
height_delta_values = self.arrays["height_delta_m"]
|
||||
slope_delta_values = self.arrays["slope_delta_deg"]
|
||||
roughness_delta_values = self.arrays["roughness_delta_m"]
|
||||
sensor_height_values = self.arrays["sensor_height_m"]
|
||||
slope_values = self.arrays["slope_deg"]
|
||||
roughness_values = self.arrays["roughness_m"]
|
||||
confidence_values = self.arrays["confidence"]
|
||||
step_point_values = self.arrays["step_candidate_point_count"]
|
||||
source_frame_indices = source.arrays["source_frame_indices"]
|
||||
session_seconds = source.arrays["session_seconds"]
|
||||
chronological: list[dict[str, object]] = []
|
||||
last_review_frame: int | None = None
|
||||
episode_index = 0
|
||||
for frame_index in range(source.frame_count):
|
||||
reasons: list[str] = []
|
||||
ratios: list[float] = []
|
||||
prediction_available = bool(
|
||||
self.arrays["prediction_available"][frame_index]
|
||||
)
|
||||
prediction_p95 = float(
|
||||
self.arrays["prediction_residual_p95_m"][frame_index]
|
||||
)
|
||||
prediction_inlier = float(
|
||||
self.arrays["prediction_inlier_fraction"][frame_index]
|
||||
)
|
||||
prediction_available = bool(prediction_available_values[frame_index])
|
||||
prediction_p95 = float(prediction_p95_values[frame_index])
|
||||
prediction_inlier = float(prediction_inlier_values[frame_index])
|
||||
if prediction_available and prediction_p95 >= tail_threshold:
|
||||
reasons.append("prediction-tail")
|
||||
ratios.append(prediction_p95 / tail_threshold)
|
||||
@@ -857,10 +912,10 @@ class K1LocalSurfaceV1:
|
||||
reasons.append("prediction-inlier-drop")
|
||||
ratios.append((1.0 - prediction_inlier) / (1.0 - inlier_floor))
|
||||
|
||||
temporal_compared = bool(self.arrays["temporal_compared"][frame_index])
|
||||
height_delta = float(self.arrays["height_delta_m"][frame_index])
|
||||
slope_delta = float(self.arrays["slope_delta_deg"][frame_index])
|
||||
roughness_delta = float(self.arrays["roughness_delta_m"][frame_index])
|
||||
temporal_compared = bool(temporal_compared_values[frame_index])
|
||||
height_delta = float(height_delta_values[frame_index])
|
||||
slope_delta = float(slope_delta_values[frame_index])
|
||||
roughness_delta = float(roughness_delta_values[frame_index])
|
||||
if temporal_compared and height_delta >= height_threshold:
|
||||
reasons.append("surface-height-jump")
|
||||
ratios.append(height_delta / height_threshold)
|
||||
@@ -882,12 +937,8 @@ class K1LocalSurfaceV1:
|
||||
{
|
||||
"rank": 0,
|
||||
"frame_index": frame_index,
|
||||
"source_frame_index": int(
|
||||
source.arrays["source_frame_indices"][frame_index]
|
||||
),
|
||||
"session_seconds": float(
|
||||
source.arrays["session_seconds"][frame_index]
|
||||
),
|
||||
"source_frame_index": int(source_frame_indices[frame_index]),
|
||||
"session_seconds": float(session_seconds[frame_index]),
|
||||
"episode_id": f"episode-{episode_index:02d}",
|
||||
"attention": (
|
||||
"high"
|
||||
@@ -898,9 +949,7 @@ class K1LocalSurfaceV1:
|
||||
"reasons": reasons,
|
||||
"prediction": {
|
||||
"available": prediction_available,
|
||||
"residual_p50_m": float(
|
||||
self.arrays["prediction_residual_p50_m"][frame_index]
|
||||
),
|
||||
"residual_p50_m": float(prediction_p50_values[frame_index]),
|
||||
"residual_p95_m": prediction_p95,
|
||||
"inlier_fraction": prediction_inlier,
|
||||
},
|
||||
@@ -911,20 +960,12 @@ class K1LocalSurfaceV1:
|
||||
"roughness_delta_m": roughness_delta,
|
||||
},
|
||||
"surface": {
|
||||
"sensor_height_m": float(
|
||||
self.arrays["sensor_height_m"][frame_index]
|
||||
),
|
||||
"slope_deg": float(self.arrays["slope_deg"][frame_index]),
|
||||
"roughness_m": float(
|
||||
self.arrays["roughness_m"][frame_index]
|
||||
),
|
||||
"confidence": float(
|
||||
self.arrays["confidence"][frame_index]
|
||||
),
|
||||
"sensor_height_m": float(sensor_height_values[frame_index]),
|
||||
"slope_deg": float(slope_values[frame_index]),
|
||||
"roughness_m": float(roughness_values[frame_index]),
|
||||
"confidence": float(confidence_values[frame_index]),
|
||||
},
|
||||
"step_candidate_point_count": int(
|
||||
self.arrays["step_candidate_point_count"][frame_index]
|
||||
),
|
||||
"step_candidate_point_count": int(step_point_values[frame_index]),
|
||||
}
|
||||
)
|
||||
items = sorted(
|
||||
@@ -2025,7 +2066,12 @@ def _logical_sha256(arrays: Mapping[str, npt.NDArray[Any]]) -> str:
|
||||
return digest.hexdigest()
|
||||
|
||||
|
||||
def _validate_artifacts(root: Path, value: object) -> dict[str, Path]:
|
||||
def _validate_artifacts(
|
||||
root: Path,
|
||||
value: object,
|
||||
*,
|
||||
verify_digests: bool = True,
|
||||
) -> dict[str, Path]:
|
||||
artifacts = _list(value, "K1 local-surface artifacts")
|
||||
resolved: dict[str, Path] = {}
|
||||
for value in artifacts:
|
||||
@@ -2048,7 +2094,7 @@ def _validate_artifacts(root: Path, value: object) -> dict[str, Path]:
|
||||
path.is_symlink()
|
||||
or not path.is_file()
|
||||
or path.stat().st_size != item["byte_length"]
|
||||
or _sha256(path) != item["sha256"]
|
||||
or (verify_digests and _sha256(path) != item["sha256"])
|
||||
):
|
||||
raise LidarGroundError("K1 local-surface artifact is invalid")
|
||||
resolved[role] = path
|
||||
|
||||
Reference in New Issue
Block a user