Skip to content

1D Boundary Condition Visualization

This notebook demonstrates how to extract and visualize 1D boundary conditions from a HEC-RAS project. The workflow:

  1. Extract cross-sections from the geometry HDF file
  2. Parse boundary conditions from the unsteady flow file
  3. Match boundaries to cross-sections and extract DSS path information
  4. Create GeoJSON with boundary condition attributes
  5. Add to RASMapper as a map layer
  6. Open RASMapper to visualize the boundary conditions

The output includes DSS path information which helps identify HMS basin connections and boundary condition types.

Setup and Imports

Python
# =============================================================================
# DEVELOPMENT MODE TOGGLE
# =============================================================================
# Set USE_LOCAL_SOURCE based on your setup:
#   True  = Use local source code (for developers editing ras-commander)
#   False = Use pip-installed package (for users)
# =============================================================================

USE_LOCAL_SOURCE = False  # <-- TOGGLE THIS

# -----------------------------------------------------------------------------
if USE_LOCAL_SOURCE:
    import sys
    from pathlib import Path
    local_path = str(Path.cwd().parent)  # Parent of examples/ = repo root
    if local_path not in sys.path:
        sys.path.insert(0, local_path)  # Insert at position 0 = highest priority
    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 (
    RasExamples, 
    init_ras_project, 
    ras,
    RasUnsteady,
    RasMap,
    RasGuiAutomation
)
from ras_commander.hdf import HdfXsec, HdfBase

# Additional imports
import pandas as pd
import geopandas as gpd
import json

# Verify which version loaded
import ras_commander
print(f"✓ Loaded: {ras_commander.__file__}")
Text Only
📦 PIP PACKAGE MODE: Loading installed ras-commander
✓ Loaded: c:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\ras_commander\__init__.py

Parameters

Configure these values to customize the notebook for your project.

Python
# =============================================================================
# PARAMETERS - Edit these to customize the notebook
# =============================================================================
from pathlib import Path

# Project Configuration
PROJECT_NAME = "BaldEagleCrkMulti2D"  # Example project with multiple 1D boundary conditions
RAS_VERSION = "7.0"                    # HEC-RAS version (6.3, 6.5, 6.6, etc.)

# Geometry Selection
TARGET_GEOM = "08"                     # G08 = "1D-2D Dam Break Model Refined Grid"

# Execution Settings (optional - not used in this notebook)
PLAN = "01"                            # Plan number to execute
NUM_CORES = 4                          # CPU cores for 2D computation
RUN_SUFFIX = "run"                     # Suffix for run folder
# GUI Visualization
RUN_GUI_VISUALIZATION = False  # Set to True for interactive RASMapper visualization

1. Extract Example Project and Initialize

We'll use the BaldEagleCrkMulti2D example project which has multiple 1D boundary conditions with DSS-linked HMS basin connections.

Important: This project has 10 different geometries. We'll use G08 ("1D-2D Dam Break Model Refined Grid") which has the 1D cross-sections that correspond to the boundary conditions.

Python
# Extract example project - BaldEagleCrkMulti2D has DSS-linked boundaries
# that show HMS basin connections
project_path = RasExamples.extract_project(PROJECT_NAME)
print(f"Project extracted to: {project_path}")

# Initialize the project
init_ras_project(project_path, RAS_VERSION)

print(f"\nProject Name: {ras.project_name}")
print(f"Project Folder: {ras.project_folder}")
print(f"\nGeometry Files: {len(ras.geom_df)}")
print(f"Plan Files: {len(ras.plan_df)}")
print(f"Unsteady Flow Files: {len(ras.unsteady_df)}")
print(f"Boundary Conditions: {len(ras.boundaries_df)}")
Text Only
2026-01-12 00:22:59 - ras_commander.RasExamples - INFO - Found zip file: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\Example_Projects_6_6.zip
2026-01-12 00:22:59 - ras_commander.RasExamples - INFO - Loading project data from CSV...
2026-01-12 00:22:59 - ras_commander.RasExamples - INFO - Loaded 68 projects from CSV.
2026-01-12 00:22:59 - ras_commander.RasExamples - INFO - ----- RasExamples Extracting Project -----
2026-01-12 00:22:59 - ras_commander.RasExamples - INFO - Extracting project 'BaldEagleCrkMulti2D'
2026-01-12 00:22:59 - ras_commander.RasExamples - INFO - Folder 'BaldEagleCrkMulti2D' already exists. Deleting existing folder...
2026-01-12 00:23:00 - ras_commander.RasExamples - INFO - Existing folder 'BaldEagleCrkMulti2D' has been deleted.
2026-01-12 00:23:01 - ras_commander.RasExamples - INFO - Successfully extracted project 'BaldEagleCrkMulti2D' to C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\BaldEagleCrkMulti2D
2026-01-12 00:23:01 - ras_commander.RasMap - INFO - Successfully parsed RASMapper file: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\BaldEagleCrkMulti2D\BaldEagleDamBrk.rasmap
2026-01-12 00:23:01 - ras_commander.RasPrj - INFO - Updated results_df with 11 plan(s)


Project extracted to: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\BaldEagleCrkMulti2D

Project Name: BaldEagleDamBrk
Project Folder: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\BaldEagleCrkMulti2D

Geometry Files: 10
Plan Files: 11
Unsteady Flow Files: 10
Boundary Conditions: 51

2. Select and Extract Cross-Sections from G08 Geometry

This project has multiple geometries. We'll use G08 specifically because it contains the 1D cross-sections that correspond to the boundary conditions. First, let's list all available geometries.

Python
# List all available geometries
print("Available Geometries:")
print("=" * 60)
geometries = RasMap.list_geometries()
for g in geometries:
    checked = "[x]" if g['checked'] else "[ ]"
    print(f"  {checked} g{g['geom_number']}: {g['name']}")

