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.
- ras2cng-0.1.0/.github/workflows/docs.yml +38 -0
- ras2cng-0.1.0/.gitignore +16 -0
- ras2cng-0.1.0/.python-version +1 -0
- ras2cng-0.1.0/.readthedocs.yaml +15 -0
- ras2cng-0.1.0/CLAUDE.md +55 -0
- ras2cng-0.1.0/LICENSE +21 -0
- ras2cng-0.1.0/PKG-INFO +195 -0
- ras2cng-0.1.0/README.md +127 -0
- ras2cng-0.1.0/docs/about/acknowledgments.md +28 -0
- ras2cng-0.1.0/docs/about/cloud-native-gis.md +45 -0
- ras2cng-0.1.0/docs/api/cli.md +98 -0
- ras2cng-0.1.0/docs/api/duckdb_session.md +3 -0
- ras2cng-0.1.0/docs/api/geometry.md +3 -0
- ras2cng-0.1.0/docs/api/index.md +34 -0
- ras2cng-0.1.0/docs/api/pmtiles.md +3 -0
- ras2cng-0.1.0/docs/api/postgis_sync.md +3 -0
- ras2cng-0.1.0/docs/api/results.md +3 -0
- ras2cng-0.1.0/docs/assets/ras2cng_logo.svg +95 -0
- ras2cng-0.1.0/docs/examples/00_using_ras_examples.md +20 -0
- ras2cng-0.1.0/docs/examples/01_export_geometry.md +29 -0
- ras2cng-0.1.0/docs/examples/02_export_results.md +27 -0
- ras2cng-0.1.0/docs/examples/03_duckdb_queries.md +23 -0
- ras2cng-0.1.0/docs/examples/04_generate_pmtiles.md +30 -0
- ras2cng-0.1.0/docs/examples/05_cloud_native_stack.md +26 -0
- ras2cng-0.1.0/docs/examples/index.md +42 -0
- ras2cng-0.1.0/docs/getting-started/cloud-native-stack.md +61 -0
- ras2cng-0.1.0/docs/getting-started/installation.md +62 -0
- ras2cng-0.1.0/docs/getting-started/quickstart.md +123 -0
- ras2cng-0.1.0/docs/index.md +91 -0
- ras2cng-0.1.0/docs/requirements-docs.txt +13 -0
- ras2cng-0.1.0/docs/user-guide/duckdb-queries.md +93 -0
- ras2cng-0.1.0/docs/user-guide/geometry-export.md +75 -0
- ras2cng-0.1.0/docs/user-guide/overview.md +44 -0
- ras2cng-0.1.0/docs/user-guide/pmtiles.md +72 -0
- ras2cng-0.1.0/docs/user-guide/postgis-sync.md +66 -0
- ras2cng-0.1.0/docs/user-guide/results-export.md +85 -0
- ras2cng-0.1.0/examples/00_using_ras_examples.py +85 -0
- ras2cng-0.1.0/examples/01_export_geometry.py +124 -0
- ras2cng-0.1.0/examples/02_export_results.py +142 -0
- ras2cng-0.1.0/examples/03_duckdb_queries.py +150 -0
- ras2cng-0.1.0/examples/04_generate_pmtiles.py +111 -0
- ras2cng-0.1.0/examples/05_cloud_native_stack.py +167 -0
- ras2cng-0.1.0/mkdocs.yml +101 -0
- ras2cng-0.1.0/pyproject.toml +93 -0
- ras2cng-0.1.0/pytest.ini +4 -0
- ras2cng-0.1.0/ras2cng/__init__.py +21 -0
- ras2cng-0.1.0/ras2cng/cli.py +164 -0
- ras2cng-0.1.0/ras2cng/duckdb_session.py +102 -0
- ras2cng-0.1.0/ras2cng/geometry.py +177 -0
- ras2cng-0.1.0/ras2cng/pmtiles.py +124 -0
- ras2cng-0.1.0/ras2cng/postgis_sync.py +58 -0
- ras2cng-0.1.0/ras2cng/results.py +96 -0
- ras2cng-0.1.0/tests/conftest.py +333 -0
- ras2cng-0.1.0/tests/test_cli.py +23 -0
- ras2cng-0.1.0/tests/test_duckdb_register.py +6 -0
- ras2cng-0.1.0/tests/test_full_extraction.py +256 -0
- ras2cng-0.1.0/tests/test_geometry_detection.py +14 -0
- ras2cng-0.1.0/tests/test_results_join.py +50 -0
- 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
|
ras2cng-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
ras2cng-0.1.0/CLAUDE.md
ADDED
|
@@ -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
|
+
[](https://badge.fury.io/py/ras2cng)
|
|
72
|
+
[](https://www.python.org/downloads/)
|
|
73
|
+
[](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.
|
ras2cng-0.1.0/README.md
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# ras2cng — RAS to Cloud Native GIS
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/py/ras2cng)
|
|
4
|
+
[](https://www.python.org/downloads/)
|
|
5
|
+
[](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
|
+
```
|