ras-commander 0.40.0__py3-none-any.whl → 0.41.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/RasPlan.py CHANGED
@@ -45,8 +45,9 @@ class RasPlan:
45
45
  """
46
46
  A class for operations on HEC-RAS plan files.
47
47
  """
48
- @log_call
48
+
49
49
  @staticmethod
50
+ @log_call
50
51
  def set_geom(plan_number: Union[str, int], new_geom: Union[str, int], ras_object=None) -> pd.DataFrame:
51
52
  """
52
53
  Set the geometry for the specified plan.
@@ -78,30 +79,28 @@ class RasPlan:
78
79
  ras_obj.flow_df = ras_obj.get_flow_entries()
79
80
  ras_obj.unsteady_df = ras_obj.get_unsteady_entries()
80
81
 
81
- # Log the current geometry DataFrame for debugging
82
- logging.debug("Current geometry DataFrame within the function:")
83
- logging.debug(ras_obj.geom_df)
84
-
85
82
  if new_geom not in ras_obj.geom_df['geom_number'].values:
86
- logging.error(f"Geometry {new_geom} not found in project.")
83
+ logger.error(f"Geometry {new_geom} not found in project.")
87
84
  raise ValueError(f"Geometry {new_geom} not found in project.")
88
85
 
89
86
  # Update the geometry for the specified plan
90
87
  ras_obj.plan_df.loc[ras_obj.plan_df['plan_number'] == plan_number, 'geom_number'] = new_geom
91
88
 
92
- logging.info(f"Geometry for plan {plan_number} set to {new_geom}")
93
- logging.debug("Updated plan DataFrame:")
94
- logging.debug(ras_obj.plan_df)
89
+ logger.info(f"Geometry for plan {plan_number} set to {new_geom}")
90
+ logger.debug("Updated plan DataFrame:")
91
+ logger.debug(ras_obj.plan_df)
95
92
 
96
93
  # Update the project file
97
94
  prj_file_path = ras_obj.prj_file
98
- try:
99
- with open(prj_file_path, 'r') as f:
100
- lines = f.readlines()
101
- except FileNotFoundError:
102
- logging.error(f"Project file not found: {prj_file_path}")
103
- raise
95
+ RasUtils.update_file(prj_file_path, RasPlan._update_geom_in_file, plan_number, new_geom)
96
+
97
+ # Re-initialize the ras object to reflect changes
98
+ ras_obj.initialize(ras_obj.project_folder, ras_obj.ras_exe_path)
104
99
 
100
+ return ras_obj.plan_df
101
+
102
+ @staticmethod
103
+ def _update_geom_in_file(lines, plan_number, new_geom):
105
104
  plan_pattern = re.compile(rf"^Plan File=p{plan_number}", re.IGNORECASE)
106
105
  geom_pattern = re.compile(r"^Geom File=g\d+", re.IGNORECASE)
107
106
 
@@ -110,22 +109,10 @@ class RasPlan:
110
109
  for j in range(i+1, len(lines)):
111
110
  if geom_pattern.match(lines[j]):
112
111
  lines[j] = f"Geom File=g{new_geom}\n"
113
- logging.info(f"Updated Geom File in project file to g{new_geom} for plan {plan_number}")
112
+ logger.info(f"Updated Geom File in project file to g{new_geom} for plan {plan_number}")
114
113
  break
115
114
  break
116
-
117
- try:
118
- with open(prj_file_path, 'w') as f:
119
- f.writelines(lines)
120
- logging.info(f"Updated project file with new geometry for plan {plan_number}")
121
- except IOError as e:
122
- logging.error(f"Failed to write to project file: {e}")
123
- raise
124
-
125
- # Re-initialize the ras object to reflect changes
126
- ras_obj.initialize(ras_obj.project_folder, ras_obj.ras_exe_path)
127
-
128
- return ras_obj.plan_df
115
+ return lines
129
116
 
130
117
  @staticmethod
131
118
  @log_call
@@ -165,18 +152,7 @@ class RasPlan:
165
152
  if not plan_file_path:
166
153
  raise FileNotFoundError(f"Plan file not found: {plan_number}")
167
154
 
168
- try:
169
- with open(plan_file_path, 'r') as f:
170
- lines = f.readlines()
171
- except FileNotFoundError:
172
- raise FileNotFoundError(f"Plan file not found: {plan_file_path}")
173
-
174
- with open(plan_file_path, 'w') as f:
175
- for line in lines:
176
- if line.startswith("Flow File=f"):
177
- f.write(f"Flow File=f{new_steady_flow_number}\n")
178
- else:
179
- f.write(line)
155
+ RasUtils.update_file(plan_file_path, RasPlan._update_steady_in_file, new_steady_flow_number)
180
156
 
181
157
  # Update the ras object's dataframes
182
158
  ras_obj.plan_df = ras_obj.get_plan_entries()
@@ -184,6 +160,10 @@ class RasPlan:
184
160
  ras_obj.flow_df = ras_obj.get_flow_entries()
185
161
  ras_obj.unsteady_df = ras_obj.get_unsteady_entries()
186
162
 
163
+ @staticmethod
164
+ def _update_steady_in_file(lines, new_steady_flow_number):
165
+ return [f"Flow File=f{new_steady_flow_number}\n" if line.startswith("Flow File=f") else line for line in lines]
166
+
187
167
  @staticmethod
188
168
  @log_call
189
169
  def set_unsteady(plan_number: str, new_unsteady_flow_number: str, ras_object=None):
@@ -223,7 +203,7 @@ class RasPlan:
223
203
  raise FileNotFoundError(f"Plan file not found: {plan_number}")
224
204
 
225
205
  try:
226
- RasUtils.update_plan_file(plan_file_path, 'Unsteady', new_unsteady_flow_number)
206
+ RasUtils.update_file(plan_file_path, RasPlan._update_unsteady_in_file, new_unsteady_flow_number)
227
207
  except Exception as e:
228
208
  raise Exception(f"Failed to update unsteady flow file: {e}")
229
209
 
@@ -234,6 +214,9 @@ class RasPlan:
234
214
  ras_obj.unsteady_df = ras_obj.get_unsteady_entries()
235
215
 
236
216
  @staticmethod
217
+ def _update_unsteady_in_file(lines, new_unsteady_flow_number):
218
+ return [f"Unsteady File=u{new_unsteady_flow_number}\n" if line.startswith("Unsteady File=u") else line for line in lines]
219
+ @staticmethod
237
220
  @log_call
238
221
  def set_num_cores(plan_number, num_cores, ras_object=None):
239
222
  """
