Skip to content

Validating RAS Mapper Layers and Terrain Files

Validation Framework

This notebook demonstrates the ras-commander validation framework for pre-flight checks and data quality assurance. The framework uses three core classes:

  • ValidationSeverity: Severity levels (INFO < WARNING < ERROR < CRITICAL)
  • ValidationResult: Single validation check result
  • ValidationReport: Aggregation of multiple validation results

Why Validation Matters: - Catch errors before expensive HEC-RAS execution - Ensure data quality for reliable results - Document assumptions and limitations - Enable graceful degradation when optional data missing

Reference

  • Validation Patterns: .claude/rules/validation/validation-patterns.md
  • RasMap API: ras_commander/RasMap.py (validation methods)
  • FEMA Data Capture Standards

LLM Forward Principle

Validation creates audit trail before execution: 1. Pre-flight checks documented: All validation results logged 2. Data quality issues flagged: Warnings visible to reviewers 3. Graceful degradation: System continues with reduced functionality when appropriate

Professional Context: Validation is not a substitute for engineering judgment. Use validation to identify issues, then apply professional expertise to determine appropriate actions.

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

USE_LOCAL_SOURCE = True  # <-- TOGGLE THIS (set to True for local development)

# -----------------------------------------------------------------------------
if USE_LOCAL_SOURCE:
    import sys
    from pathlib import Path
    local_path = str(Path.cwd().parent)  # Parent of examples/ = repo root
    if local_path not in sys.path:
        sys.path.insert(0, local_path)  # Insert at position 0 = highest priority
    print(f"📁 LOCAL SOURCE MODE: Loading from {local_path}/ras_commander")
else:
    print("📦 PIP PACKAGE MODE: Loading installed ras-commander")

# Import ras-commander (will use local or pip based on toggle above)
from ras_commander import RasExamples, RasMap, ValidationSeverity, ras

# Verify which version loaded
import ras_commander
print(f"✓ Loaded: {ras_commander.__file__}")

Understanding Severity Levels

ValidationSeverity Classification:

INFO - Informational (operation proceeds normally): - File metadata (size, format, creation date) - Successful validation checks - Data statistics and summaries

WARNING - Non-critical issue (operation may succeed): - Large files (performance impact) - Data extends beyond expected range - Missing optional datasets - Unusual but valid configurations

ERROR - Critical issue (operation will likely fail): - Required files not found - Invalid data format - Missing required datasets - Coordinate reference system undefined

CRITICAL - Blocking issue (cannot proceed): - File corrupted or unreadable - Incompatible file formats - Security violations

Decision Matrix:

Python
report = RasMap.check_layer(terrain_file)

if report.is_valid:
    # No ERROR or CRITICAL - safe to proceed
    execute_mapping()
elif report.has_warnings:
    # Warnings only - proceed with caution
    logger.warning("Quality issues detected - review before use")
    execute_mapping()
else:
    # Errors or critical - cannot proceed
    logger.error("Validation failed - fix issues before proceeding")
    report.print_report(show_passed=False)
    raise ValueError("Invalid terrain layer")

Validation Best Practices

1. Pre-Flight Checks Always validate inputs before expensive operations:

Python
# Validate terrain before mapping
report = RasMap.check_layer(terrain_file, layer_type='terrain')
if not report.is_valid:
    print("❌ Terrain validation failed - fix before mapping")
    report.print_report(show_passed=False)
    sys.exit(1)

# Proceed with mapping
execute_mapping(terrain_file)

2. Detailed vs Boolean Methods - Detailed (check_*): Returns ValidationResult/ValidationReport with full diagnostics - Boolean (is_valid_*): Returns True/False for simple checks

Use detailed when you need diagnostics, boolean for simple pass/fail.

3. Graceful Degradation

Python
# Optional land cover layer
if RasMap.is_valid_layer(land_cover_file):
    print("✓ Using land cover for Manning's n")
    roughness = compute_from_land_cover(land_cover_file)
else:
    print("⚠️ Land cover invalid - using default Manning's n")
    roughness = default_mannings_n

4. Document Assumptions Always log validation results for audit trail:

Python
report = RasMap.check_layer(terrain_file)
report.print_report()  # Document all checks, not just failures

