Notebook 05: Station Validation

This notebook validates bias-corrected gridded precipitation products against independent weather station observations from BMKG (Indonesian Meteorological Agency). Station data provides a truly independent ground-truth test using point-scale daily precipitation measurements that were not used in the correction pipeline.

What this notebook does - Extracts gridded product values at 171+ BMKG station locations - Computes 31 per-station verification metrics (continuous, categorical, distributional) - WMO multi-threshold categorical verification (POD, FAR, CSI, FBI, ETS, HSS, HK) - Regional analysis by main island and province - On-demand per-station scatter plots and time series - Saves all results as CSV for further analysis

Reproducibility note - Colab-specific steps (Drive mounting, pip install) are explicitly marked. - Outside Colab, skip those sections and keep the same workflow logic unchanged. - To port the workflow to a new environment, update only config.yml.


1 Connect Google Drive (Colab only)

This section is only required when running in Google Colab and your project/data are stored in Google Drive.

  • Mounting Drive makes your repository and datasets accessible under /content/drive.
  • If you run this notebook locally (Jupyter / VS Code), skip this section.

Expected structure (Drive) After mounting, your project root should contain: - notebooks/ - src/ - config.yml (or config.yaml)

Proceed to the code cell below to mount Drive.

from google.colab import drive
import os

# Check if the drive is mounted
if os.path.exists("/content/drive"):
    # Try to unmount
    try:
        drive.flush_and_unmount()
        print("Successfully unmounted")
    except:
        print("Unmount failed, the drive might not be mounted or busy")

# Mount the drive
drive.mount("/content/drive")
Successfully unmounted
Mounted at /content/drive

Troubleshooting:
- If Colab becomes disconnected, Reconnect the runtime and rerun the mounting cell. - If we receive an error such as Mountpoint must not already contain files, delete all the sub-folders under “/content/drive” from the Files panel before retrying. We need to delete these one by one starting from the innermost folders, until the last “drive” folder is deleted.

2 Install packages (only if needed)

In most cases, Google Colab already includes the packages required for this workflow. The most common missing dependency is netCDF4 (NetCDF I/O support).

Check what is already installed (Colab)

Before installing anything, you can inspect the current environment by running !pip list.

  • If all required packages are present and only netCDF4 is missing, install only netCDF4.
  • If other required packages are missing from !pip list, install them together with netCDF4 in the code cell below.

Local Jupyter note

If you are running in a local environment (Jupyter / VS Code), assume all dependencies were installed when preparing the environment following the main repository README. In that case, you can skip this section.

Proceed to the code cell below only when installation is necessary.

# In Google Colab, almost all packages already available, except netCDF4
!pip install netCDF4
Requirement already satisfied: netCDF4 in /usr/local/lib/python3.12/dist-packages (1.7.4)
Requirement already satisfied: cftime in /usr/local/lib/python3.12/dist-packages (from netCDF4) (1.6.5)
Requirement already satisfied: certifi in /usr/local/lib/python3.12/dist-packages (from netCDF4) (2026.4.22)
Requirement already satisfied: numpy>=1.21.2 in /usr/local/lib/python3.12/dist-packages (from netCDF4) (2.0.2)

3 Independent Station Validation

This notebook validates bias-corrected gridded precipitation products against independent weather station observations from BMKG (Indonesian Meteorological Agency).

Why Independent Validation?

The QA framework (notebook 04) evaluates corrected IMERG against CPC-UNI, which is the same reference used to train the bias correction. While informative, this is inherently circular. Station validation provides a truly independent ground-truth test using point-scale daily precipitation measurements that were not used in the correction pipeline.

Workflow

  1. Load station locations and daily precipitation observations (BMKG)
  2. Load bias-corrected gridded products (LS, LSEQM, LSEQMDL)
  3. Extract gridded values at station locations (nearest grid cell)
  4. Compute per-station verification metrics (31 metrics via compute_pixel_metrics())
  5. WMO multi-threshold categorical verification (POD, FAR, CSI, FBI, ETS, HSS, HK at 1/5/10/20/50/100/150 mm)
  6. Summarize and compare methods
  7. Visualize spatial patterns and performance curves
  8. Save validation results

References

  • WMO (2023), Guidelines for the WMO Evaluation of Records of Weather and Climate Extremes, WMO-No. 1317.
  • WMO (2009), Recommendations for the Verification and Intercomparison of QPFs and PQPFs from Operational NWP Models (Rev. 2), WMO/TD-No. 1485.
  • WMO (2008), Guide to Meteorological Instruments and Methods of Observation, WMO-No. 8.
  • Ebert, E. (2007), Methods for verifying satellite precipitation estimates.
  • Wilks, D. S. (2011), Statistical Methods in the Atmospheric Sciences.

Step 1: Setup Environment

This section prepares the notebook runtime so the project modules can be imported consistently.

The setup typically: - ensures the project root is on the Python path (so import src... works), - loads the central configuration file (config.yml / config.yaml) from the project root, and - prints key paths to confirm the run is using the intended inputs/outputs.

Important This notebook assumes Notebook 02 has already generated the corrected products.

"""
Step 1: Environment Setup

Add project root to sys.path and initialize configuration from config.yml.
"""
import os
import sys
import numpy as np
import pandas as pd
import xarray as xr
import matplotlib.pyplot as plt
import logging

# Resolve project root
if os.path.exists("/content/drive/MyDrive/hybrid-bias-correction"):
    project_root = "/content/drive/MyDrive/hybrid-bias-correction"
else:
    project_root = os.path.abspath(os.path.join(os.getcwd(), ".."))

if project_root not in sys.path:
    sys.path.insert(0, project_root)

# ===========================================================================
# AOI config selector
#   'config.yml'      -> full Indonesia (Zenodo input/output bundle)
#   'config_bali.yml' -> Bali example (ships with the repo, ~11 MB)
# Edit this single line to switch the entire pipeline between the two.
# ===========================================================================
CONFIG_FILE = 'config_bali.yml'

from src.config import initialize_config
initialize_config(os.path.join(project_root, CONFIG_FILE))
from src import config

# Initialize configuration
initialize_config(os.path.join(project_root, CONFIG_FILE))

# Setup logging for notebook
logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s')

print(f"Project root: {project_root}")
print(f"Station file: {config.STATION_FILE}")
print(f"Station data: {config.STATION_DATA_FILE}")
print(f"Output dir:   {config.STATION_VALIDATION_OUTPUT_DIR}")
2026-05-22 03:42:56,137 - INFO - Loaded configuration from /content/drive/MyDrive/hybrid-bias-correction/config_bali.yml
2026-05-22 03:42:56,142 - INFO - Configured main_dir '/content/hybrid-bias-correction' does not exist on this system. Using auto-detected project root: /content/drive/MyDrive/hybrid-bias-correction
2026-05-22 03:42:56,149 - INFO - Configuration initialized successfully.
2026-05-22 03:42:56,153 - INFO -   Main directory: /content/drive/MyDrive/hybrid-bias-correction
2026-05-22 03:42:56,156 - INFO -   Input directory: /content/drive/MyDrive/hybrid-bias-correction/data/example_bali
2026-05-22 03:42:56,157 - INFO -   Output directory: /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output
2026-05-22 03:42:56,161 - INFO -   Interactive mode: False
2026-05-22 03:42:56,195 - INFO - Loaded configuration from /content/drive/MyDrive/hybrid-bias-correction/config_bali.yml
2026-05-22 03:42:56,197 - INFO - Configured main_dir '/content/hybrid-bias-correction' does not exist on this system. Using auto-detected project root: /content/drive/MyDrive/hybrid-bias-correction
2026-05-22 03:42:56,208 - INFO - Configuration initialized successfully.
2026-05-22 03:42:56,211 - INFO -   Main directory: /content/drive/MyDrive/hybrid-bias-correction
2026-05-22 03:42:56,212 - INFO -   Input directory: /content/drive/MyDrive/hybrid-bias-correction/data/example_bali
2026-05-22 03:42:56,215 - INFO -   Output directory: /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output
2026-05-22 03:42:56,216 - INFO -   Interactive mode: False
Project root: /content/drive/MyDrive/hybrid-bias-correction
Station file: /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/bali_stations_location.csv
Station data: /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/bali_stations_data.csv
Output dir:   /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation

Step 2: Load Station Data

Load station locations (coordinates, elevation, WMO ID) and daily precipitation observations. The observation CSV uses the BMKG convention where 8888.0 indicates missing data and dates are in DD-MM-YYYY format.

"""
Step 2: Load station locations and observations.
"""
from src.station_density import load_station_locations
from src.station_validation import load_station_observations

# Load station locations
station_df = load_station_locations(config.STATION_FILE)
print(f"Loaded {len(station_df)} station locations")
print(f"Columns: {list(station_df.columns)}")
display(station_df.head(10))

# Load station observations
obs_df = load_station_observations(
    config.STATION_DATA_FILE,
    station_location_file=config.STATION_FILE
)
print(f"\nObservation data: {obs_df.shape[0]} days x {obs_df.shape[1]} stations")
print(f"Date range: {obs_df.index.min()} to {obs_df.index.max()}")
print(f"Data availability: {obs_df.notna().sum().sum() / obs_df.size * 100:.1f}%")

