Salome HOME
Code improvements, review and simplifications (1)
[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         return not self.is_local_file()
768     def raise_error_if_not_local_file(self):
769         if self.is_not_local_file():
770             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))
771         else:
772             return False
773     #
774     # Directory related tests
775     # -----------------------
776     def is_local_dir(self):
777         if os.path.isdir(self.__url):
778             return True
779         else:
780             return False
781     def is_not_local_dir(self):
782         return not self.is_local_dir()
783     def raise_error_if_not_local_dir(self):
784         if self.is_not_local_dir():
785             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))
786         else:
787             return False
788     #
789     # Mime related functions
790     # ------------------------
791     def get_standard_mime(self):
792         (__mtype, __encoding) = mimetypes.guess_type(self.__url, strict=False)
793         return __mtype
794     def get_user_mime(self):
795         __fake = "fake."+self.__usr.lower()
796         (__mtype, __encoding) = mimetypes.guess_type(__fake, strict=False)
797         return __mtype
798     def get_comprehensive_mime(self):
799         if self.get_standard_mime() is not None:
800             return self.get_standard_mime()
801         elif self.get_user_mime() is not None:
802             return self.get_user_mime()
803         else:
804             return None
805     #
806     # Name related functions
807     # ----------------------
808     def get_user_name(self):
809         return self.__url
810     def get_absolute_name(self):
811         return os.path.abspath(os.path.realpath(self.__url))
812     def get_extension(self):
813         return self.__end
814
815 class ImportFromFile(object):
816     """
817     Obtention de variables disrétisées en 1D, définies par une ou des variables
818     nommées, et sous la forme d'une série de points éventuellement indexés. La
819     lecture d'un fichier au format spécifié (ou intuité) permet de charger ces
820     fonctions depuis :
821         - des fichiers textes en colonnes de type TXT, CSV, TSV...
822         - des fichiers de données binaires NPY, NPZ, SDF...
823     La lecture du fichier complet ne se fait que si nécessaire, pour assurer la
824     performance tout en disposant de l'interprétation du contenu. Les fichiers
825     textes doivent présenter en première ligne (hors commentaire ou ligne vide)
826     les noms des variables de colonnes. Les commentaires commencent par un "#".
827     """
828     __slots__ = (
829         "_filename", "_colnames", "_colindex", "_varsline", "_format",
830         "_delimiter", "_skiprows", "__url", "__filestring", "__header",
831         "__allowvoid", "__binaryformats", "__supportedformats")
832     def __enter__(self): return self
833     def __exit__(self, exc_type, exc_val, exc_tb): return False
834     #
835     def __init__(self, Filename=None, ColNames=None, ColIndex=None, Format="Guess", AllowVoidNameList=True):
836         """
837         Verifie l'existence et les informations de définition du fichier. Les
838         noms de colonnes ou de variables sont ignorées si le format ne permet
839         pas de les indiquer.
840         Arguments :
841             - Filename : nom du fichier
842             - ColNames : noms de la ou des colonnes/variables à lire
843             - ColIndex : nom unique de la colonne/variable servant d'index
844             - Format : format du fichier et/ou des données inclues
845             - AllowVoidNameList : permet, si la liste de noms est vide, de
846               prendre par défaut toutes les colonnes
847         """
848         self.__binaryformats =(
849             "application/numpy.npy",
850             "application/numpy.npz",
851             "application/dymola.sdf",
852             )
853         self.__url = ImportDetector( Filename, Format)
854         self.__url.raise_error_if_not_local_file()
855         self._filename = self.__url.get_absolute_name()
856         PlatformInfo.checkFileNameConformity( self._filename )
857         #
858         self._format = self.__url.get_comprehensive_mime()
859         #
860         self.__header, self._varsline, self._skiprows = self.__getentete()
861         #
862         if self._format == "text/csv" or Format.upper() == "CSV":
863             self._format = "text/csv"
864             self.__filestring = "".join(self.__header)
865             if self.__filestring.count(",") > 1:
866                 self._delimiter = ","
867             elif self.__filestring.count(";") > 1:
868                 self._delimiter = ";"
869             else:
870                 self._delimiter = None
871         elif self._format == "text/tab-separated-values" or Format.upper() == "TSV":
872             self._format = "text/tab-separated-values"
873             self._delimiter = "\t"
874         else:
875             self._delimiter = None
876         #
877         if ColNames is not None: self._colnames = tuple(ColNames)
878         else:                    self._colnames = None
879         #
880         if ColIndex is not None: self._colindex = str(ColIndex)
881         else:                    self._colindex = None
882         #
883         self.__allowvoid = bool(AllowVoidNameList)
884
885     def __getentete(self, __nblines = 3):
886         "Lit l'entête du fichier pour trouver la définition des variables"
887         # La première ligne non vide non commentée est toujours considérée
888         # porter les labels de colonne, donc pas des valeurs
889         __header, __varsline, __skiprows = [], "", 1
890         if self._format in self.__binaryformats:
891             pass
892         else:
893             with open(self._filename,'r') as fid:
894                 __line = fid.readline().strip()
895                 while "#" in __line or len(__line) < 1:
896                     __header.append(__line)
897                     __skiprows += 1
898                     __line = fid.readline().strip()
899                 __varsline = __line # Ligne de labels par convention
900                 for i in range(max(0,__nblines)):
901                     __header.append(fid.readline())
902         return (__header, __varsline, __skiprows)
903
904     def __getindices(self, __colnames, __colindex, __delimiter=None ):
905         "Indices de colonnes correspondants à l'index et aux variables"
906         if __delimiter is None:
907             __varserie = self._varsline.strip('#').strip().split()
908         else:
909             __varserie = self._varsline.strip('#').strip().split(str(__delimiter))
910         #
911         if __colnames is not None:
912             __usecols = []
913             __colnames = tuple(__colnames)
914             for v in __colnames:
915                 for i, n in enumerate(__varserie):
916                     if v == n: __usecols.append(i)
917             __usecols = tuple(__usecols)
918             if len(__usecols) == 0:
919                 if self.__allowvoid:
920                     __usecols = None
921                 else:
922                     raise ValueError("Can not found any column corresponding to the required names %s"%(__colnames,))
923         else:
924             __usecols = None
925         #
926         if __colindex is not None:
927             __useindex = None
928             __colindex = str(__colindex)
929             for i, n in enumerate(__varserie):
930                 if __colindex == n: __useindex = i
931         else:
932             __useindex = None
933         #
934         return (__usecols, __useindex)
935
936     def getsupported(self):
937         self.__supportedformats = {}
938         self.__supportedformats["text/plain"]                = True
939         self.__supportedformats["text/csv"]                  = True
940         self.__supportedformats["text/tab-separated-values"] = True
941         self.__supportedformats["application/numpy.npy"]     = True
942         self.__supportedformats["application/numpy.npz"]     = True
943         self.__supportedformats["application/dymola.sdf"]    = PlatformInfo.has_sdf
944         return self.__supportedformats
945
946     def getvalue(self, ColNames=None, ColIndex=None ):
947         "Renvoie la ou les variables demandées par la liste de leurs noms"
948         # Uniquement si mise à jour
949         if ColNames is not None: self._colnames = tuple(ColNames)
950         if ColIndex is not None: self._colindex = str(ColIndex)
951         #
952         __index = None
953         if self._format == "application/numpy.npy":
954             __columns = numpy.load(self._filename)
955         #
956         elif self._format == "application/numpy.npz":
957             __columns = None
958             with numpy.load(self._filename) as __allcolumns:
959                 if self._colnames is None:
960                     self._colnames = __allcolumns.files
961                 for nom in self._colnames: # Si une variable demandée n'existe pas
962                     if nom not in __allcolumns.files:
963                         self._colnames = tuple( __allcolumns.files )
964                 for nom in self._colnames:
965                     if nom in __allcolumns.files:
966                         if __columns is not None:
967                             # Attention : toutes les variables doivent avoir la même taille
968                             __columns = numpy.vstack((__columns, numpy.reshape(__allcolumns[nom], (1,-1))))
969                         else:
970                             # Première colonne
971                             __columns = numpy.reshape(__allcolumns[nom], (1,-1))
972                 if self._colindex is not None and self._colindex in __allcolumns.files:
973                     __index = numpy.array(numpy.reshape(__allcolumns[self._colindex], (1,-1)), dtype=bytes)
974         elif self._format == "text/plain":
975             __usecols, __useindex = self.__getindices(self._colnames, self._colindex)
976             __columns = numpy.loadtxt(self._filename, usecols = __usecols, skiprows=self._skiprows)
977             if __useindex is not None:
978                 __index = numpy.loadtxt(self._filename, dtype = bytes, usecols = (__useindex,), skiprows=self._skiprows)
979             if __usecols is None: # Si une variable demandée n'existe pas
980                 self._colnames = None
981         #
982         elif self._format == "application/dymola.sdf" and PlatformInfo.has_sdf:
983             import sdf
984             __content = sdf.load(self._filename)
985             __columns = None
986             if self._colnames is None:
987                 self._colnames = [__content.datasets[i].name for i in range(len(__content.datasets))]
988             for nom in self._colnames:
989                 if nom in __content:
990                     if __columns is not None:
991                         # Attention : toutes les variables doivent avoir la même taille
992                         __columns = numpy.vstack((__columns, numpy.reshape(__content[nom].data, (1,-1))))
993                     else:
994                         # Première colonne
995                         __columns = numpy.reshape(__content[nom].data, (1,-1))
996             if self._colindex is not None and self._colindex in __content:
997                 __index = __content[self._colindex].data
998         #
999         elif self._format == "text/csv":
1000             __usecols, __useindex = self.__getindices(self._colnames, self._colindex, self._delimiter)
1001             __columns = numpy.loadtxt(self._filename, usecols = __usecols, delimiter = self._delimiter, skiprows=self._skiprows)
1002             if __useindex is not None:
1003                 __index = numpy.loadtxt(self._filename, dtype = bytes, usecols = (__useindex,), delimiter = self._delimiter, skiprows=self._skiprows)
1004             if __usecols is None: # Si une variable demandée n'existe pas
1005                 self._colnames = None
1006         #
1007         elif self._format == "text/tab-separated-values":
1008             __usecols, __useindex = self.__getindices(self._colnames, self._colindex, self._delimiter)
1009             __columns = numpy.loadtxt(self._filename, usecols = __usecols, delimiter = self._delimiter, skiprows=self._skiprows)
1010             if __useindex is not None:
1011                 __index = numpy.loadtxt(self._filename, dtype = bytes, usecols = (__useindex,), delimiter = self._delimiter, skiprows=self._skiprows)
1012             if __usecols is None: # Si une variable demandée n'existe pas
1013                 self._colnames = None
1014         else:
1015             raise ValueError("Unkown file format \"%s\" or no reader available"%self._format)
1016         if __columns is None: __columns = ()
1017         #
1018         def toString(value):
1019             try:
1020                 return value.decode()
1021             except ValueError:
1022                 return value
1023         if __index is not None:
1024             __index = tuple([toString(v) for v in __index])
1025         #
1026         return (self._colnames, __columns, self._colindex, __index)
1027
1028     def getstring(self):
1029         "Renvoie le fichier texte complet"
1030         if self._format in self.__binaryformats:
1031             return ""
1032         else:
1033             with open(self._filename,'r') as fid:
1034                 return fid.read()
1035
1036     def getformat(self):
1037         return self._format
1038
1039 class ImportScalarLinesFromFile(ImportFromFile):
1040     """
1041     Importation de fichier contenant des variables scalaires nommées. Le
1042     fichier comporte soit 2, soit 4 colonnes, obligatoirement nommées "Name",
1043     "Value", "Minimum", "Maximum" si les noms sont précisés. Sur chaque ligne
1044     est indiqué le nom, la valeur, et éventuelement deux bornes min et max (ou
1045     None si nécessaire pour une borne).
1046
1047     Seule la méthode "getvalue" est changée.
1048     """
1049     def __enter__(self): return self
1050     def __exit__(self, exc_type, exc_val, exc_tb): return False
1051     #
1052     def __init__(self, Filename=None, ColNames=None, ColIndex=None, Format="Guess"):
1053         ImportFromFile.__init__(self, Filename, ColNames, ColIndex, Format)
1054         if self._format not in ["text/plain", "text/csv", "text/tab-separated-values"]:
1055             raise ValueError("Unkown file format \"%s\""%self._format)
1056     #
1057     def getvalue(self, VarNames = None, HeaderNames=()):
1058         "Renvoie la ou les variables demandées par la liste de leurs noms"
1059         if VarNames is not None: __varnames = tuple(VarNames)
1060         else:                    __varnames = None
1061         #
1062         if "Name" in self._varsline and "Value" in self._varsline and "Minimum" in self._varsline and "Maximum" in self._varsline:
1063             __ftype = "NamValMinMax"
1064             __dtypes   = {'names'  : ('Name', 'Value', 'Minimum', 'Maximum'),
1065                           'formats': ('S128', 'g', 'g', 'g')}
1066             __usecols  = (0, 1, 2, 3)
1067             def __replaceNoneN( s ):
1068                 if s.strip() == b'None': return numpy.NINF
1069                 else:                    return s
1070             def __replaceNoneP( s ):
1071                 if s.strip() == b'None': return numpy.PINF
1072                 else:                    return s
1073             __converters = {2: __replaceNoneN, 3: __replaceNoneP}
1074         elif "Name" in self._varsline and "Value" in self._varsline and ("Minimum" not in self._varsline or "Maximum" not in self._varsline):
1075             __ftype = "NamVal"
1076             __dtypes   = {'names'  : ('Name', 'Value'),
1077                           'formats': ('S128', 'g')}
1078             __converters = None
1079             __usecols  = (0, 1)
1080         elif len(HeaderNames)>0 and numpy.all([kw in self._varsline for kw in HeaderNames]):
1081             __ftype = "NamLotOfVals"
1082             __dtypes   = {'names'  : HeaderNames,
1083                           'formats': tuple(['S128',]+['g']*(len(HeaderNames)-1))}
1084             __usecols  = tuple(range(len(HeaderNames)))
1085             def __replaceNone( s ):
1086                 if s.strip() == b'None': return numpy.NAN
1087                 else:                    return s
1088             __converters = dict()
1089             for i in range(1,len(HeaderNames)):
1090                 __converters[i] = __replaceNone
1091         else:
1092             raise ValueError("Can not find names of columns for initial values. Wrong first line is:\n            \"%s\""%self._varsline)
1093         #
1094         if self._format == "text/plain":
1095             __content = numpy.loadtxt(self._filename, dtype = __dtypes, usecols = __usecols, skiprows = self._skiprows, converters = __converters)
1096         elif self._format in ["text/csv", "text/tab-separated-values"]:
1097             __content = numpy.loadtxt(self._filename, dtype = __dtypes, usecols = __usecols, skiprows = self._skiprows, converters = __converters, delimiter = self._delimiter)
1098         else:
1099             raise ValueError("Unkown file format \"%s\""%self._format)
1100         #
1101         __names, __thevalue, __bounds = [], [], []
1102         for sub in __content:
1103             if len(__usecols) == 4:
1104                 na, va, mi, ma = sub
1105                 if numpy.isneginf(mi): mi = None # Réattribue les variables None
1106                 elif numpy.isnan(mi):  mi = None # Réattribue les variables None
1107                 if numpy.isposinf(ma): ma = None # Réattribue les variables None
1108                 elif numpy.isnan(ma):  ma = None # Réattribue les variables None
1109             elif len(__usecols) == 2 and __ftype == "NamVal":
1110                 na, va = sub
1111                 mi, ma = None, None
1112             else:
1113                 nsub = list(sub)
1114                 na = sub[0]
1115                 for i, v in enumerate(nsub[1:]):
1116                     if numpy.isnan(v): nsub[i+1] = None
1117                 va = nsub[1:]
1118                 mi, ma = None, None
1119             na = na.decode()
1120             if (__varnames is None or na in __varnames) and (na not in __names):
1121                 # Ne stocke que la premiere occurence d'une variable
1122                 __names.append(na)
1123                 __thevalue.append(va)
1124                 __bounds.append((mi,ma))
1125         #
1126         __names      = tuple(__names)
1127         __thevalue = numpy.array(__thevalue)
1128         __bounds     = tuple(__bounds)
1129         #
1130         return (__names, __thevalue, __bounds)
1131
1132 # ==============================================================================
1133 class EficasGUI(object):
1134     """
1135     Lancement autonome de l'interface EFICAS/ADAO
1136     """
1137     def __init__(self, __addpath = None):
1138         # Chemin pour l'installation (ordre important)
1139         self.__msg = ""
1140         self.__path_settings_ok = False
1141         #----------------
1142         if "EFICAS_ROOT" in os.environ:
1143             __EFICAS_ROOT = os.environ["EFICAS_ROOT"]
1144             __path_ok = True
1145         else:
1146             self.__msg += "\nKeyError:\n"+\
1147                 "  the required environment variable EFICAS_ROOT is unknown.\n"+\
1148                 "  You have either to be in SALOME environment, or to set\n"+\
1149                 "  this variable in your environment to the right path \"<...>\"\n"+\
1150                 "  to find an installed EFICAS application. For example:\n"+\
1151                 "      EFICAS_ROOT=\"<...>\" command\n"
1152             __path_ok = False
1153         try:
1154             import adao
1155             __path_ok = True and __path_ok
1156         except ImportError:
1157             self.__msg += "\nImportError:\n"+\
1158                 "  the required ADAO library can not be found to be imported.\n"+\
1159                 "  You have either to be in ADAO environment, or to be in SALOME\n"+\
1160                 "  environment, or to set manually in your Python 3 environment the\n"+\
1161                 "  right path \"<...>\" to find an installed ADAO application. For\n"+\
1162                 "  example:\n"+\
1163                 "      PYTHONPATH=\"<...>:${PYTHONPATH}\" command\n"
1164             __path_ok = False
1165         try:
1166             import PyQt5
1167             __path_ok = True and __path_ok
1168         except ImportError:
1169             self.__msg += "\nImportError:\n"+\
1170                 "  the required PyQt5 library can not be found to be imported.\n"+\
1171                 "  You have either to have a raisonable up-to-date Python 3\n"+\
1172                 "  installation (less than 5 years), or to be in SALOME environment.\n"
1173             __path_ok = False
1174         #----------------
1175         if not __path_ok:
1176             self.__msg += "\nWarning:\n"+\
1177                 "  It seems you have some troubles with your installation.\n"+\
1178                 "  Be aware that some other errors may exist, that are not\n"+\
1179                 "  explained as above, like some incomplete or obsolete\n"+\
1180                 "  Python 3, or incomplete module installation.\n"+\
1181                 "  \n"+\
1182                 "  Please correct the above error(s) before launching the\n"+\
1183                 "  standalone EFICAS/ADAO interface.\n"
1184             logging.debug("Some of the ADAO/EFICAS/QT5 paths have not been found")
1185             self.__path_settings_ok = False
1186         else:
1187             logging.debug("All the ADAO/EFICAS/QT5 paths have been found")
1188             self.__path_settings_ok = True
1189         #----------------
1190         if self.__path_settings_ok:
1191             sys.path.insert(0,__EFICAS_ROOT)
1192             sys.path.insert(0,os.path.join(adao.adao_py_dir,"daEficas"))
1193             if __addpath is not None and os.path.exists(os.path.abspath(__addpath)):
1194                 sys.path.insert(0,os.path.abspath(__addpath))
1195             logging.debug("All the paths have been correctly set up")
1196         else:
1197             print(self.__msg)
1198             logging.debug("Errors in path settings have been found")
1199
1200     def gui(self):
1201         if self.__path_settings_ok:
1202             logging.debug("Launching standalone EFICAS/ADAO interface...")
1203             from daEficas import prefs
1204             from InterfaceQT4 import eficas_go
1205             eficas_go.lanceEficas(code=prefs.code)
1206         else:
1207             logging.debug("Can not launch standalone EFICAS/ADAO interface for path errors.")
1208
1209 # ==============================================================================
1210 if __name__ == "__main__":
1211     print('\n AUTODIAGNOSTIC\n')