# Save to file for professional review
with open('validation_report.txt', 'w') as f:
    f.write(str(report))

Professional Review Checklist

  • [ ] All input layers validated before use
  • [ ] Validation reports saved for review
  • [ ] Warnings reviewed and dispositioned
  • [ ] Errors fixed or exceptions documented
  • [ ] Assumptions clearly stated
  • [ ] Graceful degradation documented (if applicable)

Parameters

Configure these values to customize the notebook for your project.

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

# Project Configuration
PROJECT_NAME = "BaldEagleCrkMulti2D"           # Example project to extract
RAS_VERSION = "7.0"               # HEC-RAS version (6.3, 6.5, 6.6, etc.)

# HDF Analysis Settings
PLAN = "01"                       # Plan number (for HDF file path)
TIME_INDEX = -1                   # Time step index (-1 = last)
PROFILE = "Max"                   # Profile name for steady analysis

Overview

This notebook demonstrates the RAS Mapper layer validation framework in ras-commander. RAS Mapper uses various geospatial layers (terrain, land cover, boundaries) to visualize and configure HEC-RAS models. Validating these layers ensures:

  • Files exist and are readable
  • Formats are supported (GeoJSON, Shapefile, GeoTIFF, HDF)
  • Coordinate reference systems (CRS) are defined
  • Raster metadata is valid
  • Spatial extents cover the model domain

The validation framework provides: - Format validation - CRS validation - Raster metadata checks - Spatial extent verification - Specialized terrain and land cover validation - Comprehensive validation reports

We'll use the Muncie example project which includes RAS Mapper layers.


Extract Example Project

Python
# Extract example project (contains RAS Mapper configuration)
project_path = RasExamples.extract_project(PROJECT_NAME)
print(f"\nProject extracted to: {project_path}")
Python
# Find geospatial files in the project
from pathlib import Path

# Common geospatial file extensions
geo_extensions = ['*.tif', '*.tiff', '*.shp', '*.geojson', '*.json', '*.hdf', '*.h5']

geo_files = []
for pattern in geo_extensions:
    geo_files.extend(project_path.glob(pattern))
    # Also check subdirectories
    geo_files.extend(project_path.glob(f"*/{pattern}"))
    geo_files.extend(project_path.glob(f"*/*/{pattern}"))

print(f"Found {len(geo_files)} geospatial file(s):")
for geo_file in geo_files[:10]:  # Show first 10
    size_kb = geo_file.stat().st_size / 1024
    print(f"  - {geo_file.relative_to(project_path)} ({size_kb:.2f} KB)")
if len(geo_files) > 10:
    print(f"  ... and {len(geo_files) - 10} more")

3. Discover Registered RASMapper Layers

rasmap_df is a compact project summary: it keeps terrain, land-cover, soils, and infiltration paths in list-valued columns so a whole project fits on one row. The layer-list methods below are more discoverable for QA/QC workflows because they return one row per registered .rasmap layer, including the layer name users see in RAS Mapper, the source filename, the resolved path, and available display/selection metadata.

Python
rasmap_files = list(project_path.glob("*.rasmap"))
rasmap_file = rasmap_files[0] if rasmap_files else None

if rasmap_file:
    print(f"Reading layer catalog from: {rasmap_file.name}")
    compact_rasmap_df = RasMap.parse_rasmap(rasmap_file)

    terrain_layers = RasMap.list_terrain_layers(project_path)
    land_classification_layers = RasMap.list_land_classification_layers(project_path)
    landcover_layers = RasMap.list_landcover_layers(project_path)
    soils_layers = RasMap.list_soils_layers(project_path)
    infiltration_layers = RasMap.list_infiltration_layers(project_path)

    print("\nCompact project summary columns:")
    display(compact_rasmap_df[[
        "terrain_hdf_path",
        "landcover_hdf_path",
        "soil_layer_path",
        "infiltration_hdf_path",
    ]])

    print("\nTerrain layers registered in RASMapper:")
    display(terrain_layers[[
        "name",
        "filename",
        "resolved_path",
        "checked",
        "type",
        "resample_method",
        "surface_on",
    ]])

    print("\nAll land-classification layers registered in RASMapper:")
    display(land_classification_layers[[
        "name",
        "classification_kind",
        "filename",
        "resolved_path",
        "checked",
        "selected_parameter",
    ]])

    print("\nFiltered wrappers for workflow-specific discovery:")
    print(f"  land cover:   {len(landcover_layers)} layer(s)")
    print(f"  soils:        {len(soils_layers)} layer(s)")
    print(f"  infiltration: {len(infiltration_layers)} layer(s)")
