Salome HOME
7f6d8b4f550cffea76571541a119990ae9b4c8aa
[modules/adao.git] / src / daComposant / daCore / Interfaces.py
1 # -*- coding: utf-8 -*-
2 #
3 # Copyright (C) 2008-2019 EDF R&D
4 #
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.
9 #
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.
14 #
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
18 #
19 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #
21 # Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
22
23 """
24     Définit les outils d'interfaces normalisées de cas.
25 """
26 __author__ = "Jean-Philippe ARGAUD"
27 __all__ = []
28
29 import os
30 import sys
31 import numpy
32 import mimetypes
33 import logging
34 import copy
35 from daCore import Persistence
36 from daCore import PlatformInfo
37 from daCore import Templates
38
39 # ==============================================================================
40 class GenericCaseViewer(object):
41     """
42     Gestion des commandes de creation d'une vue de cas
43     """
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)
48         self._lineSerie    = []
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):
69         return self._objname
70     def dump(self, __filename=None, __upa=None):
71         "Restitution normalisée des commandes"
72         self._finalize(__upa)
73         __text = "\n".join(self._lineSerie)
74         __text +="\n"
75         if __filename is not None:
76             __file = os.path.abspath(__filename)
77             __fid = open(__file,"w")
78             __fid.write(__text)
79             __fid.close()
80         return __text
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)
89         else:
90             pass # use "self._content" from initialization
91         __commands = self._extract(self._content, self._object)
92         return __commands
93
94 class _TUIViewer(GenericCaseViewer):
95     """
96     Etablissement des commandes d'un cas ADAO TUI (Cas<->TUI)
97     """
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             __text  = ""
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")
118             for k in __keys:
119                 __v = __local[k]
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 == "InputAsMF" and not __v: continue
125                 if   k == "AvoidRC"   and     __v: continue
126                 if   k == "noDetails":             continue
127                 if isinstance(__v,Persistence.Persistence): __v = __v.values()
128                 if callable(__v): __text = self._missing%__v.__name__+__text
129                 if isinstance(__v,dict):
130                     for val in __v.values():
131                         if callable(val): __text = self._missing%val.__name__+__text
132                 numpy.set_printoptions(precision=15,threshold=1000000,linewidth=1000*15)
133                 __text += "%s=%s, "%(k,repr(__v))
134                 numpy.set_printoptions(precision=8,threshold=1000,linewidth=75)
135             __text.rstrip(", ")
136             __text += ")"
137             self._addLine(__text)
138     def _extract(self, __multilines="", __object=None):
139         "Transformation un enregistrement en une commande individuelle"
140         __is_case = False
141         __commands = []
142         __multilines = __multilines.replace("\r\n","\n")
143         for line in __multilines.split("\n"):
144             if "adaoBuilder.New" in line and "=" in line:
145                 self._objname = line.split("=")[0].strip()
146                 __is_case = True
147                 logging.debug("TUI Extracting commands of '%s' object..."%(self._objname,))
148             if not __is_case:
149                 continue
150             else:
151                 if self._objname+".set" in line:
152                     __commands.append( line.replace(self._objname+".","",1) )
153                     logging.debug("TUI Extracted command: %s"%(__commands[-1],))
154         return __commands
155
156 class _COMViewer(GenericCaseViewer):
157     """
158     Etablissement des commandes d'un cas COMM (Eficas Native Format/Cas<-COM)
159     """
160     def __init__(self, __name="", __objname="case", __content=None, __object=None):
161         "Initialisation et enregistrement de l'entete"
162         GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
163         self._observerIndex = 0
164         self._addLine("# -*- coding: utf-8 -*-")
165         self._addLine("#\n# Python script using ADAO COMM\n#")
166         self._addLine("from numpy import array, matrix")
167         self._addLine("#")
168         self._addLine("%s = {}"%__objname)
169         if self._content is not None:
170             for command in self._content:
171                 self._append(*command)
172     def _extract(self, __multilines=None, __object=None):
173         "Transformation un enregistrement en une commande individuelle"
174         if __multilines is not None:
175             __multilines = __multilines.replace("ASSIMILATION_STUDY","dict")
176             __multilines = __multilines.replace("CHECKING_STUDY",    "dict")
177             __multilines = __multilines.replace("_F(",               "dict(")
178             __multilines = __multilines.replace(",),);",             ",),)")
179         __fulllines = ""
180         for line in __multilines.split("\n"):
181             if len(line) < 1: continue
182             __fulllines += line + "\n"
183         __multilines = __fulllines
184         self._objname = "case"
185         self._objdata = None
186         exec("self._objdata = "+__multilines)
187         #
188         if self._objdata is None or not(type(self._objdata) is dict) or not('AlgorithmParameters' in self._objdata):
189             raise ValueError("Impossible to load given content as an ADAO COMM one (no dictionnary or no 'AlgorithmParameters' key found).")
190         # ----------------------------------------------------------------------
191         logging.debug("COMM Extracting commands of '%s' object..."%(self._objname,))
192         __commands = []
193         __UserPostAnalysis = ""
194         for k,r in self._objdata.items():
195             __command = k
196             logging.debug("COMM Extracted command: %s:%s"%(k, r))
197             if   __command == "StudyName" and len(str(r))>0:
198                 __commands.append( "set( Concept='Name', String='%s')"%(str(r),) )
199             elif   __command == "StudyRepertory":
200                 __commands.append( "set( Concept='Directory', String='%s')"%(str(r),) )
201             #
202             elif __command == "UserPostAnalysis" and type(r) is dict:
203                 if 'STRING' in r:
204                     __UserPostAnalysis = r['STRING']
205                 elif 'SCRIPT_FILE' in r and os.path.exists(r['SCRIPT_FILE']):
206                     __UserPostAnalysis = open(r['SCRIPT_FILE'],'r').read()
207                 elif 'Template' in r and 'ValueTemplate' in r:
208                     # AnalysisPrinter...
209                     __UserPostAnalysis = r['ValueTemplate']
210                 else:
211                     __UserPostAnalysis = ""
212                 __UserPostAnalysis = __UserPostAnalysis.replace("ADD",self._objname)
213             #
214             elif __command == "AlgorithmParameters" and type(r) is dict and 'Algorithm' in r:
215                 if 'data' in r and r['Parameters'] == 'Dict':
216                     __from = r['data']
217                     if 'STRING' in __from:
218                         __parameters = ", Parameters=%s"%(repr(eval(__from['STRING'])),)
219                     elif 'SCRIPT_FILE' in __from and os.path.exists(__from['SCRIPT_FILE']):
220                         __parameters = ", Script='%s'"%(__from['SCRIPT_FILE'],)
221                 else: # if 'Parameters' in r and r['Parameters'] == 'Defaults':
222                     __Dict = copy.deepcopy(r)
223                     __Dict.pop('Algorithm','')
224                     __Dict.pop('Parameters','')
225                     if 'SetSeed' in __Dict:__Dict['SetSeed'] = int(__Dict['SetSeed'])
226                     if 'BoxBounds' in __Dict and type(__Dict['BoxBounds']) is str:
227                         __Dict['BoxBounds'] = eval(__Dict['BoxBounds'])
228                     if len(__Dict) > 0:
229                         __parameters = ', Parameters=%s'%(repr(__Dict),)
230                     else:
231                         __parameters = ""
232                 __commands.append( "set( Concept='AlgorithmParameters', Algorithm='%s'%s )"%(r['Algorithm'],__parameters) )
233             #
234             elif __command == "Observers" and type(r) is dict and 'SELECTION' in r:
235                 if type(r['SELECTION']) is str:
236                     __selection = (r['SELECTION'],)
237                 else:
238                     __selection = tuple(r['SELECTION'])
239                 for sk in __selection:
240                     __idata = r['%s_data'%sk]
241                     if __idata['NodeType'] == 'Template' and 'Template' in __idata:
242                         __template = __idata['Template']
243                         if 'Info' in __idata:
244                             __info = ", Info='%s'"%(__idata['Info'],)
245                         else:
246                             __info = ""
247                         __commands.append( "set( Concept='Observer', Variable='%s', Template='%s'%s )"%(sk,__template,__info) )
248                     if __idata['NodeType'] == 'String' and 'Value' in __idata:
249                         __value =__idata['Value']
250                         __commands.append( "set( Concept='Observer', Variable='%s', String='%s' )"%(sk,__value) )
251             #
252             # Background, ObservationError, ObservationOperator...
253             elif type(r) is dict:
254                 __argumentsList = []
255                 if 'Stored' in r and bool(r['Stored']):
256                     __argumentsList.append(['Stored',True])
257                 if 'INPUT_TYPE' in r and 'data' in r:
258                     # Vector, Matrix, ScalarSparseMatrix, DiagonalSparseMatrix, Function
259                     __itype = r['INPUT_TYPE']
260                     __idata = r['data']
261                     if 'FROM' in __idata:
262                         # String, Script, Template, ScriptWithOneFunction, ScriptWithFunctions
263                         __ifrom = __idata['FROM']
264                         __idata.pop('FROM','')
265                         if __ifrom == 'String' or __ifrom == 'Template':
266                             __argumentsList.append([__itype,__idata['STRING']])
267                         if __ifrom == 'Script':
268                             __argumentsList.append([__itype,True])
269                             __argumentsList.append(['Script',__idata['SCRIPT_FILE']])
270                         if __ifrom == 'ScriptWithOneFunction':
271                             __argumentsList.append(['OneFunction',True])
272                             __argumentsList.append(['Script',__idata.pop('SCRIPTWITHONEFUNCTION_FILE')])
273                             if len(__idata)>0:
274                                 __argumentsList.append(['Parameters',__idata])
275                         if __ifrom == 'ScriptWithFunctions':
276                             __argumentsList.append(['ThreeFunctions',True])
277                             __argumentsList.append(['Script',__idata.pop('SCRIPTWITHFUNCTIONS_FILE')])
278                             if len(__idata)>0:
279                                 __argumentsList.append(['Parameters',__idata])
280                 __arguments = ["%s = %s"%(k,repr(v)) for k,v in __argumentsList]
281                 __commands.append( "set( Concept='%s', %s )"%(__command, ", ".join(__arguments)))
282         #
283         # ----------------------------------------------------------------------
284         __commands.sort() # Pour commencer par 'AlgorithmParameters'
285         __commands.append(__UserPostAnalysis)
286         return __commands
287
288 class _SCDViewer(GenericCaseViewer):
289     """
290     Etablissement des commandes d'un cas SCD (Study Config Dictionary/Cas->SCD)
291     """
292     def __init__(self, __name="", __objname="case", __content=None, __object=None):
293         "Initialisation et enregistrement de l'entete"
294         GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
295         self._addLine("# -*- coding: utf-8 -*-")
296         self._addLine("#\n# Input for ADAO converter to YACS\n#")
297         self._addLine("from numpy import array, matrix")
298         self._addLine("#")
299         self._addLine("study_config = {}")
300         self._addLine("study_config['StudyType'] = 'ASSIMILATION_STUDY'")
301         self._addLine("study_config['Name'] = '%s'"%self._name)
302         self._addLine("observers = {}")
303         self._addLine("study_config['Observers'] = observers")
304         self._addLine("#")
305         self._addLine("inputvariables_config = {}")
306         self._addLine("inputvariables_config['Order'] =['adao_default']")
307         self._addLine("inputvariables_config['adao_default'] = -1")
308         self._addLine("study_config['InputVariables'] = inputvariables_config")
309         self._addLine("#")
310         self._addLine("outputvariables_config = {}")
311         self._addLine("outputvariables_config['Order'] = ['adao_default']")
312         self._addLine("outputvariables_config['adao_default'] = -1")
313         self._addLine("study_config['OutputVariables'] = outputvariables_config")
314         if __content is not None:
315             for command in __content:
316                 self._append(*command)
317     def _append(self, __command=None, __keys=None, __local=None, __pre=None, __switchoff=False):
318         "Transformation d'une commande individuelle en un enregistrement"
319         if __command == "set": __command = __local["Concept"]
320         else:                  __command = __command.replace("set", "", 1)
321         #
322         __text  = None
323         if __command in (None, 'execute', 'executePythonScheme', 'executeYACSScheme', 'get', 'Name'):
324             return
325         elif __command in ['Debug', 'setDebug']:
326             __text  = "#\nstudy_config['Debug'] = '1'"
327         elif __command in ['NoDebug', 'setNoDebug']:
328             __text  = "#\nstudy_config['Debug'] = '0'"
329         elif __command in ['Observer', 'setObserver']:
330             __obs   = __local['Variable']
331             self._numobservers += 1
332             __text  = "#\n"
333             __text += "observers['%s'] = {}\n"%__obs
334             if __local['String'] is not None:
335                 __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'String')
336                 __text += "observers['%s']['String'] = \"\"\"%s\"\"\"\n"%(__obs, __local['String'])
337             if __local['Script'] is not None:
338                 __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'Script')
339                 __text += "observers['%s']['Script'] = \"%s\"\n"%(__obs, __local['Script'])
340             if __local['Template'] is not None and __local['Template'] in Templates.ObserverTemplates:
341                 __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'String')
342                 __text += "observers['%s']['String'] = \"\"\"%s\"\"\"\n"%(__obs, Templates.ObserverTemplates[__local['Template']])
343             if __local['Info'] is not None:
344                 __text += "observers['%s']['info'] = \"\"\"%s\"\"\"\n"%(__obs, __local['Info'])
345             else:
346                 __text += "observers['%s']['info'] = \"\"\"%s\"\"\"\n"%(__obs, __obs)
347             __text += "observers['%s']['number'] = %s"%(__obs, self._numobservers)
348         elif __local is not None: # __keys is not None and
349             numpy.set_printoptions(precision=15,threshold=1000000,linewidth=1000*15)
350             __text  = "#\n"
351             __text += "%s_config = {}\n"%__command
352             __local.pop('self','')
353             __to_be_removed = []
354             for __k,__v in __local.items():
355                 if __v is None: __to_be_removed.append(__k)
356             for __k in __to_be_removed:
357                 __local.pop(__k)
358             for __k,__v in __local.items():
359                 if __k == "Concept": continue
360                 if __k in ['ScalarSparseMatrix','DiagonalSparseMatrix','Matrix','OneFunction','ThreeFunctions'] and 'Script' in __local: continue
361                 if __k == 'Algorithm':
362                     __text += "study_config['Algorithm'] = %s\n"%(repr(__v))
363                 elif __k == 'Script':
364                     __k = 'Vector'
365                     __f = 'Script'
366                     __v = "'"+repr(__v)+"'"
367                     for __lk in ['ScalarSparseMatrix','DiagonalSparseMatrix','Matrix']:
368                         if __lk in __local and __local[__lk]: __k = __lk
369                     if __command == "AlgorithmParameters": __k = "Dict"
370                     if 'OneFunction' in __local and __local['OneFunction']:
371                         __text += "%s_ScriptWithOneFunction = {}\n"%(__command,)
372                         __text += "%s_ScriptWithOneFunction['Function'] = ['Direct', 'Tangent', 'Adjoint']\n"%(__command,)
373                         __text += "%s_ScriptWithOneFunction['Script'] = {}\n"%(__command,)
374                         __text += "%s_ScriptWithOneFunction['Script']['Direct'] = %s\n"%(__command,__v)
375                         __text += "%s_ScriptWithOneFunction['Script']['Tangent'] = %s\n"%(__command,__v)
376                         __text += "%s_ScriptWithOneFunction['Script']['Adjoint'] = %s\n"%(__command,__v)
377                         __text += "%s_ScriptWithOneFunction['DifferentialIncrement'] = 1e-06\n"%(__command,)
378                         __text += "%s_ScriptWithOneFunction['CenteredFiniteDifference'] = 0\n"%(__command,)
379                         __k = 'Function'
380                         __f = 'ScriptWithOneFunction'
381                         __v = '%s_ScriptWithOneFunction'%(__command,)
382                     if 'ThreeFunctions' in __local and __local['ThreeFunctions']:
383                         __text += "%s_ScriptWithFunctions = {}\n"%(__command,)
384                         __text += "%s_ScriptWithFunctions['Function'] = ['Direct', 'Tangent', 'Adjoint']\n"%(__command,)
385                         __text += "%s_ScriptWithFunctions['Script'] = {}\n"%(__command,)
386                         __text += "%s_ScriptWithFunctions['Script']['Direct'] = %s\n"%(__command,__v)
387                         __text += "%s_ScriptWithFunctions['Script']['Tangent'] = %s\n"%(__command,__v)
388                         __text += "%s_ScriptWithFunctions['Script']['Adjoint'] = %s\n"%(__command,__v)
389                         __k = 'Function'
390                         __f = 'ScriptWithFunctions'
391                         __v = '%s_ScriptWithFunctions'%(__command,)
392                     __text += "%s_config['Type'] = '%s'\n"%(__command,__k)
393                     __text += "%s_config['From'] = '%s'\n"%(__command,__f)
394                     __text += "%s_config['Data'] = %s\n"%(__command,__v)
395                     __text = __text.replace("''","'")
396                 elif __k in ('Stored', 'Checked', 'ColMajor', 'InputAsMF'):
397                     if bool(__v):
398                         __text += "%s_config['%s'] = '%s'\n"%(__command,__k,int(bool(__v)))
399                 elif __k in ('AvoidRC', 'noDetails'):
400                     if not bool(__v):
401                         __text += "%s_config['%s'] = '%s'\n"%(__command,__k,int(bool(__v)))
402                 else:
403                     if __k == 'Parameters': __k = "Dict"
404                     if isinstance(__v,Persistence.Persistence): __v = __v.values()
405                     if callable(__v): __text = self._missing%__v.__name__+__text
406                     if isinstance(__v,dict):
407                         for val in __v.values():
408                             if callable(val): __text = self._missing%val.__name__+__text
409                     __text += "%s_config['Type'] = '%s'\n"%(__command,__k)
410                     __text += "%s_config['From'] = '%s'\n"%(__command,'String')
411                     __text += "%s_config['Data'] = \"\"\"%s\"\"\"\n"%(__command,repr(__v))
412             __text += "study_config['%s'] = %s_config"%(__command,__command)
413             numpy.set_printoptions(precision=8,threshold=1000,linewidth=75)
414             if __switchoff:
415                 self._switchoff = True
416         if __text is not None: self._addLine(__text)
417         if not __switchoff:
418             self._switchoff = False
419     def _finalize(self, *__args):
420         self.__loadVariablesByScript()
421         self._addLine("#")
422         self._addLine("Analysis_config = {}")
423         self._addLine("Analysis_config['From'] = 'String'")
424         self._addLine("Analysis_config['Data'] = \"\"\"import numpy")
425         self._addLine("xa=numpy.ravel(ADD.get('Analysis')[-1])")
426         self._addLine("print('Analysis:',xa)\"\"\"")
427         self._addLine("study_config['UserPostAnalysis'] = Analysis_config")
428     def __loadVariablesByScript(self):
429         __ExecVariables = {} # Necessaire pour recuperer la variable
430         exec("\n".join(self._lineSerie), __ExecVariables)
431         study_config = __ExecVariables['study_config']
432         # Pour Python 3 : self.__hasAlgorithm = bool(study_config['Algorithm'])
433         if 'Algorithm' in study_config:
434             self.__hasAlgorithm = True
435         else:
436             self.__hasAlgorithm = False
437         if not self.__hasAlgorithm and \
438                 "AlgorithmParameters" in study_config and \
439                 isinstance(study_config['AlgorithmParameters'], dict) and \
440                 "From" in study_config['AlgorithmParameters'] and \
441                 "Data" in study_config['AlgorithmParameters'] and \
442                 study_config['AlgorithmParameters']['From'] == 'Script':
443             __asScript = study_config['AlgorithmParameters']['Data']
444             __var = ImportFromScript(__asScript).getvalue( "Algorithm" )
445             __text = "#\nstudy_config['Algorithm'] = '%s'"%(__var,)
446             self._addLine(__text)
447         if self.__hasAlgorithm and \
448                 "AlgorithmParameters" in study_config and \
449                 isinstance(study_config['AlgorithmParameters'], dict) and \
450                 "From" not in study_config['AlgorithmParameters'] and \
451                 "Data" not in study_config['AlgorithmParameters']:
452             __text  = "#\n"
453             __text += "AlgorithmParameters_config['Type'] = 'Dict'\n"
454             __text += "AlgorithmParameters_config['From'] = 'String'\n"
455             __text += "AlgorithmParameters_config['Data'] = '{}'\n"
456             self._addLine(__text)
457         del study_config
458
459 class _YACSViewer(GenericCaseViewer):
460     """
461     Etablissement des commandes d'un cas YACS (Cas->SCD->YACS)
462     """
463     def __init__(self, __name="", __objname="case", __content=None, __object=None):
464         "Initialisation et enregistrement de l'entete"
465         GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
466         self.__internalSCD = _SCDViewer(__name, __objname, __content, __object)
467         self._append       = self.__internalSCD._append
468     def dump(self, __filename=None, __upa=None):
469         "Restitution normalisée des commandes"
470         # -----
471         if __filename is None:
472             raise ValueError("A file name has to be given for YACS XML output.")
473         else:
474             __file    = os.path.abspath(__filename)
475             if os.path.isfile(__file) or os.path.islink(__file):
476                 os.remove(__file)
477         # -----
478         if not PlatformInfo.has_salome or \
479             not PlatformInfo.has_adao:
480             raise ImportError(
481                 "Unable to get SALOME or ADAO environnement variables for YACS conversion.\n"+\
482                 "Please load the right environnement before trying to use it.")
483         else:
484             from daYacsSchemaCreator.run import create_schema_from_content
485         # -----
486         self.__internalSCD._finalize(__upa)
487         __SCDdump = self.__internalSCD.dump()
488         create_schema_from_content(__SCDdump, __file)
489         # -----
490         if not os.path.exists(__file):
491             __msg  = "An error occured during the ADAO YACS Schema build for\n"
492             __msg += "the target output file:\n"
493             __msg += "  %s\n"%__file
494             __msg += "See errors details in your launching terminal log.\n"
495             raise ValueError(__msg)
496         # -----
497         __fid = open(__file,"r")
498         __text = __fid.read()
499         __fid.close()
500         return __text
501
502 # ==============================================================================
503 class ImportFromScript(object):
504     """
505     Obtention d'une variable nommee depuis un fichier script importé
506     """
507     __slots__ = ("__basename", "__filenspace", "__filestring")
508     def __init__(self, __filename=None):
509         "Verifie l'existence et importe le script"
510         if __filename is None:
511             raise ValueError("The name of the file, containing the variable to be read, has to be specified.")
512         if not os.path.isfile(__filename):
513             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))
514         if os.path.dirname(__filename) != '':
515             sys.path.insert(0, os.path.dirname(__filename))
516             __basename = os.path.basename(__filename).rstrip(".py")
517         else:
518             __basename = __filename.rstrip(".py")
519         self.__basename = __basename
520         self.__filenspace = __import__(__basename, globals(), locals(), [])
521         self.__filestring = open(__filename,'r').read()
522     def getvalue(self, __varname=None, __synonym=None ):
523         "Renvoie la variable demandee par son nom ou son synonyme"
524         if __varname is None:
525             raise ValueError("The name of the variable to be read has to be specified. Please check the content of the file and the syntax.")
526         if not hasattr(self.__filenspace, __varname):
527             if __synonym is None:
528                 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))
529             elif not hasattr(self.__filenspace, __synonym):
530                 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))
531             else:
532                 return getattr(self.__filenspace, __synonym)
533         else:
534             return getattr(self.__filenspace, __varname)
535     def getstring(self):
536         "Renvoie le script complet"
537         return self.__filestring
538
539 # ==============================================================================
540 class ImportDetector(object):
541     """
542     Détection des caractéristiques de fichiers ou objets en entrée
543     """
544     __slots__ = (
545         "__url", "__usr", "__root", "__end")
546     def __enter__(self): return self
547     def __exit__(self, exc_type, exc_val, exc_tb): return False
548     #
549     def __init__(self, __url, UserMime=""):
550         if __url is None:
551             raise ValueError("The name or url of the file object has to be specified.")
552         if __url is bytes:
553             self.__url = __url.decode()
554         else:
555             self.__url = str(__url)
556         if UserMime is bytes:
557             self.__usr = UserMime.decode().lower()
558         else:
559             self.__usr = str(UserMime).lower()
560         (self.__root, self.__end) = os.path.splitext(self.__url)
561         #
562         mimetypes.add_type('application/numpy.npy', '.npy')
563         mimetypes.add_type('application/numpy.npz', '.npz')
564         mimetypes.add_type('application/dymola.sdf', '.sdf')
565         if sys.platform.startswith("win"):
566             mimetypes.add_type('text/plain', '.txt')
567             mimetypes.add_type('text/csv', '.csv')
568             mimetypes.add_type('text/tab-separated-values', '.tsv')
569     #
570     # File related f
571     # ------------------
572     def is_local_file(self):
573         if os.path.isfile(os.path.realpath(self.__url)):
574             return True
575         else:
576             return False
577     def is_not_local_file(self):
578         if not os.path.isfile(os.path.realpath(self.__url)):
579             return True
580         else:
581             return False
582     def raise_error_if_not_local_file(self):
583         if not os.path.isfile(os.path.realpath(self.__url)):
584             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))
585         else:
586             return False
587     #
588     # Directory related tests
589     # -----------------------
590     def is_local_dir(self):
591         if os.path.isdir(self.__url):
592             return True
593         else:
594             return False
595     def is_not_local_dir(self):
596         if not os.path.isdir(self.__url):
597             return True
598         else:
599             return False
600     def raise_error_if_not_local_dir(self):
601         if not os.path.isdir(self.__url):
602             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))
603         else:
604             return False
605     #
606     # Mime related functions
607     # ------------------------
608     def get_standard_mime(self):
609         (__mtype, __encoding) = mimetypes.guess_type(self.__url, strict=False)
610         return __mtype
611     def get_user_mime(self):
612         __fake = "fake."+self.__usr.lower()
613         (__mtype, __encoding) = mimetypes.guess_type(__fake, strict=False)
614         return __mtype
615     def get_comprehensive_mime(self):
616         if self.get_standard_mime() is not None:
617             return self.get_standard_mime()
618         elif self.get_user_mime() is not None:
619             return self.get_user_mime()
620         else:
621             return None
622     #
623     # Name related functions
624     # ----------------------
625     def get_user_name(self):
626         return self.__url
627     def get_absolute_name(self):
628         return os.path.abspath(os.path.realpath(self.__url))
629     def get_extension(self):
630         return self.__end
631
632 # ==============================================================================
633 class ImportFromFile(object):
634     """
635     Obtention de variables disrétisées en 1D, définies par une ou des variables
636     nommées, et sous la forme d'une série de points éventuellement indexés. La
637     lecture d'un fichier au format spécifié (ou intuité) permet de charger ces
638     fonctions depuis :
639         - des fichiers textes en colonnes de type TXT, CSV, TSV...
640         - des fichiers de données binaires NPY, NPZ, SDF...
641     La lecture du fichier complet ne se fait que si nécessaire, pour assurer la
642     performance tout en disposant de l'interprétation du contenu. Les fichiers
643     textes doivent présenter en première ligne (hors commentaire ou ligne vide)
644     les noms des variables de colonnes. Les commentaires commencent par un "#".
645     """
646     __slots__ = (
647         "_filename", "_colnames", "_colindex", "_varsline", "_format",
648         "_delimiter", "_skiprows", "__url", "__filestring", "__header",
649         "__allowvoid", "__binaryformats", "__supportedformats")
650     def __enter__(self): return self
651     def __exit__(self, exc_type, exc_val, exc_tb): return False
652     #
653     def __init__(self, Filename=None, ColNames=None, ColIndex=None, Format="Guess", AllowVoidNameList=True):
654         """
655         Verifie l'existence et les informations de définition du fichier. Les
656         noms de colonnes ou de variables sont ignorées si le format ne permet
657         pas de les indiquer.
658         Arguments :
659             - Filename : nom du fichier
660             - ColNames : noms de la ou des colonnes/variables à lire
661             - ColIndex : nom unique de la colonne/variable servant d'index
662             - Format : format du fichier et/ou des données inclues
663             - AllowVoidNameList : permet, si la liste de noms est vide, de
664               prendre par défaut toutes les colonnes
665         """
666         self.__binaryformats =(
667             "application/numpy.npy",
668             "application/numpy.npz",
669             "application/dymola.sdf",
670             )
671         self.__url = ImportDetector( Filename, Format)
672         self.__url.raise_error_if_not_local_file()
673         self._filename = self.__url.get_absolute_name()
674         #
675         self._format = self.__url.get_comprehensive_mime()
676         #
677         self.__header, self._varsline, self._skiprows = self.__getentete()
678         #
679         if self._format == "text/csv" or Format.upper() == "CSV":
680             self._format = "text/csv"
681             self.__filestring = "".join(self.__header)
682             if self.__filestring.count(",") > 1:
683                 self._delimiter = ","
684             elif self.__filestring.count(";") > 1:
685                 self._delimiter = ";"
686         elif self._format == "text/tab-separated-values" or Format.upper() == "TSV":
687             self._format = "text/tab-separated-values"
688             self._delimiter = "\t"
689         else:
690             self._delimiter = None
691         #
692         if ColNames is not None: self._colnames = tuple(ColNames)
693         else:                    self._colnames = None
694         #
695         if ColIndex is not None: self._colindex = str(ColIndex)
696         else:                    self._colindex = None
697         #
698         self.__allowvoid = bool(AllowVoidNameList)
699
700     def __getentete(self, __nblines = 3):
701         "Lit l'entête du fichier pour trouver la définition des variables"
702         __header, __varsline, __skiprows = [], "", 1
703         if self._format in self.__binaryformats:
704             pass
705         else:
706             with open(self._filename,'r') as fid:
707                 __line = fid.readline().strip()
708                 while "#" in __line or len(__line) < 1:
709                     __header.append(__line)
710                     __skiprows += 1
711                     __line = fid.readline().strip()
712                 __varsline = __line # Première ligne non commentée non vide
713                 for i in range(max(0,__nblines)):
714                     __header.append(fid.readline())
715         return (__header, __varsline, __skiprows)
716
717     def __getindices(self, __colnames, __colindex, __delimiter=None ):
718         "Indices de colonnes correspondants à l'index et aux variables"
719         if __delimiter is None:
720             __varserie = self._varsline.strip('#').strip().split()
721         else:
722             __varserie = self._varsline.strip('#').strip().split(str(__delimiter))
723         #
724         if __colnames is not None:
725             __usecols = []
726             __colnames = tuple(__colnames)
727             for v in __colnames:
728                 for i, n in enumerate(__varserie):
729                     if v == n: __usecols.append(i)
730             __usecols = tuple(__usecols)
731             if len(__usecols) == 0:
732                 if self.__allowvoid:
733                     __usecols = None
734                 else:
735                     raise ValueError("Can not found any column corresponding to the required names %s"%(__colnames,))
736         else:
737             __usecols = None
738         #
739         if __colindex is not None:
740             __useindex = None
741             __colindex = str(__colindex)
742             for i, n in enumerate(__varserie):
743                 if __colindex == n: __useindex = i
744         else:
745             __useindex = None
746         #
747         return (__usecols, __useindex)
748
749     def getsupported(self):
750         self.__supportedformats = {}
751         self.__supportedformats["text/plain"]                = True
752         self.__supportedformats["text/csv"]                  = True
753         self.__supportedformats["text/tab-separated-values"] = True
754         self.__supportedformats["application/numpy.npy"]     = True
755         self.__supportedformats["application/numpy.npz"]     = True
756         self.__supportedformats["application/dymola.sdf"]    = PlatformInfo.has_sdf
757         return self.__supportedformats
758
759     def getvalue(self, ColNames=None, ColIndex=None ):
760         "Renvoie la ou les variables demandees par la liste de leurs noms"
761         # Uniquement si mise à jour
762         if ColNames is not None: self._colnames = tuple(ColNames)
763         if ColIndex is not None: self._colindex = str(ColIndex)
764         #
765         __index = None
766         if self._format == "application/numpy.npy":
767             __columns = numpy.load(self._filename)
768         #
769         elif self._format == "application/numpy.npz":
770             __columns = None
771             with numpy.load(self._filename) as __allcolumns:
772                 if self._colnames is None:
773                     self._colnames = __allcolumns.files
774                 for nom in self._colnames:
775                     if nom in __allcolumns.files:
776                         if __columns is not None:
777                             # Attention : toutes les variables doivent avoir la même taille
778                             __columns = numpy.vstack((__columns, numpy.reshape(__allcolumns[nom], (1,-1))))
779                         else:
780                             # Première colonne
781                             __columns = numpy.reshape(__allcolumns[nom], (1,-1))
782                 if self._colindex is not None and self._colindex in __allcolumns.files:
783                     __index = numpy.array(numpy.reshape(__allcolumns[self._colindex], (1,-1)), dtype=bytes)
784         elif self._format == "text/plain":
785             __usecols, __useindex = self.__getindices(self._colnames, self._colindex)
786             __columns = numpy.loadtxt(self._filename, usecols = __usecols, skiprows=self._skiprows)
787             if __useindex is not None:
788                 __index = numpy.loadtxt(self._filename, dtype = bytes, usecols = (__useindex,), skiprows=self._skiprows)
789         #
790         elif self._format == "application/dymola.sdf" and PlatformInfo.has_sdf:
791             import sdf
792             __content = sdf.load(self._filename)
793             __columns = None
794             if self._colnames is None:
795                 self._colnames = [__content.datasets[i].name for i in range(len(__content.datasets))]
796             for nom in self._colnames:
797                 if nom in __content:
798                     if __columns is not None:
799                         # Attention : toutes les variables doivent avoir la même taille
800                         __columns = numpy.vstack((__columns, numpy.reshape(__content[nom].data, (1,-1))))
801                     else:
802                         # Première colonne
803                         __columns = numpy.reshape(__content[nom].data, (1,-1))
804             if self._colindex is not None and self._colindex in __content:
805                 __index = __content[self._colindex].data
806         #
807         elif self._format == "text/csv":
808             __usecols, __useindex = self.__getindices(self._colnames, self._colindex, self._delimiter)
809             __columns = numpy.loadtxt(self._filename, usecols = __usecols, delimiter = self._delimiter, skiprows=self._skiprows)
810             if __useindex is not None:
811                 __index = numpy.loadtxt(self._filename, dtype = bytes, usecols = (__useindex,), delimiter = self._delimiter, skiprows=self._skiprows)
812         #
813         elif self._format == "text/tab-separated-values":
814             __usecols, __useindex = self.__getindices(self._colnames, self._colindex, self._delimiter)
815             __columns = numpy.loadtxt(self._filename, usecols = __usecols, delimiter = self._delimiter, skiprows=self._skiprows)
816             if __useindex is not None:
817                 __index = numpy.loadtxt(self._filename, dtype = bytes, usecols = (__useindex,), delimiter = self._delimiter, skiprows=self._skiprows)
818         else:
819             raise ValueError("Unkown file format \"%s\" or no reader available"%self._format)
820         if __columns is None: __columns = ()
821         #
822         def toString(value):
823             try:
824                 return value.decode()
825             except ValueError:
826                 return value
827         if __index is not None:
828             __index = tuple([toString(v) for v in __index])
829         #
830         return (self._colnames, __columns, self._colindex, __index)
831
832     def getstring(self):
833         "Renvoie le fichier texte complet"
834         if self._format in self.__binaryformats:
835             return ""
836         else:
837             with open(self._filename,'r') as fid:
838                 return fid.read()
839
840     def getformat(self):
841         return self._format
842
843 # ==============================================================================
844 class ImportScalarLinesFromFile(ImportFromFile):
845     """
846     Importation de fichier contenant des variables scalaires nommées. Le
847     fichier comporte soit 2, soit 4 colonnes, obligatoirement nommées "Name",
848     "Value", "Minimum", "Maximum" si les noms sont précisés. Sur chaque ligne
849     est indiqué le nom, la valeur, et éventuelement deux bornes min et max (ou
850     None si nécessaire pour une borne).
851
852     Seule la méthode "getvalue" est changée.
853     """
854     def __enter__(self): return self
855     def __exit__(self, exc_type, exc_val, exc_tb): return False
856     #
857     def __init__(self, Filename=None, ColNames=None, ColIndex=None, Format="Guess"):
858         ImportFromFile.__init__(self, Filename, ColNames, ColIndex, Format)
859         if self._format not in ["text/plain", "text/csv", "text/tab-separated-values"]:
860             raise ValueError("Unkown file format \"%s\""%self._format)
861     #
862     def getvalue(self, VarNames = None, HeaderNames=()):
863         "Renvoie la ou les variables demandees par la liste de leurs noms"
864         if VarNames is not None: __varnames = tuple(VarNames)
865         else:                    __varnames = None
866         #
867         if "Name" in self._varsline and "Value" in self._varsline and "Minimum" in self._varsline and "Maximum" in self._varsline:
868             __ftype = "NamValMinMax"
869             __dtypes   = {'names'  : ('Name', 'Value', 'Minimum', 'Maximum'),
870                           'formats': ('S128', 'g', 'g', 'g')}
871             __usecols  = (0, 1, 2, 3)
872             def __replaceNoneN( s ):
873                 if s.strip() == b'None': return numpy.NINF
874                 else:                    return s
875             def __replaceNoneP( s ):
876                 if s.strip() == b'None': return numpy.PINF
877                 else:                    return s
878             __converters = {2: __replaceNoneN, 3: __replaceNoneP}
879         elif "Name" in self._varsline and "Value" in self._varsline and ("Minimum" not in self._varsline or "Maximum" not in self._varsline):
880             __ftype = "NamVal"
881             __dtypes   = {'names'  : ('Name', 'Value'),
882                           'formats': ('S128', 'g')}
883             __converters = None
884             __usecols  = (0, 1)
885         elif len(HeaderNames)>0 and numpy.all([kw in self._varsline for kw in HeaderNames]):
886             __ftype = "NamLotOfVals"
887             __dtypes   = {'names'  : HeaderNames,
888                           'formats': tuple(['S128',]+['g']*(len(HeaderNames)-1))}
889             __usecols  = tuple(range(len(HeaderNames)))
890             def __replaceNone( s ):
891                 if s.strip() == b'None': return numpy.NAN
892                 else:                    return s
893             __converters = dict()
894             for i in range(1,len(HeaderNames)):
895                 __converters[i] = __replaceNone
896         else:
897             raise ValueError("Can not find names of columns for initial values. Wrong first line is:\n            \"%s\""%__firstline)
898         #
899         if self._format == "text/plain":
900             __content = numpy.loadtxt(self._filename, dtype = __dtypes, usecols = __usecols, skiprows = self._skiprows, converters = __converters)
901         elif self._format in ["text/csv", "text/tab-separated-values"]:
902             __content = numpy.loadtxt(self._filename, dtype = __dtypes, usecols = __usecols, skiprows = self._skiprows, converters = __converters, delimiter = self._delimiter)
903         else:
904             raise ValueError("Unkown file format \"%s\""%self._format)
905         #
906         __names, __thevalue, __bounds = [], [], []
907         for sub in __content:
908             if len(__usecols) == 4:
909                 na, va, mi, ma = sub
910                 if numpy.isneginf(mi): mi = None # Réattribue les variables None
911                 elif numpy.isnan(mi):  mi = None # Réattribue les variables None
912                 if numpy.isposinf(ma): ma = None # Réattribue les variables None
913                 elif numpy.isnan(ma):  ma = None # Réattribue les variables None
914             elif len(__usecols) == 2 and __ftype == "NamVal":
915                 na, va = sub
916                 mi, ma = None, None
917             else:
918                 nsub = list(sub)
919                 na = sub[0]
920                 for i, v in enumerate(nsub[1:]):
921                     if numpy.isnan(v): nsub[i+1] = None
922                 va = nsub[1:]
923                 mi, ma = None, None
924             na = na.decode()
925             if (__varnames is None or na in __varnames) and (na not in __names):
926                 # Ne stocke que la premiere occurence d'une variable
927                 __names.append(na)
928                 __thevalue.append(va)
929                 __bounds.append((mi,ma))
930         #
931         __names      = tuple(__names)
932         __thevalue = numpy.array(__thevalue)
933         __bounds     = tuple(__bounds)
934         #
935         return (__names, __thevalue, __bounds)
936
937 # ==============================================================================
938 if __name__ == "__main__":
939     print('\n AUTODIAGNOSTIC \n')