@@ -266,33 +249,24 @@ class RasPlan:
266
249
  ras_obj = ras_object or ras
267
250
  ras_obj.check_initialized()
268
251
 
269
- # Determine if plan_number is a path or a plan number
270
- if Path(plan_number).is_file():
271
- plan_file_path = Path(plan_number)
272
- if not plan_file_path.exists():
273
- raise FileNotFoundError(f"Plan file not found: {plan_file_path}. Please provide a valid plan number or path.")
274
- else:
275
- # Update the plan dataframe in the ras instance to ensure it is current
276
- ras_obj.plan_df = ras_obj.get_prj_entries('Plan')
277
-
278
- # Get the full path of the plan file
279
- plan_file_path = RasPlan.get_plan_path(plan_number, ras_obj)
280
- if not plan_file_path:
281
- raise FileNotFoundError(f"Plan file not found: {plan_number}. Please provide a valid plan number or path.")
252
+ plan_file_path = RasUtils.get_plan_path(plan_number, ras_obj)
253
+ if not plan_file_path:
254
+ raise FileNotFoundError(f"Plan file not found: {plan_number}. Please provide a valid plan number or path.")
282
255
 
283
- cores_pattern = re.compile(r"(UNET D1 Cores= )\d+")
284
- try:
285
- with open(plan_file_path, 'r') as file:
286
- content = file.read()
287
- except FileNotFoundError:
288
- raise FileNotFoundError(f"Plan file not found: {plan_file_path}")
256
+ def update_num_cores(lines):
257
+ updated_lines = []
258
+ for line in lines:
259
+ if "UNET D1 Cores=" in line:
260
+ parts = line.split("=")
261
+ updated_lines.append(f"{parts[0]}= {num_cores}\n")
262
+ else:
263
+ updated_lines.append(line)
264
+ return updated_lines
289
265
 
