Skip to content

Module Reference

Complete API summary for all PyWMP v0.2.0 modules. For conceptual background see Concepts; for end-to-end examples see the Tutorials.


pywmp.units and pywmp.time_series

Every PyWMP module accepts and returns these two primitives.

from pywmp.units import UnitSystem, USC, SI
from pywmp.time_series import TimeSeries

ts = TimeSeries(times=t_array, values=v_array, units="USC")

UnitSystem: USC (US Customary, ft-cfs-in) or SI (metres-m3/s-mm).

TimeSeries: times (hr), values (units depend on context), units string.


pywmp.meteorology

Precipitation sources and storm definitions.

Class / function Purpose
DesignStorm Wrapper around a hyetograph array
IDFCurve IDF data with depth(duration, return_period)
scs_type_hyetograph(storm_type, duration_hr, dt_hr, total_in, units) SCS Type I / IA / II / III
balanced_storm_hyetograph(depth, dt) NOAA balanced-storm distribution
read_netcdf_precipitation(path) Gridded NetCDF precipitation
read_mrms_grib2(path) MRMS GRIB2 precipitation

IDF/Atlas 14 functions live in pywmp.meteorology.noaa_atlas14:

from pywmp.meteorology.noaa_atlas14 import get_idf_offline, fetch_idf_online

idf = get_idf_offline(region="SE")             # bundled Southeast US Atlas 14 data
idf = fetch_idf_online(lat=26.08, lon=-80.33)  # live NOAA HDSC API call
depth_100yr = idf.depth(duration_hr=24, return_period_yr=100)

pywmp.losses

Class Method Key parameters Reference
InitialConstantLoss compute(precip_ts) ia (in), fc (in/hr) USACE, 2023
SCSCurveLoss compute(precip_ts) CN, amc (I/II/III) NRCS, 2004; USDA SCS, 1986
GreenAmptLoss compute(precip_ts) Ks, psi, theta_i, eta Green & Ampt, 1911
SMALoss compute(precip_ts, pe_ts) six storage-zone parameters Bennett, 1998

pywmp.transform

Class Key parameters Reference
SCSUnitHydrograph lag_hr, area_mi2 NRCS, 2004; Mockus, 1957
ClarkUH Tc (hr), R (hr), time-area curve Clark, 1945
SnyderUH Cp, Ct, tp Snyder, 1938
UserUH tabular UH array

pywmp.routing

Class Key parameters Reference
MuskingumRouting K_hr, x, steps McCarthy, 1938
MuskingumCungeRouting channel geometry, Manning's n Cunge, 1969
ModifiedPulsRouting storage-outflow relationship Puls, 1928
LagRouting lag_hr

pywmp.workflow

High-level model builders.

from pywmp.workflow.design_storm import DesignStormSimulation

sim = DesignStormSimulation(
    storm_type="SCS_II",
    total_depth_in=13.7,
    duration_hr=24,
    dt_hr=0.1,
)
sim.add_subbasin("Sub1", area_mi2=2.5,
                 loss_method="SCS_CN", loss_params={"CN": 80},
                 transform_method="SCS", transform_params={"lag_hr": 1.2})
sim.add_reach("Sub1", "Outlet",
              method="Muskingum", params={"K_hr": 0.5, "x": 0.2, "steps": 3})
results = sim.run()
print(results.summary())

Helper functions: build_basin_model(), build_subbasin_masks(), estimate_scs_lag(), estimate_muskingum_k_x().


pywmp.rom

2D rain-on-mesh finite-volume solver.

ROMGrid

from pywmp.rom.mesh import ROMGrid
grid = ROMGrid.from_tif("dem.tif", units="USC")
# grid.shape -> (nrows, ncols)
# grid.dx_ft, grid.dy_ft  (cell size)

ROMSimulation

from pywmp.rom.simulation import ROMSimulation

sim = ROMSimulation(
    grid=grid,
    precipitation=precip,       # UniformPrecipitation or GriddedPrecipitation
    infiltration=infilt,        # DeficitConstantInfiltration, GriddedGreenAmpt, GriddedSCS, or None
    manning=manning,            # ManningField
    boundary_conditions=[bc],   # list of boundary condition objects
    duration_hr=24.0,
    output_interval_hr=1.0,
    backend="auto",             # "numpy", "numba", "cuda"
    solver=None,                # optional FiniteVolumeSolver with custom h_dry / cfl / max_dt_sec
    sediment=None,              # attach SuspendedSedimentTransport here
    units="USC",
    # Solver uses first-order HLL (Harten et al., 1983) finite-volume scheme;
    # wetting/drying follows Bates & De Roo (2000); CFL stability (Courant et al., 1928)
)
results = sim.run()
results.save_max_depth_tif("depth.tif")

