wolfhece 2.2.43__py3-none-any.whl → 2.2.45__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.
wolfhece/analyze_poly.py CHANGED
@@ -58,7 +58,7 @@ class Array_analysis_onepolygon():
58
58
  self.compute_values()
59
59
 
60
60
  if which == 'Area' and 'Area' not in self._values:
61
- self._add_area2velues()
61
+ self._add_area2values()
62
62
 
63
63
  if self._values is None:
64
64
  raise ValueError("No values computed. Please call compute_values() first.")
@@ -76,7 +76,7 @@ class Array_analysis_onepolygon():
76
76
  if add_values:
77
77
  if self._values is None:
78
78
  self.compute_values()
79
- self._add_area2velues()
79
+ self._add_area2values()
80
80
 
81
81
  if self._values is None:
82
82
  raise ValueError("No values computed. Please call compute_values() first.")
@@ -147,7 +147,7 @@ class Array_analysis_onepolygon():
147
147
  else:
148
148
  self._values = self._wa.statistics(self._selected_cells)
149
149
 
150
- def _add_area2velues(self):
150
+ def _add_area2values(self):
151
151
  """ Add the area of the polygon to the values """
152
152
 
153
153
  if self._selected_cells is None:
@@ -1044,7 +1044,26 @@ class Arrays_analysis_zones():
1044
1044
  if engine == 'seaborn':
1045
1045
  return self._plot_count_strictly_positive_seaborn(show=show, merge_zones=merge_zones)
1046
1046
  elif engine == 'plotly':
1047
- return self.plot_count_strictly_positive_plotly(show=show, merge_zones=merge_zones)
1047
+ return self._plot_count_strictly_positive_plotly(show=show, merge_zones=merge_zones)
1048
+
1049
+ def save_plot_count_strictly_positive(self, filepath:Path | str,
1050
+ merge_zones:bool = False,
1051
+ dpi:int = 300):
1052
+ """ Save the plot of the count of strictly positive values for each array in each zone.
1053
+ :param filepath: path to the image file (png)
1054
+ :param merge_zones: whether to merge the zones in the plot
1055
+ :param dpi: resolution of the saved plot
1056
+ :return: None
1057
+ """
1058
+ import matplotlib.pyplot as plt
1059
+ # Force Agg backend for saving the plot
1060
+ old_back = plt.get_backend()
1061
+ plt.switch_backend('Agg')
1062
+ fig, ax = self.plot_count_strictly_positive(show=False, merge_zones=merge_zones, engine='seaborn')
1063
+ fig.savefig(filepath, bbox_inches='tight', dpi=dpi)
1064
+ plt.close(fig)
1065
+ # Restore the previous backend
1066
+ plt.switch_backend(old_back)
1048
1067
 
1049
1068
  def _plot_count_strictly_positive_seaborn(self, show:bool = True, merge_zones:bool = False):
