Skip to content

Plan and Geometry Operations

RAS Commander: Plan and Geometry Operations

This notebook demonstrates how to perform operations on HEC-RAS plan and geometry files using the RAS Commander library. We'll explore how to initialize projects, clone plans and geometries, configure parameters, execute plans, and analyze results.

Operations Covered

  1. Project Initialization: Initialize a HEC-RAS project by specifying the project path and version
  2. Plan Operations:
  3. Clone an existing plan to create a new one
  4. Configure simulation parameters and intervals
  5. Set run flags and update descriptions
  6. Geometry Operations:
  7. Clone a geometry file to create a modified version
  8. Set the geometry for a plan
  9. Clear geometry preprocessor files to ensure clean results
  10. Flow Operations:
  11. Clone unsteady flow files
  12. Configure flow parameters
  13. Plan Computation: Run the plan with specified settings
  14. Results Verification: Check HDF entries to confirm results were written

Package Installation and Environment Setup

Uncomment and run package installation commands if needed

Python
# 1. Install ras-commander from pip (uncomment to install if needed)
#!pip install ras-commander
# This installs ras-commander and all dependencies
Python
# =============================================================================
# DEVELOPMENT MODE TOGGLE
# =============================================================================
USE_LOCAL_SOURCE = False  # <-- TOGGLE THIS

# Import Path (needed for both modes)
from pathlib import Path
import sys

if USE_LOCAL_SOURCE:
    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 HdfResultsPlan, RasCmdr, RasExamples, RasGeo, RasPlan, init_ras_project, ras

# Additional imports
import os
import pandas as pd
from IPython import display
from datetime import datetime

# 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

Prerequisites

Before running this notebook, ensure you have:

  1. ras-commander installed: pip install ras-commander
  2. Python 3.10+: Check with python --version
  3. HEC-RAS 6.3+: Required for plan computation
  4. Disk Space: ~1 GB (example project + cloned files)

What You'll Learn

This notebook demonstrates plan and geometry manipulation - essential skills for automating HEC-RAS workflows:

  • Cloning Plans: Create plan variants for sensitivity analysis
  • Cloning Geometries: Duplicate geometry files for modifications
  • File Associations: Link plans to specific geometry/flow files
  • Parameter Updates: Modify simulation dates, intervals, and runtime flags
  • Computation Control: Set number of cores and clear preprocessed data
  • 101_project_initialization.ipynb - Project setup fundamentals
  • 104_plan_parameter_operations.ipynb - Detailed parameter editing
  • 110_single_plan_execution.ipynb - Execute configured plans

Key Concept: Plan-Geometry Relationships

