import os
from pathlib import Path
import matplotlib.pyplot as plt
import pandas as pd
from toolbox_continu_inzicht import Config, DataAdapter
from toolbox_continu_inzicht.gwdi import (
GwdiInference,
GwdiKnmiRetrieval,
GwdiWiwbRetrieval,
)GWDI eenvoudige berekening
Dit notebook laat een minimale GWDI-run zien voor één rastercel (fid) via de toolbox-moduleklasse GwdiInference.
Het notebook laat het volgende zien: 1. Inlezen van een lokale GWDI-configuratie (yaml) voor DataAdapters. 2. Uitvoeren van GwdiInference.run(...) met de smoke single-fid dataset. 3. Vergelijken van de uitkomst met de bestaande smoke-baseline uit de unit test.
data_dir = Path.cwd() / "data_sets" / "10.gwdi_simple_calculation"
config_path = data_dir / "gwdi_simple_calculation.yaml"De configuratie ziet er als volgt uit:
GlobalVariables:
rootdir: "data_sets/10.gwdi_simple_calculation"
calc_time: "2024-02-15 08:00:00"
GwdiWiwbRetrieval:
lag_days: 0
publish_days: 35
target_date: "2024-02-14"
wiwb_precipitation_source_code: "Knmi.International.Radar.Composite.Combined"
GwdiKnmiRetrieval:
lag_days: 0
publish_days: 35
target_date: "2024-02-14"
DataAdapter:
gwdi_input_precipitation_static:
type: csv
file: "precipitation_single_fid.csv"
gwdi_input_evaporation_static:
type: csv
file: "evaporation_single_fid.csv"
gwdi_input_precipitation_dynamic:
type: python
gwdi_input_evaporation_dynamic:
type: python
gwdi_input_climate_sampling_locations:
type: csv
file: "gwdi_climate_sampling_locations_single.csv"
gwdi_input_pastas_mapping:
type: csv
file: "gwdi_pastas_mapping.csv"
dtype:
location: object
position: object
gwdi_input_pastas_models:
type: pastas_models
path: "pastas_models"
gwdi_input_stats_minima:
type: csv
file: "df_stats_minima.csv"
index_col: 0
gwdi_output:
type: pythonEerste voorbeeld: statische klimaatreeks
In dit eerste voorbeeld gebruiken we statische neerslag en verdamping (uit een CSV) om een GWDI-run met GwdiInference uit te voeren.
config = Config(config_path=config_path)
config.lees_config()
data_adapter = DataAdapter(config=config)
module = GwdiInference(data_adapter=data_adapter)
module.run(
input=[
"gwdi_input_precipitation_static",
"gwdi_input_evaporation_static",
"gwdi_input_pastas_mapping",
"gwdi_input_pastas_models",
"gwdi_input_stats_minima",
],
output="gwdi_output",
)
df_gwdi = module.df_out.copy()
df_gwdi2026-05-18 11:53:07 WARNING - base: The solver object is stored in the model.solver attribute since Pastas 1.3. Please update your pas-file to the new format by loading and saving the file with Pastas 1.3.
2026-05-18 11:53:07 WARNING - base: The solver object is stored in the model.solver attribute since Pastas 1.3. Please update your pas-file to the new format by loading and saving the file with Pastas 1.3.
2026-05-18 11:53:07 WARNING - base: The solver object is stored in the model.solver attribute since Pastas 1.3. Please update your pas-file to the new format by loading and saving the file with Pastas 1.3.
2026-05-18 11:53:07 WARNING - base: The solver object is stored in the model.solver attribute since Pastas 1.3. Please update your pas-file to the new format by loading and saving the file with Pastas 1.3.
2026-05-18 11:53:07 WARNING - base: The solver object is stored in the model.solver attribute since Pastas 1.3. Please update your pas-file to the new format by loading and saving the file with Pastas 1.3.
2026-05-18 11:53:07 WARNING - model: The stress of the stressmodel has no overlap with ml.oseries.
2026-05-18 11:53:07 WARNING - model: The stress of the stressmodel has no overlap with ml.oseries.
2026-05-18 11:53:08 WARNING - model: The stress of the stressmodel has no overlap with ml.oseries.
2026-05-18 11:53:08 WARNING - model: The stress of the stressmodel has no overlap with ml.oseries.
2026-05-18 11:53:08 WARNING - model: The stress of the stressmodel has no overlap with ml.oseries.
| fid | parameterid | methodid | datetime | value | peilbuisid | |
|---|---|---|---|---|---|---|
| 0 | 300268 | 4 | 1 | 1721865600000 | 0.476382 | 0 |
| 1 | 300268 | 4 | 1 | 1721952000000 | 0.480692 | 0 |
| 2 | 300268 | 4 | 1 | 1722038400000 | 0.511826 | 0 |
| 3 | 300268 | 4 | 1 | 1722124800000 | 0.547531 | 0 |
| 4 | 300268 | 4 | 1 | 1722211200000 | 0.589434 | 0 |
| ... | ... | ... | ... | ... | ... | ... |
| 170 | 300268 | 4 | 1 | 1724457600000 | 0.460507 | 4 |
| 171 | 300268 | 4 | 1 | 1724544000000 | 0.505857 | 4 |
| 172 | 300268 | 4 | 1 | 1724630400000 | 0.542583 | 4 |
| 173 | 300268 | 4 | 1 | 1724716800000 | 0.604032 | 4 |
| 174 | 300268 | 4 | 1 | 1724803200000 | 0.686086 | 4 |
175 rows × 6 columns
Tweede voorbeeld: dynamische klimaatreeks via WIWB + KNMI
In dit tweede voorbeeld halen we neerslag en verdamping dynamisch op voor dezelfde GWDI-run: - GwdiWiwbRetrieval levert neerslag (P) op. - GwdiKnmiRetrieval levert verdamping (evaporation) op.
In gwdi_simple_calculation.yaml gebruiken beide retrievals dezelfde resample-configuratie (resample_frequency, resample_period_start, resample_period_end) zodat de tijdstappen op elkaar aansluiten. Daarna voeren we GwdiInference uit met deze dynamische invoer.
required_env = ("WIWB_CLIENT_ID", "WIWB_KEY", "KNMI_API_KEY")
missing_env = [name for name in required_env if not os.getenv(name)]
if missing_env:
print(
f"Ontbrekende omgevingsvariabelen voor dynamische GWDI-run: {', '.join(missing_env)}"
)
else:
print(f"OK: de benodigde omgevingsvariabelen zijn aanwezig: {required_env}")Ontbrekende omgevingsvariabelen voor dynamische GWDI-run: WIWB_CLIENT_ID, WIWB_KEY, KNMI_API_KEY
# Gebruik dezelfde YAML-configuratie als in het statische voorbeeld.
data_adapter_dynamic = DataAdapter(config=config)
if missing_env:
print(
f"Ontbrekende omgevingsvariabelen voor dynamische GWDI-run: {', '.join(missing_env)}"
)
else:
wiwb_module = GwdiWiwbRetrieval(data_adapter=data_adapter_dynamic)
wiwb_module.run(
input="gwdi_input_climate_sampling_locations",
output="gwdi_input_precipitation_dynamic",
)
knmi_module = GwdiKnmiRetrieval(data_adapter=data_adapter_dynamic)
knmi_module.run(
input="gwdi_input_climate_sampling_locations",
output="gwdi_input_evaporation_dynamic",
)Ontbrekende omgevingsvariabelen voor dynamische GWDI-run: WIWB_CLIENT_ID, WIWB_KEY, KNMI_API_KEY
GwdiInference vereist exact dezelfde tijdreeksen voor verdamping en neerslag. In de praktijk kan bronbeschikbaarheid per provider toch verschillen. Daarom maken we hieronder expliciet een gezamenlijke (time, fid)-grid (intersection) voor beide reeksen.
if missing_env:
print(
f"Ontbrekende omgevingsvariabelen voor dynamische GWDI-run: {', '.join(missing_env)}"
)
else:
wiwb_grid = wiwb_module.df_out[["time", "fid"]].drop_duplicates()
knmi_grid = knmi_module.df_out[["time", "fid"]].drop_duplicates()
common_grid = wiwb_grid.merge(knmi_grid, on=["time", "fid"], how="inner")
if len(common_grid) == 0:
raise UserWarning(
"Geen overlappende (`time`, `fid`)-grid tussen WIWB en KNMI. "
"Controleer periode/resample-instellingen."
)
df_precip_dynamic = wiwb_module.df_out.merge(
common_grid, on=["time", "fid"], how="inner"
)
df_evap_dynamic = knmi_module.df_out.merge(
common_grid, on=["time", "fid"], how="inner"
)
df_precip_dynamic = df_precip_dynamic.sort_values(["time", "fid"]).reset_index(
drop=True
)
df_evap_dynamic = df_evap_dynamic.sort_values(["time", "fid"]).reset_index(
drop=True
)
print("Gezamenlijk grid:")
display(df_precip_dynamic.merge(df_evap_dynamic, on=["time", "fid"]))Ontbrekende omgevingsvariabelen voor dynamische GWDI-run: WIWB_CLIENT_ID, WIWB_KEY, KNMI_API_KEY
Tenslotte voeren we GwdiInference uit met deze dynamische invoer.
if missing_env:
print(
f"Ontbrekende omgevingsvariabelen voor dynamische GWDI-run: {', '.join(missing_env)}"
)
else:
data_adapter_dynamic.set_dataframe_adapter(
"gwdi_input_precipitation_dynamic",
df_precip_dynamic,
)
data_adapter_dynamic.set_dataframe_adapter(
"gwdi_input_evaporation_dynamic",
df_evap_dynamic,
)
module_dynamic = GwdiInference(data_adapter=data_adapter_dynamic)
module_dynamic.run(
input=[
"gwdi_input_precipitation_dynamic",
"gwdi_input_evaporation_dynamic",
"gwdi_input_pastas_mapping",
"gwdi_input_pastas_models",
"gwdi_input_stats_minima",
],
output="gwdi_output",
)
df_gwdi_dynamic = module_dynamic.df_out.copy()
plt.close("all")
fig, ax = plt.subplots()
df_gwdi_dynamic["datetime"] = pd.to_datetime(
df_gwdi_dynamic["datetime"], unit="ms", utc=True
)
df_gwdi_agg = df_gwdi_dynamic.groupby("datetime")["value"].agg(
["min", "mean", "max"]
)
ax.fill_between(
df_gwdi_agg.index,
df_gwdi_agg["min"],
df_gwdi_agg["max"],
alpha=0.2,
color="blue",
)
ax.plot(df_gwdi_agg.index, df_gwdi_agg["mean"])
ax.set_xticks(ax.get_xticks(), ax.get_xticklabels(), rotation=45, ha="right")Ontbrekende omgevingsvariabelen voor dynamische GWDI-run: WIWB_CLIENT_ID, WIWB_KEY, KNMI_API_KEY