290
- new_content = cores_pattern.sub(rf"\g<1>{num_cores}", content)
291
266
  try:
292
- with open(plan_file_path, 'w') as file:
293
- file.write(new_content)
294
- except IOError as e:
295
- raise IOError(f"Failed to write to plan file: {e}")
267
+ RasUtils.update_file(plan_file_path, update_num_cores)
268
+ except Exception as e:
269
+ raise IOError(f"Failed to update number of cores in plan file: {e}")
296
270
 
297
271
  # Update the ras object's dataframes
298
272
  ras_obj.plan_df = ras_obj.get_plan_entries()
@@ -337,21 +311,20 @@ class RasPlan:
337
311
  raise ValueError("Invalid value for `Run HTab`. Expected `0` or `-1`.")
338
312
  if use_ib_tables not in [-1, 0]:
339
313
  raise ValueError("Invalid value for `UNET Use Existing IB Tables`. Expected `0` or `-1`.")
340
- try:
341
- with open(file_path, 'r') as file:
342
- lines = file.readlines()
314
+
315
+ def update_geom_preprocessor(lines, run_htab, use_ib_tables):
343
316
  updated_lines = []
344
317
  for line in lines:
345
318
  if line.lstrip().startswith("Run HTab="):
346
- updated_line = f"Run HTab= {run_htab} \n"
347
- updated_lines.append(updated_line)
319
+ updated_lines.append(f"Run HTab= {run_htab} \n")
348
320
  elif line.lstrip().startswith("UNET Use Existing IB Tables="):
349
- updated_line = f"UNET Use Existing IB Tables= {use_ib_tables} \n"
350
- updated_lines.append(updated_line)
321
+ updated_lines.append(f"UNET Use Existing IB Tables= {use_ib_tables} \n")
351
322
  else:
352
323
  updated_lines.append(line)
353
- with open(file_path, 'w') as file:
354
- file.writelines(updated_lines)
324
+ return updated_lines
325
+
326
+ try:
327
+ RasUtils.update_file(file_path, update_geom_preprocessor, run_htab, use_ib_tables)
355
328
  except FileNotFoundError:
356
329
  raise FileNotFoundError(f"The file '{file_path}' does not exist.")
357
330
  except IOError as e:
@@ -591,79 +564,27 @@ class RasPlan:
591
564
  new_plan_num = RasPlan.get_next_number(ras_obj.plan_df['plan_number'])
592
565
  template_plan_path = ras_obj.project_folder / f"{ras_obj.project_name}.p{template_plan}"
593
566
  new_plan_path = ras_obj.project_folder / f"{ras_obj.project_name}.p{new_plan_num}"
594
-
595
- if not template_plan_path.exists():
596
- raise FileNotFoundError(f"Template plan file '{template_plan_path}' does not exist.")
597
-
598
- shutil.copy(template_plan_path, new_plan_path)
599
567
 
