Skip to content

Inspecting Results and Generating Hydraulic Product Packages

Python
# True uses this checkout; False uses the installed package.
import sys
from hashlib import sha256
import os
from pathlib import Path
from tempfile import mkdtemp

import pandas as pd
import pyarrow.parquet as pq

USE_LOCAL_SOURCE = False

REPO_ROOT = Path.cwd().resolve()
if REPO_ROOT.name.lower() == "examples":
    REPO_ROOT = REPO_ROOT.parent

if USE_LOCAL_SOURCE:
    local_path = str(REPO_ROOT)
    if local_path not in sys.path:
        sys.path.insert(0, local_path)
    print("LOCAL SOURCE MODE")
else:
    print("PIP PACKAGE MODE")

from ras_commander import HdfResultsProducts  # noqa: E402

def sha256_file(path, chunk_size=1024 * 1024):
    digest = sha256()
    with Path(path).open("rb") as stream:
        for chunk in iter(lambda: stream.read(chunk_size), b""):
            digest.update(chunk)
    return digest.hexdigest()
Text Only
PIP PACKAGE MODE

Two different operations

This notebook keeps reading and generation explicit:

  1. HdfResultsProducts.inspect_result() reads an existing HEC-RAS producer HDF without changing it. Inspection checks mechanical completion and product readiness; it is not hydraulic acceptance.
  2. HdfResultsProducts.export() generates a new ras-commander derivative package containing COG, Arrow/Parquet, GeoJSON, JSON, and optional PNG assets. Those files are not HEC-RAS model output.

No HEC-RAS execution or preprocessing occurs here. The source result HDF remains read-only and is protected with before/after SHA-256 checks.

1. Select an existing producer HDF

Set RAS_COMMANDER_RESULT_HDF to a completed, reviewed unsteady HEC-RAS plan-result HDF with a 2D flow area. This example deliberately does not synthesize or compute a model result. Generated package files are written only under the ignored working/ folder.

Python
result_hdf_setting = os.environ.get("RAS_COMMANDER_RESULT_HDF")
if not result_hdf_setting:
    raise RuntimeError(
        "Set RAS_COMMANDER_RESULT_HDF to an existing completed HEC-RAS result HDF; "
        "this notebook will not generate model output."
    )

RESULT_HDF = Path(result_hdf_setting).expanduser().resolve()
if not RESULT_HDF.is_file():
    raise FileNotFoundError(f"Existing producer HDF not found: {RESULT_HDF}")

WORK_ROOT = REPO_ROOT / "working" / "example_417_hydraulic_products"
WORK_ROOT.mkdir(parents=True, exist_ok=True)
RUN_ROOT = Path(mkdtemp(prefix="run_", dir=WORK_ROOT))
PRODUCT_DIRECTORY = RUN_ROOT / "hydraulic-products"

source_sha_before = sha256_file(RESULT_HDF)
print(f"READING existing HEC-RAS producer HDF: {RESULT_HDF}")
print(f"GENERATED derivatives will be written under: {PRODUCT_DIRECTORY}")
Text Only
READING existing HEC-RAS producer HDF: D:\CLB-Temp\clb-t3-pr534\results\Davis\DavisStormSystem.p02.hdf
GENERATED derivatives will be written under: D:\CLB-Temp\clb-t3-pr534\repo2\working\example_417_hydraulic_products\run_8tr8ohd3\hydraulic-products

2. Read and inspect the existing result

Inspection validates completion evidence, time axes, CRS, units, topology, and required arrays. The returned hydraulic_qaqc value remains not_evaluated; successful inspection does not approve the model or its results.

Python
print("READING and inspecting the existing producer HDF (no files generated)...")
inspection = HdfResultsProducts.inspect_result(RESULT_HDF)
assert inspection["source"]["access"] == "read_only"
assert inspection["hydraulic_qaqc"] == "not_evaluated"

inspection_summary = pd.Series(
    {
        "completed successfully": inspection["completed_successfully"],
        "completion evidence": ", ".join(inspection["completion_evidence"]["accepted_sources"]),
        "time start": inspection["time"]["start"],
        "time end": inspection["time"]["end"],
        "mesh names": ", ".join(inspection["mesh_names"]),
        "hydraulic QA/QC": inspection["hydraulic_qaqc"],
    },
    name="read-only result inspection",
)
display(inspection_summary.to_frame())
Text Only
2026-10-15 03:54:24 - ras_commander.hdf.HdfResultsProducts - INFO - Inspected existing HEC-RAS result HDF 'DavisStormSystem.p02.hdf' read-only: 2 mesh(es), 217 timestamps; hydraulic QA/QC not evaluated


READING and inspecting the existing producer HDF (no files generated)...
read-only result inspection
completed successfully True
completion evidence event_conditions_attribute, embedded_compute_m...
time start 2000-01-10T12:00:00
time end 2000-01-12T00:00:00
mesh names area2, DS Channel
hydraulic QA/QC not_evaluated

3. Generate a new derivative package

The output directory must not exist. export() generates bounded COG rasters, an Arrow/Parquet boundary-hydrograph table, JSON metadata and numerical evidence, a WGS84 GeoJSON footprint, and a depth preview. It publishes hydraulic-products.json last; consumers should treat a package without that manifest as incomplete.