# Summary of per-station data completeness
valid_days = obs_df.notna().sum()
print(f"\nPer-station valid days:")
print(f"  Min:    {valid_days.min()}")
print(f"  Median: {valid_days.median():.0f}")
print(f"  Max:    {valid_days.max()}")
2026-05-22 03:43:02,208 - INFO - Loaded 4 station locations from /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/bali_stations_location.csv
Loaded 4 station locations
Columns: ['ID', 'ID_WMO', 'Station', 'Lon', 'Lat', 'Elevation', 'region', 'a1name', 'a2name']
ID ID_WMO Station Lon Lat Elevation region a1name a2name
0 127 97230 Stasiun Meteorologi I Gusti Ngurah Rai 115.17000 -8.75000 4 Bali Nusa Tenggara Bali Badung
1 128 97232 Stasiun Geofisika Denpasar 115.21000 -8.67689 15 Bali Nusa Tenggara Bali Kota Denpasar
2 129 97234 Pos Pengamatan Kahang-Kahang 115.61083 -8.36500 155 Bali Nusa Tenggara Bali Karangasem
3 130 97236 Stasiun Klimatologi Jembrana 114.61760 -8.34100 25 Bali Nusa Tenggara Bali Jembrana
2026-05-22 03:43:02,333 - INFO - Loading station observations from /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/bali_stations_data.csv
2026-05-22 03:43:02,484 - INFO - Loaded 7670 days x 4 stations
2026-05-22 03:43:02,485 - INFO - Date range: 2001-01-01 00:00:00 to 2021-12-31 00:00:00
2026-05-22 03:43:02,514 - INFO - Loaded 4 station locations from /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/bali_stations_location.csv
2026-05-22 03:43:02,518 - INFO - Filtered to 4 stations present in location file
2026-05-22 03:43:02,522 - INFO - Data availability: 64.8% valid (19871 / 30680 cells)

Observation data: 7670 days x 4 stations
Date range: 2001-01-01 00:00:00 to 2021-12-31 00:00:00
Data availability: 64.8%

Per-station valid days:
  Min:    2839
  Median: 4983
  Max:    7066

Step 3: Load Bias-Corrected Gridded Products

Load the three correction stages to compare their performance against station observations: - LS: Linear Scaling only - LSEQM: Linear Scaling + Empirical Quantile Mapping with GPD - LSEQMDL: LSEQM + Deep Learning refinement

We also load raw IMERG-L and CPC-UNI as baselines.

Note: To validate a specific month/dekad, set TARGET_MONTH and TARGET_DEKAD below. Or set VALIDATE_ALL = True to loop through all available dekads.

"""
Step 3: Load bias-corrected gridded products for a single dekad.

Modify TARGET_MONTH and TARGET_DEKAD to select which dekad to validate.
"""
from src.io import get_max_day_in_month

# --- User Settings ---
TARGET_MONTH = 1   # 1-12
TARGET_DEKAD = 1   # 1, 2, or 3

# Derive dekad string for filenames
dekad_str = '01' if TARGET_DEKAD == 1 else ('11' if TARGET_DEKAD == 2 else '21')
month_str = f"{TARGET_MONTH:02d}"
print(f"Validating: Month {TARGET_MONTH}, Dekad {TARGET_DEKAD}")

# Build file paths for each correction method
methods = {
    'LS': config.ls_corrected_precip_path,
    'LSEQM': config.lseqm_corrected_precip_path,
    'LSEQMDL': config.lseqmdl_corrected_precip_path,
}

gridded_products = {}
for method_name, folder in methods.items():
    abbr = method_name.lower()
    fname = f"{config.FILENAME_PREFIX}_{abbr}_corrected_imergl_month{month_str}_dekad{dekad_str}.nc4"
    fpath = os.path.join(folder, fname)

    if os.path.exists(fpath):
        ds = xr.open_dataset(fpath)
        # Get the precipitation variable (first data variable)
        var_name = list(ds.data_vars)[0]
        gridded_products[method_name] = ds[var_name]
        print(f"  {method_name}: loaded {fpath}")
        print(f"    Shape: {ds[var_name].shape}, "
              f"Time: {pd.Timestamp(ds.time.values[0])} to "
              f"{pd.Timestamp(ds.time.values[-1])}")
    else:
        print(f"  {method_name}: NOT FOUND - {fpath}")

# Also load raw IMERG and CPC as baselines (optional)
if os.path.exists(config.imergl_file):
    imerg_ds = xr.open_dataset(config.imergl_file)
    gridded_products['IMERG'] = imerg_ds[config.IMERG_PRECIP_VAR]
    print(f"  IMERG: loaded (baseline)")

if os.path.exists(config.cpc_file):
    cpc_ds = xr.open_dataset(config.cpc_file)
    gridded_products['CPC'] = cpc_ds[config.CPC_PRECIP_VAR]
    print(f"  CPC: loaded (reference baseline)")

print(f"\nProducts available for validation: {list(gridded_products.keys())}")
Validating: Month 1, Dekad 1
  LS: loaded /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/corrected_ls/bali_cli_ls_corrected_imergl_month01_dekad01.nc4
    Shape: (250, 9, 14), Time: 2001-01-01 00:00:00 to 2025-01-10 00:00:00
  LSEQM: loaded /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/corrected_lseqm/bali_cli_lseqm_corrected_imergl_month01_dekad01.nc4
    Shape: (250, 9, 14), Time: 2001-01-01 00:00:00 to 2025-01-10 00:00:00
  LSEQMDL: loaded /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/corrected_lseqmdl/bali_cli_lseqmdl_corrected_imergl_month01_dekad01.nc4
    Shape: (250, 9, 14), Time: 2001-01-01 00:00:00 to 2025-01-10 00:00:00
  IMERG: loaded (baseline)
  CPC: loaded (reference baseline)

Products available for validation: ['LS', 'LSEQM', 'LSEQMDL', 'IMERG', 'CPC']

Step 4: Station Location Map

Visualize the spatial distribution of BMKG weather stations used for validation. Station locations are color-coded by data completeness (proportion of valid observation days).

"""
Step 4: Station location map with data completeness.
"""
# Calculate completeness per station
total_days = len(obs_df)
station_completeness = obs_df.notna().sum() / total_days * 100

# Match station locations with completeness
plot_data = station_df.copy()
plot_data['completeness'] = plot_data['ID_WMO'].astype(int).map(
    station_completeness.to_dict()
)
plot_data = plot_data.dropna(subset=['completeness'])

# Dynamic extent from config AOI (with pad), fallback to station coords
pad = float(getattr(config, 'MAP_EXTENT_PAD', 0.1))
aoi_lon = getattr(config, 'AOI_LON_RANGE', None)
aoi_lat = getattr(config, 'AOI_LAT_RANGE', None)
xlim = (aoi_lon[0] - pad, aoi_lon[1] + pad) if aoi_lon else (float(plot_data['Lon'].min()) - pad, float(plot_data['Lon'].max()) + pad)
ylim = (aoi_lat[0] - pad, aoi_lat[1] + pad) if aoi_lat else (float(plot_data['Lat'].min()) - pad, float(plot_data['Lat'].max()) + pad)
aspect = (xlim[1] - xlim[0]) / max(ylim[1] - ylim[0], 1e-6)

fig, ax = plt.subplots(figsize=(min(14, 6 * aspect), 6), constrained_layout=True)

sc = ax.scatter(
    plot_data['Lon'], plot_data['Lat'],
    c=plot_data['completeness'], cmap='RdYlGn',
    s=40, edgecolors='black', linewidths=0.5,
    vmin=0, vmax=100, zorder=5
)

ax.set_xlim(xlim)
ax.set_ylim(ylim)
ax.set_xlabel('Longitude')
ax.set_ylabel('Latitude')
title = f'BMKG Weather Stations ({len(plot_data)} stations) - color = data completeness (%)'
ax.set_title(title)
ax.set_aspect('equal')
ax.grid(True, alpha=0.3)

cb = plt.colorbar(sc, ax=ax, shrink=0.7, label='Data Completeness (%)')

plt.show()

print(f"Stations with > 50% completeness: "
      f"{(plot_data['completeness'] > 50).sum()} / {len(plot_data)}")

Stations with > 50% completeness: 3 / 4

Step 5: Extract Gridded Values at Station Locations

For each gridded product, extract the timeseries at the nearest grid cell to each station location using xr.sel(method='nearest'). This creates a paired observation-prediction dataset for each station.

"""
Step 5: Extract gridded values at station locations for each product.
"""
from src.station_validation import extract_gridded_at_stations

extracted = {}
for method_name, gridded_da in gridded_products.items():
    print(f"Extracting {method_name} at station locations...")
    extracted[method_name] = extract_gridded_at_stations(gridded_da, station_df)
    print(f"  -> {extracted[method_name].shape[0]} timesteps x "
          f"{extracted[method_name].shape[1]} stations")

print(f"\nExtraction complete for {len(extracted)} products.")
Extracting LS at station locations...
2026-05-22 03:43:35,624 - INFO - Extracting gridded values at 4 station locations
2026-05-22 03:43:35,636 - INFO - Extracted 250 timesteps x 4 stations
  -> 250 timesteps x 4 stations
Extracting LSEQM at station locations...
2026-05-22 03:43:35,637 - INFO - Extracting gridded values at 4 station locations
2026-05-22 03:43:35,647 - INFO - Extracted 250 timesteps x 4 stations
  -> 250 timesteps x 4 stations
Extracting LSEQMDL at station locations...
2026-05-22 03:43:35,649 - INFO - Extracting gridded values at 4 station locations
2026-05-22 03:43:35,658 - INFO - Extracted 250 timesteps x 4 stations
  -> 250 timesteps x 4 stations
Extracting IMERG at station locations...
2026-05-22 03:43:35,659 - INFO - Extracting gridded values at 4 station locations
2026-05-22 03:43:36,701 - INFO - Extracted 9131 timesteps x 4 stations
  -> 9131 timesteps x 4 stations
Extracting CPC at station locations...
2026-05-22 03:43:36,703 - INFO - Extracting gridded values at 4 station locations
2026-05-22 03:43:37,180 - INFO - Extracted 9131 timesteps x 4 stations
  -> 9131 timesteps x 4 stations

Extraction complete for 5 products.

Step 6: Compute Per-Station Metrics

For each product and each station, compute 31 verification metrics using the same compute_pixel_metrics() function used in the gridded evaluation. Stations with fewer than 30 valid paired days are excluded.

Key metrics to focus on: - Relative Bias: systematic over/under-estimation - Pearson Correlation: linear agreement - RMSE / MAE: error magnitude - NSE: Nash-Sutcliffe Efficiency (overall skill) - POD, FAR, CSI: categorical event detection - KS p-value: distribution similarity