# Select target geometry from parameters (G08 = "1D-2D Dam Break Model Refined Grid")
target_geom = TARGET_GEOM
geom_row = ras.geom_df[ras.geom_df['geom_number'] == target_geom]

if geom_row.empty:
    raise ValueError(f"Geometry g{target_geom} not found in project!")

geom_hdf_path = geom_row.iloc[0]['hdf_path']
print(f"\nSelected Geometry HDF: {geom_hdf_path}")

# Extract cross-sections from the selected geometry
cross_sections_gdf = HdfXsec.get_cross_sections(geom_hdf_path)
print(f"\nExtracted {len(cross_sections_gdf)} cross-sections from g{target_geom}")

# Get projection information
projection = HdfBase.get_projection(hdf_path=geom_hdf_path)
print(f"Projection: {projection[:100]}..." if len(projection) > 100 else f"Projection: {projection}")

# Show sample cross-sections
print("\nSample cross-sections:")
cross_sections_gdf[['River', 'Reach', 'RS']].head(10)
Text Only
2026-01-12 00:23:01 - ras_commander.RasMap - INFO - Found 10 geometries in .rasmap
2026-01-12 00:23:01 - ras_commander.hdf.HdfBase - INFO - Using HDF file from direct string path: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\BaldEagleCrkMulti2D\BaldEagleDamBrk.g08.hdf
2026-01-12 00:23:01 - ras_commander.hdf.HdfBase - INFO - Final validated file path: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\BaldEagleCrkMulti2D\BaldEagleDamBrk.g08.hdf
2026-01-12 00:23:01 - ras_commander.hdf.HdfBase - INFO - Found projection in RASMapper file: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\BaldEagleCrkMulti2D\Terrain\Projection.prj
2026-01-12 00:23:01 - ras_commander.hdf.HdfBase - INFO - Converted WKT to EPSG:2271 from RASMapper file Projection.prj


Available Geometries:
============================================================
  [ ] g06: Bald Eagle Multi 2D Areas
  [ ] g08: 1D-2D Dam Break Model Refined Grid
  [ ] g10: U.S 2D - D.S 1D No Dam
  [ ] g11: 2D to 2D Connection
  [ ] g12: SA to 2D Connection
  [x] g09: Single 2D Area - Internal Dam Structure
  [ ] g13: SA to 2D Flow Area
  [ ] g01: SA to 2D Flow Area - Detailed
  [ ] g03: Single 2D Area with Bridges and Breaklin
  [ ] g02: Single 2D Area -With Infiltration

Selected Geometry HDF: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\BaldEagleCrkMulti2D\BaldEagleDamBrk.g08.hdf

Extracted 89 cross-sections from g08
Projection: EPSG:2271

Sample cross-sections:
River Reach RS
0 Bald Eagle Cr. Lock Haven 137520
1 Bald Eagle Cr. Lock Haven 136948
2 Bald Eagle Cr. Lock Haven 136076
3 Bald Eagle Cr. Lock Haven 135341
4 Bald Eagle Cr. Lock Haven 134762
5 Bald Eagle Cr. Lock Haven 134327
6 Bald Eagle Cr. Lock Haven 133663
7 Bald Eagle Cr. Lock Haven 132907
8 Bald Eagle Cr. Lock Haven 132526
9 Bald Eagle Cr. Lock Haven 132172

3. View Boundary Conditions from Project

Boundary conditions are automatically parsed during init_ras_project() and stored in ras.boundaries_df. This includes DSS path information for HMS-linked boundaries.

Python
# Boundary conditions are automatically parsed during project initialization
# and stored in ras.boundaries_df - no need to call extract_boundary_and_tables()

print(f"Boundary conditions available in ras.boundaries_df: {len(ras.boundaries_df)}")
print(f"\nColumns available:")
print(ras.boundaries_df.columns.tolist())

print("\nBoundary Conditions Summary:")
display(ras.boundaries_df)

# Note: RasUnsteady.extract_boundary_and_tables() can also be used for more detailed parsing
# but ras.boundaries_df already has the key information including DSS Path
Text Only
Boundary conditions available in ras.boundaries_df: 51

Columns available:
['unsteady_number', 'boundary_condition_number', 'river_reach_name', 'river_station', 'storage_area_name', 'pump_station_name', 'bc_type', 'hydrograph_type', 'Interval', 'DSS File', 'DSS Path', 'Use DSS', 'Use Fixed Start Time', 'Fixed Start Date/Time', 'Is Critical Boundary', 'Critical Boundary Flow', 'hydrograph_num_values', 'hydrograph_values', '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']