else:
    print("No .rasmap file found for this example project.")
Python
# Look for terrain files specifically
terrain_files = [f for f in geo_files if 'terrain' in f.name.lower() or f.suffix.lower() in ['.tif', '.tiff']]

if terrain_files:
    test_terrain_file = terrain_files[0]
    print(f"Using terrain file: {test_terrain_file.name}")
else:
    print("⚠️ No terrain files found - will use synthetic examples")
    test_terrain_file = project_path / "terrain.tif"  # For examples

1. Format Validation: check_layer_format()

Validates that layer files exist, are readable, and have supported formats.

Python
# Example 1: Valid terrain file (GeoTIFF)
if terrain_files:
    result = RasMap.check_layer_format(test_terrain_file)
    print(f"File: {test_terrain_file.name}")
    print(f"Result: {result}")
    print(f"\nDetails:")
    for key, value in result.details.items():
        print(f"  {key}: {value}")
Python
# Example 2: Check various file types
file_types_to_check = {
    'GeoTIFF': [f for f in geo_files if f.suffix.lower() in ['.tif', '.tiff']],
    'Shapefile': [f for f in geo_files if f.suffix.lower() == '.shp'],
    'GeoJSON': [f for f in geo_files if f.suffix.lower() in ['.geojson', '.json']],
    'HDF': [f for f in geo_files if f.suffix.lower() in ['.hdf', '.h5']]
}

print("Format validation by file type:\n")
for file_type, files in file_types_to_check.items():
    if files:
        test_file = files[0]
        result = RasMap.check_layer_format(test_file)
        status = "✓" if result.passed else "✗"
        print(f"{status} {file_type}: {test_file.name}")
        print(f"  {result.message}")
        if result.severity == ValidationSeverity.WARNING:
            print(f"  ⚠️ {result.severity.value.upper()}")
        print()
Python
# Example 3: Invalid file (doesn't exist)
nonexistent_file = project_path / "missing_terrain.tif"

result = RasMap.check_layer_format(nonexistent_file)
print(f"File: {nonexistent_file.name}")
print(f"Result: {result}")
print(f"Passed: {result.passed}")
print(f"Severity: {result.severity.value}")

2. CRS Validation: check_layer_crs()

Validates coordinate reference system and checks compatibility with project CRS.

Python
# Example 1: Check terrain CRS
if terrain_files:
    result = RasMap.check_layer_crs(test_terrain_file)
    print(f"File: {test_terrain_file.name}")
    print(f"Result: {result}")
    print(f"\nDetails:")
    for key, value in result.details.items():
        print(f"  {key}: {value}")
Python
# Example 2: Check CRS compatibility with expected projection
if terrain_files:
    # First, get the CRS from the terrain file
    result1 = RasMap.check_layer_crs(test_terrain_file)

    if result1.passed and 'crs' in result1.details:
        terrain_crs = result1.details['crs']
        print(f"Terrain CRS: {terrain_crs}")

        # Extract EPSG code as integer (e.g., "EPSG:2965" -> 2965)
        epsg_code = None
        if terrain_crs and terrain_crs.startswith("EPSG:"):
            try:
                epsg_code = int(terrain_crs.split(":")[1])
            except (ValueError, IndexError):
                pass

        # Check if another file matches
        if len(geo_files) > 1 and epsg_code:
            other_file = [f for f in geo_files if f != test_terrain_file][0]
            result2 = RasMap.check_layer_crs(other_file, expected_epsg=epsg_code)

            print(f"\nComparing with: {other_file.name}")
            print(f"Result: {result2}")
            if result2.passed:
                print("  CRS matches terrain file")
            else:
                print("  CRS mismatch - may need reprojection")

3. Raster Metadata: check_raster_metadata()

Validates raster-specific properties (dimensions, resolution, no-data values).

