Skip to content

Advanced Structure Validation with RasCheck

This notebook demonstrates the advanced structure validation features added to RasCheck in December 2025:

  • Culvert hydraulics validation (CV_LF_01, CV_LF_02, CV_CF_01, CV_CF_02, CV_TF_04)
  • Starting WSE method validation (PF_IC_00, PF_IC_01, PF_IC_02, PF_IC_03, PF_IC_04)
Python
# =============================================================================
# DEVELOPMENT MODE TOGGLE
# =============================================================================
USE_LOCAL_SOURCE = True  # <-- Set to True for check module (in development)

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")
    print("⚠️  WARNING: Check module may not be available in pip package yet")

# Import ras-commander
from ras_commander import HdfPlan, HdfResultsPlan, HdfStruc, RasCheck, RasCmdr, RasExamples, init_ras_project, ras

# Verify which version loaded
import ras_commander
print(f"✓ Loaded: {ras_commander.__file__}")
Text Only
📁 LOCAL SOURCE MODE: Loading from <repo>/ras_commander


2026-06-11 19:13:55 - numexpr.utils - INFO - NumExpr defaulting to 8 threads.


✓ Loaded: <repo>\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 = "ConSpan Culvert"  # Steady flow culvert project (fast execution ~10 sec)
RAS_VERSION = "7.0"               # HEC-RAS version (6.3, 6.5, 6.6, etc.)
SUFFIX = "801"                    # Notebook identifier for project extraction

# Execution Settings
PLAN = "01"                       # Plan number to execute (will be updated based on available plans)
NUM_CORES = 4                     # CPU cores for 2D computation

# Note: All outputs are saved within the extracted project folder
print(f"Project will be extracted to: example_projects/{PROJECT_NAME}_{SUFFIX}/")
Text Only
Project will be extracted to: example_projects/ConSpan Culvert_801/

Import Required Modules

Python
from ras_commander import (
    RasExamples, init_ras_project, ras,
    RasCmdr, HdfResultsPlan
)
from ras_commander.hdf import HdfStruc, HdfPlan
from ras_commander.check import (
    RasCheck, CheckResults, Severity,
    RasCheckReport, ReportMetadata,
    get_default_thresholds
)

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from pathlib import Path

# Set pandas display options
pd.set_option('display.max_rows', 20)
pd.set_option('display.max_columns', None)
pd.set_option('display.width', None)

Extract and Initialize Project

We'll use the ConSpan Culvert example which is a steady flow project with culvert structures. This project executes quickly (~10 seconds) making it ideal for automated testing.

Verification for Structure Validation

After running structure validation checks:

  • [ ] All culvert flow classifications are reasonable (Inlet/Outlet control)
  • [ ] Bridge expansion coefficients < 0.5 (FHWA HDS-1 guidance)
  • [ ] Starting WSE within 0.5 ft of computed water surface
  • [ ] Structure geometry matches as-built dimensions

References: - FHWA HDS-1: Bridge Hydraulics - FHWA HDS-5: Culvert Hydraulics - USACE EM 1110-2-1416, Chapter 12: Hydraulic Structures

Python
# Extract the Bald Eagle Creek example project
project_path = RasExamples.extract_project(PROJECT_NAME, suffix=SUFFIX)
print(f"Extracted project to: {project_path}")
Text Only
2026-06-11 19:13:56 - ras_commander.RasExamples - INFO - Successfully extracted project 'ConSpan Culvert' to <repo>\examples\example_projects\ConSpan Culvert_801


Extracted project to: <repo>\examples\example_projects\ConSpan Culvert_801
Python
# Initialize the project
init_ras_project(project_path, RAS_VERSION)
print(f"Initialized project: {ras.project_name}")

# View available plans
print("\nAvailable plans:")
display(ras.plan_df[['plan_number', 'Plan Title', 'flow_type']])
Text Only
2026-06-11 19:13:56 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 7.0 at C:\Program Files (x86)\HEC\HEC-RAS\7.0\Ras.exe via filesystem (x86)