1050
1069
  """ Plot the count of strictly positive values for each array in each zone using seaborn
@@ -1122,6 +1141,32 @@ class Arrays_analysis_zones():
1122
1141
  else:
1123
1142
  raise ValueError(f"Invalid engine '{engine}'. Must be 'seaborn' or 'plotly'.")
1124
1143
 
1144
+ def save_plot_distributed_values(self, filepath:Path | str,
1145
+ bins:list[float]= [0., .3, 1.3, -1],
1146
+ operator:Literal['Mean', 'Median', 'Sum', 'Volume', 'Area'] = 'Median',
1147
+ merge_zones:bool = False,
1148
+ dpi:int = 300):
1149
+ """ Save the plot of the distribution of values in bins for each array in each zone or merged zones.
1150
+
1151
+ :param filepath: path to the image file (png)
1152
+ :param bins: list of bin edges
1153
+ :param operator: 'Mean', 'Median', 'Sum', 'Volume', 'Area
1154
+ :param merge_zones: whether to merge the zones in the plot
1155
+ :return: None
1156
+ """
1157
+ import matplotlib.pyplot as plt
1158
+
1159
+ # Force Agg backend for saving the plot
1160
+ old_back = plt.get_backend()
1161
+ plt.switch_backend('Agg')
1162
+
1163
+ fig, ax = self.plot_distributed_values(bins, operator, show=False, merge_zones=merge_zones, engine='seaborn')
1164
+
1165
+ fig.savefig(filepath, bbox_inches='tight', dpi=dpi)
1166
+ plt.close(fig)
1167
+ # Restore the previous backend
1168
+ plt.switch_backend(old_back)
1169
+
1125
1170
  def _plot_distributed_values_seaborn(self, bins:list[float],
1126
1171
  operator:Literal['Mean', 'Median', 'Sum', 'Volume', 'Area'],
1127
1172
  show:bool = True,
@@ -1137,6 +1182,11 @@ class Arrays_analysis_zones():
1137
1182
  import seaborn as sns
1138
1183
  import matplotlib.pyplot as plt
1139
1184
 
1185
+ # Check which engine is used by matplotlib
1186
+ backend = plt.get_backend()
1187
+ if backend in ['Agg']:
1188
+ show = False
1189
+
1140
1190
  df = self._values_as_df(operator, merge_zones=merge_zones)
1141
1191
 
1142
1192
  if bins[-1] == -1:
@@ -1181,6 +1231,124 @@ class Arrays_analysis_zones():
1181
1231
 
1182
1232
  return (figs, axs)
1183
1233
 
1234
+ def _get_distributed_values(self,
1235
+ bins:list[float],
1236
+ operator:Literal['Mean', 'Median', 'Sum', 'Volume', 'Area'],
1237
+ merge_zones:bool = False):
1238
+
1239
+ """ Save the distribution of values in bins for each array in each zone as a CSV file.
1240
+
1241
+ :param bins: list of bin edges
1242
+ :param operator: 'Mean', 'Median', 'Sum', 'Volume', 'Area
1243
+ :param merge_zones: whether to merge the zones in the plot
1244
+ """
1245
+
1246
+ df = self._values_as_df(operator, merge_zones=merge_zones)
1247
+ if bins[-1] == -1:
1248
+ bins[-1] = df['Value'].max()
1249
+
1250
+ # Bin and count for each array
1251
+ result = []
1252
+ for array in df['Array'].unique():
1253
+ values = df[df['Array'] == array]['Value']
1254
+ counts, edges = np.histogram(values, bins=bins)
1255
+ for edge, count in zip(edges[:-1], counts):
1256
+ result.append({'Array': array, 'Rightmost edge': edge, 'Count': count})
1257
+
1258
+ return pd.DataFrame(result)
1259
+
1260
+ def save_distributed_values(self,
1261
+ filepath:Path | str,
1262
+ bins:list[float],
1263
+ operator:Literal['Mean', 'Median', 'Sum', 'Volume', 'Area'],
1264
+ merge_zones:bool = False):
1265
+
1266
+ """ Save the distribution of values in bins for each array in each zone as a CSV file.
1267
+
1268
+ :param filepath: path to the CSV file
1269
+ :param bins: list of bin edges
1270
+ :param operator: 'Mean', 'Median', 'Sum', 'Volume', 'Area
1271
+ :param merge_zones: whether to merge the zones in the plot
1272
+ """
1273
+
1274
+ # Ensure CSV extension
1275
+ filepath = Path(filepath)
1276
+ if filepath.suffix != '.csv':
1277
+ filepath = filepath.with_suffix('.csv')
1278
+
1279
+ result = self._get_distributed_values(bins, operator, merge_zones=merge_zones)
1280
+
1281
+ result.to_csv(filepath, index=False)
1282
+
1283
+ def save_distributed_values_table(self,
1284
+ filepath:Path | str,
1285
+ bins:list[float],
1286
+ operator:Literal['Mean', 'Median', 'Sum', 'Volume', 'Area'],
1287
+ merge_zones:bool = False):
1288
+ """ Create a table of the distribution of values in bins for each array in each zone.
1289
+
1290
+ :param filepath: path to the image file (png)
1291
+ :param bins: list of bin edges
1292
+ :param operator: 'Mean', 'Median', 'Sum', 'Volume', 'Area
1293
+ :param merge_zones: whether to merge the zones in the plot
1294
+ :return: pandas DataFrame with the counts of values in each bin for each array in each zone
1295
+ """
1296
+
1297
+ # Ensure PNG extension
1298
+ filepath = Path(filepath)
1299
+ if filepath.suffix != '.png':
1300
+ filepath = filepath.with_suffix('.png')
1301
+
1302
+ results = self._get_distributed_values(bins, operator, merge_zones=merge_zones)
1303
+
1304
+ # Calculer la borne inférieure en décalant la colonne
1305
+ results["Bin Lower Edge"] = results.groupby("Array")["Rightmost edge"].shift(1).fillna(0)
1306
+
1307
+ # Créer la chaîne de caractère de l'intervalle
1308
+ results[_("Bounds [m]")] = "]" + results["Bin Lower Edge"].map(lambda x: f"{x:.2f}") + "–" + results["Rightmost edge"].map(lambda x: f"{x:.2f}") + "]"
1309
+ # Ensure 'Count' is integer
1310
+ results['Count'] = results['Count'].astype(int)
1311
+
1312
+ table = results.pivot_table(index=_("Bounds [m]"), columns='Array', values='Count', fill_value=0, sort=False)
1313
+ # Force values as integers
1314
+ table = table.astype(int)
1315
+
1316
+ table.reset_index(inplace=True)
1317
+
1318
+
1319
+ # table.columns = pd.MultiIndex.from_tuples([(_('Arrays'),col) for col in table.columns])
1320
+
1321
+ import dataframe_image as dfi
1322
+
1323
+ # Place the column labels (Array) on the same line as the row label (Intervalle)
1324
+ styled_df = table.style.format(precision=1) \
1325
+ .set_caption(_('Count')) \
1326
+ .set_properties(**{
1327
+ 'text-align': 'center',
1328
+ 'font-size': '12px',
1329
+ 'border': '1px solid black',
1330
+ }) \
1331
+ .set_table_styles([
1332
+ {
1333
+ 'selector': 'th.col_heading.level0',
1334
+ 'props': [('vertical-align', 'middle')],
1335
+ },
1336
+ {
1337
+ 'selector': 'thead th.row_heading.level0',
1338
+ 'props': [('vertical-align', 'middle')],
1339
+ },
1340
+ {
1341
+ 'selector': 'thead th',
1342
+ 'props': [('text-align', 'center'), ('background-color', '#d9edf7'), ('color', '#31708f')],
1343
+ },
1344
+ ])
1345
+ styled_df = styled_df.hide(axis="index")
1346
+
1347
+ # Export the styled DataFrame as an image
1348
+
1349
+ # Convert to html table image
1350
+ dfi.export(styled_df, filename=filepath, dpi = 300)
1351
+
1184
1352
  def _plot_distributed_values_plotly(self, bins:list[float],
1185
1353
  operator:Literal['Mean', 'Median', 'Sum', 'Volume', 'Area'],
1186
1354
  show:bool = True,
@@ -1363,6 +1531,32 @@ class Building_Waterdepth_analysis(Arrays_analysis_zones):
1363
1531
  merge_zones = False):
1364
1532
 
1365
1533
  return super()._plot_distributed_areas_seaborn(bins, operator, show=show, merge_zones=merge_zones)
1534
+
1535
+ def save_plot_distributed_areas(self, filepath,
1536
+ bins = [0, 0.3, 1.3, -1],
1537
+ operator = 'Median',
1538
+ merge_zones = False,
1539
+ dpi = 300):
1540
+ """ Save the plot of the distribution of areas in bins for each array in each zone or merged zones.
1541
+ :param filepath: path to the image file (png)
1542
+ :param bins: list of bin edges
1543
+ :param operator: 'Mean', 'Median', 'Sum', 'Volume', 'Area
1544
+ :param merge_zones: whether to merge the zones in the plot
1545
+ :param dpi: resolution of the saved plot
1546
+ :return: None
1547
+ """
1548
+
1549
+ import matplotlib.pyplot as plt
1550
+ # Force Agg backend for saving the plot
1551
+ old_back = plt.get_backend()
1552
+ plt.switch_backend('Agg')
1553
+ fig, ax = self.plot_distributed_areas(bins, operator, show=False, merge_zones=merge_zones, engine='seaborn')
1554
+ fig.savefig(filepath, bbox_inches='tight', dpi=dpi)
1555
+ plt.close(fig)
1556
+ # Restore the previous backend
1557
+ plt.switch_backend(old_back)
1558
+
1559
+
1366
1560
  class Slope_analysis:
1367
1561
  """ Class for slope analysis of in an array based on a trace vector.
