Skip to content

Floodplain Mapping via GUI Automation

This notebook demonstrates floodplain mapping using HEC-RAS GUI automation to generate: - Maximum Water Surface Elevation (WSE) rasters - Maximum Depth rasters

The workflow is fully automated: HEC-RAS opens, computes the stored maps, and auto-closes when complete. No manual interaction is required.

How It Works

RasMap.postprocess_stored_maps() handles the full workflow: 1. Backs up plan and .rasmap files 2. Sets run flags to floodplain-mapping-only (skips simulation) 3. Configures stored map layers in .rasmap XML (creates RASResults layer if missing) 4. Opens HEC-RAS GUI and clicks Compute 5. Polls plan HDF for "Complete Process" signal to detect completion 6. Auto-closes HEC-RAS and restores original files

Comparison with RasProcess CLI (Notebook 601)

Method Speed GUI Required Best For
GUI Automation (this notebook) ~15 sec Yes (auto-managed) Debugging, visual verification
RasProcess CLI (notebook 601) ~8 sec No Production, batch processing

Prerequisites

  • HEC-RAS 6.x installed (provides GUI executable)
  • Windows operating system
  • Required packages: ras-commander, rasterio, matplotlib, pywin32
Python
# =============================================================================
# DEVELOPMENT MODE TOGGLE
# =============================================================================
USE_LOCAL_SOURCE = True  # <-- Set to True to use local ras-commander source

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")

from ras_commander import RasCmdr, RasExamples, RasMap, init_ras_project, ras

import rasterio
from rasterio.plot import show
import matplotlib.pyplot as plt
from pathlib import Path

import ras_commander
print(f"Loaded: {ras_commander.__file__}")
Text Only
LOCAL SOURCE MODE: Loading from <workspace>/ras_commander


Loaded: <workspace>\ras_commander\__init__.py

Parameters

Python
# =============================================================================
# PARAMETERS
# =============================================================================

PROJECT_NAME = "BaldEagleCrkMulti2D"
RAS_VERSION = "7.0"
PLAN = "06"  # Dam break plan

print(f"Project: {PROJECT_NAME}, Plan: {PLAN}")
Text Only
Project: BaldEagleCrkMulti2D, Plan: 06

Step 1: Extract Example Project and Initialize

Python
project_path = RasExamples.extract_project(PROJECT_NAME, suffix="600")
init_ras_project(project_path, RAS_VERSION)

print(f"Project: {ras.project_name}")
print(f"Folder: {ras.project_folder}")
print(f"\nPlans:")
print(ras.plan_df[['plan_number', 'Plan Title']].to_string())
Text Only
2026-06-11 17:03:52 - ras_commander.RasExamples - INFO - Successfully extracted project 'BaldEagleCrkMulti2D' to <workspace>\examples\example_projects\BaldEagleCrkMulti2D_600


2026-06-11 17:03:52 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 7.0 at <hec_ras_install>\7.0\Ras.exe via filesystem (x86)


2026-06-11 17:03:52 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.7 Beta 5 at <hec_ras_install>\6.7 Beta 5\Ras.exe via filesystem (x86)


2026-06-11 17:03:52 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.6 at <hec_ras_install>\6.6\Ras.exe via filesystem (x86)


2026-06-11 17:03:52 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.5 at <hec_ras_install>\6.5\Ras.exe via filesystem (x86)


2026-06-11 17:03:52 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.4.1 at <hec_ras_install>\6.4.1\Ras.exe via filesystem (x86)


2026-06-11 17:03:52 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.3.1 at <hec_ras_install>\6.3.1\Ras.exe via filesystem (x86)


2026-06-11 17:03:52 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.3 at <hec_ras_install>\6.3\Ras.exe via filesystem (x86)


2026-06-11 17:03:52 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.2 at <hec_ras_install>\6.2\Ras.exe via filesystem (x86)


2026-06-11 17:03:52 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.1 at <hec_ras_install>\6.1\Ras.exe via filesystem (x86)


2026-06-11 17:03:52 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.0 at <hec_ras_install>\6.0\Ras.exe via filesystem (x86)


2026-06-11 17:03:52 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 5.0.7 at <hec_ras_install>\5.0.7\Ras.exe via filesystem (x86)


2026-06-11 17:03:52 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 5.0.6 at <hec_ras_install>\5.0.6\Ras.exe via filesystem (x86)


2026-06-11 17:03:52 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 5.0.3 at <hec_ras_install>\5.0.3\Ras.exe via filesystem (x86)


2026-06-11 17:03:52 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 4.1.0 at <hec_ras_install>\4.1.0\Ras.exe via filesystem (x86)


2026-06-11 17:03:52 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 4.0 at <hec_ras_install>\4.0\Ras.exe via filesystem (x86)


