agentsclimarketplace

Swmm climate

Skill Zhonghao1995/agentic-swmm-workflow/skills/swmm-climate

Agentic SWMM is an automated, auditable, and memory-informed framework for reproducible stormwater modelling, integrating QGIS and EPA SWMM through the aiswmm runtime, reusable Skills, and MCP interfaces, with QA verification, provenance tracking, calibration support, and Codex, Hermes, Claude code as well as OpenClaw compatibility

Install
npx -y skills add Zhonghao1995/agentic-swmm-workflow --skill swmm-climate

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 21 stars21 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Deterministic rainfall/climate formatting for SWMM. Use when converting timestamped rainfall CSV files into SWMM-ready [TIMESERIES] lines and [RAINGAGES] helper snippets for swmm-builder.

SKILL.md

6.9 KB, as published. Nobody here has run it

SWMM Climate (MVP rainfall layer)

Part of Agentic SWMM — install the project first for the executable toolchain (aiswmm CLI, SWMM solver, MCP servers).

What this skill provides

  • Deterministic conversion from simple rainfall CSV to:
    • SWMM [TIMESERIES] text lines
    • structured JSON manifest for audit/provenance
  • Deterministic helper generation for SWMM [RAINGAGES] section.
  • MCP wrapper for agentic use.

Input CSV contract

format_rainfall.py expects a header row and at minimum:

  • timestamp: date-time string, default format %Y-%m-%d %H:%M
  • rainfall_mm_per_hr: rainfall intensity in mm/hr

Optional extensions:

  • station_id (or another column via --station-column) to carry multiple stations in one file.
  • Batch mode by repeating --input and/or using --input-glob.
  • Event window slicing via --window-start and --window-end (inclusive).

Accepted rainfall units (--value-units):

  • mm_per_hr (aliases: mm/hr, mm/h)
  • in_per_hr (aliases: in/hr, in/h)

Unit policy (--unit-policy):

  • strict: only mm_per_hr accepted.
  • convert_to_mm_per_hr: supported units are converted to mm_per_hr.

SWMM .dat input contract

For SWMM-native rainfall .dat files (e.g. <series> YYYY M D HH MM value), use --input-dat <path> and declare row units via --dat-value-units:

  • mm_per_hr, in_per_hr (intensities)
  • mm_per_day, in_per_day (24h volumes; divided by 24 to mm/hr)

In .dat mode the --window-start / --window-end filters expect %Y-%m-%d. Use --default-station-id to override the series token taken from the .dat row. --input-dat may be repeated to batch multiple .dat files but cannot be mixed with --input / --input-glob.

Via the MCP tool, pass inputDatPaths: [<path>] and datValueUnits: "mm_per_day" (or another supported unit) instead of inputCsvPath.

Temporal validation:

  • duplicate timestamps are rejected per station/series.
  • timestamp monotonicity is checked per station (--timestamp-policy strict default; optional sort).

Scripts

  • scripts/format_rainfall.py
    • Reads rainfall CSV and writes:
      • timeseries text block for SWMM
      • machine-readable JSON summary
  • scripts/build_raingage_section.py
    • Builds SWMM [RAINGAGES] snippet referencing a timeseries name.
    • For rainfall JSON with multiple stations, use --station-id to choose one station’s series.

Outputs

  • Timeseries text file (SWMM-ready body for [TIMESERIES])
  • JSON summary with:
    • source path + SHA256
    • timestamp range
    • row count
    • timeseries name
  • Raingage snippet text file + JSON summary.

MCP

MCP wrapper location:

  • mcp/swmm-climate/server.js

Exposed tools:

  • format_rainfall
  • build_raingage_section

Example commands

python3 skills/swmm-climate/scripts/format_rainfall.py \
  --input skills/swmm-climate/examples/rainfall_event.csv \
  --out-json runs/swmm-climate/example_rainfall.json \
  --out-timeseries runs/swmm-climate/example_timeseries.txt \
  --series-name TS_EVENT