1368
1562
 
wolfhece/apps/version.py CHANGED
@@ -5,7 +5,7 @@ class WolfVersion():
5
5
 
6
6
  self.major = 2
7
7
  self.minor = 2
8
- self.patch = 43
8
+ self.patch = 45
9
9
 
10
10
  def __str__(self):
11
11
 
wolfhece/dike.py CHANGED
@@ -13,14 +13,209 @@ from mpl_toolkits.mplot3d.art3d import Poly3DCollection
13
13
  import matplotlib.tri as tri
14
14
  import time
15
15
 
16
- from wolfpydike.dikeBreaching import pyDike
16
+ try:
17
+ from wolfpydike.dikeBreaching import pyDike, injector
18
+ except ImportError:
19
+ # Test if wolfpydike is installed and check the version
20
+ try:
21
+ import wolfpydike
22
+ version = wolfpydike.__version__
23
+ if version < '0.1.2':
24
+ raise ImportError("wolfpydike version is too old. Please update to at least version 0.1.2")
25
+ except:
26
+ raise ImportError(_("Error importing pyDike. Make sure the pydike library is installed and accessible (use 'pip install wolfpydike')."))
27
+
28
+ from wolfhece.drawing_obj import Element_To_Draw
29
+ from wolfhece.PyParams import Wolf_Param, Type_Param, Buttons, key_Param, new_json
30
+ from wolfhece.PyDraw import Triangulation
31
+ from wolfhece.wolf_array import WolfArray
32
+ from wolfhece.matplotlib_fig import Matplotlib_Figure
33
+ from wolfhece.PyTranslate import _
34
+
35
+ try:
36
+ from wolfgpu.SimulationRunner import SimulationRunner, SimulationInjector, SimulationProxy
37
+ from wolfgpu.simple_simulation import SimulationDuration, SimpleSimulation
38
+ from wolfgpu.results_store import ResultsStore
39
+ except ImportError:
40
+ logging.warning(_("Warning: wolfgpu module not found. Coupled WOLF-pydike simulations will not be available."))
41
+ class CoupledSimulation():
42
+ """
43
+ Class for the coupled simulation between WOLF and pydike.
44
+ """
45
+ def __init__(self):
46
+ self.filename = None
47
+ self.injectorWolf = None
48
+ self.interpMatrix = None
49
+ self.sim = SimpleSimulation()
50
+ self.store_dir = None
51
+ # WHEN INTERACTIONS BETWEEN WOLF AND PYDIKE ARE ACTIVATED
52
+ self.updateFrequency = 30 #[s] Update frequency of the topo in WOLF
53
+ self.firstUpdate = 1 #[s] Time of the first update of the topo in WOLF
54
+
55
+ class InjectorWolf(Element_To_Draw):
56
+ """
57
+ Class for the injector object.
58
+ """
59
+ def __init__(self, idx = '', plotted = True, mapviewer=None, need_for_wx = False):
60
+ super().__init__(idx, plotted, mapviewer, need_for_wx)
61
+ self.wp = None
62
+ self._injector = injector()
63
+
64
+ def set_params(self, params):
65
+ """
66
+ Set the injector parameters.
67
+ :param params: Parameters to set for the injector.
68
+ """
69
+ return self._injector.set_params(params)
70
+
71
+ def get_params(self):
72
+ """
73
+ Set the injector parameters.
74
+ :param params: Parameters to set for the injector.
75
+ """
76
+ return self._injector.get_params()
77
+
78
+ def save(self):
79
+ '''
80
+ Save the parameters in a .json text file
81
+ '''
82
+ if self.filename is None:
83
+ self.save_as()
84
+ else:
85
+ with open(self.filename, 'w') as f:
86
+ json.dump(self.get_params(), f, indent=4)
87
+
88
+ def save_as(self):
89
+ '''
90
+ Save the parameters in a .json text file
91
+ '''
92
+ filterArray = "json (*.json)|*.json|all (*.*)|*.*"
93
+ fdlg = wx.FileDialog(None, _("Where should the parameters be stored (.json file)?"), wildcard=filterArray, style=wx.FD_SAVE)
94
+ ret = fdlg.ShowModal()
95
+ if ret == wx.ID_OK:
96
+ self.filename = fdlg.GetPath()
97
+ self.save()
98
+
99
+ fdlg.Destroy()
100
+
101
+ def callback_apply(self):
102
+ """
103
+ Callback function to apply changes made in the Wolf_Param window.
104
+ Update the parameters in the dike object.
105
+ """
106
+ updated_wp = self.wp.merge_dicts()
107
+ self.from_wp_to_dict(wolf_dict=updated_wp, dict_ref=self.get_params())
108
+
109
+ def show_properties(self):
110
+ """
111
+ Show properties window
112
+ """
113
+ if self.wp is None:
114
+ self.wp = self.from_dict_to_wp(params_dict=self.get_params())
115
+ self.wp.set_callbacks(callback_update=self.callback_apply, callback_destroy=None)
116
+ self.wp._set_gui_dike(title=_('Injector parametrization'))
117
+ self.wp.hide_selected_buttons([Buttons.Reload,Buttons.Save])
118
+ self.wp.Show()
119
+
120
+ def hide_properties(self):
121
+ """
122
+ Hide properties window
123
+ """
124
+ if self.wp is not None:
125
+ self.wp.Hide()
126
+
127
+ def from_wp_to_dict(self, wolf_dict, dict_ref) -> dict:
128
+ """
129
+ Convert a Wolf_Param dictionary to a "normal" dictionary used as parameters dictionary in the injector object + updates injector attributes accordingly.
130
+ 'dict_ref' used to rename keys (=mapping).
131
+ :param wolf_dict: Dictionary containing the parameters from the Wolf_Param object.
132
+ :param dict_ref: Dictionary mapping injector parameter names (keys) to explicit names in wolf_param.
133
+ :return: Dictionary with injector parameter names as keys, containing values and metadata.
134
+ """
135
+ params_dict = {}
17
136
 
