Metrics¶
xrops.metrics groups evaluation metrics by scientific diagnostic
family. Each family pairs Layer-0 xarray functions with Layer-1 Operator
wrappers that compose into Sequential pipelines and Graph networks.
For the design rationale, see the validation design doc and the validation API map.
Diagnostic families¶
| Submodule | Family | Status |
|---|---|---|
metrics.pixel |
Pointwise scalar errors | shipped |
metrics.spectral |
Power-spectrum scores, resolved scale | shipped |
metrics.multiscale |
Region- and band-conditioned skill | shipped |
metrics.physical |
Physical-balance / conservation residuals | shipped |
metrics.masked |
Coverage-aware masked wrappers | shipped |
metrics.distributional |
Distributional distances (CRPS, Wasserstein, …) | shipped |
metrics.structural |
Structural / geometric similarity (SSIM, …) | partial |
metrics.probabilistic |
Ensemble calibration | partial |
metrics.object |
Event / object verification (POD, FAR, IoU) | partial |
metrics.forecast |
Lead-time skill | stub |
metrics.lagrangian |
Trajectory / transport metrics | stub |
Ergonomic re-exports
The Layer-1 operators are re-exported flat from the package root, and a
dedicated xrops.metrics.operators module mirrors them:
Pixel — pointwise errors¶
Per-pixel scalar error and skill: MSE, RMSE, MAE, bias, normalized RMSE (and its skill-score form), correlation, and R².
MSE
¶
RMSE
¶
MAE
¶
Bias
¶
NRMSE
¶
NRMSEScore
¶
Correlation
¶
R2Score
¶
Functions¶
pixel
¶
Pointwise (pixel-level) evaluation metrics — public re-export.
Layer-0 functions: :func:mse, :func:rmse, :func:nrmse,
:func:nrmse_score, :func:mae, :func:bias, :func:correlation,
:func:r2_score.
Layer-1 operators: :class:MSE, :class:RMSE, :class:NRMSE,
:class:NRMSEScore, :class:MAE, :class:Bias, :class:Correlation,
:class:R2Score.
Implementation lives in :mod:xrops.metrics._src.pixel.
MAE
¶
MSE
¶
NRMSE
¶
RMSE
¶
Bias
¶
Correlation
¶
NRMSEScore
¶
R2Score
¶
bias
¶
Mean bias <pred - ref> reduced over dim.
correlation
¶
Pearson correlation between prediction and reference over dim.
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/pixel.py
mae
¶
mse
¶
nrmse
¶
Normalized RMSE: 1 - RMSE / sqrt(<ref^2>).
Returns a score in (-inf, 1] where 1 means a perfect match and 0
means the prediction is as wrong as a zero prediction.
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/pixel.py
nrmse_score
¶
Mercator/OceanBench-flavour NRMSE skill: 1 - RMSE / std(ref).
Differs from :func:nrmse in the denominator: this uses the
anomaly magnitude std(ref) while :func:nrmse uses the raw
signal magnitude sqrt(<ref^2>). For zero-mean references the
two agree.
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/pixel.py
r2_score
¶
Coefficient of determination: 1 - SS_res / SS_tot.
rmse
¶
Root mean squared error reduced over dim.
Spectral — power-spectrum skill¶
Power-spectral-density scores and the resolved-scale diagnostic (the wavelength at which a prediction's PSD score crosses a threshold).
PSDScore
¶
PSDScore(variable: str, psd_dims: Sequence[str], avg_dims: Sequence[str] | None = None, isotropic: bool = False, **kwargs: Any)
Bases: Operator
Two-input PSD score operator.
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/spectral.py
SegmentedPSDScore
¶
SegmentedPSDScore(*, var_ref: str, var_pred: str, npt: int, dim: str = 'num_lines', overlap: float = 0.5, max_gap: timedelta64 | None = _DEFAULT_MAX_GAP, spacing_km: float | None = None, lon: str = 'lon', lat: str = 'lat', time: str = 'time', window: str | tuple[str, float] | ArrayLike = 'hann', scaling: str = 'density')
Bases: Operator
Single-input operator for along-track segmented PSD score.
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/segmented_psd.py
WaveletPSDScore
¶
WaveletPSDScore(variable: str, scales: Sequence[float] | DataArray, *, dim: tuple[str, str] = ('y', 'x'), x0: float = 50000.0, ntheta: int = 16, k0: float = 1.0, isotropic: bool = True)
Bases: Operator
Two-input localized wavelet PSD score operator.
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/spectral.py
Functions¶
spectral
¶
Spectral evaluation metrics — public re-export.
Layer-0 functions: :func:psd_error, :func:psd_score,
:func:psd_score_spacetime, :func:along_track_psd_score,
:func:psd_score_by_region, :func:resolved_scale,
:func:resolved_scale_2d, :func:find_intercept_1D,
:func:find_intercept_2D, :func:evaluate_by_frequency_band,
:func:band_limited_rmse,
:func:wavelet_psd_score, :func:wavelet_resolved_scale_map.
Layer-1 operators: :class:PSDScore, :class:FrequencyBandSkill,
:class:BandLimitedRMSE, :class:SegmentedPSDScore.
Implementation lives in :mod:xrops.metrics._src.spectral for the
core PSD primitives, with the gap-tolerant segmented along-track
helpers (:func:along_track_psd_score, :func:psd_score_by_region,
:class:SegmentedPSDScore) defined in
:mod:xrops.metrics._src.segmented_psd and the 2-D space-time
helpers (:func:psd_score_spacetime) in
:mod:xrops.metrics._src.composite.
SegmentedPSDScore
¶
SegmentedPSDScore(*, var_ref: str, var_pred: str, npt: int, dim: str = 'num_lines', overlap: float = 0.5, max_gap: timedelta64 | None = _DEFAULT_MAX_GAP, spacing_km: float | None = None, lon: str = 'lon', lat: str = 'lat', time: str = 'time', window: str | tuple[str, float] | ArrayLike = 'hann', scaling: str = 'density')
Bases: Operator
Single-input operator for along-track segmented PSD score.
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/segmented_psd.py
BandLimitedRMSE
¶
BandLimitedRMSE(variable: str, dims: Sequence[str], bands: Mapping[str, tuple[float, float]], *, coord_spacing: Mapping[str, float] | None = None)
Bases: FrequencyBandSkill
Fixed-metric convenience subclass: FrequencyBandSkill with RMSE.
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/spectral.py
FrequencyBandSkill
¶
FrequencyBandSkill(variable: str, dims: Sequence[str], bands: Mapping[str, tuple[float, float]], *, metric: Operator | None = None, coord_spacing: Mapping[str, float] | None = None)
Bases: Operator
Apply an inner metric to band-passed (pred, ref) pairs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
variable
|
str
|
Variable to score. |
required |
dims
|
Sequence[str]
|
Dimensions to FFT along (passed through to inner metric
as well when |
required |
bands
|
Mapping[str, tuple[float, float]]
|
|
required |
metric
|
Operator | None
|
Inner :class: |
None
|
coord_spacing
|
Mapping[str, float] | None
|
Optional per-dim spacing override (in the same
physical units as |
None
|
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/spectral.py
PSDScore
¶
PSDScore(variable: str, psd_dims: Sequence[str], avg_dims: Sequence[str] | None = None, isotropic: bool = False, **kwargs: Any)
Bases: Operator
Two-input PSD score operator.
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/spectral.py
WaveletPSDScore
¶
WaveletPSDScore(variable: str, scales: Sequence[float] | DataArray, *, dim: tuple[str, str] = ('y', 'x'), x0: float = 50000.0, ntheta: int = 16, k0: float = 1.0, isotropic: bool = True)
Bases: Operator
Two-input localized wavelet PSD score operator.
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/spectral.py
psd_score_spacetime
¶
psd_score_spacetime(pred: DataArray, ref: DataArray, *, space_dim: str = 'lon', time_dim: str = 'time', avg_dims: Sequence[str] | None = ('lat',), level: float = 0.5, **xrft_kwargs: Any) -> tuple[Dataset, dict[str, float]]
Compute a 2-D space-time PSD score and resolved-scale summary.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pred
|
DataArray
|
Prediction DataArray. |
required |
ref
|
DataArray
|
Reference DataArray (same shape and coords as |
required |
space_dim
|
str
|
Spatial dimension used in the PSD. |
'lon'
|
time_dim
|
str
|
Temporal dimension used in the PSD. |
'time'
|
avg_dims
|
Sequence[str] | None
|
Optional dimensions averaged out after the PSD. |
('lat',)
|
level
|
float
|
Threshold used by :func: |
0.5
|
**xrft_kwargs
|
Any
|
Extra keyword arguments forwarded to
:func: |
{}
|
Returns:
| Type | Description |
|---|---|
Dataset
|
Tuple |
dict[str, float]
|
|
tuple[Dataset, dict[str, float]]
|
and |
Examples:
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/composite.py
along_track_psd_score
¶
along_track_psd_score(pred: DataArray, ref: DataArray, *, lon: DataArray, lat: DataArray, time: DataArray | None = None, dim: str = 'num_lines', npt: int, overlap: float = 0.5, max_gap: timedelta64 | None = _DEFAULT_MAX_GAP, spacing_km: float | None = None, window: str | tuple[str, float] | ArrayLike = 'hann', scaling: str = 'density') -> Dataset
Compute per-window along-track PSD score from prediction/reference tracks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pred
|
DataArray
|
Prediction DataArray (1-D along |
required |
ref
|
DataArray
|
Reference DataArray (1-D along |
required |
lon
|
DataArray
|
Longitude DataArray aligned with |
required |
lat
|
DataArray
|
Latitude DataArray aligned with |
required |
time
|
DataArray | None
|
Time DataArray; required when |
None
|
dim
|
str
|
Track dimension name (default |
'num_lines'
|
npt
|
int
|
Window length in samples. |
required |
overlap
|
float
|
Welch overlap fraction. |
0.5
|
max_gap
|
timedelta64 | None
|
Maximum allowed time gap before splitting a segment; pass
|
_DEFAULT_MAX_GAP
|
spacing_km
|
float | None
|
Override along-track spacing; otherwise inferred from
|
None
|
window
|
str | tuple[str, float] | ArrayLike
|
Welch window spec. |
'hann'
|
scaling
|
str
|
Welch |
'density'
|
Returns:
| Type | Description |
|---|---|
Dataset
|
Per-segment Dataset with |
Dataset
|
|
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/segmented_psd.py
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 | |
psd_score_by_region
¶
psd_score_by_region(ds_segments: Dataset, *, lat_centers: ArrayLike = _DEFAULT_LAT_CENTERS, lon_centers: ArrayLike = _DEFAULT_LON_CENTERS, delta_lat: float = 10.0, delta_lon: float = 10.0, min_segments: int = 2) -> Dataset
Average per-segment PSDs into overlapping circular-longitude boxes.
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/segmented_psd.py
band_limited_rmse
¶
band_limited_rmse(prediction: Dataset, reference: Dataset, *, variable: str, bands: Mapping[str, tuple[float, float]], dims: Sequence[str], coord_spacing: Mapping[str, float] | None = None) -> Dataset
RMSE of prediction - reference filtered to each band.
Convenience wrapper around :func:evaluate_by_frequency_band with
metric=RMSE(variable, dims=dims).
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/spectral.py
evaluate_by_frequency_band
¶
evaluate_by_frequency_band(prediction: Dataset, reference: Dataset, *, variable: str, bands: Mapping[str, tuple[float, float]], dims: Sequence[str], metric: Operator | None = None, coord_spacing: Mapping[str, float] | None = None) -> Dataset
Filter prediction and reference to each band and apply metric.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prediction
|
Dataset
|
Prediction dataset. |
required |
reference
|
Dataset
|
Reference dataset. |
required |
variable
|
str
|
Variable to score; must exist in both inputs. |
required |
bands
|
Mapping[str, tuple[float, float]]
|
|
required |
dims
|
Sequence[str]
|
Dimensions to FFT along. Coords must carry |
required |
metric
|
Operator | None
|
Inner :class: |
None
|
coord_spacing
|
Mapping[str, float] | None
|
Optional per-dim spacing overrides (in the same
physical units as |
None
|
Returns:
| Type | Description |
|---|---|
Dataset
|
Dataset stacked along a |
Dataset
|
|
Dataset
|
exceeds the Nyquist magnitude produce NaN entries plus a |
Dataset
|
class: |
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/spectral.py
719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 | |
find_intercept_1D
¶
find_intercept_1D(x: Float[ndarray, 'n'], y: Float[ndarray, 'n'], level: float = 0.5, kind: str = 'slinear', **kwargs: Any) -> float
Invert a 1-D monotone-ish curve at y = level and return x.
Uses :class:scipy.interpolate.interp1d on (y, x). Duplicate
y values (common for plateaued PSD scores) are collapsed to
their first occurrence in the sorted order before interpolating,
because interp1d requires a strictly monotone x-axis.
Extrapolates silently when level falls outside the range of the
deduplicated y.
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/spectral.py
find_intercept_2D
¶
find_intercept_2D(score: DataArray, level: float = 0.5, space_dim: str = 'freq_lon', time_dim: str = 'freq_time') -> list[DataArray]
Extract the threshold contour of a 2-D (space, time) score field.
Counterpart to :func:find_intercept_1D for the 2-D space-time
score: returns the boundary where score == level as data so it
can be quoted in a paper or compared across methods quantitatively
rather than only overlaid on a figure.
Wraps :func:skimage.measure.find_contours. Disconnected boundary
pieces are returned as separate segments. Coordinate values along
each segment are interpolated linearly from the input grid.
Args:
score: 2-D :class:xr.DataArray indexed by space_dim and
time_dim.
level: Score threshold to extract. Default 0.5.
space_dim: Name of the spatial-frequency dim. Default
"freq_lon".
time_dim: Name of the temporal-frequency dim. Default
"freq_time".
Returns:
List of :class:xr.DataArray, one per contour segment, each
with dims ("point", "axis") where axis has coordinates
(space_dim, time_dim) and contains the segment's coordinate
polyline.
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/spectral.py
psd_error
¶
psd_error(pred: DataArray, ref: DataArray, *, psd_dims: Sequence[str], avg_dims: Sequence[str] | None = None, isotropic: bool = False, **kwargs: Any) -> Dataset
PSD of the prediction error pred - ref.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pred
|
DataArray
|
Prediction DataArray. |
required |
ref
|
DataArray
|
Reference DataArray. |
required |
psd_dims
|
Sequence[str]
|
Dimensions over which to take the PSD. |
required |
avg_dims
|
Sequence[str] | None
|
Optional dims to conditionally average out after the
PSD (e.g. average over |
None
|
isotropic
|
bool
|
If |
False
|
**kwargs
|
Any
|
Forwarded to the underlying PSD function. |
{}
|
Returns:
| Type | Description |
|---|---|
Dataset
|
Dataset with a single |
Dataset
|
PSD of the error. |
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/spectral.py
psd_score
¶
psd_score(pred: DataArray, ref: DataArray, *, psd_dims: Sequence[str], avg_dims: Sequence[str] | None = None, isotropic: bool = False, **kwargs: Any) -> Dataset
Normalized PSD score 1 - PSD(err) / PSD(ref).
A score of 1 means the error has no power at that scale; 0
means the error has as much power as the reference signal.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pred
|
DataArray
|
Prediction DataArray. |
required |
ref
|
DataArray
|
Reference DataArray. |
required |
psd_dims
|
Sequence[str]
|
Dimensions over which to take the PSD. |
required |
avg_dims
|
Sequence[str] | None
|
Optional conditional-average dims applied after PSD. |
None
|
isotropic
|
bool
|
If |
False
|
**kwargs
|
Any
|
Forwarded to the underlying PSD function. |
{}
|
Returns:
| Type | Description |
|---|---|
Dataset
|
Dataset with a single |
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/spectral.py
resolved_scale
¶
Wavelength (1 / frequency) at which a PSD score crosses level.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
score
|
DataArray | Dataset
|
DataArray of PSD-score values along |
required |
frequency
|
str
|
Name of the frequency coordinate. |
required |
level
|
float
|
Score threshold (default 0.5 — the commonly-used "resolved scale" threshold). |
0.5
|
Returns:
| Type | Description |
|---|---|
float
|
Scalar wavelength at which the score first crosses |
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/spectral.py
resolved_scale_2d
¶
resolved_scale_2d(score: DataArray | Dataset, *, level: float = 0.5, space_dim: str = 'freq_lon', time_dim: str = 'freq_time') -> dict[str, float]
Summarize a 2-D contour crossing as min/max space-time wavelengths.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
score
|
DataArray | Dataset
|
2-D score field, or a Dataset containing |
required |
level
|
float
|
Contour level to summarize. |
0.5
|
space_dim
|
str
|
Spatial-frequency dimension name. |
'freq_lon'
|
time_dim
|
str
|
Temporal-frequency dimension name. |
'freq_time'
|
Returns:
| Type | Description |
|---|---|
dict[str, float]
|
Dictionary with |
dict[str, float]
|
|
dict[str, float]
|
exists at |
Examples:
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/spectral.py
wavelet_psd_score
¶
wavelet_psd_score(pred: DataArray, ref: DataArray, scales: DataArray, *, dim: tuple[str, str] = ('y', 'x'), x0: float = 50000.0, ntheta: int = 16, k0: float = 1.0, isotropic: bool = True) -> Dataset
Localized wavelet PSD score 1 - WPSD(err) / WPSD(ref).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pred
|
DataArray
|
Prediction DataArray on a locally Cartesian grid. |
required |
ref
|
DataArray
|
Reference DataArray on the same grid. |
required |
scales
|
DataArray
|
Positive Morlet scales. The first dimension is used as the scale axis. |
required |
dim
|
tuple[str, str]
|
Spatial dimensions as |
('y', 'x')
|
x0
|
float
|
Reference length scale in the same units as the spatial coords. |
50000.0
|
ntheta
|
int
|
Number of evenly spaced Morlet angles. |
16
|
k0
|
float
|
Dimensionless central Morlet wavenumber. |
1.0
|
isotropic
|
bool
|
If |
True
|
Returns:
| Type | Description |
|---|---|
Dataset
|
Dataset containing |
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/spectral.py
wavelet_resolved_scale_map
¶
wavelet_resolved_scale_map(truth: DataArray, pred: DataArray, scales: DataArray, *, dim: tuple[str, str] = ('y', 'x'), x0: float = 50000.0, ntheta: int = 16, k0: float = 1.0, threshold: float = 0.5, wavelength_scale: float = 0.001, wavelength_units: str = 'km') -> DataArray
Return the wavelength where local wavelet PSD skill crosses a threshold.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
truth
|
DataArray
|
Reference field on a locally Cartesian grid. |
required |
pred
|
DataArray
|
Prediction field on the same grid. |
required |
scales
|
DataArray
|
Positive Morlet scales used to compute the local spectra. |
required |
dim
|
tuple[str, str]
|
Spatial dimensions as |
('y', 'x')
|
x0
|
float
|
Reference length scale in the same units as the spatial coords. |
50000.0
|
ntheta
|
int
|
Number of evenly spaced Morlet angles. |
16
|
k0
|
float
|
Dimensionless central Morlet wavenumber. |
1.0
|
threshold
|
float
|
Score level defining the resolved scale. |
0.5
|
wavelength_scale
|
float
|
Multiplier applied to |
0.001
|
wavelength_units
|
str
|
Unit string written to the output attrs. |
'km'
|
Returns:
| Type | Description |
|---|---|
DataArray
|
Two-dimensional resolved wavelength in |
DataArray
|
Locations with fewer than two trusted scale samples, or where |
DataArray
|
the threshold isn't bracketed by the score column, are NaN. |
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/spectral.py
Multiscale — region & band conditioned¶
Stratify skill by geographic region or by frequency band.
EvaluateByRegion
¶
EvaluateByRegion(metric: Operator, *, regions: Any)
Bases: Operator
Apply an inner metric per region.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
metric
|
Operator
|
Inner :class: |
required |
regions
|
Any
|
One of:
* a |
required |
Pre-normalize once and reuse via :func:normalize_regions if you
intend to evaluate multiple metrics over the same regions:
```pycon
>>> mask, names = normalize_regions(natural_earth, ds)
>>> EvaluateByRegion(RMSE(...), regions=mask)
```
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/multiscale.py
RegionScores
¶
RegionScores(*, var_ref: str, var_pred: str, regions: DataArray | Regions, lon: str = 'lon', lat: str = 'lat', metrics: Sequence[str] = ('rmse', 'bias', 'correlation', 'explained_variance'), region_dim: str = 'region')
Bases: Operator
Layer-1 wrapper for :func:scores_by_region.
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/residuals.py
FrequencyBandSkill
¶
FrequencyBandSkill(variable: str, dims: Sequence[str], bands: Mapping[str, tuple[float, float]], *, metric: Operator | None = None, coord_spacing: Mapping[str, float] | None = None)
Bases: Operator
Apply an inner metric to band-passed (pred, ref) pairs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
variable
|
str
|
Variable to score. |
required |
dims
|
Sequence[str]
|
Dimensions to FFT along (passed through to inner metric
as well when |
required |
bands
|
Mapping[str, tuple[float, float]]
|
|
required |
metric
|
Operator | None
|
Inner :class: |
None
|
coord_spacing
|
Mapping[str, float] | None
|
Optional per-dim spacing override (in the same
physical units as |
None
|
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/spectral.py
BandLimitedRMSE
¶
BandLimitedRMSE(variable: str, dims: Sequence[str], bands: Mapping[str, tuple[float, float]], *, coord_spacing: Mapping[str, float] | None = None)
Bases: FrequencyBandSkill
Fixed-metric convenience subclass: FrequencyBandSkill with RMSE.
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/spectral.py
SkillByLeadTime
¶
SkillByLeadTime(metric: Operator, *, lead_dim: str = 'lead_time')
Bases: Operator
Apply an inner metric per lead-time slice.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
metric
|
Operator
|
Inner :class: |
required |
lead_dim
|
str
|
Name of the lead-time dimension on the prediction
dataset. Defaults to |
'lead_time'
|
Example
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/forecast.py
Physical — balance residuals¶
Conservation- and balance-law residuals used as physical evaluation diagnostics (geostrophic balance, divergence, potential-vorticity conservation, density inversions).
The derivative-based metrics default to lon/lat in degrees with
latitude-derived Coriolis. Idealised f/β-plane model output in metres
passes the horizontal dims, the geometry and an explicit Coriolis
parameter (same f= forms as xrops.ocn):
from xrops.metrics import divergence_error, geostrophic_imbalance
cart = {"dims": ("x", "y"), "geometry": "cartesian"}
geostrophic_imbalance(run, ssh_var="eta", **cart, f=(1e-4, 1.6e-11)) # 0 = balanced
divergence_error(run, **cart, reduce="rms") # 1/s
geostrophic_imbalance is the scale-invariant ratio
\(\mathrm{rms}(f\,\hat k\times\mathbf u + g\nabla\eta)\,/\,\mathrm{rms}(f\,\hat k\times\mathbf u)\):
0 for exact geostrophy, 1 for purely inertial flow.
GeostrophicBalanceError
¶
GeostrophicBalanceError(*, ssh_var: str = 'ssh', u_var: str = 'u', v_var: str = 'v', lat: str = 'lat', lon: str = 'lon', g: float = GRAVITY, dims: tuple[str, str] | None = None, geometry: Geometry = 'spherical', f: Coriolis = None)
Bases: Operator
Operator wrapper for :func:geostrophic_balance_error.
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/physical.py
GeostrophicImbalance
¶
GeostrophicImbalance(*, ssh_var: str = 'ssh', u_var: str = 'u', v_var: str = 'v', dims: tuple[str, str] = ('lon', 'lat'), geometry: Geometry = 'spherical', f: Coriolis = None, g: float = GRAVITY, eps: float = 1e-30)
Bases: Operator
Operator wrapper for :func:geostrophic_imbalance.
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/physical.py
DivergenceError
¶
DivergenceError(*, u_var: str = 'u', v_var: str = 'v', lat: str = 'lat', lon: str = 'lon', dims: tuple[str, str] | None = None, geometry: Geometry = 'spherical', reduce: Literal['rms'] | None = None)
Bases: Operator
Operator wrapper for :func:divergence_error.
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/physical.py
PVConservationError
¶
Bases: Operator
Operator wrapper for :func:pv_conservation_error.
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/physical.py
DensityInversionFraction
¶
Masked — coverage aware¶
Wrap any metric so it ignores masked / missing cells and reports coverage.
MaskedMetric
¶
MaskedMetric(metric: Operator, mask: DataArray | None = None)
Bases: Operator
Wrap any inner metric so it operates only on masked-valid pixels.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
metric
|
Operator
|
Inner two-input :class: |
required |
mask
|
DataArray | None
|
Optional default mask. If |
None
|
Example
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/masked.py
BinnedResiduals2D
¶
BinnedResiduals2D(*, var_ref: str, var_pred: str, lon_bins: Sequence[float], lat_bins: Sequence[float], lon: str = 'lon', lat: str = 'lat', statistics: Sequence[str] = ('mean', 'std', 'count', 'rmse'))
Bases: Operator
Layer-1 wrapper for :func:bin_residuals_2d.
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/residuals.py
Distributional distances¶
Distance between predicted and reference distributions.
CRPS
¶
Bases: _DistributionalOp
Two-input CRPS operator.
Inputs: (ds_ensemble, ds_reference) where ds_ensemble has
an ensemble_dim axis (one or more members) and ds_reference
is deterministic. A one-member ensemble scores as the absolute error
|x - y|; see :func:crps_ensemble.
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/distributional.py
Wasserstein1
¶
Wasserstein1(variable: str, *, sample_dim_a: str = 'member', sample_dim_b: str = 'member', dims: Sequence[str] | None = None)
Bases: _TwoSampleOp
1-D Wasserstein-distance operator.
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/distributional.py
EnergyDistance
¶
EnergyDistance(variable: str, *, sample_dim_a: str = 'member', sample_dim_b: str = 'member', dims: Sequence[str] | None = None)
Bases: _TwoSampleOp
Two-sample energy-distance operator.
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/distributional.py
Structural & probabilistic¶
SSIM
¶
Bases: Operator
Structural-similarity-index operator (scikit-image).
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/structural.py
GradientDifference
¶
PhaseShiftError
¶
Bases: Operator
FFT cross-correlation phase-shift operator.
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/structural.py
EnsembleCoverage
¶
EnsembleCoverage(variable: str, *, q: tuple[float, float] = (0.05, 0.95), ensemble_dim: str = 'member')
Bases: _ProbabilisticOp
Fraction of references inside the q ensemble envelope.
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/probabilistic.py
SpreadSkillRatio
¶
Bases: _ProbabilisticOp
SpreadSkillRatio(variable, ensemble_dim, dims).
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/probabilistic.py
RankHistogram
¶
ReliabilityCurve
¶
Bases: Operator
Reliability-diagram operator (probability vs event).
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/probabilistic.py
Object / event verification¶
InstanceMatcher
¶
Bases: Operator
Greedy IoU matching between predicted and reference mask stacks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
iou_threshold
|
float
|
Minimum IoU for a (pred, ref) pair to count as a
match. Defaults to |
0.5
|
scores
|
ndarray | None
|
Optional length- |
None
|
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/instance.py
InstanceF1AtIoU
¶
Bases: Operator
Instance precision / recall / F1 at a single IoU threshold.
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/instance.py
AveragePrecisionMatched
¶
Bases: Operator
VOC-style Average Precision at a single IoU threshold.
Source code in packages/xrtoolz-ops/src/xrops/metrics/_src/instance.py
CentroidDisplacement
¶
Forecast comparison¶
DieboldMariano
¶
DieboldMariano(variable: str, *, dim: str | Sequence[str] | None = None, h: int = 1, alternative: str = 'two-sided', power: float = 2.0, hln_correction: bool = True)
Bases: Operator
Layer-1 Diebold–Mariano test on a forecast-error variable.
Selects variable from two input Datasets of forecast errors
(residuals) and runs :func:dm_test, returning a Dataset with
statistic and p_value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
variable
|
str
|
Error variable to select from each input Dataset. |
required |
dim
|
str | Sequence[str] | None
|
Dimension(s) to reduce. |
None
|
h
|
int
|
Forecast horizon. |
1
|
alternative
|
str
|
|
'two-sided'
|
power
|
float
|
Loss exponent applied to |
2.0
|
hln_correction
|
bool
|
Apply the Harvey–Leybourne–Newbold correction. |
True
|