tests/test_rgbd_volume_abstention.py
"""V13 abstention: the fallback rule, the preregistered branches and the lock guards."""
import importlib.util
from pathlib import Path
import numpy as np
import pytest
SCRIPT = Path(__file__).resolve().parents[1] / "scripts" / "evaluate_rgbd_volume_abstention.py"
spec = importlib.util.spec_from_file_location("evaluate_rgbd_volume_abstention", SCRIPT)
v13 = importlib.util.module_from_spec(spec)
spec.loader.exec_module(v13)
def test_protocol_constants_are_frozen():
assert v13.THRESHOLD == 0.5 and v13.DESCRIPTIVE_THRESHOLDS == (0.3, 0.7, 0.9)
assert v13.PRIMARY == "EVAL_FAR" and v13.COHORTS["EVAL_FAR"][1:] == ("far_query", "EVAL_FAR")
assert v13.CONTRASTS["ABSTAIN_GAIN"] == ("HFILL8", "ALL", "AHFILL8", "ALL")
assert v13.CONTRASTS["HARMONIC_VS_AHFILL8"] == ("REPROJ_HARMONIC", "ALL", "AHFILL8", "ALL")
def test_abstain_takes_harmonic_on_near_and_low_opacity_far_pixels():
near = np.array([[True, False, False, False]])
opacity = np.array([[0.0, 0.2, 0.5, 0.9]])
out = v13.abstain(near, opacity, np.full((1, 4), 1.0), np.full((1, 4), 2.0), 0.5)
assert out.tolist() == [[1.0, 1.0, 2.0, 2.0]]
def rows(levels, scenes=20):
out = []
for s in range(scenes):
for method, level in levels.items():
for seed in (0,) if method.startswith("REPROJ") else (1, 2, 3):
for role in ("A", "B"):
value = level + 0.001 * (s % 5)
out.append(
{
"cohort": "EVAL_FAR",
"scene_id": f"s{s:02d}",
"role": role,
"query_id": 32,
"method": method,
"seed": seed,
**{f"absrel_{region}": value for region in v13.REGIONS},
}
)
return out
FLAGS = [
{
"cohort": "EVAL_FAR",
"scene_id": f"s{s:02d}",
"surface_in_volume": 0.5,
"far_fraction": 0.4,
"flagged_share_of_far": 0.3,
"flagged": 3.0,
"flagged_outside": 2.0,
"far_outside": 4.0,
}
for s in range(20)
]
def test_branches_follow_the_two_primary_checks():
a = v13.analyze_rows(rows({"HFILL8": 0.30, "AHFILL8": 0.25, "REPROJ_HARMONIC": 0.28}), FLAGS)
assert (a["ABSTAIN_STATUS"], a["HARMONIC_LABEL"], a["INTERPRETATION_BRANCH"]) == (
"SUPPORTED",
"ABOVE",
"A",
)
coverage = a["cohorts"]["EVAL_FAR"]["coverage"]
assert coverage["precision_outside_volume"] == pytest.approx(2 / 3)
assert coverage["recall_outside_volume"] == pytest.approx(0.5)
b = v13.analyze_rows(rows({"HFILL8": 0.25, "AHFILL8": 0.25, "REPROJ_HARMONIC": 0.28}), FLAGS)
assert (b["ABSTAIN_STATUS"], b["HARMONIC_LABEL"], b["INTERPRETATION_BRANCH"]) == (
"NOT_ESTABLISHED",
"ABOVE",
"B",
)
c = v13.analyze_rows(rows({"HFILL8": 0.30, "AHFILL8": 0.30, "REPROJ_HARMONIC": 0.28}), FLAGS)
assert (c["HARMONIC_LABEL"], c["INTERPRETATION_BRANCH"]) == ("BELOW", "C")
def test_lock_needs_the_exact_directory_a_protocol_and_no_prediction(tmp_path):
with pytest.raises(PermissionError):
v13.lock(tmp_path / "EXP-SOMETHING-ELSE")
root = tmp_path / v13.EXPERIMENT
root.mkdir()
with pytest.raises(PermissionError):
v13.lock(root)
(root / "PROTOCOL.md").write_text("protocol")
(root / "raw").mkdir()
with pytest.raises(PermissionError):
v13.lock(root)
assert not (root / "lock.json").exists()