18
- from .drawing_obj import Element_To_Draw
19
- from .PyParams import Wolf_Param, Type_Param, Buttons, key_Param
20
- from .PyDraw import Triangulation
21
- from .matplotlib_fig import Matplotlib_Figure
22
- from .PyTranslate import _
137
+ for section in wolf_dict.keys():
138
+ params_dict[section] = {}
139
+ for param_data in wolf_dict[section].values():
140
+ explicit_name = param_data[key_Param.NAME] # Extract explicit name
141
+
142
+ # Search for the corresponding injector_key inside dict_ref
143
+ injector_key = None
144
+ for section_name, section_params in dict_ref.items():
145
+ for param_key, param_details in section_params.items():
146
+ if param_details.get("explicit name") == explicit_name:
147
+ injector_key = param_key # Get the correct parameter key
148
+ break
149
+ if injector_key: # Exit the outer loop if found
150
+ break
23
151
 
152
+ if injector_key is None:
153
+ print(_("Warning: No match found in dict_ref for '%s'") % explicit_name)
154
+ continue # Skip if no match is found
155
+
156
+ params_dict[section][injector_key] = {
157
+ "value": param_data[key_Param.VALUE],
158
+ "description": param_data[key_Param.COMMENT],
159
+ "explicit name": explicit_name,
160
+ "type": param_data[key_Param.TYPE],
161
+ "choices": dict_ref[section_name][injector_key].get("choices"),
162
+ "mandatory": dict_ref[section_name][injector_key].get("mandatory"),
163
+ }
164
+
165
+ self._dike.update_paramsDict(params_dict)
166
+
167
+ return
168
+
169
+ def from_dict_to_wp(self,params_dict) -> Wolf_Param:
170
+ """ Modify the Wolf_Param object to represent the injector parameters. """
171
+
172
+ wp = Wolf_Param_dike(parent = None, # Contains all the parameters of the window
173
+ title = _("Breaching of a dike"),
174
+ to_read=False,
175
+ withbuttons=True,
176
+ toShow=False,
177
+ init_GUI=False,
178
+ force_even_if_same_default = True,
179
+ filename="default_name.json",
180
+ DestroyAtClosing=False)
181
+
182
+ for current_section in params_dict.keys():
183
+ for key in params_dict[current_section].keys():
184
+
185
+ value = params_dict[current_section][key]["value"]
186
+ description = params_dict[current_section][key]["description"]
187
+ name = params_dict[current_section][key]["explicit name"]
188
+ # Parameter type
189
+ if params_dict[current_section][key]["type"] == "Float":
190
+ type_param = Type_Param.Float
191
+ elif params_dict[current_section][key]["type"] == "Integer":
192
+ type_param = Type_Param.Integer
193
+ elif params_dict[current_section][key]["type"] == "Logical":
194
+ type_param = Type_Param.Logical
195
+ elif params_dict[current_section][key]["type"] == "String":
196
+ type_param = Type_Param.String
197
+ elif params_dict[current_section][key]["type"] == "Directory":
198
+ type_param = Type_Param.Directory
199
+ elif params_dict[current_section][key]["type"] == "File":
200
+ type_param = Type_Param.File
201
+
202
+ if params_dict[current_section][key]["choices"] != None:
203
+ wp.add_param((current_section), (name), value, type_param, whichdict='Default', jsonstr=new_json(params_dict[current_section][key]["choices"]), comment=_(description))
204
+ if params_dict[current_section][key]["mandatory"]:
205
+ wp.add_param((current_section), (name), value, type_param, whichdict='Active', jsonstr=new_json(params_dict[current_section][key]["choices"]), comment=_(description))
206
+ else:
207
+ wp.add_param((current_section), (name), value, type_param, whichdict='Default', comment=_(description))
208
+ if params_dict[current_section][key]["mandatory"]:
209
+ wp.add_param((current_section), (name), value, type_param, whichdict='Active', comment=_(description))
210
+ return wp
211
+
212
+ # def read_params(self, file_name:str, store_dir: Path = None):
213
+ # '''
214
+ # Read the model parameters and store them in a dictionary + updates attributes accordingly
215
+ # :param file_name: name of the file to read
216
+ # :param store_dir: directory where to read the file
217
+ # '''
218
+ # self._dike.read_params(file_name, store_dir)
24
219
  class DikeWolf(Element_To_Draw):