2026-06-11 19:13:56 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.7 Beta 5 at C:\Program Files (x86)\HEC\HEC-RAS\6.7 Beta 5\Ras.exe via filesystem (x86)


2026-06-11 19:13:56 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.7 Beta 4 at C:\Program Files (x86)\HEC\HEC-RAS\6.7 Beta 4\Ras.exe via filesystem (x86)


2026-06-11 19:13:56 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.6 at C:\Program Files (x86)\HEC\HEC-RAS\6.6\Ras.exe via filesystem (x86)


2026-06-11 19:13:56 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.5 at C:\Program Files (x86)\HEC\HEC-RAS\6.5\Ras.exe via filesystem (x86)


2026-06-11 19:13:56 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.4.1 at C:\Program Files (x86)\HEC\HEC-RAS\6.4.1\Ras.exe via filesystem (x86)


2026-06-11 19:13:56 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.3.1 at C:\Program Files (x86)\HEC\HEC-RAS\6.3.1\Ras.exe via filesystem (x86)


2026-06-11 19:13:56 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.3 at C:\Program Files (x86)\HEC\HEC-RAS\6.3\Ras.exe via filesystem (x86)


2026-06-11 19:13:56 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.2 at C:\Program Files (x86)\HEC\HEC-RAS\6.2\Ras.exe via filesystem (x86)


2026-06-11 19:13:57 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.1 at C:\Program Files (x86)\HEC\HEC-RAS\6.1\Ras.exe via filesystem (x86)


2026-06-11 19:13:57 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 6.0 at C:\Program Files (x86)\HEC\HEC-RAS\6.0\Ras.exe via filesystem (x86)


2026-06-11 19:13:57 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 5.0.7 at C:\Program Files (x86)\HEC\HEC-RAS\5.0.7\Ras.exe via filesystem (x86)


2026-06-11 19:13:57 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 5.0.6 at C:\Program Files (x86)\HEC\HEC-RAS\5.0.6\Ras.exe via filesystem (x86)


2026-06-11 19:13:57 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 5.0.5 at C:\Program Files (x86)\HEC\HEC-RAS\5.0.5\Ras.exe via filesystem (x86)


2026-06-11 19:13:57 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 5.0.4 at C:\Program Files (x86)\HEC\HEC-RAS\5.0.4\Ras.exe via filesystem (x86)


2026-06-11 19:13:57 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 5.0.3 at C:\Program Files (x86)\HEC\HEC-RAS\5.0.3\Ras.exe via filesystem (x86)


2026-06-11 19:13:57 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 5.0.1 at C:\Program Files (x86)\HEC\HEC-RAS\5.0.1\Ras.exe via filesystem (x86)


2026-06-11 19:13:57 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 5.0 at C:\Program Files (x86)\HEC\HEC-RAS\5.0\Ras.exe via filesystem (x86)


2026-06-11 19:13:57 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 4.1.0 at C:\Program Files (x86)\HEC\HEC-RAS\4.1.0\Ras.exe via filesystem (x86)


2026-06-11 19:13:57 - ras_commander.RasUtils - INFO - Discovered HEC-RAS 4.0 at C:\Program Files (x86)\HEC\HEC-RAS\4.0\Ras.exe via filesystem (x86)


2026-06-11 19:13:57 - ras_commander.RasUtils - INFO - Discovered 20 installed HEC-RAS version(s)


2026-06-11 19:13:57 - ras_commander.RasPrj - INFO - HEC-RAS 7.0 found via version discovery: C:\Program Files (x86)\HEC\HEC-RAS\7.0\Ras.exe


2026-06-11 19:13:57 - ras_commander.RasMap - INFO - Successfully parsed RASMapper file: <repo>\examples\example_projects\ConSpan Culvert_801\ConSpan.rasmap


2026-06-11 19:13:57 - ras_commander.RasPrj - WARNING - Could not resolve project CRS for <repo>\examples\example_projects\ConSpan Culvert_801


