wolfhece 2.1.6__py3-none-any.whl → 2.1.8__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/PyParams.py CHANGED
@@ -944,7 +944,11 @@ class Wolf_Param(wx.Frame):
944
944
  except:
945
945
  logging.debug("String type will be conserved! -- {}".format(value_param))
946
946
 
947
- page.AppendIn(parent, pg.EnumProperty(param_name, name=locname, labels=list_keys, values=list_values, value=value_param))
947
+ if type(value_param) != int:
948
+ logging.warning("Parameters -- EnumProperty -- Value {} is not an integer".format(value_param))
949
+ logging.debug("EnumProperty value must be an integer")
950
+
951
+ page.AppendIn(parent, pg.EnumProperty(param_name, name=locname, labels=list_keys, values=list_values, value=int(value_param))) # force value to 'int' type
948
952
  else:
949
953
  self._insert_with_type_based_on_value(page, group, param, prefix)
950
954
 
@@ -1055,8 +1059,12 @@ class Wolf_Param(wx.Frame):
1055
1059
  value_param = int(value_param)
1056
1060
  except:
1057
1061
  logging.debug("String type will be conserved! -- {}".format(value_param))
1058
- # print(value_param)
1059
- page.Append(pg.EnumProperty(param_name, name=locname, labels=list_keys, values=list_values, value=value_param))
1062
+
1063
+ if type(value_param) != int:
1064
+ logging.warning("Parameters -- EnumProperty -- Value {} is not an integer".format(value_param))
1065
+ logging.debug("EnumProperty value must be an integer")
1066
+
1067
+ page.Append(pg.EnumProperty(label= param_name, name= locname, labels= list_keys, values= list_values, value= int(value_param)))
1060
1068
 
1061
1069
  else:
1062
1070
  # Pas de chaîne JSON mais un commentaire complet
wolfhece/apps/version.py CHANGED
@@ -5,7 +5,7 @@ class WolfVersion():
5
5
 
6
6
  self.major = 2
7
7
  self.minor = 1
8
- self.patch = 6
8
+ self.patch = 8
9
9
 
10
10
  def __str__(self):
11
11
 
wolfhece/multiprojects.py CHANGED
@@ -80,7 +80,103 @@ class Wolf2D_Project(Project):
80
80
  self.poly = None
81
81
  self.poly_values = None
82
82
 
83
- def load_simulations(self, epsilon, verbose=False):
83
+ @classmethod
84
+ def from_existing(cls, sims:dict[str, Union[str, Wolfresults_2D, wolfres2DGPU]]):
85
+ """
86
+ Create a MultiProjects object from a dictionary of simulations
87
+
88
+ :param sims: dict[str, Union[str, Wolfresults_2D, wolfres2DGPU]] -- dictionary of simulations to add
89
+ """
90
+
91
+ newmp = cls(to_read=False)
92
+ newmp.add_simulations(sims)
93
+
94
+ return newmp
95
+
96
+ def __str__(self) -> str:
97
+ """
98
+ Return string representation
99
+ """
100
+
101
+ ret = f'Project : {Path(self.wdir)}\n'
102
+ ret += 'Key : Simulations : Type\n'
103
+ for curkey, cursim in self.mysims.items():
104
+ ret+=f'{curkey} : {cursim.filename} : {"GPU" if isinstance(cursim, wolfres2DGPU) else "CPU"}\n'
105
+
106
+ return ret
107
+
108
+ def __getitem__(self, key: tuple[str, str]):
109
+
110
+ return self.get_simulation(key)
111
+
112
+ def pop(self, key: str):
113
+ """
114
+ Remove a simulation from the project
115
+
116
+ :param key: str -- key of the simulation to remove
117
+ """
118
+
119
+ if key in self.mysims.keys():
120
+ self.mysims.pop(key)
121
+
122
+ def add(self,
123
+ key:str,
124
+ value:Union[Wolfresults_2D, wolfres2DGPU, str],
125
+ epsilon:float=None,
126
+ force_read:bool = False):
127
+ """
128
+ Add a key-value pair to the project
129
+
130
+ :param key: str -- key of the simulation to add
131
+ :param value: Wolfresults_2D, wolfres2DGPU, str -- simulation to add
132
+ :param epsilon: float -- epsilon value to use for the simulation
133
+ :param force_read: bool -- force reading the last step of the simulation
134
+
135
+ """
136
+
137
+ if epsilon is None:
138
+ epsilon = self.epsilon
139
+
140
+ if isinstance(value, str):
141
+
142
+ locpath = Path(self.wdir) / value
143
+ if locpath.exists():
144
+
145
+ if 'simul_gpu_results' in locpath.name or (locpath / 'simul_gpu_results').exists():
146
+ #GPU
147
+ self.mysims[key] = wolfres2DGPU(locpath, epsilon=self.epsilon, idx=key)
148
+ else:
149
+ #CPU
150
+ self.mysims[key] = Wolfresults_2D(locpath, epsilon=self.epsilon, idx=key)
151
+
152
+ else:
153
+ logging.warning(f'File {locpath} does not exist !')
154
+
155
+ elif isinstance(value, wolfres2DGPU):
156
+
157
+ self.mysims[key] = value
158
+
159
+ elif isinstance(value, Wolfresults_2D):
160
+
161
+ self.mysims[key] = value
162
+
163
+ if force_read:
164
+ self.mysims[key].read_oneresult()
165
+
166
+ def add_simulations(self,
167
+ sims_to_add:dict[str, Union[str, Wolfresults_2D, wolfres2DGPU]],
168
+ epsilon:float=None,
169
+ force_read:bool = False):
170
+ """
171
+ Add multiple simulations to the project
172
+
173
+ :param sims_to_add: dict[str, Union[str, Wolfresults_2D, wolfres2DGPU]] -- dictionary of simulations to add
174
+ """
175
+
176
+ for key, value in sims_to_add.items():
177
+ self.add(key, value, epsilon, force_read)
178
+
179
+ def load_simulations(self, epsilon:float, verbose:bool=False):
84
180
  """
85
181
  Load all simulations in current project
86
182
  """
