geoprior.scripts.utils#

Shared utility helpers for GeoPrior scripts.

Functions

add_city_flags(ap, *[, default_both])

add_plot_text_args(ap, *, default_out)

Common plot args for Nature workflows.

add_render_args(ap, *[, default])

Common render args for 2D sensitivity plots.

as_path(src)

canonical_city(name)

detect_artifacts(src)

Detect common v3.2 artifacts starting from a src path.

ensure_columns(df, *, aliases)

Ensure canonical columns exist by copying from the first available alias.

ensure_dir(path)

ensure_script_dirs()

evolve_spatial_field(support, *, base_field, ...)

Evolve a base field across horizons.

filter_year(df, year)

find_all(src, patterns, *[, must_exist])

Find all files matching any pattern under src.

find_eval_diag_json(src)

find_latest(src, patterns, *[, must_exist])

Find newest file matching any of patterns under src.

find_phys_json(src)

Prefer interpretable GeoPrior JSON when available.

find_preferred(src, patterns, *[, must_exist])

Try patterns in order, returning the first match.

flatten_eval_diag(diag)

Flatten eval diagnostics into keys used by plots.

label(key, *[, with_unit])

load_dataset_any(src, *[, file, ns_file, ...])

Load a combined dataset if:

load_forecast_csv(path)

Load calibrated forecast CSV and enforce basic schema.

make_noisy_actual(mean, scale, *, rng[, ...])

Sample an observed field from mean + spread.

make_spatial_field(support, *[, amplitude, ...])

Build a smooth synthetic spatial field.

make_spatial_quantile_frame(support, *, ...)

Pack one spatial mean/scale state into a forecast table.

make_spatial_scale(support, *[, base, ...])

Build a positive spatial spread / uncertainty field.

make_spatial_support(spec)

Build a synthetic spatial support cloud.

phys_json_to_mm(meta)

Normalize GeoPrior phys JSON to "mm" subs metrics.

phys_label(key, *[, with_unit])

pick_interval_metrics(phys_json, fallback)

Pick interval metrics with calibrated preference.

pick_point_metrics(phys_json, fallback)

quantile_columns_from_mean_scale(mean, scale, *)

Convert mean + scale fields into quantile columns.

resolve_cities(args)

resolve_fig_out(out)

Resolve figure output with user-path semantics.

resolve_fig_stem(out)

Resolve an output stem under scripts/figs/ if relative.

resolve_gallery_raster_path(*[, out_paths, ...])

Resolve a saved raster image for gallery display.

resolve_out_out(out)

Resolve tabular output with user-path semantics.

resolve_title(*, default, title)

safe_load_json(path)

sample_df(df, *, sample_frac, sample_n[, seed])

save_figure(fig, out, *[, formats, dpi, ...])

Save a Matplotlib figure to multiple formats.

set_paper_style(*[, fontsize, dpi])

show_gallery_saved_figure(*[, out_paths, ...])

Reload a saved raster figure and display it in matplotlib.

str_to_bool(x, *[, default])

to_float(x)

Classes

Artifacts(src[, phys_json, eval_diag_json, ...])

SpatialSupport(city, sample_idx, coord_x, ...)

Lightweight container for synthetic spatial support.

SpatialSupportSpec([city, center_x, ...])

Configuration for a synthetic city support.

Resolve a saved raster image for gallery display.

This helper supports the two common lesson patterns:

  1. a plotting backend returns out_paths

  2. a plotting backend writes from an out_base stem

Parameters:
  • out_paths (Any or None, default None) – Collection of written paths returned by a backend. This may be a list/tuple/set of paths or strings, or a mapping whose values are paths.

  • out_base (path-like or None, default None) – Output stem or filename used by the backend.

  • raster_exts (tuple of str, default (``”png”, ``"jpg", )) – Raster extensions accepted for gallery display, in priority order.

  • must_exist (bool, default True) – If True, raise an error when no existing raster file is found.

Returns:

Resolved raster path.

Return type:

Path

Raises:
  • RuntimeError – If no usable raster path can be resolved.

  • FileNotFoundError – If a candidate path was resolved but does not exist and must_exist=True.

Notes

Sphinx-Gallery reliably displays raster images when they are reloaded into a matplotlib figure. This helper resolves the raster file that should be re-opened.