2026-06-11 19:13:57 - 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 19:13:57 - ras_commander.RasPrj - INFO - Project initialized: ConSpan | Folder: <repo>\examples\example_projects\ConSpan Culvert_801


2026-06-11 19:13:57 - ras_commander.RasPrj - INFO - Using HEC-RAS executable: C:\Program Files (x86)\HEC\HEC-RAS\7.0\Ras.exe


2026-06-11 19:13:57 - 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).
═══════════════════════════════════════════════════════════════════════


Initialized project: ConSpan

Available plans:
plan_number Plan Title flow_type
0 01 ConSpan Culvert Steady
1 02 Twin Circular Culverts Steady
Python
# Find a steady flow plan for structure validation
steady_plans = ras.plan_df[ras.plan_df['flow_type'] == 'Steady']

if steady_plans.empty:
    print("⚠️  No steady flow plans found - using first available plan")
    plan_number = ras.plan_df.iloc[0]['plan_number']
else:
    # Use plan 02 if available, otherwise first steady plan
    if '02' in steady_plans['plan_number'].values:
        plan_number = '02'
    else:
        plan_number = steady_plans.iloc[0]['plan_number']

print(f"Selected plan: {plan_number} ({ras.plan_df[ras.plan_df['plan_number']==plan_number].iloc[0]['flow_type']})")

# Execute the plan (skip if results already exist)
print(f"Running Plan {plan_number}...")
success = RasCmdr.compute_plan(plan_number, skip_existing=True)
if success:
    print(f"✓ Plan {plan_number} ready for validation")
else:
    print(f"✗ Plan {plan_number} execution failed")
Text Only
2026-06-11 19:13:57 - ras_commander.RasCmdr - INFO - Using ras_object with project folder: <repo>\examples\example_projects\ConSpan Culvert_801


2026-06-11 19:13:57 - ras_commander.RasCmdr - INFO - Running HEC-RAS from the Command Line:


2026-06-11 19:13:57 - ras_commander.RasCmdr - INFO - Running command: "C:\Program Files (x86)\HEC\HEC-RAS\7.0\Ras.exe" -c "<repo>\examples\example_projects\ConSpan Culvert_801\ConSpan.prj" "<repo>\examples\example_projects\ConSpan Culvert_801\ConSpan.p02"


2026-06-11 19:13:57 - ras_commander.RasDialogWatchdog - INFO - DialogWatchdog started — polling every 1.5s for RAS dialog windows


Selected plan: 02 (Steady)
Running Plan 02...


2026-06-11 19:13:59 - ras_commander.RasCmdr - INFO - HEC-RAS execution completed for plan: 02


2026-06-11 19:13:59 - ras_commander.RasCmdr - INFO - Total run time for plan 02: 2.27 seconds


2026-06-11 19:13:59 - ras_commander.RasDialogWatchdog - INFO - DialogWatchdog stopped — no dialogs encountered


2026-06-11 19:13:59 - ras_commander.hdf.HdfResultsPlan - ERROR - Error parsing simulation times: time data 'Unknown' does not match format '%d%b%Y %H:%M:%S'


✓ Plan 02 ready for validation
Python
# Display results summary from results_df
ras.results_df[['plan_number', 'plan_title', 'completed', 'has_errors', 'has_warnings', 'runtime_complete_process_hours']]
plan_number plan_title completed has_errors has_warnings runtime_complete_process_hours
0 01 ConSpan Culvert False False False NaN
1 02 Twin Circular Culverts True False False 0.000278
Python
# Get HDF paths with defensive checking
print(f"DEBUG: Looking for plan '{plan_number}'")
print(f"DEBUG: Available plan numbers: {ras.plan_df['plan_number'].tolist()}")

# Filter for the plan
filtered_plans = ras.plan_df[ras.plan_df['plan_number'] == plan_number]
print(f"DEBUG: Filtered result shape: {filtered_plans.shape}")

