Skip to content

Using eBFE Models: Tickfaw Results-Ready Validation

This notebook validates the organized Tickfaw eBFE delivery as a full 2D example with source-provided result HDFs. It confirms local organization, reviews the saved ras-commander geometry-preprocessor evidence, and checks that plan result HDFs are present inside the RAS project folder.

What This Notebook Proves

  1. RasEbfeModels.organize_model("tickfaw") resolves to the shared organized delivery.
  2. RASMapper terrain, land-cover, and projection assets are local to the RAS project folder.
  3. The geometry preprocessor has already passed through ras-commander for plan 13 / geometry 05.
  4. Seven hydraulic result HDFs are present and loadable from the organized project folder.
Python
from pathlib import Path
import json
import logging
import os
import re
import sys
import zipfile

import h5py
import pandas as pd

logging.getLogger("ras_commander").setLevel(logging.WARNING)

try:
    from ras_commander import RasPrj, RasUtils, init_ras_project
    from ras_commander.sources.federal import RasEbfeModels
except ImportError:
    repo_root = Path.cwd().parent if Path.cwd().name == "examples" else Path.cwd()
    sys.path.insert(0, str(repo_root))
    from ras_commander import RasPrj, RasUtils, init_ras_project
    from ras_commander.sources.federal import RasEbfeModels

Configure the eBFE Workspace

Python
EBFE_WORKSPACE = Path(os.environ.get("RAS_COMMANDER_EBFE_ROOT", r"H:\Testing\eBFE Model Organization"))
DOWNLOAD_ROOT = EBFE_WORKSPACE / "Downloads"
ORGANIZED_ROOT = EBFE_WORKSPACE / "Organized"
VALIDATION_ROOT = EBFE_WORKSPACE / "Validation" / "ebfe_delivery"

organized_folder = ORGANIZED_ROOT / "Tickfaw_08070203"
if not organized_folder.exists():
    organized_folder = RasEbfeModels.organize_model(
        "tickfaw",
        download_root=DOWNLOAD_ROOT,
        output_root=ORGANIZED_ROOT,
    )

ras_model_root = organized_folder / "RAS Model"
print(f"Tickfaw organized folder: {organized_folder}")
print(f"RAS Model root exists: {ras_model_root.exists()}")
print(f"Validation root: {VALIDATION_ROOT}")
Text Only
Tickfaw organized folder: H:\Testing\eBFE Model Organization\Organized\Tickfaw_08070203
RAS Model root exists: True
Validation root: H:\Testing\eBFE Model Organization\Validation\ebfe_delivery

Discover and Initialize the RAS Project

Python
projects = RasUtils.find_valid_ras_folders(
    ras_model_root,
    max_depth=10,
    return_project_info=True,
)
project_df = pd.DataFrame(projects)
print(f"Discovered {len(project_df)} HEC-RAS project folder(s)")
project_df
Text Only
Discovered 1 HEC-RAS project folder(s)
folder project_name prj_file plan_count plan_numbers
0 H:\Testing\eBFE Model Organization\Organized\T... TickfawRASLSModel H:\Testing\eBFE Model Organization\Organized\T... 7 [13, 14, 15, 16, 17, 18, 19]
Python
project_folder = Path(project_df.iloc[0]["folder"])
ras = RasPrj()
init_ras_project(
    project_folder,
    "5.0.7",
    ras_object=ras,
    load_results_summary=False,
)

plan_columns = [
    column for column in ["plan_number", "flow_type", "Geom File", "Flow File", "HDF_Results_Path"]
    if column in ras.plan_df.columns
]
ras.plan_df[plan_columns]
plan_number flow_type Geom File Flow File HDF_Results_Path
0 13 Unsteady 05 12 H:\Testing\eBFE Model Organization\Organized\T...
1 14 Unsteady 05 13 H:\Testing\eBFE Model Organization\Organized\T...
2 15 Unsteady 05 14 H:\Testing\eBFE Model Organization\Organized\T...
3 16 Unsteady 05 15 H:\Testing\eBFE Model Organization\Organized\T...
4 17 Unsteady 05 16 H:\Testing\eBFE Model Organization\Organized\T...
5 18 Unsteady 05 17 H:\Testing\eBFE Model Organization\Organized\T...
6 19 Unsteady 05 18 H:\Testing\eBFE Model Organization\Organized\T...

Confirm Local Delivery Assets

Python
asset_rows = []
for label, pattern in {
    "projection": "Projection/*.prj",
    "terrain_hdf": "Terrain/**/*.hdf",
    "land_cover_tif": "Land Cover/**/*.tif",
    "land_cover_hdf": "Land Cover/**/*.hdf",
    "rasmap": "*.rasmap",
}.items():
    for path in sorted(project_folder.glob(pattern)):
        asset_rows.append(
            {
                "asset_type": label,
                "file": path.name,
                "relative_path": str(path.relative_to(project_folder)),
                "size_mb": round(path.stat().st_size / 1_000_000, 3),
            }
        )

