wolfhece 2.1.25__py3-none-any.whl → 2.1.28__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 +26 -10
- wolfhece/acceptability/Parallels.py +49 -20
- wolfhece/acceptability/acceptability.py +228 -134
- wolfhece/acceptability/func.py +698 -222
- wolfhece/apps/version.py +1 -1
- wolfhece/libs/WolfOGL.c +16164 -2680
- wolfhece/libs/WolfOGL.pyx +357 -0
- wolfhece/libs/wolfogl.cp310-win_amd64.pyd +0 -0
- wolfhece/pyviews.py +3 -3
- wolfhece/wolf_array.py +406 -158
- wolfhece/wolfresults_2D.py +2 -2
- {wolfhece-2.1.25.dist-info → wolfhece-2.1.28.dist-info}/METADATA +2 -1
- {wolfhece-2.1.25.dist-info → wolfhece-2.1.28.dist-info}/RECORD +16 -18
- {wolfhece-2.1.25.dist-info → wolfhece-2.1.28.dist-info}/WHEEL +1 -1
- wolfhece/libs/wolfogl.cp39-win_amd64.pyd +0 -0
- wolfhece/libs/wolfpy.cp39-win_amd64.pyd +0 -0
- {wolfhece-2.1.25.dist-info → wolfhece-2.1.28.dist-info}/entry_points.txt +0 -0
- {wolfhece-2.1.25.dist-info → wolfhece-2.1.28.dist-info}/top_level.txt +0 -0
wolfhece/acceptability/func.py
CHANGED
@@ -7,6 +7,42 @@ import glob
|
|
7
7
|
from pathlib import Path
|
8
8
|
import logging
|
9
9
|
from tqdm import tqdm
|
10
|
+
from pyogrio import list_layers, read_dataframe
|
11
|
+
from enum import Enum
|
12
|
+
import numba as nb
|
13
|
+
|
14
|
+
ENGINE = 'pyogrio' # or 'Fiona -- Pyogrio is faster
|
15
|
+
EXTENT = '.gpkg'
|
16
|
+
class Modif_Type(Enum):
|
17
|
+
"""
|
18
|
+
Enum class for the type of modification
|
19
|
+
"""
|
20
|
+
|
21
|
+
WALOUS = 'Walous layers changed to PICC buidings'
|
22
|
+
POINT2POLY_EPURATION = 'Change BDREF based on AJOUT_PDET sent by Perrine (SPI)'
|
23
|
+
POINT2POLY_PICC = 'Convert the points to polygons based on PICC'
|
24
|
+
POINT2POLY_CAPAPICC = 'Convert the points to polygons based on PICC and CaPa'
|
25
|
+
INHABITED = 'Select only inhabited buildings'
|
26
|
+
ROAD = 'Create a buffer around the roads'
|
27
|
+
COPY = 'Copy the data'
|
28
|
+
|
29
|
+
class Vulnerability_csv():
|
30
|
+
|
31
|
+
def __init__(self, file:Path) -> None:
|
32
|
+
self.file = file
|
33
|
+
self.data = pd.read_csv(file, sep=",", encoding='latin-1')
|
34
|
+
|
35
|
+
def get_layers(self) -> list:
|
36
|
+
return [a[1] for a in self.data["Path"].str.split('/')]
|
37
|
+
|
38
|
+
def get_vulnerability_level(self, layer:str) -> str:
|
39
|
+
idx = self.get_layers().index(layer)
|
40
|
+
return self.data.iloc[idx]["Vulne"]
|
41
|
+
|
42
|
+
def get_vulnerability_code(self, layer:str) -> str:
|
43
|
+
idx = self.get_layers().index(layer)
|
44
|
+
return self.data.iloc[idx]["Code"]
|
45
|
+
|
10
46
|
|
11
47
|
def get_data_type(fname:Path):
|
12
48
|
|
@@ -97,6 +133,10 @@ class Accept_Manager():
|
|
97
133
|
CaPa_Walloon:str = 'Cadastre_Walloon.gpkg',
|
98
134
|
PICC_Walloon:str = 'PICC_vDIFF.gdb',
|
99
135
|
CE_IGN_top10v:str = 'CE_IGN_TOP10V/CE_IGN_TOP10V.shp',
|
136
|
+
EPU_Stations:str = 'AJOUT_PDET_EPU_DG03_STATIONS.shp',
|
137
|
+
Ponderation_csv:str = 'Ponderation.csv',
|
138
|
+
Vulnerability_csv:str = 'Vulnerability.csv',
|
139
|
+
Intermediate_csv:str = 'Intermediate.csv'
|
100
140
|
) -> None:
|
101
141
|
|
102
142
|
self.old_dir:Path = Path(os.getcwd())
|
@@ -123,39 +163,54 @@ class Accept_Manager():
|
|
123
163
|
self.IN_STUDY_AREA = self.IN_DIR / "STUDY_AREA"
|
124
164
|
self.IN_CSV = self.IN_DIR / "CSVs"
|
125
165
|
self.IN_WATER_DEPTH = self.IN_DIR / "WATER_DEPTH"
|
166
|
+
self.IN_EPU_STATIONS= self.IN_DIR / "EPU_STATIONS_NEW"
|
126
167
|
|
127
168
|
self.ORIGINAL_GDB = self.IN_DATABASE / self._original_gdb
|
128
169
|
self.CAPA_WALLOON = self.IN_DATABASE / self._capa_walloon
|
129
170
|
self.PICC_WALLOON = self.IN_DATABASE / self._picc_walloon
|
130
171
|
self.CE_IGN_TOP10V = self.IN_DATABASE / self._ce_ign_top10v
|
172
|
+
self.EPU_STATIONS = self.IN_EPU_STATIONS / EPU_Stations
|
131
173
|
|
132
|
-
self.VULNERABILITY_CSV = self.IN_CSV /
|
133
|
-
self.POINTS_CSV = self.IN_CSV /
|
134
|
-
|
174
|
+
self.VULNERABILITY_CSV = self.IN_CSV / Vulnerability_csv
|
175
|
+
self.POINTS_CSV = self.IN_CSV / Intermediate_csv
|
176
|
+
self.PONDERATION_CSV = self.IN_CSV / Ponderation_csv
|
135
177
|
|
136
|
-
self._CSVs = [self.VULNERABILITY_CSV, self.POINTS_CSV]
|
178
|
+
self._CSVs = [self.VULNERABILITY_CSV, self.POINTS_CSV]
|
137
179
|
self._GPKGs= [self.CAPA_WALLOON, self.PICC_WALLOON]
|
138
180
|
self._GDBs = [self.ORIGINAL_GDB]
|
139
|
-
self._SHPs = [self.CE_IGN_TOP10V]
|
181
|
+
self._SHPs = [self.CE_IGN_TOP10V, self.EPU_STATIONS]
|
140
182
|
self._ALLS = self._CSVs + self._GPKGs + self._GDBs + self._SHPs
|
141
183
|
|
142
184
|
self.TMP_DIR = self.main_dir / "TEMP"
|
143
185
|
|
144
|
-
self.TMP_DATABASE = self.TMP_DIR / "DATABASES"
|
145
|
-
|
146
186
|
self.OUT_DIR = self.main_dir / "OUTPUT"
|
147
187
|
|
188
|
+
self.points2polys = []
|
189
|
+
self.lines2polys = []
|
190
|
+
|
148
191
|
self.create_paths()
|
149
192
|
self.create_paths_scenario()
|
150
193
|
|
151
194
|
def create_paths(self):
|
152
195
|
""" Create the paths for the directories and files """
|
153
196
|
|
197
|
+
self.points2polys = []
|
198
|
+
self.lines2polys = []
|
199
|
+
|
154
200
|
if self._study_area is not None:
|
155
201
|
|
156
202
|
self.Study_area:Path = Path(self._study_area)
|
157
203
|
|
158
|
-
self.TMP_STUDYAREA = self.
|
204
|
+
self.TMP_STUDYAREA = self.TMP_DIR / self.Study_area.stem
|
205
|
+
self.TMP_DATABASE = self.TMP_STUDYAREA / "DATABASES"
|
206
|
+
|
207
|
+
self.TMP_CLIPGDB = self.TMP_DATABASE / "CLIP_GDB"
|
208
|
+
self.TMP_CADASTER = self.TMP_DATABASE / "CLIP_CADASTER"
|
209
|
+
self.TMP_PICC = self.TMP_DATABASE / "CLIP_PICC"
|
210
|
+
self.TMP_IGNCE = self.TMP_DATABASE / "CLIP_IGN_CE"
|
211
|
+
self.TMP_WMODIF = self.TMP_DATABASE / "WITH_MODIF"
|
212
|
+
self.TMP_CODEVULNE = self.TMP_DATABASE / "CODE_VULNE"
|
213
|
+
|
159
214
|
self.TMP_VULN_DIR = self.TMP_STUDYAREA / "VULNERABILITY"
|
160
215
|
self.TMP_RASTERS = self.TMP_VULN_DIR / "RASTERS"
|
161
216
|
self.TMP_RASTERS_CODE = self.TMP_RASTERS / "Code"
|
@@ -164,12 +219,13 @@ class Accept_Manager():
|
|
164
219
|
self.OUT_STUDY_AREA = self.OUT_DIR / self.Study_area.stem
|
165
220
|
|
166
221
|
self.SA = self.IN_STUDY_AREA / self.Study_area
|
167
|
-
|
168
|
-
self.
|
169
|
-
self.
|
222
|
+
|
223
|
+
# self.SA_DATABASE = self.TMP_STUDYAREA / "database.gpkg"
|
224
|
+
# self.SA_CAPA = self.TMP_STUDYAREA / "CaPa.gpkg"
|
225
|
+
# self.SA_PICC = self.TMP_STUDYAREA / "PICC.gpkg"
|
170
226
|
self.SA_FINAL = self.TMP_STUDYAREA / "database_final.gpkg"
|
171
227
|
self.SA_FINAL_V = self.TMP_STUDYAREA / "database_final_V.gpkg"
|
172
|
-
self.SA_MASKED_RIVER = self.
|
228
|
+
self.SA_MASKED_RIVER = self.TMP_IGNCE / "CE_IGN_TOP10V.tiff"
|
173
229
|
|
174
230
|
self.SA_VULN = self.TMP_VULN_DIR / "Vulnerability.tiff"
|
175
231
|
self.SA_CODE = self.TMP_VULN_DIR / "Vulnerability_Code.tiff"
|
@@ -179,6 +235,12 @@ class Accept_Manager():
|
|
179
235
|
self._scenario = None
|
180
236
|
|
181
237
|
self.TMP_STUDYAREA = None
|
238
|
+
self.TMP_DATABASE = None
|
239
|
+
self.TMP_CADASTER = None
|
240
|
+
self.TMP_PICC = None
|
241
|
+
self.TMP_IGNCE = None
|
242
|
+
self.TMP_WMODIF = None
|
243
|
+
self.TMP_CODEVULNE = None
|
182
244
|
self.TMP_VULN_DIR = None
|
183
245
|
self.TMP_RASTERS = None
|
184
246
|
self.TMP_RASTERS_CODE = None
|
@@ -204,7 +266,7 @@ class Accept_Manager():
|
|
204
266
|
self.check_outputs()
|
205
267
|
|
206
268
|
def create_paths_scenario(self):
|
207
|
-
|
269
|
+
|
208
270
|
if self._scenario is not None:
|
209
271
|
|
210
272
|
self.scenario:str = str(self._scenario)
|
@@ -300,10 +362,25 @@ class Accept_Manager():
|
|
300
362
|
logging.error("The scenario does not exist in the water depth directory")
|
301
363
|
|
302
364
|
def get_files_in_rm_buildings(self) -> list[Path]:
|
303
|
-
return [Path(a) for a in glob.glob(str(self.IN_RM_BUILD_DIR / "
|
365
|
+
return [Path(a) for a in glob.glob(str(self.IN_RM_BUILD_DIR / ("*"+ EXTENT)))]
|
304
366
|
|
305
367
|
def get_files_in_rasters_vulne(self) -> list[Path]:
|
306
368
|
return [Path(a) for a in glob.glob(str(self.TMP_RASTERS_VULNE / "*.tiff"))]
|
369
|
+
|
370
|
+
def get_layers_in_gdb(self) -> list[str]:
|
371
|
+
return [a[0] for a in list_layers(str(self.ORIGINAL_GDB))]
|
372
|
+
|
373
|
+
def get_layer_types_in_gdb(self) -> list[str]:
|
374
|
+
return [a[1] for a in list_layers(str(self.ORIGINAL_GDB))]
|
375
|
+
|
376
|
+
def get_layers_in_clipgdb(self) -> list[str]:
|
377
|
+
return [Path(a).stem for a in glob.glob(str(self.TMP_CLIPGDB / ("*"+ EXTENT)))]
|
378
|
+
|
379
|
+
def get_layers_in_wmodif(self) -> list[str]:
|
380
|
+
return [Path(a).stem for a in glob.glob(str(self.TMP_WMODIF / ("*"+ EXTENT)))]
|
381
|
+
|
382
|
+
def get_layers_in_codevulne(self) -> list[str]:
|
383
|
+
return [Path(a).stem for a in glob.glob(str(self.TMP_CODEVULNE / ("*"+ EXTENT)))]
|
307
384
|
|
308
385
|
def get_files_in_rasters_code(self) -> list[Path]:
|
309
386
|
return [Path(a) for a in glob.glob(str(self.TMP_RASTERS_CODE / "*.tiff"))]
|
@@ -343,23 +420,114 @@ class Accept_Manager():
|
|
343
420
|
return cursim
|
344
421
|
|
345
422
|
return None
|
423
|
+
|
424
|
+
def get_types_in_file(self, file:str) -> list[str]:
|
425
|
+
""" Get the types of the geometries in the Shape file """
|
426
|
+
|
427
|
+
return [a[1] for a in list_layers(str(file))]
|
428
|
+
|
429
|
+
def is_type_unique(self, file:str) -> bool:
|
430
|
+
""" Check if the file contains only one type of geometry """
|
431
|
+
|
432
|
+
types = self.get_types_in_file(file)
|
433
|
+
return len(types) == 1
|
434
|
+
|
435
|
+
def is_polygons(self, set2test:set) -> bool:
|
436
|
+
""" Check if the set contains only polygons """
|
437
|
+
|
438
|
+
set2test = list(set2test)
|
439
|
+
firstone = set2test[0]
|
440
|
+
if 'Polygon' in firstone:
|
441
|
+
for curtype in set2test:
|
442
|
+
if 'Polygon' not in curtype:
|
443
|
+
return False
|
444
|
+
return True
|
445
|
+
else:
|
446
|
+
return False
|
447
|
+
|
448
|
+
def is_same_types(self, file:str) -> tuple[bool, str]:
|
449
|
+
""" Check if the file contains only the same type of geometry """
|
450
|
+
|
451
|
+
types = self.get_types_in_file(file)
|
452
|
+
|
453
|
+
if len(types) == 1:
|
454
|
+
if 'Point' in types[0]:
|
455
|
+
return True, 'Point'
|
456
|
+
elif 'Polygon' in types[0]:
|
457
|
+
return True, 'Polygon'
|
458
|
+
elif 'LineString' in types[0]:
|
459
|
+
return True, 'LineString'
|
460
|
+
else:
|
461
|
+
raise ValueError(f"The type of geometry {types[0]} is not recognized")
|
462
|
+
else:
|
463
|
+
firstone = types[0]
|
464
|
+
if 'Point' in firstone:
|
465
|
+
for curtype in types:
|
466
|
+
if 'Point' not in curtype:
|
467
|
+
return False, None
|
468
|
+
return True, 'Point'
|
469
|
+
|
470
|
+
elif 'Polygon' in firstone:
|
471
|
+
for curtype in types:
|
472
|
+
if 'Polygon' not in curtype:
|
473
|
+
return False, None
|
474
|
+
|
475
|
+
return True, 'Polygon'
|
476
|
+
|
477
|
+
elif 'LineString' in firstone:
|
478
|
+
for curtype in types:
|
479
|
+
if 'LineString' not in curtype:
|
480
|
+
return False, None
|
481
|
+
|
482
|
+
return True, 'LineString'
|
483
|
+
else:
|
484
|
+
raise ValueError(f"The type of geometry {firstone} is not recognized")
|
485
|
+
|
346
486
|
|
347
487
|
def get_return_periods(self) -> list[int]:
|
488
|
+
"""
|
489
|
+
Get the return periods from the simulations
|
490
|
+
|
491
|
+
:return list[int]: the **sorted list** of return periods
|
492
|
+
"""
|
348
493
|
|
494
|
+
# List files in directory
|
349
495
|
sims = self.get_sims_files_for_scenario()
|
350
496
|
|
351
497
|
if len(sims)==0:
|
352
498
|
logging.error("No simulations found")
|
353
499
|
return None
|
354
500
|
|
501
|
+
# Two cases:
|
502
|
+
# - Return periods are named as T2.tif, T5.tif, T10.tif, ...
|
503
|
+
# - Return periods are named as *_T2_h.tif, *_T5_h.tif, *_T10_h.tif, ...
|
355
504
|
if "_h.tif" in sims[0].name:
|
356
|
-
|
357
|
-
|
358
|
-
|
505
|
+
|
506
|
+
# Searching for the position of the return period in the name
|
507
|
+
idx_T = [cursim.name.find("_T") for cursim in sims]
|
508
|
+
idx_h = [cursim.name.find("_h.tif") for cursim in sims]
|
509
|
+
|
510
|
+
assert len(idx_T) == len(idx_h), "The number of T and h are not the same"
|
511
|
+
for curT, curh in zip(idx_T, idx_h):
|
512
|
+
assert curT != -1, "The T is not found"
|
513
|
+
assert curh != -1, "The h is not found"
|
514
|
+
assert curh > curT, "The h is before the T"
|
515
|
+
|
516
|
+
# Create the list of return periods -- only the numeric part
|
517
|
+
sims = [int(cursim.name[idx_T[i]+2:idx_h[i]]) for i, cursim in enumerate(sims)]
|
359
518
|
else:
|
360
|
-
|
361
|
-
|
362
|
-
|
519
|
+
# searching for the position of the return period in the name
|
520
|
+
idx_T = [cursim.name.find("T") for cursim in sims]
|
521
|
+
idx_h = [cursim.name.find(".tif") for cursim in sims]
|
522
|
+
|
523
|
+
assert len(idx_T) == len(idx_h), "The number of T and h are not the same"
|
524
|
+
for curT, curh in zip(idx_T, idx_h):
|
525
|
+
assert curT != -1, "The T is not found"
|
526
|
+
assert curh != -1, "The h is not found"
|
527
|
+
assert curh > curT, "The h is before the T"
|
528
|
+
|
529
|
+
# create the list of return periods -- only the numeric part
|
530
|
+
sims = [int(cursim.name[idx_T[i]+1:idx_h[i]]) for i, cursim in enumerate(sims)]
|
363
531
|
|
364
532
|
return sorted(sims)
|
365
533
|
|
@@ -376,8 +544,12 @@ class Accept_Manager():
|
|
376
544
|
|
377
545
|
pond.append(1./float(rt[0]) + (1./float(rt[0]) - 1./float(rt[1]))/2.)
|
378
546
|
for i in range(1, len(rt)-1):
|
547
|
+
# Full formula
|
379
548
|
# pond.append((1./float(rt[i-1]) - 1./float(rt[i]))/2. + (1./float(rt[i]) - 1./float(rt[i+1]))/2.)
|
549
|
+
|
550
|
+
# More compact formula
|
380
551
|
pond.append((1./float(rt[i-1]) - 1./float(rt[i+1]))/2.)
|
552
|
+
|
381
553
|
pond.append(1./float(rt[-1]) + (1./float(rt[-2]) - 1./float(rt[-1]))/2.)
|
382
554
|
|
383
555
|
return pd.DataFrame(pond, columns=["Ponderation"], index=rt)
|
@@ -419,6 +591,10 @@ class Accept_Manager():
|
|
419
591
|
logging.error("INPUT : The water depth directory does not exist")
|
420
592
|
err = True
|
421
593
|
|
594
|
+
if not self.IN_EPU_STATIONS.exists():
|
595
|
+
logging.error("INPUT : The EPU stations directory does not exist")
|
596
|
+
err = True
|
597
|
+
|
422
598
|
if self.Study_area is not None:
|
423
599
|
if not self.SA.exists():
|
424
600
|
logging.error("INPUT : The study area file does not exist")
|
@@ -441,7 +617,7 @@ class Accept_Manager():
|
|
441
617
|
err = True
|
442
618
|
|
443
619
|
if self.scenario is None:
|
444
|
-
logging.
|
620
|
+
logging.debug("The scenario has not been defined")
|
445
621
|
else:
|
446
622
|
if not self.IN_SCEN_DIR.exists():
|
447
623
|
logging.error("The scenario directory does not exist")
|
@@ -457,11 +633,20 @@ class Accept_Manager():
|
|
457
633
|
"""
|
458
634
|
|
459
635
|
self.TMP_DIR.mkdir(parents=True, exist_ok=True)
|
460
|
-
self.TMP_DATABASE.mkdir(parents=True, exist_ok=True)
|
461
636
|
|
462
637
|
if self.Study_area is not None:
|
463
638
|
self.TMP_STUDYAREA.mkdir(parents=True, exist_ok=True)
|
639
|
+
self.TMP_DATABASE.mkdir(parents=True, exist_ok=True)
|
640
|
+
self.TMP_CLIPGDB.mkdir(parents=True, exist_ok=True)
|
641
|
+
self.TMP_CADASTER.mkdir(parents=True, exist_ok=True)
|
642
|
+
self.TMP_WMODIF.mkdir(parents=True, exist_ok=True)
|
643
|
+
self.TMP_CODEVULNE.mkdir(parents=True, exist_ok=True)
|
644
|
+
self.TMP_PICC.mkdir(parents=True, exist_ok=True)
|
645
|
+
self.TMP_IGNCE.mkdir(parents=True, exist_ok=True)
|
464
646
|
self.TMP_VULN_DIR.mkdir(parents=True, exist_ok=True)
|
647
|
+
self.TMP_RASTERS.mkdir(parents=True, exist_ok=True)
|
648
|
+
self.TMP_RASTERS_CODE.mkdir(parents=True, exist_ok=True)
|
649
|
+
self.TMP_RASTERS_VULNE.mkdir(parents=True, exist_ok=True)
|
465
650
|
|
466
651
|
if self.scenario is not None:
|
467
652
|
self.TMP_SCEN_DIR.mkdir(parents=True, exist_ok=True)
|
@@ -533,12 +718,12 @@ class Accept_Manager():
|
|
533
718
|
|
534
719
|
def check_before_rasterize(self) -> bool:
|
535
720
|
|
536
|
-
if not self.
|
721
|
+
if not self.TMP_CODEVULNE.exists():
|
537
722
|
logging.error("The final database with vulnerability levels does not exist")
|
538
723
|
return False
|
539
724
|
|
540
|
-
if not self.
|
541
|
-
logging.error("The
|
725
|
+
if not self.TMP_WMODIF.exists():
|
726
|
+
logging.error("The vector data with modifications does not exist")
|
542
727
|
return False
|
543
728
|
|
544
729
|
return True
|
@@ -587,44 +772,145 @@ class Accept_Manager():
|
|
587
772
|
|
588
773
|
return True
|
589
774
|
|
590
|
-
|
775
|
+
def compare_original_clipped_layers(self) -> str:
|
776
|
+
""" Compare the original layers with the clipped ones """
|
777
|
+
|
778
|
+
layers = self.get_layers_in_gdb()
|
779
|
+
layers_clip = self.get_layers_in_clipgdb()
|
780
|
+
|
781
|
+
ret = 'These layers have not been clipped:\n'
|
782
|
+
for layer in layers:
|
783
|
+
if layer not in layers_clip:
|
784
|
+
ret += " - {}\n".format(layer)
|
785
|
+
|
786
|
+
ret += '\nThese layers have been clipped but are not present in the GDB:\n'
|
787
|
+
for layer in layers_clip:
|
788
|
+
if layer not in layers:
|
789
|
+
ret += " - {}\n".format(layer)
|
790
|
+
|
791
|
+
ret+='\n'
|
792
|
+
|
793
|
+
return ret
|
794
|
+
|
795
|
+
def compare_clipped_raster_layers(self) -> str:
|
796
|
+
""" Compare the clipped layers with the rasterized ones """
|
797
|
+
|
798
|
+
layers = self.get_layers_in_clipgdb()
|
799
|
+
layers_rast = self.get_layers_in_codevulne()
|
800
|
+
|
801
|
+
ret = 'These layers {} have not been rasterized:\n'
|
802
|
+
for layer in layers:
|
803
|
+
if layer not in layers_rast:
|
804
|
+
ret += " - {}\n".format(layer)
|
805
|
+
|
806
|
+
ret += '\nThese layers have been rasterized but are not in the orginal GDB:\n'
|
807
|
+
for layer in layers_rast:
|
808
|
+
if layer not in layers:
|
809
|
+
ret += " - {}\n".format(layer)
|
810
|
+
|
811
|
+
ret+='\n'
|
812
|
+
|
813
|
+
return ret
|
814
|
+
|
815
|
+
def get_operand(self, file:str) -> Modif_Type:
|
816
|
+
""" Get the operand based on the layer name """
|
817
|
+
LAYERS_WALOUS = ["WALOUS_2018_LB72_112",
|
818
|
+
"WALOUS_2018_LB72_31",
|
819
|
+
"WALOUS_2018_LB72_32",
|
820
|
+
"WALOUS_2018_LB72_331",
|
821
|
+
"WALOUS_2018_LB72_332",
|
822
|
+
"WALOUS_2018_LB72_333",
|
823
|
+
"WALOUS_2018_LB72_34"]
|
824
|
+
|
825
|
+
ret, curtype = self.is_same_types(file)
|
826
|
+
layer = Path(file).stem
|
827
|
+
|
828
|
+
if not ret:
|
829
|
+
raise ValueError("The layer contains different types of geometries")
|
830
|
+
|
831
|
+
if layer in LAYERS_WALOUS:
|
832
|
+
return Modif_Type.WALOUS
|
833
|
+
|
834
|
+
elif curtype=="Point":
|
835
|
+
|
836
|
+
self.points2polys.append(layer)
|
837
|
+
|
838
|
+
if layer =="BDREF_DGO3_PASH__SCHEMA_STATIONS_EPU":
|
839
|
+
return Modif_Type.POINT2POLY_EPURATION
|
840
|
+
elif layer =="INFRASIG_SOINS_SANTE__ETAB_AINES":
|
841
|
+
return Modif_Type.POINT2POLY_PICC
|
842
|
+
else:
|
843
|
+
return Modif_Type.POINT2POLY_CAPAPICC
|
844
|
+
|
845
|
+
elif layer =="Hab_2018_CABU":
|
846
|
+
return Modif_Type.INHABITED
|
847
|
+
|
848
|
+
elif layer =="INFRASIG_ROUTE_RES_ROUTIER_TE_AXES":
|
849
|
+
|
850
|
+
self.lines2polys.append(layer)
|
851
|
+
|
852
|
+
return Modif_Type.ROAD
|
853
|
+
|
854
|
+
else:
|
855
|
+
return Modif_Type.COPY
|
591
856
|
|
592
|
-
|
857
|
+
|
858
|
+
def clip_layer(layer:str,
|
593
859
|
file_path:str,
|
594
860
|
Study_Area:str,
|
595
|
-
|
861
|
+
output_dir:str):
|
596
862
|
"""
|
597
|
-
Clip the input data based on the selected bassin and saves it
|
863
|
+
Clip the input data based on the selected bassin and saves it
|
864
|
+
in separate shape files.
|
865
|
+
|
866
|
+
As shape file doen not support DateTime, the columns with DateTime
|
867
|
+
are converted to string.
|
598
868
|
|
599
869
|
:param layer: the layer name in the GDB file
|
600
870
|
:param file_path: the path to the GDB file
|
601
871
|
:param Study_Area: the path to the study area shapefile
|
602
|
-
:param
|
872
|
+
:param output_dir: the path to the output directory
|
603
873
|
"""
|
604
874
|
|
605
875
|
layer = str(layer)
|
606
876
|
file_path = str(file_path)
|
607
877
|
Study_Area = str(Study_Area)
|
608
|
-
|
878
|
+
output_dir = Path(output_dir)
|
609
879
|
|
610
|
-
St_Area = gpd.read_file(Study_Area)
|
880
|
+
St_Area = gpd.read_file(Study_Area, engine=ENGINE)
|
611
881
|
|
612
882
|
logging.info(layer)
|
613
883
|
|
614
884
|
# The data is clipped during the reading
|
615
885
|
# **It is more efficient than reading the entire data and then clipping it**
|
616
|
-
|
886
|
+
#
|
887
|
+
# FIXME: "read_dataframe" is used directly rather than "gpd.read_file" cause
|
888
|
+
# the "layer" parameter is well transmitted to the "read_dataframe" function...
|
889
|
+
df:gpd.GeoDataFrame = read_dataframe(file_path, layer=layer, mask=St_Area['geometry'][0])
|
890
|
+
|
891
|
+
if len(df) == 0:
|
892
|
+
logging.warning("No data found for layer " + str(layer))
|
893
|
+
return "No data found for layer " + str(layer)
|
617
894
|
|
618
895
|
# Force Lambert72 -> EPSG:31370
|
619
896
|
df.to_crs("EPSG:31370", inplace=True)
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
897
|
+
try:
|
898
|
+
date_columns = df.select_dtypes(include=['datetimetz']).columns.tolist()
|
899
|
+
if len(date_columns)>0:
|
900
|
+
df[date_columns] = df[date_columns].astype(str)
|
901
|
+
|
902
|
+
df.to_file(str(output_dir / (layer+EXTENT)), mode='w', engine=ENGINE)
|
903
|
+
except Exception as e:
|
904
|
+
logging.error("Error while saving the clipped " + str(layer) + " to file")
|
905
|
+
logging.error(e)
|
906
|
+
pass
|
907
|
+
|
908
|
+
logging.info("Saved the clipped " + str(layer) + " to file")
|
909
|
+
return "Saved the clipped " +str(layer)+ " to file"
|
910
|
+
|
911
|
+
|
912
|
+
def data_modification(layer:str,
|
913
|
+
manager:Accept_Manager,
|
628
914
|
picc:gpd.GeoDataFrame,
|
629
915
|
capa:gpd.GeoDataFrame ):
|
630
916
|
"""
|
@@ -642,163 +928,153 @@ def data_modification(input_database:str,
|
|
642
928
|
df1:gpd.GeoDataFrame
|
643
929
|
df2:gpd.GeoDataFrame
|
644
930
|
|
645
|
-
LAYERS_WALOUS = ["WALOUS_2018_LB72_112",
|
646
|
-
"WALOUS_2018_LB72_31",
|
647
|
-
"WALOUS_2018_LB72_32",
|
648
|
-
"WALOUS_2018_LB72_331",
|
649
|
-
"WALOUS_2018_LB72_332",
|
650
|
-
"WALOUS_2018_LB72_333",
|
651
|
-
"WALOUS_2018_LB72_34"]
|
652
|
-
|
653
|
-
input_database = str(input_database)
|
654
931
|
layer = str(layer)
|
655
|
-
output_database = str(output_database)
|
656
|
-
|
657
|
-
df:gpd.GeoDataFrame = gpd.read_file(input_database, layer = layer)
|
658
|
-
x1,y1 = df.shape
|
659
|
-
a = df.geom_type.unique()
|
660
|
-
#print(layers[i])
|
661
|
-
x,=a.shape
|
662
|
-
if x1>0:
|
663
|
-
if layer in LAYERS_WALOUS: #Walous layers changed to PICC buidings
|
664
|
-
#print("walous")
|
665
|
-
|
666
|
-
assert picc.crs == df.crs, "CRS of PICC and input data do not match"
|
667
|
-
|
668
|
-
df1= gpd.sjoin(picc, df, how="inner", predicate="intersects" )
|
669
|
-
cols=df.columns
|
670
|
-
cols = np.append(cols, "GEOREF_ID")
|
671
|
-
cols = np.append(cols, "NATUR_CODE")
|
672
|
-
df1=df1[cols]
|
673
|
-
df1.to_file(output_database,layer=layer)
|
674
|
-
elif layer =="BDREF_DGO3_PASH__SCHEMA_STATIONS_EPU": #Change BDREF based on AJOUT_PDET sent by Perrine
|
675
|
-
#print("yes")
|
676
|
-
df1 = gpd.read_file(os.getcwd()+"//INPUT//EPU_STATIONS_NEW//AJOUT_PDET_EPU_DG03_STATIONS.shp")
|
677
|
-
|
678
|
-
assert df1.crs == df.crs, "CRS of AJOUT_PDET and input data do not match"
|
679
|
-
|
680
|
-
df2 = gpd.sjoin(picc, df1, how="inner", predicate="intersects" )
|
681
|
-
df2.to_file(output_database, layer=layer)
|
682
|
-
elif layer =="INFRASIG_SOINS_SANTE__ETAB_AINES":
|
683
|
-
|
684
|
-
assert capa.crs == df.crs, "CRS of CaPa and input data do not match"
|
685
|
-
|
686
|
-
df1= gpd.sjoin(capa, df, how="inner", predicate="intersects" )
|
687
|
-
cols=df.columns
|
688
|
-
#print(cols)
|
689
|
-
cols = np.append(cols, "CaPaKey")
|
690
|
-
#print(cols)
|
691
|
-
df1=df1[cols]
|
692
|
-
df2=gpd.sjoin(picc, df1, how="inner", predicate="intersects" )
|
693
|
-
cols = np.append(cols, "GEOREF_ID")
|
694
|
-
cols = np.append(cols, "NATUR_CODE")
|
695
|
-
#df2=df2[cols]
|
696
|
-
#print(df2.columns)
|
697
|
-
df2.to_file(output_database, layer=layer)
|
698
|
-
|
699
|
-
elif a[0,]=="Point" and layer!="BDREF_DGO3_PASH__SCHEMA_STATIONS_EPU" and layer!="INFRASIG_SOINS_SANTE__ETAB_AINES":
|
700
|
-
|
701
|
-
assert capa.crs == df.crs, "CRS of CaPa and input data do not match"
|
702
|
-
assert picc.crs == df.crs, "CRS of PICC and input data do not match"
|
703
|
-
|
704
|
-
df1= gpd.sjoin(capa, df, how="inner", predicate="intersects" )
|
705
|
-
cols=df.columns
|
706
|
-
#print(cols)
|
707
|
-
cols = np.append(cols, "CaPaKey")
|
708
|
-
#print(cols)
|
709
|
-
df1=df1[cols]
|
710
|
-
df2=gpd.sjoin(picc, df1, how="inner", predicate="intersects" )
|
711
|
-
cols = np.append(cols, "GEOREF_ID")
|
712
|
-
cols = np.append(cols, "NATUR_CODE")
|
713
|
-
df2=df2[cols]
|
714
|
-
#print(df2.columns)
|
715
|
-
df2.to_file(output_database, layer=layer)
|
716
|
-
#print(layers[i])
|
717
|
-
elif layer =="Hab_2018_CABU":
|
718
|
-
df1=df[df["NbsHabTOT"]>0]
|
719
|
-
#print(df1.shape)
|
720
|
-
df1.to_file(output_database, layer=layer)
|
721
|
-
elif layer =="INFRASIG_ROUTE_RES_ROUTIER_TE_AXES":
|
722
|
-
df1=df.buffer(6, cap_style=2)
|
723
|
-
df1.to_file(output_database, layer=layer)
|
724
|
-
else:
|
725
|
-
df.to_file(output_database, layer=layer)
|
726
|
-
else:
|
727
|
-
logging.info("skipped" + str(layer) + "due to no polygon in the study area")
|
728
932
|
|
729
|
-
|
730
|
-
|
731
|
-
extent:Path,
|
732
|
-
attribute:str,
|
733
|
-
pixel_size:float):
|
734
|
-
"""
|
735
|
-
Convert a vector layer to a raster tiff file
|
933
|
+
dir_input = manager.TMP_CLIPGDB
|
934
|
+
dir_output = manager.TMP_WMODIF
|
736
935
|
|
737
|
-
|
738
|
-
|
739
|
-
:param extent: the path to the extent file
|
740
|
-
:param attribute: the attribute to rasterize
|
741
|
-
:param pixel_size: the pixel size of the raster
|
936
|
+
input_file = str(dir_input / (layer + EXTENT))
|
937
|
+
output_file = str(dir_output / (layer + EXTENT))
|
742
938
|
|
743
|
-
|
939
|
+
# Read the data
|
940
|
+
df:gpd.GeoDataFrame = gpd.read_file(input_file, engine=ENGINE)
|
941
|
+
nblines, _ = df.shape
|
744
942
|
|
745
|
-
|
943
|
+
if nblines>0:
|
944
|
+
op = manager.get_operand(input_file)
|
746
945
|
|
747
|
-
|
748
|
-
|
749
|
-
extent = Path(extent)
|
750
|
-
attribute = str(attribute)
|
751
|
-
pixel_size = float(pixel_size)
|
946
|
+
if op == Modif_Type.WALOUS:
|
947
|
+
# Walous layers changed to PICC buidings
|
752
948
|
|
753
|
-
|
754
|
-
OUT_NAME = layer + ".tiff"
|
949
|
+
assert picc.crs == df.crs, "CRS of PICC and input data do not match"
|
755
950
|
|
756
|
-
|
951
|
+
assert "GEOREF_ID" in picc.columns, "The PICC file does not contain the GEOREF_ID column"
|
952
|
+
assert "NATUR_CODE" in picc.columns, "The PICC file does not contain the NATUR_CODE column"
|
757
953
|
|
758
|
-
|
759
|
-
|
954
|
+
df1 = gpd.sjoin(picc, df, how="inner", predicate="intersects" )
|
955
|
+
cols = df.columns
|
760
956
|
|
761
|
-
|
957
|
+
cols = np.append(cols, "GEOREF_ID")
|
958
|
+
cols = np.append(cols, "NATUR_CODE")
|
762
959
|
|
763
|
-
|
960
|
+
df1 = df1[cols]
|
961
|
+
|
962
|
+
if df1.shape[0] > 0:
|
963
|
+
assert manager.is_polygons(set(df1.geom_type)), f"The layer does not contains polygons - {op}"
|
964
|
+
df1.to_file(output_file, engine=ENGINE)
|
965
|
+
else:
|
966
|
+
logging.warning("No data found for layer " + str(layer))
|
764
967
|
|
765
|
-
|
766
|
-
|
968
|
+
elif op == Modif_Type.POINT2POLY_EPURATION:
|
969
|
+
# Change BDREF based on AJOUT_PDET sent by Perrine (SPI)
|
970
|
+
|
971
|
+
# The original layer is a point layer.
|
972
|
+
# The EPU_STATIONS shape file (from SPI) is a polygon layer.
|
767
973
|
|
768
|
-
|
974
|
+
df1 = gpd.read_file(str(manager.EPU_STATIONS), engine=ENGINE)
|
769
975
|
|
770
|
-
|
771
|
-
x_max = float(np.ceil(x_max))
|
772
|
-
y_min = float(int(y_min))
|
773
|
-
y_max = float(np.ceil(y_max))
|
976
|
+
assert df1.crs == df.crs, "CRS of AJOUT_PDET and input data do not match"
|
774
977
|
|
775
|
-
|
776
|
-
source_ds:ogr.DataSource = ogr.Open(str(vector_input))
|
777
|
-
source_layer = source_ds.GetLayer(layer)
|
978
|
+
df2 = gpd.sjoin(picc, df1, how="inner", predicate="intersects" )
|
778
979
|
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
gdal.GDT_Byte,
|
785
|
-
options=["COMPRESS=LZW"])
|
980
|
+
if df2.shape[0] > 0:
|
981
|
+
assert manager.is_polygons(set(df2.geom_type)), f"The layer does not contains polygons - {op}"
|
982
|
+
df2.to_file(output_file, engine=ENGINE)
|
983
|
+
else:
|
984
|
+
logging.warning("No data found for layer " + str(layer))
|
786
985
|
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
target_ds.SetProjection(srs.ExportToWkt())
|
986
|
+
elif op == Modif_Type.POINT2POLY_PICC:
|
987
|
+
# Select the polygons that contains the points
|
988
|
+
# in theCadaster and PICC files
|
791
989
|
|
792
|
-
|
793
|
-
|
990
|
+
assert capa.crs == df.crs, "CRS of CaPa and input data do not match"
|
991
|
+
assert "CaPaKey" in capa.columns, "The CaPa file does not contain the CaPaKey column"
|
794
992
|
|
795
|
-
|
796
|
-
|
797
|
-
|
993
|
+
df1= gpd.sjoin(capa, df, how="inner", predicate="intersects" )
|
994
|
+
cols=df.columns
|
995
|
+
|
996
|
+
cols = np.append(cols, "CaPaKey")
|
997
|
+
df1=df1[cols]
|
998
|
+
df2=gpd.sjoin(picc, df1, how="inner", predicate="intersects" )
|
999
|
+
|
1000
|
+
if df2.shape[0] > 0:
|
1001
|
+
assert manager.is_polygons(set(df2.geom_type)), f"The layer does not contains polygons - {op}"
|
1002
|
+
df2.to_file(output_file, engine=ENGINE)
|
1003
|
+
else:
|
1004
|
+
logging.warning("No data found for layer " + str(layer))
|
1005
|
+
|
1006
|
+
elif op == Modif_Type.POINT2POLY_CAPAPICC:
|
1007
|
+
|
1008
|
+
# Select the polygons that contains the points
|
1009
|
+
# in theCadaster and PICC files
|
1010
|
+
|
1011
|
+
assert capa.crs == df.crs, "CRS of CaPa and input data do not match"
|
1012
|
+
assert picc.crs == df.crs, "CRS of PICC and input data do not match"
|
1013
|
+
|
1014
|
+
# Join the Layer and CaPa DataFrames : https://geopandas.org/en/stable/docs/reference/api/geopandas.sjoin.html
|
1015
|
+
# ‘inner’: use intersection of keys from both dfs; retain only left_df geometry column
|
1016
|
+
# "intersects" : Binary predicate. Valid values are determined by the spatial index used.
|
1017
|
+
df1= gpd.sjoin(capa, df, how="inner", predicate="intersects" )
|
1018
|
+
|
1019
|
+
# Retain only the columns of the input data
|
1020
|
+
cols = df.columns
|
1021
|
+
# but add the CaPaKey
|
1022
|
+
cols = np.append(cols, "CaPaKey")
|
1023
|
+
|
1024
|
+
df1 = df1[cols]
|
1025
|
+
|
1026
|
+
# Join the df1 and PICC DataFrames : https://geopandas.org/en/stable/docs/reference/api/geopandas.sjoin.html
|
1027
|
+
df2 = gpd.sjoin(picc, df1, how="inner", predicate="intersects" )
|
1028
|
+
|
1029
|
+
# Add only the GEOREF_ID and NATUR_CODE columns from PICC
|
1030
|
+
cols = np.append(cols, "GEOREF_ID")
|
1031
|
+
cols = np.append(cols, "NATUR_CODE")
|
1032
|
+
|
1033
|
+
df2 = df2[cols]
|
1034
|
+
|
1035
|
+
if df2.shape[0] > 0:
|
1036
|
+
assert manager.is_polygons(set(df2.geom_type)), f"The layer does not contains polygons - {op}"
|
1037
|
+
df2.to_file(output_file, engine=ENGINE)
|
1038
|
+
else:
|
1039
|
+
logging.warning("No data found for layer " + str(layer))
|
798
1040
|
|
799
|
-
|
1041
|
+
elif op == Modif_Type.INHABITED:
|
1042
|
+
# Select only the buildings with a number of inhabitants > 0
|
1043
|
+
df1=df[df["NbsHabTOT"]>0]
|
800
1044
|
|
801
|
-
|
1045
|
+
if df1.shape[0] > 0:
|
1046
|
+
assert manager.is_polygons(set(df1.geom_type)), f"The layer does not contains polygons - {op}"
|
1047
|
+
df1.to_file(output_file, engine=ENGINE)
|
1048
|
+
else:
|
1049
|
+
logging.warning("No data found for layer " + str(layer))
|
1050
|
+
|
1051
|
+
elif op == Modif_Type.ROAD:
|
1052
|
+
# Create a buffer around the roads
|
1053
|
+
df1=df.buffer(distance=6, cap_style=2)
|
1054
|
+
|
1055
|
+
if df1.shape[0] > 0:
|
1056
|
+
assert set(df1.geom_type) == {'Polygon'}, f"The layer does not contains polygons - {op}"
|
1057
|
+
df1.to_file(output_file, engine=ENGINE)
|
1058
|
+
else:
|
1059
|
+
logging.warning("No data found for layer " + str(layer))
|
1060
|
+
|
1061
|
+
elif op == Modif_Type.COPY:
|
1062
|
+
# just copy the data if it is polygons
|
1063
|
+
if manager.is_polygons(set(df.geom_type)):
|
1064
|
+
df.to_file(output_file, engine=ENGINE)
|
1065
|
+
else:
|
1066
|
+
logging.error("The layer does not contains polygons - " + str(layer))
|
1067
|
+
else:
|
1068
|
+
raise ValueError(f"The operand {op} is not recognized")
|
1069
|
+
|
1070
|
+
return "Data modification done for " + str(layer)
|
1071
|
+
else:
|
1072
|
+
# Normally, phase 1 does not create empty files
|
1073
|
+
# But it is better to check... ;-)
|
1074
|
+
logging.error("skipped" + str(layer) + "due to no polygon in the study area")
|
1075
|
+
return "skipped" + str(layer) + "due to no polygon in the study area"
|
1076
|
+
|
1077
|
+
def compute_vulnerability(manager:Accept_Manager):
|
802
1078
|
"""
|
803
1079
|
Compute the vulnerability for the Study Area
|
804
1080
|
|
@@ -807,45 +1083,77 @@ def Comp_Vulnerability(dirsnames:Accept_Manager):
|
|
807
1083
|
:param dirsnames: the Dirs_Names object from the calling function
|
808
1084
|
"""
|
809
1085
|
|
810
|
-
|
811
|
-
|
1086
|
+
vuln_csv = Vulnerability_csv(manager.VULNERABILITY_CSV)
|
1087
|
+
|
1088
|
+
rasters_vuln = manager.get_files_in_rasters_vulne()
|
812
1089
|
|
813
1090
|
logging.info("Number of files",len(rasters_vuln))
|
814
1091
|
|
815
|
-
ds:gdal.Dataset = gdal.
|
816
|
-
ds1:gdal.Dataset = gdal.Open(str(rasters_code[0]))
|
1092
|
+
ds:gdal.Dataset = gdal.OpenEx(str(rasters_vuln[0]), gdal.GA_ReadOnly, open_options=["SPARSE_OK=TRUE"])
|
817
1093
|
|
818
|
-
tmp_vuln =
|
819
|
-
tmp_code = np.array(ds1.GetRasterBand(1).ReadAsArray())
|
1094
|
+
tmp_vuln = ds.GetRasterBand(1)
|
820
1095
|
|
821
|
-
|
1096
|
+
# REMARK: The XSize and YSize are the number of columns and rows
|
1097
|
+
col, row = tmp_vuln.XSize, tmp_vuln.YSize
|
822
1098
|
|
823
1099
|
logging.info("Computing Vulnerability")
|
824
1100
|
|
825
|
-
array_vuln = np.
|
826
|
-
|
827
|
-
|
828
|
-
|
1101
|
+
array_vuln = np.ones((row, col), dtype=np.int8)
|
1102
|
+
|
1103
|
+
# Create a JIT function to update the arrays
|
1104
|
+
# Faster than the classical Python loop or Numpy
|
1105
|
+
@nb.jit(nopython=True, boundscheck=False, inline='always')
|
1106
|
+
# @cuda.jit(device=True, inline=True)
|
1107
|
+
def update_arrays_jit(tmp_vuln, array_vuln):
|
1108
|
+
for i in range(tmp_vuln.shape[0]):
|
1109
|
+
for j in range(tmp_vuln.shape[1]):
|
1110
|
+
if tmp_vuln[i, j] >= array_vuln[i, j]:
|
1111
|
+
array_vuln[i, j] = tmp_vuln[i, j]
|
1112
|
+
|
1113
|
+
return array_vuln
|
1114
|
+
|
1115
|
+
@nb.jit(nopython=True, boundscheck=False, inline='always')
|
1116
|
+
# @cuda.jit(device=True, inline=True)
|
1117
|
+
def update_arrays_jit_coo(row, col, locvuln, array_vuln):
|
1118
|
+
for i,j in zip(row, col):
|
1119
|
+
if locvuln >= array_vuln[i, j]:
|
1120
|
+
array_vuln[i, j] = locvuln
|
1121
|
+
|
1122
|
+
return array_vuln
|
1123
|
+
|
1124
|
+
for i in tqdm(range(len(rasters_vuln)), 'Computing Vulnerability : '):
|
829
1125
|
logging.info("Computing layer {} / {}".format(i, len(rasters_vuln)))
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
1126
|
+
|
1127
|
+
locvuln = vuln_csv.get_vulnerability_level(rasters_vuln[i].stem)
|
1128
|
+
|
1129
|
+
if locvuln == 1:
|
1130
|
+
logging.info("No need to apply the matrice, the vulnerability is 1 which is the lower value")
|
1131
|
+
continue
|
1132
|
+
|
1133
|
+
if rasters_vuln[i].with_suffix('.npz').exists():
|
1134
|
+
ij_npz = np.load(rasters_vuln[i].with_suffix('.npz'))
|
1135
|
+
ii = ij_npz['row']
|
1136
|
+
jj = ij_npz['col']
|
1137
|
+
# We use the jit
|
1138
|
+
update_arrays_jit_coo(ii, jj, locvuln, array_vuln)
|
1139
|
+
|
1140
|
+
else:
|
1141
|
+
ds = gdal.OpenEx(str(rasters_vuln[i]), open_options=["SPARSE_OK=TRUE"])
|
1142
|
+
tmp_vuln = ds.GetRasterBand(1).ReadAsArray()
|
1143
|
+
# We use the jit
|
1144
|
+
update_arrays_jit(tmp_vuln, array_vuln)
|
843
1145
|
|
844
|
-
|
1146
|
+
logging.info("Saving the computed vulnerability")
|
1147
|
+
dst_filename= str(manager.SA_VULN)
|
845
1148
|
y_pixels, x_pixels = array_vuln.shape # number of pixels in x
|
846
1149
|
|
847
1150
|
driver = gdal.GetDriverByName('GTiff')
|
848
|
-
dataset = driver.Create(dst_filename,
|
1151
|
+
dataset = driver.Create(dst_filename,
|
1152
|
+
x_pixels, y_pixels,
|
1153
|
+
gdal.GDT_Byte,
|
1154
|
+
1,
|
1155
|
+
options=["COMPRESS=LZW"])
|
1156
|
+
|
849
1157
|
dataset.GetRasterBand(1).WriteArray(array_vuln.astype(np.int8))
|
850
1158
|
# follow code is adding GeoTranform and Projection
|
851
1159
|
geotrans = ds.GetGeoTransform() # get GeoTranform from existed 'data0'
|
@@ -855,11 +1163,83 @@ def Comp_Vulnerability(dirsnames:Accept_Manager):
|
|
855
1163
|
dataset.FlushCache()
|
856
1164
|
dataset = None
|
857
1165
|
|
1166
|
+
logging.info("Computed Vulnerability for the Study Area - Done")
|
1167
|
+
|
1168
|
+
def compute_code(manager:Accept_Manager):
|
1169
|
+
"""
|
1170
|
+
Compute the code for the Study Area
|
1171
|
+
|
1172
|
+
This function **will not modify** the data by the removed buildings/scenarios.
|
1173
|
+
|
1174
|
+
:param dirsnames: the Dirs_Names object from the calling function
|
1175
|
+
"""
|
1176
|
+
|
1177
|
+
vuln_csv = Vulnerability_csv(manager.VULNERABILITY_CSV)
|
1178
|
+
|
1179
|
+
rasters_code = manager.get_files_in_rasters_code()
|
1180
|
+
|
1181
|
+
logging.info("Number of files",len(rasters_code))
|
1182
|
+
|
1183
|
+
ds:gdal.Dataset = gdal.OpenEx(str(rasters_code[0]), gdal.GA_ReadOnly, open_options=["SPARSE_OK=TRUE"])
|
1184
|
+
|
1185
|
+
tmp_code = ds.GetRasterBand(1)
|
858
1186
|
|
859
|
-
|
1187
|
+
# REMARK: The XSize and YSize are the number of columns and rows
|
1188
|
+
col, row = tmp_code.XSize, tmp_code.YSize
|
1189
|
+
|
1190
|
+
logging.info("Computing Code")
|
1191
|
+
|
1192
|
+
array_code = np.ones((row, col), dtype=np.int8)
|
1193
|
+
|
1194
|
+
# Create a JIT function to update the arrays
|
1195
|
+
# Faster than the classical Python loop or Numpy
|
1196
|
+
@nb.jit(nopython=True, boundscheck=False, inline='always')
|
1197
|
+
# @cuda.jit(device=True, inline=True)
|
1198
|
+
def update_arrays_jit(tmp_code, loccode, array_code):
|
1199
|
+
for i in range(tmp_code.shape[0]):
|
1200
|
+
for j in range(tmp_code.shape[1]):
|
1201
|
+
if tmp_code[i, j] >= array_code[i, j]:
|
1202
|
+
array_code[i, j] = loccode
|
1203
|
+
|
1204
|
+
return array_code
|
1205
|
+
|
1206
|
+
@nb.jit(nopython=True, boundscheck=False, inline='always')
|
1207
|
+
# @cuda.jit(device=True, inline=True)
|
1208
|
+
def update_arrays_jit_coo(row, col, loccode, array_code):
|
1209
|
+
for i,j in zip(row, col):
|
1210
|
+
if loccode >= array_code[i, j]:
|
1211
|
+
array_code[i, j] = loccode
|
1212
|
+
|
1213
|
+
return array_code
|
1214
|
+
|
1215
|
+
for i in tqdm(range(len(rasters_code)), 'Computing Code : '):
|
1216
|
+
logging.info("Computing layer {} / {}".format(i, len(rasters_code)))
|
1217
|
+
|
1218
|
+
loccode = vuln_csv.get_vulnerability_code(rasters_code[i].stem)
|
1219
|
+
|
1220
|
+
if rasters_code[i].with_suffix('.npz').exists():
|
1221
|
+
ij_npz = np.load(rasters_code[i].with_suffix('.npz'))
|
1222
|
+
ii = ij_npz['row']
|
1223
|
+
jj = ij_npz['col']
|
1224
|
+
# We use the jit
|
1225
|
+
update_arrays_jit_coo(ii, jj, loccode, array_code)
|
1226
|
+
|
1227
|
+
else:
|
1228
|
+
ds = gdal.OpenEx(str(rasters_code[i]), open_options=["SPARSE_OK=TRUE"])
|
1229
|
+
tmp_code = ds.GetRasterBand(1).ReadAsArray()
|
1230
|
+
# We use the jit
|
1231
|
+
update_arrays_jit(tmp_code, loccode, array_code)
|
1232
|
+
|
1233
|
+
logging.info("Saving the computed codes")
|
1234
|
+
dst_filename= str(manager.SA_CODE)
|
860
1235
|
y_pixels, x_pixels = array_code.shape # number of pixels in x
|
861
1236
|
driver = gdal.GetDriverByName('GTiff')
|
862
|
-
dataset = driver.Create(dst_filename,
|
1237
|
+
dataset = driver.Create(dst_filename,
|
1238
|
+
x_pixels, y_pixels,
|
1239
|
+
gdal.GDT_Byte,
|
1240
|
+
1,
|
1241
|
+
options=["COMPRESS=LZW"])
|
1242
|
+
|
863
1243
|
dataset.GetRasterBand(1).WriteArray(array_code.astype(np.int8))
|
864
1244
|
# follow code is adding GeoTranform and Projection
|
865
1245
|
geotrans = ds.GetGeoTransform() # get GeoTranform from existed 'data0'
|
@@ -869,9 +1249,9 @@ def Comp_Vulnerability(dirsnames:Accept_Manager):
|
|
869
1249
|
dataset.FlushCache()
|
870
1250
|
dataset = None
|
871
1251
|
|
872
|
-
logging.info("Computed
|
1252
|
+
logging.info("Computed Code for the Study Area - Done")
|
873
1253
|
|
874
|
-
def
|
1254
|
+
def compute_vulnerability4scenario(manager:Accept_Manager):
|
875
1255
|
""" Compute the vulnerability for the scenario
|
876
1256
|
|
877
1257
|
This function **will modify** the data by the removed buildings/scenarios.
|
@@ -881,16 +1261,16 @@ def Comp_Vulnerability_Scen(dirsnames:Accept_Manager):
|
|
881
1261
|
:param dirsnames: the Dirs_Names object from the calling function
|
882
1262
|
"""
|
883
1263
|
|
884
|
-
array_vuln = gdal.Open(str(
|
1264
|
+
array_vuln = gdal.Open(str(manager.SA_VULN))
|
885
1265
|
geotrans = array_vuln.GetGeoTransform() # get GeoTranform from existed 'data0'
|
886
1266
|
proj = array_vuln.GetProjection() # you can get from a exsited tif or import
|
887
1267
|
|
888
1268
|
array_vuln = np.array(array_vuln.GetRasterBand(1).ReadAsArray())
|
889
1269
|
|
890
|
-
array_code = gdal.Open(str(
|
1270
|
+
array_code = gdal.Open(str(manager.SA_CODE))
|
891
1271
|
array_code = np.array(array_code.GetRasterBand(1).ReadAsArray())
|
892
1272
|
|
893
|
-
Rbu =
|
1273
|
+
Rbu = manager.get_files_in_rm_buildings()
|
894
1274
|
|
895
1275
|
if len(Rbu)>0:
|
896
1276
|
for curfile in Rbu:
|
@@ -901,7 +1281,7 @@ def Comp_Vulnerability_Scen(dirsnames:Accept_Manager):
|
|
901
1281
|
array_vuln[ij] = 1
|
902
1282
|
array_code[ij] = 1
|
903
1283
|
|
904
|
-
dst_filename= str(
|
1284
|
+
dst_filename= str(manager.TMP_VULN)
|
905
1285
|
y_pixels, x_pixels = array_vuln.shape # number of pixels in x
|
906
1286
|
|
907
1287
|
driver = gdal.GetDriverByName('GTiff')
|
@@ -914,7 +1294,7 @@ def Comp_Vulnerability_Scen(dirsnames:Accept_Manager):
|
|
914
1294
|
dataset = None
|
915
1295
|
|
916
1296
|
|
917
|
-
dst_filename= str(
|
1297
|
+
dst_filename= str(manager.TMP_CODE)
|
918
1298
|
y_pixels, x_pixels = array_code.shape # number of pixels in x
|
919
1299
|
driver = gdal.GetDriverByName('GTiff')
|
920
1300
|
dataset = driver.Create(dst_filename, x_pixels, y_pixels, gdal.GDT_Byte, 1, options=["COMPRESS=LZW"])
|
@@ -925,9 +1305,9 @@ def Comp_Vulnerability_Scen(dirsnames:Accept_Manager):
|
|
925
1305
|
dataset.FlushCache()
|
926
1306
|
dataset = None
|
927
1307
|
|
928
|
-
logging.info("Computed Vulnerability for the scenario")
|
1308
|
+
logging.info("Computed Vulnerability and code for the scenario")
|
929
1309
|
|
930
|
-
def
|
1310
|
+
def match_vulnerability2sim(inRas:Path, outRas:Path, MODREC:Path):
|
931
1311
|
"""
|
932
1312
|
Clip the raster to the MODREC/simulation extent
|
933
1313
|
|
@@ -951,7 +1331,7 @@ def match_vuln_modrec(inRas:Path, outRas:Path, MODREC:Path):
|
|
951
1331
|
ds = gdal.Translate(outRas, ds, projWin = [minx, maxy, maxx, miny])
|
952
1332
|
ds = None
|
953
1333
|
|
954
|
-
def
|
1334
|
+
def compute_acceptability(manager:Accept_Manager,
|
955
1335
|
model_h:np.ndarray,
|
956
1336
|
vulnerability:np.ndarray,
|
957
1337
|
interval:int,
|
@@ -973,7 +1353,7 @@ def VulMod(dirsnames:Accept_Manager,
|
|
973
1353
|
|
974
1354
|
logging.info(interval)
|
975
1355
|
|
976
|
-
Qfile = pd.read_csv(
|
1356
|
+
Qfile = pd.read_csv(manager.POINTS_CSV)
|
977
1357
|
|
978
1358
|
Qfile = Qfile[Qfile["Interval"]==interval]
|
979
1359
|
Qfile = Qfile.reset_index()
|
@@ -1003,7 +1383,7 @@ def VulMod(dirsnames:Accept_Manager,
|
|
1003
1383
|
accept[ij[0][loc_ij], ij[1][loc_ij]] = loc_accept[idx]
|
1004
1384
|
|
1005
1385
|
#save raster
|
1006
|
-
dst_filename = str(
|
1386
|
+
dst_filename = str(manager.TMP_QFILES / "Q{}.tif".format(interval))
|
1007
1387
|
|
1008
1388
|
y_pixels, x_pixels = accept.shape # number of pixels in x
|
1009
1389
|
driver = gdal.GetDriverByName('GTiff')
|
@@ -1018,7 +1398,12 @@ def VulMod(dirsnames:Accept_Manager,
|
|
1018
1398
|
|
1019
1399
|
def shp_to_raster(vector_fn:str, raster_fn:str, pixel_size:float = 1.):
|
1020
1400
|
"""
|
1021
|
-
Convert a vector layer to a raster tiff file
|
1401
|
+
Convert a vector layer to a raster tiff file.
|
1402
|
+
|
1403
|
+
The raster will contain only 2 values : 0 and 1
|
1404
|
+
|
1405
|
+
- 1 : the inside of the vector layer
|
1406
|
+
- 0 : the rest == NoData/NullValue
|
1022
1407
|
|
1023
1408
|
:param vector_fn: the path to the vector file
|
1024
1409
|
:param raster_fn: the path to the raster file
|
@@ -1029,7 +1414,7 @@ def shp_to_raster(vector_fn:str, raster_fn:str, pixel_size:float = 1.):
|
|
1029
1414
|
vector_fn = str(vector_fn)
|
1030
1415
|
raster_fn = str(raster_fn)
|
1031
1416
|
|
1032
|
-
NoData_value = np.nan
|
1417
|
+
NoData_value = 0 # np.nan is not necessary a good idea
|
1033
1418
|
# Open the data sources and read the extents
|
1034
1419
|
source_ds = ogr.Open(vector_fn)
|
1035
1420
|
source_layer = source_ds.GetLayer()
|
@@ -1043,8 +1428,13 @@ def shp_to_raster(vector_fn:str, raster_fn:str, pixel_size:float = 1.):
|
|
1043
1428
|
# Create the destination data source
|
1044
1429
|
x_res = int((x_max - x_min) / pixel_size)
|
1045
1430
|
y_res = int((y_max - y_min) / pixel_size)
|
1046
|
-
|
1047
|
-
|
1431
|
+
|
1432
|
+
target_ds = gdal.GetDriverByName('GTiff').Create(raster_fn,
|
1433
|
+
x_res, y_res,
|
1434
|
+
1,
|
1435
|
+
gdal.GDT_Byte,
|
1436
|
+
options=["COMPRESS=LZW",
|
1437
|
+
'SPARSE_OK=TRUE'])
|
1048
1438
|
|
1049
1439
|
target_ds.SetGeoTransform((x_min, pixel_size, 0, y_max, 0, -pixel_size))
|
1050
1440
|
srs = osr.SpatialReference()
|
@@ -1053,6 +1443,92 @@ def shp_to_raster(vector_fn:str, raster_fn:str, pixel_size:float = 1.):
|
|
1053
1443
|
band = target_ds.GetRasterBand(1)
|
1054
1444
|
band.SetNoDataValue(NoData_value)
|
1055
1445
|
# Rasterize the areas
|
1056
|
-
gdal.RasterizeLayer(target_ds,
|
1446
|
+
gdal.RasterizeLayer(target_ds,
|
1447
|
+
bands = [1],
|
1448
|
+
layer = source_layer,
|
1449
|
+
burn_values = [1],
|
1450
|
+
options=["ALL_TOUCHED=TRUE"])
|
1057
1451
|
target_ds = None
|
1058
1452
|
vector_fn = raster_fn = None
|
1453
|
+
|
1454
|
+
def vector_to_raster(layer:str,
|
1455
|
+
manager:Accept_Manager,
|
1456
|
+
attribute:str,
|
1457
|
+
pixel_size:float,
|
1458
|
+
convert_to_sparse:bool = True):
|
1459
|
+
"""
|
1460
|
+
Convert a vector layer to a raster tiff file
|
1461
|
+
|
1462
|
+
:param layer: the layer name in the GDB file
|
1463
|
+
:param vector_input: the path to the vector file
|
1464
|
+
:param extent: the path to the extent file
|
1465
|
+
:param attribute: the attribute to rasterize
|
1466
|
+
:param pixel_size: the pixel size of the raster
|
1467
|
+
|
1468
|
+
"""
|
1469
|
+
|
1470
|
+
layer = str(layer)
|
1471
|
+
|
1472
|
+
vector_input = str(manager.TMP_CODEVULNE / (layer + EXTENT))
|
1473
|
+
extent = str(manager.SA)
|
1474
|
+
attribute = str(attribute)
|
1475
|
+
pixel_size = float(pixel_size)
|
1476
|
+
|
1477
|
+
out_file = manager.TMP_RASTERS / attribute / (layer + ".tiff")
|
1478
|
+
|
1479
|
+
if out_file.exists():
|
1480
|
+
os.remove(out_file)
|
1481
|
+
|
1482
|
+
out_file = str(out_file)
|
1483
|
+
|
1484
|
+
NoData_value = 0
|
1485
|
+
|
1486
|
+
extent_ds:ogr.DataSource = ogr.Open(extent)
|
1487
|
+
extent_layer = extent_ds.GetLayer()
|
1488
|
+
|
1489
|
+
x_min, x_max, y_min, y_max = extent_layer.GetExtent()
|
1490
|
+
|
1491
|
+
x_min = float(int(x_min))
|
1492
|
+
x_max = float(np.ceil(x_max))
|
1493
|
+
y_min = float(int(y_min))
|
1494
|
+
y_max = float(np.ceil(y_max))
|
1495
|
+
|
1496
|
+
# Open the data sources and read the extents
|
1497
|
+
source_ds:ogr.DataSource = ogr.Open(vector_input)
|
1498
|
+
if source_ds is None:
|
1499
|
+
logging.error(f"Could not open the data source {layer}")
|
1500
|
+
return
|
1501
|
+
source_layer = source_ds.GetLayer()
|
1502
|
+
|
1503
|
+
# Create the destination data source
|
1504
|
+
x_res = int((x_max - x_min) / pixel_size)
|
1505
|
+
y_res = int((y_max - y_min) / pixel_size)
|
1506
|
+
target_ds:gdal.Driver = gdal.GetDriverByName('GTiff').Create(out_file,
|
1507
|
+
x_res, y_res, 1,
|
1508
|
+
gdal.GDT_Byte,
|
1509
|
+
options=["COMPRESS=DEFLATE",
|
1510
|
+
'SPARSE_OK=TRUE',])
|
1511
|
+
|
1512
|
+
target_ds.SetGeoTransform((x_min, pixel_size, 0, y_max, 0, -pixel_size))
|
1513
|
+
srs = osr.SpatialReference()
|
1514
|
+
srs.ImportFromEPSG(31370)
|
1515
|
+
target_ds.SetProjection(srs.ExportToWkt())
|
1516
|
+
|
1517
|
+
band = target_ds.GetRasterBand(1)
|
1518
|
+
band.SetNoDataValue(NoData_value)
|
1519
|
+
|
1520
|
+
# Rasterize the areas
|
1521
|
+
gdal.RasterizeLayer(target_ds, [1],
|
1522
|
+
source_layer,
|
1523
|
+
options=["ATTRIBUTE="+attribute,
|
1524
|
+
"ALL_TOUCHED=TRUE"])
|
1525
|
+
|
1526
|
+
if convert_to_sparse:
|
1527
|
+
# Convert the raster to a npz containing the row and col of the non-null values
|
1528
|
+
array = band.ReadAsArray()
|
1529
|
+
ij = np.nonzero(array)
|
1530
|
+
np.savez_compressed(Path(out_file).with_suffix('.npz'), row=ij[0].astype(np.int32), col=ij[1].astype(np.int32))
|
1531
|
+
|
1532
|
+
target_ds = None
|
1533
|
+
|
1534
|
+
return 0
|