# Defensive check before accessing
if filtered_plans.empty:
    raise ValueError(
        f"Plan '{plan_number}' not found in project. "
        f"Available plans: {ras.plan_df['plan_number'].tolist()}"
    )

plan_row = filtered_plans.iloc[0]
plan_hdf = Path(plan_row['HDF_Results_Path'])

# Geometry HDF has .g##.hdf suffix (NOT .hdf replacing .g##)
geom_path = Path(plan_row['Geom Path'])
geom_hdf = Path(str(geom_path) + '.hdf')  # e.g., geometry.g01.hdf

print(f"Plan HDF: {plan_hdf}")
print(f"Geom HDF: {geom_hdf}")

# Verify files exist
if not plan_hdf.exists():
    print(f"⚠️  WARNING: Plan HDF not found: {plan_hdf}")
if not geom_hdf.exists():
    print(f"⚠️  WARNING: Geom HDF not found: {geom_hdf}")
Text Only
DEBUG: Looking for plan '02'
DEBUG: Available plan numbers: ['01', '02']
DEBUG: Filtered result shape: (1, 23)
Plan HDF: <repo>\examples\example_projects\ConSpan Culvert_801\ConSpan.p02.hdf
Geom HDF: <repo>\examples\example_projects\ConSpan Culvert_801\ConSpan.g02.hdf

Part 1: Culvert Hydraulics Extraction

The new HdfStruc.get_culvert_hydraulics() function extracts comprehensive culvert data from geometry HDF files.

Python
# Extract culvert hydraulic properties
culvert_data = HdfStruc.get_culvert_hydraulics(geom_hdf)

if not culvert_data.empty:
    print(f"Found {len(culvert_data)} culverts in geometry")
    print(f"\nColumns: {list(culvert_data.columns)}")
    display(culvert_data)
else:
    print("No culverts found in this project")
Text Only
2026-06-11 19:13:59 - ras_commander.hdf.HdfStruc - ERROR - Error reading culvert hydraulics from <repo>\examples\example_projects\ConSpan Culvert_801\ConSpan.g02.hdf: Cannot use .str.contains with values of inferred dtype 'bytes'.


No culverts found in this project

Culvert Hydraulics Data Fields

Field Description FHWA Reference
Structure_ID Unique culvert identifier -
Flow_Regime Flow regime setting (e.g., "Pressure and Weir Flow") HDS-5
Entrance_Coefficient Entrance loss coefficient (Ke) HDS-5 Table 1
Exit_Coefficient Exit loss coefficient (Kx) Typically 1.0
Scale_Factor Culvert scale factor -
Chart Chart selection for culvert analysis HDS-5

Reference: FHWA HDS-5 "Hydraulic Design of Highway Culverts"

Visualize Culvert Coefficients

Compare entrance and exit coefficients against FHWA guidelines:

Python
if not culvert_data.empty and 'Entrance_Coefficient' in culvert_data.columns:
    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))

    # Entrance coefficients
    ax1.barh(culvert_data['Structure_ID'], culvert_data['Entrance_Coefficient'], color='steelblue')
    ax1.axvline(0.2, color='red', linestyle='--', label='FHWA Min (0.2)')
    ax1.axvline(1.0, color='orange', linestyle='--', label='FHWA Max (1.0)')
    ax1.set_xlabel('Entrance Coefficient (Ke)')
    ax1.set_ylabel('Structure ID')
    ax1.set_title('Culvert Entrance Loss Coefficients')
    ax1.legend()
    ax1.grid(True, alpha=0.3)

    # Exit coefficients
    ax2.barh(culvert_data['Structure_ID'], culvert_data['Exit_Coefficient'], color='forestgreen')
    ax2.axvline(1.0, color='red', linestyle='--', label='Typical Value (1.0)')
    ax2.set_xlabel('Exit Coefficient (Kx)')
    ax2.set_ylabel('Structure ID')
    ax2.set_title('Culvert Exit Loss Coefficients')
    ax2.legend()
    ax2.grid(True, alpha=0.3)

    plt.tight_layout()
    plt.show()
