wolfhece 2.0.17__py3-none-any.whl → 2.0.19__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 (42) hide show
  1. wolfhece/CpGrid.py +10 -13
  2. wolfhece/PyCrosssections.py +18 -13
  3. wolfhece/PyDraw.py +80 -8
  4. wolfhece/PyHydrographs.py +2 -2
  5. wolfhece/PyParams.py +113 -35
  6. wolfhece/PyPictures.py +48 -45
  7. wolfhece/PyVertex.py +149 -18
  8. wolfhece/PyVertexvectors.py +40 -33
  9. wolfhece/apps/curvedigitizer.py +4 -1
  10. wolfhece/apps/wolfcompare2Darrays.py +11 -7
  11. wolfhece/clientserver/clientserver.py +62 -0
  12. wolfhece/friction_law.py +39 -34
  13. wolfhece/ftp/downloader.py +8 -7
  14. wolfhece/gpuview.py +14 -13
  15. wolfhece/hydrology/Catchment.py +2 -2
  16. wolfhece/hydrology/PyWatershed.py +2 -2
  17. wolfhece/hydrology/SubBasin.py +13 -11
  18. wolfhece/hydrometry/kiwis_gui.py +9 -9
  19. wolfhece/irm_qdf.py +12 -10
  20. wolfhece/lazviewer/laz_viewer.py +4 -1
  21. wolfhece/mar/Interface_MAR_WOLF_objet.py +260 -161
  22. wolfhece/opengl/py3d.py +4 -4
  23. wolfhece/pyshields.py +4 -4
  24. wolfhece/pythonfortran/example_makendarray.py +46 -41
  25. wolfhece/pythonfortran/example_numpy_memory.py +87 -83
  26. wolfhece/pythonfortran/tools.py +1 -1
  27. wolfhece/scenario/imposebc_void.py +2 -3
  28. wolfhece/scenario/update_void.py +6 -6
  29. wolfhece/wolf_array.py +47 -18
  30. wolfhece/wolfresults_2D.py +2 -4
  31. {wolfhece-2.0.17.dist-info → wolfhece-2.0.19.dist-info}/METADATA +7 -1
  32. {wolfhece-2.0.17.dist-info → wolfhece-2.0.19.dist-info}/RECORD +36 -41
  33. wolfhece/apps/wolfBernoulli.py +0 -18
  34. wolfhece/bernoulli/ModelJockgrim.py +0 -226
  35. wolfhece/bernoulli/NetworkOpenGL.py +0 -6461
  36. wolfhece/bernoulli/ReadNeupotzData.py +0 -223
  37. wolfhece/bernoulli/opti_results_interactive_plot.py +0 -212
  38. wolfhece/debug.py +0 -8
  39. /wolfhece/{bernoulli → clientserver}/__init__.py +0 -0
  40. {wolfhece-2.0.17.dist-info → wolfhece-2.0.19.dist-info}/WHEEL +0 -0
  41. {wolfhece-2.0.17.dist-info → wolfhece-2.0.19.dist-info}/entry_points.txt +0 -0
  42. {wolfhece-2.0.17.dist-info → wolfhece-2.0.19.dist-info}/top_level.txt +0 -0
wolfhece/CpGrid.py CHANGED
@@ -4,19 +4,16 @@ import wx.grid
4
4
  from .PyTranslate import _
5
5
 
6
6
  class CpGrid(wx.grid.Grid):
7
- """ A Full Copy and Paste enabled grid class which implements Excel
8
- like copy, paste, and delete functionality.
9
-
10
- Ctrl+c - Copy range of selected cells.
11
- Ctrl+v - Paste copy selection at point of currently selected cell.
12
- If paste selection is larger than copy selection,
13
- copy selection will be replicated to fill paste
14
- region if it is a modulo number of copy rows and/or
15
- columns, otherwise just the copy selection will be pasted.
16
- Ctrl+x - Delete current selection. Deleted selection can be
17
- restored with Ctrl+z, or pasted with Ctrl+v.
18
- Delete or backspace key will also perform this action.
19
- Ctrl+z - Undo the last paste or delete action.
7
+ """
8
+ A Full Copy and Paste enabled grid class which implements Excel like copy, paste, and delete functionality.
9
+
10
+ - Ctrl+c : Copy range of selected cells.
11
+ - Ctrl+v : Paste copy selection at point of currently selected cell.
12
+ - If paste selection is larger than copy selection, copy selection will be replicated to fill paste region if it is a modulo number of copy rows and/or columns, otherwise just the copy selection will be pasted.
13
+ - Ctrl+x : Delete current selection.
14
+ - Deleted selection can be restored with Ctrl+z, or pasted with Ctrl+v.
15
+ - Delete or backspace key will also perform this action.
16
+ - Ctrl+z : Undo the last paste or delete action.
20
17
 