600
- try:
601
- with open(new_plan_path, 'r') as f:
602
- plan_lines = f.readlines()
603
- except FileNotFoundError:
604
- raise FileNotFoundError(f"New plan file not found after copying: {new_plan_path}")
605
-
606
- shortid_pattern = re.compile(r'^Short Identifier=(.*)$', re.IGNORECASE)
607
- for i, line in enumerate(plan_lines):
608
- match = shortid_pattern.match(line.strip())
609
- if match:
610
- current_shortid = match.group(1)
611
- if new_plan_shortid is None:
612
- new_shortid = (current_shortid + "_copy")[:24]
613
- else:
614
- new_shortid = new_plan_shortid[:24]
615
- plan_lines[i] = f"Short Identifier={new_shortid}\n"
616
- break
617
-
618
- try:
619
- with open(new_plan_path, 'w') as f:
620
- f.writelines(plan_lines)
621
- except IOError as e:
622
- raise IOError(f"Failed to write updated short identifier to {new_plan_path}: {e}")
623
-
624
- try:
625
- with open(ras_obj.prj_file, 'r') as f:
626
- lines = f.readlines()
627
- except FileNotFoundError:
628
- raise FileNotFoundError(f"Project file not found: {ras_obj.prj_file}")
629
-
630
- # Prepare the new Plan File entry line
631
- new_plan_line = f"Plan File=p{new_plan_num}\n"
632
-
633
- # Find the correct insertion point for the new Plan File entry
634
- plan_file_pattern = re.compile(r'^Plan File=p(\d+)', re.IGNORECASE)
635
- insertion_index = None
636
- for i, line in enumerate(lines):
637
- match = plan_file_pattern.match(line.strip())
638
- if match:
639
- current_number = int(match.group(1))
640
- if current_number < int(new_plan_num):
641
- continue
642
- else:
643
- insertion_index = i
568
+ def update_shortid(lines):
569
+ shortid_pattern = re.compile(r'^Short Identifier=(.*)$', re.IGNORECASE)
570
+ for i, line in enumerate(lines):
571
+ match = shortid_pattern.match(line.strip())
572
+ if match:
573
+ current_shortid = match.group(1)
574
+ if new_plan_shortid is None:
575
+ new_shortid = (current_shortid + "_copy")[:24]
576
+ else:
577
+ new_shortid = new_plan_shortid[:24]
578
+ lines[i] = f"Short Identifier={new_shortid}\n"
644
579
  break
580
+ return lines
645
581
 
646
- if insertion_index is not None:
647
- lines.insert(insertion_index, new_plan_line)
648
- else:
649
- # Try to insert after the last Plan File entry
650
- plan_indices = [i for i, line in enumerate(lines) if plan_file_pattern.match(line.strip())]
651
- if plan_indices:
652
- last_plan_index = plan_indices[-1]
653
- lines.insert(last_plan_index + 1, new_plan_line)
654
- else:
655
- # Append at the end if no Plan File entries exist
656
- lines.append(new_plan_line)
582
+ # Use RasUtils to clone the file and update the short identifier
583
+ RasUtils.clone_file(template_plan_path, new_plan_path, update_shortid)
657
584
 
658
- try:
659
- # Write the updated lines back to the project file
660
- with open(ras_obj.prj_file, 'w') as f:
661
- f.writelines(lines)
662
- except IOError as e:
663
- raise IOError(f"Failed to write updated project file: {e}")
585
+ # Use RasUtils to update the project file
586
+ RasUtils.update_project_file(ras_obj.prj_file, 'Plan', new_plan_num, ras_object=ras_obj)
664
587
 
665
- new_plan = new_plan_num
666
-
667
588
  # Re-initialize the ras global object
668
589
  ras_obj.initialize(ras_obj.project_folder, ras_obj.ras_exe_path)
669
590
 
@@ -672,7 +593,7 @@ class RasPlan:
672
593
  ras_obj.flow_df = ras_obj.get_flow_entries()
673
594
  ras_obj.unsteady_df = ras_obj.get_unsteady_entries()
674
595
 
675
- return new_plan
596
+ return new_plan_num
676
597
 
677
598
  @staticmethod
678
599
  @log_call
@@ -706,10 +627,8 @@ class RasPlan:
706
627
  template_unsteady_path = ras_obj.project_folder / f"{ras_obj.project_name}.u{template_unsteady}"
707
628
  new_unsteady_path = ras_obj.project_folder / f"{ras_obj.project_name}.u{new_unsteady_num}"
708
629
 
