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