| """Evaluate all 569 Jive stations hourly and plot station summaries.""" |
|
|
| import json |
| import sys |
| from pathlib import Path |
| import matplotlib.pyplot as plt |
| import numpy as np |
| import yaml |
|
|
| ROOT = Path(__file__).resolve().parents[1] |
| sys.path.insert(0, str(ROOT)) |
| from model.improver_aifs import crps_from_thresholds |
|
|
|
|
| def main(): |
| config = yaml.safe_load((ROOT / "conf/config.yaml").read_text()) |
| data = np.load(ROOT / config["paths"]["inference"]) |
| raw, blend, truth = data["raw_aifs"], data["blend_expected"], data["analyses"] |
| if raw.shape != (2, 241, 3, 569): |
| raise ValueError(f"evaluation requires [2,241,3,569], received {raw.shape}") |
| metrics = {"note": "engineering validation, not paper performance", "verification_stations": 569, "hourly_leads": 241, "valid_time_folds": 2, "by_variable": {}} |
| for variable, name in enumerate(data["variables"]): |
| probability, thresholds = data[f"probability_blend_{name}"], data[f"thresholds_{name}"] |
| metrics["by_variable"][str(name)] = { |
| "raw_mse": float(np.mean((raw[:, :, variable] - truth[:, :, variable]) ** 2)), |
| "blend_mse": float(np.mean((blend[:, :, variable] - truth[:, :, variable]) ** 2)), |
| "blend_bias": float(np.mean(blend[:, :, variable] - truth[:, :, variable])), |
| "blend_crps": crps_from_thresholds(probability, thresholds, truth[:, :, variable]), |
| } |
| output = ROOT / config["paths"]["evaluation_dir"] |
| output.mkdir(parents=True, exist_ok=True) |
| (output / "metrics.json").write_text(json.dumps(metrics, indent=2) + "\n") |
| fig, axes = plt.subplots(2, 2, figsize=(11, 7), constrained_layout=True) |
| for axis, lead in zip(axes.flat, [0, 24, 120, 240]): |
| axis.scatter(data["station_longitude"], data["station_latitude"], c=np.abs(blend[0, lead, 0] - truth[0, lead, 0]), s=8, cmap="viridis") |
| axis.set_title(f"569-station temperature absolute error | {lead} h") |
| axis.set_xlabel("longitude"); axis.set_ylabel("latitude") |
| fig.savefig(output / "multi_lead_temperature.png", dpi=150); plt.close(fig) |
| print("saved=result/evaluation stations=569 hourly_leads=241 folds=2 mse_crps_bias=ok") |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|