from pathlib import Path import json import sys import pandas as pd import pytest ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(ROOT / "scripts")) from heat_demand_processing import ( # noqa: E402 build_profile_table, process_osm_features, ) from heat_profiles import load_archetypes # noqa: E402 def inputs(): payload = json.loads((ROOT / "tests/fixtures/osm_heat_sinks.json").read_text()) archetypes = load_archetypes(ROOT / "data_reference/heat_archetypes.csv") temperatures = { "winnipeg": pd.Series([-10.0] * 4380 + [20.0] * 4380), "fargo": pd.Series([-8.0] * 4380 + [22.0] * 4380), } return payload, archetypes, temperatures def test_osm_polygon_gets_area_demand_bounds_and_provenance(): payload, archetypes, temperatures = inputs() result = process_osm_features(payload, archetypes, temperatures, "2026-08-09") hospital = result.loc[result["heat_sink_id"] == "osm:way:101"].iloc[0] assert hospital.geometry.geom_type == "Polygon" assert hospital["floor_area_m2"] > hospital["footprint_area_m2"] assert hospital["annual_heat_low_mwh"] <= hospital["annual_heat_mid_mwh"] assert hospital["annual_heat_mid_mwh"] <= hospital["annual_heat_high_mwh"] assert hospital["source_url"] == "https://www.openstreetmap.org/way/101" assert hospital["evidence_state"] == "modeled_estimated" assert result.crs.to_epsg() == 4326 def test_point_only_heat_sink_stays_proxy_without_sized_demand(): payload, archetypes, temperatures = inputs() result = process_osm_features(payload, archetypes, temperatures, "2026-08-09") proxy = result.loc[result["heat_sink_id"] == "osm:node:202"].iloc[0] assert proxy["evidence_state"] == "proxy_indicator" assert pd.isna(proxy["annual_heat_mid_mwh"]) def test_site_boundary_is_not_treated_as_heated_floor_area(): payload, archetypes, temperatures = inputs() result = process_osm_features(payload, archetypes, temperatures, "2026-08-09") site = result.loc[result["heat_sink_id"] == "osm:way:303"].iloc[0] assert site.geometry.geom_type == "Polygon" assert site["evidence_state"] == "proxy_indicator" assert pd.isna(site["floor_area_m2"]) assert pd.isna(site["annual_heat_mid_mwh"]) def test_profile_table_has_8760_rows_per_sized_sink(): payload, archetypes, temperatures = inputs() sinks = process_osm_features(payload, archetypes, temperatures, "2026-08-09") profiles = build_profile_table(sinks, archetypes, temperatures) assert len(profiles) == 8760 assert profiles["heat_sink_id"].nunique() == 1 assert profiles["heat_kwh"].sum() / 1000 == pytest.approx( sinks["annual_heat_mid_mwh"].sum() )