21
18
  """
22
19
 
@@ -393,7 +393,7 @@ class profile(vector):
393
393
  self.myvertices[-1].y-self.myvertices[0].y])
394
394
  self.orient = self.orient /np.linalg.norm(self.orient)
395
395
 
396
- def get_xy_from_s(self,s) -> (float, float):
396
+ def get_xy_from_s(self,s) -> tuple[float, float]:
397
397
  """
398
398
  Récupération d'un tuple (x,y) sur base d'une distance 2D 's' orientée dans l'axe de la section
399
399
  """
@@ -672,7 +672,7 @@ class profile(vector):
672
672
 
673
673
  return length
674
674
 
675
- def get_sz(self, cumul=True) -> (np.ndarray, np.ndarray):
675
+ def get_sz(self, cumul=True) -> tuple[np.ndarray, np.ndarray]:
676
676
  """
677
677
  Retourne 2 vecteurs avec la position curvi 2D et l'altitude des points
678
678
  """
@@ -729,7 +729,7 @@ class profile(vector):
729
729
  curvert = wolfvertex(xy[i,0],xy[i,1],sz[i,1])
730
730
  self.add_vertex(curvert)
731
731
 
732
- def get_sz_banksbed(self, cumul=True, force:bool=False) -> (float, float, float, float, float, float):
732
+ def get_sz_banksbed(self, cumul=True, force:bool=False) -> tuple[float, float, float, float, float, float]:
733
733
  """
734
734
  Retourne les positions des points de référence mais avec la coordonnée curvi 2D
735
735
  - (sleft, sbed, sright, zleft, zbed, zright)
@@ -791,10 +791,10 @@ class profile(vector):
791
791
 
792
792
  return sleft,sbed,sright,zleft,zbed,zright
793
793
 
794
- def get_s3d_banksbed(self, force:bool=False)-> (float, float, float):
794
+ def get_s3d_banksbed(self, force:bool=False)-> tuple[float, float, float]:
795
795
  """
796
796
  Retourne les coordonnée curvi 3D des points de référence
797
- - (sleft, sbed, sright)
797
+ - (sleft, sbed, sright)
798
798
  """
799
799
 
800
800
  if self.prepared and not force:
@@ -1678,11 +1678,11 @@ class crosssections(Element_To_Draw):
1678
1678
 
1679
1679
  L'objet stocke ses informations dans un dictionnaire : self.myprofiles
1680
1680
  Les clés de chaque entrée sont:
1681
- ['index'] : integer
1682
- ['left'] : wolfvertex
1683
- ['bed'] : wolfvertex
1684
- ['right'] : wolfvertex
1685
- ['cs'] : profile (surcharge de vector)
1681
+ - ['index'] : integer
1682
+ - ['left'] : wolfvertex
1683
+ - ['bed'] : wolfvertex
1684
+ - ['right'] : wolfvertex
1685
+ - ['cs'] : profile (surcharge de vector)
1686
1686
 
1687
1687
  Pour le moment, il est possible de lire les fichiers et d'effectuer cerrains traitements (tri selon vecteur, export gltf...).
1688
1688
 
@@ -1694,6 +1694,7 @@ class crosssections(Element_To_Draw):
1694
1694
  - cloud_all
1695
1695
 
1696
1696
  @remark !! La classe n'est pas encore prévue pour créer des sections en travers!!
1697
+
1697
1698
  """
1698
1699
 
1699
1700
  myprofiles:dict
@@ -2419,8 +2420,10 @@ class crosssections(Element_To_Draw):
2419
2420
  self.multils = self.asshapely_ls()
2420
2421
 
2421
2422
  def sort_along(self,vecsupport:LineString,name:str,downfirst=True):
2422
- """Sélectionne les sections qui intersectent un vecteur support
2423
- et les trie selon l'abscisse curviligne"""
2423
+ """
2424
+ Sélectionne les sections qui intersectent un vecteur support
2425
+ et les trie selon l'abscisse curviligne
2426
+ """
2424
2427
 
2425
2428
  curdict = self.sorted[name]={}
2426
2429
  curdict['support'] = vecsupport
@@ -2989,7 +2992,9 @@ class Interpolator():
2989
2992
  return xy,z
2990
2993
 
2991
2994
  class Interpolators():
