wolfhece 2.2.38__py3-none-any.whl → 2.2.39__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/Coordinates_operations.py +5 -0
- wolfhece/GraphNotebook.py +72 -1
- wolfhece/GraphProfile.py +1 -1
- wolfhece/MulticriteriAnalysis.py +1579 -0
- wolfhece/PandasGrid.py +62 -1
- wolfhece/PyCrosssections.py +194 -43
- wolfhece/PyDraw.py +891 -73
- wolfhece/PyGui.py +913 -72
- wolfhece/PyGuiHydrology.py +528 -74
- wolfhece/PyPalette.py +26 -4
- wolfhece/PyParams.py +33 -0
- wolfhece/PyPictures.py +2 -2
- wolfhece/PyVertex.py +25 -0
- wolfhece/PyVertexvectors.py +94 -28
- wolfhece/PyWMS.py +52 -36
- wolfhece/acceptability/acceptability.py +15 -8
- wolfhece/acceptability/acceptability_gui.py +507 -360
- wolfhece/acceptability/func.py +80 -183
- wolfhece/apps/version.py +1 -1
- wolfhece/compare_series.py +480 -0
- wolfhece/drawing_obj.py +12 -1
- wolfhece/hydrology/Catchment.py +228 -162
- wolfhece/hydrology/Internal_variables.py +43 -2
- wolfhece/hydrology/Models_characteristics.py +69 -67
- wolfhece/hydrology/Optimisation.py +893 -182
- wolfhece/hydrology/PyWatershed.py +267 -165
- wolfhece/hydrology/SubBasin.py +185 -140
- wolfhece/hydrology/cst_exchanges.py +76 -1
- wolfhece/hydrology/forcedexchanges.py +413 -49
- wolfhece/hydrology/read.py +65 -5
- wolfhece/hydrometry/kiwis.py +14 -7
- wolfhece/insyde_be/INBE_func.py +746 -0
- wolfhece/insyde_be/INBE_gui.py +1776 -0
- wolfhece/insyde_be/__init__.py +3 -0
- wolfhece/interpolating_raster.py +366 -0
- wolfhece/irm_alaro.py +1457 -0
- wolfhece/irm_qdf.py +889 -57
- wolfhece/lifewatch.py +6 -3
- wolfhece/picc.py +124 -8
- wolfhece/pyLandUseFlanders.py +146 -0
- wolfhece/pydownloader.py +2 -1
- wolfhece/pywalous.py +225 -31
- wolfhece/toolshydrology_dll.py +149 -0
- wolfhece/wolf_array.py +63 -25
- {wolfhece-2.2.38.dist-info → wolfhece-2.2.39.dist-info}/METADATA +3 -1
- {wolfhece-2.2.38.dist-info → wolfhece-2.2.39.dist-info}/RECORD +49 -40
- {wolfhece-2.2.38.dist-info → wolfhece-2.2.39.dist-info}/WHEEL +0 -0
- {wolfhece-2.2.38.dist-info → wolfhece-2.2.39.dist-info}/entry_points.txt +0 -0
- {wolfhece-2.2.38.dist-info → wolfhece-2.2.39.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,366 @@
|
|
1
|
+
from pathlib import Path
|
2
|
+
import pandas as pd
|
3
|
+
import numpy as np
|
4
|
+
import math
|
5
|
+
import logging
|
6
|
+
import os
|
7
|
+
import subprocess
|
8
|
+
import shutil
|
9
|
+
import rasterio
|
10
|
+
from scipy.ndimage import label
|
11
|
+
|
12
|
+
from .PyTranslate import _
|
13
|
+
from .wolf_array import WolfArray, header_wolf
|
14
|
+
from .Results2DGPU import wolfres2DGPU
|
15
|
+
from .eikonal import inpaint_waterlevel, inpaint_array
|
16
|
+
|
17
|
+
|
18
|
+
class interpolating_raster():
|
19
|
+
def __init__(self):
|
20
|
+
pass
|
21
|
+
|
22
|
+
def nullvalue_for_hole(self, WA):
|
23
|
+
"""
|
24
|
+
Sets the null value for a WolfArray to 0 (as per the convention in the interpolation routine).
|
25
|
+
"""
|
26
|
+
WA.nullvalue = 0.
|
27
|
+
WA.set_nullvalue_in_mask()
|
28
|
+
|
29
|
+
def export_z_or_v_bin(self, fn_read, manager, name, type_hazard="z", type_extraction="danger_map", param_danger = [0,-1,1], threshold:float=0.01):
|
30
|
+
"""
|
31
|
+
Reads the free surface altitude from a GPU simulation and exports it in binary format.
|
32
|
+
|
33
|
+
:param str fn_read_simu: The simulation file to read.
|
34
|
+
:param str fn_laststep: The folder ``EXTRACTED_LAST_STEP`` defined in acceptability/INBE.
|
35
|
+
:param list param_danger: The time step to extract the results gpu (in order :) to start / end / every X
|
36
|
+
:param str fn_write: The path to save the output in binary format.
|
37
|
+
:param str type_hazard: Either ``'z'`` for water level only, or ``'z_v'`` for water level and velocity.
|
38
|
+
"""
|
39
|
+
where_wd = Path(manager.IN_SA_EXTRACTED)
|
40
|
+
fn_write = Path(where_wd / name )
|
41
|
+
if type_extraction == "last_step":
|
42
|
+
wolfres2DGPU_test = wolfres2DGPU(fn_read, eps = threshold)
|
43
|
+
wolfres2DGPU_test.read_oneresult(-1)
|
44
|
+
wd = wolfres2DGPU_test.get_h_for_block(1)
|
45
|
+
#wd.array[wd.array < threshold] = wd.nullvalue
|
46
|
+
top = wolfres2DGPU_test.get_top_for_block(1)
|
47
|
+
#i, j = np.where(wd.array < threshold)
|
48
|
+
#top.array[i, j] = top.nullvalue
|
49
|
+
self.nullvalue_for_hole(wd)
|
50
|
+
self.nullvalue_for_hole(top)
|
51
|
+
wd.array = wd.array + top.array
|
52
|
+
fn_write = fn_write.with_suffix('.bin')
|
53
|
+
wd.write_all(fn_write)
|
54
|
+
else:
|
55
|
+
if type_hazard == "z" :
|
56
|
+
danger_maps = wolfres2DGPU(fn_read, eps = threshold).danger_map_only_h(param_danger[0], param_danger[1], param_danger[2])
|
57
|
+
fn_write = fn_write.with_suffix('.bin')
|
58
|
+
danger_maps.write_all(fn_write)
|
59
|
+
if type_hazard == "z_v" :
|
60
|
+
danger_maps = wolfres2DGPU(fn_read, eps = threshold).danger_map(param_danger[0], param_danger[1], param_danger[2])
|
61
|
+
fn_write = fn_write.with_suffix('.bin')
|
62
|
+
danger_maps[3].write_all(fn_write)
|
63
|
+
|
64
|
+
where_v = manager.IN_SCEN_DIR_V
|
65
|
+
where_v = Path(where_v) / f"v_danger_{name}_{manager.scenario}.tif"
|
66
|
+
danger_maps[1].write_all(where_v)
|
67
|
+
|
68
|
+
def riverbed_trace(self, fn_read_simu, fn_output, threshold, type_extraction="danger_map"):
|
69
|
+
"""
|
70
|
+
Recognizes the riverbed trace based on a simulation, where water depth above a given threshold is considered part of the riverbed.
|
71
|
+
|
72
|
+
:param str fn_read_simu: The simulation file to read.
|
73
|
+
:param str fn_output: The location to save the riverbed trace as a ``.tiff`` file.
|
74
|
+
:param float threshold: The water depth threshold above which the areas are considered riverbed.
|
75
|
+
"""
|
76
|
+
|
77
|
+
if type_extraction == "last_step":
|
78
|
+
wolfres2DGPU_test = wolfres2DGPU(fn_read_simu)
|
79
|
+
wolfres2DGPU_test.read_oneresult(-1)
|
80
|
+
wd = wolfres2DGPU_test.get_h_for_block(1)
|
81
|
+
wd.array[wd.array > 1000] = 0
|
82
|
+
wd.array[wd.array > threshold] = 1
|
83
|
+
wd.array[wd.array < threshold] = 0
|
84
|
+
wd.as_WolfArray()
|
85
|
+
wd.nodata=0
|
86
|
+
wd.write_all(Path(fn_output))
|
87
|
+
|
88
|
+
else:
|
89
|
+
wd = wolfres2DGPU(fn_read_simu).danger_map_only_h(0,-1,1)
|
90
|
+
wd.array[wd.array > 1000] = 0
|
91
|
+
wd.array[wd.array > threshold] = 1
|
92
|
+
wd.array[wd.array < threshold] = 0
|
93
|
+
wd.as_WolfArray()
|
94
|
+
wd.nodata=0
|
95
|
+
wd.write_all(Path(fn_output))
|
96
|
+
|
97
|
+
|
98
|
+
def empty_folder(self, folder):
|
99
|
+
"""
|
100
|
+
Empties the content of a directory if it exists.
|
101
|
+
"""
|
102
|
+
if os.path.exists(folder):
|
103
|
+
for files in os.listdir(folder):
|
104
|
+
fn = os.path.join(folder, files)
|
105
|
+
try:
|
106
|
+
if os.path.isfile(fn) or os.path.islink(fn):
|
107
|
+
os.unlink(fn)
|
108
|
+
elif os.path.isdir(fn):
|
109
|
+
shutil.rmtree(fn)
|
110
|
+
except Exception as e:
|
111
|
+
print(f"Error when deleting file {fn}: {e}")
|
112
|
+
else:
|
113
|
+
print("The folder does not exist.")
|
114
|
+
|
115
|
+
"""
|
116
|
+
This script performs two main operations:
|
117
|
+
|
118
|
+
1. Subtraction of two raster TIFF files:
|
119
|
+
- Identifies areas with building traces by subtracting the `bathymetry.tif` from simulations
|
120
|
+
(corresponding to 'MNT_muret_bati') from `MNT` (DEM).
|
121
|
+
|
122
|
+
2. For the identified building areas (from step 1):
|
123
|
+
- Replace the values with those from the `MNT` (ground level), ensuring it reflects the terrain, not bathymetry values.
|
124
|
+
|
125
|
+
Final Output:
|
126
|
+
- The mask should highlight building traces with corresponding DEM (`MNT`) values ("ground") inside, and its name must start with "MNT_" and include "mask" in it.
|
127
|
+
|
128
|
+
Note: the computations are perfomed with tifs .tif rasters but should be translated to .bin files in the acceptability routine
|
129
|
+
"""
|
130
|
+
|
131
|
+
#----------------------------------------------------------------------------------------------------------
|
132
|
+
|
133
|
+
#1 - Soustraction bathymetry.tif (from simulations) - DEM (MNT, cfr "projet tuilage") ---------------------
|
134
|
+
|
135
|
+
def soustraction(self, fn_a, fn_b,fn_result):
|
136
|
+
with rasterio.open(fn_a) as src_a, rasterio.open(fn_b) as src_b:
|
137
|
+
if (
|
138
|
+
src_a.width != src_b.width or
|
139
|
+
src_a.height != src_b.height or
|
140
|
+
src_a.transform != src_b.transform or
|
141
|
+
src_a.crs != src_b.crs
|
142
|
+
):
|
143
|
+
logging.error(f"{fn_a} and {fn_b} do not have the same properties, please edit them.")
|
144
|
+
|
145
|
+
|
146
|
+
data_a = src_a.read(1)
|
147
|
+
data_b = src_b.read(1)
|
148
|
+
|
149
|
+
#(A - B)
|
150
|
+
data_diff = data_a - data_b
|
151
|
+
nodata_value = src_a.nodata if src_a.nodata == src_b.nodata else None
|
152
|
+
if nodata_value is not None:
|
153
|
+
data_diff[(data_a == nodata_value) | (data_b == nodata_value)] = nodata_value
|
154
|
+
|
155
|
+
data_diff[data_diff < 0.5] = 0 #sans ce nettoyage supplémentaire, l'interpolation devient non significative, car de petites valeurs de différence peuvent subsister (cfr simus Vesdre sur 2m).
|
156
|
+
data_diff[data_diff > 5000] = 0
|
157
|
+
labeled, n = label(data_diff)
|
158
|
+
# Remove small objects
|
159
|
+
threshold = 5
|
160
|
+
sizes = np.bincount(labeled.ravel())
|
161
|
+
idx_small = np.where(sizes <= threshold)[0]
|
162
|
+
data_diff[np.isin(labeled, idx_small)] = 0
|
163
|
+
|
164
|
+
out_meta = src_a.meta.copy()
|
165
|
+
out_meta.update({
|
166
|
+
"dtype": "float32",
|
167
|
+
"driver": "GTiff"
|
168
|
+
})
|
169
|
+
|
170
|
+
with rasterio.open(fn_result, "w", **out_meta) as dst:
|
171
|
+
dst.write(data_diff, 1)
|
172
|
+
|
173
|
+
|
174
|
+
#2 - DEM (MNT) value in the buildings traces ------------------------------------------------------------------
|
175
|
+
def mask_creation_data(self, mask_file, ground_file, output_file):
|
176
|
+
with rasterio.open(mask_file) as mask_src:
|
177
|
+
mask = mask_src.read(1).astype('float32')
|
178
|
+
mask_meta = mask_src.meta
|
179
|
+
|
180
|
+
indices = np.where(mask > 0)
|
181
|
+
|
182
|
+
with rasterio.open(ground_file) as bathy_src:
|
183
|
+
bathy = bathy_src.read(1)
|
184
|
+
|
185
|
+
mask[indices] = bathy[indices]
|
186
|
+
mask[mask <= 0] = 99999.
|
187
|
+
|
188
|
+
output_meta = mask_meta.copy()
|
189
|
+
output_meta.update({"dtype": 'float32'})
|
190
|
+
|
191
|
+
with rasterio.open(output_file, "w", **output_meta) as dst:
|
192
|
+
dst.write(mask, 1)
|
193
|
+
|
194
|
+
WA_mask = WolfArray(output_file)
|
195
|
+
WA_mask.write_all(Path(Path(output_file).parent / "MNT_computed_with_mask.bin"))
|
196
|
+
|
197
|
+
def MNT_and_mask_creation_all(self, fn_bathy, fn_mtn_cropped, fn_where_buildings, fn_mask_final):
|
198
|
+
#couper_raster()
|
199
|
+
self.soustraction(fn_bathy, fn_mtn_cropped, fn_where_buildings)
|
200
|
+
self.mask_creation_data(fn_where_buildings, fn_mtn_cropped, fn_mask_final)
|
201
|
+
|
202
|
+
def empty_folder(self, folder):
|
203
|
+
"""
|
204
|
+
Empties the content of a directory if it exists.
|
205
|
+
"""
|
206
|
+
if os.path.exists(folder):
|
207
|
+
for files in os.listdir(folder):
|
208
|
+
fn = os.path.join(folder, files)
|
209
|
+
try:
|
210
|
+
if os.path.isfile(fn) or os.path.islink(fn):
|
211
|
+
os.unlink(fn)
|
212
|
+
elif os.path.isdir(fn):
|
213
|
+
shutil.rmtree(fn)
|
214
|
+
except Exception as e:
|
215
|
+
print(f"Error when deleting file {fn}: {e}")
|
216
|
+
else:
|
217
|
+
print("The folder does not exist.")
|
218
|
+
|
219
|
+
|
220
|
+
#-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
221
|
+
#une classe qui lit les routines holes.exe, pour un répertoire d'entrée (on y placera un répertoire de danger maps OU de simu, puis danger) et de sortie (on y placera INPUT....)
|
222
|
+
# Interpolation
|
223
|
+
# -------------
|
224
|
+
|
225
|
+
def batch_creation_and_interpolation_fotran_holes(self, manager, checked_paths:list[Path], iftest:bool) -> tuple[bool, list[str]]:
|
226
|
+
"""Creates a batch file to launch holes.exe from the selected simulations and launches it.
|
227
|
+
|
228
|
+
- Every files in EXTRACTED_LAST_STEP are interpolated for tests (iftest==True).
|
229
|
+
- Only the check simulations of the windows are interpolated for the GUI (iftest!=True).
|
230
|
+
|
231
|
+
:param checked_paths: list of paths to the checked simulations
|
232
|
+
:param iftest: boolean to indicate if the function is called from the tests or not
|
233
|
+
"""
|
234
|
+
|
235
|
+
path_LastSteps = Path(manager.IN_SA_EXTRACTED)
|
236
|
+
|
237
|
+
# Identifying the DEM and its mask
|
238
|
+
C = None # DEM mask
|
239
|
+
D = None # DEM
|
240
|
+
for file in os.listdir(Path(manager.IN_SA_DEM)):
|
241
|
+
file_path = Path(manager.IN_SA_DEM) / file
|
242
|
+
if file_path.is_file() and file.startswith("MNT_") and file_path.suffix == ".bin":
|
243
|
+
if "mask" not in file:
|
244
|
+
D = file_path
|
245
|
+
else:
|
246
|
+
C = file_path
|
247
|
+
|
248
|
+
if D is None:
|
249
|
+
return logging.error(_("DEM (.bin) not found in DEM_FILES. The file must begins by 'MNT_' and CANNOT include the word 'mask'"))
|
250
|
+
|
251
|
+
if C is None:
|
252
|
+
return logging.error(_("DEM mask (.bin) not found in DEM_FILES. The file must begins by 'MNT_' and MUST include the word 'mask'"))
|
253
|
+
|
254
|
+
path_Interp = Path(manager.IN_SA_INTERP)
|
255
|
+
path_bat_file = os.path.join(manager.IN_SCEN_DIR, "process_files.bat")
|
256
|
+
|
257
|
+
if os.path.exists(path_bat_file):
|
258
|
+
logging.info(f"The file {path_bat_file} already exists and will be replaced.")
|
259
|
+
os.remove(path_bat_file)
|
260
|
+
|
261
|
+
path_code = os.path.join(manager.IN_WATER_DEPTH, "holes.exe")
|
262
|
+
|
263
|
+
A, B = [], []
|
264
|
+
if iftest:
|
265
|
+
# no checked box in the tests
|
266
|
+
A = [path_LastSteps / f for f in os.listdir(path_LastSteps) if f.endswith('.bin') and not f.endswith('.bin.txt')]
|
267
|
+
else :
|
268
|
+
for path in checked_paths:
|
269
|
+
parts = path.name.split("sim_")
|
270
|
+
A.extend([path_LastSteps / g for g in os.listdir(path_LastSteps) if g.endswith(f"{parts[1]}.bin")])
|
271
|
+
|
272
|
+
B = [path_Interp / f.stem for f in A]
|
273
|
+
|
274
|
+
if not A or not B or not C or not D:
|
275
|
+
logging.error(("Missing files."))
|
276
|
+
return None, None
|
277
|
+
|
278
|
+
with open(path_bat_file, "w") as bat_file:
|
279
|
+
for a, b in zip(A, B):
|
280
|
+
line = f'"{path_code}" filling in="{a}" out="{b}" mask="{C}" dem="{D} avoid_last=1"\n'
|
281
|
+
bat_file.write(line)
|
282
|
+
|
283
|
+
self.empty_folder(manager.IN_SA_INTERP)
|
284
|
+
path_bat_file = manager.IN_SCEN_DIR / "process_files.bat"
|
285
|
+
subprocess.run([path_bat_file], check=True)
|
286
|
+
|
287
|
+
renamed_files = []
|
288
|
+
path_fichier = manager.IN_SA_INTERP
|
289
|
+
for file in path_fichier.glob("*.tif"):
|
290
|
+
if "_h" in file.name:
|
291
|
+
new_name = file.stem.split("_h")[0].replace(".bin", "") + ".tif"
|
292
|
+
file.rename(file.with_name(new_name))
|
293
|
+
renamed_files.append(new_name)
|
294
|
+
|
295
|
+
#deleting the other
|
296
|
+
for file in path_fichier.glob("*.tif"):
|
297
|
+
if "_combl" in file.name or file.name not in renamed_files:
|
298
|
+
file.unlink()
|
299
|
+
|
300
|
+
return True, renamed_files
|
301
|
+
|
302
|
+
def batch_creation_and_interpolation_python_eikonal(self, manager, checked_paths:list[Path], iftest:bool, ifwd=False) -> tuple[bool, list[str]]:
|
303
|
+
"""Creates a batch file to launch holes.exe from the selected simulations and launches it.
|
304
|
+
|
305
|
+
- Every files in EXTRACTED_LAST_STEP are interpolated for tests (iftest==True).
|
306
|
+
- Only the check simulations of the windows are interpolated for the GUI (iftest!=True).
|
307
|
+
|
308
|
+
:param checked_paths: list of paths to the checked simulations
|
309
|
+
:param iftest: boolean to indicate if the function is called from the tests or not
|
310
|
+
"""
|
311
|
+
path_LastSteps = Path(manager.IN_SA_EXTRACTED)
|
312
|
+
# Identifying the DEM and its mask
|
313
|
+
C = None # DEM mask
|
314
|
+
D = None # DEM
|
315
|
+
for file in os.listdir(Path(manager.IN_SA_DEM)):
|
316
|
+
file_path = Path(manager.IN_SA_DEM) / file
|
317
|
+
if file_path.is_file() and file.startswith("MNT_") and file_path.suffix == ".bin":
|
318
|
+
if "mask" not in file:
|
319
|
+
D = file_path
|
320
|
+
else:
|
321
|
+
C = file_path
|
322
|
+
|
323
|
+
if D is None:
|
324
|
+
return logging.error(_("DTM (.bin) not found in DTM_FILES. The file must begins by 'MNT_' and CANNOT include the word 'mask'"))
|
325
|
+
|
326
|
+
if C is None:
|
327
|
+
return logging.error(_("DEM mask (.bin) not found in DEM_FILES. The file must begins by 'MNT_' and MUST include the word 'mask'"))
|
328
|
+
|
329
|
+
path_Interp = Path(manager.IN_SA_INTERP)
|
330
|
+
path_bat_file = os.path.join(manager.IN_SCEN_DIR, "process_files.bat")
|
331
|
+
|
332
|
+
if os.path.exists(path_bat_file):
|
333
|
+
logging.info(f"The file {path_bat_file} already exists and will be replaced.")
|
334
|
+
os.remove(path_bat_file)
|
335
|
+
|
336
|
+
A, B = [], []
|
337
|
+
if iftest:
|
338
|
+
# no checked box in the tests
|
339
|
+
A = [path_LastSteps / f for f in os.listdir(path_LastSteps) if f.endswith('.bin') and not f.endswith('.bin.txt')]
|
340
|
+
|
341
|
+
else :
|
342
|
+
for path in checked_paths:
|
343
|
+
parts = path.name.split("sim_")
|
344
|
+
A.extend([path_LastSteps / g for g in os.listdir(path_LastSteps) if g.endswith(f"{parts[1]}.bin")])
|
345
|
+
|
346
|
+
B = [path_Interp / f.stem for f in A]
|
347
|
+
if not A or not B or not C or not D:
|
348
|
+
logging.error(_("Missing files."))
|
349
|
+
return None, None
|
350
|
+
renamed_files = []
|
351
|
+
for a, b in zip(A, B):
|
352
|
+
wa_a = WolfArray(a)
|
353
|
+
wa_c = WolfArray(C)
|
354
|
+
wa_d = WolfArray(D)
|
355
|
+
_t, _d, wh = inpaint_array(data = wa_a.array,
|
356
|
+
where_compute = wa_c.array.data != wa_c.array.data[0,0],
|
357
|
+
test = wa_d.array.data,
|
358
|
+
ignore_last_patches= 1)
|
359
|
+
|
360
|
+
new_name = b.with_suffix(".tif")
|
361
|
+
if ifwd == True :
|
362
|
+
wa_a = wa_a - wa_d
|
363
|
+
wa_a.write_all(new_name)
|
364
|
+
renamed_files.append(new_name.name)
|
365
|
+
|
366
|
+
return True, renamed_files
|