Boundary Conditions Summary:
unsteady_number boundary_condition_number river_reach_name river_station storage_area_name pump_station_name bc_type hydrograph_type Interval DSS File ... 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
0 07 1 Bald Eagle Cr. Lock Haven 137520 Flow Hydrograph Flow Hydrograph 1HOUR Bald_Eagle_Creek.dss ... PMF with Multi 2D Areas 5.00 0 NaN NaN NaN NaN NaN NaN NaN
1 07 2 Bald Eagle Cr. Lock Haven 81454 Gate Opening None NaN NaN ... PMF with Multi 2D Areas 5.00 0 NaN NaN NaN NaN NaN NaN NaN
2 07 3 Bald Eagle Cr. Lock Haven 28519 Lateral Inflow Hydrograph Lateral Inflow Hydrograph 1HOUR Bald_Eagle_Creek.dss ... PMF with Multi 2D Areas 5.00 0 NaN NaN NaN NaN NaN NaN NaN
3 07 4 Bald Eagle Cr. Lock Haven 1 Lateral Inflow Hydrograph Lateral Inflow Hydrograph 1HOUR NaN ... PMF with Multi 2D Areas 5.00 0 NaN NaN NaN NaN NaN NaN NaN
4 07 5 Bald Eagle Cr. Lock Haven 136948 82303 Uniform Lateral Inflow Hydrograph Uniform Lateral Inflow Hydrograph 1HOUR Bald_Eagle_Creek.dss ... PMF with Multi 2D Areas 5.00 0 NaN NaN NaN NaN NaN NaN NaN
5 07 6 Bald Eagle Cr. Lock Haven 80720 67130 Uniform Lateral Inflow Hydrograph Uniform Lateral Inflow Hydrograph 1HOUR Bald_Eagle_Creek.dss ... PMF with Multi 2D Areas 5.00 0 NaN NaN NaN NaN NaN NaN NaN
6 07 7 Bald Eagle Cr. Lock Haven 76865 Lateral Inflow Hydrograph Lateral Inflow Hydrograph 1HOUR Bald_Eagle_Creek.dss ... PMF with Multi 2D Areas 5.00 0 NaN NaN NaN NaN NaN NaN NaN
7 07 8 Bald Eagle Cr. Lock Haven 67130 Lateral Inflow Hydrograph Lateral Inflow Hydrograph 1HOUR Bald_Eagle_Creek.dss ... PMF with Multi 2D Areas 5.00 0 NaN NaN NaN NaN NaN NaN NaN
8 07 9 Bald Eagle Cr. Lock Haven 66041 1 Uniform Lateral Inflow Hydrograph Uniform Lateral Inflow Hydrograph 1HOUR Bald_Eagle_Creek.dss ... PMF with Multi 2D Areas 5.00 0 NaN NaN NaN NaN NaN NaN NaN
9 07 10 Bald Eagle Cr. Lock Haven -1867 Normal Depth None NaN NaN ... PMF with Multi 2D Areas 5.00 0 NaN NaN NaN NaN NaN NaN NaN
10 08 1 Bald Eagle Cr. Lock Haven 28519 Lateral Inflow Hydrograph Lateral Inflow Hydrograph 1HOUR Bald_Eagle_Creek.dss ... PMF for Upstream 2D 4.20 0 NaN NaN NaN NaN NaN NaN NaN
11 08 2 Bald Eagle Cr. Lock Haven 1 Lateral Inflow Hydrograph Lateral Inflow Hydrograph 1HOUR NaN ... PMF for Upstream 2D 4.20 0 NaN NaN NaN NaN NaN NaN NaN
12 08 3 Bald Eagle Cr. Lock Haven 80720 67130 Uniform Lateral Inflow Hydrograph Uniform Lateral Inflow Hydrograph 1HOUR Bald_Eagle_Creek.dss ... PMF for Upstream 2D 4.20 0 NaN NaN NaN NaN NaN NaN NaN
13 08 4 Bald Eagle Cr. Lock Haven 76865 Lateral Inflow Hydrograph Lateral Inflow Hydrograph 1HOUR Bald_Eagle_Creek.dss ... PMF for Upstream 2D 4.20 0 NaN NaN NaN NaN NaN NaN NaN
14 08 5 Bald Eagle Cr. Lock Haven 67130 Lateral Inflow Hydrograph Lateral Inflow Hydrograph 1HOUR Bald_Eagle_Creek.dss ... PMF for Upstream 2D 4.20 0 NaN NaN NaN NaN NaN NaN NaN
15 08 6 Bald Eagle Cr. Lock Haven 66041 1 Uniform Lateral Inflow Hydrograph Uniform Lateral Inflow Hydrograph 1HOUR Bald_Eagle_Creek.dss ... PMF for Upstream 2D 4.20 0 NaN NaN NaN NaN NaN NaN NaN
16 08 7 Bald Eagle Cr. Lock Haven -1867 Normal Depth None NaN NaN ... PMF for Upstream 2D 4.20 0 NaN NaN NaN NaN NaN NaN NaN
17 08 8 Flow Hydrograph Flow Hydrograph 1HOUR NaN ... PMF for Upstream 2D 4.20 0 NaN NaN NaN NaN NaN NaN NaN
18 08 9 Bald Eagle Cr. Lock Haven 81454 Gate Opening None NaN NaN ... PMF for Upstream 2D 4.20 0 NaN NaN NaN NaN NaN NaN NaN
19 09 1 Bald Eagle Cr. Lock Haven 28519 Lateral Inflow Hydrograph Lateral Inflow Hydrograph 1HOUR Bald_Eagle_Creek.dss ... Upstream 2D 5.00 0 NaN NaN NaN NaN NaN NaN NaN
20 09 2 Bald Eagle Cr. Lock Haven -1867 Normal Depth None NaN NaN ... Upstream 2D 5.00 0 NaN NaN NaN NaN NaN NaN NaN
21 09 3 Flow Hydrograph Flow Hydrograph 1HOUR NaN ... Upstream 2D 5.00 0 NaN NaN NaN NaN NaN NaN NaN
22 10 1 Normal Depth None NaN NaN ... 1972 Flood Event - 2D to 2D Run 5.00 0 NaN NaN NaN NaN NaN NaN NaN
23 10 2 Normal Depth None NaN NaN ... 1972 Flood Event - 2D to 2D Run 5.00 0 NaN NaN NaN NaN NaN NaN NaN
24 10 3 Gate Opening None NaN NaN ... 1972 Flood Event - 2D to 2D Run 5.00 0 NaN NaN NaN NaN NaN NaN NaN
25 10 4 Flow Hydrograph Flow Hydrograph 1HOUR NaN ... 1972 Flood Event - 2D to 2D Run 5.00 0 NaN NaN NaN NaN NaN NaN NaN
26 11 1 Gate Opening None NaN NaN ... 1972 Flood Event - SA to 2D Run 5.00 0 NaN NaN NaN NaN NaN NaN NaN
27 11 2 Lateral Inflow Hydrograph Lateral Inflow Hydrograph 1HOUR NaN ... 1972 Flood Event - SA to 2D Run 5.00 0 NaN NaN NaN NaN NaN NaN NaN
28 11 3 Normal Depth None NaN NaN ... 1972 Flood Event - SA to 2D Run 5.00 0 NaN NaN NaN NaN NaN NaN NaN
29 11 4 Normal Depth None NaN NaN ... 1972 Flood Event - SA to 2D Run 5.00 0 NaN NaN NaN NaN NaN NaN NaN
30 12 1 Bald Eagle Cr. Lock Haven 137520 Flow Hydrograph Flow Hydrograph 15MIN Bald_Eagle_Creek.dss ... PMF for 1D - 2D 5.00 0 NaN NaN NaN NaN NaN NaN NaN
31 12 2 Bald Eagle Cr. Lock Haven 81454 Gate Opening None NaN NaN ... PMF for 1D - 2D 5.00 0 NaN NaN NaN NaN NaN NaN NaN
32 12 3 Normal Depth None NaN NaN ... PMF for 1D - 2D 5.00 0 NaN NaN NaN NaN NaN NaN NaN
33 12 4 Normal Depth None NaN NaN ... PMF for 1D - 2D 5.00 0 NaN NaN NaN NaN NaN NaN NaN
34 13 1 Normal Depth None NaN NaN ... Single 2D Area 5.00 0 NaN NaN NaN NaN NaN NaN NaN
35 13 2 Normal Depth None NaN NaN ... Single 2D Area 5.00 0 NaN NaN NaN NaN NaN NaN NaN
36 13 3 Flow Hydrograph Flow Hydrograph 1HOUR NaN ... Single 2D Area 5.00 0 NaN NaN NaN NaN NaN NaN NaN
37 13 4 Gate Opening None NaN NaN ... Single 2D Area 5.00 0 NaN NaN NaN NaN NaN NaN NaN
38 01 1 Gate Opening None NaN NaN ... 1972 Flood Event - 2D Leve Structure 5.10 0 NaN NaN NaN NaN NaN NaN NaN
39 01 2 Lateral Inflow Hydrograph Lateral Inflow Hydrograph 1HOUR NaN ... 1972 Flood Event - 2D Leve Structure 5.10 0 NaN NaN NaN NaN NaN NaN NaN
40 01 3 Normal Depth None NaN NaN ... 1972 Flood Event - 2D Leve Structure 5.10 0 NaN NaN NaN NaN NaN NaN NaN
41 01 4 Normal Depth None NaN NaN ... 1972 Flood Event - 2D Leve Structure 5.10 0 NaN NaN NaN NaN NaN NaN NaN
42 02 1 Normal Depth None NaN NaN ... Single 2D Area with Bridges 5.10 0 NaN NaN NaN NaN NaN NaN NaN
43 02 2 Normal Depth None NaN NaN ... Single 2D Area with Bridges 5.10 0 NaN NaN NaN NaN NaN NaN NaN
44 02 3 Flow Hydrograph Flow Hydrograph 1HOUR NaN ... Single 2D Area with Bridges 5.10 0 NaN NaN NaN NaN NaN NaN NaN
45 02 4 Gate Opening None NaN NaN ... Single 2D Area with Bridges 5.10 0 NaN NaN NaN NaN NaN NaN NaN
46 02 5 Normal Depth None NaN NaN ... Single 2D Area with Bridges 5.10 0 NaN NaN NaN NaN NaN NaN NaN
47 03 1 Normal Depth None NaN NaN ... Gridded Precipitation 6.00 0 Enable No Wind Forces Gridded None -1 mm/hr DSS
48 03 2 Flow Hydrograph Flow Hydrograph 1HOUR NaN ... Gridded Precipitation 6.00 0 Enable No Wind Forces Gridded None -1 mm/hr DSS
49 03 3 Normal Depth None NaN NaN ... Gridded Precipitation 6.00 0 Enable No Wind Forces Gridded None -1 mm/hr DSS
50 03 4 Gate Opening None NaN NaN ... Gridded Precipitation 6.00 0 Enable No Wind Forces Gridded None -1 mm/hr DSS

