feat(lab): complete E30 evidence review gate

This commit is contained in:
DCCONSTRUCTIONS
2026-07-27 11:00:32 +03:00
parent a44d7627fd
commit 001d597a89
55 changed files with 15897 additions and 1548 deletions
@@ -0,0 +1,503 @@
#!/usr/bin/env python3
"""Issue an immutable Codex engineering generation for LAB E30.
The decisions in this file are the compact, reproducible encoding of a visual
audit of all 42 camera-backed engineering sheets (486 immutable E30 items).
They are explicitly AI-assisted engineering judgments, not human annotation
and not navigation/safety acceptance.
"""
from __future__ import annotations
import argparse
import json
from pathlib import Path
from typing import Any, Final
import numpy as np
from k1link.compute.e30_engineering_generation import (
E30_ENGINEERING_DECISION_SCHEMA,
build_e30_engineering_generation,
)
SheetKey = tuple[str, int]
# Boxes placed on road/construction barriers, façades, signs, the recording
# rig, or other non-object image structure.
FALSE_POSITIVES: Final[frozenset[SheetKey]] = frozenset(
{
("agree-02.jpg", 2),
("agree-03.jpg", 5),
("agree-05.jpg", 5),
("agree-05.jpg", 6),
("agree-05.jpg", 7),
("agree-05.jpg", 8),
("agree-07.jpg", 4),
("agree-07.jpg", 6),
("agree-07.jpg", 12),
("camera-only-01.jpg", 9),
("camera-only-01.jpg", 10),
# Frame 162: the bus box is on the façade/background; the real truck is
# outside the box and therefore does not rescue this observation.
("camera-only-01.jpg", 4),
("camera-only-03.jpg", 6),
("camera-only-03.jpg", 7),
("camera-only-03.jpg", 8),
("camera-only-04.jpg", 1),
("camera-only-04.jpg", 2),
("camera-only-04.jpg", 3),
("camera-only-05.jpg", 11),
("camera-only-05.jpg", 12),
("camera-only-06.jpg", 1),
("camera-only-06.jpg", 2),
("camera-only-06.jpg", 3),
("camera-only-06.jpg", 4),
("camera-only-08.jpg", 11),
("camera-only-09.jpg", 3),
("camera-only-09.jpg", 4),
("camera-only-10.jpg", 3),
("camera-only-10.jpg", 4),
("unknown-02.jpg", 1),
("unknown-02.jpg", 2),
("unknown-02.jpg", 3),
("unknown-04.jpg", 9),
}
)
SELF_DETECTIONS: Final[frozenset[SheetKey]] = frozenset(
{
("camera-only-01.jpg", 8),
("camera-only-02.jpg", 1),
("camera-only-06.jpg", 10),
("camera-only-07.jpg", 4),
("camera-only-08.jpg", 4),
("camera-only-09.jpg", 7),
("camera-only-09.jpg", 9),
("camera-only-10.jpg", 6),
("geometry-only-01.jpg", 1),
("geometry-only-01.jpg", 2),
}
)
# The broad semantic group remains usable, but the fine detector label does
# not match the visible object (typically car/truck/bus or stroller/motorcycle).
CLASS_MISMATCHES: Final[frozenset[SheetKey]] = frozenset(
{
("agree-01.jpg", 4),
("agree-01.jpg", 5),
("agree-03.jpg", 7),
("agree-03.jpg", 9),
("agree-03.jpg", 11),
("agree-04.jpg", 5),
("agree-05.jpg", 2),
("agree-05.jpg", 4),
("agree-05.jpg", 11),
("agree-06.jpg", 1),
("agree-06.jpg", 2),
("agree-06.jpg", 3),
("agree-06.jpg", 12),
("agree-08.jpg", 3),
("agree-08.jpg", 4),
("agree-08.jpg", 6),
("camera-only-04.jpg", 8),
("camera-only-08.jpg", 12),
}
)
# Class-bearing objects visible in the camera projection but represented by
# E29 only as geometry-only clusters.
MISSED_OBJECTS: Final[frozenset[SheetKey]] = frozenset(
{
("geometry-only-01.jpg", 6),
("geometry-only-01.jpg", 7),
("geometry-only-01.jpg", 8),
("geometry-only-01.jpg", 9),
("geometry-only-01.jpg", 12),
("geometry-only-02.jpg", 11),
("geometry-only-02.jpg", 12),
("geometry-only-03.jpg", 1),
("geometry-only-03.jpg", 9),
("geometry-only-04.jpg", 5),
("geometry-only-05.jpg", 8),
("geometry-only-07.jpg", 4),
("geometry-only-08.jpg", 8),
("geometry-only-08.jpg", 10),
("geometry-only-08.jpg", 11),
("geometry-only-08.jpg", 12),
("geometry-only-10.jpg", 1),
("geometry-only-10.jpg", 7),
("geometry-only-10.jpg", 9),
("geometry-only-10.jpg", 10),
("geometry-only-11.jpg", 7),
}
)
# These two cases remain genuinely ambiguous after the camera-backed audit.
# The three semantic cases from generation v1 are now handled automatically:
# one detector false positive, one camera-only object, and one stale track.
AMBIGUITIES: Final[frozenset[SheetKey]] = frozenset(
{
("geometry-only-07.jpg", 6),
("geometry-only-10.jpg", 11),
}
)
EXCEPTION_REVIEW: Final[dict[SheetKey, dict[str, object]]] = {
("geometry-only-07.jpg", 6): {
"question": "Белый кластер — самостоятельное физическое препятствие?",
"focus": (
"Кадр 2622: проверьте четыре выбранные белые точки. Нужно отличить "
"занятую геометрию реального объекта от поверхности сцены или шума."
),
"effects": {
"object-present": (
"Сохранить кластер как подтверждённую занятую геометрию."
),
"background-or-noise": (
"Исключить кластер из положительной LiDAR-поддержки и учесть "
"как leakage или шум."
),
"insufficient-evidence": (
"Оставить кейс неизвестным и не использовать его для настройки "
"порогов."
),
},
},
("geometry-only-10.jpg", 11): {
"question": "Вертикальный белый кластер занимает реальное препятствие?",
"focus": (
"Кадр 4147: проверьте 31 выбранную белую точку на растительности. "
"Нужно подтвердить физически занятую область либо фон/шум."
),
"effects": {
"object-present": (
"Сохранить кластер как подтверждённую занятую геометрию."
),
"background-or-noise": (
"Исключить кластер из положительной LiDAR-поддержки и учесть "
"как leakage или шум."
),
"insufficient-evidence": (
"Оставить кейс неизвестным и не использовать его для настройки "
"порогов."
),
},
},
}
class IssueGenerationError(RuntimeError):
"""The frozen review inputs do not match the audited sheet set."""
def _read_json(path: Path) -> dict[str, Any]:
value = json.loads(path.read_text(encoding="utf-8"))
if not isinstance(value, dict):
raise IssueGenerationError(f"JSON object required: {path}")
return value
def _read_jsonl(path: Path) -> list[dict[str, Any]]:
values: list[dict[str, Any]] = []
with path.open("r", encoding="utf-8") as stream:
for line in stream:
value = json.loads(line)
if not isinstance(value, dict):
raise IssueGenerationError(f"JSONL object required: {path}")
values.append(value)
return values
def _sheet_bindings(
root: Path,
) -> tuple[dict[str, SheetKey], dict[str, dict[str, object]]]:
manifest = _read_json(root / "manifest.json")
keys_by_item: dict[str, SheetKey] = {}
sheets_by_item: dict[str, dict[str, object]] = {}
for sheet in manifest["sheets"]:
for entry in sheet["entries"]:
item_id = str(entry["item_id"])
keys_by_item[item_id] = (str(sheet["path"]), int(entry["ordinal"]))
sheets_by_item[item_id] = {
"path": sheet["path"],
"sha256": sheet["sha256"],
"ordinal": entry["ordinal"],
}
return keys_by_item, sheets_by_item
def _projected_selected_count(materialization_root: Path, item: dict[str, Any]) -> int:
with np.load(materialization_root / item["artifact"]["path"]) as arrays:
return int(np.count_nonzero(arrays["projected_selected_mask"]))
def _baseline(
*,
item: dict[str, Any],
materialization_root: Path,
) -> dict[str, object]:
stratum = str(item["stratum"])
if stratum == "conflict":
return {
"verdict": "corrected",
"effective_stratum": None,
"detector_assessment": "false-positive",
"projection_assessment": "aligned",
"point_ownership": "surface-or-background",
"cause_code": "detector_error",
"confidence": 0.97,
"note": (
"В рамке находится полосатое дорожное/строительное ограждение, "
"а не транспорт. Проекция согласована с изображением; LiDAR "
"принадлежит поверхности ограждения."
),
}
if stratum == "agree":
return {
"verdict": "confirmed",
"effective_stratum": stratum,
"detector_assessment": "valid",
"projection_assessment": "aligned",
"point_ownership": "object",
"cause_code": None,
"confidence": 0.94,
"note": (
"Камерный объект и занятые LiDAR-точки пространственно "
"согласованы; поддержка принадлежит наблюдаемому объекту."
),
}
if stratum == "camera-only":
return {
"verdict": "confirmed",
"effective_stratum": stratum,
"detector_assessment": "valid",
"projection_assessment": "aligned",
"point_ownership": "insufficient-support",
"cause_code": "sparse_support",
"confidence": 0.82,
"note": (
"Объект читается в камере, но в его рамке недостаточно "
"квалифицированной LiDAR-поддержки; глобальная регистрация "
"проекции визуально согласована."
),
}
if stratum == "unknown":
return {
"verdict": "confirmed",
"effective_stratum": stratum,
"detector_assessment": "valid",
"projection_assessment": "not-assessable",
"point_ownership": "insufficient-evidence",
"cause_code": "time_mismatch",
"confidence": 0.9,
"note": (
"E29 использует удержанный world-track, а не актуальное "
"семантическое наблюдение этого кадра. Неизвестность "
"обусловлена временной свежестью, не геометрическим порогом."
),
}
if stratum == "geometry-only":
projected = _projected_selected_count(materialization_root, item)
return {
"verdict": "confirmed",
"effective_stratum": stratum,
"detector_assessment": "not-applicable",
"projection_assessment": "aligned" if projected else "not-assessable",
"point_ownership": "static-environment",
"cause_code": None,
"confidence": 0.8,
"note": (
"Кластер соответствует статической сцене: фасаду, растительности "
"или иной геометрии без обязательного семантического объекта."
),
}
raise IssueGenerationError(f"unexpected stratum: {stratum}")
def _decision(
*,
item: dict[str, Any],
key: SheetKey,
sheet: dict[str, object],
materialization_root: Path,
) -> dict[str, Any]:
result = _baseline(item=item, materialization_root=materialization_root)
source = str(item["stratum"])
if key in AMBIGUITIES:
result.update(
verdict="insufficient-evidence",
effective_stratum=None,
detector_assessment="insufficient-evidence",
projection_assessment="not-assessable",
point_ownership="insufficient-evidence",
cause_code="unknown",
confidence=0.48,
note=(
"Камерный crop и спроецированная принадлежность не дают "
"устойчиво отделить объект от конструкции/края сцены. "
"Оставлено единственным типом ручного исключения."
),
)
elif key in SELF_DETECTIONS:
result.update(
verdict="corrected",
effective_stratum=None,
detector_assessment=(
"false-positive"
if source != "geometry-only"
else "not-applicable"
),
projection_assessment="aligned",
point_ownership="self",
cause_code="self_points",
confidence=0.96,
note=(
"Выделение принадлежит элементам собственной платформы/оператора "
"в нижней или краевой части кадра, а не внешнему объекту сцены."
),
)
elif source == "conflict" or key in FALSE_POSITIVES:
result.update(
verdict="corrected",
effective_stratum="geometry-only" if source == "agree" else None,
detector_assessment="false-positive",
projection_assessment="aligned",
point_ownership="surface-or-background",
cause_code="detector_error",
confidence=0.95,
note=(
"Детектор поставил объектную рамку на ограждение, знак, фасад "
"или иной фон. Проекция камеры и LiDAR согласована; ошибка "
"локализована в семантической детекции."
),
)
elif key in MISSED_OBJECTS:
result.update(
verdict="confirmed",
effective_stratum=source,
detector_assessment="missed-object",
projection_assessment="aligned",
point_ownership="object",
cause_code="detector_error",
confidence=0.88,
note=(
"Geometry-only кластер пространственно совпадает с различимым "
"в камере человеком или транспортом. Геометрия корректна, "
"но семантический объект пропущен."
),
)
elif key in CLASS_MISMATCHES:
result.update(
detector_assessment="class-mismatch",
cause_code="detector_error",
confidence=0.86,
note=(
"Объектная поддержка корректна на уровне широкой группы, но "
"видимый подтип не совпадает с fine-label детектора."
),
)
snapshot = item.get("e29_snapshot")
label = (
snapshot.get("label") or snapshot.get("semantic_class")
if isinstance(snapshot, dict)
else None
)
frame = item["evidence_binding"]["source_frame_index"]
exception = key in AMBIGUITIES
return {
"schema_version": E30_ENGINEERING_DECISION_SCHEMA,
"sequence": item["sequence"],
"item_id": item["item_id"],
"review_key": item["review_key"],
"source_stratum": source,
"verdict": result["verdict"],
"effective_stratum": result["effective_stratum"],
"detector_assessment": result["detector_assessment"],
"projection_assessment": result["projection_assessment"],
"point_ownership": result["point_ownership"],
"cause_code": result["cause_code"],
"confidence": result["confidence"],
"human_exception_required": exception,
"exception_reason": "ambiguity" if exception else None,
"review_prompt": EXCEPTION_REVIEW.get(key),
"evidence_note": (
f"Кадр {frame}; label={label or 'geometry-cluster'}. {result['note']}"
),
"review_sheet": sheet,
}
def _parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser()
parser.add_argument("--materialization-root", type=Path, required=True)
parser.add_argument("--review-pack-root", type=Path, required=True)
parser.add_argument("--review-sheets-root", type=Path, required=True)
parser.add_argument("--decisions-path", type=Path, required=True)
parser.add_argument("--output-root", type=Path, required=True)
return parser.parse_args()
def main() -> None:
args = _parse_args()
materialization_root = args.materialization_root.resolve()
items = _read_jsonl(materialization_root / "materialized-items.jsonl")
keys_by_item, sheets_by_item = _sheet_bindings(
args.review_sheets_root.resolve()
)
all_audited_keys = set(keys_by_item.values())
declared_sets = (
FALSE_POSITIVES,
SELF_DETECTIONS,
CLASS_MISMATCHES,
MISSED_OBJECTS,
AMBIGUITIES,
)
for index, values in enumerate(declared_sets):
if not values <= all_audited_keys:
raise IssueGenerationError(
f"annotation set {index} references a missing sheet tile"
)
for other in declared_sets[index + 1 :]:
overlap = values & other
if overlap:
raise IssueGenerationError(
f"annotation categories overlap: {sorted(overlap)}"
)
decisions = [
_decision(
item=item,
key=keys_by_item[str(item["item_id"])],
sheet=sheets_by_item[str(item["item_id"])],
materialization_root=materialization_root,
)
for item in items
]
args.decisions_path.parent.mkdir(parents=True, exist_ok=True)
with args.decisions_path.open("w", encoding="utf-8") as stream:
for decision in decisions:
stream.write(
json.dumps(
decision,
ensure_ascii=False,
sort_keys=True,
separators=(",", ":"),
allow_nan=False,
)
+ "\n"
)
manifest = build_e30_engineering_generation(
materialization_root=materialization_root,
review_pack_root=args.review_pack_root.resolve(),
review_sheets_root=args.review_sheets_root.resolve(),
decisions_path=args.decisions_path.resolve(),
output_root=args.output_root.resolve(),
producer_id="codex:a3-engineering-review",
method_id="camera-lidar-42-sheet-audit/v2",
)
print(json.dumps(manifest, ensure_ascii=False, indent=2, sort_keys=True))
if __name__ == "__main__":
main()
@@ -0,0 +1,498 @@
#!/usr/bin/env python3
"""Render reproducible camera-backed A3 engineering review sheets.
The sheets are presentation derivatives only. Every tile is bound to one
immutable E30 materialization item and contains:
* the exact camera frame;
* the complete bounded LiDAR projection;
* candidate/selected point ownership;
* the semantic bbox or a geometry-derived region of interest;
* the source metrics required for engineering adjudication.
"""
from __future__ import annotations
import argparse
import colorsys
import hashlib
import json
import math
import shutil
import tempfile
from collections import defaultdict
from pathlib import Path
from typing import Any, Final
import numpy as np
from PIL import Image, ImageDraw, ImageFont
MATERIALIZATION_SCHEMA: Final = "missioncore.e30-evidence-materialization/v2"
ITEM_SCHEMA: Final = "missioncore.e30-evidence-materialization-item/v2"
SHEET_MANIFEST_SCHEMA: Final = "missioncore.e30-engineering-review-sheets/v1"
STRATA: Final = (
"conflict",
"agree",
"camera-only",
"unknown",
"geometry-only",
)
TILE_WIDTH: Final = 480
TILE_HEIGHT: Final = 300
FULL_WIDTH: Final = 320
FULL_HEIGHT: Final = 240
ROI_WIDTH: Final = 160
ROI_HEIGHT: Final = 160
SHEET_COLUMNS: Final = 4
SHEET_ROWS: Final = 3
ITEMS_PER_SHEET: Final = SHEET_COLUMNS * SHEET_ROWS
BACKGROUND: Final = (10, 10, 11)
PANEL: Final = (22, 22, 24)
TEXT: Final = (242, 242, 239)
MUTED: Final = (155, 155, 150)
WARNING: Final = (255, 209, 102)
CONFLICT: Final = (255, 98, 92)
SELECTED: Final = (255, 255, 255)
class ReviewSheetError(RuntimeError):
"""The source evidence cannot produce trustworthy review sheets."""
def _canonical_json(value: object) -> bytes:
return json.dumps(
value,
ensure_ascii=False,
sort_keys=True,
separators=(",", ":"),
allow_nan=False,
).encode("utf-8")
def _sha256(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as stream:
while chunk := stream.read(1024 * 1024):
digest.update(chunk)
return digest.hexdigest()
def _read_json(path: Path) -> dict[str, Any]:
if path.is_symlink() or not path.is_file():
raise ReviewSheetError(f"missing regular JSON: {path}")
try:
value = json.loads(path.read_text(encoding="utf-8"))
except (OSError, UnicodeDecodeError, json.JSONDecodeError) as exc:
raise ReviewSheetError(f"invalid JSON: {path}") from exc
if not isinstance(value, dict):
raise ReviewSheetError(f"JSON must contain an object: {path}")
return value
def _read_items(path: Path) -> list[dict[str, Any]]:
if path.is_symlink() or not path.is_file():
raise ReviewSheetError("materialized item index is unavailable")
values: list[dict[str, Any]] = []
with path.open("r", encoding="utf-8") as stream:
for line_number, line in enumerate(stream, start=1):
try:
value = json.loads(line)
except json.JSONDecodeError as exc:
raise ReviewSheetError(
f"invalid materialized item at line {line_number}"
) from exc
if not isinstance(value, dict):
raise ReviewSheetError(
f"materialized item {line_number} is not an object"
)
values.append(value)
return values
def _font(size: int, *, bold: bool = False) -> ImageFont.ImageFont:
candidates = (
"/System/Library/Fonts/SFNSMono.ttf",
"/System/Library/Fonts/SFNS.ttf",
"/System/Library/Fonts/Supplemental/Arial Bold.ttf"
if bold
else "/System/Library/Fonts/Supplemental/Arial.ttf",
)
for candidate in candidates:
try:
return ImageFont.truetype(candidate, size=size)
except OSError:
continue
return ImageFont.load_default()
FONT_SMALL: Final = _font(11)
FONT_META: Final = _font(12)
FONT_BOLD: Final = _font(13, bold=True)
def _depth_color(depth: float, minimum: float, maximum: float) -> tuple[int, int, int]:
span = max(maximum - minimum, 0.001)
position = min(1.0, max(0.0, (depth - minimum) / span))
hue = (220.0 - position * 205.0) / 360.0
red, green, blue = colorsys.hls_to_rgb(hue, 0.62, 0.88)
return round(red * 255), round(green * 255), round(blue * 255)
def _verify_item(
*,
root: Path,
item: dict[str, Any],
) -> tuple[Path, Path]:
if item.get("schema_version") != ITEM_SCHEMA:
raise ReviewSheetError("materialized item schema differs")
artifact = item.get("artifact")
camera = item.get("camera_frame")
if not isinstance(artifact, dict) or not isinstance(camera, dict):
raise ReviewSheetError("item artifacts are incomplete")
item_path = root / str(artifact.get("path"))
frame_path = root / str(camera.get("path"))
for path, metadata in ((item_path, artifact), (frame_path, camera)):
if (
path.is_symlink()
or not path.is_file()
or path.stat().st_size != metadata.get("byte_length")
or _sha256(path) != metadata.get("sha256")
):
raise ReviewSheetError(f"artifact changed: {path}")
return item_path, frame_path
def _draw_projection(
*,
frame: Image.Image,
arrays: Any,
item: dict[str, Any],
) -> Image.Image:
image = frame.convert("RGB")
draw = ImageDraw.Draw(image)
pixels = np.asarray(arrays["projected_pixels_xy"], dtype=np.float64)
depths = np.asarray(arrays["projected_depth_m"], dtype=np.float64)
candidates = np.asarray(arrays["projected_candidate_mask"], dtype=np.uint8)
selected = np.asarray(arrays["projected_selected_mask"], dtype=np.uint8)
finite_depths = depths[np.isfinite(depths)]
minimum = float(finite_depths.min()) if finite_depths.size else 0.0
maximum = float(finite_depths.max()) if finite_depths.size else 1.0
for index, (x, y) in enumerate(pixels):
if not math.isfinite(float(x)) or not math.isfinite(float(y)):
continue
if x < 0 or y < 0 or x >= image.width or y >= image.height:
continue
if selected[index] == 1:
color, radius = SELECTED, 4
elif candidates[index] == 1:
color, radius = WARNING, 3
else:
color, radius = _depth_color(float(depths[index]), minimum, maximum), 1
draw.ellipse(
(
round(x) - radius,
round(y) - radius,
round(x) + radius,
round(y) + radius,
),
fill=color,
)
snapshot = item.get("e29_snapshot")
bbox = snapshot.get("bbox_xyxy") if isinstance(snapshot, dict) else None
if (
isinstance(bbox, list)
and len(bbox) == 4
and all(isinstance(value, (int, float)) for value in bbox)
):
draw.rectangle(
tuple(round(float(value)) for value in bbox),
outline=CONFLICT if item.get("stratum") == "conflict" else SELECTED,
width=3,
)
return image
def _expanded_roi(
*,
item: dict[str, Any],
arrays: Any,
width: int,
height: int,
) -> tuple[int, int, int, int]:
snapshot = item.get("e29_snapshot")
bbox = snapshot.get("bbox_xyxy") if isinstance(snapshot, dict) else None
if (
isinstance(bbox, list)
and len(bbox) == 4
and all(isinstance(value, (int, float)) for value in bbox)
):
x1, y1, x2, y2 = (float(value) for value in bbox)
else:
pixels = np.asarray(arrays["projected_pixels_xy"], dtype=np.float64)
selected = np.asarray(arrays["projected_selected_mask"], dtype=np.uint8) == 1
candidate = np.asarray(arrays["projected_candidate_mask"], dtype=np.uint8) == 1
owned = pixels[selected | candidate]
if owned.size == 0:
return 0, 0, width, height
x1, y1 = owned.min(axis=0)
x2, y2 = owned.max(axis=0)
roi_width = max(x2 - x1, 64.0)
roi_height = max(y2 - y1, 64.0)
padding = max(18.0, 0.35 * max(roi_width, roi_height))
center_x = (x1 + x2) / 2.0
center_y = (y1 + y2) / 2.0
side = min(max(roi_width, roi_height) + 2.0 * padding, float(max(width, height)))
left = max(0.0, min(float(width) - side, center_x - side / 2.0))
top = max(0.0, min(float(height) - side, center_y - side / 2.0))
right = min(float(width), left + side)
bottom = min(float(height), top + side)
return round(left), round(top), round(right), round(bottom)
def _fit_cover(image: Image.Image, size: tuple[int, int]) -> Image.Image:
target_width, target_height = size
ratio = max(target_width / image.width, target_height / image.height)
resized = image.resize(
(round(image.width * ratio), round(image.height * ratio)),
Image.Resampling.LANCZOS,
)
left = max(0, (resized.width - target_width) // 2)
top = max(0, (resized.height - target_height) // 2)
return resized.crop((left, top, left + target_width, top + target_height))
def _tile(
*,
ordinal: int,
item: dict[str, Any],
item_path: Path,
frame_path: Path,
) -> Image.Image:
with np.load(item_path, allow_pickle=False) as arrays:
with Image.open(frame_path) as source_frame:
camera = item["camera_frame"]
if source_frame.size != (camera.get("width"), camera.get("height")):
raise ReviewSheetError("camera dimensions changed")
annotated = _draw_projection(
frame=source_frame,
arrays=arrays,
item=item,
)
full = annotated.resize(
(FULL_WIDTH, FULL_HEIGHT),
Image.Resampling.LANCZOS,
)
roi_box = _expanded_roi(
item=item,
arrays=arrays,
width=annotated.width,
height=annotated.height,
)
roi = _fit_cover(annotated.crop(roi_box), (ROI_WIDTH, ROI_HEIGHT))
tile = Image.new("RGB", (TILE_WIDTH, TILE_HEIGHT), PANEL)
tile.paste(full, (0, 0))
tile.paste(roi, (FULL_WIDTH, 0))
draw = ImageDraw.Draw(tile)
draw.line((FULL_WIDTH, 0, FULL_WIDTH, ROI_HEIGHT), fill=(65, 65, 68), width=1)
draw.rectangle((0, 240, TILE_WIDTH - 1, TILE_HEIGHT - 1), fill=BACKGROUND)
snapshot = item.get("e29_snapshot")
label = (
str(snapshot.get("label"))
if isinstance(snapshot, dict) and snapshot.get("label")
else "geometry"
)
materialization = item["materialization"]
frame_index = item["evidence_binding"]["source_frame_index"]
score = materialization.get("detector_score")
score_text = "n/a" if score is None else f"{float(score):.2f}"
draw.text(
(8, 246),
f"{ordinal:02d} · {item['stratum']} · {label} · f{frame_index}",
font=FONT_BOLD,
fill=TEXT,
)
draw.text(
(8, 266),
(
f"score {score_text} · proj {materialization['projected_point_count']} "
f"· cand {materialization['candidate_point_count']} "
f"· sel {materialization['selected_point_count']}"
),
font=FONT_META,
fill=MUTED,
)
draw.text(
(FULL_WIDTH + 7, ROI_HEIGHT + 7),
item["review_key"][:24],
font=FONT_SMALL,
fill=MUTED,
)
draw.text(
(FULL_WIDTH + 7, ROI_HEIGHT + 25),
f"seq {item['sequence']} · roi {roi_box[0]},{roi_box[1]}",
font=FONT_SMALL,
fill=MUTED,
)
return tile
def render_review_sheets(
*,
materialization_root: Path,
output_root: Path,
) -> dict[str, Any]:
root = materialization_root.resolve()
manifest = _read_json(root / "manifest.json")
index_path = root / "materialized-items.jsonl"
if (
manifest.get("schema_version") != MATERIALIZATION_SCHEMA
or manifest.get("result_id") != root.name
or manifest.get("item_count") != 486
or manifest.get("camera_evidence_available") is not True
):
raise ReviewSheetError("unsupported E30 materialization")
items = _read_items(index_path)
if (
len(items) != manifest.get("item_count")
or len({item.get("item_id") for item in items}) != len(items)
):
raise ReviewSheetError("materialization index count differs")
by_stratum: dict[str, list[dict[str, Any]]] = defaultdict(list)
for item in items:
stratum = item.get("stratum")
if stratum not in STRATA:
raise ReviewSheetError("unknown E30 stratum")
by_stratum[stratum].append(item)
for values in by_stratum.values():
values.sort(
key=lambda item: (
item["evidence_binding"]["source_frame_index"],
item["sequence"],
)
)
output_root.mkdir(parents=True, exist_ok=True)
destination = output_root / root.name
if destination.exists():
if destination.is_symlink() or not destination.is_dir():
raise ReviewSheetError("review sheet destination is invalid")
shutil.rmtree(destination)
staging = Path(tempfile.mkdtemp(prefix=f".{root.name}.", dir=output_root))
sheet_documents: list[dict[str, Any]] = []
try:
for stratum in STRATA:
values = by_stratum[stratum]
for page_index, offset in enumerate(
range(0, len(values), ITEMS_PER_SHEET),
start=1,
):
page = values[offset : offset + ITEMS_PER_SHEET]
sheet = Image.new(
"RGB",
(
SHEET_COLUMNS * TILE_WIDTH,
SHEET_ROWS * TILE_HEIGHT,
),
BACKGROUND,
)
entries: list[dict[str, Any]] = []
for ordinal, item in enumerate(page, start=1):
item_path, frame_path = _verify_item(root=root, item=item)
tile = _tile(
ordinal=ordinal,
item=item,
item_path=item_path,
frame_path=frame_path,
)
column = (ordinal - 1) % SHEET_COLUMNS
row = (ordinal - 1) // SHEET_COLUMNS
sheet.paste(tile, (column * TILE_WIDTH, row * TILE_HEIGHT))
entries.append(
{
"ordinal": ordinal,
"item_id": item["item_id"],
"sequence": item["sequence"],
"review_key": item["review_key"],
"stratum": item["stratum"],
"source_frame_index": item["evidence_binding"][
"source_frame_index"
],
"label": item["e29_snapshot"].get("label"),
}
)
file_name = f"{stratum}-{page_index:02d}.jpg"
sheet_path = staging / file_name
sheet.save(sheet_path, format="JPEG", quality=94, optimize=True)
sheet_documents.append(
{
"path": file_name,
"sha256": _sha256(sheet_path),
"byte_length": sheet_path.stat().st_size,
"stratum": stratum,
"page": page_index,
"entries": entries,
}
)
identity = {
"schema_version": SHEET_MANIFEST_SCHEMA,
"materialization_id": root.name,
"materialization_manifest_sha256": _sha256(root / "manifest.json"),
"materialization_index_sha256": _sha256(index_path),
"layout": {
"columns": SHEET_COLUMNS,
"rows": SHEET_ROWS,
"tile_width": TILE_WIDTH,
"tile_height": TILE_HEIGHT,
},
"sheets": sheet_documents,
}
identity_sha256 = hashlib.sha256(_canonical_json(identity)).hexdigest()
document = {
**identity,
"identity_sha256": identity_sha256,
"sheet_count": len(sheet_documents),
"item_count": len(items),
"authority": {
"presentation_derivative_only": True,
"commands_enabled": False,
"navigation_or_safety_accepted": False,
},
}
(staging / "manifest.json").write_bytes(_canonical_json(document) + b"\n")
staging.rename(destination)
return document
except Exception:
shutil.rmtree(staging, ignore_errors=True)
raise
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--materialization-root", type=Path, required=True)
parser.add_argument("--output-root", type=Path, required=True)
args = parser.parse_args()
document = render_review_sheets(
materialization_root=args.materialization_root,
output_root=args.output_root,
)
print(
json.dumps(
{
"materialization_id": document["materialization_id"],
"sheet_count": document["sheet_count"],
"item_count": document["item_count"],
"identity_sha256": document["identity_sha256"],
},
ensure_ascii=False,
sort_keys=True,
)
)
if __name__ == "__main__":
main()
@@ -0,0 +1,60 @@
#!/usr/bin/env python3
"""Build camera-backed LAB E30 evidence from immutable A2 sources."""
from __future__ import annotations
import argparse
import json
from pathlib import Path
from k1link.compute.e30_materialization import build_e30_materialization
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--review-pack", type=Path, required=True)
parser.add_argument("--e29-root", type=Path, required=True)
parser.add_argument("--source-result-root", type=Path, required=True)
parser.add_argument("--source-pack-root", type=Path, required=True)
parser.add_argument("--local-surface-root", type=Path, required=True)
parser.add_argument("--camera-job", type=Path, required=True)
parser.add_argument("--ffmpeg", type=Path, required=True)
parser.add_argument(
"--output-root",
type=Path,
default=Path(".runtime/compute-experiments/e30/materializations"),
)
args = parser.parse_args()
result = build_e30_materialization(
review_pack_root=args.review_pack,
e29_root=args.e29_root,
source_result_root=args.source_result_root,
source_pack_root=args.source_pack_root,
local_surface_root=args.local_surface_root,
camera_job_root=args.camera_job,
ffmpeg_path=args.ffmpeg,
output_root=args.output_root,
)
print(
json.dumps(
{
"result_id": result.result_id,
"result_root": str(result.result_root),
"item_count": result.manifest["item_count"],
"camera_evidence_available": result.manifest[
"camera_evidence_available"
],
"human_review_complete": result.manifest[
"human_review_complete"
],
"lab_published": result.manifest["lab_published"],
},
ensure_ascii=False,
indent=2,
)
)
if __name__ == "__main__":
main()