2992
- """ Classe de gestion des interpolations sur sections en travers """
2995
+ """
2996
+ Classe de gestion des interpolations sur sections en travers
2997
+ """
2993
2998
 
2994
2999
  def __init__(self, banks:Zones, cs:crosssections, ds=1.) -> None:
2995
3000
  """
wolfhece/PyDraw.py CHANGED
@@ -1002,10 +1002,20 @@ class WolfMapViewer(wx.Frame):
1002
1002
  self.active_array.interpolate_on_triangulation(self.active_tri.pts, self.active_tri.tri, )
1003
1003
 
1004
1004
  def compare_cloud2array(self):
1005
+ """
1006
+ Compare the active cloud points to the active array
1007
+
1008
+ """
1009
+
1010
+ if self.active_array is None :
1011
+ logging.warning(_('No active array -- Please activate an array first'))
1012
+ return
1005
1013
 
1006
- if self.active_array is not None and self.active_cloud is not None:
1014
+ if self.active_cloud is None:
1015
+ logging.warning(_('No active cloud -- Please activate a cloud first'))
1016
+ return
1007
1017
 
1008
- self.active_array.compare_cloud(self.active_cloud)
1018
+ self.active_array.compare_cloud(self.active_cloud)
1009
1019
 
1010
1020
  def compare_tri2array(self):
1011
1021
 
@@ -1748,7 +1758,8 @@ class WolfMapViewer(wx.Frame):
1748
1758
  '2012-2013': 'ORTHO_2012_2013',
1749
1759
  '2015': 'ORTHO_2015', '2016': 'ORTHO_2016', '2017': 'ORTHO_2017',
1750
1760
  '2018': 'ORTHO_2018', '2019': 'ORTHO_2019', '2020': 'ORTHO_2020',
1751
- '2021': 'ORTHO_2021'}}
1761
+ '2021': 'ORTHO_2021', '2022 printemps': 'ORTHO_2022_PRINTEMPS', '2022 été': 'ORTHO_2022_ETE',
1762
+ '2023 été': 'ORTHO_2023_ETE'}}
1752
1763
  for idx, (k, item) in enumerate(orthos.items()):
1753
1764
  for kdx, (m, subitem) in enumerate(item.items()):
1754
1765
  self.add_object(which='wmsback',
@@ -2429,6 +2440,13 @@ class WolfMapViewer(wx.Frame):
2429
2440
  else:
2430
2441
  logging.info(_('Bad parameter in project file - array : ')+ curname[key_Param.VALUE])
2431
2442
 
2443
+ if 'cloud' in myproject.myparams.keys():
2444
+ for curid, curname in zip(myproject.myparams['cloud'].keys(), myproject.myparams['cloud'].values()):
2445
+ if exists(curname[key_Param.VALUE]):
2446
+ mycloud = cloud_vertices(curname[key_Param.VALUE])
2447
+ self.add_object('cloud', newobj=mycloud, id=curid)
2448
+ else:
2449
+ logging.info(_('Bad parameter in project file - cloud : ')+ curname[key_Param.VALUE])
2432
2450
 
2433
2451
  if 'wolf2d' in myproject.myparams.keys():
2434
2452
  for curid, curname in zip(myproject.myparams['wolf2d'].keys(), myproject.myparams['wolf2d'].values()):
@@ -3005,15 +3023,66 @@ class WolfMapViewer(wx.Frame):
3005
3023
 
3006
3024
  elif itemlabel == _("Plot active vector..."):
3007
3025
 
3026
+
3008
3027
  if self.active_vector is None:
3028
+ logging.warning(_('No active vector !'))
3009
3029
  return
3010
3030
 
3031
+ add_cloud = False
3032
+ if self.active_cloud is not None:
3033
+ dlg = wx.MessageDialog(self, _('Do you want to plot the cloud ?'), style=wx.YES_NO)
3034
+
3035
+ if dlg.ShowModal() == wx.ID_YES:
3036
+ add_cloud = True
3037
+
3038
+ prox = wx.TextEntryDialog(None,_('Proximity [m] ?'), value = '5.0')
3039
+ ret = prox.ShowModal()
3040
+ if ret == wx.ID_CANCEL:
3041
+ prox.Destroy()
3042
+ return
3043
+ try:
3044
+ proxval = float(prox.GetValue())
3045
+ except:
3046
+ prox.Destroy()
3047
+ logging.warning(_('Bad value -- Rety'))
3048
+ return
3049
+
3050
+ tol = wx.TextEntryDialog(None,_('Tolerance [m] ?'), value = '0.5')
3051
+ ret = tol.ShowModal()
3052
+ if ret == wx.ID_CANCEL:
3053
+ tol.Destroy()
3054
+ return
3055
+ try:
3056
+ tolval = float(tol.GetValue())
3057
+ except:
3058
+ tol.Destroy()
3059
+ logging.warning(_('Bad value -- Rety'))
3060
+ return
3061
+
3062
+ else:
3063
+ add_cloud = False
3064
+
3065
+ dlg.Destroy()
3066
+
3011
3067
  fig, ax = self.active_vector.plot_mpl(True, False)
3012
3068
 
3013
3069
  linkedarrays = self.get_linked_arrays()
3014
3070
 
3015
3071
  self.active_vector.plot_linked(fig, ax, linkedarrays)
3016
3072
 
3073
+ if add_cloud:
3074
+ s, z = self.active_cloud.projectontrace(self.active_vector, return_cloud=False, proximity= proxval)
3075
+
3076
+ ax.scatter( s, z, c='black', s=1.0)
3077
+
3078
+ for curs, curz in zip(s,z):
3079
+ ax.plot([curs, curs], [curz-tolval, curz+tolval], 'k--', linewidth=0.5)
3080
+ ax.plot([curs-.1, curs+.1], [curz+tolval, curz+tolval], c='black', linewidth=0.5)
3081
+ ax.plot([curs-.1, curs+.1], [curz-tolval, curz-tolval], c='black', linewidth=0.5)
3082
+
3083
+ fig.canvas.draw()
3084
+ fig.canvas.flush_events()
3085
+
3017
3086
  elif itemlabel == _("Export arrays as Geotif..."):
3018
3087
 
3019
3088
  self.export_results_as('geotiff')
@@ -4268,9 +4337,10 @@ class WolfMapViewer(wx.Frame):
4268
4337
  filterall = "all (*.*)|*.*"
4269
4338
  filterres2d = "all (*.*)|*.*"
4270
4339
  filterVector = "vec (*.vec)|*.vec|vecz (*.vecz)|*.vecz|dxf (*.dxf)|*.dxf|shp (*.shp)|*.shp|all (*.*)|*.*"
4271
- filterCloud = "xyz (*.xyz)|*.xyz|dxf (*.dxf)|*.dxf|text (*.txt)|*.txt|all (*.*)|*.*"
4340
+ filterCloud = "xyz (*.xyz)|*.xyz|dxf (*.dxf)|*.dxf|text (*.txt)|*.txt|shp (*.shp)|*.shp|all (*.*)|*.*"
4272
4341
  filtertri = "tri (*.tri)|*.tri|text (*.txt)|*.txt|dxf (*.dxf)|*.dxf|gltf (*.gltf)|*.gltf|gltf binary (*.glb)|*.glb|*.*'all (*.*)|*.*"
4273
4342
  filterCs = "vecz WOLF (*.vecz)|*.vecz|txt 2022 (*.txt)|*.txt|WOLF (*.sxy)|*.sxy|text 2000 (*.txt)|*.txt|all (*.*)|*.*"
4343
+ filterimage = "Geotif (*.tif)|*.tif|all (*.*)|*.*"
4274
4344
 
4275
4345
  if filename == '' and newobj is None:
4276
4346
  # ouverture d'une boîte de dialogue
@@ -4303,9 +4373,9 @@ class WolfMapViewer(wx.Frame):
4303
4373
 
4304
4374
  # FIXME : particularize filters for wmsback and wmsfore
4305
4375
  elif which.lower() == 'wmsback':
4306
- file = wx.FileDialog(self, "Choose file", wildcard=filterCloud)
4376
+ file = wx.FileDialog(self, "Choose file", wildcard=filterimage)
4307
4377
  elif which.lower() == 'wmsfore':
4308
- file = wx.FileDialog(self, "Choose file", wildcard=filterCloud)
4378
+ file = wx.FileDialog(self, "Choose file", wildcard=filterimage)
4309
4379
 
4310
4380
  if file.ShowModal() == wx.ID_CANCEL:
4311
4381
  file.Destroy()
@@ -4718,12 +4788,13 @@ class WolfMapViewer(wx.Frame):
4718
4788
  newobj.mapviewer = self
4719
4789
 
4720
4790
  elif which.lower() == 'cloud':
4791
+
4721
4792
  curdict = self.myclouds
4722
4793
  curtree = self.myitemscloud
4723
4794
  if newobj is None:
4724
4795
 
4725
4796
  loadhead = False
4726
- if not filename.endswith('.dxf'):
4797
+ if not filename.endswith('.dxf') and not filename.endswith('.shp'):
4727
4798
  with open(filename,'r') as f:
4728
4799
  text=f.read().splitlines()
4729
4800
  tmphead=''
@@ -4738,7 +4809,7 @@ class WolfMapViewer(wx.Frame):
4738
4809
 
4739
4810
  with wx.lib.busy.BusyInfo(_('Importing cloud points')):
4740
4811
  wait = wx.BusyCursor()
4741
- newobj = cloud_vertices(filename,header=loadhead)
4812
+ newobj = cloud_vertices(filename, header=loadhead)
4742
4813
  del wait
4743
4814
 
4744
4815
  self.myclouds.append(newobj)
@@ -6681,6 +6752,7 @@ class WolfMapViewer(wx.Frame):
6681
6752
  self.active_tile = None
6682
6753
  self.active_particle_system = None
6683
6754
  self.active_vertex = None
6755
+ self.active_cloud = None
6684
6756
 
6685
6757
  elif key == ord('C'):
6686
6758
 
wolfhece/PyHydrographs.py CHANGED
@@ -86,8 +86,8 @@ class Hydrograph(pd.Series):
86
86
  """