709
- if not template_unsteady_path.exists():
710
- raise FileNotFoundError(f"Template unsteady file '{template_unsteady_path}' does not exist.")
711
-
712
- shutil.copy(template_unsteady_path, new_unsteady_path)
630
+ # Use RasUtils to clone the file
631
+ RasUtils.clone_file(template_unsteady_path, new_unsteady_path)
713
632
 
714
633
  # Copy the corresponding .hdf file if it exists
715
634
  template_hdf_path = ras_obj.project_folder / f"{ras_obj.project_name}.u{template_unsteady}.hdf"
@@ -717,58 +636,19 @@ class RasPlan:
717
636
  if template_hdf_path.exists():
718
637
  shutil.copy(template_hdf_path, new_hdf_path)
719
638
 
720
- try:
721
- with open(ras_obj.prj_file, 'r') as f:
722
- lines = f.readlines()
723
- except FileNotFoundError:
724
- raise FileNotFoundError(f"Project file not found: {ras_obj.prj_file}")
725
-
726
- # Prepare the new Unsteady Flow File entry line
727
- new_unsteady_line = f"Unsteady File=u{new_unsteady_num}\n"
728
-
729
- # Find the correct insertion point for the new Unsteady Flow File entry
730
- unsteady_file_pattern = re.compile(r'^Unsteady File=u(\d+)', re.IGNORECASE)
731
- insertion_index = None
732
- for i, line in enumerate(lines):
733
- match = unsteady_file_pattern.match(line.strip())
734
- if match:
735
- current_number = int(match.group(1))
736
- if current_number < int(new_unsteady_num):
737
- continue
738
- else:
739
- insertion_index = i
740
- break
741
-
742
- if insertion_index is not None:
743
- lines.insert(insertion_index, new_unsteady_line)
744
- else:
745
- # Try to insert after the last Unsteady Flow File entry
746
- unsteady_indices = [i for i, line in enumerate(lines) if unsteady_file_pattern.match(line.strip())]
747
- if unsteady_indices:
748
- last_unsteady_index = unsteady_indices[-1]
749
- lines.insert(last_unsteady_index + 1, new_unsteady_line)
750
- else:
751
- # Append at the end if no Unsteady Flow File entries exist
752
- lines.append(new_unsteady_line)
753
-
754
- try:
755
- # Write the updated lines back to the project file
756
- with open(ras_obj.prj_file, 'w') as f:
757
- f.writelines(lines)
758
- except IOError as e:
759
- raise IOError(f"Failed to write updated project file: {e}")
639
+ # Use RasUtils to update the project file
640
+ RasUtils.update_project_file(ras_obj.prj_file, 'Unsteady', new_unsteady_num, ras_object=ras_obj)
760
641
 
761
- new_unsteady = new_unsteady_num
762
-
763
642
  # Re-initialize the ras global object
764
643
  ras_obj.initialize(ras_obj.project_folder, ras_obj.ras_exe_path)
765
-
644
+
766
645
  ras_obj.plan_df = ras_obj.get_plan_entries()
767
646
  ras_obj.geom_df = ras_obj.get_geom_entries()
768
647
  ras_obj.flow_df = ras_obj.get_flow_entries()
769
648
  ras_obj.unsteady_df = ras_obj.get_unsteady_entries()
770
-
771
- return new_unsteady
649
+
650
+ return new_unsteady_num
651
+
772
652
 
773
653
  @staticmethod
774
654
  @log_call
@@ -802,55 +682,12 @@ class RasPlan:
802
682
  template_flow_path = ras_obj.project_folder / f"{ras_obj.project_name}.f{template_flow}"
803
683
  new_flow_path = ras_obj.project_folder / f"{ras_obj.project_name}.f{new_flow_num}"
804
684
 