@@ -92,6 +188,7 @@ class Wolf2D_Project(Project):
92
188
  for key,val in sims_wolf2d.items():
93
189
  if verbose:
94
190
  print(key)
191
+ logging.info(f'Loading simulation {key} : {val[key_Param.VALUE]}')
95
192
 
96
193
  cursim = self.mysims[key] = Wolfresults_2D(join(self.wdir, val[key_Param.VALUE]), eps=epsilon, idx=key)
97
194
  cursim.plotted=True
@@ -102,6 +199,7 @@ class Wolf2D_Project(Project):
102
199
  for key,val in sims_gpu2d.items():
103
200
  if verbose:
104
201
  print(key)
202
+ logging.info(f'Loading simulation {key} : {val[key_Param.VALUE]}')
105
203
 
106
204
  cursim = self.mysims[key] = wolfres2DGPU(Path(join(self.wdir, val[key_Param.VALUE])), eps=epsilon, idx=key)
107
205
  cursim.plotted=True
@@ -128,6 +226,23 @@ class Wolf2D_Project(Project):
128
226
  for cursim in self.mysims.values():
129
227
  cursim.read_oneresult()
130
228
 
229
+ def get_simulation(self, key:Union[str,int]) -> Union[Wolfresults_2D, wolfres2DGPU]:
230
+ """
231
+ Get simulation by key
232
+
233
+ :param key: str or int -- key of the simulation to get or index of the simulation to get
234
+ """
235
+
236
+ if isinstance(key,int):
237
+ if key >=0 and key <len(self.mysims):
238
+ return self.mysims[self.mysims.keys()[key]]
239
+
240
+ elif isinstance(key,str):
241
+ if key in self.mysims.keys():
242
+ return self.mysims[key]
243
+
244
+ return None
245
+
131
246
  def get_simulations(self) -> list:
132
247
  """
133
248
  Return a python list of simulations
@@ -175,6 +290,7 @@ class Wolf2D_Project(Project):
175
290
  """
176
291
  Lie les palettes d'un fichier projet et leur liaison potentielle avec les matrices
177
292
  """
293
+
178
294
  pals = self.get_group('palette')
179
295
  if pals is None:
180
296
  return
@@ -207,6 +323,7 @@ class Wolf2D_Project(Project):
207
323
  """
208
324
  Change le mode de vue dans une vue possible de "views_2D"
209
325
  """
326
+
210
327
  if which in views_2D:
211
328
  with ThreadPoolExecutor() as executor:
212
329
  for cursim in self.mysims.values():
@@ -221,10 +338,11 @@ class Wolf2D_Project(Project):
221
338
  - chaque entrée est un dictionnaire dont la clé 'values' contient une liste pour chaque matrice du projet
222
339
  - chaque élément de liste est un tuple contenant toutes les valeurs utiles
223
340
  """
341
+
224
342
  self.poly = zonepoly
225
343
  self.poly_values = zonepoly.get_all_values_linked_polygon(self.get_simulations())
226
344
 
227
- def get_values(self,which_type):
345
+ def get_values(self,which_type:Union[views_2D, Literal['i','j','block']]=None):
228
346
 
229
347
  if self.poly_values is None:
230
348
  raise Warning(_('Firstly call get_values_inside with a zone as argument -- Retry !'))
@@ -271,15 +389,58 @@ class Wolf2D_Project(Project):
271
389
 
272
390
  class MultiProjects():
273
391
  """Manager of multiple project files"""
392
+
274
393
  def __init__(self, wdir='') -> None:
275
394
 
276
395
  self.projects:dict[str, Wolf2D_Project]={}
277
396
  self.wdir=wdir
278
397
 
398
+ def __getitem__(self, key:Union[str,int]) -> Project:
399
+ """
400
+ Get project by key
401
+ """
402
+
403
+ return self.get_project(key)
404
+
405
+ def get_one_simulation(self, key_project:str, key_sim:str) -> Union[Wolfresults_2D, wolfres2DGPU]:
406
+ """
407
+ Get one simulation by key in a project
408
+ """
409
+
410
+ if key_project in self.projects.keys():
411
+ return self.projects[key_project].get_simulation(key_sim)
412
+
413
+ return None
414
+
415
+ def get_same_simulation_in_projects(self, key_sim:str) -> dict[str, Union[Wolfresults_2D, wolfres2DGPU]]:
416
+ """
417
+ Get simulation by key in all projects
418
+ """
419
+
420
+ allsims = {}
421
+ for curkey, curproj in self.projects.items():
422
+ cursim = curproj.get_simulation(key_sim)
423
+ if cursim is not None:
424
+ allsims[curkey + ' - ' + key_sim] = cursim
425
+
426
+ return allsims
427
+
428
+ def __str__(self) -> str:
429
+ """
430
+ Return string representation
431
+ """
432
+
433
+ ret = 'Key : Directory\n'
434
+ for curkey,curproj in self.projects.items():
435
+ ret+=f'{curkey} : {Path(curproj.wdir)}\n'
436
+
437
+ return ret
438
+
279
439
  def add(self, project:Project, key=str, whichtype=project_type.GENERIC):
280
440
  """
281
441
  Add project to dict
282
442
  """
443
+
283
444
  if isinstance(project,str):
284
445
  if exists(project):
285
446
  pass
@@ -297,6 +458,7 @@ class MultiProjects():
297
458
  """
298
459
  Récupération d'un projet sur base du nom ou d'une position
299
460
  """
461
+
300
462
  if isinstance(key,int):
301
463
  if key >=0 and key <len(self.projects):
302
464
  return self.projects[self.projects.keys()[key]]
@@ -306,11 +468,12 @@ class MultiProjects():
306
468
  return self.projects[key]
307
469
 
308
470
  return None
309
-
471
+
310
472
  def read(self, filepath:str):
311
473
  """
312
474
  Read from file
313
475
  """
476
+
314
477
  if exists(filepath):
315
478
  with open(filepath,'r') as f:
316
479
  self.projects = json.load(f)
