Salome HOME
5a47dcfb71fa7d87b8031495e4f48a70beee84b7
[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, DataFile, Template, ScriptWithOneFunction, ScriptWithFunctions
264                         __ifrom = __idata['FROM']
265                         __idata.pop('FROM','')
266                         if __ifrom == 'String' or __ifrom == 'Template':
267                             __argumentsList.append([__itype,__idata['STRING']])
268                         if __ifrom == 'Script':
269                             __argumentsList.append([__itype,True])
270                             __argumentsList.append(['Script',__idata['SCRIPT_FILE']])
271                         if __ifrom == 'DataFile':
272                             __argumentsList.append([__itype,True])
273                             __argumentsList.append(['DataFile',__idata['DATA_FILE']])
274                         if __ifrom == 'ScriptWithOneFunction':
275                             __argumentsList.append(['OneFunction',True])
276                             __argumentsList.append(['Script',__idata.pop('SCRIPTWITHONEFUNCTION_FILE')])
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 and __local['Script'] is not None: continue
365                 if __k in ['Vector','VectorSerie'] and 'DataFile' in __local and __local['DataFile'] is not None: continue
366                 if __k == 'Algorithm':
367                     __text += "study_config['Algorithm'] = %s\n"%(repr(__v))
368                 elif __k == 'DataFile':
369                     __k = 'Vector'
370                     __f = 'DataFile'
371                     __v = "'"+repr(__v)+"'"
372                     for __lk in ['Vector','VectorSerie']:
373                         if __lk in __local and __local[__lk]: __k = __lk
374                     __text += "%s_config['Type'] = '%s'\n"%(__command,__k)
375                     __text += "%s_config['From'] = '%s'\n"%(__command,__f)
376                     __text += "%s_config['Data'] = %s\n"%(__command,__v)
377                     __text = __text.replace("''","'")
378                 elif __k == 'Script':
379                     __k = 'Vector'
380                     __f = 'Script'
381                     __v = "'"+repr(__v)+"'"
382                     for __lk in ['ScalarSparseMatrix','DiagonalSparseMatrix','Matrix']:
383                         if __lk in __local and __local[__lk]: __k = __lk
384                     if __command == "AlgorithmParameters": __k = "Dict"
385                     if 'OneFunction' in __local and __local['OneFunction']:
386                         __text += "%s_ScriptWithOneFunction = {}\n"%(__command,)
387                         __text += "%s_ScriptWithOneFunction['Function'] = ['Direct', 'Tangent', 'Adjoint']\n"%(__command,)
388                         __text += "%s_ScriptWithOneFunction['Script'] = {}\n"%(__command,)
389                         __text += "%s_ScriptWithOneFunction['Script']['Direct'] = %s\n"%(__command,__v)
390                         __text += "%s_ScriptWithOneFunction['Script']['Tangent'] = %s\n"%(__command,__v)
391                         __text += "%s_ScriptWithOneFunction['Script']['Adjoint'] = %s\n"%(__command,__v)
392                         __text += "%s_ScriptWithOneFunction['DifferentialIncrement'] = 1e-06\n"%(__command,)
393                         __text += "%s_ScriptWithOneFunction['CenteredFiniteDifference'] = 0\n"%(__command,)
394                         __k = 'Function'
395                         __f = 'ScriptWithOneFunction'
396                         __v = '%s_ScriptWithOneFunction'%(__command,)
397                     if 'ThreeFunctions' in __local and __local['ThreeFunctions']:
398                         __text += "%s_ScriptWithFunctions = {}\n"%(__command,)
399                         __text += "%s_ScriptWithFunctions['Function'] = ['Direct', 'Tangent', 'Adjoint']\n"%(__command,)
400                         __text += "%s_ScriptWithFunctions['Script'] = {}\n"%(__command,)
401                         __text += "%s_ScriptWithFunctions['Script']['Direct'] = %s\n"%(__command,__v)
402                         __text += "%s_ScriptWithFunctions['Script']['Tangent'] = %s\n"%(__command,__v)
403                         __text += "%s_ScriptWithFunctions['Script']['Adjoint'] = %s\n"%(__command,__v)
404                         __k = 'Function'
405                         __f = 'ScriptWithFunctions'
406                         __v = '%s_ScriptWithFunctions'%(__command,)
407                     __text += "%s_config['Type'] = '%s'\n"%(__command,__k)
408                     __text += "%s_config['From'] = '%s'\n"%(__command,__f)
409                     __text += "%s_config['Data'] = %s\n"%(__command,__v)
410                     __text = __text.replace("''","'")
411                 elif __k in ('Stored', 'Checked', 'ColMajor', 'InputFunctionAsMulti', 'nextStep'):
412                     if bool(__v):
413                         __text += "%s_config['%s'] = '%s'\n"%(__command,__k,int(bool(__v)))
414                 elif __k in ('AvoidRC', 'noDetails'):
415                     if not bool(__v):
416                         __text += "%s_config['%s'] = '%s'\n"%(__command,__k,int(bool(__v)))
417                 else:
418                     if __k == 'Parameters': __k = "Dict"
419                     if isinstance(__v,Persistence.Persistence): __v = __v.values()
420                     if callable(__v): __text = self._missing%__v.__name__+__text
421                     if isinstance(__v,dict):
422                         for val in __v.values():
423                             if callable(val): __text = self._missing%val.__name__+__text
424                     __text += "%s_config['Type'] = '%s'\n"%(__command,__k)
425                     __text += "%s_config['From'] = '%s'\n"%(__command,'String')
426                     __text += "%s_config['Data'] = \"\"\"%s\"\"\"\n"%(__command,repr(__v))
427             __text += "study_config['%s'] = %s_config"%(__command,__command)
428             numpy.set_printoptions(precision=8,threshold=1000,linewidth=75)
429             if __switchoff:
430                 self._switchoff = True
431         if __text is not None: self._addLine(__text)
432         if not __switchoff:
433             self._switchoff = False
434     def _finalize(self, *__args):
435         self.__loadVariablesByScript()
436         self._addLine("#")
437         self._addLine("Analysis_config = {}")
438         self._addLine("Analysis_config['From'] = 'String'")
439         self._addLine("Analysis_config['Data'] = \"\"\"import numpy")
440         self._addLine("xa=numpy.ravel(ADD.get('Analysis')[-1])")
441         self._addLine("print('Analysis:',xa)\"\"\"")
442         self._addLine("study_config['UserPostAnalysis'] = Analysis_config")
443     def __loadVariablesByScript(self):
444         __ExecVariables = {} # Necessaire pour recuperer la variable
445         exec("\n".join(self._lineSerie), __ExecVariables)
446         study_config = __ExecVariables['study_config']
447         # Pour Python 3 : self.__hasAlgorithm = bool(study_config['Algorithm'])
448         if 'Algorithm' in study_config:
449             self.__hasAlgorithm = True
450         else:
451             self.__hasAlgorithm = False
452         if not self.__hasAlgorithm and \
453                 "AlgorithmParameters" in study_config and \
454                 isinstance(study_config['AlgorithmParameters'], dict) and \
455                 "From" in study_config['AlgorithmParameters'] and \
456                 "Data" in study_config['AlgorithmParameters'] and \
457                 study_config['AlgorithmParameters']['From'] == 'Script':
458             __asScript = study_config['AlgorithmParameters']['Data']
459             __var = ImportFromScript(__asScript).getvalue( "Algorithm" )
460             __text = "#\nstudy_config['Algorithm'] = '%s'"%(__var,)
461             self._addLine(__text)
462         if self.__hasAlgorithm and \
463                 "AlgorithmParameters" in study_config and \
464                 isinstance(study_config['AlgorithmParameters'], dict) and \
465                 "From" not in study_config['AlgorithmParameters'] and \
466                 "Data" not in study_config['AlgorithmParameters']:
467             __text  = "#\n"
468             __text += "AlgorithmParameters_config['Type'] = 'Dict'\n"
469             __text += "AlgorithmParameters_config['From'] = 'String'\n"
470             __text += "AlgorithmParameters_config['Data'] = '{}'\n"
471             self._addLine(__text)
472         del study_config
473
474 class _YACSViewer(GenericCaseViewer):
475     """
476     Etablissement des commandes d'un cas YACS (Cas->SCD->YACS)
477     """
478     def __init__(self, __name="", __objname="case", __content=None, __object=None):
479         "Initialisation et enregistrement de l'entete"
480         GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
481         self.__internalSCD = _SCDViewer(__name, __objname, __content, __object)
482         self._append       = self.__internalSCD._append
483     def dump(self, __filename=None, __upa=None):
484         "Restitution normalisée des commandes"
485         # -----
486         if __filename is None:
487             raise ValueError("A file name has to be given for YACS XML output.")
488         else:
489             __file    = os.path.abspath(__filename)
490             if os.path.isfile(__file) or os.path.islink(__file):
491                 os.remove(__file)
492         # -----
493         if not PlatformInfo.has_salome or \
494             not PlatformInfo.has_adao:
495             raise ImportError(
496                 "Unable to get SALOME or ADAO environnement variables for YACS conversion.\n"+\
497                 "Please load the right environnement before trying to use it.")
498         else:
499             from daYacsSchemaCreator.run import create_schema_from_content
500         # -----
501         self.__internalSCD._finalize(__upa)
502         __SCDdump = self.__internalSCD.dump()
503         create_schema_from_content(__SCDdump, __file)
504         # -----
505         if not os.path.exists(__file):
506             __msg  = "An error occured during the ADAO YACS Schema build for\n"
507             __msg += "the target output file:\n"
508             __msg += "  %s\n"%__file
509             __msg += "See errors details in your launching terminal log.\n"
510             raise ValueError(__msg)
511         # -----
512         __fid = open(__file,"r")
513         __text = __fid.read()
514         __fid.close()
515         return __text
516
517 # ==============================================================================
518 class ImportFromScript(object):
519     """
520     Obtention d'une variable nommee depuis un fichier script importé
521     """
522     __slots__ = ("__basename", "__filenspace", "__filestring")
523     def __init__(self, __filename=None):
524         "Verifie l'existence et importe le script"
525         if __filename is None:
526             raise ValueError("The name of the file, containing the variable to be read, has to be specified.")
527         if not os.path.isfile(__filename):
528             raise ValueError("The file containing the variable to be imported doesn't seem to exist. Please check the file. The given file name is:\n  \"%s\""%str(__filename))
529         if os.path.dirname(__filename) != '':
530             sys.path.insert(0, os.path.dirname(__filename))
531             __basename = os.path.basename(__filename).rstrip(".py")
532         else:
533             __basename = __filename.rstrip(".py")
534         PlatformInfo.checkFileNameImportability( __basename+".py" )
535         self.__basename = __basename
536         self.__filenspace = __import__(__basename, globals(), locals(), [])
537         self.__filestring = open(__filename,'r').read()
538     def getvalue(self, __varname=None, __synonym=None ):
539         "Renvoie la variable demandee par son nom ou son synonyme"
540         if __varname is None:
541             raise ValueError("The name of the variable to be read has to be specified. Please check the content of the file and the syntax.")
542         if not hasattr(self.__filenspace, __varname):
543             if __synonym is None:
544                 raise ValueError("The imported script file \"%s\" doesn't contain the mandatory variable \"%s\" to be read. Please check the content of the file and the syntax."%(str(self.__basename)+".py",__varname))
545             elif not hasattr(self.__filenspace, __synonym):
546                 raise ValueError("The imported script file \"%s\" doesn't contain the mandatory variable \"%s\" to be read. Please check the content of the file and the syntax."%(str(self.__basename)+".py",__synonym))
547             else:
548                 return getattr(self.__filenspace, __synonym)
549         else:
550             return getattr(self.__filenspace, __varname)
551     def getstring(self):
552         "Renvoie le script complet"
553         return self.__filestring
554
555 # ==============================================================================
556 class ImportDetector(object):
557     """
558     Détection des caractéristiques de fichiers ou objets en entrée
559     """
560     __slots__ = (
561         "__url", "__usr", "__root", "__end")
562     def __enter__(self): return self
563     def __exit__(self, exc_type, exc_val, exc_tb): return False
564     #
565     def __init__(self, __url, UserMime=""):
566         if __url is None:
567             raise ValueError("The name or url of the file object has to be specified.")
568         if __url is bytes:
569             self.__url = __url.decode()
570         else:
571             self.__url = str(__url)
572         if UserMime is bytes:
573             self.__usr = UserMime.decode().lower()
574         else:
575             self.__usr = str(UserMime).lower()
576         (self.__root, self.__end) = os.path.splitext(self.__url)
577         #
578         mimetypes.add_type('application/numpy.npy', '.npy')
579         mimetypes.add_type('application/numpy.npz', '.npz')
580         mimetypes.add_type('application/dymola.sdf', '.sdf')
581         if sys.platform.startswith("win"):
582             mimetypes.add_type('text/plain', '.txt')
583             mimetypes.add_type('text/csv', '.csv')
584             mimetypes.add_type('text/tab-separated-values', '.tsv')
585     #
586     # File related tests
587     # ------------------
588     def is_local_file(self):
589         if os.path.isfile(os.path.realpath(self.__url)):
590             return True
591         else:
592             return False
593     def is_not_local_file(self):
594         if not os.path.isfile(os.path.realpath(self.__url)):
595             return True
596         else:
597             return False
598     def raise_error_if_not_local_file(self):
599         if not os.path.isfile(os.path.realpath(self.__url)):
600             raise ValueError("The name or the url of the file object doesn't seem to exist. The given name is:\n  \"%s\""%str(self.__url))
601         else:
602             return False
603     #
604     # Directory related tests
605     # -----------------------
606     def is_local_dir(self):
607         if os.path.isdir(self.__url):
608             return True
609         else:
610             return False
611     def is_not_local_dir(self):
612         if not os.path.isdir(self.__url):
613             return True
614         else:
615             return False
616     def raise_error_if_not_local_dir(self):
617         if not os.path.isdir(self.__url):
618             raise ValueError("The name or the url of the directory object doesn't seem to exist. The given name is:\n  \"%s\""%str(self.__url))
619         else:
620             return False
621     #
622     # Mime related functions
623     # ------------------------
624     def get_standard_mime(self):
625         (__mtype, __encoding) = mimetypes.guess_type(self.__url, strict=False)
626         return __mtype
627     def get_user_mime(self):
628         __fake = "fake."+self.__usr.lower()
629         (__mtype, __encoding) = mimetypes.guess_type(__fake, strict=False)
630         return __mtype
631     def get_comprehensive_mime(self):
632         if self.get_standard_mime() is not None:
633             return self.get_standard_mime()
634         elif self.get_user_mime() is not None:
635             return self.get_user_mime()
636         else:
637             return None
638     #
639     # Name related functions
640     # ----------------------
641     def get_user_name(self):
642         return self.__url
643     def get_absolute_name(self):
644         return os.path.abspath(os.path.realpath(self.__url))
645     def get_extension(self):
646         return self.__end
647
648 class ImportFromFile(object):
649     """
650     Obtention de variables disrétisées en 1D, définies par une ou des variables
651     nommées, et sous la forme d'une série de points éventuellement indexés. La
652     lecture d'un fichier au format spécifié (ou intuité) permet de charger ces
653     fonctions depuis :
654         - des fichiers textes en colonnes de type TXT, CSV, TSV...
655         - des fichiers de données binaires NPY, NPZ, SDF...
656     La lecture du fichier complet ne se fait que si nécessaire, pour assurer la
657     performance tout en disposant de l'interprétation du contenu. Les fichiers
658     textes doivent présenter en première ligne (hors commentaire ou ligne vide)
659     les noms des variables de colonnes. Les commentaires commencent par un "#".
660     """
661     __slots__ = (
662         "_filename", "_colnames", "_colindex", "_varsline", "_format",
663         "_delimiter", "_skiprows", "__url", "__filestring", "__header",
664         "__allowvoid", "__binaryformats", "__supportedformats")
665     def __enter__(self): return self
666     def __exit__(self, exc_type, exc_val, exc_tb): return False
667     #
668     def __init__(self, Filename=None, ColNames=None, ColIndex=None, Format="Guess", AllowVoidNameList=True):
669         """
670         Verifie l'existence et les informations de définition du fichier. Les
671         noms de colonnes ou de variables sont ignorées si le format ne permet
672         pas de les indiquer.
673         Arguments :
674             - Filename : nom du fichier
675             - ColNames : noms de la ou des colonnes/variables à lire
676             - ColIndex : nom unique de la colonne/variable servant d'index
677             - Format : format du fichier et/ou des données inclues
678             - AllowVoidNameList : permet, si la liste de noms est vide, de
679               prendre par défaut toutes les colonnes
680         """
681         self.__binaryformats =(
682             "application/numpy.npy",
683             "application/numpy.npz",
684             "application/dymola.sdf",
685             )
686         self.__url = ImportDetector( Filename, Format)
687         self.__url.raise_error_if_not_local_file()
688         self._filename = self.__url.get_absolute_name()
689         PlatformInfo.checkFileNameConformity( self._filename )
690         #
691         self._format = self.__url.get_comprehensive_mime()
692         #
693         self.__header, self._varsline, self._skiprows = self.__getentete()
694         #
695         if self._format == "text/csv" or Format.upper() == "CSV":
696             self._format = "text/csv"
697             self.__filestring = "".join(self.__header)
698             if self.__filestring.count(",") > 1:
699                 self._delimiter = ","
700             elif self.__filestring.count(";") > 1:
701                 self._delimiter = ";"
702             else:
703                 self._delimiter = None
704         elif self._format == "text/tab-separated-values" or Format.upper() == "TSV":
705             self._format = "text/tab-separated-values"
706             self._delimiter = "\t"
707         else:
708             self._delimiter = None
709         #
710         if ColNames is not None: self._colnames = tuple(ColNames)
711         else:                    self._colnames = None
712         #
713         if ColIndex is not None: self._colindex = str(ColIndex)
714         else:                    self._colindex = None
715         #
716         self.__allowvoid = bool(AllowVoidNameList)
717
718     def __getentete(self, __nblines = 3):
719         "Lit l'entête du fichier pour trouver la définition des variables"
720         # La première ligne non vide non commentée est toujours considérée
721         # porter les labels de colonne, donc pas des valeurs
722         __header, __varsline, __skiprows = [], "", 1
723         if self._format in self.__binaryformats:
724             pass
725         else:
726             with open(self._filename,'r') as fid:
727                 __line = fid.readline().strip()
728                 while "#" in __line or len(__line) < 1:
729                     __header.append(__line)
730                     __skiprows += 1
731                     __line = fid.readline().strip()
732                 __varsline = __line
733                 for i in range(max(0,__nblines)):
734                     __header.append(fid.readline())
735         return (__header, __varsline, __skiprows)
736
737     def __getindices(self, __colnames, __colindex, __delimiter=None ):
738         "Indices de colonnes correspondants à l'index et aux variables"
739         if __delimiter is None:
740             __varserie = self._varsline.strip('#').strip().split()
741         else:
742             __varserie = self._varsline.strip('#').strip().split(str(__delimiter))
743         #
744         if __colnames is not None:
745             __usecols = []
746             __colnames = tuple(__colnames)
747             for v in __colnames:
748                 for i, n in enumerate(__varserie):
749                     if v == n: __usecols.append(i)
750             __usecols = tuple(__usecols)
751             if len(__usecols) == 0:
752                 if self.__allowvoid:
753                     __usecols = None
754                 else:
755                     raise ValueError("Can not found any column corresponding to the required names %s"%(__colnames,))
756         else:
757             __usecols = None
758         #
759         if __colindex is not None:
760             __useindex = None
761             __colindex = str(__colindex)
762             for i, n in enumerate(__varserie):
763                 if __colindex == n: __useindex = i
764         else:
765             __useindex = None
766         #
767         return (__usecols, __useindex)
768
769     def getsupported(self):
770         self.__supportedformats = {}
771         self.__supportedformats["text/plain"]                = True
772         self.__supportedformats["text/csv"]                  = True
773         self.__supportedformats["text/tab-separated-values"] = True
774         self.__supportedformats["application/numpy.npy"]     = True
775         self.__supportedformats["application/numpy.npz"]     = True
776         self.__supportedformats["application/dymola.sdf"]    = PlatformInfo.has_sdf
777         return self.__supportedformats
778
779     def getvalue(self, ColNames=None, ColIndex=None ):
780         "Renvoie la ou les variables demandees par la liste de leurs noms"
781         # Uniquement si mise à jour
782         if ColNames is not None: self._colnames = tuple(ColNames)
783         if ColIndex is not None: self._colindex = str(ColIndex)
784         #
785         __index = None
786         if self._format == "application/numpy.npy":
787             __columns = numpy.load(self._filename)
788         #
789         elif self._format == "application/numpy.npz":
790             __columns = None
791             with numpy.load(self._filename) as __allcolumns:
792                 if self._colnames is None:
793                     self._colnames = __allcolumns.files
794                 for nom in self._colnames: # Si une variable demandée n'existe pas
795                     if nom not in __allcolumns.files:
796                         self._colnames = tuple( __allcolumns.files )
797                 for nom in self._colnames:
798                     if nom in __allcolumns.files:
799                         if __columns is not None:
800                             # Attention : toutes les variables doivent avoir la même taille
801                             __columns = numpy.vstack((__columns, numpy.reshape(__allcolumns[nom], (1,-1))))
802                         else:
803                             # Première colonne
804                             __columns = numpy.reshape(__allcolumns[nom], (1,-1))
805                 if self._colindex is not None and self._colindex in __allcolumns.files:
806                     __index = numpy.array(numpy.reshape(__allcolumns[self._colindex], (1,-1)), dtype=bytes)
807         elif self._format == "text/plain":
808             __usecols, __useindex = self.__getindices(self._colnames, self._colindex)
809             __columns = numpy.loadtxt(self._filename, usecols = __usecols, skiprows=self._skiprows)
810             if __useindex is not None:
811                 __index = numpy.loadtxt(self._filename, dtype = bytes, usecols = (__useindex,), skiprows=self._skiprows)
812             if __usecols is None: # Si une variable demandée n'existe pas
813                 self._colnames = None
814         #
815         elif self._format == "application/dymola.sdf" and PlatformInfo.has_sdf:
816             import sdf
817             __content = sdf.load(self._filename)
818             __columns = None
819             if self._colnames is None:
820                 self._colnames = [__content.datasets[i].name for i in range(len(__content.datasets))]
821             for nom in self._colnames:
822                 if nom in __content:
823                     if __columns is not None:
824                         # Attention : toutes les variables doivent avoir la même taille
825                         __columns = numpy.vstack((__columns, numpy.reshape(__content[nom].data, (1,-1))))
826                     else:
827                         # Première colonne
828                         __columns = numpy.reshape(__content[nom].data, (1,-1))
829             if self._colindex is not None and self._colindex in __content:
830                 __index = __content[self._colindex].data
831         #
832         elif self._format == "text/csv":
833             __usecols, __useindex = self.__getindices(self._colnames, self._colindex, self._delimiter)
834             __columns = numpy.loadtxt(self._filename, usecols = __usecols, delimiter = self._delimiter, skiprows=self._skiprows)
835             if __useindex is not None:
836                 __index = numpy.loadtxt(self._filename, dtype = bytes, usecols = (__useindex,), delimiter = self._delimiter, skiprows=self._skiprows)
837             if __usecols is None: # Si une variable demandée n'existe pas
838                 self._colnames = None
839         #
840         elif self._format == "text/tab-separated-values":
841             __usecols, __useindex = self.__getindices(self._colnames, self._colindex, self._delimiter)
842             __columns = numpy.loadtxt(self._filename, usecols = __usecols, delimiter = self._delimiter, skiprows=self._skiprows)
843             if __useindex is not None:
844                 __index = numpy.loadtxt(self._filename, dtype = bytes, usecols = (__useindex,), delimiter = self._delimiter, skiprows=self._skiprows)
845             if __usecols is None: # Si une variable demandée n'existe pas
846                 self._colnames = None
847         else:
848             raise ValueError("Unkown file format \"%s\" or no reader available"%self._format)
849         if __columns is None: __columns = ()
850         #
851         def toString(value):
852             try:
853                 return value.decode()
854             except ValueError:
855                 return value
856         if __index is not None:
857             __index = tuple([toString(v) for v in __index])
858         #
859         return (self._colnames, __columns, self._colindex, __index)
860
861     def getstring(self):
862         "Renvoie le fichier texte complet"
863         if self._format in self.__binaryformats:
864             return ""
865         else:
866             with open(self._filename,'r') as fid:
867                 return fid.read()
868
869     def getformat(self):
870         return self._format
871
872 class ImportScalarLinesFromFile(ImportFromFile):
873     """
874     Importation de fichier contenant des variables scalaires nommées. Le
875     fichier comporte soit 2, soit 4 colonnes, obligatoirement nommées "Name",
876     "Value", "Minimum", "Maximum" si les noms sont précisés. Sur chaque ligne
877     est indiqué le nom, la valeur, et éventuelement deux bornes min et max (ou
878     None si nécessaire pour une borne).
879
880     Seule la méthode "getvalue" est changée.
881     """
882     def __enter__(self): return self
883     def __exit__(self, exc_type, exc_val, exc_tb): return False
884     #
885     def __init__(self, Filename=None, ColNames=None, ColIndex=None, Format="Guess"):
886         ImportFromFile.__init__(self, Filename, ColNames, ColIndex, Format)
887         if self._format not in ["text/plain", "text/csv", "text/tab-separated-values"]:
888             raise ValueError("Unkown file format \"%s\""%self._format)
889     #
890     def getvalue(self, VarNames = None, HeaderNames=()):
891         "Renvoie la ou les variables demandees par la liste de leurs noms"
892         if VarNames is not None: __varnames = tuple(VarNames)
893         else:                    __varnames = None
894         #
895         if "Name" in self._varsline and "Value" in self._varsline and "Minimum" in self._varsline and "Maximum" in self._varsline:
896             __ftype = "NamValMinMax"
897             __dtypes   = {'names'  : ('Name', 'Value', 'Minimum', 'Maximum'),
898                           'formats': ('S128', 'g', 'g', 'g')}
899             __usecols  = (0, 1, 2, 3)
900             def __replaceNoneN( s ):
901                 if s.strip() == b'None': return numpy.NINF
902                 else:                    return s
903             def __replaceNoneP( s ):
904                 if s.strip() == b'None': return numpy.PINF
905                 else:                    return s
906             __converters = {2: __replaceNoneN, 3: __replaceNoneP}
907         elif "Name" in self._varsline and "Value" in self._varsline and ("Minimum" not in self._varsline or "Maximum" not in self._varsline):
908             __ftype = "NamVal"
909             __dtypes   = {'names'  : ('Name', 'Value'),
910                           'formats': ('S128', 'g')}
911             __converters = None
912             __usecols  = (0, 1)
913         elif len(HeaderNames)>0 and numpy.all([kw in self._varsline for kw in HeaderNames]):
914             __ftype = "NamLotOfVals"
915             __dtypes   = {'names'  : HeaderNames,
916                           'formats': tuple(['S128',]+['g']*(len(HeaderNames)-1))}
917             __usecols  = tuple(range(len(HeaderNames)))
918             def __replaceNone( s ):
919                 if s.strip() == b'None': return numpy.NAN
920                 else:                    return s
921             __converters = dict()
922             for i in range(1,len(HeaderNames)):
923                 __converters[i] = __replaceNone
924         else:
925             raise ValueError("Can not find names of columns for initial values. Wrong first line is:\n            \"%s\""%__firstline)
926         #
927         if self._format == "text/plain":
928             __content = numpy.loadtxt(self._filename, dtype = __dtypes, usecols = __usecols, skiprows = self._skiprows, converters = __converters)
929         elif self._format in ["text/csv", "text/tab-separated-values"]:
930             __content = numpy.loadtxt(self._filename, dtype = __dtypes, usecols = __usecols, skiprows = self._skiprows, converters = __converters, delimiter = self._delimiter)
931         else:
932             raise ValueError("Unkown file format \"%s\""%self._format)
933         #
934         __names, __thevalue, __bounds = [], [], []
935         for sub in __content:
936             if len(__usecols) == 4:
937                 na, va, mi, ma = sub
938                 if numpy.isneginf(mi): mi = None # Réattribue les variables None
939                 elif numpy.isnan(mi):  mi = None # Réattribue les variables None
940                 if numpy.isposinf(ma): ma = None # Réattribue les variables None
941                 elif numpy.isnan(ma):  ma = None # Réattribue les variables None
942             elif len(__usecols) == 2 and __ftype == "NamVal":
943                 na, va = sub
944                 mi, ma = None, None
945             else:
946                 nsub = list(sub)
947                 na = sub[0]
948                 for i, v in enumerate(nsub[1:]):
949                     if numpy.isnan(v): nsub[i+1] = None
950                 va = nsub[1:]
951                 mi, ma = None, None
952             na = na.decode()
953             if (__varnames is None or na in __varnames) and (na not in __names):
954                 # Ne stocke que la premiere occurence d'une variable
955                 __names.append(na)
956                 __thevalue.append(va)
957                 __bounds.append((mi,ma))
958         #
959         __names      = tuple(__names)
960         __thevalue = numpy.array(__thevalue)
961         __bounds     = tuple(__bounds)
962         #
963         return (__names, __thevalue, __bounds)
964
965 # ==============================================================================
966 class EficasGUI(object):
967     """
968     Lancement autonome de l'interface EFICAS/ADAO
969     """
970     def __init__(self, __addpath = None):
971         # Chemin pour l'installation (ordre important)
972         if "EFICAS_ROOT" in os.environ:
973             __EFICAS_ROOT = os.environ["EFICAS_ROOT"]
974             __path_ok = True
975         else:
976             print("\nKeyError:\n"+\
977                 "  the required environment variable EFICAS_ROOT is unknown.\n"+\
978                 "  You have either to be in SALOME environment, or to set this\n"+\
979                 "  variable in your environment to the right path \"<...>\" to find\n"+\
980                 "  an installed EFICAS application. For example:\n"+\
981                 "    EFICAS_ROOT=\"<...>\" %s"%__file__
982                 )
983             __path_ok = False
984         try:
985             import adao
986             __path_ok = True
987         except ImportError:
988             print("\nImportError:\n"+\
989                 "  the required ADAO library can not be found to be imported.\n"+\
990                 "  You have either to be in ADAO environment, or to be in SALOME\n"+\
991                 "  environment, or to set manually in your Python 3 environment the\n"+\
992                 "  right path \"<...>\" to find an installed ADAO application. For\n"+\
993                 "  example:\n"+\
994                 "    PYTHONPATH=\"<...>:${PYTHONPATH}\" %s"%__file__
995                 )
996             __path_ok = False
997         try:
998             import PyQt5
999             __path_ok = True
1000         except ImportError:
1001             print("\nImportError:\n"+\
1002                 "  the required PyQt5 library can not be found to be imported.\n"+\
1003                 "  You have either to have a raisonable up-to-date Python 3\n"+\
1004                 "  installation (less than 5 years), or to be in SALOME environment."
1005                 )
1006             __path_ok = False
1007         if not __path_ok:
1008             print("\nWarning:\n"+\
1009                 "  It seems you have some troubles with your installation. It may\n"+\
1010                 "  exists other errors that are not explained as above, like some\n"+\
1011                 "  incomplete or obsolete Python 3 and module installation.\n"+\
1012                 "  \n"+\
1013                 "  Please correct the above error(s) before launching the\n"+\
1014                 "  standalone EFICAS/ADAO interface \"%s\"\n"%__file__
1015                   )
1016             sys.exit(2)
1017         else:
1018             logging.debug("All the ADAO/EFICAS/QT5 paths have been found")
1019         sys.path.insert(0,__EFICAS_ROOT)
1020         sys.path.insert(0,os.path.join(adao.adao_py_dir,"daEficas"))
1021         if __addpath is not None and os.path.exists(os.path.abspath(__addpath)):
1022             sys.path.insert(0,os.path.abspath(__addpath))
1023         logging.debug("All the paths have been correctly set up")
1024         #
1025     def gui(self):
1026         logging.debug("Launching the standalone EFICAS/ADAO interface...")
1027         from daEficas import prefs
1028         from InterfaceQT4 import eficas_go
1029         eficas_go.lanceEficas(code=prefs.code)
1030
1031 # ==============================================================================
1032 if __name__ == "__main__":
1033     print('\n AUTODIAGNOSTIC\n')