| name | hecras_parse_geometry |
| shared_corpus | true |
| harness_scope | shared |
| source_owner | gpt-cmdr |
| security_review | internal |
| description | Parses and modifies HEC-RAS plain text geometry files (.g##) using fixed-width
FORTRAN format. Handles cross sections, storage areas, bridges, culverts,
lateral structures, and Manning's n tables. Use when reading geometry files,
modifying cross sections, updating roughness, extracting structure data,
parsing .g## files, working with XS station-elevation data, or analyzing
bridge/culvert geometry. Keywords: parse, geometry, .g##, cross section, XS,
Manning's n, bridge, culvert, storage, fixed-width, lateral structure,
inline weir, 2D land cover, bank stations.
|
Parsing HEC-RAS Geometry Files
Primary Sources (read these for details):
- Implementation guide:
ras_commander/geom/AGENTS.md (parsing algorithms, API reference)
- Working examples:
examples/201_1d_plaintext_geometry.ipynb and examples/202_2d_plaintext_geometry.ipynb (comprehensive demonstrations)
Follow these quick-reference patterns for common tasks. Read the primary sources above for implementation details, parsing algorithms, and complete API documentation.
Quick Start Patterns
List Cross Sections
from ras_commander.geom.GeomCrossSection import GeomCrossSection
xs_df = GeomCrossSection.get_cross_sections("model.g01")
xs_df = GeomCrossSection.get_cross_sections(
"model.g01",
river="Ohio River",
reach="Reach 1"
)
Read Cross Section Geometry
df = GeomCrossSection.get_station_elevation(
"model.g01",
"Ohio River",
"Reach 1",
"1000"
)
banks = GeomCrossSection.get_bank_stations(
"model.g01",
"Ohio River",
"Reach 1",
"1000"
)
Modify Cross Section
df = GeomCrossSection.get_station_elevation(
"model.g01",
"Ohio River",
"Reach 1",
"1000"
)
df.loc[df['Station'].between(100, 200), 'Elevation'] -= 2.0
banks = GeomCrossSection.get_bank_stations(
"model.g01",
"Ohio River",
"Reach 1",
"1000"
)
GeomCrossSection.set_station_elevation(
"model.g01",
"Ohio River",
"Reach 1",
"1000",
df,
bank_left=banks['BankLeft'],
bank_right=banks['BankRight']
)
Update 2D Manning's n
from ras_commander.geom.GeomLandCover import GeomLandCover
lc_df = GeomLandCover.get_base_mannings_n("model.g01")
lc_df.loc[lc_df['LandCoverID'] == 42, 'ManningsN'] = 0.15
GeomLandCover.set_base_mannings_n("model.g01", lc_df)
Extract Storage Areas
from ras_commander.geom.GeomStorage import GeomStorage
storage_areas = GeomStorage.get_storage_areas("model.g01", exclude_2d=True)
df = GeomStorage.get_elevation_volume("model.g01", "Detention Basin 1")
Read Bridge Geometry
from ras_commander.geom.GeomBridge import GeomBridge
bridges = GeomBridge.get_bridges("model.g01")
deck_df = GeomBridge.get_deck(
"model.g01",
"Ohio River",
"Reach 1",
"1000"
)
piers_df = GeomBridge.get_piers(
"model.g01",
"Ohio River",
"Reach 1",
"1000"
)
Read Culverts
from ras_commander.geom.GeomCulvert import GeomCulvert
culverts_df = GeomCulvert.get_all("model.g01")
culverts_df = GeomCulvert.get_all(
"model.g01",
river="Ohio River",
reach="Reach 1"
)
Module Organization
| Module | Class | Purpose |
|---|
| GeomParser | GeomParser | Fixed-width format parsing utilities |
| GeomCrossSection | GeomCrossSection | 1D cross section operations |
| GeomStorage | GeomStorage | Storage area elevation-volume curves |
| GeomLandCover | GeomLandCover | 2D Manning's n land cover tables |
| GeomLateral | GeomLateral | Lateral structures and SA/2D connections |
| GeomInlineWeir | GeomInlineWeir | Inline weir structures |
| GeomBridge | GeomBridge | Bridge/culvert structure geometry |
| GeomCulvert | GeomCulvert | Culvert data extraction |
| GeomPreprocessor | GeomPreprocessor | Geometry preprocessor file management |
Read ras_commander/geom/AGENTS.md for complete API documentation.
Critical Implementation Notes
Bank Station Interpolation
Rely on set_station_elevation() to ensure bank stations appear as exact points automatically:
- If bank station exists in data: uses it directly
- If bank station missing: interpolates elevation and inserts point
- Do not manually interpolate bank stations -- the API handles this
500 Point Limit
HEC-RAS enforces maximum 500 points per cross section:
if len(df) > 500:
raise ValueError(f"Cross section has {len(df)} points (max 500)")
Case-Sensitive Identifiers
River, Reach, and RS are case-sensitive:
GeomCrossSection.get_station_elevation(geom_file, "Ohio River", ...)
GeomCrossSection.get_station_elevation(geom_file, "ohio river", ...)
Use exact casing from get_cross_sections() DataFrame.
Automatic Backups
All write operations create .bak files:
Original: model.g01
Modified: model.g01
Backup: model.g01.bak
Fixed-Width Format
HEC-RAS uses FORTRAN-era formatting:
- Column width: 8 characters per value
- Values per line: 10 values (80 characters total)
- Count interpretation:
#Sta/Elev= 40 means 40 PAIRS (80 total values)
See ras_commander/geom/AGENTS.md for parsing algorithm details.
Common Workflows
Batch Modify All Cross Sections
xs_df = GeomCrossSection.get_cross_sections("model.g01")
for _, row in xs_df.iterrows():
river = row['River']
reach = row['Reach']
rs = row['RS']
df = GeomCrossSection.get_station_elevation("model.g01", river, reach, rs)
df['Elevation'] += 1.0
banks = GeomCrossSection.get_bank_stations("model.g01", river, reach, rs)
GeomCrossSection.set_station_elevation(
"model.g01",
river,
reach,
rs,
df,
bank_left=banks['BankLeft'],
bank_right=banks['BankRight']
)
Extract All Storage Curves
from ras_commander.geom.GeomStorage import GeomStorage
storage_areas = GeomStorage.get_storage_areas("model.g01", exclude_2d=True)
for area_name in storage_areas:
df = GeomStorage.get_elevation_volume("model.g01", area_name)
print(f"{area_name}: {len(df)} elevation points")
Survey All Culverts
from ras_commander.geom.GeomCulvert import GeomCulvert
culverts_df = GeomCulvert.get_all("model.g01")
shape_map = {
1: "Circular", 2: "Box", 3: "Pipe Arch", 4: "Ellipse",
5: "Arch", 6: "Semi-Circle", 7: "Low Profile Arch",
8: "High Profile Arch", 9: "Con Span"
}
for _, row in culverts_df.iterrows():
shape_name = shape_map[row['Shape']]
print(f"{row['River']} - {row['RS']}: {shape_name} culvert")
Error Handling
File Not Found
from pathlib import Path
if not Path(geom_file).exists():
raise FileNotFoundError(f"Geometry file not found: {geom_file}")
Invalid River/Reach/RS
xs_df = GeomCrossSection.get_cross_sections(geom_file)
print(xs_df[['River', 'Reach', 'RS']])
df = GeomCrossSection.get_station_elevation(
geom_file,
"Ohio River",
"Reach 1",
"1000"
)
Point Limit Exceeded
if len(df) > 500:
from scipy.interpolate import interp1d
f = interp1d(df['Station'], df['Elevation'])
new_stations = np.linspace(df['Station'].min(), df['Station'].max(), 450)
df = pd.DataFrame({
'Station': new_stations,
'Elevation': f(new_stations)
})
raise ValueError(f"Cross section has {len(df)} points (max 500)")
Primary Sources
Read these for complete details:
-
ras_commander/geom/AGENTS.md
- Parsing algorithms (fixed-width format, count interpretation)
- Complete API reference for all 9 modules
- Technical patterns and implementation notes
- Culvert shape codes table
- Deprecated class mappings
-
examples/201_1d_plaintext_geometry.ipynb and examples/202_2d_plaintext_geometry.ipynb
- Working code demonstrations for all modules
- Real HEC-RAS project examples
- Output visualizations
- Error handling examples
- Integration with other ras-commander features
Import Pattern
All classes use static methods - no instantiation required:
from ras_commander.geom.GeomCrossSection import GeomCrossSection
from ras_commander.geom.GeomStorage import GeomStorage
from ras_commander.geom.GeomBridge import GeomBridge
from ras_commander.geom.GeomCulvert import GeomCulvert
from ras_commander.geom.GeomLandCover import GeomLandCover
xs_df = GeomCrossSection.get_cross_sections("model.g01")
Cross-References
Rules (follow these):
.claude/rules/hec-ras/geometry.md -- Geometry domain overview, fixed-width format, bank stations
.claude/rules/python/state-machine-empty-line-handling.md -- Empty line handling in parsers
.claude/rules/python/api-first-principle.md -- API-first mandate
Agents (delegate when needed):
geometry-parser -- Delegate for complex geometry analysis
quality-assurance -- Delegate for geometry repair
Skills (related workflows):
qa_repair_geometry -- Use downstream for fixing geometry errors found during parsing
hecras_extract_results -- Use when parsing geometry alongside HDF results
Primary sources:
ras_commander/geom/AGENTS.md -- Complete geometry module documentation
examples/201_1d_plaintext_geometry.ipynb -- 1D cross section parsing
examples/202_2d_plaintext_geometry.ipynb -- 2D Manning's n tables
examples/205_extract_xs_xyz_from_geometry.ipynb -- XS coordinate extraction