@@ -319,6 +482,7 @@ class MultiProjects():
319
482
  """
320
483
  Write to file
321
484
  """
485
+
322
486
  with open(filepath,'w') as f:
323
487
  json.dump(self.projects,f)
324
488
 
@@ -326,6 +490,7 @@ class MultiProjects():
326
490
  """
327
491
  Load all simulations in projects
328
492
  """
493
+
329
494
  for keyp,valp in self.projects.items():
330
495
  print(keyp)
331
496
  valp.load_simulations(epsilon, verbose)
@@ -334,14 +499,18 @@ class MultiProjects():
334
499
  """
335
500
  Update all simulations in projects
336
501
  """
502
+
337
503
  for keyp,valp in self.projects.items():
338
504
  print(keyp)
339
505
  valp.update_simulations(epsilon, verbose)
340
506
 
341
- def get_simulations_list(self, which_project=None) -> list:
507
+ def get_simulations_list(self, which_project:Union[str, list[str]]=None) -> list:
342
508
  """
343
509
  Return a python list of simulations
510
+
511
+ :param which_project: str or list of str -- key(s) of the project(s) to get simulations from
344
512
  """
513
+
345
514
  if which_project is None:
346
515
  allsims=[]
347
516
  for curproj in self.projects.values():
@@ -349,6 +518,15 @@ class MultiProjects():
349
518
  allsims+=curproj.get_simulations()
350
519
  return allsims
351
520
 
521
+ elif isinstance(which_project, list):
522
+ allsims=[]
523
+ for curkey in which_project:
524
+ if curkey in self.projects.keys():
525
+ curproj = self.projects[curkey]
526
+ if isinstance(curproj, Wolf2D_Project):
527
+ allsims+=curproj.get_simulations()
528
+ return allsims
529
+
352
530
  elif which_project in self.projects.keys():
353
531
  curproj = self.projects[which_project]
354
532
  if isinstance(curproj, Wolf2D_Project):
@@ -356,10 +534,13 @@ class MultiProjects():
356
534
 
357
535
  return None
358
536
 
359
- def get_simulations_dict(self, which_project=None) -> dict:
537
+ def get_simulations_dict(self, which_project:Union[str, list[str]]=None) -> dict:
360
538
  """
361
539
  Return a python dict of simulations
540
+
541
+ :param which_project: str or list of str -- key(s) of the project(s) to get simulations from
362
542
  """
543
+
363
544
  if which_project is None:
364
545
  allsims={}
365
546
  for curkey, curproj in self.projects.items():
@@ -367,6 +548,15 @@ class MultiProjects():
367
548
  allsims[curkey] = curproj.get_simulations()
368
549
  return allsims
369
550
 
551
+ elif isinstance(which_project, list):
552
+ allsims={}
553
+ for curkey in which_project:
554
+ if curkey in self.projects.keys():
555
+ curproj = self.projects[curkey]
556
+ if isinstance(curproj, Wolf2D_Project):
557
+ allsims[curkey] = curproj.get_simulations()
558
+ return allsims
559
+
370
560
  elif which_project in self.projects.keys():
371
561
  curproj = self.projects[which_project]
372
562
  if isinstance(curproj, Wolf2D_Project):
@@ -374,7 +564,9 @@ class MultiProjects():
374
564
 
375
565
  return None
376
566
 
377
- def set_currentview(self, which):
567
+ def set_currentview(self, which:views_2D):
568
+ """ Change le mode de vue dans une vue possible de 'views_2D' """
569
+
378
570
  for curproj in self.projects.values():
379
571
  if isinstance(curproj, Wolf2D_Project):
380
572
  curproj.set_currentview(which)
wolfhece/pybridges.py CHANGED
@@ -31,6 +31,7 @@ class stored_values_unk(Enum):
31
31
  UNORM = (5, views_2D.UNORM.value)
32
32
  FROUDE = (6, views_2D.FROUDE.value)
33
33
  WATERLEVEL = (7, views_2D.WATERLEVEL.value)
34
+ WATERSTAGE = (7, views_2D.WATERLEVEL.value)
34
35
  TOPOGRAPHY = (8, views_2D.TOPOGRAPHY.value)
35
36
  HEAD = (-1, _('Difference of waterlevel (up-down)'))
36
37
  DIFFERENCE_Z_UP_DOWN = (-1, _('Difference of waterlevel (up-down)'))
@@ -7,20 +7,151 @@ from typing import Literal, Union
7
7
  import matplotlib.pyplot as plt
8
8
  from enum import Enum
9
9
  import logging
10
+ from pathlib import Path
10
11
 
11
12
  from .PyTranslate import _
12
13
  from .PyVertexvectors import Zones, zone, vector, vectorproperties, getIfromRGB
13
14
  from .drawing_obj import Element_To_Draw
14
15
  from .PyTranslate import _
15
- from .wolfresults_2D import views_2D
16
+ from .wolfresults_2D import views_2D, Wolfresults_2D
17
+ from .Results2DGPU import wolfres2DGPU
16
18
  from .pybridges import stored_values_pos,stored_values_unk, parts_values, operators, stored_values_coords
17
19
 
20
+ from zipfile import ZIP_DEFLATED, ZipFile
21
+
22
+ class ZipFileWrapper(ZipFile):
23
+ def open(self, name="data", mode="r", pwd=None, **kwargs):
24
+ return super().open(name=name, mode=mode, pwd=pwd, **kwargs)
25
+
26
+ def read(self):
27
+ return super().read(name="data")
28
+
18
29
  class Extracting_Zones(Zones):
30
+ """
31
+ Classe permettant de récupérer les valeurs à l'intérieur des polygones
32
+ définis dans plusieurs zones.
33
+
34
+ Ces polygones ne sont pas nécessairement ordonnés ou relatifs au lit mineur.
35
+
36
+ """
19
37
 
20
38
  def __init__(self, filename='', ox: float = 0, oy: float = 0, tx: float = 0, ty: float = 0, parent=None, is2D=True, idx: str = '', plotted: bool = True, mapviewer=None, need_for_wx: bool = False) -> None:
