ras2cng 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. ras2cng-0.1.0/.github/workflows/docs.yml +38 -0
  2. ras2cng-0.1.0/.gitignore +16 -0
  3. ras2cng-0.1.0/.python-version +1 -0
  4. ras2cng-0.1.0/.readthedocs.yaml +15 -0
  5. ras2cng-0.1.0/CLAUDE.md +55 -0
  6. ras2cng-0.1.0/LICENSE +21 -0
  7. ras2cng-0.1.0/PKG-INFO +195 -0
  8. ras2cng-0.1.0/README.md +127 -0
  9. ras2cng-0.1.0/docs/about/acknowledgments.md +28 -0
  10. ras2cng-0.1.0/docs/about/cloud-native-gis.md +45 -0
  11. ras2cng-0.1.0/docs/api/cli.md +98 -0
  12. ras2cng-0.1.0/docs/api/duckdb_session.md +3 -0
  13. ras2cng-0.1.0/docs/api/geometry.md +3 -0
  14. ras2cng-0.1.0/docs/api/index.md +34 -0
  15. ras2cng-0.1.0/docs/api/pmtiles.md +3 -0
  16. ras2cng-0.1.0/docs/api/postgis_sync.md +3 -0
  17. ras2cng-0.1.0/docs/api/results.md +3 -0
  18. ras2cng-0.1.0/docs/assets/ras2cng_logo.svg +95 -0
  19. ras2cng-0.1.0/docs/examples/00_using_ras_examples.md +20 -0
  20. ras2cng-0.1.0/docs/examples/01_export_geometry.md +29 -0
  21. ras2cng-0.1.0/docs/examples/02_export_results.md +27 -0
  22. ras2cng-0.1.0/docs/examples/03_duckdb_queries.md +23 -0
  23. ras2cng-0.1.0/docs/examples/04_generate_pmtiles.md +30 -0
  24. ras2cng-0.1.0/docs/examples/05_cloud_native_stack.md +26 -0
  25. ras2cng-0.1.0/docs/examples/index.md +42 -0
  26. ras2cng-0.1.0/docs/getting-started/cloud-native-stack.md +61 -0
  27. ras2cng-0.1.0/docs/getting-started/installation.md +62 -0
  28. ras2cng-0.1.0/docs/getting-started/quickstart.md +123 -0
  29. ras2cng-0.1.0/docs/index.md +91 -0
  30. ras2cng-0.1.0/docs/requirements-docs.txt +13 -0
  31. ras2cng-0.1.0/docs/user-guide/duckdb-queries.md +93 -0
  32. ras2cng-0.1.0/docs/user-guide/geometry-export.md +75 -0
  33. ras2cng-0.1.0/docs/user-guide/overview.md +44 -0
  34. ras2cng-0.1.0/docs/user-guide/pmtiles.md +72 -0
  35. ras2cng-0.1.0/docs/user-guide/postgis-sync.md +66 -0
  36. ras2cng-0.1.0/docs/user-guide/results-export.md +85 -0
  37. ras2cng-0.1.0/examples/00_using_ras_examples.py +85 -0
  38. ras2cng-0.1.0/examples/01_export_geometry.py +124 -0
  39. ras2cng-0.1.0/examples/02_export_results.py +142 -0
  40. ras2cng-0.1.0/examples/03_duckdb_queries.py +150 -0
  41. ras2cng-0.1.0/examples/04_generate_pmtiles.py +111 -0
  42. ras2cng-0.1.0/examples/05_cloud_native_stack.py +167 -0
  43. ras2cng-0.1.0/mkdocs.yml +101 -0
  44. ras2cng-0.1.0/pyproject.toml +93 -0
  45. ras2cng-0.1.0/pytest.ini +4 -0
  46. ras2cng-0.1.0/ras2cng/__init__.py +21 -0
  47. ras2cng-0.1.0/ras2cng/cli.py +164 -0
  48. ras2cng-0.1.0/ras2cng/duckdb_session.py +102 -0
  49. ras2cng-0.1.0/ras2cng/geometry.py +177 -0
  50. ras2cng-0.1.0/ras2cng/pmtiles.py +124 -0
  51. ras2cng-0.1.0/ras2cng/postgis_sync.py +58 -0
  52. ras2cng-0.1.0/ras2cng/results.py +96 -0
  53. ras2cng-0.1.0/tests/conftest.py +333 -0
  54. ras2cng-0.1.0/tests/test_cli.py +23 -0
  55. ras2cng-0.1.0/tests/test_duckdb_register.py +6 -0
  56. ras2cng-0.1.0/tests/test_full_extraction.py +256 -0
  57. ras2cng-0.1.0/tests/test_geometry_detection.py +14 -0
  58. ras2cng-0.1.0/tests/test_results_join.py +50 -0
  59. ras2cng-0.1.0/uv.lock +3832 -0