25
220
 
26
221
  def __init__(self, idx = '', plotted = True, mapviewer=None, need_for_wx = False):
@@ -28,15 +223,64 @@ class DikeWolf(Element_To_Draw):
28
223
 
29
224
  self.filename = None
30
225
  self.wp = None
226
+ self.injector = None
227
+ self.interpMatrix = None
31
228
  self._dike = pyDike()
32
229
 
33
- def run(self, store_dir=None):
230
+ def run_lumped(self, params_dir=None):
34
231
  """
35
- Run the dike breaching simulation.
232
+ Run the dike breaching simulation using the lumped model.
36
233
  :param store_dir: Directory where the simulation will be run.
37
234
  """
38
235
  try:
39
- self._dike.run(store_dir=store_dir)
236
+ self._dike.run_initialization(params_dir=params_dir)
237
+ for time_idx in np.arange(0,self._dike.t_end_idx,1):
238
+ self._dike.run(time_idx)
239
+ logging.info(_("Breaching simulation done."))
240
+ except subprocess.CalledProcessError as e:
241
+ logging.error(_("Error while running the breaching simulation: %s") % e)
242
+
243
+ def set_injector(self):
244
+ """
245
+ Set the injector for the dike object.
246
+ :param injector: Injector object to be set.
247
+ """
248
+ self.injectorWolf = InjectorWolf()
249
+ self.mapviewer.add_object(newobj=self.injectorWolf, which='injector', id=_("Injector_{filename}").format(filename=self.filename))
250
+
251
+ def run_2Dcoupled(self, params_dir=None):
252
+ """
253
+ Run the dike breaching simulation coupled with WOLF.
254
+ :param store_dir: Directory where the simulation will be run.
255
+ """
256
+ if self.injectorWolf is None:
257
+ logging.error(_("Injector is not set. Please set the injector before running the simulation."))
258
+ return
259
+
260
+ # Select WOLF array file
261
+ filterArray = "Wolf array files (*.bin)|*.bin"
262
+ dlg = wx.FileDialog(self.mapviewer, _('Choose the file containing the Wolf array on which interpolation is applied'), wildcard=filterArray, style=wx.FD_FILE_MUST_EXIST)
263
+ ret=dlg.ShowModal()
264
+ if ret == wx.ID_CANCEL:
265
+ dlg.Destroy()
266
+ path_TriangArray = dlg.GetPath()
267
+ self.interpMatrix = WolfArray(fname = path_TriangArray)
268
+
269
+ # Select WOLF simulation data folder
270
+ dlg = wx.DirDialog(self.mapviewer, _('Folder containing WOLF simulation data'), style=wx.DD_DEFAULT_STYLE)
271
+ ret=dlg.ShowModal()
272
+ if ret == wx.ID_CANCEL:
273
+ dlg.Destroy()
274
+ path_sim = dlg.GetPath()
275
+ sim = SimpleSimulation.load(path_sim)
276
+
277
+ # self.mapviewer.add_object(newobj=sim, which='triangulation', id=_("Triangulation_{filename}_{index:03d}").format(filename=self.filename, index=current_idx))
278
+ # logging.info(_("Added triangulation for time index %d to viewer.") % current_idx)
279
+
280
+ try:
281
+ self._dike.run_initialization(params_dir=params_dir)
282
+ for time_idx in np.arange(0,self._dike.t_end_idx,1):
283
+ self._dike.run(time_idx)
40
284
  logging.info(_("Breaching simulation done."))