Boundary conditions

Class Usage
NormalDepthOutlet(edge) Free outfall at domain edge ("north"/"south"/"east"/"west")
FixedStageBC(edge, stage_ts) Time-varying water surface elevation at domain edge
InflowBC(cell_row, cell_col, q_ts) Point inflow (1D hydrograph coupling)
InternalInflowBC(mask, q_ts) Distributed inflow over a cell mask

Infiltration

Class Key parameters
DeficitConstantInfiltration(initial_loss, fc, units, grid_shape) SCS-equivalent
GriddedGreenAmptInfiltration(Ks, psi, theta_i, eta) spatially distributed
GriddedSCSInfiltration(cn_array) CN from raster

pywmp.hybrid

from pywmp.hybrid.coupler import HybridSimulation, HybridExcessPrecipSimulation

# Outlet-to-inflow mode
hybrid = HybridSimulation(
    upstream_model=sim_1d,
    rom_grid=grid,
    boundary_spec="outlet",
)
h_results = hybrid.run()

# Excess-precipitation mode
excess = HybridExcessPrecipSimulation(
    upstream_model=sim_1d,
    rom_grid=grid,
    mask_spec=subbasin_masks,   # SubbasinMaskSpec
)
e_results = excess.run()

pywmp.sediment

import numpy as np
from pywmp.sediment import (
    SedimentParameters, RUSLEErosion,
    SuspendedSedimentTransport, BedloadTransport, SedimentResults
)
from pywmp.sediment.ls_factor import compute_ls_from_tif

# Build parameter grid
params = SedimentParameters(
    K=0.28 * np.ones(grid.shape),   # RUSLE K (Wischmeier & Smith, 1978; Renard et al., 1997)
    C=0.15 * np.ones(grid.shape),   # cover-management factor (Renard et al., 1997)
    D50_mm=0.25 * np.ones(grid.shape),  # median grain size
    P=1.0,                          # support-practice factor
)

# Derive LS from DEM slope arrays (returned by rom grid or computed separately)
Sx, Sy = ...   # slope arrays from DEM, same shape as grid
erosion = RUSLEErosion(params, Sx, Sy)

sst = SuspendedSedimentTransport(
    params=params,
    grid=grid,
    erosion=erosion,
)

# Attach to ROMSimulation
sim = ROMSimulation(..., sediment=sst)
results = sim.run()

sed_results = results.sediment    # SedimentResults
print(sed_results.total_erosion_tons, sed_results.total_deposition_tons)

LS factor helpers:

from pywmp.sediment.ls_factor import compute_ls_from_tif, compute_ls_single_cell
ls = compute_ls_from_tif("dem.tif")   # returns LS raster array

Bedload (gravel channels):

bl = BedloadTransport(
    params, Sx, Sy, dx=grid.dx_ft,
    theta_cr=0.0495,      # Wong & Parker (2006) corrected Shields criterion
    use_wong_parker=True,  # corrects MPM (1948) coefficient from 8.0 to 3.97
)
sst = SuspendedSedimentTransport(params, grid, erosion=erosion, bedload=bl)

pywmp.wq

from pywmp.wq import TSSModel, TPModel, WQTransport, EMC_TP_BY_NLCD

tss = TSSModel(
    shape=grid.shape,
    dx=grid.dx_ft,
    D=0.5,              # diffusion coefficient (ft2/s)
    init_conc_mg_L=5.0,
)

tp = TPModel(
    shape=grid.shape,
    dx=grid.dx_ft,
    emc_tp_mg_L=0.3,    # EMC approach: USEPA (1983); Driver & Tasker (1990)
    k_settle=1e-5,      # settling rate (m/s)
)

# Step both models at each ROM time step using depth/velocity arrays
tss.step(h, u, v, dt)
tp.step(h, u, v, dt)