"""
Step 6: Compute per-station metrics for each product.
"""
from src.station_validation import compute_station_metrics

threshold = config.WET_DAY_THRESHOLD  # 1.0 mm/day
all_metrics = {}

for method_name, gridded_df in extracted.items():
    print(f"\n{'='*50}")
    print(f"Computing metrics: {method_name}")
    print(f"{'='*50}")

    metrics_df = compute_station_metrics(obs_df, gridded_df, threshold=threshold)
    all_metrics[method_name] = metrics_df

    if not metrics_df.empty:
        print(f"  Stations evaluated: {len(metrics_df)}")
        print(f"  Median valid days:  {metrics_df['n_valid_days'].median():.0f}")
        print(f"  Median corr:        {metrics_df['pearson_correlation'].median():.3f}")
        print(f"  Median NSE:         {metrics_df['nse'].median():.3f}")
        print(f"  Median RMSE:        {metrics_df['rmse'].median():.2f} mm/day")
        print(f"  Median rel. bias:   {metrics_df['relative_bias'].median():.3f}")
    else:
        print(f"  WARNING: No stations had sufficient data")

print(f"\nMetrics computed for {len(all_metrics)} products.")

==================================================
Computing metrics: LS
==================================================
2026-05-22 03:43:41,353 - INFO - Computing metrics for 4 common stations
2026-05-22 03:43:41,403 - INFO - Computed metrics for 4 stations
  Stations evaluated: 4
  Median valid days:  146
  Median corr:        0.399
  Median NSE:         -0.221
  Median RMSE:        22.48 mm/day
  Median rel. bias:   -0.051

==================================================
Computing metrics: LSEQM
==================================================
2026-05-22 03:43:41,404 - INFO - Computing metrics for 4 common stations
2026-05-22 03:43:41,438 - INFO - Computed metrics for 4 stations
  Stations evaluated: 4
  Median valid days:  146
  Median corr:        0.401
  Median NSE:         -0.224
  Median RMSE:        22.55 mm/day
  Median rel. bias:   0.023

==================================================
Computing metrics: LSEQMDL
==================================================
2026-05-22 03:43:41,440 - INFO - Computing metrics for 4 common stations
2026-05-22 03:43:41,471 - INFO - Computed metrics for 4 stations
  Stations evaluated: 4
  Median valid days:  146
  Median corr:        0.401
  Median NSE:         -0.223
  Median RMSE:        22.55 mm/day
  Median rel. bias:   0.024

==================================================
Computing metrics: IMERG
==================================================
2026-05-22 03:43:41,473 - INFO - Computing metrics for 4 common stations
2026-05-22 03:43:41,562 - INFO - Computed metrics for 4 stations
  Stations evaluated: 4
  Median valid days:  4983
  Median corr:        0.336
  Median NSE:         -0.088
  Median RMSE:        16.47 mm/day
  Median rel. bias:   -0.176

==================================================
Computing metrics: CPC
==================================================
2026-05-22 03:43:41,564 - INFO - Computing metrics for 4 common stations
2026-05-22 03:43:41,657 - INFO - Computed metrics for 4 stations
  Stations evaluated: 4
  Median valid days:  4982
  Median corr:        0.283
  Median NSE:         -0.104
  Median RMSE:        16.96 mm/day
  Median rel. bias:   -0.179

Metrics computed for 5 products.

Step 6b: WMO Multi-Threshold Categorical Verification

The standard 31 metrics (Step 6) compute categorical scores only at the 1 mm wet-day threshold. However, skill at detecting moderate-to-extreme events is often more important for downstream applications (flood warning, water resource planning).

This step applies the WMO/TD-No. 1485 (WWRP 2009-1) multi-threshold verification framework. For each station and each threshold, a 2x2 contingency table is built and the following WMO-standard scores are computed:

Score Formula Interpretation
POD a/(a+c) Fraction of observed events correctly detected
FAR b/(a+b) Fraction of predicted events that did not occur
CSI a/(a+b+c) Balanced accuracy excluding correct negatives
FBI (a+b)/(a+c) Frequency bias (>1 = overforecasting)
ETS (a-a_r)/(a+b+c-a_r) Skill relative to random chance
HSS 2(ad-bc)/[…] Fraction correct adjusted for chance
HK POD-POFD Ability to discriminate event from non-event

Thresholds follow WMO/TD-No. 1485 Section 3.2 combined with BMKG intensity classes: 1, 5, 10, 20, 50, 100, 150 mm/day.

Per WMO/TD-1485 guidance, scores are suppressed when fewer than 10 observed events exist at a threshold.

"""
Step 6b: WMO multi-threshold categorical verification.

Computes POD, FAR, CSI, FBI, ETS, HSS, HK at thresholds
1, 5, 10, 20, 50, 100, 150 mm/day (WMO/TD-1485 + BMKG).
"""
from src.station_validation import (
    compute_multi_threshold_metrics,
    summarize_multi_threshold,
    WMO_THRESHOLDS,
    WMO_THRESHOLD_LABELS,
)

all_mt_metrics = {}
all_mt_summaries = {}

for method_name, gridded_df in extracted.items():
    print(f"\n{'='*60}")
    print(f"Multi-threshold verification: {method_name}")
    print(f"{'='*60}")

    mt_df = compute_multi_threshold_metrics(obs_df, gridded_df)
    all_mt_metrics[method_name] = mt_df

    if not mt_df.empty:
        mt_summary = summarize_multi_threshold(mt_df)
        all_mt_summaries[method_name] = mt_summary

        print(f"  Stations evaluated: {len(mt_df)}")
        print(f"\n  Threshold |  POD  |  FAR  |  CSI  |  FBI  |  ETS  |  HSS  |  HK   | Events")
        print(f"  {'-'*82}")
        for thr in WMO_THRESHOLDS:
            label = WMO_THRESHOLD_LABELS[thr]
            row = mt_summary.loc[thr] if thr in mt_summary.index else None
            if row is not None:
                print(f"  {thr:>4d} mm ({label:>11s}) | "
                      f"{row.get('pod_median', np.nan):5.3f} | "
                      f"{row.get('far_median', np.nan):5.3f} | "
                      f"{row.get('csi_median', np.nan):5.3f} | "
                      f"{row.get('fbi_median', np.nan):5.3f} | "
                      f"{row.get('ets_median', np.nan):5.3f} | "
                      f"{row.get('hss_median', np.nan):5.3f} | "
                      f"{row.get('hk_median', np.nan):5.3f} | "
                      f"{row.get('mean_obs_events', 0):6.0f}")
    else:
        print(f"  WARNING: No stations had sufficient data")

print(f"\nMulti-threshold verification complete for {len(all_mt_metrics)} products.")

============================================================
Multi-threshold verification: LS
============================================================
2026-05-22 03:43:45,777 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-22 03:43:45,792 - INFO - Multi-threshold metrics computed for 4 stations
  Stations evaluated: 4

  Threshold |  POD  |  FAR  |  CSI  |  FBI  |  ETS  |  HSS  |  HK   | Events
  ----------------------------------------------------------------------------------
     1 mm ( measurable) | 0.819 | 0.179 | 0.702 | 1.056 | 0.181 | 0.300 | 0.314 |    101
     5 mm (      light) | 0.655 | 0.391 | 0.458 | 1.071 | 0.120 | 0.213 | 0.212 |     70
    10 mm (moderate_low) | 0.591 | 0.415 | 0.423 | 0.988 | 0.196 | 0.327 | 0.330 |     53
    20 mm (   moderate) | 0.312 | 0.631 | 0.204 | 0.912 | 0.097 | 0.175 | 0.166 |     32
    50 mm (      heavy) | 0.312 | 0.545 | 0.227 | 0.688 | 0.194 | 0.325 | 0.279 |      8
   100 mm ( very_heavy) |   nan |   nan |   nan |   nan |   nan |   nan |   nan |      2
   150 mm (    extreme) |   nan |   nan |   nan |   nan |   nan |   nan |   nan |      0

============================================================
Multi-threshold verification: LSEQM
============================================================
2026-05-22 03:43:45,859 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-22 03:43:45,871 - INFO - Multi-threshold metrics computed for 4 stations
  Stations evaluated: 4

  Threshold |  POD  |  FAR  |  CSI  |  FBI  |  ETS  |  HSS  |  HK   | Events
  ----------------------------------------------------------------------------------
     1 mm ( measurable) | 0.819 | 0.179 | 0.702 | 1.056 | 0.181 | 0.300 | 0.314 |    101
     5 mm (      light) | 0.686 | 0.383 | 0.485 | 1.048 | 0.140 | 0.244 | 0.244 |     70
    10 mm (moderate_low) | 0.601 | 0.411 | 0.436 | 0.993 | 0.206 | 0.342 | 0.346 |     53
    20 mm (   moderate) | 0.323 | 0.623 | 0.211 | 0.892 | 0.107 | 0.192 | 0.182 |     32
    50 mm (      heavy) | 0.312 | 0.583 | 0.217 | 0.750 | 0.182 | 0.308 | 0.273 |      8
   100 mm ( very_heavy) |   nan |   nan |   nan |   nan |   nan |   nan |   nan |      2
   150 mm (    extreme) |   nan |   nan |   nan |   nan |   nan |   nan |   nan |      0

============================================================
Multi-threshold verification: LSEQMDL
============================================================
2026-05-22 03:43:45,932 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-22 03:43:45,944 - INFO - Multi-threshold metrics computed for 4 stations
  Stations evaluated: 4

  Threshold |  POD  |  FAR  |  CSI  |  FBI  |  ETS  |  HSS  |  HK   | Events
  ----------------------------------------------------------------------------------
     1 mm ( measurable) | 0.819 | 0.179 | 0.702 | 1.056 | 0.181 | 0.300 | 0.314 |    101
     5 mm (      light) | 0.686 | 0.383 | 0.485 | 1.048 | 0.140 | 0.244 | 0.244 |     70
    10 mm (moderate_low) | 0.601 | 0.411 | 0.436 | 0.993 | 0.206 | 0.342 | 0.346 |     53
    20 mm (   moderate) | 0.323 | 0.623 | 0.211 | 0.912 | 0.103 | 0.186 | 0.177 |     32
    50 mm (      heavy) | 0.312 | 0.583 | 0.217 | 0.750 | 0.182 | 0.308 | 0.273 |      8
   100 mm ( very_heavy) |   nan |   nan |   nan |   nan |   nan |   nan |   nan |      2
   150 mm (    extreme) |   nan |   nan |   nan |   nan |   nan |   nan |   nan |      0

