1 # -*- coding: utf-8 -*-
3 # Copyright (C) 2008-2018 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"
34 from daCore import Persistence
35 from daCore import PlatformInfo
36 from daCore import Templates
38 # ==============================================================================
39 class GenericCaseViewer(object):
41 Gestion des commandes de creation d'une vue de cas
43 def __init__(self, __name="", __objname="case", __content=None, __object=None):
44 "Initialisation et enregistrement de l'entete"
45 self._name = str(__name)
46 self._objname = str(__objname)
48 self._switchoff = False
49 self._numobservers = 2
50 self._content = __content
51 self._object = __object
52 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# """
53 def _append(self, *args):
54 "Transformation de commande individuelle en enregistrement"
55 raise NotImplementedError()
56 def _extract(self, *args):
57 "Transformation d'enregistrement en commande individuelle"
58 raise NotImplementedError()
59 def _finalize(self, __upa=None):
60 "Enregistrement du final"
61 if __upa is not None and len(__upa)>0:
62 self._lineSerie.append("%s.execute()"%(self._objname,))
63 self._lineSerie.append(__upa)
64 def _addLine(self, line=""):
65 "Ajoute un enregistrement individuel"
66 self._lineSerie.append(line)
67 def _get_objname(self):
69 def dump(self, __filename=None, __upa=None):
70 "Restitution normalisée des commandes"
72 __text = "\n".join(self._lineSerie)
74 if __filename is not None:
75 __file = os.path.abspath(__filename)
76 __fid = open(__file,"w")
80 def load(self, __filename=None, __content=None, __object=None):
81 "Chargement normalisé des commandes"
82 if __filename is not None and os.path.exists(__filename):
83 self._content = open(__filename, 'r').read()
84 elif __content is not None and type(__content) is str:
85 self._content = __content
86 elif __object is not None and type(__object) is dict:
87 self._object = copy.deepcopy(__object)
89 pass # use "self._content" from initialization
90 __commands = self._extract(self._content, self._object)
93 class _TUIViewer(GenericCaseViewer):
95 Etablissement des commandes d'un cas ADAO TUI (Cas<->TUI)
97 def __init__(self, __name="", __objname="case", __content=None, __object=None):
98 "Initialisation et enregistrement de l'entete"
99 GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
100 self._addLine("# -*- coding: utf-8 -*-")
101 self._addLine("#\n# Python script using ADAO TUI\n#")
102 self._addLine("from numpy import array, matrix")
103 self._addLine("import adaoBuilder")
104 self._addLine("%s = adaoBuilder.New('%s')"%(self._objname, self._name))
105 if self._content is not None:
106 for command in self._content:
107 self._append(*command)
108 def _append(self, __command=None, __keys=None, __local=None, __pre=None, __switchoff=False):
109 "Transformation d'une commande individuelle en un enregistrement"
110 if __command is not None and __keys is not None and __local is not None:
112 if __pre is not None:
113 __text += "%s = "%__pre
114 __text += "%s.%s( "%(self._objname,str(__command))
115 if "self" in __keys: __keys.remove("self")
116 if __command not in ("set","get") and "Concept" in __keys: __keys.remove("Concept")
119 if __v is None: continue
120 if k == "Checked" and not __v: continue
121 if k == "Stored" and not __v: continue
122 if k == "AvoidRC" and __v: continue
123 if k == "noDetails": continue
124 if isinstance(__v,Persistence.Persistence): __v = __v.values()
125 if callable(__v): __text = self._missing%__v.__name__+__text
126 if isinstance(__v,dict):
127 for val in __v.values():
128 if callable(val): __text = self._missing%val.__name__+__text
129 numpy.set_printoptions(precision=15,threshold=1000000,linewidth=1000*15)
130 __text += "%s=%s, "%(k,repr(__v))
131 numpy.set_printoptions(precision=8,threshold=1000,linewidth=75)
134 self._addLine(__text)
135 def _extract(self, __multilines="", __object=None):
136 "Transformation un enregistrement en une commande individuelle"
139 __multilines = __multilines.replace("\r\n","\n")
140 for line in __multilines.split("\n"):
141 if "adaoBuilder.New" in line and "=" in line:
142 self._objname = line.split("=")[0].strip()
144 logging.debug("TUI Extracting commands of '%s' object..."%(self._objname,))
148 if self._objname+".set" in line:
149 __commands.append( line.replace(self._objname+".","",1) )
150 logging.debug("TUI Extracted command: %s"%(__commands[-1],))
153 class _COMViewer(GenericCaseViewer):
155 Etablissement des commandes d'un cas COMM (Eficas Native Format/Cas<-COM)
157 def __init__(self, __name="", __objname="case", __content=None, __object=None):
158 "Initialisation et enregistrement de l'entete"
159 GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
160 self._observerIndex = 0
161 self._addLine("# -*- coding: utf-8 -*-")
162 self._addLine("#\n# Python script using ADAO COMM\n#")
163 self._addLine("from numpy import array, matrix")
165 self._addLine("%s = {}"%__objname)
166 if self._content is not None:
167 for command in self._content:
168 self._append(*command)
169 def _extract(self, __multilines=None, __object=None):
170 "Transformation un enregistrement en une commande individuelle"
171 if __multilines is not None:
172 __multilines = __multilines.replace("ASSIMILATION_STUDY","dict")
173 __multilines = __multilines.replace("CHECKING_STUDY", "dict")
174 __multilines = __multilines.replace("_F(", "dict(")
175 __multilines = __multilines.replace(",),);", ",),)")
177 for line in __multilines.split("\n"):
178 if len(line) < 1: continue
179 __fulllines += line + "\n"
180 __multilines = __fulllines
181 self._objname = "case"
183 exec("self._objdata = "+__multilines)
185 if self._objdata is None or not(type(self._objdata) is dict) or not('AlgorithmParameters' in self._objdata):
186 raise ValueError("Impossible to load given content as an ADAO COMM one (no dictionnary or no 'AlgorithmParameters' key found).")
187 # ----------------------------------------------------------------------
188 logging.debug("COMM Extracting commands of '%s' object..."%(self._objname,))
190 __UserPostAnalysis = ""
191 for k,r in self._objdata.items():
193 logging.debug("COMM Extracted command: %s:%s"%(k, r))
194 if __command == "StudyName" and len(str(r))>0:
195 __commands.append( "set( Concept='Name', String='%s')"%(str(r),) )
196 elif __command == "StudyRepertory":
197 __commands.append( "set( Concept='Directory', String='%s')"%(str(r),) )
199 elif __command == "UserPostAnalysis" and type(r) is dict:
201 __UserPostAnalysis = r['STRING']
202 elif 'SCRIPT_FILE' in r and os.path.exists(r['SCRIPT_FILE']):
203 __UserPostAnalysis = open(r['SCRIPT_FILE'],'r').read()
204 elif 'Template' in r and 'ValueTemplate' in r:
206 __UserPostAnalysis = r['ValueTemplate']
208 __UserPostAnalysis = ""
209 __UserPostAnalysis = __UserPostAnalysis.replace("ADD",self._objname)
211 elif __command == "AlgorithmParameters" and type(r) is dict and 'Algorithm' in r:
212 if 'data' in r and r['Parameters'] == 'Dict':
214 if 'STRING' in __from:
215 __parameters = ", Parameters=%s"%(repr(eval(__from['STRING'])),)
216 elif 'SCRIPT_FILE' in __from and os.path.exists(__from['SCRIPT_FILE']):
217 __parameters = ", Script='%s'"%(__from['SCRIPT_FILE'],)
218 else: # if 'Parameters' in r and r['Parameters'] == 'Defaults':
219 __Dict = copy.deepcopy(r)
220 __Dict.pop('Algorithm','')
221 __Dict.pop('Parameters','')
222 if 'SetSeed' in __Dict:__Dict['SetSeed'] = int(__Dict['SetSeed'])
223 if 'BoxBounds' in __Dict and type(__Dict['BoxBounds']) is str:
224 __Dict['BoxBounds'] = eval(__Dict['BoxBounds'])
226 __parameters = ', Parameters=%s'%(repr(__Dict),)
229 __commands.append( "set( Concept='AlgorithmParameters', Algorithm='%s'%s )"%(r['Algorithm'],__parameters) )
231 elif __command == "Observers" and type(r) is dict and 'SELECTION' in r:
232 if type(r['SELECTION']) is str:
233 __selection = (r['SELECTION'],)
235 __selection = tuple(r['SELECTION'])
236 for sk in __selection:
237 __idata = r['%s_data'%sk]
238 if __idata['NodeType'] == 'Template' and 'Template' in __idata:
239 __template = __idata['Template']
240 if 'Info' in __idata:
241 __info = ", Info='%s'"%(__idata['Info'],)
244 __commands.append( "set( Concept='Observer', Variable='%s', Template='%s'%s )"%(sk,__template,__info) )
245 if __idata['NodeType'] == 'String' and 'Value' in __idata:
246 __value =__idata['Value']
247 __commands.append( "set( Concept='Observer', Variable='%s', String='%s' )"%(sk,__value) )
249 # Background, ObservationError, ObservationOperator...
250 elif type(r) is dict:
252 if 'Stored' in r and bool(r['Stored']):
253 __argumentsList.append(['Stored',True])
254 if 'INPUT_TYPE' in r and 'data' in r:
255 # Vector, Matrix, ScalarSparseMatrix, DiagonalSparseMatrix, Function
256 __itype = r['INPUT_TYPE']
258 if 'FROM' in __idata:
259 # String, Script, Template, ScriptWithOneFunction, ScriptWithFunctions
260 __ifrom = __idata['FROM']
261 __idata.pop('FROM','')
262 if __ifrom == 'String' or __ifrom == 'Template':
263 __argumentsList.append([__itype,__idata['STRING']])
264 if __ifrom == 'Script':
265 __argumentsList.append([__itype,True])
266 __argumentsList.append(['Script',__idata['SCRIPT_FILE']])
267 if __ifrom == 'ScriptWithOneFunction':
268 __argumentsList.append(['OneFunction',True])
269 __argumentsList.append(['Script',__idata.pop('SCRIPTWITHONEFUNCTION_FILE')])
271 __argumentsList.append(['Parameters',__idata])
272 if __ifrom == 'ScriptWithFunctions':
273 __argumentsList.append(['ThreeFunctions',True])
274 __argumentsList.append(['Script',__idata.pop('SCRIPTWITHFUNCTIONS_FILE')])
276 __argumentsList.append(['Parameters',__idata])
277 __arguments = ["%s = %s"%(k,repr(v)) for k,v in __argumentsList]
278 __commands.append( "set( Concept='%s', %s )"%(__command, ", ".join(__arguments)))
280 # ----------------------------------------------------------------------
281 __commands.sort() # Pour commencer par 'AlgorithmParameters'
282 __commands.append(__UserPostAnalysis)
285 class _SCDViewer(GenericCaseViewer):
287 Etablissement des commandes d'un cas SCD (Study Config Dictionary/Cas->SCD)
289 def __init__(self, __name="", __objname="case", __content=None, __object=None):
290 "Initialisation et enregistrement de l'entete"
291 GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
292 self._addLine("# -*- coding: utf-8 -*-")
293 self._addLine("#\n# Input for ADAO converter to YACS\n#")
294 self._addLine("from numpy import array, matrix")
296 self._addLine("study_config = {}")
297 self._addLine("study_config['StudyType'] = 'ASSIMILATION_STUDY'")
298 self._addLine("study_config['Name'] = '%s'"%self._name)
299 self._addLine("observers = {}")
300 self._addLine("study_config['Observers'] = observers")
302 self._addLine("inputvariables_config = {}")
303 self._addLine("inputvariables_config['Order'] =['adao_default']")
304 self._addLine("inputvariables_config['adao_default'] = -1")
305 self._addLine("study_config['InputVariables'] = inputvariables_config")
307 self._addLine("outputvariables_config = {}")
308 self._addLine("outputvariables_config['Order'] = ['adao_default']")
309 self._addLine("outputvariables_config['adao_default'] = -1")
310 self._addLine("study_config['OutputVariables'] = outputvariables_config")
311 if __content is not None:
312 for command in __content:
313 self._append(*command)
314 def _append(self, __command=None, __keys=None, __local=None, __pre=None, __switchoff=False):
315 "Transformation d'une commande individuelle en un enregistrement"
316 if __command == "set": __command = __local["Concept"]
317 else: __command = __command.replace("set", "", 1)
320 if __command in (None, 'execute', 'executePythonScheme', 'executeYACSScheme', 'get', 'Name'):
322 elif __command in ['Debug', 'setDebug']:
323 __text = "#\nstudy_config['Debug'] = '1'"
324 elif __command in ['NoDebug', 'setNoDebug']:
325 __text = "#\nstudy_config['Debug'] = '0'"
326 elif __command in ['Observer', 'setObserver']:
327 __obs = __local['Variable']
328 self._numobservers += 1
330 __text += "observers['%s'] = {}\n"%__obs
331 if __local['String'] is not None:
332 __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'String')
333 __text += "observers['%s']['String'] = \"\"\"%s\"\"\"\n"%(__obs, __local['String'])
334 if __local['Script'] is not None:
335 __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'Script')
336 __text += "observers['%s']['Script'] = \"%s\"\n"%(__obs, __local['Script'])
337 if __local['Template'] is not None and __local['Template'] in Templates.ObserverTemplates:
338 __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'String')
339 __text += "observers['%s']['String'] = \"\"\"%s\"\"\"\n"%(__obs, Templates.ObserverTemplates[__local['Template']])
340 if __local['Info'] is not None:
341 __text += "observers['%s']['info'] = \"\"\"%s\"\"\"\n"%(__obs, __local['Info'])
343 __text += "observers['%s']['info'] = \"\"\"%s\"\"\"\n"%(__obs, __obs)
344 __text += "observers['%s']['number'] = %s"%(__obs, self._numobservers)
345 elif __local is not None: # __keys is not None and
346 numpy.set_printoptions(precision=15,threshold=1000000,linewidth=1000*15)
348 __text += "%s_config = {}\n"%__command
349 __local.pop('self','')
351 for __k,__v in __local.items():
352 if __v is None: __to_be_removed.append(__k)
353 for __k in __to_be_removed:
355 for __k,__v in __local.items():
356 if __k == "Concept": continue
357 if __k in ['ScalarSparseMatrix','DiagonalSparseMatrix','Matrix','OneFunction','ThreeFunctions'] and 'Script' in __local: continue
358 if __k == 'Algorithm':
359 __text += "study_config['Algorithm'] = %s\n"%(repr(__v))
360 elif __k == 'Script':
363 __v = "'"+repr(__v)+"'"
364 for __lk in ['ScalarSparseMatrix','DiagonalSparseMatrix','Matrix']:
365 if __lk in __local and __local[__lk]: __k = __lk
366 if __command == "AlgorithmParameters": __k = "Dict"
367 if 'OneFunction' in __local and __local['OneFunction']:
368 __text += "%s_ScriptWithOneFunction = {}\n"%(__command,)
369 __text += "%s_ScriptWithOneFunction['Function'] = ['Direct', 'Tangent', 'Adjoint']\n"%(__command,)
370 __text += "%s_ScriptWithOneFunction['Script'] = {}\n"%(__command,)
371 __text += "%s_ScriptWithOneFunction['Script']['Direct'] = %s\n"%(__command,__v)
372 __text += "%s_ScriptWithOneFunction['Script']['Tangent'] = %s\n"%(__command,__v)
373 __text += "%s_ScriptWithOneFunction['Script']['Adjoint'] = %s\n"%(__command,__v)
374 __text += "%s_ScriptWithOneFunction['DifferentialIncrement'] = 1e-06\n"%(__command,)
375 __text += "%s_ScriptWithOneFunction['CenteredFiniteDifference'] = 0\n"%(__command,)
377 __f = 'ScriptWithOneFunction'
378 __v = '%s_ScriptWithOneFunction'%(__command,)
379 if 'ThreeFunctions' in __local and __local['ThreeFunctions']:
380 __text += "%s_ScriptWithFunctions = {}\n"%(__command,)
381 __text += "%s_ScriptWithFunctions['Function'] = ['Direct', 'Tangent', 'Adjoint']\n"%(__command,)
382 __text += "%s_ScriptWithFunctions['Script'] = {}\n"%(__command,)
383 __text += "%s_ScriptWithFunctions['Script']['Direct'] = %s\n"%(__command,__v)
384 __text += "%s_ScriptWithFunctions['Script']['Tangent'] = %s\n"%(__command,__v)
385 __text += "%s_ScriptWithFunctions['Script']['Adjoint'] = %s\n"%(__command,__v)
387 __f = 'ScriptWithFunctions'
388 __v = '%s_ScriptWithFunctions'%(__command,)
389 __text += "%s_config['Type'] = '%s'\n"%(__command,__k)
390 __text += "%s_config['From'] = '%s'\n"%(__command,__f)
391 __text += "%s_config['Data'] = %s\n"%(__command,__v)
392 __text = __text.replace("''","'")
393 elif __k in ('Stored', 'Checked'):
395 __text += "%s_config['%s'] = '%s'\n"%(__command,__k,int(bool(__v)))
396 elif __k in ('AvoidRC', 'noDetails'):
398 __text += "%s_config['%s'] = '%s'\n"%(__command,__k,int(bool(__v)))
400 if __k == 'Parameters': __k = "Dict"
401 if isinstance(__v,Persistence.Persistence): __v = __v.values()
402 if callable(__v): __text = self._missing%__v.__name__+__text
403 if isinstance(__v,dict):
404 for val in __v.values():
405 if callable(val): __text = self._missing%val.__name__+__text
406 __text += "%s_config['Type'] = '%s'\n"%(__command,__k)
407 __text += "%s_config['From'] = '%s'\n"%(__command,'String')
408 __text += "%s_config['Data'] = \"\"\"%s\"\"\"\n"%(__command,repr(__v))
409 __text += "study_config['%s'] = %s_config"%(__command,__command)
410 numpy.set_printoptions(precision=8,threshold=1000,linewidth=75)
412 self._switchoff = True
413 if __text is not None: self._addLine(__text)
415 self._switchoff = False
416 def _finalize(self, *__args):
417 self.__loadVariablesByScript()
419 self._addLine("Analysis_config = {}")
420 self._addLine("Analysis_config['From'] = 'String'")
421 self._addLine("Analysis_config['Data'] = \"\"\"import numpy")
422 self._addLine("xa=numpy.ravel(ADD.get('Analysis')[-1])")
423 self._addLine("print 'Analysis:',xa\"\"\"")
424 self._addLine("study_config['UserPostAnalysis'] = Analysis_config")
425 def __loadVariablesByScript(self):
426 __ExecVariables = {} # Necessaire pour recuperer la variable
427 exec("\n".join(self._lineSerie), __ExecVariables)
428 study_config = __ExecVariables['study_config']
429 # Pour Python 3 : self.__hasAlgorithm = bool(study_config['Algorithm'])
430 if 'Algorithm' in study_config:
431 self.__hasAlgorithm = True
433 self.__hasAlgorithm = False
434 if not self.__hasAlgorithm and \
435 "AlgorithmParameters" in study_config and \
436 isinstance(study_config['AlgorithmParameters'], dict) and \
437 "From" in study_config['AlgorithmParameters'] and \
438 "Data" in study_config['AlgorithmParameters'] and \
439 study_config['AlgorithmParameters']['From'] == 'Script':
440 __asScript = study_config['AlgorithmParameters']['Data']
441 __var = ImportFromScript(__asScript).getvalue( "Algorithm" )
442 __text = "#\nstudy_config['Algorithm'] = '%s'"%(__var,)
443 self._addLine(__text)
444 if self.__hasAlgorithm and \
445 "AlgorithmParameters" in study_config and \
446 isinstance(study_config['AlgorithmParameters'], dict) and \
447 "From" not in study_config['AlgorithmParameters'] and \
448 "Data" not in study_config['AlgorithmParameters']:
450 __text += "AlgorithmParameters_config['Type'] = 'Dict'\n"
451 __text += "AlgorithmParameters_config['From'] = 'String'\n"
452 __text += "AlgorithmParameters_config['Data'] = '{}'\n"
453 self._addLine(__text)
456 class _YACSViewer(GenericCaseViewer):
458 Etablissement des commandes d'un cas YACS (Cas->SCD->YACS)
460 def __init__(self, __name="", __objname="case", __content=None, __object=None):
461 "Initialisation et enregistrement de l'entete"
462 GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
463 self.__internalSCD = _SCDViewer(__name, __objname, __content, __object)
464 self._append = self.__internalSCD._append
465 def dump(self, __filename=None, __upa=None):
466 "Restitution normalisée des commandes"
468 if __filename is None:
469 raise ValueError("A file name has to be given for YACS XML output.")
471 __file = os.path.abspath(__filename)
472 if os.path.isfile(__file) or os.path.islink(__file):
475 if not PlatformInfo.has_salome or \
476 not PlatformInfo.has_adao:
478 "Unable to get SALOME or ADAO environnement variables for YACS conversion.\n"+\
479 "Please load the right environnement before trying to use it.")
481 from daYacsSchemaCreator.run import create_schema_from_content
483 self.__internalSCD._finalize(__upa)
484 __SCDdump = self.__internalSCD.dump()
485 create_schema_from_content(__SCDdump, __file)
487 if not os.path.exists(__file):
488 __msg = "An error occured during the ADAO YACS Schema build for\n"
489 __msg += "the target output file:\n"
490 __msg += " %s\n"%__file
491 __msg += "See errors details in your launching terminal log.\n"
492 raise ValueError(__msg)
494 __fid = open(__file,"r")
495 __text = __fid.read()
499 # ==============================================================================
500 class ImportFromScript(object):
502 Obtention d'une variable nommee depuis un fichier script importé
504 __slots__ = ("__basename", "__filenspace", "__filestring")
505 def __init__(self, __filename=None):
506 "Verifie l'existence et importe le script"
507 if __filename is None:
508 raise ValueError("The name of the file, containing the variable to be read, has to be specified.")
509 if not os.path.isfile(__filename):
510 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))
511 if os.path.dirname(__filename) != '':
512 sys.path.insert(0, os.path.dirname(__filename))
513 __basename = os.path.basename(__filename).rstrip(".py")
515 __basename = __filename.rstrip(".py")
516 self.__basename = __basename
517 self.__filenspace = __import__(__basename, globals(), locals(), [])
518 self.__filestring = open(__filename,'r').read()
519 def getvalue(self, __varname=None, __synonym=None ):
520 "Renvoie la variable demandee par son nom ou son synonyme"
521 if __varname is None:
522 raise ValueError("The name of the variable to be read has to be specified. Please check the content of the file and the syntax.")
523 if not hasattr(self.__filenspace, __varname):
524 if __synonym is None:
525 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))
526 elif not hasattr(self.__filenspace, __synonym):
527 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))
529 return getattr(self.__filenspace, __synonym)
531 return getattr(self.__filenspace, __varname)
533 "Renvoie le script complet"
534 return self.__filestring
536 # ==============================================================================
537 class ImportFromFile(object):
539 Obtention de variables disrétisées en 1D, définies par une ou des variables
540 nommées, et sous la forme d'une série de points éventuellement indexés. La
541 lecture d'un fichier au format spécifié (ou intuité) permet de charger ces
543 - des fichiers textes en colonnes de type TXT, CSV, TSV...
544 - des fichiers de données binaires NPY, NPZ...
545 La lecture du fichier complet ne se fait que si nécessaire, pour assurer la
546 performance tout en disposant de l'interprétation du contenu. Les fichiers
547 textes doivent présenter en première ligne (hors commentaire ou ligne vide)
548 les noms des variables de colonnes. Les commentaires commencent par un "#".
551 "_filename", "_varsline", "_format", "_delimiter", "_skiprows",
552 "__colnames", "__colindex", "__filestring", "__header")
553 def __enter__(self): return self
554 def __exit__(self, exc_type, exc_val, exc_tb): return False
556 def __init__(self, Filename=None, ColNames=None, ColIndex=None, Format="Guess"):
558 Verifie l'existence et les informations de définition du fichier. Les
559 noms de colonnes ou de variables sont ignorées si le format ne permet
562 - Filename : nom du fichier
563 - ColNames : noms de la ou des colonnes/variables à lire
564 - ColIndex : nom unique de la colonne/variable servant d'index
565 - Format : format du fichier et/ou des données inclues
568 raise ValueError("The name of the file, containing the variables to be read, has to be specified.")
569 if not os.path.isfile(Filename):
570 raise ValueError("The file, containing the variables to be read, doesn't seem to exist. Please check the file. The given file name is:\n \"%s\""%str(Filename))
571 self._filename = os.path.abspath(Filename)
573 self.__header, self._varsline, self._skiprows = self.__getentete(self._filename)
575 self._delimiter = None
576 self.__filestring = "".join(self.__header)
577 if Format.upper() == "GUESS":
578 if self._filename.split(".")[-1].lower() == "npy":
580 elif self._filename.split(".")[-1].lower() == "npz":
582 elif self.__filestring.count(",") > 1 and self._filename.split(".")[-1].lower() == "csv":
584 self._delimiter = ","
585 elif self.__filestring.count(";") > 1 and self._filename.split(".")[-1].lower() == "csv":
587 self._delimiter = ";"
588 elif self.__filestring.count("\t") > 1 and self._filename.split(".")[-1].lower() == "tsv":
590 self._delimiter = "\t"
591 elif self.__filestring.count(" ") > 1 and self._filename.split(".")[-1].lower() == "txt":
594 raise ValueError("Can not guess the file format, please specify the good one")
595 elif Format.upper() == "CSV" and self._delimiter is None:
596 if self.__filestring.count(",") > 1 and self._filename.split(".")[-1].lower() == "csv":
598 self._delimiter = ","
599 elif self.__filestring.count(";") > 1 and self._filename.split(".")[-1].lower() == "csv":
601 self._delimiter = ";"
602 elif Format.upper() == "TSV" and self._delimiter is None:
604 self._delimiter = "\t"
606 self._format = str(Format).upper()
608 if ColNames is not None: self.__colnames = tuple(ColNames)
609 else: self.__colnames = None
611 if ColIndex is not None: self.__colindex = str(ColIndex)
612 else: self.__colindex = None
614 def __getentete(self, __filename, __nblines = 3):
615 "Lit l'entête du fichier pour trouver la définition des variables"
616 __header, __varsline, __skiprows = [], "", 1
617 if __filename.split(".")[-1].lower() in ("npy", "npz"):
620 with open(__filename,'r') as fid:
621 __line = fid.readline().strip()
622 while "#" in __line or len(__line) < 1:
623 __header.append(__line)
625 __line = fid.readline().strip()
626 __varsline = __line # Première ligne non commentée non vide
627 for i in range(max(0,__nblines)):
628 __header.append(fid.readline())
629 return (__header, __varsline, __skiprows)
631 def __getindices(self, __colnames, __colindex, __delimiter=None ):
632 "Indices de colonnes correspondants à l'index et aux variables"
633 if __delimiter is None:
634 __varserie = self._varsline.strip('#').strip().split()
636 __varserie = self._varsline.strip('#').strip().split(str(__delimiter))
638 if __colnames is not None:
640 __colnames = tuple(__colnames)
642 for i, n in enumerate(__varserie):
643 if v == n: __usecols.append(i)
644 __usecols = tuple(__usecols)
645 if len(__usecols) == 0: __usecols = None
649 if __colindex is not None:
651 __colindex = str(__colindex)
652 for i, n in enumerate(__varserie):
653 if __colindex == n: __useindex = i
657 return (__usecols, __useindex)
659 def getvalue(self, ColNames=None, ColIndex=None ):
660 "Renvoie la ou les variables demandees par la liste de leurs noms"
661 # Uniquement si mise à jour
662 if ColNames is not None: self.__colnames = tuple(ColNames)
663 if ColIndex is not None: self.__colindex = str(ColIndex)
666 if self._format == "NPY":
667 __columns = numpy.load(self._filename)
668 elif self._format == "NPZ":
670 with numpy.load(self._filename) as __allcolumns:
671 if self.__colnames is None:
672 self.__colnames = __allcolumns.files
673 for nom in self.__colnames:
674 if nom in __allcolumns.files:
675 if __columns is not None:
676 # Attention : toutes les variables doivent avoir la même taille
677 __columns = numpy.vstack((__columns, numpy.reshape(__allcolumns[nom], (1,-1))))
680 __columns = numpy.reshape(__allcolumns[nom], (1,-1))
681 if self.__colindex is not None and self.__colindex in __allcolumns.files:
682 __index = numpy.reshape(__allcolumns[self.__colindex], (1,-1))
683 elif self._format == "TXT":
684 __usecols, __useindex = self.__getindices(self.__colnames, self.__colindex)
685 __columns = numpy.loadtxt(self._filename, usecols = __usecols, skiprows=self._skiprows)
686 if __useindex is not None:
687 __index = numpy.loadtxt(self._filename, usecols = __useindex, skiprows=self._skiprows)
689 elif self._format == "CSV":
690 __usecols, __useindex = self.__getindices(self.__colnames, self.__colindex, self._delimiter)
691 __columns = numpy.loadtxt(self._filename, usecols = __usecols, delimiter = self._delimiter, skiprows=self._skiprows)
692 if __useindex is not None:
693 __index = numpy.loadtxt(self._filename, usecols = __useindex, delimiter = self._delimiter, skiprows=self._skiprows)
695 elif self._format == "TSV":
696 __usecols, __useindex = self.__getindices(self.__colnames, self.__colindex, self._delimiter)
697 __columns = numpy.loadtxt(self._filename, usecols = __usecols, delimiter = self._delimiter, skiprows=self._skiprows)
698 if __useindex is not None:
699 __index = numpy.loadtxt(self._filename, usecols = __useindex, delimiter = self._delimiter, skiprows=self._skiprows)
701 raise ValueError("Unkown file format %s"%self._format)
703 return (self.__colnames, __columns, self.__colindex, __index)
706 "Renvoie le fichier complet"
707 with open(self._filename,'r') as fid:
710 # ==============================================================================
711 class ImportScalarLinesFromFile(ImportFromFile):
713 Importation de fichier contenant des variables scalaires nommées. Le
714 fichier comporte soit 2, soit 4 colonnes, obligatoirement nommées "Name",
715 "Value", "Minimum", "Maximum" si les noms sont précisés. Sur chaque ligne
716 est indiqué le nom, la valeur, et éventuelement deux bornes min et max (ou
717 None si nécessaire pour une borne).
719 Seule la méthode "getvalue" est changée.
721 def __enter__(self): return self
722 def __exit__(self, exc_type, exc_val, exc_tb): return False
724 def __init__(self, Filename=None, ColNames=None, ColIndex=None, Format="Guess"):
725 ImportFromFile.__init__(self, Filename, ColNames, ColIndex, Format)
726 if self._format not in ["TXT", "CSV", "TSV"]:
727 raise ValueError("Unkown file format \"%s\""%self._format)
729 def getvalue(self, VarNames = None, HeaderNames=()):
730 "Renvoie la ou les variables demandees par la liste de leurs noms"
731 if VarNames is not None: __varnames = tuple(VarNames)
732 else: __varnames = None
734 if "Name" in self._varsline and "Value" in self._varsline and "Minimum" in self._varsline and "Maximum" in self._varsline:
735 __ftype = "NamValMinMax"
736 __dtypes = {'names' : ('Name', 'Value', 'Minimum', 'Maximum'),
737 'formats': ('S128', 'g', 'g', 'g')}
738 __usecols = (0, 1, 2, 3)
739 def __replaceNoneN( s ):
740 if s.strip() == b'None': return numpy.NINF
742 def __replaceNoneP( s ):
743 if s.strip() == b'None': return numpy.PINF
745 __converters = {2: __replaceNoneN, 3: __replaceNoneP}
746 elif "Name" in self._varsline and "Value" in self._varsline and ("Minimum" not in self._varsline or "Maximum" not in self._varsline):
748 __dtypes = {'names' : ('Name', 'Value'),
749 'formats': ('S128', 'g')}
752 elif len(HeaderNames)>0 and numpy.all([kw in self._varsline for kw in HeaderNames]):
753 __ftype = "NamLotOfVals"
754 __dtypes = {'names' : HeaderNames,
755 'formats': tuple(['S128',]+['g']*(len(HeaderNames)-1))}
756 __usecols = tuple(range(len(HeaderNames)))
757 def __replaceNone( s ):
758 if s.strip() == b'None': return numpy.NAN
760 __converters = dict()
761 for i in range(1,len(HeaderNames)):
762 __converters[i] = __replaceNone
764 raise ValueError("Can not find names of columns for initial values. Wrong first line is:\n \"%s\""%__firstline)
766 if self._format == "TXT":
767 __content = numpy.loadtxt(self._filename, dtype = __dtypes, usecols = __usecols, skiprows = self._skiprows, converters = __converters)
768 elif self._format in ["CSV", "TSV"]:
769 __content = numpy.loadtxt(self._filename, dtype = __dtypes, usecols = __usecols, skiprows = self._skiprows, converters = __converters, delimiter = self._delimiter)
771 raise ValueError("Unkown file format \"%s\""%self._format)
773 __names, __background, __bounds = [], [], []
774 for sub in __content:
775 if len(__usecols) == 4:
777 if numpy.isneginf(mi): mi = None # Réattribue les variables None
778 elif numpy.isnan(mi): mi = None # Réattribue les variables None
779 if numpy.isposinf(ma): ma = None # Réattribue les variables None
780 elif numpy.isnan(ma): ma = None # Réattribue les variables None
781 elif len(__usecols) == 2 and __ftype == "NamVal":
787 for i, v in enumerate(nsub[1:]):
788 if numpy.isnan(v): nsub[i+1] = None
792 if (__varnames is None or na in __varnames) and (na not in __names):
793 # Ne stocke que la premiere occurence d'une variable
795 __background.append(va)
796 __bounds.append((mi,ma))
798 __names = tuple(__names)
799 __background = numpy.array(__background)
800 __bounds = tuple(__bounds)
802 return (__names, __background, __bounds)
804 # ==============================================================================
805 if __name__ == "__main__":
806 print('\n AUTODIAGNOSTIC \n')