Source code for mhm_tools.common.metrics.waspaef
"""
Calculate the Wasserstein SPAtial EFficiency metric.
Values go from 0 to infinity and can be interpreted as a distance from reference dataset.
Based on
Gómez, M. J., Barboza, L. A., Hidalgo, H. G., and Alfaro, E. J.:
Comparison of indicators to evaluate the performance of climate models,
International Journal of Climatology, 44, 4907-4924, https://doi.org/10.1002/joc.8619, 2024.a, b, c
Implementation based on:
Karpasitis, A.: Code for the MSPAEF metric, Zenodo [code], https://doi.org/10.5281/zenodo.15094921, 2025.a
"""
import numpy as np
from mhm_tools.common.metrics.spaef import filter_nan
[docs]
def WASPAEF(s, o):
"""Calculate WASPAEF and its correlation, spread, and distance components."""
s, o = filter_nan(s, o)
rho = np.corrcoef(s, o)[0, 1]
sigma = np.std(s) / np.std(o)
observed = np.sort(o)
simulated = np.sort(s)
# Original implementation changes are possible since flatten forces same length
# for this case this implementation matches paper description
# data_min = min(np.min(simulated), np.min(observed))
# data_max = max(np.max(simulated), np.max(observed))
# n_bins = int(np.around(np.sqrt(len(o)), 0))
# # Calculate the bin edges, ensuring they are integers
# bin_edges = np.linspace(
# int(np.floor(data_min)), int(np.ceil(data_max)), n_bins + 1
# ) ### Bin edges for histogram using original data
# data_comp_pdf, _ = np.histogram(
# observed.flatten(), bins=bin_edges, density=False
# ) ### Histogram bins for original data of comparison dataset
# data_pdf, _ = np.histogram(
# simulated.flatten(), bins=bin_edges, density=False
# ) ### Histogram bins for original data of model dataset
# wd = wasserstein_distance(
# bin_edges[:-1], bin_edges[:-1], data_comp_pdf, data_pdf
# ) ##### Wasserstein distance of histograms of the original data
wd = np.sqrt(np.mean((observed - simulated) ** 2))
waspaef = np.sqrt((rho - 1) ** 2 + (sigma - 1) ** 2 + wd**2)
return waspaef, rho, sigma, wd