2026-06-11 17:03:52 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.7 Beta 4a at <hec_ras_install>\6.7 Beta 4a\Ras.exe via filesystem (x86)


2026-06-11 17:03:52 - ras_commander.RasUtils - INFO - Discovered 16 installed HEC-RAS version(s)


2026-06-11 17:03:52 - ras_commander.RasPrj - INFO - HEC-RAS 7.0 found via version discovery: <hec_ras_install>\7.0\Ras.exe


2026-06-11 17:03:53 - ras_commander.RasMap - INFO - Successfully parsed RASMapper file: <workspace>\examples\example_projects\BaldEagleCrkMulti2D_600\BaldEagleDamBrk.rasmap


2026-06-11 17:03:53 - ras_commander.RasPrj - INFO - ras-commander v0.98.0 | An open-source project of CLB Engineering Corporation (https://clbengineering.com/) | Docs: https://rascommander.info | GitHub: https://github.com/gpt-cmdr/ras-commander


2026-06-11 17:03:53 - ras_commander.RasPrj - INFO - Project initialized: BaldEagleDamBrk | Folder: <workspace>\examples\example_projects\BaldEagleCrkMulti2D_600


2026-06-11 17:03:53 - ras_commander.RasPrj - INFO - Using HEC-RAS executable: <hec_ras_install>\7.0\Ras.exe


2026-06-11 17:03:53 - ras_commander.RasPrj - INFO - 
═══════════════════════════════════════════════════════════════════════
ras-commander | HEC-RAS Automation Library
Docs: https://rascommander.info/
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).
═══════════════════════════════════════════════════════════════════════


Project: BaldEagleDamBrk
Folder: <workspace>\examples\example_projects\BaldEagleCrkMulti2D_600

Plans:
   plan_number                               Plan Title
0           13                  PMF with Multi 2D Areas
1           15              1d-2D Dambreak Refined Grid
2           17                          2D to 1D No Dam
3           18                             2D to 2D Run
4           19                   SA to 2D Dam Break Run
5           03  Single 2D Area - Internal Dam Structure
6           04  SA to 2D Area Conn - 2D Levee Structure
7           02                 SA to Detailed 2D Breach
8           01             SA to Detailed 2D Breach FEQ
9           05          Single 2D area with Bridges FEQ
10          06            Gridded Precip - Infiltration

Step 2: Compute Plan (if needed)

GUI automation generates stored maps from existing HDF results. The plan must be computed first.

Python
hdf_path = ras.project_folder / f"{ras.project_name}.p{PLAN}.hdf"

if not hdf_path.exists():
    print(f"Computing plan {PLAN}...")
    RasCmdr.compute_plan(PLAN, num_cores=2)
    print(f"Plan {PLAN} complete.")
else:
    print(f"Plan {PLAN} already computed ({hdf_path.stat().st_size / (1024*1024):.1f} MB)")
Text Only
2026-06-11 17:03:53 - ras_commander.RasCmdr - INFO - Using ras_object with project folder: <workspace>\examples\example_projects\BaldEagleCrkMulti2D_600


2026-06-11 17:03:53 - ras_commander.RasUtils - INFO - Successfully updated file: <workspace>\examples\example_projects\BaldEagleCrkMulti2D_600\BaldEagleDamBrk.p06


Computing plan 06...


2026-06-11 17:03:53 - ras_commander.RasCmdr - INFO - Set number of cores to 2 for plan: 06


2026-06-11 17:03:53 - ras_commander.RasCmdr - INFO - Running HEC-RAS from the Command Line:


2026-06-11 17:03:53 - ras_commander.RasCmdr - INFO - Running command: "<hec_ras_install>\7.0\Ras.exe" -c "<workspace>\examples\example_projects\BaldEagleCrkMulti2D_600\BaldEagleDamBrk.prj" "<workspace>\examples\example_projects\BaldEagleCrkMulti2D_600\BaldEagleDamBrk.p06"


2026-06-11 17:03:53 - ras_commander.RasDialogWatchdog - INFO - DialogWatchdog started — polling every 1.5s for RAS dialog windows


2026-06-11 17:22:46 - ras_commander.RasCmdr - INFO - HEC-RAS execution completed for plan: 06


2026-06-11 17:22:46 - ras_commander.RasCmdr - INFO - Total run time for plan 06: 1132.87 seconds


2026-06-11 17:22:46 - ras_commander.RasDialogWatchdog - INFO - DialogWatchdog stopped — no dialogs encountered


Plan 06 complete.

Step 3: Generate Maps via GUI Automation

One function call handles everything: - Configures .rasmap with stored map layers - Sets plan flags to mapping-only (skips re-running the simulation) - Opens HEC-RAS, clicks Compute, monitors HDF for completion - Auto-closes HEC-RAS when maps are generated - Restores original plan and .rasmap files