============================================================
Multi-threshold verification: IMERG
============================================================
2026-05-22 03:43:46,011 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-22 03:43:46,030 - INFO - Multi-threshold metrics computed for 4 stations
  Stations evaluated: 4

  Threshold |  POD  |  FAR  |  CSI  |  FBI  |  ETS  |  HSS  |  HK   | Events
  ----------------------------------------------------------------------------------
     1 mm ( measurable) | 0.699 | 0.343 | 0.493 | 1.072 | 0.248 | 0.397 | 0.416 |   2024
     5 mm (      light) | 0.512 | 0.471 | 0.349 | 0.974 | 0.235 | 0.380 | 0.377 |   1269
    10 mm (moderate_low) | 0.407 | 0.537 | 0.277 | 0.900 | 0.200 | 0.334 | 0.317 |    900
    20 mm (   moderate) | 0.250 | 0.647 | 0.171 | 0.770 | 0.131 | 0.231 | 0.202 |    530
    50 mm (      heavy) | 0.088 | 0.830 | 0.063 | 0.484 | 0.053 | 0.099 | 0.077 |    140
   100 mm ( very_heavy) | 0.051 | 0.911 | 0.038 | 0.442 | 0.036 | 0.069 | 0.050 |     20
   150 mm (    extreme) |   nan |   nan |   nan |   nan |   nan |   nan |   nan |      3

============================================================
Multi-threshold verification: CPC
============================================================
2026-05-22 03:43:46,106 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-22 03:43:46,124 - INFO - Multi-threshold metrics computed for 4 stations
  Stations evaluated: 4

  Threshold |  POD  |  FAR  |  CSI  |  FBI  |  ETS  |  HSS  |  HK   | Events
  ----------------------------------------------------------------------------------
     1 mm ( measurable) | 0.698 | 0.336 | 0.499 | 1.092 | 0.280 | 0.434 | 0.439 |   2023
     5 mm (      light) | 0.517 | 0.458 | 0.354 | 0.974 | 0.214 | 0.350 | 0.347 |   1268
    10 mm (moderate_low) | 0.395 | 0.546 | 0.270 | 0.884 | 0.173 | 0.292 | 0.279 |    900
    20 mm (   moderate) | 0.257 | 0.662 | 0.175 | 0.745 | 0.123 | 0.214 | 0.193 |    529
    50 mm (      heavy) | 0.092 | 0.814 | 0.065 | 0.459 | 0.055 | 0.102 | 0.079 |    140
   100 mm ( very_heavy) | 0.000 | 1.000 | 0.000 | 0.282 | -0.001 | -0.001 | -0.001 |     20
   150 mm (    extreme) |   nan |   nan |   nan |   nan |   nan |   nan |   nan |      3

Multi-threshold verification complete for 5 products.

Step 6c: Extract Gridded Metrics and QA at Station Locations

Extract pixel-level metrics (from notebook 03 output) and QA categories/scores (from notebook 04 output) at the nearest grid cell to each BMKG station.

This allows comparing what the gridded evaluation says about a station’s location versus what the independent station validation shows. Discrepancies can reveal scale-dependent effects (0.1-degree grid cell vs. point measurement).

"""
Step 6c: Extract gridded metrics and QA at station locations.

Requires metrics/QA NetCDF files from notebooks 03 and 04.
Missing files are skipped gracefully.

Filename patterns (from notebooks 03/04):
  metrics: {prefix}_{prefix}_{ref}_{test}_month{MM}_dekad{DD}.nc4
  QA:      {prefix}_{prefix}_{ref}_{test}_month{MM}_dekad{DD}.nc4
  where prefix = metricssd|metricsts|qualitysd|qualityts
        ref = cpc|imergl|imergf
        test = imergl_ls|imergl_lseqm|imergl_lseqmdl
"""
from src.station_validation import extract_metrics_at_stations, extract_qa_at_stations

# Reference to use for station comparison (CPC is most relevant)
REF_LABEL = 'cpc'

# --- Extract gridded metrics (from notebook 03) ---
all_gridded_metrics = {}
for method_abbr in ['ls', 'lseqm', 'lseqmdl']:
    metrics_dir = config.metrics_path_template.replace('{method}', method_abbr)
    test_label = f"imergl_{method_abbr}"

    # Try single-dekad first, then timeseries
    for prefix in ['metricssd', 'metricsts']:
        fname = (f"{config.FILENAME_PREFIX}_{prefix}_{REF_LABEL}_{test_label}"
                 f"_month{month_str}_dekad{dekad_str}.nc4")
        fpath = os.path.join(metrics_dir, fname)
        df = extract_metrics_at_stations(fpath, station_df)
        if not df.empty:
            key = f"{method_abbr.upper()}_{prefix}"
            all_gridded_metrics[key] = df
            print(f"  Metrics {key}: {len(df)} stations, "
                  f"{len(df.columns)} variables")

# --- Extract gridded QA (from notebook 04) ---
all_gridded_qa = {}
for method_abbr in ['ls', 'lseqm', 'lseqmdl']:
    qa_dir = config.quality_path_template.replace('{method}', method_abbr)
    test_label = f"imergl_{method_abbr}"

    for prefix in ['qualitysd', 'qualityts']:
        fname = (f"{config.FILENAME_PREFIX}_{prefix}_{REF_LABEL}_{test_label}"
                 f"_month{month_str}_dekad{dekad_str}.nc4")
        fpath = os.path.join(qa_dir, fname)
        df = extract_qa_at_stations(fpath, station_df)
        if not df.empty:
            key = f"{method_abbr.upper()}_{prefix}"
            all_gridded_qa[key] = df
            print(f"  QA {key}: {len(df)} stations, {len(df.columns)} variables")

print(f"\nGridded metrics extracted: {list(all_gridded_metrics.keys())}")
print(f"Gridded QA extracted: {list(all_gridded_qa.keys())}")

# Display sample for LSEQMDL single-dekad
sample_key = 'LSEQMDL_metricssd'
if sample_key in all_gridded_metrics:
    print(f"\nSample gridded metrics at stations ({sample_key}):")
    sample_cols = ['pearson_correlation', 'relative_bias', 'rmse', 'nse', 'csi']
    avail = [c for c in sample_cols if c in all_gridded_metrics[sample_key].columns]
    if avail:
        display(all_gridded_metrics[sample_key][avail].describe().round(4))
2026-05-22 03:43:52,366 - INFO - Extracted 31 metrics at 4 stations from /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/metrics_ls/bali_cli_metricssd_cpc_imergl_ls_month01_dekad01.nc4
  Metrics LS_metricssd: 4 stations, 31 variables
2026-05-22 03:43:52,495 - INFO - Extracted 31 metrics at 4 stations from /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/metrics_ls/bali_cli_metricsts_cpc_imergl_ls_month01_dekad01.nc4
  Metrics LS_metricsts: 4 stations, 31 variables
2026-05-22 03:43:52,657 - INFO - Extracted 31 metrics at 4 stations from /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/metrics_lseqm/bali_cli_metricssd_cpc_imergl_lseqm_month01_dekad01.nc4
  Metrics LSEQM_metricssd: 4 stations, 31 variables
2026-05-22 03:43:52,797 - INFO - Extracted 31 metrics at 4 stations from /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/metrics_lseqm/bali_cli_metricsts_cpc_imergl_lseqm_month01_dekad01.nc4
  Metrics LSEQM_metricsts: 4 stations, 31 variables
2026-05-22 03:43:52,955 - INFO - Extracted 31 metrics at 4 stations from /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/metrics_lseqmdl/bali_cli_metricssd_cpc_imergl_lseqmdl_month01_dekad01.nc4
  Metrics LSEQMDL_metricssd: 4 stations, 31 variables
2026-05-22 03:43:53,091 - INFO - Extracted 31 metrics at 4 stations from /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/metrics_lseqmdl/bali_cli_metricsts_cpc_imergl_lseqmdl_month01_dekad01.nc4
  Metrics LSEQMDL_metricsts: 4 stations, 31 variables
2026-05-22 03:43:53,138 - INFO - Extracted 6 QA variables at 4 stations from /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/quality_ls/bali_cli_qualitysd_cpc_imergl_ls_month01_dekad01.nc4
  QA LS_qualitysd: 4 stations, 6 variables
2026-05-22 03:43:53,214 - INFO - Extracted 6 QA variables at 4 stations from /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/quality_ls/bali_cli_qualityts_cpc_imergl_ls_month01_dekad01.nc4
  QA LS_qualityts: 4 stations, 6 variables
2026-05-22 03:43:53,320 - INFO - Extracted 6 QA variables at 4 stations from /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/quality_lseqm/bali_cli_qualitysd_cpc_imergl_lseqm_month01_dekad01.nc4
  QA LSEQM_qualitysd: 4 stations, 6 variables
2026-05-22 03:43:53,477 - INFO - Extracted 6 QA variables at 4 stations from /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/quality_lseqm/bali_cli_qualityts_cpc_imergl_lseqm_month01_dekad01.nc4
  QA LSEQM_qualityts: 4 stations, 6 variables
2026-05-22 03:43:53,572 - INFO - Extracted 6 QA variables at 4 stations from /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/quality_lseqmdl/bali_cli_qualitysd_cpc_imergl_lseqmdl_month01_dekad01.nc4
  QA LSEQMDL_qualitysd: 4 stations, 6 variables