Python
# Example 1: Check terrain raster metadata
if terrain_files:
    results = RasMap.check_raster_metadata(test_terrain_file)
    print(f"File: {test_terrain_file.name}")
    print(f"Number of checks: {len(results)}")
    print(f"\nResults:")
    for result in results:
        status = "PASS" if result.passed else "FAIL"
        print(f"  [{status}] {result.check_name}: {result.message}")
        if result.details:
            for key, value in result.details.items():
                print(f"      {key}: {value}")
Python
# Example 2: Check multiple raster files
raster_files = [f for f in geo_files if f.suffix.lower() in ['.tif', '.tiff']]

if raster_files:
    print(f"Raster metadata for {len(raster_files)} file(s):\n")

    for raster_file in raster_files[:3]:  # Check first 3
        results = RasMap.check_raster_metadata(raster_file)
        print(f"File: {raster_file.name}")

        # Extract key metrics from results
        for result in results:
            if result.check_name == 'resolution_check' and result.details:
                print(f"  Resolution: {result.details.get('resolution', 'N/A')} meters")
            elif result.check_name == 'nodata_check' and result.details:
                print(f"  No-data: {result.details.get('nodata_percent', 'N/A'):.1f}%")
            elif result.check_name == 'extent_info' and result.details:
                bounds = result.details.get('bounds')
                if bounds:
                    print(f"  Extent: {bounds[0]:.2f}, {bounds[1]:.2f} to {bounds[2]:.2f}, {bounds[3]:.2f}")
        print()

4. Spatial Extent: check_spatial_extent()

Validates spatial coverage and checks overlap with expected domain.

Python
# Example 1: Check terrain spatial extent
# First we need to get the layer's bounds to establish a model extent
if terrain_files:
    import rasterio

    # Get bounds of the terrain file
    with rasterio.open(test_terrain_file) as src:
        terrain_bounds = src.bounds
        model_extent = (terrain_bounds.left, terrain_bounds.bottom, 
                       terrain_bounds.right, terrain_bounds.top)

    print(f"File: {test_terrain_file.name}")
    print(f"Model extent (from terrain): {model_extent}")

    # Now check spatial extent with that as the reference
    result = RasMap.check_spatial_extent(test_terrain_file, model_extent)
    print(f"\nResult: {result}")
    print(f"\nDetails:")
    for key, value in result.details.items():
        print(f"  {key}: {value}")
Python
# Example 2: Check coverage overlap between layers
if len(geo_files) >= 2 and terrain_files:
    import rasterio

    # Use terrain as the model extent reference
    with rasterio.open(test_terrain_file) as src:
        terrain_bounds = src.bounds
        model_extent = (terrain_bounds.left, terrain_bounds.bottom,
                       terrain_bounds.right, terrain_bounds.top)

    file1 = test_terrain_file
    file2 = [f for f in geo_files if f != test_terrain_file][0]

    print(f"Checking overlap:\n")
    print(f"Reference (model extent from terrain): {test_terrain_file.name}")
    print(f"  Bounds: minx={model_extent[0]:.2f}, miny={model_extent[1]:.2f}, maxx={model_extent[2]:.2f}, maxy={model_extent[3]:.2f}")

    # Check if second file overlaps with model extent
    result = RasMap.check_spatial_extent(file2, model_extent)

    print(f"\nFile 2: {file2.name}")
    print(f"  {result}")

    if result.passed:
        print(f"\n  Files have overlapping coverage")
        if result.details and 'coverage_percent' in result.details:
            print(f"  Coverage: {result.details['coverage_percent']:.1f}%")
    else:
        print(f"\n  Coverage mismatch detected")

5. Terrain Layer Validation: check_terrain_layer()

Specialized validation for terrain/elevation layers.

Python
# Example 1: Comprehensive terrain validation
# The check_terrain_layer method validates terrain layers in a rasmap file

rasmap_files = list(project_path.glob("*.rasmap"))