41
285
  except subprocess.CalledProcessError as e:
42
286
  logging.error(_("Error while running the breaching simulation: %s") % e)
@@ -143,9 +387,13 @@ class DikeWolf(Element_To_Draw):
143
387
  type_param = Type_Param.File
144
388
 
145
389
  if params_dict[current_section][key]["choices"] != None:
146
- wp.add_param((current_section), (name), value, type_param, whichdict='Default', jsonstr={"Values":params_dict[current_section][key]["choices"]}, comment=_(description))
390
+ wp.add_param((current_section), (name), value, type_param,
391
+ whichdict='Default', jsonstr=new_json(params_dict[current_section][key]["choices"]),
392
+ comment=_(description))
147
393
  if params_dict[current_section][key]["mandatory"]:
148
- wp.add_param((current_section), (name), value, type_param, whichdict='Active', jsonstr={"Values":params_dict[current_section][key]["choices"]}, comment=_(description))
394
+ wp.add_param((current_section), (name), value, type_param,
395
+ whichdict='Active', jsonstr=new_json(params_dict[current_section][key]["choices"]),
396
+ comment=_(description))
149
397
  else:
150
398
  wp.add_param((current_section), (name), value, type_param, whichdict='Default', comment=_(description))
151
399
  if params_dict[current_section][key]["mandatory"]:
