wolfhece 1.8.12__py3-none-any.whl → 2.0.0__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/GraphNotebook.py +0 -1
- wolfhece/PyCrosssections.py +591 -5
- wolfhece/PyDraw.py +1151 -413
- wolfhece/PyGui.py +2 -4
- wolfhece/PyParams.py +1515 -852
- wolfhece/PyVertex.py +73 -73
- wolfhece/PyVertexvectors.py +226 -808
- wolfhece/RatingCurve.py +19 -6
- wolfhece/apps/wolf2D.py +11 -0
- wolfhece/apps/wolfcompare2Darrays.py +51 -22
- wolfhece/bernoulli/NetworkOpenGL.py +337 -341
- wolfhece/drawing_obj.py +25 -0
- wolfhece/hydrology/Catchment.py +77 -77
- wolfhece/hydrology/Optimisation.py +206 -53
- wolfhece/hydrology/PostProcessHydrology.py +22 -22
- wolfhece/hydrology/SubBasin.py +17 -17
- wolfhece/hydrology/constant.py +4 -0
- wolfhece/hydrology/cst_exchanges.py +2 -1
- wolfhece/lazviewer/processing/estimate_normals/estimate_normals.cp310-win_amd64.pyd +0 -0
- wolfhece/lazviewer/vfuncs/vfuncs.cp310-win_amd64.pyd +0 -0
- wolfhece/libs/WolfDll.dll +0 -0
- wolfhece/libs/wolfogl.cp310-win_amd64.pyd +0 -0
- wolfhece/libs/wolfpy.cp310-win_amd64.pyd +0 -0
- wolfhece/mesh2d/wolf2dprev.py +4 -4
- wolfhece/multiprojects.py +13 -13
- wolfhece/pylogging.py +1 -1
- wolfhece/pyshields.py +213 -136
- wolfhece/pyviews.py +23 -23
- wolfhece/wolf_array.py +69 -152
- wolfhece/wolf_texture.py +39 -16
- wolfhece/wolfresults_2D.py +4 -4
- {wolfhece-1.8.12.dist-info → wolfhece-2.0.0.dist-info}/METADATA +3 -2
- {wolfhece-1.8.12.dist-info → wolfhece-2.0.0.dist-info}/RECORD +38 -34
- wolfhece/apps/wolfgpu.py +0 -19
- /wolfhece/lazviewer/processing/estimate_normals/{estimate_normals.pyd → estimate_normals.cp39-win_amd64.pyd} +0 -0
- /wolfhece/lazviewer/vfuncs/{vfuncs.pyd → vfuncs.cp39-win_amd64.pyd} +0 -0
- {wolfhece-1.8.12.dist-info → wolfhece-2.0.0.dist-info}/LICENCE +0 -0
- {wolfhece-1.8.12.dist-info → wolfhece-2.0.0.dist-info}/WHEEL +0 -0
- {wolfhece-1.8.12.dist-info → wolfhece-2.0.0.dist-info}/top_level.txt +0 -0
wolfhece/PyParams.py
CHANGED
@@ -5,6 +5,9 @@ import os.path
|
|
5
5
|
import json
|
6
6
|
import logging
|
7
7
|
from typing import Union, Literal
|
8
|
+
from enum import Enum
|
9
|
+
from copy import deepcopy
|
10
|
+
import numpy as np
|
8
11
|
|
9
12
|
try:
|
10
13
|
from .PyTranslate import _
|
@@ -17,112 +20,290 @@ if not '_' in __builtins__:
|
|
17
20
|
|
18
21
|
PARAM_TRUE = '.True.'
|
19
22
|
PARAM_FALSE = '.False.'
|
20
|
-
|
21
|
-
|
23
|
+
PREFIX_DEFAULT = 'def'
|
24
|
+
|
25
|
+
class Type_Param(Enum):
|
26
|
+
"""
|
27
|
+
Enum to define the type of a parameter
|
28
|
+
|
29
|
+
Strings are also used by Fortran Code -- modify with care
|
30
|
+
"""
|
31
|
+
Integer_or_Float = 'Integer_or_Float'
|
32
|
+
Integer = 'integer'
|
33
|
+
Logical = 'Logical'
|
34
|
+
Float = 'Float'
|
35
|
+
File = 'File'
|
36
|
+
file = 'file'
|
37
|
+
Directory = 'Directory'
|
38
|
+
directory = 'directory'
|
39
|
+
Color = 'Color'
|
40
|
+
Fontname = 'Fontname'
|
41
|
+
String = 'String'
|
42
|
+
Empty = ''
|
43
|
+
Double = 'double'
|
44
|
+
Real = 'real'
|
45
|
+
|
46
|
+
|
47
|
+
class key_Param(Enum):
|
48
|
+
"""
|
49
|
+
Enum to define the keys of a parameter
|
50
|
+
|
51
|
+
"""
|
52
|
+
NAME = 'name'
|
53
|
+
TYPE = 'type'
|
54
|
+
VALUE = 'value'
|
55
|
+
COMMENT = 'comment'
|
56
|
+
ADDED_JSON = 'added_json'
|
57
|
+
|
58
|
+
class Buttons(Enum):
|
59
|
+
""" Enum to define the buttons """
|
60
|
+
Load = 'Load'
|
61
|
+
Save = 'Save'
|
62
|
+
Apply = 'Apply'
|
63
|
+
Reload = 'Reload'
|
64
|
+
|
65
|
+
def new_json(values:dict, fullcomment:str='') -> dict:
|
66
|
+
"""
|
67
|
+
Create a new JSON string from values and fullcomment
|
68
|
+
|
69
|
+
@param values : values to store in the JSON string - dict of key:value - value must be integer
|
70
|
+
@param fullcomment : full comment to store in the JSON string - str - can be multiline with \n
|
71
|
+
"""
|
22
72
|
return {"Values":values, "Full_Comment":fullcomment}
|
23
73
|
|
24
|
-
|
74
|
+
def new_infos_incr(groupname:str= None, paramname:str='nb', min:int=1, max:int=100) -> tuple[str]:
|
75
|
+
"""
|
76
|
+
Create a new string for an incrementable group or parameter
|
77
|
+
|
78
|
+
@param groupname : name of the reference group (optional) -- if ommitted, the reference group is in the same group as the parameter
|
79
|
+
@param paramname : name of the reference parameter
|
80
|
+
@param min : minimum value
|
81
|
+
@param max : maximum value
|
82
|
+
"""
|
83
|
+
if groupname is None:
|
84
|
+
return paramname, str(min), str(max)
|
85
|
+
else:
|
86
|
+
return groupname, paramname, str(min), str(max)
|
87
|
+
|
88
|
+
# FIXME : Généliser avec les dictionnaire avec Enum
|
89
|
+
def search_type(chain:str) -> Type_Param:
|
90
|
+
""" recherche du typage dans une chaîne de caractères """
|
91
|
+
|
92
|
+
if chain.lower().find(Type_Param.Integer.value)>-1 and chain.find(Type_Param.Double.value)>-1:
|
93
|
+
return Type_Param.Integer_or_Float
|
94
|
+
elif chain.lower().find(Type_Param.Integer.value)>-1:
|
95
|
+
return Type_Param.Integer
|
96
|
+
elif chain.find(Type_Param.Logical.value)>-1:
|
97
|
+
return Type_Param.Logical
|
98
|
+
elif chain.find(Type_Param.Double.value)>-1 or chain.find('dble')>-1 or chain.find(Type_Param.Real.value)>-1:
|
99
|
+
return Type_Param.Float
|
100
|
+
elif chain.find('({})'.format(Type_Param.file))>-1:
|
101
|
+
return Type_Param.File
|
102
|
+
elif chain.find('({})'.format(Type_Param.directory))>-1 or chain.find('(dir)')>-1:
|
103
|
+
return Type_Param.Directory
|
104
|
+
else:
|
105
|
+
return Type_Param.String
|
106
|
+
|
107
|
+
|
25
108
|
class Wolf_Param(wx.Frame):
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
myparams_default:dict[str, dict]
|
30
|
-
myIncGroup:dict
|
31
|
-
myIncParam:dict
|
32
|
-
prop:pg.PropertyGridManager
|
33
|
-
wx_exists:bool
|
109
|
+
"""
|
110
|
+
**FR**
|
111
|
+
Gestion des paramètres au format WOLF.
|
34
112
|
|
35
|
-
|
36
|
-
|
37
|
-
name='',
|
38
|
-
value='',
|
39
|
-
type:Literal['Integer_or_Float',
|
40
|
-
'Integer',
|
41
|
-
'Logical',
|
42
|
-
'Float',
|
43
|
-
'File',
|
44
|
-
'Directory',
|
45
|
-
'Color',
|
46
|
-
'Fontname',
|
47
|
-
'']='',
|
48
|
-
comment='',
|
49
|
-
jsonstr=None,
|
50
|
-
whichdict:Literal['All', 'Default', 'Active', '']=''):
|
51
|
-
"""
|
52
|
-
Add or update a parameter
|
113
|
+
Fichier texte
|
114
|
+
-------------
|
53
115
|
|
54
|
-
|
55
|
-
|
56
|
-
@param value : param'a value
|
57
|
-
@param type : type -> will influence the GUI
|
58
|
-
@param comment : param's comment -- helpful to understand the parameter
|
59
|
-
@param jsonstr : string containing JSON data -- used in GUI
|
60
|
-
param whichdict : where to store the param -- Default, Active or All
|
116
|
+
Les fichiers '*.param' sont des fichiers texte contenant des paramètres de type nom=valeur et compatibles avec les codes Fortran.
|
117
|
+
L'extension '.param.default' est utilisée pour stocker les paramètres par défaut.
|
61
118
|
|
62
|
-
|
63
|
-
"""
|
64
|
-
if whichdict=='All':
|
65
|
-
locparams=[self.myparams,self.myparams_default]
|
66
|
-
elif whichdict=='Default':
|
67
|
-
locparams=[self.myparams_default]
|
68
|
-
elif whichdict=='Active' or whichdict=='':
|
69
|
-
locparams=[self.myparams]
|
119
|
+
Une autre extension est possible mais un fichier '.default' sera créé automatiquement si ce fichier n'existe pas.
|
70
120
|
|
71
|
-
|
72
|
-
if not groupname in curdict.keys():
|
73
|
-
curdict[groupname]={}
|
121
|
+
Le séparateur (nom, valeur, commentaire) est la tabulation '\t'. Aucun autre caractère ne doit être utilisé comme séparateur.
|
74
122
|
|
75
|
-
|
76
|
-
curdict[groupname][name]={}
|
123
|
+
Les groupes sont définis par un nom suivi de ':'. Cela signifie que ':' ne peut pas être utilisé dans un nom de paramètre.
|
77
124
|
|
78
|
-
|
125
|
+
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"} ).
|
79
126
|
|
80
|
-
|
81
|
-
|
82
|
-
curpar['value']=value
|
83
|
-
curpar['comment']=comment
|
127
|
+
Organisation Python
|
128
|
+
-------------------
|
84
129
|
|
85
|
-
|
86
|
-
if isinstance(jsonstr, str):
|
87
|
-
parsed_json = json.loads(jsonstr)
|
88
|
-
elif isinstance(jsonstr, dict):
|
89
|
-
parsed_json = jsonstr
|
130
|
+
L'objet Python est basé sur des dictionnaires Python. Un dictionnaire par groupe de paramètres.
|
90
131
|
|
91
|
-
|
132
|
+
Les paramètres sont donc stockés dans un dictionnaire de dictionnaires. Le premier niveau est le nom du groupe, le second niveau est le nom du paramètre.
|
92
133
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
if isinstance(key, tuple) or isinstance(key, list):
|
100
|
-
group, name = key
|
101
|
-
return self.get_param(group, name)
|
102
|
-
elif isinstance(key, str):
|
103
|
-
return self.get_group(key)
|
134
|
+
Les paramètres disposent des clés suivantes :
|
135
|
+
- name : nom du paramètre (str)
|
136
|
+
- type : type du paramètre (str) -- see Type_Param
|
137
|
+
- value : valeur du paramètre (str) -- peut être converti dynamiquement en int, float, bool, str, ... sur base du type
|
138
|
+
- comment : commentaire du paramètre (str) -- helpful to understand the parameter
|
139
|
+
- 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, ...)
|
104
140
|
|
105
|
-
|
106
|
-
|
141
|
+
Dictionnaires
|
142
|
+
-------------
|
107
143
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
144
|
+
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
|
+
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
|
+
|
147
|
+
Groupe/Paramètre incrémentable
|
148
|
+
------------------------------
|
149
|
+
|
150
|
+
Il est également possible de définir des groupes ou des paramètres incrémentables.
|
151
|
+
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 '$...$' :
|
152
|
+
- groupname : nom du groupe (uniquement pour groupe incrémentable)
|
153
|
+
- paramname : nom du paramètre contenant le nombre de groupe/paramètre
|
154
|
+
- min : valeur minimale
|
155
|
+
- max : valeur maximale
|
156
|
+
|
157
|
+
Le nombre de groupes est ainsi défini par le couple (key:value) = (groupname:paramname). Le nombre de groupes doit donc être logiquement positionné dans un groupe distinct.
|
158
|
+
Le nombre de paramètres est ainsi défini par le paramètre "paramname" qui est attendu dans le groupe contenant le paramètre incrémentable.
|
159
|
+
Le nombre de groupes/paramètres est un entier compris entre 'min' et 'max'.
|
160
|
+
|
161
|
+
Les informations génériques sont stockées dans les dictionnaires "myIncGroup" et "myIncParam".
|
162
|
+
|
163
|
+
UI
|
164
|
+
--
|
165
|
+
|
166
|
+
Une interface graphique est disponible pour modifier les paramètres. Elle est basée sur "wxPython" et la classe "wxPropertyGrid".
|
167
|
+
L'attribut wx_exists permet de savoir si wxPython est en cours d'excution ou non.
|
168
|
+
|
169
|
+
Accès aux données
|
170
|
+
-----------------
|
171
|
+
|
172
|
+
Les paramètres sont accessibles via la procédure __getitem__ en fournissant un tuple (groupname, paramname).
|
173
|
+
Il est possible de modifier un paramètre via la procédure __setitem__.
|
174
|
+
|
175
|
+
Il est possible :
|
176
|
+
- d'ajoutrer un groupe via la procédure add_group. Pour un groupe incrémentabe, le nom doit contenir les infos génériques entre '$...$'.
|
177
|
+
- d'ajouter un paramètre ou un paramètre incrémentable via la procédure addparam :
|
178
|
+
- pour un paramètre classique en choisissant le dictionnaire cible ['All', 'Default', 'Active', 'IncGroup', '']
|
179
|
+
- '' == 'Active'
|
180
|
+
- 'All' == 'Default' + 'Active'
|
181
|
+
- 'IncGroup' pour ajouter un paramètre au template du groupe incrémentable --> sera dupliqué lors de la MAJ du nompbre réel de groupes
|
182
|
+
- pour un paramètre incrémentable, en fournissant les données nécessaires dans une chaîne $n(refname,min,max)$ ou $n(groupname,refname,min,max)$
|
183
|
+
- si le groupe visé n'existe pas, il sera créé si toutes les infos sont disponibles.
|
184
|
+
- d'ajouter seulement un paramètre incrémentable via la procédure add_IncParam.
|
185
|
+
|
186
|
+
**EN**
|
187
|
+
Management of parameters in WOLF format.
|
188
|
+
|
189
|
+
Text File
|
190
|
+
----------
|
191
|
+
|
192
|
+
'*.param' files are text files containing parameters in the name=value format and compatible with Fortran codes.
|
193
|
+
The '.param.default' extension is used to store default parameters.
|
194
|
+
|
195
|
+
Another extension is possible, but a '.default' file will be automatically created if this file does not exist.
|
196
|
+
|
197
|
+
The separator (name, value, comment) is the tab character '\t'. No other character should be used as a separator.
|
198
|
+
|
199
|
+
Groups are defined by a name followed by ':'. This means that ':' cannot be used in a parameter name.
|
200
|
+
|
201
|
+
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
|
+
|
203
|
+
Python Organization
|
204
|
+
-------------------
|
205
|
+
|
206
|
+
The Python object is based on Python dictionaries. One dictionary per parameter group.
|
207
|
+
|
208
|
+
Therefore, parameters are stored in a dictionary of dictionaries. The first level is the group name, and the second level is the parameter name.
|
209
|
+
|
210
|
+
Parameters have the following keys:
|
211
|
+
- name: parameter name (str)
|
212
|
+
- type: parameter type (str) -- see Type_Param
|
213
|
+
- value: parameter value (str) -- can be dynamically converted to int, float, bool, str, ... based on the type
|
214
|
+
- comment: parameter comment (str) -- helpful to understand the parameter
|
215
|
+
- added_json: dictionary containing additional information (optional) -- used to store additional information about the parameter (e.g., possible values, extended comments, ...)
|
216
|
+
|
217
|
+
Dictionaries
|
218
|
+
-------------
|
219
|
+
|
220
|
+
There is a default values dictionary "myparams_default." For Python-Fortran interaction, Fortran writes these parameters.
|
221
|
+
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
|
+
|
223
|
+
Incrementable Group/Parameter
|
224
|
+
------------------------------
|
225
|
+
|
226
|
+
It is also possible to define incrementable groups or parameters.
|
227
|
+
To do this, in the group/parameter name, add information between '$...$' at the desired **number** location of the group/parameter:
|
228
|
+
- groupname: group name (only for incrementable group)
|
229
|
+
- paramname: parameter name containing the group/parameter number
|
230
|
+
- min: minimum value
|
231
|
+
- max: maximum value
|
232
|
+
|
233
|
+
The number of groups is defined by the (key:value) pair (groupname:paramname). The number of groups must logically be positioned in a distinct group.
|
234
|
+
The number of parameters is defined by the "paramname" parameter expected in the group containing the incrementable parameter.
|
235
|
+
The number of groups/parameters is an integer between 'min' and 'max'.
|
236
|
+
|
237
|
+
Generic information is stored in the "myIncGroup" and "myIncParam" dictionaries.
|
238
|
+
|
239
|
+
UI
|
240
|
+
--
|
241
|
+
|
242
|
+
A graphical interface is available to modify parameters. It is based on "wxPython" and the "wxPropertyGrid" class.
|
243
|
+
The wx_exists attribute indicates whether wxPython is currently running or not.
|
244
|
+
|
245
|
+
Data Access
|
246
|
+
-----------------
|
247
|
+
|
248
|
+
Parameters are accessible via the __getitem__ method by providing a tuple (groupname, paramname).
|
249
|
+
It is possible to modify a parameter via the __setitem__ method.
|
250
|
+
|
251
|
+
It is possible to:
|
252
|
+
- add a group via the add_group method. For an incrementable group, the name must contain generic information between '$...$'.
|
253
|
+
- add a parameter or an incrementable parameter via the addparam method:
|
254
|
+
- for a regular parameter by choosing the target dictionary ['All', 'Default', 'Active', 'IncGroup', '']
|
255
|
+
- '' == 'Active'
|
256
|
+
- 'All' == 'Default' + 'Active'
|
257
|
+
- 'IncGroup' to add a parameter to the template of the incrementable group --> will be duplicated when updating the actual number of groups
|
258
|
+
- for an incrementable parameter, by providing the necessary data in a string $n(refname,min,max)$ or $n(groupname,refname,min,max)$
|
259
|
+
- if the targeted group does not exist, it will be created if all information is available.
|
260
|
+
- only add an incrementable parameter via the add_IncParam method.
|
261
|
+
```
|
262
|
+
"""
|
263
|
+
|
264
|
+
# Définition des propriétés
|
265
|
+
filename:str # File name
|
266
|
+
myparams:dict[str, dict] # dict for active parameters, see key_Param for keys
|
267
|
+
myparams_default:dict[str, dict] # dict for default parameters, see key_Param for keys
|
268
|
+
|
269
|
+
myIncGroup:dict # dict for incrementable groups
|
270
|
+
myIncParam:dict # dict for incrementable parameters
|
271
|
+
|
272
|
+
prop:pg.PropertyGridManager # wxPropertyGridManager -- see UI
|
273
|
+
wx_exists:bool # True if wxPython is running
|
114
274
|
|
115
|
-
#Initialisation
|
116
275
|
def __init__(self,
|
117
|
-
parent=None,
|
118
|
-
title="Default Title",
|
119
|
-
w=500,
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
276
|
+
parent:wx.Window = None,
|
277
|
+
title:str = "Default Title",
|
278
|
+
w:int = 500,
|
279
|
+
h:int = 800,
|
280
|
+
ontop:bool = False,
|
281
|
+
to_read:bool = True,
|
282
|
+
filename:str = '',
|
283
|
+
withbuttons: bool = True,
|
284
|
+
DestroyAtClosing:bool = True,
|
285
|
+
toShow:bool = True,
|
286
|
+
init_GUI:bool = True):
|
287
|
+
"""
|
288
|
+
Initialisation
|
289
|
+
|
290
|
+
@param parent : parent frame (wx.Window)
|
291
|
+
@param title : title of the frame
|
292
|
+
@param w : width of the frame
|
293
|
+
@param h : height of the frame
|
294
|
+
@param ontop : if True, the frame will be on top of all other windows
|
295
|
+
@param to_read : if True, the file will be read
|
296
|
+
@param filename : filename to read
|
297
|
+
@param withbuttons : if True, buttons will be displayed
|
298
|
+
@param DestroyAtClosing : if True, the frame will be destroyed when closed
|
299
|
+
@param toShow : if True, the frame will be displayed
|
300
|
+
|
301
|
+
|
302
|
+
Callbacks (see 'set_callbacks'):
|
303
|
+
- callback : callback function when 'apply' is pressed
|
304
|
+
- callbackdestroy : callback function before destroying the frame
|
305
|
+
|
306
|
+
"""
|
126
307
|
|
127
308
|
# Initialisation des propriétés
|
128
309
|
self.filename=filename
|
@@ -130,35 +311,98 @@ class Wolf_Param(wx.Frame):
|
|
130
311
|
self.myparams_default={}
|
131
312
|
self.myIncGroup={}
|
132
313
|
self.myIncParam={}
|
314
|
+
self.update_incr_at_every_change = True
|
133
315
|
|
134
|
-
self._callback = None
|
135
|
-
self._callbackdestroy=None
|
316
|
+
self._callback:function = None
|
317
|
+
self._callbackdestroy:function = None
|
136
318
|
|
137
319
|
self.wx_exists = wx.App.Get() is not None # test if wx App is running
|
320
|
+
self.show_in_active_if_default = False
|
138
321
|
|
139
322
|
if to_read:
|
140
323
|
self.ReadFile(filename)
|
141
324
|
|
142
|
-
if self.wx_exists:
|
143
|
-
self.
|
325
|
+
if self.wx_exists and init_GUI:
|
326
|
+
self._set_gui(parent,title,w,h,ontop,to_read,withbuttons,DestroyAtClosing,toShow)
|
327
|
+
else:
|
328
|
+
self.prop = None
|
329
|
+
|
330
|
+
def set_callbacks(self, callback_update, callback_destroy):
|
331
|
+
""" Set the callbacks for the update and destroy events """
|
332
|
+
|
333
|
+
self.callback = callback_update
|
334
|
+
self.callbackdestroy = callback_destroy
|
335
|
+
|
336
|
+
def get_nb_groups(self) -> tuple[int, int]:
|
337
|
+
""" Return the number of groups in active and default parameters """
|
338
|
+
return len(self.myparams.keys()), len(self.myparams_default.keys())
|
339
|
+
|
340
|
+
def get_nb_params(self, group:str) -> tuple[int, int]:
|
341
|
+
""" Return the number of parameters in a group in active and default parameters """
|
342
|
+
return len(self.myparams[group].keys()) if group in self.myparams.keys() else None, len(self.myparams_default[group].keys()) if group in self.myparams_default.keys() else None
|
343
|
+
|
344
|
+
def get_nb_inc_params(self) -> int:
|
345
|
+
""" Return the number of incrementable parameters """
|
346
|
+
return len(self.myIncParam.keys())
|
347
|
+
|
348
|
+
def get_nb_inc_groups(self) -> int:
|
349
|
+
""" Return the number of incrementable groups """
|
350
|
+
return len(self.myIncGroup.keys())
|
144
351
|
|
145
352
|
@property
|
146
353
|
def callback(self):
|
354
|
+
""" Return the callback function """
|
147
355
|
return self._callback
|
148
356
|
|
149
357
|
@callback.setter
|
150
358
|
def callback(self, value):
|
359
|
+
""" Set the callback function """
|
151
360
|
self._callback= value
|
152
361
|
|
153
362
|
@property
|
154
363
|
def callbackdestroy(self):
|
155
|
-
|
364
|
+
""" Return the callback function """
|
365
|
+
return self._callbackdestroy
|
156
366
|
|
157
367
|
@callbackdestroy.setter
|
158
368
|
def callbackdestroy(self, value):
|
369
|
+
""" Set the callback function """
|
159
370
|
self._callbackdestroy= value
|
160
371
|
|
161
|
-
|
372
|
+
# GUI Events - WxPython
|
373
|
+
# ---------------------
|
374
|
+
|
375
|
+
def _set_gui(self,
|
376
|
+
parent:wx.Window = None,
|
377
|
+
title:str = "Default Title",
|
378
|
+
w:int = 500,
|
379
|
+
h:int = 800,
|
380
|
+
ontop:bool = False,
|
381
|
+
to_read:bool = True,
|
382
|
+
withbuttons:bool = True,
|
383
|
+
DestroyAtClosing:bool = True,
|
384
|
+
toShow:bool = True):
|
385
|
+
"""
|
386
|
+
Set the GUI if wxPython is running
|
387
|
+
|
388
|
+
Gui is based on wxPropertyGridManager.
|
389
|
+
|
390
|
+
On the left, there is a group of buttons to load, save, apply or reload the parameters.
|
391
|
+
On the right, there is the wxPropertyGridManager for the default and active parameters. Active parameters are displayed in bold.
|
392
|
+
|
393
|
+
To activate a parameter, double-click on it in the default tab. It will be copied to the active tab and the value will be modifiable.
|
394
|
+
|
395
|
+
@param parent : parent frame
|
396
|
+
@param title : title of the frame
|
397
|
+
@param w : width of the frame
|
398
|
+
@param h : height of the frame
|
399
|
+
@param ontop : if True, the frame will be on top of all other windows
|
400
|
+
@param to_read : if True, the file will be read
|
401
|
+
@param withbuttons : if True, buttons will be displayed
|
402
|
+
@param DestroyAtClosing : if True, the frame will be destroyed when closed
|
403
|
+
@param toShow : if True, the frame will be displayed
|
404
|
+
|
405
|
+
"""
|
162
406
|
|
163
407
|
#Appel à l'initialisation d'un frame général
|
164
408
|
if ontop:
|
@@ -221,677 +465,1116 @@ class Wolf_Param(wx.Frame):
|
|
221
465
|
|
222
466
|
#ajout du sizert à la page
|
223
467
|
self.SetSizer(self.sizer)
|
224
|
-
#self.SetSize(w,h)
|
468
|
+
# self.SetSize(w,h)
|
225
469
|
self.SetAutoLayout(1)
|
226
470
|
self.sizer.Fit(self)
|
227
471
|
|
228
472
|
#affichage de la page
|
229
473
|
self.Show(toShow)
|
230
474
|
|
231
|
-
def hide_selected_buttons(self):
|
232
|
-
""" Mask selected buttons
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
475
|
+
def hide_selected_buttons(self, to_hide:list[Buttons] = [Buttons.Load, Buttons.Save, Buttons.Reload]):
|
476
|
+
""" Mask selected buttons - Default conserve only 'Apply change' """
|
477
|
+
|
478
|
+
for locbutton in to_hide:
|
479
|
+
if locbutton == Buttons.Load:
|
480
|
+
self.sizerbut.Hide(self.loadme)
|
481
|
+
elif locbutton == Buttons.Save:
|
482
|
+
self.sizerbut.Hide(self.saveme)
|
483
|
+
elif locbutton == Buttons.Reload:
|
484
|
+
self.sizerbut.Hide(self.reloadme)
|
485
|
+
elif locbutton == Buttons.Apply:
|
486
|
+
self.sizerbut.Hide(self.applychange)
|
237
487
|
|
238
|
-
|
239
|
-
|
488
|
+
def OnDblClick(self, event:wx.MouseEvent):
|
489
|
+
"""
|
490
|
+
Double-click event handler to add a parameter to the active tab or reset to default value.
|
491
|
+
Gestion du double-click pour ajouter des éléments ou remise à valeur par défaut.
|
492
|
+
"""
|
240
493
|
|
241
|
-
#obtention de la propriété sur laquelle on a cliqué
|
494
|
+
# obtention de la propriété sur laquelle on a cliqué
|
242
495
|
p = event.GetProperty()
|
243
|
-
#nom et valeur du paramètre
|
496
|
+
# nom et valeur du paramètre
|
244
497
|
name = p.GetName()
|
245
|
-
|
498
|
+
from_default_page = name[0:3]==PREFIX_DEFAULT
|
499
|
+
# val = p.GetValue()
|
246
500
|
|
247
|
-
#nom du groupe
|
501
|
+
# nom du groupe
|
248
502
|
group=p.GetParent()
|
249
503
|
groupname=group.GetName()
|
250
504
|
|
251
|
-
#on se place sur la page des paramètres actifs
|
252
|
-
|
253
|
-
|
254
|
-
|
505
|
+
# on se place sur la page des paramètres actifs
|
506
|
+
page_active:pg.PropertyGridPage
|
507
|
+
page_active = self.prop.GetPage(0)
|
508
|
+
# on récupère le nom du paramètre sans le nom du groupe
|
509
|
+
if from_default_page:
|
510
|
+
paramname = name[3+len(groupname):]
|
255
511
|
else:
|
256
|
-
|
512
|
+
paramname = name[len(groupname):]
|
513
|
+
|
514
|
+
if not self.is_in_default(groupname):
|
515
|
+
logging.debug(_('Group {} not found in default parameters -- Maybe an incrementable group'.format(groupname)))
|
516
|
+
return
|
517
|
+
|
518
|
+
if not self.is_in_default(groupname, paramname):
|
519
|
+
logging.warning(_('Param {} not found in default parameters -- Maybe an incrementable param '.format(paramname)))
|
520
|
+
return
|
257
521
|
|
258
522
|
#pointage vers le paramètre par défaut
|
259
|
-
param_def = self.myparams_default[groupname][
|
523
|
+
param_def = self.myparams_default[groupname][paramname]
|
260
524
|
|
261
|
-
if
|
525
|
+
if from_default_page:
|
262
526
|
#click depuis la page des param par défaut
|
263
527
|
|
264
528
|
#essai pour voir si le groupe existe ou non dans les params actifs
|
265
|
-
|
266
|
-
|
267
|
-
except:
|
268
|
-
locgroup=None
|
269
|
-
|
270
|
-
#si groupe non existant on ajoute
|
271
|
-
if locgroup is None:
|
272
|
-
page.Append(pg.PropertyCategory(groupname))
|
529
|
+
if not self.is_in_active(groupname):
|
530
|
+
page_active.Append(pg.PropertyCategory(groupname))
|
273
531
|
|
274
532
|
#teste si param existe
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
param=None
|
279
|
-
|
280
|
-
if param is None:
|
281
|
-
#si non existant --> on ajoute, si existant --> rien
|
282
|
-
locname = groupname + propname
|
283
|
-
if 'added_json' in param_def.keys():
|
284
|
-
list_keys = [ k for k in param_def['added_json']['Values'].keys()]
|
285
|
-
list_values = [ k for k in param_def['added_json']['Values'].values()]
|
286
|
-
page.AppendIn(groupname,pg.EnumProperty(propname,name=locname,labels=list_keys,values=list_values,value=int(param_def['value'])))
|
287
|
-
else:
|
288
|
-
if param_def['type']=='Integer_or_Float':
|
289
|
-
page.AppendIn(groupname,pg.IntProperty(propname,name=locname,value=float(param_def['value'])))
|
290
|
-
elif param_def['type']=='Integer':
|
291
|
-
page.AppendIn(groupname,pg.IntProperty(propname,name=locname,value=int(param_def['value'])))
|
292
|
-
elif param_def['type']=='Logical':
|
293
|
-
if param_def['value']=='.true.' or param_def['value']=='.True.':
|
294
|
-
mybool=True
|
295
|
-
elif param_def['value']=='.false.' or param_def['value']=='.False.':
|
296
|
-
mybool=False
|
297
|
-
page.AppendIn(groupname,pg.BoolProperty(propname,name=locname,value=mybool))
|
298
|
-
elif param_def['type']=='Float':
|
299
|
-
page.AppendIn(groupname,pg.FloatProperty(propname,name=locname,value=float(param_def['value'])))
|
300
|
-
elif param_def['type']=='File':
|
301
|
-
page.AppendIn(groupname,pg.FileProperty(propname,name=locname,value=param_def['value']))
|
302
|
-
elif param_def['type']=='Directory':
|
303
|
-
newobj=pg.DirProperty(locname,locname,value=param_def['value'])
|
304
|
-
newobj.SetLabel(propname)
|
305
|
-
page.Append(newobj)
|
306
|
-
elif param_def['type']=='Color':
|
307
|
-
page.AppendIn(groupname,pg.ColourProperty(propname,name=locname,value=param_def['value']))
|
308
|
-
elif param_def['type']=='Fontname':
|
309
|
-
page.AppendIn(groupname,pg.FontProperty(propname,name=locname,value=param_def['value']))
|
310
|
-
else:
|
311
|
-
page.AppendIn(groupname,pg.StringProperty(propname,name=locname,value=param_def['value']))
|
312
|
-
|
313
|
-
try:
|
314
|
-
self.prop.SetPropertyHelpString(locname,param_def['added_json']['Full_Comment'])
|
315
|
-
except:
|
316
|
-
self.prop.SetPropertyHelpString(locname,param_def['comment'])
|
533
|
+
if not self.is_in_active(groupname, paramname):
|
534
|
+
#si non existant --> on ajoute, si existant --> rien à faire
|
535
|
+
self._add_elem_to_page(page_active, groupname, param_def)
|
317
536
|
|
318
537
|
else:
|
319
538
|
#recopiage de la valeur par défaut
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
elif param_def['type']=='Float':
|
331
|
-
self.prop.SetPropertyValue(groupname + propname,float(param_def['value']))
|
332
|
-
elif param_def['type']=='File':
|
333
|
-
self.prop.SetPropertyValue(groupname + propname,param_def['value'])
|
334
|
-
elif param_def['type']=='Directory':
|
335
|
-
self.prop.SetPropertyValue(groupname + propname,param_def['value'])
|
336
|
-
elif param_def['type']=='Color':
|
337
|
-
self.prop.SetPropertyValue(groupname + propname,param_def['value'])
|
338
|
-
elif param_def['type']=='Fontname':
|
339
|
-
self.prop.SetPropertyValue(groupname + propname,param_def['value'])
|
340
|
-
else:
|
341
|
-
self.prop.SetPropertyValue(groupname + propname,param_def['value'])
|
539
|
+
defvalue = self.value_as_type(param_def[key_Param.VALUE],
|
540
|
+
param_def[key_Param.TYPE],
|
541
|
+
bool_as_int=True,
|
542
|
+
color_as=str)
|
543
|
+
self.prop.SetPropertyValue(groupname + paramname, defvalue)
|
544
|
+
|
545
|
+
def OnClose(self, event:wx.MouseEvent):
|
546
|
+
""" Close event of the frame """
|
547
|
+
if not self._callbackdestroy is None:
|
548
|
+
self._callbackdestroy()
|
342
549
|
|
343
|
-
|
344
|
-
|
345
|
-
|
550
|
+
if self.DestroyAtClosing:
|
551
|
+
self.Destroy()
|
552
|
+
else:
|
553
|
+
self.Hide()
|
554
|
+
pass
|
555
|
+
|
556
|
+
def SavetoFile(self, event:wx.MouseEvent):
|
557
|
+
""" sauvegarde dans le fichier texte """
|
558
|
+
|
559
|
+
with open(self.filename, 'w') as myfile:
|
560
|
+
|
561
|
+
for group in self.myparams.keys():
|
562
|
+
myfile.write(' ' + group +':\n')
|
563
|
+
for param_name in self.myparams[group].keys():
|
564
|
+
myfile.write(param_name +'\t' + str(self.myparams[group][param_name][key_Param.VALUE])+'\n')
|
565
|
+
|
566
|
+
myfile.close()
|
567
|
+
|
568
|
+
def Reload(self, event:wx.MouseEvent):
|
569
|
+
""" relecture du fichier sur base du nom déjà connu """
|
570
|
+
if self.filename=='':
|
571
|
+
logging.warning(_('No filename given'))
|
572
|
+
return
|
573
|
+
self.Clear()
|
574
|
+
self.ReadFile(self.filename)
|
575
|
+
self.Populate()
|
576
|
+
|
577
|
+
def LoadFromFile(self, event:wx.MouseEvent):
|
578
|
+
""" Load parameters from file """
|
579
|
+
|
580
|
+
self.Clear()
|
581
|
+
# read the file
|
346
582
|
self.ReadFile()
|
583
|
+
# populate the property grid
|
347
584
|
self.Populate()
|
348
585
|
|
349
|
-
|
350
|
-
|
351
|
-
if len(args)>0:
|
352
|
-
#s'il y a un argument on le prend tel quel
|
353
|
-
self.filename = str(args[0])
|
354
|
-
else:
|
355
|
-
#ouverture d'une boîte de dialogue
|
356
|
-
file=wx.FileDialog(self,"Choose .param file", wildcard="param (*.param)|*.param|all (*.*)|*.*")
|
357
|
-
if file.ShowModal() == wx.ID_CANCEL:
|
358
|
-
return
|
359
|
-
else:
|
360
|
-
#récuparétaion du nom de fichier avec chemin d'accès
|
361
|
-
self.filename =file.GetPath()
|
586
|
+
def ApplytoMemory(self, event:wx.MouseEvent):
|
587
|
+
""" Transfert des données en mémoire --> remplissage des dictionnaires """
|
362
588
|
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
self.
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
#lecture du contenu
|
374
|
-
if os.path.isfile(self.filename):
|
375
|
-
with open(self.filename, 'r') as myfile:
|
376
|
-
#split des lignes --> récupération des infos sans '\n' en fin de ligne
|
377
|
-
# différent de .readlines() qui lui ne supprime pas les '\n'
|
378
|
-
myparamsline = myfile.read().splitlines()
|
379
|
-
myfile.close()
|
589
|
+
if self.prop.IsPageModified(0):
|
590
|
+
#on boucle sur tous les paramètres pour les ajouter au dictionnaire si non présents
|
591
|
+
for group in self.myparams_default.keys():
|
592
|
+
for param_name in self.myparams_default[group].keys():
|
593
|
+
self._Apply1ParamtoMemory(group, param_name)
|
594
|
+
self._update_IncGroup(withGUI=True)
|
595
|
+
self._update_IncParam(withGUI=True)
|
596
|
+
|
597
|
+
if not self._callback is None:
|
598
|
+
self._callback()
|
380
599
|
else:
|
381
|
-
|
382
|
-
logging.warning(self.filename)
|
383
|
-
return
|
600
|
+
wx.MessageDialog(self,'Nothing to do!')
|
384
601
|
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
602
|
+
def _Apply1ParamtoMemory(self,
|
603
|
+
group:str,
|
604
|
+
param_name:str,
|
605
|
+
isIncrementable:bool=False,
|
606
|
+
genGroup:str="",
|
607
|
+
genParam:str=""):
|
608
|
+
"""
|
609
|
+
Routine interne de MAJ d'un paramètre
|
390
610
|
|
391
|
-
|
392
|
-
|
611
|
+
@param group : nom du groupe
|
612
|
+
@param param_name : nom du paramètre
|
613
|
+
@param isIncrementable : True si le paramètre est incrémentable
|
614
|
+
@param genGroup : generic name of an incrementable group
|
615
|
+
@param genParam : generic name of an incrementable param
|
393
616
|
|
394
|
-
|
395
|
-
def ParseFile(self,myparamsline,todict):
|
617
|
+
"""
|
396
618
|
|
397
|
-
|
398
|
-
if param.endswith(':'):
|
399
|
-
#création d'un dict sur base du nom de groupe, sans le :
|
400
|
-
curgroup = param.replace(':','')
|
401
|
-
curgroup = curgroup.strip()
|
402
|
-
#Par défaut un groupe n'est pas incrémentable
|
403
|
-
isInc = False
|
404
|
-
#On verifie si le groupe est incrémentable
|
405
|
-
curgroup,iterInfo = self.Extract_IncrInfo(curgroup)
|
406
|
-
# Groupe avec indice incrémentable
|
407
|
-
if iterInfo is not None:
|
408
|
-
isInc = True
|
409
|
-
iterGroup = iterInfo[0]
|
410
|
-
iterParam = iterInfo[1]
|
411
|
-
iterMin = iterInfo[2]
|
412
|
-
iterMax = iterInfo[3]
|
413
|
-
if not curgroup in self.myIncGroup:
|
414
|
-
self.myIncGroup[curgroup] = {}
|
415
|
-
# self.myIncGroup[curgroup] = {}
|
416
|
-
self.myIncGroup[curgroup]["Ref group"] = iterGroup
|
417
|
-
self.myIncGroup[curgroup]["Ref param"] = iterParam
|
418
|
-
self.myIncGroup[curgroup]["Min"] = iterMin
|
419
|
-
self.myIncGroup[curgroup]["Max"] = iterMax
|
420
|
-
self.myIncGroup[curgroup]["Dict"] = {}
|
421
|
-
if not "Saved" in self.myIncGroup[curgroup]:
|
422
|
-
self.myIncGroup[curgroup]["Saved"] = {}
|
423
|
-
# Groupe classique
|
424
|
-
else:
|
425
|
-
todict[curgroup]={}
|
426
|
-
elif param.startswith('%'):
|
427
|
-
#c'est du commentaire --> rien à faire sauf si c'est du code json
|
428
|
-
if param.startswith('%json'):
|
429
|
-
#c'est du code json --> on le prend tel quel
|
430
|
-
parsed_json = json.loads(param.replace('%json',''))
|
431
|
-
curparam['added_json']=parsed_json
|
432
|
-
elif param.strip() == '':
|
433
|
-
if self.wx_exists:
|
434
|
-
wx.LogWarning(_("WARNING : A void line is present where it should not be. Removing the blank line"))
|
435
|
-
else:
|
436
|
-
logging.warning(_('A void line is present where it should not be. Removing the blank line'))
|
437
|
-
myparamsline.remove(param)
|
438
|
-
else:
|
439
|
-
#split sur base d'une tabulation
|
440
|
-
paramloc=param.split('\t')
|
441
|
-
#on enlève les espaces avant et après toutes les variables
|
442
|
-
for i in range(len(paramloc)) :
|
443
|
-
paramloc[i] = paramloc[i].strip()
|
444
|
-
paramloc[0], iterInfo = self.Extract_IncrInfo(paramloc[0])
|
445
|
-
#le parametre courant est pas incrémentable -> ajout au dictionnaire particulier des paramètres
|
446
|
-
if iterInfo is not None:
|
447
|
-
if not curgroup in self.myIncParam:
|
448
|
-
self.myIncParam[curgroup] = {}
|
449
|
-
if not paramloc[0] in self.myIncParam[curgroup]:
|
450
|
-
self.myIncParam[curgroup][paramloc[0]] = {}
|
451
|
-
# self.myIncParam[curgroup][paramloc[0]] = {}
|
452
|
-
self.myIncParam[curgroup][paramloc[0]]["Group"] = curgroup
|
453
|
-
if len(iterInfo)>1:
|
454
|
-
self.myIncParam[curgroup][paramloc[0]]["Ref param"] = iterInfo[0]
|
455
|
-
self.myIncParam[curgroup][paramloc[0]]["Min"] = iterInfo[1]
|
456
|
-
self.myIncParam[curgroup][paramloc[0]]["Max"] = iterInfo[2]
|
457
|
-
self.myIncParam[curgroup][paramloc[0]]["Dict"] = {}
|
458
|
-
|
459
|
-
if not "Saved" in self.myIncParam[curgroup][paramloc[0]]:
|
460
|
-
self.myIncParam[curgroup][paramloc[0]]["Saved"] = {}
|
461
|
-
# self.myIncGroup[curgroup]["Dict"][paramloc[0]]=self.myIncParam[paramloc[0]]
|
462
|
-
#pointage du param courant dans le dict de référence
|
463
|
-
curparam=self.myIncParam[curgroup][paramloc[0]]["Dict"]
|
464
|
-
else:
|
465
|
-
#on verifie si le groupe est incrémentable pour pointer vers le bon dictionnaire
|
466
|
-
if isInc:
|
467
|
-
#création d'un dict sur base du nom de paramètre
|
468
|
-
self.myIncGroup[curgroup]["Dict"][paramloc[0]]={}
|
469
|
-
#pointage du param courant dans le dict de référence
|
470
|
-
curparam=self.myIncGroup[curgroup]["Dict"][paramloc[0]]
|
471
|
-
else:
|
472
|
-
#création d'un dict sur base du nom de paramètre
|
473
|
-
todict[curgroup][paramloc[0]]={}
|
474
|
-
#pointage du param courant dans le dict
|
475
|
-
curparam=todict[curgroup][paramloc[0]]
|
619
|
+
assert self.wx_exists, "wxPython is not running"
|
476
620
|
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
if paramloc[2].find('integer')>-1 and paramloc[2].find('double')>-1:
|
484
|
-
curparam['type']='Integer_or_Float'
|
485
|
-
elif paramloc[2].find('integer')>-1:
|
486
|
-
curparam['type']='Integer'
|
487
|
-
elif paramloc[2].find('logical')>-1:
|
488
|
-
curparam['type']='Logical'
|
489
|
-
elif paramloc[2].find('double')>-1 or param.find('dble')>-1 or param.find('real')>-1:
|
490
|
-
curparam['type']='Float'
|
491
|
-
elif paramloc[2].find('(file)')>-1:
|
492
|
-
curparam['type']='File'
|
493
|
-
elif paramloc[2].find('(directory)')>-1 or param.find('(dir)')>-1:
|
494
|
-
curparam['type']='Directory'
|
495
|
-
else:
|
496
|
-
if not 'type' in curparam:
|
497
|
-
curparam['type'] = None
|
498
|
-
|
499
|
-
try:
|
500
|
-
param_def=self.myparams_default[curgroup][paramloc[0]]
|
501
|
-
curparam['type']=param_def['type']
|
502
|
-
except:
|
503
|
-
pass
|
504
|
-
except:
|
505
|
-
curparam['comment']=''
|
506
|
-
if not 'type' in curparam:
|
507
|
-
curparam['type'] = None
|
621
|
+
if isIncrementable:
|
622
|
+
if(genParam != ""):
|
623
|
+
if(genGroup != ""):
|
624
|
+
dict_param_def = self.myIncParam[genGroup][genParam]["Dict"][genParam]
|
625
|
+
else:
|
626
|
+
dict_param_def = self.myIncParam[group][genParam]["Dict"]
|
508
627
|
|
509
|
-
|
510
|
-
|
511
|
-
#gestion des paramètres actifs
|
512
|
-
try:
|
513
|
-
self.prop.Clear()
|
514
|
-
except:
|
515
|
-
pass
|
516
|
-
page = self.prop.AddPage("Active Parameters")
|
517
|
-
page = self.prop.AddPage("Default Parameters")
|
628
|
+
elif(genGroup != ""):
|
629
|
+
dict_param_def = self.myIncGroup[genGroup]["Dict"][param_name]
|
518
630
|
|
519
|
-
|
631
|
+
else:
|
632
|
+
dict_param_def = self.myparams_default[group][param_name]
|
520
633
|
|
521
|
-
if
|
522
|
-
for group in self.myparams.keys():
|
523
|
-
page.Append(pg.PropertyCategory(group))
|
634
|
+
if self.is_in_default(group, param_name):
|
524
635
|
|
525
|
-
|
636
|
+
# récupératrion de la valeur par défaut
|
637
|
+
val_default = self.prop.GetPropertyByName(PREFIX_DEFAULT + group + param_name).m_value
|
526
638
|
|
527
|
-
|
528
|
-
|
639
|
+
# 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):
|
641
|
+
val_active = self.prop.GetPropertyByName(group + param_name).m_value
|
642
|
+
else:
|
643
|
+
val_active = val_default
|
529
644
|
|
530
|
-
|
531
|
-
|
532
|
-
param_def=self.myparams_default[group][param_name]
|
533
|
-
if 'added_json' in param_def.keys():
|
534
|
-
list_keys = [ k for k in param_def['added_json']['Values'].keys()]
|
535
|
-
list_values = [ k for k in param_def['added_json']['Values'].values()]
|
536
|
-
page.Append(pg.EnumProperty(param_name,name=locname,labels=list_keys,values=list_values,value=int(float(param['value']))))
|
537
|
-
else:
|
538
|
-
if param_def['type']=='Integer_or_Float':
|
539
|
-
page.Append(pg.IntProperty(label=param_name,name=locname,value=float(param['value'])))
|
540
|
-
elif param_def['type']=='Integer':
|
541
|
-
page.Append(pg.IntProperty(label=param_name,name=locname,value=int(param['value'])))
|
542
|
-
elif param_def['type']=='Logical':
|
543
|
-
if param['value']=='.true.' or param['value']=='.True.':
|
544
|
-
mybool=True
|
545
|
-
elif param['value']=='.false.' or param['value']=='.False.':
|
546
|
-
mybool=False
|
547
|
-
elif param['value']==False or param['value']=='false':
|
548
|
-
mybool=False
|
549
|
-
elif param['value']==True or param['value']=='true':
|
550
|
-
mybool=True
|
551
|
-
page.Append(pg.BoolProperty(label=param_name,name=locname,value=mybool))
|
552
|
-
elif param_def['type']=='Float':
|
553
|
-
page.Append(pg.FloatProperty(label=param_name,name=locname,value=float(param['value'])))
|
554
|
-
elif param_def['type']=='File':
|
555
|
-
page.Append(pg.FileProperty(label=param_name,name=locname,value=param['value']))
|
556
|
-
elif param_def['type']=='Directory':
|
557
|
-
newobj=pg.DirProperty(locname,locname,value=param['value'])
|
558
|
-
newobj.SetLabel(param_name)
|
559
|
-
page.Append(newobj)
|
560
|
-
elif param_def['type']=='Color':
|
561
|
-
page.Append(pg.ColourProperty(label=param_name,name=locname,value=param['value']))
|
562
|
-
elif param_def['type']=='Fontname':
|
563
|
-
page.Append(pg.FontProperty(label=param_name,name=locname,value=param['value']))
|
564
|
-
else:
|
565
|
-
page.Append(pg.StringProperty(label=param_name,name=locname,value=param['value']))
|
566
|
-
except:
|
567
|
-
#si le groupe par défaut n'a pas de groupe équivalent, on lit les élément du groupe actif
|
568
|
-
if 'added_json' in param.keys():
|
569
|
-
list_keys = [ k for k in param['added_json']['Values'].keys()]
|
570
|
-
list_values = [ k for k in param['added_json']['Values'].values()]
|
571
|
-
page.Append(pg.EnumProperty(label=param_name,name=locname,labels=list_keys,values=list_values,value=int(param['value'])))
|
572
|
-
else:
|
573
|
-
if param['type']=='Integer_or_Float':
|
574
|
-
page.Append(pg.IntProperty(label=param_name,name=locname,value=float(param['value'])))
|
575
|
-
elif param['type']=='Integer':
|
576
|
-
page.Append(pg.IntProperty(label=param_name,name=locname,value=int(param['value'])))
|
577
|
-
elif param['type']=='Logical':
|
578
|
-
if param['value']=='.true.' or param['value']=='.True.':
|
579
|
-
mybool=True
|
580
|
-
elif param['value']=='.false.' or param['value']=='.False.':
|
581
|
-
mybool=False
|
582
|
-
elif param['value']==False or param['value']=='false':
|
583
|
-
mybool=False
|
584
|
-
elif param['value']==True or param['value']=='true':
|
585
|
-
mybool=True
|
586
|
-
page.Append(pg.BoolProperty(label=param_name,name=locname,value=mybool))
|
587
|
-
elif param['type']=='Float':
|
588
|
-
page.Append(pg.FloatProperty(label=param_name,name=locname,value=float(param['value'])))
|
589
|
-
elif param['type']=='File':
|
590
|
-
page.Append(pg.FileProperty(label=param_name,name=locname,value=param['value']))
|
591
|
-
elif param['type']=='Directory':
|
592
|
-
newobj=pg.DirProperty(locname,locname,value=param['value'])
|
593
|
-
newobj.SetLabel(param_name)
|
594
|
-
page.Append(newobj)
|
595
|
-
elif param['type']=='Color':
|
596
|
-
page.Append(pg.ColourProperty(label=param_name,name=locname,value=param['value']))
|
597
|
-
elif param['type']=='Fontname':
|
598
|
-
page.Append(pg.FontProperty(label=param_name,name=locname,value=param['value']))
|
599
|
-
else:
|
600
|
-
page.Append(pg.StringProperty(label=param_name,name=locname,value=param['value']))
|
601
|
-
|
602
|
-
try:
|
603
|
-
self.prop.SetPropertyHelpString(locname,param_def['added_json']['Full_Comment'])
|
604
|
-
except:
|
605
|
-
try:
|
606
|
-
self.prop.SetPropertyHelpString(locname,param_def['comment'])
|
607
|
-
except:
|
608
|
-
self.prop.SetPropertyHelpString(locname,param['comment'])
|
645
|
+
val_active = self.value_as_type(val_active, dict_param_def[key_Param.TYPE])
|
646
|
+
val_default = self.value_as_type(val_default, dict_param_def[key_Param.TYPE])
|
609
647
|
|
610
|
-
|
611
|
-
|
648
|
+
if val_active != val_default:
|
649
|
+
self[(group, param_name)] = val_active
|
650
|
+
else:
|
651
|
+
logging.debug(_('Parameter {} not modified'.format(param_name)))
|
612
652
|
|
613
|
-
|
614
|
-
|
615
|
-
|
653
|
+
else:
|
654
|
+
# 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
|
+
# Si la valeur n'est pas présente, on ne fait rien
|
656
|
+
if self.is_in_active(group, param_name):
|
657
|
+
val_active = self.prop.GetPropertyByName(group + param_name).m_value
|
658
|
+
val_active = self.value_as_type(val_active, dict_param_def[key_Param.TYPE])
|
616
659
|
|
617
|
-
|
660
|
+
self[(group, param_name)] = val_active
|
661
|
+
else:
|
662
|
+
logging.debug(_('Parameter {} not found in default parameters'.format(param_name)))
|
618
663
|
|
619
|
-
|
620
|
-
|
664
|
+
def position(self,position):
|
665
|
+
""" Position the frame """
|
666
|
+
self.SetPosition(wx.Point(position[0],position[1]+50))
|
621
667
|
|
622
|
-
|
623
|
-
|
624
|
-
|
668
|
+
def Populate(self):
|
669
|
+
"""
|
670
|
+
Filling the property management object based on dictionaries
|
625
671
|
|
626
|
-
|
627
|
-
list_keys = [ k for k in param['added_json']['Values'].keys()]
|
628
|
-
list_values = [ k for k in param['added_json']['Values'].values()]
|
629
|
-
page.Append(pg.EnumProperty(param_name,name=locname,labels=list_keys,values=list_values,value=int(float(param['value']))))
|
630
|
-
else:
|
631
|
-
if param['type']=='Integer_or_Float':
|
632
|
-
page.Append(pg.IntProperty(label=param_name,name=locname,value=float(param['value'])))
|
633
|
-
elif param['type']=='Integer':
|
634
|
-
page.Append(pg.IntProperty(label=param_name,name=locname,value=int(param['value'])))
|
635
|
-
elif param['type']=='Logical':
|
636
|
-
if param['value']=='.true.' or param['value']=='.True.':
|
637
|
-
mybool=True
|
638
|
-
elif param['value']=='.false.' or param['value']=='.False.':
|
639
|
-
mybool=False
|
640
|
-
elif param['value']==False or param['value']=='false':
|
641
|
-
mybool=False
|
642
|
-
elif param['value']==True or param['value']=='true':
|
643
|
-
mybool=True
|
644
|
-
page.Append(pg.BoolProperty(label=param_name,name=locname,value=mybool))
|
645
|
-
elif param['type']=='Float':
|
646
|
-
page.Append(pg.FloatProperty(label=param_name,name=locname,value=float(param['value'])))
|
647
|
-
elif param['type']=='File':
|
648
|
-
page.Append(pg.FileProperty(label=param_name,name=locname,value=param['value']))
|
649
|
-
elif param['type']=='Directory':
|
650
|
-
newobj=pg.DirProperty(locname,locname,value=param['value'])
|
651
|
-
newobj.SetLabel(param_name)
|
652
|
-
page.Append(newobj)
|
653
|
-
elif param['type']=='Color':
|
654
|
-
page.Append(pg.ColourProperty(label=param_name,name=locname,value=param['value']))
|
655
|
-
elif param_def['type']=='Fontname':
|
656
|
-
page.Append(pg.FontProperty(label=param_name,name=locname,value=param['value']))
|
657
|
-
else:
|
658
|
-
page.Append(pg.StringProperty(label=param_name,name=locname,value=param['value']))
|
672
|
+
Use default AND active parameters
|
659
673
|
|
660
|
-
|
661
|
-
|
662
|
-
except:
|
663
|
-
self.prop.SetPropertyHelpString(locname,param['comment'])
|
674
|
+
Useful only if wxPython is running
|
675
|
+
"""
|
664
676
|
|
665
|
-
|
666
|
-
|
667
|
-
|
677
|
+
if self.prop is None:
|
678
|
+
logging.error("ERROR : wxPython is not running - Impossible to populate the property grid")
|
679
|
+
return
|
668
680
|
|
669
|
-
def PopulateOnePage(self):
|
670
|
-
#gestion des paramètres actifs
|
671
681
|
self.prop.Clear()
|
672
|
-
page = self.prop.AddPage("Current")
|
673
|
-
|
674
|
-
if len(self.myparams)>0:
|
675
|
-
for group in self.myparams.keys():
|
676
|
-
page.Append(pg.PropertyCategory(group))
|
677
682
|
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
683
|
+
page_active:pg.PropertyGridPage
|
684
|
+
page_default:pg.PropertyGridPage
|
685
|
+
page_active = self.prop.AddPage(_("Active Parameters"))
|
686
|
+
page_default = self.prop.AddPage(_("Default Parameters"))
|
682
687
|
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
page.Append(pg.FloatProperty(label=param_name,name=locname,value=float(param['value'])))
|
700
|
-
elif param['type']=='File':
|
701
|
-
page.Append(pg.FileProperty(label=param_name,name=locname,value=param['value']))
|
702
|
-
elif param['type']=='Directory':
|
703
|
-
newobj=pg.DirProperty(locname,locname,value=param['value'])
|
704
|
-
newobj.SetLabel(param_name)
|
705
|
-
page.Append(newobj)
|
706
|
-
elif param['type']=='Color':
|
707
|
-
page.Append(pg.ColourProperty(label=param_name,name=locname,value=param['value']))
|
708
|
-
elif param['type']=='Fontname':
|
709
|
-
page.Append(pg.FontProperty(label=param_name,name=locname,value=param['value']))
|
710
|
-
else:
|
711
|
-
page.Append(pg.StringProperty(label=param_name,name=locname,value=param['value']))
|
688
|
+
#gestion des paramètres actifs
|
689
|
+
for group, params in self.myparams.items():
|
690
|
+
page_active.Append(pg.PropertyCategory(group))
|
691
|
+
for param_name, param in params.items():
|
692
|
+
param:dict
|
693
|
+
if self.is_in_default(group, param_name):
|
694
|
+
param_def = self.myparams_default[group][param_name]
|
695
|
+
|
696
|
+
if self.show_in_active_if_default:
|
697
|
+
self._add_elem_to_page(page_active, group, param, param_def = param_def)
|
698
|
+
elif param[key_Param.VALUE] != param_def[key_Param.VALUE]:
|
699
|
+
self._add_elem_to_page(page_active, group, param, param_def = param_def)
|
700
|
+
else:
|
701
|
+
logging.debug(_('Parameter {} not found in default parameters'.format(param_name)))
|
702
|
+
param_def = None
|
703
|
+
self._add_elem_to_page(page_active, group, param, param_def = param_def)
|
712
704
|
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
705
|
+
#gestion des paramètres par défaut
|
706
|
+
for group, params in self.myparams_default.items():
|
707
|
+
page_default.Append(pg.PropertyCategory(group))
|
708
|
+
for param_name, param in params.items():
|
709
|
+
param:dict
|
710
|
+
self._add_elem_to_page(page_default, group, param, prefix = PREFIX_DEFAULT)
|
717
711
|
|
718
712
|
# Display a header above the grid
|
719
713
|
self.prop.ShowHeader()
|
720
714
|
self.prop.Refresh()
|
721
715
|
|
722
|
-
|
723
|
-
|
724
|
-
# self.ApplytoMemory(0)
|
716
|
+
def _add_elem_to_page(self, page:pg.PropertyGridPage, group:str, param:dict, param_def:dict = None, prefix:str=''):
|
717
|
+
""" Add an element to a page """
|
725
718
|
|
726
|
-
|
719
|
+
param_name = param[key_Param.NAME]
|
720
|
+
locname = prefix + group + param_name
|
727
721
|
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
722
|
+
if param_def is not None:
|
723
|
+
# priority to default parameters
|
724
|
+
if key_Param.ADDED_JSON in param_def.keys():
|
725
|
+
param[key_Param.ADDED_JSON] = param_def[key_Param.ADDED_JSON]
|
726
|
+
param[key_Param.COMMENT] = param_def[key_Param.COMMENT]
|
727
|
+
param[key_Param.TYPE] = param_def[key_Param.TYPE]
|
732
728
|
|
733
|
-
|
729
|
+
if key_Param.ADDED_JSON in param.keys() and param[key_Param.ADDED_JSON] is not None:
|
730
|
+
# Ajout des choix via chaîne JSON
|
731
|
+
list_keys = [ k for k in param[key_Param.ADDED_JSON]['Values'].keys()]
|
732
|
+
list_values = [ k for k in param[key_Param.ADDED_JSON]['Values'].values()]
|
734
733
|
|
735
|
-
|
736
|
-
def Reload(self,event):
|
737
|
-
self.myparams.clear()
|
738
|
-
self.myparams_default.clear()
|
739
|
-
self.ReadFile(self.filename)
|
740
|
-
self.Populate()
|
734
|
+
page.Append(pg.EnumProperty(param_name, name=locname, labels=list_keys, values=list_values, value=int(param[key_Param.VALUE])))
|
741
735
|
|
742
|
-
|
743
|
-
|
736
|
+
self.prop.SetPropertyHelpString(locname , param[key_Param.ADDED_JSON]['Full_Comment'])
|
737
|
+
else:
|
744
738
|
|
745
|
-
|
746
|
-
self.myparams={}
|
739
|
+
locvalue = self[(group, param_name)]
|
747
740
|
|
748
|
-
|
749
|
-
|
750
|
-
for group in self.myparams_default.keys():
|
751
|
-
groupexists = False
|
752
|
-
for param_name in self.myparams_default[group].keys():
|
753
|
-
groupexists = self.Apply1ParamtoMemory(group, param_name, groupexists=groupexists)
|
741
|
+
if isinstance(locvalue, float):
|
742
|
+
page.Append(pg.FloatProperty(label = param_name, name = locname, value = locvalue))
|
754
743
|
|
744
|
+
elif isinstance(locvalue, int):
|
745
|
+
# bool is also an int
|
746
|
+
if isinstance(locvalue, bool):
|
747
|
+
page.Append(pg.BoolProperty(label=param_name, name = locname, value = locvalue))
|
748
|
+
else:
|
749
|
+
page.Append(pg.IntProperty(label = param_name, name = locname, value = locvalue))
|
755
750
|
|
756
|
-
|
757
|
-
|
758
|
-
self.Update_IncGroup(withGUI=True)
|
759
|
-
self.Update_IncParam(withGUI=True)
|
760
|
-
else:
|
761
|
-
wx.MessageDialog(self,'Nothing to do!')
|
751
|
+
elif param[key_Param.TYPE]==Type_Param.File:
|
752
|
+
page.Append(pg.FileProperty(label=param_name, name = locname, value = param[key_Param.VALUE]))
|
762
753
|
|
763
|
-
|
764
|
-
|
754
|
+
elif param[key_Param.TYPE]==Type_Param.Directory:
|
755
|
+
page.Append(pg.DirProperty(label = param_name, name = locname, value = locvalue))
|
756
|
+
# newobj.SetLabel(param_name)
|
757
|
+
# page.Append(newobj)
|
765
758
|
|
766
|
-
|
767
|
-
|
768
|
-
self._callbackdestroy()
|
759
|
+
elif param[key_Param.TYPE]==Type_Param.Color:
|
760
|
+
page.Append(pg.ColourProperty(label = param_name, name = locname, value = locvalue))
|
769
761
|
|
770
|
-
|
771
|
-
|
772
|
-
else:
|
773
|
-
self.Hide()
|
774
|
-
pass
|
762
|
+
elif param[key_Param.TYPE]==Type_Param.Fontname:
|
763
|
+
page.Append(pg.FontProperty(label = param_name, name = locname, value = locvalue))
|
775
764
|
|
776
|
-
|
765
|
+
else:
|
766
|
+
page.Append(pg.StringProperty(label = param_name, name = locname, value = locvalue))
|
777
767
|
|
778
|
-
|
768
|
+
self.prop.SetPropertyHelpString(locname, param[key_Param.COMMENT])
|
779
769
|
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
myfile.write(param_name +'\t' + str(self.myparams[group][param_name]['value'])+'\n')
|
770
|
+
def PopulateOnePage(self):
|
771
|
+
"""
|
772
|
+
Filling the property management object based on dictionaries
|
784
773
|
|
785
|
-
|
774
|
+
Use ONLY active parameters
|
786
775
|
|
776
|
+
Useful only if wxPython is running -- e.g. class "PyDraw"
|
777
|
+
"""
|
787
778
|
|
788
|
-
|
789
|
-
|
779
|
+
if self.prop is None:
|
780
|
+
logging.error("ERROR : wxPython is not running - Impossible to populate the property grid")
|
781
|
+
return
|
790
782
|
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
element = self.myparams_default[group][name]["value"]
|
796
|
-
except:
|
797
|
-
element = None
|
798
|
-
return element
|
783
|
+
#gestion des paramètres actifs
|
784
|
+
self.prop.Clear()
|
785
|
+
page:pg.PropertyGridPage
|
786
|
+
page = self.prop.AddPage("Current")
|
799
787
|
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
if curType is None:
|
806
|
-
curType = 'String'
|
807
|
-
except:
|
808
|
-
try:
|
809
|
-
curType = self.myparams_default[group][name]["type"]
|
810
|
-
except:
|
811
|
-
curType = 'String'
|
788
|
+
for group, params in self.myparams.items():
|
789
|
+
page.Append(pg.PropertyCategory(group))
|
790
|
+
for param_name, param in params.items():
|
791
|
+
param:dict
|
792
|
+
self._add_elem_to_page(page, group, param)
|
812
793
|
|
794
|
+
# Display a header above the grid
|
795
|
+
self.prop.ShowHeader()
|
796
|
+
self.prop.Refresh()
|
813
797
|
|
814
|
-
if curType == 'Integer':
|
815
|
-
element = int(element)
|
816
|
-
elif curType == 'Logical':
|
817
|
-
element = bool(element)
|
818
|
-
elif curType == 'Float':
|
819
|
-
element = float(element)
|
820
|
-
elif curType == 'Integer_or_Float':
|
821
|
-
element = float(element)
|
822
|
-
elif curType == 'Color':
|
823
|
-
if isinstance(element,str):
|
824
|
-
element = element.replace('(','')
|
825
|
-
element = element.replace(')','')
|
826
|
-
element = element.split(',')
|
827
798
|
|
828
|
-
|
799
|
+
# File management
|
800
|
+
# ---------------
|
829
801
|
|
802
|
+
def check_default_file(self, filename:str):
|
803
|
+
""" Check if a default file exists """
|
830
804
|
|
831
|
-
|
832
|
-
|
805
|
+
if os.path.isfile(filename + '.default'):
|
806
|
+
return True
|
807
|
+
else:
|
808
|
+
return False
|
833
809
|
|
834
|
-
|
835
|
-
|
836
|
-
except:
|
837
|
-
element = None
|
810
|
+
def ReadFile(self,*args):
|
811
|
+
""" Lecture d'un fichier .param et remplissage des dictionnaires myparams et myparams_default """
|
838
812
|
|
839
|
-
|
813
|
+
if len(args)>0:
|
814
|
+
#s'il y a un argument on le prend tel quel
|
815
|
+
self.filename = str(args[0])
|
816
|
+
else:
|
817
|
+
if self.wx_exists:
|
818
|
+
#ouverture d'une boîte de dialogue
|
819
|
+
file=wx.FileDialog(self,"Choose .param file", wildcard="param (*.param)|*.param|all (*.*)|*.*")
|
820
|
+
if file.ShowModal() == wx.ID_CANCEL:
|
821
|
+
return
|
822
|
+
else:
|
823
|
+
#récuparétaion du nom de fichier avec chemin d'accès
|
824
|
+
self.filename =file.GetPath()
|
825
|
+
else:
|
826
|
+
logging.warning("ERROR : no filename given and wxPython is not running")
|
827
|
+
return
|
840
828
|
|
829
|
+
if not os.path.isfile(self.filename):
|
830
|
+
logging.warning("ERROR : cannot find the following file : {}".format(self.filename))
|
831
|
+
return
|
841
832
|
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
833
|
+
myparamsline_default = None
|
834
|
+
if self.check_default_file(self.filename):
|
835
|
+
with open(self.filename+'.default', 'r') as myfile:
|
836
|
+
myparamsline_default = myfile.read()
|
837
|
+
|
838
|
+
# lecture du contenu
|
839
|
+
with open(self.filename, 'r') as myfile:
|
840
|
+
myparamsline = myfile.read()
|
841
|
+
|
842
|
+
self.fill_from_strings(myparamsline, myparamsline_default)
|
843
|
+
|
844
|
+
if not self.check_default_file(self.filename):
|
845
|
+
self._CreateDefaultFile()
|
846
|
+
|
847
|
+
def fill_from_strings(self, chain:str, chaindefault:str = None):
|
848
|
+
""" Fill the dictionaries from a string """
|
849
|
+
|
850
|
+
myparamsline = chain.splitlines()
|
851
|
+
self.ParseFile(myparamsline,self.myparams)
|
852
|
+
|
853
|
+
if chaindefault is not None:
|
854
|
+
myparamsline = chaindefault.splitlines()
|
855
|
+
|
856
|
+
self.ParseFile(myparamsline,self.myparams_default)
|
857
|
+
|
858
|
+
# mise à jour des groupes incrémentables et des paramètres incrémentables
|
859
|
+
self._update_IncGroup()
|
860
|
+
self._update_IncParam()
|
861
|
+
|
862
|
+
def ParseFile(self, myparamsline:list[str], todict:dict):
|
863
|
+
"""
|
864
|
+
Parsing the file to find groups and parameters and filling a dictionary
|
865
|
+
|
866
|
+
Each parameter is stored in a dictionary associated to the upper group.
|
867
|
+
|
868
|
+
'add_group' is used to add a group in the dictionary 'todict'.
|
869
|
+
'groupname' will be there sanitized (strip, decoded if iteratable...) to be used in '_add_param_from_str'.
|
870
|
+
|
871
|
+
myparamsline format:
|
872
|
+
['groupname1:', 'param1', 'param2', 'groupname2:', 'param1', ...]
|
873
|
+
|
874
|
+
"""
|
875
|
+
|
876
|
+
if isinstance(myparamsline, str):
|
877
|
+
logging.warning("ERROR : myparamsline must be a list of strings -- forcing conversion")
|
878
|
+
myparamsline = myparamsline.splitlines()
|
879
|
+
|
880
|
+
for param in myparamsline:
|
881
|
+
if param.endswith(':'):
|
882
|
+
# GROUPE
|
883
|
+
# ------
|
884
|
+
|
885
|
+
#création d'un dict sur base du nom de groupe, sans le :
|
886
|
+
groupname = param.replace(':','')
|
887
|
+
groupname, groupdict = self.add_group(groupname, todict)
|
888
|
+
|
889
|
+
elif param.startswith('%'):
|
890
|
+
# COMMENTAIRE
|
891
|
+
# -----------
|
892
|
+
#c'est du commentaire --> rien à faire sauf si c'est du code json
|
893
|
+
if param.startswith('%json'):
|
894
|
+
#c'est du code json --> on le prend tel quel
|
895
|
+
parsed_json = json.loads(param.replace('%json',''))
|
896
|
+
curparam[key_Param.ADDED_JSON]=parsed_json
|
897
|
+
|
898
|
+
elif param.strip() == '':
|
899
|
+
# VOID LINE
|
900
|
+
# ---------
|
901
|
+
logging.warning(_('A void line is present where it should not be. Removing the blank line'))
|
902
|
+
myparamsline.remove(param)
|
903
|
+
|
904
|
+
else:
|
905
|
+
# PARAMETRE
|
906
|
+
# ---------
|
907
|
+
curparam = self._add_param_from_str(param, groupname, groupdict)
|
908
|
+
|
909
|
+
def _CreateDefaultFile(self):
|
910
|
+
""" Create a default file """
|
911
|
+
|
912
|
+
with open(self.filename+'.default', 'w') as myfile:
|
913
|
+
|
914
|
+
for group in self.myparams.keys():
|
915
|
+
myfile.write(' ' + group +':\n')
|
916
|
+
for param_name in self.myparams[group].keys():
|
917
|
+
myfile.write(param_name +'\t' + str(self.myparams[group][param_name][key_Param.VALUE])+'\n')
|
918
|
+
|
919
|
+
myfile.close()
|
920
|
+
|
921
|
+
def _Extract_IncrInfo(self, nameStr:str) -> tuple[str, list[str, str, int, int]]:
|
922
|
+
"""
|
923
|
+
Extract the information of an incrementable group or param
|
924
|
+
|
925
|
+
The name of an incrementable group or param is of the form: $n(group, param, min, max)$
|
926
|
+
"""
|
927
|
+
iterInfo = []
|
928
|
+
newName = ""
|
929
|
+
|
930
|
+
positions = [i for i, char in enumerate(nameStr) if char == "$"]
|
931
|
+
|
932
|
+
assert np.mod(len(positions),2) == 0, "ERROR : the number of '$' must be even"
|
933
|
+
|
934
|
+
if len(positions)>0:
|
935
|
+
# indice incrémentable détecté
|
936
|
+
|
937
|
+
# search for the first '$'
|
938
|
+
posSep1 = positions[0] #nameStr.find("$")
|
939
|
+
# search for the last '$'
|
940
|
+
posSep2 = positions[-1] #nameStr[posSep1+1:].find("$")
|
941
|
+
|
942
|
+
# select the string between the two '$'
|
943
|
+
iterCode = nameStr[posSep1:posSep1+posSep2+1]
|
944
|
+
|
945
|
+
positions_left = [i for i, char in enumerate(iterCode) if char == "("]
|
946
|
+
positions_right = [i for i, char in enumerate(iterCode) if char == ")"]
|
947
|
+
|
948
|
+
if len(positions_left)==0 and len(positions_right)==0:
|
949
|
+
# no '(' and no ')' --> no incrementable information
|
950
|
+
return nameStr, None
|
951
|
+
|
952
|
+
assert len(positions_left)>0, "ERROR : no '(' found in the name of an incrementable group or param"
|
953
|
+
assert len(positions_right)>0, "ERROR : no ')' found in the name of an incrementable group or param"
|
954
|
+
|
955
|
+
# search for the first '('
|
956
|
+
posSep1 = positions_left[0] #iterCode.find("(")
|
957
|
+
# search for the second ')'
|
958
|
+
posSep2 = positions_right[-1] #iterCode[posSep1:].find(")")
|
959
|
+
|
960
|
+
# select the string between the two '('
|
961
|
+
iterCode = iterCode[posSep1:posSep2+1]
|
962
|
+
|
963
|
+
# remove the incrementable code from the name --> conserve $n$
|
964
|
+
newName = nameStr.replace(iterCode,'')
|
965
|
+
# remove the spaces before and after the name
|
966
|
+
newName = newName.strip()
|
967
|
+
|
968
|
+
# decode the incrementable information
|
969
|
+
iterInfo = iterCode[1:-1].split(',')
|
970
|
+
# remove the spaces before and after the information
|
971
|
+
iterInfo = [x.strip() for x in iterInfo]
|
972
|
+
|
973
|
+
if len(iterInfo)==3:
|
974
|
+
# no group name provided --> use the current group
|
975
|
+
iterInfo = [iterInfo[0], int(iterInfo[1]), int(iterInfo[2])]
|
976
|
+
elif len(iterInfo)==4:
|
977
|
+
# group name provided --> use the provided group
|
978
|
+
iterInfo = [iterInfo[0], iterInfo[1], int(iterInfo[2]), int(iterInfo[3])]
|
979
|
+
else:
|
980
|
+
logging.error(_("The incrementable information must be of the form: $n(group, param, min, max)$ or $n(param, min, max)$"))
|
981
|
+
else:
|
982
|
+
newName = nameStr
|
983
|
+
iterInfo = None
|
984
|
+
|
985
|
+
return newName, iterInfo
|
986
|
+
|
987
|
+
|
988
|
+
# Clear/Rest
|
989
|
+
# ----------
|
990
|
+
|
991
|
+
def Clear(self):
|
992
|
+
""" Clear all the parameters """
|
993
|
+
|
994
|
+
self.myparams.clear()
|
995
|
+
self.myparams_default.clear()
|
996
|
+
self.myIncGroup.clear()
|
997
|
+
self.myIncParam.clear()
|
998
|
+
if self.prop is not None:
|
999
|
+
self.prop.Clear()
|
1000
|
+
|
1001
|
+
# Object access
|
1002
|
+
# -------------
|
1003
|
+
|
1004
|
+
def add_group(self, groupname:str, todict:dict = None) -> tuple[str,dict]:
|
1005
|
+
"""
|
1006
|
+
Add a group in the dictionary 'todict' if provided or in the IncGroup dictionary
|
1007
|
+
|
1008
|
+
return sanitized groupname and dictionnary attached to the group
|
1009
|
+
"""
|
1010
|
+
|
1011
|
+
groupname = groupname.strip()
|
1012
|
+
|
1013
|
+
#On verifie si le groupe est incrémentable
|
1014
|
+
groupname, iterInfo = self._Extract_IncrInfo(groupname)
|
1015
|
+
|
1016
|
+
if iterInfo is None:
|
1017
|
+
if todict is None:
|
1018
|
+
logging.error(_("You must provide a dictionary to store the group -- Retry"))
|
1019
|
+
return None
|
1020
|
+
|
1021
|
+
# Groupe classique
|
1022
|
+
todict[groupname]={}
|
1023
|
+
return groupname, todict[groupname]
|
1024
|
+
else:
|
1025
|
+
# Le groupe est incrémentable
|
1026
|
+
iterGroup = iterInfo[0] # nom du groupe contenant le paramètre de nombre de groupes
|
1027
|
+
iterParam = iterInfo[1] # nom du paramètre contenant le nombre de groupes
|
1028
|
+
iterMin = iterInfo[2] # valeur minimale
|
1029
|
+
iterMax = iterInfo[3] # valeur maximale
|
1030
|
+
|
1031
|
+
return groupname, self.add_IncGroup(groupname, iterMin, iterMax, iterGroup, iterParam)
|
1032
|
+
|
1033
|
+
def _add_param_in_dict(self,
|
1034
|
+
group:dict,
|
1035
|
+
name:str,
|
1036
|
+
value:Union[float, int, str] = '', # la valeur est de toute façon stockée en 'str'
|
1037
|
+
type:Type_Param=None,
|
1038
|
+
comment:str = '',
|
1039
|
+
jsonstr:str = None) -> dict:
|
1040
|
+
|
1041
|
+
if not name in group.keys():
|
1042
|
+
group[name]={}
|
1043
|
+
|
1044
|
+
curpar=group[name]
|
1045
|
+
|
1046
|
+
curpar[key_Param.NAME]=name
|
1047
|
+
curpar[key_Param.TYPE]=type
|
1048
|
+
curpar[key_Param.VALUE]=value
|
1049
|
+
curpar[key_Param.COMMENT]=comment
|
1050
|
+
|
1051
|
+
if jsonstr is not None:
|
1052
|
+
if isinstance(jsonstr, str):
|
1053
|
+
parsed_json = json.loads(jsonstr.replace('%json',''))
|
1054
|
+
elif isinstance(jsonstr, dict):
|
1055
|
+
parsed_json = jsonstr
|
1056
|
+
|
1057
|
+
curpar[key_Param.ADDED_JSON]=parsed_json
|
1058
|
+
else:
|
1059
|
+
curpar[key_Param.ADDED_JSON]=None
|
1060
|
+
return curpar
|
1061
|
+
|
1062
|
+
def _new_IncParam_dict(self, groupname, refgroupname, refparamname, min_value, max_value) -> dict:
|
1063
|
+
""" Create a new dictionary for an incrementable parameter """
|
1064
|
+
|
1065
|
+
newdict = {}
|
1066
|
+
newdict["Group"] = groupname
|
1067
|
+
newdict["Ref group"] = refgroupname
|
1068
|
+
newdict["Ref param"] = refparamname
|
1069
|
+
newdict["Min"] = min_value
|
1070
|
+
newdict["Max"] = max_value
|
1071
|
+
newdict["Dict"] = {}
|
1072
|
+
|
1073
|
+
return newdict
|
1074
|
+
|
1075
|
+
def _add_param_from_str(self, param:str, groupname:str, groupdict:dict, seperator:str = '\t'):
|
1076
|
+
""" Add a parameter from a complex string """
|
1077
|
+
|
1078
|
+
#split sur base du sépérateur
|
1079
|
+
paramloc=param.split(seperator)
|
1080
|
+
|
1081
|
+
#on enlève les espaces avant et après toutes les variables
|
1082
|
+
paramloc = [x.strip() for x in paramloc]
|
1083
|
+
|
1084
|
+
paramloc[0], iterInfo = self._Extract_IncrInfo(paramloc[0])
|
1085
|
+
|
1086
|
+
if iterInfo is not None:
|
1087
|
+
#le parametre courant est incrémentable -> ajout au dictionnaire particulier des paramètres
|
1088
|
+
if not groupname in self.myIncParam:
|
1089
|
+
self.myIncParam[groupname] = {}
|
1090
|
+
|
1091
|
+
if not paramloc[0] in self.myIncParam[groupname]:
|
1092
|
+
curdict = self.myIncParam[groupname][paramloc[0]] = self._new_IncParam_dict(groupname, groupname if len(iterInfo)==3 else iterInfo[0], iterInfo[-3], iterInfo[-2], iterInfo[-1])
|
1093
|
+
|
1094
|
+
if not "Saved" in curdict:
|
1095
|
+
curdict["Saved"] = {}
|
1096
|
+
|
1097
|
+
#pointage du param courant dans le dict de référence
|
1098
|
+
curparam=curdict["Dict"]
|
1099
|
+
else:
|
1100
|
+
#création d'un dict sur base du nom de paramètre
|
1101
|
+
curparam=groupdict[paramloc[0]]={}
|
1102
|
+
|
1103
|
+
curparam[key_Param.NAME]=paramloc[0]
|
1104
|
+
|
1105
|
+
if len(paramloc)>1:
|
1106
|
+
#ajout de la valeur
|
1107
|
+
curparam[key_Param.VALUE]=paramloc[1]
|
848
1108
|
|
849
|
-
#teste si param existe
|
850
|
-
try:
|
851
|
-
param = self.myparams[group][name]
|
852
|
-
except:
|
853
|
-
param=None
|
854
1109
|
try:
|
855
|
-
|
1110
|
+
# tentative d'ajout du commentaire --> pas obligatoirement présent
|
1111
|
+
curparam[key_Param.COMMENT]=paramloc[2]
|
1112
|
+
|
1113
|
+
# recherche du type dans le commentaire
|
1114
|
+
curparam[key_Param.TYPE]=search_type(paramloc[2])
|
1115
|
+
if curparam[key_Param.TYPE] == Type_Param.String:
|
1116
|
+
# recherche du type dans la châine complète
|
1117
|
+
type_in_fulchain = search_type(param)
|
1118
|
+
|
1119
|
+
if type_in_fulchain != Type_Param.String:
|
1120
|
+
curparam[key_Param.TYPE] = type_in_fulchain
|
1121
|
+
try:
|
1122
|
+
# tentaive de recherche du type dans les valeurs par défaut
|
1123
|
+
param_def=self.myparams_default[groupname][paramloc[0]]
|
1124
|
+
curparam[key_Param.TYPE]=param_def[key_Param.TYPE]
|
1125
|
+
except:
|
1126
|
+
pass
|
856
1127
|
except:
|
857
|
-
|
858
|
-
|
1128
|
+
curparam[key_Param.COMMENT]=''
|
1129
|
+
try:
|
1130
|
+
# tentative de recherche du type dans les valeurs par défaut
|
1131
|
+
param_def=self.myparams_default[groupname][paramloc[0]]
|
1132
|
+
curparam[key_Param.TYPE]=param_def[key_Param.TYPE]
|
1133
|
+
except:
|
1134
|
+
if not key_Param.TYPE in curparam:
|
1135
|
+
curparam[key_Param.TYPE] = None
|
1136
|
+
else:
|
1137
|
+
curparam[key_Param.VALUE]=''
|
1138
|
+
curparam[key_Param.COMMENT]=''
|
1139
|
+
curparam[key_Param.TYPE]=None
|
1140
|
+
|
1141
|
+
return curparam
|
1142
|
+
|
1143
|
+
def addparam(self,
|
1144
|
+
groupname:str = '',
|
1145
|
+
name:str = '',
|
1146
|
+
value:Union[float, int, str] = '', # la valeur est de toute façon stockée en 'str'
|
1147
|
+
type:Type_Param=None,
|
1148
|
+
comment:str = '',
|
1149
|
+
jsonstr:str = None,
|
1150
|
+
whichdict:Literal['All', 'Default', 'Active', 'IncGroup', '']=''):
|
1151
|
+
"""
|
1152
|
+
Add or update a parameter
|
1153
|
+
|
1154
|
+
@param groupname : groupe in which the new param will be strored - If it does not exist, it will be created
|
1155
|
+
@param name : param's name - If it does not exist, it will be created
|
1156
|
+
@param value : param'a value
|
1157
|
+
@param type : type -> will influence the GUI
|
1158
|
+
@param comment : param's comment -- helpful to understand the parameter
|
1159
|
+
@param jsonstr : string containing JSON data -- used in GUI
|
1160
|
+
param whichdict : where to store the param -- Default, Active or All, or IncGroup if the param is part of an incrementable group
|
1161
|
+
|
1162
|
+
jsonstr can be a dict i.e. '{"Values":{choice1:1, choice2:2, choice3:3}, "Full_Comment":'Yeah baby !'}'
|
1163
|
+
|
1164
|
+
Return 0 if OK, -1 if the group is incrementable and not created, -2 if the group does not exist
|
1165
|
+
"""
|
1166
|
+
|
1167
|
+
if isinstance(type, str):
|
1168
|
+
if type == 'Integer':
|
1169
|
+
type = Type_Param.Integer
|
1170
|
+
elif type == 'Float':
|
1171
|
+
type = Type_Param.Float
|
1172
|
+
elif type == 'Integer_or_Float':
|
1173
|
+
type = Type_Param.Integer_or_Float
|
1174
|
+
elif type == 'Logical':
|
1175
|
+
type = Type_Param.Logical
|
1176
|
+
elif type == 'File':
|
1177
|
+
type = Type_Param.File
|
1178
|
+
elif type == 'Directory':
|
1179
|
+
type = Type_Param.Directory
|
1180
|
+
elif type == 'Color':
|
1181
|
+
type = Type_Param.Color
|
1182
|
+
elif type == 'Fontname':
|
1183
|
+
type = Type_Param.Fontname
|
1184
|
+
elif type == 'String':
|
1185
|
+
type = Type_Param.String
|
1186
|
+
else:
|
1187
|
+
type = None
|
1188
|
+
|
1189
|
+
name_wo, iterInfo = self._Extract_IncrInfo(name)
|
1190
|
+
if iterInfo is not None:
|
1191
|
+
return self.add_IncParam(groupname, name, value, comment, type, added_json=jsonstr)
|
1192
|
+
|
1193
|
+
if '$n$' in groupname:
|
1194
|
+
if whichdict != 'IncGroup':
|
1195
|
+
logging.warning(_("WARNING : group is incrementable. -- You must use 'IncGroup' for whichdict"))
|
1196
|
+
whichdict = 'IncGroup'
|
1197
|
+
elif '$n(' in groupname:
|
1198
|
+
if whichdict != 'IncGroup':
|
1199
|
+
logging.warning(_("WARNING : group is incrementable. -- You must use 'IncGroup' for whichdict"))
|
1200
|
+
whichdict = 'IncGroup'
|
1201
|
+
|
1202
|
+
groupname, iterInfo = self._Extract_IncrInfo(groupname)
|
1203
|
+
|
1204
|
+
if iterInfo is None:
|
1205
|
+
logging.error(_("ERROR : infos not found in {} -- Retry".format(groupname)))
|
1206
|
+
return -1
|
1207
|
+
|
1208
|
+
# Le groupe est incrémentable
|
1209
|
+
iterGroup = iterInfo[0] # nom du groupe contenant le paramètre de nombre de groupes
|
1210
|
+
iterParam = iterInfo[1] # nom du paramètre contenant le nombre de groupes
|
1211
|
+
iterMin = iterInfo[2] # valeur minimale
|
1212
|
+
iterMax = iterInfo[3] # valeur maximale
|
1213
|
+
|
1214
|
+
if groupname not in self.myIncGroup.keys():
|
1215
|
+
self.add_IncGroup(groupname, iterMin, iterMax, iterGroup, iterParam)
|
1216
|
+
|
1217
|
+
if whichdict=='IncGroup':
|
1218
|
+
if not groupname in self.myIncGroup.keys():
|
1219
|
+
logging.error(_("ERROR : group {} does not exist. -- You must first create it".format(groupname)))
|
1220
|
+
logging.error(_(" or pass infos in the group name : $n(group, param, min, max)$"))
|
1221
|
+
return -2
|
1222
|
+
|
1223
|
+
self._add_param_in_dict(self.myIncGroup[groupname]["Dict"], name, value, type, comment, jsonstr)
|
1224
|
+
return 0
|
1225
|
+
|
1226
|
+
else:
|
1227
|
+
if whichdict=='All':
|
1228
|
+
locparams=[self.myparams, self.myparams_default]
|
1229
|
+
elif whichdict=='Default':
|
1230
|
+
locparams=[self.myparams_default]
|
1231
|
+
elif whichdict=='Active' or whichdict=='':
|
1232
|
+
locparams=[self.myparams]
|
1233
|
+
|
1234
|
+
for curdict in locparams:
|
1235
|
+
if not groupname in curdict.keys():
|
1236
|
+
curdict[groupname]={}
|
1237
|
+
|
1238
|
+
self._add_param_in_dict(curdict[groupname], name, value, type, comment, jsonstr)
|
1239
|
+
|
1240
|
+
return 0
|
1241
|
+
|
1242
|
+
def add_param(self,
|
1243
|
+
groupname:str = '',
|
1244
|
+
name:str = '',
|
1245
|
+
value:Union[float, int, str] = '', # la valeur est de toute façon stockée en 'str'
|
1246
|
+
type:Type_Param=None,
|
1247
|
+
comment:str = '',
|
1248
|
+
jsonstr:str = None,
|
1249
|
+
whichdict:Literal['All', 'Default', 'Active', 'IncGroup', '']=''):
|
1250
|
+
"""alias of addparam"""
|
1251
|
+
return self.addparam(groupname, name, value, type, comment, jsonstr, whichdict)
|
1252
|
+
|
1253
|
+
def __getitem__(self, key:tuple[str, str]):
|
1254
|
+
"""
|
1255
|
+
Retrieve :
|
1256
|
+
- value's parameter from group if key is a tuple or a list (group, param_name)
|
1257
|
+
- group dict if key is a string
|
1258
|
+
"""
|
1259
|
+
if isinstance(key, tuple) or isinstance(key, list):
|
1260
|
+
group, name = key
|
1261
|
+
return self.get_param(group, name)
|
1262
|
+
elif isinstance(key, str):
|
1263
|
+
return self.get_group(key)
|
1264
|
+
|
1265
|
+
def __setitem__(self, key:str, value:Union[float, int, str, bool]):
|
1266
|
+
"""set item, key is a tuple or a list (group, param_name)"""
|
1267
|
+
|
1268
|
+
if isinstance(key, tuple) or isinstance(key, list):
|
1269
|
+
group, name = key
|
1270
|
+
if self.get_param(group, name) is not None:
|
1271
|
+
self.change_param(group, name, value)
|
1272
|
+
else:
|
1273
|
+
self.addparam(group, name, value, self._detect_type_from_value(value))
|
1274
|
+
|
1275
|
+
def is_in_active(self, group:str, name:str = None) -> bool:
|
1276
|
+
""" Return True if the parameter is in the active parameters """
|
1277
|
+
return self.is_in(group, name, whichdict='Active')
|
1278
|
+
|
1279
|
+
def is_in_default(self, group:str, name:str = None) -> bool:
|
1280
|
+
""" Return True if the parameter is in the default parameters """
|
1281
|
+
return self.is_in(group, name, whichdict='Default')
|
1282
|
+
|
1283
|
+
def is_in(self, group:str, name:str = None, whichdict:Literal['All', 'Default', 'Active', 'IncGroup', '']='Active') -> bool:
|
1284
|
+
""" Return True if the parameter is in the whichdict parameters """
|
1285
|
+
|
1286
|
+
if whichdict=='All':
|
1287
|
+
locparams=[self.myparams, self.myparams_default]
|
1288
|
+
elif whichdict=='Default':
|
1289
|
+
locparams=[self.myparams_default]
|
1290
|
+
elif whichdict=='Active' or whichdict=='':
|
1291
|
+
locparams=[self.myparams]
|
1292
|
+
|
1293
|
+
for curdict in locparams:
|
1294
|
+
if group in curdict.keys():
|
1295
|
+
if name is not None:
|
1296
|
+
if name in curdict[group].keys():
|
1297
|
+
ret = True
|
1298
|
+
else:
|
1299
|
+
return False
|
859
1300
|
else:
|
860
|
-
|
861
|
-
|
862
|
-
|
1301
|
+
ret = True
|
1302
|
+
else:
|
1303
|
+
return False
|
863
1304
|
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
1305
|
+
return ret
|
1306
|
+
|
1307
|
+
def get_param_dict(self, group:str, name:str) -> dict[str, Union[str, int, float, bool, tuple[int, int, int]]]:
|
1308
|
+
"""
|
1309
|
+
Returns the parameter dict if found, otherwise None obj
|
1310
|
+
"""
|
1311
|
+
|
1312
|
+
if self.is_in_active(group, name):
|
1313
|
+
return self.myparams[group][name]
|
1314
|
+
elif self.is_in_default(group, name):
|
1315
|
+
return self.myparams_default[group][name]
|
1316
|
+
else:
|
1317
|
+
return None
|
1318
|
+
|
1319
|
+
def get_type(self, group:str, name:str) -> Type_Param:
|
1320
|
+
"""
|
1321
|
+
Returns the type of the parameter if found, otherwise None obj
|
1322
|
+
"""
|
1323
|
+
|
1324
|
+
curtype = None
|
1325
|
+
|
1326
|
+
if self.is_in_default(group, name):
|
1327
|
+
if key_Param.TYPE in self.myparams_default[group][name].keys():
|
1328
|
+
curtype = self.myparams_default[group][name][key_Param.TYPE]
|
1329
|
+
|
1330
|
+
if self.is_in_active(group, name) and curtype is None:
|
1331
|
+
if key_Param.TYPE in self.myparams[group][name].keys():
|
1332
|
+
curtype = self.myparams[group][name][key_Param.TYPE]
|
1333
|
+
|
1334
|
+
return curtype if curtype is not None else Type_Param.String
|
1335
|
+
|
1336
|
+
def value_as_type(self, value, type,
|
1337
|
+
bool_as_int:bool = False,
|
1338
|
+
color_as:Union[int,str,float]= int) :
|
1339
|
+
|
1340
|
+
""" Convert the value to the right type """
|
1341
|
+
if type == Type_Param.Integer:
|
1342
|
+
value = int(value)
|
1343
|
+
elif type == Type_Param.Float:
|
1344
|
+
value = float(value)
|
1345
|
+
elif type == Type_Param.Logical:
|
1346
|
+
if isinstance(value,str):
|
1347
|
+
if value.lower() in ['.false.', 'false', 'faux']:
|
1348
|
+
value = False
|
1349
|
+
elif value.lower() in ['.true.', 'true', 'vrai']:
|
1350
|
+
value = True
|
1351
|
+
else:
|
1352
|
+
value = bool(value)
|
1353
|
+
|
1354
|
+
if bool_as_int:
|
1355
|
+
value = int(value)
|
1356
|
+
|
1357
|
+
elif type == Type_Param.Color:
|
1358
|
+
if color_as == str:
|
1359
|
+
value = str(value)
|
1360
|
+
else:
|
1361
|
+
if isinstance(value,str):
|
1362
|
+
value = value.replace('(','')
|
1363
|
+
value = value.replace(')','')
|
1364
|
+
value = value.split(',')
|
1365
|
+
elif isinstance(value, wx.Colour):
|
1366
|
+
value = [value.Red(), value.Green(), value.Blue(), value.Alpha()]
|
1367
|
+
|
1368
|
+
if color_as == int:
|
1369
|
+
value = tuple([int(x) for x in value])
|
1370
|
+
|
1371
|
+
elif color_as == float:
|
1372
|
+
value = tuple([float(x)/255. for x in value])
|
1373
|
+
|
1374
|
+
elif type == Type_Param.Integer_or_Float:
|
1375
|
+
value = float(value)
|
1376
|
+
elif type == Type_Param.String:
|
1377
|
+
value = str(value)
|
1378
|
+
elif type == Type_Param.File:
|
1379
|
+
value = str(value)
|
1380
|
+
elif type == Type_Param.Directory:
|
1381
|
+
value = str(value)
|
1382
|
+
elif type == Type_Param.Fontname:
|
1383
|
+
value = str(value)
|
1384
|
+
else:
|
1385
|
+
value = str(value)
|
1386
|
+
|
1387
|
+
return value
|
1388
|
+
|
1389
|
+
def get_param(self, group:str, name:str, default_value=None):
|
1390
|
+
"""
|
1391
|
+
Returns the value of the parameter if found, otherwise None obj
|
1392
|
+
|
1393
|
+
used in __getitem__
|
1394
|
+
"""
|
1395
|
+
|
1396
|
+
if self.is_in_active(group, name):
|
1397
|
+
element = self.myparams[group][name][key_Param.VALUE]
|
1398
|
+
elif self.is_in_default(group, name):
|
1399
|
+
element = self.myparams_default[group][name][key_Param.VALUE]
|
1400
|
+
else:
|
1401
|
+
element = default_value
|
1402
|
+
return element
|
1403
|
+
|
1404
|
+
# String conversion according to its type
|
1405
|
+
curType = self.get_type(group, name)
|
1406
|
+
return self.value_as_type(element, curType)
|
1407
|
+
|
1408
|
+
def get_group(self, group:str) -> dict:
|
1409
|
+
"""
|
1410
|
+
Return the group dictionnary if found, otherwise None obj
|
1411
|
+
Check the active parameters first, then the default parameters
|
1412
|
+
|
1413
|
+
Used in __getitem__
|
1414
|
+
"""
|
1415
|
+
|
1416
|
+
if self.is_in_active(group):
|
1417
|
+
return self.myparams[group]
|
1418
|
+
elif self.is_in_default(group):
|
1419
|
+
return self.myparams_default[group]
|
1420
|
+
else:
|
1421
|
+
return None
|
1422
|
+
|
1423
|
+
def _detect_type_from_value(self, value:Union[float, int, str, bool, tuple[int, int, int]]) -> Type_Param:
|
1424
|
+
""" Detect the type from the value """
|
1425
|
+
|
1426
|
+
if isinstance(value, float):
|
1427
|
+
return Type_Param.Float
|
1428
|
+
elif isinstance(value, int):
|
1429
|
+
return Type_Param.Integer
|
1430
|
+
elif isinstance(value, bool):
|
1431
|
+
return Type_Param.Logical
|
1432
|
+
elif isinstance(value, tuple):
|
1433
|
+
return Type_Param.Color
|
1434
|
+
else:
|
1435
|
+
return Type_Param.String
|
1436
|
+
|
1437
|
+
def change_param(self, group:str, name:str, value:Union[float, int, str, bool]):
|
1438
|
+
""" Modify the value of the parameter if found, otherwise None obj """
|
1439
|
+
|
1440
|
+
#essai pour voir si le groupe existe ou non
|
1441
|
+
param = self.get_param_dict(group, name)
|
1442
|
+
|
1443
|
+
if param is None:
|
1444
|
+
# le paramètre n'existe pas --> on l'ajoute
|
1445
|
+
if self.wx_exists:
|
1446
|
+
wx.MessageBox(_('This parameter is neither in the active group nor in the default group!'), _('Error'), wx.OK|wx.ICON_ERROR)
|
1447
|
+
else:
|
1448
|
+
logging.error(_('This parameter is neither in the current group nor in the default group!'))
|
1449
|
+
|
1450
|
+
self.add_param(group, name, value,
|
1451
|
+
self._detect_type_from_value(value),
|
1452
|
+
whichdict='All')
|
1453
|
+
|
1454
|
+
elif not self.is_in_active(group, name) and self.is_in_default(group, name):
|
1455
|
+
# le paramètre est dans les paramètres par défaut mais pas dans les paramètres actifs --> on l'ajoute
|
1456
|
+
default_value = self.myparams_default[group][name]
|
1457
|
+
self.add_param(group, name, value,
|
1458
|
+
default_value[key_Param.TYPE],
|
1459
|
+
comment=default_value[key_Param.COMMENT],
|
1460
|
+
jsonstr=default_value[key_Param.ADDED_JSON],
|
1461
|
+
whichdict='Active')
|
1462
|
+
elif self.is_in_active(group, name):
|
871
1463
|
param = self.myparams[group][name]
|
1464
|
+
param[key_Param.VALUE] = value
|
1465
|
+
|
1466
|
+
if self.update_incr_at_every_change:
|
1467
|
+
self._update_IncGroup()
|
1468
|
+
self._update_IncParam()
|
1469
|
+
|
1470
|
+
|
1471
|
+
# GROUPES/PARAMETRES INCREMENTABLES
|
1472
|
+
# ---------------------------------
|
1473
|
+
|
1474
|
+
def update_incremental_groups_params(self, update_groups=True, update_params=True):
|
1475
|
+
""" Update the incremental groups and parameters """
|
1476
|
+
|
1477
|
+
if update_groups:
|
1478
|
+
self._update_IncGroup()
|
1479
|
+
if update_params:
|
1480
|
+
self._update_IncParam()
|
1481
|
+
|
1482
|
+
|
1483
|
+
def isIncrementable_group(self, group:Union[str, dict]) -> bool:
|
1484
|
+
"""
|
1485
|
+
Return True if the group is incrementable
|
1486
|
+
"""
|
1487
|
+
|
1488
|
+
if isinstance(group, str):
|
1489
|
+
if group in self.myIncGroup.keys():
|
1490
|
+
return True
|
1491
|
+
elif '$n$' in group:
|
1492
|
+
return True
|
1493
|
+
elif '$n(' in group:
|
1494
|
+
return True
|
1495
|
+
else:
|
1496
|
+
return False
|
1497
|
+
elif isinstance(group, dict):
|
1498
|
+
if group in self.myIncGroup:
|
1499
|
+
return True
|
1500
|
+
else:
|
1501
|
+
return False
|
1502
|
+
|
1503
|
+
|
1504
|
+
def isIncrementable_param(self, param:Union[str, dict]) -> bool:
|
1505
|
+
"""
|
1506
|
+
Return True if the group is incrementable
|
1507
|
+
"""
|
1508
|
+
if isinstance(param, str):
|
1509
|
+
if param in self.myIncGroup.keys():
|
1510
|
+
return True
|
1511
|
+
elif '$n$' in param:
|
1512
|
+
return True
|
1513
|
+
elif '$n(' in param:
|
1514
|
+
return True
|
1515
|
+
else:
|
1516
|
+
return False
|
1517
|
+
elif isinstance(param, dict):
|
1518
|
+
if param in self.myIncParam:
|
1519
|
+
return True
|
1520
|
+
else:
|
1521
|
+
return False
|
1522
|
+
|
1523
|
+
def add_IncGroup(self,
|
1524
|
+
group:str,
|
1525
|
+
min:int,
|
1526
|
+
max:int,
|
1527
|
+
refGroup:str,
|
1528
|
+
refParam:str):
|
1529
|
+
|
1530
|
+
if not group in self.myIncGroup:
|
1531
|
+
# creation d'un dict sur base du nom de groupe
|
1532
|
+
curdict = self.myIncGroup[group] = {}
|
1533
|
+
else:
|
1534
|
+
curdict = self.myIncGroup[group]
|
872
1535
|
|
873
|
-
|
1536
|
+
curdict["Ref group"] = refGroup
|
1537
|
+
curdict["Ref param"] = refParam
|
1538
|
+
curdict["Min"] = int(min)
|
1539
|
+
curdict["Max"] = int(max)
|
1540
|
+
curdict["Dict"] = {}
|
874
1541
|
|
1542
|
+
if not "Saved" in curdict:
|
1543
|
+
curdict["Saved"] = {}
|
875
1544
|
|
1545
|
+
return curdict["Dict"]
|
876
1546
|
|
877
|
-
# Mise à jour des groupes inctrémmentables:
|
878
|
-
# Les groupes existants dans les paramètres courants seront sauvés dans le dicionnaire myIncGroup avec son incrément associé.
|
879
|
-
# Tout groupe sauvé avec le même incrément sera écrasé.
|
880
|
-
# Si le nombre associé au groupe est plus grand que désiré, tous les groupes en surplus seront sauvés dans dans le dicionnaire myIncGroup
|
881
|
-
# mais supprimé du dictionnaire de paramètre courant.
|
882
|
-
# S'il n'y a pas assez de groupe dans les paramètres courant, on les ajoute avec les valeurs sauvées, sinon avec des valeurs par défaut.
|
883
|
-
# Also check the max and min values
|
884
|
-
def Update_IncGroup(self, withGUI=False):
|
885
1547
|
|
1548
|
+
def _update_IncGroup(self, withGUI:bool=False):
|
1549
|
+
"""
|
1550
|
+
Mise à jour des groupes inctrémmentables:
|
1551
|
+
Les groupes existants dans les paramètres courants seront sauvés dans le dicionnaire myIncGroup avec son incrément associé.
|
1552
|
+
Tout groupe sauvé avec le même incrément sera écrasé.
|
1553
|
+
Si le nombre associé au groupe est plus grand que désiré, tous les groupes en surplus seront sauvés dans dans le dicionnaire myIncGroup
|
1554
|
+
mais supprimé du dictionnaire de paramètre courant.
|
1555
|
+
S'il n'y a pas assez de groupe dans les paramètres courant, on les ajoute avec les valeurs sauvées, sinon avec des valeurs par défaut.
|
1556
|
+
|
1557
|
+
Also check the max and min values
|
1558
|
+
"""
|
886
1559
|
for curIncGroup in self.myIncGroup:
|
1560
|
+
|
1561
|
+
# groupe contenant le paramètre du nombre de groupes incrémentables
|
887
1562
|
refGroup = self.myIncGroup[curIncGroup]["Ref group"]
|
1563
|
+
# paramètre contenant le nompbre de groupes incrémentables
|
888
1564
|
refParam = self.myIncGroup[curIncGroup]["Ref param"]
|
1565
|
+
# nombre de groupes min
|
889
1566
|
iterMin = int(self.myIncGroup[curIncGroup]["Min"])
|
1567
|
+
# nombre de groupes max
|
890
1568
|
iterMax = int(self.myIncGroup[curIncGroup]["Max"])
|
1569
|
+
|
1570
|
+
# nombre de groupes
|
891
1571
|
nbElements = int(self.get_param(refGroup,refParam))
|
892
|
-
|
1572
|
+
|
1573
|
+
# dictionnaire de sauvegarde
|
1574
|
+
# savedDict = {}
|
893
1575
|
savedDict = self.myIncGroup[curIncGroup]["Saved"]
|
894
1576
|
templateDict = self.myIncGroup[curIncGroup]["Dict"]
|
1577
|
+
|
895
1578
|
if(nbElements is None):
|
896
1579
|
if self.wx_exists:
|
897
1580
|
wx.MessageBox(_('The reference of the incrementable group does not exist!'), _('Error'), wx.OK|wx.ICON_ERROR)
|
@@ -900,77 +1583,194 @@ class Wolf_Param(wx.Frame):
|
|
900
1583
|
|
901
1584
|
elif(nbElements>iterMax):
|
902
1585
|
nbElements = iterMax
|
1586
|
+
|
903
1587
|
# elif(nbElements<iterMin):
|
904
1588
|
# nbElements = iterMax
|
905
1589
|
|
906
1590
|
for i in range(1,nbElements+1):
|
1591
|
+
# nom indicé du groupe incrémpentable
|
907
1592
|
curGroup = curIncGroup.replace("$n$",str(i))
|
1593
|
+
|
908
1594
|
if(withGUI):
|
909
|
-
|
1595
|
+
# If a graphical interface exists, we need to ensure that the encoded data is transferred to memory/object first.
|
910
1596
|
for curParam in templateDict:
|
911
|
-
|
1597
|
+
self._Apply1ParamtoMemory(curGroup, curParam, isIncrementable=True, genGroup=curIncGroup)
|
912
1598
|
|
913
1599
|
if(curGroup in self.myparams):
|
914
|
-
|
915
|
-
savedDict[curGroup] = self.myparams[curGroup]
|
1600
|
+
# We keep a copy in the 'Saved' dictionary
|
1601
|
+
savedDict[curGroup] = deepcopy(self.myparams[curGroup]) # deepcopy is necessary because it is a dict od dict
|
1602
|
+
|
916
1603
|
elif(curGroup in savedDict):
|
917
|
-
|
918
|
-
self.myparams[curGroup] = savedDict[curGroup]
|
1604
|
+
# Priority to the saved dictionary, rather than the default dictionary
|
1605
|
+
self.myparams[curGroup] = deepcopy(savedDict[curGroup]) # deepcopy is necessary because it is a dict od dict
|
1606
|
+
|
919
1607
|
else:
|
920
|
-
|
921
|
-
self.myparams[curGroup] = templateDict
|
1608
|
+
# nothing found --> we create a new group from the default dictionary
|
1609
|
+
self.myparams[curGroup] = deepcopy(templateDict) # deepcopy is necessary because it is a dict od dict
|
922
1610
|
|
923
1611
|
for i in range(nbElements+1,iterMax+1):
|
1612
|
+
# all potential groups with an index greater than the desired number of elements
|
924
1613
|
curGroup = curIncGroup.replace("$n$",str(i))
|
1614
|
+
|
925
1615
|
if(curGroup in self.myparams):
|
926
|
-
savedDict[curGroup] =
|
927
|
-
savedDict[curGroup] = self.myparams[curGroup].copy()
|
928
|
-
self.myparams[curGroup] = {}
|
1616
|
+
savedDict[curGroup] = deepcopy(self.myparams[curGroup]) # deepcopy is necessary because it is a dict od dict, copy is not enough
|
929
1617
|
del self.myparams[curGroup]
|
930
1618
|
else:
|
931
1619
|
break
|
932
1620
|
|
933
1621
|
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
1622
|
+
def add_IncParam(self,
|
1623
|
+
group:str,
|
1624
|
+
name:str,
|
1625
|
+
value:Union[float, int, str],
|
1626
|
+
comment:str,
|
1627
|
+
type:Type_Param,
|
1628
|
+
min:int = 0,
|
1629
|
+
max:int = 0,
|
1630
|
+
refParam:str = None,
|
1631
|
+
refGroup:str = None,
|
1632
|
+
added_json:str = None):
|
1633
|
+
"""
|
1634
|
+
Ajout d'un paramètre incrémentable
|
1635
|
+
|
1636
|
+
@param group: nom du groupe
|
1637
|
+
@param name: nom du paramètre
|
1638
|
+
@param value: valeur du paramètre
|
1639
|
+
@param comment: commentaire du paramètre
|
1640
|
+
@param type: type du paramètre
|
1641
|
+
@param min: valeur minimale
|
1642
|
+
@param max: valeur maximale
|
1643
|
+
@param refParam: nom du paramètre contenant le nombre de paramètres - doit être dans le même groupe
|
1644
|
+
|
1645
|
+
"""
|
1646
|
+
|
1647
|
+
if added_json is not None:
|
1648
|
+
if isinstance(added_json, str):
|
1649
|
+
added_json = json.loads(added_json.replace('%json',''))
|
1650
|
+
elif isinstance(added_json, dict):
|
1651
|
+
pass
|
1652
|
+
|
1653
|
+
if group not in self.myIncParam:
|
1654
|
+
self.myIncParam[group] = {}
|
1655
|
+
|
1656
|
+
name, iterInfo = self._Extract_IncrInfo(name)
|
1657
|
+
|
1658
|
+
if iterInfo is not None:
|
1659
|
+
if len(iterInfo) == 3:
|
1660
|
+
refParam, min, max = iterInfo
|
1661
|
+
refGroup = None
|
1662
|
+
elif len(iterInfo) == 4:
|
1663
|
+
refGroup, refParam, min, max = iterInfo
|
1664
|
+
else:
|
1665
|
+
logging.error("ERROR : wrong number of arguments in the incrementable parameter name {}!".format(name))
|
1666
|
+
|
1667
|
+
refGroup = refGroup if refGroup is not None else group
|
1668
|
+
|
1669
|
+
assert min >=0, "ERROR : min must be >= 0"
|
1670
|
+
assert max >0, "ERROR : max must be > 0"
|
1671
|
+
assert max >= min, "ERROR : max must be >= min"
|
1672
|
+
assert refParam is not None, "ERROR : refParam can not be None"
|
1673
|
+
assert refGroup is not None, "ERROR : refGroup can not be None"
|
1674
|
+
|
1675
|
+
curdict = self.myIncParam[group][name] = {}
|
1676
|
+
curdict["Group"] = group
|
1677
|
+
curdict["Ref group"] = refGroup
|
1678
|
+
curdict["Ref param"] = refParam
|
1679
|
+
curdict["Min"] = min
|
1680
|
+
curdict["Max"] = max
|
1681
|
+
curdict["Dict"] = {}
|
1682
|
+
curdict["Dict"][name] = {}
|
1683
|
+
curdict["Dict"][name][key_Param.NAME] = name
|
1684
|
+
curdict["Dict"][name][key_Param.VALUE] = value
|
1685
|
+
curdict["Dict"][name][key_Param.COMMENT] = comment
|
1686
|
+
curdict["Dict"][name][key_Param.TYPE] = type
|
1687
|
+
if added_json is not None:
|
1688
|
+
curdict["Dict"][name][key_Param.ADDED_JSON] = added_json
|
1689
|
+
else:
|
1690
|
+
curdict["Dict"][name][key_Param.ADDED_JSON] = None
|
1691
|
+
curdict["Saved"] = {}
|
1692
|
+
curdict["Saved"][group] = {}
|
1693
|
+
curdict["Saved"][group][name] = {}
|
1694
|
+
curdict["Saved"][group][name][key_Param.NAME] = name
|
1695
|
+
curdict["Saved"][group][name][key_Param.VALUE] = value
|
1696
|
+
curdict["Saved"][group][name][key_Param.COMMENT] = comment
|
1697
|
+
curdict["Saved"][group][name][key_Param.TYPE] = type
|
1698
|
+
if added_json is not None:
|
1699
|
+
curdict["Saved"][group][name][key_Param.ADDED_JSON] = added_json
|
1700
|
+
else:
|
1701
|
+
curdict["Saved"][group][name][key_Param.ADDED_JSON] = None
|
1702
|
+
|
1703
|
+
return 0
|
1704
|
+
|
942
1705
|
|
1706
|
+
def _update_IncParam(self, withGUI:bool=False):
|
1707
|
+
"""
|
1708
|
+
Mise à jour des paramètres inctrémmentables:
|
1709
|
+
Les paramètres existants dans les paramètres courants seront sauvés dans le dicionnaire myIncParam avec son incrément associé.
|
1710
|
+
Tout groupe sauvé avec le même incrément sera écrasé.
|
1711
|
+
Si le nombre associé au groupe est plus grand que désiré, tous les groupe en surplus seront sauvé dans dans le dicionnaire myIncParam
|
1712
|
+
mais supprimé du dictionnaire de paramètre courant.
|
1713
|
+
S'il n'y a pas assez de groupe dans les paramètres courant, on les ajoute avec les valeurs sauvées, sinon avec des valeurs par défaut.
|
1714
|
+
|
1715
|
+
Also check the max and min values
|
1716
|
+
"""
|
943
1717
|
for refGroup in self.myIncParam:
|
944
1718
|
for curIncParam in self.myIncParam[refGroup]:
|
945
1719
|
if(refGroup.find("$n$")>-1):
|
946
1720
|
nbMax = int(self.myIncGroup[refGroup]["Max"])
|
947
|
-
|
1721
|
+
|
948
1722
|
i=1
|
949
1723
|
while(i<nbMax+1):
|
950
1724
|
curGroup = refGroup.replace("$n$",str(i))
|
951
1725
|
i += 1
|
952
1726
|
if curGroup in self.myparams:
|
953
|
-
self.
|
1727
|
+
self._Update_OneIncParam(curIncParam, curGroup, genGroup=refGroup, withGUI=withGUI)
|
954
1728
|
else:
|
955
1729
|
break
|
956
1730
|
else:
|
957
|
-
# Si tous les autres paramètres restent inchangés, ce groupe n'est pas présent dans le dictionnaire.
|
958
|
-
# Il faut donc le créer
|
959
1731
|
if not refGroup in self.myparams:
|
960
1732
|
self.myparams[refGroup] = {}
|
961
|
-
self.
|
1733
|
+
self._Update_OneIncParam(curIncParam, refGroup, genGroup=refGroup, withGUI=withGUI)
|
1734
|
+
|
1735
|
+
|
1736
|
+
def _Update_OneIncParam(self, curIncParam:str, curGroup:str, genGroup:str, withGUI:bool=False):
|
1737
|
+
"""
|
1738
|
+
Routine interne de mise à jour d'un seul paramétre incrémentable
|
1739
|
+
|
1740
|
+
@param curIncParam : nom du paramètre incrémentable - contient $n$ à remplacer par le numéro
|
1741
|
+
@param curGroup : nom du groupe de référence - ! peut être un groupe icrémentable !
|
1742
|
+
@param genGroup : nom du groupe générique dans lequel sont stockés les informations sur le paramètre (key, value, min, max, ...)
|
1743
|
+
@param withGUI : True si on est en mode GUI
|
1744
|
+
|
1745
|
+
"""
|
962
1746
|
|
1747
|
+
refGroup = self.myIncParam[genGroup][curIncParam]["Ref group"] # groupe dans lequel est stocké le nombre de paramètres
|
1748
|
+
refParam = self.myIncParam[genGroup][curIncParam]["Ref param"] # nom du paramètre contenant le nombre de paramètres
|
1749
|
+
iterMin = int(self.myIncParam[genGroup][curIncParam]["Min"]) # nombre minimal de paramètres
|
1750
|
+
iterMax = int(self.myIncParam[genGroup][curIncParam]["Max"]) # nombre maximal de paramètres
|
1751
|
+
|
1752
|
+
# logging.info(curGroup+" / "+refParam)
|
1753
|
+
|
1754
|
+
if '$n$' in refGroup:
|
1755
|
+
# le groupe de référence est incrémentable --> le paramètre est à trouver dans le groupe courant
|
1756
|
+
|
1757
|
+
part_Group = refGroup.replace("$n$","")
|
1758
|
+
if part_Group in curGroup:
|
1759
|
+
refGroup = curGroup
|
1760
|
+
else:
|
1761
|
+
logging.error(_("ERROR : the reference group {} does not exist or is not well defined {}!".format(part_Group, curGroup)))
|
1762
|
+
|
1763
|
+
nbElements = self[(refGroup, refParam)] #int(self.get_param(refGroup, refParam))
|
1764
|
+
|
1765
|
+
if nbElements is None:
|
1766
|
+
logging.error(_("ERROR : the reference of the incrementable parameter does not exist!"))
|
1767
|
+
return
|
963
1768
|
|
964
|
-
def Update_OneIncParam(self, curIncParam, refGroup, genGroup, withGUI=False):
|
965
|
-
refParam = self.myIncParam[genGroup][curIncParam]["Ref param"]
|
966
|
-
iterMin = int(self.myIncParam[genGroup][curIncParam]["Min"])
|
967
|
-
iterMax = int(self.myIncParam[genGroup][curIncParam]["Max"])
|
968
|
-
logging.info(refGroup+" / "+refParam)
|
969
|
-
nbElements = int(self.get_param(refGroup,refParam))
|
970
1769
|
savedDict = {}
|
971
1770
|
savedDict = self.myIncParam[genGroup][curIncParam]["Saved"]
|
972
|
-
if(not(
|
973
|
-
savedDict[
|
1771
|
+
if(not(curGroup in savedDict)):
|
1772
|
+
savedDict[curGroup] = {}
|
1773
|
+
|
974
1774
|
templateDict = self.myIncParam[genGroup][curIncParam]["Dict"]
|
975
1775
|
if(nbElements is None):
|
976
1776
|
if self.wx_exists:
|
@@ -982,178 +1782,41 @@ class Wolf_Param(wx.Frame):
|
|
982
1782
|
# elif(nbElements<iterMin):
|
983
1783
|
# nbElements = iterMax
|
984
1784
|
|
985
|
-
for i in range(1,nbElements+1):
|
1785
|
+
for i in range(1, nbElements+1):
|
986
1786
|
curParam = curIncParam.replace("$n$",str(i))
|
987
1787
|
|
988
1788
|
if(withGUI):
|
989
|
-
|
990
|
-
groupexists = self.Apply1ParamtoMemory(refGroup, curParam, groupexists=groupexists,isIncrementable=True,genGroup=genGroup,genParam=curIncParam)
|
991
|
-
|
992
|
-
if(curParam in self.myparams[refGroup]):
|
993
|
-
savedDict[refGroup][curParam] = {}
|
994
|
-
savedDict[refGroup][curParam] = self.myparams[refGroup][curParam]
|
995
|
-
elif(curParam in savedDict[refGroup]):
|
996
|
-
self.myparams[refGroup][curParam] = {}
|
997
|
-
self.myparams[refGroup][curParam] = savedDict[refGroup][curParam]
|
998
|
-
else:
|
999
|
-
self.myparams[refGroup][curParam] = {}
|
1000
|
-
self.myparams[refGroup][curParam] = templateDict.copy()
|
1001
|
-
|
1002
|
-
for i in range(nbElements+1,iterMax+1):
|
1003
|
-
curParam = curIncParam.replace("$n$",str(i))
|
1004
|
-
if(curParam in self.myparams):
|
1005
|
-
savedDict[refGroup][curParam] = {}
|
1006
|
-
savedDict[refGroup][curParam] = self.myparams[refGroup][curParam].copy()
|
1007
|
-
self.myparams[refGroup][curParam] = {}
|
1008
|
-
else:
|
1009
|
-
break
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1014
|
-
def Extract_IncrInfo(self, nameStr:str):
|
1015
|
-
|
1016
|
-
iterInfo = []
|
1017
|
-
newName = ""
|
1018
|
-
posSep1 = nameStr.find("$")
|
1019
|
-
posSep2 = nameStr[posSep1+1:].find("$")
|
1020
|
-
|
1021
|
-
# Groupe avec indice incrémentable
|
1022
|
-
if posSep1>-1 or posSep2>-1:
|
1023
|
-
iterCode = nameStr[posSep1+1:posSep1+posSep2+1]
|
1024
|
-
posSep1 = iterCode.find("(")
|
1025
|
-
posSep2 = iterCode[posSep1:].find(")")
|
1026
|
-
iterCode = iterCode[posSep1+1:posSep2+1]
|
1027
|
-
newName = nameStr.replace("("+iterCode+")",'')
|
1028
|
-
# newName = nameStr.replace(':','')
|
1029
|
-
newName = newName.strip()
|
1030
|
-
iterInfo = iterCode.split(',')
|
1031
|
-
else:
|
1032
|
-
newName = nameStr
|
1033
|
-
iterInfo = None
|
1789
|
+
self._Apply1ParamtoMemory(curGroup, curParam, isIncrementable=True, genGroup=genGroup, genParam=curIncParam)
|
1034
1790
|
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
# @var genGroup : generic name of an incrementable group
|
1039
|
-
# @var genParam : generic name of an incrementable param
|
1040
|
-
def Apply1ParamtoMemory(self, group, param_name, groupexists=False, isIncrementable=False, genGroup="", genParam=""):
|
1791
|
+
if(curParam in self.myparams[curGroup]):
|
1792
|
+
savedDict[curGroup][curParam] = {}
|
1793
|
+
savedDict[curGroup][curParam] = self.myparams[curGroup][curParam]
|
1041
1794
|
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
param = self.myIncParam[genGroup][genParam]["Dict"]
|
1046
|
-
else:
|
1047
|
-
param = self.myIncParam[group][genParam]["Dict"]
|
1795
|
+
elif(curParam in savedDict[curGroup]):
|
1796
|
+
self.myparams[curGroup][curParam] = {}
|
1797
|
+
self.myparams[curGroup][curParam] = savedDict[curGroup][curParam]
|
1048
1798
|
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1799
|
+
else:
|
1800
|
+
self.myparams[curGroup][curParam] = {}
|
1801
|
+
self.myparams[curGroup][curParam][key_Param.NAME] = curParam
|
1802
|
+
self.myparams[curGroup][curParam][key_Param.VALUE] = templateDict[curIncParam][key_Param.VALUE]
|
1803
|
+
self.myparams[curGroup][curParam][key_Param.COMMENT] = templateDict[curIncParam][key_Param.COMMENT]
|
1804
|
+
self.myparams[curGroup][curParam][key_Param.TYPE] = templateDict[curIncParam][key_Param.TYPE]
|
1805
|
+
if key_Param.ADDED_JSON in templateDict[curIncParam]:
|
1806
|
+
self.myparams[curGroup][curParam][key_Param.ADDED_JSON] = templateDict[curIncParam][key_Param.ADDED_JSON]
|
1807
|
+
|
1808
|
+
# transfert des paramètres en surplus dans le dictionnaire savedDict
|
1809
|
+
for i in range(nbElements+1, iterMax+1):
|
1810
|
+
curParam = curIncParam.replace("$n$",str(i))
|
1054
1811
|
|
1055
|
-
|
1056
|
-
|
1812
|
+
if(curParam in self.myparams[curGroup]):
|
1813
|
+
savedDict[curGroup][curParam] = {}
|
1814
|
+
savedDict[curGroup][curParam] = self.myparams[curGroup][curParam].copy()
|
1815
|
+
self.myparams[curGroup].pop(curParam)
|
1057
1816
|
|
1058
|
-
if curprop is not None :
|
1059
|
-
toApply = False
|
1060
|
-
if param['type']=='Integer_or_Float':
|
1061
|
-
vpar = float(curprop.m_value)
|
1062
|
-
if isIncrementable:
|
1063
|
-
toApply = True
|
1064
|
-
else:
|
1065
|
-
vpardef = float(curdefprop.m_value)
|
1066
|
-
if vpar != vpardef :
|
1067
|
-
toApply = True
|
1068
|
-
if toApply:
|
1069
|
-
if not groupexists :
|
1070
|
-
self.myparams[group]={}
|
1071
|
-
groupexists = True
|
1072
|
-
self.myparams[group][param_name] = {}
|
1073
|
-
self.myparams[group][param_name]['value']=vpar
|
1074
|
-
elif param['type']=='Integer':
|
1075
|
-
if isIncrementable:
|
1076
|
-
toApply = True
|
1077
|
-
elif int(curprop.m_value) != int(curdefprop.m_value) :
|
1078
|
-
toApply = True
|
1079
|
-
if toApply:
|
1080
|
-
if not groupexists :
|
1081
|
-
self.myparams[group]={}
|
1082
|
-
groupexists = True
|
1083
|
-
self.myparams[group][param_name] = {}
|
1084
|
-
self.myparams[group][param_name]['value']=int(curprop.m_value)
|
1085
|
-
elif param['type']=='Logical':
|
1086
|
-
if isIncrementable:
|
1087
|
-
toApply = True
|
1088
|
-
elif curprop.m_value != curdefprop.m_value :
|
1089
|
-
toApply = True
|
1090
|
-
if toApply:
|
1091
|
-
if not groupexists :
|
1092
|
-
self.myparams[group]={}
|
1093
|
-
groupexists = True
|
1094
|
-
self.myparams[group][param_name] = {}
|
1095
|
-
if curprop.m_value:
|
1096
|
-
self.myparams[group][param_name]['value']='.true.'
|
1097
|
-
else:
|
1098
|
-
self.myparams[group][param_name]['value']='.false.'
|
1099
|
-
elif param['type']=='Float':
|
1100
|
-
#try:
|
1101
|
-
# vpar = float(curprop.m_value.replace('d','e'))
|
1102
|
-
#except:
|
1103
|
-
vpar = float(curprop.m_value)
|
1104
|
-
|
1105
|
-
#try:
|
1106
|
-
# vpardef = float(curdefprop.m_value.replace('d','e'))
|
1107
|
-
#except:
|
1108
|
-
if isIncrementable:
|
1109
|
-
toApply = True
|
1110
|
-
else:
|
1111
|
-
vpardef = float(curdefprop.m_value)
|
1112
|
-
if vpar != vpardef :
|
1113
|
-
toApply = True
|
1114
|
-
|
1115
|
-
if toApply:
|
1116
|
-
if not groupexists :
|
1117
|
-
self.myparams[group]={}
|
1118
|
-
groupexists = True
|
1119
|
-
self.myparams[group][param_name] = {}
|
1120
|
-
self.myparams[group][param_name]['value']=vpar
|
1121
|
-
elif param['type']=='File':
|
1122
|
-
if isIncrementable:
|
1123
|
-
toApply = True
|
1124
|
-
elif str(curprop.m_value) != str(curdefprop.m_value) :
|
1125
|
-
toApply = True
|
1126
|
-
if toApply:
|
1127
|
-
if not groupexists :
|
1128
|
-
self.myparams[group]={}
|
1129
|
-
groupexists = True
|
1130
|
-
self.myparams[group][param_name] = {}
|
1131
|
-
self.myparams[group][param_name]['value']=str(curprop.m_value)
|
1132
|
-
elif param['type']=='Directory':
|
1133
|
-
if isIncrementable:
|
1134
|
-
toApply = True
|
1135
|
-
elif str(curprop.m_value) != str(curdefprop.m_value) :
|
1136
|
-
toApply = True
|
1137
|
-
if toApply:
|
1138
|
-
if not groupexists :
|
1139
|
-
self.myparams[group]={}
|
1140
|
-
groupexists = True
|
1141
|
-
self.myparams[group][param_name] = {}
|
1142
|
-
self.myparams[group][param_name]['value']=str(curprop.m_value)
|
1143
1817
|
else:
|
1144
|
-
|
1145
|
-
|
1146
|
-
elif str(curprop.m_value) != str(curdefprop.m_value) :
|
1147
|
-
toApply = True
|
1148
|
-
if toApply:
|
1149
|
-
if not groupexists :
|
1150
|
-
self.myparams[group]={}
|
1151
|
-
groupexists = True
|
1152
|
-
self.myparams[group][param_name] = {}
|
1153
|
-
self.myparams[group][param_name]['value']=str(curprop.m_value)
|
1154
|
-
|
1155
|
-
return groupexists
|
1156
|
-
|
1818
|
+
# inutile de continuer, on a atteint le dernier paramètre
|
1819
|
+
break
|
1157
1820
|
|
1158
1821
|
if __name__ =="__main__":
|
1159
1822
|
test = Wolf_Param()
|