21
39
  super().__init__(filename, ox, oy, tx, ty, parent, is2D, idx, plotted, mapviewer, need_for_wx)
22
- self.parts = {}
23
- self.linked = {}
40
+
41
+ self.parts:dict = None
42
+ self.linked:Union[dict, list] = None
43
+
44
+ def cache_data(self, outputfile:str):
45
+ """
46
+ Serialize the values in a file
47
+ """
48
+ self._serialize_values(outputfile)
49
+
50
+ def load_data(self, inputfile:str):
51
+ """
52
+ Deserialize the values from a file
53
+ """
54
+ self._deserialize_values(inputfile)
55
+
56
+ def _serialize_values(self, outputfile:str):
57
+ """
58
+ Serialize the values in a file
59
+ """
60
+
61
+ import json
62
+ from codecs import getwriter
63
+ from typing import IO
64
+
65
+ class NumpyArrayEncoder(json.JSONEncoder):
66
+ def default(self, obj):
67
+ if isinstance(obj, np.integer):
68
+ return int(obj)
69
+ elif isinstance(obj, np.floating):
70
+ return float(obj)
71
+ elif isinstance(obj, np.ndarray):
72
+ return obj.tolist()
73
+ elif obj == Wolfresults_2D:
74
+ return 'CPU'
75
+ elif obj == wolfres2DGPU:
76
+ return 'GPU'
77
+
78
+ return json.JSONEncoder.default(self, obj)
79
+
80
+ def _json_dump_bytes(fp: IO, obj):
81
+ StreamWriter = getwriter("utf-8")
82
+ return json.dump(fp=StreamWriter(fp), obj=obj, cls=NumpyArrayEncoder, indent=4)
83
+
84
+ def json_dump_zip(fp: IO, obj):
85
+ with ZipFileWrapper(fp, mode="w", compression=ZIP_DEFLATED, compresslevel=9) as zip_file:
86
+ with zip_file.open(mode="w") as _fp:
87
+ _json_dump_bytes(fp=_fp, obj=obj)
88
+
89
+
90
+ with open(outputfile, 'wb') as f:
91
+
92
+ json_dump_zip(fp = f, obj = {'linked' : self.linked, 'values': self.parts})
93
+
94
+
95
+ def _deserialize_values(self, inputfile:str):
96
+ """
97
+ Deserialize the values from a file
98
+ """
99
+
100
+ import json
101
+ from codecs import getwriter
102
+ from typing import IO
103
+
104
+ def json_load_zip(fp: IO):
105
+ with ZipFileWrapper(fp, mode="r") as zip_file:
106
+ return json.load(zip_file)
107
+
108
+ inputfile = Path(inputfile)
109
+ if not inputfile.exists():
110
+ logging.error(_('File {0} does not exist').format(inputfile))
111
+ return
112
+
113
+ with open(inputfile, 'rb') as f:
114
+ data = json_load_zip(f) #json.load(f)
115
+
116
+ tmp_linked = data['linked']
117
+ if isinstance(tmp_linked, dict):
118
+ self.linked = {}
119
+ for curkey, curgroup in tmp_linked.items():
120
+ self.linked[curkey] = [(curlink[0], Wolfresults_2D if curlink[1] == 'CPU' else wolfres2DGPU) for curlink in curgroup]
121
+
122
+ tmp_values = data['values']
123
+ self.parts = {}
124
+
125
+ for cuzone, curparts in tmp_values.items():
126
+ self.parts[cuzone] = {}
127
+
128
+ for curproj, curdict in curparts.items():
129
+ self.parts[cuzone][curproj] = {}
130
+ for curpoly, curval in curdict.items():
131
+ self.parts[cuzone][curproj][curpoly] = {}
132
+ for curgroup, curarray in curval.items():
133
+ locdict = self.parts[cuzone][curproj][curpoly][curgroup] = {}
134
+
135
+ for cursim, curnparray in curarray.items():
136
+ locdict[cursim] = np.array([np.array([ tuple(lst1), np.array(lst2, dtype= np.int32)], dtype=object ) for lst1, lst2 in curnparray], dtype=object)
137
+
138
+ elif isinstance(tmp_linked, list):
139
+ self.linked = [(curlink[0], Wolfresults_2D if curlink[1] == 'CPU' else wolfres2DGPU) for curlink in tmp_linked]
140
+
141
+ tmp_values = data['values']
142
+ self.parts = {}
143
+
144
+ for cuzone, curparts in tmp_values.items():
145
+ self.parts[cuzone] = {}
146
+
147
+ for curpoly, curval in curparts.items():
148
+ self.parts[cuzone][curpoly] = {}
149
+ for curgroup, curarray in curval.items():
150
+ locdict = self.parts[cuzone][curpoly][curgroup] = {}
151
+
152
+ for cursim, curnparray in curarray.items():
153
+ locdict[cursim] = np.array([np.array([ tuple(lst1), np.array(lst2, dtype= np.int32)], dtype=object ) for lst1, lst2 in curnparray], dtype=object)
154
+
24
155
 
25
156
  def find_values_inside_parts(self, linked_arrays):
26
157
  """
@@ -45,13 +176,14 @@ class Extracting_Zones(Zones):
45
176
 
46
177
  self.linked = [(curlink.idx, type(curlink)) for curlink in linked_arrays]
47
178
 
179
+ self.parts = {}
48
180
  for curzone in self.myzones:
49
-
50
181
  if isinstance(linked_arrays, dict):
51
182
  locparts = self.parts[curzone.myname] = {}
52
183
  for curkey, curgroup in linked_arrays.items():
53
184
  locparts[curkey] = curzone.get_all_values_linked_polygon(curgroup, key_idx_names='name', getxy=True)
54
- elif isinstance(linked_arrays, list):
185
+
186
+ elif isinstance(linked_arrays, list):
55
187
  self.parts[curzone.myname] = curzone.get_all_values_linked_polygon(linked_arrays, key_idx_names='name', getxy=True)
56
188
 
57
189
  def _get_heads(self,
@@ -228,6 +360,14 @@ class Extracting_Zones(Zones):
228
360
 
229
361
  class Polygons_Analyze(Zones):
230
362
  """