Python
# Get available terrains
rasmap_path = ras.project_folder / f"{ras.project_name}.rasmap"
terrains = RasMap.get_terrain_names(rasmap_path)
print(f"Available terrains: {terrains}")

# Generate stored maps — HEC-RAS will open and auto-close
success = RasMap.postprocess_stored_maps(
    plan_number=PLAN,
    specify_terrain=terrains[0] if terrains else None,
    layers=['Depth', 'WSEL']
)

if success:
    print("\nSuccessfully generated stored maps via GUI automation")
else:
    print("\nFailed to generate stored maps")
Text Only
2026-06-11 17:22:46 - ras_commander.RasMap - INFO - Extracted terrain names: ['Terrain50']


2026-06-11 17:22:46 - ras_commander.RasMap - INFO - Checking .rasmap compatibility...


2026-06-11 17:22:46 - ras_commander.RasMap - INFO - .rasmap file is already compatible (version 2.0.0)


2026-06-11 17:22:46 - ras_commander.RasMap - INFO - .rasmap compatibility check passed: Already compatible (version 2.0.0)


2026-06-11 17:22:46 - ras_commander.RasMap - INFO - Backing up plan file <workspace>\examples\example_projects\BaldEagleCrkMulti2D_600\BaldEagleDamBrk.p06 to <workspace>\examples\example_projects\BaldEagleCrkMulti2D_600\BaldEagleDamBrk.p06.storedmap.bak


2026-06-11 17:22:46 - ras_commander.RasMap - INFO - Updating plan run flags for floodplain mapping for plan 06...


2026-06-11 17:22:46 - ras_commander.RasPlan - INFO - Successfully updated run flags in plan file: <workspace>\examples\example_projects\BaldEagleCrkMulti2D_600\BaldEagleDamBrk.p06 (flags modified: 4)


2026-06-11 17:22:46 - ras_commander.RasMap - INFO - Backing up rasmap file <workspace>\examples\example_projects\BaldEagleCrkMulti2D_600\BaldEagleDamBrk.rasmap to <workspace>\examples\example_projects\BaldEagleCrkMulti2D_600\BaldEagleDamBrk.rasmap.storedmap.bak


2026-06-11 17:22:46 - ras_commander.RasMap - INFO - Created new RASResults layer 'Gridded Precip - Infiltration' for plan 06 (none existed in .rasmap)


2026-06-11 17:22:46 - ras_commander.RasMap - INFO - Added 'Depth' stored map to results layer for plan 06.


2026-06-11 17:22:46 - ras_commander.RasMap - INFO - Added 'WSE' stored map to results layer for plan 06.


2026-06-11 17:22:46 - ras_commander.RasMap - INFO - Filtered terrains, keeping only 'Terrain50'.


2026-06-11 17:22:46 - ras_commander.RasMap - INFO - Using GUI automation to run floodplain mapping...


2026-06-11 17:22:46 - ras_commander.gui.workflows.open_compute - INFO - Setting current plan to 06 in project file...


2026-06-11 17:22:46 - ras_commander.RasPrj - INFO - Set current plan to p06 in <workspace>\examples\example_projects\BaldEagleCrkMulti2D_600\BaldEagleDamBrk.prj


2026-06-11 17:22:46 - ras_commander.gui.workflows.open_compute - INFO - Current plan set to 06 in <workspace>\examples\example_projects\BaldEagleCrkMulti2D_600\BaldEagleDamBrk.prj


2026-06-11 17:22:46 - ras_commander.gui.hecras_elements - INFO - Opening HEC-RAS...


2026-06-11 17:22:46 - ras_commander.gui.hecras_elements - INFO - HEC-RAS opened with Process ID: 9104


Available terrains: ['Terrain50']


2026-06-11 17:22:50 - ras_commander.gui.hecras_elements - INFO - Waiting for HEC-RAS main window...


2026-06-11 17:22:52 - ras_commander.gui.hecras_elements - INFO - Found HEC-RAS main window: HEC-RAS 7.0


2026-06-11 17:22:53 - ras_commander.gui.workflows.open_compute - INFO - Clicking 'Run > Unsteady Flow Analysis' menu...


2026-06-11 17:22:54 - ras_commander.gui.win32_primitives - INFO - Clicked menu item ID: 47


2026-06-11 17:22:56 - ras_commander.gui.workflows.open_compute - INFO - Looking for Unsteady Flow Analysis dialog...


2026-06-11 17:22:56 - ras_commander.gui.workflows.open_compute - INFO - Found dialog matching 'Unsteady Flow Analysis'


2026-06-11 17:22:56 - ras_commander.gui.workflows.open_compute - INFO - Found dialog window: 'Unsteady Flow Analysis'


2026-06-11 17:22:56 - ras_commander.gui.workflows.open_compute - INFO - Looking for Compute button...


2026-06-11 17:22:56 - ras_commander.gui.workflows.open_compute - WARNING - Could not find Compute button - trying keyboard shortcut...


