wolfhece 2.2.38__py3-none-any.whl → 2.2.40__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.
Files changed (50) hide show
  1. wolfhece/Coordinates_operations.py +5 -0
  2. wolfhece/GraphNotebook.py +72 -1
  3. wolfhece/GraphProfile.py +1 -1
  4. wolfhece/MulticriteriAnalysis.py +1579 -0
  5. wolfhece/PandasGrid.py +62 -1
  6. wolfhece/PyCrosssections.py +194 -43
  7. wolfhece/PyDraw.py +891 -73
  8. wolfhece/PyGui.py +913 -72
  9. wolfhece/PyGuiHydrology.py +528 -74
  10. wolfhece/PyPalette.py +26 -4
  11. wolfhece/PyParams.py +33 -0
  12. wolfhece/PyPictures.py +2 -2
  13. wolfhece/PyVertex.py +25 -0
  14. wolfhece/PyVertexvectors.py +94 -28
  15. wolfhece/PyWMS.py +52 -36
  16. wolfhece/acceptability/acceptability.py +15 -8
  17. wolfhece/acceptability/acceptability_gui.py +507 -360
  18. wolfhece/acceptability/func.py +80 -183
  19. wolfhece/apps/version.py +1 -1
  20. wolfhece/compare_series.py +480 -0
  21. wolfhece/drawing_obj.py +12 -1
  22. wolfhece/hydrology/Catchment.py +228 -162
  23. wolfhece/hydrology/Internal_variables.py +43 -2
  24. wolfhece/hydrology/Models_characteristics.py +69 -67
  25. wolfhece/hydrology/Optimisation.py +893 -182
  26. wolfhece/hydrology/PyWatershed.py +267 -165
  27. wolfhece/hydrology/SubBasin.py +185 -140
  28. wolfhece/hydrology/cst_exchanges.py +76 -1
  29. wolfhece/hydrology/forcedexchanges.py +413 -49
  30. wolfhece/hydrology/read.py +65 -5
  31. wolfhece/hydrometry/kiwis.py +14 -7
  32. wolfhece/insyde_be/INBE_func.py +746 -0
  33. wolfhece/insyde_be/INBE_gui.py +1776 -0
  34. wolfhece/insyde_be/__init__.py +3 -0
  35. wolfhece/interpolating_raster.py +366 -0
  36. wolfhece/irm_alaro.py +1457 -0
  37. wolfhece/irm_qdf.py +889 -57
  38. wolfhece/lazviewer/laz_viewer.py +4 -1
  39. wolfhece/lifewatch.py +6 -3
  40. wolfhece/picc.py +124 -8
  41. wolfhece/pyLandUseFlanders.py +146 -0
  42. wolfhece/pydownloader.py +35 -1
  43. wolfhece/pywalous.py +225 -31
  44. wolfhece/toolshydrology_dll.py +149 -0
  45. wolfhece/wolf_array.py +63 -25
  46. {wolfhece-2.2.38.dist-info → wolfhece-2.2.40.dist-info}/METADATA +3 -1
  47. {wolfhece-2.2.38.dist-info → wolfhece-2.2.40.dist-info}/RECORD +50 -41
  48. {wolfhece-2.2.38.dist-info → wolfhece-2.2.40.dist-info}/WHEEL +0 -0
  49. {wolfhece-2.2.38.dist-info → wolfhece-2.2.40.dist-info}/entry_points.txt +0 -0
  50. {wolfhece-2.2.38.dist-info → wolfhece-2.2.40.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,1776 @@
1
+ """
2
+ Author: University of Liege, HECE, Damien Sansen
3
+ Date: 2025
4
+
5
+ Copyright (c) 2025 University of Liege. All rights reserved.
6
+
7
+ This script and its content are protected by copyright law. Unauthorized
8
+ copying or distribution of this file, via any medium, is strictly prohibited.
9
+ """
10
+
11
+ import wx
12
+ import numpy as np
13
+ import logging
14
+ import shutil
15
+ import os
16
+ import sys
17
+ import glob
18
+ from osgeo import gdal, osr
19
+ import geopandas as gpd
20
+ import pandas as pd
21
+ import matplotlib.pyplot as plt
22
+ from matplotlib.figure import Figure
23
+ from pathlib import Path
24
+ from scipy.ndimage import label
25
+ from gettext import gettext as _
26
+ from shapely.geometry import Polygon
27
+ from scipy.ndimage import binary_dilation
28
+ from itertools import permutations
29
+
30
+ sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
31
+ from wolfhece.wolf_array import WolfArray, header_wolf
32
+ from wolfhece.scenario.config_manager import Config_Manager_2D_GPU
33
+ from wolfhece.PyDraw import WolfMapViewer, draw_type
34
+ from wolfhece.Results2DGPU import wolfres2DGPU
35
+ from wolfhece.PyGui import MapManager
36
+ from wolfhece.interpolating_raster import interpolating_raster
37
+ from wolfhece.insyde_be.INBE_func import INBE_functions
38
+ from wolfhece.PyTranslate import _
39
+
40
+ BATHYMETRY_FOR_SIMULATION = "__bathymetry_after_scripts.tif"
41
+
42
+ #Other repository : hece_damage-------------------------------------------------------------
43
+ _root_dir = os.path.dirname(os.path.abspath(__file__))
44
+ hece_damage_path = os.path.abspath(os.path.join(_root_dir, "..", "..", "..", "hece_damage"))
45
+ sys.path.insert(0, hece_damage_path)
46
+ try:
47
+ from insyde_be.Py_INBE import PyINBE, INBE_Manager
48
+ except Exception as e:
49
+ logging.error(_(f"Problem to import insyde_be.Py_INBE: {e}"))
50
+ try:
51
+ from insyde_be.Py_INBE import PyINBE, INBE_Manager
52
+ except Exception as e:
53
+ logging.error(_(f"Problem to import insyde_be.Py_INBE: {e}"))
54
+ sys.path.pop(0) # ou sys.path = original_sys_path si tu préfères
55
+
56
+ def riverbed_trace_dilated(fn_read_simu, fn_output, threshold, type_extraction, id_begin=None, id_end=None, id_step=None):
57
+ """
58
+ Recognizes the riverbed trace based on a simulation, where water depth above a given threshold is considered part of the riverbed.
59
+ Inputs:
60
+ - fn_read_simu: the simulation file to read.
61
+ - fn_output: the location to save the riverbed trace as a .tiff file.
62
+ - threshold: the water depth threshold above which the areas are considered riverbed.
63
+ """
64
+
65
+ if type_extraction == "last_step":
66
+ wolfres2DGPU_test = wolfres2DGPU(fn_read_simu)
67
+ wolfres2DGPU_test.read_oneresult(-1)
68
+ wd = wolfres2DGPU_test.get_h_for_block(1)
69
+ wd.array[wd.array > 1000] = 0
70
+ wd.array[wd.array > threshold] = 1
71
+ wd.array[wd.array < threshold] = 0
72
+ wd.as_WolfArray()
73
+ wd.nodata=0
74
+ wd.write_all(Path(fn_output))
75
+
76
+ if type_extraction=="danger_map":
77
+ wd = wolfres2DGPU(fn_read_simu) .danger_map_only_h(id_begin,id_end,id_step)
78
+ wd.array[wd.array > 1000] = 0
79
+ wd.array[wd.array > threshold] = 1
80
+ wd.array[wd.array < threshold] = 0
81
+ wd.as_WolfArray()
82
+ wd.nodata=0
83
+ wd.write_all(Path(fn_output))
84
+
85
+ def dilatation_mask_river(manager_inbe):
86
+ mask_river = Path(manager_inbe.IN_RIVER_MASK_SCEN) / "Masked_River_extent.tiff"
87
+ WA_mask_river = WolfArray(mask_river)
88
+ array = binary_dilation(WA_mask_river.array)
89
+ WA_mask_river.array[:,:] = array[:,:]
90
+ out = Path(manager_inbe.IN_RIVER_MASK_SCEN_tif)
91
+ WA_mask_river.as_WolfArray()
92
+ WA_mask_river.write_all(out)
93
+ return print(f"Dilated mask river written in {Path(manager_inbe.IN_RIVER_MASK_SCEN_tif)}")
94
+
95
+ def empty_folder(folder):
96
+ """
97
+ Empties the content of a directory if it exists.
98
+ """
99
+ if os.path.exists(folder):
100
+ for files in os.listdir(folder):
101
+ fn = os.path.join(folder, files)
102
+ try:
103
+ if os.path.isfile(fn) or os.path.islink(fn):
104
+ os.unlink(fn)
105
+ elif os.path.isdir(fn):
106
+ shutil.rmtree(fn)
107
+ except Exception as e:
108
+ print(f"Error when deleting file {fn}: {e}")
109
+ else:
110
+ print("The folder does not exist.")
111
+
112
+ def get_transform_and_crs(tif_file):
113
+ """
114
+ For TIFF file manipulation, reads the CRS and the geotransform, and returns them.
115
+ """
116
+ ds = gdal.Open(tif_file)
117
+ transform = ds.GetGeoTransform()
118
+ crs_wkt = ds.GetProjection()
119
+ crs = osr.SpatialReference()
120
+ crs.ImportFromWkt(crs_wkt)
121
+ return transform, crs
122
+
123
+ def create_shapefile_from_prop_tif(fn_tif, shapefile_path):
124
+ unused, unused, width, height, unused, unused = get_header_info(fn_tif)
125
+ ds = gdal.Open(fn_tif)
126
+ width = ds.RasterXSize
127
+ height = ds.RasterYSize
128
+ gt = ds.GetGeoTransform()
129
+
130
+ originX, pixelWidth, unused, originY, unused, pixelHeight = gt
131
+
132
+ top_left = (originX, originY)
133
+ top_right = (originX + width * pixelWidth, originY)
134
+ bottom_left = (originX, originY + height * pixelHeight)
135
+ bottom_right = (originX + width * pixelWidth, originY + height * pixelHeight)
136
+
137
+ rectangle = Polygon([top_left, top_right, bottom_right, bottom_left, top_left])
138
+
139
+ sr = osr.SpatialReference()
140
+ sr.ImportFromWkt(ds.GetProjection())
141
+ crs_wkt = sr.ExportToWkt()
142
+
143
+ gdf = gpd.GeoDataFrame({'geometry': [rectangle]}, crs=crs_wkt)
144
+ gdf.to_file(shapefile_path)
145
+ ds = None
146
+
147
+ def get_header_info(fn):
148
+ """
149
+ Reads the headers from the file at path 'fn'.
150
+ """
151
+ class_header = header_wolf()
152
+ class_header.read_txt_header(fn)
153
+ dx,dy = class_header.dx, class_header.dy
154
+ nbx,nby = class_header.nbx, class_header.nby
155
+ X,Y = class_header.origx, class_header.origy
156
+ return dx,dy,nbx,nby,X,Y
157
+
158
+ def get_header_comparison(list_fn):
159
+ """
160
+ Reads the headers from the files in list_fn and compares them. The result 'comp' is True if the headers are identical, and False otherwise.
161
+ """
162
+
163
+ header_infos = [get_header_info(fn) for fn in list_fn]
164
+ variable_names = ["dx", "dy", "nbx", "nby", "X", "Y"]
165
+ for idx, name in enumerate(variable_names):
166
+ values = [header[idx] for header in header_infos]
167
+ if len(set(values)) > 1:
168
+ comp = False
169
+ else:
170
+ comp = True
171
+ return comp
172
+
173
+
174
+ def display_info_header(self_dx, self_nbxy, self_O, fn):
175
+ """
176
+ Displays the header at the path 'fn', and update the values displayed in the window.
177
+ """
178
+ dx,dy,nbx,nby,X,Y= get_header_info(fn)
179
+ self_dx.SetLabel(f"({dx},{dy})")
180
+ self_nbxy.SetLabel(f"({nbx},{nby})")
181
+ self_O.SetLabel(f"({X},{Y})")
182
+ return dx,dy,nbx,nby,X,Y
183
+
184
+ def vanish_info_header(self_dx, self_nbxy, self_O):
185
+ self_dx.SetLabel("")
186
+ self_nbxy.SetLabel("")
187
+ self_O.SetLabel("")
188
+
189
+ def update_info_header(self_dx, self_nbxy, self_O, fn):
190
+ """
191
+ Upate the displayed header values by reading the simulations headers if exist.
192
+ """
193
+ if not os.path.exists(fn):
194
+ os.makedirs(fn)
195
+
196
+ tif_files = [f for f in os.listdir(fn) if f.lower().endswith('.tif')]
197
+ tif_list_fn = [os.path.join(fn, tif_file) for tif_file in tif_files]
198
+ if tif_files:
199
+ if get_header_comparison(tif_list_fn) :
200
+ dx,dy,nbx,nby,X,Y = display_info_header(self_dx, self_nbxy, self_O, tif_list_fn[0])
201
+ return dx,dy,nbx,nby,X,Y
202
+ else:
203
+ logging.error(_("The interpolated files have different headers. Please fix it."))
204
+ return False, False, False, False, False, False
205
+ else :
206
+ vanish_info_header(self_dx, self_nbxy, self_O)
207
+ return False, False, False, False, False, False
208
+
209
+ def search_for_modif_bath_and_copy(main_gpu, from_path, path_vuln):
210
+ """
211
+ When loading gpu simulations for last step extraction, search for modified bath_ topography file, according to
212
+ the structure coded in the scenarios manager. If they exist, their extent is copied to CHANGE_VULNE, called vuln_ and
213
+ MNTmodifs_, to enable the user to modify it later. In addition, returns True if such files exist and False if they do not.
214
+ """
215
+ found_bath = False
216
+ scen_manager = Config_Manager_2D_GPU(main_gpu, create_ui_if_wx=False)
217
+ curtree = scen_manager.get_tree(from_path)
218
+ curdicts = scen_manager.get_dicts(curtree)
219
+ all_tif_bath = [scen_manager._select_tif_partname(curdict, 'bath_') for curdict in curdicts]
220
+ all_tif_bath = [curel for curlist in all_tif_bath if len(curlist)>0 for curel in curlist if curel.name.startswith('bath_')]
221
+ if len(all_tif_bath) :
222
+ found_bath = True
223
+ for tif_file in all_tif_bath:
224
+ found_bath = True
225
+ src_ds = gdal.Open(str(tif_file))
226
+ driver = gdal.GetDriverByName("GTiff")
227
+
228
+ xsize = src_ds.RasterXSize
229
+ ysize = src_ds.RasterYSize
230
+ geotransform = src_ds.GetGeoTransform()
231
+ projection = src_ds.GetProjection()
232
+
233
+ # MNTmodifs_ file
234
+ output_file = path_vuln / tif_file.name.replace("bath_", "MNTmodifs_")
235
+ dst_ds = driver.Create(str(output_file), xsize, ysize, 1, gdal.GDT_Float32)
236
+ dst_ds.SetGeoTransform(geotransform)
237
+ dst_ds.SetProjection(projection)
238
+ data = np.ones((ysize, xsize), dtype=np.float32)
239
+ dst_ds.GetRasterBand(1).WriteArray(data)
240
+ dst_ds.GetRasterBand(1).SetNoDataValue(0)
241
+ dst_ds = None
242
+
243
+ src_ds = None
244
+
245
+ return found_bath
246
+
247
+ def create_INPUT_OUTPUT_forScenario(maindir, study_area, scenario, simu_gpu=None, danger=None):
248
+ """Creates folder for a new study area or/and scenario. The last argument simu_gpu is used when loading simulation (indicates path to the simulation folder),
249
+ if not used, indicate None to ignore it."""
250
+ study_area = Path(study_area).stem
251
+ base_pathwd = Path(maindir) / "INPUT" / "WATER_DEPTH" / study_area / scenario
252
+ subfolders = ["DEM_FILES", "INTERP_WD", "EXTRACTED_LAST_STEP_WD"]
253
+ os.makedirs(base_pathwd, exist_ok=True)
254
+ for folder in subfolders:
255
+ os.makedirs(os.path.join(base_pathwd, folder), exist_ok=True)
256
+
257
+ base_change = Path(maindir) / "INPUT" / "CHANGE_DEM" / study_area / scenario
258
+ os.makedirs(base_change, exist_ok=True)
259
+
260
+ base_CSV = Path(maindir) / "INPUT" / "CSVs" / study_area / scenario
261
+ os.makedirs(base_CSV, exist_ok=True)
262
+
263
+ base_river = Path(maindir) / "INPUT" / "RIVER_MASK" / study_area / scenario
264
+ os.makedirs(base_river, exist_ok=True)
265
+
266
+ base_velocity = Path(maindir) / "INPUT" / "VELOCITY" / study_area / scenario
267
+ os.makedirs(base_velocity, exist_ok=True)
268
+
269
+ if simu_gpu != None:
270
+ path_bat_gpu = Path(simu_gpu) / "bathymetry.tif"
271
+ if path_bat_gpu.exists():
272
+ create_shapefile_from_prop_tif(path_bat_gpu, Path(maindir) / "INPUT" / "STUDY_AREA" / f"{study_area}.shp")
273
+ logging.info(_("Study area file created in INPUT/STUDY_AREA."))
274
+ else :
275
+ logging.error(_(f"Error in the study area creation : no bathymetry.tif file in the given simulation folder {simu_gpu}. Please provide it in this folder and try again."))
276
+ if danger != None:
277
+ if danger.exists():
278
+ create_shapefile_from_prop_tif(danger, Path(maindir) / "INPUT" / "STUDY_AREA" / f"{study_area}.shp")
279
+ logging.info(("Study area file created in INPUT/STUDY_AREA."))
280
+ else :
281
+ logging.error(_(f"Error in the study area creation : no bathymetry.tif file in the given simulation folder {simu_gpu}. Please provide it in this folder and try again."))
282
+
283
+
284
+
285
+ INBE_Manager(main_dir=maindir, Study_area=Path(study_area).stem, scenario=scenario)
286
+ logging.info((f"Files created in INPUT and OUTPUT for the study area named '{study_area}', and the scenario named '{scenario}'"))
287
+ return
288
+
289
+
290
+ class INBEGui(wx.Frame):
291
+ """ The main frame for the damage computation with INSYDE-BE (=INBE) """
292
+
293
+ def __init__(self, parent=None, width=1024, height=500):
294
+
295
+ super(wx.Frame, self).__init__(parent, title='Damage modelling - INBE manager', size=(width, height))
296
+
297
+ self._manager = None
298
+ self._mapviewer = None
299
+ self.InitUI()
300
+ self._func = INBE_functions()
301
+
302
+ self.df_results_Ti = None
303
+
304
+ @property
305
+ def mapviewer(self):
306
+ return self._mapviewer
307
+
308
+ @mapviewer.setter
309
+ def mapviewer(self, value):
310
+ from ..PyDraw import WolfMapViewer
311
+
312
+ if not isinstance(value, WolfMapViewer):
313
+ raise TypeError("The mapviewer must be a WolfMapViewer")
314
+
315
+ self._mapviewer = value
316
+
317
+ def layout(self, self_fct):
318
+ """Update the layers for the main buttons"""
319
+ font = self_fct.GetFont()
320
+ font.SetWeight(wx.FONTWEIGHT_BOLD)
321
+ self_fct.SetFont(font)
322
+ self_fct.SetBackgroundColour(wx.Colour(222, 209, 209))
323
+ #self_fct.Bind(wx.EVT_ENTER_WINDOW, self.OnHoverEnter)
324
+ #self_fct.Bind(wx.EVT_LEAVE_WINDOW, self.OnHoverLeave)
325
+
326
+ def on_button_click(self, event):
327
+ self.PopupMenu(self.menu)
328
+
329
+ def on_button_click2(self, event2):
330
+ self.PopupMenu(self.menu2)
331
+
332
+ def onRiverbed(self, event):
333
+ """Two options for the 'Update Riverbed' button: either the new riverbed trace
334
+ file already exists and the user selects it, or it does not exist, and the user points to
335
+ a no-overflow simulation, allowing the code to create the trace."""
336
+ menu_id = event.GetId()
337
+ if menu_id == 1:
338
+ logging.info(_("Option 1 : the file exists, pointing towards it."))
339
+ dlg = wx.FileDialog(None, "Please select the .tiff file with the NEW trace of the riverbed.",
340
+ style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST,
341
+ wildcard="TIFF files (*.tiff)|*.tiff")
342
+
343
+ if dlg.ShowModal() == wx.ID_OK:
344
+ selected_file = Path(dlg.GetPath())
345
+ copied_file = self._manager.OUT_SCEN_DIR / "copy_file"
346
+ shutil.copy(selected_file, copied_file)
347
+ logging.info(_(f"File copied to: {copied_file}"))
348
+
349
+ new_name = Path(self._manager.IN_RIVER_MASK_SCEN) / "Masked_River_extent.tiff"
350
+
351
+ with wx.MessageDialog(self, f"Modified riverbed imported and called Masked_River_extent_scenarios.tiff.",
352
+ "File imported.", wx.OK | wx.ICON_INFORMATION) as dlg:
353
+ dlg.ShowModal()
354
+
355
+ if new_name.exists():
356
+ new_name.unlink()
357
+
358
+ copied_file.rename(new_name)
359
+ dilatation_mask_river(self._manager)
360
+ logging.info(_(f"File renamed and dilated to: {new_name}"))
361
+ else:
362
+ logging.info(_('No file selected. Please try again.'))
363
+
364
+ elif menu_id == 2: #No file, so need to create
365
+ logging.info(_("Option 2 : pointing to simulation with low discharge (no overflows!)."))
366
+
367
+ with wx.DirDialog(self, "Please select a simul_gpu_results folder of a simulation with low discharges (no overflows).", style=wx.DD_DEFAULT_STYLE) as dir_dlg:
368
+ if dir_dlg.ShowModal() == wx.ID_OK:
369
+ selected_folder = Path(dir_dlg.GetPath())
370
+ if os.path.basename(selected_folder) == "simul_gpu_results" :
371
+ logging.info(_(f"Selected folder: {selected_folder}"))
372
+ fn_output = Path(self._manager.IN_RIVER_MASK_SCEN) / "Masked_River_extent.tiff"
373
+ dlg = wx.TextEntryDialog(self, "What water depth threshold (in meters) should be used to define the riverbed trace, above which\n"
374
+ "the water depth is considered part of the riverbed? Use a dot as a decimal separator (e.g 0.3).", "Type a water depth threshold in [m] (e.g 0.3)", "")
375
+
376
+ if dlg.ShowModal() == wx.ID_OK:
377
+ while True:
378
+ try:
379
+ valeur = dlg.GetValue()
380
+ threshold = float(valeur)
381
+ if threshold < 1e-5 or threshold > 150:
382
+ wx.MessageBox(
383
+ "Error: The value must be positive > 0 and reasonable. Please, try again.",
384
+ "Error", wx.OK | wx.ICON_ERROR
385
+ )
386
+ break
387
+
388
+ dialog = wx.SingleChoiceDialog(
389
+ parent=None,
390
+ message=f"Threshold accepted. Considering riverbed where water depth > {threshold}[m] via",
391
+ caption="Choix",
392
+ choices=["last step", "danger map"]
393
+ )
394
+
395
+ if dialog.ShowModal() == wx.ID_OK:
396
+ choix = dialog.GetStringSelection()
397
+ if choix == "last step":
398
+ type_extraction = "last step"
399
+ id_begin, id_end, id_step =None, None, None
400
+ else:
401
+ type_extraction = "danger_map"
402
+
403
+ dlg_start = wx.TextEntryDialog(None, "From which time step? (integer)", "Start step")
404
+ if dlg_start.ShowModal() == wx.ID_OK:
405
+ id_begin = int(dlg_start.GetValue())
406
+ dlg_start.Destroy()
407
+
408
+ dlg_end = wx.TextEntryDialog(None, "Until which time step? (integer, enter -1 for last)", "End step")
409
+ if dlg_end.ShowModal() == wx.ID_OK:
410
+ id_end = int(dlg_end.GetValue())
411
+ dlg_end.Destroy()
412
+
413
+ dlg_step = wx.TextEntryDialog(None, "Extract every how many steps? (integer)", "Step interval")
414
+ if dlg_step.ShowModal() == wx.ID_OK:
415
+ id_step = int(dlg_step.GetValue())
416
+ dlg_step.Destroy()
417
+
418
+ dialog.Destroy()
419
+ logging.info(_("Detecting riverbed."))
420
+ riverbed_trace_dilated(selected_folder, fn_output, threshold, type_extraction, id_begin, id_end, id_step)
421
+ dilatation_mask_river(self._manager)
422
+ logging.info(_("File created."))
423
+ with wx.MessageDialog(
424
+ self,
425
+ "Masked_River_extent_scenarios.tiff successfully created and dilated.",
426
+ "File created.", wx.OK | wx.ICON_INFORMATION
427
+ ) as dlg_success:
428
+ dlg_success.ShowModal()
429
+ break
430
+ except ValueError:
431
+ wx.MessageBox(
432
+ "Error: Invalid entry. Please enter a valid number (positive > 0, reasonable, using with DOT as a decimal separator).",
433
+ "Error", wx.OK | wx.ICON_ERROR
434
+ )
435
+ break
436
+
437
+ else:
438
+ logging.info(_("Cancelled."))
439
+ dlg.Destroy()
440
+ else:
441
+ logging.info(_("No folder (or wrong one) selected. Please try again (must be simul_gpu_results)."))
442
+
443
+
444
+ def layout_listbox(self, self_fct):
445
+ """Changes the layout for the listbox : light grey."""
446
+ self_fct.SetBackgroundColour(wx.Colour(220, 220, 220))
447
+
448
+ def InitUI(self):
449
+ self.gpu_bathy = None
450
+ self.maindir = None
451
+
452
+ sizer_hor_main = wx.BoxSizer(wx.HORIZONTAL)
453
+ sizer_vert1 = wx.BoxSizer(wx.VERTICAL)
454
+ sizer_hor_threads = wx.BoxSizer(wx.HORIZONTAL)
455
+ sizer_hor1 = wx.BoxSizer(wx.HORIZONTAL)
456
+ sizer_hor2 = wx.BoxSizer(wx.HORIZONTAL)
457
+ sizer_hor3 = wx.BoxSizer(wx.HORIZONTAL)
458
+ sizer_hor4 = wx.BoxSizer(wx.HORIZONTAL)
459
+ sizer_hor5 = wx.BoxSizer(wx.HORIZONTAL)
460
+ sizer_hor_scen = wx.BoxSizer(wx.HORIZONTAL)
461
+
462
+ # 1st LINE - Loading INBE folder
463
+ panel = wx.Panel(self)
464
+ self._but_maindir = wx.Button(panel, label=_('Main Directory'))
465
+ self._but_maindir.SetFont(wx.Font(9, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD))
466
+ self._but_maindir.Bind(wx.EVT_BUTTON, self.OnMainDir)
467
+
468
+ self._listbox_studyarea = wx.ListBox(panel, choices=[], style=wx.LB_SINGLE)
469
+ self.layout_listbox(self._listbox_studyarea)
470
+ self._listbox_studyarea.Bind(wx.EVT_LISTBOX, self.OnStudyArea)
471
+ self._listbox_studyarea.SetToolTip(_("Choose the study area existed in the folder."))
472
+
473
+ self._listbox_scenario = wx.ListBox(panel, choices=[], style=wx.LB_SINGLE)
474
+ self.layout_listbox(self._listbox_scenario)
475
+ self._listbox_scenario.Bind(wx.EVT_LISTBOX, self.OnScenario)
476
+ self._listbox_scenario.SetToolTip(_("Choose the INBE scenario."))
477
+
478
+ sizer_ver_small = wx.BoxSizer(wx.VERTICAL)
479
+ self._but_checkfiles = wx.Button(panel, label=_('Check structure'))
480
+ self._but_checkfiles.Bind(wx.EVT_BUTTON, self.OnCheckFiles)
481
+ self._but_checkfiles.SetToolTip(_("Checks if the folder is correctly structured\n with INPUT and OUTPUT."))
482
+ self._but_checksim = wx.Button(panel, label=_('Check simulations'))
483
+ self._but_checksim.SetToolTip(_("Displays the loaded simulations, interpolated in INTERP_WD."))
484
+ self._but_checksim.Bind(wx.EVT_BUTTON, self.OnHydrodynInput)
485
+ self._but_checkpicc = wx.Button(panel, label=_('Check PICC'))
486
+ self._but_checkpicc.Bind(wx.EVT_BUTTON, self.OnCheckPICC)
487
+ self._but_checkpicc.SetToolTip(_("Checks if PICC exists and how much residential building ('Habitations') are read. The process may be slow. Please, be patient."))
488
+ self._but_checkpond= wx.Button(panel, label=_('Check ponderation'))
489
+ self._but_checkpond.Bind(wx.EVT_BUTTON, self.OnCheckPond)
490
+ self._but_checkpond.SetToolTip(_("Displays a graph of the computed weighting coefficient\n of the final INBE computations."))
491
+
492
+ # 2nd LINE - Hydrodynamic part
493
+ self._but_loadgpu = wx.ToggleButton(panel, label=_('Working with new\n hydraulic scenarios'))
494
+ self._but_loadgpu.SetToolTip(_("To load or change the hydraulic simulations"))
495
+ self._but_loadgpu.SetFont(wx.Font(9, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD))
496
+ self._but_loadgpu.Bind(wx.EVT_TOGGLEBUTTON, self.OnLoadingSimu)
497
+ sizer_hor2.Add(self._but_loadgpu, 1, wx.ALL | wx.EXPAND, 0)
498
+
499
+ self._check_listbox = wx.CheckListBox(panel, choices=[], style=wx.LB_MULTIPLE | wx.CHK_CHECKED)
500
+ self.layout_listbox(self._check_listbox)
501
+ self.sims = {}
502
+ sizer_hor2.Add(self._check_listbox, 1, wx.ALL | wx.EXPAND, 0)
503
+
504
+ self._but_danger = wx.Button(panel, label=_('Extract last step or\n compute danger maps ▼'))
505
+ self._but_danger.SetToolTip(_("To create the danger maps of velocities and water depth. Please be patient."))
506
+ self._but_danger.Bind(wx.EVT_BUTTON, self.on_button_click2)
507
+ self.menu2 = wx.Menu()
508
+ self.menu2.Append(1, _("Extract the last step of the simulation."))
509
+ self.menu2.Append(2, _("Compute the danger maps of the simulation."))
510
+ self.menu2.Bind(wx.EVT_MENU, self.OnDanger)
511
+ sizer_hor2.Add(self._but_danger, 1, wx.ALL | wx.EXPAND, 0)
512
+
513
+ sizer_ver_small2 = wx.BoxSizer(wx.VERTICAL)
514
+ self._but_DEM = wx.Button(panel, label=_("Check DEM, DTM for interpolation"))
515
+ self._but_DEM.SetToolTip(_("To display the existing DEM input for the interpolation of the simulated free surfaces."))
516
+ self._but_DEM.Bind(wx.EVT_BUTTON, self.OnDEM)
517
+
518
+ self._but_MNTmodifs = wx.Button(panel, label=_("Check 'MNTmodifs_' scenarios"))
519
+ self._but_MNTmodifs.SetToolTip(_("To display the existing MNTmodifs_ scenario files for the DTM input of interpolation of the simulated free surfaces."))
520
+ self._but_MNTmodifs.Bind(wx.EVT_BUTTON, self.OnCheckMNTmodifs)
521
+
522
+ sizer_hor2.Add(sizer_ver_small2, 0, wx.ALL | wx.EXPAND, 5)
523
+
524
+ self._but_extrinterp = wx.Button(panel, label=_('Read and interpolate'))
525
+ self._but_extrinterp.SetToolTip(_("Reads and interpolates the danger maps computed (if not done, use previous buttons) of wolf gpu simulations."))
526
+ self._but_extrinterp.Bind(wx.EVT_BUTTON, self.OnInterpolation)
527
+ sizer_hor2.Add(self._but_extrinterp, 1, wx.ALL | wx.EXPAND, 0)
528
+
529
+
530
+ sizer_hor1.Add(self._but_maindir, 2, wx.ALL | wx.EXPAND, 0)
531
+ sizer_hor1.Add(self._listbox_studyarea, 1, wx.ALL | wx.EXPAND, 0)
532
+ sizer_hor1.Add(self._listbox_scenario, 1, wx.ALL | wx.EXPAND, 0)
533
+ sizer_hor1.Add(sizer_ver_small, 0, wx.ALL | wx.EXPAND, 5)
534
+
535
+ #3rd line
536
+ sizer_hor_threads = wx.BoxSizer(wx.HORIZONTAL)
537
+ text_dx = wx.StaticText(panel, label=_('Resolution (dx,dy) [m]:'))
538
+ self.input_dx = wx.StaticText(panel)
539
+ self.input_dx.SetMinSize((80, -1))
540
+ text_nbxy = wx.StaticText(panel, label=_('(nbx, nby):'))
541
+ self.input_nbxy = wx.StaticText(panel)
542
+ self.input_nbxy.SetMinSize((90, -1))
543
+ text_O = wx.StaticText(panel, label=_('Origin (X,Y):'))
544
+ self.input_O = wx.StaticText(panel)
545
+ self.input_O.SetMinSize((170, -1))
546
+ text_inflation = wx.StaticText(panel, label=_('Inflation factor:'))
547
+ self._inflation = wx.SpinCtrlDouble(panel, value="1.3", min=1.2, max=2.5, inc=0.1)
548
+ self._inflation.SetToolTip(_("Inflation factor from 2020 (corresponding year of the unitary prices), to the year of analysis. Defaults to 1.3[%] (corresponds to 2023)."))
549
+
550
+ self._but_toggle_admin = wx.ToggleButton(panel, label=_('Admin mode'))
551
+ self._but_toggle_admin.SetToolTip(_("To activate admin mode. enter password."))
552
+ self.toggle_state_Admin = False
553
+ self._but_toggle_admin.Bind(wx.EVT_TOGGLEBUTTON, self.OnToggleAdmin)
554
+
555
+ sizer_hor_threads.Add(text_dx, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 1)
556
+ sizer_hor_threads.Add(self.input_dx, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 1)
557
+ sizer_hor_threads.Add(text_nbxy, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 1)
558
+ sizer_hor_threads.Add(self.input_nbxy, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 1)
559
+ sizer_hor_threads.Add(text_O, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 1)
560
+ sizer_hor_threads.Add(self.input_O, 1, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 1)
561
+ sizer_hor_threads.Add(text_inflation, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 1)
562
+ sizer_hor_threads.Add(self._inflation, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 1)
563
+ #sizer_hor_threads.Add(self._nb_process, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 1)
564
+ sizer_hor_threads.Add(self._but_toggle_admin, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 1)
565
+
566
+ # Last lines + scenarios
567
+ #------------------------
568
+
569
+ self._but_upriverbed = wx.Button(panel, label=_("Update riverbed ▼"))
570
+ self._but_upriverbed.SetToolTip(_("Select one of the two options to create the riverbed mask."))
571
+ self._but_upriverbed.Bind(wx.EVT_BUTTON, self.on_button_click)
572
+ self.menu = wx.Menu()
573
+ self.menu.Append(1, _("File of riverbed trace exists."))
574
+ self.menu.Append(2, _("Point to a low discharge simulation and calculate the riverbed trace."))
575
+ self.menu.Bind(wx.EVT_MENU, self.onRiverbed)
576
+ sizer_hor_scen.Add(self._but_upriverbed, 1, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 1)
577
+
578
+ self._check_listbox_Ti = wx.CheckListBox(panel, choices=[], style=wx.LB_MULTIPLE | wx.CHK_CHECKED)
579
+ self.layout_listbox(self._check_listbox_Ti)
580
+ self.sims_Ti = {}
581
+ sizer_hor4.Add(self._check_listbox_Ti, 1, wx.ALL | wx.EXPAND, 0)
582
+
583
+ self._but_input = wx.Button(panel, label=_('Input table creation\n by reading PICC and WOLF'))
584
+ self.layout(self._but_input)
585
+ self._but_input.Bind(wx.EVT_BUTTON, self.OnInput)
586
+ sizer_hor4.Add(self._but_input, 1, wx.ALL | wx.EXPAND, 0)
587
+
588
+ text_tri = wx.StaticText(panel, label=_('Select percentil'))
589
+ self._tri = wx.SpinCtrlDouble(panel, value="1", min=0.05, max=1, inc=0.05)
590
+ self._tri.SetToolTip(_("Percentile of the number of results to be represented in the analysis."))
591
+ text_tri.SetMinSize((100,-1))
592
+ self._tri.SetMinSize((50,-1))
593
+ sizer_hor5.Add(text_tri, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 1)
594
+ sizer_hor5.Add(self._tri, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 1)
595
+
596
+ self._but_readresults = wx.Button(panel, label=_('Read results'))
597
+ self.layout(self._but_readresults)
598
+ self._but_readresults.Bind(wx.EVT_BUTTON, self.OnReadResults)
599
+ sizer_hor5.Add(self._but_readresults, 1, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 1)
600
+ #self._but_readresults.Hide()
601
+
602
+ #self._listbox_scenario2 = wx.CheckListBox(panel, choices=[], style=wx.LB_MULTIPLE | wx.CHK_CHECKED)
603
+ #self.layout_listbox(self._listbox_scenario2)
604
+ #self.list_scen_output = {}
605
+ #self._listbox_scenario2.SetToolTip("Choose the scenarios to compare.")
606
+ #sizer_hor5.Add(self._but_setcomp, 1, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 1)
607
+
608
+ self._listbox_CompScen = wx.CheckListBox(panel, choices=[], style=wx.LB_MULTIPLE | wx.CHK_CHECKED)
609
+ self.layout_listbox(self._listbox_CompScen)
610
+ self._listbox_CompScen.SetToolTip(_("Choose the INBE scenarios to compare (minimum 2), in the same study area selected at the manager first line."))
611
+ sizer_hor5.Add(self._listbox_CompScen, 1, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 1)
612
+
613
+
614
+ self._but_setcomp = wx.Button(panel, label=_('Comparison'))
615
+ self.layout(self._but_setcomp)
616
+ self._but_setcomp.Bind(wx.EVT_BUTTON, self.OnSetComp0)
617
+ sizer_hor5.Add(self._but_setcomp, 1, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 1)
618
+ #self._but_setcomp.Hide()
619
+
620
+
621
+
622
+ self._but_default_TEMP = wx.Button(panel, label=_('Default values and\n individual damage'))
623
+ self._but_default_TEMP.SetToolTip(_("Impute the default values to the input tables, and compute the individual damage."))
624
+ self.layout(self._but_default_TEMP)
625
+ self._but_default_TEMP.Bind(wx.EVT_BUTTON, self.OnDefault_TEMP)
626
+ sizer_hor4.Add(self._but_default_TEMP, 1, wx.ALL | wx.EXPAND, 0)
627
+
628
+ self._but_combined_OUTPUT = wx.Button(panel, label=_('Combined damage'))
629
+ self._but_combined_OUTPUT.SetToolTip(_("Compute the combined damage."))
630
+ self.layout(self._but_combined_OUTPUT)
631
+ self._but_combined_OUTPUT.Bind(wx.EVT_BUTTON, self.Oncombined_OUTPUT)
632
+ sizer_hor4.Add(self._but_combined_OUTPUT, 1, wx.ALL | wx.EXPAND, 0)
633
+
634
+ #Lines order
635
+ sizer_ver_small.Add(self._but_checkfiles, 0, wx.ALL | wx.EXPAND, 1)
636
+ sizer_ver_small.Add(self._but_checksim, 0, wx.ALL | wx.EXPAND, 1)
637
+ sizer_ver_small.Add(self._but_checkpond, 0, wx.ALL | wx.EXPAND, 1)
638
+ sizer_ver_small.Add(self._but_checkpicc, 0, wx.ALL | wx.EXPAND, 1)
639
+
640
+ sizer_vert1.Add(sizer_hor1, 1, wx.EXPAND, 0)
641
+ sizer_vert1.Add(sizer_hor2, 1, wx.EXPAND, 0)
642
+ sizer_vert1.Add(sizer_hor_threads, 0, wx.EXPAND, 0)
643
+ sizer_vert1.Add(sizer_hor_scen, 1, wx.EXPAND, 0)
644
+ sizer_vert1.Add(sizer_hor3, 1, wx.EXPAND, 0)
645
+ sizer_vert1.Add(sizer_hor4, 1, wx.EXPAND, 0)
646
+ sizer_vert1.Add(sizer_hor5, 1, wx.EXPAND, 0)
647
+ sizer_hor_main.Add(sizer_vert1, proportion=1, flag=wx.EXPAND, border=0)
648
+
649
+ sizer_ver_small2.Add(self._but_MNTmodifs, 0, wx.ALL | wx.EXPAND, 1)
650
+ sizer_ver_small2.Add(self._but_DEM, 0, wx.ALL | wx.EXPAND, 1)
651
+
652
+ #Disabled if Main Directory + SA + Scenario not selected
653
+ self._but_default_TEMP.Enable(False)
654
+ self._but_danger.Enable(False)
655
+ self._but_input.Enable(False)
656
+ self._tri.Enable(False)
657
+ self._but_readresults.Enable(False)
658
+ self._but_checkfiles.Enable(False)
659
+ self._but_DEM.Enable(False)
660
+ self._but_MNTmodifs.Enable(False)
661
+ self._but_extrinterp.Enable(False)
662
+ self._but_combined_OUTPUT.Enable(False)
663
+ self._but_upriverbed.Enable(False)
664
+ self._but_checksim.Enable(False)
665
+ self._but_checkpicc.Enable(False)
666
+ self._but_loadgpu.Enable(False)
667
+ self._but_checkpond.Enable(False)
668
+ self._but_setcomp.Enable(False)
669
+
670
+ panel.SetSizer(sizer_hor_main)
671
+ panel.Layout()
672
+
673
+
674
+ def OnSims(self, e:wx.ListEvent):
675
+ """ Load sim into the mapviewer """
676
+ pass
677
+
678
+ def OnSimsDBLClick(self, e:wx.ListEvent):
679
+ """ Load sim into the mapviewer """
680
+ if self.mapviewer is None:
681
+ return
682
+
683
+ from ..PyDraw import draw_type
684
+
685
+ idx_sim = e.GetSelection()
686
+ tmppath = self._manager.get_filepath_for_return_period(self._manager.get_return_periods()[idx_sim])
687
+ if tmppath.stem not in self.mapviewer.get_list_keys(drawing_type=draw_type.ARRAYS):
688
+ self.mapviewer.add_object('array', filename=str(tmppath), id=tmppath.stem)
689
+ self.mapviewer.Refresh()
690
+
691
+ def OnCheckFiles(self, e):
692
+ """ Check the files """
693
+ if self._manager is None:
694
+ logging.error(_("No main directory selected -- Nothing to check"))
695
+ return
696
+
697
+ i=self._manager.check_inputs()
698
+
699
+ if i == False :
700
+ logging.error(_(f"Missing files in INPUT. Please provide them by following the right structure."))
701
+ with wx.MessageDialog(self, f"Missing files in INPUT. Inputs can not be created automatically : you must provide them.\nPlease read the logs and terminal to see the missing ones.", "Error", wx.OK | wx.ICON_ERROR) as dlg:
702
+ dlg.ShowModal()
703
+ return
704
+ else :
705
+ if (self._manager._study_area is None) or (self._manager._scenario is None):
706
+ logging.error(_(f"No study area and/or scenario selected, no check of OUTPUT."))
707
+ with wx.MessageDialog(self, f"INPUT is well structured, but OUTPUT has not been checked because there is no study area and scenario selected.", "Checking", wx.OK | wx.ICON_INFORMATION) as dlg:
708
+ dlg.ShowModal()
709
+ else:
710
+ logging.info(_(f"The folder is well structured."))
711
+ #t=self._manager.check_temporary()
712
+ o=self._manager.check_outputs()
713
+ with wx.MessageDialog(self, f"Main directory is checked.\nINPUT is well structured, and OUTPUT has been checked. If folders were missing, they have been created\nMain directory at {self.maindir}", "Checking", wx.OK | wx.ICON_INFORMATION) as dlg:
714
+ dlg.ShowModal()
715
+ #logging.info(f"scenario {self._manager._scenario} {self._manager.scenario} et SA {self._manager._study_area} {self._manager.Study_area}")
716
+
717
+ def OnHydrodynInput(self,e):
718
+ """ A test to check if the FILLED water depths files exist.
719
+ -If YES : the code can go on
720
+ -If NO : either need to be computed, either the code will use the baseline ones
721
+ """
722
+
723
+ if self._manager is None:
724
+ logging.error(_("No main directory selected -- Nothing to check"))
725
+ return
726
+
727
+ if self._manager.IN_SA_INTERP is None:
728
+ with wx.MessageDialog(self, "No simulation found in the manager. Please select the simulations first.", "Error", wx.OK | wx.ICON_ERROR) as dlg:
729
+ dlg.ShowModal()
730
+ return
731
+
732
+ paths_FilledWD = self._manager.get_sims_files_for_scenario()
733
+
734
+ if len(paths_FilledWD) == 0 :
735
+ logging.info(_("There are no interpolated free surface files."))
736
+ dialog = wx.MessageDialog(None, "There are no interpolated free surface files. Please choose an action.", "Checking- Choose an option",
737
+ wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION)
738
+
739
+ dialog.SetYesNoLabels("Use the ones in the scenario_baseline (assumption)", "Load other simulations")
740
+ response = dialog.ShowModal()
741
+
742
+ if response == wx.ID_YES:
743
+ logging.info(_("Decision of using baseline simulations."))
744
+ paths_FilledWD_base = self._manager.get_sims_files_for_baseline()
745
+ if len(paths_FilledWD_base) == 0 :
746
+ logging.info(_("Cannot select files in the _baseline folder (no files or no folder!)."))
747
+ else:
748
+ self._manager.copy_tif_files(paths_FilledWD_base, self._manager.IN_SA_INTERP)
749
+
750
+ elif response == wx.ID_NO:
751
+ logging.info(_("Decision of loading simulations."))
752
+ with wx.MessageDialog(self, f"Please use the 'Working with new hydraulic scenarios' button of the manager and follow the instructions.", "Redirecting",
753
+ wx.OK | wx.ICON_INFORMATION) as dlg:
754
+ dlg.ShowModal()
755
+ else:
756
+ logging.info(_("Cancelled"))
757
+
758
+ dialog.Destroy()
759
+
760
+ else:
761
+ name_paths_FilledWD = []
762
+
763
+ for names in paths_FilledWD:
764
+ logging.info(_(f"Interpolated free surface file(s) found: {names.name}. \n Reminder : the names of the simulations MUST be 'T.' or 'Q.' with '.' the return period."))
765
+ name_paths_FilledWD.append(names.name)
766
+ with wx.MessageDialog(self,
767
+ f"{len(paths_FilledWD)} file(s) of interpolated free surface found in the folder : {name_paths_FilledWD}.",
768
+ "Information",
769
+ style=wx.OK | wx.ICON_INFORMATION) as dlg:
770
+ dlg.ShowModal()
771
+ update_info_header(self.input_dx,self.input_nbxy,self.input_O,self._manager.IN_SA_INTERP)
772
+
773
+
774
+ def OnCheckPond(self,e): #Maybe later ? Idk
775
+ if self._manager is None:
776
+ logging.error(_("No main directory selected -- Nothing to check"))
777
+ return
778
+ if self._manager.IN_SA_INTERP is None:
779
+ logging.error(_("No IN_SA_INTERP attribute found in the manager."))
780
+ with wx.MessageDialog(self, "No simulation found in the manager. Please select the simulations first.", "Error", wx.OK | wx.ICON_ERROR) as dlg:
781
+ dlg.ShowModal()
782
+ return
783
+ ponds = self._manager.get_ponderations()
784
+ if isinstance(ponds, pd.DataFrame):
785
+ logging.info(_(f"Plotting the coefficients graph."))
786
+ ponds.plot(kind='bar', color='gray', edgecolor='black')
787
+ plt.ylabel("Weighting coefficients [-]")
788
+ plt.xlabel("Return period [years]")
789
+ plt.grid(axis='y', linestyle='--', alpha=0.7)
790
+ plt.show()
791
+ else:
792
+ with wx.MessageDialog(self,
793
+ "No coefficients computed, because no return period found in the interpolated simulation folder. Try after loading gpu simulations",
794
+ "Checking",
795
+ style=wx.OK | wx.ICON_INFORMATION) as dlg:
796
+ dlg.ShowModal()
797
+
798
+ def OnCheckPICC(self, e):
799
+ logging.info(_(f"Checking PICC for study area {self._manager._study_area}, in {self._manager.scenario}."))
800
+ unused, nb, unused = self._func.PICC_read(self._manager)#._study_area, self._manager.scenario)
801
+ if nb != None :
802
+ with wx.MessageDialog(self,
803
+ f"PICC Successfully read. There are {nb} residential building(s) ('Habitation') contained in\n the selected study area {self._manager._study_area}, in {self._manager.scenario}.",
804
+ "Checking PICC",
805
+ style=wx.OK | wx.ICON_INFORMATION) as dlg:
806
+ dlg.ShowModal()
807
+ else :
808
+ path = Path(self._manager.IN_DATABASE) / "PICC_Vesdre.shp"
809
+ with wx.MessageDialog(self,
810
+ f"Error while reading PICC, please ensure the file exists in {path}",
811
+ "Error checking PICC",
812
+ style=wx.OK | wx.ICON_INFORMATION) as dlg:
813
+ dlg.ShowModal()
814
+
815
+
816
+ def OnMainDir(self, e):
817
+ """Selects the main directory to be read."""
818
+ vanish_info_header(self.input_dx,self.input_nbxy,self.input_O)
819
+
820
+ with wx.DirDialog(self, "Choose the main directory containing the data (folders INPUT and OUTPUT):",
821
+ style=wx.DD_DEFAULT_STYLE
822
+ ) as dlg:
823
+
824
+ if dlg.ShowModal() == wx.ID_OK:
825
+ self._manager = INBE_Manager(main_dir=dlg.GetPath())#, Study_area="scenario_manager", scenario = "scenario_before2021")
826
+ self.maindir=dlg.GetPath()
827
+
828
+ folders = ["INPUT"]
829
+
830
+ for folder in folders:
831
+ if not os.path.isdir(os.path.join(self.maindir, folder)):
832
+ logging.error(_("INPUT folder is missing."))
833
+ wx.MessageBox(
834
+ f"Missing INPUT folder. Please organize correctly this folder {self.maindir}.",
835
+ "Error",
836
+ wx.OK | wx.ICON_ERROR
837
+ )
838
+ dlg.Destroy()
839
+ return
840
+
841
+ folders = ['RIVER_MASK', 'DATABASE', 'STUDY_AREA', 'CSVs', 'WATER_DEPTH', 'VELOCITY']
842
+ missing = []
843
+ for folder in folders:
844
+ if not os.path.isdir(os.path.join(self.maindir, "INPUT", folder)):
845
+ logging.error(_(f"INPUT/{folder} folder is missing."))
846
+ missing.append(folder)
847
+ if missing:
848
+ wx.MessageBox(
849
+ f"Missing folders : {missing}. Please organize correctly your INPUT folder in {self.maindir}.",
850
+ "Error",
851
+ wx.OK | wx.ICON_ERROR
852
+ )
853
+ dlg.Destroy()
854
+ return
855
+
856
+ folders = ["OUTPUT"]#TEMP",
857
+ for folder in folders:
858
+ if not os.path.isdir(os.path.join(self.maindir, folder)):
859
+ logging.info(_(f"Creating {folder} folder."))
860
+ os.makedirs(os.path.join(self.maindir, folder))
861
+
862
+ self._but_default_TEMP.Enable(True)
863
+ self._but_input.Enable(True)
864
+ self._but_checkfiles.Enable(True)
865
+ self._but_upriverbed.Enable(True)
866
+ self._tri.Enable(True)
867
+ self._but_readresults.Enable(True)
868
+ self._but_checksim.Enable(True)
869
+ self._but_checkpicc.Enable(True)
870
+ self._but_loadgpu.Enable(True)
871
+ self._but_checkpond.Enable(True)
872
+ self._but_combined_OUTPUT.Enable(True)
873
+ self._but_setcomp.Enable(True)
874
+
875
+ #Must be False if come back :
876
+ self._but_DEM.Enable(False)
877
+ self._but_MNTmodifs.Enable(False)
878
+ self._but_extrinterp.Enable(False)
879
+
880
+ self._listbox_scenario.Clear()
881
+ studyareas = self._manager.get_list_studyareas()
882
+ if len(studyareas) == 0 :
883
+ logging.info(_("Folder loaded but no study areas found in the folder (INPUT/STUDY_AREA). Please use the button to load hydraulic simulations in the manager."))
884
+ return
885
+ self._listbox_studyarea.Clear()
886
+ self._listbox_studyarea.InsertItems(studyareas, 0)
887
+
888
+ logging.info(_("All the directories are present"))
889
+
890
+ def OnStudyArea(self, e):
891
+ """ Change the study area """
892
+ if self._manager is None:
893
+ return
894
+ vanish_info_header(self.input_dx,self.input_nbxy,self.input_O)
895
+ self._listbox_scenario.Clear()
896
+ self.file_paths = None
897
+ study_area:str = self._manager.get_list_studyareas(with_suffix=True)[e.GetSelection()]
898
+
899
+ self._manager.change_studyarea(study_area)
900
+ list_sc, list_SA = self._manager.get_list_scenarios_extended()
901
+ self.items = list(zip(list_SA, list_sc)) # [(SA, Scenario), ...]
902
+ choices = [f"{sa} / {sc}" for sa, sc in self.items]
903
+ self._listbox_CompScen.Set(choices)
904
+
905
+ #self._listbox_CompScen.Set(list_sc_extended)#get_list_individual_T())
906
+
907
+ sc = self._manager.get_list_scenarios()
908
+
909
+ if len(sc)!=0:
910
+ self._listbox_scenario.InsertItems(sc, 0)
911
+ else :
912
+ logging.error(_("No scenario available associated with this study area."))
913
+
914
+ if self.mapviewer is not None:
915
+ tmp_path = self._manager.IN_STUDY_AREA / study_area
916
+
917
+ from ..PyDraw import draw_type
918
+ if not tmp_path.stem in self.mapviewer.get_list_keys(drawing_type=draw_type.VECTORS):
919
+ self.mapviewer.add_object('vector', filename=str(tmp_path), id=tmp_path.stem)
920
+ self.mapviewer.Refresh()
921
+ self._but_DEM.Enable(False)
922
+ self._but_MNTmodifs.Enable(False)
923
+ self._but_extrinterp.Enable(False)
924
+
925
+ def OnScenario(self, e):
926
+ """ Change the scenario """
927
+ if self._manager is None:
928
+ return
929
+ scenario = self._manager.get_list_scenarios()[e.GetSelection()]
930
+ self._but_DEM.Enable(True)
931
+ self._but_MNTmodifs.Enable(True)
932
+ self._but_extrinterp.Enable(True)
933
+ self._manager.change_scenario(scenario)
934
+ create_INPUT_OUTPUT_forScenario(self.maindir, self._manager.Study_area, self._manager.scenario, None)
935
+ update_info_header(self.input_dx,self.input_nbxy,self.input_O,self._manager.IN_SA_INTERP)
936
+ self._check_listbox_Ti.Set(self._manager.get_list_interp()) #not in accept
937
+
938
+ def OnLoadingSimu(self,e):
939
+ """ Link between INBE and simulations
940
+ -Load a hydraulic scenarios from the scenario manager
941
+ -Create scenario and study area if needed.
942
+ """
943
+ #MAde for Vesdre & Daniela, very specific. Maybe to be kept... [xyz]
944
+ #dlg = wx.SingleChoiceDialog(
945
+ # None,
946
+ # "What do you want to load?",
947
+ # "Loading choice",
948
+ # ["Existing danger maps", "Wolf-GPU simulation"]
949
+ #)
950
+ #if dlg.ShowModal() == wx.ID_OK:
951
+ # choice = dlg.GetStringSelection()
952
+ # if choice == "Existing danger maps":
953
+ # dlg0 = wx.MessageDialog(
954
+ # None,
955
+ # "Please follow these steps:\n\n"
956
+ # "• Create a folder named after your study area (e.g., Theux).\n"
957
+ # "• Inside this folder, create a subfolder for the scenario (e.g., scenario_example).\n"
958
+ # "• In this scenario subfolder, include:\n"
959
+ # " - A water level danger map in .tif format (e.g., T2021.tif).\n"
960
+ # " - Optionally, a velocity danger map named like:\n"
961
+ # " v_danger_T2021_scenario_example.tif\n\n"
962
+ # "Then, select the scenario folder (e.g., Desktop\\Theux\\scenario_example).",
963
+ # "Information",
964
+ # wx.OK | wx.ICON_INFORMATION
965
+ # )
966
+ # dlg0.ShowModal()
967
+ # dlg0.Destroy()
968
+ #
969
+ #
970
+ # dlg_path = wx.DirDialog(
971
+ # None,
972
+ # "Please point toward the specific scenario folder (e.g Desktop\Theux\scenario_2021)."
973
+ # )
974
+ # if dlg_path.ShowModal() == wx.ID_OK:
975
+ # full_path = dlg_path.GetPath()
976
+ #
977
+ # study_area_folder = os.path.basename(os.path.dirname(full_path))
978
+ # scenario_folder = os.path.basename(full_path)
979
+ #
980
+ # tif_path = None
981
+ # for file in os.listdir(full_path):
982
+ # if file.endswith(".tif") and file.startswith("T"):
983
+ # tif_path = os.path.join(full_path, file)
984
+ # break
985
+ #
986
+ #
987
+ # create_INPUT_TEMP_OUTPUT_forScenario(self.maindir, study_area_folder, scenario_folder, danger=Path(tif_path))
988
+ #
989
+ # self._manager.change_studyarea(study_area_folder +'.shp')
990
+ # self._manager.change_scenario(scenario_folder)
991
+ # self._listbox_studyarea.Clear()
992
+ # self._listbox_studyarea.InsertItems(self._manager.get_list_studyareas(), 0)
993
+ # self._listbox_scenario.Clear()
994
+ # self._listbox_scenario.InsertItems(self._manager.get_list_scenarios(), 0)
995
+ #
996
+ # path_wd = self._manager.IN_SA_EXTRACTED
997
+ # WA_bin = WolfArray(tif_path)
998
+ # WA_bin.write_all(os.path.join(path_wd, os.path.splitext(os.path.basename(tif_path))[0] + ".bin"))
999
+ #
1000
+ # path_v = self._manager.IN_SCEN_DIR_V
1001
+ # logging.info(_(f"Scanning the folder {full_path} to get the danger map(s)."))
1002
+ # for file in os.listdir(full_path):
1003
+ # if file.startswith("v_danger_") and file.endswith(".tif"):
1004
+ # shutil.copy(os.path.join(full_path, file), path_v)
1005
+ # dlg = wx.MessageDialog(
1006
+ # None,
1007
+ # "Folders created and danger map(s) imported.",
1008
+ # "Information",
1009
+ # wx.OK | wx.ICON_INFORMATION
1010
+ # )
1011
+ # dlg.ShowModal()
1012
+ # dlg.Destroy()
1013
+ # logging.info(_("Folders created and danger map(s) imported."))
1014
+ #
1015
+ dlg = wx.DirDialog(None, "Please select the main scenario manager folder (containing the scenarios, the folder discharge, the scripts.py...), named after the STUDY AREA.\n If you cancel, this button wont be activated or will be desactivated.", style=wx.DD_DEFAULT_STYLE)
1016
+ if dlg.ShowModal() == wx.ID_OK:
1017
+ self._but_loadgpu.SetValue(True)
1018
+ main_gpu = Path(dlg.GetPath())
1019
+ study_area = main_gpu.name
1020
+ logging.info(_(f"Selected folder for GPU result such as the STUDY AREA is {study_area}"))
1021
+ dlg = wx.DirDialog(None, "Please select the scenarios folder (containing the 'simulations' folder) of the specific HYDRAULIC SCENARIO.", defaultPath=str(main_gpu), style=wx.DD_DEFAULT_STYLE)
1022
+ if dlg.ShowModal() == wx.ID_OK:
1023
+ scenario = Path(dlg.GetPath())
1024
+ hydraulic_scen=scenario.joinpath("simulations")
1025
+ scenario=scenario.name
1026
+ logging.info(_(f"Selected hydraulic scenario : {scenario}"))
1027
+ create_INPUT_OUTPUT_forScenario(self.maindir, study_area, scenario, main_gpu)
1028
+ self._manager.change_studyarea(study_area+'.shp')
1029
+ self._manager.change_scenario(scenario)
1030
+
1031
+ self._listbox_studyarea.Clear()
1032
+ self._listbox_studyarea.InsertItems(self._manager.get_list_studyareas(), 0)
1033
+ self._listbox_scenario.Clear()
1034
+ self._listbox_scenario.InsertItems(self._manager.get_list_scenarios(), 0)
1035
+
1036
+ #Blue color of selection even if not directly clicked :
1037
+ index_to_select = self._listbox_scenario.FindString(scenario)
1038
+ if index_to_select != wx.NOT_FOUND:
1039
+ self._listbox_scenario.SetSelection(index_to_select)
1040
+ self._listbox_scenario.SetItemBackgroundColour(index_to_select, wx.Colour(0, 120, 215))
1041
+
1042
+ index_to_select = self._listbox_studyarea.FindString(study_area)
1043
+ if index_to_select != wx.NOT_FOUND:
1044
+ self._listbox_studyarea.SetSelection(index_to_select)
1045
+ self._listbox_studyarea.SetItemBackgroundColour(index_to_select, wx.Colour(0, 120, 215))
1046
+ self._listbox_studyarea.Refresh()
1047
+ self._listbox_scenario.Refresh()
1048
+
1049
+ else:
1050
+ logging.error('No hydraulic scenario selected, toggle button desactivated.')
1051
+ self._but_loadgpu.SetValue(False)
1052
+ return
1053
+ else:
1054
+ logging.error('No folder found / selected. Please try again.')
1055
+ self._but_loadgpu.SetValue(False)
1056
+ return
1057
+
1058
+ self._check_listbox.Clear()
1059
+ self.sims = {}
1060
+ for subdir in hydraulic_scen.iterdir():
1061
+ if subdir.is_dir() and subdir.name.startswith("sim_"):
1062
+ self.sims[subdir.name] = subdir
1063
+ else:
1064
+ logging.info(_('No folder sim_ found / selected. Please try again.'))
1065
+ self.datadir_simulations = hydraulic_scen
1066
+ self.file_paths = {Path(sim).name: Path(sim) for sim in sorted(self.sims.keys())}
1067
+ self._check_listbox.Set(sorted(sim for sim in self.sims.keys()))
1068
+
1069
+ logging.info(_(f"GPU simulations loaded in the checkbox.\n\nPlease select the ones you want to interpolate and use the button 'Reading and interpolating free surface'."))
1070
+ message = "GPU simulations loaded in the checkbox\n\nPlease select the ones you want to interpolate and use the button 'Reading and interpolating free surface'."
1071
+
1072
+ found_bath = search_for_modif_bath_and_copy(Path(main_gpu), Path(hydraulic_scen.parent), self._manager.IN_CH_DEM_SC)
1073
+ if found_bath :
1074
+ message+= "\nIn addition, modification files for bathymetry (bath_) have been found in the gpu simulations, a copy has been made for a change in the vulnerability and DEM (see vuln_ and MNTmodifs_ in CHANGE_VULNE). Please edit them."
1075
+ logging.info(_(f"Modification files for bathymetry (bath_) have been found in the gpu simulations, a copy has been made for a change in the vulnerability and DEM (see vuln_ and MNTmodifs_ in CHANGE_VULNE). Please edit them."))
1076
+
1077
+ self.gpu_bathy = hydraulic_scen.parent / BATHYMETRY_FOR_SIMULATION # this is the last bathymetry after the scripts have been run
1078
+ self._but_extrinterp.Enable(True)
1079
+ self._but_DEM.Enable(True)
1080
+ self._but_danger.Enable(True)
1081
+ self._but_MNTmodifs.Enable(True)
1082
+ with wx.MessageDialog(self,
1083
+ message,
1084
+ "Information",
1085
+ style=wx.OK | wx.ICON_INFORMATION) as dlg:
1086
+ dlg.ShowModal()
1087
+
1088
+ def OnDanger(self,e):
1089
+ """ Specific button to extract last step or to compute the wd danger map"""
1090
+ menu_id = e.GetId()
1091
+ param_danger = [0, -1, 1]
1092
+ if menu_id == 1:
1093
+ type_extraction = "last_step"
1094
+ logging.info(_("Option 1 : last step extraction and interpolation."))
1095
+ elif menu_id == 2:
1096
+ type_extraction = "danger_map"
1097
+ logging.info(_("Option 2 : danger map computation and interpolation."))
1098
+ dlg = wx.TextEntryDialog(None,
1099
+ "Enter parameters as (e.g 0, -1, 1): from which step, until which step (-1 if latest step), by number of step",
1100
+ "Parameters", "0, -1, 1")
1101
+ if dlg.ShowModal() == wx.ID_OK:
1102
+ try:
1103
+ param_danger = [int(x.strip()) for x in dlg.GetValue().split(",")]
1104
+ except:
1105
+ wx.MessageBox("Invalid input. Use format: 0, -1, 1", "Error")
1106
+ dlg.Destroy()
1107
+
1108
+ else :
1109
+ return
1110
+
1111
+
1112
+ with wx.TextEntryDialog(
1113
+ self,
1114
+ "What threshold (in meters) do you want to apply to filter the water depth danger map?",
1115
+ "Water Depth Threshold",
1116
+ "0.01"
1117
+ ) as dlg:
1118
+ threshold = None
1119
+ if dlg.ShowModal() == wx.ID_OK:
1120
+ val = dlg.GetValue().strip().replace(',', '.')
1121
+ try:
1122
+ threshold = float(val)
1123
+ if threshold <= 0:
1124
+ wx.MessageBox("Please enter a strictly positive number.", "Invalid Value", wx.ICON_ERROR)
1125
+ threshold = None
1126
+ return
1127
+ except Exception:
1128
+ wx.MessageBox("Invalid input — please enter a number (e.g., 0.01).", "Error", wx.ICON_ERROR)
1129
+ threshold = None
1130
+ return
1131
+ else :
1132
+ return
1133
+ if not hasattr(self, 'file_paths'):
1134
+ with wx.MessageDialog(self,
1135
+ f"Please, first load gpu simulations via the previous button.",
1136
+ "Attention",
1137
+ style=wx.OK | wx.ICON_ERROR) as dlg:
1138
+ dlg.ShowModal()
1139
+ return
1140
+ logging.info(_(f"Threshold for water depth selected : {threshold} [m]"))
1141
+ checked_indices = self._check_listbox.GetCheckedItems()
1142
+ checked_items = [self._check_listbox.GetString(index) for index in checked_indices]
1143
+ selected_paths = [self.file_paths[item] for item in checked_items]
1144
+ if not selected_paths:
1145
+ wx.MessageBox("No selection detected. Using all items in the list.", "Info", wx.ICON_INFORMATION)
1146
+ selected_items = list(self._check_listbox.GetStrings())
1147
+ selected_paths = [self.file_paths[item] for item in selected_items]
1148
+ path_simulations = self.datadir_simulations
1149
+
1150
+ #dx,dy,nbx,nby,X,Y = False, False, False, False, False, False
1151
+ _interpol = interpolating_raster()
1152
+ for sim_ in selected_paths:
1153
+ if sim_.name.startswith("sim_"):
1154
+ self.sims[sim_.name] = sim_
1155
+ fn_read = Path(path_simulations/ sim_ / "simul_gpu_results")
1156
+ logging.info(_(f"Found simulation folder: {sim_}"))
1157
+ parts = sim_.name.split("sim_")
1158
+ if len(parts) > 1:
1159
+ logging.info(_("Computing water depth and velocity danger maps"))
1160
+ name = parts[1]
1161
+ # dx,dy,nbx,nby,X,Y = display_info_header(self.input_dx, self.input_nbxy, self.input_O, fn_write.with_suffix(".bin"))
1162
+ _interpol.export_z_or_v_bin(fn_read, self._manager, name, type_hazard="z_v", type_extraction = type_extraction, param_danger = param_danger, threshold=threshold)
1163
+
1164
+ else:
1165
+ logging.info(_(f"Please, ensure your simulations are named with the return period, e.g sim_T4"))
1166
+ else:
1167
+ logging.info(_('No folder found / selected. Please try again...'))
1168
+
1169
+ dlg = wx.MessageDialog(self,
1170
+ "Danger maps created in INPUT\WATER_DEPTH\... and INPUT\VELOCITY\...",
1171
+ "Success.",
1172
+ wx.OK | wx.ICON_INFORMATION)
1173
+ dlg.ShowModal()
1174
+ dlg.Destroy()
1175
+
1176
+
1177
+
1178
+ def OnDEM(self,e):
1179
+ """Import and create the inputs for the interpolation routine (name including 'MNT_...' and 'MNT_..._with_mask'.
1180
+ See function MTN_And_mask_creation_all"""
1181
+ path = self._manager.IN_SA_DEM
1182
+ names_inDEM = [f for f in os.listdir(path) if os.path.isfile(os.path.join(path, f))]
1183
+ if len(names_inDEM) != 0 :
1184
+ dialog = wx.MessageDialog(None, f"The DEM_FILES folder is not empty and contains the files {names_inDEM}. ", "Confirmation", wx.YES_NO | wx.ICON_QUESTION)
1185
+ dialog.SetYesNoLabels("Delete and reload", "Keep and leave")
1186
+ response = dialog.ShowModal()
1187
+ if response == wx.ID_YES:
1188
+ for file_name in names_inDEM:
1189
+ file_path = os.path.join(path, file_name)
1190
+ os.remove(file_path)
1191
+ logging.info(_("Files in DEM_FILES deleted."))
1192
+ else :
1193
+ logging.info(_("No update of DEM_FILES."))
1194
+ return
1195
+
1196
+ #Avec ajout BATHT_AFTER_SCRIPT
1197
+ if self.gpu_bathy == None:
1198
+ with wx.FileDialog(self, "Please select the bathymetry file of simulation, with all the modifications (e.g. '__bathymetry_after_scripts.tif') in .tif format.", wildcard="TIFF files (*.tif)|*.tif",
1199
+ style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as dlg:
1200
+ if dlg.ShowModal() != wx.ID_OK:
1201
+ return
1202
+ self.gpu_bathy = dlg.GetPath()
1203
+
1204
+ with wx.FileDialog(self, "Please select the DEM file in .tif format (without modifications, MNTmodifs_ will be used afterwards).", wildcard="TIFF files (*.tif)|*.tif",
1205
+ style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as dlg:
1206
+ result = dlg.ShowModal()
1207
+ if result != wx.ID_OK:
1208
+ return
1209
+
1210
+ path_DEM_base = dlg.GetPath()
1211
+ logging.info(_("DEM file selected."))
1212
+
1213
+ #DEM and masked DEM creation
1214
+ path = self._manager.IN_CH_DEM_SC
1215
+ names_inCHVUL_MNTmodifs = [f for f in os.listdir(path) if os.path.isfile(os.path.join(path, f)) and f.startswith("MNTmodifs_")]
1216
+ #path_MNT_computed is the path to the DEM with the MNTmodifs if exist, or the given true DEM if not
1217
+ path_MNT_computed = Path(path_DEM_base)
1218
+ if len(names_inCHVUL_MNTmodifs) !=0:
1219
+ path_MNT_computed = Path(self._manager.IN_CH_DEM_MNT_tif.with_suffix('.tif'))
1220
+ dialog = wx.MessageDialog(None, f"Please modify the 'MNTmodifs_' files in INPUT\CHANGE_VULNE\... as in the hydraulic scenario you want to study. They are: {names_inCHVUL_MNTmodifs}", "Confirmation", wx.YES_NO | wx.ICON_QUESTION)
1221
+ dialog.SetYesNoLabels("Done, continue", "Not done, stop")
1222
+ response = dialog.ShowModal()
1223
+
1224
+ if response == wx.ID_NO:
1225
+ logging.info(_("No modifications done in MNTmodifs_ files, process stopped."))
1226
+ return
1227
+
1228
+ if os.path.exists(self._manager.IN_CH_DEM_SC):
1229
+ existence=False
1230
+ existence, fail = self._func.create_vrtIfExists(Path(path_DEM_base), Path(self._manager.IN_CH_DEM_SC), Path(self._manager.IN_CH_DEM_MNT_VRT), name="MNTmodifs_")
1231
+ if existence:
1232
+ self._manager.translate_vrt2tif(self._manager.IN_CH_DEM_MNT_VRT, self._manager.IN_CH_DEM_MNT_tif)
1233
+ logging.info(_(f"Scenarios have been applied to DEM see {self._manager.IN_CH_DEM_MNT_tif}.tif."))
1234
+ WA_mask = WolfArray(self._manager.IN_CH_DEM_MNT_tif.with_suffix('.tif'))
1235
+ WA_mask.write_all(Path(self._manager.IN_SA_DEM / "MNT_loaded.bin"))
1236
+
1237
+ else :
1238
+ logging.info(_(f"No MNTmodifs_ files in {self._manager.IN_CH_DEM_SC}. The given file {path_DEM_base} has not been modified"))
1239
+ WA_mask = WolfArray(path_DEM_base)
1240
+ WA_mask.write_all(Path(self._manager.IN_SA_DEM / "MNT_loaded.bin"))
1241
+ else:
1242
+ logging.error(_(f"Path {self._manager.IN_CH_DEM_SC} does not exist."))
1243
+
1244
+
1245
+ #self._manager.IN_CH_DEM_MNT_tif ou fn_mnt_cropped : ground + riverbed
1246
+ fn_wherebuildings_buffer = self._manager.IN_CH_DEM_SC/ "buffer_wherebuilding.tif"
1247
+ fn_mask = self._manager.IN_SA_DEM / "MNT_computed_with_mask.tif"
1248
+ _interpol = interpolating_raster()
1249
+ _interpol.MNT_and_mask_creation_all(self.gpu_bathy, path_MNT_computed, fn_wherebuildings_buffer, fn_mask)
1250
+ if fn_wherebuildings_buffer.exists():
1251
+ fn_wherebuildings_buffer.unlink()
1252
+ if fn_mask.exists():
1253
+ fn_mask.unlink()
1254
+ dlg = wx.MessageDialog(self,
1255
+ "DEM files created in INPUT\WATER_DEPTH\...\DEM_FILES.",
1256
+ "Success.",
1257
+ wx.OK | wx.ICON_INFORMATION)
1258
+ dlg.ShowModal()
1259
+ dlg.Destroy()
1260
+ return
1261
+
1262
+ def check_and_convert_rasters(self, manager, prefix, type_file, numpy_type, nodata_value, message_supp=None):
1263
+ logging.info(_(f"Checking the scenarios for {prefix}."))
1264
+
1265
+ #tif_paths = self._manager.get_modifiedrasters(name=prefix)
1266
+ tif_paths = manager.get_modifiedrasters(name=prefix)
1267
+ good, bad, bad_paths = [], [], []
1268
+
1269
+ for f in tif_paths:
1270
+ ds = gdal.Open(f)
1271
+ if ds:
1272
+ file_type = gdal.GetDataTypeName(ds.GetRasterBand(1).DataType)
1273
+ ds = None
1274
+ if file_type == type_file:
1275
+ good.append(f.stem)
1276
+ else:
1277
+ suffix_to_add = f"_{file_type}"
1278
+ new_name = f.parent / f"{f.stem}{suffix_to_add}{f.suffix}"
1279
+ if not f.stem.endswith(suffix_to_add):
1280
+ f.rename(new_name)
1281
+ else:
1282
+ new_name = f
1283
+ bad.append(new_name.stem)
1284
+ bad_paths.append(new_name)
1285
+
1286
+ if bad:
1287
+ message_intro = (
1288
+ f"Detected {prefix} scenario files:\n"
1289
+ f"{', '.join([f.stem for f in tif_paths])}\n\n"
1290
+ f"However, wrong type in file(s): {', '.join(bad)}. "
1291
+ f"Its/Their type has been added to their name (expected {type_file}).\n\n"
1292
+ f"Do you want to try to convert them to {type_file} automatically?"
1293
+ )
1294
+
1295
+ dlg = wx.MessageDialog(None, message_intro, "Warning", wx.YES_NO | wx.ICON_WARNING)
1296
+ result = dlg.ShowModal()
1297
+ dlg.Destroy()
1298
+
1299
+ if result == wx.ID_YES:
1300
+ for path in bad_paths:
1301
+ with gdal.Open(path, gdal.GA_ReadOnly) as ds:
1302
+ band = ds.GetRasterBand(1)
1303
+ arr = band.ReadAsArray()
1304
+ nodata = band.GetNoDataValue()
1305
+ geotransform = ds.GetGeoTransform()
1306
+ projection = ds.GetProjection()
1307
+
1308
+ # SPÉCIAL POUR LE CAS int8
1309
+ if type_file == "Byte":
1310
+ mask_valid = np.ones_like(arr, dtype=bool)
1311
+ if nodata is not None:
1312
+ mask_valid = arr != nodata
1313
+
1314
+ valid_values = arr[mask_valid]
1315
+ if not np.all((valid_values >= 1) & (valid_values <= 5)):
1316
+ wx.MessageBox(
1317
+ f"Impossible to change the type to int8, there exist other type of data in the raster(s) !\n {message_supp}",
1318
+ "Error", wx.OK | wx.ICON_ERROR
1319
+ )
1320
+ return
1321
+
1322
+ arr_new = arr.astype(numpy_type)
1323
+ if nodata is not None:
1324
+ arr_new[arr == nodata] = nodata_value
1325
+ else:
1326
+ arr_new[arr_new < 1] = nodata_value #if nodata doesnt exist
1327
+
1328
+ dirname, filename = os.path.split(path)
1329
+ new_filename = filename.replace(prefix, f"{prefix}AUTO_").replace(".tif", f"_to_{type_file}.tif")
1330
+ old_filename = filename.replace(prefix, f"OLD_{prefix}")
1331
+ new_path = os.path.join(dirname, new_filename)
1332
+ old_path = os.path.join(dirname, old_filename)
1333
+
1334
+ os.rename(path, old_path)
1335
+ driver = gdal.GetDriverByName("GTiff")
1336
+ out_ds = driver.Create(new_path, arr.shape[1], arr.shape[0], 1,
1337
+ gdal.GetDataTypeByName(type_file))
1338
+ out_ds.SetGeoTransform(geotransform)
1339
+ out_ds.SetProjection(projection)
1340
+ out_band = out_ds.GetRasterBand(1)
1341
+ out_band.WriteArray(arr_new)
1342
+ out_band.SetNoDataValue(nodata_value)
1343
+ out_band.FlushCache()
1344
+ out_ds = None
1345
+
1346
+ wx.MessageBox(
1347
+ f"Files converted to {type_file}. Previous ones renamed with 'OLD_...'.",
1348
+ "Information", wx.OK | wx.ICON_INFORMATION
1349
+ )
1350
+ else:
1351
+ wx.MessageBox(
1352
+ f"Detected {prefix} scenario files:\n{', '.join([f.stem for f in tif_paths])}\n Everything is fine.",
1353
+ "Information", wx.OK | wx.ICON_INFORMATION
1354
+ )
1355
+
1356
+ def OnCheckMNTmodifs(self,e):
1357
+ """Checks if scenarios MNTmodifs_ exist in CHANGE_VULNE and test the type (float32)"""
1358
+ self.check_and_convert_rasters(self._manager, "MNTmodifs_", "Float32", np.float32, 99999.)
1359
+ return
1360
+
1361
+ def OnInterpolation(self,e):
1362
+ """Interpolates the last extracted time steps present in LAST_STEP_EXTRACTED using the fast marching
1363
+ interpolation routine, by creating a batch file
1364
+ while performing multiple checks on the required input files."""
1365
+ _interpol = interpolating_raster()
1366
+
1367
+ if self.file_paths is None: # Si on n’a pas chargé de simulations : on recrée la structure et ce qu'on aurait eu, mais avec tous les fichiers présents
1368
+ iftest = True
1369
+ checked_paths = []
1370
+
1371
+ else :
1372
+ checked_names = self._check_listbox.GetCheckedStrings()
1373
+ if not checked_names:
1374
+ logging.info(_("No items selected. Adding all paths."))
1375
+ checked_paths = list(self.file_paths.values())
1376
+ iftest = False
1377
+ else:
1378
+ logging.info(_("Adding only the selected simulations."))
1379
+ checked_paths = [self.file_paths[name] for name in checked_names]
1380
+ iftest = False
1381
+
1382
+ if len(self.file_paths) == 0 :
1383
+ return logging.info(_("No files in EXTRACTED_LAST_STEP_WD. Please provide some or use the 'Load gpu simulation' button."))
1384
+
1385
+ #interp_bool, renamed_files = _interpol.batch_creation_and_interpolation_fotran_holes(self._manager, checked_paths, iftest)
1386
+ interp_bool, renamed_files = _interpol.batch_creation_and_interpolation_python_eikonal(self._manager, checked_paths, iftest, True)
1387
+
1388
+ if interp_bool:
1389
+ logging.info(_("Filling completed."))
1390
+ with wx.MessageDialog(self, f"Filling completed. Created files : {renamed_files}",
1391
+ "Redirecting", wx.OK | wx.ICON_INFORMATION) as dlg:
1392
+ dlg.ShowModal()
1393
+ update_info_header(self.input_dx,self.input_nbxy,self.input_O,self._manager.IN_SA_INTERP)
1394
+ self._check_listbox_Ti.Set(self._manager.get_list_interp())
1395
+ else :
1396
+ logging.error(_("Something went wrong for the interpolation."))
1397
+
1398
+ def OnToggleAdmin(self, e):
1399
+ if self.toggle_state_Admin:
1400
+ self.toggle_state_Admin = False
1401
+ self._but_toggle_admin.SetBackgroundColour(wx.NullColour)
1402
+ #self._but_setcomp.Hide()
1403
+ #self._but_readresults.Hide()
1404
+ return
1405
+
1406
+ dlg = wx.TextEntryDialog(self, "Enter developer password:", "Authentication")
1407
+ if dlg.ShowModal() == wx.ID_OK:
1408
+ password = dlg.GetValue()
1409
+ if password == "LetMeIn#":
1410
+ self.toggle_state_Admin = True
1411
+ self._but_toggle_admin.SetBackgroundColour(wx.Colour(175, 175, 175))
1412
+ #self._but_setcomp.Show()
1413
+ #self._but_readresults.Show()
1414
+
1415
+ self.mapviewer.Refresh()
1416
+ else:
1417
+ wx.MessageBox("Wrong password.", "Error")
1418
+ self.toggle_state_Admin = False
1419
+ self._but_toggle_admin.SetBackgroundColour(wx.NullColour)
1420
+ dlg.Destroy()
1421
+
1422
+ def OnInput(self, e):
1423
+ multiple = 0
1424
+ dlg1 = wx.SingleChoiceDialog(
1425
+ self,
1426
+ message="What hazard variable do you want to read in the GPU simulations?",
1427
+ caption="Hazard Variable Choice",
1428
+ choices=["only wd", "both wd and v"]
1429
+ )
1430
+
1431
+ if dlg1.ShowModal() == wx.ID_OK:
1432
+ selection1 = dlg1.GetStringSelection()
1433
+ if selection1 == "only wd" :
1434
+ hazard_choice = "wd"
1435
+ else :
1436
+ hazard_choice = "both"
1437
+ else:
1438
+ return
1439
+
1440
+ dlg1.Destroy()
1441
+
1442
+ if hazard_choice == "both":
1443
+ multiple_str = wx.GetTextFromUser(
1444
+ message="What buffer size (as the factor of the resolution dx) do you want to use\n (to capture the maximum velocity)? Enter a number between 1 and 10:",
1445
+ caption="Buffer size",
1446
+ parent=self
1447
+ )
1448
+ try:
1449
+ multiple = int(multiple_str)
1450
+ if not (1 <= multiple <= 10):
1451
+ wx.MessageBox("Value must be between 1 and 10.", "Error", wx.ICON_ERROR)
1452
+ return
1453
+ except ValueError:
1454
+ wx.MessageBox("Invalid number.", "Error", wx.ICON_ERROR)
1455
+ return
1456
+
1457
+ dlg2 = wx.SingleChoiceDialog(
1458
+ self,
1459
+ message="What operator for wd?",
1460
+ caption="Operator Choice",
1461
+ choices=["mean", "max", "median", "percentil"]
1462
+ )
1463
+ percentil=None
1464
+ if dlg2.ShowModal() == wx.ID_OK:
1465
+ operator_choice = dlg2.GetStringSelection()
1466
+ if operator_choice == "percentil":
1467
+ dlg_percentil = wx.TextEntryDialog(
1468
+ self,
1469
+ message="Enter the desired percentile (0-100):",
1470
+ caption="Percentile Input"
1471
+ )
1472
+ if dlg_percentil.ShowModal() == wx.ID_OK:
1473
+ try:
1474
+ percentil = float(dlg_percentil.GetValue())
1475
+ if not (0 <= percentil <= 100):
1476
+ wx.MessageBox("Value must be between 0 and 100", "Invalid Input", wx.ICON_ERROR)
1477
+ return
1478
+ except ValueError:
1479
+ wx.MessageBox("Please enter a valid number", "Invalid Input", wx.ICON_ERROR)
1480
+ return
1481
+ else:
1482
+ return
1483
+ else:
1484
+ return
1485
+
1486
+ dlg2.Destroy()
1487
+
1488
+ Ti_list = [self._check_listbox_Ti.GetString(i) for i in range(self._check_listbox_Ti.GetCount()) if self._check_listbox_Ti.IsChecked(i)]
1489
+ if Ti_list ==[]:
1490
+ logging.error(_("No scenario selected in the checkbox, all the simulations are selected by default."))
1491
+ Ti_list = list(self._check_listbox_Ti.GetStrings())
1492
+ logging.info(_(f"Ti_list = {Ti_list}"))
1493
+
1494
+ logging.info(_(f"Ti_list = {Ti_list}"))
1495
+ resolution = self.input_dx.GetLabel()
1496
+ values = resolution.strip("()").split(",")
1497
+ dx = float(values[0])
1498
+
1499
+ save_where_output = self._func.pre_processing_auto(Ti_list, self._manager.main_dir, self._manager._study_area, self._manager.scenario, multiple, dx, percentil, operator_wd = operator_choice, hazard = hazard_choice)
1500
+
1501
+ if len(save_where_output) == 0 :
1502
+ with wx.MessageDialog(self,
1503
+ f"Something went wrong.",
1504
+ "Error in preprocessing",
1505
+ style=wx.OK| wx.ICON_ERROR) as dlg:
1506
+ dlg.ShowModal()
1507
+ else :
1508
+ with wx.MessageDialog(self,
1509
+ f"Input tables successfully created in {save_where_output}.",
1510
+ "Preprocessing finished.",
1511
+ style=wx.OK | wx.ICON_INFORMATION) as dlg:
1512
+ dlg.ShowModal()
1513
+
1514
+
1515
+ def OnDefault_TEMP(self, e):
1516
+ """ Impute default values to inputs and run INBE on each Ti"""
1517
+ if self._manager is None:
1518
+ return
1519
+
1520
+ Ti_list = [self._check_listbox_Ti.GetString(i) for i in range(self._check_listbox_Ti.GetCount()) if self._check_listbox_Ti.IsChecked(i)]
1521
+ if Ti_list ==[]:
1522
+ logging.error(_("No scenario selected in the checkbox, all the simulations are selected by default."))
1523
+ Ti_list = list(self._check_listbox_Ti.GetStrings())
1524
+ logging.info(_(f"Ti_list = {Ti_list}"))
1525
+
1526
+ inflation = float(self._inflation.GetValue())
1527
+ type_computation = "from_wolfsimu"
1528
+ self.df_results_Ti, save_output_TEMP, save_output_defaultINPUT = self._func.computation_dfesults_forfolder(self._manager, type_computation, Ti_list, inflation)
1529
+
1530
+ if len(save_output_defaultINPUT) == 0 :
1531
+ with wx.MessageDialog(self,
1532
+ f"Something went wrong. Nothing created.",
1533
+ "Error in the computations.",
1534
+ style=wx.OK| wx.ICON_ERROR) as dlg:
1535
+ dlg.ShowModal()
1536
+ else :
1537
+ paths_in = "\n".join(str(p) for p in save_output_defaultINPUT)
1538
+ paths_temp = "\n".join(str(p) for p in save_output_TEMP)
1539
+
1540
+ dlg = wx.MessageDialog(
1541
+ self,
1542
+ "Do you want to spread the information of damage on a raster?",
1543
+ "Damage raster",
1544
+ wx.YES_NO | wx.ICON_QUESTION
1545
+ )
1546
+
1547
+ ifraster = dlg.ShowModal()
1548
+ dlg.Destroy()
1549
+
1550
+ if ifraster == wx.ID_YES:
1551
+ self._func.raster_auto(self._manager, "individual_damage", Ti_list)
1552
+
1553
+ with wx.MessageDialog(self,
1554
+ f"Default values imputed to the input in:\n{paths_in}\n\nAnd individual damage (inflation {inflation}) computed in:\n{paths_temp}.",
1555
+ "Preprocessing finished.",
1556
+ style=wx.OK | wx.ICON_INFORMATION) as dlg:
1557
+ dlg.ShowModal()
1558
+
1559
+ def Oncombined_OUTPUT(self,e):
1560
+ """Compute the combined damage"""
1561
+
1562
+ #Option de comment combiner, majorer damage ? To do
1563
+
1564
+ ponds = self._manager.get_ponderations()
1565
+ logging.info(_("Ponderation coeficients (computed automatically based on available set of damage files):"))
1566
+ logging.info(ponds)
1567
+ if self._manager is None:
1568
+ return
1569
+
1570
+ dlg2 = wx.SingleChoiceDialog(
1571
+ self,
1572
+ message="What kind of combinaison?",
1573
+ caption="Combinaison choice",
1574
+ choices=["Weighted sum"]#, "Squared (to code)", "..."]
1575
+ )
1576
+
1577
+ if dlg2.ShowModal() == wx.ID_OK:
1578
+ operator_choice = dlg2.GetStringSelection()
1579
+ else:
1580
+ return
1581
+
1582
+ dlg2.Destroy()
1583
+
1584
+ if operator_choice != "Weighted sum":
1585
+ with wx.MessageDialog(self,
1586
+ f"Need to be coded :)",
1587
+ "Be patient.",
1588
+ style=wx.OK| wx.ICON_ERROR) as dlg:
1589
+ dlg.ShowModal()
1590
+ return
1591
+ #if df_results_Ti == None :
1592
+ # with wx.MessageDialog(self,
1593
+ # f"Please use the previous button, or code something to read the indiv damages...",
1594
+ # "Error in the computations.",
1595
+ # style=wx.OK| wx.ICON_ERROR) as dlg:
1596
+ # dlg.ShowModal()
1597
+ # return
1598
+
1599
+ unused, output_path = self._func.computation_combined_damage(ponds, self._manager)
1600
+
1601
+ dlg = wx.MessageDialog(
1602
+ self,
1603
+ "Do you want to spread the information of combined damage on a raster?",
1604
+ "Damage raster",
1605
+ wx.YES_NO | wx.ICON_QUESTION
1606
+ )
1607
+
1608
+ ifraster = dlg.ShowModal()
1609
+ dlg.Destroy()
1610
+
1611
+ if ifraster == wx.ID_YES:
1612
+ self._func.raster_auto(self._manager, "combined")
1613
+
1614
+
1615
+ with wx.MessageDialog(self,
1616
+ f"Combined damage computed, and written in {output_path}.",
1617
+ "Computations finished.",
1618
+ style=wx.OK | wx.ICON_INFORMATION) as dlg:
1619
+ dlg.ShowModal()
1620
+
1621
+ def OnReadResults(self, e):
1622
+ sort_percentil = float(self._tri.GetValue())
1623
+ cols = ["code", "d_cleaning", "d_removal", "d_non_stru", "d_structural", "d_finishing", "d_systems", "d_total"]
1624
+
1625
+ if not self._manager.OUT_COMB.exists():
1626
+ logging.error(_(f"No file {self._manager.OUT_COMB}. Please, compute it first."))
1627
+ wx.MessageBox(_(f"No file {self._manager.OUT_COMB}. Please, compute it first.", "Missing file.", wx.ICON_ERROR))
1628
+ return
1629
+ df_results = pd.read_excel(self._manager.OUT_COMB, usecols=cols)
1630
+
1631
+
1632
+ sums = df_results.sum(numeric_only=True)
1633
+
1634
+
1635
+ #summary = '\n'.join([f"{col} : {val:,.0f} €" for col, val in sums.items()])
1636
+ summary = '\n'.join([f"{col[2:].capitalize()} : {val:,.0f} €" for col, val in sums.items()])
1637
+ with wx.MessageDialog(self,
1638
+ f"Sum of damage per categories :\n\n{summary}",
1639
+ "Quick analysis.",
1640
+ style=wx.OK | wx.ICON_INFORMATION) as dlg:
1641
+ dlg.ShowModal()
1642
+
1643
+
1644
+ dlg = wx.MessageDialog(
1645
+ self,
1646
+ "Do you want to plot the damage histogram for every residential building ?",
1647
+ "Histogram creation.",
1648
+ wx.YES_NO | wx.ICON_QUESTION
1649
+ )
1650
+ ifhisto = dlg.ShowModal()
1651
+ dlg.Destroy()
1652
+
1653
+ if ifhisto == wx.ID_YES:
1654
+ self._func.plot_damage(df_results, sorted_cond = True)
1655
+
1656
+ return
1657
+
1658
+ #def OnSetComp0(self, e):
1659
+ # """Analyze two or more scenarios with a baseline"""
1660
+ # with wx.MessageDialog(
1661
+ # self,
1662
+ # "After clicking OK, please select at least two damage scenarios (individual or combined) to compare (of a same study area).\n"
1663
+ # "The first one selected will be used as the reference.\n\n"
1664
+ # "⚠ No tests coded — the user is responsible for the comparison.\n\n"
1665
+ # "The file selection dialog will reopen until you click Cancel, press Escape, or close the window.",
1666
+ # "Instructions.",
1667
+ # style=wx.OK | wx.ICON_INFORMATION
1668
+ # ) as dlg:
1669
+ # dlg.ShowModal()
1670
+
1671
+ # paths = []
1672
+
1673
+ # if self._manager is not None and self._manager.main_dir is not None:
1674
+ # defaultDir = self._manager.main_dir
1675
+ # else:
1676
+ # defaultDir = os.getcwd()
1677
+
1678
+ # while True:
1679
+ # with wx.FileDialog(
1680
+ # self,
1681
+ # "Select a damage scenario file",
1682
+ # defaultDir=defaultDir,
1683
+ # wildcard="Excel files (*.xlsx)|*.xlsx",
1684
+ # style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST
1685
+ # ) as file_dlg:
1686
+
1687
+ # if file_dlg.ShowModal() == wx.ID_CANCEL:
1688
+ # break
1689
+
1690
+ # path = file_dlg.GetPath()
1691
+
1692
+ # if path:
1693
+ # paths.append(path)
1694
+ # defaultDir = os.path.dirname(path)
1695
+ #
1696
+ # with wx.MessageDialog(
1697
+ # self,
1698
+ # f"{paths}",
1699
+ # "Scenarios selected:",
1700
+ # style=wx.OK | wx.ICON_INFORMATION
1701
+ # ) as dlg:
1702
+ # dlg.ShowModal()
1703
+
1704
+ # self._func.histo_total_from_list(paths, float(self._tri.GetValue()))
1705
+ # return
1706
+
1707
+ def OnSetComp0(self, e):
1708
+ """Analyze two or more scenarios with a baseline"""
1709
+ #scenarios = [self._listbox_CompScen.GetString(i) for i in self._listbox_CompScen.GetCheckedItems()]
1710
+ checked_idx = self._listbox_CompScen.GetCheckedItems()
1711
+ scenarios = [self.items[i][1] for i in checked_idx]
1712
+ study_areas = [self.items[i][0] for i in checked_idx]
1713
+
1714
+ if len(scenarios) < 2:
1715
+ wx.MessageBox("Please select at least 2 scenarios.", "Not enough scenarios to compare.", wx.ICON_ERROR)
1716
+ return
1717
+
1718
+ dlg1 = wx.SingleChoiceDialog(
1719
+ self,
1720
+ message="Which of the selected scenarios is the reference for comparison ?",
1721
+ caption="Reference scenario",
1722
+ choices=scenarios
1723
+ )
1724
+
1725
+ if dlg1.ShowModal() == wx.ID_OK:
1726
+ reference = dlg1.GetStringSelection()
1727
+ else:
1728
+ return
1729
+ dlg1.Destroy()
1730
+
1731
+ #Reference = the FIRST
1732
+ idx_ref = scenarios.index(reference)
1733
+ scenarios = [scenarios[idx_ref]] + [sc for i, sc in enumerate(scenarios) if i != idx_ref]
1734
+ study_areas = [study_areas[idx_ref]] + [sa for i, sa in enumerate(study_areas) if i != idx_ref]
1735
+
1736
+ instances = [INBE_Manager(main_dir=self.maindir, Study_area=sa, scenario=sc) for sc, sa in zip(scenarios, study_areas)] #zip life
1737
+
1738
+ dlg2 = wx.SingleChoiceDialog(
1739
+ self,
1740
+ message=f"What do you want to compare (selected reference = {reference}) ?",
1741
+ caption="Comparison choice",
1742
+ choices=["Individual damage (Ti)", "Combined damage"]
1743
+ )
1744
+
1745
+ if dlg2.ShowModal() == wx.ID_OK:
1746
+ choice = dlg2.GetStringSelection()
1747
+ else:
1748
+ return
1749
+ dlg2.Destroy()
1750
+
1751
+ if choice == "Individual damage (Ti)":
1752
+ dlg3 = wx.SingleChoiceDialog(
1753
+ self,
1754
+ message="Which return period do you want to compare ?",
1755
+ caption="Comparison Choice",
1756
+ choices=instances[0].get_list_individual_T(instances[0])
1757
+ )
1758
+
1759
+ if dlg3.ShowModal() == wx.ID_OK:
1760
+ choice_T = dlg3.GetStringSelection()
1761
+ else:
1762
+ return
1763
+ dlg3.Destroy()
1764
+
1765
+ paths = [inst.OUT_SCEN_DIR / f"individual_damage_T{choice_T}.xlsx" for inst in instances]
1766
+ else:
1767
+ choice_T = None
1768
+ paths = [inst.OUT_COMB for inst in instances]
1769
+
1770
+ self._func.histo_total_from_list(paths, float(self._tri.GetValue()))
1771
+ #si len scatter_INBE_dtotal > 2 alors deux à deux avec le bon baseline [0]
1772
+
1773
+
1774
+ for instB in instances[1:]:
1775
+ self._func.scatter_INBE_dtotal(instances[0], instB, max_val=None, Ti = choice_T, quant = float(self._tri.GetValue()))
1776
+