Expose station network coverage and settlement station details
This commit is contained in:
@@ -22,6 +22,7 @@ from web.core import (
|
||||
)
|
||||
from src.analysis.deb_algorithm import calculate_dynamic_weights
|
||||
from src.analysis.settlement_rounding import apply_city_settlement
|
||||
from src.data_collection.country_networks import build_country_network_snapshot
|
||||
from src.data_collection.city_registry import ALIASES
|
||||
from src.models.lgbm_daily_high import predict_lgbm_daily_high
|
||||
|
||||
@@ -817,6 +818,7 @@ def _analyze(city: str, force_refresh: bool = False) -> Dict[str, Any]:
|
||||
if not isinstance(mm, dict):
|
||||
mm = {}
|
||||
risk = CITY_RISK_PROFILES.get(city, {})
|
||||
network_snapshot = build_country_network_snapshot(city, raw)
|
||||
|
||||
# ── 2. Current conditions (city-specific settlement source first, then METAR/MGM fallback) ──
|
||||
mc = metar.get("current", {}) if metar else {}
|
||||
@@ -1495,6 +1497,16 @@ def _analyze(city: str, force_refresh: bool = False) -> Dict[str, Any]:
|
||||
"raw_metar": mc.get("raw_metar"),
|
||||
"source_label": "METAR",
|
||||
},
|
||||
"settlement_station": network_snapshot.get("settlement_station") or {},
|
||||
"airport_primary": network_snapshot.get("airport_primary_current") or {},
|
||||
"airport_primary_today_obs": network_snapshot.get("airport_primary_today_obs") or [],
|
||||
"official_nearby": network_snapshot.get("official_nearby") or [],
|
||||
"official_network_source": network_snapshot.get("official_network_source"),
|
||||
"official_network_status": network_snapshot.get("official_network_status") or {},
|
||||
"network_lead_signal": network_snapshot.get("network_lead_signal") or {},
|
||||
"network_spread_signal": network_snapshot.get("network_spread_signal") or {},
|
||||
"center_station_candidate": network_snapshot.get("center_station_candidate"),
|
||||
"airport_vs_network_delta": network_snapshot.get("airport_vs_network_delta"),
|
||||
"mgm": mgm_data,
|
||||
"mgm_nearby": raw.get("mgm_nearby", []),
|
||||
"nearby_source": raw.get("nearby_source") or ("mgm" if city.lower() in TURKISH_MGM_CITIES else "metar_cluster"),
|
||||
@@ -1691,6 +1703,7 @@ def _build_city_detail_payload(
|
||||
"current_temp": data.get("current", {}).get("temp"),
|
||||
"settlement_source": data.get("current", {}).get("settlement_source"),
|
||||
"settlement_source_label": data.get("current", {}).get("settlement_source_label"),
|
||||
"settlement_station": data.get("settlement_station") or {},
|
||||
"deb_prediction": data.get("deb", {}).get("prediction"),
|
||||
"risk_level": data.get("risk", {}).get("level"),
|
||||
"risk_warning": data.get("risk", {}).get("warning"),
|
||||
@@ -1711,6 +1724,15 @@ def _build_city_detail_payload(
|
||||
"mgm": data.get("mgm") or {},
|
||||
"mgm_nearby": data.get("mgm_nearby") or [],
|
||||
"nearby_source": data.get("nearby_source") or ("mgm" if str(data.get("name") or "").lower() in TURKISH_MGM_CITIES else "metar_cluster"),
|
||||
"airport_primary": data.get("airport_primary") or {},
|
||||
"airport_primary_today_obs": data.get("airport_primary_today_obs") or [],
|
||||
"official_nearby": data.get("official_nearby") or [],
|
||||
"official_network_source": data.get("official_network_source"),
|
||||
"official_network_status": data.get("official_network_status") or {},
|
||||
"network_lead_signal": data.get("network_lead_signal") or {},
|
||||
"network_spread_signal": data.get("network_spread_signal") or {},
|
||||
"center_station_candidate": data.get("center_station_candidate"),
|
||||
"airport_vs_network_delta": data.get("airport_vs_network_delta"),
|
||||
},
|
||||
"timeseries": {
|
||||
"metar_recent_obs": data.get("metar_recent_obs") or [],
|
||||
@@ -1731,6 +1753,15 @@ def _build_city_detail_payload(
|
||||
"taf": data.get("taf") or {},
|
||||
"market_scan": market_scan,
|
||||
"risk": data.get("risk"),
|
||||
"settlement_station": data.get("settlement_station") or {},
|
||||
"airport_primary": data.get("airport_primary") or {},
|
||||
"official_nearby": data.get("official_nearby") or [],
|
||||
"official_network_source": data.get("official_network_source"),
|
||||
"official_network_status": data.get("official_network_status") or {},
|
||||
"network_lead_signal": data.get("network_lead_signal") or {},
|
||||
"network_spread_signal": data.get("network_spread_signal") or {},
|
||||
"center_station_candidate": data.get("center_station_candidate"),
|
||||
"airport_vs_network_delta": data.get("airport_vs_network_delta"),
|
||||
"airport_current": data.get("airport_current") or {},
|
||||
"nearby_source": data.get("nearby_source") or ("mgm" if str(data.get("name") or "").lower() in TURKISH_MGM_CITIES else "metar_cluster"),
|
||||
"ai_analysis": data.get("ai_analysis") or "",
|
||||
|
||||
@@ -17,6 +17,7 @@ from loguru import logger
|
||||
from src.utils.config_loader import load_config
|
||||
from src.utils.config_validation import validate_runtime_env
|
||||
from src.data_collection.weather_sources import WeatherDataCollector
|
||||
from src.data_collection.country_networks import provider_coverage_summary
|
||||
from src.data_collection.city_risk_profiles import CITY_RISK_PROFILES # noqa: F401
|
||||
from src.data_collection.polymarket_readonly import PolymarketReadOnlyLayer
|
||||
from src.auth.supabase_entitlement import SUPABASE_ENTITLEMENT, extract_bearer_token
|
||||
@@ -748,5 +749,6 @@ def build_system_status_payload() -> Dict[str, Any]:
|
||||
"metrics": build_metrics_summary(),
|
||||
"probability": _probability_summary(),
|
||||
"training_data": _training_data_summary(),
|
||||
"station_networks": provider_coverage_summary(),
|
||||
"cities_count": len(CITIES),
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ from src.analysis.deb_algorithm import load_history
|
||||
from src.analysis.probability_snapshot_archive import load_snapshot_rows_for_day
|
||||
from src.database.runtime_state import TrainingFeatureRecordRepository, TruthRecordRepository
|
||||
from src.analysis.settlement_rounding import apply_city_settlement
|
||||
from src.data_collection.country_networks import get_country_network_provider
|
||||
from src.data_collection.city_registry import ALIASES
|
||||
from src.utils.metrics import export_prometheus_metrics
|
||||
from web.analysis_service import (
|
||||
@@ -271,6 +272,7 @@ async def list_cities(request: Request):
|
||||
city_meta = CITY_REGISTRY.get(name, {}) or {}
|
||||
deb_recent = deb_recent_index.get(name, {})
|
||||
settlement_source = str(info.get("settlement_source") or "metar").strip().lower() or "metar"
|
||||
provider = get_country_network_provider(name)
|
||||
out.append(
|
||||
{
|
||||
"name": name,
|
||||
@@ -288,6 +290,10 @@ async def list_cities(request: Request):
|
||||
settlement_source,
|
||||
settlement_source.upper(),
|
||||
),
|
||||
"settlement_station_code": city_meta.get("settlement_station_code") or city_meta.get("icao"),
|
||||
"settlement_station_label": city_meta.get("settlement_station_label") or city_meta.get("airport_name"),
|
||||
"network_provider": provider.provider_code,
|
||||
"network_provider_label": provider.provider_label,
|
||||
"deb_recent_tier": deb_recent.get("tier", "other"),
|
||||
"deb_recent_hit_rate": deb_recent.get("hit_rate"),
|
||||
"deb_recent_sample_count": deb_recent.get("sample_count", 0),
|
||||
@@ -329,6 +335,12 @@ async def city_history(request: Request, name: str):
|
||||
features = feature_rows.get(day) or {}
|
||||
if truth.get("actual_high") is not None:
|
||||
record["actual_high"] = truth.get("actual_high")
|
||||
record["settlement_source"] = truth.get("settlement_source")
|
||||
record["settlement_station_code"] = truth.get("settlement_station_code")
|
||||
record["settlement_station_label"] = truth.get("settlement_station_label")
|
||||
record["truth_version"] = truth.get("truth_version")
|
||||
record["updated_by"] = truth.get("updated_by")
|
||||
record["truth_updated_at"] = truth.get("truth_updated_at")
|
||||
if isinstance(features, dict):
|
||||
if features.get("deb_prediction") is not None:
|
||||
record["deb_prediction"] = features.get("deb_prediction")
|
||||
@@ -379,6 +391,12 @@ async def city_history(request: Request, name: str):
|
||||
"mu": float(mu) if mu is not None else None,
|
||||
"mgm": float(mgm) if mgm is not None else None,
|
||||
"forecasts": forecasts,
|
||||
"settlement_source": rec.get("settlement_source"),
|
||||
"settlement_station_code": rec.get("settlement_station_code"),
|
||||
"settlement_station_label": rec.get("settlement_station_label"),
|
||||
"truth_version": rec.get("truth_version"),
|
||||
"updated_by": rec.get("updated_by"),
|
||||
"truth_updated_at": rec.get("truth_updated_at"),
|
||||
"actual_peak_time": peak_ref.get("actual_peak_time"),
|
||||
"deb_at_peak_minus_12h": peak_ref.get("deb_at_peak_minus_12h"),
|
||||
"deb_at_peak_minus_12h_time": peak_ref.get("deb_at_peak_minus_12h_time"),
|
||||
|
||||
Reference in New Issue
Block a user