Links HEC-HMS watershed models to HEC-RAS river models by extracting HMS DSS results and preparing them for RAS boundary condition import. Handles flow hydrograph export, spatial referencing (HMS outlets to RAS cross sections), DSS pathname formatting, quality validation, and time series alignment. Use when setting up HMS→RAS workflows, exporting HMS results for RAS, preparing upstream boundary conditions, or coordinating watershed-to-river integrated modeling. Leverages shared RasDss infrastructure for consistent DSS operations across both tools. Trigger keywords: HMS to RAS, link HMS RAS, boundary condition, upstream BC, watershed to river, integrated model, export HMS, DSS pathname, spatial matching, hydrograph.
from hms_commander import init_hms_project, HmsCmdr, HmsResults, HmsGeo
# 1. Execute HMS simulation
init_hms_project("watershed")
HmsCmdr.compute_run("Design_Storm")
# 2. Extract flow hydrograph for RAS
dss_file = hms.run_df.loc["Design_Storm", "dss_file"]
flows = HmsResults.get_outflow_timeseries(dss_file, "Watershed_Outlet")
# 3. Document outlet location for spatial matching
lat, lon = HmsGeo.get_project_centroid_latlon("project.geo")
print(f"Outlet location: {lat:.4f}°N, {lon:.4f}°W")
# 4. Handoff to RAS engineer
print(f"DSS file: {dss_file}")
print(f"Pathname: /BASIN/WATERSHED_OUTLET/FLOW/15MIN/DESIGN_STORM/")
print(f"Peak flow: {flows['Flow'].max()} cfs")
Code:
hms_commander/HmsResults.py - Flow extractionhms_commander/HmsDss.py - DSS operations (wraps RasDss)hms_commander/HmsGeo.py - Spatial reference: Uses for shared DSS infrastructure
ras_commander.RasDssRules: .claude/rules/integration/hms-ras-linking.md - Complete workflow
Cross-Reference: ras-commander/.claude/skills/importing-hms-boundaries/ - RAS side
HEC-HMS (Watershed) HEC-RAS (River)
↓ ↓
1. Precipitation Geometry
↓ ↓
2. Runoff Generation ←── 5. Import HMS Flows
↓ ↓
3. DSS Output 6. Hydraulic Analysis
↓ ↓
4. Extract & Validate Flood Inundation
HMS Responsibilities (this skill):
RAS Responsibilities (see ras-commander):
from hms_commander import HmsResults
# Extract single outlet
flows = HmsResults.get_outflow_timeseries(dss_file, "Outlet")
# Returns: DataFrame with datetime index, flow in cfs
# Extract multiple tributaries
tributaries = ["Trib_A", "Trib_B", "Trib_C"]
for trib in tributaries:
flows = HmsResults.get_outflow_timeseries(dss_file, trib)
print(f"{trib}: Peak = {flows['Flow'].max()} cfs")
See: hms_extract_dss-results skill for complete extraction capabilities
from hms_commander import HmsGeo
# Get project centroid (general reference)
lat, lon = HmsGeo.get_project_centroid_latlon("project.geo", crs_epsg="EPSG:2278")
# Export subbasin boundaries to GeoJSON
HmsGeo.export_all_geojson(
basin_path="project.basin",
output_dir="geojson",
geo_path="project.geo"
)
# Creates: geojson/subbasins.geojson
# RAS engineer can view in GIS to match outlets → cross sections
Critical: RAS engineer needs outlet locations to spatially match HMS→RAS
HMS uses standard DSS pathname: /A/B/C/D/E/F/
Parts:
Example: /WATERSHED/OUTLET/FLOW/15MIN/100YR/
from hms_commander import HmsDss
# Parse pathname
parts = HmsDss.parse_dss_pathname("/WATERSHED/OUTLET/FLOW/15MIN/100YR/")
# Returns: {'basin': 'WATERSHED', 'element': 'OUTLET', ...}
# Create pathname
pathname = HmsDss.create_dss_pathname(
basin="WATERSHED",
element="Outlet",
param_type="FLOW",
interval="15MIN"
)
See: .claude/rules/integration/hms-ras-linking.md for pathname details
Before handing off to RAS:
from hms_commander import HmsResults
# Check peak flows
peaks = HmsResults.get_peak_flows(dss_file)
assert all(peaks["Peak Flow (cfs)"] > 0), "Negative peaks!"
# Check volume conservation
volumes = HmsResults.get_volume_summary(dss_file)
precip_vol = volumes["Precipitation Volume (ac-ft)"].sum()
runoff_vol = volumes["Runoff Volume (ac-ft)"].sum()
loss_ratio = 1 - (runoff_vol / precip_vol)
print(f"Loss ratio: {loss_ratio:.1%}") # Should be 20-70%
# Check time series completeness
flows = HmsResults.get_outflow_timeseries(dss_file, "Outlet")
assert flows.notna().all().all(), "Missing data!"
Complete Example:
from hms_commander import init_hms_project, HmsCmdr, HmsResults, HmsGeo, hms
# === HMS SIDE ===
# 1. Execute watershed simulation
init_hms_project(r"C:\Projects\Watershed")
HmsCmdr.compute_run("100yr_Storm")
# 2. Extract results
dss_file = hms.run_df.loc["100yr_Storm", "dss_file"]
outlet_flows = HmsResults.get_outflow_timeseries(dss_file, "Watershed_Outlet")
# 3. Validate quality
peaks = HmsResults.get_peak_flows(dss_file)
peak_flow = peaks.loc["Watershed_Outlet", "Peak Flow (cfs)"]
peak_time = peaks.loc["Watershed_Outlet", "Time to Peak"]
print(f"Peak: {peak_flow} cfs at {peak_time}")
# 4. Document spatial reference
lat, lon = HmsGeo.get_project_centroid_latlon("Watershed.geo", crs_epsg="EPSG:2278")
HmsGeo.export_all_geojson("Watershed.basin", "geojson", "Watershed.geo")
# 5. Prepare handoff documentation
print(f"""
HMS Results Ready for RAS Import
=================================
DSS File: {dss_file}
Pathname: /WATERSHED/WATERSHED_OUTLET/FLOW/15MIN/100YR_STORM/
Outlet Location: {lat:.4f}°N, {lon:.4f}°W
Peak Flow: {peak_flow} cfs
Time to Peak: {peak_time}
GeoJSON: geojson/subbasins.geojson (view in GIS for spatial matching)
Next Step: RAS engineer imports as upstream boundary condition
""")
# === RAS SIDE (informational, see ras-commander) ===
# 1. Open RAS project
# 2. Import DSS file as upstream boundary condition
# 3. Spatially match outlet location to RAS cross section
# 4. Validate time series alignment
# 5. Run hydraulic analysis
See: examples/single-outlet-to-ras.md for complete walkthrough
# Extract flows for multiple tributaries
tributaries = ["North_Fork", "South_Fork", "West_Branch"]
for trib in tributaries:
flows = HmsResults.get_outflow_timeseries(dss_file, trib)
peak = flows['Flow'].max()
print(f"{trib}: Peak = {peak} cfs")
# Each becomes separate RAS upstream BC
See: examples/multiple-tributaries.md for complete example
from hms_commander import HmsBasin
# Get all junctions in basin model
junctions = HmsBasin.get_junctions("project.basin")
# Extract flows at each junction
for junction in junctions.index:
flows = HmsResults.get_outflow_timeseries(dss_file, junction)
# Each junction becomes lateral inflow in RAS
See: examples/lateral-inflows.md for complete example
Both HMS and RAS use RasDss:
from hms_commander import HmsDss
# HmsDss wraps ras_commander.RasDss
if HmsDss.is_available():
catalog = HmsDss.get_catalog(dss_file)
flows = HmsDss.read_timeseries(dss_file, pathname)
Why This Matters:
See: .claude/rules/hec-hms/dss-operations.md for DSS integration details
HMS: Typically 15-minute or 1-hour intervals RAS: Computation interval set in unsteady flow plan
Recommendations:
HMS: CFS (cubic feet per second) - standard RAS: CFS (cubic feet per second) - standard
✅ Units match - no conversion needed
Critical: Both must use same coordinate system
# Ensure HMS uses same CRS as RAS project
lat, lon = HmsGeo.get_project_centroid_latlon(
"project.geo",
crs_epsg="EPSG:2278" # Match RAS project CRS
)
def validate_hms_results_for_ras(dss_file, outlet_name):
"""Validate HMS results before RAS import."""
from hms_commander import HmsResults
# 1. Check peak flows are positive
peaks = HmsResults.get_peak_flows(dss_file)
assert peaks.loc[outlet_name, "Peak Flow (cfs)"] > 0, "Zero or negative peak!"
# 2. Check volume conservation
volumes = HmsResults.get_volume_summary(dss_file)
precip_vol = volumes["Precipitation Volume (ac-ft)"].sum()
runoff_vol = volumes["Runoff Volume (ac-ft)"].sum()
loss_ratio = 1 - (runoff_vol / precip_vol)
assert 0.2 <= loss_ratio <= 0.7, f"Unrealistic loss ratio: {loss_ratio:.1%}"
# 3. Check time series has no gaps
flows = HmsResults.get_outflow_timeseries(dss_file, outlet_name)
assert flows.notna().all().all(), "Missing data in time series!"
# 4. Check reasonable flow values
assert flows["Flow"].min() >= 0, "Negative flows detected!"
print("✅ HMS results validated for RAS import")
return True
See: reference/quality-checks.md for complete validation procedures
Symptom: RAS reports "DSS file not found"
Solution: Provide absolute path or copy DSS to RAS project folder
import shutil
shutil.copy(hms_dss_file, ras_project_folder)
Symptom: Uncertain which RAS cross section matches HMS outlet
Solution: Export HMS boundaries to GeoJSON, view in GIS alongside RAS geometry
HmsGeo.export_all_geojson("basin.basin", "geojson", "project.geo")
# Open geojson/subbasins.geojson in QGIS/ArcGIS with RAS geometry
Symptom: HMS results have missing timesteps
Solution: Check HMS log file, re-run with shorter time interval
# Check for computation errors in HMS log
log_file = hms.project_folder / "RUN_Design_Storm.log"
print(log_file.read_text())
Detailed Documentation (load on-demand):
reference/dss-pathname-format.md - Complete pathname structurereference/spatial-matching.md - GIS-based outlet matchingreference/quality-checks.md - Validation proceduresreference/time-alignment.md - Time step compatibilityComplete Examples:
examples/single-outlet-to-ras.md - Basic workflowexamples/multiple-tributaries.md - Multiple upstream BCsexamples/lateral-inflows.md - Internal junction flowsexamples/qaqc-checklist.md - Pre-handoff validationBefore This Skill:
hms_execute_runs skill)hms_parse_basin-models skill)hms_update_met-models skill)After This Skill:
ras-commander/.claude/skills/importing-hms-boundaries/)Cross-Repository:
Potential: Production task agent for end-to-end linking
Would Automate:
Status: Documented in planning, not yet implemented
See: hms_agents/HMS_to_RAS_Linker/ (placeholder for future)
Navigation: This skill covers the HMS side of HMS→RAS integration. For the RAS side, see ras-commander/.claude/skills/importing-hms-boundaries/. For coordinated workflows, use the hms-ras-workflow-coordinator subagent.