1 # -*- coding: utf-8 -*-
3 # Copyright (C) 2008-2020 EDF R&D
5 # This library is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU Lesser General Public
7 # License as published by the Free Software Foundation; either
8 # version 2.1 of the License.
10 # This library is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 # Lesser General Public License for more details.
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with this library; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 # Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
24 Définit les outils d'interfaces normalisées de cas.
26 __author__ = "Jean-Philippe ARGAUD"
35 from daCore import Persistence
36 from daCore import PlatformInfo
37 from daCore import Templates
39 # ==============================================================================
40 class GenericCaseViewer(object):
42 Gestion des commandes de création d'une vue de cas
44 def __init__(self, __name="", __objname="case", __content=None, __object=None):
45 "Initialisation et enregistrement de l'entete"
46 self._name = str(__name)
47 self._objname = str(__objname)
49 self._switchoff = False
50 self._numobservers = 2
51 self._content = __content
52 self._object = __object
53 self._missing = """raise ValueError("This case requires beforehand to import or define the variable named <%s>. When corrected, remove this command, correct and uncomment the following one.")\n# """
54 def _append(self, *args):
55 "Transformation d'une commande individuelle en un enregistrement"
56 raise NotImplementedError()
57 def _extract(self, *args):
58 "Transformation d'enregistrement(s) en commande(s) individuelle(s)"
59 raise NotImplementedError()
60 def _finalize(self, __upa=None):
61 "Enregistrement du final"
62 if __upa is not None and len(__upa)>0:
63 self._lineSerie.append("%s.execute()"%(self._objname,))
64 self._lineSerie.append(__upa)
65 def _addLine(self, line=""):
66 "Ajoute un enregistrement individuel"
67 self._lineSerie.append(line)
68 def _get_objname(self):
70 def dump(self, __filename=None, __upa=None):
71 "Restitution normalisée des commandes"
73 __text = "\n".join(self._lineSerie)
75 if __filename is not None:
76 __file = os.path.abspath(__filename)
77 __fid = open(__file,"w")
81 def load(self, __filename=None, __content=None, __object=None):
82 "Chargement normalisé des commandes"
83 if __filename is not None and os.path.exists(__filename):
84 self._content = open(__filename, 'r').read()
85 elif __content is not None and type(__content) is str:
86 self._content = __content
87 elif __object is not None and type(__object) is dict:
88 self._object = copy.deepcopy(__object)
90 pass # use "self._content" from initialization
91 __commands = self._extract(self._content, self._object)
94 class _TUIViewer(GenericCaseViewer):
96 Établissement des commandes d'un cas ADAO TUI (Cas<->TUI)
98 def __init__(self, __name="", __objname="case", __content=None, __object=None):
99 "Initialisation et enregistrement de l'entete"
100 GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
101 self._addLine("# -*- coding: utf-8 -*-")
102 self._addLine("#\n# Python script using ADAO TUI\n#")
103 self._addLine("from numpy import array, matrix")
104 self._addLine("from adao import adaoBuilder")
105 self._addLine("%s = adaoBuilder.New('%s')"%(self._objname, self._name))
106 if self._content is not None:
107 for command in self._content:
108 self._append(*command)
109 def _append(self, __command=None, __keys=None, __local=None, __pre=None, __switchoff=False):
110 "Transformation d'une commande individuelle en un enregistrement"
111 if __command is not None and __keys is not None and __local is not None:
112 if "Concept" in __keys:
113 logging.debug("TUI Order processed: %s"%(__local["Concept"],))
115 if __pre is not None:
116 __text += "%s = "%__pre
117 __text += "%s.%s( "%(self._objname,str(__command))
118 if "self" in __keys: __keys.remove("self")
119 if __command not in ("set","get") and "Concept" in __keys: __keys.remove("Concept")
121 if k not in __local: continue
123 if __v is None: continue
124 if k == "Checked" and not __v: continue
125 if k == "Stored" and not __v: continue
126 if k == "ColMajor" and not __v: continue
127 if k == "InputFunctionAsMulti" and not __v: continue
128 if k == "nextStep" and not __v: continue
129 if k == "AvoidRC" and __v: continue
130 if k == "noDetails": continue
131 if isinstance(__v,Persistence.Persistence): __v = __v.values()
132 if callable(__v): __text = self._missing%__v.__name__+__text
133 if isinstance(__v,dict):
134 for val in __v.values():
135 if callable(val): __text = self._missing%val.__name__+__text
136 numpy.set_printoptions(precision=15,threshold=1000000,linewidth=1000*15)
137 __text += "%s=%s, "%(k,repr(__v))
138 numpy.set_printoptions(precision=8,threshold=1000,linewidth=75)
141 self._addLine(__text)
142 def _extract(self, __multilines="", __object=None):
143 "Transformation d'enregistrement(s) en commande(s) individuelle(s)"
146 __multilines = __multilines.replace("\r\n","\n")
147 for line in __multilines.split("\n"):
148 if "adaoBuilder.New" in line and "=" in line:
149 self._objname = line.split("=")[0].strip()
151 logging.debug("TUI Extracting commands of '%s' object..."%(self._objname,))
155 if self._objname+".set" in line:
156 __commands.append( line.replace(self._objname+".","",1) )
157 logging.debug("TUI Extracted command: %s"%(__commands[-1],))
160 class _COMViewer(GenericCaseViewer):
162 Établissement des commandes d'un cas COMM (Eficas Native Format/Cas<-COM)
164 def __init__(self, __name="", __objname="case", __content=None, __object=None):
165 "Initialisation et enregistrement de l'entete"
166 GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
167 self._observerIndex = 0
168 self._addLine("# -*- coding: utf-8 -*-")
169 self._addLine("#\n# Python script using ADAO COMM\n#")
170 self._addLine("from numpy import array, matrix")
172 self._addLine("%s = {}"%__objname)
173 if self._content is not None:
174 for command in self._content:
175 self._append(*command)
176 def _extract(self, __multilines=None, __object=None):
177 "Transformation d'enregistrement(s) en commande(s) individuelle(s)"
178 if __multilines is not None:
179 if "ASSIMILATION_STUDY" in __multilines:
180 __multilines = __multilines.replace("ASSIMILATION_STUDY","dict")
181 if "CHECKING_STUDY" in __multilines:
182 __multilines = __multilines.replace("CHECKING_STUDY", "dict")
183 __multilines = __multilines.replace("_F(", "dict(")
184 __multilines = __multilines.replace(",),);", ",),)")
186 for line in __multilines.split("\n"):
187 if len(line) < 1: continue
188 __fulllines += line + "\n"
189 __multilines = __fulllines
190 self._objname = "case"
192 exec("self._objdata = "+__multilines)
194 if self._objdata is None or not(type(self._objdata) is dict) or not('AlgorithmParameters' in self._objdata):
195 raise ValueError("Impossible to load given content as an ADAO COMM one (no dictionnary or no 'AlgorithmParameters' key found).")
196 # ----------------------------------------------------------------------
197 logging.debug("COMM Extracting commands of '%s' object..."%(self._objname,))
199 __UserPostAnalysis = ""
200 for k,r in self._objdata.items():
202 logging.debug("COMM Extracted command: %s:%s"%(k, r))
203 if __command == "StudyName" and len(str(r))>0:
204 __commands.append( "set( Concept='Name', String='%s')"%(str(r),) )
205 elif __command == "StudyRepertory":
206 __commands.append( "set( Concept='Directory', String='%s')"%(str(r),) )
207 elif __command == "Debug" and str(r) == "0":
208 __commands.append( "set( Concept='NoDebug' )" )
209 elif __command == "Debug" and str(r) == "1":
210 __commands.append( "set( Concept='Debug' )" )
212 elif __command == "UserPostAnalysis" and type(r) is dict:
214 __UserPostAnalysis = r['STRING']
215 elif 'SCRIPT_FILE' in r and os.path.exists(r['SCRIPT_FILE']):
216 __UserPostAnalysis = open(r['SCRIPT_FILE'],'r').read()
217 elif 'Template' in r and 'ValueTemplate' in r:
219 __UserPostAnalysis = r['ValueTemplate']
221 __UserPostAnalysis = ""
222 __UserPostAnalysis = __UserPostAnalysis.replace("ADD",self._objname)
224 elif __command == "AlgorithmParameters" and type(r) is dict and 'Algorithm' in r:
225 if 'data' in r and r['Parameters'] == 'Dict':
227 if 'STRING' in __from:
228 __parameters = ", Parameters=%s"%(repr(eval(__from['STRING'])),)
229 elif 'SCRIPT_FILE' in __from and os.path.exists(__from['SCRIPT_FILE']):
230 __parameters = ", Script='%s'"%(__from['SCRIPT_FILE'],)
231 else: # if 'Parameters' in r and r['Parameters'] == 'Defaults':
232 __Dict = copy.deepcopy(r)
233 __Dict.pop('Algorithm','')
234 __Dict.pop('Parameters','')
235 if 'SetSeed' in __Dict:__Dict['SetSeed'] = int(__Dict['SetSeed'])
236 if 'BoxBounds' in __Dict and type(__Dict['BoxBounds']) is str:
237 __Dict['BoxBounds'] = eval(__Dict['BoxBounds'])
239 __parameters = ', Parameters=%s'%(repr(__Dict),)
242 __commands.append( "set( Concept='AlgorithmParameters', Algorithm='%s'%s )"%(r['Algorithm'],__parameters) )
244 elif __command == "Observers" and type(r) is dict and 'SELECTION' in r:
245 if type(r['SELECTION']) is str:
246 __selection = (r['SELECTION'],)
248 __selection = tuple(r['SELECTION'])
249 for sk in __selection:
250 __idata = r['%s_data'%sk]
251 if __idata['NodeType'] == 'Template' and 'Template' in __idata:
252 __template = __idata['Template']
253 if 'Info' in __idata:
254 __info = ", Info='%s'"%(__idata['Info'],)
257 __commands.append( "set( Concept='Observer', Variable='%s', Template='%s'%s )"%(sk,__template,__info) )
258 if __idata['NodeType'] == 'String' and 'Value' in __idata:
259 __value =__idata['Value']
260 __commands.append( "set( Concept='Observer', Variable='%s', String='%s' )"%(sk,__value) )
262 # Background, ObservationError, ObservationOperator...
263 elif type(r) is dict:
265 if 'Stored' in r and bool(r['Stored']):
266 __argumentsList.append(['Stored',True])
267 if 'INPUT_TYPE' in r and 'data' in r:
268 # Vector, Matrix, ScalarSparseMatrix, DiagonalSparseMatrix, Function
269 __itype = r['INPUT_TYPE']
271 if 'FROM' in __idata:
272 # String, Script, DataFile, Template, ScriptWithOneFunction, ScriptWithFunctions
273 __ifrom = __idata['FROM']
274 __idata.pop('FROM','')
275 if __ifrom == 'String' or __ifrom == 'Template':
276 __argumentsList.append([__itype,__idata['STRING']])
277 if __ifrom == 'Script':
278 __argumentsList.append([__itype,True])
279 __argumentsList.append(['Script',__idata['SCRIPT_FILE']])
280 if __ifrom == 'DataFile':
281 __argumentsList.append([__itype,True])
282 __argumentsList.append(['DataFile',__idata['DATA_FILE']])
283 if __ifrom == 'ScriptWithOneFunction':
284 __argumentsList.append(['OneFunction',True])
285 __argumentsList.append(['Script',__idata.pop('SCRIPTWITHONEFUNCTION_FILE')])
287 __argumentsList.append(['Parameters',__idata])
288 if __ifrom == 'ScriptWithFunctions':
289 __argumentsList.append(['ThreeFunctions',True])
290 __argumentsList.append(['Script',__idata.pop('SCRIPTWITHFUNCTIONS_FILE')])
292 __argumentsList.append(['Parameters',__idata])
293 __arguments = ["%s = %s"%(k,repr(v)) for k,v in __argumentsList]
294 __commands.append( "set( Concept='%s', %s )"%(__command, ", ".join(__arguments)))
296 # ----------------------------------------------------------------------
297 __commands.sort() # Pour commencer par 'AlgorithmParameters'
298 __commands.append(__UserPostAnalysis)
301 class _SCDViewer(GenericCaseViewer):
303 Établissement des commandes d'un cas SCD (Study Config Dictionary/Cas->SCD)
305 Remarque : le fichier généré est différent de celui obtenu par EFICAS
307 def __init__(self, __name="", __objname="case", __content=None, __object=None):
308 "Initialisation et enregistrement de l'entête"
309 GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
310 self._addLine("# -*- coding: utf-8 -*-")
311 self._addLine("#\n# Input for ADAO converter to SCD\n#")
313 self._addLine("study_config = {}")
314 self._addLine("study_config['StudyType'] = 'ASSIMILATION_STUDY'")
315 self._addLine("study_config['Name'] = '%s'"%self._name)
316 self._addLine("observers = {}")
317 self._addLine("study_config['Observers'] = observers")
319 self._addLine("inputvariables_config = {}")
320 self._addLine("inputvariables_config['Order'] =['adao_default']")
321 self._addLine("inputvariables_config['adao_default'] = -1")
322 self._addLine("study_config['InputVariables'] = inputvariables_config")
324 self._addLine("outputvariables_config = {}")
325 self._addLine("outputvariables_config['Order'] = ['adao_default']")
326 self._addLine("outputvariables_config['adao_default'] = -1")
327 self._addLine("study_config['OutputVariables'] = outputvariables_config")
328 if __content is not None:
329 for command in __content:
330 self._append(*command)
331 def _append(self, __command=None, __keys=None, __local=None, __pre=None, __switchoff=False):
332 "Transformation d'une commande individuelle en un enregistrement"
333 if __command == "set": __command = __local["Concept"]
334 else: __command = __command.replace("set", "", 1)
335 logging.debug("SCD Order processed: %s"%(__command))
338 if __command in (None, 'execute', 'executePythonScheme', 'executeYACSScheme', 'get', 'Name'):
340 elif __command in ['Debug', 'setDebug']:
341 __text = "#\nstudy_config['Debug'] = '1'"
342 elif __command in ['NoDebug', 'setNoDebug']:
343 __text = "#\nstudy_config['Debug'] = '0'"
344 elif __command in ['Observer', 'setObserver']:
345 __obs = __local['Variable']
346 self._numobservers += 1
348 __text += "observers['%s'] = {}\n"%__obs
349 if __local['String'] is not None:
350 __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'String')
351 __text += "observers['%s']['String'] = \"\"\"%s\"\"\"\n"%(__obs, __local['String'])
352 if __local['Script'] is not None:
353 __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'Script')
354 __text += "observers['%s']['Script'] = \"%s\"\n"%(__obs, __local['Script'])
355 if __local['Template'] is not None and __local['Template'] in Templates.ObserverTemplates:
356 __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'String')
357 __text += "observers['%s']['String'] = \"\"\"%s\"\"\"\n"%(__obs, Templates.ObserverTemplates[__local['Template']])
358 if __local['Info'] is not None:
359 __text += "observers['%s']['info'] = \"\"\"%s\"\"\"\n"%(__obs, __local['Info'])
361 __text += "observers['%s']['info'] = \"\"\"%s\"\"\"\n"%(__obs, __obs)
362 __text += "observers['%s']['number'] = %s"%(__obs, self._numobservers)
363 elif __local is not None: # __keys is not None and
364 numpy.set_printoptions(precision=15,threshold=1000000,linewidth=1000*15)
366 __text += "%s_config = {}\n"%__command
367 __local.pop('self','')
369 __vectorIsDataFile = False
370 __vectorIsScript = False
371 for __k,__v in __local.items():
372 if __v is None: __to_be_removed.append(__k)
373 for __k in __to_be_removed:
375 for __k,__v in __local.items():
376 if __k == "Concept": continue
377 if __k in ['ScalarSparseMatrix','DiagonalSparseMatrix','Matrix','OneFunction','ThreeFunctions'] and 'Script' in __local and __local['Script'] is not None: continue
378 if __k in ['Vector','VectorSerie'] and 'DataFile' in __local and __local['DataFile'] is not None: continue
379 if __k == 'Parameters' and not (__command in ['AlgorithmParameters','SupplementaryParameters']): continue
380 if __k == 'Algorithm':
381 __text += "study_config['Algorithm'] = %s\n"%(repr(__v))
382 elif __k == 'DataFile':
385 __v = "'"+repr(__v)+"'"
386 for __lk in ['Vector','VectorSerie']:
387 if __lk in __local and __local[__lk]: __k = __lk
388 __text += "%s_config['Type'] = '%s'\n"%(__command,__k)
389 __text += "%s_config['From'] = '%s'\n"%(__command,__f)
390 __text += "%s_config['Data'] = %s\n"%(__command,__v)
391 __text = __text.replace("''","'")
392 __vectorIsDataFile = True
393 elif __k == 'Script':
396 __v = "'"+repr(__v)+"'"
397 for __lk in ['ScalarSparseMatrix','DiagonalSparseMatrix','Matrix']:
398 if __lk in __local and __local[__lk]: __k = __lk
399 if __command == "AlgorithmParameters": __k = "Dict"
400 if 'OneFunction' in __local and __local['OneFunction']:
401 __text += "%s_ScriptWithOneFunction = {}\n"%(__command,)
402 __text += "%s_ScriptWithOneFunction['Function'] = ['Direct', 'Tangent', 'Adjoint']\n"%(__command,)
403 __text += "%s_ScriptWithOneFunction['Script'] = {}\n"%(__command,)
404 __text += "%s_ScriptWithOneFunction['Script']['Direct'] = %s\n"%(__command,__v)
405 __text += "%s_ScriptWithOneFunction['Script']['Tangent'] = %s\n"%(__command,__v)
406 __text += "%s_ScriptWithOneFunction['Script']['Adjoint'] = %s\n"%(__command,__v)
407 __text += "%s_ScriptWithOneFunction['DifferentialIncrement'] = 1e-06\n"%(__command,)
408 __text += "%s_ScriptWithOneFunction['CenteredFiniteDifference'] = 0\n"%(__command,)
410 __f = 'ScriptWithOneFunction'
411 __v = '%s_ScriptWithOneFunction'%(__command,)
412 if 'ThreeFunctions' in __local and __local['ThreeFunctions']:
413 __text += "%s_ScriptWithFunctions = {}\n"%(__command,)
414 __text += "%s_ScriptWithFunctions['Function'] = ['Direct', 'Tangent', 'Adjoint']\n"%(__command,)
415 __text += "%s_ScriptWithFunctions['Script'] = {}\n"%(__command,)
416 __text += "%s_ScriptWithFunctions['Script']['Direct'] = %s\n"%(__command,__v)
417 __text += "%s_ScriptWithFunctions['Script']['Tangent'] = %s\n"%(__command,__v)
418 __text += "%s_ScriptWithFunctions['Script']['Adjoint'] = %s\n"%(__command,__v)
420 __f = 'ScriptWithFunctions'
421 __v = '%s_ScriptWithFunctions'%(__command,)
422 __text += "%s_config['Type'] = '%s'\n"%(__command,__k)
423 __text += "%s_config['From'] = '%s'\n"%(__command,__f)
424 __text += "%s_config['Data'] = %s\n"%(__command,__v)
425 __text = __text.replace("''","'")
426 __vectorIsScript = True
427 elif __k in ('Stored', 'Checked', 'ColMajor', 'InputFunctionAsMulti', 'nextStep'):
429 __text += "%s_config['%s'] = '%s'\n"%(__command,__k,int(bool(__v)))
430 elif __k in ('AvoidRC', 'noDetails'):
432 __text += "%s_config['%s'] = '%s'\n"%(__command,__k,int(bool(__v)))
434 if __k == 'Vector' and __vectorIsScript: continue
435 if __k == 'Vector' and __vectorIsDataFile: continue
436 if __k == 'Parameters': __k = "Dict"
437 if isinstance(__v,Persistence.Persistence): __v = __v.values()
438 if callable(__v): __text = self._missing%__v.__name__+__text
439 if isinstance(__v,dict):
440 for val in __v.values():
441 if callable(val): __text = self._missing%val.__name__+__text
442 __text += "%s_config['Type'] = '%s'\n"%(__command,__k)
443 __text += "%s_config['From'] = '%s'\n"%(__command,'String')
444 __text += "%s_config['Data'] = \"\"\"%s\"\"\"\n"%(__command,repr(__v))
445 __text += "study_config['%s'] = %s_config"%(__command,__command)
446 numpy.set_printoptions(precision=8,threshold=1000,linewidth=75)
448 self._switchoff = True
449 if __text is not None: self._addLine(__text)
451 self._switchoff = False
452 def _finalize(self, *__args):
453 self.__loadVariablesByScript()
455 self._addLine("Analysis_config = {}")
456 self._addLine("Analysis_config['From'] = 'String'")
457 self._addLine("Analysis_config['Data'] = \"\"\"import numpy")
458 self._addLine("xa=numpy.ravel(ADD.get('Analysis')[-1])")
459 self._addLine("print('Analysis:',xa)\"\"\"")
460 self._addLine("study_config['UserPostAnalysis'] = Analysis_config")
461 def __loadVariablesByScript(self):
462 __ExecVariables = {} # Necessaire pour recuperer la variable
463 exec("\n".join(self._lineSerie), __ExecVariables)
464 study_config = __ExecVariables['study_config']
465 # Pour Python 3 : self.__hasAlgorithm = bool(study_config['Algorithm'])
466 if 'Algorithm' in study_config:
467 self.__hasAlgorithm = True
469 self.__hasAlgorithm = False
470 if not self.__hasAlgorithm and \
471 "AlgorithmParameters" in study_config and \
472 isinstance(study_config['AlgorithmParameters'], dict) and \
473 "From" in study_config['AlgorithmParameters'] and \
474 "Data" in study_config['AlgorithmParameters'] and \
475 study_config['AlgorithmParameters']['From'] == 'Script':
476 __asScript = study_config['AlgorithmParameters']['Data']
477 __var = ImportFromScript(__asScript).getvalue( "Algorithm" )
478 __text = "#\nstudy_config['Algorithm'] = '%s'"%(__var,)
479 self._addLine(__text)
480 if self.__hasAlgorithm and \
481 "AlgorithmParameters" in study_config and \
482 isinstance(study_config['AlgorithmParameters'], dict) and \
483 "From" not in study_config['AlgorithmParameters'] and \
484 "Data" not in study_config['AlgorithmParameters']:
486 __text += "AlgorithmParameters_config['Type'] = 'Dict'\n"
487 __text += "AlgorithmParameters_config['From'] = 'String'\n"
488 __text += "AlgorithmParameters_config['Data'] = '{}'\n"
489 self._addLine(__text)
492 class _YACSViewer(GenericCaseViewer):
494 Etablissement des commandes d'un cas YACS (Cas->SCD->YACS)
496 def __init__(self, __name="", __objname="case", __content=None, __object=None):
497 "Initialisation et enregistrement de l'entete"
498 GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
499 self.__internalSCD = _SCDViewer(__name, __objname, __content, __object)
500 self._append = self.__internalSCD._append
501 def dump(self, __filename=None, __upa=None):
502 "Restitution normalisée des commandes"
504 if __filename is None:
505 raise ValueError("A file name has to be given for YACS XML output.")
507 __file = os.path.abspath(__filename)
508 if os.path.isfile(__file) or os.path.islink(__file):
511 if not PlatformInfo.has_salome or \
512 not PlatformInfo.has_adao:
514 "Unable to get SALOME or ADAO environnement for YACS conversion.\n"+\
515 "Please load the right SALOME environnement before trying to use it.")
517 from daYacsSchemaCreator.run import create_schema_from_content
519 self.__internalSCD._finalize(__upa)
520 __SCDdump = self.__internalSCD.dump()
521 create_schema_from_content(__SCDdump, __file)
523 if not os.path.exists(__file):
524 __msg = "An error occured during the ADAO YACS Schema build for\n"
525 __msg += "the target output file:\n"
526 __msg += " %s\n"%__file
527 __msg += "See errors details in your launching terminal log.\n"
528 raise ValueError(__msg)
530 __fid = open(__file,"r")
531 __text = __fid.read()
535 # ==============================================================================
536 class ImportFromScript(object):
538 Obtention d'une variable nommee depuis un fichier script importé
540 __slots__ = ("__basename", "__filenspace", "__filestring")
541 def __init__(self, __filename=None):
542 "Verifie l'existence et importe le script"
543 if __filename is None:
544 raise ValueError("The name of the file, containing the variable to be read, has to be specified.")
545 if not os.path.isfile(__filename):
546 raise ValueError("The file containing the variable to be imported doesn't seem to exist. Please check the file. The given file name is:\n \"%s\""%str(__filename))
547 if os.path.dirname(__filename) != '':
548 sys.path.insert(0, os.path.dirname(__filename))
549 __basename = os.path.basename(__filename).rstrip(".py")
551 __basename = __filename.rstrip(".py")
552 PlatformInfo.checkFileNameImportability( __basename+".py" )
553 self.__basename = __basename
554 self.__filenspace = __import__(__basename, globals(), locals(), [])
555 self.__filestring = open(__filename,'r').read()
556 def getvalue(self, __varname=None, __synonym=None ):
557 "Renvoie la variable demandee par son nom ou son synonyme"
558 if __varname is None:
559 raise ValueError("The name of the variable to be read has to be specified. Please check the content of the file and the syntax.")
560 if not hasattr(self.__filenspace, __varname):
561 if __synonym is None:
562 raise ValueError("The imported script file \"%s\" doesn't contain the mandatory variable \"%s\" to be read. Please check the content of the file and the syntax."%(str(self.__basename)+".py",__varname))
563 elif not hasattr(self.__filenspace, __synonym):
564 raise ValueError("The imported script file \"%s\" doesn't contain the mandatory variable \"%s\" to be read. Please check the content of the file and the syntax."%(str(self.__basename)+".py",__synonym))
566 return getattr(self.__filenspace, __synonym)
568 return getattr(self.__filenspace, __varname)
570 "Renvoie le script complet"
571 return self.__filestring
573 # ==============================================================================
574 class ImportDetector(object):
576 Détection des caractéristiques de fichiers ou objets en entrée
579 "__url", "__usr", "__root", "__end")
580 def __enter__(self): return self
581 def __exit__(self, exc_type, exc_val, exc_tb): return False
583 def __init__(self, __url, UserMime=""):
585 raise ValueError("The name or url of the file object has to be specified.")
587 self.__url = __url.decode()
589 self.__url = str(__url)
590 if UserMime is bytes:
591 self.__usr = UserMime.decode().lower()
593 self.__usr = str(UserMime).lower()
594 (self.__root, self.__end) = os.path.splitext(self.__url)
596 mimetypes.add_type('application/numpy.npy', '.npy')
597 mimetypes.add_type('application/numpy.npz', '.npz')
598 mimetypes.add_type('application/dymola.sdf', '.sdf')
599 if sys.platform.startswith("win"):
600 mimetypes.add_type('text/plain', '.txt')
601 mimetypes.add_type('text/csv', '.csv')
602 mimetypes.add_type('text/tab-separated-values', '.tsv')
606 def is_local_file(self):
607 if os.path.isfile(os.path.realpath(self.__url)):
611 def is_not_local_file(self):
612 if not os.path.isfile(os.path.realpath(self.__url)):
616 def raise_error_if_not_local_file(self):
617 if not os.path.isfile(os.path.realpath(self.__url)):
618 raise ValueError("The name or the url of the file object doesn't seem to exist. The given name is:\n \"%s\""%str(self.__url))
622 # Directory related tests
623 # -----------------------
624 def is_local_dir(self):
625 if os.path.isdir(self.__url):
629 def is_not_local_dir(self):
630 if not os.path.isdir(self.__url):
634 def raise_error_if_not_local_dir(self):
635 if not os.path.isdir(self.__url):
636 raise ValueError("The name or the url of the directory object doesn't seem to exist. The given name is:\n \"%s\""%str(self.__url))
640 # Mime related functions
641 # ------------------------
642 def get_standard_mime(self):
643 (__mtype, __encoding) = mimetypes.guess_type(self.__url, strict=False)
645 def get_user_mime(self):
646 __fake = "fake."+self.__usr.lower()
647 (__mtype, __encoding) = mimetypes.guess_type(__fake, strict=False)
649 def get_comprehensive_mime(self):
650 if self.get_standard_mime() is not None:
651 return self.get_standard_mime()
652 elif self.get_user_mime() is not None:
653 return self.get_user_mime()
657 # Name related functions
658 # ----------------------
659 def get_user_name(self):
661 def get_absolute_name(self):
662 return os.path.abspath(os.path.realpath(self.__url))
663 def get_extension(self):
666 class ImportFromFile(object):
668 Obtention de variables disrétisées en 1D, définies par une ou des variables
669 nommées, et sous la forme d'une série de points éventuellement indexés. La
670 lecture d'un fichier au format spécifié (ou intuité) permet de charger ces
672 - des fichiers textes en colonnes de type TXT, CSV, TSV...
673 - des fichiers de données binaires NPY, NPZ, SDF...
674 La lecture du fichier complet ne se fait que si nécessaire, pour assurer la
675 performance tout en disposant de l'interprétation du contenu. Les fichiers
676 textes doivent présenter en première ligne (hors commentaire ou ligne vide)
677 les noms des variables de colonnes. Les commentaires commencent par un "#".
680 "_filename", "_colnames", "_colindex", "_varsline", "_format",
681 "_delimiter", "_skiprows", "__url", "__filestring", "__header",
682 "__allowvoid", "__binaryformats", "__supportedformats")
683 def __enter__(self): return self
684 def __exit__(self, exc_type, exc_val, exc_tb): return False
686 def __init__(self, Filename=None, ColNames=None, ColIndex=None, Format="Guess", AllowVoidNameList=True):
688 Verifie l'existence et les informations de définition du fichier. Les
689 noms de colonnes ou de variables sont ignorées si le format ne permet
692 - Filename : nom du fichier
693 - ColNames : noms de la ou des colonnes/variables à lire
694 - ColIndex : nom unique de la colonne/variable servant d'index
695 - Format : format du fichier et/ou des données inclues
696 - AllowVoidNameList : permet, si la liste de noms est vide, de
697 prendre par défaut toutes les colonnes
699 self.__binaryformats =(
700 "application/numpy.npy",
701 "application/numpy.npz",
702 "application/dymola.sdf",
704 self.__url = ImportDetector( Filename, Format)
705 self.__url.raise_error_if_not_local_file()
706 self._filename = self.__url.get_absolute_name()
707 PlatformInfo.checkFileNameConformity( self._filename )
709 self._format = self.__url.get_comprehensive_mime()
711 self.__header, self._varsline, self._skiprows = self.__getentete()
713 if self._format == "text/csv" or Format.upper() == "CSV":
714 self._format = "text/csv"
715 self.__filestring = "".join(self.__header)
716 if self.__filestring.count(",") > 1:
717 self._delimiter = ","
718 elif self.__filestring.count(";") > 1:
719 self._delimiter = ";"
721 self._delimiter = None
722 elif self._format == "text/tab-separated-values" or Format.upper() == "TSV":
723 self._format = "text/tab-separated-values"
724 self._delimiter = "\t"
726 self._delimiter = None
728 if ColNames is not None: self._colnames = tuple(ColNames)
729 else: self._colnames = None
731 if ColIndex is not None: self._colindex = str(ColIndex)
732 else: self._colindex = None
734 self.__allowvoid = bool(AllowVoidNameList)
736 def __getentete(self, __nblines = 3):
737 "Lit l'entête du fichier pour trouver la définition des variables"
738 # La première ligne non vide non commentée est toujours considérée
739 # porter les labels de colonne, donc pas des valeurs
740 __header, __varsline, __skiprows = [], "", 1
741 if self._format in self.__binaryformats:
744 with open(self._filename,'r') as fid:
745 __line = fid.readline().strip()
746 while "#" in __line or len(__line) < 1:
747 __header.append(__line)
749 __line = fid.readline().strip()
751 for i in range(max(0,__nblines)):
752 __header.append(fid.readline())
753 return (__header, __varsline, __skiprows)
755 def __getindices(self, __colnames, __colindex, __delimiter=None ):
756 "Indices de colonnes correspondants à l'index et aux variables"
757 if __delimiter is None:
758 __varserie = self._varsline.strip('#').strip().split()
760 __varserie = self._varsline.strip('#').strip().split(str(__delimiter))
762 if __colnames is not None:
764 __colnames = tuple(__colnames)
766 for i, n in enumerate(__varserie):
767 if v == n: __usecols.append(i)
768 __usecols = tuple(__usecols)
769 if len(__usecols) == 0:
773 raise ValueError("Can not found any column corresponding to the required names %s"%(__colnames,))
777 if __colindex is not None:
779 __colindex = str(__colindex)
780 for i, n in enumerate(__varserie):
781 if __colindex == n: __useindex = i
785 return (__usecols, __useindex)
787 def getsupported(self):
788 self.__supportedformats = {}
789 self.__supportedformats["text/plain"] = True
790 self.__supportedformats["text/csv"] = True
791 self.__supportedformats["text/tab-separated-values"] = True
792 self.__supportedformats["application/numpy.npy"] = True
793 self.__supportedformats["application/numpy.npz"] = True
794 self.__supportedformats["application/dymola.sdf"] = PlatformInfo.has_sdf
795 return self.__supportedformats
797 def getvalue(self, ColNames=None, ColIndex=None ):
798 "Renvoie la ou les variables demandees par la liste de leurs noms"
799 # Uniquement si mise à jour
800 if ColNames is not None: self._colnames = tuple(ColNames)
801 if ColIndex is not None: self._colindex = str(ColIndex)
804 if self._format == "application/numpy.npy":
805 __columns = numpy.load(self._filename)
807 elif self._format == "application/numpy.npz":
809 with numpy.load(self._filename) as __allcolumns:
810 if self._colnames is None:
811 self._colnames = __allcolumns.files
812 for nom in self._colnames: # Si une variable demandée n'existe pas
813 if nom not in __allcolumns.files:
814 self._colnames = tuple( __allcolumns.files )
815 for nom in self._colnames:
816 if nom in __allcolumns.files:
817 if __columns is not None:
818 # Attention : toutes les variables doivent avoir la même taille
819 __columns = numpy.vstack((__columns, numpy.reshape(__allcolumns[nom], (1,-1))))
822 __columns = numpy.reshape(__allcolumns[nom], (1,-1))
823 if self._colindex is not None and self._colindex in __allcolumns.files:
824 __index = numpy.array(numpy.reshape(__allcolumns[self._colindex], (1,-1)), dtype=bytes)
825 elif self._format == "text/plain":
826 __usecols, __useindex = self.__getindices(self._colnames, self._colindex)
827 __columns = numpy.loadtxt(self._filename, usecols = __usecols, skiprows=self._skiprows)
828 if __useindex is not None:
829 __index = numpy.loadtxt(self._filename, dtype = bytes, usecols = (__useindex,), skiprows=self._skiprows)
830 if __usecols is None: # Si une variable demandée n'existe pas
831 self._colnames = None
833 elif self._format == "application/dymola.sdf" and PlatformInfo.has_sdf:
835 __content = sdf.load(self._filename)
837 if self._colnames is None:
838 self._colnames = [__content.datasets[i].name for i in range(len(__content.datasets))]
839 for nom in self._colnames:
841 if __columns is not None:
842 # Attention : toutes les variables doivent avoir la même taille
843 __columns = numpy.vstack((__columns, numpy.reshape(__content[nom].data, (1,-1))))
846 __columns = numpy.reshape(__content[nom].data, (1,-1))
847 if self._colindex is not None and self._colindex in __content:
848 __index = __content[self._colindex].data
850 elif self._format == "text/csv":
851 __usecols, __useindex = self.__getindices(self._colnames, self._colindex, self._delimiter)
852 __columns = numpy.loadtxt(self._filename, usecols = __usecols, delimiter = self._delimiter, skiprows=self._skiprows)
853 if __useindex is not None:
854 __index = numpy.loadtxt(self._filename, dtype = bytes, usecols = (__useindex,), delimiter = self._delimiter, skiprows=self._skiprows)
855 if __usecols is None: # Si une variable demandée n'existe pas
856 self._colnames = None
858 elif self._format == "text/tab-separated-values":
859 __usecols, __useindex = self.__getindices(self._colnames, self._colindex, self._delimiter)
860 __columns = numpy.loadtxt(self._filename, usecols = __usecols, delimiter = self._delimiter, skiprows=self._skiprows)
861 if __useindex is not None:
862 __index = numpy.loadtxt(self._filename, dtype = bytes, usecols = (__useindex,), delimiter = self._delimiter, skiprows=self._skiprows)
863 if __usecols is None: # Si une variable demandée n'existe pas
864 self._colnames = None
866 raise ValueError("Unkown file format \"%s\" or no reader available"%self._format)
867 if __columns is None: __columns = ()
871 return value.decode()
874 if __index is not None:
875 __index = tuple([toString(v) for v in __index])
877 return (self._colnames, __columns, self._colindex, __index)
880 "Renvoie le fichier texte complet"
881 if self._format in self.__binaryformats:
884 with open(self._filename,'r') as fid:
890 class ImportScalarLinesFromFile(ImportFromFile):
892 Importation de fichier contenant des variables scalaires nommées. Le
893 fichier comporte soit 2, soit 4 colonnes, obligatoirement nommées "Name",
894 "Value", "Minimum", "Maximum" si les noms sont précisés. Sur chaque ligne
895 est indiqué le nom, la valeur, et éventuelement deux bornes min et max (ou
896 None si nécessaire pour une borne).
898 Seule la méthode "getvalue" est changée.
900 def __enter__(self): return self
901 def __exit__(self, exc_type, exc_val, exc_tb): return False
903 def __init__(self, Filename=None, ColNames=None, ColIndex=None, Format="Guess"):
904 ImportFromFile.__init__(self, Filename, ColNames, ColIndex, Format)
905 if self._format not in ["text/plain", "text/csv", "text/tab-separated-values"]:
906 raise ValueError("Unkown file format \"%s\""%self._format)
908 def getvalue(self, VarNames = None, HeaderNames=()):
909 "Renvoie la ou les variables demandees par la liste de leurs noms"
910 if VarNames is not None: __varnames = tuple(VarNames)
911 else: __varnames = None
913 if "Name" in self._varsline and "Value" in self._varsline and "Minimum" in self._varsline and "Maximum" in self._varsline:
914 __ftype = "NamValMinMax"
915 __dtypes = {'names' : ('Name', 'Value', 'Minimum', 'Maximum'),
916 'formats': ('S128', 'g', 'g', 'g')}
917 __usecols = (0, 1, 2, 3)
918 def __replaceNoneN( s ):
919 if s.strip() == b'None': return numpy.NINF
921 def __replaceNoneP( s ):
922 if s.strip() == b'None': return numpy.PINF
924 __converters = {2: __replaceNoneN, 3: __replaceNoneP}
925 elif "Name" in self._varsline and "Value" in self._varsline and ("Minimum" not in self._varsline or "Maximum" not in self._varsline):
927 __dtypes = {'names' : ('Name', 'Value'),
928 'formats': ('S128', 'g')}
931 elif len(HeaderNames)>0 and numpy.all([kw in self._varsline for kw in HeaderNames]):
932 __ftype = "NamLotOfVals"
933 __dtypes = {'names' : HeaderNames,
934 'formats': tuple(['S128',]+['g']*(len(HeaderNames)-1))}
935 __usecols = tuple(range(len(HeaderNames)))
936 def __replaceNone( s ):
937 if s.strip() == b'None': return numpy.NAN
939 __converters = dict()
940 for i in range(1,len(HeaderNames)):
941 __converters[i] = __replaceNone
943 raise ValueError("Can not find names of columns for initial values. Wrong first line is:\n \"%s\""%__firstline)
945 if self._format == "text/plain":
946 __content = numpy.loadtxt(self._filename, dtype = __dtypes, usecols = __usecols, skiprows = self._skiprows, converters = __converters)
947 elif self._format in ["text/csv", "text/tab-separated-values"]:
948 __content = numpy.loadtxt(self._filename, dtype = __dtypes, usecols = __usecols, skiprows = self._skiprows, converters = __converters, delimiter = self._delimiter)
950 raise ValueError("Unkown file format \"%s\""%self._format)
952 __names, __thevalue, __bounds = [], [], []
953 for sub in __content:
954 if len(__usecols) == 4:
956 if numpy.isneginf(mi): mi = None # Réattribue les variables None
957 elif numpy.isnan(mi): mi = None # Réattribue les variables None
958 if numpy.isposinf(ma): ma = None # Réattribue les variables None
959 elif numpy.isnan(ma): ma = None # Réattribue les variables None
960 elif len(__usecols) == 2 and __ftype == "NamVal":
966 for i, v in enumerate(nsub[1:]):
967 if numpy.isnan(v): nsub[i+1] = None
971 if (__varnames is None or na in __varnames) and (na not in __names):
972 # Ne stocke que la premiere occurence d'une variable
974 __thevalue.append(va)
975 __bounds.append((mi,ma))
977 __names = tuple(__names)
978 __thevalue = numpy.array(__thevalue)
979 __bounds = tuple(__bounds)
981 return (__names, __thevalue, __bounds)
983 # ==============================================================================
984 class EficasGUI(object):
986 Lancement autonome de l'interface EFICAS/ADAO
988 def __init__(self, __addpath = None):
989 # Chemin pour l'installation (ordre important)
991 self.__path_settings_ok = False
993 if "EFICAS_ROOT" in os.environ:
994 __EFICAS_ROOT = os.environ["EFICAS_ROOT"]
997 self.__msg += "\nKeyError:\n"+\
998 " the required environment variable EFICAS_ROOT is unknown.\n"+\
999 " You have either to be in SALOME environment, or to set\n"+\
1000 " this variable in your environment to the right path \"<...>\"\n"+\
1001 " to find an installed EFICAS application. For example:\n"+\
1002 " EFICAS_ROOT=\"<...>\" command\n"
1006 __path_ok = True and __path_ok
1008 self.__msg += "\nImportError:\n"+\
1009 " the required ADAO library can not be found to be imported.\n"+\
1010 " You have either to be in ADAO environment, or to be in SALOME\n"+\
1011 " environment, or to set manually in your Python 3 environment the\n"+\
1012 " right path \"<...>\" to find an installed ADAO application. For\n"+\
1014 " PYTHONPATH=\"<...>:${PYTHONPATH}\" command\n"
1018 __path_ok = True and __path_ok
1020 self.__msg += "\nImportError:\n"+\
1021 " the required PyQt5 library can not be found to be imported.\n"+\
1022 " You have either to have a raisonable up-to-date Python 3\n"+\
1023 " installation (less than 5 years), or to be in SALOME environment.\n"
1027 self.__msg += "\nWarning:\n"+\
1028 " It seems you have some troubles with your installation.\n"+\
1029 " Be aware that some other errors may exist, that are not\n"+\
1030 " explained as above, like some incomplete or obsolete\n"+\
1031 " Python 3, or incomplete module installation.\n"+\
1033 " Please correct the above error(s) before launching the\n"+\
1034 " standalone EFICAS/ADAO interface.\n"
1035 logging.debug("Some of the ADAO/EFICAS/QT5 paths have not been found")
1036 self.__path_settings_ok = False
1038 logging.debug("All the ADAO/EFICAS/QT5 paths have been found")
1039 self.__path_settings_ok = True
1041 if self.__path_settings_ok:
1042 sys.path.insert(0,__EFICAS_ROOT)
1043 sys.path.insert(0,os.path.join(adao.adao_py_dir,"daEficas"))
1044 if __addpath is not None and os.path.exists(os.path.abspath(__addpath)):
1045 sys.path.insert(0,os.path.abspath(__addpath))
1046 logging.debug("All the paths have been correctly set up")
1049 logging.debug("Errors in path settings have been found")
1052 if self.__path_settings_ok:
1053 logging.debug("Launching standalone EFICAS/ADAO interface...")
1054 from daEficas import prefs
1055 from InterfaceQT4 import eficas_go
1056 eficas_go.lanceEficas(code=prefs.code)
1058 logging.debug("Can not launch standalone EFICAS/ADAO interface for path errors.")
1060 # ==============================================================================
1061 if __name__ == "__main__":
1062 print('\n AUTODIAGNOSTIC\n')