wolfhece 2.2.1__py3-none-any.whl → 2.2.3__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/PandasGrid.py +67 -0
- wolfhece/PyDraw.py +671 -30
- wolfhece/PyGui.py +6 -2
- wolfhece/PyHydrographs.py +2 -3
- wolfhece/PyPalette.py +10 -0
- wolfhece/PyParams.py +2 -3
- wolfhece/PyVertex.py +7 -7
- wolfhece/PyVertexvectors.py +1 -0
- wolfhece/PyWMS.py +72 -3
- wolfhece/acceptability/Parallels.py +25 -19
- wolfhece/acceptability/acceptability_gui.py +104 -131
- wolfhece/acceptability/func.py +99 -13
- wolfhece/apps/check_install.py +6 -6
- wolfhece/apps/splashscreen.py +5 -0
- wolfhece/apps/version.py +1 -1
- wolfhece/assets/__init__.py +1 -0
- wolfhece/assets/speedometer.py +135 -0
- wolfhece/dike.py +684 -0
- wolfhece/drowning_victims/Class.py +2165 -0
- wolfhece/drowning_victims/Functions.py +1019 -0
- wolfhece/drowning_victims/__init__.py +0 -0
- wolfhece/lifewatch.py +88 -0
- wolfhece/scenario/config_manager.py +4 -4
- wolfhece/wolf_array.py +58 -33
- wolfhece/wolf_texture.py +9 -2
- {wolfhece-2.2.1.dist-info → wolfhece-2.2.3.dist-info}/METADATA +3 -1
- {wolfhece-2.2.1.dist-info → wolfhece-2.2.3.dist-info}/RECORD +30 -22
- {wolfhece-2.2.1.dist-info → wolfhece-2.2.3.dist-info}/WHEEL +0 -0
- {wolfhece-2.2.1.dist-info → wolfhece-2.2.3.dist-info}/entry_points.txt +0 -0
- {wolfhece-2.2.1.dist-info → wolfhece-2.2.3.dist-info}/top_level.txt +0 -0
wolfhece/acceptability/func.py
CHANGED
@@ -15,6 +15,7 @@ from ..PyVertexvectors import Zones, zone, vector, wolfvertex, getIfromRGB
|
|
15
15
|
from ..PyTranslate import _
|
16
16
|
from ..scenario. config_manager import Config_Manager_2D_GPU
|
17
17
|
|
18
|
+
import subprocess
|
18
19
|
import geopandas as gpd
|
19
20
|
import pandas as pd
|
20
21
|
import numpy as np
|
@@ -94,6 +95,23 @@ def cleaning_directory(dir:Path):
|
|
94
95
|
if item.is_file():
|
95
96
|
os.remove(item)
|
96
97
|
|
98
|
+
def empty_folder(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
|
+
|
97
115
|
class Accept_Manager():
|
98
116
|
"""
|
99
117
|
Structure to store the directories and names of the files.
|
@@ -608,10 +626,8 @@ class Accept_Manager():
|
|
608
626
|
for i in range(1, len(rt)-1):
|
609
627
|
# Full formula
|
610
628
|
# pond.append((1./float(rt[i-1]) - 1./float(rt[i]))/2. + (1./float(rt[i]) - 1./float(rt[i+1]))/2.)
|
611
|
-
|
612
629
|
# More compact formula
|
613
630
|
pond.append((1./float(rt[i-1]) - 1./float(rt[i+1]))/2.)
|
614
|
-
|
615
631
|
pond.append(1./float(rt[-1]) + (1./float(rt[-2]) - 1./float(rt[-1]))/2.)
|
616
632
|
|
617
633
|
return pd.DataFrame(pond, columns=["Ponderation"], index=rt)
|
@@ -898,15 +914,15 @@ class Accept_Manager():
|
|
898
914
|
|
899
915
|
if len(code) == 0:
|
900
916
|
logging.error("The code rasters do not exist")
|
901
|
-
return
|
917
|
+
return False
|
902
918
|
|
903
919
|
if len(vuln) == 0:
|
904
920
|
logging.error("The vulnerability rasters do not exist")
|
905
|
-
return
|
921
|
+
return False
|
906
922
|
|
907
923
|
if len(code) != len(vuln):
|
908
924
|
logging.error("The number of code and vulnerability rasters do not match")
|
909
|
-
return
|
925
|
+
return False
|
910
926
|
|
911
927
|
# we take a reference raster
|
912
928
|
ref = gdal.Open(str(code[0]))
|
@@ -982,14 +998,18 @@ class Accept_Manager():
|
|
982
998
|
|
983
999
|
def check_nodata(self, name, path_baseline):
|
984
1000
|
""" Check nodata in a path """
|
1001
|
+
from ..wolf_array import WOLF_ARRAY_FULL_INTEGER8
|
985
1002
|
list_tif = Accept_Manager.select_name_tif(self, path_baseline, self.IN_CH_SA_SC, name)
|
986
1003
|
for cur_lst in list_tif:
|
987
1004
|
curarray:WolfArray = WolfArray(cur_lst)
|
988
|
-
if curarray.
|
989
|
-
curarray.nullvalue
|
990
|
-
|
991
|
-
|
992
|
-
|
1005
|
+
if curarray.wolftype != WOLF_ARRAY_FULL_INTEGER8:
|
1006
|
+
if curarray.nullvalue != 99999.:
|
1007
|
+
curarray.nullvalue = 99999.
|
1008
|
+
curarray.set_nullvalue_in_mask()
|
1009
|
+
curarray.write_all()
|
1010
|
+
logging.warning(_('nodata changed in favor of 99999. value for file {} !'.format(cur_lst)))
|
1011
|
+
else:
|
1012
|
+
logging.info(_('nodata value is {} for file {} !'.format(curarray.nullvalue, cur_lst)))
|
993
1013
|
|
994
1014
|
def create_vrtIfExists(self, fn_baseline, fn_scenario, fn_vrt, name):
|
995
1015
|
""" Create a vrt file from a path """
|
@@ -1037,9 +1057,73 @@ class Accept_Manager():
|
|
1037
1057
|
else :
|
1038
1058
|
logging.error("No Masked_River_extent files. Please provide them.")
|
1039
1059
|
return trace
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1060
|
+
|
1061
|
+
# Interpolation
|
1062
|
+
# -----------------------------
|
1063
|
+
def batch_creation_and_interpolation(self, checked_paths, iftest):
|
1064
|
+
"""Creates a batch file to launch holes.exe from the selected simulations and launches it.
|
1065
|
+
-Every files in EXTRACTED_LAST_STEP are interpolated for tests (iftest==True).
|
1066
|
+
-Only the check simulations of the windows are interpolated for the GUI (iftest!=True)."""
|
1067
|
+
path_LastSteps = Path(self.IN_SA_EXTRACTED)
|
1068
|
+
C = None
|
1069
|
+
D = None
|
1070
|
+
for file in os.listdir(Path(self.IN_SA_DEM)):
|
1071
|
+
file_path = Path(self.IN_SA_DEM) / file
|
1072
|
+
if file_path.is_file() and file.startswith("MNT_") and file_path.suffix == ".bin":
|
1073
|
+
if "mask" not in file:
|
1074
|
+
D = file_path
|
1075
|
+
else:
|
1076
|
+
C = file_path
|
1077
|
+
if D == None:
|
1078
|
+
return logging.error("DEM (.bin) not found in DEM_FILES. The file must begins by 'MNT_' and CANNOT include the word 'mask'")
|
1079
|
+
|
1080
|
+
if C == None:
|
1081
|
+
return logging.error("DEM mask (.bin) not found in DEM_FILES. The file must begins by 'MNT_' and MUST include the word 'mask'")
|
1082
|
+
|
1083
|
+
path_Interp = Path(self.IN_SA_INTERP)
|
1084
|
+
path_bat_file = os.path.join(self.IN_SCEN_DIR, "process_files.bat")
|
1085
|
+
|
1086
|
+
if os.path.exists(path_bat_file):
|
1087
|
+
logging.info(f"The file {path_bat_file} already exists and will be replaced.")
|
1088
|
+
os.remove(path_bat_file)
|
1089
|
+
path_code = os.path.join(self.IN_WATER_DEPTH, "holes.exe")
|
1090
|
+
A, B = [], []
|
1091
|
+
if iftest == True:
|
1092
|
+
#no checked box in the tests
|
1093
|
+
path_Interp = Path(self.IN_SA_INTERP)
|
1094
|
+
path_LastSteps = Path(self.IN_SA_EXTRACTED)
|
1095
|
+
A = [os.path.join(path_LastSteps,f) for f in os.listdir(path_LastSteps) if f.endswith('.bin') and not f.endswith('.bin.txt')]
|
1096
|
+
B = [os.path.join(path_Interp, os.path.splitext(os.path.basename(f))[0]) for f in A]
|
1097
|
+
|
1098
|
+
else :
|
1099
|
+
for path in checked_paths:
|
1100
|
+
parts = path.name.split("sim_")
|
1101
|
+
A.extend([os.path.join(path_LastSteps, g) for g in os.listdir(path_LastSteps) if g.endswith(f"{parts[1]}.bin")])
|
1102
|
+
B = [os.path.join(path_Interp, os.path.splitext(os.path.basename(f))[0]) for f in A]
|
1103
|
+
if not A or not B or not C or not D:
|
1104
|
+
return logging.error("Missing files.")
|
1105
|
+
with open(path_bat_file, "w") as bat_file:
|
1106
|
+
for a, b in zip(A, B):
|
1107
|
+
line = f'"{path_code}" filling in="{a}" out="{b}" mask="{C}" dem="{D} avoid_last=1"\n'
|
1108
|
+
bat_file.write(line)
|
1109
|
+
|
1110
|
+
empty_folder(self.IN_SA_INTERP)
|
1111
|
+
path_bat_file = os.path.join(self.IN_SCEN_DIR, "process_files.bat")
|
1112
|
+
subprocess.run([path_bat_file], check=True)
|
1113
|
+
|
1114
|
+
renamed_files = []
|
1115
|
+
path_fichier=self.IN_SA_INTERP
|
1116
|
+
for file in path_fichier.glob("*.tif"):
|
1117
|
+
if "_h" in file.name:
|
1118
|
+
new_name = file.stem.split("_h")[0].replace(".bin", "") + ".tif"
|
1119
|
+
file.rename(file.with_name(new_name))
|
1120
|
+
renamed_files.append(new_name)
|
1121
|
+
#deleting the other
|
1122
|
+
for file in path_fichier.glob("*.tif"):
|
1123
|
+
if "_combl" in file.name or file.name not in renamed_files:
|
1124
|
+
file.unlink()
|
1125
|
+
|
1126
|
+
return True, renamed_files
|
1043
1127
|
|
1044
1128
|
def clip_layer(layer:str,
|
1045
1129
|
file_path:str,
|
@@ -1569,6 +1653,8 @@ def compute_acceptability(manager:Accept_Manager,
|
|
1569
1653
|
points_accept["h-1"][idx_pts],
|
1570
1654
|
points_accept["h-2.5"][idx_pts]]
|
1571
1655
|
|
1656
|
+
accept_pts = list(accept_pts).copy()
|
1657
|
+
|
1572
1658
|
update_accept(accept, model_h, ij, bounds, accept_pts)
|
1573
1659
|
|
1574
1660
|
if save_to_file:
|
wolfhece/apps/check_install.py
CHANGED
@@ -37,12 +37,12 @@ def main():
|
|
37
37
|
else:
|
38
38
|
ret += 'WolfGPU not installed\n Please install WolfGPU if needed\n\n'
|
39
39
|
|
40
|
-
try:
|
41
|
-
|
42
|
-
|
43
|
-
except ImportError as e:
|
44
|
-
|
45
|
-
|
40
|
+
# try:
|
41
|
+
# from ..libs import wolfpy
|
42
|
+
# ret += 'Wolfpy accessible\n\n'
|
43
|
+
# except ImportError as e:
|
44
|
+
# ret += 'Wolfpy not accessible\n\n'
|
45
|
+
# ret += 'Error : ' + str(e) + '\n\n'
|
46
46
|
|
47
47
|
try:
|
48
48
|
from ..PyGui import MapManager
|
wolfhece/apps/splashscreen.py
CHANGED
@@ -11,6 +11,11 @@ copying or distribution of this file, via any medium, is strictly prohibited.
|
|
11
11
|
"""
|
12
12
|
This is a minimal wxPython SplashScreen
|
13
13
|
"""
|
14
|
+
try:
|
15
|
+
from osgeo import gdal
|
16
|
+
except ImportError as e:
|
17
|
+
print(f"Import Error: {e} - GDAL")
|
18
|
+
print("Please install GDAL for your Python version.")
|
14
19
|
|
15
20
|
from os.path import dirname, join, exists
|
16
21
|
import wx
|
wolfhece/apps/version.py
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
from . import _add_path
|
@@ -0,0 +1,135 @@
|
|
1
|
+
import matplotlib.pyplot as plt
|
2
|
+
import numpy as np
|
3
|
+
from matplotlib.colors import LinearSegmentedColormap
|
4
|
+
|
5
|
+
|
6
|
+
|
7
|
+
class Semi_Circle_Gauge():
|
8
|
+
|
9
|
+
def __init__(self):
|
10
|
+
# Create a polar plot for the speedometer background
|
11
|
+
self.fig, self.ax = plt.subplots(figsize=(6, 3), subplot_kw={'projection': 'polar'})
|
12
|
+
self.ax.set_theta_zero_location('W')
|
13
|
+
self.ax.set_theta_direction(-1)
|
14
|
+
|
15
|
+
def plot_background(self):
|
16
|
+
# Define the ranges for red, yellow, and green
|
17
|
+
theta = np.linspace(0, np.pi, 500)
|
18
|
+
# Create metallic gradient for green with highlights for a modern effect
|
19
|
+
green_cmap = LinearSegmentedColormap.from_list(
|
20
|
+
"metallic_green", ["#003300", "#00FF00", "#66FF66", "#00FF00", "#003300"]
|
21
|
+
)
|
22
|
+
green_colors = green_cmap(np.linspace(0, 1, 500))
|
23
|
+
self.ax.fill_between(theta, 0, 1, where=(theta <= np.pi/3), color=None, alpha=0.7, facecolor=green_colors)
|
24
|
+
# green_cmap = LinearSegmentedColormap.from_list("metallic_green", ["#006400", "#00FF00", "#006400"])
|
25
|
+
# green_colors = green_cmap(np.linspace(0, 1, 500))
|
26
|
+
# ax.fill_between(theta, 0, 1, where=(theta <= np.pi/3), color=None, alpha=0.7, facecolor=green_colors)
|
27
|
+
|
28
|
+
# Create metallic gradient for yellow
|
29
|
+
yellow_cmap = LinearSegmentedColormap.from_list("metallic_yellow", ["#FFD700", "#FFFF00", "#FFD700"])
|
30
|
+
yellow_colors = yellow_cmap(np.linspace(0, 1, 500))
|
31
|
+
self.ax.fill_between(theta, 0, 1, where=((theta > np.pi/3) & (theta <= 2*np.pi/3)), color=None, alpha=0.7, facecolor=yellow_colors)
|
32
|
+
|
33
|
+
# Create metallic gradient for red
|
34
|
+
red_cmap = LinearSegmentedColormap.from_list("metallic_red", ["#8B0000", "#FF0000", "#8B0000"])
|
35
|
+
red_colors = red_cmap(np.linspace(0, 1, 500))
|
36
|
+
self.ax.fill_between(theta, 0, 1, where=(theta > 2*np.pi/3), color=None, alpha=0.7, facecolor=red_colors)
|
37
|
+
|
38
|
+
# Remove polar grid and labels for a clean look
|
39
|
+
self.ax.grid(False)
|
40
|
+
self.ax.set_yticks([])
|
41
|
+
self.ax.set_xticks([])
|
42
|
+
|
43
|
+
self.ax.set_ylim(0, 1)
|
44
|
+
self.ax.set_xlim(0, np.pi)
|
45
|
+
|
46
|
+
def plot_needle(self, value, color='black'):
|
47
|
+
# Add a needle to indicate a specific value
|
48
|
+
width = 0.1 # Needle width
|
49
|
+
self.ax.fill([value, value-width, value, value+width, value],
|
50
|
+
[0, .25, .9, .25, 0], color='black', linewidth=2, zorder=5)
|
51
|
+
self.ax.plot([value, value+width*.9, value],
|
52
|
+
[.9, .25, 0], color='grey', linewidth=2, zorder=6)
|
53
|
+
self.ax.plot([value, value+width, value],
|
54
|
+
[.9, .25, 0], color='white', linewidth=1, zorder=6)
|
55
|
+
# Plot a black semi-circle at the origin
|
56
|
+
semi_circle = plt.Circle((0, 0), 0.1, transform=self.ax.transData._b, color='black', zorder=7)
|
57
|
+
self.ax.add_artist(semi_circle)
|
58
|
+
|
59
|
+
def plot_text(self, text, value):
|
60
|
+
# Add text to the speedometer
|
61
|
+
# The text is above the speedometer in the center
|
62
|
+
# The value is the angle of the needle
|
63
|
+
self.ax.text(np.pi/2., 1.15, text, fontsize=12, ha='center', va='center', color='black')
|
64
|
+
|
65
|
+
class Rectangular_Gauge():
|
66
|
+
|
67
|
+
def __init__(self, horizontal_or_vertical='vertical'):
|
68
|
+
# Create a rectangular plot for the speedometer background
|
69
|
+
|
70
|
+
if horizontal_or_vertical == 'horizontal':
|
71
|
+
self.fig, self.ax = plt.subplots(figsize=(6, 3))
|
72
|
+
self.direction = 'horizontal'
|
73
|
+
else:
|
74
|
+
# Default to vertical if not specified
|
75
|
+
self.fig, self.ax = plt.subplots(figsize=(3, 6))
|
76
|
+
self.direction = 'vertical'
|
77
|
+
|
78
|
+
self.ax.set_xlim(0, 1)
|
79
|
+
self.ax.set_ylim(0, 1)
|
80
|
+
|
81
|
+
def plot_background(self):
|
82
|
+
# Define the ranges for red, yellow, and green
|
83
|
+
|
84
|
+
if self.direction == 'horizontal':
|
85
|
+
# Horizontal speedometer
|
86
|
+
self.ax.fill_between([0, 1/3], 0, 1, color='green', alpha=0.7)
|
87
|
+
self.ax.fill_between([1/3, 2/3], 0, 1, color='yellow', alpha=0.7)
|
88
|
+
self.ax.fill_between([2/3, 1], 0, 1, color='red', alpha=0.7)
|
89
|
+
else:
|
90
|
+
# Vertical speedometer
|
91
|
+
self.ax.fill_between([0, 1], 0, 1/3, color='green', alpha=0.7)
|
92
|
+
self.ax.fill_between([0, 1], 1/3, 2/3, color='yellow', alpha=0.7)
|
93
|
+
self.ax.fill_between([0, 1], 2/3, 1, color='red', alpha=0.7)
|
94
|
+
|
95
|
+
# Remove grid and ticks for a clean look
|
96
|
+
self.ax.grid(False)
|
97
|
+
self.ax.set_xticks([])
|
98
|
+
self.ax.set_yticks([])
|
99
|
+
|
100
|
+
def plot_needle(self, value):
|
101
|
+
# Add a needle to indicate a specific value
|
102
|
+
width = 0.01 # Needle width
|
103
|
+
|
104
|
+
if self.direction == 'horizontal':
|
105
|
+
# Horizontal speedometer
|
106
|
+
self.ax.fill([value-width, value+width, value+width, value-width],
|
107
|
+
[0.25, 0.25, 0.9, 0.9], color='black', linewidth=2)
|
108
|
+
else:
|
109
|
+
# Vertical speedometer
|
110
|
+
self.ax.fill([0, 1, 1, 0],
|
111
|
+
[value-width, value-width, value+width, value+width], color='black', linewidth=2)
|
112
|
+
|
113
|
+
def plot_text(self, text, value):
|
114
|
+
# Add text to the speedometer
|
115
|
+
self.ax.text(0.5, 1.15, text, fontsize=12, ha='center', va='center', color='black')
|
116
|
+
|
117
|
+
|
118
|
+
|
119
|
+
|
120
|
+
if __name__ == "__main__":
|
121
|
+
# Test the speedometer function
|
122
|
+
fig = Semi_Circle_Gauge()
|
123
|
+
import matplotlib.animation as animation
|
124
|
+
|
125
|
+
def update(frame):
|
126
|
+
fig.ax.clear()
|
127
|
+
fig.plot_background() # Reinitialize the speedometer to clear previous needle
|
128
|
+
fig.plot_needle(frame)
|
129
|
+
fig.plot_text("Danger: {:.2f}".format(frame), frame)
|
130
|
+
|
131
|
+
# Create an animation with values ranging from 0 to π
|
132
|
+
ani = animation.FuncAnimation(fig.fig, update, frames=np.linspace(0, np.pi, 100), interval=50)
|
133
|
+
|
134
|
+
plt.show()
|
135
|
+
pass
|