fix: bound detection QA to inference coverage
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 00:35:39 +02:00
parent 2f9898bc82
commit 0cad8fdf76
12 changed files with 159 additions and 45 deletions
@@ -8,6 +8,7 @@ from shapely.geometry import box
from app.core.errors import AppError
from app.services.detection_qa_service import DetectionQaService
from app.services.qa_service import QaService
def test_tile_coverage_transforms_projected_manifest_bounds_to_epsg4326() -> None:
@@ -78,3 +79,46 @@ def test_coverage_filter_reports_outside_and_boundary_clipped_population() -> No
assert population.excluded_outside_count == 1
assert population.clipped_boundary_count == 1
assert population.geometries[1][1].bounds == pytest.approx((0.8, 0.8, 1.0, 1.0))
def test_coverage_filter_preserves_prefiltered_database_population_count() -> None:
dataset_id = uuid4()
coverage = DetectionQaService.build_tile_coverage(
{
"source_dataset_id": str(dataset_id),
"crs": "EPSG:4326",
"tiles": [{"bounds": [0.0, 0.0, 1.0, 1.0]}],
},
manifest_path="/app/storage/tiles/manifest.json",
expected_dataset_id=dataset_id,
)
population = DetectionQaService.filter_population(
[
({"id": "inside"}, box(0.1, 0.1, 0.2, 0.2)),
({"id": "crossing"}, box(0.8, 0.8, 1.2, 1.2)),
],
coverage,
raw_count=3,
)
assert population.raw_count == 3
assert population.evaluated_count == 2
assert population.excluded_outside_count == 1
assert population.clipped_boundary_count == 1
def test_iou_matching_keeps_exact_results_with_many_spatially_disjoint_references() -> None:
references = [({"id": f"outside-{index}"}, box(index + 10, 10, index + 10.5, 10.5)) for index in range(100)]
references.append(({"id": "match"}, box(0.0, 0.0, 1.0, 1.0)))
evidence = QaService._match_io_u_evidence(
[({"id": "candidate"}, box(0.0, 0.0, 1.0, 1.0))],
references,
0.5,
)
assert evidence.matches == 1
assert evidence.false_positives == 0
assert evidence.false_negatives == 100
assert evidence.match_evidence[0]["reference_feature_id"] == "match"
@@ -42,6 +42,9 @@ class FakeQuery:
def first(self):
return self.rows[0] if self.rows else None
def count(self):
return len(self.rows)
class FakeSession:
def __init__(self, objects=None, query_rows=None) -> None: