feat(perception): mine native fisheye risk cases
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib.util
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
REPOSITORY_ROOT = Path(__file__).resolve().parents[1]
|
||||
RUNNER_PATH = (
|
||||
REPOSITORY_ROOT / "experiments" / "perception" / "run_m48q_native_risk_case_mining_worker.py"
|
||||
)
|
||||
SPEC = importlib.util.spec_from_file_location("m48q_case_mining", RUNNER_PATH)
|
||||
assert SPEC is not None and SPEC.loader is not None
|
||||
MODULE = importlib.util.module_from_spec(SPEC)
|
||||
sys.modules[SPEC.name] = MODULE
|
||||
SPEC.loader.exec_module(MODULE)
|
||||
|
||||
|
||||
def candidate(sequence: int, *buckets: str):
|
||||
return MODULE.FrameCandidate(
|
||||
sequence=sequence,
|
||||
frame_id=f"frame-{sequence:06d}",
|
||||
evidence_time_ns=sequence * 1_000_000,
|
||||
proposals=(),
|
||||
native_count=0,
|
||||
legacy_count=0,
|
||||
matched_count=0,
|
||||
buckets=frozenset(buckets),
|
||||
)
|
||||
|
||||
|
||||
def test_selection_is_deterministic_balanced_and_separated() -> None:
|
||||
candidates = [
|
||||
candidate(sequence, "person" if sequence % 2 == 0 else "vehicle")
|
||||
for sequence in range(0, 400, 5)
|
||||
]
|
||||
quotas = {"person": 3, "vehicle": 3}
|
||||
|
||||
first = MODULE.select_cases(
|
||||
candidates,
|
||||
bucket_quotas=quotas,
|
||||
minimum_sequence_separation=10,
|
||||
)
|
||||
second = MODULE.select_cases(
|
||||
candidates,
|
||||
bucket_quotas=quotas,
|
||||
minimum_sequence_separation=10,
|
||||
)
|
||||
|
||||
assert [item.sequence for item in first] == [item.sequence for item in second]
|
||||
assert len(first) == 6
|
||||
assert all(
|
||||
abs(left.sequence - right.sequence) >= 10
|
||||
for index, left in enumerate(first)
|
||||
for right in first[index + 1 :]
|
||||
)
|
||||
|
||||
|
||||
def test_selection_refuses_missing_bucket_coverage() -> None:
|
||||
with pytest.raises(MODULE.M48QCaseMiningError, match="animal produced 0/1"):
|
||||
MODULE.select_cases(
|
||||
[candidate(0, "person")],
|
||||
bucket_quotas={"animal": 1},
|
||||
minimum_sequence_separation=1,
|
||||
)
|
||||
|
||||
|
||||
def test_profile_freezes_raw_raster_and_false_authority() -> None:
|
||||
import json
|
||||
|
||||
profile = json.loads(
|
||||
(
|
||||
REPOSITORY_ROOT / "config" / "perception" / "m48q-native-risk-case-mining-v1.json"
|
||||
).read_text("utf-8")
|
||||
)
|
||||
|
||||
assert profile["source"] == {
|
||||
"source_id": "RAVNOVES00",
|
||||
"frame_count": 4489,
|
||||
"raster_width": 800,
|
||||
"raster_height": 600,
|
||||
"video_sha256": "cadd1696ff000904eb78633a0a8418104b8024f178b91f3421789021ccb160e8",
|
||||
"geometric_resampling": False,
|
||||
"rectification": False,
|
||||
"warp": False,
|
||||
}
|
||||
assert sum(profile["selection"]["bucket_quotas"].values()) == 24
|
||||
assert profile["scope"]["quality_evaluated"] is False
|
||||
assert profile["authority"] == MODULE.FALSE_AUTHORITY
|
||||
Reference in New Issue
Block a user