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.
@@ -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 ["The code rasters do not exist"]
917
+ return False
902
918
 
903
919
  if len(vuln) == 0:
904
920
  logging.error("The vulnerability rasters do not exist")
905
- return ["The vulnerability rasters do not exist"]
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 ["The number of code and vulnerability rasters do not match"]
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.nullvalue != 99999.:
989
- curarray.nullvalue = 99999.
990
- curarray.set_nullvalue_in_mask()
991
- curarray.write_all()
992
- logging.warning(_('nodata changed in favor of 99999. value for file {} !'.format(cur_lst)))
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:
@@ -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
- 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'
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
@@ -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
@@ -5,7 +5,7 @@ class WolfVersion():
5
5
 
6
6
  self.major = 2
7
7
  self.minor = 2
8
- self.patch = 1
8
+ self.patch = 3
9
9
 
10
10
  def __str__(self):
11
11
 
@@ -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