if rasmap_files and terrain_files:
    rasmap_file = rasmap_files[0]
    print(f"RASMapper file: {rasmap_file.name}")

    # Get terrain names from the rasmap
    terrain_names = RasMap.get_terrain_names(rasmap_file)

    if terrain_names:
        layer_name = terrain_names[0]
        print(f"Terrain layer found: {layer_name}")

        result = RasMap.check_terrain_layer(rasmap_file, layer_name)
        print(f"\nResult: {result}")
        print(f"\nDetails:")
        for key, value in result.details.items():
            if isinstance(value, dict):
                print(f"  {key}:")
                for sub_key, sub_val in value.items():
                    print(f"    {sub_key}: {sub_val}")
            else:
                print(f"  {key}: {value}")
    else:
        print("No terrain layers found in rasmap")
else:
    print("No rasmap file found - skipping terrain layer validation")
    print("\nTo validate terrain layers in a rasmap:")
    print("  result = RasMap.check_terrain_layer('project.rasmap', 'Terrain_Name')")
Python
# Example 2: Validate elevation range using rasterio directly
# Since check_terrain_layer works with rasmap, let's use rasterio for elevation stats
if terrain_files:
    import rasterio
    import numpy as np

    with rasterio.open(test_terrain_file) as src:
        data = src.read(1)  # Read first band
        nodata = src.nodata

        # Mask nodata values
        if nodata is not None:
            valid_data = data[data != nodata]
        else:
            valid_data = data.flatten()

        # Calculate statistics
        min_elev = float(np.min(valid_data)) if len(valid_data) > 0 else None
        max_elev = float(np.max(valid_data)) if len(valid_data) > 0 else None
        mean_elev = float(np.mean(valid_data)) if len(valid_data) > 0 else None

    print(f"Terrain elevation statistics for {test_terrain_file.name}:\n")
    print(f"  Minimum: {min_elev:.2f}" if min_elev is not None else "  Minimum: N/A")
    print(f"  Maximum: {max_elev:.2f}" if max_elev is not None else "  Maximum: N/A")
    print(f"  Mean: {mean_elev:.2f}" if mean_elev is not None else "  Mean: N/A")

    # Check for reasonable range
    if min_elev is not None and max_elev is not None:
        if min_elev < -500 or max_elev > 15000:
            print("\n  WARNING: Elevation range may be unrealistic for US terrain")
            print("     Check units (should be feet or meters, not mm or other)")
        else:
            print("\n  Elevation range appears reasonable")

6. Land Cover Validation: check_land_cover_layer()

Specialized validation for land cover/Manning's n layers.

Python
# Example 1: Discover and validate land-cover layers by their RASMapper names.
# list_landcover_layers() filters the broader land-classification catalog to
# Manning's n / land-cover sidecars and exposes the layer name needed below.
if rasmap_file and not landcover_layers.empty:
    for _, layer in landcover_layers.iterrows():
        layer_name = layer["name"]
        print(f"\nValidating land-cover layer: {layer_name}")
        print(f"  Sidecar HDF: {layer['resolved_path']}")

        land_cover_result = RasMap.check_land_cover_layer(rasmap_file, layer_name)
        print(f"  Valid: {land_cover_result.passed}")
        print(f"  Severity: {land_cover_result.severity.value}")
        print(f"  Message: {land_cover_result.message}")
else:
    print("No land-cover layers found in this project rasmap file.")

7. Comprehensive Layer Validation: check_layer()

Performs all applicable validation checks and returns a comprehensive report.

Python
# Example 1: Comprehensive validation of a terrain layer in a rasmap file
rasmap_files = list(project_path.glob("*.rasmap"))

if rasmap_files:
    rasmap_file = rasmap_files[0]
    print(f"RASMapper file: {rasmap_file.name}")

    # Get terrain names
    terrain_names = RasMap.get_terrain_names(rasmap_file)

    if terrain_names:
        layer_name = terrain_names[0]
        layer_type = "Terrain"

        print(f"\nValidating layer: {layer_name}")
        print(f"Layer type: {layer_type}")

        report = RasMap.check_layer(
            rasmap_path=rasmap_file,
            layer_name=layer_name,
            layer_type=layer_type
        )

        print(f"\nReport summary: {report.summary}")
        print(f"Is valid: {report.is_valid}")
        print(f"Has warnings: {report.has_warnings}")

        # Print formatted report
        print("\nDetailed Report:")
        report.print_report(show_passed=True)
    else:
        print("No terrain layers found in rasmap file")