2026-05-22 03:43:53,684 - INFO - Extracted 6 QA variables at 4 stations from /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/quality_lseqmdl/bali_cli_qualityts_cpc_imergl_lseqmdl_month01_dekad01.nc4
  QA LSEQMDL_qualityts: 4 stations, 6 variables

Gridded metrics extracted: ['LS_metricssd', 'LS_metricsts', 'LSEQM_metricssd', 'LSEQM_metricsts', 'LSEQMDL_metricssd', 'LSEQMDL_metricsts']
Gridded QA extracted: ['LS_qualitysd', 'LS_qualityts', 'LSEQM_qualitysd', 'LSEQM_qualityts', 'LSEQMDL_qualitysd', 'LSEQMDL_qualityts']

Sample gridded metrics at stations (LSEQMDL_metricssd):
pearson_correlation relative_bias rmse nse csi
count 4.0000 4.0000 4.0000 4.0000 4.0000
mean 0.6061 0.0435 14.2283 0.1445 0.7296
std 0.1364 0.0130 0.5565 0.2943 0.0329
min 0.4829 0.0274 13.4000 -0.2143 0.6916
25% 0.4931 0.0362 14.1739 -0.0326 0.7108
50% 0.5956 0.0448 14.4578 0.1812 0.7292
75% 0.7086 0.0521 14.5122 0.3583 0.7481
max 0.7503 0.0569 14.5975 0.4299 0.7685

Step 7: Summary Comparison Table

Compare the median (and IQR) of key metrics across all correction methods. This shows how each successive correction stage improves (or degrades) the agreement with independent station observations.

"""
Step 7: Summary comparison table across methods.
"""
from src.station_validation import summarize_station_metrics

# Key metrics to highlight
key_metrics = [
    'pearson_correlation', 'relative_bias', 'rmse', 'mae', 'nse',
    'pod', 'far', 'csi', 'stdev_ratio', 'ks_pvalue'
]

# Build comparison table (median across stations for each method)
comparison_rows = []
for method_name, metrics_df in all_metrics.items():
    if metrics_df.empty:
        continue
    row = {'Method': method_name, 'N_stations': len(metrics_df)}
    for m in key_metrics:
        if m in metrics_df.columns:
            row[m] = metrics_df[m].median()
    comparison_rows.append(row)

comparison_df = pd.DataFrame(comparison_rows).set_index('Method')

print("\n" + "="*70)
print("STATION VALIDATION: Median Metrics Across Methods")
print("="*70)
display(comparison_df.round(4))

# Also show full summary statistics for the best method
if 'LSEQMDL' in all_metrics and not all_metrics['LSEQMDL'].empty:
    print("\n" + "-"*70)
    print("Full Summary Statistics: LSEQMDL")
    print("-"*70)
    summary = summarize_station_metrics(all_metrics['LSEQMDL'])
    display(summary[key_metrics].round(4))

======================================================================
STATION VALIDATION: Median Metrics Across Methods
======================================================================
N_stations pearson_correlation relative_bias rmse mae nse pod far csi stdev_ratio ks_pvalue
Method
LS 4 0.3995 -0.0509 22.4848 12.9765 -0.2212 0.8185 0.1790 0.7024 0.9459 0.0118
LSEQM 4 0.4012 0.0228 22.5474 13.2474 -0.2235 0.8185 0.1790 0.7024 0.9260 0.2416
LSEQMDL 4 0.4014 0.0238 22.5474 13.2474 -0.2229 0.8185 0.1790 0.7024 0.9260 0.2416
IMERG 4 0.3362 -0.1763 16.4651 7.5916 -0.0882 0.6990 0.3427 0.4930 0.7728 0.0000
CPC 4 0.2826 -0.1786 16.9618 7.7614 -0.1038 0.6982 0.3362 0.4987 0.7730 0.0000

----------------------------------------------------------------------
Full Summary Statistics: LSEQMDL
----------------------------------------------------------------------
pearson_correlation relative_bias rmse mae nse pod far csi stdev_ratio ks_pvalue
count 4.0000 4.0000 4.0000 4.0000 4.0000 4.0000 4.0000 4.0000 4.0000 4.0000
mean 0.3472 0.0062 21.5816 13.0452 -0.2372 0.8218 0.2052 0.6780 0.9454 0.2559
std 0.1513 0.0846 4.3823 2.7980 0.2368 0.0527 0.0789 0.0724 0.1171 0.1651
min 0.1277 -0.1015 15.4503 9.4290 -0.4714 0.7698 0.1440 0.5746 0.8260 0.1095
p25 0.3072 -0.0411 20.3912 12.2355 -0.4260 0.7817 0.1560 0.6548 0.8839 0.1178
median 0.4014 0.0238 22.5474 13.2474 -0.2229 0.8185 0.1790 0.7024 0.9260 0.2416
p75 0.4413 0.0711 23.7378 14.0571 -0.0341 0.8586 0.2282 0.7256 0.9875 0.3797
max 0.4582 0.0788 25.7812 16.2570 -0.0316 0.8804 0.3186 0.7326 1.1038 0.4308

Step 8: Per-Station Scatter Plot (On-Demand)

Generate a scatter plot of observed vs. predicted daily precipitation for a specific station. Each correction method gets its own panel with key metrics annotated (r, NSE, RMSE, RB).

Usage: Set STATION_WMO_ID below to the WMO station number you want to inspect. Run this cell multiple times with different station IDs as needed.

"""
Step 8: Per-station scatter plot.

Change STATION_WMO_ID and re-run this cell to inspect different stations.
"""
from src.station_validation import plot_station_scatter

# --- User input: which station to plot ---
STATION_WMO_ID = 97230  # <-- Change this to any valid WMO station ID

# List available stations for reference
available_stations = sorted(set(obs_df.columns) & set(list(extracted.values())[0].columns))
print(f"Available stations ({len(available_stations)} total): "
      f"{available_stations[:15]}{'...' if len(available_stations) > 15 else ''}")

# Check if requested station exists
if STATION_WMO_ID not in available_stations:
    print(f"\nStation {STATION_WMO_ID} not found in available stations.")
    print("Pick one from the list above.")
else:
    print(f"\nGenerating scatter plot for station {STATION_WMO_ID}...")
    fig = plot_station_scatter(
        obs_df, extracted, STATION_WMO_ID,
        station_df=station_df,
        threshold=config.WET_DAY_THRESHOLD,
    )
Available stations (4 total): [97230, 97232, 97234, 97236]

Generating scatter plot for station 97230...

Step 9: Per-Station Daily Precipitation Time Series (On-Demand)

Plot daily precipitation as dots (not lines) over time for a single station. Each dataset is shown in a different color: - Black: BMKG observed - Red: LS corrected - Orange: LSEQM corrected - Green: LSEQMDL corrected

Horizontal dashed lines mark WMO rainfall intensity thresholds (5, 10, 20, 50, 100 mm/day) for visual reference, following BMKG/WMO intensity classes.

Usage: Set STATION_WMO_ID below and re-run. Key metrics (r, RMSE, NSE) are annotated for each product.

"""
Step 9: Per-station daily precipitation time series dot plot.

Change STATION_WMO_ID and re-run this cell to inspect different stations.
"""
from src.station_validation import plot_station_timeseries

# --- User input: which station to plot ---
STATION_WMO_ID = 97230  # <-- Change this to any valid WMO station ID

# List available stations for reference
available_stations = sorted(set(obs_df.columns) & set(list(extracted.values())[0].columns))
print(f"Available stations ({len(available_stations)} total): "
      f"{available_stations[:15]}{'...' if len(available_stations) > 15 else ''}")

# Check if requested station exists
if STATION_WMO_ID not in available_stations:
    print(f"\nStation {STATION_WMO_ID} not found in available stations.")
    print("Pick one from the list above.")
else:
    print(f"\nGenerating time series plot for station {STATION_WMO_ID}...")
    fig = plot_station_timeseries(
        obs_df, extracted, STATION_WMO_ID,
        station_df=station_df,
        thresholds=(5, 10, 20, 50, 100),
    )
Available stations (4 total): [97230, 97232, 97234, 97236]

Generating time series plot for station 97230...

Step 10: Save Validation Results

Save per-station metrics as CSV files for each method, with station metadata (name, coordinates, elevation) included.

"""
Step 10: Save validation results as CSV.

Saves:
  - Per-station 31-metric results (one CSV per method)
  - Per-station multi-threshold WMO metrics (one CSV per method)
  - Multi-threshold summary table (one CSV per method)
  - Cross-method comparison summary
"""
from src.station_validation import save_station_validation

output_dir = config.STATION_VALIDATION_OUTPUT_DIR
if output_dir is None:
    output_dir = os.path.join(config.output_dir, 'station_validation')

os.makedirs(output_dir, exist_ok=True)
saved_files = []

for method_name, metrics_df in all_metrics.items():
    if metrics_df.empty:
        print(f"  {method_name}: skipped (no data)")
        continue

    # --- 31-metric per-station results ---
    output_file = os.path.join(
        output_dir,
        f"station_validation_{method_name.lower()}_month{month_str}_dekad{dekad_str}.csv"
    )
    result = save_station_validation(
        metrics_df, station_df, output_file, method_name=method_name
    )
    if result:
        saved_files.append(result)
        print(f"  {method_name} (31-metric): saved -> {result}")

    # --- Multi-threshold per-station results ---
    if method_name in all_mt_metrics and not all_mt_metrics[method_name].empty:
        mt_file = os.path.join(
            output_dir,
            f"station_multi_threshold_{method_name.lower()}_month{month_str}_dekad{dekad_str}.csv"
        )
        mt_merged = all_mt_metrics[method_name].copy()
        # Merge station metadata
        loc_info = station_df[['ID_WMO', 'Station', 'Lon', 'Lat', 'Elevation']].copy()
        loc_info['ID_WMO'] = loc_info['ID_WMO'].astype(int)
        loc_info = loc_info.set_index('ID_WMO')
        mt_merged = mt_merged.join(loc_info, how='left')
        mt_merged.to_csv(mt_file, float_format='%.6f')
        saved_files.append(mt_file)
        print(f"  {method_name} (multi-thr): saved -> {mt_file}")

    # --- Multi-threshold summary ---
    if method_name in all_mt_summaries and not all_mt_summaries[method_name].empty:
        mt_sum_file = os.path.join(
            output_dir,
            f"multi_threshold_summary_{method_name.lower()}_month{month_str}_dekad{dekad_str}.csv"
        )
        all_mt_summaries[method_name].to_csv(mt_sum_file, float_format='%.6f')
        saved_files.append(mt_sum_file)
        print(f"  {method_name} (summary):   saved -> {mt_sum_file}")

