API Reference#
This page provides detailed documentation for the NWM Coastal Python API.
Configuration Classes#
CoastalCalibConfig#
CoastalCalibConfig
dataclass
#
CoastalCalibConfig(
simulation,
boundary,
paths,
model_config,
monitoring=MonitoringConfig(),
download=DownloadConfig(),
)
Complete coastal calibration workflow configuration.
Supports both SCHISM and SFINCS models via the polymorphic
:attr:model_config field. The concrete type is selected by the
model key in the YAML file and resolved through
:data:MODEL_REGISTRY.
from_yaml
classmethod
#
Load configuration from YAML file with optional inheritance.
Supports variable interpolation using ${section.key} syntax. Variables are resolved from other config values, e.g.:
${user}-> value of$USERenvironment variable${simulation.coastal_domain}-> value ofsimulation.coastal_domain${model}-> the model type string ("schism"or"sfincs")
| PARAMETER | DESCRIPTION |
|---|---|
config_path
|
Path to YAML configuration file.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
CoastalCalibConfig
|
Loaded configuration. |
| RAISES | DESCRIPTION |
|---|---|
FileNotFoundError
|
If the configuration file does not exist. |
YAMLError
|
If the YAML file is malformed. |
Source code in src/coastal_calibration/config/schema.py
from_dict
classmethod
#
Create config from a plain dictionary.
| PARAMETER | DESCRIPTION |
|---|---|
data
|
Configuration dictionary with the same structure as the YAML
file (see :meth:
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
CoastalCalibConfig
|
|
Source code in src/coastal_calibration/config/schema.py
to_yaml
#
Write configuration to YAML file.
| PARAMETER | DESCRIPTION |
|---|---|
path
|
Path to YAML output file. Parent directories will be created if they don't exist.
TYPE:
|
Source code in src/coastal_calibration/config/schema.py
to_dict
#
Convert config to dictionary.
Source code in src/coastal_calibration/config/schema.py
validate
#
Validate configuration and return list of errors.
Source code in src/coastal_calibration/config/schema.py
SimulationConfig#
SimulationConfig
dataclass
#
Simulation time and domain configuration.
start_date is normalized to naive UTC in __post_init__
so the rest of the pipeline can compare and serialize it without
crossing the naive/aware boundary. Tz-aware values are converted to
UTC then stripped; tz-naive values are passed through (assumed UTC
by the project's data contract — NWM/STOFS are published on UTC
days).
nwm_domain_for
classmethod
#
NWM domain identifier for an arbitrary coastal domain name.
Same mapping as :attr:nwm_domain, but callable without a
configured simulation and lenient about names outside
:data:CoastalDomain ("conus" is passed straight through, as
the downloader accepts it). Used for naming the download cache,
where the NWM domain is the right key: atlgulf and pacific
pull byte-identical CONUS forcing and should share one copy.
Source code in src/coastal_calibration/config/schema.py
BoundaryConfig#
BoundaryConfig
dataclass
#
Boundary condition configuration.
| PARAMETER | DESCRIPTION |
|---|---|
source
|
Boundary forcing source.
TYPE:
|
stofs_file
|
STOFS NetCDF (only used when
TYPE:
|
tidal_model
|
pyTMD model identifier (see
TYPE:
|
PathConfig#
PathConfig
dataclass
#
PathConfig(
work_dir,
raw_download_dir=None,
hot_start_file=None,
parm_dir=None,
nwm_dir=None,
tidal_atlas_dir=None,
)
Path configuration for data and executables.
Only work_dir is required. All other fields are optional and
only needed by specific workflow stages.
meteo_subdir
classmethod
#
Relative meteo path, meteo/<source>/<nwm domain>.
Every NWM domain names its hourly forcing YYYYMMDDHH.LDASIN_DOMAIN1,
so files from different domains collide unless each domain gets its
own directory: a cached Hawaii file would otherwise be served for a
PRVI run covering the same hour.
Source code in src/coastal_calibration/config/schema.py
meteo_dir
#
streamflow_subdir
classmethod
#
Relative streamflow path, hydro/nwm/<nwm domain>.
Keyed the same way as :meth:meteo_subdir, so a domain reads the
same everywhere under the download directory even though NWM
spells it differently in its own URLs (puertorico there,
prvi here).
Only nwm_ana streamflow is downloaded; nwm_retro is read
straight from the S3 Zarr store, so it has no directory here.
Source code in src/coastal_calibration/config/schema.py
streamflow_dir
#
Directory for downloaded nwm_ana streamflow data.
coastal_dir
#
geogrid_file
#
Geogrid file path for the given domain (requires parm_dir).
ModelConfig#
ModelConfig
#
Bases: ABC
Abstract base class for model-specific configuration.
Each concrete subclass owns its compute parameters, environment variable
construction, stage ordering, validation, and SLURM script generation.
This keeps model-specific concerns out of the shared configuration and
makes adding new models straightforward: create a new subclass,
implement the abstract methods, and register it in :data:MODEL_REGISTRY.
| ATTRIBUTE | DESCRIPTION |
|---|---|
omp_num_threads |
Number of OpenMP threads per process.
TYPE:
|
runtime_env |
Extra environment variables for the model run subprocess.
Merged last so they can override any auto-detected value.
Only used by model run stages (
TYPE:
|
model_name
abstractmethod
property
#
Return the model identifier string (e.g. 'schism', 'sfincs').
stage_order
abstractmethod
property
#
Ordered list of stage names for this model's pipeline.
build_environment
abstractmethod
#
Add model-specific environment variables to env (mutating).
Called by :meth:WorkflowStage.build_environment after shared
variables (OpenMP pinning, HDF5 file locking) have been populated.
Source code in src/coastal_calibration/config/schema.py
validate
abstractmethod
#
create_stages
abstractmethod
#
SchismModelConfig#
SchismModelConfig
dataclass
#
SchismModelConfig(
prebuilt_dir=None,
geogrid_file=None,
nodes=1,
ntasks_per_node=0,
exclusive=True,
nscribes=0,
omp_num_threads=2,
oversubscribe=False,
schism_exe=None,
include_noaa_gages=False,
discharge_file=None,
create_water_level_animation=False,
animation_fps=10,
animation_time_stride=1,
obs_points_csv=None,
output_freq_hours=1.0,
single_output_file=False,
run_param_overrides=dict(),
runtime_env=dict(),
)
Bases: ModelConfig
SCHISM model configuration.
Contains compute parameters (MPI layout, SCHISM binary), the path to a prebuilt model directory, and the geogrid file used for atmospheric forcing regridding.
| PARAMETER | DESCRIPTION |
|---|---|
prebuilt_dir
|
Path to the directory containing the pre-built SCHISM model
files (
TYPE:
|
geogrid_file
|
Path to the WRF geogrid file (e.g.
TYPE:
|
nodes
|
Number of SLURM nodes. Defaults to
TYPE:
|
ntasks_per_node
|
MPI tasks per node. When
TYPE:
|
exclusive
|
Request exclusive node access.
TYPE:
|
nscribes
|
Number of SCHISM scribe processes. When
TYPE:
|
omp_num_threads
|
OpenMP threads per MPI rank. Defaults to
TYPE:
|
oversubscribe
|
Pass
TYPE:
|
schism_exe
|
Path to a compiled SCHISM executable. When set, the
TYPE:
|
include_noaa_gages
|
When True, automatically query NOAA CO-OPS for water level
stations within the model domain (computed from the concave
hull of open boundary nodes in
TYPE:
|
discharge_file
|
Path to a
TYPE:
|
create_water_level_animation
|
When True, the
TYPE:
|
animation_fps
|
Frames per second for the animation output.
TYPE:
|
animation_time_stride
|
Keep every
TYPE:
|
obs_points_csv
|
Path to a CSV with columns
TYPE:
|
output_freq_hours
|
How often SCHISM writes field outputs, in hours. Translated into
the
TYPE:
|
single_output_file
|
When True, set
TYPE:
|
run_param_overrides
|
Arbitrary key/value pairs written into
TYPE:
|
resolved_discharge_file
property
#
Resolve the NWM-reaches discharge CSV, or None to skip discharge.
Resolution order:
discharge_fileexplicitly set → use it if it exists, elseNone. An explicit configuration is treated as exclusive: it does not silently fall back to the prebuilt-directory convention.discharge_fileunset → look fornwmReaches.csvnext to the prebuilt model (matching the Pacific/Hawaii/PRVI/AtlGulf convention). Use it if present.- Otherwise →
None(river forcing is skipped and SCHISM is configured withif_source = 0).
A missing optional file degrades gracefully — the caller skips discharge rather than aborting.
elevation_correction_csv
property
#
Return elevation_correction.csv next to the prebuilt model.
Returns None when prebuilt_dir is unset or when the
correction file is absent. Callers can pass the result straight
into readers that accept an optional path without re-doing the
exists() check.
SfincsModelConfig#
SfincsModelConfig
dataclass
#
SfincsModelConfig(
prebuilt_dir,
model_root=None,
discharge_locations_file=None,
merge_discharge=False,
include_precip=False,
include_wind=False,
include_pressure=False,
meteo_res=None,
forcing_to_mesh_offset_m=0.0,
vdatum_mesh_to_msl_m=0.0,
sfincs_exe=None,
omp_num_threads=0,
run_param_overrides=dict(),
floodmap_dem=None,
floodmap_hmin=0.05,
floodmap_enabled=True,
floodmap_land_only=True,
create_water_level_animation=False,
animation_fps=10,
animation_time_stride=1,
obs_points_csv=None,
runtime_env=dict(),
)
Bases: ModelConfig
SFINCS model configuration.
SFINCS runs on a single node using OpenMP (all available cores). There is no MPI or multi-node support.
| PARAMETER | DESCRIPTION |
|---|---|
prebuilt_dir
|
Path to the directory containing the pre-built model files
(
TYPE:
|
model_root
|
Output directory for the built model. Defaults to
TYPE:
|
discharge_locations_file
|
Path to a SFINCS
TYPE:
|
merge_discharge
|
Whether to merge with pre-existing discharge source points.
TYPE:
|
include_precip
|
When True, add precipitation forcing from the meteorological
data catalog entry (derived from
TYPE:
|
include_wind
|
When True, add spatially-varying wind forcing (
TYPE:
|
include_pressure
|
When True, add spatially-varying atmospheric pressure forcing
(
TYPE:
|
meteo_res
|
Output resolution (m) for gridded meteorological forcing
(precipitation, wind, pressure). When None (default) the
resolution is determined from the SFINCS quadtree grid — it
equals the base cell size (coarsest level) so that the meteo
grid is never finer than needed. Setting an explicit value
(e.g. .. note:: Without this parameter the HydroMT
TYPE:
|
forcing_to_mesh_offset_m
|
Vertical offset in meters added to the boundary-condition water levels before they enter SFINCS. Tidal-only sources (harmonic prediction) provide oscillations centered on
zero (MSL) but carry no information about where MSL sits on the
mesh's vertical datum. This parameter anchors the forcing signal
to the correct geodetic height on the mesh. Set it to the
elevation of MSL in the mesh datum obtained from VDatum
(e.g. For sources that already report water levels in the mesh datum
(e.g. STOFS on a NAVD88 mesh) set this to Defaults to
TYPE:
|
vdatum_mesh_to_msl_m
|
Vertical offset in meters added to the simulated water level
before comparison with NOAA CO-OPS observations (which are in
MSL). The model output inherits the mesh vertical datum, so
this converts it to MSL (e.g. Defaults to
TYPE:
|
sfincs_exe
|
Path to a compiled SFINCS executable. When set, the
TYPE:
|
omp_num_threads
|
Number of OpenMP threads. Defaults to the number of physical CPU
cores on the current machine (see :func:
TYPE:
|
run_param_overrides
|
Arbitrary key/value pairs written to
TYPE:
|
create_water_level_animation
|
When True, the
TYPE:
|
animation_fps
|
Frames per second for the animation output.
TYPE:
|
animation_time_stride
|
Keep every
TYPE:
|
obs_points_csv
|
Path to a CSV with columns
TYPE:
|
MonitoringConfig#
MonitoringConfig
dataclass
#
MonitoringConfig(
log_level="INFO",
log_file=None,
enable_progress_tracking=True,
enable_timing=True,
)
Workflow monitoring configuration.
DownloadConfig#
DownloadConfig
dataclass
#
Data download configuration.
SFINCS Creation Configuration#
SfincsCreateConfig#
SfincsCreateConfig
dataclass
#
SfincsCreateConfig(
aoi,
output_dir,
download_dir=None,
grid=GridConfig(),
elevation=ElevationConfig(),
mask=MaskConfig(),
subgrid=SubgridConfig(),
data_catalog=DataCatalogConfig(),
monitoring=MonitoringConfig(),
river_discharge=None,
aoi_simplify_neck_m=0.0,
add_noaa_gages=False,
observation_points=list(),
observation_locations_file=None,
merge_observations=False,
obs_snap_depth_threshold=-2.0,
obs_snap_search_radius_m=1000.0,
)
Root configuration for SFINCS model creation workflow.
Loaded from YAML via :meth:from_yaml. All paths are resolved to
absolute paths during construction.
stage_order
property
#
Ordered list of creation stages to execute.
Roughness is embedded in the quadtree subgrid tables, so there
is no separate roughness stage. The create_discharge stage
is included only when :attr:river_discharge is configured.
from_yaml
classmethod
#
Load configuration from a YAML file.
| PARAMETER | DESCRIPTION |
|---|---|
config_path
|
Path to YAML configuration file.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
SfincsCreateConfig
|
Loaded configuration. |
| RAISES | DESCRIPTION |
|---|---|
FileNotFoundError
|
If the configuration file does not exist. |
YAMLError
|
If the YAML file is malformed. |
Source code in src/coastal_calibration/config/create_schema.py
from_dict
classmethod
#
Create config from a plain dictionary.
| PARAMETER | DESCRIPTION |
|---|---|
data
|
Configuration dictionary with the same structure as the YAML
file (see :meth:
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
SfincsCreateConfig
|
|
Source code in src/coastal_calibration/config/create_schema.py
405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 | |
to_yaml
#
Write configuration to a YAML file.
| PARAMETER | DESCRIPTION |
|---|---|
path
|
Path to YAML output file. Parent directories are created automatically.
TYPE:
|
Source code in src/coastal_calibration/config/create_schema.py
to_dict
#
Convert configuration to a plain dictionary.
Source code in src/coastal_calibration/config/create_schema.py
660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 | |
validate
#
Validate configuration and return a list of error messages.
| RETURNS | DESCRIPTION |
|---|---|
list of str
|
Validation errors (empty when the config is valid). |
Source code in src/coastal_calibration/config/create_schema.py
GridConfig#
GridConfig
dataclass
#
Grid generation configuration.
ElevationConfig#
ElevationConfig
dataclass
#
ElevationConfig(
datasets=(
lambda: [
ElevationDataset(
name="copdem_30m",
zmin=0.001,
source="copdem_30m",
),
ElevationDataset(
name="gebco_15arcs",
zmin=-20000,
source="gebco_15arcs",
),
]
)(),
buffer_cells=1,
)
Elevation and bathymetry configuration.
MaskConfig#
MaskConfig
dataclass
#
Active-cell mask and boundary configuration.
SubgridConfig#
SubgridConfig
dataclass
#
SubgridConfig(
nr_subgrid_pixels=5,
lulc_dataset="esa_worldcover",
lulc_source="esa_worldcover",
reclass_table=None,
manning_land=0.04,
manning_sea=0.02,
)
Subgrid table configuration.
Roughness parameters are included here because for quadtree grids the Manning coefficients are embedded directly in the subgrid tables.
RiverDischargeConfig#
RiverDischargeConfig
dataclass
#
River discharge source point configuration.
Derives discharge source points from user-provided flowline geometries (e.g. exported from the QGIS plugin). Each flowline's downstream endpoint (closest to the AOI boundary) is registered as a SFINCS discharge source location.
Workflow Runners#
CoastalCalibRunner#
CoastalCalibRunner
#
Main workflow runner for coastal model calibration.
This class orchestrates the entire calibration workflow, managing stage execution and progress monitoring.
Supports both SCHISM (model="schism", default) and SFINCS
(model="sfincs") pipelines. The model type is selected via
config.model.
Initialize the workflow runner.
| PARAMETER | DESCRIPTION |
|---|---|
config
|
Coastal calibration configuration.
TYPE:
|
Source code in src/coastal_calibration/runner.py
validate
#
Validate configuration and prerequisites.
| RETURNS | DESCRIPTION |
|---|---|
list of str
|
List of validation error messages (empty if valid). |
Source code in src/coastal_calibration/runner.py
run
#
Execute the calibration workflow.
| PARAMETER | DESCRIPTION |
|---|---|
start_from
|
Stage name to start from (skip earlier stages).
TYPE:
|
stop_after
|
Stage name to stop after (skip later stages).
TYPE:
|
dry_run
|
If True, validate but don't execute.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
WorkflowResult
|
Result with execution details. |
Source code in src/coastal_calibration/runner.py
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 | |
SfincsCreator#
SfincsCreator
#
Runner that orchestrates the SFINCS model creation pipeline.
Mirrors :class:~coastal_calibration.runner.CoastalCalibRunner but
operates on a :class:SfincsCreateConfig and delegates to
:class:~coastal_calibration.sfincs.create.CreateStage instances.
Source code in src/coastal_calibration/sfincs/create.py
run
#
Execute the SFINCS model creation workflow.
| PARAMETER | DESCRIPTION |
|---|---|
start_from
|
Stage name to start from (skip earlier stages).
TYPE:
|
stop_after
|
Stage name to stop after (skip later stages).
TYPE:
|
dry_run
|
If True, validate but don't execute.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
WorkflowResult
|
Result with execution details. |
Source code in src/coastal_calibration/sfincs/create.py
1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 | |
WorkflowResult#
WorkflowResult
dataclass
#
WorkflowResult(
success,
job_id,
start_time,
end_time,
stages_completed,
stages_failed,
outputs,
errors,
)
Result of a workflow execution.
to_dict
#
Convert to dictionary.
Source code in src/coastal_calibration/runner.py
save
#
Save result to JSON file.
| PARAMETER | DESCRIPTION |
|---|---|
path
|
Path to output JSON file. Parent directories will be created if they don't exist.
TYPE:
|
Source code in src/coastal_calibration/runner.py
Plotting#
SfincsGridInfo#
SfincsGridInfo
dataclass
#
SfincsGridInfo(
grid_type,
crs,
base_resolution,
levels,
n_faces=None,
n_edges=None,
shape=None,
_verts=None,
_level_per_face=None,
_mask=None,
_grid_extent=None,
)
Summary of a SFINCS model grid.
Use :meth:from_model_root to construct from a SFINCS model
directory. The instance carries enough pre-computed state to
drive :func:plot_mesh without re-loading the model.
Examples:
>>> info = SfincsGridInfo.from_model_root("run/sfincs_model")
>>> print(info)
SfincsGridInfo(quadtree, EPSG:32619)
Faces: 293,850
Edges: 596,123
Level 1: 7,090 cells (512 m)
...
from_model_root
classmethod
#
Load grid metadata from a SFINCS model directory.
| PARAMETER | DESCRIPTION |
|---|---|
model_root
|
Path to the SFINCS model directory (must contain
TYPE:
|
Source code in src/coastal_calibration/sfincs/plotting.py
plot_mesh#
plot_mesh
#
plot_mesh(
info,
*,
ax=None,
title=None,
basemap=True,
basemap_source=None,
basemap_zoom=11,
figsize=(11, 7),
)
Plot the SFINCS mesh colored by refinement level.
| PARAMETER | DESCRIPTION |
|---|---|
info
|
Grid metadata from :meth:
TYPE:
|
ax
|
Existing axes to plot into. A new figure is created when None.
TYPE:
|
title
|
Plot title. Defaults to a description derived from info.
TYPE:
|
basemap
|
If True (default), overlay satellite imagery via contextily.
TYPE:
|
basemap_source
|
Tile provider passed to
TYPE:
|
basemap_zoom
|
Zoom level for the basemap tiles.
TYPE:
|
figsize
|
Figure size when ax is None.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
(Figure, Axes)
|
|
Source code in src/coastal_calibration/sfincs/plotting.py
plot_floodmap#
plot_floodmap
#
plot_floodmap(
floodmap_path,
*,
ax=None,
title=None,
basemap=True,
basemap_source=None,
basemap_zoom=12,
max_display_px=2000,
vmax_percentile=98,
figsize=(11, 7),
color_map="viridis_r",
)
Plot a flood-depth COG with an optional satellite basemap.
Reads at an overview level that keeps the longest axis under max_display_px pixels, masks dry / NaN pixels, and renders with a reverse viridis color map.
| PARAMETER | DESCRIPTION |
|---|---|
floodmap_path
|
Path to the flood-depth GeoTIFF (e.g.
TYPE:
|
ax
|
Existing axes to plot into. A new figure is created when None.
TYPE:
|
title
|
Plot title. Defaults to
TYPE:
|
basemap
|
If True (default), overlay satellite imagery via contextily.
TYPE:
|
basemap_source
|
Tile provider passed to
TYPE:
|
basemap_zoom
|
Zoom level for the basemap tiles, by default 12.
TYPE:
|
max_display_px
|
Target maximum dimension (in pixels) for the rendered raster. Controls which overview level is read, by default 2000.
TYPE:
|
vmax_percentile
|
Upper percentile for the color-map range.
TYPE:
|
figsize
|
Figure size when ax is None, by default (11, 7).
TYPE:
|
color_map
|
Name of the Matplotlib colormap to use for plotting the flood depth, by default "viridis_r".
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
(Figure, Axes)
|
|
Source code in src/coastal_calibration/sfincs/plotting.py
349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 | |
plot_station_comparison#
plot_station_comparison
#
Create station comparison figures for one or more simulated runs.
| PARAMETER | DESCRIPTION |
|---|---|
runs
|
Maps each run's label to a
TYPE:
|
station_ids
|
NOAA station IDs, one per column of every run's elevation array.
TYPE:
|
figs_dir
|
Output directory for figures (created if needed).
TYPE:
|
obs_ds
|
Observed water levels with a
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[Path]
|
Paths to the saved PNG figures, in pagination order (4 stations per 2x2 figure). |
Notes
A station is plotable if any run or the observations has at least one finite value at that station. Stations with no data anywhere are silently skipped.
Runs are drawn on top of observations. Colors are drawn from the
tab10 colormap (cycling at 10 runs); markers cycle through a
10-shape palette independently.
Source code in src/coastal_calibration/plotting/stations.py
106 107 108 109 110 111 112 113 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 | |
plot_water_level#
plot_water_level
#
plot_water_level(
ds,
time=0,
*,
variable=None,
ax=None,
cmap="viridis",
vmin=None,
vmax=None,
colorbar=True,
title=None,
figsize=(10, 7),
shading_regular="auto",
mask_dry=True,
dry_threshold=0.05,
basemap=False,
basemap_source=None,
basemap_zoom=None,
crs=None,
)
Render a single water-level (or water-depth) frame from ds.
| PARAMETER | DESCRIPTION |
|---|---|
ds
|
Dataset produced by one of the
TYPE:
|
time
|
Time selector. Integers are positional (
TYPE:
|
variable
|
Data variable to plot. Common choices:
TYPE:
|
ax
|
Axes to draw into. A new figure + axes are created when None.
TYPE:
|
cmap
|
Matplotlib colormap name.
TYPE:
|
vmin
|
Colormap limits. When None, both are computed from the 1st/99th percentiles of the full time series after dry-cell masking so outlier bed-elevation cells do not dominate the scale.
TYPE:
|
vmax
|
Colormap limits. When None, both are computed from the 1st/99th percentiles of the full time series after dry-cell masking so outlier bed-elevation cells do not dominate the scale.
TYPE:
|
colorbar
|
If True, attach a colorbar to the axes.
TYPE:
|
title
|
Plot title. Defaults to
TYPE:
|
figsize
|
Figure size when ax is None.
TYPE:
|
shading_regular
|
TYPE:
|
mask_dry
|
Mask cells classified as dry. The mask is sourced (in priority order):
When neither variable is present the dataset is plotted unmasked.
TYPE:
|
dry_threshold
|
Water-depth threshold (m) used by the fallback mask. 5 cm is a common SFINCS/HydroMT convention for "wet enough to plot".
TYPE:
|
basemap
|
If True, overlay a satellite basemap via :mod:
TYPE:
|
basemap_source
|
Tile provider passed to :func:
TYPE:
|
basemap_zoom
|
Zoom level for the basemap tiles; None lets contextily pick.
TYPE:
|
crs
|
Override the dataset CRS for basemap reprojection (e.g.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
(ax, collection)
|
The axes used for drawing and the primitive collection
( |
| RAISES | DESCRIPTION |
|---|---|
KeyError
|
If ds lacks the |
ValueError
|
If no water-level variable can be auto-detected or the mesh type is unknown. |
Notes
When ax is None a new figure is created and the caller owns it —
remember to plt.close(ax.get_figure()) when looping over many
frames outside a notebook, otherwise matplotlib accumulates figures
and memory grows unbounded.
Source code in src/coastal_calibration/plotting/spatial.py
412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 | |
animate_water_level#
animate_water_level
#
animate_water_level(
ds,
outfile,
*,
variable=None,
fps=10,
time_stride=1,
dpi=150,
writer="auto",
cmap="viridis",
vmin=None,
vmax=None,
figsize=(10, 7),
title_prefix=None,
mask_dry=True,
dry_threshold=0.05,
)
Render a time-animation of the water-level field to a movie file.
| PARAMETER | DESCRIPTION |
|---|---|
ds
|
Canonical dataset from a
TYPE:
|
outfile
|
Destination path. The suffix selects the writer:
TYPE:
|
variable
|
Variable to animate. Defaults to the result of :func:
TYPE:
|
fps
|
Frames per second in the output.
TYPE:
|
time_stride
|
Keep every
TYPE:
|
dpi
|
Output resolution.
TYPE:
|
writer
|
Writer selector;
TYPE:
|
cmap
|
Matplotlib colormap name.
TYPE:
|
vmin
|
Colormap limits — shared across all frames. When None, each is
filled in from the 1st/99th percentile of the full time series
(see :func:
TYPE:
|
vmax
|
Colormap limits — shared across all frames. When None, each is
filled in from the 1st/99th percentile of the full time series
(see :func:
TYPE:
|
figsize
|
Figure size.
TYPE:
|
title_prefix
|
Prefix prepended to the auto-generated per-frame title.
TYPE:
|
mask_dry
|
Mask dry cells in every frame using
TYPE:
|
dry_threshold
|
Water-depth threshold (m) for the fallback mask.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Path
|
The resolved output path. |
| RAISES | DESCRIPTION |
|---|---|
RuntimeError
|
If an |
ValueError
|
If the output suffix is unrecognized and no explicit writer was given. |
Notes
The renderer is built from :func:plot_water_level, so any future
additions to the frame layout (basemaps, projections, annotations)
automatically flow through to animations.
Source code in src/coastal_calibration/plotting/animate.py
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 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | |
Output Readers#
load_schism_elevation#
load_schism_elevation
#
Load SCHISM 2-D elevation across all output blocks.
| PARAMETER | DESCRIPTION |
|---|---|
run_dir
|
SCHISM run directory. Either the project root (the reader will look
under
TYPE:
|
time_slice
|
Slice applied along the concatenated time dimension before the dataset is returned. Useful for previews of long runs.
TYPE:
|
correction_file
|
Path to
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Dataset
|
Dataset with variables |
| RAISES | DESCRIPTION |
|---|---|
NotADirectoryError
|
If run_dir is not a directory. |
FileNotFoundError
|
If no |
KeyError
|
If any required mesh variable is missing from the first block. |
Notes
The reader does not require dask. Blocks are concatenated manually
via :func:xarray.concat after opening each file with the default engine.
Mesh variables (node coordinates and face connectivity) are read from
the first block only — SCHISM keeps these constant across a run.
Source code in src/coastal_calibration/schism/outputs.py
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 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 | |
load_sfincs_water_level#
load_sfincs_water_level
#
Load SFINCS time-dependent water-level + depth from sfincs_map.nc.
| PARAMETER | DESCRIPTION |
|---|---|
run_dir
|
SFINCS run directory containing
TYPE:
|
time_slice
|
Slice applied along the time dimension before the dataset is returned. Useful for previews of long runs.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Dataset
|
Canonical dataset containing both Any 2-D geographic coordinates |
| RAISES | DESCRIPTION |
|---|---|
NotADirectoryError
|
If run_dir is neither a directory nor a |
FileNotFoundError
|
If the map output file cannot be located, or if a structured
|
KeyError
|
If a required variable ( |
ValueError
|
If |
Notes
The reader intentionally opens sfincs_map.nc directly with xarray
rather than going through :class:hydromt_sfincs.SfincsModel. This
keeps post-processing independent of a full HydroMT model setup and
works in lightweight environments where only xarray + netcdf4
are available. A HydroMT-based path can be added in a follow-up if
needed for quadtree outputs.
Source code in src/coastal_calibration/sfincs/outputs.py
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 | |
Observation Points#
load_obs_points#
load_obs_points
#
Read a user-supplied observation-points CSV.
| PARAMETER | DESCRIPTION |
|---|---|
path
|
Path to a CSV with columns
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
DataFrame
|
A frame with exactly those three columns. |
| RAISES | DESCRIPTION |
|---|---|
FileNotFoundError
|
If path does not exist. |
ValueError
|
If any required column is missing, if IDs are not unique, or if any coordinate is non-finite. |
Source code in src/coastal_calibration/observations.py
validate_points_in_domain#
validate_points_in_domain
#
Raise if any point in points falls outside the model WGS84 bbox.
| PARAMETER | DESCRIPTION |
|---|---|
points
|
Must have
TYPE:
|
ds
|
Canonical dataset from a
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Polygon
|
The WGS84 bounding polygon used for the check. Callers typically discard this; it is returned for inspection / logging. |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
If one or more points are outside the domain. The error message lists offending IDs (up to 10). |
Source code in src/coastal_calibration/observations.py
extract_water_level_series#
extract_water_level_series
#
Extract per-point water-level time series by nearest-cell lookup.
| PARAMETER | DESCRIPTION |
|---|---|
ds
|
Canonical dataset from a
TYPE:
|
points
|
Must carry columns
TYPE:
|
variable
|
Data variable to extract. When None (default), auto-detects
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
DataFrame
|
Indexed by the dataset's time axis, with one column per input
point (named by its |
Notes
The unstructured-mesh lookup is brute-force — one argmin scan
of all mesh nodes/faces per observation point, implemented in
Python. This is intentional (avoids a SciPy runtime dep and keeps
peak memory bounded), but it scales as O(n_cells * n_points).
Up to a few hundred obs points against a multi-million-node mesh
stays well under a second; past that, pre-build a spatial index at
the caller instead of calling this function inside a loop.
Source code in src/coastal_calibration/observations.py
Flood Depth Map#
create_flood_depth_map#
create_flood_depth_map
#
create_flood_depth_map(
model_root,
dem_path,
output_path=None,
*,
index_path=None,
create_index=True,
hmin=0.05,
land_only=True,
dem_offset=0.0,
reproj_method="nearest",
nrmax=2000,
model=None,
log=None,
)
Create a downscaled flood depth map from SFINCS output.
Reads the maximum water surface elevation (zsmax) from the SFINCS
map output, optionally builds an index COG that maps DEM pixels to
SFINCS grid cells, then downscales onto a high-resolution DEM to
produce a Cloud Optimized GeoTIFF of maximum flood depth.
| PARAMETER | DESCRIPTION |
|---|---|
model_root
|
Path to the SFINCS model directory (must contain
TYPE:
|
dem_path
|
Path to a high-resolution DEM GeoTIFF covering the model domain.
TYPE:
|
output_path
|
Output flood depth COG path. Defaults to
TYPE:
|
index_path
|
Path for the index COG (DEM pixels -> SFINCS cell mapping).
Defaults to
TYPE:
|
create_index
|
If True (default), (re)generate the index COG via
:func:
TYPE:
|
hmin
|
Minimum flood depth (m) to classify a pixel as flooded.
TYPE:
|
land_only
|
Drop pixels the model shows as permanently wet, so the map is inundation rather than inundation plus the sea.
TYPE:
|
dem_offset
|
Vertical offset (m) added to dem_path to put it on the model's
datum. Non-zero when the dataset this DEM came from was merged with
an
TYPE:
|
reproj_method
|
Reprojection method (
TYPE:
|
nrmax
|
Maximum cells per processing block (controls peak memory).
TYPE:
|
model
|
An already-loaded :class:
TYPE:
|
log
|
Logging callback accepting a single message; falls back to the module logger when None.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Path
|
Path to the generated flood depth COG. |
| RAISES | DESCRIPTION |
|---|---|
FileNotFoundError
|
If the DEM or |
FloodmapInputError
|
If |
Source code in src/coastal_calibration/sfincs/floodmap.py
338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 | |
Downloader#
validate_date_ranges#
validate_date_ranges
#
Validate that requested dates are within available ranges.
Source code in src/coastal_calibration/data/downloader.py
NOAA CO-OPS API#
COOPSAPIClient#
COOPSAPIClient
#
Client for interacting with NOAA CO-OPS API.
Initialize COOPS API client.
| PARAMETER | DESCRIPTION |
|---|---|
timeout
|
Request timeout in seconds, by default 120
TYPE:
|
| RAISES | DESCRIPTION |
|---|---|
ImportError
|
If plot optional dependencies are not installed. |
Source code in src/coastal_calibration/data/coops_api.py
stations_metadata
property
#
Get metadata for all water level stations as a GeoDataFrame.
| RETURNS | DESCRIPTION |
|---|---|
GeoDataFrame
|
GeoDataFrame with station metadata and Point geometries. |
validate_parameters
#
Validate API parameters.
| PARAMETER | DESCRIPTION |
|---|---|
product
|
Data product type
TYPE:
|
datum
|
Vertical datum
TYPE:
|
units
|
Unit system
TYPE:
|
time_zone
|
Time zone
TYPE:
|
interval
|
Time interval for predictions
TYPE:
|
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
If any parameter is invalid |
Source code in src/coastal_calibration/data/coops_api.py
build_url
#
Build API request URL for a station.
| PARAMETER | DESCRIPTION |
|---|---|
station_id
|
Station ID
TYPE:
|
begin_date
|
Start date
TYPE:
|
end_date
|
End date
TYPE:
|
product
|
Data product
TYPE:
|
datum
|
Vertical datum
TYPE:
|
units
|
Unit system
TYPE:
|
time_zone
|
Time zone
TYPE:
|
interval
|
Time interval for predictions
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
str
|
Complete API request URL |
Source code in src/coastal_calibration/data/coops_api.py
fetch_data
#
Fetch data from API for multiple URLs.
| PARAMETER | DESCRIPTION |
|---|---|
urls
|
List of API request URLs
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[dict | None]
|
List of JSON responses (None for failed requests) |
Source code in src/coastal_calibration/data/coops_api.py
get_datums
#
Retrieve datum information for one or more stations.
| PARAMETER | DESCRIPTION |
|---|---|
station_ids
|
Single station ID or list of station IDs
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
StationDatum | list[StationDatum]
|
Single StationDatum object if input is str, list of StationDatum if input is list |
| RAISES | DESCRIPTION |
|---|---|
COOPSUnavailableError
|
If every request failed at the transport level (API outage). |
ValueError
|
If responses came back but none had valid datum data. |
Source code in src/coastal_calibration/data/coops_api.py
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 | |
query_coops_byids#
query_coops_byids
#
query_coops_byids(
station_ids,
begin_date,
end_date,
*,
product="water_level",
datum="MLLW",
units="metric",
time_zone="gmt",
interval=None,
)
Fetch water level data from NOAA CO-OPS API for multiple stations.
| PARAMETER | DESCRIPTION |
|---|---|
station_ids
|
List of station IDs to retrieve data for.
TYPE:
|
begin_date
|
Start date in format: yyyyMMdd, yyyyMMdd HH:mm, MM/dd/yyyy, or MM/dd/yyyy HH:mm
TYPE:
|
end_date
|
End date in same format as begin_date.
TYPE:
|
product
|
Data product to retrieve, by default
TYPE:
|
datum
|
Vertical datum for water levels, by default "MLLW".
TYPE:
|
units
|
Units for data, by default "metric".
TYPE:
|
time_zone
|
Time zone for returned data, by default "gmt".
TYPE:
|
interval
|
Time interval for predictions product only, by default None.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Dataset
|
Dataset containing water level data with dimensions (time, station). |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
If invalid parameters are provided or if API returns errors. |
Source code in src/coastal_calibration/data/coops_api.py
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 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 | |
query_coops_bygeometry#
query_coops_bygeometry
#
query_coops_bygeometry(
geometry,
begin_date,
end_date,
*,
product="water_level",
datum="MLLW",
units="metric",
time_zone="gmt",
interval=None,
)
Fetch water level data from NOAA CO-OPS API for stations within a geometry.
| PARAMETER | DESCRIPTION |
|---|---|
geometry
|
Geometry to select stations within (Point, Polygon, etc.)
TYPE:
|
begin_date
|
Start date in format: yyyyMMdd, yyyyMMdd HH:mm, MM/dd/yyyy, or MM/dd/yyyy HH:mm
TYPE:
|
end_date
|
End date in same format as begin_date.
TYPE:
|
product
|
Data product to retrieve, by default
TYPE:
|
datum
|
Vertical datum for water levels, by default "MLLW".
TYPE:
|
units
|
Units for data, by default "metric".
TYPE:
|
time_zone
|
Time zone for returned data, by default "gmt".
TYPE:
|
interval
|
Time interval for predictions product only, by default None.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Dataset
|
Dataset containing water level data for stations within the geometry. |
Source code in src/coastal_calibration/data/coops_api.py
Type Aliases#
# Model type
ModelType = Literal["schism", "sfincs"]
# Meteorological data source
MeteoSource = Literal["nwm_retro", "nwm_ana"]
# Coastal domain identifier
CoastalDomain = Literal["prvi", "hawaii", "atlgulf", "pacific"]
# Boundary condition source
BoundarySource = Literal["tpxo", "stofs"]
# Logging level
LogLevel = Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
Constants#
Default Paths#
Default Path Templates#
DEFAULT_WORK_DIR_TEMPLATE = (
"/ngen-test/coastal/${user}/"
"${model}_${simulation.coastal_domain}_${boundary.source}_${simulation.meteo_source}/"
"${model}_${simulation.start_date}"
)
DEFAULT_RAW_DOWNLOAD_DIR_TEMPLATE = (
"/ngen-test/coastal/${user}/"
"${model}_${simulation.coastal_domain}_${boundary.source}_${simulation.meteo_source}/"
"raw_data"
)