Reload a saved raster figure and display it in matplotlib.

Parameters:
  • out_paths (Any or None, default None) – Written paths returned by a plotting backend.

  • out_base (path-like or None, default None) – Output stem or filename used by the backend.

  • image_path (path-like or None, default None) – Explicit image path. When provided, this takes precedence over out_paths and out_base.

  • figsize (tuple of float, default (8.4, 5.4)) – Figure size passed to plt.subplots.

  • hide_axes (bool, default True) – If True, hide axis decorations.

  • title (str or None, default None) – Optional title for the display figure.

Returns:

Notes

Imports are done locally so lesson pages can reuse this helper without adding top-level matplotlib image imports everywhere.

geoprior.scripts.utils.str_to_bool(x, *, default=False)[source]#
Parameters:
Return type:

bool

geoprior.scripts.utils.add_city_flags(ap, *, default_both=True)[source]#
Parameters:

default_both (bool)

Return type:

None

geoprior.scripts.utils.add_plot_text_args(ap, *, default_out)[source]#

Common plot args for Nature workflows.

Use cases: - Hide text for Illustrator editing. - Keep titles/labels in SVG as editable text.

Conventions: - “legend” includes colorbar (if present). - “labels” means axis labels and cbar label. - ticklabels are controlled separately.

Parameters:

default_out (str)

Return type:

None

geoprior.scripts.utils.add_render_args(ap, *, default='heatmap')[source]#

Common render args for 2D sensitivity plots.

render:
  • heatmap: pivot->imshow (discrete grid)

  • tricontour: smooth contourf on scattered points

  • pcolormesh: grid-aware shading using real coords

Parameters:

default (str)

Return type:

None

geoprior.scripts.utils.find_all(src, patterns, *, must_exist=False)[source]#

Find all files matching any pattern under src.

  • If src is a file:

    return [src] if it matches, else [].

  • If src is a directory:

    search recursively (rglob) for all patterns.

Returned list is sorted by mtime (newest first), with duplicates removed.

Parameters:
Return type:

list[Path]

geoprior.scripts.utils.resolve_title(*, default, title)[source]#
Parameters:
  • default (str)

  • title (str | None)

Return type:

str

geoprior.scripts.utils.resolve_cities(args)[source]#
Return type:

list[str]

geoprior.scripts.utils.resolve_fig_out(out)[source]#

Resolve figure output with user-path semantics.

Bare relative names go to scripts/figs/. Relative paths with an explicit parent are kept.

Parameters:

out (str)

Return type:

Path

geoprior.scripts.utils.resolve_fig_stem(out)[source]#

Resolve an output stem under scripts/figs/ if relative.

If user passes a filename with suffix (e.g. foo.png), we treat it as a stem and strip the suffix.

Parameters:

out (Any)

Return type:

Path

geoprior.scripts.utils.save_figure(fig, out, *, formats=None, dpi=None, bbox_inches='tight', pad_inches=0.02, transparent=False, close=True, verbose=True, strict=False)[source]#

Save a Matplotlib figure to multiple formats.

Parameters:
  • fig (Any) – Matplotlib Figure.

  • out (Any) – Output stem or path. If relative, saved under scripts/figs/. If has suffix, suffix is stripped and treated as stem.

  • formats (Sequence[str] | None) – Iterable of extensions (png/svg/pdf/eps). Default exports all 4.

  • dpi (int | None) – DPI for raster formats (png). If None, uses current rcParams.

  • bbox_inches (str) – Passed through to fig.savefig.

  • pad_inches (float) – Passed through to fig.savefig.

  • transparent (bool) – Passed through to fig.savefig.

  • close (bool) – Close the figure after saving.

  • verbose (bool) – Print a compact “[OK]” line with what was written.

  • strict (bool) – If True, any save failure raises immediately. If False, failures are warned and other formats continue.

Returns:

Mapping ext -> output Path for successfully written files.

Return type:

written

geoprior.scripts.utils.ensure_columns(df, *, aliases)[source]#

Ensure canonical columns exist by copying from the first available alias.

Returns:

mapping canonical -> source column used

Parameters:
Return type:

dict[str, str]

