Salome HOME
Minor documentation review corrections (6)
[modules/adao.git] / src / daComposant / daCore / Interfaces.py
1 # -*- coding: utf-8 -*-
2 #
3 # Copyright (C) 2008-2021 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 from daCore import Reporting
39
40 # ==============================================================================
41 class GenericCaseViewer(object):
42     """
43     Gestion des commandes de création d'une vue de cas
44     """
45     def __init__(self, __name="", __objname="case", __content=None, __object=None):
46         "Initialisation et enregistrement de l'entete"
47         self._name         = str(__name)
48         self._objname      = str(__objname)
49         self._lineSerie    = []
50         self._switchoff    = False
51         self._numobservers = 2
52         self._content      = __content
53         self._object       = __object
54         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# """
55     def _append(self, *args):
56         "Transformation d'une commande individuelle en un enregistrement"
57         raise NotImplementedError()
58     def _extract(self, *args):
59         "Transformation d'enregistrement(s) en commande(s) individuelle(s)"
60         raise NotImplementedError()
61     def _finalize(self, __upa=None):
62         "Enregistrement du final"
63         __hasNotExecute = True
64         for l in self._lineSerie:
65             if "%s.execute"%(self._objname,) in l: __hasNotExecute = False
66         if __hasNotExecute:
67             self._lineSerie.append("%s.execute()"%(self._objname,))
68         if __upa is not None and len(__upa)>0:
69             __upa = __upa.replace("ADD.",str(self._objname)+".")
70             self._lineSerie.append(__upa)
71     def _addLine(self, line=""):
72         "Ajoute un enregistrement individuel"
73         self._lineSerie.append(line)
74     def _get_objname(self):
75         return self._objname
76     def dump(self, __filename=None, __upa=None):
77         "Restitution normalisée des commandes"
78         self._finalize(__upa)
79         __text = "\n".join(self._lineSerie)
80         __text +="\n"
81         if __filename is not None:
82             __file = os.path.abspath(__filename)
83             __fid = open(__file,"w")
84             __fid.write(__text)
85             __fid.close()
86         return __text
87     def load(self, __filename=None, __content=None, __object=None):
88         "Chargement normalisé des commandes"
89         if __filename is not None and os.path.exists(__filename):
90             self._content = open(__filename, 'r').read()
91         elif __content is not None and type(__content) is str:
92             self._content = __content
93         elif __object is not None and type(__object) is dict:
94             self._object = copy.deepcopy(__object)
95         else:
96             pass # use "self._content" from initialization
97         __commands = self._extract(self._content, self._object)
98         return __commands
99
100 class _TUIViewer(GenericCaseViewer):
101     """
102     Établissement des commandes d'un cas ADAO TUI (Cas<->TUI)
103     """
104     def __init__(self, __name="", __objname="case", __content=None, __object=None):
105         "Initialisation et enregistrement de l'entete"
106         GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
107         self._addLine("# -*- coding: utf-8 -*-")
108         self._addLine("#\n# Python script using ADAO TUI\n#")
109         self._addLine("from numpy import array, matrix")
110         self._addLine("from adao import adaoBuilder")
111         self._addLine("%s = adaoBuilder.New('%s')"%(self._objname, self._name))
112         if self._content is not None:
113             for command in self._content:
114                 self._append(*command)
115     def _append(self, __command=None, __keys=None, __local=None, __pre=None, __switchoff=False):
116         "Transformation d'une commande individuelle en un enregistrement"
117         if __command is not None and __keys is not None and __local is not None:
118             if "Concept" in __keys:
119                 logging.debug("TUI Order processed: %s"%(__local["Concept"],))
120             __text  = ""
121             if __pre is not None:
122                 __text += "%s = "%__pre
123             __text += "%s.%s( "%(self._objname,str(__command))
124             if "self" in __keys: __keys.remove("self")
125             if __command not in ("set","get") and "Concept" in __keys: __keys.remove("Concept")
126             for k in __keys:
127                 if k not in __local: continue
128                 __v = __local[k]
129                 if __v is None: continue
130                 if   k == "Checked"              and not __v: continue
131                 if   k == "Stored"               and not __v: continue
132                 if   k == "ColMajor"             and not __v: continue
133                 if   k == "InputFunctionAsMulti" and not __v: continue
134                 if   k == "nextStep"             and not __v: continue
135                 if   k == "AvoidRC"              and     __v: continue
136                 if   k == "noDetails":                        continue
137                 if isinstance(__v,Persistence.Persistence): __v = __v.values()
138                 if callable(__v): __text = self._missing%__v.__name__+__text
139                 if isinstance(__v,dict):
140                     for val in __v.values():
141                         if callable(val): __text = self._missing%val.__name__+__text
142                 numpy.set_printoptions(precision=15,threshold=1000000,linewidth=1000*15)
143                 __text += "%s=%s, "%(k,repr(__v))
144                 numpy.set_printoptions(precision=8,threshold=1000,linewidth=75)
145             __text = __text.rstrip(", ")
146             __text += " )"
147             self._addLine(__text)
148     def _extract(self, __multilines="", __object=None):
149         "Transformation d'enregistrement(s) en commande(s) individuelle(s)"
150         __is_case = False
151         __commands = []
152         __multilines = __multilines.replace("\r\n","\n")
153         for line in __multilines.split("\n"):
154             if "adaoBuilder.New" in line and "=" in line:
155                 self._objname = line.split("=")[0].strip()
156                 __is_case = True
157                 logging.debug("TUI Extracting commands of '%s' object..."%(self._objname,))
158             if not __is_case:
159                 continue
160             else:
161                 if self._objname+".set" in line:
162                     __commands.append( line.replace(self._objname+".","",1) )
163                     logging.debug("TUI Extracted command: %s"%(__commands[-1],))
164         return __commands
165
166 class _COMViewer(GenericCaseViewer):
167     """
168     Établissement des commandes d'un cas COMM (Eficas Native Format/Cas<-COM)
169     """
170     def __init__(self, __name="", __objname="case", __content=None, __object=None):
171         "Initialisation et enregistrement de l'entete"
172         GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
173         self._observerIndex = 0
174         self._addLine("# -*- coding: utf-8 -*-")
175         self._addLine("#\n# Python script using ADAO COMM\n#")
176         self._addLine("from numpy import array, matrix")
177         self._addLine("#")
178         self._addLine("%s = {}"%__objname)
179         if self._content is not None:
180             for command in self._content:
181                 self._append(*command)
182     def _extract(self, __multilines=None, __object=None):
183         "Transformation d'enregistrement(s) en commande(s) individuelle(s)"
184         __suppparameters = {}
185         if __multilines is not None:
186             if "ASSIMILATION_STUDY" in __multilines:
187                 __suppparameters.update({'StudyType':"ASSIMILATION_STUDY"})
188                 __multilines = __multilines.replace("ASSIMILATION_STUDY","dict")
189             elif "OPTIMIZATION_STUDY" in __multilines:
190                 __suppparameters.update({'StudyType':"ASSIMILATION_STUDY"})
191                 __multilines = __multilines.replace("OPTIMIZATION_STUDY",    "dict")
192             elif "REDUCTION_STUDY" in __multilines:
193                 __suppparameters.update({'StudyType':"ASSIMILATION_STUDY"})
194                 __multilines = __multilines.replace("REDUCTION_STUDY",    "dict")
195             elif "CHECKING_STUDY" in __multilines:
196                 __suppparameters.update({'StudyType':"CHECKING_STUDY"})
197                 __multilines = __multilines.replace("CHECKING_STUDY",    "dict")
198             else:
199                 __multilines = __multilines.replace("ASSIMILATION_STUDY","dict")
200             #
201             __multilines = __multilines.replace("_F(",               "dict(")
202             __multilines = __multilines.replace(",),);",             ",),)")
203         __fulllines = ""
204         for line in __multilines.split("\n"):
205             if len(line) < 1: continue
206             __fulllines += line + "\n"
207         __multilines = __fulllines
208         self._objname = "case"
209         self._objdata = None
210         exec("self._objdata = "+__multilines)
211         #
212         if self._objdata is None or not(type(self._objdata) is dict) or not('AlgorithmParameters' in self._objdata):
213             raise ValueError("Impossible to load given content as an ADAO COMM one (no dictionnary or no 'AlgorithmParameters' key found).")
214         # ----------------------------------------------------------------------
215         logging.debug("COMM Extracting commands of '%s' object..."%(self._objname,))
216         __commands = []
217         __UserPostAnalysis = ""
218         for k,r in self._objdata.items():
219             __command = k
220             logging.debug("COMM Extracted command: %s:%s"%(k, r))
221             if   __command == "StudyName" and len(str(r))>0:
222                 __commands.append( "set( Concept='Name', String='%s')"%(str(r),) )
223             elif   __command == "StudyRepertory":
224                 __commands.append( "set( Concept='Directory', String='%s')"%(str(r),) )
225             elif   __command == "Debug" and str(r) == "0":
226                 __commands.append( "set( Concept='NoDebug' )" )
227             elif   __command == "Debug" and str(r) == "1":
228                 __commands.append( "set( Concept='Debug' )" )
229             elif   __command == "ExecuteInContainer":
230                 __suppparameters.update({'ExecuteInContainer':r})
231             #
232             elif __command == "UserPostAnalysis" and type(r) is dict:
233                 if 'STRING' in r:
234                     __UserPostAnalysis = r['STRING'].replace("ADD.",str(self._objname)+".")
235                     __commands.append( "set( Concept='UserPostAnalysis', String=\"\"\"%s\"\"\" )"%(__UserPostAnalysis,) )
236                 elif 'SCRIPT_FILE' in r and os.path.exists(r['SCRIPT_FILE']):
237                     __UserPostAnalysis = open(r['SCRIPT_FILE'],'r').read()
238                     __commands.append( "set( Concept='UserPostAnalysis', Script='%s' )"%(r['SCRIPT_FILE'],) )
239                 elif 'Template' in r and not 'ValueTemplate' in r:
240                     # AnalysisPrinter...
241                     if r['Template'] not in Templates.UserPostAnalysisTemplates:
242                         raise ValueError("User post-analysis template \"%s\" does not exist."%(r['Template'],))
243                     else:
244                         __UserPostAnalysis = Templates.UserPostAnalysisTemplates[r['Template']]
245                     __commands.append( "set( Concept='UserPostAnalysis', Template='%s' )"%(r['Template'],) )
246                 elif 'Template' in r and 'ValueTemplate' in r:
247                     # Le template ayant pu être modifié, donc on ne prend que le ValueTemplate...
248                     __UserPostAnalysis = r['ValueTemplate']
249                     __commands.append( "set( Concept='UserPostAnalysis', String=\"\"\"%s\"\"\" )"%(__UserPostAnalysis,) )
250                 else:
251                     __UserPostAnalysis = ""
252             #
253             elif __command == "AlgorithmParameters" and type(r) is dict and 'Algorithm' in r:
254                 if 'data' in r and r['Parameters'] == 'Dict':
255                     __from = r['data']
256                     if 'STRING' in __from:
257                         __parameters = ", Parameters=%s"%(repr(eval(__from['STRING'])),)
258                     elif 'SCRIPT_FILE' in __from and os.path.exists(__from['SCRIPT_FILE']):
259                         __parameters = ", Script='%s'"%(__from['SCRIPT_FILE'],)
260                 else: # if 'Parameters' in r and r['Parameters'] == 'Defaults':
261                     __Dict = copy.deepcopy(r)
262                     __Dict.pop('Algorithm','')
263                     __Dict.pop('Parameters','')
264                     if 'SetSeed' in __Dict:__Dict['SetSeed'] = int(__Dict['SetSeed'])
265                     if 'BoxBounds' in __Dict and type(__Dict['BoxBounds']) is str:
266                         __Dict['BoxBounds'] = eval(__Dict['BoxBounds'])
267                     if len(__Dict) > 0:
268                         __parameters = ', Parameters=%s'%(repr(__Dict),)
269                     else:
270                         __parameters = ""
271                 __commands.append( "set( Concept='AlgorithmParameters', Algorithm='%s'%s )"%(r['Algorithm'],__parameters) )
272             #
273             elif __command == "Observers" and type(r) is dict and 'SELECTION' in r:
274                 if type(r['SELECTION']) is str:
275                     __selection = (r['SELECTION'],)
276                 else:
277                     __selection = tuple(r['SELECTION'])
278                 for sk in __selection:
279                     __idata = r['%s_data'%sk]
280                     if __idata['NodeType'] == 'Template' and 'Template' in __idata:
281                         __template = __idata['Template']
282                         if 'Info' in __idata:
283                             __info = ", Info=\"\"\"%s\"\"\""%(__idata['Info'],)
284                         else:
285                             __info = ""
286                         __commands.append( "set( Concept='Observer', Variable='%s', Template=\"\"\"%s\"\"\"%s )"%(sk,__template,__info) )
287                     if __idata['NodeType'] == 'String' and 'Value' in __idata:
288                         __value =__idata['Value']
289                         __commands.append( "set( Concept='Observer', Variable='%s', String=\"\"\"%s\"\"\" )"%(sk,__value) )
290             #
291             # Background, ObservationError, ObservationOperator...
292             elif type(r) is dict:
293                 __argumentsList = []
294                 if 'Stored' in r and bool(r['Stored']):
295                     __argumentsList.append(['Stored',True])
296                 if 'INPUT_TYPE' in r and 'data' in r:
297                     # Vector, Matrix, ScalarSparseMatrix, DiagonalSparseMatrix, Function
298                     __itype = r['INPUT_TYPE']
299                     __idata = r['data']
300                     if 'FROM' in __idata:
301                         # String, Script, DataFile, Template, ScriptWithOneFunction, ScriptWithFunctions
302                         __ifrom = __idata['FROM']
303                         __idata.pop('FROM','')
304                         if __ifrom == 'String' or __ifrom == 'Template':
305                             __argumentsList.append([__itype,__idata['STRING']])
306                         if __ifrom == 'Script':
307                             __argumentsList.append([__itype,True])
308                             __argumentsList.append(['Script',__idata['SCRIPT_FILE']])
309                         if __ifrom == 'DataFile':
310                             __argumentsList.append([__itype,True])
311                             __argumentsList.append(['DataFile',__idata['DATA_FILE']])
312                         if __ifrom == 'ScriptWithOneFunction':
313                             __argumentsList.append(['OneFunction',True])
314                             __argumentsList.append(['Script',__idata.pop('SCRIPTWITHONEFUNCTION_FILE')])
315                             if len(__idata)>0:
316                                 __argumentsList.append(['Parameters',__idata])
317                         if __ifrom == 'ScriptWithFunctions':
318                             __argumentsList.append(['ThreeFunctions',True])
319                             __argumentsList.append(['Script',__idata.pop('SCRIPTWITHFUNCTIONS_FILE')])
320                             if len(__idata)>0:
321                                 __argumentsList.append(['Parameters',__idata])
322                 __arguments = ["%s = %s"%(k,repr(v)) for k,v in __argumentsList]
323                 __commands.append( "set( Concept='%s', %s )"%(__command, ", ".join(__arguments)))
324         #
325         __commands.append( "set( Concept='%s', Parameters=%s )"%('SupplementaryParameters', repr(__suppparameters)))
326         #
327         # ----------------------------------------------------------------------
328         __commands.sort() # Pour commencer par 'AlgorithmParameters'
329         __commands.append(__UserPostAnalysis)
330         return __commands
331
332 class _SCDViewer(GenericCaseViewer):
333     """
334     Établissement des commandes d'un cas SCD (Study Config Dictionary/Cas->SCD)
335
336     Remarque : le fichier généré est différent de celui obtenu par EFICAS
337     """
338     def __init__(self, __name="", __objname="case", __content=None, __object=None):
339         "Initialisation et enregistrement de l'entête"
340         GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
341         #
342         if __content is not None:
343             for command in __content:
344                 if command[0] == "set": __command = command[2]["Concept"]
345                 else:                   __command = command[0].replace("set", "", 1)
346                 if __command == 'Name':
347                     self._name = command[2]["String"]
348         #
349         self.__DebugCommandNotSet = True
350         self.__ObserverCommandNotSet = True
351         self.__UserPostAnalysisNotSet = True
352         #
353         self._addLine("# -*- coding: utf-8 -*-")
354         self._addLine("#\n# Input for ADAO converter to SCD\n#")
355         self._addLine("#")
356         self._addLine("study_config = {}")
357         self._addLine("study_config['Name'] = '%s'"%self._name)
358         self._addLine("#")
359         self._addLine("inputvariables_config = {}")
360         self._addLine("inputvariables_config['Order'] =['adao_default']")
361         self._addLine("inputvariables_config['adao_default'] = -1")
362         self._addLine("study_config['InputVariables'] = inputvariables_config")
363         self._addLine("#")
364         self._addLine("outputvariables_config = {}")
365         self._addLine("outputvariables_config['Order'] = ['adao_default']")
366         self._addLine("outputvariables_config['adao_default'] = -1")
367         self._addLine("study_config['OutputVariables'] = outputvariables_config")
368         if __content is not None:
369             for command in __content:
370                 self._append(*command)
371     def _append(self, __command=None, __keys=None, __local=None, __pre=None, __switchoff=False):
372         "Transformation d'une commande individuelle en un enregistrement"
373         if __command == "set": __command = __local["Concept"]
374         else:                  __command = __command.replace("set", "", 1)
375         logging.debug("SCD Order processed: %s"%(__command))
376         #
377         __text  = None
378         if __command in (None, 'execute', 'executePythonScheme', 'executeYACSScheme', 'get', 'Name'):
379             return
380         elif __command in ['Directory',]:
381             __text  = "#\nstudy_config['Repertory'] = %s"%(repr(__local['String']))
382         elif __command in ['Debug', 'setDebug']:
383             __text  = "#\nstudy_config['Debug'] = '1'"
384             self.__DebugCommandNotSet = False
385         elif __command in ['NoDebug', 'setNoDebug']:
386             __text  = "#\nstudy_config['Debug'] = '0'"
387             self.__DebugCommandNotSet = False
388         elif __command in ['Observer', 'setObserver']:
389             if self.__ObserverCommandNotSet:
390                 self._addLine("observers = {}")
391                 self._addLine("study_config['Observers'] = observers")
392                 self.__ObserverCommandNotSet = False
393             __obs   = __local['Variable']
394             self._numobservers += 1
395             __text  = "#\n"
396             __text += "observers['%s'] = {}\n"%__obs
397             if __local['String'] is not None:
398                 __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'String')
399                 __text += "observers['%s']['String'] = \"\"\"%s\"\"\"\n"%(__obs, __local['String'])
400             if __local['Script'] is not None:
401                 __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'Script')
402                 __text += "observers['%s']['Script'] = \"%s\"\n"%(__obs, __local['Script'])
403             if __local['Template'] is not None and __local['Template'] in Templates.ObserverTemplates:
404                 __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'String')
405                 __text += "observers['%s']['String'] = \"\"\"%s\"\"\"\n"%(__obs, Templates.ObserverTemplates[__local['Template']])
406             if __local['Info'] is not None:
407                 __text += "observers['%s']['info'] = \"\"\"%s\"\"\"\n"%(__obs, __local['Info'])
408             else:
409                 __text += "observers['%s']['info'] = \"\"\"%s\"\"\"\n"%(__obs, __obs)
410             __text += "observers['%s']['number'] = %s"%(__obs, self._numobservers)
411         elif __command in ['UserPostAnalysis', 'setUserPostAnalysis']:
412             __text  = "#\n"
413             __text += "Analysis_config = {}\n"
414             if __local['String'] is not None:
415                 __text += "Analysis_config['From'] = 'String'\n"
416                 __text += "Analysis_config['Data'] = \"\"\"%s\"\"\"\n"%(__local['String'],)
417             if __local['Script'] is not None:
418                 __text += "Analysis_config['From'] = 'Script'\n"
419                 __text += "Analysis_config['Data'] = \"\"\"%s\"\"\"\n"%(__local['Script'],)
420             if __local['Template'] is not None and __local['Template'] in Templates.UserPostAnalysisTemplates:
421                 __text += "Analysis_config['From'] = 'String'\n"
422                 __text += "Analysis_config['Data'] = \"\"\"%s\"\"\"\n"%(Templates.UserPostAnalysisTemplates[__local['Template']],)
423             __text += "study_config['UserPostAnalysis'] = Analysis_config"
424             self.__UserPostAnalysisNotSet = False
425         elif __local is not None: # __keys is not None and
426             numpy.set_printoptions(precision=15,threshold=1000000,linewidth=1000*15)
427             __text  = "#\n"
428             __text += "%s_config = {}\n"%__command
429             __local.pop('self','')
430             __to_be_removed = []
431             __vectorIsDataFile = False
432             __vectorIsScript = False
433             for __k,__v in __local.items():
434                 if __v is None: __to_be_removed.append(__k)
435             for __k in __to_be_removed:
436                 __local.pop(__k)
437             for __k,__v in __local.items():
438                 if __k == "Concept": continue
439                 if __k in ['ScalarSparseMatrix','DiagonalSparseMatrix','Matrix','OneFunction','ThreeFunctions'] and 'Script' in __local and __local['Script'] is not None: continue
440                 if __k in ['Vector','VectorSerie'] and 'DataFile' in __local and __local['DataFile'] is not None: continue
441                 if __k == 'Parameters' and not (__command in ['AlgorithmParameters','SupplementaryParameters']): continue
442                 if __k == 'Algorithm':
443                     __text += "study_config['Algorithm'] = %s\n"%(repr(__v))
444                 elif __k == 'DataFile':
445                     __k = 'Vector'
446                     __f = 'DataFile'
447                     __v = "'"+repr(__v)+"'"
448                     for __lk in ['Vector','VectorSerie']:
449                         if __lk in __local and __local[__lk]: __k = __lk
450                     __text += "%s_config['Type'] = '%s'\n"%(__command,__k)
451                     __text += "%s_config['From'] = '%s'\n"%(__command,__f)
452                     __text += "%s_config['Data'] = %s\n"%(__command,__v)
453                     __text = __text.replace("''","'")
454                     __vectorIsDataFile = True
455                 elif __k == 'Script':
456                     __k = 'Vector'
457                     __f = 'Script'
458                     __v = "'"+repr(__v)+"'"
459                     for __lk in ['ScalarSparseMatrix','DiagonalSparseMatrix','Matrix']:
460                         if __lk in __local and __local[__lk]: __k = __lk
461                     if __command == "AlgorithmParameters": __k = "Dict"
462                     if 'OneFunction' in __local and __local['OneFunction']:
463                         __text += "%s_ScriptWithOneFunction = {}\n"%(__command,)
464                         __text += "%s_ScriptWithOneFunction['Function'] = ['Direct', 'Tangent', 'Adjoint']\n"%(__command,)
465                         __text += "%s_ScriptWithOneFunction['Script'] = {}\n"%(__command,)
466                         __text += "%s_ScriptWithOneFunction['Script']['Direct'] = %s\n"%(__command,__v)
467                         __text += "%s_ScriptWithOneFunction['Script']['Tangent'] = %s\n"%(__command,__v)
468                         __text += "%s_ScriptWithOneFunction['Script']['Adjoint'] = %s\n"%(__command,__v)
469                         __text += "%s_ScriptWithOneFunction['DifferentialIncrement'] = 1e-06\n"%(__command,)
470                         __text += "%s_ScriptWithOneFunction['CenteredFiniteDifference'] = 0\n"%(__command,)
471                         __k = 'Function'
472                         __f = 'ScriptWithOneFunction'
473                         __v = '%s_ScriptWithOneFunction'%(__command,)
474                     if 'ThreeFunctions' in __local and __local['ThreeFunctions']:
475                         __text += "%s_ScriptWithFunctions = {}\n"%(__command,)
476                         __text += "%s_ScriptWithFunctions['Function'] = ['Direct', 'Tangent', 'Adjoint']\n"%(__command,)
477                         __text += "%s_ScriptWithFunctions['Script'] = {}\n"%(__command,)
478                         __text += "%s_ScriptWithFunctions['Script']['Direct'] = %s\n"%(__command,__v)
479                         __text += "%s_ScriptWithFunctions['Script']['Tangent'] = %s\n"%(__command,__v)
480                         __text += "%s_ScriptWithFunctions['Script']['Adjoint'] = %s\n"%(__command,__v)
481                         __k = 'Function'
482                         __f = 'ScriptWithFunctions'
483                         __v = '%s_ScriptWithFunctions'%(__command,)
484                     __text += "%s_config['Type'] = '%s'\n"%(__command,__k)
485                     __text += "%s_config['From'] = '%s'\n"%(__command,__f)
486                     __text += "%s_config['Data'] = %s\n"%(__command,__v)
487                     __text = __text.replace("''","'")
488                     __vectorIsScript = True
489                 elif __k in ('Stored', 'Checked', 'ColMajor', 'InputFunctionAsMulti', 'nextStep'):
490                     if bool(__v):
491                         __text += "%s_config['%s'] = '%s'\n"%(__command,__k,int(bool(__v)))
492                 elif __k in ('AvoidRC', 'noDetails'):
493                     if not bool(__v):
494                         __text += "%s_config['%s'] = '%s'\n"%(__command,__k,int(bool(__v)))
495                 else:
496                     if __k == 'Vector' and __vectorIsScript: continue
497                     if __k == 'Vector' and __vectorIsDataFile: continue
498                     if __k == 'Parameters': __k = "Dict"
499                     if isinstance(__v,Persistence.Persistence): __v = __v.values()
500                     if callable(__v): __text = self._missing%__v.__name__+__text
501                     if isinstance(__v,dict):
502                         for val in __v.values():
503                             if callable(val): __text = self._missing%val.__name__+__text
504                     __text += "%s_config['Type'] = '%s'\n"%(__command,__k)
505                     __text += "%s_config['From'] = '%s'\n"%(__command,'String')
506                     __text += "%s_config['Data'] = \"\"\"%s\"\"\"\n"%(__command,repr(__v))
507             __text += "study_config['%s'] = %s_config"%(__command,__command)
508             numpy.set_printoptions(precision=8,threshold=1000,linewidth=75)
509             if __switchoff:
510                 self._switchoff = True
511         if __text is not None: self._addLine(__text)
512         if not __switchoff:
513             self._switchoff = False
514     def _finalize(self, *__args):
515         self.__loadVariablesByScript()
516         if self.__DebugCommandNotSet:
517             self._addLine("#\nstudy_config['Debug'] = '0'")
518         if self.__UserPostAnalysisNotSet:
519             self._addLine("#")
520             self._addLine("Analysis_config = {}")
521             self._addLine("Analysis_config['From'] = 'String'")
522             self._addLine("Analysis_config['Data'] = \"\"\"import numpy")
523             self._addLine("xa=numpy.ravel(ADD.get('Analysis')[-1])")
524             self._addLine("print('Analysis:',xa)\"\"\"")
525             self._addLine("study_config['UserPostAnalysis'] = Analysis_config")
526     def __loadVariablesByScript(self):
527         __ExecVariables = {} # Necessaire pour recuperer la variable
528         exec("\n".join(self._lineSerie), __ExecVariables)
529         study_config = __ExecVariables['study_config']
530         # Pour Python 3 : self.__hasAlgorithm = bool(study_config['Algorithm'])
531         if 'Algorithm' in study_config:
532             self.__hasAlgorithm = True
533         else:
534             self.__hasAlgorithm = False
535         if not self.__hasAlgorithm and \
536                 "AlgorithmParameters" in study_config and \
537                 isinstance(study_config['AlgorithmParameters'], dict) and \
538                 "From" in study_config['AlgorithmParameters'] and \
539                 "Data" in study_config['AlgorithmParameters'] and \
540                 study_config['AlgorithmParameters']['From'] == 'Script':
541             __asScript = study_config['AlgorithmParameters']['Data']
542             __var = ImportFromScript(__asScript).getvalue( "Algorithm" )
543             __text = "#\nstudy_config['Algorithm'] = '%s'"%(__var,)
544             self._addLine(__text)
545         if self.__hasAlgorithm and \
546                 "AlgorithmParameters" in study_config and \
547                 isinstance(study_config['AlgorithmParameters'], dict) and \
548                 "From" not in study_config['AlgorithmParameters'] and \
549                 "Data" not in study_config['AlgorithmParameters']:
550             __text  = "#\n"
551             __text += "AlgorithmParameters_config['Type'] = 'Dict'\n"
552             __text += "AlgorithmParameters_config['From'] = 'String'\n"
553             __text += "AlgorithmParameters_config['Data'] = '{}'\n"
554             self._addLine(__text)
555         if 'SupplementaryParameters' in study_config and \
556                 isinstance(study_config['SupplementaryParameters'], dict) and \
557                 "From" in study_config['SupplementaryParameters'] and \
558                 study_config['SupplementaryParameters']["From"] == 'String' and \
559                 "Data" in study_config['SupplementaryParameters']:
560             __dict = eval(study_config['SupplementaryParameters']["Data"])
561             if 'ExecuteInContainer' in __dict:
562                 self._addLine("#\nstudy_config['ExecuteInContainer'] = '%s'"%__dict['ExecuteInContainer'])
563             else:
564                 self._addLine("#\nstudy_config['ExecuteInContainer'] = 'No'")
565             if 'StudyType' in __dict:
566                 self._addLine("#\nstudy_config['StudyType'] = '%s'"%__dict['StudyType'])
567             if 'StudyType' in __dict and __dict['StudyType'] != "ASSIMILATION_STUDY":
568                 self.__UserPostAnalysisNotSet = False
569         del study_config
570
571 class _YACSViewer(GenericCaseViewer):
572     """
573     Etablissement des commandes d'un cas YACS (Cas->SCD->YACS)
574     """
575     def __init__(self, __name="", __objname="case", __content=None, __object=None):
576         "Initialisation et enregistrement de l'entete"
577         GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
578         self.__internalSCD = _SCDViewer(__name, __objname, __content, __object)
579         self._append       = self.__internalSCD._append
580     def dump(self, __filename=None, __upa=None):
581         "Restitution normalisée des commandes"
582         # -----
583         if __filename is None:
584             raise ValueError("A file name has to be given for YACS XML output.")
585         else:
586             __file    = os.path.abspath(__filename)
587             if os.path.isfile(__file) or os.path.islink(__file):
588                 os.remove(__file)
589         # -----
590         if not PlatformInfo.has_salome or \
591             not PlatformInfo.has_adao:
592             raise ImportError(
593                 "Unable to get SALOME or ADAO environnement for YACS conversion.\n"+\
594                 "Please load the right SALOME environnement before trying to use it.")
595         else:
596             from daYacsSchemaCreator.run import create_schema_from_content
597         # -----
598         self.__internalSCD._finalize(__upa)
599         __SCDdump = self.__internalSCD.dump()
600         create_schema_from_content(__SCDdump, __file)
601         # -----
602         if not os.path.exists(__file):
603             __msg  = "An error occured during the ADAO YACS Schema build for\n"
604             __msg += "the target output file:\n"
605             __msg += "  %s\n"%__file
606             __msg += "See errors details in your launching terminal log.\n"
607             raise ValueError(__msg)
608         # -----
609         __fid = open(__file,"r")
610         __text = __fid.read()
611         __fid.close()
612         return __text
613
614 # ==============================================================================
615 class _ReportViewer(GenericCaseViewer):
616     """
617     Partie commune de restitution simple
618     """
619     def __init__(self, __name="", __objname="case", __content=None, __object=None):
620         "Initialisation et enregistrement de l'entete"
621         GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
622         self._r = Reporting.ReportStorage()
623         self._r.clear()
624         if self._name == "":
625             self._r.append("ADAO Study report", "title")
626         else:
627             self._r.append(str(self._name), "title")
628         if self._content is not None:
629             for command in self._content:
630                 self._append(*command)
631     def _append(self, __command=None, __keys=None, __local=None, __pre=None, __switchoff=False):
632         "Transformation d'une commande individuelle en un enregistrement"
633         if __command is not None and __keys is not None and __local is not None:
634             if __command in ("set","get") and "Concept" in __keys: __command = __local["Concept"]
635             __text  = ""
636             __text += "<i>%s</i> command has been set"%str(__command.replace("set",""))
637             __ktext = ""
638             for k in __keys:
639                 if k not in __local: continue
640                 __v = __local[k]
641                 if __v is None: continue
642                 if   k == "Checked"              and not __v: continue
643                 if   k == "Stored"               and not __v: continue
644                 if   k == "ColMajor"             and not __v: continue
645                 if   k == "InputFunctionAsMulti" and not __v: continue
646                 if   k == "nextStep"             and not __v: continue
647                 if   k == "AvoidRC"              and     __v: continue
648                 if   k == "noDetails":                        continue
649                 if   k == "Concept":                          continue
650                 if   k == "self":                             continue
651                 if isinstance(__v,Persistence.Persistence): __v = __v.values()
652                 numpy.set_printoptions(precision=15,threshold=1000000,linewidth=1000*15)
653                 __ktext += "\n        %s = %s, "%(k,repr(__v))
654                 numpy.set_printoptions(precision=8,threshold=1000,linewidth=75)
655             if len(__ktext) > 0:
656                 __text += " with values:" + __ktext
657             __text = __text.rstrip(", ")
658             self._r.append(__text, "uli")
659     def _finalize(self, __upa=None):
660         "Enregistrement du final"
661         raise NotImplementedError()
662
663 class _SimpleReportInRstViewer(_ReportViewer):
664     """
665     Restitution simple en RST
666     """
667     def _finalize(self, __upa=None):
668         self._lineSerie.append(Reporting.ReportViewInRst(self._r).__str__())
669
670 class _SimpleReportInHtmlViewer(_ReportViewer):
671     """
672     Restitution simple en HTML
673     """
674     def _finalize(self, __upa=None):
675         self._lineSerie.append(Reporting.ReportViewInHtml(self._r).__str__())
676
677 class _SimpleReportInPlainTxtViewer(_ReportViewer):
678     """
679     Restitution simple en TXT
680     """
681     def _finalize(self, __upa=None):
682         self._lineSerie.append(Reporting.ReportViewInPlainTxt(self._r).__str__())
683
684 # ==============================================================================
685 class ImportFromScript(object):
686     """
687     Obtention d'une variable nommee depuis un fichier script importé
688     """
689     __slots__ = ("__basename", "__filenspace", "__filestring")
690     def __init__(self, __filename=None):
691         "Verifie l'existence et importe le script"
692         if __filename is None:
693             raise ValueError("The name of the file, containing the variable to be read, has to be specified.")
694         if not os.path.isfile(__filename):
695             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))
696         if os.path.dirname(__filename) != '':
697             sys.path.insert(0, os.path.dirname(__filename))
698             __basename = os.path.basename(__filename).rstrip(".py")
699         else:
700             __basename = __filename.rstrip(".py")
701         PlatformInfo.checkFileNameImportability( __basename+".py" )
702         self.__basename = __basename
703         try:
704             self.__filenspace = __import__(__basename, globals(), locals(), [])
705         except NameError:
706             self.__filenspace = ""
707         with open(__filename,'r') as fid:
708             self.__filestring = fid.read()
709     def getvalue(self, __varname=None, __synonym=None ):
710         "Renvoie la variable demandee par son nom ou son synonyme"
711         if __varname is None:
712             raise ValueError("The name of the variable to be read has to be specified. Please check the content of the file and the syntax.")
713         if not hasattr(self.__filenspace, __varname):
714             if __synonym is None:
715                 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))
716             elif not hasattr(self.__filenspace, __synonym):
717                 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))
718             else:
719                 return getattr(self.__filenspace, __synonym)
720         else:
721             return getattr(self.__filenspace, __varname)
722     def getstring(self):
723         "Renvoie le script complet"
724         return self.__filestring
725
726 # ==============================================================================
727 class ImportDetector(object):
728     """
729     Détection des caractéristiques de fichiers ou objets en entrée
730     """
731     __slots__ = (
732         "__url", "__usr", "__root", "__end")
733     def __enter__(self): return self
734     def __exit__(self, exc_type, exc_val, exc_tb): return False
735     #
736     def __init__(self, __url, UserMime=""):
737         if __url is None:
738             raise ValueError("The name or url of the file object has to be specified.")
739         if __url is bytes:
740             self.__url = __url.decode()
741         else:
742             self.__url = str(__url)
743         if UserMime is bytes:
744             self.__usr = UserMime.decode().lower()
745         else:
746             self.__usr = str(UserMime).lower()
747         (self.__root, self.__end) = os.path.splitext(self.__url)
748         #
749         mimetypes.add_type('application/numpy.npy', '.npy')
750         mimetypes.add_type('application/numpy.npz', '.npz')
751         mimetypes.add_type('application/dymola.sdf', '.sdf')
752         if sys.platform.startswith("win"):
753             mimetypes.add_type('text/plain', '.txt')
754             mimetypes.add_type('text/csv', '.csv')
755             mimetypes.add_type('text/tab-separated-values', '.tsv')
756     #
757     # File related tests
758     # ------------------
759     def is_local_file(self):
760         if os.path.isfile(os.path.realpath(self.__url)):
761             return True
762         else:
763             return False
764     def is_not_local_file(self):
765         if not os.path.isfile(os.path.realpath(self.__url)):
766             return True
767         else:
768             return False
769     def raise_error_if_not_local_file(self):
770         if not os.path.isfile(os.path.realpath(self.__url)):
771             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))
772         else:
773             return False
774     #
775     # Directory related tests
776     # -----------------------
777     def is_local_dir(self):
778         if os.path.isdir(self.__url):
779             return True
780         else:
781             return False
782     def is_not_local_dir(self):
783         if not os.path.isdir(self.__url):
784             return True
785         else:
786             return False
787     def raise_error_if_not_local_dir(self):
788         if not os.path.isdir(self.__url):
789             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))
790         else:
791             return False
792     #
793     # Mime related functions
794     # ------------------------
795     def get_standard_mime(self):
796         (__mtype, __encoding) = mimetypes.guess_type(self.__url, strict=False)
797         return __mtype
798     def get_user_mime(self):
799         __fake = "fake."+self.__usr.lower()
800         (__mtype, __encoding) = mimetypes.guess_type(__fake, strict=False)
801         return __mtype
802     def get_comprehensive_mime(self):
803         if self.get_standard_mime() is not None:
804             return self.get_standard_mime()
805         elif self.get_user_mime() is not None:
806             return self.get_user_mime()
807         else:
808             return None
809     #
810     # Name related functions
811     # ----------------------
812     def get_user_name(self):
813         return self.__url
814     def get_absolute_name(self):
815         return os.path.abspath(os.path.realpath(self.__url))
816     def get_extension(self):
817         return self.__end
818
819 class ImportFromFile(object):
820     """
821     Obtention de variables disrétisées en 1D, définies par une ou des variables
822     nommées, et sous la forme d'une série de points éventuellement indexés. La
823     lecture d'un fichier au format spécifié (ou intuité) permet de charger ces
824     fonctions depuis :
825         - des fichiers textes en colonnes de type TXT, CSV, TSV...
826         - des fichiers de données binaires NPY, NPZ, SDF...
827     La lecture du fichier complet ne se fait que si nécessaire, pour assurer la
828     performance tout en disposant de l'interprétation du contenu. Les fichiers
829     textes doivent présenter en première ligne (hors commentaire ou ligne vide)
830     les noms des variables de colonnes. Les commentaires commencent par un "#".
831     """
832     __slots__ = (
833         "_filename", "_colnames", "_colindex", "_varsline", "_format",
834         "_delimiter", "_skiprows", "__url", "__filestring", "__header",
835         "__allowvoid", "__binaryformats", "__supportedformats")
836     def __enter__(self): return self
837     def __exit__(self, exc_type, exc_val, exc_tb): return False
838     #
839     def __init__(self, Filename=None, ColNames=None, ColIndex=None, Format="Guess", AllowVoidNameList=True):
840         """
841         Verifie l'existence et les informations de définition du fichier. Les
842         noms de colonnes ou de variables sont ignorées si le format ne permet
843         pas de les indiquer.
844         Arguments :
845             - Filename : nom du fichier
846             - ColNames : noms de la ou des colonnes/variables à lire
847             - ColIndex : nom unique de la colonne/variable servant d'index
848             - Format : format du fichier et/ou des données inclues
849             - AllowVoidNameList : permet, si la liste de noms est vide, de
850               prendre par défaut toutes les colonnes
851         """
852         self.__binaryformats =(
853             "application/numpy.npy",
854             "application/numpy.npz",
855             "application/dymola.sdf",
856             )
857         self.__url = ImportDetector( Filename, Format)
858         self.__url.raise_error_if_not_local_file()
859         self._filename = self.__url.get_absolute_name()
860         PlatformInfo.checkFileNameConformity( self._filename )
861         #
862         self._format = self.__url.get_comprehensive_mime()
863         #
864         self.__header, self._varsline, self._skiprows = self.__getentete()
865         #
866         if self._format == "text/csv" or Format.upper() == "CSV":
867             self._format = "text/csv"
868             self.__filestring = "".join(self.__header)
869             if self.__filestring.count(",") > 1:
870                 self._delimiter = ","
871             elif self.__filestring.count(";") > 1:
872                 self._delimiter = ";"
873             else:
874                 self._delimiter = None
875         elif self._format == "text/tab-separated-values" or Format.upper() == "TSV":
876             self._format = "text/tab-separated-values"
877             self._delimiter = "\t"
878         else:
879             self._delimiter = None
880         #
881         if ColNames is not None: self._colnames = tuple(ColNames)
882         else:                    self._colnames = None
883         #
884         if ColIndex is not None: self._colindex = str(ColIndex)
885         else:                    self._colindex = None
886         #
887         self.__allowvoid = bool(AllowVoidNameList)
888
889     def __getentete(self, __nblines = 3):
890         "Lit l'entête du fichier pour trouver la définition des variables"
891         # La première ligne non vide non commentée est toujours considérée
892         # porter les labels de colonne, donc pas des valeurs
893         __header, __varsline, __skiprows = [], "", 1
894         if self._format in self.__binaryformats:
895             pass
896         else:
897             with open(self._filename,'r') as fid:
898                 __line = fid.readline().strip()
899                 while "#" in __line or len(__line) < 1:
900                     __header.append(__line)
901                     __skiprows += 1
902                     __line = fid.readline().strip()
903                 __varsline = __line
904                 for i in range(max(0,__nblines)):
905                     __header.append(fid.readline())
906         return (__header, __varsline, __skiprows)
907
908     def __getindices(self, __colnames, __colindex, __delimiter=None ):
909         "Indices de colonnes correspondants à l'index et aux variables"
910         if __delimiter is None:
911             __varserie = self._varsline.strip('#').strip().split()
912         else:
913             __varserie = self._varsline.strip('#').strip().split(str(__delimiter))
914         #
915         if __colnames is not None:
916             __usecols = []
917             __colnames = tuple(__colnames)
918             for v in __colnames:
919                 for i, n in enumerate(__varserie):
920                     if v == n: __usecols.append(i)
921             __usecols = tuple(__usecols)
922             if len(__usecols) == 0:
923                 if self.__allowvoid:
924                     __usecols = None
925                 else:
926                     raise ValueError("Can not found any column corresponding to the required names %s"%(__colnames,))
927         else:
928             __usecols = None
929         #
930         if __colindex is not None:
931             __useindex = None
932             __colindex = str(__colindex)
933             for i, n in enumerate(__varserie):
934                 if __colindex == n: __useindex = i
935         else:
936             __useindex = None
937         #
938         return (__usecols, __useindex)
939
940     def getsupported(self):
941         self.__supportedformats = {}
942         self.__supportedformats["text/plain"]                = True
943         self.__supportedformats["text/csv"]                  = True
944         self.__supportedformats["text/tab-separated-values"] = True
945         self.__supportedformats["application/numpy.npy"]     = True
946         self.__supportedformats["application/numpy.npz"]     = True
947         self.__supportedformats["application/dymola.sdf"]    = PlatformInfo.has_sdf
948         return self.__supportedformats
949
950     def getvalue(self, ColNames=None, ColIndex=None ):
951         "Renvoie la ou les variables demandees par la liste de leurs noms"
952         # Uniquement si mise à jour
953         if ColNames is not None: self._colnames = tuple(ColNames)
954         if ColIndex is not None: self._colindex = str(ColIndex)
955         #
956         __index = None
957         if self._format == "application/numpy.npy":
958             __columns = numpy.load(self._filename)
959         #
960         elif self._format == "application/numpy.npz":
961             __columns = None
962             with numpy.load(self._filename) as __allcolumns:
963                 if self._colnames is None:
964                     self._colnames = __allcolumns.files
965                 for nom in self._colnames: # Si une variable demandée n'existe pas
966                     if nom not in __allcolumns.files:
967                         self._colnames = tuple( __allcolumns.files )
968                 for nom in self._colnames:
969                     if nom in __allcolumns.files:
970                         if __columns is not None:
971                             # Attention : toutes les variables doivent avoir la même taille
972                             __columns = numpy.vstack((__columns, numpy.reshape(__allcolumns[nom], (1,-1))))
973                         else:
974                             # Première colonne
975                             __columns = numpy.reshape(__allcolumns[nom], (1,-1))
976                 if self._colindex is not None and self._colindex in __allcolumns.files:
977                     __index = numpy.array(numpy.reshape(__allcolumns[self._colindex], (1,-1)), dtype=bytes)
978         elif self._format == "text/plain":
979             __usecols, __useindex = self.__getindices(self._colnames, self._colindex)
980             __columns = numpy.loadtxt(self._filename, usecols = __usecols, skiprows=self._skiprows)
981             if __useindex is not None:
982                 __index = numpy.loadtxt(self._filename, dtype = bytes, usecols = (__useindex,), skiprows=self._skiprows)
983             if __usecols is None: # Si une variable demandée n'existe pas
984                 self._colnames = None
985         #
986         elif self._format == "application/dymola.sdf" and PlatformInfo.has_sdf:
987             import sdf
988             __content = sdf.load(self._filename)
989             __columns = None
990             if self._colnames is None:
991                 self._colnames = [__content.datasets[i].name for i in range(len(__content.datasets))]
992             for nom in self._colnames:
993                 if nom in __content:
994                     if __columns is not None:
995                         # Attention : toutes les variables doivent avoir la même taille
996                         __columns = numpy.vstack((__columns, numpy.reshape(__content[nom].data, (1,-1))))
997                     else:
998                         # Première colonne
999                         __columns = numpy.reshape(__content[nom].data, (1,-1))
1000             if self._colindex is not None and self._colindex in __content:
1001                 __index = __content[self._colindex].data
1002         #
1003         elif self._format == "text/csv":
1004             __usecols, __useindex = self.__getindices(self._colnames, self._colindex, self._delimiter)
1005             __columns = numpy.loadtxt(self._filename, usecols = __usecols, delimiter = self._delimiter, skiprows=self._skiprows)
1006             if __useindex is not None:
1007                 __index = numpy.loadtxt(self._filename, dtype = bytes, usecols = (__useindex,), delimiter = self._delimiter, skiprows=self._skiprows)
1008             if __usecols is None: # Si une variable demandée n'existe pas
1009                 self._colnames = None
1010         #
1011         elif self._format == "text/tab-separated-values":
1012             __usecols, __useindex = self.__getindices(self._colnames, self._colindex, self._delimiter)
1013             __columns = numpy.loadtxt(self._filename, usecols = __usecols, delimiter = self._delimiter, skiprows=self._skiprows)
1014             if __useindex is not None:
1015                 __index = numpy.loadtxt(self._filename, dtype = bytes, usecols = (__useindex,), delimiter = self._delimiter, skiprows=self._skiprows)
1016             if __usecols is None: # Si une variable demandée n'existe pas
1017                 self._colnames = None
1018         else:
1019             raise ValueError("Unkown file format \"%s\" or no reader available"%self._format)
1020         if __columns is None: __columns = ()
1021         #
1022         def toString(value):
1023             try:
1024                 return value.decode()
1025             except ValueError:
1026                 return value
1027         if __index is not None:
1028             __index = tuple([toString(v) for v in __index])
1029         #
1030         return (self._colnames, __columns, self._colindex, __index)
1031
1032     def getstring(self):
1033         "Renvoie le fichier texte complet"
1034         if self._format in self.__binaryformats:
1035             return ""
1036         else:
1037             with open(self._filename,'r') as fid:
1038                 return fid.read()
1039
1040     def getformat(self):
1041         return self._format
1042
1043 class ImportScalarLinesFromFile(ImportFromFile):
1044     """
1045     Importation de fichier contenant des variables scalaires nommées. Le
1046     fichier comporte soit 2, soit 4 colonnes, obligatoirement nommées "Name",
1047     "Value", "Minimum", "Maximum" si les noms sont précisés. Sur chaque ligne
1048     est indiqué le nom, la valeur, et éventuelement deux bornes min et max (ou
1049     None si nécessaire pour une borne).
1050
1051     Seule la méthode "getvalue" est changée.
1052     """
1053     def __enter__(self): return self
1054     def __exit__(self, exc_type, exc_val, exc_tb): return False
1055     #
1056     def __init__(self, Filename=None, ColNames=None, ColIndex=None, Format="Guess"):
1057         ImportFromFile.__init__(self, Filename, ColNames, ColIndex, Format)
1058         if self._format not in ["text/plain", "text/csv", "text/tab-separated-values"]:
1059             raise ValueError("Unkown file format \"%s\""%self._format)
1060     #
1061     def getvalue(self, VarNames = None, HeaderNames=()):
1062         "Renvoie la ou les variables demandees par la liste de leurs noms"
1063         if VarNames is not None: __varnames = tuple(VarNames)
1064         else:                    __varnames = None
1065         #
1066         if "Name" in self._varsline and "Value" in self._varsline and "Minimum" in self._varsline and "Maximum" in self._varsline:
1067             __ftype = "NamValMinMax"
1068             __dtypes   = {'names'  : ('Name', 'Value', 'Minimum', 'Maximum'),
1069                           'formats': ('S128', 'g', 'g', 'g')}
1070             __usecols  = (0, 1, 2, 3)
1071             def __replaceNoneN( s ):
1072                 if s.strip() == b'None': return numpy.NINF
1073                 else:                    return s
1074             def __replaceNoneP( s ):
1075                 if s.strip() == b'None': return numpy.PINF
1076                 else:                    return s
1077             __converters = {2: __replaceNoneN, 3: __replaceNoneP}
1078         elif "Name" in self._varsline and "Value" in self._varsline and ("Minimum" not in self._varsline or "Maximum" not in self._varsline):
1079             __ftype = "NamVal"
1080             __dtypes   = {'names'  : ('Name', 'Value'),
1081                           'formats': ('S128', 'g')}
1082             __converters = None
1083             __usecols  = (0, 1)
1084         elif len(HeaderNames)>0 and numpy.all([kw in self._varsline for kw in HeaderNames]):
1085             __ftype = "NamLotOfVals"
1086             __dtypes   = {'names'  : HeaderNames,
1087                           'formats': tuple(['S128',]+['g']*(len(HeaderNames)-1))}
1088             __usecols  = tuple(range(len(HeaderNames)))
1089             def __replaceNone( s ):
1090                 if s.strip() == b'None': return numpy.NAN
1091                 else:                    return s
1092             __converters = dict()
1093             for i in range(1,len(HeaderNames)):
1094                 __converters[i] = __replaceNone
1095         else:
1096             raise ValueError("Can not find names of columns for initial values. Wrong first line is:\n            \"%s\""%__firstline)
1097         #
1098         if self._format == "text/plain":
1099             __content = numpy.loadtxt(self._filename, dtype = __dtypes, usecols = __usecols, skiprows = self._skiprows, converters = __converters)
1100         elif self._format in ["text/csv", "text/tab-separated-values"]:
1101             __content = numpy.loadtxt(self._filename, dtype = __dtypes, usecols = __usecols, skiprows = self._skiprows, converters = __converters, delimiter = self._delimiter)
1102         else:
1103             raise ValueError("Unkown file format \"%s\""%self._format)
1104         #
1105         __names, __thevalue, __bounds = [], [], []
1106         for sub in __content:
1107             if len(__usecols) == 4:
1108                 na, va, mi, ma = sub
1109                 if numpy.isneginf(mi): mi = None # Réattribue les variables None
1110                 elif numpy.isnan(mi):  mi = None # Réattribue les variables None
1111                 if numpy.isposinf(ma): ma = None # Réattribue les variables None
1112                 elif numpy.isnan(ma):  ma = None # Réattribue les variables None
1113             elif len(__usecols) == 2 and __ftype == "NamVal":
1114                 na, va = sub
1115                 mi, ma = None, None
1116             else:
1117                 nsub = list(sub)
1118                 na = sub[0]
1119                 for i, v in enumerate(nsub[1:]):
1120                     if numpy.isnan(v): nsub[i+1] = None
1121                 va = nsub[1:]
1122                 mi, ma = None, None
1123             na = na.decode()
1124             if (__varnames is None or na in __varnames) and (na not in __names):
1125                 # Ne stocke que la premiere occurence d'une variable
1126                 __names.append(na)
1127                 __thevalue.append(va)
1128                 __bounds.append((mi,ma))
1129         #
1130         __names      = tuple(__names)
1131         __thevalue = numpy.array(__thevalue)
1132         __bounds     = tuple(__bounds)
1133         #
1134         return (__names, __thevalue, __bounds)
1135
1136 # ==============================================================================
1137 class EficasGUI(object):
1138     """
1139     Lancement autonome de l'interface EFICAS/ADAO
1140     """
1141     def __init__(self, __addpath = None):
1142         # Chemin pour l'installation (ordre important)
1143         self.__msg = ""
1144         self.__path_settings_ok = False
1145         #----------------
1146         if "EFICAS_ROOT" in os.environ:
1147             __EFICAS_ROOT = os.environ["EFICAS_ROOT"]
1148             __path_ok = True
1149         else:
1150             self.__msg += "\nKeyError:\n"+\
1151                 "  the required environment variable EFICAS_ROOT is unknown.\n"+\
1152                 "  You have either to be in SALOME environment, or to set\n"+\
1153                 "  this variable in your environment to the right path \"<...>\"\n"+\
1154                 "  to find an installed EFICAS application. For example:\n"+\
1155                 "      EFICAS_ROOT=\"<...>\" command\n"
1156             __path_ok = False
1157         try:
1158             import adao
1159             __path_ok = True and __path_ok
1160         except ImportError:
1161             self.__msg += "\nImportError:\n"+\
1162                 "  the required ADAO library can not be found to be imported.\n"+\
1163                 "  You have either to be in ADAO environment, or to be in SALOME\n"+\
1164                 "  environment, or to set manually in your Python 3 environment the\n"+\
1165                 "  right path \"<...>\" to find an installed ADAO application. For\n"+\
1166                 "  example:\n"+\
1167                 "      PYTHONPATH=\"<...>:${PYTHONPATH}\" command\n"
1168             __path_ok = False
1169         try:
1170             import PyQt5
1171             __path_ok = True and __path_ok
1172         except ImportError:
1173             self.__msg += "\nImportError:\n"+\
1174                 "  the required PyQt5 library can not be found to be imported.\n"+\
1175                 "  You have either to have a raisonable up-to-date Python 3\n"+\
1176                 "  installation (less than 5 years), or to be in SALOME environment.\n"
1177             __path_ok = False
1178         #----------------
1179         if not __path_ok:
1180             self.__msg += "\nWarning:\n"+\
1181                 "  It seems you have some troubles with your installation.\n"+\
1182                 "  Be aware that some other errors may exist, that are not\n"+\
1183                 "  explained as above, like some incomplete or obsolete\n"+\
1184                 "  Python 3, or incomplete module installation.\n"+\
1185                 "  \n"+\
1186                 "  Please correct the above error(s) before launching the\n"+\
1187                 "  standalone EFICAS/ADAO interface.\n"
1188             logging.debug("Some of the ADAO/EFICAS/QT5 paths have not been found")
1189             self.__path_settings_ok = False
1190         else:
1191             logging.debug("All the ADAO/EFICAS/QT5 paths have been found")
1192             self.__path_settings_ok = True
1193         #----------------
1194         if self.__path_settings_ok:
1195             sys.path.insert(0,__EFICAS_ROOT)
1196             sys.path.insert(0,os.path.join(adao.adao_py_dir,"daEficas"))
1197             if __addpath is not None and os.path.exists(os.path.abspath(__addpath)):
1198                 sys.path.insert(0,os.path.abspath(__addpath))
1199             logging.debug("All the paths have been correctly set up")
1200         else:
1201             print(self.__msg)
1202             logging.debug("Errors in path settings have been found")
1203
1204     def gui(self):
1205         if self.__path_settings_ok:
1206             logging.debug("Launching standalone EFICAS/ADAO interface...")
1207             from daEficas import prefs
1208             from InterfaceQT4 import eficas_go
1209             eficas_go.lanceEficas(code=prefs.code)
1210         else:
1211             logging.debug("Can not launch standalone EFICAS/ADAO interface for path errors.")
1212
1213 # ==============================================================================
1214 if __name__ == "__main__":
1215     print('\n AUTODIAGNOSTIC\n')