Link calibration rows to QA evidence map
This commit is contained in:
@@ -7,6 +7,13 @@
|
||||
|
||||
# Changelog
|
||||
|
||||
## Sprint 135 Calibration evidence handoff (2026-07-08)
|
||||
|
||||
- Added a guided-calibration table action that opens the persisted QA/QC evidence map for successful threshold rows.
|
||||
- Reused the existing quality-check evidence API and Map workspace overlay flow; no backend route, migration, model, provider or inference behavior changed.
|
||||
- Kept unsuccessful/queued calibration rows read-only by disabling evidence actions until a persisted `quality_check_id` exists.
|
||||
- Added regression coverage for the Detection Lab wiring and TODO tracking.
|
||||
|
||||
## Sprint 134 External remote-sensing YOLO candidate benchmark (2026-07-07)
|
||||
|
||||
- Evaluated the Hugging Face `agademer/yolo-remote-sensing-photovoltaic` YOLOv8l detection checkpoint as an explicit operator-provided runtime model asset.
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
|
||||
|
||||
def test_guided_calibration_rows_link_to_existing_qa_evidence_map() -> None:
|
||||
lab = ROOT / "frontend" / "src" / "components" / "detection" / "DetectionLab.tsx"
|
||||
app = ROOT / "frontend" / "src" / "App.tsx"
|
||||
todo = ROOT / "docs" / "TODO.md"
|
||||
|
||||
lab_source = lab.read_text(encoding="utf-8")
|
||||
app_source = app.read_text(encoding="utf-8")
|
||||
todo_source = todo.read_text(encoding="utf-8")
|
||||
|
||||
assert "onOpenCalibrationEvidence" in lab_source
|
||||
assert "Open evidence map" in lab_source
|
||||
assert "disabled={!row.quality_check_id || row.status !== 'success'}" in lab_source
|
||||
assert "onOpenCalibrationEvidence(row.quality_check_id)" in lab_source
|
||||
assert "Evidence" in lab_source
|
||||
assert "quality_check_id" in lab_source
|
||||
|
||||
assert "onOpenCalibrationEvidence={openQualityEvidenceOnMap}" in app_source
|
||||
assert "[x] Link guided calibration rows to the QA evidence map" in todo_source
|
||||
@@ -1,3 +1,28 @@
|
||||
## Sprint 135 Calibration evidence handoff (2026-07-08)
|
||||
|
||||
Changed:
|
||||
- Added an `Open evidence map` action to successful guided detection calibration rows.
|
||||
- Wired the Detection Lab action to the existing `openQualityEvidenceOnMap` flow, which loads persisted QA/QC evidence GeoJSON and opens the Map workspace overlay.
|
||||
- Added compact table action styling and regression coverage in `backend/tests/test_sprint135_calibration_evidence_handoff.py`.
|
||||
- Updated `CHANGELOG.md` and `docs/TODO.md`.
|
||||
|
||||
Tested:
|
||||
- Red step: `python -m pytest backend\tests\test_sprint135_calibration_evidence_handoff.py -q` failed while the Detection Lab evidence handoff prop was absent.
|
||||
- `python -m pytest backend\tests\test_sprint135_calibration_evidence_handoff.py backend\tests\test_sprint134_guided_detection_calibration_runner.py backend\tests\test_sprint133_detection_threshold_calibration_ux.py backend\tests\test_sprint112_qa_evidence_overlay.py -q` (`7 passed`)
|
||||
- `python -m compileall backend/app`
|
||||
- `cd frontend && npm run typecheck`
|
||||
- `cd frontend && npm run build`
|
||||
- `bash scripts/run_readiness_check.sh` (`414 passed`; frontend typecheck/build passed; Alembic head `202606120900`; live smoke syntax passed)
|
||||
|
||||
Open:
|
||||
- Live Tower deploy validation still needs to run for this pass.
|
||||
|
||||
Limitations:
|
||||
- This pass adds review handoff only. It does not create new QA metrics, promote thresholds, mutate model configuration, download models, add provider fetching or change API/database contracts.
|
||||
|
||||
Next recommended pass:
|
||||
- Add an operator-facing calibration evidence summary/export shortcut once the map handoff has been used on real AOI runs.
|
||||
|
||||
## Sprint 134 External remote-sensing YOLO candidate benchmark (2026-07-07)
|
||||
|
||||
Changed:
|
||||
|
||||
@@ -421,5 +421,6 @@ This file now starts with the current implementation status. Older preparation/b
|
||||
- [x] Add structured raster tile manifest handoff into Detection Lab with linked preflight visibility.
|
||||
- [x] Add full threshold calibration comparison UX so detection runs can compare candidate thresholds before promotion.
|
||||
- [x] Add guided in-app detection calibration runner for explicit threshold sweeps.
|
||||
- [x] Link guided calibration rows to the QA evidence map.
|
||||
- [ ] Add more AOIs after the tile-level baseline so the next local model attempt is not limited to Geel/Mol/Turnhout.
|
||||
- [ ] Add negative/background AOIs so the next tile dataset is not all positive tiles.
|
||||
|
||||
@@ -993,6 +993,7 @@ function App(): JSX.Element {
|
||||
onRunQa={runDetectionQa}
|
||||
onSetCalibrationThresholdText={setCalibrationThresholdText}
|
||||
onRunCalibration={runDetectionCalibration}
|
||||
onOpenCalibrationEvidence={openQualityEvidenceOnMap}
|
||||
/>
|
||||
|
||||
<SegmentationLab
|
||||
|
||||
@@ -79,6 +79,7 @@ interface DetectionLabProps {
|
||||
onRunQa: () => void
|
||||
onSetCalibrationThresholdText: (value: string) => void
|
||||
onRunCalibration: () => void
|
||||
onOpenCalibrationEvidence: (qualityCheckId: string) => void
|
||||
}
|
||||
|
||||
export function DetectionLab({
|
||||
@@ -133,6 +134,7 @@ export function DetectionLab({
|
||||
onRunQa,
|
||||
onSetCalibrationThresholdText,
|
||||
onRunCalibration,
|
||||
onOpenCalibrationEvidence,
|
||||
}: DetectionLabProps): JSX.Element {
|
||||
const selectedDetectionModel = detectionModels.find((model) => model.model_id === selectedDetectionModelId) ?? null
|
||||
const selectedModelAsset = modelAssets.find((asset) => asset.model_asset_id === selectedModelAssetId) ?? null
|
||||
@@ -583,6 +585,7 @@ export function DetectionLab({
|
||||
<th>F1</th>
|
||||
<th>False positives</th>
|
||||
<th>False negatives</th>
|
||||
<th>Evidence</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -596,6 +599,17 @@ export function DetectionLab({
|
||||
<td>{formatNullableNumber(row.f1_score ?? null, 3)}</td>
|
||||
<td>{row.false_positives ?? 'n/a'}</td>
|
||||
<td>{row.false_negatives ?? 'n/a'}</td>
|
||||
<td>
|
||||
<button
|
||||
className="secondary-action table-action"
|
||||
type="button"
|
||||
onClick={() => row.quality_check_id ? onOpenCalibrationEvidence(row.quality_check_id) : undefined}
|
||||
disabled={!row.quality_check_id || row.status !== 'success'}
|
||||
aria-label={`Open evidence map for threshold ${row.threshold.toFixed(2)}`}
|
||||
>
|
||||
Open evidence map
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
|
||||
@@ -3309,6 +3309,12 @@ button.entity-card {
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.table-action {
|
||||
min-height: 2rem;
|
||||
padding: 0.35rem 0.6rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.calibration-summary-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
|
||||
Reference in New Issue
Block a user