51 rows × 29 columns

4. View DSS Information from Boundary Conditions

The ras.boundaries_df DataFrame already contains DSS path information parsed during project initialization.

New in v0.88+: DSS path components are pre-parsed into individual columns: - dss_part_a: Basin/Project name (e.g., "BALD EAGLE 40") - key for HMS matching - dss_part_b: Location identifier - dss_part_c: Parameter (FLOW, STAGE, etc.) - dss_part_d: Start date - dss_part_e: Time interval (5MIN, 1HOUR, etc.) - dss_part_f: Run identifier

DSS Path Format: //PART_A/PART_B/PART_C/PART_D/PART_E/PART_F/

Python
# DSS information is already available in ras.boundaries_df
# No custom parsing needed - the API handles this during project initialization

print("DSS Information from ras.boundaries_df:")
print("=" * 80)

# Show relevant columns including DSS Path, DSS File, and parsed DSS parts (v0.88+ feature)
dss_columns = ['river_reach_name', 'river_station', 'bc_type', 'DSS Path', 'DSS File', 'Interval', 'dss_part_a']
available_cols = [c for c in dss_columns if c in ras.boundaries_df.columns]

if available_cols:
    display(ras.boundaries_df[available_cols])
else:
    # Try alternative column names
    print("Available columns:", ras.boundaries_df.columns.tolist())
    display(ras.boundaries_df)

# Show HMS basin names using the new dss_part_a column (v0.88+ feature)
if 'dss_part_a' in ras.boundaries_df.columns:
    print("\nHMS Basin Names (from dss_part_a column - v0.88+ feature):")
    for idx, row in ras.boundaries_df.iterrows():
        dss_part_a = row.get('dss_part_a', '')
        if pd.notna(dss_part_a) and str(dss_part_a).strip():
            print(f"  {row.get('river_reach_name', 'Unknown')}: {dss_part_a}")
