ras-commander 0.47.0__py3-none-any.whl → 0.49.0__py3-none-any.whl
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.
- ras_commander/Decorators.py +18 -1
- ras_commander/HdfBase.py +307 -197
- ras_commander/HdfBndry.py +94 -287
- ras_commander/HdfFluvialPluvial.py +156 -239
- ras_commander/HdfInfiltration.py +410 -0
- ras_commander/HdfMesh.py +121 -41
- ras_commander/HdfPipe.py +127 -175
- ras_commander/HdfPlan.py +144 -58
- ras_commander/HdfPlot.py +104 -0
- ras_commander/HdfPump.py +76 -28
- ras_commander/HdfResultsMesh.py +186 -167
- ras_commander/HdfResultsPlan.py +76 -220
- ras_commander/HdfResultsPlot.py +182 -0
- ras_commander/HdfResultsXsec.py +185 -145
- ras_commander/HdfStruc.py +65 -35
- ras_commander/HdfUtils.py +435 -518
- ras_commander/HdfXsec.py +137 -127
- ras_commander/RasCmdr.py +13 -0
- ras_commander/RasExamples.py +14 -0
- ras_commander/RasGeo.py +11 -0
- ras_commander/RasGpt.py +8 -0
- ras_commander/RasMapper.py +105 -0
- ras_commander/RasPlan.py +30 -0
- ras_commander/RasPrj.py +34 -0
- ras_commander/RasToGo.py +16 -0
- ras_commander/RasUnsteady.py +15 -0
- ras_commander/RasUtils.py +31 -0
- ras_commander/__init__.py +10 -0
- {ras_commander-0.47.0.dist-info → ras_commander-0.49.0.dist-info}/METADATA +74 -9
- ras_commander-0.49.0.dist-info/RECORD +34 -0
- ras_commander-0.47.0.dist-info/RECORD +0 -30
- {ras_commander-0.47.0.dist-info → ras_commander-0.49.0.dist-info}/LICENSE +0 -0
- {ras_commander-0.47.0.dist-info → ras_commander-0.49.0.dist-info}/WHEEL +0 -0
- {ras_commander-0.47.0.dist-info → ras_commander-0.49.0.dist-info}/top_level.txt +0 -0
ras_commander/HdfXsec.py
CHANGED
@@ -6,6 +6,26 @@ from the https://github.com/fema-ffrd/rashdf library,
|
|
6
6
|
released under MIT license and Copyright (c) 2024 fema-ffrd
|
7
7
|
|
8
8
|
The file has been forked and modified for use in RAS Commander.
|
9
|
+
|
10
|
+
-----
|
11
|
+
|
12
|
+
All of the methods in this class are static and are designed to be used without instantiation.
|
13
|
+
|
14
|
+
Available Functions:
|
15
|
+
- get_cross_sections(): Extract cross sections from HDF geometry file
|
16
|
+
- get_river_centerlines(): Extract river centerlines from HDF geometry file
|
17
|
+
- get_river_stationing(): Calculate river stationing along centerlines
|
18
|
+
- get_river_reaches(): Return the model 1D river reach lines
|
19
|
+
- get_river_edge_lines(): Return the model river edge lines
|
20
|
+
- get_river_bank_lines(): Extract river bank lines from HDF geometry file
|
21
|
+
- _interpolate_station(): Private helper method for station interpolation
|
22
|
+
|
23
|
+
All functions follow the get_ prefix convention for methods that return data.
|
24
|
+
Private helper methods use the underscore prefix convention.
|
25
|
+
|
26
|
+
Each function returns a GeoDataFrame containing geometries and associated attributes
|
27
|
+
specific to the requested feature type. All functions include proper error handling
|
28
|
+
and logging.
|
9
29
|
"""
|
10
30
|
|
11
31
|
from pathlib import Path
|
@@ -28,54 +48,54 @@ logger = get_logger(__name__)
|
|
28
48
|
|
29
49
|
class HdfXsec:
|
30
50
|
"""
|
31
|
-
|
51
|
+
Handles cross-section and river geometry data extraction from HEC-RAS HDF files.
|
32
52
|
|
33
|
-
This class provides methods to extract and process
|
34
|
-
|
35
|
-
|
53
|
+
This class provides static methods to extract and process:
|
54
|
+
- Cross-section geometries and attributes
|
55
|
+
- River centerlines and reaches
|
56
|
+
- River edge and bank lines
|
57
|
+
- Station-elevation profiles
|
36
58
|
|
37
|
-
|
38
|
-
|
39
|
-
handling and data conversion.
|
59
|
+
All methods are designed to return GeoDataFrames with standardized geometries
|
60
|
+
and attributes following the HEC-RAS data structure.
|
40
61
|
|
41
62
|
Note:
|
42
|
-
|
43
|
-
|
44
|
-
|
63
|
+
Requires HEC-RAS geometry HDF files with standard structure and naming conventions.
|
64
|
+
All methods use proper error handling and logging.
|
65
|
+
"""
|
45
66
|
@staticmethod
|
46
67
|
@log_call
|
47
|
-
def
|
68
|
+
def get_cross_sections(hdf_path: str, datetime_to_str: bool = True, ras_object=None) -> gpd.GeoDataFrame:
|
48
69
|
"""
|
49
|
-
|
50
|
-
|
70
|
+
Extracts cross-section geometries and attributes from a HEC-RAS geometry HDF file.
|
71
|
+
|
51
72
|
Parameters
|
52
73
|
----------
|
53
74
|
hdf_path : str
|
54
|
-
Path to HDF file
|
75
|
+
Path to the HEC-RAS geometry HDF file
|
55
76
|
datetime_to_str : bool, optional
|
56
|
-
Convert datetime objects to strings,
|
77
|
+
Convert datetime objects to strings, defaults to True
|
57
78
|
ras_object : RasPrj, optional
|
58
|
-
RAS project object,
|
59
|
-
|
79
|
+
RAS project object for additional context, defaults to None
|
80
|
+
|
60
81
|
Returns
|
61
82
|
-------
|
62
83
|
gpd.GeoDataFrame
|
63
|
-
|
64
|
-
-
|
65
|
-
-
|
66
|
-
-
|
67
|
-
-
|
68
|
-
-
|
69
|
-
-
|
70
|
-
-
|
71
|
-
-
|
72
|
-
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
- Ineffective blocks data
|
84
|
+
Cross-section data with columns:
|
85
|
+
- geometry: LineString of cross-section path
|
86
|
+
- station_elevation: Station-elevation profile points
|
87
|
+
- mannings_n: Dictionary of Manning's n values and stations
|
88
|
+
- ineffective_blocks: List of ineffective flow area blocks
|
89
|
+
- River, Reach, RS: River system identifiers
|
90
|
+
- Name, Description: Cross-section labels
|
91
|
+
- Len Left/Channel/Right: Flow path lengths
|
92
|
+
- Left/Right Bank: Bank station locations
|
93
|
+
- Additional hydraulic parameters and attributes
|
94
|
+
|
95
|
+
Notes
|
96
|
+
-----
|
97
|
+
The returned GeoDataFrame includes the coordinate system from the HDF file
|
98
|
+
when available. All byte strings are converted to regular strings.
|
79
99
|
"""
|
80
100
|
try:
|
81
101
|
with h5py.File(hdf_path, 'r') as hdf:
|
@@ -216,70 +236,34 @@ class HdfXsec:
|
|
216
236
|
logging.error(f"Error processing cross-section data: {str(e)}")
|
217
237
|
return gpd.GeoDataFrame()
|
218
238
|
|
219
|
-
|
220
|
-
@staticmethod
|
221
|
-
@log_call
|
222
|
-
def _get_polylines(hdf_path: Path, path: str, info_name: str = "Polyline Info", parts_name: str = "Polyline Parts", points_name: str = "Polyline Points") -> List[LineString]:
|
223
|
-
"""
|
224
|
-
Helper method to extract polylines from HDF file.
|
225
|
-
|
226
|
-
[rest of docstring remains the same]
|
227
|
-
"""
|
228
|
-
try:
|
229
|
-
with h5py.File(hdf_path, 'r') as hdf_file:
|
230
|
-
polyline_info_path = f"{path}/{info_name}"
|
231
|
-
polyline_parts_path = f"{path}/{parts_name}"
|
232
|
-
polyline_points_path = f"{path}/{points_name}"
|
233
|
-
|
234
|
-
polyline_info = hdf_file[polyline_info_path][()]
|
235
|
-
polyline_parts = hdf_file[polyline_parts_path][()]
|
236
|
-
polyline_points = hdf_file[polyline_points_path][()]
|
237
|
-
|
238
|
-
geoms = []
|
239
|
-
for pnt_start, pnt_cnt, part_start, part_cnt in polyline_info:
|
240
|
-
points = polyline_points[pnt_start : pnt_start + pnt_cnt]
|
241
|
-
if part_cnt == 1:
|
242
|
-
geoms.append(LineString(points))
|
243
|
-
else:
|
244
|
-
parts = polyline_parts[part_start : part_start + part_cnt]
|
245
|
-
geoms.append(
|
246
|
-
MultiLineString(
|
247
|
-
list(
|
248
|
-
points[part_pnt_start : part_pnt_start + part_pnt_cnt]
|
249
|
-
for part_pnt_start, part_pnt_cnt in parts
|
250
|
-
)
|
251
|
-
)
|
252
|
-
)
|
253
|
-
return geoms
|
254
|
-
except Exception as e:
|
255
|
-
logger.error(f"Error getting polylines: {str(e)}")
|
256
|
-
return []
|
257
|
-
|
258
|
-
|
259
239
|
@staticmethod
|
260
240
|
@log_call
|
261
241
|
@standardize_input(file_type='geom_hdf')
|
262
|
-
def
|
242
|
+
def get_river_centerlines(hdf_path: Path, datetime_to_str: bool = False) -> GeoDataFrame:
|
263
243
|
"""
|
264
|
-
|
244
|
+
Extracts river centerline geometries and attributes from HDF geometry file.
|
265
245
|
|
266
246
|
Parameters
|
267
247
|
----------
|
268
248
|
hdf_path : Path
|
269
249
|
Path to the HEC-RAS geometry HDF file
|
270
250
|
datetime_to_str : bool, optional
|
271
|
-
Convert datetime objects to strings,
|
251
|
+
Convert datetime objects to strings, defaults to False
|
272
252
|
|
273
253
|
Returns
|
274
254
|
-------
|
275
255
|
GeoDataFrame
|
276
|
-
|
277
|
-
-
|
278
|
-
- Reach Name
|
279
|
-
-
|
280
|
-
-
|
281
|
-
|
282
|
-
|
256
|
+
River centerline data with columns:
|
257
|
+
- geometry: LineString of river centerline
|
258
|
+
- River Name, Reach Name: River system identifiers
|
259
|
+
- US/DS Type, Name: Upstream/downstream connection info
|
260
|
+
- length: Centerline length in project units
|
261
|
+
Additional attributes from the HDF file are included
|
262
|
+
|
263
|
+
Notes
|
264
|
+
-----
|
265
|
+
Returns an empty GeoDataFrame if no centerlines are found.
|
266
|
+
All string attributes are stripped of whitespace.
|
283
267
|
"""
|
284
268
|
try:
|
285
269
|
with h5py.File(hdf_path, 'r') as hdf_file:
|
@@ -289,18 +273,23 @@ class HdfXsec:
|
|
289
273
|
|
290
274
|
centerline_data = hdf_file["Geometry/River Centerlines"]
|
291
275
|
|
292
|
-
# Get attributes
|
276
|
+
# Get attributes directly from HDF dataset
|
293
277
|
attrs = centerline_data["Attributes"][()]
|
294
|
-
v_conv_val = np.vectorize(HdfUtils._convert_ras_hdf_value)
|
295
278
|
|
296
|
-
# Create dictionary
|
297
|
-
centerline_dict = {
|
298
|
-
|
299
|
-
|
300
|
-
|
279
|
+
# Create initial dictionary for DataFrame
|
280
|
+
centerline_dict = {}
|
281
|
+
|
282
|
+
# Process each attribute field
|
283
|
+
for name in attrs.dtype.names:
|
284
|
+
values = attrs[name]
|
285
|
+
if values.dtype.kind == 'S':
|
286
|
+
# Convert byte strings to regular strings
|
287
|
+
centerline_dict[name] = [val.decode('utf-8').strip() for val in values]
|
288
|
+
else:
|
289
|
+
centerline_dict[name] = values.tolist() # Convert numpy array to list
|
301
290
|
|
302
|
-
# Get
|
303
|
-
geoms =
|
291
|
+
# Get polylines using utility function
|
292
|
+
geoms = HdfBase.get_polylines_from_parts(
|
304
293
|
hdf_path,
|
305
294
|
"Geometry/River Centerlines",
|
306
295
|
info_name="Polyline Info",
|
@@ -312,30 +301,29 @@ class HdfXsec:
|
|
312
301
|
centerline_gdf = GeoDataFrame(
|
313
302
|
centerline_dict,
|
314
303
|
geometry=geoms,
|
315
|
-
crs=
|
304
|
+
crs=HdfBase.get_projection(hdf_path)
|
316
305
|
)
|
317
306
|
|
318
|
-
#
|
307
|
+
# Clean up string columns
|
319
308
|
str_columns = ['River Name', 'Reach Name', 'US Type',
|
320
|
-
|
309
|
+
'US Name', 'DS Type', 'DS Name']
|
321
310
|
for col in str_columns:
|
322
311
|
if col in centerline_gdf.columns:
|
323
|
-
centerline_gdf[col] = centerline_gdf[col].
|
324
|
-
lambda x: x.decode('utf-8').strip() if isinstance(x, bytes) else x
|
325
|
-
)
|
312
|
+
centerline_gdf[col] = centerline_gdf[col].str.strip()
|
326
313
|
|
327
|
-
#
|
314
|
+
# Add length calculation in project units
|
328
315
|
if not centerline_gdf.empty:
|
329
|
-
# Calculate length in project units
|
330
316
|
centerline_gdf['length'] = centerline_gdf.geometry.length
|
331
317
|
|
332
|
-
#
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
centerline_gdf[col] = centerline_gdf[col].
|
338
|
-
|
318
|
+
# Convert datetime columns if requested
|
319
|
+
if datetime_to_str:
|
320
|
+
datetime_cols = centerline_gdf.select_dtypes(
|
321
|
+
include=['datetime64']).columns
|
322
|
+
for col in datetime_cols:
|
323
|
+
centerline_gdf[col] = centerline_gdf[col].dt.strftime(
|
324
|
+
'%Y-%m-%d %H:%M:%S')
|
325
|
+
|
326
|
+
logger.info(f"Extracted {len(centerline_gdf)} river centerlines")
|
339
327
|
return centerline_gdf
|
340
328
|
|
341
329
|
except Exception as e:
|
@@ -348,21 +336,27 @@ class HdfXsec:
|
|
348
336
|
@log_call
|
349
337
|
def get_river_stationing(centerlines_gdf: GeoDataFrame) -> GeoDataFrame:
|
350
338
|
"""
|
351
|
-
|
339
|
+
Calculates stationing along river centerlines with interpolated points.
|
352
340
|
|
353
341
|
Parameters
|
354
342
|
----------
|
355
343
|
centerlines_gdf : GeoDataFrame
|
356
|
-
|
344
|
+
River centerline geometries from get_river_centerlines()
|
357
345
|
|
358
346
|
Returns
|
359
347
|
-------
|
360
348
|
GeoDataFrame
|
361
|
-
Original
|
362
|
-
- station_start: Starting station
|
363
|
-
- station_end: Ending station
|
364
|
-
- stations: Array of
|
365
|
-
- points: Array of point geometries
|
349
|
+
Original centerlines with additional columns:
|
350
|
+
- station_start: Starting station value (0 or length)
|
351
|
+
- station_end: Ending station value (length or 0)
|
352
|
+
- stations: Array of station values along centerline
|
353
|
+
- points: Array of interpolated point geometries
|
354
|
+
|
355
|
+
Notes
|
356
|
+
-----
|
357
|
+
Station direction (increasing/decreasing) is determined by
|
358
|
+
upstream/downstream junction connections. Stations are calculated
|
359
|
+
at 100 evenly spaced points along each centerline.
|
366
360
|
"""
|
367
361
|
if centerlines_gdf.empty:
|
368
362
|
logger.warning("Empty centerlines GeoDataFrame provided")
|
@@ -411,7 +405,21 @@ class HdfXsec:
|
|
411
405
|
|
412
406
|
@staticmethod
|
413
407
|
def _interpolate_station(line, distance):
|
414
|
-
"""
|
408
|
+
"""
|
409
|
+
Interpolates a point along a line at a given distance.
|
410
|
+
|
411
|
+
Parameters
|
412
|
+
----------
|
413
|
+
line : LineString
|
414
|
+
Shapely LineString geometry
|
415
|
+
distance : float
|
416
|
+
Distance along the line to interpolate
|
417
|
+
|
418
|
+
Returns
|
419
|
+
-------
|
420
|
+
tuple
|
421
|
+
(x, y) coordinates of interpolated point
|
422
|
+
"""
|
415
423
|
if distance <= 0:
|
416
424
|
return line.coords[0]
|
417
425
|
elif distance >= line.length:
|
@@ -423,7 +431,7 @@ class HdfXsec:
|
|
423
431
|
@staticmethod
|
424
432
|
@log_call
|
425
433
|
@standardize_input(file_type='geom_hdf')
|
426
|
-
def
|
434
|
+
def get_river_reaches(hdf_path: Path, datetime_to_str: bool = False) -> GeoDataFrame:
|
427
435
|
"""
|
428
436
|
Return the model 1D river reach lines.
|
429
437
|
|
@@ -448,7 +456,7 @@ class HdfXsec:
|
|
448
456
|
return GeoDataFrame()
|
449
457
|
|
450
458
|
river_data = hdf_file["Geometry/River Centerlines"]
|
451
|
-
v_conv_val = np.vectorize(HdfUtils.
|
459
|
+
v_conv_val = np.vectorize(HdfUtils.convert_ras_string)
|
452
460
|
river_attrs = river_data["Attributes"][()]
|
453
461
|
river_dict = {"river_id": range(river_attrs.shape[0])}
|
454
462
|
river_dict.update(
|
@@ -456,12 +464,14 @@ class HdfXsec:
|
|
456
464
|
)
|
457
465
|
|
458
466
|
# Get polylines for river reaches
|
459
|
-
geoms =
|
460
|
-
|
467
|
+
geoms = HdfBase.get_polylines_from_parts(
|
468
|
+
hdf_path, "Geometry/River Centerlines"
|
469
|
+
)
|
470
|
+
|
461
471
|
river_gdf = GeoDataFrame(
|
462
472
|
river_dict,
|
463
473
|
geometry=geoms,
|
464
|
-
crs=
|
474
|
+
crs=HdfBase.get_projection(hdf_path),
|
465
475
|
)
|
466
476
|
if datetime_to_str:
|
467
477
|
river_gdf["Last Edited"] = river_gdf["Last Edited"].apply(
|
@@ -476,7 +486,7 @@ class HdfXsec:
|
|
476
486
|
@staticmethod
|
477
487
|
@log_call
|
478
488
|
@standardize_input(file_type='geom_hdf')
|
479
|
-
def
|
489
|
+
def get_river_edge_lines(hdf_path: Path, datetime_to_str: bool = False) -> GeoDataFrame:
|
480
490
|
"""
|
481
491
|
Return the model river edge lines.
|
482
492
|
|
@@ -504,7 +514,7 @@ class HdfXsec:
|
|
504
514
|
# Get attributes if they exist
|
505
515
|
if "Attributes" in edge_data:
|
506
516
|
attrs = edge_data["Attributes"][()]
|
507
|
-
v_conv_val = np.vectorize(HdfUtils.
|
517
|
+
v_conv_val = np.vectorize(HdfUtils.convert_ras_string)
|
508
518
|
|
509
519
|
# Create dictionary of attributes
|
510
520
|
edge_dict = {"edge_id": range(attrs.shape[0])}
|
@@ -519,7 +529,7 @@ class HdfXsec:
|
|
519
529
|
edge_dict = {"edge_id": [], "bank_side": []}
|
520
530
|
|
521
531
|
# Get polyline geometries
|
522
|
-
geoms =
|
532
|
+
geoms = HdfBase.get_polylines_from_parts(
|
523
533
|
hdf_path,
|
524
534
|
"Geometry/River Edge Lines",
|
525
535
|
info_name="Polyline Info",
|
@@ -531,7 +541,7 @@ class HdfXsec:
|
|
531
541
|
edge_gdf = GeoDataFrame(
|
532
542
|
edge_dict,
|
533
543
|
geometry=geoms,
|
534
|
-
crs=
|
544
|
+
crs=HdfBase.get_projection(hdf_path)
|
535
545
|
)
|
536
546
|
|
537
547
|
# Convert datetime objects to strings if requested
|
@@ -553,7 +563,7 @@ class HdfXsec:
|
|
553
563
|
@staticmethod
|
554
564
|
@log_call
|
555
565
|
@standardize_input(file_type='geom_hdf')
|
556
|
-
def
|
566
|
+
def get_river_bank_lines(hdf_path: Path, datetime_to_str: bool = False) -> GeoDataFrame:
|
557
567
|
"""
|
558
568
|
Extract river bank lines from HDF geometry file.
|
559
569
|
|
@@ -580,7 +590,7 @@ class HdfXsec:
|
|
580
590
|
return GeoDataFrame()
|
581
591
|
|
582
592
|
# Get polyline geometries using existing helper method
|
583
|
-
geoms =
|
593
|
+
geoms = HdfBase.get_polylines_from_parts(
|
584
594
|
hdf_path,
|
585
595
|
"Geometry/River Bank Lines",
|
586
596
|
info_name="Polyline Info",
|
@@ -598,7 +608,7 @@ class HdfXsec:
|
|
598
608
|
bank_gdf = GeoDataFrame(
|
599
609
|
bank_dict,
|
600
610
|
geometry=geoms,
|
601
|
-
crs=
|
611
|
+
crs=HdfBase.get_projection(hdf_path)
|
602
612
|
)
|
603
613
|
|
604
614
|
# Add length calculation in project units
|
ras_commander/RasCmdr.py
CHANGED
@@ -21,6 +21,19 @@ Example:
|
|
21
21
|
|
22
22
|
logger.debug("Additional debug information")
|
23
23
|
# Function logic here
|
24
|
+
|
25
|
+
|
26
|
+
-----
|
27
|
+
|
28
|
+
All of the methods in this class are static and are designed to be used without instantiation.
|
29
|
+
|
30
|
+
List of Functions in RasCmdr:
|
31
|
+
- compute_plan()
|
32
|
+
- compute_parallel()
|
33
|
+
- compute_test_mode()
|
34
|
+
|
35
|
+
|
36
|
+
|
24
37
|
"""
|
25
38
|
import os
|
26
39
|
import subprocess
|
ras_commander/RasExamples.py
CHANGED
@@ -22,6 +22,20 @@ Example:
|
|
22
22
|
logger = logging.getLogger(__name__)
|
23
23
|
logger.debug("Additional debug information")
|
24
24
|
# Function logic here
|
25
|
+
|
26
|
+
|
27
|
+
-----
|
28
|
+
|
29
|
+
All of the methods in this class are static and are designed to be used without instantiation.
|
30
|
+
|
31
|
+
List of Functions in RasExamples:
|
32
|
+
- get_example_projects()
|
33
|
+
- list_categories()
|
34
|
+
- list_projects()
|
35
|
+
- extract_project()
|
36
|
+
- is_project_extracted()
|
37
|
+
- clean_projects_directory()
|
38
|
+
|
25
39
|
"""
|
26
40
|
import os
|
27
41
|
import requests
|
ras_commander/RasGeo.py
CHANGED
@@ -22,6 +22,17 @@ Example:
|
|
22
22
|
logger = logging.getLogger(__name__)
|
23
23
|
logger.debug("Additional debug information")
|
24
24
|
# Function logic here
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
-----
|
29
|
+
|
30
|
+
All of the methods in this class are static and are designed to be used without instantiation.
|
31
|
+
|
32
|
+
List of Functions in RasGeo:
|
33
|
+
- clear_geompre_files()
|
34
|
+
|
35
|
+
|
25
36
|
"""
|
26
37
|
import os
|
27
38
|
from pathlib import Path
|
ras_commander/RasGpt.py
CHANGED
@@ -17,3 +17,11 @@ class RasGpt:
|
|
17
17
|
# These will simply filter the data to only include the relevant information for the area of focus.
|
18
18
|
|
19
19
|
#
|
20
|
+
# IDEAS
|
21
|
+
# 1. Package up a standard set of information for LLM analysis
|
22
|
+
# - General project information
|
23
|
+
# - Cross section information (for specific cross sections)
|
24
|
+
# - Structure information (for specific structures)
|
25
|
+
# - Include time series results and relevant HEC Guidance for LLM to reference
|
26
|
+
|
27
|
+
# 2. Use Library Assistant to call LLM
|
@@ -0,0 +1,105 @@
|
|
1
|
+
"""
|
2
|
+
Class: RasMapper
|
3
|
+
|
4
|
+
List of Functions:
|
5
|
+
get_raster_map(hdf_path: Path)
|
6
|
+
clip_raster_with_boundary(raster_path: Path, boundary_path: Path)
|
7
|
+
calculate_zonal_stats(boundary_path: Path, raster_data, transform, nodata)
|
8
|
+
|
9
|
+
"""
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
from pathlib import Path
|
14
|
+
import pandas as pd
|
15
|
+
import geopandas as gpd
|
16
|
+
import rasterio
|
17
|
+
from rasterio.mask import mask
|
18
|
+
import h5py
|
19
|
+
from .Decorators import log_call, standardize_input
|
20
|
+
from .HdfInfiltration import HdfInfiltration
|
21
|
+
|
22
|
+
class RasMapper:
|
23
|
+
"""Class for handling RAS Mapper operations and data extraction"""
|
24
|
+
|
25
|
+
@staticmethod
|
26
|
+
@log_call
|
27
|
+
def get_raster_map(hdf_path: Path) -> dict:
|
28
|
+
"""Read the raster map from HDF file and create value mapping
|
29
|
+
|
30
|
+
Args:
|
31
|
+
hdf_path: Path to the HDF file
|
32
|
+
|
33
|
+
Returns:
|
34
|
+
Dictionary mapping raster values to mukeys
|
35
|
+
"""
|
36
|
+
with h5py.File(hdf_path, 'r') as hdf:
|
37
|
+
raster_map_data = hdf['Raster Map'][:]
|
38
|
+
return {int(item[0]): item[1].decode('utf-8') for item in raster_map_data}
|
39
|
+
|
40
|
+
@staticmethod
|
41
|
+
@log_call
|
42
|
+
def clip_raster_with_boundary(raster_path: Path, boundary_path: Path):
|
43
|
+
"""Clip a raster using a boundary polygon
|
44
|
+
|
45
|
+
Args:
|
46
|
+
raster_path: Path to the raster file
|
47
|
+
boundary_path: Path to the boundary shapefile
|
48
|
+
|
49
|
+
Returns:
|
50
|
+
Tuple of (clipped_image, transform, nodata_value)
|
51
|
+
"""
|
52
|
+
watershed = gpd.read_file(boundary_path)
|
53
|
+
raster = rasterio.open(raster_path)
|
54
|
+
|
55
|
+
out_image, out_transform = mask(raster, watershed.geometry, crop=True)
|
56
|
+
nodata = raster.nodatavals[0]
|
57
|
+
|
58
|
+
return out_image[0], out_transform, nodata
|
59
|
+
|
60
|
+
@staticmethod
|
61
|
+
@log_call
|
62
|
+
def calculate_zonal_stats(boundary_path: Path, raster_data, transform, nodata):
|
63
|
+
"""Calculate zonal statistics for a boundary
|
64
|
+
|
65
|
+
Args:
|
66
|
+
boundary_path: Path to boundary shapefile
|
67
|
+
raster_data: Numpy array of raster values
|
68
|
+
transform: Raster transform
|
69
|
+
nodata: Nodata value
|
70
|
+
|
71
|
+
Returns:
|
72
|
+
List of statistics by zone
|
73
|
+
"""
|
74
|
+
watershed = gpd.read_file(boundary_path)
|
75
|
+
return zonal_stats(watershed, raster_data,
|
76
|
+
affine=transform,
|
77
|
+
nodata=nodata,
|
78
|
+
categorical=True)
|
79
|
+
|
80
|
+
# Example usage:
|
81
|
+
"""
|
82
|
+
# Initialize paths
|
83
|
+
raster_path = Path('input_files/gSSURGO_InfiltrationDC.tif')
|
84
|
+
boundary_path = Path('input_files/WF_Boundary_Simple.shp')
|
85
|
+
hdf_path = raster_path.with_suffix('.hdf')
|
86
|
+
|
87
|
+
# Get raster mapping
|
88
|
+
raster_map = RasMapper.get_raster_map(hdf_path)
|
89
|
+
|
90
|
+
# Clip raster with boundary
|
91
|
+
clipped_data, transform, nodata = RasMapper.clip_raster_with_boundary(
|
92
|
+
raster_path, boundary_path)
|
93
|
+
|
94
|
+
# Calculate zonal statistics
|
95
|
+
stats = RasMapper.calculate_zonal_stats(
|
96
|
+
boundary_path, clipped_data, transform, nodata)
|
97
|
+
|
98
|
+
# Calculate soil statistics
|
99
|
+
soil_stats = HdfInfiltration.calculate_soil_statistics(
|
100
|
+
stats, raster_map)
|
101
|
+
|
102
|
+
# Get significant mukeys (>1%)
|
103
|
+
significant_mukeys = HdfInfiltration.get_significant_mukeys(
|
104
|
+
soil_stats, threshold=1.0)
|
105
|
+
"""
|
ras_commander/RasPlan.py
CHANGED
@@ -22,6 +22,36 @@ Example:
|
|
22
22
|
logger = logging.getLogger(__name__)
|
23
23
|
logger.debug("Additional debug information")
|
24
24
|
# Function logic here
|
25
|
+
|
26
|
+
|
27
|
+
-----
|
28
|
+
|
29
|
+
All of the methods in this class are static and are designed to be used without instantiation.
|
30
|
+
|
31
|
+
List of Functions in RasPlan:
|
32
|
+
- set_geom(): Set the geometry for a specified plan
|
33
|
+
- set_steady(): Apply a steady flow file to a plan file
|
34
|
+
- set_unsteady(): Apply an unsteady flow file to a plan file
|
35
|
+
- set_num_cores(): Update the maximum number of cores to use
|
36
|
+
- set_geom_preprocessor(): Update geometry preprocessor settings
|
37
|
+
- clone_plan(): Create a new plan file based on a template
|
38
|
+
- clone_unsteady(): Copy unsteady flow files from a template
|
39
|
+
- clone_steady(): Copy steady flow files from a template
|
40
|
+
- clone_geom(): Copy geometry files from a template
|
41
|
+
- get_next_number(): Determine the next available number from a list
|
42
|
+
- get_plan_value(): Retrieve a specific value from a plan file
|
43
|
+
- get_results_path(): Get the results file path for a plan
|
44
|
+
- get_plan_path(): Get the full path for a plan number
|
45
|
+
- get_flow_path(): Get the full path for a flow number
|
46
|
+
- get_unsteady_path(): Get the full path for an unsteady number
|
47
|
+
- get_geom_path(): Get the full path for a geometry number
|
48
|
+
- update_run_flags(): Update various run flags in a plan file
|
49
|
+
- update_plan_intervals(): Update computation and output intervals
|
50
|
+
- update_plan_description(): Update the description in a plan file
|
51
|
+
- read_plan_description(): Read the description from a plan file
|
52
|
+
- update_simulation_date(): Update simulation start and end dates
|
53
|
+
|
54
|
+
|
25
55
|
"""
|
26
56
|
import os
|
27
57
|
import re
|