else:
    print("No culvert coefficient data available for visualization")
Text Only
No culvert coefficient data available for visualization

Part 2: Culvert Validation Checks

RasCheck now includes 5 culvert validation checks:

Check ID Description Severity
CV_LF_01 Entrance loss coefficient out of FHWA range (0.2-1.0) WARNING
CV_LF_02 Exit loss coefficient deviates from typical (1.0) WARNING
CV_CF_01 Chart selection may not be appropriate WARNING
CV_CF_02 Flow regime classification questionable WARNING
CV_TF_04 Multiple barrel flow distribution issues WARNING
Python
# Extract steady profiles
profiles = HdfResultsPlan.get_steady_profile_names(plan_hdf)
print(f"Profiles: {profiles}")

# Run structure checks (includes culvert validation)
structure_results = RasCheck.check_structures(plan_hdf, geom_hdf, profiles)

print(f"Structure Check Results:")
print(f"  Total Messages: {len(structure_results.messages)}")
print(f"  Errors: {structure_results.get_error_count()}")
print(f"  Warnings: {structure_results.get_warning_count()}")
Text Only
2026-06-11 19:13:59 - ras_commander.hdf.HdfStruc - WARNING - Dataset not found: Geometry/Structures/Bridge Coefficient Attributes


2026-06-11 19:13:59 - ras_commander.hdf.HdfBase - CRITICAL - No valid projection found. Checked:
1. HDF file projection attribute: <repo>\examples\example_projects\ConSpan Culvert_801\ConSpan.g02.hdf
2. No RASMapper projection file found
To fix this:
1. Open RASMapper
2. Click Map > Set Projection
3. Select an appropriate projection file or coordinate system
4. Save the RASMapper project


2026-06-11 19:13:59 - ras_commander.hdf.HdfStruc - WARNING - Bridge Coefficient Attributes missing or 'Structure ID' not present.


Profiles: ['5 yr', '10 yr', '25 yr', '50 yr']
Structure Check Results:
  Total Messages: 3
  Errors: 0
  Warnings: 3
Python
# Filter for culvert-specific messages (CV_ prefix)
culvert_msgs = [msg for msg in structure_results.messages if msg.message_id.startswith('CV_')]

if culvert_msgs:
    print(f"Found {len(culvert_msgs)} culvert validation messages:\n")
    for msg in culvert_msgs:
        print(f"[{msg.severity.value}] {msg.message_id}: {msg.message}")
        if msg.help_text:
            print(f"  → {msg.help_text}")
        print()
else:
    print("✓ No culvert validation issues found")
Text Only
✓ No culvert validation issues found

Culvert Check Details

CV_LF_01: Entrance Loss Coefficient

What it checks: Entrance loss coefficients (Ke) should be within FHWA guidelines (0.2 to 1.0)

Why it matters: - Too low (<0.2): Underestimates entrance losses, overpredicts capacity - Too high (>1.0): Overestimates losses, underpredicts capacity

FHWA Reference: HDS-5 Table 1 - Entrance Loss Coefficients

CV_LF_02: Exit Loss Coefficient

What it checks: Exit loss coefficients (Kx) typically should be 1.0

Why it matters: Exit losses represent full velocity head recovery. Values other than 1.0 should be justified.

CV_CF_01 & CV_CF_02: Chart and Flow Regime

What it checks: Appropriate chart selection and flow regime classification

Why it matters: Using the wrong chart or flow regime leads to incorrect culvert performance predictions.

CV_TF_04: Multiple Barrel Distribution

What it checks: Flow distribution among multiple barrels

Why it matters: Unequal flow distribution can cause unexpected hydraulic behavior.


Part 3: Starting WSE Method Extraction

The new HdfPlan.get_starting_wse_method() function extracts initial condition methods from plan HDF files.