asset_df = pd.DataFrame(asset_rows)
asset_df
asset_type file relative_path size_mb
0 projection projection_file.prj Projection\projection_file.prj 0.001
1 terrain_hdf Terrain_Repaired.hdf Terrain\Terrain_Repaired.hdf 69.397
2 land_cover_tif LandCover.tif Land Cover\LandCover.tif 19.459
3 land_cover_hdf LandCover.hdf Land Cover\LandCover.hdf 0.011
4 rasmap TickfawRASLSModel.rasmap TickfawRASLSModel.rasmap 0.018

Review Saved Audit Evidence

Python
def find_latest_json(root: Path, patterns: list[str], text_patterns: list[str] | None = None) -> Path | None:
    if not root.exists():
        return None
    candidates = []
    for pattern in patterns:
        candidates.extend(root.rglob(pattern))
    candidates = sorted({path for path in candidates if path.is_file()}, key=lambda path: path.stat().st_mtime)
    if not text_patterns:
        return candidates[-1] if candidates else None
    for path in reversed(candidates):
        try:
            text = path.read_text(encoding="utf-8", errors="ignore")
        except OSError:
            continue
        if any(pattern.lower() in text.lower() for pattern in text_patterns):
            return path
    return None


def size_gb(path: Path) -> float:
    return round(path.stat().st_size / 1_000_000_000, 3)


def classify_plan_hdf(path: Path) -> dict[str, object]:
    with h5py.File(path, "r") as hdf:
        top_groups = sorted(hdf.keys())
        has_geometry = "Geometry" in hdf
        has_plan_data = "Plan Data" in hdf
        has_event_conditions = "Event Conditions" in hdf
        has_summary_only = list(hdf.keys()) == ["Results"] and "Summary" in hdf["Results"]
        if has_geometry and has_plan_data:
            classification = "hydraulic results"
        elif has_summary_only:
            classification = "compute messages only"
        else:
            classification = "unknown HDF layout"
    return {
        "file": path.name,
        "size_gb": size_gb(path),
        "classification": classification,
        "has_geometry": has_geometry,
        "has_plan_data": has_plan_data,
        "has_event_conditions": has_event_conditions,
        "top_groups": ", ".join(top_groups),
    }


def existing_path_count(values) -> int:
    return sum(bool(value) and Path(str(value)).exists() for value in values)
Python
audit_path = find_latest_json(
    VALIDATION_ROOT,
    ["e2e_delivery_audit_*.json"],
    ["Tickfaw_08070203", "Tickfaw", "08070203"],
)
print(f"Audit report: {audit_path}")

audit_payload = json.loads(audit_path.read_text(encoding="utf-8")) if audit_path else []
tickfaw_record = audit_payload[0] if audit_payload else {}
project_record = tickfaw_record.get("projects", [{}])[0]

audit_summary = pd.DataFrame(
    [
        {
            "status": tickfaw_record.get("status"),
            "project_count": tickfaw_record.get("project_count"),
            "audit_issues": len(tickfaw_record.get("issues", [])),
            "project_crs": project_record.get("project_crs"),
            "terrain_layers": len(project_record.get("terrain_layers", [])),
            "land_cover_layers": len(project_record.get("land_cover_layers", [])),
            "dss_reference_count": project_record.get("dss_reference_count"),
            "output_hdf_count": project_record.get("output_hdf_count"),
            "outputs_inside_project": project_record.get("outputs_inside_project"),
            "crs_mismatches": len(project_record.get("terrain_crs_mismatches", []))
            + len(project_record.get("land_cover_crs_mismatches", [])),
        }
    ]
)
audit_summary
Text Only
Audit report: H:\Testing\eBFE Model Organization\Validation\ebfe_delivery\e2e_delivery_audit_20260427_082751.json
status project_count audit_issues project_crs terrain_layers land_cover_layers dss_reference_count output_hdf_count outputs_inside_project crs_mismatches
0 audited 1 0 EPSG:2278 1 1 14 7 True 0

Review Geometry-Preprocessor Evidence

Python
preprocessor_root = VALIDATION_ROOT / "preprocessor_validation"
preprocessor_path = find_latest_json(
    preprocessor_root,
    ["geometry_preprocessor_validation_*.json"],
    ["Tickfaw_08070203", "TickfawRASLSModel", "tickfaw"],
)
print(f"Preprocessor report: {preprocessor_path}")

payload = json.loads(preprocessor_path.read_text(encoding="utf-8"))
records = payload.get("records", [])
plan_rows = []
for record in records:
    for plan in record.get("plans", []):
        plan_rows.append(
            {
                "study": record.get("study"),
                "project": record.get("project_name"),
                "status": record.get("status"),
                "plan": plan.get("plan_number"),
                "geometry": plan.get("geometry_number"),
                "flow_type": plan.get("flow_type"),
                "elapsed_seconds": round(plan.get("elapsed_seconds", 0), 1),
                "errors": plan.get("error_count"),
                "warnings": plan.get("warning_count"),
                "return_code": plan.get("return_code"),
            }
        )