HEC-RAS plans reference specific geometry and flow files. When cloning: - Plans (.p##): Simulation configuration (runtime flags, dates, output options) - Geometries (.g##): Channel cross sections, 2D mesh, structures - Flow Files (.f##, .u##): Boundary conditions and hydrographs

Pattern: Clone plan → Clone geometry → Associate cloned geometry with cloned plan → Modify parameters → Execute

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 = "Muncie"           # Example project to extract
RAS_VERSION = "7.0"               # HEC-RAS version (6.3, 6.5, 6.6, etc.)
Python
# Extract specific projects we'll use in this tutorial
# This will download them if not present and extract them to the example_projects folder
bald_eagle_path = RasExamples.extract_project("Balde Eagle Creek", suffix="103")
print(bald_eagle_path)
Text Only
2026-01-11 20:44:09 - 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-11 20:44:09 - ras_commander.RasExamples - INFO - Loading project data from CSV...


2026-01-11 20:44:09 - ras_commander.RasExamples - INFO - Loaded 68 projects from CSV.
2026-01-11 20:44:09 - ras_commander.RasExamples - INFO - ----- RasExamples Extracting Project -----
2026-01-11 20:44:09 - ras_commander.RasExamples - INFO - Extracting project 'Balde Eagle Creek' as 'Balde Eagle Creek_103'
2026-01-11 20:44:09 - ras_commander.RasExamples - INFO - Successfully extracted project 'Balde Eagle Creek' to C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103


C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103

Project Initialization

The first step is to initialize the HEC-RAS project. This is done using the init_ras_project() function, which takes the project folder path and HEC-RAS version as parameters.

Python
init_ras_project(bald_eagle_path, RAS_VERSION)
print(f"Initialized HEC-RAS project: {ras.project_name}")

# Display the current plan files in the project
print("\nHEC-RAS Project Plan Data (plan_df):")
display.display(ras.plan_df)
Text Only
2026-01-11 20:44:09 - ras_commander.RasMap - INFO - Successfully parsed RASMapper file: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.rasmap
2026-01-11 20:44:09 - ras_commander.RasPrj - INFO - Updated results_df with 2 plan(s)


Initialized HEC-RAS project: BaldEagle

HEC-RAS Project Plan Data (plan_df):
plan_number unsteady_number geometry_number Plan Title Program Version Short Identifier Simulation Date Computation Interval Mapping Interval Run HTab ... PS Cores DSS File Friction Slope Method HDF_Results_Path Geom File Geom Path Flow File Flow Path full_path flow_type
0 01 02 01 Unsteady with Bridges and Dam 5.00 UnsteadyFlow 18FEB1999,0000,24FEB1999,0500 2MIN 1HOUR 1 ... None dss 2 None 01 C:\Users\billk_clb\anaconda3\envs\rascmdr_pipt... 02 C:\Users\billk_clb\anaconda3\envs\rascmdr_pipt... C:\Users\billk_clb\anaconda3\envs\rascmdr_pipt... Unsteady
1 02 None 01 Steady Flow Run NaN SteadyRun 02/18/1999,0000,02/24/1999,0500 2MIN NaN 1 ... None dss 1 None 01 C:\Users\billk_clb\anaconda3\envs\rascmdr_pipt... 02 C:\Users\billk_clb\anaconda3\envs\rascmdr_pipt... C:\Users\billk_clb\anaconda3\envs\rascmdr_pipt... Steady

2 rows × 27 columns

Understanding Plan and Geometry Operations in HEC-RAS

Before diving into the operations, let's understand what plan and geometry files are in HEC-RAS:

  • Plan Files (.p*): Define the simulation parameters including the reference to geometry and flow files, as well as computational settings.
  • Geometry Files (.g*): Define the physical characteristics of the river/channel system including cross-sections, 2D areas, and structures.

The RasPlan and RasGeo classes provide methods for working with these files, including:

  1. Creating new plans and geometries by cloning existing ones
  2. Modifying simulation parameters and settings
  3. Associating geometries with plans
  4. Managing preprocessor files
  5. Retrieving information from plans and geometries

In the following sections, we'll explore these operations in detail.

Cloning Plans and Geometries

Let's start by cloning a plan to create a new simulation scenario.

Python
# Clone plan "01" to create a new plan
new_plan_number = RasPlan.clone_plan("1", new_shortid="Combined Test Plan")
print(f"New plan created: {new_plan_number}")

# Display updated plan files
print("\nUpdated plan files:")
display.display(ras.plan_df)

# Get the path to the new plan file
plan_path = RasPlan.get_plan_path(new_plan_number)
print(f"\nNew plan file path: {plan_path}")

# Let's examine the new plan's details
new_plan = ras.plan_df[ras.plan_df['plan_number'] == new_plan_number].iloc[0]
print(f"\nNew plan details:")
print(f"Plan number: {new_plan_number}")
print(f"Description: {new_plan.get('description', 'No description')}")
print(f"Short Identifier: {new_plan.get('Short Identifier', 'Not available')}")
print(f"Geometry file: {new_plan.get('Geom File', 'None')}")
print(f"File path: {new_plan['full_path']}")
Text Only
2026-01-11 20:44:09 - ras_commander.RasUtils - INFO - File cloned from C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p01 to C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03
2026-01-11 20:44:09 - ras_commander.RasUtils - INFO - Successfully updated file: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03
2026-01-11 20:44:09 - ras_commander.RasUtils - INFO - Project file updated with new Plan entry: 03
2026-01-11 20:44:09 - ras_commander.RasMap - INFO - Successfully parsed RASMapper file: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.rasmap
2026-01-11 20:44:09 - ras_commander.RasPrj - INFO - Updated results_df with 3 plan(s)


New plan created: 03

Updated plan files:
plan_number unsteady_number geometry_number Plan Title Program Version Short Identifier Simulation Date Computation Interval Mapping Interval Run HTab ... UNET D2 Cores PS Cores DSS File Friction Slope Method HDF_Results_Path Geom File Geom Path Flow File Flow Path full_path
0 01 02 01 Unsteady with Bridges and Dam 5.00 UnsteadyFlow 18FEB1999,0000,24FEB1999,0500 2MIN 1HOUR 1 ... 0.0 None dss 2 None 01 C:\Users\billk_clb\anaconda3\envs\rascmdr_pipt... 02 C:\Users\billk_clb\anaconda3\envs\rascmdr_pipt... C:\Users\billk_clb\anaconda3\envs\rascmdr_pipt...
1 02 None 01 Steady Flow Run NaN SteadyRun 02/18/1999,0000,02/24/1999,0500 2MIN NaN 1 ... NaN None dss 1 None 01 C:\Users\billk_clb\anaconda3\envs\rascmdr_pipt... 02 C:\Users\billk_clb\anaconda3\envs\rascmdr_pipt... C:\Users\billk_clb\anaconda3\envs\rascmdr_pipt...
2 03 02 01 Unsteady with Bridges and Dam 5.00 Combined Test Plan 18FEB1999,0000,24FEB1999,0500 2MIN 1HOUR 1 ... 0.0 None dss 2 None 01 C:\Users\billk_clb\anaconda3\envs\rascmdr_pipt... 02 C:\Users\billk_clb\anaconda3\envs\rascmdr_pipt... C:\Users\billk_clb\anaconda3\envs\rascmdr_pipt...

3 rows × 26 columns

Text Only
New plan file path: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03

New plan details:
Plan number: 03
Description: No description
Short Identifier: Combined Test Plan
Geometry file: 01
File path: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03

Verification: Plan Cloning

Success Criteria: - New plan file created in project folder (check ras.plan_df) - Cloned plan has unique plan number - Original plan unchanged

Visual Inspection:

Python
# Verify plan was cloned
print(f"Original plans: {ras.plan_df['plan_number'].tolist()}")
# Should show new plan number (e.g., ["01", "02", "03", "new_number"])

# Open project in HEC-RAS GUI
# Verify new plan appears in plan list with correct title

Audit Trail:

Python
# Document cloning operation
import json
audit = {
    'operation': 'clone_plan',
    'source_plan': "01",
    'new_plan': new_plan_number,
    'new_title': current_title
}

with open(project_folder / 'clone_audit.json', 'w') as f:
    json.dump(audit, f, indent=2)

Why Clone Plans?

Use Cases: 1. Sensitivity Analysis: Test different parameters without modifying original 2. Scenario Planning: Compare mitigation alternatives (baseline vs proposed) 3. Batch Processing: Create multiple plan variants programmatically

Python
# Get the current plan title and shortid
current_title = RasPlan.get_plan_title(new_plan_number)
current_shortid = RasPlan.get_shortid(new_plan_number)

print(f"Current plan title: {current_title}")
print(f"Current plan shortid: {current_shortid}")
Text Only
2026-01-11 20:44:09 - ras_commander.RasPlan - INFO - Retrieved Plan Title: Unsteady with Bridges and Dam
2026-01-11 20:44:09 - ras_commander.RasPlan - INFO - Retrieved Short Identifier: Combined Test Plan


Current plan title: Unsteady with Bridges and Dam
Current plan shortid: Combined Test Plan
Python
# Update the title and shortid to append " clonedplan"
new_title = f"{current_title} clonedplan"
new_shortid = f"{current_shortid} clonedplan"

RasPlan.set_plan_title(new_plan_number, new_title)
RasPlan.set_shortid(new_plan_number, new_shortid)

print(f"\nUpdated plan title: {RasPlan.get_plan_title(new_plan_number)}")
print(f"Updated plan shortid: {RasPlan.get_shortid(new_plan_number)}")
Text Only
2026-01-11 20:44:09 - ras_commander.RasUtils - INFO - Constructed plan file path: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03
2026-01-11 20:44:09 - ras_commander.RasPlan - INFO - Updated Plan Title in plan file to: Unsteady with Bridges and Dam clonedplan
2026-01-11 20:44:09 - ras_commander.RasPlan - WARNING - Short Identifier too long (24 char max). Truncating: Combined Test Plan clonedplan
2026-01-11 20:44:09 - ras_commander.RasUtils - INFO - Constructed plan file path: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03
2026-01-11 20:44:09 - ras_commander.RasPlan - INFO - Updated Short Identifier in plan file to: Combined Test Plan clone
2026-01-11 20:44:09 - ras_commander.RasPlan - INFO - Retrieved Plan Title: Unsteady with Bridges and Dam clonedplan
2026-01-11 20:44:09 - ras_commander.RasPlan - INFO - Retrieved Short Identifier: Combined Test Plan clone



Updated plan title: Unsteady with Bridges and Dam clonedplan
Updated plan shortid: Combined Test Plan clone
Python
# Get the current plan title and shortid again to confirm the changes
current_title = RasPlan.get_plan_title(new_plan_number)
current_shortid = RasPlan.get_shortid(new_plan_number)

print(f"Current plan title: {current_title}")
print(f"Current plan shortid: {current_shortid}")
Text Only
2026-01-11 20:44:09 - ras_commander.RasPlan - INFO - Retrieved Plan Title: Unsteady with Bridges and Dam clonedplan
2026-01-11 20:44:09 - ras_commander.RasPlan - INFO - Retrieved Short Identifier: Combined Test Plan clone


Current plan title: Unsteady with Bridges and Dam clonedplan
Current plan shortid: Combined Test Plan clone

Now let's clone a geometry file. This allows us to make modifications to a geometry without affecting the original.

Python
# Clone geometry "01" to create a new geometry file
new_geom_number = RasPlan.clone_geom("01")
print(f"New geometry created: {new_geom_number}")

# Display updated geometry files
print("\nUpdated geometry files:")
display.display(ras.geom_df)

# Get the path to the new geometry file
geom_path = RasPlan.get_geom_path(new_geom_number)
print(f"\nNew geometry file path: {geom_path}")

# Examine the new geometry's details
new_geom = ras.geom_df.loc[ras.geom_df['geom_number'] == new_geom_number].squeeze()
print(f"\nNew geometry details:")
print(f"Geometry number: {new_geom_number}")
print(f"Geometry file: {new_geom.get('geom_file', 'Not available')}")
print(f"File path: {new_geom.get('full_path', 'Not available')}")
print(f"HDF path: {new_geom.get('hdf_path', 'None')}")
Text Only
2026-01-11 20:44:09 - ras_commander.RasUtils - INFO - File cloned from C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.g01 to C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.g02
2026-01-11 20:44:10 - ras_commander.RasUtils - INFO - File cloned from C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.g01.hdf to C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.g02.hdf
2026-01-11 20:44:10 - ras_commander.RasUtils - INFO - Project file updated with new Geom entry: 02


New geometry created: 02

Updated geometry files:
geom_file geom_number full_path hdf_path
0 g01 01 C:\Users\billk_clb\anaconda3\envs\rascmdr_pipt... C:\Users\billk_clb\anaconda3\envs\rascmdr_pipt...
1 g02 02 C:\Users\billk_clb\anaconda3\envs\rascmdr_pipt... C:\Users\billk_clb\anaconda3\envs\rascmdr_pipt...
Text Only
2026-01-11 20:44:10 - ras_commander.RasPlan - INFO - Found geometry path: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.g02



New geometry file path: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.g02

New geometry details:
Geometry number: 02
Geometry file: Not available
File path: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.g02
HDF path: None

Let's also clone an unsteady flow file to complete our new simulation setup.

Python
# Clone unsteady flow "02" to create a new unsteady flow file
new_unsteady_number = RasPlan.clone_unsteady("02")
print(f"New unsteady flow created: {new_unsteady_number}")

# Display updated unsteady flow files
print("\nUpdated unsteady flow files:")
display.display(ras.unsteady_df)

# Examine the new unsteady flow's details
new_unsteady = ras.unsteady_df[ras.unsteady_df['unsteady_number'] == new_unsteady_number].iloc[0]
print(f"\nNew unsteady flow details:")
print(f"Unsteady number: {new_unsteady_number}")
print(f"File path: {new_unsteady['full_path']}")
print(f"Flow Title: {new_unsteady.get('Flow Title', 'Not available')}")
Text Only
2026-01-11 20:44:10 - ras_commander.RasUtils - INFO - File cloned from C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.u02 to C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.u01
2026-01-11 20:44:10 - ras_commander.RasUtils - INFO - Successfully updated file: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.u01
2026-01-11 20:44:10 - ras_commander.RasUtils - INFO - Project file updated with new Unsteady entry: 01
2026-01-11 20:44:10 - ras_commander.RasMap - INFO - Successfully parsed RASMapper file: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.rasmap
2026-01-11 20:44:10 - ras_commander.RasPrj - INFO - Updated results_df with 3 plan(s)


New unsteady flow created: 01

Updated unsteady flow files:
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
0 02 C:\Users\billk_clb\anaconda3\envs\rascmdr_pipt... Flow Hydrograph 2 6.30 0 Disable No Wind Forces None None 0 mm/hr DSS
1 01 C:\Users\billk_clb\anaconda3\envs\rascmdr_pipt... Flow Hydrograph 2 6.30 0 Disable No Wind Forces None None 0 mm/hr DSS
Text Only
New unsteady flow details:
Unsteady number: 01
File path: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.u01
Flow Title: Flow Hydrograph 2

Associating Files and Setting Parameters

Now that we have cloned our plan, geometry, and unsteady flow files, we need to associate them with each other and set various parameters.

Setting Geometry for a Plan

Let's associate our new geometry with our new plan:

Python
# Set the new geometry for the cloned plan
updated_geom_df = RasPlan.set_geom(new_plan_number, new_geom_number)
plan_path = RasPlan.get_plan_path(new_plan_number, ras_object=ras)
print(f"Updated geometry for plan {new_plan_number} to geometry {new_geom_number}")
print(f"Plan file path: {plan_path}")

# Let's verify the change
updated_plan = ras.plan_df[ras.plan_df['plan_number'] == new_plan_number].iloc[0]
print(f"\nVerified that plan {new_plan_number} now uses geometry file: {updated_plan.get('Geom File', 'None')}")
Text Only
2026-01-11 20:44:10 - ras_commander.RasPlan - INFO - Updated Geom File in plan file to g02 for plan 03
2026-01-11 20:44:10 - ras_commander.RasPlan - INFO - Geometry for plan 03 set to 02


Updated geometry for plan 03 to geometry 02
Plan file path: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03

Verified that plan 03 now uses geometry file: g02

Setting Unsteady Flow for a Plan

Similarly, let's associate our new unsteady flow file with our plan:

Python
# Set unsteady flow for the cloned plan
RasPlan.set_unsteady(new_plan_number, new_unsteady_number)
print(f"Updated unsteady flow for plan {new_plan_number} to unsteady flow {new_unsteady_number}")
Text Only
Updated unsteady flow for plan 03 to unsteady flow 01

Clearing Geometry Preprocessor Files

When working with geometry files, it's important to clear the preprocessor files to ensure clean results. These files (with .c* extension) contain computed hydraulic properties that should be recomputed when the geometry changes.

Python
# Clear geometry preprocessor files for the cloned plan
RasGeo.clear_geompre_files(plan_path)
print(f"Cleared geometry preprocessor files for plan {new_plan_number}")

# Check if preprocessor file exists after clearing
geom_preprocessor_suffix = '.c' + ''.join(Path(plan_path).suffixes[1:])
geom_preprocessor_file = Path(plan_path).with_suffix(geom_preprocessor_suffix)
print(f"Preprocessor file exists after clearing: {geom_preprocessor_file.exists()}")
Text Only
2026-01-11 20:44:10 - ras_commander.geom.GeomPreprocessor - INFO - Clearing geometry preprocessor file for single plan: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03
2026-01-11 20:44:10 - ras_commander.geom.GeomPreprocessor - WARNING - No geometry preprocessor file found for: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03
2026-01-11 20:44:10 - ras_commander.geom.GeomPreprocessor - INFO - Geometry dataframe updated successfully.


Cleared geometry preprocessor files for plan 03
Preprocessor file exists after clearing: False

GeomPreprocessor: Correct .c## File Resolution

When clearing geometry preprocessor files, GeomPreprocessor looks up the plan's geometry_number from plan_df to target the correct .c## file. This matters when the plan number differs from the geometry number — for example, plan 03 uses geometry 02, so the preprocessor targets .c02 (not .c03).

Python
# Show that plan 03 uses geometry 02 (not 03)
plan_row = ras.plan_df[ras.plan_df['plan_number'] == new_plan_number].iloc[0]
geom_num = plan_row['geometry_number']
print(f"Plan {new_plan_number} uses geometry {geom_num}")
print(f"  -> GeomPreprocessor targets .c{geom_num} (not .c{new_plan_number})")

# Verify the correct .c## file is the one that was cleared
from pathlib import Path
project_folder = Path(plan_path).parent
project_name = ras.project_name

correct_c_file = project_folder / f"{project_name}.c{geom_num}"
wrong_c_file = project_folder / f"{project_name}.c{new_plan_number}"

print(f"\n  Correct target: {correct_c_file.name} exists={correct_c_file.exists()}")
print(f"  Wrong target:   {wrong_c_file.name} exists={wrong_c_file.exists()}")

Setting Computation Parameters

Let's set the computation parameters for our plan:

Python
# Set the number of cores to use for the computation
RasPlan.set_num_cores(new_plan_number, 2)
print(f"Updated number of cores for plan {new_plan_number} to 2")

# Verify by extracting the value from the plan file
cores_value = RasPlan.get_plan_value(new_plan_number, "UNET D1 Cores")
print(f"\nVerified that UNET D1 Cores is set to: {cores_value}")

# Set geometry preprocessor options
RasPlan.set_geom_preprocessor(plan_path, run_htab=-1, use_ib_tables=-1)
print(f"Updated geometry preprocessor options for plan {new_plan_number}")
print(f"- Run HTab: -1 (Force recomputation of geometry tables)")
print(f"- Use Existing IB Tables: -1 (Force recomputation of interpolation/boundary tables)")

# Verify by extracting the values from the plan file
run_htab_value = RasPlan.get_plan_value(new_plan_number, "Run HTab")
ib_tables_value = RasPlan.get_plan_value(new_plan_number, "UNET Use Existing IB Tables")
print(f"\nVerified setting values:")
print(f"- Run HTab: {run_htab_value}")
print(f"- UNET Use Existing IB Tables: {ib_tables_value}")
Text Only
2026-01-11 20:44:10 - ras_commander.RasUtils - INFO - Constructed plan file path: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03
2026-01-11 20:44:10 - ras_commander.RasUtils - INFO - Successfully updated file: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03
2026-01-11 20:44:10 - ras_commander.RasUtils - INFO - Successfully updated file: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03


Updated number of cores for plan 03 to 2

Verified that UNET D1 Cores is set to: 2
Updated geometry preprocessor options for plan 03
- Run HTab: -1 (Force recomputation of geometry tables)
- Use Existing IB Tables: -1 (Force recomputation of interpolation/boundary tables)

Verified setting values:
- Run HTab: -1
- UNET Use Existing IB Tables: -1

Updating Simulation Parameters

Now, let's update various simulation parameters for our plan:

Python
# 1. Update simulation date
start_date = datetime(2023, 1, 1, 0, 0)  # January 1, 2023, 00:00
end_date = datetime(2023, 1, 5, 23, 59)  # January 5, 2023, 23:59

RasPlan.update_simulation_date(new_plan_number, start_date, end_date)
print(f"Updated simulation date for plan {new_plan_number}:")
print(f"- Start Date: {start_date}")
print(f"- End Date: {end_date}")
Text Only
2026-01-11 20:44:10 - ras_commander.RasPlan - INFO - Updated simulation date in plan file: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03


Updated simulation date for plan 03:
- Start Date: 2023-01-01 00:00:00
- End Date: 2023-01-05 23:59:00
Python
# Verify the update
sim_date = RasPlan.get_plan_value(new_plan_number, "Simulation Date")
print(f"Verified Simulation Date value: {sim_date}")
Text Only
Verified Simulation Date value: 01JAN2023,0000,05JAN2023,2359
Python
# 2. Update plan intervals
RasPlan.update_plan_intervals(
    new_plan_number,
    computation_interval="1MIN",  # Computational time step
    output_interval="15MIN",      # How often results are written
    mapping_interval="30MIN"      # How often mapping outputs are created
)
print(f"\nUpdated plan intervals for plan {new_plan_number}:")
print(f"- Computation Interval: 1MIN")
print(f"- Output Interval: 15MIN")
print(f"- Mapping Interval: 30MIN")

# Verify the updates
comp_interval = RasPlan.get_plan_value(new_plan_number, "Computation Interval")
mapping_interval = RasPlan.get_plan_value(new_plan_number, "Mapping Interval")
print(f"Verified interval values:")
print(f"- Computation Interval: {comp_interval}")
print(f"- Mapping Interval: {mapping_interval}")
Text Only
2026-01-11 20:44:10 - ras_commander.RasPlan - INFO - Successfully updated intervals in plan file: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03



Updated plan intervals for plan 03:
- Computation Interval: 1MIN
- Output Interval: 15MIN
- Mapping Interval: 30MIN
Verified interval values:
- Computation Interval: 1MIN
- Mapping Interval: 30MIN
Python
# 3. Update run flags
RasPlan.update_run_flags(
    new_plan_number,
    geometry_preprocessor=True,   # Run the geometry preprocessor
    unsteady_flow_simulation=True, # Run unsteady flow simulation
    post_processor=True,          # Run post-processing
    floodplain_mapping=True       # Generate floodplain mapping outputs
)
print(f"\nUpdated run flags for plan {new_plan_number}:")
print(f"- Geometry Preprocessor: True")
print(f"- Unsteady Flow Simulation: True")
print(f"- Post Processor: True")
print(f"- Floodplain Mapping: True")
Text Only
2026-01-11 20:44:10 - ras_commander.RasPlan - INFO - Successfully updated run flags in plan file: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03 (flags modified: 4)



Updated run flags for plan 03:
- Geometry Preprocessor: True
- Unsteady Flow Simulation: True
- Post Processor: True
- Floodplain Mapping: True
Python
# Verify the updates
run_htab = RasPlan.get_plan_value(new_plan_number, "Run HTab")
run_unet = RasPlan.get_plan_value(new_plan_number, "Run UNet")
print(f"Verified run flag values:")
print(f"- Run HTab (Geometry Preprocessor): {run_htab}")
print(f"- Run UNet (Unsteady Flow): {run_unet}")

# 4. Update plan description
new_description = "Combined plan with modified geometry and unsteady flow\nJanuary 2023 simulation\n1-minute computation interval\nGeometry and unsteady flow from cloned files"
RasPlan.update_plan_description(new_plan_number, new_description)
print(f"\nUpdated description for plan {new_plan_number}")

# Read back the description
current_description = RasPlan.read_plan_description(new_plan_number)
print(f"Current plan description:\n{current_description}")
Text Only
2026-01-11 20:44:10 - ras_commander.RasPlan - WARNING - Unknown key: Run UNet. Valid keys are: Run RASMapper, Short Identifier, Mapping Interval, Run UNET, Description, Run WQNET, PS Cores, Simulation Date, Run Post Process, UNET D2 Solver Type, Geom File, UNET 1D Methodology, UNET Use Existing IB Tables, Plan Title, Run HTab, Program Version, Run Sediment, Flow File, DSS File, UNET D2 Cores, UNET D1 Cores, Plan File, Friction Slope Method, UNET D2 Name, Computation Interval
 Add more keys and explanations in get_plan_value() as needed.


Verified run flag values:
- Run HTab (Geometry Preprocessor): -1
- Run UNet (Unsteady Flow): -1


2026-01-11 20:44:10 - ras_commander.RasPlan - WARNING - No description found in plan file: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03



Updated description for plan 03
Current plan description:

Computing the Plan

Now that we have set up all the parameters, let's compute the plan using RasCmdr.compute_plan():

Python
# Compute the plan with our configured settings
# Note: This may take several minutes depending on the complexity of the model
print(f"Computing plan {new_plan_number}...")
success = RasCmdr.compute_plan(new_plan_number, clear_geompre=True)

if success:
    print(f"Plan {new_plan_number} computed successfully")
else:
    print(f"Failed to compute plan {new_plan_number}")
Text Only
2026-01-11 20:44:10 - ras_commander.RasCmdr - INFO - Using ras_object with project folder: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103
2026-01-11 20:44:10 - ras_commander.geom.GeomPreprocessor - INFO - Clearing geometry preprocessor file for single plan: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03
2026-01-11 20:44:10 - ras_commander.geom.GeomPreprocessor - WARNING - No geometry preprocessor file found for: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03
2026-01-11 20:44:10 - ras_commander.geom.GeomPreprocessor - INFO - Geometry dataframe updated successfully.
2026-01-11 20:44:10 - ras_commander.RasCmdr - INFO - Cleared geometry preprocessor files for plan: 03
2026-01-11 20:44:10 - ras_commander.RasCmdr - INFO - Running HEC-RAS from the Command Line:
2026-01-11 20:44:10 - ras_commander.RasCmdr - INFO - Running command: "C:\Program Files (x86)\HEC\HEC-RAS\6.6\Ras.exe" -c "C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.prj" "C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03"


Computing plan 03...


2026-01-11 20:46:11 - ras_commander.RasCmdr - INFO - HEC-RAS execution completed for plan: 03
2026-01-11 20:46:11 - ras_commander.RasCmdr - INFO - Total run time for plan 03: 120.78 seconds
2026-01-11 20:46:11 - ras_commander.hdf.HdfResultsPlan - INFO - Using existing Path object HDF file: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03.hdf
2026-01-11 20:46:11 - ras_commander.hdf.HdfResultsPlan - INFO - Final validated file path: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03.hdf
2026-01-11 20:46:11 - ras_commander.hdf.HdfResultsPlan - INFO - Reading computation messages from HDF: BaldEagle.p03.hdf
2026-01-11 20:46:11 - ras_commander.hdf.HdfResultsPlan - INFO - Successfully extracted 1756 characters from HDF
2026-01-11 20:46:11 - ras_commander.hdf.HdfResultsPlan - INFO - Using existing Path object HDF file: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03.hdf
2026-01-11 20:46:11 - ras_commander.hdf.HdfResultsPlan - INFO - Final validated file path: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03.hdf
2026-01-11 20:46:11 - ras_commander.hdf.HdfResultsPlan - INFO - Extracting Plan Information from: BaldEagle.p03.hdf
2026-01-11 20:46:11 - ras_commander.hdf.HdfResultsPlan - INFO - Plan Name: Unsteady with Bridges and Dam clonedplan
2026-01-11 20:46:11 - ras_commander.hdf.HdfResultsPlan - INFO - Simulation Duration (hours): 119.98333333333333
2026-01-11 20:46:11 - ras_commander.hdf.HdfResultsPlan - INFO - Using existing Path object HDF file: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03.hdf
2026-01-11 20:46:11 - ras_commander.hdf.HdfResultsPlan - INFO - Final validated file path: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03.hdf
2026-01-11 20:46:11 - ras_commander.hdf.HdfResultsPlan - INFO - Using existing Path object HDF file: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03.hdf
2026-01-11 20:46:11 - ras_commander.hdf.HdfResultsPlan - INFO - Final validated file path: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03.hdf
c:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\ras_commander\RasPrj.py:1513: FutureWarning: The behavior of DataFrame concatenation with empty or all-NA entries is deprecated. In a future version, this will no longer exclude empty or all-NA columns when determining the result dtypes. To retain the old behavior, exclude the relevant entries before the concat operation.
  self.results_df = pd.concat([self.results_df, new_results], ignore_index=True)
2026-01-11 20:46:11 - ras_commander.RasPrj - INFO - Updated results_df with 1 plan(s)


Plan 03 computed successfully

Verifying Results

After computation, we should check if results were written correctly:

Python
# Refresh the plan entries to ensure we have the latest data
ras.plan_df = ras.get_plan_entries()
hdf_entries = ras.get_hdf_entries()

if not hdf_entries.empty:
    print("HDF entries for the project:")
    display.display(hdf_entries)

    # Check if our new plan has an HDF file
    new_plan_hdf = hdf_entries[hdf_entries['plan_number'] == new_plan_number]
    if not new_plan_hdf.empty:
        print(f"\nPlan {new_plan_number} has a valid HDF results file:")
        print(f"HDF Path: {new_plan_hdf.iloc[0]['HDF_Results_Path']}")
    else:
        print(f"\nNo HDF entry found for plan {new_plan_number}")
else:
    print("No HDF entries found. This could mean the plan hasn't been computed successfully or the results haven't been written yet.")

# Display all plan entries to see their HDF paths
print("\nAll plan entries with their HDF paths:")
plan_hdf_info = ras.plan_df[['plan_number', 'HDF_Results_Path']]
display.display(plan_hdf_info)
Text Only
HDF entries for the project:
plan_number unsteady_number geometry_number Plan Title Program Version Short Identifier Simulation Date Computation Interval Mapping Interval Run HTab ... PS Cores DSS File Friction Slope Method description HDF_Results_Path Geom File Geom Path Flow File Flow Path full_path
2 03 01 02 Unsteady with Bridges and Dam clonedplan 5.00 Combined Test Plan clone 01JAN2023,0000,05JAN2023,2359 1MIN 30MIN -1 ... None dss 2 Combined plan with modified geometry and unste... C:\Users\billk_clb\anaconda3\envs\rascmdr_pipt... 02 C:\Users\billk_clb\anaconda3\envs\rascmdr_pipt... 01 C:\Users\billk_clb\anaconda3\envs\rascmdr_pipt... C:\Users\billk_clb\anaconda3\envs\rascmdr_pipt...

1 rows × 27 columns

Text Only
Plan 03 has a valid HDF results file:
HDF Path: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03.hdf

All plan entries with their HDF paths:
plan_number HDF_Results_Path
0 01 None
1 02 None
2 03 C:\Users\billk_clb\anaconda3\envs\rascmdr_pipt...

If the plan was computed successfully, we can examine the runtime data and volume accounting from the HDF results:

Python
# Get computation runtime data from HDF
print("Checking computation runtime data...")
runtime_df = HdfResultsPlan.get_runtime_data(new_plan_number)

if runtime_df is not None and not runtime_df.empty:
    print("\nSimulation Runtime Statistics:")
    display.display(runtime_df)

    # Extract key metrics
    sim_duration = runtime_df['Simulation Duration (s)'].iloc[0]
    compute_time = runtime_df['Complete Process (hr)'].iloc[0]
    compute_speed = runtime_df['Complete Process Speed (hr/hr)'].iloc[0]

    print(f"\nSimulation Duration: {sim_duration:.2f} seconds")
    print(f"Computation Time: {compute_time:.5f} hours")
    print(f"Computation Speed: {compute_speed:.2f} (simulation hours/compute hours)")
else:
    print("No runtime data found. This may indicate the simulation didn't complete successfully.")

# Get volume accounting data
print("\nChecking volume accounting...")
volume_df = HdfResultsPlan.get_volume_accounting(new_plan_number)

if volume_df is not None and not isinstance(volume_df, bool):
    # Handle volume_df as a dictionary
    if isinstance(volume_df, dict):
        error_percent = volume_df.get('Error Percent')
        if error_percent is not None:
            print(f"\nFinal Volume Balance Error: {float(error_percent):.8f}%")

        # Print other key statistics
        print("\nDetailed Volume Statistics:")
        print(f"Volume Starting: {float(volume_df['Volume Starting']):.2f} {volume_df['Vol Accounting in'].decode()}")
        print(f"Volume Ending: {float(volume_df['Volume Ending']):.2f} {volume_df['Vol Accounting in'].decode()}")
        print(f"Total Inflow: {float(volume_df['Total Boundary Flux of Water In']):.2f} {volume_df['Vol Accounting in'].decode()}")
        print(f"Total Outflow: {float(volume_df['Total Boundary Flux of Water Out']):.2f} {volume_df['Vol Accounting in'].decode()}")
else:
    print("No volume accounting data found. This may indicate the simulation didn't complete successfully.")
Text Only
2026-01-11 20:46:11 - ras_commander.hdf.HdfResultsPlan - INFO - Final validated file path: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03.hdf
2026-01-11 20:46:11 - ras_commander.hdf.HdfResultsPlan - INFO - Extracting Plan Information from: BaldEagle.p03.hdf
2026-01-11 20:46:11 - ras_commander.hdf.HdfResultsPlan - INFO - Plan Name: Unsteady with Bridges and Dam clonedplan
2026-01-11 20:46:11 - ras_commander.hdf.HdfResultsPlan - INFO - Simulation Duration (hours): 119.98333333333333


Checking computation runtime data...

Simulation Runtime Statistics:
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 Unsteady with Bridges and Dam clonedplan BaldEagle.p03.hdf 2023-01-01 2023-01-05 23:59:00 431940.0 119.983333 N/A 0.025894 N/A 0.003038 0.032869 39489.851892 3650.361706
Text Only
2026-01-11 20:46:11 - ras_commander.hdf.HdfResultsPlan - INFO - Final validated file path: C:\Users\billk_clb\anaconda3\envs\rascmdr_piptest\Lib\site-packages\examples\example_projects\Balde Eagle Creek_103\BaldEagle.p03.hdf



Simulation Duration: 431940.00 seconds
Computation Time: 0.03287 hours
Computation Speed: 3650.36 (simulation hours/compute hours)

Checking volume accounting...

Viewing Execution Summary with results_df

The results_df DataFrame shows which plans have been executed.

Python
# Display execution summary only for the plan run in this notebook (filtered and transposed)
print("Execution Summary (for current plan):")
ras.results_df.T
Text Only
Execution Summary (for current plan):
0 1 2
plan_number 01 02 03
plan_title Unsteady with Bridges and Dam Steady Flow Run Unsteady with Bridges and Dam clonedplan
flow_type Unsteady Steady Unsteady
hdf_path C:\Users\billk_clb\anaconda3\envs\rascmdr_pipt... C:\Users\billk_clb\anaconda3\envs\rascmdr_pipt... C:\Users\billk_clb\anaconda3\envs\rascmdr_pipt...
hdf_exists False False True
hdf_mtime NaT NaT 2026-01-11 20:46:10.766280
completed False False True
has_errors False False False
has_warnings False False False
error_count 0 0 0
warning_count 0 0 0
first_error_line None None None
rt_simulation_start NaT NaT 2023-01-01 00:00:00
rt_simulation_end NaT NaT 2023-01-05 23:59:00
rt_simulation_hours NaN NaN 119.983333
rt_complete_process_hours NaN NaN 0.032869
rt_unsteady_compute_hours NaN NaN 0.003038
rt_complete_process_speed NaN NaN 3650.361706
unsteady_time_of_maximum_stage NaN NaN None
unsteady_time_of_maximum_velocity NaN NaN None
unsteady_time_of_maximum_flow NaN NaN None
unsteady_computation_interval NaN NaN None
steady_solution NaN NaN NaN
vol_Error NaN NaN -12.049353
vol_Error_Percent NaN NaN 0.005847
vol_Total_Boundary_Flux_of_Water_In NaN NaN 196776.984375
vol_Total_Boundary_Flux_of_Water_Out NaN NaN 104118.132812
vol_Vol_Accounting_in NaN NaN Acre Feet
vol_Volume_Ending NaN NaN 101953.601562
vol_Volume_Starting NaN NaN 9306.797852

Deleting Plans, Geometries, and Flow Files

After working with cloned elements, you may want to clean up by deleting them. By default, all delete methods move files to a timestamped Backup/ folder instead of permanently deleting them. This provides a safety net for recovering accidentally deleted files.

The permanent deletion parameter can be used to skip the backup and permanently remove files.

Python
# First, let's clone fresh elements to demonstrate deletion
# (Our earlier clones may have been used for computation)
demo_plan = RasPlan.clone_plan("01", new_shortid="Delete Demo Plan")
demo_geom = RasPlan.clone_geom("01")
demo_unsteady = RasPlan.clone_unsteady("02")
print(f"Created demo plan: {demo_plan}")
print(f"Created demo geometry: {demo_geom}")
print(f"Created demo unsteady: {demo_unsteady}")
print()
print(f"Plan count before deletion: {len(ras.plan_df)}")
print(f"Geometry count before deletion: {len(ras.geom_df)}")
print(f"Unsteady count before deletion: {len(ras.unsteady_df)}")

# Delete the plan (default: backs up to Backup/ folder)
RasPlan.delete_plan(demo_plan)
print()
print(f"Plan count after deleting plan {demo_plan}: {len(ras.plan_df)}")

# Delete the geometry (default: backs up .g##, .g##.hdf, .c## to Backup/)
RasPlan.delete_geom(demo_geom, force=True)
print(f"Geometry count after deleting geom {demo_geom}: {len(ras.geom_df)}")

# Delete the unsteady flow (default: backs up to Backup/)
RasPlan.delete_unsteady(demo_unsteady, force=True)
print(f"Unsteady count after deleting unsteady {demo_unsteady}: {len(ras.unsteady_df)}")

# Show the Backup folder contents
backup_dir = ras.project_folder / "Backup"
if backup_dir.exists():
    print()
    print("Backup folder contents:")
    for folder in sorted(backup_dir.iterdir()):
        print(f"  {folder.name}/")
        for f in sorted(folder.iterdir()):
            print(f"    {f.name}")
Python
# Demonstrate permanent deletion (no backup)
perm_plan = RasPlan.clone_plan("01", new_shortid="Perm Delete Demo")
print(f"Created plan {perm_plan} for permanent deletion demo")

# Permanently delete - files are removed, not backed up
RasPlan.delete_plan(perm_plan)
print(f"Plan {perm_plan} permanently deleted (no backup created)")
print(f"Plan count after permanent deletion: {len(ras.plan_df)}")

HEC-RAS Plan File Structure Reference

Understanding plan file structure helps debug cloning operations:

Plan File (.p##) Components

Text Only
Proj Title=My Project
Plan Title=Baseline Run
Geom File=g01          # Links to geometry file
Flow File=f01          # Links to flow file
Run HTab=0             # Hydraulic tables flag
Run Unsteady=0         # Unsteady flow flag

HEC Documentation

  • HEC-RAS User's Manual - Chapter 3: Plan window and file management https://www.hec.usace.army.mil/software/hec-ras/documentation.aspx
  • HEC-RAS User's Manual - Chapter 5: Editing parameters

LLM Forward: Reviewable Modifications

When modifying plans programmatically, create comparison reports:

Python
def document_plan_changes(original_plan, modified_plan, output_file):
    # Document what changed between plans
    changes = []

    for param in ['Run HTab', 'Run Unsteady', 'Computation Interval']:
        orig_val = RasPlan.get_plan_value(original_plan, param)
        new_val = RasPlan.get_plan_value(modified_plan, param)

        if orig_val != new_val:
            changes.append({
                'parameter': param,
                'original': orig_val,
                'modified': new_val
            })

    # Export for review
    import pandas as pd
    df = pd.DataFrame(changes)
    df.to_csv(output_file, index=False)

    return df

# Usage
changes_df = document_plan_changes(
    "01",
    new_plan_number,
    project_folder / 'plan_modifications.csv'
)

This enables: - Change tracking: Know exactly what was modified - Peer review: Non-programmers can verify changes - Reproducibility: Document modifications for future reference

Summary of Plan and Geometry Operations

In this notebook, we've covered a comprehensive range of operations on HEC-RAS plan and geometry files using the RAS Commander library:

  1. Project Initialization: We initialized a HEC-RAS project to work with
  2. Plan Operations:
  3. Created a new plan by cloning an existing one
  4. Updated simulation parameters (dates, intervals, etc.)
  5. Set run flags for different components
  6. Updated the plan description
  7. Geometry Operations:
  8. Created a new geometry by cloning an existing one
  9. Associated the new geometry with our plan
  10. Cleared geometry preprocessor files
  11. Unsteady Flow Operations:
  12. Created a new unsteady flow file by cloning an existing one
  13. Associated it with our plan
  14. Computation and Verification:
  15. Computed our plan with the specified settings
  16. Verified the results using HDF entries
  17. Analyzed runtime statistics and volume accounting
  18. Deletion with Backup:
  19. Deleted cloned plans, geometries, and unsteady files
  20. Files moved to timestamped Backup/ folder by default
  21. Used permanent deletion for irreversible deletion

Key Classes and Functions Used

  • RasPlan: For plan operations (cloning, setting components, modifying parameters, and deletion)
  • RasGeo: For geometry operations (cloning, clearing preprocessor files)
  • RasCmdr: For executing HEC-RAS simulations

Next Steps

To further enhance your HEC-RAS automation, consider exploring:

  1. Parameter Sweeps: Create and run multiple plans with varying parameters
  2. Parallel Computations: Run multiple plans simultaneously using RasCmdr.compute_parallel()
  3. Advanced Results Analysis: Use the HDF classes to extract and analyze specific model results
  4. Spatial Visualization: Create maps and plots of simulation results
  5. Model Calibration: Automate comparison between model results and observations

The RAS Commander library provides a powerful framework for automating and streamlining your HEC-RAS workflows, enabling more efficient hydraulic modeling and analyses.

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.