# Retrieve load at outlet
print(tss.outlet_load_kg, tp.outlet_load_kg)

EMC_TP_BY_NLCD is a dict mapping NLCD integer class to TP event mean concentration (mg/L).


pywmp.coastal

from pywmp.coastal import SeawallSLRSweep, SeawallGeometry

# SeawallGeometry is typically built from a DEM and seawall mask via a helper
# (see the coastal simulation module for the from_dem constructor)
sweep = SeawallSLRSweep(
    geometry=geom,
    slr_levels_ft=[0.0, 0.5, 1.0, 1.5, 2.5],
    rain_ts=rain_ts,             # optional TimeSeries for compound event
    normal_tide_ft=0.52,         # MHHW baseline
    ocean_edge="south",
    duration_hr=24.0,
    backend="auto",
)
sweep_results = sweep.run()
print(sweep_results.summary())   # peak stage, flooded area, overtopping per SLR level

pywmp.calibration

from pywmp.calibration import CalibrationEngine, ParameterSet, ParameterBound

def run_model(params: dict) -> np.ndarray:
    # build and run your model; return simulated array
    ...

ps = ParameterSet([
    ParameterBound("CN",    lo=60.0, hi=98.0, initial=80.0),
    ParameterBound("lag_hr", lo=0.3, hi=4.0,  initial=1.2),
])

engine = CalibrationEngine(
    model_fn=run_model,
    observed=obs_array,
    params=ps,
    objective="kge",       # "nse", "kge", "rmse", "volume_error", or Callable
    verbose=True,
)

# Run differential evolution global search (Storn & Price, 1997)
results = engine.run_differential_evolution(maxiter=300, popsize=15)
print(results.summary())
# results.best_params   -> dict of parameter name -> value
# results.best_objective -> float (NSE/KGE; Nash & Sutcliffe, 1970 / Gupta et al., 2009)
# results.history       -> list of CalibrationRecord

pywmp.validation

from pywmp.validation import (
    HydroMetrics, ModelVsObserved, GaugeStation,
    SpatialFloodValidation,
    download_streamflow, download_stage,
    nse, kge, rmse, pbias, peak_flow_error
)

# Scalar metrics from arrays
# NSE: Nash & Sutcliffe (1970); KGE: Gupta et al. (2009); Kling et al. (2012)
m = HydroMetrics(obs=obs_array, sim=sim_array)
print(m.nse, m.kge.r, m.kge.alpha, m.kge.beta, m.rmse, m.pbias)

# USGS NWIS gauge comparison
gauge = GaugeStation("02298202", name="Peace River at Arcadia",
                     lat=27.21, lon=-81.87, da_mi2=1367.0)
obs_df = download_streamflow("02298202", start="2020-09-01", end="2020-09-30")
comparison = ModelVsObserved(obs_df["q_cfs"], sim_series, gauge=gauge)
print(comparison.metrics())

# Spatial flood extent comparison (vs FEMA NFHL or SAR)
sv = SpatialFloodValidation(
    sim_depth=depth_array,     # float array, ft
    ref_mask=fema_ae_mask,     # bool array (True = flooded in reference; FEMA, 2023)
    valid_mask=domain_mask,    # bool array (True = valid domain cells)
    depth_threshold=0.1,
)
# CSI: Schaefer (1990); HR/FAR: Wing et al. (2017); performance: Bates et al. (2010)
print(sv.csi, sv.hit_rate, sv.far, sv.f1)

Standalone functions: nse(obs, sim), kge(obs, sim) -> KGEComponents, rmse(obs, sim), pbias(obs, sim), peak_flow_error(obs, sim), peak_timing_error(obs, sim).


pywmp.datasets

from pywmp.datasets import DatasetManager

dm = DatasetManager(
    aoi=(-81.70, 27.85, -81.50, 27.95),   # (minx, miny, maxx, maxy) WGS-84
    output_dir="data/watershed/",
    cache=True,                            # skip re-download if file exists
)

dm.download_dem(resolution_m=10)
dm.download_watershed(huc_level=12)
dm.download_nhd()
dm.download_nlcd(year=2021)
dm.download_soils()
dm.download_cn()                          # requires NLCD and soils
dm.download_atlas14(lat=27.9, lon=-81.6)
dm.download_floodzone()
print(dm.summary())