Python
# Extract starting WSE method
wse_method = HdfPlan.get_starting_wse_method(plan_hdf)

print("Starting Water Surface Elevation Method:")
print("="*50)
for key, value in wse_method.items():
    print(f"  {key}: {value}")
Text Only
2026-06-11 19:13:59 - ras_commander.hdf.HdfPlan - WARNING - Starting WSE method not found in <repo>\examples\example_projects\ConSpan Culvert_801\ConSpan.p02.hdf


Starting Water Surface Elevation Method:
==================================================
  method: Unknown
  note: Boundary condition method not found in HDF file

Starting WSE Methods Explained

Method When to Use Parameters
Normal Depth Subcritical flow, mild slope Requires friction slope
Critical Depth Supercritical flow (Fr > 1.0) None
Known WSE Specific boundary elevation available Requires WSE value
EGL Slope Line Gradually varied flow Requires energy slope

Note: The starting WSE method applies at the downstream boundary for steady flow computations.

Python
# Visualize method parameters if applicable
method = wse_method.get('method', 'Unknown')

if 'Normal' in method and 'slope' in wse_method:
    slope = wse_method['slope']
    print(f"\nNormal Depth Analysis:")
    print(f"  Friction Slope: {slope:.6f}")
    print(f"  Slope as ratio: 1:{1/slope:.0f}" if slope > 0 else "  Slope: Invalid")

    # Check reasonableness
    if abs(slope) < 0.0001:
        print("  ⚠️  WARNING: Very flat slope - may cause convergence issues")
    elif abs(slope) > 0.1:
        print("  ⚠️  WARNING: Very steep slope - verify this is correct")
    else:
        print("  ✓ Slope appears reasonable")

elif 'Known' in method and 'wse' in wse_method:
    wse_value = wse_method['wse']
    print(f"\nKnown WSE Analysis:")
    print(f"  Specified WSE: {wse_value:.2f} ft")

    # Check reasonableness
    if wse_value < -100 or wse_value > 10000:
        print("  ⚠️  WARNING: WSE may be unreasonable for this project")
    else:
        print("  ✓ WSE appears reasonable")

Part 4: Starting WSE Validation Checks

RasCheck now includes 4 starting WSE validation checks:

Check ID Description Severity
PF_IC_00 Starting WSE method could not be determined WARNING
PF_IC_01 Known WSE may be unreasonable WARNING
PF_IC_02 Normal depth slope may cause convergence issues WARNING
PF_IC_03 Critical depth used (informational) INFO
PF_IC_04 EGL slope method used (informational) INFO
Python
# Run profile checks (includes starting WSE validation)
profile_results = RasCheck.check_profiles(plan_hdf, profiles)

print(f"Profile Check Results:")
print(f"  Total Messages: {len(profile_results.messages)}")
print(f"  Errors: {profile_results.get_error_count()}")
print(f"  Warnings: {profile_results.get_warning_count()}")
print(f"  Info: {len([m for m in profile_results.messages if m.severity == Severity.INFO])}")
Text Only
Profile Check Results:
  Total Messages: 127
  Errors: 0
  Warnings: 100
  Info: 27
Python
# Filter for starting WSE messages (PF_IC_ prefix)
wse_msgs = [msg for msg in profile_results.messages if msg.message_id.startswith('PF_IC_')]

if wse_msgs:
    print(f"Found {len(wse_msgs)} starting WSE validation messages:\n")
    for msg in wse_msgs:
        print(f"[{msg.severity.value}] {msg.message_id}: {msg.message}")
        if msg.help_text:
            print(f"  → {msg.help_text}")
        print()
else:
    print("✓ No starting WSE validation issues found")
Text Only
✓ No starting WSE validation issues found

Starting WSE Check Details

PF_IC_01: Known WSE Range

What it checks: Known WSE values should be within realistic range (-100 to 10,000 ft)

Why it matters: Extreme values likely indicate data entry errors.

