wolfhece 2.1.23__py3-none-any.whl → 2.1.27__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/PyPalette.py CHANGED
@@ -24,6 +24,7 @@ class wolfpalette(wx.Frame,LinearSegmentedColormap):
24
24
  nb:int
25
25
  colors:np.array
26
26
  colorsflt:np.array
27
+ colorsuint8:np.array
27
28
 
28
29
  def __init__(self, parent=None, title=_('Colormap'),w=100,h=500,nseg=1024):
29
30
 
@@ -45,17 +46,32 @@ class wolfpalette(wx.Frame,LinearSegmentedColormap):
45
46
  LinearSegmentedColormap.__init__(self,'wolf',{},nseg)
46
47
  self.set_bounds()
47
48
 
49
+ @property
50
+ def colormin_uint8(self):
51
+ return self.colormin.astype(np.uint8)*255
52
+
53
+ @property
54
+ def colormax_uint8(self):
55
+ return self.colormax.astype(np.uint8)*255
56
+
48
57
  def get_colors_f32(self):
49
58
 
50
59
  colors = self.colorsflt[:,:3].astype(np.float32)
51
60
 
52
61
  return colors
62
+
63
+ def get_colors_uint8(self):
64
+
65
+ colors = self.colorsflt[:,:3].astype(np.uint8) * 255
66
+
67
+ return colors
53
68
 
54
69
  def set_bounds(self):
55
70
  self.set_under(tuple(self.colormin))
56
71
  self.set_over(tuple(self.colormax))
57
72
 
58
- def get_rgba(self,x):
73
+ def get_rgba(self, x:np.ndarray):
74
+ """Récupération de la couleur en fonction de la valeur x"""
59
75
 
60
76
  dval=self.values[-1]-self.values[0]
61
77
  if dval==0.:
@@ -63,23 +79,24 @@ class wolfpalette(wx.Frame,LinearSegmentedColormap):
63
79
  xloc = (x-self.values[0])/dval
64
80
 
65
81
  if self.interval_cst:
66
- rgba = np.ones((xloc.shape[0],xloc.shape[1],4))
82
+ rgba = np.ones((xloc.shape[0],xloc.shape[1],4), dtype=np.uint8)
67
83
 
68
84
  ij = np.where(xloc<0.)
69
- rgba[ij[0],ij[1]] = self.colormin
85
+ rgba[ij[0],ij[1]] = self.colormin_uint8
70
86
  ij = np.where(xloc>=1.)
71
- rgba[ij[0],ij[1]] = self.colormax
87
+ rgba[ij[0],ij[1]] = self.colormax_uint8
72
88
 
73
89
  for i in range(self.nb-1):
74
90
  val1 = (self.values[i]-self.values[0])/dval
75
91
  val2 = (self.values[i+1]-self.values[0])/dval
76
- c1 = self.colorsflt[i]
92
+ # c1 = self.colorsflt[i]
93
+ c1 = self.colorsuint8[i]
77
94
  ij = np.where((xloc>=val1) & (xloc<val2))
78
95
  rgba[ij[0],ij[1]] = c1
79
96
 
80
97
  return rgba
81
98
  else:
82
- return self(xloc)
99
+ return self(xloc, bytes=True)
83
100
 
84
101
  def export_palette_matplotlib(self,name):
85
102
  cmaps = OrderedDict()
@@ -110,7 +127,7 @@ class wolfpalette(wx.Frame,LinearSegmentedColormap):
110
127
 
111
128
  return self.nb,self.values,self._segmentdata,self.colorsflt
112
129
 