363
+ Classe permettant de récupérer les valeurs à l'intérieur des polygones
364
+ définis dans la dernière zone d'une fichier .vecz.
365
+
366
+ Ce fichier est typiquement le résultat de la création de polygones
367
+ sur base de parallèles via l'interface graphique.
368
+
369
+ Utile notamment dans l'analyse de modélisations 2D (CPU et/ou GPU).
370
+
231
371
  """
232
372
 
233
373
  def __init__(self, myfile='', ds:float=5., ox: float = 0, oy: float = 0, tx: float = 0, ty: float = 0, parent=None, is2D=True, wx_exists:bool = False):
@@ -235,11 +375,15 @@ class Polygons_Analyze(Zones):
235
375
 
236
376
  self.myname = splitext(basename(myfile))[0]
237
377
 
378
+ self.linked:Union[dict,list] = None # type is depending on the type of linked arrays
379
+ self.river_values:dict = None
380
+
238
381
  self.riverbed = self.get_zone(0).myvectors[1]
239
382
  self.riverbed.prepare_shapely()
240
383
 
241
384
  self.polygons_zone:zone
242
385
  self.polygons_zone = self.get_zone(-1)
386
+
243
387
  self.polygons_curvi = {}
244
388
  for curvert in self.polygons_zone.myvectors:
245
389
  self.polygons_curvi[curvert.myname] = curvert.myvertices[0].z
@@ -247,41 +391,130 @@ class Polygons_Analyze(Zones):
247
391
  for vec in self.polygons_zone.myvectors:
248
392
  vec.myprop.used=False # cache les polygones pour ne pas surcharger l'affichage éventuel
249
393
 
250
- def colorize(self):
251
- """Colorisation des polygones pour l'interface graphique"""
252
- self.centralpart.myprop.color = getIfromRGB((0,255,0))
253
- self.upstream.myprop.color = getIfromRGB((255,0,0))
254
- self.downstream.myprop.color = getIfromRGB((0,0,255))
394
+ def cache_data(self, outputfile:str):
395
+ """
396
+ Serialize the values in a json file -- zipped
397
+ """
398
+
399
+ self._serialize_values(outputfile)
255
400
 
256
- def highlighting(self, rgb=(255,0,0), linewidth=3):
401
+ def load_data(self, inputfile:str):
257
402
  """
258
- Mise en évidence
403
+ Deserialize the values from a json file -- zipped
259
404
  """
260
- self.centralpart.highlighting(rgb,linewidth)
261
405
 
262
- def withdrawal(self):
406
+ self._deserialize_values(inputfile)
407
+
408
+ def _serialize_values(self, outputfile:str):
263
409
  """
264
- Mise en retrait
410
+ Serialize the values in a file
265
411
  """
266
- self.centralpart.withdrawal()
412
+
413
+ import json
414
+ from codecs import getwriter
415
+ from typing import IO
416
+
417
+ class NumpyArrayEncoder(json.JSONEncoder):
418
+ def default(self, obj):
419
+ if isinstance(obj, np.integer):
420
+ return int(obj)
421
+ elif isinstance(obj, np.floating):
422
+ return float(obj)
423
+ elif isinstance(obj, np.ndarray):
424
+ return obj.tolist()
425
+ elif obj == Wolfresults_2D:
426
+ return 'CPU'
427
+ elif obj == wolfres2DGPU:
428
+ return 'GPU'
429
+
430
+ return json.JSONEncoder.default(self, obj)
431
+
432
+ def _json_dump_bytes(fp: IO, obj):
433
+ StreamWriter = getwriter("utf-8")
434
+ return json.dump(fp=StreamWriter(fp), obj=obj, cls=NumpyArrayEncoder, indent=4)
435
+
436
+ def json_dump_zip(fp: IO, obj):
437
+ with ZipFileWrapper(fp, mode="w", compression=ZIP_DEFLATED, compresslevel=9) as zip_file:
438
+ with zip_file.open(mode="w") as _fp:
439
+ _json_dump_bytes(fp=_fp, obj=obj)
440
+
441
+
442
+ with open(outputfile, 'wb') as f:
443
+
444
+ json_dump_zip(fp = f, obj = {'linked' : self.linked, 'values': self.river_values})
445
+
446
+
447
+ def _deserialize_values(self, inputfile:str):
448
+ """
449
+ Deserialize the values from a file
450
+ """
451
+
452
+ import json
453
+ from codecs import getwriter
454
+ from typing import IO
455
+
456
+ def json_load_zip(fp: IO):
457
+ with ZipFileWrapper(fp, mode="r") as zip_file:
458
+ return json.load(zip_file)
459
+
460
+ inputfile = Path(inputfile)
461
+ if not inputfile.exists():
462
+ logging.error(_('File {0} does not exist').format(inputfile))
463
+ return
464
+
465
+ with open(inputfile, 'rb') as f:
466
+ data = json_load_zip(f) #json.load(f)
467
+
468
+ tmp_linked = data['linked']
469
+ if isinstance(tmp_linked, dict):
470
+ self.linked = {}
471
+ for curkey, curgroup in tmp_linked.items():
472
+ self.linked[curkey] = [(curlink[0], Wolfresults_2D if curlink[1] == 'CPU' else wolfres2DGPU) for curlink in curgroup]
473
+
474
+ tmp_values = data['values']
475
+ self.river_values = {}
476
+ for curproj, curdict in tmp_values.items():
477
+ self.river_values[curproj] = {}
478
+ for curpoly, curval in curdict.items():
479
+ self.river_values[curproj][curpoly] = {}
480
+ for curgroup, curarray in curval.items():
481
+ locdict = self.river_values[curproj][curpoly][curgroup] = {}
482
+
483
+ for cursim, curnparray in curarray.items():
484
+ locdict[cursim] = np.array([np.array([ tuple(lst1), np.array(lst2, dtype= np.int32)], dtype=object ) for lst1, lst2 in curnparray], dtype=object)
485
+
486
+ elif isinstance(tmp_linked, list):
487
+ self.linked = [(curlink[0], Wolfresults_2D if curlink[1] == 'CPU' else wolfres2DGPU) for curlink in tmp_linked]
488
+
489
+ tmp_values = data['values']
490
+ self.river_values = {}
491
+ for curpoly, curval in tmp_values.items():
492
+ self.river_values[curpoly] = {}
493
+ for curgroup, curarray in curval.items():
494
+ locdict = self.river_values[curpoly][curgroup] = {}
495
+
496
+ for cursim, curnparray in curarray.items():
497
+ locdict[cursim] = np.array([np.array([ tuple(lst1), np.array(lst2, dtype= np.int32)], dtype=object ) for lst1, lst2 in curnparray], dtype=object)
498
+
267
499
 