PF_IC_02: Normal Depth Slope

What it checks: - Very flat slopes (<0.0001) may cause convergence problems - Very steep slopes (>0.1) are unusual and should be verified

Why it matters: Inappropriate slopes lead to computational instability or incorrect boundary conditions.

PF_IC_03: Critical Depth Appropriateness

What it checks: Critical depth is appropriate when Froude number > 1.0 (supercritical flow)

Why it matters: Using critical depth for subcritical flow is incorrect.

PF_IC_04: EGL Method Verification

What it checks: Energy grade line method is appropriate for gradually varied flow

Why it matters: Verifies boundary condition method matches flow regime.


Part 5: Comprehensive Validation Report

Generate a complete validation report including all new checks:

Python
# Run all checks
all_results = RasCheck.run_all(plan_number)

print("Complete Validation Results:")
print("="*50)
print(f"  Total Messages: {len(all_results.messages)}")
print(f"  Errors: {all_results.get_error_count()}")
print(f"  Warnings: {all_results.get_warning_count()}")
print(f"  Info: {len([m for m in all_results.messages if m.severity == Severity.INFO])}")
Text Only
2026-06-11 19:13:59 - ras_commander.check.RasCheck - INFO - Detected flow type: steady


2026-06-11 19:13:59 - ras_commander.check.check_nt - WARNING - Could not check structure transition coefficients: could not convert string to float: '20.208*'


2026-06-11 19:13:59 - ras_commander.hdf.HdfStruc - WARNING - Dataset not found: Geometry/Structures/Bridge Coefficient Attributes


2026-06-11 19:13:59 - ras_commander.hdf.HdfBase - CRITICAL - No valid projection found. Checked:
1. HDF file projection attribute: <repo>\examples\example_projects\ConSpan Culvert_801\ConSpan.g02.hdf
2. No RASMapper projection file found
To fix this:
1. Open RASMapper
2. Click Map > Set Projection
3. Select an appropriate projection file or coordinate system
4. Save the RASMapper project


2026-06-11 19:13:59 - ras_commander.hdf.HdfStruc - WARNING - Bridge Coefficient Attributes missing or 'Structure ID' not present.


2026-06-11 19:13:59 - ras_commander.check.check_nt - INFO - Checking HTAB parameters for 10 cross sections


2026-06-11 19:13:59 - ras_commander.geom.GeomCrossSection - INFO - Extracted HTAB params for Spring Creek/Culvrt Reach/RS 20.535: has_htab_lines=False, starting_el=None, increment=None, num_points=None


2026-06-11 19:13:59 - ras_commander.geom.GeomCrossSection - INFO - Extracted HTAB params for Spring Creek/Culvrt Reach/RS 20.422: has_htab_lines=False, starting_el=None, increment=None, num_points=None


2026-06-11 19:13:59 - ras_commander.geom.GeomCrossSection - INFO - Extracted HTAB params for Spring Creek/Culvrt Reach/RS 20.308: has_htab_lines=False, starting_el=None, increment=None, num_points=None


2026-06-11 19:13:59 - ras_commander.geom.GeomCrossSection - INFO - Extracted HTAB params for Spring Creek/Culvrt Reach/RS 20.251: has_htab_lines=False, starting_el=None, increment=None, num_points=None


2026-06-11 19:13:59 - ras_commander.geom.GeomCrossSection - INFO - Extracted HTAB params for Spring Creek/Culvrt Reach/RS 20.238: has_htab_lines=False, starting_el=None, increment=None, num_points=None


2026-06-11 19:13:59 - ras_commander.geom.GeomCrossSection - INFO - Extracted HTAB params for Spring Creek/Culvrt Reach/RS 20.227: has_htab_lines=False, starting_el=None, increment=None, num_points=None


2026-06-11 19:13:59 - ras_commander.geom.GeomCrossSection - INFO - Extracted HTAB params for Spring Creek/Culvrt Reach/RS 20.208*: has_htab_lines=False, starting_el=None, increment=None, num_points=None


