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 creation 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 de commande individuelle en enregistrement"
56 raise NotImplementedError()
57 def _extract(self, *args):
58 "Transformation d'enregistrement en commande individuelle"
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 Etablissement 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:
113 if __pre is not None:
114 __text += "%s = "%__pre
115 __text += "%s.%s( "%(self._objname,str(__command))
116 if "self" in __keys: __keys.remove("self")
117 if __command not in ("set","get") and "Concept" in __keys: __keys.remove("Concept")
120 if __v is None: continue
121 if k == "Checked" and not __v: continue
122 if k == "Stored" and not __v: continue
123 if k == "ColMajor" and not __v: continue
124 if k == "InputFunctionAsMulti" and not __v: continue
125 if k == "nextStep" and not __v: continue
126 if k == "AvoidRC" and __v: continue
127 if k == "noDetails": continue
128 if isinstance(__v,Persistence.Persistence): __v = __v.values()
129 if callable(__v): __text = self._missing%__v.__name__+__text
130 if isinstance(__v,dict):
131 for val in __v.values():
132 if callable(val): __text = self._missing%val.__name__+__text
133 numpy.set_printoptions(precision=15,threshold=1000000,linewidth=1000*15)
134 __text += "%s=%s, "%(k,repr(__v))
135 numpy.set_printoptions(precision=8,threshold=1000,linewidth=75)
138 self._addLine(__text)
139 def _extract(self, __multilines="", __object=None):
140 "Transformation un enregistrement en une commande individuelle"
143 __multilines = __multilines.replace("\r\n","\n")
144 for line in __multilines.split("\n"):
145 if "adaoBuilder.New" in line and "=" in line:
146 self._objname = line.split("=")[0].strip()
148 logging.debug("TUI Extracting commands of '%s' object..."%(self._objname,))
152 if self._objname+".set" in line:
153 __commands.append( line.replace(self._objname+".","",1) )
154 logging.debug("TUI Extracted command: %s"%(__commands[-1],))
157 class _COMViewer(GenericCaseViewer):
159 Etablissement des commandes d'un cas COMM (Eficas Native Format/Cas<-COM)
161 def __init__(self, __name="", __objname="case", __content=None, __object=None):
162 "Initialisation et enregistrement de l'entete"
163 GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
164 self._observerIndex = 0
165 self._addLine("# -*- coding: utf-8 -*-")
166 self._addLine("#\n# Python script using ADAO COMM\n#")
167 self._addLine("from numpy import array, matrix")
169 self._addLine("%s = {}"%__objname)
170 if self._content is not None:
171 for command in self._content:
172 self._append(*command)
173 def _extract(self, __multilines=None, __object=None):
174 "Transformation un enregistrement en une commande individuelle"
175 if __multilines is not None:
176 __multilines = __multilines.replace("ASSIMILATION_STUDY","dict")
177 __multilines = __multilines.replace("CHECKING_STUDY", "dict")
178 __multilines = __multilines.replace("_F(", "dict(")
179 __multilines = __multilines.replace(",),);", ",),)")
181 for line in __multilines.split("\n"):
182 if len(line) < 1: continue
183 __fulllines += line + "\n"
184 __multilines = __fulllines
185 self._objname = "case"
187 exec("self._objdata = "+__multilines)
189 if self._objdata is None or not(type(self._objdata) is dict) or not('AlgorithmParameters' in self._objdata):
190 raise ValueError("Impossible to load given content as an ADAO COMM one (no dictionnary or no 'AlgorithmParameters' key found).")
191 # ----------------------------------------------------------------------
192 logging.debug("COMM Extracting commands of '%s' object..."%(self._objname,))
194 __UserPostAnalysis = ""
195 for k,r in self._objdata.items():
197 logging.debug("COMM Extracted command: %s:%s"%(k, r))
198 if __command == "StudyName" and len(str(r))>0:
199 __commands.append( "set( Concept='Name', String='%s')"%(str(r),) )
200 elif __command == "StudyRepertory":
201 __commands.append( "set( Concept='Directory', String='%s')"%(str(r),) )
203 elif __command == "UserPostAnalysis" and type(r) is dict:
205 __UserPostAnalysis = r['STRING']
206 elif 'SCRIPT_FILE' in r and os.path.exists(r['SCRIPT_FILE']):
207 __UserPostAnalysis = open(r['SCRIPT_FILE'],'r').read()
208 elif 'Template' in r and 'ValueTemplate' in r:
210 __UserPostAnalysis = r['ValueTemplate']
212 __UserPostAnalysis = ""
213 __UserPostAnalysis = __UserPostAnalysis.replace("ADD",self._objname)
215 elif __command == "AlgorithmParameters" and type(r) is dict and 'Algorithm' in r:
216 if 'data' in r and r['Parameters'] == 'Dict':
218 if 'STRING' in __from:
219 __parameters = ", Parameters=%s"%(repr(eval(__from['STRING'])),)
220 elif 'SCRIPT_FILE' in __from and os.path.exists(__from['SCRIPT_FILE']):
221 __parameters = ", Script='%s'"%(__from['SCRIPT_FILE'],)
222 else: # if 'Parameters' in r and r['Parameters'] == 'Defaults':
223 __Dict = copy.deepcopy(r)
224 __Dict.pop('Algorithm','')
225 __Dict.pop('Parameters','')
226 if 'SetSeed' in __Dict:__Dict['SetSeed'] = int(__Dict['SetSeed'])
227 if 'BoxBounds' in __Dict and type(__Dict['BoxBounds']) is str:
228 __Dict['BoxBounds'] = eval(__Dict['BoxBounds'])
230 __parameters = ', Parameters=%s'%(repr(__Dict),)
233 __commands.append( "set( Concept='AlgorithmParameters', Algorithm='%s'%s )"%(r['Algorithm'],__parameters) )
235 elif __command == "Observers" and type(r) is dict and 'SELECTION' in r:
236 if type(r['SELECTION']) is str:
237 __selection = (r['SELECTION'],)
239 __selection = tuple(r['SELECTION'])
240 for sk in __selection:
241 __idata = r['%s_data'%sk]
242 if __idata['NodeType'] == 'Template' and 'Template' in __idata:
243 __template = __idata['Template']
244 if 'Info' in __idata:
245 __info = ", Info='%s'"%(__idata['Info'],)
248 __commands.append( "set( Concept='Observer', Variable='%s', Template='%s'%s )"%(sk,__template,__info) )
249 if __idata['NodeType'] == 'String' and 'Value' in __idata:
250 __value =__idata['Value']
251 __commands.append( "set( Concept='Observer', Variable='%s', String='%s' )"%(sk,__value) )
253 # Background, ObservationError, ObservationOperator...
254 elif type(r) is dict:
256 if 'Stored' in r and bool(r['Stored']):
257 __argumentsList.append(['Stored',True])
258 if 'INPUT_TYPE' in r and 'data' in r:
259 # Vector, Matrix, ScalarSparseMatrix, DiagonalSparseMatrix, Function
260 __itype = r['INPUT_TYPE']
262 if 'FROM' in __idata:
263 # String, Script, DataFile, Template, ScriptWithOneFunction, ScriptWithFunctions
264 __ifrom = __idata['FROM']
265 __idata.pop('FROM','')
266 if __ifrom == 'String' or __ifrom == 'Template':
267 __argumentsList.append([__itype,__idata['STRING']])
268 if __ifrom == 'Script':
269 __argumentsList.append([__itype,True])
270 __argumentsList.append(['Script',__idata['SCRIPT_FILE']])
271 if __ifrom == 'DataFile':
272 __argumentsList.append([__itype,True])
273 __argumentsList.append(['DataFile',__idata['DATA_FILE']])
274 if __ifrom == 'ScriptWithOneFunction':
275 __argumentsList.append(['OneFunction',True])
276 __argumentsList.append(['Script',__idata.pop('SCRIPTWITHONEFUNCTION_FILE')])
278 __argumentsList.append(['Parameters',__idata])
279 if __ifrom == 'ScriptWithFunctions':
280 __argumentsList.append(['ThreeFunctions',True])
281 __argumentsList.append(['Script',__idata.pop('SCRIPTWITHFUNCTIONS_FILE')])
283 __argumentsList.append(['Parameters',__idata])
284 __arguments = ["%s = %s"%(k,repr(v)) for k,v in __argumentsList]
285 __commands.append( "set( Concept='%s', %s )"%(__command, ", ".join(__arguments)))
287 # ----------------------------------------------------------------------
288 __commands.sort() # Pour commencer par 'AlgorithmParameters'
289 __commands.append(__UserPostAnalysis)
292 class _SCDViewer(GenericCaseViewer):
294 Etablissement des commandes d'un cas SCD (Study Config Dictionary/Cas->SCD)
296 def __init__(self, __name="", __objname="case", __content=None, __object=None):
297 "Initialisation et enregistrement de l'entete"
298 GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
299 self._addLine("# -*- coding: utf-8 -*-")
300 self._addLine("#\n# Input for ADAO converter to YACS\n#")
301 self._addLine("from numpy import array, matrix")
303 self._addLine("study_config = {}")
304 self._addLine("study_config['StudyType'] = 'ASSIMILATION_STUDY'")
305 self._addLine("study_config['Name'] = '%s'"%self._name)
306 self._addLine("observers = {}")
307 self._addLine("study_config['Observers'] = observers")
309 self._addLine("inputvariables_config = {}")
310 self._addLine("inputvariables_config['Order'] =['adao_default']")
311 self._addLine("inputvariables_config['adao_default'] = -1")
312 self._addLine("study_config['InputVariables'] = inputvariables_config")
314 self._addLine("outputvariables_config = {}")
315 self._addLine("outputvariables_config['Order'] = ['adao_default']")
316 self._addLine("outputvariables_config['adao_default'] = -1")
317 self._addLine("study_config['OutputVariables'] = outputvariables_config")
318 if __content is not None:
319 for command in __content:
320 self._append(*command)
321 def _append(self, __command=None, __keys=None, __local=None, __pre=None, __switchoff=False):
322 "Transformation d'une commande individuelle en un enregistrement"
323 if __command == "set": __command = __local["Concept"]
324 else: __command = __command.replace("set", "", 1)
327 if __command in (None, 'execute', 'executePythonScheme', 'executeYACSScheme', 'get', 'Name'):
329 elif __command in ['Debug', 'setDebug']:
330 __text = "#\nstudy_config['Debug'] = '1'"
331 elif __command in ['NoDebug', 'setNoDebug']:
332 __text = "#\nstudy_config['Debug'] = '0'"
333 elif __command in ['Observer', 'setObserver']:
334 __obs = __local['Variable']
335 self._numobservers += 1
337 __text += "observers['%s'] = {}\n"%__obs
338 if __local['String'] is not None:
339 __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'String')
340 __text += "observers['%s']['String'] = \"\"\"%s\"\"\"\n"%(__obs, __local['String'])
341 if __local['Script'] is not None:
342 __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'Script')
343 __text += "observers['%s']['Script'] = \"%s\"\n"%(__obs, __local['Script'])
344 if __local['Template'] is not None and __local['Template'] in Templates.ObserverTemplates:
345 __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'String')
346 __text += "observers['%s']['String'] = \"\"\"%s\"\"\"\n"%(__obs, Templates.ObserverTemplates[__local['Template']])
347 if __local['Info'] is not None:
348 __text += "observers['%s']['info'] = \"\"\"%s\"\"\"\n"%(__obs, __local['Info'])
350 __text += "observers['%s']['info'] = \"\"\"%s\"\"\"\n"%(__obs, __obs)
351 __text += "observers['%s']['number'] = %s"%(__obs, self._numobservers)
352 elif __local is not None: # __keys is not None and
353 numpy.set_printoptions(precision=15,threshold=1000000,linewidth=1000*15)
355 __text += "%s_config = {}\n"%__command
356 __local.pop('self','')
358 for __k,__v in __local.items():
359 if __v is None: __to_be_removed.append(__k)
360 for __k in __to_be_removed:
362 for __k,__v in __local.items():
363 if __k == "Concept": continue
364 if __k in ['ScalarSparseMatrix','DiagonalSparseMatrix','Matrix','OneFunction','ThreeFunctions'] and 'Script' in __local and __local['Script'] is not None: continue
365 if __k in ['Vector','VectorSerie'] and 'DataFile' in __local and __local['DataFile'] is not None: continue
366 if __k == 'Algorithm':
367 __text += "study_config['Algorithm'] = %s\n"%(repr(__v))
368 elif __k == 'DataFile':
371 __v = "'"+repr(__v)+"'"
372 for __lk in ['Vector','VectorSerie']:
373 if __lk in __local and __local[__lk]: __k = __lk
374 __text += "%s_config['Type'] = '%s'\n"%(__command,__k)
375 __text += "%s_config['From'] = '%s'\n"%(__command,__f)
376 __text += "%s_config['Data'] = %s\n"%(__command,__v)
377 __text = __text.replace("''","'")
378 elif __k == 'Script':
381 __v = "'"+repr(__v)+"'"
382 for __lk in ['ScalarSparseMatrix','DiagonalSparseMatrix','Matrix']:
383 if __lk in __local and __local[__lk]: __k = __lk
384 if __command == "AlgorithmParameters": __k = "Dict"
385 if 'OneFunction' in __local and __local['OneFunction']:
386 __text += "%s_ScriptWithOneFunction = {}\n"%(__command,)
387 __text += "%s_ScriptWithOneFunction['Function'] = ['Direct', 'Tangent', 'Adjoint']\n"%(__command,)
388 __text += "%s_ScriptWithOneFunction['Script'] = {}\n"%(__command,)
389 __text += "%s_ScriptWithOneFunction['Script']['Direct'] = %s\n"%(__command,__v)
390 __text += "%s_ScriptWithOneFunction['Script']['Tangent'] = %s\n"%(__command,__v)
391 __text += "%s_ScriptWithOneFunction['Script']['Adjoint'] = %s\n"%(__command,__v)
392 __text += "%s_ScriptWithOneFunction['DifferentialIncrement'] = 1e-06\n"%(__command,)
393 __text += "%s_ScriptWithOneFunction['CenteredFiniteDifference'] = 0\n"%(__command,)
395 __f = 'ScriptWithOneFunction'
396 __v = '%s_ScriptWithOneFunction'%(__command,)
397 if 'ThreeFunctions' in __local and __local['ThreeFunctions']:
398 __text += "%s_ScriptWithFunctions = {}\n"%(__command,)
399 __text += "%s_ScriptWithFunctions['Function'] = ['Direct', 'Tangent', 'Adjoint']\n"%(__command,)
400 __text += "%s_ScriptWithFunctions['Script'] = {}\n"%(__command,)
401 __text += "%s_ScriptWithFunctions['Script']['Direct'] = %s\n"%(__command,__v)
402 __text += "%s_ScriptWithFunctions['Script']['Tangent'] = %s\n"%(__command,__v)
403 __text += "%s_ScriptWithFunctions['Script']['Adjoint'] = %s\n"%(__command,__v)
405 __f = 'ScriptWithFunctions'
406 __v = '%s_ScriptWithFunctions'%(__command,)
407 __text += "%s_config['Type'] = '%s'\n"%(__command,__k)
408 __text += "%s_config['From'] = '%s'\n"%(__command,__f)
409 __text += "%s_config['Data'] = %s\n"%(__command,__v)
410 __text = __text.replace("''","'")
411 elif __k in ('Stored', 'Checked', 'ColMajor', 'InputFunctionAsMulti', 'nextStep'):
413 __text += "%s_config['%s'] = '%s'\n"%(__command,__k,int(bool(__v)))
414 elif __k in ('AvoidRC', 'noDetails'):
416 __text += "%s_config['%s'] = '%s'\n"%(__command,__k,int(bool(__v)))
418 if __k == 'Parameters': __k = "Dict"
419 if isinstance(__v,Persistence.Persistence): __v = __v.values()
420 if callable(__v): __text = self._missing%__v.__name__+__text
421 if isinstance(__v,dict):
422 for val in __v.values():
423 if callable(val): __text = self._missing%val.__name__+__text
424 __text += "%s_config['Type'] = '%s'\n"%(__command,__k)
425 __text += "%s_config['From'] = '%s'\n"%(__command,'String')
426 __text += "%s_config['Data'] = \"\"\"%s\"\"\"\n"%(__command,repr(__v))
427 __text += "study_config['%s'] = %s_config"%(__command,__command)
428 numpy.set_printoptions(precision=8,threshold=1000,linewidth=75)
430 self._switchoff = True
431 if __text is not None: self._addLine(__text)
433 self._switchoff = False
434 def _finalize(self, *__args):
435 self.__loadVariablesByScript()
437 self._addLine("Analysis_config = {}")
438 self._addLine("Analysis_config['From'] = 'String'")
439 self._addLine("Analysis_config['Data'] = \"\"\"import numpy")
440 self._addLine("xa=numpy.ravel(ADD.get('Analysis')[-1])")
441 self._addLine("print('Analysis:',xa)\"\"\"")
442 self._addLine("study_config['UserPostAnalysis'] = Analysis_config")
443 def __loadVariablesByScript(self):
444 __ExecVariables = {} # Necessaire pour recuperer la variable
445 exec("\n".join(self._lineSerie), __ExecVariables)
446 study_config = __ExecVariables['study_config']
447 # Pour Python 3 : self.__hasAlgorithm = bool(study_config['Algorithm'])
448 if 'Algorithm' in study_config:
449 self.__hasAlgorithm = True
451 self.__hasAlgorithm = False
452 if not self.__hasAlgorithm and \
453 "AlgorithmParameters" in study_config and \
454 isinstance(study_config['AlgorithmParameters'], dict) and \
455 "From" in study_config['AlgorithmParameters'] and \
456 "Data" in study_config['AlgorithmParameters'] and \
457 study_config['AlgorithmParameters']['From'] == 'Script':
458 __asScript = study_config['AlgorithmParameters']['Data']
459 __var = ImportFromScript(__asScript).getvalue( "Algorithm" )
460 __text = "#\nstudy_config['Algorithm'] = '%s'"%(__var,)
461 self._addLine(__text)
462 if self.__hasAlgorithm and \
463 "AlgorithmParameters" in study_config and \
464 isinstance(study_config['AlgorithmParameters'], dict) and \
465 "From" not in study_config['AlgorithmParameters'] and \
466 "Data" not in study_config['AlgorithmParameters']:
468 __text += "AlgorithmParameters_config['Type'] = 'Dict'\n"
469 __text += "AlgorithmParameters_config['From'] = 'String'\n"
470 __text += "AlgorithmParameters_config['Data'] = '{}'\n"
471 self._addLine(__text)
474 class _YACSViewer(GenericCaseViewer):
476 Etablissement des commandes d'un cas YACS (Cas->SCD->YACS)
478 def __init__(self, __name="", __objname="case", __content=None, __object=None):
479 "Initialisation et enregistrement de l'entete"
480 GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
481 self.__internalSCD = _SCDViewer(__name, __objname, __content, __object)
482 self._append = self.__internalSCD._append
483 def dump(self, __filename=None, __upa=None):
484 "Restitution normalisée des commandes"
486 if __filename is None:
487 raise ValueError("A file name has to be given for YACS XML output.")
489 __file = os.path.abspath(__filename)
490 if os.path.isfile(__file) or os.path.islink(__file):
493 if not PlatformInfo.has_salome or \
494 not PlatformInfo.has_adao:
496 "Unable to get SALOME or ADAO environnement variables for YACS conversion.\n"+\
497 "Please load the right environnement before trying to use it.")
499 from daYacsSchemaCreator.run import create_schema_from_content
501 self.__internalSCD._finalize(__upa)
502 __SCDdump = self.__internalSCD.dump()
503 create_schema_from_content(__SCDdump, __file)
505 if not os.path.exists(__file):
506 __msg = "An error occured during the ADAO YACS Schema build for\n"
507 __msg += "the target output file:\n"
508 __msg += " %s\n"%__file
509 __msg += "See errors details in your launching terminal log.\n"
510 raise ValueError(__msg)
512 __fid = open(__file,"r")
513 __text = __fid.read()
517 # ==============================================================================
518 class ImportFromScript(object):
520 Obtention d'une variable nommee depuis un fichier script importé
522 __slots__ = ("__basename", "__filenspace", "__filestring")
523 def __init__(self, __filename=None):
524 "Verifie l'existence et importe le script"
525 if __filename is None:
526 raise ValueError("The name of the file, containing the variable to be read, has to be specified.")
527 if not os.path.isfile(__filename):
528 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))
529 if os.path.dirname(__filename) != '':
530 sys.path.insert(0, os.path.dirname(__filename))
531 __basename = os.path.basename(__filename).rstrip(".py")
533 __basename = __filename.rstrip(".py")
534 PlatformInfo.checkFileNameImportability( __basename+".py" )
535 self.__basename = __basename
536 self.__filenspace = __import__(__basename, globals(), locals(), [])
537 self.__filestring = open(__filename,'r').read()
538 def getvalue(self, __varname=None, __synonym=None ):
539 "Renvoie la variable demandee par son nom ou son synonyme"
540 if __varname is None:
541 raise ValueError("The name of the variable to be read has to be specified. Please check the content of the file and the syntax.")
542 if not hasattr(self.__filenspace, __varname):
543 if __synonym is None:
544 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))
545 elif not hasattr(self.__filenspace, __synonym):
546 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))
548 return getattr(self.__filenspace, __synonym)
550 return getattr(self.__filenspace, __varname)
552 "Renvoie le script complet"
553 return self.__filestring
555 # ==============================================================================
556 class ImportDetector(object):
558 Détection des caractéristiques de fichiers ou objets en entrée
561 "__url", "__usr", "__root", "__end")
562 def __enter__(self): return self
563 def __exit__(self, exc_type, exc_val, exc_tb): return False
565 def __init__(self, __url, UserMime=""):
567 raise ValueError("The name or url of the file object has to be specified.")
569 self.__url = __url.decode()
571 self.__url = str(__url)
572 if UserMime is bytes:
573 self.__usr = UserMime.decode().lower()
575 self.__usr = str(UserMime).lower()
576 (self.__root, self.__end) = os.path.splitext(self.__url)
578 mimetypes.add_type('application/numpy.npy', '.npy')
579 mimetypes.add_type('application/numpy.npz', '.npz')
580 mimetypes.add_type('application/dymola.sdf', '.sdf')
581 if sys.platform.startswith("win"):
582 mimetypes.add_type('text/plain', '.txt')
583 mimetypes.add_type('text/csv', '.csv')
584 mimetypes.add_type('text/tab-separated-values', '.tsv')
588 def is_local_file(self):
589 if os.path.isfile(os.path.realpath(self.__url)):
593 def is_not_local_file(self):
594 if not os.path.isfile(os.path.realpath(self.__url)):
598 def raise_error_if_not_local_file(self):
599 if not os.path.isfile(os.path.realpath(self.__url)):
600 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))
604 # Directory related tests
605 # -----------------------
606 def is_local_dir(self):
607 if os.path.isdir(self.__url):
611 def is_not_local_dir(self):
612 if not os.path.isdir(self.__url):
616 def raise_error_if_not_local_dir(self):
617 if not os.path.isdir(self.__url):
618 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))
622 # Mime related functions
623 # ------------------------
624 def get_standard_mime(self):
625 (__mtype, __encoding) = mimetypes.guess_type(self.__url, strict=False)
627 def get_user_mime(self):
628 __fake = "fake."+self.__usr.lower()
629 (__mtype, __encoding) = mimetypes.guess_type(__fake, strict=False)
631 def get_comprehensive_mime(self):
632 if self.get_standard_mime() is not None:
633 return self.get_standard_mime()
634 elif self.get_user_mime() is not None:
635 return self.get_user_mime()
639 # Name related functions
640 # ----------------------
641 def get_user_name(self):
643 def get_absolute_name(self):
644 return os.path.abspath(os.path.realpath(self.__url))
645 def get_extension(self):
648 class ImportFromFile(object):
650 Obtention de variables disrétisées en 1D, définies par une ou des variables
651 nommées, et sous la forme d'une série de points éventuellement indexés. La
652 lecture d'un fichier au format spécifié (ou intuité) permet de charger ces
654 - des fichiers textes en colonnes de type TXT, CSV, TSV...
655 - des fichiers de données binaires NPY, NPZ, SDF...
656 La lecture du fichier complet ne se fait que si nécessaire, pour assurer la
657 performance tout en disposant de l'interprétation du contenu. Les fichiers
658 textes doivent présenter en première ligne (hors commentaire ou ligne vide)
659 les noms des variables de colonnes. Les commentaires commencent par un "#".
662 "_filename", "_colnames", "_colindex", "_varsline", "_format",
663 "_delimiter", "_skiprows", "__url", "__filestring", "__header",
664 "__allowvoid", "__binaryformats", "__supportedformats")
665 def __enter__(self): return self
666 def __exit__(self, exc_type, exc_val, exc_tb): return False
668 def __init__(self, Filename=None, ColNames=None, ColIndex=None, Format="Guess", AllowVoidNameList=True):
670 Verifie l'existence et les informations de définition du fichier. Les
671 noms de colonnes ou de variables sont ignorées si le format ne permet
674 - Filename : nom du fichier
675 - ColNames : noms de la ou des colonnes/variables à lire
676 - ColIndex : nom unique de la colonne/variable servant d'index
677 - Format : format du fichier et/ou des données inclues
678 - AllowVoidNameList : permet, si la liste de noms est vide, de
679 prendre par défaut toutes les colonnes
681 self.__binaryformats =(
682 "application/numpy.npy",
683 "application/numpy.npz",
684 "application/dymola.sdf",
686 self.__url = ImportDetector( Filename, Format)
687 self.__url.raise_error_if_not_local_file()
688 self._filename = self.__url.get_absolute_name()
689 PlatformInfo.checkFileNameConformity( self._filename )
691 self._format = self.__url.get_comprehensive_mime()
693 self.__header, self._varsline, self._skiprows = self.__getentete()
695 if self._format == "text/csv" or Format.upper() == "CSV":
696 self._format = "text/csv"
697 self.__filestring = "".join(self.__header)
698 if self.__filestring.count(",") > 1:
699 self._delimiter = ","
700 elif self.__filestring.count(";") > 1:
701 self._delimiter = ";"
703 self._delimiter = None
704 elif self._format == "text/tab-separated-values" or Format.upper() == "TSV":
705 self._format = "text/tab-separated-values"
706 self._delimiter = "\t"
708 self._delimiter = None
710 if ColNames is not None: self._colnames = tuple(ColNames)
711 else: self._colnames = None
713 if ColIndex is not None: self._colindex = str(ColIndex)
714 else: self._colindex = None
716 self.__allowvoid = bool(AllowVoidNameList)
718 def __getentete(self, __nblines = 3):
719 "Lit l'entête du fichier pour trouver la définition des variables"
720 # La première ligne non vide non commentée est toujours considérée
721 # porter les labels de colonne, donc pas des valeurs
722 __header, __varsline, __skiprows = [], "", 1
723 if self._format in self.__binaryformats:
726 with open(self._filename,'r') as fid:
727 __line = fid.readline().strip()
728 while "#" in __line or len(__line) < 1:
729 __header.append(__line)
731 __line = fid.readline().strip()
733 for i in range(max(0,__nblines)):
734 __header.append(fid.readline())
735 return (__header, __varsline, __skiprows)
737 def __getindices(self, __colnames, __colindex, __delimiter=None ):
738 "Indices de colonnes correspondants à l'index et aux variables"
739 if __delimiter is None:
740 __varserie = self._varsline.strip('#').strip().split()
742 __varserie = self._varsline.strip('#').strip().split(str(__delimiter))
744 if __colnames is not None:
746 __colnames = tuple(__colnames)
748 for i, n in enumerate(__varserie):
749 if v == n: __usecols.append(i)
750 __usecols = tuple(__usecols)
751 if len(__usecols) == 0:
755 raise ValueError("Can not found any column corresponding to the required names %s"%(__colnames,))
759 if __colindex is not None:
761 __colindex = str(__colindex)
762 for i, n in enumerate(__varserie):
763 if __colindex == n: __useindex = i
767 return (__usecols, __useindex)
769 def getsupported(self):
770 self.__supportedformats = {}
771 self.__supportedformats["text/plain"] = True
772 self.__supportedformats["text/csv"] = True
773 self.__supportedformats["text/tab-separated-values"] = True
774 self.__supportedformats["application/numpy.npy"] = True
775 self.__supportedformats["application/numpy.npz"] = True
776 self.__supportedformats["application/dymola.sdf"] = PlatformInfo.has_sdf
777 return self.__supportedformats
779 def getvalue(self, ColNames=None, ColIndex=None ):
780 "Renvoie la ou les variables demandees par la liste de leurs noms"
781 # Uniquement si mise à jour
782 if ColNames is not None: self._colnames = tuple(ColNames)
783 if ColIndex is not None: self._colindex = str(ColIndex)
786 if self._format == "application/numpy.npy":
787 __columns = numpy.load(self._filename)
789 elif self._format == "application/numpy.npz":
791 with numpy.load(self._filename) as __allcolumns:
792 if self._colnames is None:
793 self._colnames = __allcolumns.files
794 for nom in self._colnames: # Si une variable demandée n'existe pas
795 if nom not in __allcolumns.files:
796 self._colnames = tuple( __allcolumns.files )
797 for nom in self._colnames:
798 if nom in __allcolumns.files:
799 if __columns is not None:
800 # Attention : toutes les variables doivent avoir la même taille
801 __columns = numpy.vstack((__columns, numpy.reshape(__allcolumns[nom], (1,-1))))
804 __columns = numpy.reshape(__allcolumns[nom], (1,-1))
805 if self._colindex is not None and self._colindex in __allcolumns.files:
806 __index = numpy.array(numpy.reshape(__allcolumns[self._colindex], (1,-1)), dtype=bytes)
807 elif self._format == "text/plain":
808 __usecols, __useindex = self.__getindices(self._colnames, self._colindex)
809 __columns = numpy.loadtxt(self._filename, usecols = __usecols, skiprows=self._skiprows)
810 if __useindex is not None:
811 __index = numpy.loadtxt(self._filename, dtype = bytes, usecols = (__useindex,), skiprows=self._skiprows)
812 if __usecols is None: # Si une variable demandée n'existe pas
813 self._colnames = None
815 elif self._format == "application/dymola.sdf" and PlatformInfo.has_sdf:
817 __content = sdf.load(self._filename)
819 if self._colnames is None:
820 self._colnames = [__content.datasets[i].name for i in range(len(__content.datasets))]
821 for nom in self._colnames:
823 if __columns is not None:
824 # Attention : toutes les variables doivent avoir la même taille
825 __columns = numpy.vstack((__columns, numpy.reshape(__content[nom].data, (1,-1))))
828 __columns = numpy.reshape(__content[nom].data, (1,-1))
829 if self._colindex is not None and self._colindex in __content:
830 __index = __content[self._colindex].data
832 elif self._format == "text/csv":
833 __usecols, __useindex = self.__getindices(self._colnames, self._colindex, self._delimiter)
834 __columns = numpy.loadtxt(self._filename, usecols = __usecols, delimiter = self._delimiter, skiprows=self._skiprows)
835 if __useindex is not None:
836 __index = numpy.loadtxt(self._filename, dtype = bytes, usecols = (__useindex,), delimiter = self._delimiter, skiprows=self._skiprows)
837 if __usecols is None: # Si une variable demandée n'existe pas
838 self._colnames = None
840 elif self._format == "text/tab-separated-values":
841 __usecols, __useindex = self.__getindices(self._colnames, self._colindex, self._delimiter)
842 __columns = numpy.loadtxt(self._filename, usecols = __usecols, delimiter = self._delimiter, skiprows=self._skiprows)
843 if __useindex is not None:
844 __index = numpy.loadtxt(self._filename, dtype = bytes, usecols = (__useindex,), delimiter = self._delimiter, skiprows=self._skiprows)
845 if __usecols is None: # Si une variable demandée n'existe pas
846 self._colnames = None
848 raise ValueError("Unkown file format \"%s\" or no reader available"%self._format)
849 if __columns is None: __columns = ()
853 return value.decode()
856 if __index is not None:
857 __index = tuple([toString(v) for v in __index])
859 return (self._colnames, __columns, self._colindex, __index)
862 "Renvoie le fichier texte complet"
863 if self._format in self.__binaryformats:
866 with open(self._filename,'r') as fid:
872 class ImportScalarLinesFromFile(ImportFromFile):
874 Importation de fichier contenant des variables scalaires nommées. Le
875 fichier comporte soit 2, soit 4 colonnes, obligatoirement nommées "Name",
876 "Value", "Minimum", "Maximum" si les noms sont précisés. Sur chaque ligne
877 est indiqué le nom, la valeur, et éventuelement deux bornes min et max (ou
878 None si nécessaire pour une borne).
880 Seule la méthode "getvalue" est changée.
882 def __enter__(self): return self
883 def __exit__(self, exc_type, exc_val, exc_tb): return False
885 def __init__(self, Filename=None, ColNames=None, ColIndex=None, Format="Guess"):
886 ImportFromFile.__init__(self, Filename, ColNames, ColIndex, Format)
887 if self._format not in ["text/plain", "text/csv", "text/tab-separated-values"]:
888 raise ValueError("Unkown file format \"%s\""%self._format)
890 def getvalue(self, VarNames = None, HeaderNames=()):
891 "Renvoie la ou les variables demandees par la liste de leurs noms"
892 if VarNames is not None: __varnames = tuple(VarNames)
893 else: __varnames = None
895 if "Name" in self._varsline and "Value" in self._varsline and "Minimum" in self._varsline and "Maximum" in self._varsline:
896 __ftype = "NamValMinMax"
897 __dtypes = {'names' : ('Name', 'Value', 'Minimum', 'Maximum'),
898 'formats': ('S128', 'g', 'g', 'g')}
899 __usecols = (0, 1, 2, 3)
900 def __replaceNoneN( s ):
901 if s.strip() == b'None': return numpy.NINF
903 def __replaceNoneP( s ):
904 if s.strip() == b'None': return numpy.PINF
906 __converters = {2: __replaceNoneN, 3: __replaceNoneP}
907 elif "Name" in self._varsline and "Value" in self._varsline and ("Minimum" not in self._varsline or "Maximum" not in self._varsline):
909 __dtypes = {'names' : ('Name', 'Value'),
910 'formats': ('S128', 'g')}
913 elif len(HeaderNames)>0 and numpy.all([kw in self._varsline for kw in HeaderNames]):
914 __ftype = "NamLotOfVals"
915 __dtypes = {'names' : HeaderNames,
916 'formats': tuple(['S128',]+['g']*(len(HeaderNames)-1))}
917 __usecols = tuple(range(len(HeaderNames)))
918 def __replaceNone( s ):
919 if s.strip() == b'None': return numpy.NAN
921 __converters = dict()
922 for i in range(1,len(HeaderNames)):
923 __converters[i] = __replaceNone
925 raise ValueError("Can not find names of columns for initial values. Wrong first line is:\n \"%s\""%__firstline)
927 if self._format == "text/plain":
928 __content = numpy.loadtxt(self._filename, dtype = __dtypes, usecols = __usecols, skiprows = self._skiprows, converters = __converters)
929 elif self._format in ["text/csv", "text/tab-separated-values"]:
930 __content = numpy.loadtxt(self._filename, dtype = __dtypes, usecols = __usecols, skiprows = self._skiprows, converters = __converters, delimiter = self._delimiter)
932 raise ValueError("Unkown file format \"%s\""%self._format)
934 __names, __thevalue, __bounds = [], [], []
935 for sub in __content:
936 if len(__usecols) == 4:
938 if numpy.isneginf(mi): mi = None # Réattribue les variables None
939 elif numpy.isnan(mi): mi = None # Réattribue les variables None
940 if numpy.isposinf(ma): ma = None # Réattribue les variables None
941 elif numpy.isnan(ma): ma = None # Réattribue les variables None
942 elif len(__usecols) == 2 and __ftype == "NamVal":
948 for i, v in enumerate(nsub[1:]):
949 if numpy.isnan(v): nsub[i+1] = None
953 if (__varnames is None or na in __varnames) and (na not in __names):
954 # Ne stocke que la premiere occurence d'une variable
956 __thevalue.append(va)
957 __bounds.append((mi,ma))
959 __names = tuple(__names)
960 __thevalue = numpy.array(__thevalue)
961 __bounds = tuple(__bounds)
963 return (__names, __thevalue, __bounds)
965 # ==============================================================================
966 class EficasGUI(object):
968 Lancement autonome de l'interface EFICAS/ADAO
970 def __init__(self, __addpath = None):
971 # Chemin pour l'installation (ordre important)
973 self.__path_settings_ok = False
975 if "EFICAS_ROOT" in os.environ:
976 __EFICAS_ROOT = os.environ["EFICAS_ROOT"]
979 self.__msg += "\nKeyError:\n"+\
980 " the required environment variable EFICAS_ROOT is unknown.\n"+\
981 " You have either to be in SALOME environment, or to set\n"+\
982 " this variable in your environment to the right path \"<...>\"\n"+\
983 " to find an installed EFICAS application. For example:\n"+\
984 " EFICAS_ROOT=\"<...>\" command\n"
988 __path_ok = True and __path_ok
990 self.__msg += "\nImportError:\n"+\
991 " the required ADAO library can not be found to be imported.\n"+\
992 " You have either to be in ADAO environment, or to be in SALOME\n"+\
993 " environment, or to set manually in your Python 3 environment the\n"+\
994 " right path \"<...>\" to find an installed ADAO application. For\n"+\
996 " PYTHONPATH=\"<...>:${PYTHONPATH}\" command\n"
1000 __path_ok = True and __path_ok
1002 self.__msg += "\nImportError:\n"+\
1003 " the required PyQt5 library can not be found to be imported.\n"+\
1004 " You have either to have a raisonable up-to-date Python 3\n"+\
1005 " installation (less than 5 years), or to be in SALOME environment.\n"
1009 self.__msg += "\nWarning:\n"+\
1010 " It seems you have some troubles with your installation.\n"+\
1011 " Be aware that some other errors may exist, that are not\n"+\
1012 " explained as above, like some incomplete or obsolete\n"+\
1013 " Python 3, or incomplete module installation.\n"+\
1015 " Please correct the above error(s) before launching the\n"+\
1016 " standalone EFICAS/ADAO interface.\n"
1017 logging.debug("Some of the ADAO/EFICAS/QT5 paths have not been found")
1018 self.__path_settings_ok = False
1020 logging.debug("All the ADAO/EFICAS/QT5 paths have been found")
1021 self.__path_settings_ok = True
1023 if self.__path_settings_ok:
1024 sys.path.insert(0,__EFICAS_ROOT)
1025 sys.path.insert(0,os.path.join(adao.adao_py_dir,"daEficas"))
1026 if __addpath is not None and os.path.exists(os.path.abspath(__addpath)):
1027 sys.path.insert(0,os.path.abspath(__addpath))
1028 logging.debug("All the paths have been correctly set up")
1031 logging.debug("Errors in path settings have been found")
1034 if self.__path_settings_ok:
1035 logging.debug("Launching standalone EFICAS/ADAO interface...")
1036 from daEficas import prefs
1037 from InterfaceQT4 import eficas_go
1038 eficas_go.lanceEficas(code=prefs.code)
1040 logging.debug("Can not launch standalone EFICAS/ADAO interface for path errors.")
1042 # ==============================================================================
1043 if __name__ == "__main__":
1044 print('\n AUTODIAGNOSTIC\n')