268
500
  def compute_distance(self, poly:LineString):
269
501
  """
270
502
  Compute the curvilinear distance along a support polyline
271
503
  """
504
+
272
505
  for curvert in self.polygons_zone.myvectors:
506
+ # Centre du polygone
273
507
  centerx = np.sum(np.asarray([cur.x for cur in curvert.myvertices[:4]]))/4.
274
508
  centery = np.sum(np.asarray([cur.y for cur in curvert.myvertices[:4]]))/4.
509
+
275
510
  self.polygons_curvi[curvert.myname] = poly.project(Point([centerx,centery]))
276
511
 
277
- def find_values_inside_parts(self, linked_arrays):
512
+ def find_values_inside_parts(self, linked_arrays:Union[dict,list]):
278
513
  """
279
- Récupère les valeurs à l'intérieur :
280
- - des parties du pont (amont, centrale, aval)
281
- - de la discrétisation rivière en polygones
514
+ Récupère les valeurs à l'intérieur des polygones - dernière zone du fichier
282
515
 
283
- Retour :
284
- - dictionnaire dont la clé est le nom (ou l'index) du polygone dans la zone --> parties centrale, amont ou aval
516
+ Stockage :
517
+ - dictionnaire dont la clé est le nom (ou l'index) du polygone dans la zone
285
518
  - chaque entrée est un dictionnaire dont la clé 'values' contient un dictionnaire pour chaque matrice du projet
286
519
  - chaque élément de ce sous-dictionnaire est un tuple contenant toutes les valeurs utiles
287
520
 
@@ -291,9 +524,16 @@ class Polygons_Analyze(Zones):
291
524
 
292
525
  """
293
526
 
294
- self.linked={}
295
- for curkey, curgroup in linked_arrays.items():
296
- self.linked[curkey] = [(curlink.idx, type(curlink)) for curlink in curgroup]
527
+ if isinstance(linked_arrays, dict):
528
+
529
+ self.linked={}
530
+
531
+ for curkey, curgroup in linked_arrays.items():
532
+ self.linked[curkey] = [(curlink.idx, type(curlink)) for curlink in curgroup]
533
+
534
+ elif isinstance(linked_arrays, list):
535
+
536
+ self.linked = [(curlink.idx, type(curlink)) for curlink in linked_arrays]
297
537
 
298
538
  # récupération des valeurs danbs les polygones "rivière"
299
539
  curzone = self.polygons_zone
@@ -302,12 +542,15 @@ class Polygons_Analyze(Zones):
302
542
  self.river_values={}
303
543
  for curkey, curgroup in linked_arrays.items():
304
544
  self.river_values[curkey] = curzone.get_all_values_linked_polygon(curgroup, key_idx_names='name')
545
+
305
546
  elif isinstance(linked_arrays, list):
547
+
306
548
  self.river_values = curzone.get_all_values_linked_polygon(linked_arrays, key_idx_names='name')
307
549
 
308
550
  def _get_river_heads(self,
309
551
  which_group=None):
310
552
  """Compute Head"""
553
+
311
554
  head = {}
312
555
 
313
556
  z = self.get_river_values(stored_values_unk.WATERLEVEL, which_group)
@@ -400,6 +643,11 @@ class Polygons_Analyze(Zones):
400
643
  which_value:Union[stored_values_unk,stored_values_pos],
401
644
  which_group=None,
402
645
  operator:operators=operators.MEDIAN) -> dict:
646
+ """
647
+ Get values for the river polygons with an operator
648
+
649
+ operator : MEDIAN, MIN, MAX, PERCENTILE95, PERCENTILE5, ALL
650
+ """
403
651
 
404
652
  def extract_info(vals):
405
653
  vals_ret={}
@@ -407,18 +655,23 @@ class Polygons_Analyze(Zones):
407
655
  curdict = vals_ret[curkeypoly]={}
408
656
  for curkey, curvals in curpoly.items():
409
657
  if curvals is not None:
410
- if operator == operators.MEDIAN:
411
- curdict[curkey] = np.median(curvals)
412
- elif operator == operators.MIN:
413
- curdict[curkey] = np.min(curvals)
414
- elif operator == operators.MAX:
415
- curdict[curkey] = np.max(curvals)
416
- elif operator == operators.PERCENTILE95:
417
- curdict[curkey] = np.percentile(curvals,95)
418
- elif operator == operators.PERCENTILE5:
419
- curdict[curkey] = np.percentile(curvals,5)
420
- elif operator == operators.ALL:
421
- curdict[curkey] = (np.median(curvals), np.min(curvals), np.max(curvals), np.percentile(curvals,95), np.percentile(curvals,5))
658
+ try:
659
+ if operator == operators.MEDIAN:
660
+ curdict[curkey] = np.median(curvals)
661
+ elif operator == operators.MIN:
662
+ curdict[curkey] = np.min(curvals)
663
+ elif operator == operators.MAX:
664
+ curdict[curkey] = np.max(curvals)
665
+ elif operator == operators.PERCENTILE95:
666
+ curdict[curkey] = np.percentile(curvals,95)
667
+ elif operator == operators.PERCENTILE5:
668
+ curdict[curkey] = np.percentile(curvals,5)
669
+ elif operator == operators.ALL:
670
+ curdict[curkey] = (np.median(curvals), np.min(curvals), np.max(curvals), np.percentile(curvals,95), np.percentile(curvals,5))
671
+ except:
672
+ logging.error(_('Error in extract_info for key {0}').format(curkey))
673
+ curdict[curkey] = -1.
674
+
422
675
  return vals_ret