geoprior.scripts.utils.load_dataset_any(src, *, file=None, ns_file='nansha_dataset.final.ready.csv', zh_file='zhongshan_dataset.final.ready.csv')[source]#
Load a combined dataset if:
  • src is a CSV file, or

  • src is a dir and –file is provided.

Otherwise load ns_file + zh_file from src dir and concatenate.

Parameters:
Return type:

DataFrame

geoprior.scripts.utils.filter_year(df, year)[source]#
Parameters:
Return type:

DataFrame

geoprior.scripts.utils.sample_df(df, *, sample_frac, sample_n, seed=42)[source]#
Parameters:
Return type:

DataFrame

class geoprior.scripts.utils.SpatialSupport(city, sample_idx, coord_x, coord_y, x_norm, y_norm, extent)[source]#

Bases: object

Lightweight container for synthetic spatial support.

Parameters:
city: str#
sample_idx: ndarray#
coord_x: ndarray#
coord_y: ndarray#
x_norm: ndarray#
y_norm: ndarray#
extent: tuple[float, float, float, float]#
to_frame()[source]#

Return support as a compact DataFrame.

Return type:

DataFrame

__init__(city, sample_idx, coord_x, coord_y, x_norm, y_norm, extent)#
Parameters:
Return type:

None

class geoprior.scripts.utils.SpatialSupportSpec(city='City', center_x=0.0, center_y=0.0, span_x=1000.0, span_y=800.0, nx=60, ny=44, jitter_x=0.0, jitter_y=0.0, footprint='ellipse', keep_frac=1.0, seed=0)[source]#

Bases: object

Configuration for a synthetic city support.

Parameters:
city: str = 'City'#
center_x: float = 0.0#
center_y: float = 0.0#
span_x: float = 1000.0#
span_y: float = 800.0#
nx: int = 60#
ny: int = 44#
jitter_x: float = 0.0#
jitter_y: float = 0.0#
footprint: str = 'ellipse'#
keep_frac: float = 1.0#
seed: int = 0#
__init__(city='City', center_x=0.0, center_y=0.0, span_x=1000.0, span_y=800.0, nx=60, ny=44, jitter_x=0.0, jitter_y=0.0, footprint='ellipse', keep_frac=1.0, seed=0)#
Parameters:
Return type:

None

geoprior.scripts.utils.make_spatial_support(spec)[source]#

Build a synthetic spatial support cloud.

Parameters:

spec (SpatialSupportSpec) – Support configuration.

Returns:

Support container with coordinates, normalized coordinates, and sample indices.

Return type:

SpatialSupport

Notes

This helper is intended for gallery pages and tests. It produces a stable, reproducible spatial support that looks more like a compact urban footprint than a plain rectangular mesh.

geoprior.scripts.utils.make_spatial_field(support, *, amplitude=1.0, drift_x=0.0, drift_y=0.0, phase=0.0, hotspot_weight=0.92, secondary_weight=0.54, ridge_weight=0.16, wave_weight=0.1, local_weight=0.0)[source]#

Build a smooth synthetic spatial field.

The field combines: - one main hotspot, - one secondary lobe, - one ridge, - one wave component, - one linear drift.

Returns:

Field values on the support points.

Return type:

np.ndarray

Parameters:
geoprior.scripts.utils.make_spatial_scale(support, *, base=0.3, x_weight=0.08, hotspot_weight=0.05, step_weight=0.0, step=0, floor=1e-06)[source]#

Build a positive spatial spread / uncertainty field.

Parameters:
  • support (SpatialSupport) – Support container.

  • base (float, default 0.30) – Base scale level.

  • x_weight (float, default 0.08) – East-west spread increase.

  • hotspot_weight (float, default 0.05) – Extra spread near the main hotspot.

  • step_weight (float, default 0.0) – Optional horizon-dependent increase.

  • step (int, default 0) – Horizon index used with step_weight.

  • floor (float, default 1e-6) – Minimum allowed scale.

Returns:

Positive spread field.

Return type:

np.ndarray

geoprior.scripts.utils.evolve_spatial_field(support, *, base_field, step, growth=1.0, phase_step=0.18, drift_scale=0.65, drift_x=0.34, drift_y=0.2, wave_amp=0.7)[source]#

Evolve a base field across horizons.

This keeps the same geography but lets: - the mean intensity grow, - the wave phase shift, - the field drift slightly.