@@ -156,22 +404,22 @@ class DikeWolf(Element_To_Draw):
156
404
  """
157
405
  Load the main outputs and/or the triangulation of the simulation.
158
406
  """
159
- filterArray = "Parameter files (*_params.json)|*_params.json"
407
+ filterArray = "Parameter files (*_paramsDike.json)|*_paramsDike.json"
160
408
  dlg = wx.FileDialog(self.mapviewer, _('Choose the file containing the simulation parametrization'), wildcard=filterArray, style=wx.FD_FILE_MUST_EXIST)
161
409
  ret=dlg.ShowModal()
162
410
  if ret == wx.ID_CANCEL:
163
411
  dlg.Destroy()
164
412
  self.param_path = dlg.GetPath()
165
- if self.param_path.endswith("_params.json"):
166
- gen_path = self.param_path.removesuffix("_params.json")
413
+ if self.param_path.endswith("_paramsDike.json"):
414
+ gen_path = self.param_path.removesuffix("_paramsDike.json")
167
415
  else:
168
- logging.warning(_("ERROR : the name of the file containing the simulation parametrization should end with '_params.json'"))
416
+ logging.warning(_("ERROR : the name of the file containing the simulation parametrization should end with '_paramsDike.json'"))
169
417
  dlg.Destroy()