423
676
 
424
677
  vals = self.get_river_values(which_value, which_group)
@@ -432,6 +685,32 @@ class Polygons_Analyze(Zones):
432
685
 
433
686
  return vals_ret
434
687
 
688
+ def get_s_values(self,
689
+ which_value:Union[stored_values_unk,stored_values_pos]=stored_values_unk.WATERLEVEL,
690
+ which_group:str=None,
691
+ which_sim:str=None,
692
+ operator:operators=operators.MEDIAN):
693
+ """ Get the values of the river polygons for a specific simulation """
694
+
695
+ s=[]
696
+ val=[]
697
+
698
+ myval = self.get_river_values_op(which_value, which_group, operator)
699
+
700
+ for curkey, curval in myval.items():
701
+ if len(curval)>0 and which_sim in curval.keys():
702
+ val.append(curval[which_sim])
703
+ s.append(self.polygons_curvi[curkey])
704
+
705
+ # Tri des valeurs selon l'absisse curviligne
706
+ ret = sorted(zip(s, val))
707
+
708
+ # Séparation des listes triées
709
+ s, val = zip(*ret)
710
+
711
+ return s, val
712
+
713
+
435
714
  def plot_unk(self,
436
715
  figax = None,
437
716
  which_value:Union[stored_values_unk,stored_values_pos]=stored_values_unk.WATERLEVEL,
@@ -440,6 +719,7 @@ class Polygons_Analyze(Zones):
440
719
  options:dict=None,
441
720
  label=True,
442
721
  show=False):
722
+ """ Plot the values of the river polygons """
443
723
 
444
724
  if figax is None:
445
725
  fig,ax = plt.subplots(1,1)
@@ -520,6 +800,7 @@ class Polygons_Analyze(Zones):
520
800
  which_group=None,
521
801
  operator:operators=operators.MEDIAN,
522
802
  show=False):
803
+ """ Plot the waterline """
523
804
 
524
805
  fig,ax = self.plot_unk(figax, stored_values_unk.TOPOGRAPHY, which_group, operator, options={'color':'black', 'linewidth':2}, label=False, show=False)
525
806
  figax=(fig,ax)
@@ -539,6 +820,7 @@ class Polygons_Analyze(Zones):
539
820
  which_group=None,
540
821
  operator:operators=operators.MEDIAN,
541
822
  show=False):
823
+ """ Plot the bed elevation """
542
824
 
543
825
  fig,ax = self.plot_unk(figax, stored_values_unk.TOPOGRAPHY, which_group, operator, options={'color':'black', 'linewidth':2}, label=False, show=False)
544
826
 
@@ -555,6 +837,7 @@ class Polygons_Analyze(Zones):
555
837
  which_group=None,
556
838
  operator:operators=operators.MEDIAN,
557
839
  show=False):
840
+ """ Plot the water stage /water level """
558
841
 
559
842
  fig,ax = self.plot_unk(figax, stored_values_unk.WATERLEVEL, which_group, operator, options={'color':'blue', 'linewidth':2}, show=False)
560
843
 
@@ -571,6 +854,7 @@ class Polygons_Analyze(Zones):
571
854
  which_group=None,
572
855
  operator:operators=operators.MEDIAN,
573
856
  show=False):
857
+ """ Plot the water head """
574
858
 
575
859
  fig,ax = self.plot_unk(figax, stored_values_unk.HEAD, which_group, operator, options={'color':'blue', 'linewidth':2}, show=False)
576
860
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: wolfhece
3
- Version: 2.1.6
3
+ Version: 2.1.8
4
4
  Author-email: Pierre Archambeau <pierre.archambeau@uliege.be>
5
5
  License: AGPL-v3 License
6
6
  Project-URL: Homepage, https://uee.uliege.be/hece
@@ -11,7 +11,7 @@ wolfhece/PyGui.py,sha256=VKE785z9XLIWNbxqpyEceLK_wtmPJyq6A_M_qX_94Lg,104772
11
11
  wolfhece/PyGuiHydrology.py,sha256=wKhR-KthPRyzJ887NmsozmUpm2CIQIwO3IbYORCYjrE,7290
12
12
  wolfhece/PyHydrographs.py,sha256=GKK8U0byI45H9O_e4LAOOi7Aw0Tg7Q0Lx322stPg5IQ,3453
13
13
  wolfhece/PyPalette.py,sha256=_Nm2Lc4UxYlZgK8ifZDioG8a0at8oiteYC0x_4XugFc,24384
14
- wolfhece/PyParams.py,sha256=361iy9b9zTjoPCj9gh8-OIo0TBW5laLG87AkWE6f_eg,96290
14
+ wolfhece/PyParams.py,sha256=963fkDSEadlLLxe7WM4Nl6nLOeZsOWSFmfg7hIsWPU4,96785
15
15
  wolfhece/PyPictures.py,sha256=-mJB0JL2YYiEK3D7_ssDkvYiMWK4ve9kXhozQXNeSx8,2216
16
16
  wolfhece/PyTranslate.py,sha256=4appkmNeHHZLFmUtaA_k5_5QL-5ymxnbVN4R2OblmtE,622
17
17
  wolfhece/PyVertex.py,sha256=dHTjyYYTn0F_NWerlAOBKHV79RUzEEtMJMldQtVc1Cs,40092
@@ -34,13 +34,13 @@ wolfhece/import_ascfiles.py,sha256=jg4urcLdSgFS1Knvh7AVGJqM44qc_uYDNrR568tMh-A,4
34
34
  wolfhece/ins.py,sha256=0aU1mo4tYbw64Gwzrqbh-NCTH1tukmk0mpPHjRPHZXU,12661
35
35
  wolfhece/irm_qdf.py,sha256=749SlAXiN1oXp5tfBJoPNJWxydQlY55K0qvIM5YexlM,15436