else:
    # Fallback: Show DSS paths for manual identification
    print("\nDSS Paths (for HMS basin identification):")
    for idx, row in ras.boundaries_df.iterrows():
        dss_path = row.get('DSS Path', '')
        if dss_path:
            print(f"  {row.get('river_reach_name', 'Unknown')}: {dss_path}")

5. Match Boundaries to Cross-Sections and Create GeoJSON

Now we'll match each boundary condition from ras.boundaries_df to its corresponding cross-section geometry. The DSS path information is already available in the DataFrame - no custom parsing needed!

Python
# Use built-in dss_part_a column from boundaries_df for HMS basin names
# Note: As of ras-commander v0.88+, DSS path components are pre-parsed into columns:
#   - dss_part_a: Basin/Project name (e.g., "BALD EAGLE 40", "FISHING CREEK")
#   - dss_part_b: Location/Parameter (e.g., "FLOW")
#   - dss_part_c: Parameter type
#   - dss_part_d: Start date
#   - dss_part_e: Time interval
#   - dss_part_f: Run identifier

# Check if dss_part_a column is available (v0.88+ feature)
if 'dss_part_a' in ras.boundaries_df.columns:
    print("Using built-in dss_part_a column for HMS basin names (v0.88+ feature)")
    get_hms_basin = lambda idx: str(ras.boundaries_df.loc[idx, 'dss_part_a']) if pd.notna(ras.boundaries_df.loc[idx, 'dss_part_a']) else ""
else:
    # Fallback for older ras-commander versions - parse DSS path manually
    print("Using fallback DSS path parsing (dss_part_a column not available)")
    def extract_hms_basin_fallback(dss_path):
        """
        Extract HMS basin name from DSS path Part A.
        DSS Path format: //A/B/C/D/E/F/
        - Part A (index 2): Basin/Location name (e.g., "BALD EAGLE 40", "FISHING CREEK")
        """
        if not dss_path or pd.isna(dss_path) or str(dss_path).strip() == '':
            return ""
        parts = str(dss_path).split('/')
        if len(parts) > 2:
            return parts[2] if parts[2] else ""
        return ""
    get_hms_basin = lambda idx: extract_hms_basin_fallback(ras.boundaries_df.loc[idx, 'DSS Path'])

# Use ras.boundaries_df which already has boundary condition data
print(f"Processing {len(ras.boundaries_df)} boundary conditions from ras.boundaries_df")

# Map boundaries to cross-sections
boundary_xs_data = []

for idx, boundary in ras.boundaries_df.iterrows():
    # Get location info from boundaries_df
    # Note: Boundary Location format is River,Reach,Station,...
    # Current parsing puts: River->river_reach_name, Reach->river_station, Station->storage_area_name
    river_name = str(boundary.get('river_reach_name', '')).strip()
    reach_name = str(boundary.get('river_station', '')).strip()  # Actually contains Reach!

    # The actual station is in storage_area_name due to field offset
    actual_station = str(boundary.get('storage_area_name', '')).strip()

    bc_type = str(boundary.get('bc_type', 'Unknown'))

    # Skip if missing location info
    if not river_name or not actual_station or actual_station == 'nan' or actual_station == '':
        continue

    # Get DSS information directly from boundaries_df
    dss_path = str(boundary.get('DSS Path', '')) if pd.notna(boundary.get('DSS Path')) else ''
    dss_file = str(boundary.get('DSS File', '')) if pd.notna(boundary.get('DSS File')) else ''

    # Clean up DSS path (remove 'nan' strings)
    if dss_path.lower() == 'nan':
        dss_path = ''

    # Get HMS basin name using the built-in column or fallback
    hms_basin = get_hms_basin(idx)

    # Find matching cross-section by River and Station
    exact_matches = cross_sections_gdf[
        (cross_sections_gdf['River'].str.contains(river_name, case=False, na=False)) &
        (cross_sections_gdf['RS'].astype(str) == actual_station)
    ]

    # If no match, try matching by Reach and Station
    if exact_matches.empty and reach_name:
        exact_matches = cross_sections_gdf[
            (cross_sections_gdf['Reach'].str.contains(reach_name, case=False, na=False)) &
            (cross_sections_gdf['RS'].astype(str) == actual_station)
        ]

    if not exact_matches.empty:
        matched_xs = exact_matches.iloc[0]

        boundary_xs_data.append({
            'river': matched_xs['River'],
            'reach': matched_xs['Reach'],
            'station': matched_xs['RS'],
            'boundary_type': bc_type,
            'dss_file': dss_file,
            'dss_path': dss_path,
            'hms_basin': hms_basin,
            'geometry': matched_xs['geometry']
        })
        print(f"  Matched: {river_name}/{reach_name} @ RS {actual_station} -> HMS: {hms_basin if hms_basin else '(no DSS)'}")
    else:
        print(f"  No XS match: {river_name}/{reach_name} @ RS {actual_station}")

print(f"\nSuccessfully matched {len(boundary_xs_data)} boundary conditions to cross-sections")
print(f"Boundaries with DSS links: {sum(1 for b in boundary_xs_data if b['dss_path'])}")

6. Create Output Folder and Save GeoJSON

Save the boundary condition GeoJSON to a dedicated subfolder within the project.

Important: GeoJSON files for RASMapper must be in WGS84 (EPSG:4326) coordinate system. The code below reprojects from the project CRS to WGS84 before saving.

Python
# Create output folder
output_folder = ras.project_folder / "1D_Boundary_Conditions"
output_folder.mkdir(exist_ok=True)
print(f"Output folder: {output_folder}")

