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