36
36
  wolfhece/ismember.py,sha256=fkLvaH9fhx-p0QrlEzqa6ySO-ios3ysjAgXVXzLgSpY,2482
37
- wolfhece/multiprojects.py,sha256=AMwEQZqo1Twh6tSPP-4L29-Fa8cI9d6dWce7l88awws,14675
37
+ wolfhece/multiprojects.py,sha256=tHrAdOBoEEsuNS8hV7udbvduOZLj_NqF3ee5hSDBhN8,20903
38
38
  wolfhece/picc.py,sha256=KKPNk1BEe7QBzo2icIsdsxUopJ1LXYTomfdfeG2gCeA,7419
39
39
  wolfhece/pyGui1D.py,sha256=pzLWXQ_w3Y_yI846w1GklFO9h5lWZOqiUzg1BUPkuRI,121616
40
- wolfhece/pybridges.py,sha256=HJ1BL1HC7UrgpQ-3jKXkqPFmc-TzToL28Uex2hjHk6c,57166
40
+ wolfhece/pybridges.py,sha256=4PRSsWngDmQnlVuN2tJj0C_HT1h47ExH9QTUPs_Wxlg,57215
41
41
  wolfhece/pydike.py,sha256=G4jfSZaAHHr4VWEJqnXSvEswXvlOz1yhbhQ6uu3AqyM,1943
42
42
  wolfhece/pylogging.py,sha256=i9Zugx3t9dPc7nBwcP20L_R4_k_WawpAQsvbZU8l9Hg,4230
43
- wolfhece/pypolygons_scen.py,sha256=lrUty990vT1iiILiIuTY8pNStiaZOi2dXWJuL9C-4Ps,26211
43
+ wolfhece/pypolygons_scen.py,sha256=Zqr_vs--QEKRSxG-SfduqSR0aPT5rM3BRxmXTOSh2Iw,37146
44
44
  wolfhece/pyshields.py,sha256=YS6VVjjzoA-ZR6YRccqjMcW3McNqNLoQODC6TNNkmPw,22983
45
45
  wolfhece/pyviews.py,sha256=hYdyrEvWF48dGBDOLIwmC28C0L8I28U4ohXk9nltF94,9666
46
46
  wolfhece/pywalous.py,sha256=GRS5TKoVT0J-3PBqMdlyFRHrqkdYC-uHgDPcMjoDEZw,18674
@@ -66,7 +66,7 @@ wolfhece/apps/check_install.py,sha256=jrKR-njqnpIh6ZJqvP6KbDUPVCfwTNQj4glQhcyzs9
66
66
  wolfhece/apps/curvedigitizer.py,sha256=avWERHuVxPnJBOD_ibczwW_XG4vAenqWS8W1zjhBox8,4898
67
67
  wolfhece/apps/isocurrent.py,sha256=4XnNWPa8mYUK7V4zdDRFrHFIXNG2AN2og3TqWKKcqjY,3811
68
68
  wolfhece/apps/splashscreen.py,sha256=LkEVMK0eCc84NeCWD3CGja7fuQ_k1PrZdyqD3GQk_8c,2118
69
- wolfhece/apps/version.py,sha256=e4viWx1A5GTOG7x_ee5ipUIoVs03YPj1mmqIboCFecM,387
69
+ wolfhece/apps/version.py,sha256=PDHOsWyysK2-MjO9X84FVTmdBAJq_uSXODfI01muO7E,387
70
70
  wolfhece/apps/wolf.py,sha256=gqfm-ZaUJqNsfCzmdtemSeqLw-GVdSVix-evg5WArJI,293
71
71
  wolfhece/apps/wolf2D.py,sha256=gWD9ee2-1pw_nUxjgRaJMuSe4kUT-RWhOeoTt_Lh1mM,267
72
72
  wolfhece/apps/wolf_logo.bmp,sha256=ruJ4MA51CpGO_AYUp_dB4SWKHelvhOvd7Q8NrVOjDJk,3126
@@ -264,8 +264,8 @@ wolfhece/sounds/sonsw2.wav,sha256=pFLVt6By0_EPQNt_3KfEZ9a1uSuYTgQSX1I_Zurv9Rc,11
264
264
  wolfhece/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
265
265
  wolfhece/ui/wolf_multiselection_collapsiblepane.py,sha256=yGbU_JsF56jsmms0gh7mxa7tbNQ_SxqhpAZxhm-mTy4,14860
266
266
  wolfhece/ui/wolf_times_selection_comparison_models.py,sha256=wCxGRnE3kzEkWlWA6-3X8ADOFux_B0a5QWJ2GnXTgJw,4709
267
- wolfhece-2.1.6.dist-info/METADATA,sha256=cugMr7AdpxcXB9lUui3lqbla85asvy4lo-Q8-0per-Y,2281
268
- wolfhece-2.1.6.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
269
- wolfhece-2.1.6.dist-info/entry_points.txt,sha256=AIu1KMswrdsqNq_2jPtrRIU4tLjuTnj2dCY-pxIlshw,276
270
- wolfhece-2.1.6.dist-info/top_level.txt,sha256=EfqZXMVCn7eILUzx9xsEu2oBbSo9liWPFWjIHik0iCI,9
271
- wolfhece-2.1.6.dist-info/RECORD,,
267
+ wolfhece-2.1.8.dist-info/METADATA,sha256=na4Fmpn_XCY_8wAgiMs1m3YfEMKwUNC7mZ33W2JzU70,2281
268
+ wolfhece-2.1.8.dist-info/WHEEL,sha256=cpQTJ5IWu9CdaPViMhC9YzF8gZuS5-vlfoFihTBC86A,91
269
+ wolfhece-2.1.8.dist-info/entry_points.txt,sha256=AIu1KMswrdsqNq_2jPtrRIU4tLjuTnj2dCY-pxIlshw,276
270
+ wolfhece-2.1.8.dist-info/top_level.txt,sha256=EfqZXMVCn7eILUzx9xsEu2oBbSo9liWPFWjIHik0iCI,9
271
+ wolfhece-2.1.8.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (70.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5