ras-commander 0.1.5__py2.py3-none-any.whl → 0.20.dev0__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/_version.py +2 -2
- ras_commander-0.20.dev0.dist-info/METADATA +342 -0
- ras_commander-0.20.dev0.dist-info/RECORD +15 -0
- {ras_commander-0.1.5.dist-info → ras_commander-0.20.dev0.dist-info}/WHEEL +1 -1
- 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.5.dist-info/METADATA +0 -133
- ras_commander-0.1.5.dist-info/RECORD +0 -17
- {ras_commander-0.1.5.dist-info → ras_commander-0.20.dev0.dist-info}/LICENSE +0 -0
- {ras_commander-0.1.5.dist-info → ras_commander-0.20.dev0.dist-info}/top_level.txt +0 -0
ras_commander/plan_operations.py
DELETED
@@ -1,307 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Operations for modifying and updating HEC-RAS plan files.
|
3
|
-
"""
|
4
|
-
import re
|
5
|
-
from pathlib import Path
|
6
|
-
|
7
|
-
|
8
|
-
from .project_config import ProjectConfig
|
9
|
-
|
10
|
-
class PlanOperations:
|
11
|
-
"""
|
12
|
-
A class for operations on HEC-RAS plan files.
|
13
|
-
"""
|
14
|
-
@staticmethod
|
15
|
-
def apply_geometry_to_plan(plan_file, geometry_number):
|
16
|
-
"""
|
17
|
-
Apply a geometry file to a plan file.
|
18
|
-
|
19
|
-
Parameters:
|
20
|
-
plan_file (str): Full path to the HEC-RAS plan file (.pXX)
|
21
|
-
geometry_number (str): Geometry number to apply (e.g., '01')
|
22
|
-
|
23
|
-
Returns:
|
24
|
-
None
|
25
|
-
|
26
|
-
Raises:
|
27
|
-
ValueError: If the specified geometry number is not found in the project file
|
28
|
-
"""
|
29
|
-
config = ProjectConfig()
|
30
|
-
config.check_initialized()
|
31
|
-
|
32
|
-
if f"g{geometry_number}" not in config.ras_geom_entries['geom_number'].values:
|
33
|
-
raise ValueError(f"Geometry number g{geometry_number} not found in project file.")
|
34
|
-
with open(plan_file, 'r') as f:
|
35
|
-
lines = f.readlines()
|
36
|
-
with open(plan_file, 'w') as f:
|
37
|
-
for line in lines:
|
38
|
-
if line.startswith("Geom File="):
|
39
|
-
f.write(f"Geom File=g{geometry_number}\n")
|
40
|
-
print(f"Updated Geom File in {plan_file} to g{geometry_number}")
|
41
|
-
else:
|
42
|
-
f.write(line)
|
43
|
-
|
44
|
-
@staticmethod
|
45
|
-
def apply_flow_to_plan(plan_file, flow_number):
|
46
|
-
"""
|
47
|
-
Apply a steady flow file to a plan file.
|
48
|
-
|
49
|
-
Parameters:
|
50
|
-
plan_file (str): Full path to the HEC-RAS plan file (.pXX)
|
51
|
-
flow_number (str): Flow number to apply (e.g., '02')
|
52
|
-
|
53
|
-
Returns:
|
54
|
-
None
|
55
|
-
|
56
|
-
Raises:
|
57
|
-
ValueError: If the specified flow number is not found in the project file
|
58
|
-
"""
|
59
|
-
config = ProjectConfig()
|
60
|
-
config.check_initialized()
|
61
|
-
|
62
|
-
if f"{flow_number}" not in config.ras_flow_entries['flow_number'].values:
|
63
|
-
raise ValueError(f"Flow number f{flow_number} not found in project file.")
|
64
|
-
with open(plan_file, 'r') as f:
|
65
|
-
lines = f.readlines()
|
66
|
-
with open(plan_file, 'w') as f:
|
67
|
-
for line in lines:
|
68
|
-
if line.startswith("Flow File="):
|
69
|
-
f.write(f"Flow File=f{flow_number}\n")
|
70
|
-
print(f"Updated Flow File in {plan_file} to f{flow_number}")
|
71
|
-
else:
|
72
|
-
f.write(line)
|
73
|
-
|
74
|
-
@staticmethod
|
75
|
-
def copy_plan_from_template(template_plan):
|
76
|
-
"""
|
77
|
-
Create a new plan file based on a template and update the project file.
|
78
|
-
|
79
|
-
Parameters:
|
80
|
-
|
81
|
-
template_plan (str): Plan file to use as template (e.g., '01')
|
82
|
-
project_folder, project_name,
|
83
|
-
Returns:
|
84
|
-
str: New plan number
|
85
|
-
"""
|
86
|
-
config = ProjectConfig()
|
87
|
-
config.check_initialized()
|
88
|
-
|
89
|
-
# Read existing plan numbers
|
90
|
-
ras_plan_entries = config.ras_plan_entries
|
91
|
-
|
92
|
-
# Get next available plan number
|
93
|
-
new_plan_num = PlanOperations.get_next_available_number(ras_plan_entries['plan_number'])
|
94
|
-
|
95
|
-
# Copy template plan file to new plan file
|
96
|
-
template_plan_path = Path(config.project_folder) / f"{config.project_name}.p{template_plan}"
|
97
|
-
new_plan_path = Path(config.project_folder) / f"{config.project_name}.p{new_plan_num}"
|
98
|
-
new_plan_path.write_bytes(template_plan_path.read_bytes())
|
99
|
-
print(f"Copied {template_plan_path} to {new_plan_path}")
|
100
|
-
|
101
|
-
# Update project file with new plan
|
102
|
-
project_file = config.project_file
|
103
|
-
with open(project_file, 'a') as f:
|
104
|
-
f.write(f"\nPlan File=p{new_plan_num}")
|
105
|
-
print(f"Updated {project_file} with new plan p{new_plan_num}")
|
106
|
-
config = ProjectConfig()
|
107
|
-
return f"{new_plan_num}"
|
108
|
-
|
109
|
-
@staticmethod
|
110
|
-
def get_next_available_number(existing_numbers):
|
111
|
-
"""
|
112
|
-
Determine the next available number from a list of existing numbers.
|
113
|
-
|
114
|
-
Parameters:
|
115
|
-
existing_numbers (list): List of existing numbers as strings
|
116
|
-
|
117
|
-
Returns:
|
118
|
-
str: Next available number as a zero-padded string
|
119
|
-
"""
|
120
|
-
existing_numbers = sorted(int(num) for num in existing_numbers)
|
121
|
-
next_number = 1
|
122
|
-
for num in existing_numbers:
|
123
|
-
if num == next_number:
|
124
|
-
next_number += 1
|
125
|
-
else:
|
126
|
-
break
|
127
|
-
return f"{next_number:02d}"
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
@staticmethod
|
132
|
-
def apply_unsteady_to_plan(plan_file, unsteady_number):
|
133
|
-
"""
|
134
|
-
Apply an unsteady flow file to a plan file.
|
135
|
-
|
136
|
-
Parameters:
|
137
|
-
plan_file (str): Full path to the HEC-RAS plan file (.pXX)
|
138
|
-
unsteady_number (str): Unsteady flow number to apply (e.g., '01')
|
139
|
-
|
140
|
-
Returns:
|
141
|
-
None
|
142
|
-
|
143
|
-
Raises:
|
144
|
-
ValueError: If the specified unsteady number is not found in the project file
|
145
|
-
"""
|
146
|
-
config = ProjectConfig()
|
147
|
-
config.check_initialized()
|
148
|
-
|
149
|
-
if f"u{unsteady_number}" not in config.ras_unsteady_entries['unsteady_number'].values:
|
150
|
-
raise ValueError(f"Unsteady number u{unsteady_number} not found in project file.")
|
151
|
-
with open(plan_file, 'r') as f:
|
152
|
-
lines = f.readlines()
|
153
|
-
with open(plan_file, 'w') as f:
|
154
|
-
for line in lines:
|
155
|
-
if line.startswith("Unsteady File=") or line.startswith("Flow File=u"):
|
156
|
-
f.write(f"Unsteady File=u{unsteady_number}\n")
|
157
|
-
print(f"Updated Unsteady File in {plan_file} to u{unsteady_number}")
|
158
|
-
else:
|
159
|
-
f.write(line)
|
160
|
-
|
161
|
-
@staticmethod
|
162
|
-
def set_num_cores(plan_file, num_cores):
|
163
|
-
"""
|
164
|
-
Update the maximum number of cores to use in the HEC-RAS plan file.
|
165
|
-
|
166
|
-
Parameters:
|
167
|
-
plan_file (str): Full path to the plan file
|
168
|
-
num_cores (int): Maximum number of cores to use
|
169
|
-
|
170
|
-
Returns:
|
171
|
-
None
|
172
|
-
"""
|
173
|
-
config = ProjectConfig()
|
174
|
-
config.check_initialized()
|
175
|
-
|
176
|
-
cores_pattern = re.compile(r"(UNET D1 Cores= )\d+")
|
177
|
-
with open(plan_file, 'r') as file:
|
178
|
-
content = file.read()
|
179
|
-
new_content = cores_pattern.sub(rf"\g<1>{num_cores}", content)
|
180
|
-
with open(plan_file, 'w') as file:
|
181
|
-
file.write(new_content)
|
182
|
-
print(f"Updated {plan_file} with {num_cores} cores.")
|
183
|
-
|
184
|
-
@staticmethod
|
185
|
-
def update_geompre_flags(file_path, run_htab_value, use_ib_tables_value):
|
186
|
-
"""
|
187
|
-
Update the simulation plan file to modify the `Run HTab` and `UNET Use Existing IB Tables` settings.
|
188
|
-
|
189
|
-
Parameters:
|
190
|
-
file_path (str): Path to the simulation plan file (.p06 or similar) that you want to modify.
|
191
|
-
run_htab_value (int): Value for the `Run HTab` setting:
|
192
|
-
- `0` : Do not run the geometry preprocessor, use existing geometry tables.
|
193
|
-
- `-1` : Run the geometry preprocessor, forcing a recomputation of the geometry tables.
|
194
|
-
use_ib_tables_value (int): Value for the `UNET Use Existing IB Tables` setting:
|
195
|
-
- `0` : Use existing interpolation/boundary (IB) tables without recomputing them.
|
196
|
-
- `-1` : Do not use existing IB tables, force a recomputation.
|
197
|
-
|
198
|
-
Returns:
|
199
|
-
None
|
200
|
-
|
201
|
-
Raises:
|
202
|
-
ValueError: If `run_htab_value` or `use_ib_tables_value` are not integers or not within the accepted values (`0` or `-1`).
|
203
|
-
FileNotFoundError: If the specified file does not exist.
|
204
|
-
IOError: If there is an error reading or writing the file.
|
205
|
-
"""
|
206
|
-
config = ProjectConfig()
|
207
|
-
config.check_initialized()
|
208
|
-
|
209
|
-
if run_htab_value not in [-1, 0]:
|
210
|
-
raise ValueError("Invalid value for `Run HTab`. Expected `0` or `-1`.")
|
211
|
-
if use_ib_tables_value not in [-1, 0]:
|
212
|
-
raise ValueError("Invalid value for `UNET Use Existing IB Tables`. Expected `0` or `-1`.")
|
213
|
-
try:
|
214
|
-
print(f"Reading the file: {file_path}")
|
215
|
-
with open(file_path, 'r') as file:
|
216
|
-
lines = file.readlines()
|
217
|
-
print("Updating the file with new settings...")
|
218
|
-
updated_lines = []
|
219
|
-
for line in lines:
|
220
|
-
if line.strip().startswith("Run HTab="):
|
221
|
-
updated_line = f"Run HTab= {run_htab_value} \n"
|
222
|
-
updated_lines.append(updated_line)
|
223
|
-
print(f"Updated 'Run HTab' to {run_htab_value}")
|
224
|
-
elif line.strip().startswith("UNET Use Existing IB Tables="):
|
225
|
-
updated_line = f"UNET Use Existing IB Tables= {use_ib_tables_value} \n"
|
226
|
-
updated_lines.append(updated_line)
|
227
|
-
print(f"Updated 'UNET Use Existing IB Tables' to {use_ib_tables_value}")
|
228
|
-
else:
|
229
|
-
updated_lines.append(line)
|
230
|
-
print(f"Writing the updated settings back to the file: {file_path}")
|
231
|
-
with open(file_path, 'w') as file:
|
232
|
-
file.writelines(updated_lines)
|
233
|
-
print("File update completed successfully.")
|
234
|
-
except FileNotFoundError:
|
235
|
-
raise FileNotFoundError(f"The file '{file_path}' does not exist.")
|
236
|
-
except IOError as e:
|
237
|
-
raise IOError(f"An error occurred while reading or writing the file: {e}")
|
238
|
-
|
239
|
-
@staticmethod
|
240
|
-
def get_plan_full_path(plan_number: str) -> str:
|
241
|
-
"""Return the full path for a given plan number."""
|
242
|
-
config = ProjectConfig()
|
243
|
-
config.check_initialized()
|
244
|
-
|
245
|
-
plan_path = config.ras_plan_entries[config.ras_plan_entries['plan_number'] == plan_number]
|
246
|
-
if not plan_path.empty:
|
247
|
-
return plan_path['full_path'].iloc[0]
|
248
|
-
else:
|
249
|
-
raise ValueError(f"Plan number {plan_number} not found.")
|
250
|
-
|
251
|
-
@staticmethod
|
252
|
-
def get_results_full_path(plan_number: str) -> str:
|
253
|
-
"""Return the results path for a given plan number."""
|
254
|
-
config = ProjectConfig()
|
255
|
-
config.check_initialized()
|
256
|
-
|
257
|
-
results_path = config.ras_plan_entries[config.ras_plan_entries['plan_number'] == plan_number]
|
258
|
-
if not results_path.empty:
|
259
|
-
results_file_path = Path(results_path['results_path'].iloc[0])
|
260
|
-
if results_file_path.exists():
|
261
|
-
print(f"Results file for Plan number {plan_number} exists at: {results_file_path}")
|
262
|
-
return str(results_file_path)
|
263
|
-
else:
|
264
|
-
print(f"Error: Results file for Plan number {plan_number} does not exist at the expected location: {results_file_path}")
|
265
|
-
return None
|
266
|
-
else:
|
267
|
-
print(f"Error: Results file for Plan number {plan_number} not found in the entries.")
|
268
|
-
return None
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
@staticmethod
|
274
|
-
def get_flow_full_path(flow_number: str) -> str:
|
275
|
-
"""Return the full path for a given flow number."""
|
276
|
-
config = ProjectConfig()
|
277
|
-
config.check_initialized()
|
278
|
-
|
279
|
-
flow_path = config.ras_flow_entries[config.ras_flow_entries['flow_number'] == flow_number]
|
280
|
-
if not flow_path.empty:
|
281
|
-
return flow_path['full_path'].iloc[0]
|
282
|
-
else:
|
283
|
-
raise ValueError(f"Flow number {flow_number} not found.")
|
284
|
-
|
285
|
-
@staticmethod
|
286
|
-
def get_unsteady_full_path(unsteady_number: str) -> str:
|
287
|
-
"""Return the full path for a given unsteady number."""
|
288
|
-
config = ProjectConfig()
|
289
|
-
config.check_initialized()
|
290
|
-
|
291
|
-
unsteady_path = config.ras_unsteady_entries[config.ras_unsteady_entries['unsteady_number'] == unsteady_number]
|
292
|
-
if not unsteady_path.empty:
|
293
|
-
return unsteady_path['full_path'].iloc[0]
|
294
|
-
else:
|
295
|
-
raise ValueError(f"Unsteady number {unsteady_number} not found.")
|
296
|
-
|
297
|
-
@staticmethod
|
298
|
-
def get_geom_full_path(geometry_number: str) -> str:
|
299
|
-
"""Return the full path for a given geometry number."""
|
300
|
-
config = ProjectConfig()
|
301
|
-
config.check_initialized()
|
302
|
-
|
303
|
-
geom_path = config.ras_geom_entries[config.ras_geom_entries['geom_number'] == geometry_number]
|
304
|
-
if not geom_path.empty:
|
305
|
-
return geom_path['full_path'].iloc[0]
|
306
|
-
else:
|
307
|
-
raise ValueError(f"Geometry number {geometry_number} not found.")
|
ras_commander/project_config.py
DELETED
@@ -1,64 +0,0 @@
|
|
1
|
-
from pathlib import Path
|
2
|
-
from .project_setup import find_hecras_project_file, load_project_data
|
3
|
-
|
4
|
-
# Notes (do note delete):
|
5
|
-
# This ProjectConfig class is a singleton, so it will have the same values for all instances.
|
6
|
-
# The class is very important for the project setup, as it will be used to store all the project's basic information.
|
7
|
-
# Instead of having to pass around the project folder, project file, etc., we can just pass around the ProjectConfig class instance.
|
8
|
-
# The class will need to be initialized with the project folder, which will then be used to set all the other project information.
|
9
|
-
# The project information will be stored in the instance as class variables.
|
10
|
-
|
11
|
-
# Documentation Notes:
|
12
|
-
# print each variable name and value after it is defined, so the user can easily reference the project's basic information using the self. class variables
|
13
|
-
# example: print(f"self.project_file: {self.project_file}")
|
14
|
-
|
15
|
-
class ProjectConfig:
|
16
|
-
_instance = None
|
17
|
-
|
18
|
-
def __new__(cls):
|
19
|
-
if cls._instance is None:
|
20
|
-
cls._instance = super(ProjectConfig, cls).__new__(cls)
|
21
|
-
cls._instance.initialized = False
|
22
|
-
return cls._instance
|
23
|
-
|
24
|
-
def initialize(self, project_folder, hecras_exe_path):
|
25
|
-
self.project_folder = Path(project_folder)
|
26
|
-
print(f"self.project_folder: {self.project_folder}")
|
27
|
-
|
28
|
-
self.project_file = find_hecras_project_file(self.project_folder)
|
29
|
-
print(f"self.project_file: {self.project_file}")
|
30
|
-
|
31
|
-
if self.project_file is None:
|
32
|
-
raise ValueError(f"No HEC-RAS project file found in {self.project_folder}")
|
33
|
-
|
34
|
-
self.project_name = self.project_file.stem
|
35
|
-
print(f"self.project_name: {self.project_name}")
|
36
|
-
|
37
|
-
self.hecras_exe_path = hecras_exe_path
|
38
|
-
print(f"self.hecras_exe_path: {self.hecras_exe_path}")
|
39
|
-
|
40
|
-
self._load_project_data()
|
41
|
-
self.initialized = True
|
42
|
-
print(f"self.initialized: {self.initialized}")
|
43
|
-
|
44
|
-
def _load_project_data(self):
|
45
|
-
data = load_project_data(self.project_file)
|
46
|
-
self.ras_plan_entries = data['ras_plan_entries']
|
47
|
-
print(f"self.ras_plan_entries: {self.ras_plan_entries}")
|
48
|
-
|
49
|
-
self.ras_flow_entries = data['ras_flow_entries']
|
50
|
-
print(f"self.ras_flow_entries: {self.ras_flow_entries}")
|
51
|
-
|
52
|
-
self.ras_unsteady_entries = data['ras_unsteady_entries']
|
53
|
-
print(f"self.ras_unsteady_entries: {self.ras_unsteady_entries}")
|
54
|
-
|
55
|
-
self.ras_geom_entries = data['ras_geom_entries']
|
56
|
-
print(f"self.ras_geom_entries: {self.ras_geom_entries}")
|
57
|
-
|
58
|
-
@property
|
59
|
-
def is_initialized(self):
|
60
|
-
return self.initialized
|
61
|
-
|
62
|
-
def check_initialized(self):
|
63
|
-
if not self.initialized:
|
64
|
-
raise RuntimeError("Project not initialized. Call init_ras_project() first.")
|
ras_commander/project_init.py
DELETED
@@ -1,174 +0,0 @@
|
|
1
|
-
from .project_config import ProjectConfig
|
2
|
-
from pathlib import Path
|
3
|
-
|
4
|
-
def init_ras_project(ras_project_folder, hecras_version_or_path):
|
5
|
-
"""
|
6
|
-
Initialize a HEC-RAS project.
|
7
|
-
|
8
|
-
This function sets up a HEC-RAS project by validating the project folder,
|
9
|
-
determining the HEC-RAS executable path, and initializing the project configuration.
|
10
|
-
|
11
|
-
Args:
|
12
|
-
ras_project_folder (str): Path to the HEC-RAS project folder.
|
13
|
-
hecras_version_or_path (str): Either the HEC-RAS version number or the full path to the HEC-RAS executable.
|
14
|
-
|
15
|
-
Returns:
|
16
|
-
ProjectConfig: An initialized ProjectConfig object containing the project configuration.
|
17
|
-
|
18
|
-
Raises:
|
19
|
-
FileNotFoundError: If the specified RAS project folder does not exist.
|
20
|
-
|
21
|
-
Note:
|
22
|
-
This function prints a confirmation message upon successful initialization.
|
23
|
-
|
24
|
-
Future Development Roadmap:
|
25
|
-
|
26
|
-
1. Load critical keys and values from the project files into the project config
|
27
|
-
Implemented:
|
28
|
-
- Project Name
|
29
|
-
- Project Folder
|
30
|
-
- Lists of plan, flow, unsteady, and geometry files
|
31
|
-
- HEC-RAS Executable Path
|
32
|
-
|
33
|
-
Not Implemented:
|
34
|
-
- Units
|
35
|
-
- Coordinate System
|
36
|
-
- rasmap file path (replace prj file path extension with ".rasmap" and add it to the project config)
|
37
|
-
- Current Plan
|
38
|
-
- Description (including checks to see if it is a valid string and within the default max length)
|
39
|
-
- DSS Start Date=01JAN1999 (note format is MMDDYYY)
|
40
|
-
- DSS Start Time=1200 (note format is HHMM)
|
41
|
-
- DSS End Date=04JAN1999 (note format is MMDDYYY)
|
42
|
-
- DSS End Time=1200 (note format is HHMM)
|
43
|
-
- DSS File=dss
|
44
|
-
- DSS File=Bald_Eagle_Creek.dss
|
45
|
-
|
46
|
-
Other not implemented:
|
47
|
-
|
48
|
-
2. Load critical keys and lists of string values from the plan files into the project config
|
49
|
-
- Plan Title
|
50
|
-
- Plan Shortid
|
51
|
-
- Simulation Date
|
52
|
-
- Geometry File
|
53
|
-
- Flow File (may not be present) - if present, the plan is a 1D steady plan
|
54
|
-
- Unsteady File (may not be present) - if present, the plan is a 1D or 2D unsteady plan
|
55
|
-
- UNET D2 Name (may not be present) - if present, the plan is a 2D plan
|
56
|
-
- Type (1D Steady, 1D Unsteady, 1D/2D, or 2D)
|
57
|
-
- UNET 1D Methodology
|
58
|
-
|
59
|
-
3. Load critical keys and strings from the unsteady flow files into the project config
|
60
|
-
- Flow Title
|
61
|
-
- Pandas Dataframe for any Boundary Conditions present and whether they are defined in the file or whether they use a DSS file input
|
62
|
-
- One dataframe for all unsteady flow files, with each Boundary Location in each file having its own row
|
63
|
-
- For each unsteady flow filereturn an appended dataframe with each boundary condition and it's "Boundary Name", "Interval", "DSS Path", "Flow Hydrograph Slope", and whether Use DSS is True or False
|
64
|
-
- Need to incorporate knowledge from the excel methods we used for setting boundary conditions
|
65
|
-
|
66
|
-
4. Load critical keys and strings from the steady flow files into the project config
|
67
|
-
- Flow Title
|
68
|
-
- Since steady models are not as commonly used, this is a low priority integration (external contributions are welcome)
|
69
|
-
|
70
|
-
|
71
|
-
5. Load critical keys and values from the rasmap file into the project config
|
72
|
-
- rasmap_projection_string
|
73
|
-
- Version #Ex: <Version>2.0.0</Version>
|
74
|
-
- RASProjectionFilename Filename=".\Terrain\Projection.prj"
|
75
|
-
|
76
|
-
- List of ras terrains as pandas dataframes
|
77
|
-
- for each, list of tiff files and order
|
78
|
-
- flag whether terrain mods exist
|
79
|
-
|
80
|
-
- List of Infiltration hdf files as pandas dataframes
|
81
|
-
- Mapping of infiltration layers to geometries
|
82
|
-
|
83
|
-
- List of land cover hdf files as pandas dataframes
|
84
|
-
- Mapping of land cover to geometries
|
85
|
-
|
86
|
-
- List of all Mannings N layers, hdf files and mapping to geometries as pandas dataframes
|
87
|
-
|
88
|
-
6. Create a list of all valid hdf plan files are present in the project folder, and flag whether they contain a completed simulation
|
89
|
-
|
90
|
-
This roadmap for the project_init function will provide the basic information needed to support most basic hec-ras automation workflows.
|
91
|
-
|
92
|
-
Remember, this project init might be called multiple times. Every time, it should clear any previously created datafrarmes and variables and replace them. It is important that revisions can be made, init be re-run, and information is current and reflects the current state of the project.
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
"""
|
97
|
-
# Check if the provided paths exist
|
98
|
-
if not Path(ras_project_folder).exists():
|
99
|
-
raise FileNotFoundError(f"The specified RAS project folder does not exist: {ras_project_folder}, Please check the path and try again.")
|
100
|
-
|
101
|
-
hecras_exe_path = get_hecras_exe_path(hecras_version_or_path)
|
102
|
-
|
103
|
-
config = ProjectConfig()
|
104
|
-
config.initialize(ras_project_folder, hecras_exe_path)
|
105
|
-
print(f"HEC-RAS project initialized: {config.project_name}")
|
106
|
-
return config
|
107
|
-
|
108
|
-
|
109
|
-
def get_hecras_exe_path(hecras_version_or_path):
|
110
|
-
"""
|
111
|
-
Determine the HEC-RAS executable path based on the input.
|
112
|
-
|
113
|
-
Args:
|
114
|
-
hecras_version_or_path (str): Either a version number or a full path to the HEC-RAS executable.
|
115
|
-
|
116
|
-
Returns:
|
117
|
-
str: The full path to the HEC-RAS executable.
|
118
|
-
|
119
|
-
Raises:
|
120
|
-
ValueError: If the input is neither a valid version number nor a valid file path.
|
121
|
-
FileNotFoundError: If the executable file does not exist at the specified or constructed path.
|
122
|
-
"""
|
123
|
-
|
124
|
-
|
125
|
-
# hecras_exe_path should be changed to hecras_version_or_path
|
126
|
-
# Based on whether a full path is provided, or a version number is provided, the path will be set accordingly
|
127
|
-
# By default, HEC-RAS is installed in the Program Files (x86) folder
|
128
|
-
# For example: hecras_exe_path = r"C:\Program Files (x86)\HEC\HEC-RAS\6.5\Ras.exe" for version 6.5
|
129
|
-
# an f string to build the path based on the version number
|
130
|
-
# hecras_exe_path = f"C:\Program Files (x86)\HEC\HEC-RAS\{hecras_version}\Ras.exe"
|
131
|
-
# where hecras_version is one of the following:
|
132
|
-
|
133
|
-
# List of HEC-RAS version numbers
|
134
|
-
ras_version_numbers = [
|
135
|
-
"6.5", "6.4.1", "6.3.1", "6.3", "6.2", "6.1", "6.0",
|
136
|
-
"5.0.7", "5.0.6", "5.0.5", "5.0.4", "5.0.3", "5.0.1", "5.0",
|
137
|
-
"4.1", "4.0", "3.1.3", "3.1.2", "3.1.1", "3.0", "2.2"
|
138
|
-
]
|
139
|
-
|
140
|
-
hecras_path = Path(hecras_version_or_path)
|
141
|
-
|
142
|
-
# Check if the input is a full path
|
143
|
-
if hecras_path.is_file() and hecras_path.suffix.lower() == '.exe':
|
144
|
-
return str(hecras_path)
|
145
|
-
|
146
|
-
# Check if the input is a version number
|
147
|
-
if hecras_version_or_path in ras_version_numbers:
|
148
|
-
default_path = Path(f"C:/Program Files (x86)/HEC/HEC-RAS/{hecras_version_or_path}/Ras.exe")
|
149
|
-
if default_path.is_file():
|
150
|
-
return str(default_path)
|
151
|
-
else:
|
152
|
-
raise FileNotFoundError(f"HEC-RAS executable not found at the expected path: {default_path}")
|
153
|
-
|
154
|
-
# Check if it's a newer version
|
155
|
-
try:
|
156
|
-
version_float = float(hecras_version_or_path)
|
157
|
-
if version_float > max(float(v) for v in ras_version_numbers):
|
158
|
-
newer_version_path = Path(f"C:/Program Files (x86)/HEC/HEC-RAS/{hecras_version_or_path}/Ras.exe")
|
159
|
-
if newer_version_path.is_file():
|
160
|
-
return str(newer_version_path)
|
161
|
-
else:
|
162
|
-
raise FileNotFoundError(f"Newer version of HEC-RAS was specified. Check the version number or pass the full Ras.exe path as the function argument instead of the version number. The script looked for the executable at: {newer_version_path}")
|
163
|
-
except ValueError:
|
164
|
-
pass # Not a valid float, so not a version number
|
165
|
-
|
166
|
-
raise ValueError(f"Invalid HEC-RAS version or path: {hecras_version_or_path}. "
|
167
|
-
f"Please provide a valid version number from {ras_version_numbers} "
|
168
|
-
"or a full path to the HEC-RAS executable.")
|
169
|
-
# Return the validated HEC-RAS executable path
|
170
|
-
return hecras_exe_path
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|