VRain design-rainfall package — format specification (v1.0)
The hand-off file between the VRain suite and VBasin. One small JSON document,
UTF-8, written by VRain tools (VRain_package.py) and read by VBasin
(vstream.vrain_import). Any other software can produce or consume it.
File name: vrain_design_rainfall.json (other names are accepted as long as
the format field is right). Units: depth mm, duration hours, time hours.
Top-level fields
| Field | Required | Type | Meaning |
|---|---|---|---|
format | yes | string | must be "vrain-design-rainfall" |
format_version | yes | string | "1.0"; readers accept any 1.x |
generator | yes | object | {tool, version, created_utc} — which VRain tool wrote it |
label | no | string | human label (station, basin, pathway) |
source | no | object | free-form provenance: pathway, distribution, n_years, report path, grid description … |
units | no | object | {"depth":"mm","duration":"hour","time":"hour"} (informative; values are always these) |
design_depth | one of ① | object | headline depth per return period (see below) |
subbasins | one of ① | array | per-sub-basin depths |
stations | one of ① | array | per-station (point) depths |
temporal_pattern | one of ① | object | dimensionless hyetograph |
temporal_patterns_by_subbasin | no | object | {name: temporal_pattern} |
ddf | no | object | depth–duration–frequency table |
hyetographs | no | array | references to real (mm) hyetograph CSVs |
notes | no | array of string | caveats shown to the user |
① At least one of design_depth, subbasins, stations, temporal_pattern
must be present. A package with only temporal_pattern is a pattern-only
package (VRainStorm) and cannot provide depths.
Return periods are JSON object keys (strings): "2", "25", "1.1".
design_depth
"design_depth": {
"scope": "basin", // "basin" | "point" | "subbasin"
"duration_hr": 24, // duration the depth is quoted at
"by_return_period": {"2": 110.9, "5": 135.4, "25": 161.5, "100": 177.3}
}basin— areal value for the whole basin (Thiessen-weighted series, grid average, VRainBasin whole-basin DDF). Use directly.subbasin— headline is the area-weighted mean of the sub-basin values.point— gauge value (single station or mean of stations). Not areal; VBasin logs a warning and uses it as the basin target as-is.
All depths must be positive numbers; NaN/inf are dropped at write time.
subbasins[]
{"name": "Subbasin-NW", "area_km2": 1926.4, "duration_hr": 24,
"by_return_period": {"2": 123.4, "25": 183.6}}VBasin matches name to its own Sub-DAS names exactly first, then loosely
(case-insensitive, ignoring spaces/hyphens/underscores). Unmatched VBasin
Sub-DAS fall back to design_depth with a logged warning.
stations[]
{"name": "Sta A", "x": 110.37, "y": -7.80, "crs": "EPSG:4326",
"duration_hr": 24, "by_return_period": {"2": 95.1, "25": 140.2}}temporal_pattern
"temporal_pattern": {
"method": "huff_pooled", // huff_pooled | huff_modal_quartile | abm | manual | ...
"quartile": "Second Quarter", // optional (Huff)
"duration_hr": 6.0, // null when time_basis = "fraction"
"time_basis": "hours", // "hours" (default) | "fraction"
"time_hr": [1, 2, 3, 4, 5, 6], // END of each interval, strictly increasing, > 0
"fraction": [0.10, 0.20, 0.40, 0.20, 0.07, 0.03] // sums to 1 (±2 %)
}With time_basis: "fraction" the time axis is a fraction of the storm duration
(0–1]; the reader stretches it to the storm duration chosen in VBasin. Readers
re-sample the cumulative curve onto their own time step, so the pattern does
not need to match the model dt.
ddf
"ddf": {"scope": "basin",
"durations_hr": [1, 2, 3, 6, 12, 24],
"by_return_period": {"2": [7.5, 14.8, 22.2, 44.0, 86.5, 161.5], "25": [...]}}Arrays are aligned with durations_hr; null marks a missing value.
hyetographs[]
{"return_period": 25, "method": "huff_pooled", "layout": "wide", "subbasin": null,
"columns": "Time, Hours_from_start, <one column per sub-basin> (mm)",
"csv": "../05_storms/huff_pooled/hyetograph_huff_pooled-T25.csv"}csv is relative to the JSON file. layout: "wide" = one column per
sub-basin; layout: "long" (optional) = subbasin,time_hr,mm.
Validation rules (reader and writer)
format == "vrain-design-rainfall", major version1.- At least one content block (rule ① above).
design_depth.by_return_periodnon-empty, all values numeric and > 0.temporal_pattern.time_hrandfractionequal length, non-empty;time_hrpositive and strictly increasing;fraction≥ 0, sum > 0 (writers normalise to 1); withtime_basis: fractionthe last time ≤ 1.- Readers must refuse (not silently ignore) a file that fails 1–4.
- Readers must not interpolate missing return periods; a requested return period absent from the package is an error.
Writers in VRain
| Tool | File | Content |
|---|---|---|
| VRainMaster v.5 | vrain_design_rainfall.json (primary) + VRain_VBasin_<Pathway>.json per pathway | areal/point depths, sub-daily DDF table as ddf, grid pathway with sub-basins + pattern |
| VRainBasin v.3 | 07_VBasin/vrain_design_rainfall.json (+ vrain_temporal_pattern.csv, README) | basin + per-sub-basin DDF depths, pooled Huff pattern per sub-basin, hyetograph refs |
| VRainFreq v.5 | <export>_vbasin.json, VRain_Freq_<col>_vbasin.json | point depth of the recommended distribution |
| VRainStorm v.4 | VRain_<id>-vbasin_pattern-<dur>.json/.csv | pattern-only (modal Huff quartile) |
Reader in VBasin
vstream.vrain_import.load_vrain_package(path) → VRainPackage;
targets_from_package(pkg, network, return_periods, scope) →
(target_by_rp, target_by_subbasin); pattern_from_package(pkg, storm_duration_hr)
→ (time_hr, fraction, duration_hr). GUI: tab 2A, panel 1b, source Paket
VRain. YAML: banjir.rainfall_source: vrain. CLI: vbasin vrain-check.
Spatial distribution in VBasin: a basin-scope depth is applied uniformly to
every Sub-DAS (build_design_storm(..., spatial_pattern="uniform")); a package
with subbasins[] gives each matched Sub-DAS its own depth. No station
catalogue is used, so the depths reaching HEC-HMS are exactly the package's.
Versioning
Backwards-compatible additions (new optional fields) bump the minor version
(1.1); readers accept any 1.x. Incompatible changes bump the major version.