Files
geointel/backend/tests/test_sprint201_semantic_selection_metrics.py
T
Codex df015e10e0
GeoIntel CI / docs-smoke (push) Canceled after 0s
GeoIntel CI / contract-smoke (push) Canceled after 0s
Align historical metrics with polygon semantics
2026-07-15 23:49:30 +02:00

179 lines
6.2 KiB
Python

from __future__ import annotations
from pathlib import Path
from uuid import uuid4
from app.models import Dataset
from app.schemas.operations import VectorSelectionSummary
from app.services.vector_feature_service import VectorFeatureService
ROOT = Path(__file__).parents[2]
BBOX = {"min_x": 5.0, "min_y": 51.1, "max_x": 5.2, "max_y": 51.3, "crs": "EPSG:4326"}
class ScalarQuery:
def __init__(self, value: float):
self.value = value
def filter(self, *args): # noqa: ANN002, ARG002
return self
def scalar(self):
return self.value
class SequenceScalarSession:
def __init__(self, values: list[float]):
self.values = iter(values)
def query(self, *args): # noqa: ANN002, ARG002
return ScalarQuery(next(self.values))
def themed_dataset(theme: str, *, method: str = "feature_count") -> Dataset:
return Dataset(
id=uuid4(),
project_id=uuid4(),
name=f"regional-{theme}.geojson",
dataset_type="vector",
dataset_role="reference",
source_name="grb",
reference_layer_name=theme,
source_metadata={
"theme": theme,
"selection_aggregation": {
"method": method,
"label": theme.title(),
"unit": "objecten",
},
},
)
def test_building_selection_promotes_footprint_area_and_retains_object_count() -> None:
result = VectorFeatureService.summarize_features_by_bbox(
SequenceScalarSession([125_000.0]),
dataset=themed_dataset("buildings"),
bbox=BBOX,
total_feature_count=40,
)
assert result["primary_metric_key"] == "footprint_area"
assert result["metric_label"] == "Bebouwde grondoppervlakte"
assert result["metric_value"] == 12.5
assert result["metric_unit"] == "ha"
assert [(item["metric_key"], item["metric_value"]) for item in result["metrics"]] == [
("footprint_area", 12.5),
("feature_count", 40.0),
]
assert "niet de totale vloeroppervlakte" in result["warning"]
VectorSelectionSummary(**result)
def test_water_selection_reports_surface_length_and_honest_volume_limitation() -> None:
result = VectorFeatureService.summarize_features_by_bbox(
SequenceScalarSession([52_500.0, 12_750.0]),
dataset=themed_dataset("water"),
bbox=BBOX,
total_feature_count=23,
)
assert result["metric_value"] == 5.25
assert result["metric_unit"] == "ha"
assert [(item["metric_key"], item["metric_value"], item["metric_unit"]) for item in result["metrics"]] == [
("water_area", 5.25, "ha"),
("watercourse_length", 12.75, "km"),
("feature_count", 23.0, "objecten"),
]
assert "Watervolume is niet berekenbaar" in result["warning"]
def test_population_keeps_configured_metric_and_adds_sector_count() -> None:
dataset = themed_dataset("population", method="sum")
dataset.source_metadata["selection_aggregation"].update(
{"metric_key": "population", "property": "population_total", "label": "Inwoners", "unit": "inwoners"}
)
result = VectorFeatureService.summarize_features_by_bbox(
SequenceScalarSession([86_458.0]),
dataset=dataset,
bbox=BBOX,
total_feature_count=733,
)
assert result["primary_metric_key"] == "population"
assert result["metric_value"] == 86_458.0
assert result["metrics"][1] == {
"metric_key": "feature_count",
"metric_label": "Statistische sectoren",
"metric_value": 733.0,
"metric_unit": "objecten",
"aggregation_method": "feature_count",
"is_estimate": False,
"warning": None,
}
def test_station_measurement_uses_numeric_mean_without_area_extrapolation() -> None:
dataset = themed_dataset("water", method="mean")
dataset.source_name = "waterinfo"
dataset.source_metadata.update(
{
"semantic_metrics": False,
"selection_aggregation": {
"metric_key": "water_level",
"method": "mean",
"property": "annual_mean_water_level_m",
"label": "Jaargemiddelde waterstand",
"unit": "m",
"warning": "Puntmeting; geen gebiedsdekkend watervolume.",
},
}
)
result = VectorFeatureService.summarize_features_by_bbox(
SequenceScalarSession([30.455]),
dataset=dataset,
bbox=BBOX,
total_feature_count=1,
)
assert result["metric_value"] == 30.455
assert result["aggregation_method"] == "mean"
assert result["metric_unit"] == "m"
assert result["warning"] == "Puntmeting; geen gebiedsdekkend watervolume."
def test_regional_historical_polygons_do_not_emit_irrelevant_line_metrics() -> None:
dataset = themed_dataset("water", method="intersection_area")
dataset.source_metadata["selection_aggregation"].update(
{"metric_key": "water_area", "label": "Historische wateroppervlakte", "unit": "ha"}
)
dataset.provenance_metadata = {"operator_tool": "provision_regional_historical_landuse.py"}
result = VectorFeatureService.summarize_features_by_bbox(
SequenceScalarSession([52_500.0]),
dataset=dataset,
bbox=BBOX,
total_feature_count=23,
)
assert [(item["metric_key"], item["metric_unit"]) for item in result["metrics"]] == [
("water_area", "ha"),
("feature_count", "objecten"),
]
def test_future_regional_imports_persist_semantic_aggregation_configuration() -> None:
buildings = (ROOT / "scripts/provision_regional_grb_buildings.py").read_text(encoding="utf-8")
context = (ROOT / "scripts/provision_regional_grb_context.py").read_text(encoding="utf-8")
frontend = (ROOT / "frontend/src/components/map/MapWorkspace.tsx").read_text(encoding="utf-8")
assert '"method": "intersection_area"' in buildings
assert '"label": "Bebouwde grondoppervlakte"' in buildings
assert 'metric_method="intersection_length"' in context
assert 'metric_label="Wateroppervlakte"' in context
assert 'metric_label="Perceeloppervlakte"' in context
assert 'aria-label="Aanvullende gebiedsmetingen"' in frontend
assert "activeSelectionResult.summary.warning" in frontend