fix: polish measured map quality output
GeoIntel CI / docs-smoke (push) Canceled after 0s
GeoIntel CI / contract-smoke (push) Canceled after 0s

This commit is contained in:
Codex
2026-07-15 03:10:22 +02:00
parent d22abe8e7b
commit 2a9b48d2b5
6 changed files with 33 additions and 4 deletions
+3
View File
@@ -29,6 +29,9 @@
envelopes, bounded evidence access and the map QA threshold. envelopes, bounded evidence access and the map QA threshold.
- Passed the complete readiness gate with 592 backend tests, 88 documented API - Passed the complete readiness gate with 592 backend tests, 88 documented API
routes, one Alembic head and a green frontend typecheck/production build. routes, one Alembic head and a green frontend typecheck/production build.
- Live browser validation caught and fixed cramped map-result metric cells;
quality values now use a readable two-column layout and the map legend calls
unverified model output `AI-kandidaten`.
## Sprint 196 Map-driven official orthophoto analysis (2026-07-15) ## Sprint 196 Map-driven official orthophoto analysis (2026-07-15)
@@ -248,6 +248,7 @@ def test_map_detection_qa_uses_documented_footprint_threshold_and_honest_labels(
assert "kandidaten" in hook assert "kandidaten" in hook
assert "precision" in hook.lower() assert "precision" in hook.lower()
assert "false, iouThreshold" in app_source assert "false, iouThreshold" in app_source
assert "AI-kandidaten" in (ROOT / "frontend" / "src" / "components" / "map" / "MapWorkspace.tsx").read_text(encoding="utf-8")
assert "VectorFeature.id.in_(uuid_identifiers)" in evidence_service assert "VectorFeature.id.in_(uuid_identifiers)" in evidence_service
assert "VectorFeature.source_feature_id.in_(identifiers)" in evidence_service assert "VectorFeature.source_feature_id.in_(identifiers)" in evidence_service
assert "for row in db.query(VectorFeature).filter(VectorFeature.dataset_id" not in evidence_service assert "for row in db.query(VectorFeature).filter(VectorFeature.dataset_id" not in evidence_service
+20
View File
@@ -8168,6 +8168,26 @@ Validation before deployment:
- Focused review/evidence regressions passed and the production bundle retained - Focused review/evidence regressions passed and the production bundle retained
separate React, application and MapLibre chunks. separate React, application and MapLibre chunks.
Live operational proof:
- Tower deployed commit `d22abe8` with AI extras enabled. The all-in-one
runtime became healthy, PostGIS 3.6 passed, Alembic reached `202607150001`,
and the new table exposed 13 columns plus six expected indexes.
- Quality check `acaca138-dbb9-4498-ae53-d0732b6270e3` returned 206 persisted
evidence geometries in 338 ms with zero unresolved ids. All 72 reviewable
false-positive/false-negative features were explicitly `unreviewed`.
- A new browser-driven 35.57 ha Mol rectangle acquired the official orthophoto,
ran the configured local YOLO model and persisted analysis run
`14f3b856-1ff0-4939-892a-3c8347a669f1` plus quality check
`087d2b6a-6d3c-4508-ab1e-da49734097c2` at IoU `0.25`.
- The live run produced 100 candidates, 73 matches, precision `0.73`, recall
`0.4965986395`, F1 `0.5910931174`, mean IoU `0.5361610234`, 27 false
positives and 74 false negatives. The UI showed these values as measured
candidates and retained the explicit `controle vereist` source warning.
- Browser audits at 1280x720 and 3440x1440 had no console warnings/errors or
horizontal overflow. The review queue rendered 50 paginated rows; the
ultrawide map used about 2,410 px. A final compact-metric fix was queued after
the 1280 px screenshot exposed cramped six-column labels.
Next: Next:
- Deploy the migration and UI, verify one live review queue and map QA result, - Deploy the migration and UI, verify one live review queue and map QA result,
then complete representative manual decisions before constructing any new then complete representative manual decisions before constructing any new
+1 -1
View File
@@ -1140,7 +1140,7 @@ export function MapWorkspace({
<span><i className="geo-legend-area" /> Werkgebied</span> <span><i className="geo-legend-area" /> Werkgebied</span>
{analysisOverlayActive ? ( {analysisOverlayActive ? (
<> <>
<span><i className="geo-legend-layer geo-legend-layer-buildings" /> Gevonden gebouwen</span> <span><i className="geo-legend-layer geo-legend-layer-buildings" /> AI-kandidaten</span>
<span><i className="geo-legend-selection" /> Selectie</span> <span><i className="geo-legend-selection" /> Selectie</span>
</> </>
) : analysisMode === 'evolution' && temporalComparison?.object_changes.available ? ( ) : analysisMode === 'evolution' && temporalComparison?.object_changes.available ? (
@@ -46,6 +46,10 @@ function qualityMetricValue(metric: MetricRead | undefined): string {
return Number.isInteger(value) ? String(value) : value.toFixed(3) return Number.isInteger(value) ? String(value) : value.toFixed(3)
} }
function qualityScoreValue(value: number | null | undefined): string {
return typeof value === 'number' && Number.isFinite(value) ? value.toFixed(3) : 'n/a'
}
function qualityStatusLabel(status: string | null | undefined): string { function qualityStatusLabel(status: string | null | undefined): string {
if (!status || status === 'waiting') return 'nog niet uitgevoerd' if (!status || status === 'waiting') return 'nog niet uitgevoerd'
if (status === 'completed' || status === 'ok') return 'afgerond' if (status === 'completed' || status === 'ok') return 'afgerond'
@@ -173,7 +177,7 @@ export function QualityResultsPanel({
</div> </div>
<div> <div>
<span>Laatste score</span> <span>Laatste score</span>
<strong>{latestCheck?.score ?? 'n/a'}</strong> <strong>{qualityScoreValue(latestCheck?.score)}</strong>
</div> </div>
<div> <div>
<span>Laatste status</span> <span>Laatste status</span>
@@ -272,7 +276,7 @@ export function QualityResultsPanel({
<div> <div>
<span>Status</span> <span>Status</span>
<strong>{selectedQualityCheck.status}</strong> <strong>{selectedQualityCheck.status}</strong>
<p>Score: {selectedQualityCheck.score ?? 'n/a'}</p> <p>Score: {qualityScoreValue(selectedQualityCheck.score)}</p>
</div> </div>
<div> <div>
<span>Afgerond</span> <span>Afgerond</span>
@@ -508,7 +512,7 @@ export function QualityResultsPanel({
<div className="quality-score-row"> <div className="quality-score-row">
<div> <div>
<span>Score</span> <span>Score</span>
<strong>{check.score ?? 'n/a'}</strong> <strong>{qualityScoreValue(check.score)}</strong>
</div> </div>
<div> <div>
<span>Meetwaarden</span> <span>Meetwaarden</span>
+1
View File
@@ -1872,6 +1872,7 @@ details.ai-lab-model-surface > summary strong {
.geo-image-quality-metrics { .geo-image-quality-metrics {
grid-column: 1 / -1; grid-column: 1 / -1;
grid-template-columns: repeat(2, minmax(0, 1fr));
margin-top: 0.35rem; margin-top: 0.35rem;
border-top: 1px solid var(--line); border-top: 1px solid var(--line);
padding-top: 0.65rem; padding-top: 0.65rem;