pd.DataFrame(plan_rows)
Text Only
Preprocessor report: H:\Testing\eBFE Model Organization\Validation\ebfe_delivery\preprocessor_validation\geometry_preprocessor_validation_20260424_185812.json
study project status plan geometry flow_type elapsed_seconds errors warnings return_code
0 tickfaw TickfawRASLSModel passed 13 05 Unsteady 662.9 0 0 0

Verify Result-HDF Availability

Python
organized_plan_hdfs = sorted(project_folder.glob("*.p??.hdf"))
hdf_summary = pd.DataFrame(classify_plan_hdf(path) for path in organized_plan_hdfs)
print(
    f"{existing_path_count(ras.plan_df['HDF_Results_Path'])} of {len(ras.plan_df)} plan dataframe HDF paths exist locally"
)
hdf_summary
Text Only
7 of 7 plan dataframe HDF paths exist locally
file size_gb classification has_geometry has_plan_data has_event_conditions top_groups
0 TickfawRASLSModel.p13.hdf 1.383 hydraulic results True True True Event Conditions, Geometry, Plan Data, Results
1 TickfawRASLSModel.p14.hdf 1.405 hydraulic results True True True Event Conditions, Geometry, Plan Data, Results
2 TickfawRASLSModel.p15.hdf 1.361 hydraulic results True True True Event Conditions, Geometry, Plan Data, Results
3 TickfawRASLSModel.p16.hdf 1.397 hydraulic results True True True Event Conditions, Geometry, Plan Data, Results
4 TickfawRASLSModel.p17.hdf 1.603 hydraulic results True True True Event Conditions, Geometry, Plan Data, Results
5 TickfawRASLSModel.p18.hdf 1.609 hydraulic results True True True Event Conditions, Geometry, Plan Data, Results
6 TickfawRASLSModel.p19.hdf 1.620 hydraulic results True True True Event Conditions, Geometry, Plan Data, Results
Python
result_path_df = ras.plan_df[["plan_number", "HDF_Results_Path"]].copy()
result_path_df["exists"] = result_path_df["HDF_Results_Path"].apply(
    lambda value: bool(value) and Path(str(value)).exists()
)
result_path_df["inside_project"] = result_path_df["HDF_Results_Path"].apply(
    lambda value: bool(value)
    and Path(str(value)).exists()
    and project_folder in Path(str(value)).parents
)
result_path_df
plan_number HDF_Results_Path exists inside_project
0 13 H:\Testing\eBFE Model Organization\Organized\T... True True
1 14 H:\Testing\eBFE Model Organization\Organized\T... True True
2 15 H:\Testing\eBFE Model Organization\Organized\T... True True
3 16 H:\Testing\eBFE Model Organization\Organized\T... True True
4 17 H:\Testing\eBFE Model Organization\Organized\T... True True
5 18 H:\Testing\eBFE Model Organization\Organized\T... True True
6 19 H:\Testing\eBFE Model Organization\Organized\T... True True

Optional Preprocessor Re-Run Command

Python
RUN_GEOMETRY_PREPROCESSOR = False

repo_root = Path.cwd().parent if Path.cwd().name == "examples" else Path.cwd()
batch_script = repo_root / "scripts" / "ebfe_geometry_preprocessor_batch.py"
cmd = [
    sys.executable,
    str(batch_script),
    "--study",
    "tickfaw",
    "--plan",
    "13",
    "--max-wait",
    "7200",
    "--output-dir",
    str(VALIDATION_ROOT / "preprocessor_validation"),
]
display_cmd = [
    "python",
    str(batch_script.relative_to(repo_root)),
    *cmd[2:],
]

if RUN_GEOMETRY_PREPROCESSOR:
    import subprocess

    subprocess.run(cmd, check=True)
else:
    print("Geometry preprocessor is opt-in for the committed notebook.")
    print(" ".join(f'"{part}"' if " " in part else part for part in display_cmd))
Text Only
Geometry preprocessor is opt-in for the committed notebook.
python scripts\ebfe_geometry_preprocessor_batch.py --study tickfaw --plan 13 --max-wait 7200 --output-dir "H:\Testing\eBFE Model Organization\Validation\ebfe_delivery\preprocessor_validation"

Delivery-Format Interpretation

Tickfaw is a results-ready eBFE demonstration model. The organized project has local terrain, land cover, projection, and RASMapper references; all seven plan result HDFs resolve inside the project folder; and the ras-commander geometry preprocessor validation passed for plan 13 / geometry 05 with no errors or warnings.

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.