python3 skills/swmm-climate/scripts/format_rainfall.py \
  --input skills/swmm-climate/examples/rainfall_multi_station.csv \
  --station-column station_id \
  --series-name-template 'TS_EVENT_{station_safe}' \
  --out-json runs/swmm-climate/example_multi_station.json \
  --out-timeseries runs/swmm-climate/example_multi_station.txt
python3 skills/swmm-climate/scripts/format_rainfall.py \
  --input skills/swmm-climate/examples/rainfall_batch_rg1.csv \
  --input skills/swmm-climate/examples/rainfall_batch_rg2.csv \
  --window-start '2025-06-01 00:05' \
  --window-end '2025-06-01 00:15' \
  --series-name TS_BATCH \
  --out-json runs/swmm-climate/example_batch_windowed.json \
  --out-timeseries runs/swmm-climate/example_batch_windowed.txt
python3 skills/swmm-climate/scripts/build_raingage_section.py \
  --gage-id RG1 \
  --rainfall-json runs/swmm-climate/example_multi_station.json \
  --station-id RG1 \
  --interval-min 5 \
  --out-text runs/swmm-climate/example_raingage.txt \
  --out-json runs/swmm-climate/example_raingage.json

Design storms

Use design_storm.py to synthesise a hyetograph from a return period and IDF coefficients when no measured rainfall data exists. The output format matches format_rainfall.py so build_inp --rainfall-json consumes it unchanged.

Methods

MethodWhen to useRequired inputs
chicago (Keifer-Chu)IDF formula coefficients available--form, coefficient flags, --return-period, --duration
alternating_blockExplicit IDF table (duration → intensity)--idf-csv or --idf-json, --duration

IDF formula forms (chicago method)

CN form (--form CN): q = 167·A1·(1+C·lgP)/(t+b)^n [L/s/ha → converted to mm/hr] Flags: --a1, --C, --b, --n

Generic form (--form generic): i = a/(t+b)^c [mm/hr] Flags: --a-coeff, --b, --c-exp

Example — 2-year Chicago hyetograph (CN form, 120 min, 5-min timestep)

python3 skills/swmm-climate/scripts/design_storm.py \
  --method chicago \
  --form CN \
  --a1 10.0 \
  --C 0.811 \
  --b 11.0 \
  --n 0.711 \
  --return-period 2 \
  --duration 120 \
  --dt 5 \
  --out-json runs/swmm-climate/storm_p2y.json \
  --out-timeseries runs/swmm-climate/storm_p2y.txt

Executed output:

{
  "ok": true,
  "out_json": "/tmp/design_storm_test/storm_p2y.json",
  "out_timeseries": "/tmp/design_storm_test/storm_p2y.txt",
  "series_name": "TS_DESIGN_P2Y_120MIN",
  "series_names": [
    "TS_DESIGN_P2Y_120MIN"
  ],
  "rows": 24,
  "stations": 1,
  "interval_minutes": 5
}

Example — alternating-block from an IDF table (inline JSON)

python3 skills/swmm-climate/scripts/design_storm.py \
  --method alternating_block \
  --idf-json '[{"duration_min":5,"intensity_mm_per_hr":60},{"duration_min":10,"intensity_mm_per_hr":45},{"duration_min":30,"intensity_mm_per_hr":28},{"duration_min":60,"intensity_mm_per_hr":18},{"duration_min":120,"intensity_mm_per_hr":11}]' \
  --duration 120 \
  --dt 5 \
  --return-period 2 \
  --out-json runs/swmm-climate/storm_ab_p2y.json \
  --out-timeseries runs/swmm-climate/storm_ab_p2y.txt

MCP tool

generate_design_storm on the swmm-climate MCP server (third tool after format_rainfall and build_raingage_section). Pass camelCase equivalents: method, duration, outJson, outTimeseries, form, returnPeriod, dt, r, a1, cCoeff, b, n, aCoeff, cExp, idfCsv, idfJson, seriesName.

Known limitations

  • MVP focuses on rainfall intensity and raingage section helper only.
  • No temperature/evaporation/wind climatology conversion in this pass.
  • swmm-builder path in this repo still assembles a single raingage reference per build step.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.