Python
print(f"GENERATING new ras-commander derivative products: {PRODUCT_DIRECTORY}")
manifest = HdfResultsProducts.export(
    RESULT_HDF,
    PRODUCT_DIRECTORY,
    max_dimension=2048,
    include_preview=True,
)

manifest_path = PRODUCT_DIRECTORY / HdfResultsProducts.MANIFEST_FILENAME
assert manifest_path.is_file()
assert manifest["source"]["sha256"] == source_sha_before
assert manifest["product_package"]["hec_ras_model_output_generated"] is False
assert manifest["status"]["hydraulic_qaqc"] == "not_evaluated"
print(f"Generated package-complete manifest: {manifest_path}")
Text Only
2026-10-15 03:54:24 - ras_commander.hdf.HdfResultsProducts - INFO - Inspected existing HEC-RAS result HDF 'DavisStormSystem.p02.hdf' read-only: 2 mesh(es), 217 timestamps; hydraulic QA/QC not evaluated


GENERATING new ras-commander derivative products: D:\CLB-Temp\clb-t3-pr534\repo2\working\example_417_hydraulic_products\run_8tr8ohd3\hydraulic-products


2026-10-15 03:54:25 - ras_commander.hdf.HdfResultsMesh - INFO - Maximum-depth source for mesh 'area2' in 'DavisStormSystem.p02.hdf': derived in memory by ras-commander from HEC-RAS HDF 'Water Surface' minus 'Cells Minimum Elevation'; no 'Depth' dataset was created or written.


2026-10-15 03:54:25 - ras_commander.hdf.HdfResultsMesh - INFO - Maximum-depth source for mesh 'DS Channel' in 'DavisStormSystem.p02.hdf': derived in memory by ras-commander from HEC-RAS HDF 'Water Surface' minus 'Cells Minimum Elevation'; no 'Depth' dataset was created or written.


2026-10-15 03:54:29 - ras_commander.hdf.HdfResultsProducts - INFO - Generated ras-commander hydraulic product package 'hydraulic-products' from existing HEC-RAS result 'DavisStormSystem.p02.hdf' read-only; no HEC-RAS model output was created or modified; hydraulic QA/QC not evaluated


Generated package-complete manifest: D:\CLB-Temp\clb-t3-pr534\repo2\working\example_417_hydraulic_products\run_8tr8ohd3\hydraulic-products\hydraulic-products.json

4. Verify checksums and read the generated Parquet asset

Every manifest asset is checked independently. The boundary-hydrograph asset is then read with required pyarrow, consistent with the core Arrow/Parquet product contract.

Python
asset_rows = []
for asset_name, asset in manifest["assets"].items():
    asset_path = PRODUCT_DIRECTORY / asset["href"]
    assert asset_path.is_file()
    actual_sha = sha256_file(asset_path)
    assert actual_sha == asset["sha256"]
    asset_rows.append(
        {
            "asset": asset_name,
            "filename": asset_path.name,
            "bytes": asset_path.stat().st_size,
            "sha256 verified": True,
        }
    )

hydrograph_asset = manifest["assets"]["hydraulic-hydrographs"]
hydrograph_table = pq.read_table(PRODUCT_DIRECTORY / hydrograph_asset["href"])
print(f"READING generated Arrow/Parquet asset: {hydrograph_asset['href']}")
print(hydrograph_table.schema)
display(pd.DataFrame(asset_rows))
Text Only
READING generated Arrow/Parquet asset: hydraulic-hydrographs.parquet
time: timestamp[ns]
bc_name: string
variable: string
value: double
units: string
area_2d: string
-- schema metadata --
pandas: '{"index_columns": [], "column_indexes": [], "columns": [{"name":' + 763
asset filename bytes sha256 verified
0 hydraulic-hydrographs hydraulic-hydrographs.parquet 6179 True
1 maximum-depth maximum-depth.tif 126306 True
2 maximum-velocity maximum-velocity.tif 126500 True
3 maximum-wse maximum-wse.tif 124186 True
4 numerical-qaqc numerical-qaqc.json 2459 True
5 preview maximum-depth-preview.png 77237 True
6 result-footprint result-footprint.geojson 7351 True
7 result-metadata result-metadata.json 3808 True

5. Verify source immutability

The final source hash proves that inspection and derivative generation did not alter the producer HDF. This point-in-time check is an audit assertion, not a continuous file lock.

Python
source_sha_after = sha256_file(RESULT_HDF)
assert source_sha_after == source_sha_before
print("READ-ONLY verification passed: producer HDF SHA-256 is unchanged.")
print("GENERATED package is a ras-commander derivative, not HEC-RAS model output.")
Text Only
READ-ONLY verification passed: producer HDF SHA-256 is unchanged.
GENERATED package is a ras-commander derivative, not HEC-RAS model output.

Scope and next steps

This core ras-commander contract is intentionally narrow: deterministic inspection and a checksum-pinned hydraulic product package. For broader cloud-native project archives, geometry/result joins, DuckDB workflows, and PMTiles publishing, see 961_cloud_native_results_export.ipynb and the external ras2cng project.

Before publishing or relying on these products, independently review completion messages, numerical evidence, units, CRS, raster resolution, source provenance, and hydraulic suitability. Mechanical readiness is not engineering acceptance.