87
87
  Read a wolf file at the format infil[n].tv and
88
88
  return its data as a dictionnary where:
89
- - keys are times and,
90
- - values are discharges.
89
+ - keys are times and
90
+ - values are discharges
91
91
 
92
92
  """
93
93
  data = {}
wolfhece/PyParams.py CHANGED
@@ -110,10 +110,9 @@ class Wolf_Param(wx.Frame):
110
110
  **FR**
111
111
  Gestion des paramètres au format WOLF.
112
112
 
113
- Fichier texte
114
- -------------
113
+ **Fichier texte**
115
114
 
116
- Les fichiers '*.param' sont des fichiers texte contenant des paramètres de type nom=valeur et compatibles avec les codes Fortran.
115
+ Les fichiers '.param' sont des fichiers texte contenant des paramètres de type nom=valeur et compatibles avec les codes Fortran.
117
116
  L'extension '.param.default' est utilisée pour stocker les paramètres par défaut.
118
117
 
119
118
  Une autre extension est possible mais un fichier '.default' sera créé automatiquement si ce fichier n'existe pas.
@@ -124,8 +123,7 @@ class Wolf_Param(wx.Frame):
124
123
 
125
124
  Les lignes débutant par '%' sont des commentaires. Il est possible d'ajouter du code JSON dans un commentaire. Pour cela, il faut ajouter '%json' au début de la ligne suivi d'un dictionnaire (e.g. %json{"Values":{'key1':1, 'key2':2}, "Full_Comment":"fullcomment"} ).
126
125
 
127
- Organisation Python
128
- -------------------
126
+ **Organisation Python**
129
127
 
130
128
  L'objet Python est basé sur des dictionnaires Python. Un dictionnaire par groupe de paramètres.
131
129
 
@@ -138,14 +136,12 @@ class Wolf_Param(wx.Frame):
138
136
  - comment : commentaire du paramètre (str) -- helpful to understand the parameter
139
137
  - added_json : dictionnaire contenant des informations supplémentaires (optionnel) -- permet de stocker des informations supplémentaires sur le paramètre (ex : valeurs possibles, commentaires étendus, ...)
140
138
 
141
- Dictionnaires
142
- -------------
139
+ **Dictionnaires**
143
140
 
144
141
  Il existe un dictionnaire de valeurs par défaut "myparams_default". Pour l'interaction Python-Fortran, c'est le Fortran qui écrit ces paramètres.
145
142
  Il existe un dictionnaire de paramètres actifs "myparams". Il est utilisé pour stocker les paramètres modifiés par l'utilisateur. Normalement, seuls les paramètres modifiés par l'utilisateur sont stockés dans ce dictionnaire et sont écrits sur disque.
146
143
 
147
- Groupe/Paramètre incrémentable
148
- ------------------------------
144
+ **Groupe/Paramètre incrémentable**
149
145
 
150
146
  Il est également possible de définir des groupes ou des paramètres incrémentables.
151
147
  Pour cela, dans le nom du groupe/paramètre, il faut ajouter, à l'emplacement souhaité du **numéro** du groupe/paramètre, des informations entre '$...$' :
@@ -160,14 +156,12 @@ class Wolf_Param(wx.Frame):
160
156
 
161
157
  Les informations génériques sont stockées dans les dictionnaires "myIncGroup" et "myIncParam".
162
158
 
163
- UI
164
- --
159
+ **UI**
165
160
 
166
161
  Une interface graphique est disponible pour modifier les paramètres. Elle est basée sur "wxPython" et la classe "wxPropertyGrid".
167
162
  L'attribut wx_exists permet de savoir si wxPython est en cours d'excution ou non.
168
163
 
169
- Accès aux données
170
- -----------------
164
+ **Accès aux données**
171
165
 
172
166
  Les paramètres sont accessibles via la procédure __getitem__ en fournissant un tuple (groupname, paramname).
173
167
  Il est possible de modifier un paramètre via la procédure __setitem__.
@@ -186,10 +180,9 @@ class Wolf_Param(wx.Frame):
186
180
  **EN**
187
181
  Management of parameters in WOLF format.
188
182
 
189
- Text File
190
- ----------
183
+ **Text File**
191
184
 
192
- '*.param' files are text files containing parameters in the name=value format and compatible with Fortran codes.
185
+ '.param' files are text files containing parameters in the name=value format and compatible with Fortran codes.
193
186
  The '.param.default' extension is used to store default parameters.
194
187
 
195
188
  Another extension is possible, but a '.default' file will be automatically created if this file does not exist.
@@ -200,8 +193,7 @@ class Wolf_Param(wx.Frame):
200
193
 
201
194
  Lines starting with '%' are comments. It is possible to add JSON code in a comment. To do this, add '%json' at the beginning of the line followed by a dictionary (e.g., %json{"Values":{'key1':1, 'key2':2}, "Full_Comment":"fullcomment"}).
202
195
 
203
- Python Organization
204
- -------------------
196
+ **Python Organization**
205
197
 
206
198
  The Python object is based on Python dictionaries. One dictionary per parameter group.
207
199
 
@@ -214,14 +206,12 @@ class Wolf_Param(wx.Frame):
214
206
  - comment: parameter comment (str) -- helpful to understand the parameter
215
207
  - added_json: dictionary containing additional information (optional) -- used to store additional information about the parameter (e.g., possible values, extended comments, ...)
216
208
 
217
- Dictionaries
218
- -------------
209
+ **Dictionaries**
219
210
 
220
211
  There is a default values dictionary "myparams_default." For Python-Fortran interaction, Fortran writes these parameters.
221
212
  There is an active parameters dictionary "myparams." It is used to store parameters modified by the user. Normally, only parameters modified by the user are stored in this dictionary and written to disk.
222
213
 
223
- Incrementable Group/Parameter
224
- ------------------------------
214
+ **Incrementable Group/Parameter**
225
215
 
226
216
  It is also possible to define incrementable groups or parameters.
227
217
  To do this, in the group/parameter name, add information between '$...$' at the desired **number** location of the group/parameter:
@@ -236,14 +226,12 @@ class Wolf_Param(wx.Frame):
236
226
 
237
227
  Generic information is stored in the "myIncGroup" and "myIncParam" dictionaries.
238
228
 
239
- UI
240
- --
229
+ **UI**
241
230
 
242
231
  A graphical interface is available to modify parameters. It is based on "wxPython" and the "wxPropertyGrid" class.
243
232
  The wx_exists attribute indicates whether wxPython is currently running or not.
244
233
 
245
- Data Access
246
- -----------------
234
+ **Data Access**
247
235
 
248
236
  Parameters are accessible via the __getitem__ method by providing a tuple (groupname, paramname).
249
237
  It is possible to modify a parameter via the __setitem__ method.
@@ -258,7 +246,7 @@ class Wolf_Param(wx.Frame):
258
246
  - for an incrementable parameter, by providing the necessary data in a string $n(refname,min,max)$ or $n(groupname,refname,min,max)$
259
247
  - if the targeted group does not exist, it will be created if all information is available.
260
248
  - only add an incrementable parameter via the add_IncParam method.
261
- ```
249
+
262
250
  """
