Pipes and Pumps¶
Overview¶
This notebook demonstrates extracting results for hydraulic structures within 2D flow areas: pipes, culverts, and pump stations. These structures convey flow through or around 2D mesh areas.
Structure Types in 2D Areas: - SA/2D Connections: Connect storage areas to 2D areas - Lateral Structures: Weirs, gates, culverts between 2D areas - Pump Stations: Mechanical pumps (rating curve or multi-stage) - Culverts: Buried conduits (can pressure flow)
HDF5 Structure for Hydraulic Structures¶
/Results/Unsteady/Output/
├── Output Blocks/
│ └── Base Output/
│ └── Unsteady Time Series/
│ ├── SA/2D Connections/
│ │ └── {Connection Name}/
│ │ ├── Flow/ # Flow through connection
│ │ ├── Velocity/ # Average velocity
│ │ └── Upstream Water Surface/
│ ├── Pump Stations/
│ │ └── {Pump Name}/
│ │ ├── Flow/
│ │ ├── Status/ # On/off status
│ │ └── Power/ # Power consumption
│ └── 2D Area Connections/
│ └── {Structure Name}/
│ ├── Flow/
│ ├── Headwater/ # Upstream WSE
│ └── Tailwater/ # Downstream WSE
Key Structure Datasets: - Flow: Discharge through structure (cfs or cms) - Headwater/Tailwater: WSE upstream and downstream - Velocity: Average flow velocity - Pump Status: Operating state (on/off/cycling)
Reference Documentation¶
- HEC-RAS 2D Modeling User's Manual, Chapter 7: Hydraulic Structures
- HEC-RAS Hydraulic Reference Manual, Chapter 8: Culverts
- HEC-RAS Pump Station Guidance
Common Use Cases¶
- Stormwater Networks: Pipes/culverts in urban drainage
- Flood Control: Pump stations for interior drainage
- Highway Crossings: Road culverts through 2D floodplains
- Levee Systems: Closures and pump-around structures
# =============================================================================
# DEVELOPMENT MODE TOGGLE
# =============================================================================
USE_LOCAL_SOURCE = False # <-- TOGGLE THIS
if USE_LOCAL_SOURCE:
import sys
from pathlib import Path
local_path = str(Path.cwd().parent)
if local_path not in sys.path:
sys.path.insert(0, local_path)
print(f"📁 LOCAL SOURCE MODE: Loading from {local_path}/ras_commander")
else:
print("📦 PIP PACKAGE MODE: Loading installed ras-commander")
# Import ras-commander
from ras_commander import HdfBase, HdfMesh, HdfPipe, HdfPump, HdfResultsPlan, HdfUtils, RasCmdr, RasExamples, init_ras_project, ras
# Verify which version loaded
import ras_commander
print(f"✓ Loaded: {ras_commander.__file__}")
📦 PIP PACKAGE MODE: Loading installed ras-commander
2026-05-23 08:54:05 - numexpr.utils - INFO - NumExpr defaulting to 8 threads.
✓ Loaded: C:\GH\symphony-workspaces\ras-commander\CLB-852\ras_commander\__init__.py
Parameters¶
Configure these values to customize the notebook for your project.
# =============================================================================
# PARAMETERS - Edit these to customize the notebook
# =============================================================================
# Project Configuration
PROJECT_NAME = "Davis" # Example project to extract
RAS_VERSION = "7.0" # HEC-RAS version (6.3, 6.5, 6.6, etc.)
# HDF Analysis Settings
PLAN = "02" # Plan number (for HDF file path)
TIME_INDEX = -1 # Time step index (-1 = last)
PROFILE = "Max" # Profile name for steady analysis
import os
import sys
from pathlib import Path
import h5py
import numpy as np
import pandas as pd
import requests
from tqdm import tqdm
import scipy
import xarray as xr
import geopandas as gpd
import matplotlib.pyplot as plt
from IPython import display
import psutil # For getting system CPU info
from concurrent.futures import ThreadPoolExecutor, as_completed
import time
import subprocess
import shutil
from datetime import datetime, timedelta
from pathlib import Path # Ensure pathlib is imported for file operations
import pyproj
from shapely.geometry import Point, LineString, Polygon
Use Example Project or Load Your Own Project¶
# Extract or reuse the Davis example project.
try:
from _notebook_prereqs import ensure_plan_result_hdf, get_or_extract_example_project
except ModuleNotFoundError:
import sys
examples_dir = Path.cwd() if Path.cwd().name == "examples" else Path.cwd() / "examples"
if examples_dir.exists() and str(examples_dir) not in sys.path:
sys.path.insert(0, str(examples_dir))
from _notebook_prereqs import ensure_plan_result_hdf, get_or_extract_example_project
pipes_ex_path = get_or_extract_example_project(PROJECT_NAME, suffix="12")
print(f"Extracted project path: {pipes_ex_path}")
# Verify the path exists
print(f"Davis project exists: {pipes_ex_path.exists()}")
# Initialize the RAS project (Pipe Networks are only supported in versions 6.6 and above)
import logging
init_ras_project(pipes_ex_path, RAS_VERSION)
logging.info(f"Davis project initialized with folder: {ras.project_folder}")
# Ensure the required results HDF is present before analysis cells run.
plan_number = PLAN
plan_hdf = ensure_plan_result_hdf(
plan_number,
ras_object=ras,
num_cores=2,
clear_geompre=False,
)
print(f"Plan HDF: {plan_hdf}")
2026-05-23 08:54:07 - ras_commander.RasExamples - INFO - Successfully extracted project 'Davis' to c:\GH\symphony-workspaces\ras-commander\CLB-852\examples\example_projects\Davis_12
2026-05-23 08:54:07 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 7.0 at C:\Program Files (x86)\HEC\HEC-RAS\7.0\Ras.exe via filesystem (x86)
2026-05-23 08:54:07 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.7 Beta 5 at C:\Program Files (x86)\HEC\HEC-RAS\6.7 Beta 5\Ras.exe via filesystem (x86)
2026-05-23 08:54:07 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.7 Beta 4 at C:\Program Files (x86)\HEC\HEC-RAS\6.7 Beta 4\Ras.exe via filesystem (x86)
2026-05-23 08:54:07 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.5 at C:\Program Files (x86)\HEC\HEC-RAS\6.5\Ras.exe via filesystem (x86)
2026-05-23 08:54:07 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.4.1 at C:\Program Files (x86)\HEC\HEC-RAS\6.4.1\Ras.exe via filesystem (x86)
2026-05-23 08:54:07 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.3.1 at C:\Program Files (x86)\HEC\HEC-RAS\6.3.1\Ras.exe via filesystem (x86)
2026-05-23 08:54:07 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.3 at C:\Program Files (x86)\HEC\HEC-RAS\6.3\Ras.exe via filesystem (x86)
2026-05-23 08:54:07 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.2 at C:\Program Files (x86)\HEC\HEC-RAS\6.2\Ras.exe via filesystem (x86)
2026-05-23 08:54:07 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.1 at C:\Program Files (x86)\HEC\HEC-RAS\6.1\Ras.exe via filesystem (x86)
2026-05-23 08:54:07 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.0 at C:\Program Files (x86)\HEC\HEC-RAS\6.0\Ras.exe via filesystem (x86)
2026-05-23 08:54:07 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 5.0.7 at C:\Program Files (x86)\HEC\HEC-RAS\5.0.7\Ras.exe via filesystem (x86)
2026-05-23 08:54:07 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 5.0.6 at C:\Program Files (x86)\HEC\HEC-RAS\5.0.6\Ras.exe via filesystem (x86)
2026-05-23 08:54:07 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 5.0.5 at C:\Program Files (x86)\HEC\HEC-RAS\5.0.5\Ras.exe via filesystem (x86)
2026-05-23 08:54:07 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 5.0.4 at C:\Program Files (x86)\HEC\HEC-RAS\5.0.4\Ras.exe via filesystem (x86)
2026-05-23 08:54:07 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 5.0.3 at C:\Program Files (x86)\HEC\HEC-RAS\5.0.3\Ras.exe via filesystem (x86)
2026-05-23 08:54:07 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 5.0.1 at C:\Program Files (x86)\HEC\HEC-RAS\5.0.1\Ras.exe via filesystem (x86)
2026-05-23 08:54:07 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 5.0 at C:\Program Files (x86)\HEC\HEC-RAS\5.0\Ras.exe via filesystem (x86)
2026-05-23 08:54:07 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 4.1.0 at C:\Program Files (x86)\HEC\HEC-RAS\4.1.0\Ras.exe via filesystem (x86)
2026-05-23 08:54:07 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 4.0 at C:\Program Files (x86)\HEC\HEC-RAS\4.0\Ras.exe via filesystem (x86)
2026-05-23 08:54:07 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.6 at C:\Program Files (x86)\HEC\HEC-RAS\6.6\Ras.exe via filesystem (x86)
2026-05-23 08:54:07 - ras_commander.RasUtils - INFO - Discovered 20 installed HEC-RAS version(s)
2026-05-23 08:54:07 - ras_commander.RasPrj - INFO - HEC-RAS 7.0 found via version discovery: C:\Program Files (x86)\HEC\HEC-RAS\7.0\Ras.exe
2026-05-23 08:54:07 - ras_commander.RasMap - INFO - Successfully parsed RASMapper file: C:\GH\symphony-workspaces\ras-commander\CLB-852\examples\example_projects\Davis_12\DavisStormSystem.rasmap
Extracted project to: c:\GH\symphony-workspaces\ras-commander\CLB-852\examples\example_projects\Davis_12
Davis project exists: True
2026-05-23 08:54:07 - ras_commander.RasPrj - INFO - ras-commander v0.96.2 | An open-source project of CLB Engineering Corporation (https://clbengineering.com/) | Docs: https://ras-commander.readthedocs.io | GitHub: https://github.com/gpt-cmdr/ras-commander
2026-05-23 08:54:07 - ras_commander.RasPrj - INFO - Project initialized: DavisStormSystem | Folder: C:\GH\symphony-workspaces\ras-commander\CLB-852\examples\example_projects\Davis_12
2026-05-23 08:54:07 - ras_commander.RasPrj - INFO - Using HEC-RAS executable: C:\Program Files (x86)\HEC\HEC-RAS\7.0\Ras.exe
2026-05-23 08:54:07 - ras_commander.RasPrj - INFO -
═══════════════════════════════════════════════════════════════════════
ras-commander | HEC-RAS Automation Library
Docs: https://gpt-cmdr.github.io/ras-commander/
Repo: https://github.com/gpt-cmdr/ras-commander
═══════════════════════════════════════════════════════════════════════
PROJECT DATAFRAMES (single source of truth — use these, not file globbing):
ras.plan_df Plans, HDF paths, geometry/flow associations
ras.geom_df Geometry files and HDF preprocessor paths
ras.flow_df Steady flow files
ras.unsteady_df Unsteady flow files and configurations
ras.boundaries_df Boundary conditions (type, name, location)
ras.results_df Lightweight HDF results summaries
ras.rasmap_df RASMapper layers, terrain, land cover paths
KEY APIS (static classes — call directly, never instantiate):
Execution: RasCmdr.compute_plan() / compute_parallel() / compute_test_mode()
Plan Files: RasPlan.clone_plan() / clone_geom() / set_geom()
Unsteady: RasUnsteady — IC/BC management, gate openings, precipitation
Geometry: GeomCrossSection, GeomBridge, GeomStorage, GeomLateral, GeomMesh
HDF Results: HdfResultsPlan.get_wse() / get_compute_messages()
HdfResultsMesh.get_mesh_max_ws() / get_mesh_cells_timeseries()
HdfMesh.get_mesh_cell_points()
QA/QC: RasCheck.run_check() / RasFixit (geometry repair)
DSS: RasDss.get_timeseries() / check_pathname()
USGS: UsgsGaugeSpatial, GaugeMatcher, RasUsgsBoundaryGeneration
Precipitation: StormGenerator, Atlas14Storm, PrecipAorc, Atlas14Variance
Terrain: RasTerrain.create_terrain_hdf() / RasTerrainMod
MULTI-PROJECT: Pass ras_object= to all API calls when using local RasPrj instances.
EXAMPLES: 100+ notebooks in examples/ (100s=execution, 200s=geometry, 300s=unsteady,
400s=HDF results, 500s=remote, 800s=QA/QC, 900s=data integration).
Review relevant notebooks before assembling new workflows.
PLATFORM: Most HEC-RAS operations require Windows. Linux/Wine support for
headless execution, data access, geometry modification, and preprocessing
is available via RasProcess (HEC-RAS 6.6+). See ras_commander/RasProcess.py.
Remote distributed execution: ras_commander/remote/ (PsExec, Docker, SSH, cloud).
═══════════════════════════════════════════════════════════════════════
2026-05-23 08:54:07 - root - INFO - Davis project initialized with folder: C:\GH\symphony-workspaces\ras-commander\CLB-852\examples\example_projects\Davis_12
2026-05-23 08:54:07 - ras_commander.RasCmdr - INFO - Using ras_object with project folder: C:\GH\symphony-workspaces\ras-commander\CLB-852\examples\example_projects\Davis_12
2026-05-23 08:54:07 - ras_commander.RasUtils - INFO - Successfully updated file: C:\GH\symphony-workspaces\ras-commander\CLB-852\examples\example_projects\Davis_12\DavisStormSystem.p02
2026-05-23 08:54:07 - ras_commander.RasCmdr - INFO - Set number of cores to 2 for plan: 02
2026-05-23 08:54:07 - ras_commander.RasCmdr - INFO - Running HEC-RAS from the Command Line:
2026-05-23 08:54:07 - ras_commander.RasCmdr - INFO - Running command: "C:\Program Files (x86)\HEC\HEC-RAS\7.0\Ras.exe" -c "C:\GH\symphony-workspaces\ras-commander\CLB-852\examples\example_projects\Davis_12\DavisStormSystem.prj" "C:\GH\symphony-workspaces\ras-commander\CLB-852\examples\example_projects\Davis_12\DavisStormSystem.p02"
2026-05-23 08:57:15 - ras_commander.RasCmdr - INFO - HEC-RAS execution completed for plan: 02
2026-05-23 08:57:15 - ras_commander.RasCmdr - INFO - Total run time for plan 02: 187.43 seconds
ComputeResult(SUCCESS, results_df_row=available)
OPTIONAL: Use your own project instead¶
your_project_path = Path(r"D:\yourprojectpath")
init_ras_project(your_project_path, "6.6") plan_number = "01" # Plan number to use for this notebook
If you use this code cell, don't run the previous cell or change to markdown¶
NOTE: Ensure the HDF Results file was generated by HEC-RAS Version 6.x or above¶
Explore Project Dataframes using 'ras' Object¶
Plan DataFrame for the project:
| plan_number | unsteady_number | geometry_number | Plan Title | Program Version | Short Identifier | Simulation Date | Computation Interval | Mapping Interval | Run HTab | ... | DSS File | Friction Slope Method | UNET D2 SolverType | UNET D2 Name | HDF_Results_Path | Geom File | Geom Path | Flow File | Flow Path | full_path | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 02 | 01 | 02 | Full System ROM with Pump | 6.60 | Full System ROM with Pump | 10JAN2000,1200,11JAN2000,2400 | 12SEC | 10MIN | -1 | ... | dss | 1 | PARDISO (Direct) | area2 | C:\GH\symphony-workspaces\ras-commander\CLB-85... | 02 | C:\GH\symphony-workspaces\ras-commander\CLB-85... | 01 | C:\GH\symphony-workspaces\ras-commander\CLB-85... | C:\GH\symphony-workspaces\ras-commander\CLB-85... |
1 rows × 34 columns
Unsteady DataFrame for the project:
| unsteady_number | full_path | Flow Title | Program Version | Use Restart | Precipitation Mode | Wind Mode | Met BC=Precipitation|Mode | Met BC=Evapotranspiration|Mode | Met BC=Precipitation|Expanded View | Met BC=Precipitation|Constant Units | Met BC=Precipitation|Gridded Source | description | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 01 | C:\GH\symphony-workspaces\ras-commander\CLB-85... | Full System Rain w/ Pump | 6.60 | 0 | Disable | No Wind Forces | Constant | None | -1 | in/hr | DSS |
Boundary Conditions DataFrame for the project:
| unsteady_number | boundary_condition_number | river_reach_name | river_station | storage_area_name | pump_station_name | area_2d | bc_line_name | bc_type | hydrograph_type | ... | Program Version | Use Restart | Precipitation Mode | Wind Mode | Met BC=Precipitation|Mode | Met BC=Evapotranspiration|Mode | Met BC=Precipitation|Expanded View | Met BC=Precipitation|Constant Units | Met BC=Precipitation|Gridded Source | description | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 01 | 1 | DS Channel | DS Normal | Normal Depth | NaN | ... | 6.60 | 0 | Disable | No Wind Forces | Constant | None | -1 | in/hr | DSS | |||||
| 1 | 01 | 2 | area2 | Precipitation Hydrograph | Precipitation Hydrograph | ... | 6.60 | 0 | Disable | No Wind Forces | Constant | None | -1 | in/hr | DSS |
2 rows × 34 columns
| plan_number | unsteady_number | geometry_number | Plan Title | Program Version | Short Identifier | Simulation Date | Computation Interval | Mapping Interval | Run HTab | ... | DSS File | Friction Slope Method | UNET D2 SolverType | UNET D2 Name | HDF_Results_Path | Geom File | Geom Path | Flow File | Flow Path | full_path | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 02 | 01 | 02 | Full System ROM with Pump | 6.60 | Full System ROM with Pump | 10JAN2000,1200,11JAN2000,2400 | 12SEC | 10MIN | -1 | ... | dss | 1 | PARDISO (Direct) | area2 | C:\GH\symphony-workspaces\ras-commander\CLB-85... | 02 | C:\GH\symphony-workspaces\ras-commander\CLB-85... | 01 | C:\GH\symphony-workspaces\ras-commander\CLB-85... | C:\GH\symphony-workspaces\ras-commander\CLB-85... |
1 rows × 34 columns
Find Paths for Results and Geometry HDF's¶
# Get the plan HDF path for the plan_number defined above
plan_hdf_path = ras.plan_df.loc[ras.plan_df['plan_number'] == plan_number, 'HDF_Results_Path'].values[0]
'C:\\GH\\symphony-workspaces\\ras-commander\\CLB-852\\examples\\example_projects\\Davis_12\\DavisStormSystem.p02.hdf'
# Alternate: Get the geometry HDF path if you are extracting geometry elements from the geometry HDF
geom_hdf_path = ras.plan_df.loc[ras.plan_df['plan_number'] == plan_number, 'Geom Path'].values[0] + '.hdf'
'C:\\GH\\symphony-workspaces\\ras-commander\\CLB-852\\examples\\example_projects\\Davis_12\\DavisStormSystem.g02.hdf'
# Extract runtime and compute time data
print("\nExtracting runtime and compute time data")
runtime_df = HdfResultsPlan.get_runtime_data(hdf_path=plan_number)
runtime_df
Extracting runtime and compute time data
| Plan Name | File Name | Simulation Start Time | Simulation End Time | Simulation Duration (s) | Simulation Time (hr) | Completing Geometry (hr) | Preprocessing Geometry (hr) | Completing Event Conditions (hr) | Unsteady Flow Computations (hr) | Complete Process (hr) | Unsteady Flow Speed (hr/hr) | Complete Process Speed (hr/hr) | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | Full System ROM with Pump | DavisStormSystem.p02.hdf | 2000-01-10 12:00:00 | 2000-01-12 | 129600.0 | 36.0 | N/A | 0.00003 | N/A | 0.050751 | 0.051632 | 709.347958 | 697.246522 |
2D Models with Pipe Networks: HDF Data Extraction Examples¶
# Get pipe conduits
pipe_conduits_gdf = HdfPipe.get_pipe_conduits("02") # NOTE: Here we use the plan number instead of the path variable. The library decorators ensure this maps correctly.
print("\nPipe Conduits: pipe_conduits_gdf")
pipe_conduits_gdf
Pipe Conduits: pipe_conduits_gdf
| Name | System Name | US Node | DS Node | Modeling Approach | Conduit Length | Max Cell Length | Shape | Rise | Span | ... | US Entrance Loss Coefficient | DS Exit Loss Coefficient | US Backflow Loss Coefficient | DS Backflow Loss Coefficient | DS Gate Type | Major Group | Minor Group | DS Flap Gate | Polyline | Terrain_Profiles | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 134 | Davis | O13-DMH007 | O13-DMH006 | Hydraulic | 443.740020 | 40.0 | Circular | 6.00 | 6.00 | ... | 0.2 | 0.4 | 0.2 | 0.4 | None | Major Group 2 | 0 | LINESTRING (6635295.441 1965214.2465, 6635196.... | [(0.0, 40.819695), (21.217846, 40.642994), (35... | |
| 1 | 133 | Davis | O13-DMH024 | O13-DMH009 | Hydraulic | 800.000024 | 40.0 | Circular | 6.00 | 6.00 | ... | 0.2 | 0.4 | 0.2 | 0.4 | None | Major Group 2 | 0 | LINESTRING (6635597.5485 1964008.2795, 6635403... | [(0.0, 40.530186), (21.1467, 40.44057), (50.88... | |
| 2 | 132 | Davis | O13-DMH006 | O13-SDS03 | Hydraulic | 443.740070 | 40.0 | Circular | 6.00 | 6.00 | ... | 0.2 | 0.4 | 0.2 | 0.4 | None | Major Group 2 | 0 | LINESTRING (6635196.5532 1965646.8276, 6635131... | [(0.0, 41.700996), (26.817467, 41.552666), (83... | |
| 3 | 131 | Davis | N13-DMH022 | O13-SDS03 | Hydraulic | 982.809915 | 40.0 | Circular | 6.00 | 6.00 | ... | 0.2 | 0.4 | 0.2 | 0.4 | None | Major Group | 0 | LINESTRING (6634067.2602 1966167.7235, 6634761... | [(0.0, 43.376995), (17.315952, 43.37471), (42.... | |
| 4 | 130 | Davis | O13-DMH009 | O13-DMH007 | Hydraulic | 443.231808 | 40.0 | Circular | 6.00 | 6.00 | ... | 0.2 | 0.4 | 0.2 | 0.4 | None | Major Group 2 | 0 | LINESTRING (6635403.0525 1964784.2765, 6635295... | [(0.0, 40.699738), (84.2007, 40.623585), (113.... | |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 127 | 5 | Davis | P13-DI019 | P13-DMH014 | Hydraulic | 55.979169 | 40.0 | Circular | 1.25 | 1.25 | ... | 0.2 | 0.4 | 0.2 | 0.4 | None | 0 | LINESTRING (6634655.8786 1962994.2229, 6634695... | [(0.0, 42.047863), (35.334522, 42.0), (55.9791... | ||
| 128 | 4 | Davis | O14-DI083 | O14-DI081 | Hydraulic | 308.809005 | 40.0 | Circular | 1.25 | 1.25 | ... | 0.2 | 0.4 | 0.2 | 0.4 | None | 0 | LINESTRING (6637776.3431 1963594.9664, 6637752... | [(0.0, 44.843853), (33.0322, 44.765797), (94.1... | ||
| 129 | 3 | Davis | P12-DI011 | P12-DMH005 | Hydraulic | 131.688547 | 40.0 | Circular | 1.25 | 1.25 | ... | 0.2 | 0.4 | 0.2 | 0.4 | None | 0 | LINESTRING (6631602.9099 1963059.1324, 6631558... | [(0.0, 43.631783), (13.137807, 43.916145), (18... | ||
| 130 | 2 | Davis | P12-DI012 | P12-DI011 | Hydraulic | 97.998216 | 40.0 | Circular | 1.25 | 1.25 | ... | 0.2 | 0.4 | 0.2 | 0.4 | None | 0 | LINESTRING (6631662.213 1962981.1145, 6631602.... | [(0.0, 43.573406), (11.616912, 43.510483), (47... | ||
| 131 | 1 | Davis | P12-DI041 | P12-DI042 | Hydraulic | 106.331064 | 40.0 | Circular | 1.25 | 1.25 | ... | 0.2 | 0.4 | 0.2 | 0.4 | None | 0 | LINESTRING (6631979.2535 1962977.423, 6632043.... | [(0.0, 43.332245), (16.201994, 43.217068), (47... |
132 rows × 26 columns
# Plot the pipe conduit linestrings
import matplotlib.pyplot as plt
# Create a new figure with a specified size
plt.figure(figsize=(12, 9))
# Plot each linestring from the GeoDataFrame
for idx, row in pipe_conduits_gdf.iterrows():
# Extract coordinates from the linestring
x_coords, y_coords = row['Polyline'].xy
# Plot the linestring
plt.plot(x_coords, y_coords, 'b-', linewidth=1, alpha=0.7)
# Add vertical line markers at endpoints
plt.plot([x_coords[0]], [y_coords[0]], 'x', color='black', markersize=4)
plt.plot([x_coords[-1]], [y_coords[-1]], 'x', color='black', markersize=4)
# Calculate center point of the line
center_x = (x_coords[0] + x_coords[-1]) / 2
center_y = (y_coords[0] + y_coords[-1]) / 2
# Add pipe name label at center, oriented top-right
plt.text(center_x, center_y, f'{row["Name"]}', fontsize=8,
verticalalignment='bottom', horizontalalignment='left',
rotation=45) # 45 degree angle for top-right orientation
# Add title and labels
plt.title('Pipe Conduit Network Layout')
plt.xlabel('Easting')
plt.ylabel('Northing')
# Add grid
plt.grid(True, linestyle='--', alpha=0.6)
# Adjust layout to prevent label clipping
plt.tight_layout()
# Display the plot
plt.show()

# Plot the first 2 terrain profiles
import matplotlib.pyplot as plt
# Extract terrain profiles from the GeoDataFrame
terrain_profiles = pipe_conduits_gdf['Terrain_Profiles'].tolist()
# Create separate plots for the first 2 terrain profiles
for i in range(2):
profile = terrain_profiles[i]
# Unzip the profile into x and y coordinates
x_coords, y_coords = zip(*profile)
# Create a new figure for each profile
plt.figure(figsize=(12, 6))
plt.plot(x_coords, y_coords, marker='o', linestyle='-', color='g', alpha=0.7)
# Add title and labels
plt.title(f'Terrain Profile {i + 1}')
plt.xlabel('Distance along profile (m)')
plt.ylabel('Elevation (m)')
# Add grid
plt.grid(True, linestyle='--', alpha=0.6)
# Adjust layout to prevent label clipping
plt.tight_layout()
# Display the plot
plt.show()


# Use get_hdf5_dataset_info function to get Pipe Conduits data:
#HdfUtils.get_hdf5_dataset_info(plan_hdf_path, "/Geometry/Pipe Nodes/")
# Get pipe nodes
pipe_nodes_gdf = HdfPipe.get_pipe_nodes(plan_hdf_path)
print("\nPipe Nodes:")
pipe_nodes_gdf
Pipe Nodes:
| Name | System Name | Node Type | Node Status | Condtui Connections (US:DS) | Invert Elevation | Base Area | Terrain Elevation | Terrain Elevation Override | Depth | Top Inlet Type | Top Inlet Elevation | Side Inlet Type | Side Inlet Elevation | Total Connection Count | geometry | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | O14-di027 | Davis | Junction | Junction -with top inlet | 1:1 | 36.060001 | 36.0 | 39.860001 | NaN | 3.799999 | Top Inlet 1 | 39.863369 | NaN | 2 | POINT (6637926.8105 1964917.3197) | |
| 1 | P11-DMH004 | Davis | Junction | Junction -with top inlet | 1:1 | 38.169998 | 36.0 | 48.720001 | NaN | 10.550003 | Top Inlet 1 | 48.718811 | NaN | 2 | POINT (6629444.6337 1963504.411) | |
| 2 | O14-DMH005 | Davis | Junction | Junction -with top inlet | 1:1 | 31.559999 | 36.0 | 40.840000 | NaN | 9.280001 | Top Inlet 1 | 40.843731 | NaN | 2 | POINT (6637368.4974 1966084.5743) | |
| 3 | P11-DMH011 | Davis | Junction | Junction -with top inlet | 1:1 | 37.400002 | 36.0 | 45.330002 | NaN | 7.930000 | Top Inlet 1 | 45.332291 | NaN | 2 | POINT (6630653.5194 1963548.271) | |
| 4 | O15-DMH016 | Davis | Start | US Junction -with top inlet | 0:1 | 38.639999 | 36.0 | 41.700001 | NaN | 3.060001 | Top Inlet 1 | 41.700871 | NaN | 1 | POINT (6638669.1365 1964981.6636) | |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 128 | O11-DMH017 | Davis | Junction | Junction -with top inlet | 3:1 | 31.410000 | 36.0 | 46.750000 | NaN | 15.340000 | Top Inlet 1 | 46.750332 | NaN | 4 | POINT (6630676.6795 1966070.6225) | |
| 129 | N12-DMH010 | Davis | Junction | Junction -with top inlet | 2:1 | 31.639999 | 36.0 | 46.570000 | NaN | 14.930000 | Top Inlet 1 | 46.572021 | NaN | 3 | POINT (6630802.8125 1966200.091) | |
| 130 | N12-DMH009 | Davis | Junction | Junction -with top inlet | 1:1 | 31.740000 | 36.0 | 46.200001 | NaN | 14.460001 | Top Inlet 1 | 46.197262 | NaN | 2 | POINT (6631619.097 1966201.567) | |
| 131 | N12-DMH027 | Davis | Junction | Junction -with top inlet | 2:1 | 29.709999 | 36.0 | 44.830002 | NaN | 15.120003 | Top Inlet 1 | 44.833260 | NaN | 3 | POINT (6632530.277 1966194.4425) | |
| 132 | O13-SDS03 | Davis | Junction | Junction -with top inlet | 3:0 | 24.600000 | 1000.0 | 50.939999 | NaN | 26.339998 | Top Inlet 1 | 50.940022 | NaN | 3 | POINT (6635026.261 1966041.155) |
133 rows × 16 columns
# Use get_hdf5_dataset_info function to get Pipe Conduits data:
#HdfUtils.get_hdf5_dataset_info(plan_hdf_path, "/Geometry/Pipe Networks/")
# Get pipe network data
pipe_network_gdf = HdfPipe.get_pipe_network(plan_hdf_path)
print("\nPipe Network Data:")
pipe_network_gdf
2026-05-23 08:57:15 - root - INFO - Selected Pipe Network: Davis
Pipe Network Data:
| Cell_ID | Conduit_ID | Node_ID | Minimum_Elevation | DS_Face_Indices | Face_Indices | US_Face_Indices | Cell_Property_Info_Index | US Face Elevation | DS Face Elevation | Min Elevation | Area | Info Index | Cell_Polygon | Face_Polylines | Node_Point | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 0 | -1 | 26.824432 | [1] | [0, 1] | [0] | 0 | 26.934290 | 26.824432 | 26.824432 | 242.040024 | 0 | POLYGON ((6635288.02154 1965233.24073, 6635279... | [LINESTRING (6635288.021542038 1965233.2407260... | None |
| 1 | 1 | 0 | -1 | 26.714573 | [2] | [1, 2] | [1] | 0 | 26.934290 | 26.824432 | 26.824432 | 242.040024 | 0 | POLYGON ((6635288.02154 1965233.24073, 6635279... | [LINESTRING (6635288.021542038 1965233.2407260... | None |
| 2 | 2 | 0 | -1 | 26.604715 | [3] | [2, 3] | [2] | 0 | 26.934290 | 26.824432 | 26.824432 | 242.040024 | 0 | POLYGON ((6635288.02154 1965233.24073, 6635279... | [LINESTRING (6635288.021542038 1965233.2407260... | None |
| 3 | 3 | 0 | -1 | 26.494858 | [4] | [3, 4] | [3] | 0 | 26.934290 | 26.824432 | 26.824432 | 242.040024 | 0 | POLYGON ((6635288.02154 1965233.24073, 6635279... | [LINESTRING (6635288.021542038 1965233.2407260... | None |
| 4 | 4 | 0 | -1 | 26.385000 | [5] | [4, 5] | [4] | 0 | 26.934290 | 26.824432 | 26.824432 | 242.040024 | 0 | POLYGON ((6635288.02154 1965233.24073, 6635279... | [LINESTRING (6635288.021542038 1965233.2407260... | None |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 1987 | 1987 | -1 | 72 | 39.456257 | [1976] | [1976] | [] | 325 | 33.416916 | 33.301682 | 33.301682 | 141.037354 | 28 | POLYGON ((6635288.02154 1965233.24073, 6635279... | [LINESTRING (6635288.021542038 1965233.2407260... | None |
| 1988 | 1988 | -1 | 79 | 42.074768 | [1977] | [1977] | [] | 326 | 33.301682 | 33.186447 | 33.186447 | 141.037354 | 28 | POLYGON ((6635288.02154 1965233.24073, 6635279... | [LINESTRING (6635288.021542038 1965233.2407260... | None |
| 1989 | 1989 | -1 | 42 | 40.804863 | [1984] | [1988, 1984] | [1988] | 327 | 33.186447 | 33.071213 | 33.071213 | 141.037354 | 28 | POLYGON ((6635288.02154 1965233.24073, 6635279... | [LINESTRING (6635288.021542038 1965233.2407260... | None |
| 1990 | 1990 | -1 | 46 | 41.998379 | [1987] | [1987] | [] | 328 | 33.071213 | 32.955978 | 32.955978 | 141.037354 | 28 | POLYGON ((6635288.02154 1965233.24073, 6635279... | [LINESTRING (6635288.021542038 1965233.2407260... | None |
| 1991 | 1991 | -1 | 45 | 37.606800 | [1989] | [1989] | [] | 329 | 32.955978 | 32.840744 | 32.840744 | 141.037354 | 28 | POLYGON ((6635288.02154 1965233.24073, 6635279... | [LINESTRING (6635288.021542038 1965233.2407260... | None |
1992 rows × 16 columns
# Get pump stations
pump_stations_gdf = HdfPump.get_pump_stations(plan_hdf_path)
print("\nPump Stations:")
pump_stations_gdf
Pump Stations:
| geometry | station_id | Name | Inlet River | Inlet Reach | Inlet RS | Inlet RS Distance | Inlet SA/2D | Inlet Pipe Node | Outlet River | ... | Outlet Pipe Node | Reference River | Reference Reach | Reference RS | Reference RS Distance | Reference SA/2D | Reference Point | Reference Pipe Node | Highest Pump Line Elevation | Pump Groups | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | POINT (6635027.027 1966080.07) | 0 | Pump Station #1 | NaN | Davis [O13-SDS03] | ... | NaN | NaN | 1 |
1 rows × 24 columns
# Get pump groups
pump_groups_df = HdfPump.get_pump_groups(plan_hdf_path)
print("\nPump Groups:")
pump_groups_df
Pump Groups:
| Pump Station ID | Name | Bias On | Start Up Time | Shut Down Time | Width | Pumps | efficiency_curve_start | efficiency_curve_count | efficiency_curve | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | Pump Station #1 | 0 | 5.0 | NaN | 5.0 | 1 | 0 | 6 | [[2.0, 70.0], [4.0, 60.0], [6.0, 55.0], [8.0, ... |
# Use HdfUtils for extracting projection
print("\nExtracting Projection from HDF")
projection = HdfBase.get_projection(hdf_path=geom_hdf_path)
print(f"Projection: {projection}")
Extracting Projection from HDF
Projection: EPSG:2871
# Set CRS for GeoDataFrames
if projection:
pipe_conduits_gdf.set_crs(projection, inplace=True, allow_override=True)
pipe_nodes_gdf.set_crs(projection, inplace=True, allow_override=True)
print("Pipe Conduits GeoDataFrame columns:")
print(pipe_conduits_gdf.columns)
print("\nPipe Nodes GeoDataFrame columns:")
print(pipe_nodes_gdf.columns)
perimeter_polygons = HdfMesh.get_mesh_areas(geom_hdf_path)
if projection:
perimeter_polygons.set_crs(projection, inplace=True, allow_override=True)
print("\nPerimeter Polygons GeoDataFrame columns:")
print(perimeter_polygons.columns)
Pipe Conduits GeoDataFrame columns:
Index(['Name', 'System Name', 'US Node', 'DS Node', 'Modeling Approach',
'Conduit Length', 'Max Cell Length', 'Shape', 'Rise', 'Span',
'Manning's n', 'US Offset', 'DS Offset', 'US Elevation', 'DS Elevation',
'Slope', 'US Entrance Loss Coefficient', 'DS Exit Loss Coefficient',
'US Backflow Loss Coefficient', 'DS Backflow Loss Coefficient',
'DS Gate Type', 'Major Group', 'Minor Group', 'DS Flap Gate',
'Polyline', 'Terrain_Profiles'],
dtype='str')
Pipe Nodes GeoDataFrame columns:
Index(['Name', 'System Name', 'Node Type', 'Node Status',
'Condtui Connections (US:DS)', 'Invert Elevation', 'Base Area',
'Terrain Elevation', 'Terrain Elevation Override', 'Depth',
'Top Inlet Type', 'Top Inlet Elevation', 'Side Inlet Type',
'Side Inlet Elevation', 'Total Connection Count', 'geometry'],
dtype='str')
Perimeter Polygons GeoDataFrame columns:
Index(['mesh_name', 'geometry'], dtype='str')
import matplotlib.pyplot as plt
from shapely import wkt
import matplotlib.patches as mpatches
import matplotlib.lines as mlines
import numpy as np
fig, ax = plt.subplots(figsize=(28, 20))
# Plot cell polygons with 50% transparency behind the pipe network
cell_polygons_df = HdfMesh.get_mesh_cell_polygons(geom_hdf_path)
if not cell_polygons_df.empty:
cell_polygons_df.plot(ax=ax, edgecolor='lightgray', facecolor='lightgray', alpha=0.5)
# Plot pipe conduits - the Polyline column already contains LineString geometries
pipe_conduits_gdf.set_geometry('Polyline', inplace=True)
# Plot each pipe conduit individually to ensure all are shown
for idx, row in pipe_conduits_gdf.iterrows():
ax.plot(*row.Polyline.xy, color='blue', linewidth=1)
# Create a colormap for node elevations
norm = plt.Normalize(pipe_nodes_gdf['Invert Elevation'].min(),
pipe_nodes_gdf['Invert Elevation'].max())
cmap = plt.cm.viridis
# Plot pipe nodes colored by invert elevation
scatter = ax.scatter(pipe_nodes_gdf.geometry.x, pipe_nodes_gdf.geometry.y,
c=pipe_nodes_gdf['Invert Elevation'],
cmap=cmap, norm=norm,
s=100)
# Add colorbar
cbar = plt.colorbar(scatter)
cbar.set_label('Invert Elevation (ft)', rotation=270, labelpad=15)
# Add combined labels for invert and drop inlet elevations
for idx, row in pipe_nodes_gdf.iterrows():
label_text = "" # Initialize label_text for each node
# Add drop inlet elevation label if it exists and is not NaN
if 'Drop Inlet Elevation' in row and not np.isnan(row['Drop Inlet Elevation']):
label_text += f"TOC: {row['Drop Inlet Elevation']:.2f}\n"
label_text += f"INV: {row['Invert Elevation']:.2f}"
ax.annotate(label_text,
xy=(row.geometry.x, row.geometry.y),
xytext=(-10, -10), textcoords='offset points',
fontsize=8,
bbox=dict(facecolor='white', edgecolor='black', boxstyle='round,pad=0.5'))
# Add perimeter polygons
if not perimeter_polygons.empty:
perimeter_polygons.plot(ax=ax, edgecolor='black', facecolor='none')
# Create proxy artists for legend
conduit_line = mlines.Line2D([], [], color='blue', label='Conduits')
node_point = mlines.Line2D([], [], color='blue', marker='o', linestyle='None',
markersize=10, label='Nodes')
perimeter = mpatches.Patch(facecolor='none', edgecolor='black',
label='Perimeter Polygons')
ax.set_title('Pipe Network with Node Elevations')
# Add legend with proxy artists
ax.legend(handles=[conduit_line, node_point, perimeter])
# Set aspect ratio to be equal and adjust limits
ax.set_aspect('equal', 'datalim')
ax.autoscale_view()
plt.show()

# Visualize pump stations on a map
fig, ax = plt.subplots(figsize=(12, 8))
pump_stations_gdf.plot(ax=ax, color='green', markersize=50, label='Pump Station')
# Add perimeter polygons
if not perimeter_polygons.empty:
perimeter_polygons.plot(ax=ax, edgecolor='black', facecolor='none', label='Perimeter Polygons')
ax.set_title('Pump Station Location')
ax.legend()
plt.show()
C:\Users\billk_clb\AppData\Local\Temp\ipykernel_24548\1821049155.py:10: UserWarning: Legend does not support handles for PatchCollection instances.
See: https://matplotlib.org/stable/tutorials/intermediate/legend_guide.html#implementing-a-custom-legend-handler
ax.legend()

# Example 3: Get pipe network timeseries
valid_variables = [
"Cell Courant", "Cell Water Surface", "Face Flow", "Face Velocity",
"Face Water Surface", "Pipes/Pipe Flow DS", "Pipes/Pipe Flow US",
"Pipes/Vel DS", "Pipes/Vel US", "Nodes/Depth", "Nodes/Water Surface"
]
print("Valid variables for pipe network timeseries:")
for var in valid_variables:
print(f"- {var}")
# Extract pipe network timeseries for each valid pipe-related variable
pipe_variables = [var for var in valid_variables if var.startswith("Pipes/") or var.startswith("Nodes/")]
for variable in pipe_variables:
try:
pipe_timeseries = HdfPipe.get_pipe_network_timeseries(plan_hdf_path, variable=variable)
print(f"\nPipe Network Timeseries ({variable}):")
print(pipe_timeseries.head()) # Print first few rows to avoid overwhelming output
except Exception as e:
print(f"Error extracting {variable}: {str(e)}")
2026-05-23 08:57:17 - ras_commander.hdf.HdfPipe - ERROR - Required dataset not found in HDF file: "Unable to synchronously open object (object 'Drop Inlet Flow' doesn't exist)"
Valid variables for pipe network timeseries:
- Cell Courant
- Cell Water Surface
- Face Flow
- Face Velocity
- Face Water Surface
- Pipes/Pipe Flow DS
- Pipes/Pipe Flow US
- Pipes/Vel DS
- Pipes/Vel US
- Nodes/Depth
- Nodes/Drop Inlet Flow
- Nodes/Water Surface
Pipe Network Timeseries (Pipes/Pipe Flow DS):
<xarray.DataArray 'Pipes/Pipe Flow DS' (time: 5, location: 5)> Size: 100B
array([[ 0. , 0. , 0. , 0. , 0. ],
[-0. , -0. , -0. , -0. , -0. ],
[-0. , -0. , -0. , -0. , -0. ],
[-0. , -0.00299399, -0. , -0. , -0. ],
[-0. , -0.01100602, -0. , -0. , -0. ]],
dtype=float32)
Coordinates:
* time (time) datetime64[us] 40B 2000-01-10T12:00:00 ... 2000-01-10T12...
* location (location) int64 40B 0 1 2 3 4
Attributes:
units: ft^3/s
variable: Pipes/Pipe Flow DS
Pipe Network Timeseries (Pipes/Pipe Flow US):
<xarray.DataArray 'Pipes/Pipe Flow US' (time: 5, location: 5)> Size: 100B
array([[ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
0.0000000e+00],
[-0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
-0.0000000e+00],
[-0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
-0.0000000e+00],
[-0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
3.9259396e-02],
[-0.0000000e+00, 1.0572882e-05, -0.0000000e+00, -0.0000000e+00,
8.2022630e-02]], dtype=float32)
Coordinates:
* time (time) datetime64[us] 40B 2000-01-10T12:00:00 ... 2000-01-10T12...
* location (location) int64 40B 0 1 2 3 4
Attributes:
units: ft^3/s
variable: Pipes/Pipe Flow US
Pipe Network Timeseries (Pipes/Vel DS):
<xarray.DataArray 'Pipes/Vel DS' (time: 5, location: 5)> Size: 100B
array([[ 0. , 0. , 0. , 0. , 0. ],
[-0. , -0. , -0. , -0. , -0. ],
[-0. , -0. , -0. , -0. , -0. ],
[-0. , -0.16168177, -0. , -0. , -0. ],
[-0. , -0.10933261, -0. , -0. , -0. ]],
dtype=float32)
Coordinates:
* time (time) datetime64[us] 40B 2000-01-10T12:00:00 ... 2000-01-10T12...
* location (location) int64 40B 0 1 2 3 4
Attributes:
units: ft/s
variable: Pipes/Vel DS
Pipe Network Timeseries (Pipes/Vel US):
<xarray.DataArray 'Pipes/Vel US' (time: 5, location: 5)> Size: 100B
array([[ 0. , 0. , 0. , 0. , 0. ],
[-0. , -0. , -0. , -0. , -0. ],
[-0. , -0. , -0. , -0. , -0. ],
[-0. , -0. , -0. , -0. , 0.45621765],
[-0. , 0.02145246, -0. , -0. , 0.47108054]],
dtype=float32)
Coordinates:
* time (time) datetime64[us] 40B 2000-01-10T12:00:00 ... 2000-01-10T12...
* location (location) int64 40B 0 1 2 3 4
Attributes:
units: ft/s
variable: Pipes/Vel US
Pipe Network Timeseries (Nodes/Depth):
<xarray.DataArray 'Nodes/Depth' (time: 5, location: 5)> Size: 100B
array([[ 0. , 0. , 0. , 0. , 0. ],
[-0.04570961, -0.04727364, -0.03162766, -0.01459312, 0. ],
[-0.04570961, -0.04727364, -0.03162766, -0.01459312, 0. ],
[-0.04570961, -0.04727364, -0.03162766, 0.06485876, 0. ],
[-0.04570961, -0.04727364, -0.03037816, 0.11818657, 0. ]],
dtype=float32)
Coordinates:
* time (time) datetime64[us] 40B 2000-01-10T12:00:00 ... 2000-01-10T12...
* location (location) int64 40B 0 1 2 3 4
Attributes:
units: ft
variable: Nodes/Depth
Error extracting Nodes/Drop Inlet Flow: "Unable to synchronously open object (object 'Drop Inlet Flow' doesn't exist)"
Pipe Network Timeseries (Nodes/Water Surface):
<xarray.DataArray 'Nodes/Water Surface' (time: 5, location: 5)> Size: 100B
array([[26.98 , 25.79 , 28.87 , 27.36 , 24.6 ],
[26.93429 , 25.742727, 28.838373, 27.345407, 24.6 ],
[26.93429 , 25.742727, 28.838373, 27.345407, 24.6 ],
[26.93429 , 25.742727, 28.838373, 27.42486 , 24.6 ],
[26.93429 , 25.742727, 28.839622, 27.478188, 24.6 ]],
dtype=float32)
Coordinates:
* time (time) datetime64[us] 40B 2000-01-10T12:00:00 ... 2000-01-10T12...
* location (location) int64 40B 0 1 2 3 4
Attributes:
units: ft
variable: Nodes/Water Surface
Pipe Network Timeseries Data Description¶
The get_pipe_network_timeseries function returns an xarray DataArray for each variable. Here's a general description of the data structure:
- Pipes/Pipe Flow DS and Pipes/Pipe Flow US:
- Dimensions: time, location (pipe IDs)
- Units: ft^3/s (cubic feet per second)
-
Description: Represents the flow rate at the downstream (DS) and upstream (US) ends of pipes over time.
-
Pipes/Vel DS and Pipes/Vel US:
- Dimensions: time, location (pipe IDs)
- Units: ft/s (feet per second)
-
Description: Shows the velocity at the downstream (DS) and upstream (US) ends of pipes over time.
-
Nodes/Depth:
- Dimensions: time, location (node IDs)
- Units: ft (feet)
-
Description: Indicates the depth of water at each node over time.
-
Nodes/Water Surface:
- Dimensions: time, location (node IDs)
- Units: ft (feet)
- Description: Shows the water surface elevation at each node over time.
General notes: - The 'time' dimension represents the simulation timesteps. - The 'location' dimension represents either pipe IDs or node IDs, depending on the variable. - The number of timesteps and locations may vary depending on the specific dataset and simulation setup. - Negative values in flow variables may indicate reverse flow direction.
import matplotlib.pyplot as plt
from matplotlib.dates import DateFormatter
import numpy as np
import random
# Define the variables we want to plot
variables = [
"Pipes/Pipe Flow DS", "Pipes/Pipe Flow US", "Pipes/Vel DS", "Pipes/Vel US",
"Nodes/Depth", "Nodes/Water Surface"
]
# Create a separate plot for each variable
for variable in variables:
try:
# Get the data for the current variable
data = HdfPipe.get_pipe_network_timeseries(plan_hdf_path, variable=variable)
# Create a new figure
fig, ax = plt.subplots(figsize=(12, 6))
# Pick one random location
random_location = random.choice(data.location.values)
# Determine if it's a pipe or node variable
if variable.startswith("Pipes/"):
location_type = "Conduit ID"
else:
location_type = "Node ID"
# Plot the data for the randomly selected location
ax.plot(data.time, data.sel(location=random_location), label=f'{location_type} {random_location}')
# Set the title and labels
ax.set_title(f'{variable} Over Time ({location_type} {random_location})')
ax.set_xlabel('Time') # Corrected from ax.xlabel to ax.set_xlabel
ax.set_ylabel(f'{variable} ({data.attrs["units"]})') # Corrected from ax.ylabel to ax.set_ylabel
# Format the x-axis to show dates nicely
ax.xaxis.set_major_formatter(DateFormatter('%Y-%m-%d %H:%M'))
plt.xticks(rotation=45)
# Add a legend
ax.legend(title=location_type, loc='upper left')
# Adjust the layout
plt.tight_layout()
# Show the plot
plt.show()
except Exception as e:
print(f"Error plotting {variable}: {str(e)}")





2026-05-23 08:57:18 - ras_commander.hdf.HdfPipe - ERROR - Required dataset not found in HDF file: "Unable to synchronously open object (object 'Drop Inlet Flow' doesn't exist)"
Error plotting Nodes/Drop Inlet Flow: "Unable to synchronously open object (object 'Drop Inlet Flow' doesn't exist)"

# Example 8: Get pump station timeseries
pump_station_name = pump_stations_gdf.iloc[0]['Name'] # Get the first pump station name
# Use the results_pump_station_timeseries method
pump_timeseries = HdfPump.get_pump_station_timeseries(plan_hdf_path, pump_station=pump_station_name)
print(f"\nPump Station Timeseries ({pump_station_name}):")
print(pump_timeseries)
Pump Station Timeseries (Pump Station #1):
<xarray.DataArray 'Pump Station #1' (time: 217, variable: 5)> Size: 4kB
array([[ 0. , 24.6 , 38.888123, 0. , 0. ],
[ 0. , 24.6 , 38.888123, 0. , 0. ],
[ 0. , 24.6 , 38.888123, 0. , 0. ],
...,
[ 0. , 25.579357, 40.7534 , 0. , 0. ],
[ 0. , 25.841583, 40.652042, 0. , 0. ],
[ 0. , 26.042273, 40.59146 , 0. , 0. ]],
shape=(217, 5), dtype=float32)
Coordinates:
* time (time) datetime64[us] 2kB 2000-01-10T12:00:00 ... 2000-01-12
* variable (variable) <U12 240B 'Flow' 'Stage HW' ... 'Pumps on'
Attributes:
units: [[b'Flow' b'cfs']\n [b'Stage HW' b'ft']\n [b'Stage TW'...
unit_by_variable: {'Flow': 'cfs', 'Stage HW': 'ft', 'Stage TW': 'ft', 'P...
pump_station: Pump Station #1
# Use get_hdf5_dataset_info function to get Pipe Conduits data:
HdfBase.get_dataset_info(plan_hdf_path, "/Geometry/Pump Stations/")
Exploring group: /Geometry/Pump Stations/
Dataset: /Geometry/Pump Stations//Attributes
Shape: (1,)
Dtype: [('Name', 'S16'), ('Inlet River', 'S16'), ('Inlet Reach', 'S16'), ('Inlet RS', 'S8'), ('Inlet RS Distance', '<f4'), ('Inlet SA/2D', 'S16'), ('Inlet Pipe Node', 'S32'), ('Outlet River', 'S16'), ('Outlet Reach', 'S16'), ('Outlet RS', 'S8'), ('Outlet RS Distance', '<f4'), ('Outlet SA/2D', 'S16'), ('Outlet Pipe Node', 'S32'), ('Reference River', 'S16'), ('Reference Reach', 'S16'), ('Reference RS', 'S8'), ('Reference RS Distance', '<f4'), ('Reference SA/2D', 'S16'), ('Reference Point', 'S32'), ('Reference Pipe Node', 'S32'), ('Highest Pump Line Elevation', '<f4'), ('Pump Groups', '<i4')]
Dataset: /Geometry/Pump Stations//Points
Shape: (1, 2)
Dtype: float64
Attributes for /Geometry/Pump Stations//Points:
Column: b'X,Y'
Row: b'Points'
Group: /Geometry/Pump Stations//Pump Groups
Dataset: /Geometry/Pump Stations//Pump Groups/Attributes
Shape: (1,)
Dtype: [('Pump Station ID', '<i4'), ('Name', 'S16'), ('Bias On', 'u1'), ('Start Up Time', '<f4'), ('Shut Down Time', '<f4'), ('Width', '<f4'), ('Pumps', '<i4')]
Dataset: /Geometry/Pump Stations//Pump Groups/Efficiency Curves Info
Shape: (1, 2)
Dtype: int32
Attributes for /Geometry/Pump Stations//Pump Groups/Efficiency Curves Info:
Column: [b'Starting Index' b'Count']
Row: b'Feature'
Dataset: /Geometry/Pump Stations//Pump Groups/Efficiency Curves Values
Shape: (6, 2)
Dtype: float32
Attributes for /Geometry/Pump Stations//Pump Groups/Efficiency Curves Values:
Column: [b'Head' b'Flow']
Row: b'Points'
Group: /Geometry/Pump Stations//Pump Groups/Pumps
Dataset: /Geometry/Pump Stations//Pump Groups/Pumps/Attributes
Shape: (1,)
Dtype: [('Pump Group ID', '<i4'), ('Name', 'S16'), ('WS On', '<f4'), ('WS Off', '<f4'), ('Default Centerline', 'u1')]
Dataset: /Geometry/Pump Stations//Pump Groups/Pumps/Centerline Info
Shape: (1, 4)
Dtype: int32
Attributes for /Geometry/Pump Stations//Pump Groups/Pumps/Centerline Info:
Column: [b'Point Starting Index' b'Point Count' b'Part Starting Index'
b'Part Count']
Feature Type: b'Polyline'
Row: b'Feature'
Dataset: /Geometry/Pump Stations//Pump Groups/Pumps/Centerline Parts
Shape: (1, 2)
Dtype: int32
Attributes for /Geometry/Pump Stations//Pump Groups/Pumps/Centerline Parts:
Column: [b'Point Starting Index' b'Point Count']
Row: b'Part'
Dataset: /Geometry/Pump Stations//Pump Groups/Pumps/Centerline Points
Shape: (2, 2)
Dtype: float64
Attributes for /Geometry/Pump Stations//Pump Groups/Pumps/Centerline Points:
Column: [b'X' b'Y']
Row: b'Points'
Dataset: /Geometry/Pump Stations//Pump Groups/Pumps/Outlet Cells
Shape: (1,)
Dtype: [('Pump Station ID', '<i4'), ('Pump Group ID', '<i4'), ('Pump ID', '<i4'), ('Cell Index', '<i4'), ('Station Start', '<f4'), ('Station End', '<f4')]
# Extract the pump station timeseries data
pump_station_name = pump_stations_gdf.iloc[0]['Name'] # Get the first pump station name
pump_timeseries = HdfPump.get_pump_station_timeseries(plan_hdf_path, pump_station=pump_station_name)
# Print the pump station timeseries
print(f"\nPump Station Timeseries ({pump_station_name}):")
print(pump_timeseries)
# Create a new figure for plotting
fig, ax = plt.subplots(figsize=(12, 12))
# Plot each variable in the timeseries
for variable in pump_timeseries.coords['variable'].values:
data = pump_timeseries.sel(variable=variable)
# Decode units to strings
unit = pump_timeseries.attrs["units"][list(pump_timeseries.coords["variable"].values).index(variable)][1].decode('utf-8')
# Check if the variable is 'Pumps on' to plot it differently
if variable == 'Pumps on':
# Plot with color based on the on/off status
colors = ['green' if val > 0 else 'red' for val in data.values.flatten()]
ax.scatter(pump_timeseries['time'], data, label=f'{variable} ({unit})', color=colors)
else:
ax.plot(pump_timeseries['time'], data, label=f'{variable} ({unit})')
# Label the peak values
peak_time = pump_timeseries['time'][data.argmax()]
peak_value = data.max()
ax.annotate(f'Peak: {peak_value:.2f}', xy=(peak_time, peak_value),
xytext=(peak_time, peak_value + 0.1 * peak_value),
arrowprops=dict(facecolor='black', arrowstyle='->'),
fontsize=10, color='black', ha='center')
# Set the title and labels
ax.set_title(f'Timeseries Data for Pump Station: {pump_station_name}')
ax.set_xlabel('Time')
ax.set_ylabel('Values')
# Format the x-axis to show dates nicely
ax.xaxis.set_major_formatter(DateFormatter('%Y-%m-%d %H:%M'))
plt.xticks(rotation=45)
# Add a legend
ax.legend(title='Variables', loc='upper left')
# Adjust the layout
plt.tight_layout()
# Show the plot
plt.show()
C:\Users\billk_clb\anaconda3\envs\symphony-dev\Lib\site-packages\xarray\core\dataarray.py:6439: FutureWarning: Behaviour of argmin/argmax with neither dim nor axis argument will change to return a dict of indices of each dimension. To get a single, flat index, please use np.argmin(da.data) or np.argmax(da.data) instead of da.argmin() or da.argmax().
result = self.variable.argmax(dim, axis, keep_attrs, skipna)
C:\Users\billk_clb\anaconda3\envs\symphony-dev\Lib\site-packages\xarray\core\dataarray.py:6439: FutureWarning: Behaviour of argmin/argmax with neither dim nor axis argument will change to return a dict of indices of each dimension. To get a single, flat index, please use np.argmin(da.data) or np.argmax(da.data) instead of da.argmin() or da.argmax().
result = self.variable.argmax(dim, axis, keep_attrs, skipna)
C:\Users\billk_clb\anaconda3\envs\symphony-dev\Lib\site-packages\xarray\core\dataarray.py:6439: FutureWarning: Behaviour of argmin/argmax with neither dim nor axis argument will change to return a dict of indices of each dimension. To get a single, flat index, please use np.argmin(da.data) or np.argmax(da.data) instead of da.argmin() or da.argmax().
result = self.variable.argmax(dim, axis, keep_attrs, skipna)
C:\Users\billk_clb\anaconda3\envs\symphony-dev\Lib\site-packages\xarray\core\dataarray.py:6439: FutureWarning: Behaviour of argmin/argmax with neither dim nor axis argument will change to return a dict of indices of each dimension. To get a single, flat index, please use np.argmin(da.data) or np.argmax(da.data) instead of da.argmin() or da.argmax().
result = self.variable.argmax(dim, axis, keep_attrs, skipna)
Pump Station Timeseries (Pump Station #1):
<xarray.DataArray 'Pump Station #1' (time: 217, variable: 5)> Size: 4kB
array([[ 0. , 24.6 , 38.888123, 0. , 0. ],
[ 0. , 24.6 , 38.888123, 0. , 0. ],
[ 0. , 24.6 , 38.888123, 0. , 0. ],
...,
[ 0. , 25.579357, 40.7534 , 0. , 0. ],
[ 0. , 25.841583, 40.652042, 0. , 0. ],
[ 0. , 26.042273, 40.59146 , 0. , 0. ]],
shape=(217, 5), dtype=float32)
Coordinates:
* time (time) datetime64[us] 2kB 2000-01-10T12:00:00 ... 2000-01-12
* variable (variable) <U12 240B 'Flow' 'Stage HW' ... 'Pumps on'
Attributes:
units: [[b'Flow' b'cfs']\n [b'Stage HW' b'ft']\n [b'Stage TW'...
unit_by_variable: {'Flow': 'cfs', 'Stage HW': 'ft', 'Stage TW': 'ft', 'P...
pump_station: Pump Station #1

Exploring HDF Datasets with HdfBase.get_dataset_info¶
This allows users to find HDF information that is not included in the ras-commander library. Find the path in HDFView and set the group_path below to explore the HDF datasets and attributes. Then, use the output to write your own function to extract the data.
Use get_hdf5_dataset_info function to get Pipe Conduits data:¶
HdfBase.get_dataset_info(plan_hdf_path, "/Geometry/Pipe Conduits/")
For HDF datasets that are not supported by the RAS-Commander library, provide the dataset path to HdfBase.get_dataset_info and provide the output to an LLM along with a relevent HDF* class(es) to generate new functions that extend the library's coverage.
RAS Mapper Pipe Profile-Line Renderers¶
The following cells sample a Davis pipe conduit with the pythonnet-backed RAS Mapper profile-line renderers exposed by HdfResultsQuery. The same polyline is used for pipe velocity, pipe flow, and the corresponding native pipe time-series renderers.
from ras_commander import HdfResultsQuery
with h5py.File(plan_hdf_path, "r") as hdf:
conduit_attrs = hdf["Geometry/Pipe Conduits/Attributes"][:]
conduit_points = hdf["Geometry/Pipe Conduits/Polyline Points"][:]
conduit_info = hdf["Geometry/Pipe Conduits/Polyline Info"][:]
conduit_index = 0
start_idx, point_count = conduit_info[conduit_index, 0], conduit_info[conduit_index, 1]
pipe_profile_line = LineString(conduit_points[start_idx:start_idx + point_count, :2])
pipe_name = conduit_attrs[conduit_index]["Name"].decode("utf-8", errors="ignore")
pipe_time_index = 7
pipe_velocity_profile = HdfResultsQuery.query_polyline_pipe_velocity_profile(
plan_hdf_path,
pipe_profile_line,
time_index=pipe_time_index,
sample_spacing=40.0,
terrain_raster=plan_hdf_path,
)
pipe_flow_profile = HdfResultsQuery.query_polyline_pipe_flow_profile(
plan_hdf_path,
pipe_profile_line,
time_index=pipe_time_index,
sample_spacing=40.0,
terrain_raster=plan_hdf_path,
)
print(f"Pipe conduit {pipe_name}: {len(pipe_velocity_profile)} profile samples")
display.display(pipe_velocity_profile.head())
Pipe conduit 134: 29 profile samples
| station | x | y | mesh_name | face_id | velocity_mag | depth | terrain_elev | |
|---|---|---|---|---|---|---|---|---|
| 0 | 0.000000 | 6.635295e+06 | 1.965214e+06 | area2 | 1763 | NaN | NaN | NaN |
| 1 | 20.170002 | 6.635291e+06 | 1.965234e+06 | area2 | 1624 | 1.729614 | NaN | NaN |
| 2 | 40.340004 | 6.635286e+06 | 1.965254e+06 | area2 | 1624 | 1.748997 | NaN | NaN |
| 3 | 60.510006 | 6.635282e+06 | 1.965273e+06 | area2 | 1624 | 1.768380 | NaN | NaN |
| 4 | 60.510006 | 6.635282e+06 | 1.965273e+06 | area2 | 1624 | 1.768380 | NaN | NaN |
fig, axes = plt.subplots(1, 2, figsize=(12, 4), constrained_layout=True)
axes[0].plot(
pipe_velocity_profile["station"],
pipe_velocity_profile["velocity_mag"],
color="#1f77b4",
linewidth=2,
label="Velocity",
)
axes[0].set_title(f"Davis Pipe {pipe_name} Velocity Profile")
axes[0].set_xlabel("Station along conduit (ft)")
axes[0].set_ylabel("Velocity (ft/s)")
axes[0].grid(True, alpha=0.3)
axes[0].legend()
axes[1].plot(
pipe_flow_profile["station"],
pipe_flow_profile["flow"],
color="#2ca02c",
linewidth=2,
label="Flow",
)
axes[1].set_title(f"Davis Pipe {pipe_name} Flow Profile")
axes[1].set_xlabel("Station along conduit (ft)")
axes[1].set_ylabel("Flow (cfs)")
axes[1].grid(True, alpha=0.3)
axes[1].legend()
plt.show()

pipe_velocity_timeseries = HdfResultsQuery.query_polyline_pipe_velocity_timeseries(
plan_hdf_path,
pipe_profile_line,
time_range=(pipe_time_index, pipe_time_index + 2),
sample_spacing=40.0,
terrain_raster=plan_hdf_path,
)
pipe_flow_timeseries = HdfResultsQuery.query_polyline_pipe_flow_timeseries(
plan_hdf_path,
pipe_profile_line,
time_range=(pipe_time_index, pipe_time_index + 2),
sample_spacing=40.0,
terrain_raster=plan_hdf_path,
)
summary = pd.DataFrame({
"quantity": ["pipe velocity", "pipe flow"],
"rows": [len(pipe_velocity_timeseries), len(pipe_flow_timeseries)],
"finite_samples": [
pipe_velocity_timeseries["velocity_mag"].notna().sum(),
pipe_flow_timeseries["flow"].notna().sum(),
],
"source": [
pipe_velocity_timeseries.attrs.get("velocity_source"),
pipe_flow_timeseries.attrs.get("flow_source"),
],
})
display.display(summary)
| quantity | rows | finite_samples | source | |
|---|---|---|---|---|
| 0 | pipe velocity | 58 | 54 | [RasMapperLib.Render.VelocityPipeTimeSeries] |
| 1 | pipe flow | 58 | 54 | [RasMapperLib.Render.FlowPipeTimeSeries] |