| name | hecras_export_cloud-native |
| shared_corpus | true |
| harness_scope | shared |
| source_owner | gpt-cmdr |
| security_review | internal |
| description | Export HEC-RAS geometry and simulation results to cloud-native formats:
GeoParquet, PMTiles (vector and raster), and PostGIS. Uses ras2cng
as a CLI wrapper over ras-commander parsers. Use when exporting HEC-RAS mesh
geometry to GeoParquet, publishing results as PMTiles for web maps, querying
HEC-RAS outputs with DuckDB SQL, syncing flood results to PostGIS, converting
HEC-RAS to cloud-native geospatial formats, or generating vector tiles from
simulation outputs. Keywords: GeoParquet, PMTiles, DuckDB, PostGIS, cloud-native,
vector tiles, geometry export, mesh cells, cross sections, ras2cng.
|
Exporting HEC-RAS to Cloud-Native Formats
When the user asks to export HEC-RAS results to GeoParquet, PMTiles, or PostGIS, use this skill with the ras2cng CLI (RAS to Cloud Native GIS). This CLI wraps ras-commander parsers to export HEC-RAS geometry and results to GeoParquet, vector/raster PMTiles, and PostGIS.
Repo: C:\GH\ras2cng
Quick Start
1. Export Geometry to GeoParquet
ras2cng geometry model.g01.hdf mesh_cells.parquet
ras2cng geometry model.g01 cross_sections.parquet
ras2cng geometry model.g01.hdf mesh_cells.parquet --layer mesh_cells
ras2cng geometry model.g01.hdf xs.parquet --layer cross_sections
ras2cng geometry model.g01.hdf cl.parquet --layer centerlines
2. Export Results to GeoParquet
ras2cng results model.p01.hdf max_depth.parquet
ras2cng results model.p01.hdf max_wse.parquet --var "Maximum Water Surface"
ras2cng results model.p01.hdf max_depth.parquet \
--geometry mesh_cells.parquet \
--var "Maximum Depth"
ras2cng results model.p01.hdf ./results_dir/ --all \
--geometry mesh_cells.parquet
3. Query with DuckDB
ras2cng query max_depth.parquet "SELECT mesh_name, AVG(maximum_depth) FROM _ GROUP BY mesh_name"
ras2cng query max_depth.parquet "SELECT * FROM _ WHERE maximum_depth > 5" --output deep.csv
ras2cng query max_depth.parquet "SELECT * FROM _ WHERE maximum_depth > 5" --output deep.parquet
4. Generate PMTiles
ras2cng pmtiles mesh_cells.parquet mesh_cells.pmtiles --layer mesh_cells
ras2cng pmtiles mesh_cells.parquet mesh_cells.pmtiles \
--layer mesh_cells --min-zoom 8 --max-zoom 14
ras2cng pmtiles results.tif results.pmtiles
5. Sync to PostGIS
ras2cng sync mesh_cells.parquet "postgresql://user:pass@localhost/mydb" mesh_cells
ras2cng sync mesh_cells.parquet "postgresql://user:pass@localhost/mydb" mesh_cells \
--schema hydraulics --if-exists append
Python API
All CLI commands have equivalent Python functions importable from ras2cng:
from ras2cng import (
export_geometry_layers,
export_results_layer,
export_all_variables,
DuckSession,
query_parquet,
spatial_join,
generate_pmtiles_from_input,
sync_to_postgres,
)
from pathlib import Path
export_geometry_layers(
Path("model.g01.hdf"),
Path("mesh_cells.parquet"),
layer="mesh_cells",
)
export_results_layer(
plan_hdf=Path("model.p01.hdf"),
output=Path("max_depth.parquet"),
variable="Maximum Depth",
geom_file=Path("mesh_cells.parquet"),
)
exported_vars = export_all_variables(
plan_hdf=Path("model.p01.hdf"),
output_dir=Path("./results/"),
geom_file=Path("mesh_cells.parquet"),
)
df = query_parquet(Path("max_depth.parquet"), "SELECT * FROM _ WHERE maximum_depth > 3")
with DuckSession() as duck:
duck.register_parquet("max_depth.parquet")
df = duck.sql("SELECT mesh_name, MAX(maximum_depth) FROM _ GROUP BY mesh_name")
File Type Detection
Detection is suffix-based — no file inspection needed:
| Suffix Pattern | Type | Parser Used |
|---|
*.g01.hdf, *.g02.hdf, ... | HDF geometry | HdfMesh, HdfXsec |
*.g01, *.g02, ... | Text geometry | GeomParser |
*.p01.hdf, *.p02.hdf, ... | Plan results | HdfResultsMesh |
Geometry Layers
| Layer Name | Available In | Contents |
|---|
mesh_cells | HDF geometry (.g??.hdf) | 2D mesh cell polygons (falls back to points if polygons unavailable) |
cross_sections | HDF geometry + text geometry | 1D cross section cut lines |
centerlines | HDF geometry + text geometry | River/reach centerlines |
Default behavior (no --layer):
- HDF geometry → exports
mesh_cells first (falls back to first available)
- Text geometry → exports
cross_sections first (falls back to first available)
Results Variables
Column names in output GeoParquet use snake_case (ras-commander normalization):
| HEC-RAS Variable Name | Output Column |
|---|
Maximum Depth | maximum_depth |
Maximum Water Surface | maximum_water_surface |
Maximum Velocity | maximum_velocity |
Join behavior: When geom_file is provided and results are points, the function merges
on (mesh_name, cell_id) — results columns are attached to the polygon GeoDataFrame.
Result: each row is a mesh cell polygon with hydraulic attributes.
Full Typical Workflow
ras2cng geometry MyModel.g01.hdf mesh_cells.parquet --layer mesh_cells
ras2cng results MyModel.p01.hdf max_depth_polygons.parquet \
--geometry mesh_cells.parquet \
--var "Maximum Depth"
ras2cng query max_depth_polygons.parquet \
"SELECT * FROM _ WHERE maximum_depth > 3.0 ORDER BY maximum_depth DESC LIMIT 100" \
--output deep_areas.parquet
ras2cng pmtiles max_depth_polygons.parquet flood_depth.pmtiles \
--layer flood --min-zoom 8 --max-zoom 14
ras2cng sync max_depth_polygons.parquet \
"postgresql://gis:pass@localhost/flood_db" max_depth \
--schema hydraulics
Installation
pip install -e ".[all]"
pip install -e ".[duckdb,postgis,pmtiles]"
External CLI dependencies for PMTiles (install separately):
tippecanoe — GeoJSON → vector PMTiles
pmtiles — go-pmtiles CLI for archive operations
gdal_translate — raster conversion (part of GDAL)
DuckDB Session Details
DuckSession auto-loads the spatial extension. register_parquet() detects WKB geometry
columns and wraps them with ST_GeomFromWKB() so spatial queries work directly:
with DuckSession() as duck:
duck.register_parquet("mesh_cells.parquet")
result = duck.sql("""
SELECT mesh_name, ST_Area(geometry) as cell_area_m2
FROM _
WHERE ST_Within(geometry, ST_GeomFromText('POLYGON((x1 y1, ...))', 4326))
""")
Error Patterns
| Error | Cause | Fix |
|---|
Unsupported geometry file format | Suffix not .g?? or .g??.hdf | Check file path and extension |
No geometry layers could be extracted | Empty or malformed file | Verify HEC-RAS file is valid |
No results found for variable | Variable name typo or not in plan | Check variable name; use list_available_summary_variables() |
tippecanoe: command not found | PMTiles CLI not installed | Install tippecanoe separately |
Source Files
| File | Purpose |
|---|
C:\GH\ras2cng\ras2cng\cli.py | Typer CLI entrypoint (5 commands) |
C:\GH\ras2cng\ras2cng\geometry.py | HDF + text geometry export |
C:\GH\ras2cng\ras2cng\results.py | Plan results + polygon join |
C:\GH\ras2cng\ras2cng\duckdb_session.py | DuckDB wrapper with spatial |
C:\GH\ras2cng\ras2cng\pmtiles.py | Vector/raster PMTiles pipeline |
C:\GH\ras2cng\ras2cng\postgis_sync.py | GeoParquet → PostGIS |
C:\GH\ras2cng\pyproject.toml | Package metadata + entrypoints |
Cross-References
Skills (related workflows):
hecras_extract_results -- Use upstream to extract HDF results before export
hecras_parse_geometry -- Use for geometry data to export
Primary sources:
- ras2cng CLI documentation