@@ -0,0 +1,38 @@
1
+ name: Deploy Docs
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+ paths:
8
+ - "docs/**"
9
+ - "ras2cng/**"
10
+ - "mkdocs.yml"
11
+ workflow_dispatch:
12
+
13
+ permissions:
14
+ contents: write
15
+
16
+ jobs:
17
+ deploy:
18
+ runs-on: ubuntu-latest
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+ with:
22
+ fetch-depth: 0 # needed for git-revision-date-localized
23
+
24
+ - name: Install uv
25
+ uses: astral-sh/setup-uv@v3
26
+
27
+ - name: Set up Python
28
+ uses: actions/setup-python@v5
29
+ with:
30
+ python-version: "3.12"
31
+
32
+ - name: Install docs dependencies
33
+ run: |
34
+ pip install -r docs/requirements-docs.txt
35
+ pip install -e .
36
+
37
+ - name: Deploy to GitHub Pages
38
+ run: mkdocs gh-deploy --force
@@ -0,0 +1,16 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ dist/
5
+ build/
6
+ .eggs/
7
+ *.egg
8
+ .venv/
9
+ .env
10
+ .pytest_cache/
11
+ outputs/
12
+ out/
13
+ agent_tasks/
14
+ *.parquet
15
+ *.pmtiles
16
+ site/
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,15 @@
1
+ version: 2
2
+
3
+ build:
4
+ os: ubuntu-22.04
5
+ tools:
6
+ python: "3.12"
7
+
8
+ mkdocs:
9
+ configuration: mkdocs.yml
10
+
11
+ python:
12
+ install:
13
+ - requirements: docs/requirements-docs.txt
14
+ - method: pip
15
+ path: .
@@ -0,0 +1,55 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ **ras2cng** (RAS to Cloud Native GIS) — CLI tool for exporting HEC-RAS geometry and results to GeoParquet, querying with DuckDB, generating PMTiles vector/raster tiles, and syncing to PostGIS. Built on [`ras-commander`](https://github.com/gpt-cmdr/ras-commander) for HEC-RAS file parsing.
8
+
9
+ ## Build & Development Commands
10
+
11
+ ```bash
12
+ # Install with all optional dependencies (creates/updates .venv and uv.lock)
13
+ uv sync --all-extras
14
+
15
+ # Run tests
16
+ uv run pytest
17
+
18
+ # Run a single test
19
+ uv run pytest tests/test_geometry_detection.py -v
20
+
21
+ # Run the CLI
22
+ uv run ras2cng --help
23
+
24
+ # Build distributable wheel
25
+ uv build
26
+
27
+ # Add a runtime dependency
28
+ uv add somepackage
29
+
30
+ # Add a dev-only dependency
31
+ uv add --dev somepackage
32
+ ```
33
+
34
+ Python >= 3.10 required (`.python-version` pins 3.12). Virtual environment is managed by uv in `.venv/`.
35
+
36
+ ## Architecture
37
+
38
+ **CLI layer** (`cli.py`): Typer app with 5 commands (`geometry`, `results`, `query`, `pmtiles`, `sync`). Uses lazy imports — heavy dependencies are imported inside command functions, not at module level.
39
+
40
+ **Core modules** — each handles one concern:
41
+ - `geometry.py` — Detects file type (HDF `.g??.hdf` vs text `.g??`) and routes to the appropriate ras-commander parser (`HdfMesh`, `HdfXsec`, `GeomParser`). Falls back from mesh cell polygons to points if polygons unavailable.
42
+ - `results.py` — Exports 2D mesh summary variables from plan HDF files. When results are points and a polygon geometry file is provided, joins results onto polygons via `mesh_name`/`cell_id` merge.
43
+ - `duckdb_session.py` — `DuckSession` class wraps DuckDB with auto-loaded spatial extension. `register_parquet()` detects WKB geometry columns and converts them to DuckDB GEOMETRY type. The table alias is always `_`.
44
+ - `pmtiles.py` — Dispatches between vector (GeoParquet → GeoJSON → tippecanoe → PMTiles) and raster (GeoTIFF → gdal_translate → pmtiles) pipelines. Requires external CLIs: `tippecanoe`, `gdal_translate`, `pmtiles`.
45
+ - `postgis_sync.py` — GeoParquet → PostGIS via SQLAlchemy/GeoAlchemy2 with automatic spatial index creation.
46
+
47
+ **Data flow**: HEC-RAS files → ras-commander → GeoDataFrame → GeoParquet (snappy compression). All output uses `to_parquet(..., compression="snappy", index=False)`.
48
+
49
+ ## Key Conventions
50
+
51
+ - ras-commander normalizes column names to **snake_case** (e.g., "Maximum Depth" → `maximum_depth`)
52
+ - DuckDB queries use `_` as the table name placeholder
53
+ - Geometry layers: `mesh_cells`, `cross_sections`, `centerlines`
54
+ - File type detection is suffix-based: `.g01.hdf` = HDF geometry, `.g01` = text geometry, `.p01.hdf` = plan results
55
+ - Tests mock ras-commander calls since actual HEC-RAS model files are not in the repo
ras2cng-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 William M. Katzenmeyer, P.E., C.F.M. / CLB Engineering
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
ras2cng-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,195 @@
1
+ Metadata-Version: 2.4
2
+ Name: ras2cng
3
+ Version: 0.1.0
4
+ Summary: CLI for exporting HEC-RAS geometry/results to cloud-native GIS formats (GeoParquet, PMTiles, DuckDB, PostGIS)
5
+ Project-URL: Homepage, https://github.com/gpt-cmdr/ras2cng
6
+ Project-URL: Repository, https://github.com/gpt-cmdr/ras2cng
7
+ Project-URL: Documentation, https://gpt-cmdr.github.io/ras2cng/
8
+ Project-URL: Bug Tracker, https://github.com/gpt-cmdr/ras2cng/issues
9
+ Author-email: "William M. Katzenmeyer, P.E., C.F.M." <bill@clbengineering.com>
10
+ License: MIT License
11
+
12
+ Copyright (c) 2024 William M. Katzenmeyer, P.E., C.F.M. / CLB Engineering
13
+
14
+ Permission is hereby granted, free of charge, to any person obtaining a copy
15
+ of this software and associated documentation files (the "Software"), to deal
16
+ in the Software without restriction, including without limitation the rights
17
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18
+ copies of the Software, and to permit persons to whom the Software is
19
+ furnished to do so, subject to the following conditions:
20
+
21
+ The above copyright notice and this permission notice shall be included in all
22
+ copies or substantial portions of the Software.
23
+
24
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30
+ SOFTWARE.
31
+ License-File: LICENSE
32
+ Keywords: cloud-native-gis,duckdb,flood-modeling,geoparquet,geospatial,hec-ras,hydraulics,pmtiles,postgis,ras-commander
33
+ Classifier: Development Status :: 4 - Beta
34
+ Classifier: Environment :: Console
35
+ Classifier: Intended Audience :: Developers
36
+ Classifier: Intended Audience :: Science/Research
37
+ Classifier: License :: OSI Approved :: MIT License
38
+ Classifier: Operating System :: OS Independent
39
+ Classifier: Programming Language :: Python :: 3
40
+ Classifier: Programming Language :: Python :: 3.10
41
+ Classifier: Programming Language :: Python :: 3.11
42
+ Classifier: Programming Language :: Python :: 3.12
43
+ Classifier: Topic :: Scientific/Engineering :: GIS
44
+ Classifier: Topic :: Scientific/Engineering :: Hydrology
45
+ Classifier: Topic :: Utilities
46
+ Requires-Python: >=3.10
47
+ Requires-Dist: geopandas>=0.14.0
48
+ Requires-Dist: pandas>=2.0.0
49
+ Requires-Dist: pyarrow>=14.0.0
50
+ Requires-Dist: ras-commander>=0.89.0
51
+ Requires-Dist: rich>=13.0.0
52
+ Requires-Dist: typer>=0.9.0
53
+ Provides-Extra: all
54
+ Requires-Dist: duckdb>=1.0.0; extra == 'all'
55
+ Requires-Dist: geoalchemy2>=0.14.0; extra == 'all'
56
+ Requires-Dist: psycopg2-binary>=2.9.0; extra == 'all'
57
+ Requires-Dist: rasterio>=1.3.0; extra == 'all'
58
+ Requires-Dist: sqlalchemy>=2.0.0; extra == 'all'
59
+ Provides-Extra: duckdb
60
+ Requires-Dist: duckdb>=1.0.0; extra == 'duckdb'
61
+ Provides-Extra: pmtiles
62
+ Requires-Dist: rasterio>=1.3.0; extra == 'pmtiles'
63
+ Provides-Extra: postgis
64
+ Requires-Dist: geoalchemy2>=0.14.0; extra == 'postgis'
65
+ Requires-Dist: psycopg2-binary>=2.9.0; extra == 'postgis'
66
+ Requires-Dist: sqlalchemy>=2.0.0; extra == 'postgis'
67
+ Description-Content-Type: text/markdown
68
+
69
+ # ras2cng — RAS to Cloud Native GIS
70
+
71
+ [![PyPI version](https://badge.fury.io/py/ras2cng.svg)](https://badge.fury.io/py/ras2cng)
72
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/)
73
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
74
+
75
+ CLI tool for exporting HEC-RAS **geometry** and **results** to cloud-native GIS formats:
76
+ **GeoParquet**, **DuckDB**, **PMTiles**, and **PostGIS**.
77
+
78
+ Built on [`ras-commander`](https://github.com/gpt-cmdr/ras-commander) for HEC-RAS file parsing.
79
+
80
+ ## Installation
81
+
82
+ ```bash
83
+ # Core (geometry + results export)
84
+ pip install ras2cng
85
+
86
+ # All optional extras (DuckDB analytics, PostGIS sync, PMTiles rasterio)
87
+ pip install "ras2cng[all]"
88
+
89
+ # Individual extras
90
+ pip install "ras2cng[duckdb]" # DuckDB SQL analytics
91
+ pip install "ras2cng[postgis]" # PostGIS sync
92
+ pip install "ras2cng[pmtiles]" # rasterio (PMTiles also needs tippecanoe + pmtiles CLIs)
93
+ ```
94
+
95
+ ## Quick Start
96
+
97
+ ```bash
98
+ # Export mesh cell geometry from HDF
99
+ ras2cng geometry model.g01.hdf mesh_cells.parquet --layer mesh_cells
100
+
101
+ # Export max depth results joined to polygon geometry
102
+ ras2cng results model.p01.hdf max_depth.parquet \
103
+ --geometry mesh_cells.parquet --var "Maximum Depth"
104
+
105
+ # Query with DuckDB (use _ as table name)
106
+ ras2cng query max_depth.parquet \
107
+ "SELECT mesh_name, AVG(maximum_depth) FROM _ GROUP BY mesh_name"
108
+
109
+ # Generate PMTiles (requires tippecanoe + pmtiles on PATH)
110
+ ras2cng pmtiles max_depth.parquet flood_depth.pmtiles --layer flood --min-zoom 8 --max-zoom 14
111
+
112
+ # Sync to PostGIS
113
+ ras2cng sync max_depth.parquet "postgresql://user:pass@host/db" max_depth --schema hydraulics
114
+ ```
115
+
116
+ ## Python API
117
+
118
+ ```python
119
+ from ras2cng import (
120
+ export_geometry_layers,
121
+ export_results_layer,
122
+ export_all_variables,
123
+ DuckSession,
124
+ query_parquet,
125
+ generate_pmtiles_from_input,
126
+ sync_to_postgres,
127
+ )
128
+ from pathlib import Path
129
+
130
+ # Export geometry
131
+ export_geometry_layers(Path("model.g01.hdf"), Path("mesh_cells.parquet"), layer="mesh_cells")
132
+
133
+ # Export results joined to polygon geometry
134
+ export_results_layer(
135
+ plan_hdf=Path("model.p01.hdf"),
136
+ output=Path("max_depth.parquet"),
137
+ variable="Maximum Depth",
138
+ geom_file=Path("mesh_cells.parquet"),
139
+ )
140
+
141
+ # DuckDB query (table alias is always _)
142
+ df = query_parquet(Path("max_depth.parquet"), "SELECT * FROM _ WHERE maximum_depth > 3.0")
143
+
144
+ # Advanced DuckDB session with spatial
145
+ with DuckSession() as duck:
146
+ duck.register_parquet("max_depth.parquet")
147
+ df = duck.query("SELECT mesh_name, MAX(maximum_depth) FROM _ GROUP BY mesh_name")
148
+ ```
149
+
150
+ ## Extractable Data
151
+
152
+ ### Geometry Layers
153
+
154
+ | Layer | Geometry | Source |
155
+ |---|---|---|
156
+ | `mesh_cells` | Polygon (Point fallback) | HDF geometry only (`*.g??.hdf`) |
157
+ | `cross_sections` | LineString | HDF geometry + text geometry (`*.g??`) |
158
+ | `centerlines` | LineString | HDF geometry + text geometry |
159
+
160
+ ### Results Variables
161
+
162
+ Exported from plan HDF files (`*.p??.hdf`). Common 2D mesh summary variables:
163
+
164
+ - `Maximum Depth` → `maximum_depth`
165
+ - `Maximum Water Surface` → `maximum_water_surface`
166
+ - `Maximum Velocity` → `maximum_velocity`
167
+
168
+ Column names are **snake_case** (ras-commander normalization). Use `--all` to export every available variable.
169
+
170
+ ### Output Formats
171
+
172
+ | Format | Command | Requirements |
173
+ |---|---|---|
174
+ | GeoParquet | `geometry`, `results` | Built-in |
175
+ | DuckDB SQL | `query` | `pip install "ras2cng[duckdb]"` |
176
+ | Vector PMTiles | `pmtiles` | tippecanoe + pmtiles CLIs |
177
+ | Raster PMTiles | `pmtiles` | gdal_translate + pmtiles CLIs |
178
+ | PostGIS | `sync` | `pip install "ras2cng[postgis]"` |
179
+
180
+ ## External CLIs for PMTiles
181
+
182
+ ```bash
183
+ # via conda-forge
184
+ conda install -c conda-forge tippecanoe pmtiles
185
+ ```
186
+
187
+ Or download from [felt/tippecanoe](https://github.com/felt/tippecanoe/releases) and [protomaps/go-pmtiles](https://github.com/protomaps/go-pmtiles/releases).
188
+
189
+ ## Documentation
190
+
191
+ Full documentation: [https://gpt-cmdr.github.io/ras2cng/](https://gpt-cmdr.github.io/ras2cng/)
192
+
193
+ ## License
194
+
195
+ MIT License — see [LICENSE](LICENSE) for details.
@@ -0,0 +1,127 @@
1
+ # ras2cng — RAS to Cloud Native GIS
2
+
3
+ [![PyPI version](https://badge.fury.io/py/ras2cng.svg)](https://badge.fury.io/py/ras2cng)
4
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+
7
+ CLI tool for exporting HEC-RAS **geometry** and **results** to cloud-native GIS formats:
8
+ **GeoParquet**, **DuckDB**, **PMTiles**, and **PostGIS**.
9
+
10
+ Built on [`ras-commander`](https://github.com/gpt-cmdr/ras-commander) for HEC-RAS file parsing.
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ # Core (geometry + results export)
16
+ pip install ras2cng
17
+
18
+ # All optional extras (DuckDB analytics, PostGIS sync, PMTiles rasterio)
19
+ pip install "ras2cng[all]"
20
+
21
+ # Individual extras
22
+ pip install "ras2cng[duckdb]" # DuckDB SQL analytics
23
+ pip install "ras2cng[postgis]" # PostGIS sync
24
+ pip install "ras2cng[pmtiles]" # rasterio (PMTiles also needs tippecanoe + pmtiles CLIs)
25
+ ```
26
+
27
+ ## Quick Start
28
+
29
+ ```bash
30
+ # Export mesh cell geometry from HDF
31
+ ras2cng geometry model.g01.hdf mesh_cells.parquet --layer mesh_cells
32
+
33
+ # Export max depth results joined to polygon geometry
34
+ ras2cng results model.p01.hdf max_depth.parquet \
35
+ --geometry mesh_cells.parquet --var "Maximum Depth"
36
+
37
+ # Query with DuckDB (use _ as table name)
38
+ ras2cng query max_depth.parquet \
39
+ "SELECT mesh_name, AVG(maximum_depth) FROM _ GROUP BY mesh_name"
40
+
41
+ # Generate PMTiles (requires tippecanoe + pmtiles on PATH)
42
+ ras2cng pmtiles max_depth.parquet flood_depth.pmtiles --layer flood --min-zoom 8 --max-zoom 14
43
+
44
+ # Sync to PostGIS
45
+ ras2cng sync max_depth.parquet "postgresql://user:pass@host/db" max_depth --schema hydraulics
46
+ ```
47
+
48
+ ## Python API
49
+
50
+ ```python
51
+ from ras2cng import (
52
+ export_geometry_layers,
53
+ export_results_layer,
54
+ export_all_variables,
55
+ DuckSession,
56
+ query_parquet,
57
+ generate_pmtiles_from_input,
58
+ sync_to_postgres,
59
+ )
60
+ from pathlib import Path
61
+
62
+ # Export geometry
63
+ export_geometry_layers(Path("model.g01.hdf"), Path("mesh_cells.parquet"), layer="mesh_cells")
64
+
65
+ # Export results joined to polygon geometry
66
+ export_results_layer(
67
+ plan_hdf=Path("model.p01.hdf"),
68
+ output=Path("max_depth.parquet"),
69
+ variable="Maximum Depth",
70
+ geom_file=Path("mesh_cells.parquet"),
71
+ )
72
+
73
+ # DuckDB query (table alias is always _)
74
+ df = query_parquet(Path("max_depth.parquet"), "SELECT * FROM _ WHERE maximum_depth > 3.0")
75
+
76
+ # Advanced DuckDB session with spatial
77
+ with DuckSession() as duck:
78
+ duck.register_parquet("max_depth.parquet")
79
+ df = duck.query("SELECT mesh_name, MAX(maximum_depth) FROM _ GROUP BY mesh_name")
80
+ ```
81
+
82
+ ## Extractable Data
83
+
84
+ ### Geometry Layers
85
+
86
+ | Layer | Geometry | Source |
87
+ |---|---|---|
88
+ | `mesh_cells` | Polygon (Point fallback) | HDF geometry only (`*.g??.hdf`) |
89
+ | `cross_sections` | LineString | HDF geometry + text geometry (`*.g??`) |
90
+ | `centerlines` | LineString | HDF geometry + text geometry |
91
+
92
+ ### Results Variables
93
+
94
+ Exported from plan HDF files (`*.p??.hdf`). Common 2D mesh summary variables:
95
+
96
+ - `Maximum Depth` → `maximum_depth`
97
+ - `Maximum Water Surface` → `maximum_water_surface`
98
+ - `Maximum Velocity` → `maximum_velocity`
99
+
100
+ Column names are **snake_case** (ras-commander normalization). Use `--all` to export every available variable.
101
+
102
+ ### Output Formats
103
+
104
+ | Format | Command | Requirements |
105
+ |---|---|---|
106
+ | GeoParquet | `geometry`, `results` | Built-in |
107
+ | DuckDB SQL | `query` | `pip install "ras2cng[duckdb]"` |
108
+ | Vector PMTiles | `pmtiles` | tippecanoe + pmtiles CLIs |
109
+ | Raster PMTiles | `pmtiles` | gdal_translate + pmtiles CLIs |
110
+ | PostGIS | `sync` | `pip install "ras2cng[postgis]"` |
111
+
112
+ ## External CLIs for PMTiles
113
+
114
+ ```bash
115
+ # via conda-forge
116
+ conda install -c conda-forge tippecanoe pmtiles
117
+ ```
118
+
119
+ Or download from [felt/tippecanoe](https://github.com/felt/tippecanoe/releases) and [protomaps/go-pmtiles](https://github.com/protomaps/go-pmtiles/releases).
120
+
121
+ ## Documentation
122
+
123
+ Full documentation: [https://gpt-cmdr.github.io/ras2cng/](https://gpt-cmdr.github.io/ras2cng/)
124
+
125
+ ## License
126
+
127
+ MIT License — see [LICENSE](LICENSE) for details.
@@ -0,0 +1,28 @@
1
+ # Acknowledgments
2
+
3
+ ## ras-commander
4
+
5
+ ras2cng is built on top of [ras-commander](https://github.com/gpt-cmdr/ras-commander), the
6
+ Python library for HEC-RAS automation and data extraction. ras-commander handles all the
7
+ complexity of HEC-RAS HDF file parsing, text geometry parsing, and result extraction.
8
+
9
+ ## Cloud-Native Geospatial Stack
10
+
11
+ ras2cng uses several excellent open-source projects in its pipeline:
12
+
13
+ - [Apache Parquet / PyArrow](https://arrow.apache.org/) — columnar storage format
14
+ - [GeoParquet](https://geoparquet.org/) — geospatial extension to Parquet
15
+ - [DuckDB](https://duckdb.org/) — in-process analytical SQL engine
16
+ - [PMTiles / Protomaps](https://protomaps.com/) — serverless tile archive format
17
+ - [tippecanoe](https://github.com/felt/tippecanoe) — vector tile generation
18
+ - [PostGIS](https://postgis.net/) — spatial extension for PostgreSQL
19
+ - [GeoPandas](https://geopandas.org/) — geospatial DataFrames for Python
20
+ - [Marimo](https://marimo.io/) — reactive Python notebooks
21
+
22
+ ## CLB Engineering
23
+
24
+ ras2cng is developed and maintained by [CLB Engineering](https://clbengineering.com), a water
25
+ resources engineering firm specializing in flood modeling, hydraulic analysis, and cloud-native
26
+ geospatial tooling.
27
+
28
+ **William M. Katzenmeyer, P.E., C.F.M.** — primary developer
@@ -0,0 +1,45 @@
1
+ # Cloud-Native GIS Philosophy
2
+
3
+ ## The Traditional Geospatial Tax
4
+
5
+ Traditional GIS workflows impose significant overhead on hydraulic model delivery:
6
+
7
+ - Results must be exported to Shapefile or File GDB
8
+ - A GIS analyst must symbolize, project, and publish to a map server
9
+ - Users need licensed GIS software to view or query results
10
+ - Every analysis requires loading the full dataset into memory
11
+
12
+ ## Cloud-Native Formats Break This Pattern
13
+
14
+ Cloud-native geospatial formats were designed for the web and cloud environments from the ground up:
15
+
16
+ **GeoParquet** stores geometry alongside attributes in Apache Parquet's columnar format. Reading
17
+ 10 columns out of 50 reads only those columns from disk — not the full row. Snappy compression
18
+ achieves 5–10x size reduction versus Shapefiles. The Arrow memory layout enables zero-copy
19
+ transfer into pandas, DuckDB, and other analytical engines.
20
+
21
+ **PMTiles** is a single archive file containing all zoom levels of a tile pyramid. HTTP range
22
+ requests fetch only the tiles needed for the current viewport. No tile server process needs to
23
+ run — serve directly from S3, Cloudflare R2, or a CDN. A flood model result that previously
24
+ required a $500/month tile server can be served for pennies.
25
+
26
+ **DuckDB** is an in-process analytical SQL engine that reads GeoParquet files directly with its
27
+ spatial extension. Complex queries across millions of mesh cells run in seconds on a laptop.
28
+ No server to provision, no connection pool to manage, no network latency.
29
+
30
+ ## Why This Matters for Flood Modeling
31
+
32
+ Flood model results are uniquely suited to the cloud-native stack:
33
+
34
+ 1. **Large**: 2D mesh models have 100k–10M cells. Columnar formats make per-column reads fast.
35
+ 2. **Spatial**: Every result is geometry. PMTiles serves flood extents at web speed.
36
+ 3. **Queryable**: "Show all cells where depth > 2 ft" is a trivial SQL filter on GeoParquet.
37
+ 4. **Shareable**: A single `.pmtiles` file on S3 can be embedded in any web map, shared via URL,
38
+ or downloaded without special software.
39
+
40
+ ## The ras2cng Philosophy
41
+
42
+ ras2cng is the bridge between HEC-RAS simulation outputs and the cloud-native geospatial stack.
43
+ It handles the parsing complexity of HEC-RAS HDF files (via ras-commander) and produces
44
+ standards-compliant GeoParquet that works everywhere — QGIS, DuckDB, MapLibre, PostGIS,
45
+ Observable, R, JavaScript.
@@ -0,0 +1,98 @@
1
+ # CLI Reference
2
+
3
+ ## ras2cng --help
4
+
5
+ ```
6
+ Usage: ras2cng [OPTIONS] COMMAND [ARGS]...
7
+
8
+ Export HEC-RAS geometry/results to GeoParquet; query with DuckDB; generate
9
+ PMTiles; sync to PostGIS.
10
+
11
+ Commands:
12
+ geometry Export HEC-RAS geometry to GeoParquet.
13
+ results Export HEC-RAS 2D mesh summary results to GeoParquet.
14
+ query Query GeoParquet files using DuckDB SQL.
15
+ pmtiles Generate PMTiles from GeoParquet (vector) or GeoTIFF (raster).
16
+ sync Sync GeoParquet data to PostGIS.
17
+ ```
18
+
19
+ ## ras2cng geometry
20
+
21
+ ```
22
+ Usage: ras2cng geometry [OPTIONS] GEOM_FILE OUTPUT
23
+
24
+ Export HEC-RAS geometry to GeoParquet.
25
+
26
+ Arguments:
27
+ GEOM_FILE HEC-RAS geometry file (*.g??) or geometry HDF (*.g??.hdf)
28
+ OUTPUT Output GeoParquet file path
29
+
30
+ Options:
31
+ -l, --layer TEXT Geometry layer: mesh_cells, cross_sections, centerlines
32
+ ```
33
+
34
+ ## ras2cng results
35
+
36
+ ```
37
+ Usage: ras2cng results [OPTIONS] PLAN_HDF OUTPUT
38
+
39
+ Export HEC-RAS 2D mesh summary results to GeoParquet.
40
+
41
+ Arguments:
42
+ PLAN_HDF HEC-RAS plan HDF file (*.p??.hdf)
43
+ OUTPUT Output GeoParquet path (or directory when using --all)
44
+
45
+ Options:
46
+ -g, --geometry PATH Geometry GeoParquet for spatial join
47
+ -v, --var TEXT Result variable to export [default: Maximum Depth]
48
+ --all Export all available summary variables to the output directory
49
+ ```
50
+
51
+ ## ras2cng query
52
+
53
+ ```
54
+ Usage: ras2cng query [OPTIONS] INPUT_FILE SQL
55
+
56
+ Query GeoParquet files using DuckDB SQL.
57
+
58
+ Arguments:
59
+ INPUT_FILE Input GeoParquet file
60
+ SQL SQL query (use _ as table name)
61
+
62
+ Options:
63
+ -o, --output PATH Optional output file (CSV or Parquet)
64
+ ```
65
+
66
+ ## ras2cng pmtiles
67
+
68
+ ```
69
+ Usage: ras2cng pmtiles [OPTIONS] INPUT_FILE OUTPUT
70
+
71
+ Generate PMTiles from GeoParquet (vector) or GeoTIFF (raster).
72
+
73
+ Arguments:
74
+ INPUT_FILE Input GeoParquet file or GeoTIFF
75
+ OUTPUT Output PMTiles file path
76
+
77
+ Options:
78
+ -l, --layer TEXT Vector tile layer name [default: layer]
79
+ --min-zoom INTEGER Minimum zoom
80
+ --max-zoom INTEGER Maximum zoom
81
+ ```
82
+
83
+ ## ras2cng sync
84
+
85
+ ```
86
+ Usage: ras2cng sync [OPTIONS] INPUT_FILE POSTGRES_URI TABLE_NAME
87
+
88
+ Sync GeoParquet data to PostGIS.
89
+
90
+ Arguments:
91
+ INPUT_FILE Input GeoParquet file
92
+ POSTGRES_URI PostgreSQL connection URI
93
+ TABLE_NAME Target table name
94
+
95
+ Options:
96
+ -s, --schema TEXT Target schema [default: public]
97
+ --if-exists TEXT replace|append|fail [default: replace]
98
+ ```
@@ -0,0 +1,3 @@
1
+ # ras2cng.duckdb_session
2
+
3
+ ::: ras2cng.duckdb_session
@@ -0,0 +1,3 @@
1
+ # ras2cng.geometry
2
+
3
+ ::: ras2cng.geometry