geoprior.utils.scale_metrics#

Utilities for computing error metrics in physical units given Stage-1 scaling metadata.

Main entry points include inverse_scale_target(...), point_metrics(...), and per_horizon_metrics(...).

These are designed to work with the NATCOM pipeline where Stage-1 stores a scaler_info dict in the manifest:

scaler_info[target_name] = {
    "scaler_path": ".../main_scaler.joblib",
    "all_features": [...],
    "idx": <index in scaler>,
    "scaler": <fitted MinMaxScaler>,  # optional, attached at Stage-2
}

They can also handle a bare scaler object, a scaler path, or manual min/max or mean/std parameters.

Functions

auto_noise_std_from_increments(y_inc, *[, ...])

Compute noise std as a fraction of a robust increment scale.

evaluate_point_forecast(model, out, ...[, ...])

End-to-end helper for point-forecast evaluation.

inverse_scale_target(y_scaled, *[, ...])

Inverse-transform a scaled target array back to physical units.

per_horizon_metrics(y_true, y_pred, *[, ...])

Per-horizon MAE/R².

point_metrics(y_true, y_pred, *[, ...])

Compute MAE/MSE/R², optionally in physical units.

resolve_noise_std(y_inc, *[, noise_std, ...])

Prefer explicit noise_std when provided, otherwise auto-compute from increments.

scale_target(y_phys, *[, scaler_info, ...])

Forward-transform physical values into scaled space.

geoprior.utils.scale_metrics.evaluate_point_forecast(model, out, y_true_subs, *, y_true_gwl=None, n_q=3, quantiles=None, q=None, use_physical=False, return_physical=None, scaler_info=None, subs_target_name='subsidence', gwl_target_name='gwl', scaler_entry=None, scaler=None, feature_index=None, n_features=None, params=None, strict=True, output_names=None)[source]#

End-to-end helper for point-forecast evaluation.

Pipeline: extract predictions from model and out, canonicalize BHQO quantile outputs when needed, pick a point prediction, optionally inverse-scale it, and compute global and per-horizon metrics.

Parameters:
  • model (Any) – Passed to extract_preds(…).

  • out (Any) – Passed to extract_preds(…).

  • y_true_subs (Any) – True subsidence, shape (B, H, 1) or (B, H).

  • y_true_gwl (Any | None) – Optional true gwl/head, same shape conventions.

  • n_q (int) – Quantile-selection controls for (B, H, Q, 1) outputs. If q is None, the median is preferred. If q is an integer, it is treated as a direct quantile index. If q is a float and quantiles is provided, the nearest quantile is selected; otherwise the float is treated as a fraction in [0, 1].

  • quantiles (Sequence[float] | None) – Quantile-selection controls for (B, H, Q, 1) outputs. If q is None, the median is preferred. If q is an integer, it is treated as a direct quantile index. If q is a float and quantiles is provided, the nearest quantile is selected; otherwise the float is treated as a fraction in [0, 1].

  • q (float | int | None) – Quantile-selection controls for (B, H, Q, 1) outputs. If q is None, the median is preferred. If q is an integer, it is treated as a direct quantile index. If q is a float and quantiles is provided, the nearest quantile is selected; otherwise the float is treated as a fraction in [0, 1].

  • use_physical (bool) – If True, compute metrics in physical units.

  • return_physical (bool | None) – If None, defaults to use_physical. If True, return physical-space arrays such as subs_pred_phys and gwl_pred_phys when possible.

  • scaler_info (Mapping[str, Any] | None) – Passed through to inverse_scale_target(...).

  • scaler_entry (Mapping[str, Any] | None) – Passed through to inverse_scale_target(...).

  • scaler (Any | None) – Passed through to inverse_scale_target(...).

  • feature_index (int | None) – Passed through to inverse_scale_target(...).

  • n_features (int | None) – Passed through to inverse_scale_target(...).

  • params (Mapping[str, float] | None) – Passed through to inverse_scale_target(...).

  • subs_target_name (str)

  • gwl_target_name (str)

  • strict (bool)

  • output_names (Sequence[str] | None)

Returns:

Dictionary containing model-space predictions, optional physical-space predictions, and global and per-horizon metrics for subsidence and groundwater outputs.

Return type:

dict

geoprior.utils.scale_metrics.auto_noise_std_from_increments(y_inc, *, noise_frac=0.1, percentile=95.0, min_std=0.0, max_std=None, eps=1e-12)[source]#

Compute noise std as a fraction of a robust increment scale.