# Cross-method comparison summary
if not comparison_df.empty:
    summary_file = os.path.join(
        output_dir,
        f"station_validation_summary_month{month_str}_dekad{dekad_str}.csv"
    )
    comparison_df.to_csv(summary_file, float_format='%.6f')
    saved_files.append(summary_file)
    print(f"  Summary: saved -> {summary_file}")

print(f"\nSaved {len(saved_files)} files to {output_dir}")
2026-05-22 03:44:24,508 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month01_dekad01.csv
  LS (31-metric): saved -> /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month01_dekad01.csv
  LS (multi-thr): saved -> /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_multi_threshold_ls_month01_dekad01.csv
  LS (summary):   saved -> /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/multi_threshold_summary_ls_month01_dekad01.csv
2026-05-22 03:44:26,997 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month01_dekad01.csv
  LSEQM (31-metric): saved -> /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month01_dekad01.csv
  LSEQM (multi-thr): saved -> /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_multi_threshold_lseqm_month01_dekad01.csv
  LSEQM (summary):   saved -> /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/multi_threshold_summary_lseqm_month01_dekad01.csv
2026-05-22 03:44:29,175 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month01_dekad01.csv
  LSEQMDL (31-metric): saved -> /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month01_dekad01.csv
  LSEQMDL (multi-thr): saved -> /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_multi_threshold_lseqmdl_month01_dekad01.csv
  LSEQMDL (summary):   saved -> /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/multi_threshold_summary_lseqmdl_month01_dekad01.csv
2026-05-22 03:44:30,760 - INFO - Saved station validation results (IMERG) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_imerg_month01_dekad01.csv
  IMERG (31-metric): saved -> /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_imerg_month01_dekad01.csv
  IMERG (multi-thr): saved -> /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_multi_threshold_imerg_month01_dekad01.csv
  IMERG (summary):   saved -> /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/multi_threshold_summary_imerg_month01_dekad01.csv
2026-05-22 03:44:30,804 - INFO - Saved station validation results (CPC) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_cpc_month01_dekad01.csv
  CPC (31-metric): saved -> /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_cpc_month01_dekad01.csv
  CPC (multi-thr): saved -> /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_multi_threshold_cpc_month01_dekad01.csv
  CPC (summary):   saved -> /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/multi_threshold_summary_cpc_month01_dekad01.csv
  Summary: saved -> /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_summary_month01_dekad01.csv

Saved 16 files to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation

Summary

This notebook validated bias-corrected precipitation products (LS, LSEQM, LSEQM+DL) against independent BMKG weather station observations for the selected month and dekad.

Key outputs: - Per-station 31-metric results (continuous, categorical, distributional) - WMO multi-threshold verification (POD, FAR, CSI, FBI, ETS, HSS, HK at 1/5/10/20/50/100/150 mm) - Regional and provincial summaries - On-demand per-station scatter plots and time series

All CSV outputs are saved to data/output/station_validation/ and can be used for further analysis in R, Excel, or other tools.

Batch visualization (spatial maps, multi-threshold curves, regional box plots) has been moved to notebook 06 where it runs alongside QA and Taylor diagram batch visualization in a single unified batch cell.


Batch Validation - All Months and Dekads

Run station validation for all 36 month/dekad combinations and save results. This cell is self-contained: it loads data, computes metrics, and saves CSV outputs for each period.

Prerequisites - run these cells before executing the batch:

Cell Purpose
Step 1 Environment setup, imports, config
Step 2 Load station locations and observations

Steps 3–10 are not required - the batch loop handles loading, extraction, metric computation, and saving internally for each period.

"""
Batch validation across all 36 month x dekad combinations.

For each period:
  1. Load corrected gridded products (LS, LSEQM, LSEQMDL)
  2. Extract at station locations
  3. Compute per-station 31 metrics + multi-threshold WMO metrics
  4. Save CSV outputs

Requires: Step 1 (setup) + Step 2 (station data loaded into obs_df, station_df).
"""
from src.station_validation import (
    extract_gridded_at_stations,
    compute_station_metrics,
    compute_multi_threshold_metrics,
    summarize_multi_threshold,
    save_station_validation,
    merge_station_metadata,
)

batch_output_dir = config.STATION_VALIDATION_OUTPUT_DIR
if batch_output_dir is None:
    batch_output_dir = os.path.join(config.output_dir, 'station_validation')
os.makedirs(batch_output_dir, exist_ok=True)

threshold = config.WET_DAY_THRESHOLD
n_done = 0
n_skip = 0

for _m in range(1, 13):
    for _d in [1, 2, 3]:
        _month_str = f"{_m:02d}"
        _dekad_str = '01' if _d == 1 else ('11' if _d == 2 else '21')
        tag = f"month {_month_str} dekad {_dekad_str}"
        print(f"  {tag}  ", end="")

        try:
            # --- Load corrected products for this period ---
            _methods = {
                'LS': config.ls_corrected_precip_path,
                'LSEQM': config.lseqm_corrected_precip_path,
                'LSEQMDL': config.lseqmdl_corrected_precip_path,
            }
            _products = {}
            for _mname, _folder in _methods.items():
                _abbr = _mname.lower()
                _fname = f"{config.FILENAME_PREFIX}_{_abbr}_corrected_imergl_month{_month_str}_dekad{_dekad_str}.nc4"
                _fpath = os.path.join(_folder, _fname)
                if os.path.exists(_fpath):
                    _ds = xr.open_dataset(_fpath)
                    _var = list(_ds.data_vars)[0]
                    _products[_mname] = _ds[_var]

            if not _products:
                print("no products found, skipping")
                n_skip += 1
                continue

            # --- Extract at stations ---
            _extracted = {}
            for _mname, _da in _products.items():
                _extracted[_mname] = extract_gridded_at_stations(_da, station_df)

            # --- Compute metrics + multi-threshold ---
            for _mname, _gdf in _extracted.items():
                _metrics = compute_station_metrics(obs_df, _gdf, threshold=threshold)
                if _metrics.empty:
                    continue

                # Save 31-metric CSV
                _out = os.path.join(
                    batch_output_dir,
                    f"station_validation_{_mname.lower()}_month{_month_str}_dekad{_dekad_str}.csv"
                )
                save_station_validation(_metrics, station_df, _out, method_name=_mname)

                # Multi-threshold CSV
                _mt = compute_multi_threshold_metrics(obs_df, _gdf)
                if not _mt.empty:
                    _mt_out = os.path.join(
                        batch_output_dir,
                        f"station_multi_threshold_{_mname.lower()}_month{_month_str}_dekad{_dekad_str}.csv"
                    )
                    _loc = station_df[['ID_WMO', 'Station', 'Lon', 'Lat', 'Elevation']].copy()
                    _loc['ID_WMO'] = _loc['ID_WMO'].astype(int)
                    _loc = _loc.set_index('ID_WMO')
                    _mt.join(_loc, how='left').to_csv(_mt_out, float_format='%.6f')

                    # Summary CSV
                    _mt_sum = summarize_multi_threshold(_mt)
                    if not _mt_sum.empty:
                        _sum_out = os.path.join(
                            batch_output_dir,
                            f"multi_threshold_summary_{_mname.lower()}_month{_month_str}_dekad{_dekad_str}.csv"
                        )
                        _mt_sum.to_csv(_sum_out, float_format='%.6f')

            # Close datasets
            for _da in _products.values():
                if hasattr(_da, 'close'):
                    _da.close()

            n_done += 1
            print("done")

        except Exception as e:
            n_skip += 1
            print(f"FAILED: {e}")

print(f"\nBatch complete: {n_done} done, {n_skip} skipped out of 36 periods.")
print(f"Output directory: {batch_output_dir}")
  month 01 dekad 01  2026-05-20 08:41:50,037 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:50,050 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:50,051 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:50,061 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:50,063 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:50,073 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:50,073 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:50,108 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:50,237 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month01_dekad01.csv