263
251
 
264
252
  # Définition des propriétés
@@ -283,7 +271,8 @@ class Wolf_Param(wx.Frame):
283
271
  withbuttons: bool = True,
284
272
  DestroyAtClosing:bool = True,
285
273
  toShow:bool = True,
286
- init_GUI:bool = True):
274
+ init_GUI:bool = True,
275
+ force_even_if_same_default:bool = False):
287
276
  """
288
277
  Initialisation
289
278
 
@@ -297,7 +286,7 @@ class Wolf_Param(wx.Frame):
297
286
  :param withbuttons : if True, buttons will be displayed
298
287
  :param DestroyAtClosing : if True, the frame will be destroyed when closed
299
288
  :param toShow : if True, the frame will be displayed
300
-
289
+ :param force_even_if_same_default : if True, the parameter will be displayed even if the default and active parameters are the same
301
290
 
302
291
  Callbacks (see 'set_callbacks'):
303
292
  - callback : callback function when 'apply' is pressed
@@ -317,7 +306,7 @@ class Wolf_Param(wx.Frame):
317
306
  self._callbackdestroy:function = None
318
307
 
319
308
  self.wx_exists = wx.App.Get() is not None # test if wx App is running
320
- self.show_in_active_if_default = False
309
+ self.show_in_active_if_default = force_even_if_same_default
321
310
 
322
311
  if to_read:
323
312
  self.ReadFile(filename)
@@ -469,6 +458,8 @@ class Wolf_Param(wx.Frame):
469
458
  self.SetAutoLayout(1)
470
459
  self.sizer.Fit(self)
471
460
 
461
+ self.SetSize(0,0,w,h)
462
+
472
463
  #affichage de la page
473
464
  self.Show(toShow)
474
465
 
@@ -530,9 +521,13 @@ class Wolf_Param(wx.Frame):
530
521
  page_active.Append(pg.PropertyCategory(groupname))
531
522
 
532
523
  #teste si param existe
533
- if not self.is_in_active(groupname, paramname):
524
+ activeprop = self.prop.GetPropertyByName(groupname + paramname)
525
+ if activeprop is None:
534
526
  #si non existant --> on ajoute, si existant --> rien à faire
535
- self._add_elem_to_page(page_active, groupname, param_def)
527
+ self._insert_elem_to_page(page_active, groupname, param_def)
528
+ # if not self.is_in_active(groupname, paramname):
529
+ # #si non existant --> on ajoute, si existant --> rien à faire
530
+ # self._add_elem_to_page(page_active, groupname, param_def)
536
531
 
537
532
  else:
538
533
  #recopiage de la valeur par défaut
@@ -583,6 +578,16 @@ class Wolf_Param(wx.Frame):
583
578
  # populate the property grid
584
579
  self.Populate()
585
580
 
581
+ def _get_prop_names(self, page:pg.PropertyGridPage) -> list[str]:
582
+ """ Return the names of the properties in a page """
583
+
584
+ return [prop.GetName() for prop in page.GetPyIterator(pg.PG_ITERATE_ALL)]
585
+
586
+ def _is_in_propperty_page(self, page:pg.PropertyGridPage, group:str, param:str="") -> bool:
587
+ """ Test if a parameter is in a page """
588
+
589
+ return (group + param) in self._get_prop_names(page)
590
+
586
591
  def ApplytoMemory(self, event:wx.MouseEvent):
587
592
  """ Transfert des données en mémoire --> remplissage des dictionnaires """
588
593
 
@@ -597,7 +602,19 @@ class Wolf_Param(wx.Frame):
597
602
  if not self._callback is None:
598
603
  self._callback()
599
604
  else:
600
- wx.MessageDialog(self,'Nothing to do!')
605
+ if self.wx_exists:
606
+ dlg = wx.MessageDialog(self,'Nothing to do!')
607
+ dlg.ShowModal()
608
+
609
+ @property
610
+ def page_active(self) -> pg.PropertyGridPage:
611
+ """ Return the active page """
612
+ return self.prop.GetPage(0)
613
+
614
+ @property
615
+ def page_default(self) -> pg.PropertyGridPage:
616
+ """ Return the default page """
617
+ return self.prop.GetPage(1)
601
618
 
602
619
  def _Apply1ParamtoMemory(self,
603
620
  group:str,
@@ -637,7 +654,8 @@ class Wolf_Param(wx.Frame):
637
654
  val_default = self.prop.GetPropertyByName(PREFIX_DEFAULT + group + param_name).m_value
638
655
 
639
656
  # on tente de rcupérer la valeur active mais il ets possible qu'elle n'existe pas si sa valeur est identique à la valeur par défaut
640
- if self.is_in_active(group, param_name):
657
+ if self._is_in_propperty_page(self.page_active, group, param_name):
658
+ # if self.is_in_active(group, param_name):
641
659
  val_active = self.prop.GetPropertyByName(group + param_name).m_value
642
660
  else:
643
661
  val_active = val_default
@@ -653,7 +671,8 @@ class Wolf_Param(wx.Frame):
653
671
  else:
654
672
  # La valeur par défaut n'existe pas --> on prend la valeur active car c'est certainement une valeur incrémentable ou d'un groupe incrémentable
655
673
  # Si la valeur n'est pas présente, on ne fait rien
656
- if self.is_in_active(group, param_name):
674
+ if self._is_in_propperty_page(self.page_active, group, param_name):
675
+ # if self.is_in_active(group, param_name):
657
676
  val_active = self.prop.GetPropertyByName(group + param_name).m_value
658
677
  val_active = self.value_as_type(val_active, dict_param_def[key_Param.TYPE])
659
678
 
@@ -687,7 +706,9 @@ class Wolf_Param(wx.Frame):
687
706
 
688
707
  #gestion des paramètres actifs
689
708
  for group, params in self.myparams.items():
709
+
690
710
  page_active.Append(pg.PropertyCategory(group))
711
+
691
712
  for param_name, param in params.items():
692
713
  param:dict
693
714
  if self.is_in_default(group, param_name):
@@ -713,6 +734,63 @@ class Wolf_Param(wx.Frame):
713
734
  self.prop.ShowHeader()
714
735
  self.prop.Refresh()
715
736
 
737
+ def _insert_elem_to_page(self, page:pg.PropertyGridPage, group:str, param:dict, param_def:dict = None, prefix:str=''):
738
+ """ Insert an element to a page """
739
+
740
+ param_name = param[key_Param.NAME]
741
+ locname = prefix + group + param_name
742
+
743
+ # Get parent item based on group name
744
+ parent = page.GetPropertyByName(group)
745
+ assert parent is not None, "Group {} not found in page".format(group)
746
+ assert isinstance(parent, pg.PropertyCategory), "Parent is not a PropertyCategory"
747
+
748
+ if param_def is not None:
749
+ # priority to default parameters
750
+ if key_Param.ADDED_JSON in param_def.keys():
751
+ param[key_Param.ADDED_JSON] = param_def[key_Param.ADDED_JSON]
752
+ param[key_Param.COMMENT] = param_def[key_Param.COMMENT]
753
+ param[key_Param.TYPE] = param_def[key_Param.TYPE]
754
+
755
+ if key_Param.ADDED_JSON in param.keys() and param[key_Param.ADDED_JSON] is not None:
756
+ # Ajout des choix via chaîne JSON
757
+ list_keys = [ k for k in param[key_Param.ADDED_JSON]['Values'].keys()]
758
+ list_values = [ k for k in param[key_Param.ADDED_JSON]['Values'].values()]
759
+
760
+ page.AppendIn(parent, pg.EnumProperty(param_name, name=locname, labels=list_keys, values=list_values, value=int(param[key_Param.VALUE])))
761
+
762
+ self.prop.SetPropertyHelpString(locname , param[key_Param.ADDED_JSON]['Full_Comment'])
763
+ else:
764
+
765
+ locvalue = self[(group, param_name)]
766
+
767
+ if isinstance(locvalue, float):
768
+ page.AppendIn(parent, pg.FloatProperty(label = param_name, name = locname, value = locvalue))
769
+
770
+ elif isinstance(locvalue, int):
771
+ # bool is also an int
772
+ if isinstance(locvalue, bool):
773
+ page.AppendIn(parent, pg.BoolProperty(label=param_name, name = locname, value = locvalue))
774
+ else:
775
+ page.AppendIn(parent, pg.IntProperty(label = param_name, name = locname, value = locvalue))
776
+
777
+ elif param[key_Param.TYPE]==Type_Param.File:
778
+ page.AppendIn(parent, pg.FileProperty(label=param_name, name = locname, value = param[key_Param.VALUE]))
779
+
780
+ elif param[key_Param.TYPE]==Type_Param.Directory:
781
+ page.AppendIn(parent, pg.DirProperty(label = param_name, name = locname, value = locvalue))
782
+
783
+ elif param[key_Param.TYPE]==Type_Param.Color:
784
+ page.AppendIn(parent, pg.ColourProperty(label = param_name, name = locname, value = locvalue))
785
+
786
+ elif param[key_Param.TYPE]==Type_Param.Fontname:
787
+ page.AppendIn(parent, pg.FontProperty(label = param_name, name = locname, value = locvalue))
788
+
789
+ else:
790
+ page.AppendIn(parent, pg.StringProperty(label = param_name, name = locname, value = locvalue))
791
+
792
+ self.prop.SetPropertyHelpString(locname, param[key_Param.COMMENT])
793
+
716
794
  def _add_elem_to_page(self, page:pg.PropertyGridPage, group:str, param:dict, param_def:dict = None, prefix:str=''):
717
795
  """ Add an element to a page """
718
796