Federate official Belgium data sources
This commit is contained in:
@@ -255,6 +255,23 @@ def resolve_boundary_path(args: argparse.Namespace, scope: GeographicScope) -> P
|
||||
return Path(legacy)
|
||||
if scope.key == "mol" and DEFAULT_BOUNDARY_PATH.exists():
|
||||
return DEFAULT_BOUNDARY_PATH
|
||||
if scope.key == "belgium":
|
||||
national_scope_dir = args.scope_output_root / "belgium-north-sea"
|
||||
manifest_path = national_scope_dir / "manifest.json"
|
||||
boundary_path = national_scope_dir / "belgium_land_boundary.geojson"
|
||||
if not manifest_path.is_file() or not boundary_path.is_file():
|
||||
raise RuntimeError(
|
||||
"Official Belgium boundary evidence is missing; "
|
||||
"run provision_belgium_north_sea_scope.py --fetch-only first"
|
||||
)
|
||||
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
|
||||
artifact = (manifest.get("artifacts") or {}).get("belgium_land_boundary") or {}
|
||||
if (
|
||||
manifest.get("scope") != "belgium-and-belgian-north-sea"
|
||||
or artifact.get("sha256") != sha256_path(boundary_path)
|
||||
):
|
||||
raise RuntimeError("Official Belgium boundary evidence does not match the retained manifest")
|
||||
return boundary_path
|
||||
scope_dir = args.scope_output_root / scope.key
|
||||
manifest_path = scope_dir / f"{scope.key.replace('-', '_')}_scope_manifest.json"
|
||||
if not manifest_path.exists():
|
||||
@@ -330,13 +347,14 @@ def scoped_population_rows(source_rows: list[dict[str, Any]], scope: GeographicS
|
||||
if sector_code in seen:
|
||||
raise RuntimeError(f"Statbel population table contains duplicate sector {sector_code}")
|
||||
seen.add(sector_code)
|
||||
if nis_code not in members:
|
||||
if not scope.all_municipalities and nis_code not in members:
|
||||
continue
|
||||
municipality_name = members.get(nis_code) or str(row.get("TX_DESCR_NL") or nis_code).strip()
|
||||
rows[sector_code] = {
|
||||
"population_total": int(total_raw),
|
||||
"sector_name_nl": row.get("TX_DESCR_SECTOR_NL"),
|
||||
"municipality_name_nl": row.get("TX_DESCR_NL"),
|
||||
"municipality": members[nis_code],
|
||||
"municipality": municipality_name,
|
||||
"nis_code": nis_code,
|
||||
}
|
||||
if not rows:
|
||||
@@ -358,7 +376,10 @@ def build_snapshot(
|
||||
missing_population = 0
|
||||
for source_feature in sector_payload.get("features") or []:
|
||||
properties = source_feature.get("properties") or {}
|
||||
if str(properties.get("cd_munty_refnis") or "") not in member_codes:
|
||||
if (
|
||||
not scope.all_municipalities
|
||||
and str(properties.get("cd_munty_refnis") or "") not in member_codes
|
||||
):
|
||||
continue
|
||||
sector_code = str(properties.get("cd_sector") or "").strip()
|
||||
population_values = population.get(sector_code)
|
||||
@@ -406,8 +427,8 @@ def build_snapshot(
|
||||
"features": features,
|
||||
"coverage_scope": scope.key,
|
||||
"scope_type": scope.scope_type,
|
||||
"member_count": len(scope.members),
|
||||
"member_nis_codes": list(scope.nis_codes),
|
||||
"member_count": int(accounting.get("member_count") or len(scope.members)),
|
||||
"member_nis_codes": list(accounting.get("member_nis_codes") or scope.nis_codes),
|
||||
"geometry_clipped_to_area": True,
|
||||
"observation_year": year,
|
||||
"missing_population_sector_count": missing_population,
|
||||
@@ -594,14 +615,21 @@ def upload_snapshot(
|
||||
observed_at = f"{year}-01-01T00:00:00Z"
|
||||
preflight = load_preflight_manifest(preflight_path, path, year, scope)
|
||||
accounting = preflight["scope_accounting"]
|
||||
coverage_zones = (
|
||||
["belgium", "flanders", "wallonia", "brussels"]
|
||||
if scope.key == "belgium"
|
||||
else ["flanders"]
|
||||
)
|
||||
source_metadata = {
|
||||
"provider": "Statbel",
|
||||
"authority_level": "authoritative",
|
||||
"theme": "population",
|
||||
"coverage_zones": coverage_zones,
|
||||
"coverage_scope": scope.key,
|
||||
"scope_type": scope.scope_type,
|
||||
"scope_display_name": scope.display_name,
|
||||
"member_count": len(scope.members),
|
||||
"member_nis_codes": list(scope.nis_codes),
|
||||
"member_count": int(accounting.get("member_count") or len(scope.members)),
|
||||
"member_nis_codes": list(accounting.get("member_nis_codes") or scope.nis_codes),
|
||||
"geometry_clipped_to_area": True,
|
||||
"attribution": ATTRIBUTION,
|
||||
"license": "CC BY 4.0",
|
||||
@@ -742,6 +770,7 @@ def main() -> int:
|
||||
"path": path,
|
||||
"manifest_path": manifest_path if manifest_path.is_file() else None,
|
||||
"feature_count": len(payload.get("features") or []),
|
||||
"member_count": int(payload.get("member_count") or len(scope.members)),
|
||||
"preflight_status": preflight_status,
|
||||
}
|
||||
)
|
||||
@@ -814,7 +843,10 @@ def main() -> int:
|
||||
"status": "ok",
|
||||
"scope": scope.key,
|
||||
"display_name": scope.display_name,
|
||||
"member_count": len(scope.members),
|
||||
"member_count": max(
|
||||
(int(item.get("member_count") or 0) for item in prepared),
|
||||
default=len(scope.members),
|
||||
),
|
||||
"series": series_key(scope),
|
||||
"snapshots": results,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user