2026-05-20 08:41:50,239 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:50,258 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:50,373 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:50,420 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:50,444 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month01_dekad01.csv
2026-05-20 08:41:50,445 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:50,457 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:50,534 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:50,574 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:50,590 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month01_dekad01.csv
2026-05-20 08:41:50,592 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:50,608 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 01 dekad 11  2026-05-20 08:41:50,793 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:50,805 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:50,807 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:50,818 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:50,819 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:50,828 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:50,829 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:50,862 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:50,882 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month01_dekad11.csv
2026-05-20 08:41:50,883 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:50,902 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:50,985 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:51,014 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:51,033 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month01_dekad11.csv
2026-05-20 08:41:51,034 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:51,045 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:51,132 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:51,164 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:51,188 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month01_dekad11.csv
2026-05-20 08:41:51,189 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:51,201 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 01 dekad 21  2026-05-20 08:41:51,368 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:51,379 - INFO - Extracted 275 timesteps x 4 stations
2026-05-20 08:41:51,381 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:51,396 - INFO - Extracted 275 timesteps x 4 stations
2026-05-20 08:41:51,398 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:51,416 - INFO - Extracted 275 timesteps x 4 stations
2026-05-20 08:41:51,418 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:51,458 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:51,492 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month01_dekad21.csv
2026-05-20 08:41:51,495 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:51,509 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:51,585 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:51,610 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:51,628 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month01_dekad21.csv
2026-05-20 08:41:51,630 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:51,642 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:51,744 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:51,779 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:51,795 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month01_dekad21.csv
2026-05-20 08:41:51,796 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:51,807 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 02 dekad 01  2026-05-20 08:41:51,954 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:51,963 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:51,964 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:51,971 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:51,972 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:51,980 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:51,981 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:52,016 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:52,033 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month02_dekad01.csv
2026-05-20 08:41:52,035 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:52,045 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:52,123 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:52,159 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:52,180 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month02_dekad01.csv
2026-05-20 08:41:52,183 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:52,201 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:52,287 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:52,319 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:52,336 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month02_dekad01.csv
2026-05-20 08:41:52,338 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:52,351 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 02 dekad 11  2026-05-20 08:41:52,492 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:52,505 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:52,506 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:52,520 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:52,521 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:52,540 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:52,541 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:52,586 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:52,614 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month02_dekad11.csv
2026-05-20 08:41:52,616 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:52,627 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:52,714 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:52,769 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:52,797 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month02_dekad11.csv
2026-05-20 08:41:52,799 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:52,818 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:52,918 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:52,960 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:52,979 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month02_dekad11.csv
2026-05-20 08:41:52,980 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:52,996 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 02 dekad 21  2026-05-20 08:41:53,155 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:53,162 - INFO - Extracted 206 timesteps x 4 stations
2026-05-20 08:41:53,162 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:53,169 - INFO - Extracted 206 timesteps x 4 stations
2026-05-20 08:41:53,170 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:53,177 - INFO - Extracted 206 timesteps x 4 stations
2026-05-20 08:41:53,177 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:53,199 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:53,215 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month02_dekad21.csv
2026-05-20 08:41:53,216 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:53,226 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:53,287 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:53,310 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:53,324 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month02_dekad21.csv
2026-05-20 08:41:53,325 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:53,334 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:53,397 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:53,422 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:53,436 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month02_dekad21.csv
2026-05-20 08:41:53,437 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:53,446 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 03 dekad 01  2026-05-20 08:41:53,570 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:53,578 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:53,579 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:53,587 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:53,587 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:53,596 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:53,596 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:53,619 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:53,632 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month03_dekad01.csv
2026-05-20 08:41:53,633 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:53,643 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:53,704 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:53,729 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:53,743 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month03_dekad01.csv
2026-05-20 08:41:53,743 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:53,753 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:53,817 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:53,847 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:53,859 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month03_dekad01.csv
2026-05-20 08:41:53,861 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:53,871 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 03 dekad 11  2026-05-20 08:41:53,979 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:53,987 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:53,987 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:53,995 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:53,995 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:54,002 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:54,003 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:54,024 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:54,037 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month03_dekad11.csv
2026-05-20 08:41:54,038 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:54,048 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:54,118 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:54,140 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:54,152 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month03_dekad11.csv
2026-05-20 08:41:54,153 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:54,164 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:54,222 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:54,249 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:54,262 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month03_dekad11.csv
2026-05-20 08:41:54,263 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:54,274 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 03 dekad 21  2026-05-20 08:41:54,385 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:54,392 - INFO - Extracted 275 timesteps x 4 stations
2026-05-20 08:41:54,392 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:54,399 - INFO - Extracted 275 timesteps x 4 stations
2026-05-20 08:41:54,400 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:54,406 - INFO - Extracted 275 timesteps x 4 stations
2026-05-20 08:41:54,407 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:54,427 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:54,440 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month03_dekad21.csv
2026-05-20 08:41:54,441 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:54,450 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:54,509 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:54,534 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:54,547 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month03_dekad21.csv
2026-05-20 08:41:54,549 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:54,560 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:54,630 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:54,654 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:54,669 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month03_dekad21.csv
2026-05-20 08:41:54,671 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:54,680 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 04 dekad 01  2026-05-20 08:41:55,033 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:55,040 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:55,040 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:55,047 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:55,047 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:55,054 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:55,055 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:55,074 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:55,087 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month04_dekad01.csv
2026-05-20 08:41:55,088 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:55,097 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:55,154 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:55,178 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:55,190 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month04_dekad01.csv
2026-05-20 08:41:55,191 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:55,200 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:55,258 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:55,285 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:55,300 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month04_dekad01.csv
2026-05-20 08:41:55,301 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:55,311 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 04 dekad 11  2026-05-20 08:41:55,935 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:55,942 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:55,943 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:55,951 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:55,951 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:55,959 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:55,959 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:55,979 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:55,991 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month04_dekad11.csv
2026-05-20 08:41:55,992 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:56,001 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:56,057 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:56,079 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:56,091 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month04_dekad11.csv
2026-05-20 08:41:56,092 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:56,102 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:56,163 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:56,185 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:56,198 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month04_dekad11.csv
2026-05-20 08:41:56,199 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:56,210 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 04 dekad 21  2026-05-20 08:41:56,887 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:56,898 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:56,899 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:56,905 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:56,905 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:56,912 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:56,913 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:56,934 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:56,948 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month04_dekad21.csv
2026-05-20 08:41:56,949 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:56,959 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:57,017 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:57,037 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:57,051 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month04_dekad21.csv
2026-05-20 08:41:57,052 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:57,062 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:57,120 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:57,150 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:57,171 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month04_dekad21.csv
2026-05-20 08:41:57,173 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:57,187 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 05 dekad 01  2026-05-20 08:41:57,803 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:57,813 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:57,814 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:57,821 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:57,822 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:57,829 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:57,830 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:57,856 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:57,870 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month05_dekad01.csv
2026-05-20 08:41:57,871 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:57,884 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:57,978 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:58,006 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:58,026 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month05_dekad01.csv
2026-05-20 08:41:58,028 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:58,039 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:58,106 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:58,138 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:58,153 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month05_dekad01.csv
2026-05-20 08:41:58,154 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:58,164 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 05 dekad 11  2026-05-20 08:41:58,768 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:58,775 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:58,775 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:58,783 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:58,783 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:58,789 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:41:58,790 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:58,808 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:58,821 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month05_dekad11.csv
2026-05-20 08:41:58,822 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:58,832 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:58,886 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:58,907 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:58,936 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month05_dekad11.csv
2026-05-20 08:41:58,937 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:58,951 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:59,012 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:59,035 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:59,049 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month05_dekad11.csv
2026-05-20 08:41:59,050 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:59,060 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 05 dekad 21  2026-05-20 08:41:59,622 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:59,629 - INFO - Extracted 275 timesteps x 4 stations
2026-05-20 08:41:59,629 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:59,635 - INFO - Extracted 275 timesteps x 4 stations
2026-05-20 08:41:59,635 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:41:59,642 - INFO - Extracted 275 timesteps x 4 stations
2026-05-20 08:41:59,643 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:59,662 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:59,675 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month05_dekad21.csv
2026-05-20 08:41:59,676 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:59,686 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:59,746 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:59,765 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:59,778 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month05_dekad21.csv
2026-05-20 08:41:59,779 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:59,789 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:41:59,865 - INFO - Computing metrics for 4 common stations
2026-05-20 08:41:59,887 - INFO - Computed metrics for 4 stations
2026-05-20 08:41:59,903 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month05_dekad21.csv
2026-05-20 08:41:59,904 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:41:59,914 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 06 dekad 01  2026-05-20 08:42:00,563 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:00,572 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:00,572 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:00,580 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:00,580 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:00,588 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:00,589 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:00,611 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:00,629 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month06_dekad01.csv
2026-05-20 08:42:00,630 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:00,641 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:00,701 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:00,728 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:00,749 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month06_dekad01.csv
2026-05-20 08:42:00,750 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:00,761 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:00,820 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:00,849 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:00,865 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month06_dekad01.csv
2026-05-20 08:42:00,867 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:00,877 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 06 dekad 11  2026-05-20 08:42:01,541 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:01,549 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:01,550 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:01,558 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:01,559 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:01,565 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:01,566 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:01,598 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:01,623 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month06_dekad11.csv
2026-05-20 08:42:01,624 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:01,635 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:01,694 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:01,721 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:01,735 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month06_dekad11.csv
2026-05-20 08:42:01,736 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:01,751 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:01,810 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:01,835 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:01,872 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month06_dekad11.csv
2026-05-20 08:42:01,873 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:01,884 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 06 dekad 21  2026-05-20 08:42:02,504 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:02,515 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:02,516 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:02,525 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:02,526 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:02,535 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:02,536 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:02,560 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:02,577 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month06_dekad21.csv
2026-05-20 08:42:02,578 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:02,590 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:02,658 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:02,687 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:02,705 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month06_dekad21.csv
2026-05-20 08:42:02,706 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:02,719 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:02,783 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:02,808 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:02,825 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month06_dekad21.csv
2026-05-20 08:42:02,826 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:02,837 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 07 dekad 01  2026-05-20 08:42:03,616 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:03,625 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:03,625 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:03,633 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:03,636 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:03,644 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:03,647 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:03,673 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:03,690 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month07_dekad01.csv
2026-05-20 08:42:03,693 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:03,703 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:03,765 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:03,793 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:03,810 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month07_dekad01.csv
2026-05-20 08:42:03,811 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:03,822 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:03,891 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:03,924 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:03,940 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month07_dekad01.csv
2026-05-20 08:42:03,941 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:03,954 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 07 dekad 11  2026-05-20 08:42:04,526 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:04,535 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:04,536 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:04,546 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:04,548 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:04,557 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:04,559 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:04,591 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:04,615 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month07_dekad11.csv
2026-05-20 08:42:04,616 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:04,631 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:04,703 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:04,735 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:04,751 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month07_dekad11.csv
2026-05-20 08:42:04,753 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:04,774 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:04,853 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:04,881 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:04,899 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month07_dekad11.csv
2026-05-20 08:42:04,900 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:04,915 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 07 dekad 21  2026-05-20 08:42:05,601 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:05,609 - INFO - Extracted 275 timesteps x 4 stations
2026-05-20 08:42:05,610 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:05,616 - INFO - Extracted 275 timesteps x 4 stations
2026-05-20 08:42:05,617 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:05,625 - INFO - Extracted 275 timesteps x 4 stations
2026-05-20 08:42:05,625 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:05,648 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:05,664 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month07_dekad21.csv
2026-05-20 08:42:05,665 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:05,675 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:05,733 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:05,759 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:05,779 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month07_dekad21.csv
2026-05-20 08:42:05,780 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:05,793 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:05,854 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:05,883 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:05,902 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month07_dekad21.csv
2026-05-20 08:42:05,903 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:05,916 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 08 dekad 01  2026-05-20 08:42:07,103 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:07,113 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:07,114 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:07,121 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:07,123 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:07,135 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:07,136 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:07,173 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:07,192 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month08_dekad01.csv
2026-05-20 08:42:07,194 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:07,205 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:07,255 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:07,277 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:07,291 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month08_dekad01.csv
2026-05-20 08:42:07,293 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:07,304 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:07,359 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:07,386 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:07,405 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month08_dekad01.csv
2026-05-20 08:42:07,406 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:07,416 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 08 dekad 11  2026-05-20 08:42:08,057 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:08,064 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:08,065 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:08,073 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:08,074 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:08,082 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:08,083 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:08,105 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:08,121 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month08_dekad11.csv
2026-05-20 08:42:08,123 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:08,135 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:08,212 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:08,236 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:08,254 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month08_dekad11.csv
2026-05-20 08:42:08,256 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:08,268 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:08,326 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:08,356 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:08,374 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month08_dekad11.csv
2026-05-20 08:42:08,375 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:08,388 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 08 dekad 21  2026-05-20 08:42:08,933 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:08,939 - INFO - Extracted 275 timesteps x 4 stations
2026-05-20 08:42:08,940 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:08,947 - INFO - Extracted 275 timesteps x 4 stations
2026-05-20 08:42:08,947 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:08,955 - INFO - Extracted 275 timesteps x 4 stations
2026-05-20 08:42:08,955 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:08,976 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:09,007 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month08_dekad21.csv
2026-05-20 08:42:09,007 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:09,019 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:09,068 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:09,101 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:09,116 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month08_dekad21.csv
2026-05-20 08:42:09,117 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:09,128 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:09,281 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:09,306 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:09,322 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month08_dekad21.csv
2026-05-20 08:42:09,323 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:09,333 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 09 dekad 01  2026-05-20 08:42:09,876 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:09,883 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:09,883 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:09,891 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:09,892 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:09,899 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:09,900 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:09,921 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:09,951 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month09_dekad01.csv
2026-05-20 08:42:09,952 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:09,962 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:10,009 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:10,029 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:10,042 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month09_dekad01.csv
2026-05-20 08:42:10,043 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:10,052 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:10,101 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:10,123 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:10,137 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month09_dekad01.csv
2026-05-20 08:42:10,138 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:10,153 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 09 dekad 11  2026-05-20 08:42:10,710 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:10,719 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:10,720 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:10,727 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:10,729 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:10,737 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:10,738 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:10,762 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:10,792 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month09_dekad11.csv
2026-05-20 08:42:10,793 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:10,805 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:10,868 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:10,890 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:10,906 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month09_dekad11.csv
2026-05-20 08:42:10,907 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:10,919 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:10,984 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:11,008 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:11,026 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month09_dekad11.csv
2026-05-20 08:42:11,027 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:11,038 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 09 dekad 21  2026-05-20 08:42:11,607 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:11,616 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:11,617 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:11,629 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:11,630 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:11,639 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:11,640 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:11,662 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:11,682 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month09_dekad21.csv
2026-05-20 08:42:11,683 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:11,696 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:11,771 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:11,796 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:11,811 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month09_dekad21.csv
2026-05-20 08:42:11,812 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:11,823 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:11,891 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:11,918 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:11,935 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month09_dekad21.csv
2026-05-20 08:42:11,936 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:11,948 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 10 dekad 01  2026-05-20 08:42:12,471 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:12,480 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:12,481 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:12,488 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:12,489 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:12,496 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:12,497 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:12,524 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:12,540 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month10_dekad01.csv
2026-05-20 08:42:12,541 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:12,552 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:12,610 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:12,632 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:12,645 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month10_dekad01.csv
2026-05-20 08:42:12,646 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:12,656 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:12,718 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:12,739 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:12,752 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month10_dekad01.csv
2026-05-20 08:42:12,753 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:12,763 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 10 dekad 11  2026-05-20 08:42:13,355 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:13,362 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:13,362 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:13,369 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:13,370 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:13,376 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:13,377 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:13,397 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:13,411 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month10_dekad11.csv
2026-05-20 08:42:13,412 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:13,423 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:13,481 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:13,501 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:13,514 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month10_dekad11.csv
2026-05-20 08:42:13,514 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:13,524 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:13,578 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:13,599 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:13,613 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month10_dekad11.csv
2026-05-20 08:42:13,614 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:13,629 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 10 dekad 21  2026-05-20 08:42:14,259 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:14,266 - INFO - Extracted 275 timesteps x 4 stations
2026-05-20 08:42:14,266 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:14,274 - INFO - Extracted 275 timesteps x 4 stations
2026-05-20 08:42:14,277 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:14,284 - INFO - Extracted 275 timesteps x 4 stations
2026-05-20 08:42:14,284 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:14,305 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:14,317 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month10_dekad21.csv
2026-05-20 08:42:14,318 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:14,333 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:14,395 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:14,415 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:14,427 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month10_dekad21.csv
2026-05-20 08:42:14,429 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:14,440 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:14,499 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:14,521 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:14,535 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month10_dekad21.csv
2026-05-20 08:42:14,536 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:14,544 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 11 dekad 01  2026-05-20 08:42:15,233 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:15,241 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:15,242 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:15,251 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:15,253 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:15,266 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:15,269 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:15,320 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:15,338 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month11_dekad01.csv
2026-05-20 08:42:15,340 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:15,353 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:15,439 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:15,468 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:15,483 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month11_dekad01.csv
2026-05-20 08:42:15,484 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:15,499 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:15,570 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:15,598 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:15,613 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month11_dekad01.csv
2026-05-20 08:42:15,615 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:15,630 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 11 dekad 11  2026-05-20 08:42:16,248 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:16,258 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:16,258 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:16,267 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:16,268 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:16,280 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:16,281 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:16,314 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:16,327 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month11_dekad11.csv
2026-05-20 08:42:16,329 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:16,342 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:16,426 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:16,467 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:16,484 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month11_dekad11.csv
2026-05-20 08:42:16,485 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:16,498 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:16,564 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:16,591 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:16,603 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month11_dekad11.csv
2026-05-20 08:42:16,607 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:16,617 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 11 dekad 21  2026-05-20 08:42:17,266 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:17,272 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:17,273 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:17,280 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:17,281 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:17,290 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:17,290 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:17,315 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:17,347 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month11_dekad21.csv
2026-05-20 08:42:17,348 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:17,361 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:17,416 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:17,440 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:17,453 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month11_dekad21.csv
2026-05-20 08:42:17,454 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:17,465 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:17,536 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:17,560 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:17,574 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month11_dekad21.csv
2026-05-20 08:42:17,575 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:17,588 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 12 dekad 01  2026-05-20 08:42:18,264 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:18,270 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:18,271 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:18,280 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:18,280 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:18,288 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:18,288 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:18,310 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:18,327 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month12_dekad01.csv
2026-05-20 08:42:18,328 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:18,340 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:18,411 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:18,438 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:18,450 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month12_dekad01.csv
2026-05-20 08:42:18,451 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:18,462 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:18,530 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:18,563 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:18,576 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month12_dekad01.csv
2026-05-20 08:42:18,578 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:18,589 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 12 dekad 11  2026-05-20 08:42:19,113 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:19,121 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:19,121 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:19,129 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:19,130 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:19,137 - INFO - Extracted 250 timesteps x 4 stations
2026-05-20 08:42:19,138 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:19,160 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:19,176 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month12_dekad11.csv
2026-05-20 08:42:19,177 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:19,187 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:19,272 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:19,294 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:19,307 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month12_dekad11.csv
2026-05-20 08:42:19,307 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:19,319 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:19,380 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:19,404 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:19,422 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month12_dekad11.csv
2026-05-20 08:42:19,423 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:19,432 - INFO - Multi-threshold metrics computed for 4 stations
done
  month 12 dekad 21  2026-05-20 08:42:20,023 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:20,029 - INFO - Extracted 275 timesteps x 4 stations
