wolfhece 2.1.128__py3-none-any.whl → 2.2.1__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.
Files changed (44) hide show
  1. wolfhece/PyDraw.py +109 -46
  2. wolfhece/PyGui.py +3 -0
  3. wolfhece/PyGuiHydrology.py +24 -24
  4. wolfhece/PyPalette.py +27 -11
  5. wolfhece/PyParams.py +5 -1
  6. wolfhece/PyVertexvectors.py +52 -7
  7. wolfhece/Results2DGPU.py +17 -0
  8. wolfhece/acceptability/acceptability_gui.py +29 -18
  9. wolfhece/acceptability/func.py +23 -21
  10. wolfhece/apps/version.py +2 -2
  11. wolfhece/eikonal.py +1 -1
  12. wolfhece/hydrology/Catchment.py +113 -12
  13. wolfhece/hydrology/Comparison.py +54 -52
  14. wolfhece/hydrology/Optimisation.py +309 -178
  15. wolfhece/hydrology/PostProcessHydrology.py +6 -3
  16. wolfhece/hydrology/RetentionBasin.py +21 -14
  17. wolfhece/hydrology/SubBasin.py +128 -12
  18. wolfhece/hydrology/constant.py +3 -0
  19. wolfhece/hydrology/cst_exchanges.py +364 -38
  20. wolfhece/hydrology/plot_hydrology.py +34 -18
  21. wolfhece/hydrology/read.py +16 -6
  22. wolfhece/lagrangian/particle_system_ui.py +1 -1
  23. wolfhece/lagrangian/particles.py +1 -1
  24. wolfhece/lazviewer/processing/estimate_normals/estimate_normals.cp310-win_amd64.pyd +0 -0
  25. wolfhece/lazviewer/vfuncsdir/vfuncs.cp310-win_amd64.pyd +0 -0
  26. wolfhece/lazviewer/viewer/viewer.exe +0 -0
  27. wolfhece/lazviewer/viewer/viewer_np1_23_5.exe +0 -0
  28. wolfhece/libs/WolfDll.dll +0 -0
  29. wolfhece/libs/Wolf_tools.dll +0 -0
  30. wolfhece/libs/get_infos.cp310-win_amd64.pyd +0 -0
  31. wolfhece/libs/verify_wolf.cp310-win_amd64.pyd +0 -0
  32. wolfhece/libs/wolfogl.cp310-win_amd64.pyd +0 -0
  33. wolfhece/radar/wolfradar.py +75 -22
  34. wolfhece/shapes/__init__.py +0 -0
  35. wolfhece/shapes/circle.py +335 -0
  36. wolfhece/tools2d_dll.py +359 -0
  37. wolfhece/wolf_array.py +3 -2
  38. wolfhece/wolfresults_2D.py +162 -33
  39. {wolfhece-2.1.128.dist-info → wolfhece-2.2.1.dist-info}/METADATA +15 -9
  40. {wolfhece-2.1.128.dist-info → wolfhece-2.2.1.dist-info}/RECORD +43 -39
  41. wolfhece/libs/wolfpy.cp310-win_amd64.pyd +0 -0
  42. {wolfhece-2.1.128.dist-info → wolfhece-2.2.1.dist-info}/WHEEL +0 -0
  43. {wolfhece-2.1.128.dist-info → wolfhece-2.2.1.dist-info}/entry_points.txt +0 -0
  44. {wolfhece-2.1.128.dist-info → wolfhece-2.2.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,359 @@
1
+ from pathlib import Path
2
+ import numpy as np
3
+ import ctypes as ct
4
+ import logging
5
+
6
+ from .wolf_array import header_wolf, getkeyblock
7
+
8
+ try:
9
+ import pefile
10
+ except ImportError:
11
+ logging.warning("pefile module not found. Exported functions will not be listed.")
12
+
13
+
14
+ class Tools2DFortran:
15
+ """
16
+ Fortran routines/functions available in "2d_cpu_tools.f90" in Wolf_OO
17
+
18
+ Ref : https://docs.python.org/3/library/ctypes.html et https://gcc.gnu.org/onlinedocs/gfortran/Interoperability-with-C.html
19
+ Ref : https://stackoverflow.com/questions/59330863/cant-import-dll-module-in-python
20
+ """
21
+
22
+ def __init__(self, fn_simul:str | Path, debugmode:bool = False, path_to_dll:Path = None):
23
+
24
+ if debugmode:
25
+ if path_to_dll is None:
26
+ self.dll_file = Path(__file__).parent / "libs" / "Wolf_tools_debug.dll"
27
+ else:
28
+ self.dll_file = path_to_dll / "Wolf_tools_debug.dll"
29
+ else:
30
+ if path_to_dll is None:
31
+ self.dll_file = Path(__file__).parent / "libs" / "Wolf_tools.dll"
32
+ else:
33
+ self.dll_file = path_to_dll / "Wolf_tools.dll"
34
+
35
+ self.dll_file = self.dll_file.absolute()
36
+
37
+ if not Path(self.dll_file).exists():
38
+ logging.error(f"File {self.dll_file} does not exist.")
39
+ return
40
+
41
+ # Load the DLL
42
+ try:
43
+ self.lib = ct.CDLL(str(self.dll_file))
44
+ except OSError as e:
45
+ logging.error(f"Could not load the DLL: {e}")
46
+ return
47
+
48
+ fn_simul = Path(fn_simul).absolute()
49
+
50
+ self.fn_simul = str(fn_simul)
51
+
52
+ if not Path(self.fn_simul).exists():
53
+ logging.error(f"File {self.fn_simul} does not exist.")
54
+ return
55
+
56
+ # Convert to ANSI encoding - this is important for Fortran on Windows and Latin-1 encoding
57
+ self.fn_simul = self.fn_simul.encode('ansi')
58
+
59
+ # res2D_init
60
+ self.lib.r2D_init.restype = None
61
+ self.lib.r2D_init.argtypes = [ct.c_char_p, ct.c_int]
62
+
63
+ self.lib.r2D_nbblocks.restype = ct.c_int
64
+ self.lib.r2D_nbblocks.argtypes = []
65
+
66
+ self.lib.r2D_header_block.restype = ct.c_int
67
+ self.lib.r2D_header_block.argtypes = [
68
+ ct.POINTER(ct.c_int), # nbx
69
+ ct.POINTER(ct.c_int), # nby
70
+ ct.POINTER(ct.c_double), # ox
71
+ ct.POINTER(ct.c_double), # oy
72
+ ct.POINTER(ct.c_double), # tx
73
+ ct.POINTER(ct.c_double), # ty
74
+ ct.POINTER(ct.c_double), # dx
75
+ ct.POINTER(ct.c_double), # dy
76
+ ct.c_int # which_block
77
+ ]
78
+
79
+ self.lib.r2D_getsizes.restype = None
80
+ self.lib.r2D_getsizes.argtypes = [
81
+ ct.POINTER(ct.c_int), # nbx
82
+ ct.POINTER(ct.c_int), # nby
83
+ ct.c_int # which_block
84
+ ]
85
+
86
+ self.lib.r2D_getnbresults.restype = ct.c_int
87
+ self.lib.r2D_getnbresults.argtypes = []
88
+
89
+ self.lib.r2D_getresults.restype = None
90
+ self.lib.r2D_getresults.argtypes = [
91
+ ct.c_int, # which
92
+ ct.c_int, # nbx
93
+ ct.c_int, # nby
94
+ ct.POINTER(ct.c_float), # waterdepth
95
+ ct.POINTER(ct.c_float), # qx
96
+ ct.POINTER(ct.c_float), # qy
97
+ ct.c_int # which_block
98
+ ]
99
+
100
+ self.lib.r2D_getturbresults.restype = None
101
+ self.lib.r2D_getturbresults.argtypes = [
102
+ ct.c_int, # which
103
+ ct.c_int, # nbx
104
+ ct.c_int, # nby
105
+ ct.POINTER(ct.c_float), # k
106
+ ct.POINTER(ct.c_float), # e
107
+ ct.c_int # which_block
108
+ ]
109
+
110
+ self.lib.r2D_get_times_steps.restype = None
111
+ self.lib.r2D_get_times_steps.argtypes = [
112
+ ct.POINTER(ct.c_float), # times
113
+ ct.POINTER(ct.c_int), # steps
114
+ ct.c_int # nb
115
+ ]
116
+
117
+ self.lib.r2D_get_conv_border.restype = None
118
+ self.lib.r2D_get_conv_border.argtypes = [
119
+ ct.c_char_p, # ptr_fnsim
120
+ ct.c_char_p, # ptr_fnvec
121
+ ct.c_int, # simul_type
122
+ ct.c_char_p, # ptr_fnres
123
+ ct.c_char_p, # ptr_fncut
124
+ ct.c_int, # len_fnsim
125
+ ct.c_int, # len_fnvec
126
+ ct.c_int, # len_fnres
127
+ ct.c_int # len_fncut
128
+ ]
129
+
130
+
131
+ def _list_exported_functions(self):
132
+ """
133
+ Fortran routines/functions available in
134
+ """
135
+
136
+ pe = pefile.PE(self.dll_file)
137
+
138
+ if not hasattr(pe, 'DIRECTORY_ENTRY_EXPORT'):
139
+ print("No exported functions found.")
140
+ return
141
+
142
+ for exp in pe.DIRECTORY_ENTRY_EXPORT.symbols:
143
+ print(f"Function: {exp.name.decode('utf-8') if exp.name else 'None'}, Address: {hex(exp.address)}")
144
+
145
+ def _r2D_init(self):
146
+ """
147
+ Alias for the Fortran function r2D_init.
148
+
149
+ subroutine r2D_init(ptr_path, len_path) bind(C, name="r2d_init")
150
+ !DEC$ ATTRIBUTES DLLEXPORT :: r2d_init
151
+ type(c_ptr), value, intent(in) :: ptr_path
152
+ integer(c_int), value, intent(in) :: len_path
153
+
154
+ end subroutine
155
+ """
156
+ self.lib.r2D_init(self.fn_simul, ct.c_int(len(self.fn_simul)))
157
+
158
+ def r2D_get_number_of_blocks(self):
159
+ """
160
+ Alias for the Fortran function r2D_nbblocks.
161
+
162
+ function r2D_nbblocks() result(nb_blocks) bind(C, name="r2D_nbblocks")
163
+ !DEC$ ATTRIBUTES DLLEXPORT :: r2D_nbblocks
164
+ integer(c_int) :: nb_blocks
165
+
166
+ end function
167
+ """
168
+ self._r2D_init()
169
+ nb_blocks = self.lib.r2D_nbblocks()
170
+ return nb_blocks
171
+
172
+ def r2D_get_header_one_block(self, which_block:int):
173
+ """
174
+ Alias for the Fortran function r2D_header_block.
175
+
176
+ function r2D_header_block(nbx, nby, dx,dy,ox,oy,tx,ty,which_block) result(ret) bind(C, name="r2D_header_block")
177
+ !DEC$ ATTRIBUTES DLLEXPORT :: r2D_header_block
178
+ !DEC$ attributes REFERENCE :: nbx, nby
179
+ !DEC$ attributes REFERENCE :: dx, dy, ox, oy, tx, ty
180
+ !DEC$ attributes VALUE :: which_block
181
+ integer(c_int) :: nbx,nby, ret
182
+ double precision :: ox,oy,tx,ty,dx,dy
183
+ integer(c_int), intent(in) :: which_block
184
+
185
+ end function
186
+ """
187
+
188
+ self._r2D_init()
189
+ nbx = ct.c_int()
190
+ nby = ct.c_int()
191
+ ox = ct.c_double()
192
+ oy = ct.c_double()
193
+ tx = ct.c_double()
194
+ ty = ct.c_double()
195
+ dx = ct.c_double()
196
+ dy = ct.c_double()
197
+ self.lib.r2D_header_block(ct.byref(nbx), ct.byref(nby), ct.byref(dx), ct.byref(dy),
198
+ ct.byref(ox), ct.byref(oy), ct.byref(tx), ct.byref(ty), ct.c_int(which_block))
199
+
200
+ return (nbx.value, nby.value, dx.value, dy.value, ox.value, oy.value, tx.value, ty.value)
201
+
202
+ def _r2D_get_header_block_python(self, which_block:int) -> header_wolf:
203
+ """ Return a header_wolf object with the header of the block number which_block."""
204
+ nbx, nby, dx, dy, ox, oy, tx, ty = self.r2D_get_header_one_block(which_block)
205
+ newhead = header_wolf()
206
+ newhead.nbx = nbx
207
+ newhead.nby = nby
208
+ newhead.dx = dx
209
+ newhead.dy = dy
210
+ newhead.origin = ox, oy
211
+ newhead.translation = tx, ty
212
+
213
+ return newhead
214
+
215
+ def r2D_get_header_allblocks(self):
216
+
217
+ nbblocks = self.r2D_get_number_of_blocks()
218
+ blocks = {}
219
+
220
+ for i in range(1, nbblocks+1):
221
+ key = getkeyblock(i, addone=False)
222
+ blocks[key] = self._r2D_get_header_block_python(i)
223
+
224
+ return blocks
225
+
226
+ def r2D_get_shape(self, which_block:int):
227
+ """
228
+ Alias for the Fortran function r2D_getsizes.
229
+
230
+ subroutine r2D_getsizes(nbx,nby,which_block) bind(C, name="r2D_getsizes")
231
+ !DEC$ ATTRIBUTES DLLEXPORT :: r2D_getsizes
232
+ integer(c_int), intent(out) :: nbx,nby
233
+ integer(c_int), intent(in) :: which_block
234
+
235
+ end subroutine
236
+ """
237
+
238
+ self._r2D_init()
239
+ nbx = ct.c_int()
240
+ nby = ct.c_int()
241
+ self.lib.r2D_getsizes(ct.byref(nbx), ct.byref(nby), ct.c_int(which_block))
242
+
243
+ return nbx.value, nby.value
244
+
245
+
246
+ def r2D_get_number_of_results(self):
247
+ """
248
+ Alias for the Fortran function r2D_getnbresults.
249
+
250
+ function r2D_getnbresults() result(nb) bind(C, name="r2D_getnbresults")
251
+ !DEC$ ATTRIBUTES DLLEXPORT :: r2D_getnbresults
252
+ integer(c_int) :: nb
253
+
254
+ end function
255
+ """
256
+
257
+ self._r2D_init()
258
+ nb = self.lib.r2D_getnbresults()
259
+ return nb
260
+
261
+ def r2D_get_one_result(self, which:int, which_block:int):
262
+ """
263
+ Alias for the Fortran function r2D_getresults.
264
+
265
+ subroutine r2D_getresults(which,nbx,nby,waterdepth,qx,qy,which_block) bind(C, name="r2D_getresults")
266
+ !DEC$ ATTRIBUTES DLLEXPORT :: r2D_getresults
267
+ integer(c_int), intent(in) :: nbx,nby,which
268
+ integer(c_int), intent(in) :: which_block
269
+ real, dimension(nbx,nby), intent(out) :: waterdepth,qx,qy
270
+
271
+ end subroutine
272
+ """
273
+
274
+ self._r2D_init()
275
+
276
+ nbx, nby = self.r2D_get_shape(which_block)
277
+ waterdepth = np.zeros((nbx, nby), dtype=np.float32, order='F')
278
+ qx = np.zeros((nbx, nby), dtype=np.float32, order='F')
279
+ qy = np.zeros((nbx, nby), dtype=np.float32, order='F')
280
+
281
+ self.lib.r2D_getresults(ct.c_int(which), ct.c_int(nbx), ct.c_int(nby),
282
+ waterdepth.ctypes.data_as(ct.POINTER(ct.c_float)),
283
+ qx.ctypes.data_as(ct.POINTER(ct.c_float)),
284
+ qy.ctypes.data_as(ct.POINTER(ct.c_float)),
285
+ ct.c_int(which_block))
286
+
287
+ return waterdepth, qx, qy
288
+
289
+ def r2D_get_one_turbulent_result(self, which:int, which_block:int):
290
+ """
291
+ Alias for the Fortran function r2D_getturbresults.
292
+
293
+ subroutine r2D_getturbresults(which,nbx,nby,k,e,which_block) bind(C, name="r2D_getturbresults")
294
+ !DEC$ ATTRIBUTES DLLEXPORT :: r2D_getturbresults
295
+ integer(c_int), intent(in) :: nbx,nby,which
296
+ integer(c_int), intent(in) :: which_block
297
+ real, dimension(nbx,nby), intent(out) :: k,e
298
+
299
+ end subroutine
300
+ """
301
+
302
+ self._r2D_init()
303
+
304
+ nbx, nby = self.r2D_get_shape(which_block)
305
+ k = np.zeros((nbx, nby), dtype=np.float32, order='F')
306
+ e = np.zeros((nbx, nby), dtype=np.float32, order='F')
307
+ self.lib.r2D_getturbresults(ct.c_int(which), ct.c_int(nbx), ct.c_int(nby),
308
+ k.ctypes.data_as(ct.POINTER(ct.c_float)),
309
+ e.ctypes.data_as(ct.POINTER(ct.c_float)),
310
+ ct.c_int(which_block))
311
+
312
+ return k, e
313
+
314
+ def r2D_get_times_steps(self):
315
+ """
316
+ Alias for the Fortran function get_times_steps.
317
+
318
+ subroutine get_times_steps(times, steps, nb) bind(C, name="get_times_steps")
319
+ !DEC$ ATTRIBUTES DLLEXPORT :: r2D_gettimes_steps
320
+ integer(c_int), intent(in) :: nb
321
+ real, dimension(nb), intent(out) :: times
322
+ integer, dimension(nb), intent(out) :: steps
323
+
324
+ end subroutine
325
+ """
326
+
327
+ self._r2D_init()
328
+ nb = self.r2D_get_number_of_results()
329
+ times = np.zeros((nb), dtype=np.float32, order='F')
330
+ steps = np.zeros((nb), dtype=np.int32, order='F')
331
+ self.lib.r2D_get_times_steps(times.ctypes.data_as(ct.POINTER(ct.c_float)),
332
+ steps.ctypes.data_as(ct.POINTER(ct.c_int)),
333
+ ct.c_int(nb))
334
+ return times, steps
335
+
336
+ def r2D_create_convergence_border(self, vec:str='', simtype:int=0, res:str='', cutcell:str=''):
337
+ """
338
+ Alias for the Fortran function get_conv_border.
339
+
340
+ subroutine get_conv_border(ptr_fnsim, ptr_fnvec, simul_type, ptr_fnres, ptr_fncut, len_fnsim, len_fnvec, len_fnres, len_fncut) bind(C, name="get_conv_border")
341
+ !DEC$ ATTRIBUTES DLLEXPORT :: r2D_get_conv_border
342
+ type(c_ptr), value, intent(in) :: ptr_fnsim, ptr_fnvec, ptr_fnres, ptr_fncut
343
+ integer(c_int), value, intent(in) :: len_fnsim, len_fnvec, len_fnres, len_fncut
344
+
345
+ end subroutine
346
+ """
347
+
348
+ fn_vec = str(vec).encode('ansi')
349
+ fn_res = str(res).encode('ansi')
350
+ fn_cutcell = str(cutcell).encode('ansi')
351
+
352
+ self._r2D_init()
353
+ self.lib.r2D_get_conv_border(self.fn_simul, fn_vec, simtype, fn_res, fn_cutcell,
354
+ ct.c_int(len(self.fn_simul)),
355
+ ct.c_int(len(fn_vec)),
356
+ ct.c_int(len(fn_res)),
357
+ ct.c_int(len(fn_cutcell)))
358
+
359
+ return 0
wolfhece/wolf_array.py CHANGED
@@ -6058,7 +6058,7 @@ class WolfArray(Element_To_Draw, header_wolf):
6058
6058
  Statistics on Selected data or the whole array if no selection
6059
6059
 
6060
6060
  :param inside_polygon: vector or Polygon to select data inside the polygon
6061
- :return: mean, std, median, sum, values
6061
+ :return: mean, std, median, sum, volume (sum*dx*dy), values
6062
6062
  """
6063
6063
 
6064
6064
  if inside_polygon is not None:
@@ -6074,8 +6074,9 @@ class WolfArray(Element_To_Draw, header_wolf):
6074
6074
  std = np.std(vals)
6075
6075
  median = np.median(vals)
6076
6076
  sum = np.sum(vals)
6077
+ vol = sum * self.dx * self.dy
6077
6078
 
6078
- return {_('Mean'): mean, _('Std'): std, _('Median'): median, _('Sum'): sum, _('Values'): vals}
6079
+ return {_('Mean'): mean, _('Std'): std, _('Median'): median, _('Sum'): sum, _('Volume'): vol, _('Values'): vals}
6079
6080
 
6080
6081
  def export_geotif(self, outdir:str= '', extent:str= '', EPSG:int = 31370):
6081
6082
  """
@@ -45,31 +45,32 @@ from .mesh2d.wolf2dprev import prev_parameters_simul, blocks_file
45
45
  from .GraphNotebook import PlotPanel
46
46
  from .CpGrid import CpGrid
47
47
  from .matplotlib_fig import Matplotlib_Figure
48
+ from .tools2d_dll import Tools2DFortran
48
49
 
49
50
 
50
- try:
51
- from .libs import wolfpy
52
- except Exception as ex:
53
- # This convoluted error handling is here to catch an issue
54
- # which was difficult to track down: wolfpy was there
55
- # but its DLL were not available.
51
+ # try:
52
+ # from .libs import wolfpy
53
+ # except Exception as ex:
54
+ # # This convoluted error handling is here to catch an issue
55
+ # # which was difficult to track down: wolfpy was there
56
+ # # but its DLL were not available.
56
57
 
57
- from importlib.util import find_spec
58
- s = find_spec('wolfhece.libs.wolfpy')
58
+ # from importlib.util import find_spec
59
+ # s = find_spec('wolfhece.libs.wolfpy')
59
60
 
60
- # Not too sure about this find_spec. If the root
61
- # directory is not the good one, the import search may
62
- # end up in the site packages, loading the wrong wolfpy.
61
+ # # Not too sure about this find_spec. If the root
62
+ # # directory is not the good one, the import search may
63
+ # # end up in the site packages, loading the wrong wolfpy.
63
64
 
64
- base = Path(__file__).parent.parts
65
- package = Path(s.origin).parent.parts
66
- is_submodule = (len(base) <= len(package)) and all(i==j for i, j in zip(base, package))
65
+ # base = Path(__file__).parent.parts
66
+ # package = Path(s.origin).parent.parts
67
+ # is_submodule = (len(base) <= len(package)) and all(i==j for i, j in zip(base, package))
67
68
 
68
- if is_submodule:
69
- msg = _("wolfpy was found but we were not able to load it. It may be an issue with its DLL dependencies")
70
- msg += _("The actual error was: {}").format(str(ex))
69
+ # if is_submodule:
70
+ # msg = _("wolfpy was found but we were not able to load it. It may be an issue with its DLL dependencies")
71
+ # msg += _("The actual error was: {}").format(str(ex))
71
72
 
72
- raise Exception(msg)
73
+ # raise Exception(msg)
73
74
 
74
75
  from .wolf_array import WolfArray, getkeyblock, header_wolf, WolfArrayMB, WolfArrayMNAP, header_wolf, SelectionData, SelectionDataMB, VERSION_RGB
75
76
  from .mesh2d import wolf2dprev
@@ -130,6 +131,12 @@ def u_splitting(q_left, q_right, h_left, h_right):
130
131
  else:
131
132
  return (q_left/h_left + q_right/h_right) / 2.
132
133
 
134
+ def _process_danger_map_chunk(chunk):
135
+ import pickle
136
+ obj, start, end, every = chunk
137
+ # Create a new instance of the class for each chunk
138
+ new:Wolfresults_2D = pickle.loads(pickle.dumps(obj))
139
+ return new.danger_map(start, end, every)
133
140
 
134
141
  class Props_Res_2D(wx.Frame):
135
142
  """
@@ -2213,6 +2220,7 @@ class Wolfresults_2D(Element_To_Draw):
2213
2220
  self.filename = fname
2214
2221
 
2215
2222
  self.filenamegen=self.filename
2223
+ self._dll_tools = Tools2DFortran(self.filenamegen) # DLL de calculs de la classe Tools2DFortran
2216
2224
 
2217
2225
  if exists(self.filename + '.trl'):
2218
2226
  with open(self.filename + '.trl') as f:
@@ -2224,14 +2232,16 @@ class Wolfresults_2D(Element_To_Draw):
2224
2232
  self.read_param_simul()
2225
2233
 
2226
2234
  if exists(self.filename+'.head') or exists(join(dirname(self.filename),'bloc1.head')):
2227
- wolfpy.r2d_init(self.filename.ljust(255).encode('ansi'))
2228
- nb_blocks = wolfpy.r2d_nbblocks()
2235
+ # wolfpy.r2d_init(self.filename.ljust(255).encode('ansi'))
2236
+ # nb_blocks = wolfpy.r2d_nbblocks()
2229
2237
 
2238
+ nb_blocks = self._dll_tools.r2D_get_number_of_blocks()
2230
2239
  for i in range(nb_blocks):
2231
2240
  curblock = OneWolfResult(i, parent=self)
2232
2241
  self.myblocks[getkeyblock(i)] = curblock
2233
2242
 
2234
- nbx,nby,dx,dy,ox,oy,tx,ty = wolfpy.r2d_hblock(i+1)
2243
+ # nbx,nby,dx,dy,ox,oy,tx,ty = wolfpy.r2d_hblock(i+1)
2244
+ nbx, nby,dx,dy,ox,oy,tx,ty = self._dll_tools.r2D_get_header_one_block(i+1)
2235
2245
 
2236
2246
  curhead = self.head_blocks[getkeyblock(i)]=header_wolf()
2237
2247
  curhead.nbx = nbx
@@ -2745,8 +2755,10 @@ class Wolfresults_2D(Element_To_Draw):
2745
2755
  if nb == 0:
2746
2756
  self.times, self.timesteps = [],[]
2747
2757
  else:
2748
- wolfpy.r2d_init(self.filename.ljust(255).encode('ansi'))
2749
- self.times, self.timesteps = wolfpy.get_times_steps(nb)
2758
+ # wolfpy.r2d_init(self.filename.ljust(255).encode('ansi'))
2759
+ # self.times, self.timesteps = wolfpy.get_times_steps(nb)
2760
+
2761
+ self.times, self.timesteps = self._dll_tools.r2D_get_times_steps()
2750
2762
 
2751
2763
  return self.times, self.timesteps
2752
2764
 
@@ -2996,8 +3008,10 @@ class Wolfresults_2D(Element_To_Draw):
2996
3008
  """Récupération du nombre de pas sauvegardés --> utilisation de la librairie Fortran"""
2997
3009
 
2998
3010
  if exists(self.filename+'.head'):
2999
- wolfpy.r2d_init(self.filename.ljust(255).encode('ansi'))
3000
- nb = wolfpy.r2d_getnbresults()
3011
+ # wolfpy.r2d_init(self.filename.ljust(255).encode('ansi'))
3012
+ # nb = wolfpy.r2d_getnbresults()
3013
+
3014
+ nb = self._dll_tools.r2D_get_number_of_results()
3001
3015
  self._nb_results = nb
3002
3016
 
3003
3017
  if force_update_timessteps:
@@ -3021,8 +3035,12 @@ class Wolfresults_2D(Element_To_Draw):
3021
3035
  nby = block.waterdepth.nby
3022
3036
 
3023
3037
  # Fortran is 1-based --> which_step+1
3024
- block.waterdepth.array, block.qx.array, block.qy.array = wolfpy.r2d_getresults(which_step+1, nbx, nby, whichblock)
3025
- block.k.array, block.eps.array = wolfpy.r2d_getturbresults(which_step+1, nbx, nby, whichblock)
3038
+ # block.waterdepth.array, block.qx.array, block.qy.array = wolfpy.r2d_getresults(which_step+1, nbx, nby, whichblock)
3039
+ # block.k.array, block.eps.array = wolfpy.r2d_getturbresults(which_step+1, nbx, nby, whichblock)
3040
+
3041
+ block.waterdepth.array, block.qx.array, block.qy.array = self._dll_tools.r2D_get_one_result(which_step+1, whichblock)
3042
+ block.k.array, block.eps.array = self._dll_tools.r2D_get_one_turbulent_result(which_step+1, whichblock)
3043
+
3026
3044
  block._force_update_shields = True
3027
3045
 
3028
3046
  def _read_oneblockresult_withoutmask_only_h(self, which_step:int=-1,whichblock:int=-1):
@@ -3040,7 +3058,9 @@ class Wolfresults_2D(Element_To_Draw):
3040
3058
  nby = block.waterdepth.nby
3041
3059
 
3042
3060
  # Fortran is 1-based --> which_step+1
3043
- block.waterdepth.array, block.qx.array, block.qy.array = wolfpy.r2d_getresults(which_step+1, nbx, nby, whichblock)
3061
+ # block.waterdepth.array, block.qx.array, block.qy.array = wolfpy.r2d_getresults(which_step+1, nbx, nby, whichblock)
3062
+
3063
+ block.waterdepth.array, block.qx.array, block.qy.array = self._dll_tools.r2D_get_one_result(which_step+1, whichblock)
3044
3064
  block._force_update_shields = True
3045
3065
 
3046
3066
  def read_oneblockresult(self, which_step:int=-1, whichblock:int=-1):
@@ -3114,7 +3134,7 @@ class Wolfresults_2D(Element_To_Draw):
3114
3134
 
3115
3135
  if exists(self.filename+'.head'):
3116
3136
  logging.info(_('Reading from results - step :{}'.format(which+1)))
3117
- wolfpy.r2d_init(self.filename.ljust(255).encode('ansi'))
3137
+ # wolfpy.r2d_init(self.filename.ljust(255).encode('ansi'))
3118
3138
  for i in range(self.nb_blocks):
3119
3139
  self.read_oneblockresult(which, i+1)
3120
3140
  else:
@@ -3137,7 +3157,7 @@ class Wolfresults_2D(Element_To_Draw):
3137
3157
 
3138
3158
  if exists(self.filename+'.head'):
3139
3159
  logging.info(_('Reading from results - step :{}'.format(which+1)))
3140
- wolfpy.r2d_init(self.filename.ljust(255).encode('ansi'))
3160
+ # wolfpy.r2d_init(self.filename.ljust(255).encode('ansi'))
3141
3161
  for i in range(self.nb_blocks):
3142
3162
  self._read_oneblockresult_only_h(which, i+1)
3143
3163
  else:
@@ -3175,7 +3195,7 @@ class Wolfresults_2D(Element_To_Draw):
3175
3195
  if exists(self.filename+'.head'):
3176
3196
 
3177
3197
  logging.info(_('Reading result step :{}'.format(self.current_result)))
3178
- wolfpy.r2d_init(self.filename.ljust(255).encode('ansi'))
3198
+ # wolfpy.r2d_init(self.filename.ljust(255).encode('ansi'))
3179
3199
 
3180
3200
  for i in range(self.nb_blocks):
3181
3201
  self.read_oneblockresult(self.current_result, i+1)
@@ -4989,7 +5009,11 @@ class Wolfresults_2D(Element_To_Draw):
4989
5009
  curdanger.reset()
4990
5010
  curdanger.mask_reset()
4991
5011
 
4992
- for time_step in tqdm(range(start, end, every)):
5012
+ to_compute = np.arange(start, end, every)
5013
+ #add the end
5014
+ if end not in to_compute:
5015
+ to_compute = np.append(to_compute, end)
5016
+ for time_step in tqdm(to_compute):
4993
5017
 
4994
5018
  if callback is not None:
4995
5019
  callback(time_step, "Step {} / {}".format(time_step+1, end))
@@ -5066,6 +5090,111 @@ class Wolfresults_2D(Element_To_Draw):
5066
5090
 
5067
5091
  return (danger_map_matrix_h, danger_map_matrix_v, danger_map_matrix_mom, danger_map_matrix_z, danger_map_matrix_head)
5068
5092
 
5093
+ def __getstate__(self):
5094
+ """Get the state of the object for pickling"""
5095
+ state = self.__dict__.copy()
5096
+ # Remove unpicklable attributes
5097
+
5098
+ topop = ['mapviewer', 'properties', 'mngselection', 'myops']
5099
+
5100
+ for cur_pop in topop:
5101
+ if cur_pop in state:
5102
+ state.pop(cur_pop)
5103
+ return state
5104
+
5105
+ def __setstate__(self, state):
5106
+ """Set the state of the object after unpickling"""
5107
+ # Restore the state of the object
5108
+ self.__dict__.update(state)
5109
+ # Reinitialize any attributes that were removed during pickling
5110
+ self.mapviewer = None
5111
+ self.properties = None
5112
+ self.mngselection = None
5113
+ self.myops = None
5114
+
5115
+ def danger_map_multiprocess(self, start:int=0, end:int=-1, every:int=1, callback=None, nb_processors:int = -1) -> Union[tuple[WolfArray, WolfArray, WolfArray, WolfArray], tuple[WolfArrayMB, WolfArrayMB, WolfArrayMB, WolfArrayMB]]:
5116
+ """
5117
+ Create Danger Maps using multiprocessing
5118
+
5119
+ :param start: start time step - 0-based
5120
+ :param end: end time step - 0-based
5121
+ :param every: step interval
5122
+ :param callback: optional callback to update progress
5123
+ """
5124
+
5125
+ from multiprocessing import Pool, cpu_count
5126
+
5127
+ if nb_processors == -1:
5128
+ nb_processors = cpu_count()
5129
+
5130
+ if nb_processors > self.get_nbresults():
5131
+ nb_processors = self.get_nbresults()
5132
+
5133
+ # Split the range of time steps into chunks for multiprocessing
5134
+ if end == -1:
5135
+ end = self.get_nbresults()
5136
+
5137
+ starts = [start + i * every for i in range(nb_processors)]
5138
+ ends = [end - i * every for i in range(nb_processors-1,-1,-1)]
5139
+
5140
+ # pop all start above end
5141
+ for i in range(nb_processors-1,0,-1):
5142
+ if starts[i] >= end:
5143
+ starts.pop(i)
5144
+ ends.pop(i)
5145
+
5146
+ # set end above start
5147
+ for i in range(len(starts)):
5148
+ if starts[i] >= ends[i]:
5149
+ ends[i] = starts[i] + every
5150
+
5151
+ chunks = [(self, start + i * every, end - (nb_processors - i) * every + 1, nb_processors) for i in range(min(nb_processors, len(starts)))]
5152
+
5153
+ # Create a pool of workers
5154
+ with Pool(processes=nb_processors) as pool:
5155
+ results = pool.map(_process_danger_map_chunk, chunks)
5156
+
5157
+ danger_map_matrix_h = self.as_WolfArray(copyarray=True)
5158
+ danger_map_matrix_v = self.as_WolfArray(copyarray=True)
5159
+ danger_map_matrix_mom = self.as_WolfArray(copyarray=True)
5160
+ danger_map_matrix_z = self.as_WolfArray(copyarray=True)
5161
+ danger_map_matrix_head= self.as_WolfArray(copyarray=True)
5162
+
5163
+ danger = [danger_map_matrix_h, danger_map_matrix_v, danger_map_matrix_mom, danger_map_matrix_z, danger_map_matrix_head]
5164
+
5165
+ for curdanger in danger:
5166
+ curdanger.nullvalue = 0.
5167
+ curdanger.reset()
5168
+ curdanger.mask_reset()
5169
+
5170
+ if self.nb_blocks>1:
5171
+ for result in results:
5172
+ for idx, curdanger in enumerate(danger):
5173
+ for i in range(self.nb_blocks):
5174
+ curdanger[i].array.data = np.maximum(curdanger[i].array.data, result[idx][i].array.data)
5175
+ curdanger[i].array.mask = np.logical_or(curdanger[i].array.mask, result[idx][i].array.mask)
5176
+ else:
5177
+ for result in results:
5178
+ for idx, curdanger in enumerate(danger):
5179
+ curdanger.array.data[:,:] = np.maximum(curdanger.array.data, result[idx].array.data)
5180
+ curdanger.array.mask[:,:] = np.logical_or(curdanger.array.mask, result[idx].array.mask)
5181
+
5182
+ danger_map_matrix_h.mask_lower(self.epsilon)
5183
+
5184
+ if self.nb_blocks>1:
5185
+ for i in range(self.nb_blocks):
5186
+ danger_map_matrix_v[i].array.mask[:,:] = danger_map_matrix_h[i].array.mask[:,:]
5187
+ danger_map_matrix_mom[i].array.mask[:,:] = danger_map_matrix_h[i].array.mask[:,:]
5188
+ danger_map_matrix_z[i].array.mask[:,:] = danger_map_matrix_h[i].array.mask[:,:]
5189
+ danger_map_matrix_head[i].array.mask[:,:] = danger_map_matrix_h[i].array.mask[:,:]
5190
+ else:
5191
+ danger_map_matrix_v.array.mask[:,:] = danger_map_matrix_h.array.mask[:,:]
5192
+ danger_map_matrix_mom.array.mask[:,:] = danger_map_matrix_h.array.mask[:,:]
5193
+ danger_map_matrix_z.array.mask[:,:] = danger_map_matrix_h.array.mask[:,:]
5194
+ danger_map_matrix_head.array.mask[:,:] = danger_map_matrix_h.array.mask[:,:]
5195
+
5196
+ return (danger_map_matrix_h, danger_map_matrix_v, danger_map_matrix_mom, danger_map_matrix_z, danger_map_matrix_head)
5197
+
5069
5198
  def danger_map_only_h(self, start:int=0, end:int=-1, every:int=1) -> WolfArray:
5070
5199
  """
5071
5200
  Create Danger Maps
@@ -5431,7 +5560,7 @@ class Wolfresults_2D(Element_To_Draw):
5431
5560
  curavg.mask_reset()
5432
5561
 
5433
5562
  for time_step in tqdm(range(start, end, every)):
5434
-
5563
+
5435
5564
  if callback is not None:
5436
5565
  callback(time_step, "Step {} / {}".format(time_step+1, end))
5437
5566