2026-06-11 17:22:56 - ras_commander.gui.workflows.open_compute - INFO - Sent Enter key via win32api


2026-06-11 17:22:57 - ras_commander.gui.workflows.open_compute - INFO - Polling HDF for completion signal: BaldEagleDamBrk.p06.hdf


2026-06-11 17:23:09 - ras_commander.gui.workflows.open_compute - INFO - Detected 'Complete Process' in HDF — computation complete


2026-06-11 17:23:09 - ras_commander.gui.workflows.open_compute - INFO - Closing HEC-RAS...


2026-06-11 17:23:09 - ras_commander.gui.workflows.open_compute - INFO - HEC-RAS closed automatically after computation


2026-06-11 17:23:09 - ras_commander.RasMap - INFO - Floodplain mapping computation successful.


2026-06-11 17:23:09 - ras_commander.RasMap - INFO - Restoring original plan file from <workspace>\examples\example_projects\BaldEagleCrkMulti2D_600\BaldEagleDamBrk.p06.storedmap.bak


2026-06-11 17:23:09 - ras_commander.RasMap - INFO - Restoring original rasmap file from <workspace>\examples\example_projects\BaldEagleCrkMulti2D_600\BaldEagleDamBrk.rasmap.storedmap.bak



Successfully generated stored maps via GUI automation

Step 4: Verify Output Files

Python
# Find the output directory using Short Identifier from plan_df
plan_info = ras.plan_df[ras.plan_df['plan_number'] == PLAN].iloc[0]
short_id = plan_info.get('Short Identifier', f'Plan_{PLAN}')
output_folder = ras.project_folder / short_id

print(f"Output folder: {output_folder}")

if output_folder.exists():
    tif_files = sorted(output_folder.glob('*.tif'))
    vrt_files = sorted(output_folder.glob('*.vrt'))
    print(f"\nGenerated files:")
    for f in tif_files + vrt_files:
        print(f"  {f.name} ({f.stat().st_size / 1024:.1f} KB)")
else:
    print("Output folder not found — maps were not generated")
Text Only
Output folder: <workspace>\examples\example_projects\BaldEagleCrkMulti2D_600\Grid Precip Infiltration

Generated files:
  Depth (Max).Terrain50.dtm_20ft.tif (4952.5 KB)
  WSE (Max).Terrain50.dtm_20ft.tif (3546.9 KB)
  Depth (Max).vrt (3.3 KB)
  WSE (Max).vrt (3.0 KB)

Step 5: Visualize Results

Python
# Find depth and WSE TIF files
depth_tifs = sorted(output_folder.glob('Depth*.tif')) if output_folder.exists() else []
wse_tifs = sorted(output_folder.glob('WSE*.tif')) if output_folder.exists() else []

if depth_tifs:
    fig, axes = plt.subplots(1, 2, figsize=(16, 8))

    # Plot depth raster
    with rasterio.open(depth_tifs[0]) as src:
        show(src, ax=axes[0], cmap='Blues')
        axes[0].set_title(f'Max Depth - Plan {PLAN}')
        axes[0].set_xlabel('Easting')
        axes[0].set_ylabel('Northing')
        print(f"Depth raster: {src.width}x{src.height}, CRS: {src.crs}")

    # Plot WSE raster
    if wse_tifs:
        with rasterio.open(wse_tifs[0]) as src:
            show(src, ax=axes[1], cmap='terrain')
            axes[1].set_title(f'Max WSE - Plan {PLAN}')
            axes[1].set_xlabel('Easting')
            axes[1].set_ylabel('Northing')
            print(f"WSE raster: {src.width}x{src.height}, CRS: {src.crs}")

    plt.tight_layout()
    plt.show()
else:
    print("No depth rasters found for visualization")
Text Only
Depth raster: 6705x4852, CRS: EPSG:2271


WSE raster: 6705x4852, CRS: EPSG:2271

png

Technical Notes

Completion Detection

The GUI automation detects when floodplain mapping is complete by polling the plan HDF file: 1. Records the HDF modification time before launching HEC-RAS 2. After clicking Compute, polls every 2 seconds 3. When the HDF is modified AND contains "Complete Process" in compute messages, mapping is done 4. HEC-RAS is terminated automatically and backup files are restored

RASResults Layer Creation

Some example projects have an empty <Results /> section in their .rasmap file (no RASResults layers). The function automatically creates the required <Layer Type="RASResults"> XML element when one doesn't exist, referencing the plan's HDF file.

When to Use GUI vs RasProcess

  • GUI Automation (this notebook): Useful when you need to debug mapping issues or verify output visually in RASMapper. The HEC-RAS window is visible during computation.
  • RasProcess CLI (notebook 601): Faster, headless, recommended for production and batch workflows. No GUI window opens.