Returns:

Evolved field for the requested step.

Return type:

np.ndarray

Parameters:
geoprior.scripts.utils.quantile_columns_from_mean_scale(mean, scale, *, quantiles=(0.1, 0.5, 0.9), prefix='subsidence')[source]#

Convert mean + scale fields into quantile columns.

Parameters:
  • mean (np.ndarray) – Central field.

  • scale (np.ndarray) – Positive spread field.

  • quantiles (sequence of float) – Quantile levels in (0, 1).

  • prefix (str, default "subsidence") – Output column prefix.

Returns:

Mapping from quantile column names such as subsidence_q10 and subsidence_q50 to arrays.

Return type:

dict[str, np.ndarray]

geoprior.scripts.utils.make_spatial_quantile_frame(support, *, year, forecast_step, mean, scale, quantiles=(0.1, 0.5, 0.9), actual=None, prefix='subsidence', unit='mm')[source]#

Pack one spatial mean/scale state into a forecast table.

Parameters:
  • support (SpatialSupport) – Support container.

  • year (int) – Calendar year for coord_t.

  • forecast_step (int) – Forecast step or horizon index.

  • mean (np.ndarray) – Central field.

  • scale (np.ndarray) – Positive spread field.

  • quantiles (sequence of float) – Quantile levels to export.

  • actual (np.ndarray or None, default None) – Optional observed target values.

  • prefix (str, default "subsidence") – Column prefix.

  • unit (str, default "mm") – Unit label.

Returns:

Forecast-ready long table for one year.

Return type:

pd.DataFrame

geoprior.scripts.utils.make_noisy_actual(mean, scale, *, rng, noise_scale=1.0)[source]#

Sample an observed field from mean + spread.

Parameters:
  • mean (np.ndarray) – Mean field.

  • scale (np.ndarray) – Positive spread field.

  • rng (np.random.Generator) – Random generator.

  • noise_scale (float, default 1.0) – Global multiplier applied to the spread.

Returns:

Noisy observed field.

Return type:

np.ndarray

geoprior.scripts.utils.ensure_dir(path)[source]#
Parameters:

path (Path)

Return type:

Path

geoprior.scripts.utils.ensure_script_dirs()[source]#
Return type:

None

geoprior.scripts.utils.as_path(src)[source]#
Parameters:

src (Any)

Return type:

Path

geoprior.scripts.utils.canonical_city(name)[source]#
Parameters:

name (str)

Return type:

str

geoprior.scripts.utils.label(key, *, with_unit=True)[source]#
Parameters:
Return type:

str

geoprior.scripts.utils.phys_label(key, *, with_unit=True)[source]#
Parameters:
Return type:

str

geoprior.scripts.utils.set_paper_style(*, fontsize=8, dpi=600)[source]#
Parameters:
Return type:

None

geoprior.scripts.utils.find_preferred(src, patterns, *, must_exist=False)[source]#

Try patterns in order, returning the first match.

Unlike find_latest() with multiple patterns, this respects priority order.

Parameters:
Return type:

Path | None

geoprior.scripts.utils.find_eval_diag_json(src)[source]#
Parameters:

src (Any)

Return type:

Path | None

geoprior.scripts.utils.find_latest(src, patterns, *, must_exist=False)[source]#

Find newest file matching any of patterns under src.

  • If src is a file: returns it if it matches any pattern.

  • If src is a directory: searches recursively and returns the most recently modified candidate.

Parameters:
Return type:

Path | None

class geoprior.scripts.utils.Artifacts(src: 'Path', phys_json: 'Path | None' = None, eval_diag_json: 'Path | None' = None, forecast_test_csv: 'Path | None' = None, forecast_test_future_csv: 'Path | None' = None, forecast_val_csv: 'Path | None' = None, forecast_future_csv: 'Path | None' = None, physics_payload: 'Path | None' = None, coords_npz: 'Path | None' = None)[source]#

Bases: object

Parameters:
  • src (Path)

  • phys_json (Path | None)

  • eval_diag_json (Path | None)

  • forecast_test_csv (Path | None)

  • forecast_test_future_csv (Path | None)

  • forecast_val_csv (Path | None)

  • forecast_future_csv (Path | None)

  • physics_payload (Path | None)

  • coords_npz (Path | None)