# Create GeoDataFrame
if boundary_xs_data:
    boundary_gdf = gpd.GeoDataFrame(boundary_xs_data)

    # Get CRS from project (use the projection from geometry HDF)
    project_crs = HdfBase.get_projection(hdf_path=geom_hdf_path)
    boundary_gdf.crs = project_crs
    print(f"Project CRS: {project_crs}")

    # IMPORTANT: Reproject to WGS84 (EPSG:4326) for RASMapper compatibility
    # RASMapper requires GeoJSON layers to be in WGS84 coordinate system
    boundary_gdf_wgs84 = boundary_gdf.to_crs("EPSG:4326")
    print(f"Reprojected to: EPSG:4326 (WGS84) for RASMapper")

    # Save GeoJSON in WGS84
    output_geojson = output_folder / "boundary_cross_sections.geojson"
    boundary_gdf_wgs84.to_file(output_geojson, driver='GeoJSON')
    print(f"Saved GeoJSON: {output_geojson}")

    # Display the data
    print("Boundary Condition Data:")
    display(boundary_gdf.drop(columns=['geometry']))
else:
    print("No boundary conditions matched to cross-sections.")
    output_geojson = None
Text Only
2026-01-12 00:23:01 - ras_commander.hdf.HdfBase - INFO - Using HDF file from direct string path: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\BaldEagleCrkMulti2D\BaldEagleDamBrk.g08.hdf
2026-01-12 00:23:01 - ras_commander.hdf.HdfBase - INFO - Final validated file path: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\BaldEagleCrkMulti2D\BaldEagleDamBrk.g08.hdf
2026-01-12 00:23:01 - ras_commander.hdf.HdfBase - INFO - Found projection in RASMapper file: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\BaldEagleCrkMulti2D\Terrain\Projection.prj
2026-01-12 00:23:01 - ras_commander.hdf.HdfBase - INFO - Converted WKT to EPSG:2271 from RASMapper file Projection.prj


Output folder: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\BaldEagleCrkMulti2D\1D_Boundary_Conditions


2026-01-12 00:23:01 - pyogrio._io - INFO - Created 5 records


Project CRS: EPSG:2271
Reprojected to: EPSG:4326 (WGS84) for RASMapper
Saved GeoJSON: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\BaldEagleCrkMulti2D\1D_Boundary_Conditions\boundary_cross_sections.geojson
Boundary Condition Data:
river reach station boundary_type dss_file dss_path hms_basin
0 Bald Eagle Cr. Lock Haven 137520 Flow Hydrograph Bald_Eagle_Creek.dss //BALD EAGLE 40/FLOW/01JAN1999/15MIN/RUN:PMF-E... BALD EAGLE 40
1 Bald Eagle Cr. Lock Haven 136948 Uniform Lateral Inflow Hydrograph Bald_Eagle_Creek.dss //RESERVOIR LOCAL/FLOW/01JAN1999/15MIN/RUN:PMF... RESERVOIR LOCAL
2 Bald Eagle Cr. Lock Haven 80720 Uniform Lateral Inflow Hydrograph Bald_Eagle_Creek.dss //LOCAL DOWNSTREAM OF DAM/FLOW/01JAN1999/15MIN... LOCAL DOWNSTREAM OF DAM
3 Bald Eagle Cr. Lock Haven 80720 Uniform Lateral Inflow Hydrograph Bald_Eagle_Creek.dss //LOCAL DOWNSTREAM OF DAM/FLOW/01JAN1999/15MIN... LOCAL DOWNSTREAM OF DAM
4 Bald Eagle Cr. Lock Haven 137520 Flow Hydrograph Bald_Eagle_Creek.dss //BALD EAGLE 40/FLOW/01JAN1999/15MIN/RUN:PMF-E... BALD EAGLE 40

7. Show Current Map Layers in RASMapper

Before adding the new layer, let's see what layers are currently in the .rasmap file.

Python
# List current map layers
print("Current Map Layers in .rasmap:")
print("=" * 60)

layers_before = RasMap.list_map_layers()

if layers_before:
    for i, layer in enumerate(layers_before, 1):
        checked = "[x]" if layer['checked'] else "[ ]"
        print(f"{i}. {checked} {layer['name']}")
        print(f"      Type: {layer['type']}")
        print(f"      File: {layer['filename']}")
else:
    print("No map layers found (empty MapLayers section)")

print(f"\nTotal layers: {len(layers_before)}")
Text Only
Current Map Layers in .rasmap:
============================================================


2026-01-12 00:23:01 - ras_commander.RasMap - INFO - Found 4 map layers in .rasmap


1. [ ] Google Hybrid
      Type: WMSLayer
      File: %LocalAppData%\HEC\Mapping\5.1\XML\Google Hybrid.xml
2. [ ] LandCover
      Type: LandCoverLayer
      File: .\Land Classification\LandCover.hdf
3. [ ] Hydrologic Soil Groups
      Type: LandCoverLayer
      File: .\Soils Data\Hydrologic Soil Groups.hdf
4. [ ] Infiltration
      Type: LandCoverLayer
      File: .\Soils Data\Infiltration.hdf

Total layers: 4

8. Add Boundary Conditions Layer to RASMapper

Add the GeoJSON file as a new map layer in RASMapper with labels showing the DSS path.

Python
if output_geojson and output_geojson.exists():
    # Add the layer to .rasmap
    layer_name = "1D Boundary Conditions"

    print(f"Adding layer '{layer_name}' to RASMapper...")

    result = RasMap.add_map_layer(
        layer_name=layer_name,
        layer_file=output_geojson,
        layer_type="PolylineFeatureLayer",
        checked=True,
        label_field="dss_path",  # Show DSS path as labels
        symbology={
            "line_color": (255, 0, 0, 255),  # Red
            "line_width": 3
        }
    )

    if result:
        print(f"Successfully added layer!")
    else:
        print("Failed to add layer")
else:
    print("No GeoJSON file to add")
Text Only
2026-01-12 00:23:01 - ras_commander.RasMap - INFO - Added map layer '1D Boundary Conditions' to C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\BaldEagleCrkMulti2D\BaldEagleDamBrk.rasmap


Adding layer '1D Boundary Conditions' to RASMapper...
Successfully added layer!