113
- def distribute_values(self, minval=-99999, maxval=-99999, step=0, wx_permitted=True):
130
+ def distribute_values(self, minval:float=-99999, maxval:float=-99999, step=0, wx_permitted=True):
114
131
  """ Distribution des valeurs de la palette
115
132
 
116
133
  :param minval: valeur minimale
@@ -460,8 +477,7 @@ class wolfpalette(wx.Frame,LinearSegmentedColormap):
460
477
  self.colors[curcol,1] = colors[curcol,1]
461
478
  self.colors[curcol,2] = colors[curcol,2]
462
479
  self.colors[curcol,3] = colors[curcol,3]
463
-
464
-
480
+
465
481
  self.fill_segmentdata()
466
482
 
467
483
  def defaultgray(self):
@@ -469,7 +485,6 @@ class wolfpalette(wx.Frame,LinearSegmentedColormap):
469
485
  self.nb=2
470
486
  self.values = np.asarray([0.,1.])
471
487
  self.colors = np.asarray([[0,0,0,255],[255,255,255,255]],dtype=np.int32)
472
- self.colorsflt = np.asarray([[0.,0.,0.,1.],[1.,1.,1.,1.]],dtype=np.float64)
473
488
 
474
489
  self.fill_segmentdata()
475
490
 
@@ -477,6 +492,7 @@ class wolfpalette(wx.Frame,LinearSegmentedColormap):
477
492
  """Mise à jour de la palatte de couleurs"""
478
493
 
479
494
  self.colorsflt = self.colors.astype(float)/255.
495
+ self.colorsuint8 = self.colors.astype(np.uint8)
480
496
 
481
497
  dval=self.values[-1]-self.values[0]
482
498
 
@@ -0,0 +1,106 @@
1
+ from .func import clip_layer, data_modification, vector_to_raster, compute_vulnerability, match_vulnerability2sim, compute_acceptability, shp_to_raster, Accept_Manager
2
+ import geopandas as gpd
3
+ import multiprocessing
4
+ from functools import partial
5
+ import os
6
+ from pathlib import Path
7
+
8
+ def parallel_gpd_clip(layer:list[str],
9
+ file_path:str,
10
+ Study_Area:str,
11
+ output_dir:str,
12
+ number_procs:int = 1):
13
+ """
14
+ Clip the layers to the study area.
15
+
16
+ Process the layers in parallel.
17
+
18
+ FIXME: The GPKG driver is it totally parallel compliant?
19
+
20
+ :param layer: List of layers to clip
21
+ :param file_path: The path to the file
22
+ :param Study_Area: The study area
23
+ :param output_dir: The output directory where the clipped layers are stored
24
+ :param number_procs: The number of processors to use
25
+
26
+ """
27
+ file_path = str(file_path)
28
+ Study_Area = str(Study_Area)
29
+ output_dir = str(output_dir)
30
+
31
+ if number_procs == 1:
32
+
33
+ for curlayer in layer:
34
+ clip_layer(curlayer, file_path, Study_Area, output_dir)
35
+
36
+ else:
37
+ pool = multiprocessing.Pool(processes=number_procs)
38
+ prod_x=partial(clip_layer,
39
+ file_path=file_path,
40
+ Study_Area=Study_Area,
41
+ output_dir=output_dir)
42
+ result_list = pool.map(prod_x, layer)
43
+
44
+ def parallel_v2r(manager:Accept_Manager,
45
+ attribute:str,
46
+ pixel:float,
47
+ number_procs:int = 1):
48
+ """
49
+ Convert the vector layers to raster.
50
+
51
+ Process the layers in parallel.
52
+
53
+ :remark: It is permitted to execute this function in multiprocessing because we write separate files.
54
+
55
+ :param manager: The Accept_Manager object
56
+ :param attribute: The attribute to convert to raster
57
+ :param pixel: The pixel size of the raster
58
+ :param number_procs: The number of processors to use
59
+
60
+ """
61
+
62
+ attribute = str(attribute)
63
+ layers = manager.get_layers_in_codevulne()
64
+
65
+ if number_procs == 1:
66
+ for curlayer in layers:
67
+ vector_to_raster(curlayer, manager, attribute, pixel)
68
+ else:
69
+ pool = multiprocessing.Pool(processes=number_procs)
70
+ prod_x=partial(vector_to_raster,
71
+ manager=manager,
72
+ attribute=attribute,
73
+ pixel_size=pixel)
74
+
75
+ result_list = pool.map(prod_x, layers)
76
+
77
+ def parallel_datamod(manager:Accept_Manager,
78
+ picc:gpd.GeoDataFrame,
79
+ capa:gpd.GeoDataFrame,
80
+ number_procs:int = 1):
81
+ """
82
+ Apply the data modification to the layers.
83
+
84
+ Process the layers in parallel.
85
+
86
+ :remark: It is permitted to execute this function in multiprocessing because we write separate files.
87
+
88
+ :param manager: The Accept_Manager object
89
+ :param number_procs: The number of processors to use
90
+
91
+ """
92
+
93
+ layers = manager.get_layers_in_clipgdb()
94
+
95
+ if number_procs == 1:
96
+ for curlayer in layers:
97
+ data_modification(curlayer, manager, picc, capa)
98
+ else:
99
+ pool = multiprocessing.Pool(processes=number_procs)
100
+ prod_x=partial(data_modification,
101
+ manager=manager,
102
+ picc=picc,
103
+ capa=capa)
104
+
105
+ result_list = pool.map(prod_x, layers)
106
+
@@ -0,0 +1,3 @@
1
+ # from .acceptability import base_data_creation, Vulnerability, acceptability
2
+ #from .Parallels import parallel_gpd_clip, parallel_v2r
3
+ #from .func gpd_clip, data_modification, vector_to_raster, Comp_Vulnerability, match_vuln_modrec, VulMod, shp_to_raster
@@ -0,0 +1,477 @@
1
+ from .Parallels import parallel_gpd_clip, parallel_v2r, parallel_datamod
2
+ from .func import data_modification, compute_vulnerability, compute_vulnerability4scenario, match_vulnerability2sim, compute_acceptability, shp_to_raster, Accept_Manager, cleaning_directory, EXTENT, Vulnerability_csv
3
+
4
+ import pandas as pd
5
+ import os
6
+ from osgeo import gdal
7
+ import fiona
8
+ import glob
9
+ import numpy as np
10
+ import geopandas as gpd
11
+ from pathlib import Path
12
+ import logging
13
+ from tqdm import tqdm
14
+ from enum import Enum
15
+ from pyogrio import read_dataframe
16
+
17
+ class steps_base_data_creation(Enum):
18
+ """
19
+ Enum for the steps in the base data creation
20
+ """
21
+ CLIP_GDB = 1
22
+ CLIP_CADASTER = 2
23
+ CLIP_PICC = 3
24
+ POINTS2POLYS = 4
25
+ RASTERIZE_IGN = 5
26
+ PREPROCESS_VULNCODE = 6
27
+ DATABASE_TO_RASTER = 7
28
+
29
+ class steps_vulnerability(Enum):
30
+ """
31
+ Enum for the steps in the vulnerability computation
32
+ """
33
+ CREATE_RASTERS = 1
34
+ APPLY_MODIFS = 2
35
+ MATCH_SIMUL = 3
36
+
37
+ def Base_data_creation(main_dir:str = 'Data',
38
+ Original_gdb:str = 'GT_Resilence_dataRisques202010.gdb',
39
+ Study_area:str = 'Bassin_Vesdre.shp',
40
+ CaPa_Walloon:str = 'Cadastre_Walloon.gpkg',
41
+ PICC_Walloon:str = 'PICC_vDIFF.gdb',
42
+ CE_IGN_top10v:str = 'CE_IGN_TOP10V/CE_IGN_TOP10V.shp',
43
+ resolution:float = 1.,
44
+ number_procs:int = 8,
45
+ steps:list[int] | list[steps_base_data_creation] = [1,2,3,4,5,6,7]):
46
+ """
47
+ Create the databse.
48
+
49
+ In this step, the following operations are performed:
50
+ - Clip the original gdb file to the study area
51
+ - Clip the Cadastre Walloon file to the study area
52
+ - Clip the PICC Walloon file to the study area
53
+ - Clip and Rasterize the IGN top10v file
54
+ - Create the study area database with the vulnerability levels
55
+
56
+
57
+ :param main_dir: The main data directory
58
+ :param Original_gdb: The original gdb file from SPW - GT Resilience
59
+ :param Study_area: The study area shapefile -- Data will be clipped to this area
60
+ :param CaPa_Walloon: The Cadastre Walloon file -- Shapfeile from SPW
61
+ :param PICC_Walloon: The PICC Walloon file -- Shapefile from SPW
62
+ :param CE_IGN_top10v: The CE "Cours d'eau" IGN top10v file -- Shapefile from IGN with river layer
63
+ :param resolution: The output resolution of the raster files
64
+ :param number_procs: The number of processors to use for parallel processing
65
+
66
+ """
67
+ LAYER_CABU = "CaBu"
68
+ LAYER_CAPA = "CaPa"
69
+ LAYER_BATIEMPRISE = "CONSTR_BATIEMPRISE"
70
+
71
+ manager = Accept_Manager(main_dir,
72
+ Study_area,
73
+ Original_gdb=Original_gdb,
74
+ CaPa_Walloon=CaPa_Walloon,
75
+ PICC_Walloon=PICC_Walloon,
76
+ CE_IGN_top10v=CE_IGN_top10v)
77
+
78
+ if not manager.check_before_database_creation():
79
+ logging.error("The necessary files are missing - Verify logs for more information")
80
+ return
81
+
82
+ manager.change_dir()
83
+ done = []
84
+
85
+ if 1 in steps or 6 in steps or steps_base_data_creation.PREPROCESS_VULNCODE in steps or steps_base_data_creation.CLIP_GDB in steps:
86
+ # Load the vulnerability CSV to get the layers
87
+ vulnerability_csv = Vulnerability_csv(manager.VULNERABILITY_CSV)
88
+
89
+ if 1 in steps or steps_base_data_creation.CLIP_GDB in steps:
90
+ # Clean the directory to avoid any conflict
91
+ # GPKG driver does not overwrite the existing file but adds new layers
92
+ cleaning_directory(manager.TMP_CLIPGDB)
93
+
94
+ # ********************************************************************************************************************
95
+ # Step 1, Clip Original GDB
96
+
97
+ # Clip the GDB file and store it in dirsnames.SA_DATABASE
98
+ parallel_gpd_clip(vulnerability_csv.get_layers(), manager.ORIGINAL_GDB, manager.SA, manager.TMP_CLIPGDB, number_procs)
99
+
100
+ done.append(steps_base_data_creation.CLIP_GDB)
101
+
102
+ if 2 in steps or steps_base_data_creation.CLIP_CADASTER in steps:
103
+ # ********************************************************************************************************************
104
+ # Step 2, Clip Cadaster data
105
+ cleaning_directory(manager.TMP_CADASTER)
106
+
107
+ # Only 2 layers are present in the Cadastre Walloon file
108
+ # Clip the Cadastre Walloon file and store it in dirsnames.SA_CAPA
109
+ parallel_gpd_clip([LAYER_CABU, LAYER_CAPA], manager.CAPA_WALLOON, manager.SA, manager.TMP_CADASTER, min(2, number_procs))
110
+
111
+ done.append(steps_base_data_creation.CLIP_CADASTER)
112
+
113
+ if 3 in steps or steps_base_data_creation.CLIP_PICC in steps:
114
+ # ********************************************************************************************************************
115
+ # Step 3, Clip PICC data
116
+ cleaning_directory(manager.TMP_PICC)
117
+
118
+ # ONly 1 layer is needed from the PICC Walloon file
119
+ # Clip the PICC Walloon file and store it in dirsnames.SA_PICC
120
+ parallel_gpd_clip([LAYER_BATIEMPRISE], manager.PICC_WALLOON, manager.SA, manager.TMP_PICC, min(1, number_procs))
121
+
122
+ done.append(steps_base_data_creation.CLIP_PICC)
123
+
124
+ if 4 in steps or steps_base_data_creation.POINTS2POLYS in steps:
125
+ # ********************************************************************************************************************
126
+ # Step 4, create database based on changes in report
127
+
128
+ cleaning_directory(manager.TMP_WMODIF)
129
+
130
+ # PreLoad Picc and CaPa from clipped files
131
+ Picc:gpd.GeoDataFrame = read_dataframe(str(manager.TMP_PICC / (LAYER_BATIEMPRISE+EXTENT)), layer=LAYER_BATIEMPRISE)
132
+ CaPa:gpd.GeoDataFrame = read_dataframe(str(manager.TMP_CADASTER / (LAYER_CAPA+EXTENT)), layer=LAYER_CAPA)
133
+
134
+ assert Picc.crs == CaPa.crs, "The crs of the two shapefiles are different"
135
+
136
+ parallel_datamod(manager=manager, picc=Picc, capa=CaPa, number_procs=number_procs)
137
+
138
+ done.append(steps_base_data_creation.POINTS2POLYS)
139
+
140
+ if 5 in steps or steps_base_data_creation.RASTERIZE_IGN in steps:
141
+ # ********************************************************************************************************************
142
+ # Step 5 : Rasaterize the IGN data "Course d'eau" to get the riverbed mask
143
+ shp_to_raster(manager.CE_IGN_TOP10V, manager.SA_MASKED_RIVER, resolution)
144
+
145
+ done.append(steps_base_data_creation.RASTERIZE_IGN)
146
+
147
+ if 6 in steps or steps_base_data_creation.PREPROCESS_VULNCODE in steps:
148
+ # ********************************************************************************************************************
149
+ # Step 6 : Pre-processing for Vulnerability
150
+ # Save the database with vulnerability levels and codes
151
+ # This database will be rasterized in 'Database_to_raster'
152
+
153
+ layers_sa = manager.get_layers_in_wmodif()
154
+ layers_csv = vulnerability_csv.get_layers()
155
+
156
+ # Search difference between the two lists of layers
157
+ list_shp = list(set(layers_csv).difference(layers_sa))
158
+
159
+ logging.info("Excluded layers due to no features in shapefiles:")
160
+ logging.info(list_shp)
161
+
162
+ not_in_csv = [curlayer for curlayer in layers_sa if curlayer not in layers_csv]
163
+ if len(not_in_csv) > 0:
164
+ logging.error("Not treated layers due to no vulnerability level or code:")
165
+ logging.error(not_in_csv)
166
+
167
+ logging.info("STEP1: Saving the database for Vulnerability with attributes Vulne and Code")
168
+
169
+ for curlayer in layers_sa:
170
+ logging.info(curlayer)
171
+
172
+ in_file = str(manager.TMP_WMODIF / (curlayer+EXTENT))
173
+ out_file = str(manager.TMP_CODEVULNE / (curlayer+EXTENT))
174
+
175
+ shp:gpd.GeoDataFrame = gpd.read_file(in_file)
176
+
177
+ nb_lines, _ = shp.shape
178
+ if nb_lines > 0:
179
+ shp["Path"] = curlayer
180
+ shp["Vulne"] = vulnerability_csv.get_vulnerability_level(curlayer)
181
+ shp["Code"] = vulnerability_csv.get_vulnerability_code(curlayer)
182
+ shp = shp[["geometry", "Path", "Vulne","Code"]]
183
+ shp.to_file(out_file)
184
+ else:
185
+ # Normally, Phase 1 should have removed the empty shapefiles
186
+ # But, we never know... ;-)
187
+ logging.warning(f"Empty shapefile {curlayer} in {in_file}")
188
+
189
+ done.append(steps_base_data_creation.PREPROCESS_VULNCODE)
190
+
191
+ if 7 in steps or steps_base_data_creation.DATABASE_TO_RASTER in steps:
192
+ # Rasterize the database
193
+ cleaning_directory(manager.TMP_RASTERS)
194
+ cleaning_directory(manager.TMP_RASTERS_CODE)
195
+ cleaning_directory(manager.TMP_RASTERS_VULNE)
196
+
197
+ Database_to_raster(main_dir, Study_area, resolution, number_procs=number_procs)
198
+
199
+ done.append(steps_base_data_creation.DATABASE_TO_RASTER)
200
+
201
+ manager.restore_dir()
202
+
203
+ return done
204
+
205
+ def Database_to_raster(main_dir:str = 'Data',
206
+ Study_area:str = 'Bassin_Vesdre.shp',
207
+ resolution:float = 1.,
208
+ number_procs:int = 16):
209
+ """
210
+ Convert the vector database to raster database based on their vulnerability values
211
+
212
+ Each leyer is converted to a raster file with the vulnerability values
213
+ and the code values.
214
+
215
+ They are stored in the TEMP/DATABASES/*StudyArea*/VULNERABILITY/RASTERS in:
216
+ - Code
217
+ - Vulne
218
+
219
+ :param main_dir: The main data directory
220
+ :param Study_area: The study area shapefile
221
+ :param resolution: The resolution of the output raster files - default is 1 meter
222
+ :param number_procs: The number of processors to use for parallel processing
223
+
224
+ The parallel processing is safe as each layer is processed independently.
225
+ """
226
+
227
+ manager = Accept_Manager(main_dir, Study_area)
228
+
229
+ resolution = float(resolution)
230
+
231
+ if not manager.check_before_rasterize():
232
+ logging.error("The necessary files are missing - Verify logs for more information")
233
+ return
234
+
235
+ manager.change_dir()
236
+
237
+ logging.info("Convert vectors to raster based on their vulnerability values")
238
+
239
+ attributes = ["Vulne", "Code"]
240
+ for cur_attrib in attributes:
241
+ parallel_v2r(manager, cur_attrib, resolution, number_procs)
242
+
243
+ manager.restore_dir()
244
+
245
+ def Vulnerability(main_dir:str = 'Data',
246
+ scenario:str = 'Scenario1',
247
+ Study_area:str = 'Bassin_Vesdre.shp',
248
+ resolution:float = 1.,
249
+ steps:list[int] | list[steps_vulnerability] = [1,2,3]):
250
+ """
251
+ Compute the vulnerability for the study area and the scenario, if needed.
252
+
253
+ The vulnerability is computed in 3 steps:
254
+ 1. Compute the vulnerability for the study area
255
+ 2. Compute the vulnerability for the scenario
256
+ 3. Clip the vulnerability rasters to the simulation area
257
+
258
+ During step 3, three matrices are computed and clipped to the simulation area:
259
+ - Vulnerability
260
+ - Code
261
+ - Masked River
262
+
263
+ :param main_dir: The main data directory
264
+ :param scenario: The scenario name
265
+ :param Study_area: The study area shapefile
266
+ :param resolution: The resolution of the output raster files - default is 1 meter
267
+ :param steps: The steps to compute the vulnerability - default is [1,2,3]
268
+
269
+ To be more rapid, the steps can be computed separately.
270
+ - [1,2,3] : All steps are computed - Necessary for the first time
271
+ - [2,3] : Only the scenario and clipping steps are computed -- Useful for scenario changes
272
+ - [3] : Only the clipping step is computed -- Useful if simulation area changes but scenario is the same
273
+
274
+ """
275
+
276
+ manager = Accept_Manager(main_dir, Study_area, scenario=scenario)
277
+
278
+ if not manager.check_before_vulnerability():
279
+ logging.error("The necessary files are missing - Verify logs for more information")
280
+ return
281
+
282
+ logging.info("Starting VULNERABILITY computations at {} m resolution".format(resolution))
283
+
284
+ manager.change_dir()
285
+ done = []
286
+
287
+ if 1 in steps or steps_vulnerability.CREATE_RASTERS in steps:
288
+ # Step 1 : Compute the vulnerability rasters for the study area
289
+ # The data **will not** be impacted by the scenario modifications
290
+
291
+ logging.info("Generate Vulnerability rasters {}m".format(resolution))
292
+
293
+ cleaning_directory(manager.TMP_SCEN_DIR)
294
+
295
+ compute_vulnerability(manager)
296
+
297
+ done.append(steps_vulnerability.CREATE_RASTERS)
298
+
299
+ if 2 in steps or steps_vulnerability.APPLY_MODIFS in steps:
300
+ # Step 2 : Compute the vulnerability rasters for the scenario
301
+ # The data **will be** impacted by the scenario modifications
302
+
303
+ if not manager.check_vuln_code_sa():
304
+ logging.error("The vulnerability and code files for the study area are missing")
305
+ logging.warning("Force the computation even if not prescribed in the steps")
306
+
307
+ Vulnerability(main_dir, scenario, Study_area, resolution, [1])
308
+
309
+ bu:list[Path] = manager.get_files_in_rm_buildings()
310
+
311
+ if len(bu)>0:
312
+ for curfile in bu:
313
+ tiff_file = manager.TMP_RM_BUILD_DIR / (curfile.stem + ".tiff")
314
+ shp_to_raster(curfile, tiff_file)
315
+
316
+ compute_vulnerability4scenario(manager)
317
+ else:
318
+ logging.warning(f"No buildings were removed in water depth analysis OR No shapefiles in {manager.IN_RM_BUILD_DIR}")
319
+
320
+ done.append(steps_vulnerability.APPLY_MODIFS)
321
+
322
+ if 3 in steps or steps_vulnerability.MATCH_SIMUL in steps:
323
+ # Step 3 : Clip the vulnerability/code rasters to the **simulation area**
324
+
325
+ logging.info("Save Vulnerability files for the area of interest")
326
+
327
+ return_periods = manager.get_return_periods()
328
+ TMAX = manager.get_filepath_for_return_period(return_periods[-1])
329
+
330
+ if TMAX is None:
331
+ logging.error("The file for the maximum return period is missing")
332
+ return
333
+
334
+ match_vulnerability2sim(manager.SA_MASKED_RIVER,manager.OUT_MASKED_RIVER, TMAX)
335
+ match_vulnerability2sim(manager.SA_VULN, manager.OUT_VULN, TMAX)
336
+ match_vulnerability2sim(manager.SA_CODE, manager.OUT_CODE, TMAX)
337
+
338
+ done.append(steps_vulnerability.MATCH_SIMUL)
339
+
340
+ manager.restore_dir()
341
+
342
+ return done
343
+
344
+ def Acceptability(main_dir:str = 'Vesdre',
345
+ scenario:str = 'Scenario1',
346
+ Study_area:str = 'Bassin_Vesdre.shp'):
347
+ """ Compute acceptability for the scenario """
348
+
349
+ manager = Accept_Manager(main_dir, Study_area, scenario=scenario)
350
+
351
+ manager.change_dir()
352
+
353
+ # Load the vulnerability raster **for the scenario**
354
+ vulne = gdal.Open(str(manager.OUT_VULN))
355
+ # Convert to numpy array
356
+ vulne = vulne.GetRasterBand(1).ReadAsArray()
357
+
358
+ # Load the river mask
359
+ riv = gdal.Open(str(manager.OUT_MASKED_RIVER))
360
+
361
+ # Get the geotransform and projection for the output tiff
362
+ geotrans = riv.GetGeoTransform()
363
+ proj = riv.GetProjection()
364
+
365
+ # Convert to numpy array
366
+ riv = riv.GetRasterBand(1).ReadAsArray()
367
+
368
+ # Get the return periods available
369
+ return_periods = manager.get_return_periods()
370
+
371
+ # Prepare the river bed filter
372
+ # Useful as we iterate over the return periods
373
+ # and the river bed is the same for all return periods
374
+ ij_riv = np.where(riv == 1)
375
+
376
+ # Compute acceptability for each return period
377
+ for curT in tqdm(return_periods):
378
+
379
+ # Load the **FILLED** modelled water depth for the return period
380
+ model_h = gdal.Open(str(manager.get_sim_file_for_return_period(curT)))
381
+ # Convert to numpy array
382
+ model_h = model_h.GetRasterBand(1).ReadAsArray()
383
+
384
+ # Set nan if the water depth is 0.
385
+ # 'nan' is a good choice as it will not be considered in the computation.
386
+ model_h[model_h == 0] = np.nan
387
+ # Set nan in the river bed
388
+ model_h[ij_riv] = np.nan
389
+
390
+ logging.info("Return period {}".format(curT))
391
+ # Compute the local acceptability for the return period
392
+ compute_acceptability(manager, model_h, vulne, curT, (geotrans, proj))
393
+
394
+ # At this point, the local acceptability for each return period is computed
395
+ # and stored in tiff files in the TEMP/SutyArea/scenario/Q_FILES directory
396
+
397
+ # Get the list of Q files
398
+ qs = manager.get_q_files()
399
+ # Initialize the dictionary to store the acceptability values
400
+ q_dict = {}
401
+
402
+ # Iterate over the return periods
403
+ for curT in return_periods:
404
+ logging.info("vm"+str(curT))
405
+
406
+ # We set the filename from the return period, not the "qs" list
407
+ q_filename = manager.TMP_QFILES / "Q{}.tif".format(curT)
408
+
409
+ # Check if the file exists
410
+ assert q_filename.exists(), "The file {} does not exist".format(q_filename)
411
+ # Check if the file is in the "qs" list
412
+ assert q_filename in qs, "The file {} is not in the list of Q files".format(q_filename)
413
+
414
+ # Load the Q file for the return period
415
+ tmp_data = gdal.Open(str(q_filename))
416
+ # Convert to numpy array
417
+ q_dict["vm"+str(curT)] = tmp_data.GetRasterBand(1).ReadAsArray()
418
+
419
+ # Force the deletion of the variable, rather than waiting for the garbage collector
420
+ # May be useful if the files are large
421
+ del tmp_data
422
+
423
+ # Pointing the last return period, maybe 1000 but not always
424
+ array_t1000 = q_dict["vm{}".format(return_periods[-1])]
425
+ # Get the indices where the value is -99999
426
+ # We will force the same mask for all lower return periods
427
+ ij_t1000 = np.where(array_t1000 == -99999)
428
+
429
+ # Iterate over the return periods
430
+ for curT in return_periods:
431
+
432
+ if curT != return_periods[-1]:
433
+ logging.info(curT)
434
+
435
+ # Alias
436
+ tmp_array = q_dict["vm{}".format(curT)]
437
+
438
+ # Set the -99999 values to 0
439
+ tmp_array[tmp_array == -99999] = 0.
440
+ # Set the masked values, for the last return period, to nan
441
+ tmp_array[ij_t1000] = np.nan
442
+
443
+ # # Load the ponderation file
444
+ # pond = pd.read_csv(dirsnames.PONDERATION_CSV)
445
+ # # Set the index to the interval, so we can use the interval as a key
446
+ # pond.set_index("Interval", inplace=True)
447
+
448
+ # Get ponderations for the return periods
449
+ pond = manager.get_ponderations()
450
+
451
+ assert len(pond) == len(return_periods), "The number of ponderations is not equal to the number of return periods"
452
+ assert pond["Ponderation"].sum() > 0.999999 and pond["Ponderation"].sum()<1.0000001, "The sum of the ponderations is not equal to 1"
453
+
454
+ # Initialize the combined acceptability matrix -- Ponderate mean of the local acceptability
455
+ comb = np.zeros(q_dict["vm{}".format(return_periods[-1])].shape)
456
+
457
+ for curT in return_periods:
458
+ comb += q_dict["vm{}".format(curT)] * pond["Ponderation"][curT]
459
+
460
+ y_pixels, x_pixels = comb.shape # number of pixels in x
461
+
462
+ # Set up output GeoTIFF
463
+ driver = gdal.GetDriverByName('GTiff')
464
+ dataset = driver.Create(str(manager.OUT_ACCEPT), x_pixels, y_pixels, 1, gdal.GDT_Float32, options=["COMPRESS=LZW"])
465
+ dataset.GetRasterBand(1).WriteArray(comb.astype(np.float32))
466
+ dataset.SetGeoTransform(geotrans)
467
+ dataset.SetProjection(proj)
468
+ dataset.FlushCache()
469
+ del(dataset)
470
+
471
+ # Resample to 100m
472
+ Agg = gdal.Warp(str(manager.OUT_ACCEPT_100M), str(manager.OUT_ACCEPT), xRes=100, yRes=100, resampleAlg='Average')
473
+ del(Agg)
474
+
475
+ manager.restore_dir()
476
+
477
+ return 0