src: Path#
phys_json: Path | None = None#
eval_diag_json: Path | None = None#
forecast_test_csv: Path | None = None#
forecast_test_future_csv: Path | None = None#
forecast_val_csv: Path | None = None#
forecast_future_csv: Path | None = None#
physics_payload: Path | None = None#
coords_npz: Path | None = None#
__init__(src, phys_json=None, eval_diag_json=None, forecast_test_csv=None, forecast_test_future_csv=None, forecast_val_csv=None, forecast_future_csv=None, physics_payload=None, coords_npz=None)#
Parameters:
  • src (Path)

  • phys_json (Path | None)

  • eval_diag_json (Path | None)

  • forecast_test_csv (Path | None)

  • forecast_test_future_csv (Path | None)

  • forecast_val_csv (Path | None)

  • forecast_future_csv (Path | None)

  • physics_payload (Path | None)

  • coords_npz (Path | None)

Return type:

None

geoprior.scripts.utils.detect_artifacts(src)[source]#

Detect common v3.2 artifacts starting from a src path.

Examples

If src is a run directory such as .../results/nansha_..._stage1/train_YYYYmmdd-HHMMSS, the helper auto-locates common artifacts including:

  • geoprior_eval_phys_*.json

  • eval_diagnostics.json

  • *_calibrated.csv

  • *_future.csv

  • physics payload files

  • coordinate archives

Parameters:

src (Any)

Return type:

Artifacts

geoprior.scripts.utils.safe_load_json(path)[source]#
Parameters:

path (Any | None)

Return type:

dict[str, Any]

geoprior.scripts.utils.load_forecast_csv(path)[source]#

Load calibrated forecast CSV and enforce basic schema.

Expected columns are consistent with the uncertainty scripts:

sample_idx, forecast_step, subsidence_q10, subsidence_q50, subsidence_q90, subsidence_actual

Parameters:

path (Any)

Return type:

DataFrame

geoprior.scripts.utils.phys_json_to_mm(meta)[source]#

Normalize GeoPrior phys JSON to “mm” subs metrics.

v3.2 may produce: - interpretable JSON: already in mm (no-op) - raw JSON: often distance-like metrics in meters

We convert: - distance-like: MAE / RMSE / sharpness -> × scale - squared: MSE -> × scale²

This conversion touches (if present): - metrics_evaluate: subs_pred_* keys - point_metrics - per_horizon: mae/mse/rmse/sharpness - interval_metrics: sharpness* - interval_calibration: sharpness* keys

Parameters:

meta (dict[str, Any])

Return type:

dict[str, Any]

geoprior.scripts.utils.pick_point_metrics(phys_json, fallback)[source]#
Parameters:
Return type:

tuple[float, float, float]

geoprior.scripts.utils.pick_interval_metrics(phys_json, fallback)[source]#

Pick interval metrics with calibrated preference.

Preference order:
  1. phys_json.interval_calibration: - calibrated_phys (paper / physical) - calibrated (often SI)

  2. phys_json.interval_metrics

  3. phys_json.metrics_evaluate (may be uncalibrated)

  4. eval diagnostics JSON (flattened)

Returns:

  • coverage80 (float) – Unitless.

  • sharpness80 (float) – Returned in mm when we can infer conversion.

Parameters:
Return type:

tuple[float, float]

geoprior.scripts.utils.flatten_eval_diag(diag)[source]#

Flatten eval diagnostics into keys used by plots.

Supported input shapes include:

  • flat mappings such as {"mae": ..., "coverage80": ...}

  • mappings with an "__overall__" block

  • mappings with "overall_key" plus an "eval_after" block

Parameters:

diag (dict[str, Any])

Return type:

dict[str, float]

geoprior.scripts.utils.to_float(x)[source]#
Parameters:

x (Any)

Return type:

float

geoprior.scripts.utils.resolve_out_out(out)[source]#

Resolve tabular output with user-path semantics.

Bare relative names go to scripts/out/. Relative paths with an explicit parent are kept.

Parameters:

out (str)

Return type:

Path

geoprior.scripts.utils.find_phys_json(src)[source]#

Prefer interpretable GeoPrior JSON when available.

Parameters:

src (Any)

Return type:

Path | None