2026-05-20 08:42:20,030 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:20,040 - INFO - Extracted 275 timesteps x 4 stations
2026-05-20 08:42:20,040 - INFO - Extracting gridded values at 4 station locations
2026-05-20 08:42:20,049 - INFO - Extracted 275 timesteps x 4 stations
2026-05-20 08:42:20,049 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:20,074 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:20,088 - INFO - Saved station validation results (LS) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_ls_month12_dekad21.csv
2026-05-20 08:42:20,089 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:20,099 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:20,160 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:20,182 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:20,210 - INFO - Saved station validation results (LSEQM) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqm_month12_dekad21.csv
2026-05-20 08:42:20,211 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:20,223 - INFO - Multi-threshold metrics computed for 4 stations
2026-05-20 08:42:20,285 - INFO - Computing metrics for 4 common stations
2026-05-20 08:42:20,312 - INFO - Computed metrics for 4 stations
2026-05-20 08:42:20,327 - INFO - Saved station validation results (LSEQMDL) to /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation/station_validation_lseqmdl_month12_dekad21.csv
2026-05-20 08:42:20,328 - INFO - Computing multi-threshold metrics (7 thresholds) for 4 stations
2026-05-20 08:42:20,340 - INFO - Multi-threshold metrics computed for 4 stations
done

Batch complete: 36 done, 0 skipped out of 36 periods.
Output directory: /content/drive/MyDrive/hybrid-bias-correction/data/example_bali/output/station_validation

End of Code

Back to top