170
418
  return
171
419
 
172
420
  self.param_path = Path(self.param_path)
173
- self.filename = (self.param_path.name).removesuffix("_params.json")
174
- self.read_params(file_name=self.filename+"_params", store_dir=self.param_path.parent)
421
+ self.filename = (self.param_path.name).removesuffix("_paramsDike.json")
422
+ self.read_params(file_name=self.filename, store_dir=self.param_path.parent)
175
423
 
176
424
  try:
177
425
  mainOutputs_path = Path(gen_path + '_mainOutputs.txt')
@@ -596,7 +844,7 @@ class Wolf_Param_dike(Wolf_Param):
596
844
  # read the file
597
845
  if self.wx_exists:
598
846
  #ouverture d'une boîte de dialogue
599
- file=wx.FileDialog(self,_("Choose .json file"), wildcard="json (*.json)|*.json|all (*.*)|*.*")
847
+ file=wx.FileDialog(self,_("Choose .json file"), wildcard="Parameter files (*_paramsDike.json)|*_paramsDike.json")
600
848
  if file.ShowModal() == wx.ID_CANCEL:
601
849
  return
602
850
  else:
@@ -658,7 +906,7 @@ class Wolf_Param_dike(Wolf_Param):
658
906
  type_param = Type_Param.File
659
907
 
660
908
  if params_dict[current_section][key]["choices"] != None:
661
- wp.add_param((current_section), (name), value, type_param, whichdict=whichdict, jsonstr={_("Values"):params_dict[current_section][key]["choices"]}, comment=_(description))
909
+ wp.add_param((current_section), (name), value, type_param, whichdict=whichdict, jsonstr=new_json(params_dict[current_section][key]["choices"]), comment=_(description))
662
910
  else:
663
911
  wp.add_param((current_section), (name), value, type_param, whichdict=whichdict, comment=_(description))
664
912
 
wolfhece/eikonal.py CHANGED
@@ -435,6 +435,7 @@ def inpaint_waterlevel(water_level:np.ndarray | np.ma.MaskedArray,
435
435
  :param dy: (float, optional): The mesh size in y direction.
436
436
  :param NoDataValue: (float, optional): The NoDataValue, used if mask is not explicitly provided (mask attribute or water_level as a Numpy MaskedArray). Default is 0.
437
437
  :param multiprocess: (bool, optional): Whether to use multiprocessing.
438
+ :param epsilon: (float, optional): The minimum value to consider that a water height is present.
438
439
  """
439
440
  if inplace:
440
441
  if isinstance(water_level, np.ma.MaskedArray):