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