else:
    print("No rasmap file found in project")
    print("\nTo validate layers in a rasmap:")
    print("  report = RasMap.check_layer('project.rasmap', 'Layer_Name', 'Terrain')")
Python
# Example 2: Filter validation results by severity
rasmap_files = list(project_path.glob("*.rasmap"))

if rasmap_files:
    rasmap_file = rasmap_files[0]
    terrain_names = RasMap.get_terrain_names(rasmap_file)

    if terrain_names:
        layer_name = terrain_names[0]
        layer_type = "Terrain"

        report = RasMap.check_layer(rasmap_file, layer_name, layer_type)

        # Get only errors
        errors = report.get_results_by_severity(ValidationSeverity.ERROR)
        print(f"Errors found: {len(errors)}")
        for error in errors:
            print(f"  [FAIL] {error}")

        # Get only warnings
        warnings = report.get_results_by_severity(ValidationSeverity.WARNING)
        print(f"\nWarnings found: {len(warnings)}")
        for warning in warnings:
            print(f"  [WARN] {warning}")

        # Get info messages
        info = report.get_results_by_severity(ValidationSeverity.INFO)
        print(f"\nInfo messages: {len(info)}")
        for msg in info:
            print(f"  [INFO] {msg}")
    else:
        print("No terrain layers found")
else:
    print("No rasmap file found - skipping severity filtering example")

8. Boolean Convenience: is_valid_layer()

Quick boolean check for layer validity.

Python
# Example: Quick validation of terrain layers in a rasmap file
rasmap_files = list(project_path.glob("*.rasmap"))

if rasmap_files:
    rasmap_file = rasmap_files[0]
    terrain_names = RasMap.get_terrain_names(rasmap_file)

    print(f"Quick validation of terrain layers in {rasmap_file.name}:\n")

    for layer_name in terrain_names:
        layer_type = "Terrain"

        is_valid = RasMap.is_valid_layer(rasmap_file, layer_name, layer_type)
        status = "VALID" if is_valid else "INVALID"
        print(f"{status}: {layer_name} ({layer_type})")

    if not terrain_names:
        print("No terrain layers found in rasmap")
else:
    print("No rasmap file found in project")
    print("\nQuick validation example:")
    print("  is_valid = RasMap.is_valid_layer('project.rasmap', 'Terrain_2024', 'Terrain')")

9. Practical Use Case: Pre-Flight Check for Model Setup

Validate all required RAS Mapper layers before model setup.

Python
# Simulate pre-flight check for model setup
print("=" * 80)
print("PRE-FLIGHT CHECK: RAS Mapper Layer Validation")
print("=" * 80)

rasmap_files = list(project_path.glob("*.rasmap"))

if rasmap_files:
    rasmap_file = rasmap_files[0]
    print(f"\nRASMapper file: {rasmap_file.name}")

    # Get terrain layers
    terrain_names = RasMap.get_terrain_names(rasmap_file)
    all_valid = True

    for layer_name in terrain_names:
        layer_type = "Terrain"

        print(f"\n{'='*80}")
        print(f"Checking: {layer_name} ({layer_type})")
        print(f"{'='*80}")

        # Quick check
        is_valid = RasMap.is_valid_layer(rasmap_file, layer_name, layer_type)

        if is_valid:
            print(f"  PASS")
        else:
            print(f"  FAIL - running detailed diagnostics...")

            # Get detailed report
            report = RasMap.check_layer(rasmap_file, layer_name, layer_type)
            report.print_report(show_passed=False)

            all_valid = False

    if not terrain_names:
        print("\n  No terrain layers found in rasmap")
        all_valid = False

    print("\n" + "=" * 80)
    if all_valid:
        print("PRE-FLIGHT CHECK PASSED - All terrain layers valid")
        print("  Ready to configure RAS Mapper")
    else:
        print("PRE-FLIGHT CHECK FAILED - Fix layer issues before proceeding")
    print("=" * 80)
else:
    print("\nNo rasmap file found in project")
    print("\nPre-flight check requires a .rasmap file with configured layers")

Geometry and Plan HDF Association Audit