805
- if not template_flow_path.exists():
806
- raise FileNotFoundError(f"Template steady flow file '{template_flow_path}' does not exist.")
807
-
808
- shutil.copy(template_flow_path, new_flow_path)
809
-
810
- # Read the contents of the project file
811
- try:
812
- with open(ras_obj.prj_file, 'r') as f:
813
- lines = f.readlines()
814
- except FileNotFoundError:
815
- raise FileNotFoundError(f"Project file not found: {ras_obj.prj_file}")
816
-
817
- # Prepare the new Steady Flow File entry line
818
- new_flow_line = f"Flow File=f{new_flow_num}\n"
819
-
820
- # Find the correct insertion point for the new Steady Flow File entry
821
- flow_file_pattern = re.compile(r'^Flow File=f(\d+)', re.IGNORECASE)
822
- insertion_index = None
823
- for i, line in enumerate(lines):
824
- match = flow_file_pattern.match(line.strip())
825
- if match:
826
- current_number = int(match.group(1))
827
- if current_number < int(new_flow_num):
828
- continue
829
- else:
830
- insertion_index = i
831
- break
832
-
833
- if insertion_index is not None:
834
- lines.insert(insertion_index, new_flow_line)
835
- else:
836
- # Try to insert after the last Steady Flow File entry
837
- flow_indices = [i for i, line in enumerate(lines) if flow_file_pattern.match(line.strip())]
838
- if flow_indices:
839
- last_flow_index = flow_indices[-1]
840
- lines.insert(last_flow_index + 1, new_flow_line)
841
- else:
842
- # Append at the end if no Steady Flow File entries exist
843
- lines.append(new_flow_line)
685
+ # Use RasUtils to clone the file
686
+ RasUtils.clone_file(template_flow_path, new_flow_path)
844
687
 
845
- try:
846
- # Write the updated lines back to the project file
847
- with open(ras_obj.prj_file, 'w') as f:
848
- f.writelines(lines)
849
- except IOError as e:
850
- raise IOError(f"Failed to write updated project file: {e}")
688
+ # Use RasUtils to update the project file
689
+ RasUtils.update_project_file(ras_obj.prj_file, 'Flow', new_flow_num, ras_object=ras_obj)
851
690
 
852
- new_steady = new_flow_num
853
-
854
691
  # Re-initialize the ras global object
855
692
  ras_obj.initialize(ras_obj.project_folder, ras_obj.ras_exe_path)
856
693
 
@@ -859,7 +696,7 @@ class RasPlan:
859
696
  ras_obj.flow_df = ras_obj.get_flow_entries()
860
697
  ras_obj.unsteady_df = ras_obj.get_unsteady_entries()
861
698
 
862
- return new_steady
699
+ return new_flow_num
863
700
 
864
701
  @staticmethod
865
702
  @log_call
@@ -884,75 +721,29 @@ class RasPlan:
884
721
  # Update geometry entries without reinitializing the entire project
885
722
  ras_obj.geom_df = ras_obj.get_prj_entries('Geom')
886
723
 
887
- template_geom_filename = f"{ras_obj.project_name}.g{template_geom}"
888
- template_geom_path = ras_obj.project_folder / template_geom_filename
724
+ new_geom_num = RasPlan.get_next_number(ras_obj.geom_df['geom_number'])
725
+ template_geom_path = ras_obj.project_folder / f"{ras_obj.project_name}.g{template_geom}"
726
+ new_geom_path = ras_obj.project_folder / f"{ras_obj.project_name}.g{new_geom_num}"
889
727
 
890
- if not template_geom_path.is_file():
891
- raise FileNotFoundError(f"Template geometry file '{template_geom_path}' does not exist.")
892
-
893
- next_geom_number = RasPlan.get_next_number(ras_obj.geom_df['geom_number'])
894
-
895
- new_geom_filename = f"{ras_obj.project_name}.g{next_geom_number}"
896
- new_geom_path = ras_obj.project_folder / new_geom_filename
897
-
898
- shutil.copyfile(template_geom_path, new_geom_path)
728
+ # Use RasUtils to clone the file
729
+ RasUtils.clone_file(template_geom_path, new_geom_path)
899
730
 