9. Show Map Layers After Adding

Verify the new layer was added successfully.

Python
# List map layers after adding
print("Map Layers After Adding Boundary Conditions:")
print("=" * 60)

layers_after = RasMap.list_map_layers()

for i, layer in enumerate(layers_after, 1):
    checked = "[x]" if layer['checked'] else "[ ]"
    # Highlight the new layer
    marker = " <-- NEW" if layer['name'] == "1D Boundary Conditions" else ""
    print(f"{i}. {checked} {layer['name']}{marker}")
    print(f"      Type: {layer['type']}")
    print(f"      File: {layer['filename']}")

print(f"\nTotal layers: {len(layers_after)} (was {len(layers_before)})")
Text Only
2026-01-12 00:23:01 - ras_commander.RasMap - INFO - Found 5 map layers in .rasmap


Map Layers After Adding Boundary Conditions:
============================================================
1. [ ] Google Hybrid
      Type: WMSLayer
      File: %LocalAppData%\HEC\Mapping\5.1\XML\Google Hybrid.xml
2. [ ] LandCover
      Type: LandCoverLayer
      File: .\Land Classification\LandCover.hdf
3. [ ] Hydrologic Soil Groups
      Type: LandCoverLayer
      File: .\Soils Data\Hydrologic Soil Groups.hdf
4. [ ] Infiltration
      Type: LandCoverLayer
      File: .\Soils Data\Infiltration.hdf
5. [x] 1D Boundary Conditions <-- NEW
      Type: PolylineFeatureLayer
      File: .\1D_Boundary_Conditions\boundary_cross_sections.geojson

Total layers: 5 (was 4)

10. Configure Geometry Visibility

Before opening RASMapper, we'll hide all geometries except G08 (the one we used for cross-section extraction). This ensures the boundary condition layer displays correctly with the matching geometry.

Python
# Hide all geometries except G08
print("Configuring geometry visibility...")
print("=" * 60)

# First, hide all geometries
count = RasMap.set_all_geometries_visibility(visible=False, except_geom=target_geom)
print(f"Set visibility for {count} geometries")

# Now show only G08
RasMap.set_geometry_visibility(target_geom, visible=True)

# Verify the configuration
print("\nGeometry visibility after configuration:")
for g in RasMap.list_geometries():
    checked = "[x]" if g['checked'] else "[ ]"
    marker = " <-- SELECTED" if g['geom_number'] == target_geom else ""
    print(f"  {checked} g{g['geom_number']}: {g['name']}{marker}")
Text Only
2026-01-12 00:23:01 - ras_commander.RasMap - INFO - Modified visibility for 10 geometries
2026-01-12 00:23:01 - ras_commander.RasMap - INFO - Set geometry '1D-2D Dam Break Model Refined Grid' visibility to True
2026-01-12 00:23:01 - ras_commander.RasMap - INFO - Found 10 geometries in .rasmap


Configuring geometry visibility...
============================================================
Set visibility for 10 geometries

Geometry visibility after configuration:
  [ ] g06: Bald Eagle Multi 2D Areas
  [x] g08: 1D-2D Dam Break Model Refined Grid <-- SELECTED
  [ ] g10: U.S 2D - D.S 1D No Dam
  [ ] g11: 2D to 2D Connection
  [ ] g12: SA to 2D Connection
  [ ] g09: Single 2D Area - Internal Dam Structure
  [ ] g13: SA to 2D Flow Area
  [ ] g01: SA to 2D Flow Area - Detailed
  [ ] g03: Single 2D Area with Bridges and Breaklin
  [ ] g02: Single 2D Area -With Infiltration

11. Open RASMapper for Visualization

Open RASMapper to view the boundary conditions layer with G08 geometry. This will: 1. Launch HEC-RAS with the current project 2. Open RASMapper via GIS Tools > RAS Mapper 3. Wait for you to explore and close RASMapper 4. Automatically close HEC-RAS when done

Note: Only G08 geometry will be visible. The boundary condition cross-sections should appear in red with DSS path labels showing HMS basin names.

Python
print("Opening RASMapper...")
print("=" * 60)
print("")
print("In RASMapper, you should see:")
print("  - '1D Boundary Conditions' layer in the layer tree")
print("  - Red cross-section lines at boundary locations")
print("  - DSS path labels if zoomed in")
print("")
print("Close RASMapper and HEC-RAS when done to continue.")
print("=" * 60)

# Open RASMapper and wait for user to close it
if RUN_GUI_VISUALIZATION:
    result = RasGuiAutomation.open_rasmapper(wait_for_user=True)

    if result:
        print("\nRASMapper session completed successfully!")
    else:
        print("\nRASMapper session ended (may have had issues)")
else:
    print("\nSkipping RASMapper GUI (RUN_GUI_VISUALIZATION = False)")
Text Only
2026-01-12 00:23:01 - ras_commander.RasGuiAutomation - INFO - Opening HEC-RAS...
2026-01-12 00:23:01 - ras_commander.RasGuiAutomation - INFO - HEC-RAS opened with Process ID: 238196


Opening RASMapper...
============================================================

In RASMapper, you should see:
  - '1D Boundary Conditions' layer in the layer tree
  - Red cross-section lines at boundary locations
  - DSS path labels if zoomed in

Close RASMapper and HEC-RAS when done to continue.
============================================================