Parameters:
  • y_inc (np.ndarray) – Deterministic increments (before noise). Any shape; will be flattened.

  • noise_frac (float, default 0.10) – Fraction applied to the percentile scale.

  • percentile (float, default 95.0) – Percentile of the absolute increments used as the scale.

  • min_std (float, default 0.0) – Lower bound for returned std.

  • max_std (float or None, default None) – Optional upper bound for returned std.

  • eps (float, default 1e-12) – Small positive value for safe fallback.

Returns:

A finite, non-negative std value.

Return type:

float

Notes

Non-finite values are filtered first. If the percentile-based scale is approximately zero, the function falls back to the maximum absolute increment, then the mean absolute increment, and finally to eps.

geoprior.utils.scale_metrics.resolve_noise_std(y_inc, *, noise_std=None, noise_frac=0.1, percentile=95.0, min_std=0.0, max_std=None)[source]#

Prefer explicit noise_std when provided, otherwise auto-compute from increments.

Parameters:
Return type:

float

geoprior.utils.scale_metrics.scale_target(y_phys, *, scaler_info=None, target_name=None, scaler_entry=None, scaler=None, feature_index=None, n_features=None, params=None)[source]#

Forward-transform physical values into scaled space.

Mirrors inverse_scale_target(…) conventions.

Parameters:
Return type:

ndarray

geoprior.utils.scale_metrics.inverse_scale_target(y_scaled, *, scaler_info=None, target_name=None, scaler_entry=None, scaler=None, feature_index=None, n_features=None, params=None)[source]#

Inverse-transform a scaled target array back to physical units.

Supports three patterns:

  1. Stage-1 scaler_info dict (preferred in NATCOM): pass scaler_info=scaler_info_dict, target_name="subsidence".

  2. A bare scaler instance or a path to a joblib dump via scaler=.... If multi-feature, also pass feature_index and optionally n_features.

  3. Manual scaling parameters via params such as {"min", "max"}, {"mean", "std"}, or {"scale", "shift"}.

Parameters:
  • y_scaled (array-like) – Scaled values, e.g. of shape (N, H, 1) or (N,).

  • scaler_info (mapping, optional)

  • target_name (str, optional)

  • scaler_entry (mapping, optional)

  • scaler (object or str, optional)

  • feature_index (int, optional)

  • n_features (int, optional)

  • params (mapping, optional) – Manual parameters: - {"min", "max"} → MinMax scaling - {"mean", "std"} → standardization - {"scale", "shift"} → x = scale * x_scaled + shift.

Returns:

Array with same shape as y_scaled but in physical units when scaling information is available. If nothing usable is found, returns the input as a NumPy array.

Return type:

np.ndarray

geoprior.utils.scale_metrics.point_metrics(y_true, y_pred, *, use_physical=False, scaler_info=None, target_name=None, scaler_entry=None, scaler=None, feature_index=None, n_features=None, params=None)[source]#

Compute MAE/MSE/R², optionally in physical units.

If use_physical=True, both y_true and y_pred are inverse- transformed via inverse_scale_target before computing metrics.

Parameters:
  • y_true (array-like) – Arbitrary shapes (e.g. (N, H, 1)); flattened internally.

  • y_pred (array-like) – Arbitrary shapes (e.g. (N, H, 1)); flattened internally.

  • use_physical (bool, default False) – If True, inverse-transform y_true and y_pred to physical units before computing metrics.

  • scaler_info (optional) – Passed through to inverse_scale_target.

  • target_name (optional) – Passed through to inverse_scale_target.

  • scaler_entry (optional) – Passed through to inverse_scale_target.

  • scaler (optional) – Passed through to inverse_scale_target.

  • feature_index (optional) – Passed through to inverse_scale_target.

  • n_features (optional) – Passed through to inverse_scale_target.

  • params (optional) – Passed through to inverse_scale_target.

Returns:

{“mae”: …, “mse”: …, “r2”: …}

Return type:

dict

geoprior.utils.scale_metrics.per_horizon_metrics(y_true, y_pred, *, use_physical=False, scaler_info=None, target_name=None, scaler_entry=None, scaler=None, feature_index=None, n_features=None, params=None)[source]#

Per-horizon MAE/R².

Parameters:
  • y_true (array-like) – Shape (N, H, 1) or (N, H).

  • y_pred (array-like) – Shape (N, H, 1) or (N, H).

  • use_physical (bool, default False) – If True, inverse-transform to physical units before computing.

  • scaler_info (Mapping[str, Any] | None)

  • target_name (str | None)

  • scaler_entry (Mapping[str, Any] | None)

  • scaler (Any | None)

  • feature_index (int | None)

  • n_features (int | None)

  • params (Mapping[str, float] | None)

Returns:

  • mae_dict (dict) – {‘H1’: mae_h1, …}

  • r2_dict (dict) – {‘H1’: r2_h1, …}

Return type:

tuple[dict, dict]