ras-commander 0.1.6__py2.py3-none-any.whl → 0.21.0__py2.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/README.md +187 -0
- ras_commander/RasCommander.py +456 -0
- ras_commander/RasExamples.py +304 -0
- ras_commander/RasGeo.py +83 -0
- ras_commander/RasPlan.py +1216 -0
- ras_commander/RasPrj.py +400 -0
- ras_commander/RasUnsteady.py +53 -0
- ras_commander/RasUtils.py +283 -0
- ras_commander/__init__.py +33 -0
- ras_commander-0.21.0.dist-info/METADATA +342 -0
- ras_commander-0.21.0.dist-info/RECORD +14 -0
- {ras_commander-0.1.6.dist-info → ras_commander-0.21.0.dist-info}/WHEEL +1 -1
- ras_commander/_version.py +0 -16
- ras_commander/execution.py +0 -315
- ras_commander/file_operations.py +0 -173
- ras_commander/geometry_operations.py +0 -184
- ras_commander/plan_operations.py +0 -307
- ras_commander/project_config.py +0 -64
- ras_commander/project_init.py +0 -174
- ras_commander/project_management.py +0 -227
- ras_commander/project_setup.py +0 -15
- ras_commander/unsteady_operations.py +0 -172
- ras_commander/utilities.py +0 -195
- ras_commander-0.1.6.dist-info/METADATA +0 -133
- ras_commander-0.1.6.dist-info/RECORD +0 -17
- {ras_commander-0.1.6.dist-info → ras_commander-0.21.0.dist-info}/LICENSE +0 -0
- {ras_commander-0.1.6.dist-info → ras_commander-0.21.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,283 @@
|
|
1
|
+
"""
|
2
|
+
Utility functions for the ras_commander library.
|
3
|
+
"""
|
4
|
+
import shutil
|
5
|
+
import logging
|
6
|
+
import time
|
7
|
+
from pathlib import Path
|
8
|
+
from .RasPrj import ras
|
9
|
+
|
10
|
+
class RasUtils:
|
11
|
+
"""
|
12
|
+
A class containing utility functions for the ras_commander library.
|
13
|
+
When integrating new functions that do not clearly fit into other classes, add them here.
|
14
|
+
"""
|
15
|
+
|
16
|
+
@staticmethod
|
17
|
+
def create_backup(file_path: Path, backup_suffix: str = "_backup", ras_object=None) -> Path:
|
18
|
+
"""
|
19
|
+
Create a backup of the specified file.
|
20
|
+
|
21
|
+
Parameters:
|
22
|
+
file_path (Path): Path to the file to be backed up
|
23
|
+
backup_suffix (str): Suffix to append to the backup file name
|
24
|
+
ras_object (RasPrj, optional): RAS object to use. If None, uses the default ras object.
|
25
|
+
|
26
|
+
Returns:
|
27
|
+
Path: Path to the created backup file
|
28
|
+
|
29
|
+
Example:
|
30
|
+
>>> backup_path = RasUtils.create_backup(Path("project.prj"))
|
31
|
+
>>> print(f"Backup created at: {backup_path}")
|
32
|
+
"""
|
33
|
+
ras_obj = ras_object or ras
|
34
|
+
ras_obj.check_initialized()
|
35
|
+
|
36
|
+
original_path = Path(file_path)
|
37
|
+
backup_path = original_path.with_name(f"{original_path.stem}{backup_suffix}{original_path.suffix}")
|
38
|
+
shutil.copy2(original_path, backup_path)
|
39
|
+
logging.info(f"Backup created: {backup_path}")
|
40
|
+
return backup_path
|
41
|
+
|
42
|
+
@staticmethod
|
43
|
+
def restore_from_backup(backup_path: Path, remove_backup: bool = True, ras_object=None) -> Path:
|
44
|
+
"""
|
45
|
+
Restore a file from its backup.
|
46
|
+
|
47
|
+
Parameters:
|
48
|
+
backup_path (Path): Path to the backup file
|
49
|
+
remove_backup (bool): Whether to remove the backup file after restoration
|
50
|
+
ras_object (RasPrj, optional): RAS object to use. If None, uses the default ras object.
|
51
|
+
|
52
|
+
Returns:
|
53
|
+
Path: Path to the restored file
|
54
|
+
|
55
|
+
Example:
|
56
|
+
>>> restored_path = RasUtils.restore_from_backup(Path("project_backup.prj"))
|
57
|
+
>>> print(f"File restored to: {restored_path}")
|
58
|
+
"""
|
59
|
+
ras_obj = ras_object or ras
|
60
|
+
ras_obj.check_initialized()
|
61
|
+
|
62
|
+
backup_path = Path(backup_path)
|
63
|
+
original_path = backup_path.with_name(backup_path.stem.rsplit('_backup', 1)[0] + backup_path.suffix)
|
64
|
+
shutil.copy2(backup_path, original_path)
|
65
|
+
logging.info(f"File restored: {original_path}")
|
66
|
+
if remove_backup:
|
67
|
+
backup_path.unlink()
|
68
|
+
logging.info(f"Backup removed: {backup_path}")
|
69
|
+
return original_path
|
70
|
+
|
71
|
+
@staticmethod
|
72
|
+
def create_directory(directory_path: Path, ras_object=None) -> Path:
|
73
|
+
"""
|
74
|
+
Ensure that a directory exists, creating it if necessary.
|
75
|
+
|
76
|
+
Parameters:
|
77
|
+
directory_path (Path): Path to the directory
|
78
|
+
ras_object (RasPrj, optional): RAS object to use. If None, uses the default ras object.
|
79
|
+
|
80
|
+
Returns:
|
81
|
+
Path: Path to the ensured directory
|
82
|
+
|
83
|
+
Example:
|
84
|
+
>>> ensured_dir = RasUtils.create_directory(Path("output"))
|
85
|
+
>>> print(f"Directory ensured: {ensured_dir}")
|
86
|
+
"""
|
87
|
+
ras_obj = ras_object or ras
|
88
|
+
ras_obj.check_initialized()
|
89
|
+
|
90
|
+
path = Path(directory_path)
|
91
|
+
path.mkdir(parents=True, exist_ok=True)
|
92
|
+
logging.info(f"Directory ensured: {path}")
|
93
|
+
return path
|
94
|
+
|
95
|
+
@staticmethod
|
96
|
+
def find_files_by_extension(extension: str, ras_object=None) -> list:
|
97
|
+
"""
|
98
|
+
List all files in the project directory with a specific extension.
|
99
|
+
|
100
|
+
Parameters:
|
101
|
+
extension (str): File extension to filter (e.g., '.prj')
|
102
|
+
ras_object (RasPrj, optional): RAS object to use. If None, uses the default ras object.
|
103
|
+
|
104
|
+
Returns:
|
105
|
+
list: List of file paths matching the extension
|
106
|
+
|
107
|
+
Example:
|
108
|
+
>>> prj_files = RasUtils.find_files_by_extension('.prj')
|
109
|
+
>>> print(f"Found {len(prj_files)} .prj files")
|
110
|
+
"""
|
111
|
+
ras_obj = ras_object or ras
|
112
|
+
ras_obj.check_initialized()
|
113
|
+
|
114
|
+
files = list(ras_obj.project_folder.glob(f"*{extension}"))
|
115
|
+
return [str(file) for file in files]
|
116
|
+
|
117
|
+
@staticmethod
|
118
|
+
def get_file_size(file_path: Path, ras_object=None) -> int:
|
119
|
+
"""
|
120
|
+
Get the size of a file in bytes.
|
121
|
+
|
122
|
+
Parameters:
|
123
|
+
file_path (Path): Path to the file
|
124
|
+
ras_object (RasPrj, optional): RAS object to use. If None, uses the default ras object.
|
125
|
+
|
126
|
+
Returns:
|
127
|
+
int: Size of the file in bytes
|
128
|
+
|
129
|
+
Example:
|
130
|
+
>>> size = RasUtils.get_file_size(Path("project.prj"))
|
131
|
+
>>> print(f"File size: {size} bytes")
|
132
|
+
"""
|
133
|
+
ras_obj = ras_object or ras
|
134
|
+
ras_obj.check_initialized()
|
135
|
+
|
136
|
+
path = Path(file_path)
|
137
|
+
if path.exists():
|
138
|
+
return path.stat().st_size
|
139
|
+
else:
|
140
|
+
logging.warning(f"File not found: {path}")
|
141
|
+
return None
|
142
|
+
|
143
|
+
@staticmethod
|
144
|
+
def get_file_modification_time(file_path: Path, ras_object=None) -> float:
|
145
|
+
"""
|
146
|
+
Get the last modification time of a file.
|
147
|
+
|
148
|
+
Parameters:
|
149
|
+
file_path (Path): Path to the file
|
150
|
+
ras_object (RasPrj, optional): RAS object to use. If None, uses the default ras object.
|
151
|
+
|
152
|
+
Returns:
|
153
|
+
float: Last modification time as a timestamp
|
154
|
+
|
155
|
+
Example:
|
156
|
+
>>> mtime = RasUtils.get_file_modification_time(Path("project.prj"))
|
157
|
+
>>> print(f"Last modified: {mtime}")
|
158
|
+
"""
|
159
|
+
ras_obj = ras_object or ras
|
160
|
+
ras_obj.check_initialized()
|
161
|
+
|
162
|
+
path = Path(file_path)
|
163
|
+
if path.exists():
|
164
|
+
return path.stat().st_mtime
|
165
|
+
else:
|
166
|
+
logging.warning(f"File not found: {path}")
|
167
|
+
return None
|
168
|
+
|
169
|
+
@staticmethod
|
170
|
+
def get_plan_path(current_plan_number: int, ras_object=None) -> Path:
|
171
|
+
"""
|
172
|
+
Get the path for a plan file with a given plan number.
|
173
|
+
|
174
|
+
Parameters:
|
175
|
+
current_plan_number (int): The plan number (1 to 99)
|
176
|
+
ras_object (RasPrj, optional): RAS object to use. If None, uses the default ras object.
|
177
|
+
|
178
|
+
Returns:
|
179
|
+
Path: Full path to the plan file with the given plan number
|
180
|
+
|
181
|
+
Example:
|
182
|
+
>>> plan_path = RasUtils.get_plan_path(1)
|
183
|
+
>>> print(f"Plan file path: {plan_path}")
|
184
|
+
"""
|
185
|
+
ras_obj = ras_object or ras
|
186
|
+
ras_obj.check_initialized()
|
187
|
+
|
188
|
+
current_plan_number = f"{int(current_plan_number):02d}" # Ensure two-digit format
|
189
|
+
plan_name = f"{ras_obj.project_name}.p{current_plan_number}"
|
190
|
+
return ras_obj.project_folder / plan_name
|
191
|
+
|
192
|
+
@staticmethod
|
193
|
+
def remove_with_retry(path: Path, max_attempts: int = 5, initial_delay: float = 1.0, is_folder: bool = True, ras_object=None) -> bool:
|
194
|
+
"""
|
195
|
+
Attempts to remove a file or folder with retry logic and exponential backoff.
|
196
|
+
|
197
|
+
Parameters:
|
198
|
+
path (Path): Path to the file or folder to be removed.
|
199
|
+
max_attempts (int): Maximum number of removal attempts.
|
200
|
+
initial_delay (float): Initial delay between attempts in seconds.
|
201
|
+
is_folder (bool): If True, the path is treated as a folder; if False, it's treated as a file.
|
202
|
+
ras_object (RasPrj, optional): RAS object to use. If None, uses the default ras object.
|
203
|
+
|
204
|
+
Returns:
|
205
|
+
bool: True if the file or folder was successfully removed, False otherwise.
|
206
|
+
|
207
|
+
Example:
|
208
|
+
>>> success = RasUtils.remove_with_retry(Path("temp_folder"), is_folder=True)
|
209
|
+
>>> print(f"Removal successful: {success}")
|
210
|
+
"""
|
211
|
+
ras_obj = ras_object or ras
|
212
|
+
ras_obj.check_initialized()
|
213
|
+
|
214
|
+
path = Path(path)
|
215
|
+
for attempt in range(max_attempts):
|
216
|
+
try:
|
217
|
+
if path.exists():
|
218
|
+
if is_folder:
|
219
|
+
shutil.rmtree(path)
|
220
|
+
else:
|
221
|
+
path.unlink()
|
222
|
+
return True
|
223
|
+
except PermissionError:
|
224
|
+
if attempt < max_attempts - 1:
|
225
|
+
delay = initial_delay * (2 ** attempt) # Exponential backoff
|
226
|
+
logging.warning(f"Failed to remove {path}. Retrying in {delay} seconds...")
|
227
|
+
time.sleep(delay)
|
228
|
+
else:
|
229
|
+
logging.error(f"Failed to remove {path} after {max_attempts} attempts. Skipping.")
|
230
|
+
return False
|
231
|
+
return False
|
232
|
+
|
233
|
+
@staticmethod
|
234
|
+
def update_plan_file(plan_number: int, file_type: str, entry_number: int, ras_object=None) -> None:
|
235
|
+
"""
|
236
|
+
Update a plan file with a new file reference.
|
237
|
+
|
238
|
+
Parameters:
|
239
|
+
plan_number (int): The plan number (1 to 99)
|
240
|
+
file_type (str): Type of file to update ('Geom', 'Flow', or 'Unsteady')
|
241
|
+
entry_number (int): Number (from 1 to 99) to set
|
242
|
+
ras_object (RasPrj, optional): RAS object to use. If None, uses the default ras object.
|
243
|
+
|
244
|
+
Raises:
|
245
|
+
ValueError: If an invalid file_type is provided
|
246
|
+
FileNotFoundError: If the plan file doesn't exist
|
247
|
+
|
248
|
+
Example:
|
249
|
+
>>> update_plan_entries(1, "Geom", 2)
|
250
|
+
"""
|
251
|
+
ras_obj = ras_object or ras
|
252
|
+
ras_obj.check_initialized()
|
253
|
+
|
254
|
+
valid_file_types = {'Geom': 'g', 'Flow': 'f', 'Unsteady': 'u'}
|
255
|
+
if file_type not in valid_file_types:
|
256
|
+
raise ValueError(f"Invalid file_type. Expected one of: {', '.join(valid_file_types.keys())}")
|
257
|
+
|
258
|
+
plan_file_path = RasUtils.get_plan_path(plan_number, ras_object)
|
259
|
+
if not plan_file_path.exists():
|
260
|
+
raise FileNotFoundError(f"Plan file not found: {plan_file_path}")
|
261
|
+
|
262
|
+
file_prefix = valid_file_types[file_type]
|
263
|
+
search_pattern = f"{file_type} File="
|
264
|
+
entry_number = f"{int(entry_number):02d}" # Ensure two-digit format
|
265
|
+
|
266
|
+
with plan_file_path.open('r') as file:
|
267
|
+
lines = file.readlines()
|
268
|
+
|
269
|
+
for i, line in enumerate(lines):
|
270
|
+
if line.startswith(search_pattern):
|
271
|
+
lines[i] = f"{search_pattern}{file_prefix}{entry_number}\n"
|
272
|
+
logging.info(f"Updated {file_type} File in {plan_file_path} to {file_prefix}{entry_number}")
|
273
|
+
break
|
274
|
+
|
275
|
+
with plan_file_path.open('w') as file:
|
276
|
+
file.writelines(lines)
|
277
|
+
|
278
|
+
logging.info(f"Successfully updated plan file: {plan_file_path}")
|
279
|
+
ras_obj.plan_df = ras_obj.get_plan_entries()
|
280
|
+
ras_obj.geom_df = ras_obj.get_geom_entries()
|
281
|
+
ras_obj.flow_df = ras_obj.get_flow_entries()
|
282
|
+
ras_obj.unsteady_df = ras_obj.get_unsteady_entries()
|
283
|
+
|
ras_commander/__init__.py
CHANGED
@@ -5,3 +5,36 @@ try:
|
|
5
5
|
except PackageNotFoundError:
|
6
6
|
# package is not installed
|
7
7
|
__version__ = "unknown"
|
8
|
+
|
9
|
+
# Import all necessary functions and classes directly
|
10
|
+
from .RasPrj import ras, init_ras_project, get_ras_exe
|
11
|
+
from .RasPrj import RasPrj
|
12
|
+
from .RasPlan import RasPlan
|
13
|
+
from .RasGeo import RasGeo
|
14
|
+
from .RasUnsteady import RasUnsteady
|
15
|
+
from .RasCommander import RasCommander
|
16
|
+
from .RasUtils import RasUtils
|
17
|
+
from .RasExamples import RasExamples
|
18
|
+
|
19
|
+
# Import all attributes from these modules
|
20
|
+
from .RasPrj import *
|
21
|
+
from .RasPrj import *
|
22
|
+
from .RasPlan import *
|
23
|
+
from .RasGeo import *
|
24
|
+
from .RasUnsteady import *
|
25
|
+
from .RasCommander import *
|
26
|
+
from .RasUtils import *
|
27
|
+
from .RasExamples import *
|
28
|
+
# Define __all__ to specify what should be imported when using "from ras_commander import *"
|
29
|
+
__all__ = [
|
30
|
+
"ras",
|
31
|
+
"init_ras_project",
|
32
|
+
"get_ras_exe",
|
33
|
+
"RasPrj",
|
34
|
+
"RasPlan",
|
35
|
+
"RasGeo",
|
36
|
+
"RasUnsteady",
|
37
|
+
"RasCommander",
|
38
|
+
"RasUtils",
|
39
|
+
"RasExamples"
|
40
|
+
]
|
@@ -0,0 +1,342 @@
|
|
1
|
+
Metadata-Version: 2.1
|
2
|
+
Name: ras_commander
|
3
|
+
Version: 0.21.0
|
4
|
+
Summary: A library for automating HEC-RAS operations using python functions.
|
5
|
+
Author-email: "William Katzenmeyer, P.E., C.F.M." <heccommander@gmail.com>
|
6
|
+
Project-URL: Homepage, https://github.com/yourusername/ras_commander
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
9
|
+
Classifier: Operating System :: OS Independent
|
10
|
+
Requires-Python: >=3.9
|
11
|
+
Description-Content-Type: text/markdown
|
12
|
+
License-File: LICENSE
|
13
|
+
|
14
|
+
## RAS-Commander Library Organization
|
15
|
+
|
16
|
+
| Directory/File | Purpose |
|
17
|
+
|---|---|
|
18
|
+
| ras_commander/__init__.py | Initializes the library and defines the public API. |
|
19
|
+
| ras_commander/RasCommander.py | Handles execution of HEC-RAS simulations. |
|
20
|
+
| ras_commander/RasFileOps.py | Provides functions for reading and parsing HEC-RAS project files. |
|
21
|
+
| ras_commander/RasGeo.py | Provides functions for manipulating geometry files. |
|
22
|
+
| ras_commander/RasPlan.py | Provides functions for modifying and updating plan files. |
|
23
|
+
| ras_commander/RasPrj.py | Defines the RasPrj class for managing project-level information. |
|
24
|
+
| ras_commander/rasinit.py | Provides the `init_ras_project` function to initialize a project. |
|
25
|
+
| ras_commander/RasPrj.py | Provides functions for managing HEC-RAS projects (e.g., copying files, updating project file). |
|
26
|
+
| ras_commander/RasUnsteady.py | Provides functions for manipulating unsteady flow files. |
|
27
|
+
| ras_commander/RasUtils.py | Provides general utility functions (e.g., file backup, directory creation). |
|
28
|
+
|
29
|
+
## Project Organization Diagram
|
30
|
+
|
31
|
+
```
|
32
|
+
ras_commander
|
33
|
+
├── .github
|
34
|
+
│ └── workflows
|
35
|
+
│ └── python-package.yml
|
36
|
+
├── ras_commander
|
37
|
+
│ ├── __init__.py
|
38
|
+
│ ├── RasCommander.py
|
39
|
+
│ ├── RasFileOps.py
|
40
|
+
│ ├── RasGeo.py
|
41
|
+
│ ├── RasPlan.py
|
42
|
+
│ ├── RasPrj.py
|
43
|
+
│ ├── rasinit.py
|
44
|
+
│ ├── RasPrj.py
|
45
|
+
│ ├── RasUnsteady.py
|
46
|
+
│ └── RasUtils.py
|
47
|
+
├── tests
|
48
|
+
│ └── ... (test files)
|
49
|
+
├── .gitignore
|
50
|
+
├── LICENSE
|
51
|
+
├── README.md
|
52
|
+
├── pyproject.toml
|
53
|
+
├── setup.cfg
|
54
|
+
└── setup.py
|
55
|
+
```
|
56
|
+
|
57
|
+
## Functions Overview
|
58
|
+
|
59
|
+
| Function | Arguments | Purpose |
|
60
|
+
|---|---|---|
|
61
|
+
| `init_ras_project` | `ras_project_folder`, `ras_exe_path` | Initializes a HEC-RAS project by setting up the `RasPrj` with project details. |
|
62
|
+
| `compute_plan` | `plan_file` | Executes a HEC-RAS plan file. |
|
63
|
+
| `compute_plan_from_folder` | `test_plan_file`, `test_folder_path` | Execute a single HEC-RAS plan from a folder other than the project path. |
|
64
|
+
| `compute_test_mode` | `project_folder` | Recreates the -test function from the HEC-RAS interface, primarily by copying the project directory, forcing recomputation, and running each plan. |
|
65
|
+
| `compute_parallel` | `config`, `max_workers`, `cores_per_run` | Run HEC-RAS plans in parallel. |
|
66
|
+
| `compute_parallel_all` | `project_folder`, `ras_exe_path` | Run all HEC-RAS plans in parallel from a project folder path. |
|
67
|
+
|
68
|
+
[The rest of the function list remains the same, just ensure the class names are updated to their new lowercase versions]
|
69
|
+
|
70
|
+
## Potential Uses of RAS-Commander Functions
|
71
|
+
|
72
|
+
[This section remains unchanged]
|
73
|
+
|
74
|
+
## GitHub Actions
|
75
|
+
|
76
|
+
[This section remains unchanged]
|
77
|
+
|
78
|
+
## Basic Usage Instructions
|
79
|
+
|
80
|
+
To get started with RAS-Commander, follow these steps:
|
81
|
+
|
82
|
+
1. Install the library:
|
83
|
+
```
|
84
|
+
pip install ras-commander
|
85
|
+
```
|
86
|
+
|
87
|
+
2. Import the necessary modules:
|
88
|
+
```python
|
89
|
+
from ras_commander import rasinit, RasFileOps, RasPrj, RasPlan, RasGeo, RasUnsteady, RasCommander, RasUtils
|
90
|
+
```
|
91
|
+
|
92
|
+
3. Initialize a HEC-RAS project:
|
93
|
+
```python
|
94
|
+
project_folder = r"C:\path\to\your\project"
|
95
|
+
ras_exe_path = r"C:\Program Files (x86)\HEC\HEC-RAS\6.5\Ras.exe"
|
96
|
+
config = rasinit(project_folder, ras_exe_path)
|
97
|
+
```
|
98
|
+
|
99
|
+
4. Perform operations on your HEC-RAS project. For example:
|
100
|
+
|
101
|
+
- Execute a single plan:
|
102
|
+
```python
|
103
|
+
plan_file = RasPlan.get_plan_path("01")
|
104
|
+
RasCommander.compute_plan(plan_file)
|
105
|
+
```
|
106
|
+
|
107
|
+
- Run multiple plans in parallel:
|
108
|
+
```python
|
109
|
+
max_workers = 2
|
110
|
+
cores_per_run = 1
|
111
|
+
results = RasCommander.compute_parallel(config, max_workers, cores_per_run)
|
112
|
+
```
|
113
|
+
|
114
|
+
- Copy and modify geometry files:
|
115
|
+
```python
|
116
|
+
RasGeo.clone_geom(config.project_folder, "01")
|
117
|
+
plan_file = RasPlan.get_plan_path("01")
|
118
|
+
RasGeo.set_geom(plan_file, "02")
|
119
|
+
```
|
120
|
+
|
121
|
+
- Work with unsteady flow files:
|
122
|
+
```python
|
123
|
+
new_unsteady_number = RasUnsteady.clone_unsteady(config.project_folder, "01")
|
124
|
+
plan_file = RasPlan.get_plan_path("01")
|
125
|
+
RasUnsteady.set_unsteady(plan_file, new_unsteady_number)
|
126
|
+
```
|
127
|
+
|
128
|
+
5. Access project information:
|
129
|
+
```python
|
130
|
+
print(f"Project name: {config.project_name}")
|
131
|
+
print(f"Project file: {config.prj_file}")
|
132
|
+
print(f"Project folder: {config.project_folder}")
|
133
|
+
```
|
134
|
+
|
135
|
+
For more detailed examples and advanced usage, refer to the function documentation and the examples provided in the repository.
|
136
|
+
|
137
|
+
|
138
|
+
|
139
|
+
|
140
|
+
NOTES: INCORPORATE INTO THE README.MD FILE ABOVE UNDER A NEW SECTION FOR CURRENT USES AND ROADMAP ITEMS, THEN DELETE THIS NOTE
|
141
|
+
|
142
|
+
|
143
|
+
Potential Uses of HEC-RAS Automation Functions
|
144
|
+
This set of functions provides a powerful foundation for automating various aspects of HEC-RAS modeling workflows. Here are some potential applications:
|
145
|
+
1. Calibration and Sensitivity Analysis:
|
146
|
+
Automated Parameter Variation: Users can create multiple simulation scenarios with varying parameters (e.g., Manning's n values, boundary conditions, initial conditions) to calibrate their model against observed data.
|
147
|
+
Sensitivity Testing: Evaluate the impact of different input parameters on model outputs by generating a range of scenarios and analyzing the results. This helps identify critical parameters that require more attention during calibration.
|
148
|
+
2. Real-time Forecasting:
|
149
|
+
Dynamic Model Updates: Integrate with external data sources (e.g., weather forecasts, streamflow observations) to automatically update boundary conditions and initial conditions in unsteady flow files before running the simulation.
|
150
|
+
Ensemble Forecasting: Generate multiple forecasts by incorporating uncertainty in input data and model parameters. This provides a more comprehensive understanding of potential future flow conditions.
|
151
|
+
3. Scenario Analysis:
|
152
|
+
Land Use Change Impacts: Evaluate the effects of land use changes on flood risk by modifying Manning's n values using extract_2d_mannings_tables, modify_2d_mannings_table, and write_2d_mannings_tables and running simulations with updated geometry files.
|
153
|
+
Climate Change Impacts: Analyze the potential impacts of projected climate changes on flood risk by adjusting precipitation patterns and other relevant parameters in unsteady flow files.
|
154
|
+
4. Batch Processing and High-Performance Computing:
|
155
|
+
Large-scale Model Runs: Utilize run_plans_parallel to execute multiple simulations concurrently on a multi-core system, significantly reducing processing time for large-scale models or complex scenarios.
|
156
|
+
Automated Report Generation: Integrate with Python libraries like matplotlib and bokeh to automatically generate customized reports summarizing simulation results, including tables, figures, and maps.
|
157
|
+
5. Model Development and Testing:
|
158
|
+
Rapid Prototyping: Quickly set up and run new model configurations using template files and automated workflows, facilitating rapid model development and testing.
|
159
|
+
Regression Testing: Ensure model integrity and consistency after code changes or updates by automatically running a predefined set of simulations and comparing results with expected outputs.
|
160
|
+
6. User-Friendly Interfaces:
|
161
|
+
GUI Development: Integrate with Python GUI libraries like Tkinter or PyQt to create user-friendly interfaces for automating HEC-RAS workflows, allowing non-programmers to access the power of automation.
|
162
|
+
|
163
|
+
|
164
|
+
|
165
|
+
|
166
|
+
|
167
|
+
|
168
|
+
Certainly! I'll create an updated README.md for the ras_commander library, incorporating the information you've provided and the context from the previous HEC-Commander tools. Here's the updated README.md:
|
169
|
+
|
170
|
+
```markdown
|
171
|
+
# ras_commander
|
172
|
+
|
173
|
+
ras_commander is a Python library for automating HEC-RAS operations, providing a set of tools to interact with HEC-RAS project files, execute simulations, and manage project data. This library is an evolution of the RAS-Commander 1.0 Python Notebook Application previously released under the HEC-Commander tools.
|
174
|
+
|
175
|
+
## Features
|
176
|
+
|
177
|
+
- Automate HEC-RAS project management and simulations
|
178
|
+
- Support for both single and multiple project instances
|
179
|
+
- Parallel execution of HEC-RAS plans
|
180
|
+
- Utilities for managing geometry, plan, and unsteady flow files
|
181
|
+
- Example project management for testing and development
|
182
|
+
- Two primary operation modes: "Run Missing" and "Build from DSS"
|
183
|
+
|
184
|
+
## Installation
|
185
|
+
|
186
|
+
Install ras_commander using pip:
|
187
|
+
|
188
|
+
```bash
|
189
|
+
pip install ras_commander
|
190
|
+
```
|
191
|
+
|
192
|
+
## Requirements
|
193
|
+
|
194
|
+
- Python 3.9+
|
195
|
+
- HEC-RAS 6.5 (other versions may work but are not officially supported)
|
196
|
+
|
197
|
+
For a full list of dependencies, see the `requirements.txt` file.
|
198
|
+
|
199
|
+
## Quick Start
|
200
|
+
|
201
|
+
```python
|
202
|
+
from ras_commander import init_ras_project, RasCommander, RasPlan
|
203
|
+
|
204
|
+
# Initialize a project
|
205
|
+
init_ras_project("/path/to/project", "6.5")
|
206
|
+
|
207
|
+
# Execute a single plan
|
208
|
+
RasCommander.compute_plan("01")
|
209
|
+
|
210
|
+
# Execute plans in parallel
|
211
|
+
results = RasCommander.compute_parallel(
|
212
|
+
plan_numbers=["01", "02"],
|
213
|
+
max_workers=2,
|
214
|
+
cores_per_run=2
|
215
|
+
)
|
216
|
+
|
217
|
+
# Modify a plan
|
218
|
+
RasPlan.set_geom("01", "02")
|
219
|
+
```
|
220
|
+
|
221
|
+
## Key Components
|
222
|
+
|
223
|
+
- `RasPrj`: Manages HEC-RAS projects
|
224
|
+
- `RasCommander`: Handles execution of HEC-RAS simulations
|
225
|
+
- `RasPlan`: Provides functions for modifying and updating plan files
|
226
|
+
- `RasGeo`: Handles operations related to geometry files
|
227
|
+
- `RasUnsteady`: Manages unsteady flow file operations
|
228
|
+
- `RasUtils`: Contains utility functions for file operations and data management
|
229
|
+
- `RasExamples`: Manages and loads HEC-RAS example projects
|
230
|
+
|
231
|
+
## Documentation
|
232
|
+
|
233
|
+
For detailed usage instructions and API documentation, please refer to the [Comprehensive Library Guide](Comprehensive_Library_Guide.md).
|
234
|
+
|
235
|
+
## Examples
|
236
|
+
|
237
|
+
Check out the `examples/` directory for sample scripts demonstrating various features of ras_commander.
|
238
|
+
|
239
|
+
## Development
|
240
|
+
|
241
|
+
### Setting up the development environment
|
242
|
+
|
243
|
+
1. Clone the repository:
|
244
|
+
```
|
245
|
+
git clone https://github.com/yourusername/ras_commander.git
|
246
|
+
```
|
247
|
+
2. Create a virtual environment and activate it:
|
248
|
+
```
|
249
|
+
python -m venv venv
|
250
|
+
source venv/bin/activate # On Windows, use `venv\Scripts\activate`
|
251
|
+
```
|
252
|
+
3. Install the development dependencies:
|
253
|
+
```
|
254
|
+
pip install -r requirements.txt
|
255
|
+
```
|
256
|
+
Certainly! I'll provide an updated Project Organization Diagram based on the current structure of the ras_commander library. Here's the updated diagram:
|
257
|
+
|
258
|
+
|
259
|
+
## Project Organization Diagram
|
260
|
+
|
261
|
+
```
|
262
|
+
ras_commander
|
263
|
+
├── .github
|
264
|
+
│ └── workflows
|
265
|
+
│ └── python-package.yml
|
266
|
+
├── ras_commander
|
267
|
+
│ ├── __init__.py
|
268
|
+
│ ├── RasCommander.py
|
269
|
+
│ ├── RasExamples.py
|
270
|
+
│ ├── RasGeo.py
|
271
|
+
│ ├── RasPlan.py
|
272
|
+
│ ├── RasPrj.py
|
273
|
+
│ ├── RasUnsteady.py
|
274
|
+
│ └── RasUtils.py
|
275
|
+
├── examples
|
276
|
+
│ ├── 01_project_initialization.py
|
277
|
+
│ ├── 02_plan_operations.py
|
278
|
+
│ ├── 03_geometry_operations.py
|
279
|
+
│ ├── 04_unsteady_flow_operations.py
|
280
|
+
│ ├── 05_utility_functions.py
|
281
|
+
│ ├── 06_single_plan_execution.py
|
282
|
+
│ ├── 07_sequential_plan_execution.py
|
283
|
+
│ ├── 08_parallel_execution.py
|
284
|
+
│ ├── 09_specifying_plans.py
|
285
|
+
│ ├── 10_arguments_for_compute.py
|
286
|
+
│ ├── 11_Using_RasExamples.ipynb
|
287
|
+
│ ├── 12_plan_set_execution.py
|
288
|
+
│ └── 13_multiple_project_operations.py
|
289
|
+
├── tests
|
290
|
+
│ └── ... (test files)
|
291
|
+
├── .gitignore
|
292
|
+
├── LICENSE
|
293
|
+
├── README.md
|
294
|
+
├── STYLE_GUIDE.md
|
295
|
+
├── Comprehensive_Library_Guide.md
|
296
|
+
├── pyproject.toml
|
297
|
+
├── setup.cfg
|
298
|
+
├── setup.py
|
299
|
+
└── requirements.txt
|
300
|
+
|
301
|
+
|
302
|
+
## Inclusion of .cursorrules for AI-driven Coding Experience
|
303
|
+
|
304
|
+
Open the ras_commander folder in the Cursor IDE, and it will automatically include the .cursorrules file in your instructions. Additionally, two other provided methods for interacting with the library though your current AI subscriptions:
|
305
|
+
|
306
|
+
- ChatGPT: ras_commander GPT Assistant (LINK HERE)
|
307
|
+
- Latest LLM summaries of the code base:
|
308
|
+
- Entire code base: LINK HERE (TOKEN COUNT) (for Claude or Gemini)
|
309
|
+
- Examples and Function Docstrings Only: LINK HERE (TOKEN COUNT) (for GPT-4o, o1 or Llama 3.1 405b)
|
310
|
+
- Cursor IDE through .cursorrules file
|
311
|
+
|
312
|
+
There are a series of scripts provided in the "llm_summaries" folder that provide summaries of the code base, and the docstrings of the functions. They can be run in your local environment, or provided to ChatGPT's code interpreter for execution.
|
313
|
+
|
314
|
+
## RAS-Commander GPT Assistant
|
315
|
+
|
316
|
+
The ras_commander GPT assistant has access the entire code base, and can be a helpful tool for understanding the library and its capabilities. However, it is subject to the same context window limitations and file retrieval limtations as I have covered in ADD BLOG LINK HERE. For best results, use the llm summaries above to provide robust context to the model before asking to generate complex workflows.
|
317
|
+
|
318
|
+
## Contributing
|
319
|
+
|
320
|
+
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details on how to submit pull requests, report issues, and suggest improvements.
|
321
|
+
|
322
|
+
## Style Guide
|
323
|
+
|
324
|
+
This project follows a specific style guide to maintain consistency across the codebase. Please refer to the [Style Guide](STYLE_GUIDE.md) for details on coding conventions, documentation standards, and best practices.
|
325
|
+
|
326
|
+
|
327
|
+
|
328
|
+
|
329
|
+
## License
|
330
|
+
|
331
|
+
ras_commander is released under the MIT License. See the license file for details.
|
332
|
+
|
333
|
+
## Acknowledgments
|
334
|
+
|
335
|
+
ras_commander is based on the HEC-Commander project's "Command Line is All You Need" approach, leveraging the HEC-RAS command-line interface for automation. The initial development of this library was presented in the HEC-Commander Tools repository. In a 2024 Australian Water School webinar, Bill demonstrated the derivation of basic HEC-RAS automation functions from plain language instructions. Leveraging the previously developed code and AI tools, the library was created. The primary tools used for this initial development were Anthropic's Claude, GPT-4o, Google's Gemini Experimental models,and the Cursor AI Coding IDE.
|
336
|
+
|
337
|
+
|
338
|
+
|
339
|
+
## Contact
|
340
|
+
|
341
|
+
For questions, suggestions, or support, please contact:
|
342
|
+
William Katzenmeyer, P.E., C.F.M. - billk@fenstermaker.com
|
@@ -0,0 +1,14 @@
|
|
1
|
+
ras_commander/README.md,sha256=MNWyvD9-MA3m3_HRZCk4uzrtIjyyYhhFs5CZ9M8ZNEo,5936
|
2
|
+
ras_commander/RasCommander.py,sha256=tsCsvHdjbB28_tqJhy4h5iyYfgd5aLCcI0IfsN_GUqM,21277
|
3
|
+
ras_commander/RasExamples.py,sha256=qNV1KK42S0TllyQ3wWnahQT2GEW1R-_39XI-fOYQemQ,13548
|
4
|
+
ras_commander/RasGeo.py,sha256=VY7-Ksw2iclH9C9mY7unQ_a11aCkCLiyhmFgJmSNdsk,3571
|
5
|
+
ras_commander/RasPlan.py,sha256=02agZMG29C8Ra50LSd9JF4SpomABRDJXCwNBK6dJCqM,49731
|
6
|
+
ras_commander/RasPrj.py,sha256=LhlMR6qP9xvLMiPFuwRhRM5yosyLH2h1EyZbnhKgxE8,15163
|
7
|
+
ras_commander/RasUnsteady.py,sha256=cOpFAZrXrxBBdoi-i3iWboQzrtCUb_sPGQ05dZnadF4,1852
|
8
|
+
ras_commander/RasUtils.py,sha256=dkeh7k1yvrViNQ0NzG4jB4hiEvmsWZJu-_w04ccrpdI,10402
|
9
|
+
ras_commander/__init__.py,sha256=eoOVbWnLH-e405O6ADkO6qhx45a0n60CFgFl7mj4HYs,1089
|
10
|
+
ras_commander-0.21.0.dist-info/LICENSE,sha256=_pbd6qHnlsz1iQ-ozDW_49r86BZT6CRwO2iBtw0iN6M,457
|
11
|
+
ras_commander-0.21.0.dist-info/METADATA,sha256=F_Og5eixNK5qhCfKff4WcRWKGYX6sjKO4PrM62wf7rw,14478
|
12
|
+
ras_commander-0.21.0.dist-info/WHEEL,sha256=muXAwoPanksrVvf9Mcykr8l6Q0JyBrGUVYr50kE4bxo,109
|
13
|
+
ras_commander-0.21.0.dist-info/top_level.txt,sha256=i76S7eKLFC8doKcXDl3aiOr9RwT06G8adI6YuKbQDaA,14
|
14
|
+
ras_commander-0.21.0.dist-info/RECORD,,
|