Standalone helper: download_for_aoi(aoi, output_dir, lat, lon) runs all eight downloaders in sequence.


pywmp.flood

from pywmp.flood.dem_io import read_tif, write_tif
from pywmp.flood.watershed import WatershedDelineator
from pywmp.flood.hand import HANDRaster
from pywmp.flood.inundation import compute_stats

# DEM I/O
dem, cell_size_ft, nodata, transform, crs = read_tif("dem.tif")

# HAND raster
hand = HANDRaster.from_tif("dem.tif")
hand.compute()  # fills sinks, D8 flow, flow accumulation, HAND

# Inundation statistics
stats = compute_stats(depth_array, cell_size=cell_size_ft)
print(stats.flooded_area_acres, stats.mean_depth_ft, stats.max_depth_ft)

pywmp.cascade

SFWMD Cascade 2001 project parser and detention routing engine.

from pywmp.cascade import parse_cascade_dat, CascadeSimulation

# Parse an official .dat project file
project = parse_cascade_dat("my_project.dat")

# Run the simulation
sim = CascadeSimulation(project)
results = sim.run()
results.to_json("cascade_results.json")

Structure types: CascadeGravityStructure, CascadeGatedSpillway, CascadePumpStation, CascadeDropInlet.


pywmp.api

Optional REST API server for remote simulation control.

pip install "pywmp[api]"
python -m pywmp.api.app

See REST API Tutorial for endpoint examples.


References

Full citations for all methods referenced in this page. See also the master bibliography.

Bates, P. D., & De Roo, A. P. J. (2000). Journal of Hydrology, 236(1–2), 54–77. DOI ↗

Bates, P. D., Horritt, M. S., & Fewtrell, T. J. (2010). Journal of Hydrology, 387(1–2), 33–45. DOI ↗

Clark, C. O. (1945). Transactions ASCE, 110(1), 1419–1446. DOI ↗

Cunge, J. A. (1969). Journal of Hydraulic Research, 7(2), 205–230. DOI ↗

Driver, N. E., & Tasker, G. D. (1990). USGS Water-Supply Paper 2363. PDF ↗

Federal Emergency Management Agency. (2023). National Flood Hazard Layer (NFHL). FEMA MSC ↗

Green, W. H., & Ampt, G. A. (1911). Journal of Agricultural Science, 4(1), 1–24. DOI ↗

Gupta, H. V., Kling, H., Yilmaz, K. K., & Martinez, G. F. (2009). Journal of Hydrology, 377(1–2), 80–91. DOI ↗

Harten, A., Lax, P. D., & van Leer, B. (1983). SIAM Review, 25(1), 35–61. DOI ↗

Kling, H., Fuchs, M., & Paulin, M. (2012). Journal of Hydrology, 424–425, 264–277. DOI ↗

Meyer-Peter, E., & Müller, R. (1948). Proceedings 2nd IAHSR Meeting, pp. 39–64. TU Delft ↗

Mockus, V. (1957). Use of storm and watershed characteristics in synthetic hydrograph analysis and application. American Geophysical Union. USDA NAL ↗

Nash, J. E., & Sutcliffe, J. V. (1970). Journal of Hydrology, 10(3), 282–290. DOI ↗

Natural Resources Conservation Service. (2004). National Engineering Handbook, Part 630: Hydrology. USDA. USDA NAL ↗

Puls, L. G. (1928). Flood regulation of the Tennessee River. USACE. HathiTrust ↗

Renard, K. G., et al. (1997). RUSLE (Agriculture Handbook 703). USDA. ARS ↗

Schaefer, J. T. (1990). Weather and Forecasting, 5(4), 570–575. DOI ↗

Snyder, F. F. (1938). Transactions AGU, 19(1), 447–454. DOI ↗

Storn, R., & Price, K. (1997). Journal of Global Optimization, 11(4), 341–359. DOI ↗

U.S. Environmental Protection Agency. (1983). Results of the NURP (USEPA 400/3-83-16). EPA ↗

Wing, O. E. J., et al. (2017). Water Resources Research, 53(9), 7968–7986. DOI ↗

Wischmeier, W. H., & Smith, D. D. (1978). Agriculture Handbook 537. USDA. ARS ↗

Wong, M., & Parker, G. (2006). Journal of Hydraulic Engineering, 132(11), 1159–1168. DOI ↗