The .rasmap file tells RAS Mapper which layers are available. Compiled geometry and plan/result HDF files also carry /Geometry attributes such as Terrain Filename, Terrain Layername, Land Cover Filename, and Infiltration Filename. RasMap.get_hdf_geometry_association() reads those attributes without mutating the model, which makes it useful for checking whether plans/results are tied to the expected terrain and classification layers.

Python
import pandas as pd

geometry_hdfs = sorted(project_path.glob("*.g*.hdf"))
plan_hdfs = sorted(project_path.glob(f"*.p{PLAN}.hdf"))

association_rows = []
for artifact_type, hdf_candidates in [
    ("geometry", geometry_hdfs),
    ("plan/result", plan_hdfs),
]:
    if not hdf_candidates:
        continue

    hdf_path = hdf_candidates[0]
    association = RasMap.get_hdf_geometry_association(hdf_path)
    association_rows.append({
        "artifact_type": artifact_type,
        "hdf_path": str(hdf_path),
        "terrain_hdf_path": association.get("terrain_hdf_path"),
        "terrain_layer_name": association.get("terrain_layer_name"),
        "landcover_hdf_path": association.get("landcover_hdf_path"),
        "landcover_layer_name": association.get("landcover_layer_name"),
        "infiltration_hdf_path": association.get("infiltration_hdf_path"),
        "infiltration_layer_name": association.get("infiltration_layer_name"),
    })

if association_rows:
    association_df = pd.DataFrame(association_rows)
    display(association_df)
else:
    print("No geometry or plan/result HDF files found to audit.")

10. Visualization: Layer Extent Comparison (Optional)

Visualize spatial extents of multiple layers to verify coverage.

Python
# Optional: Visualize layer extents using matplotlib and rasterio
try:
    import matplotlib.pyplot as plt
    import matplotlib.patches as patches
    import rasterio

    raster_files = [f for f in geo_files if f.suffix.lower() in ['.tif', '.tiff']]

    if raster_files:
        fig, ax = plt.subplots(figsize=(10, 8))

        colors = ['red', 'blue', 'green', 'orange', 'purple']

        for i, raster_file in enumerate(raster_files[:5]):  # Plot first 5
            try:
                with rasterio.open(raster_file) as src:
                    bounds = src.bounds

                    # Extract bounds
                    minx = bounds.left
                    miny = bounds.bottom
                    maxx = bounds.right
                    maxy = bounds.top

                    width = maxx - minx
                    height = maxy - miny

                    # Draw rectangle
                    rect = patches.Rectangle(
                        (minx, miny), width, height,
                        linewidth=2, edgecolor=colors[i % len(colors)],
                        facecolor='none', label=raster_file.name
                    )
                    ax.add_patch(rect)
            except Exception as e:
                print(f"Could not read {raster_file.name}: {e}")

        ax.set_xlabel('Easting')
        ax.set_ylabel('Northing')
        ax.set_title('Spatial Extents of Geospatial Layers')
        ax.legend(loc='upper right')
        ax.autoscale()
        ax.set_aspect('equal')
        plt.grid(True, alpha=0.3)
        plt.tight_layout()
        plt.show()

        print("\nExtent visualization complete")
        print("  Overlapping rectangles indicate good coverage alignment")
    else:
        print("No raster files found for visualization")

except ImportError as e:
    print(f"Visualization dependencies not available: {e}")

Cleanup

Python
# Clean up extracted project
import shutil

if project_path.parent.name == "example_projects":
    shutil.rmtree(project_path.parent, ignore_errors=True)
    print("✓ Cleaned up example projects")

Summary

This notebook demonstrated the RAS Mapper layer validation framework:

Individual Validation Methods: - check_layer_format() - Validates file format and accessibility - check_layer_crs() - Validates coordinate reference system - check_raster_metadata() - Validates raster properties - check_spatial_extent() - Validates spatial coverage

Specialized Validations: - check_terrain_layer() - Terrain-specific validation - check_land_cover_layer() - Land cover-specific validation

Comprehensive Validation: - check_layer() - Runs all applicable checks, returns ValidationReport

Boolean Convenience: - is_valid_layer() - Quick validity check

Validation Reports: - Filter by severity (INFO, WARNING, ERROR, CRITICAL) - Get failed checks - Print formatted reports

Use these tools to ensure RAS Mapper layers are valid before model setup and execution!

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.