2026-01-12 00:23:02 - ras_commander.RasGuiAutomation - INFO - Found 'already running' dialog - clicking Yes to continue
2026-01-12 00:23:02 - ras_commander.RasGuiAutomation - INFO - Clicked button: &Yes
2026-01-12 00:23:02 - ras_commander.RasGuiAutomation - INFO - Clicked 'Yes' button on already running dialog
2026-01-12 00:23:03 - ras_commander.RasGuiAutomation - INFO - Waiting for HEC-RAS main window...
2026-01-12 00:23:05 - ras_commander.RasGuiAutomation - INFO - Found HEC-RAS main window: HEC-RAS 6.6
2026-01-12 00:23:05 - ras_commander.RasGuiAutomation - INFO - Opening RASMapper via menu...
2026-01-12 00:23:05 - ras_commander.RasGuiAutomation - INFO - Found RAS Mapper menu item: 'RAS Mapper ...' (ID: 102)
2026-01-12 00:23:05 - ras_commander.RasGuiAutomation - INFO - Clicked menu item ID: 102
2026-01-12 00:23:05 - ras_commander.RasGuiAutomation - INFO - Clicked RAS Mapper menu via menu ID
2026-01-12 00:23:05 - ras_commander.RasGuiAutomation - INFO - Waiting for RASMapper window (up to 300 seconds)...
2026-01-12 00:23:05 - ras_commander.RasGuiAutomation - INFO - Note: Large projects may take several minutes to load...
2026-01-12 00:23:20 - ras_commander.RasGuiAutomation - INFO - RASMapper opened: RAS Mapper (took 15s)
2026-01-12 00:23:20 - ras_commander.RasGuiAutomation - INFO - Waiting for user to close RASMapper...

12. Summary

This notebook demonstrated the complete workflow for visualizing 1D boundary conditions in RASMapper:

Step Description Status
1 Extract example project Complete
2 Select G08 geometry and extract cross-sections Complete
3 View boundary conditions from project Complete
4 View DSS information (HMS basin links) Complete
5 Match boundaries to cross-sections Complete
6 Create GeoJSON output Complete
7 Show map layers before adding Complete
8 Add boundary conditions layer to RASMapper Complete
9 Show map layers after adding Complete
10 Configure geometry visibility (show only G08) Complete
11 Open RASMapper for visualization Complete

New RasMap Functions Used

  • RasMap.list_geometries() - List all geometry layers with visibility status
  • RasMap.set_geometry_visibility(geom, visible) - Show/hide a specific geometry
  • RasMap.set_all_geometries_visibility(visible, except_geom) - Show/hide all geometries except one
Python
# Final summary
print("\nOutput Files Created:")
print("=" * 60)
if output_geojson and output_geojson.exists():
    print(f"GeoJSON: {output_geojson}")
    print(f"Size: {output_geojson.stat().st_size / 1024:.1f} KB")

    # Count features
    with open(output_geojson) as f:
        data = json.load(f)
    print(f"Features: {len(data['features'])} boundary conditions")

print(f"\nRASMapper Configuration Updated:")
print(f"  .rasmap file: {ras.project_folder / f'{ras.project_name}.rasmap'}")
print(f"  New layer: '1D Boundary Conditions'")

Optional: Remove the Map Layer

The cells below demonstrate how to remove the boundary conditions layer from RASMapper. Convert these markdown cells to code cells to execute them.

List Current Layers

Python
# List current layers
layers = RasMap.list_map_layers()
print("Current Map Layers:")
for layer in layers:
    print(f"  - {layer['name']}")

Remove the Boundary Conditions Layer

Python
# Remove the boundary conditions layer
layer_to_remove = "1D Boundary Conditions"

result = RasMap.remove_map_layer(layer_to_remove)

if result:
    print(f"Successfully removed layer '{layer_to_remove}'")
else:
    print(f"Layer '{layer_to_remove}' not found or could not be removed")

Verify Layer Removal

Python
# Verify the layer was removed
layers_after_removal = RasMap.list_map_layers()

print("Layers after removal:")
if layers_after_removal:
    for layer in layers_after_removal:
        print(f"  - {layer['name']}")
else:
    print("  (no layers)")

# Check if our layer is gone
layer_names = [l['name'] for l in layers_after_removal]
if "1D Boundary Conditions" not in layer_names:
    print("\n'1D Boundary Conditions' layer has been removed!")

Open RASMapper to Verify Removal

Python
# Open RASMapper to verify the layer is gone
print("Opening RASMapper to verify layer removal...")
RasGuiAutomation.open_rasmapper(wait_for_user=True)
print("Done!")

Notes

GeoJSON Coordinate System Requirement

IMPORTANT: GeoJSON files for RASMapper must be in WGS84 (EPSG:4326) coordinate system. RASMapper will not display GeoJSON layers correctly if they are in a projected coordinate system (like State Plane). Always reproject your GeoDataFrame to WGS84 before saving:

Python
# Reproject to WGS84 before saving GeoJSON for RASMapper
gdf_wgs84 = gdf.to_crs("EPSG:4326")
gdf_wgs84.to_file("output.geojson", driver="GeoJSON")

DSS Path Format

The DSS path follows the HEC-DSS convention:

Text Only
//BASIN_NAME/PARAMETER/START_DATE/TIME_INTERVAL/RUN_ID/

For example: //UPPER_BASIN/FLOW/01JAN2020/1HOUR/RUN:1/

  • BASIN_NAME: The HMS basin/element name
  • PARAMETER: FLOW, STAGE, PRECIP, etc.
  • START_DATE: Simulation start date
  • TIME_INTERVAL: 1HOUR, 15MIN, etc.
  • RUN_ID: HMS simulation run identifier

Supported Layer Types

  • PolylineFeatureLayer - For lines (cross-sections, reaches)
  • PolygonFeatureLayer - For polygons (basins, 2D areas)
  • PointFeatureLayer - For points (structures, gages)

Symbology Options

Python
symbology = {
    "line_color": (R, G, B, A),  # RGBA values 0-255
    "line_width": int,           # Line width in pixels
    "fill_color": (R, G, B, A),  # For polygons only
}
CLB Engineering Corporation  ·  LLM Forward Engineering
RAS Commander is a free and open-source project maintained by CLB Engineering Corporation. For agencies and firms seeking to modernize H&H workflows with LLM Forward approaches, contact CLB to partner with the engineers who wrote the automation.