2026-06-11 19:13:59 - ras_commander.geom.GeomCrossSection - INFO - Extracted HTAB params for Spring Creek/Culvrt Reach/RS 20.189: has_htab_lines=False, starting_el=None, increment=None, num_points=None


2026-06-11 19:13:59 - ras_commander.geom.GeomCrossSection - INFO - Extracted HTAB params for Spring Creek/Culvrt Reach/RS 20.095: has_htab_lines=False, starting_el=None, increment=None, num_points=None


2026-06-11 19:13:59 - ras_commander.geom.GeomCrossSection - INFO - Extracted HTAB params for Spring Creek/Culvrt Reach/RS 20.000: has_htab_lines=False, starting_el=None, increment=None, num_points=None


2026-06-11 19:13:59 - ras_commander.check.check_nt - INFO - HTAB check complete: 0 issues found (0 errors, 0 warnings)


2026-06-11 19:13:59 - ras_commander.check.check_nt - INFO - Checking structure HTAB parameters for 1 structures


2026-06-11 19:13:59 - ras_commander.check.check_nt - INFO - Structure HTAB check complete: 0 info items found


Complete Validation Results:
==================================================
  Total Messages: 168
  Errors: 0
  Warnings: 127
  Info: 41
Python
# Show new check coverage
new_check_ids = ['CV_LF_01', 'CV_LF_02', 'CV_CF_01', 'CV_CF_02', 'CV_TF_04',
                 'PF_IC_00', 'PF_IC_01', 'PF_IC_02', 'PF_IC_03', 'PF_IC_04']

new_checks_found = [msg for msg in all_results.messages if msg.message_id in new_check_ids]

print(f"\nNew Advanced Validation Checks (9 total):")
print(f"  Messages from new checks: {len(new_checks_found)}")

if new_checks_found:
    print("\n  Check IDs triggered:")
    for check_id in set(msg.message_id for msg in new_checks_found):
        count = len([m for m in new_checks_found if m.message_id == check_id])
        print(f"    {check_id}: {count} message(s)")
Text Only
New Advanced Validation Checks (9 total):
  Messages from new checks: 0
Python
# Generate HTML report
report_path = project_path / "ras_checker" / "advanced_validation_report.html"
report_path.parent.mkdir(parents=True, exist_ok=True)

metadata = ReportMetadata(
    project_name=ras.project_name,
    project_path=project_path,
    plan_name="Steady Flow with Advanced Checks"
)

output_path = all_results.to_html(report_path, metadata=metadata)
print(f"\n✓ HTML report generated: {output_path}")
Text Only
2026-06-11 19:13:59 - ras_commander.check.report - INFO - Generated HTML report: <repo>\examples\example_projects\ConSpan Culvert_801\ras_checker\advanced_validation_report.html



✓ HTML report generated: <repo>\examples\example_projects\ConSpan Culvert_801\ras_checker\advanced_validation_report.html

Summary

This notebook demonstrated the 9 new validation checks added to RasCheck:

Culvert Checks (5)

  • CV_LF_01: Entrance loss coefficient validation
  • CV_LF_02: Exit loss coefficient validation
  • CV_CF_01: Chart selection appropriateness
  • CV_CF_02: Flow regime classification
  • CV_TF_04: Multiple barrel flow distribution

Starting WSE Checks (4)

  • PF_IC_00: Method determination
  • PF_IC_01: Known WSE reasonableness
  • PF_IC_02: Normal depth slope validation
  • PF_IC_03: Critical depth applicability
  • PF_IC_04: EGL method verification

New HDF Extraction Functions

  • HdfStruc.get_culvert_hydraulics() - Extract comprehensive culvert data
  • HdfPlan.get_starting_wse_method() - Extract initial condition method
  • 300_quality_assurance_rascheck.ipynb - Comprehensive RasCheck overview
  • 302_custom_workflows_and_standards.ipynb - State-specific standards and custom workflows