900
731
  # Handle HDF file copy
901
732
  template_hdf_path = ras_obj.project_folder / f"{ras_obj.project_name}.g{template_geom}.hdf"
902
- new_hdf_path = ras_obj.project_folder / f"{ras_obj.project_name}.g{next_geom_number}.hdf"
733
+ new_hdf_path = ras_obj.project_folder / f"{ras_obj.project_name}.g{new_geom_num}.hdf"
903
734
  if template_hdf_path.is_file():
904
- shutil.copyfile(template_hdf_path, new_hdf_path)
905
-
906
- try:
907
- with open(ras_obj.prj_file, 'r') as file:
908
- lines = file.readlines()
909
- except FileNotFoundError:
910
- raise FileNotFoundError(f"Project file not found: {ras_obj.prj_file}")
911
-
912
- # Prepare the new Geometry File entry line
913
- new_geom_line = f"Geom File=g{next_geom_number}\n"
914
-
915
- # Find the correct insertion point for the new Geometry File entry
916
- geom_file_pattern = re.compile(r'^Geom File=g(\d+)', re.IGNORECASE)
917
- insertion_index = None
918
- for i, line in enumerate(lines):
919
- match = geom_file_pattern.match(line.strip())
920
- if match:
921
- current_number = int(match.group(1))
922
- if current_number < int(next_geom_number):
923
- continue
924
- else:
925
- insertion_index = i
926
- break
927
-
928
- if insertion_index is not None:
929
- lines.insert(insertion_index, new_geom_line)
930
- else:
931
- # Try to insert after the last Geometry File entry
932
- geom_indices = [i for i, line in enumerate(lines) if geom_file_pattern.match(line.strip())]
933
- if geom_indices:
934
- last_geom_index = geom_indices[-1]
935
- lines.insert(last_geom_index + 1, new_geom_line)
936
- else:
937
- # Append at the end if no Geometry File entries exist
938
- lines.append(new_geom_line)
735
+ RasUtils.clone_file(template_hdf_path, new_hdf_path)
939
736
 
940
- try:
941
- # Write the updated lines back to the project file
942
- with open(ras_obj.prj_file, 'w') as file:
943
- file.writelines(lines)
944
- except IOError as e:
945
- raise IOError(f"Failed to write updated project file: {e}")
737
+ # Use RasUtils to update the project file
738
+ RasUtils.update_project_file(ras_obj.prj_file, 'Geom', new_geom_num, ras_object=ras_obj)
946
739
 
947
- new_geom = next_geom_number
948
-
949
740
  # Update all dataframes in the ras object
950
741
  ras_obj.plan_df = ras_obj.get_plan_entries()
951
742
  ras_obj.geom_df = ras_obj.get_geom_entries()
952
743
  ras_obj.flow_df = ras_obj.get_flow_entries()
953
744
  ras_obj.unsteady_df = ras_obj.get_unsteady_entries()
954
745
 
955
- return new_geom
746
+ return new_geom_num
956
747
 
957
748
  @staticmethod
958
749
  @log_call
ras_commander/RasPrj.py CHANGED
@@ -398,8 +398,8 @@ class RasPrj:
398
398
  Get HDF entries for plans that have results.
399
399
 
400
400
  Returns:
401
- pd.DataFrame: A DataFrame containing plan entries with HDF results.
402
- Returns an empty DataFrame if no HDF entries are found.
401
+ pd.DataFrame: A DataFrame containing plan entries with HDF results.
402
+ Returns an empty DataFrame if no HDF entries are found.
403
403
  """
404
404
  self.check_initialized()
405
405
 
@@ -676,7 +676,7 @@ def init_ras_project(ras_project_folder, ras_version=None, ras_instance=None):
676
676
  ras_project_folder : str
677
677
  The path to the RAS project folder.
678
678
  ras_version : str, optional
679
- The version of RAS to use (e.g., "6.5").
679
+ The version of RAS to use (e.g., "6.6").
680
680
  The version can also be a full path to the Ras.exe file. (Useful when calling ras objects for folder copies.)
681
681
  If None, the function will attempt to use the version from the global 'ras' object or a default path.
682
682
  You MUST specify a version number via init at some point or ras will not run.
@@ -697,7 +697,7 @@ def init_ras_project(ras_project_folder, ras_version=None, ras_instance=None):
697
697
  # Use the global 'ras' object after initialization
698
698
 
699
699
  2. For managing multiple projects:
700
- project1 = init_ras_project("/path/to/project1", "6.5", ras_instance=RasPrj())
700
+ project1 = init_ras_project("/path/to/project1", "6.6", ras_instance=RasPrj())
701
701
  project2 = init_ras_project("/path/to/project2", ras_instance=RasPrj())
702
702
 
703
703
  Notes:
@@ -740,28 +740,23 @@ def get_ras_exe(ras_version=None):
740
740
  Determine the HEC-RAS executable path based on the input.
741
741
 
742
742
  Args:
743
- ras_version (str, optional): Either a version number or a full path to the HEC-RAS executable.
744
- If None, the function will attempt to use the version from the global 'ras' object
745
- or a default path.
743
+ ras_version (str, optional): Either a version number or a full path to the HEC-RAS executable.
744
+ If None, the function will attempt to use the version from the global 'ras' object
745
+ or a default path.
746
746
 
747
747
  Returns:
748
- str: The full path to the HEC-RAS executable.
748
+ str: The full path to the HEC-RAS executable.
749
749
 
750
750
  Raises:
751
- ValueError: If the input is neither a valid version number nor a valid file path.
751
+ ValueError: If the input is neither a valid version number nor a valid file path.
752
752
 
753
753
  Notes:
754
- - If ras_version is not provided, the function will first check the global 'ras' object for a path.
755
- - If the global 'ras' object is not initialized or doesn't have a path, a default path will be used.
756
- - The default path allows the library to function in environments without HEC-RAS installed.
757
- - This enables the HEC-Commander GPT to operate without stopping, even if HEC-RAS is not present.
758
- - End users MUST use logging to check for operational errors, as full code stops prevent the GPT from running.
754
+ - If ras_version is not provided, the function will first check the global 'ras' object for a path.
755
+ - If the global 'ras' object is not initialized or doesn't have a path, a default path will be used.
756
+ - The default path allows the library to function in environments without HEC-RAS installed.
757
+ - This enables the HEC-Commander GPT to operate without stopping, even if HEC-RAS is not present.
758
+ - End users MUST use logging to check for operational errors, as full code stops prevent the GPT from running.
759
759
  """
760
- # If ras_version is not provided, use the version of the global 'ras' object.
761
- # If the global 'ras' object is not initialized, use the default path: default_path = Path("/path/to/Ras.exe")
762
- # This default path allows the library to function in environments without HEC-RAS installed.
763
- # It enables our HEC-Commander GPT to operate without stopping, even though HEC-RAS is not present.
764
- # End users MUST use logging to check for operational errors, as full code stops prevent the GPT from running.
765
760
  if ras_version is None:
766
761
  if hasattr(ras, 'ras_exe_path') and ras.ras_exe_path:
767
762
  logger.info(f"Using HEC-RAS executable from global 'ras' object: {ras.ras_exe_path}")
@@ -772,7 +767,7 @@ def get_ras_exe(ras_version=None):
772
767
  return str(default_path)
773
768
 
774
769
  ras_version_numbers = [
775
- "6.5", "6.4.1", "6.3.1", "6.3", "6.2", "6.1", "6.0",
770
+ "6.6", "6.5", "6.4.1", "6.3.1", "6.3", "6.2", "6.1", "6.0",
776
771
  "5.0.7", "5.0.6", "5.0.5", "5.0.4", "5.0.3", "5.0.1", "5.0",
777
772
  "4.1", "4.0", "3.1.3", "3.1.2", "3.1.1", "3.0", "2.2"
778
773
  ]