Salome HOME
Minor documentation and code review corrections (38)
[modules/adao.git] / src / daComposant / daCore / Interfaces.py
1 # -*- coding: utf-8 -*-
2 #
3 # Copyright (C) 2008-2023 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     #
409     def _append(self, __command=None, __keys=None, __local=None, __pre=None, __switchoff=False):
410         "Transformation d'une commande individuelle en un enregistrement"
411         if __command == "set": __command = __local["Concept"]
412         else:                  __command = __command.replace("set", "", 1)
413         logging.debug("SCD Order processed: %s"%(__command))
414         #
415         __text  = None
416         if __command in (None, 'execute', 'executePythonScheme', 'executeYACSScheme', 'get', 'Name'):
417             return
418         elif __command in ['Directory',]:
419             __text  = "#\nstudy_config['Repertory'] = %s"%(repr(__local['String']))
420         elif __command in ['Debug', 'setDebug']:
421             __text  = "#\nstudy_config['Debug'] = '1'"
422             self.__DebugCommandNotSet = False
423         elif __command in ['NoDebug', 'setNoDebug']:
424             __text  = "#\nstudy_config['Debug'] = '0'"
425             self.__DebugCommandNotSet = False
426         elif __command in ['Observer', 'setObserver']:
427             if self.__ObserverCommandNotSet:
428                 self._addLine("observers = {}")
429                 self._addLine("study_config['Observers'] = observers")
430                 self.__ObserverCommandNotSet = False
431             __obs   = __local['Variable']
432             self._numobservers += 1
433             __text  = "#\n"
434             __text += "observers['%s'] = {}\n"%__obs
435             if __local['String'] is not None:
436                 __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'String')
437                 __text += "observers['%s']['String'] = \"\"\"%s\"\"\"\n"%(__obs, __local['String'])
438             if __local['Script'] is not None:
439                 __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'Script')
440                 __text += "observers['%s']['Script'] = \"%s\"\n"%(__obs, __local['Script'])
441             if __local['Template'] is not None and __local['Template'] in Templates.ObserverTemplates:
442                 __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'String')
443                 __text += "observers['%s']['String'] = \"\"\"%s\"\"\"\n"%(__obs, Templates.ObserverTemplates[__local['Template']])
444             if __local['Info'] is not None:
445                 __text += "observers['%s']['info'] = \"\"\"%s\"\"\"\n"%(__obs, __local['Info'])
446             else:
447                 __text += "observers['%s']['info'] = \"\"\"%s\"\"\"\n"%(__obs, __obs)
448             __text += "observers['%s']['number'] = %s"%(__obs, self._numobservers)
449         elif __command in ['UserPostAnalysis', 'setUserPostAnalysis']:
450             __text  = "#\n"
451             __text += "Analysis_config = {}\n"
452             if __local['String'] is not None:
453                 __text += "Analysis_config['From'] = 'String'\n"
454                 __text += "Analysis_config['Data'] = \"\"\"%s\"\"\"\n"%(__local['String'],)
455             if __local['Script'] is not None:
456                 __text += "Analysis_config['From'] = 'Script'\n"
457                 __text += "Analysis_config['Data'] = \"\"\"%s\"\"\"\n"%(__local['Script'],)
458             if __local['Template'] is not None and __local['Template'] in Templates.UserPostAnalysisTemplates:
459                 __text += "Analysis_config['From'] = 'String'\n"
460                 __text += "Analysis_config['Data'] = \"\"\"%s\"\"\"\n"%(Templates.UserPostAnalysisTemplates[__local['Template']],)
461             __text += "study_config['UserPostAnalysis'] = Analysis_config"
462             self.__UserPostAnalysisNotSet = False
463         elif __local is not None: # __keys is not None and
464             numpy.set_printoptions(precision=15,threshold=1000000,linewidth=1000*15)
465             __text  = "#\n"
466             __text += "%s_config = {}\n"%__command
467             __local.pop('self','')
468             __to_be_removed = []
469             __vectorIsDataFile = False
470             __vectorIsScript = False
471             for __k,__v in __local.items():
472                 if __v is None: __to_be_removed.append(__k)
473             for __k in __to_be_removed:
474                 __local.pop(__k)
475             for __k,__v in __local.items():
476                 if __k == "Concept": continue
477                 if __k in ['ScalarSparseMatrix','DiagonalSparseMatrix','Matrix','OneFunction','ThreeFunctions'] \
478                     and 'Script' in __local and __local['Script'] is not None: continue
479                 if __k in ['Vector','VectorSerie'] \
480                     and 'DataFile' in __local and __local['DataFile'] is not None: continue
481                 if __k == 'Parameters' and not (__command in ['AlgorithmParameters','SupplementaryParameters']): continue
482                 if __k == 'Algorithm':
483                     __text += "study_config['Algorithm'] = %s\n"%(repr(__v))
484                 elif __k == 'DataFile':
485                     __k = 'Vector'
486                     __f = 'DataFile'
487                     __v = "'"+repr(__v)+"'"
488                     for __lk in ['Vector','VectorSerie']:
489                         if __lk in __local and __local[__lk]: __k = __lk
490                     __text += "%s_config['Type'] = '%s'\n"%(__command,__k)
491                     __text += "%s_config['From'] = '%s'\n"%(__command,__f)
492                     __text += "%s_config['Data'] = %s\n"%(__command,__v)
493                     __text = __text.replace("''","'")
494                     __vectorIsDataFile = True
495                 elif __k == 'Script':
496                     __k = 'Vector'
497                     __f = 'Script'
498                     __v = "'"+repr(__v)+"'"
499                     for __lk in ['ScalarSparseMatrix','DiagonalSparseMatrix','Matrix']:
500                         if __lk in __local and __local[__lk]: __k = __lk
501                     if __command == "AlgorithmParameters": __k = "Dict"
502                     if 'OneFunction' in __local and __local['OneFunction']:
503                         __text += "%s_ScriptWithOneFunction = {}\n"%(__command,)
504                         __text += "%s_ScriptWithOneFunction['Function'] = ['Direct', 'Tangent', 'Adjoint']\n"%(__command,)
505                         __text += "%s_ScriptWithOneFunction['Script'] = {}\n"%(__command,)
506                         __text += "%s_ScriptWithOneFunction['Script']['Direct'] = %s\n"%(__command,__v)
507                         __text += "%s_ScriptWithOneFunction['Script']['Tangent'] = %s\n"%(__command,__v)
508                         __text += "%s_ScriptWithOneFunction['Script']['Adjoint'] = %s\n"%(__command,__v)
509                         __text += "%s_ScriptWithOneFunction['DifferentialIncrement'] = 1e-06\n"%(__command,)
510                         __text += "%s_ScriptWithOneFunction['CenteredFiniteDifference'] = 0\n"%(__command,)
511                         __k = 'Function'
512                         __f = 'ScriptWithOneFunction'
513                         __v = '%s_ScriptWithOneFunction'%(__command,)
514                     if 'ThreeFunctions' in __local and __local['ThreeFunctions']:
515                         __text += "%s_ScriptWithFunctions = {}\n"%(__command,)
516                         __text += "%s_ScriptWithFunctions['Function'] = ['Direct', 'Tangent', 'Adjoint']\n"%(__command,)
517                         __text += "%s_ScriptWithFunctions['Script'] = {}\n"%(__command,)
518                         __text += "%s_ScriptWithFunctions['Script']['Direct'] = %s\n"%(__command,__v)
519                         __text += "%s_ScriptWithFunctions['Script']['Tangent'] = %s\n"%(__command,__v)
520                         __text += "%s_ScriptWithFunctions['Script']['Adjoint'] = %s\n"%(__command,__v)
521                         __k = 'Function'
522                         __f = 'ScriptWithFunctions'
523                         __v = '%s_ScriptWithFunctions'%(__command,)
524                     __text += "%s_config['Type'] = '%s'\n"%(__command,__k)
525                     __text += "%s_config['From'] = '%s'\n"%(__command,__f)
526                     __text += "%s_config['Data'] = %s\n"%(__command,__v)
527                     __text = __text.replace("''","'")
528                     __vectorIsScript = True
529                 elif __k in ('Stored', 'Checked', 'ColMajor', 'InputFunctionAsMulti', 'nextStep'):
530                     if bool(__v):
531                         __text += "%s_config['%s'] = '%s'\n"%(__command,__k,int(bool(__v)))
532                 elif __k in ('PerformanceProfile', 'noDetails'):
533                     if not bool(__v):
534                         __text += "%s_config['%s'] = '%s'\n"%(__command,__k,int(bool(__v)))
535                 else:
536                     if __k == 'Vector' and __vectorIsScript: continue
537                     if __k == 'Vector' and __vectorIsDataFile: continue
538                     if __k == 'Parameters': __k = "Dict"
539                     if isinstance(__v,Persistence.Persistence): __v = __v.values()
540                     if callable(__v): __text = self._missing%__v.__name__+__text
541                     if isinstance(__v,dict):
542                         for val in __v.values():
543                             if callable(val): __text = self._missing%val.__name__+__text
544                     __text += "%s_config['Type'] = '%s'\n"%(__command,__k)
545                     __text += "%s_config['From'] = '%s'\n"%(__command,'String')
546                     __text += "%s_config['Data'] = \"\"\"%s\"\"\"\n"%(__command,repr(__v))
547             __text += "study_config['%s'] = %s_config"%(__command,__command)
548             numpy.set_printoptions(precision=8,threshold=1000,linewidth=75)
549             if __switchoff:
550                 self._switchoff = True
551         if __text is not None: self._addLine(__text)
552         if not __switchoff:
553             self._switchoff = False
554     #
555     def _finalize(self, *__args):
556         self.__loadVariablesByScript()
557         if self.__DebugCommandNotSet:
558             self._addLine("#\nstudy_config['Debug'] = '0'")
559         if self.__UserPostAnalysisNotSet:
560             self._addLine("#")
561             self._addLine("Analysis_config = {}")
562             self._addLine("Analysis_config['From'] = 'String'")
563             self._addLine("Analysis_config['Data'] = \"\"\"import numpy")
564             self._addLine("xa=ADD.get('Analysis')[-1]")
565             self._addLine("print('Analysis:',xa)\"\"\"")
566             self._addLine("study_config['UserPostAnalysis'] = Analysis_config")
567     #
568     def __loadVariablesByScript(self):
569         __ExecVariables = {} # Necessaire pour recuperer la variable
570         exec("\n".join(self._lineSerie), __ExecVariables)
571         study_config = __ExecVariables['study_config']
572         # Pour Python 3 : self.__hasAlgorithm = bool(study_config['Algorithm'])
573         if 'Algorithm' in study_config:
574             self.__hasAlgorithm = True
575         else:
576             self.__hasAlgorithm = False
577         if not self.__hasAlgorithm and \
578                 "AlgorithmParameters" in study_config and \
579                 isinstance(study_config['AlgorithmParameters'], dict) and \
580                 "From" in study_config['AlgorithmParameters'] and \
581                 "Data" in study_config['AlgorithmParameters'] and \
582                 study_config['AlgorithmParameters']['From'] == 'Script':
583             __asScript = study_config['AlgorithmParameters']['Data']
584             __var = ImportFromScript(__asScript).getvalue( "Algorithm" )
585             __text = "#\nstudy_config['Algorithm'] = '%s'"%(__var,)
586             self._addLine(__text)
587         if self.__hasAlgorithm and \
588                 "AlgorithmParameters" in study_config and \
589                 isinstance(study_config['AlgorithmParameters'], dict) and \
590                 "From" not in study_config['AlgorithmParameters'] and \
591                 "Data" not in study_config['AlgorithmParameters']:
592             __text  = "#\n"
593             __text += "AlgorithmParameters_config['Type'] = 'Dict'\n"
594             __text += "AlgorithmParameters_config['From'] = 'String'\n"
595             __text += "AlgorithmParameters_config['Data'] = '{}'\n"
596             self._addLine(__text)
597         if 'SupplementaryParameters' in study_config and \
598                 isinstance(study_config['SupplementaryParameters'], dict) and \
599                 "From" in study_config['SupplementaryParameters'] and \
600                 study_config['SupplementaryParameters']["From"] == 'String' and \
601                 "Data" in study_config['SupplementaryParameters']:
602             __dict = eval(study_config['SupplementaryParameters']["Data"])
603             if 'ExecuteInContainer' in __dict:
604                 self._addLine("#\nstudy_config['ExecuteInContainer'] = '%s'"%__dict['ExecuteInContainer'])
605             else:
606                 self._addLine("#\nstudy_config['ExecuteInContainer'] = 'No'")
607             if 'StudyType' in __dict:
608                 self._addLine("#\nstudy_config['StudyType'] = '%s'"%__dict['StudyType'])
609             if 'StudyType' in __dict and __dict['StudyType'] != "ASSIMILATION_STUDY":
610                 self.__UserPostAnalysisNotSet = False
611         del study_config
612
613 class _YACSViewer(GenericCaseViewer):
614     """
615     Etablissement des commandes d'un cas YACS (Cas->SCD->YACS)
616     """
617     __slots__ = ("__internalSCD", "_append")
618     #
619     def __init__(self, __name="", __objname="case", __content=None, __object=None):
620         "Initialisation et enregistrement de l'entete"
621         GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
622         self.__internalSCD = _SCDViewer(__name, __objname, __content, __object)
623         self._append       = self.__internalSCD._append
624     #
625     def dump(self, __filename=None, __upa=None):
626         "Restitution normalisée des commandes"
627         # -----
628         if __filename is None:
629             raise ValueError("A file name has to be given for YACS XML output.")
630         else:
631             __file    = os.path.abspath(__filename)
632             if os.path.isfile(__file) or os.path.islink(__file):
633                 os.remove(__file)
634         # -----
635         if not PlatformInfo.has_salome or \
636             not PlatformInfo.has_adao:
637             raise ImportError(
638                 "Unable to get SALOME (%s) or ADAO (%s) environnement for YACS conversion.\n"%(PlatformInfo.has_salome,PlatformInfo.has_adao)+\
639                 "Please load the right SALOME environnement before trying to use it.")
640         else:
641             from daYacsSchemaCreator.run import create_schema_from_content
642         # -----
643         self.__internalSCD._finalize(__upa)
644         __SCDdump = self.__internalSCD.dump()
645         create_schema_from_content(__SCDdump, __file)
646         # -----
647         if not os.path.exists(__file):
648             __msg  = "An error occured during the ADAO YACS Schema build for\n"
649             __msg += "the target output file:\n"
650             __msg += "  %s\n"%__file
651             __msg += "See errors details in your launching terminal log.\n"
652             raise ValueError(__msg)
653         # -----
654         __fid = open(__file,"r")
655         __text = __fid.read()
656         __fid.close()
657         return __text
658
659 # ==============================================================================
660 class _ReportViewer(GenericCaseViewer):
661     """
662     Partie commune de restitution simple
663     """
664     __slots__ = ("_r")
665     #
666     def __init__(self, __name="", __objname="case", __content=None, __object=None):
667         "Initialisation et enregistrement de l'entete"
668         GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
669         self._r = Reporting.ReportStorage()
670         self._r.clear()
671         if self._name == "":
672             self._r.append("ADAO Study report", "title")
673         else:
674             self._r.append(str(self._name), "title")
675         if self._content is not None:
676             for command in self._content:
677                 self._append(*command)
678     #
679     def _append(self, __command=None, __keys=None, __local=None, __pre=None, __switchoff=False):
680         "Transformation d'une commande individuelle en un enregistrement"
681         if __command is not None and __keys is not None and __local is not None:
682             if __command in ("set","get") and "Concept" in __keys: __command = __local["Concept"]
683             __text  = ""
684             __text += "<i>%s</i> command has been set"%str(__command.replace("set",""))
685             __ktext = ""
686             for k in __keys:
687                 if k not in __local: continue
688                 __v = __local[k]
689                 if __v is None: continue
690                 if   k == "Checked"              and not __v: continue
691                 if   k == "Stored"               and not __v: continue
692                 if   k == "ColMajor"             and not __v: continue
693                 if   k == "InputFunctionAsMulti" and not __v: continue
694                 if   k == "nextStep"             and not __v: continue
695                 if   k == "PerformanceProfile"   and     __v: continue
696                 if   k == "noDetails":                        continue
697                 if   k == "Concept":                          continue
698                 if   k == "self":                             continue
699                 if isinstance(__v,Persistence.Persistence): __v = __v.values()
700                 numpy.set_printoptions(precision=15,threshold=1000000,linewidth=1000*15)
701                 __ktext += "\n        %s = %s,"%(k,repr(__v))
702                 numpy.set_printoptions(precision=8,threshold=1000,linewidth=75)
703             if len(__ktext) > 0:
704                 __text += " with values:" + __ktext
705             __text = __text.rstrip(", ")
706             self._r.append(__text, "uli")
707     #
708     def _finalize(self, __upa=None):
709         "Enregistrement du final"
710         raise NotImplementedError()
711
712 class _SimpleReportInRstViewer(_ReportViewer):
713     """
714     Restitution simple en RST
715     """
716     __slots__ = ()
717     #
718     def _finalize(self, __upa=None):
719         self._lineSerie.append(Reporting.ReportViewInRst(self._r).__str__())
720
721 class _SimpleReportInHtmlViewer(_ReportViewer):
722     """
723     Restitution simple en HTML
724     """
725     __slots__ = ()
726     #
727     def _finalize(self, __upa=None):
728         self._lineSerie.append(Reporting.ReportViewInHtml(self._r).__str__())
729
730 class _SimpleReportInPlainTxtViewer(_ReportViewer):
731     """
732     Restitution simple en TXT
733     """
734     __slots__ = ()
735     #
736     def _finalize(self, __upa=None):
737         self._lineSerie.append(Reporting.ReportViewInPlainTxt(self._r).__str__())
738
739 # ==============================================================================
740 class ImportFromScript(object):
741     """
742     Obtention d'une variable nommee depuis un fichier script importé
743     """
744     __slots__ = ("__basename", "__filenspace", "__filestring")
745     #
746     def __init__(self, __filename=None):
747         "Verifie l'existence et importe le script"
748         if __filename is None:
749             raise ValueError("The name of the file, containing the variable to be read, has to be specified.")
750         if not os.path.isfile(__filename):
751             raise ValueError(
752                 "The file containing the variable to be imported doesn't seem to"+\
753                 " exist. Please check the file. The given file name is:\n  \"%s\""%str(__filename))
754         if os.path.dirname(__filename) != '':
755             sys.path.insert(0, os.path.dirname(__filename))
756             __basename = os.path.basename(__filename).rstrip(".py")
757         else:
758             __basename = __filename.rstrip(".py")
759         PlatformInfo.checkFileNameImportability( __basename+".py" )
760         self.__basename = __basename
761         try:
762             self.__filenspace = __import__(__basename, globals(), locals(), [])
763         except NameError:
764             self.__filenspace = ""
765         with open(__filename,'r') as fid:
766             self.__filestring = fid.read()
767     #
768     def getvalue(self, __varname=None, __synonym=None ):
769         "Renvoie la variable demandee par son nom ou son synonyme"
770         if __varname is None:
771             raise ValueError("The name of the variable to be read has to be specified. Please check the content of the file and the syntax.")
772         if not hasattr(self.__filenspace, __varname):
773             if __synonym is None:
774                 raise ValueError(
775                     "The imported script file \"%s\""%(str(self.__basename)+".py",)+\
776                     " doesn't contain the mandatory variable \"%s\""%(__varname,)+\
777                     " to be read. Please check the content of the file and the syntax.")
778             elif not hasattr(self.__filenspace, __synonym):
779                 raise ValueError(
780                     "The imported script file \"%s\""%(str(self.__basename)+".py",)+\
781                     " doesn't contain the mandatory variable \"%s\""%(__synonym,)+\
782                     " to be read. Please check the content of the file and the syntax.")
783             else:
784                 return getattr(self.__filenspace, __synonym)
785         else:
786             return getattr(self.__filenspace, __varname)
787     #
788     def getstring(self):
789         "Renvoie le script complet"
790         return self.__filestring
791
792 # ==============================================================================
793 class ImportDetector(object):
794     """
795     Détection des caractéristiques de fichiers ou objets en entrée
796     """
797     __slots__ = ("__url", "__usr", "__root", "__end")
798     #
799     def __enter__(self):
800         return self
801     def __exit__(self, exc_type, exc_val, exc_tb):
802         return False
803     #
804     def __init__(self, __url, UserMime=""):
805         if __url is None:
806             raise ValueError("The name or url of the file object has to be specified.")
807         if __url is bytes:
808             self.__url = __url.decode()
809         else:
810             self.__url = str(__url)
811         if UserMime is bytes:
812             self.__usr = UserMime.decode().lower()
813         else:
814             self.__usr = str(UserMime).lower()
815         (self.__root, self.__end) = os.path.splitext(self.__url)
816         #
817         mimetypes.add_type('application/numpy.npy', '.npy')
818         mimetypes.add_type('application/numpy.npz', '.npz')
819         mimetypes.add_type('application/dymola.sdf', '.sdf')
820         if sys.platform.startswith("win"):
821             mimetypes.add_type('text/plain', '.txt')
822             mimetypes.add_type('text/csv', '.csv')
823             mimetypes.add_type('text/tab-separated-values', '.tsv')
824     #
825     # File related tests
826     # ------------------
827     def is_local_file(self):
828         if os.path.isfile(os.path.realpath(self.__url)):
829             return True
830         else:
831             return False
832     #
833     def is_not_local_file(self):
834         return not self.is_local_file()
835     #
836     def raise_error_if_not_local_file(self):
837         if self.is_not_local_file():
838             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))
839         else:
840             return False
841     #
842     # Directory related tests
843     # -----------------------
844     def is_local_dir(self):
845         if os.path.isdir(self.__url):
846             return True
847         else:
848             return False
849     #
850     def is_not_local_dir(self):
851         return not self.is_local_dir()
852     #
853     def raise_error_if_not_local_dir(self):
854         if self.is_not_local_dir():
855             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))
856         else:
857             return False
858     #
859     # Mime related functions
860     # ------------------------
861     def get_standard_mime(self):
862         (__mtype, __encoding) = mimetypes.guess_type(self.__url, strict=False)
863         return __mtype
864     #
865     def get_user_mime(self):
866         __fake = "fake."+self.__usr.lower()
867         (__mtype, __encoding) = mimetypes.guess_type(__fake, strict=False)
868         return __mtype
869     #
870     def get_comprehensive_mime(self):
871         if self.get_standard_mime() is not None:
872             return self.get_standard_mime()
873         elif self.get_user_mime() is not None:
874             return self.get_user_mime()
875         else:
876             return None
877     #
878     # Name related functions
879     # ----------------------
880     def get_user_name(self):
881         return self.__url
882     #
883     def get_absolute_name(self):
884         return os.path.abspath(os.path.realpath(self.__url))
885     #
886     def get_extension(self):
887         return self.__end
888
889 class ImportFromFile(object):
890     """
891     Obtention de variables disrétisées en 1D, définies par une ou des variables
892     nommées, et sous la forme d'une série de points éventuellement indexés. La
893     lecture d'un fichier au format spécifié (ou intuité) permet de charger ces
894     fonctions depuis :
895         - des fichiers textes en colonnes de type TXT, CSV, TSV...
896         - des fichiers de données binaires NPY, NPZ, SDF...
897     La lecture du fichier complet ne se fait que si nécessaire, pour assurer la
898     performance tout en disposant de l'interprétation du contenu. Les fichiers
899     textes doivent présenter en première ligne (hors commentaire ou ligne vide)
900     les noms des variables de colonnes. Les commentaires commencent par un "#".
901     """
902     __slots__ = (
903         "_filename", "_colnames", "_colindex", "_varsline", "_format",
904         "_delimiter", "_skiprows", "__url", "__filestring", "__header",
905         "__allowvoid", "__binaryformats", "__supportedformats")
906     #
907     def __enter__(self):
908         return self
909     #
910     def __exit__(self, exc_type, exc_val, exc_tb):
911         return False
912     #
913     def __init__(self, Filename=None, ColNames=None, ColIndex=None, Format="Guess", AllowVoidNameList=True):
914         """
915         Verifie l'existence et les informations de définition du fichier. Les
916         noms de colonnes ou de variables sont ignorées si le format ne permet
917         pas de les indiquer.
918         Arguments :
919             - Filename : nom du fichier
920             - ColNames : noms de la ou des colonnes/variables à lire
921             - ColIndex : nom unique de la colonne/variable servant d'index
922             - Format : format du fichier et/ou des données inclues
923             - AllowVoidNameList : permet, si la liste de noms est vide, de
924               prendre par défaut toutes les colonnes
925         """
926         self.__binaryformats =(
927             "application/numpy.npy",
928             "application/numpy.npz",
929             "application/dymola.sdf",
930             )
931         self.__url = ImportDetector( Filename, Format)
932         self.__url.raise_error_if_not_local_file()
933         self._filename = self.__url.get_absolute_name()
934         PlatformInfo.checkFileNameConformity( self._filename )
935         #
936         self._format = self.__url.get_comprehensive_mime()
937         #
938         self.__header, self._varsline, self._skiprows = self.__getentete()
939         #
940         if self._format == "text/csv" or Format.upper() == "CSV":
941             self._format = "text/csv"
942             self.__filestring = "".join(self.__header)
943             if self.__filestring.count(",") > 1:
944                 self._delimiter = ","
945             elif self.__filestring.count(";") > 1:
946                 self._delimiter = ";"
947             else:
948                 self._delimiter = None
949         elif self._format == "text/tab-separated-values" or Format.upper() == "TSV":
950             self._format = "text/tab-separated-values"
951             self._delimiter = "\t"
952         else:
953             self._delimiter = None
954         #
955         if ColNames is not None: self._colnames = tuple(ColNames)
956         else:                    self._colnames = None
957         #
958         if ColIndex is not None: self._colindex = str(ColIndex)
959         else:                    self._colindex = None
960         #
961         self.__allowvoid = bool(AllowVoidNameList)
962     #
963     def __getentete(self, __nblines = 3):
964         "Lit l'entête du fichier pour trouver la définition des variables"
965         # La première ligne non vide non commentée est toujours considérée
966         # porter les labels de colonne, donc pas des valeurs
967         __header, __varsline, __skiprows = [], "", 1
968         if self._format in self.__binaryformats:
969             pass
970         else:
971             with open(self._filename,'r') as fid:
972                 __line = fid.readline().strip()
973                 while "#" in __line or len(__line) < 1:
974                     __header.append(__line)
975                     __skiprows += 1
976                     __line = fid.readline().strip()
977                 __varsline = __line # Ligne de labels par convention
978                 for i in range(max(0,__nblines)):
979                     __header.append(fid.readline())
980         return (__header, __varsline, __skiprows)
981     #
982     def __getindices(self, __colnames, __colindex, __delimiter=None ):
983         "Indices de colonnes correspondants à l'index et aux variables"
984         if __delimiter is None:
985             __varserie = self._varsline.strip('#').strip().split()
986         else:
987             __varserie = self._varsline.strip('#').strip().split(str(__delimiter))
988         #
989         if __colnames is not None:
990             __usecols = []
991             __colnames = tuple(__colnames)
992             for v in __colnames:
993                 for i, n in enumerate(__varserie):
994                     if v == n: __usecols.append(i)
995             __usecols = tuple(__usecols)
996             if len(__usecols) == 0:
997                 if self.__allowvoid:
998                     __usecols = None
999                 else:
1000                     raise ValueError("Can not found any column corresponding to the required names %s"%(__colnames,))
1001         else:
1002             __usecols = None
1003         #
1004         if __colindex is not None:
1005             __useindex = None
1006             __colindex = str(__colindex)
1007             for i, n in enumerate(__varserie):
1008                 if __colindex == n: __useindex = i
1009         else:
1010             __useindex = None
1011         #
1012         return (__usecols, __useindex)
1013     #
1014     def getsupported(self):
1015         self.__supportedformats = {}
1016         self.__supportedformats["text/plain"]                = True
1017         self.__supportedformats["text/csv"]                  = True
1018         self.__supportedformats["text/tab-separated-values"] = True
1019         self.__supportedformats["application/numpy.npy"]     = True
1020         self.__supportedformats["application/numpy.npz"]     = True
1021         self.__supportedformats["application/dymola.sdf"]    = PlatformInfo.has_sdf
1022         return self.__supportedformats
1023     #
1024     def getvalue(self, ColNames=None, ColIndex=None ):
1025         "Renvoie la ou les variables demandées par la liste de leurs noms"
1026         # Uniquement si mise à jour
1027         if ColNames is not None: self._colnames = tuple(ColNames)
1028         if ColIndex is not None: self._colindex = str(ColIndex)
1029         #
1030         __index = None
1031         if self._format == "application/numpy.npy":
1032             __columns = numpy.load(self._filename)
1033         #
1034         elif self._format == "application/numpy.npz":
1035             __columns = None
1036             with numpy.load(self._filename) as __allcolumns:
1037                 if self._colnames is None:
1038                     self._colnames = __allcolumns.files
1039                 for nom in self._colnames: # Si une variable demandée n'existe pas
1040                     if nom not in __allcolumns.files:
1041                         self._colnames = tuple( __allcolumns.files )
1042                 for nom in self._colnames:
1043                     if nom in __allcolumns.files:
1044                         if __columns is not None:
1045                             # Attention : toutes les variables doivent avoir la même taille
1046                             __columns = numpy.vstack((__columns, numpy.reshape(__allcolumns[nom], (1,-1))))
1047                         else:
1048                             # Première colonne
1049                             __columns = numpy.reshape(__allcolumns[nom], (1,-1))
1050                 if self._colindex is not None and self._colindex in __allcolumns.files:
1051                     __index = numpy.array(numpy.reshape(__allcolumns[self._colindex], (1,-1)), dtype=bytes)
1052         elif self._format == "text/plain":
1053             __usecols, __useindex = self.__getindices(self._colnames, self._colindex)
1054             __columns = numpy.loadtxt(self._filename, usecols = __usecols, skiprows=self._skiprows)
1055             if __useindex is not None:
1056                 __index = numpy.loadtxt(self._filename, dtype = bytes, usecols = (__useindex,), skiprows=self._skiprows)
1057             if __usecols is None: # Si une variable demandée n'existe pas
1058                 self._colnames = None
1059         #
1060         elif self._format == "application/dymola.sdf" and PlatformInfo.has_sdf:
1061             import sdf
1062             __content = sdf.load(self._filename)
1063             __columns = None
1064             if self._colnames is None:
1065                 self._colnames = [__content.datasets[i].name for i in range(len(__content.datasets))]
1066             for nom in self._colnames:
1067                 if nom in __content:
1068                     if __columns is not None:
1069                         # Attention : toutes les variables doivent avoir la même taille
1070                         __columns = numpy.vstack((__columns, numpy.reshape(__content[nom].data, (1,-1))))
1071                     else:
1072                         # Première colonne
1073                         __columns = numpy.reshape(__content[nom].data, (1,-1))
1074             if self._colindex is not None and self._colindex in __content:
1075                 __index = __content[self._colindex].data
1076         #
1077         elif self._format == "text/csv":
1078             __usecols, __useindex = self.__getindices(self._colnames, self._colindex, self._delimiter)
1079             __columns = numpy.loadtxt(self._filename, usecols = __usecols, delimiter = self._delimiter, skiprows=self._skiprows)
1080             if __useindex is not None:
1081                 __index = numpy.loadtxt(self._filename, dtype = bytes, usecols = (__useindex,), delimiter = self._delimiter, skiprows=self._skiprows)
1082             if __usecols is None: # Si une variable demandée n'existe pas
1083                 self._colnames = None
1084         #
1085         elif self._format == "text/tab-separated-values":
1086             __usecols, __useindex = self.__getindices(self._colnames, self._colindex, self._delimiter)
1087             __columns = numpy.loadtxt(self._filename, usecols = __usecols, delimiter = self._delimiter, skiprows=self._skiprows)
1088             if __useindex is not None:
1089                 __index = numpy.loadtxt(self._filename, dtype = bytes, usecols = (__useindex,), delimiter = self._delimiter, skiprows=self._skiprows)
1090             if __usecols is None: # Si une variable demandée n'existe pas
1091                 self._colnames = None
1092         else:
1093             raise ValueError("Unkown file format \"%s\" or no reader available"%self._format)
1094         if __columns is None: __columns = ()
1095
1096         def toString(value):
1097             try:
1098                 return value.decode()
1099             except ValueError:
1100                 return value
1101         if __index is not None:
1102             __index = tuple([toString(v) for v in __index])
1103         #
1104         return (self._colnames, __columns, self._colindex, __index)
1105     #
1106     def getstring(self):
1107         "Renvoie le fichier texte complet"
1108         if self._format in self.__binaryformats:
1109             return ""
1110         else:
1111             with open(self._filename,'r') as fid:
1112                 return fid.read()
1113     #
1114     def getformat(self):
1115         return self._format
1116
1117 class ImportScalarLinesFromFile(ImportFromFile):
1118     """
1119     Importation de fichier contenant des variables scalaires nommées. Le
1120     fichier comporte soit 2, soit 4 colonnes, obligatoirement nommées "Name",
1121     "Value", "Minimum", "Maximum" si les noms sont précisés. Sur chaque ligne
1122     est indiqué le nom, la valeur, et éventuelement deux bornes min et max (ou
1123     None si nécessaire pour une borne).
1124
1125     Seule la méthode "getvalue" est changée.
1126     """
1127     __slots__ = ()
1128     #
1129     def __enter__(self):
1130         return self
1131     #
1132     def __exit__(self, exc_type, exc_val, exc_tb):
1133         return False
1134     #
1135     def __init__(self, Filename=None, ColNames=None, ColIndex=None, Format="Guess"):
1136         ImportFromFile.__init__(self, Filename, ColNames, ColIndex, Format)
1137         if self._format not in ["text/plain", "text/csv", "text/tab-separated-values"]:
1138             raise ValueError("Unkown file format \"%s\""%self._format)
1139     #
1140     def getvalue(self, VarNames = None, HeaderNames=()):
1141         "Renvoie la ou les variables demandées par la liste de leurs noms"
1142         if VarNames is not None: __varnames = tuple(VarNames)
1143         else:                    __varnames = None
1144         #
1145         if "Name" in self._varsline and "Value" in self._varsline and "Minimum" in self._varsline and "Maximum" in self._varsline:
1146             __ftype = "NamValMinMax"
1147             __dtypes   = {'names'  : ('Name', 'Value', 'Minimum', 'Maximum'),
1148                           'formats': ('S128', 'g', 'g', 'g')}
1149             __usecols  = (0, 1, 2, 3)
1150
1151             def __replaceNoneN( s ):
1152                 if s.strip() == b'None': return numpy.NINF
1153                 else:                    return s
1154
1155             def __replaceNoneP( s ):
1156                 if s.strip() == b'None': return numpy.PINF
1157                 else:                    return s
1158             __converters = {2: __replaceNoneN, 3: __replaceNoneP}
1159         elif "Name" in self._varsline and "Value" in self._varsline and ("Minimum" not in self._varsline or "Maximum" not in self._varsline):
1160             __ftype = "NamVal"
1161             __dtypes   = {'names'  : ('Name', 'Value'),
1162                           'formats': ('S128', 'g')}
1163             __converters = None
1164             __usecols  = (0, 1)
1165         elif len(HeaderNames)>0 and numpy.all([kw in self._varsline for kw in HeaderNames]):
1166             __ftype = "NamLotOfVals"
1167             __dtypes   = {'names'  : HeaderNames,
1168                           'formats': tuple(['S128',]+['g']*(len(HeaderNames)-1))}
1169             __usecols  = tuple(range(len(HeaderNames)))
1170
1171             def __replaceNone( s ):
1172                 if s.strip() == b'None': return numpy.NAN
1173                 else:                    return s
1174             __converters = dict()
1175             for i in range(1,len(HeaderNames)):
1176                 __converters[i] = __replaceNone
1177         else:
1178             raise ValueError("Can not find names of columns for initial values. Wrong first line is:\n            \"%s\""%self._varsline)
1179         #
1180         if self._format == "text/plain":
1181             __content = numpy.loadtxt(
1182                 self._filename,
1183                 dtype      = __dtypes,
1184                 usecols    = __usecols,
1185                 skiprows   = self._skiprows,
1186                 converters = __converters,
1187                 )
1188         elif self._format in ["text/csv", "text/tab-separated-values"]:
1189             __content = numpy.loadtxt(
1190                 self._filename,
1191                 dtype      = __dtypes,
1192                 usecols    = __usecols,
1193                 skiprows   = self._skiprows,
1194                 converters = __converters,
1195                 delimiter  = self._delimiter,
1196                 )
1197         else:
1198             raise ValueError("Unkown file format \"%s\""%self._format)
1199         #
1200         __names, __thevalue, __bounds = [], [], []
1201         for sub in __content:
1202             if len(__usecols) == 4:
1203                 na, va, mi, ma = sub
1204                 if numpy.isneginf(mi): mi = None # Réattribue les variables None
1205                 elif numpy.isnan(mi):  mi = None # Réattribue les variables None
1206                 if numpy.isposinf(ma): ma = None # Réattribue les variables None
1207                 elif numpy.isnan(ma):  ma = None # Réattribue les variables None
1208             elif len(__usecols) == 2 and __ftype == "NamVal":
1209                 na, va = sub
1210                 mi, ma = None, None
1211             else:
1212                 nsub = list(sub)
1213                 na = sub[0]
1214                 for i, v in enumerate(nsub[1:]):
1215                     if numpy.isnan(v): nsub[i+1] = None
1216                 va = nsub[1:]
1217                 mi, ma = None, None
1218             na = na.decode()
1219             if (__varnames is None or na in __varnames) and (na not in __names):
1220                 # Ne stocke que la premiere occurence d'une variable
1221                 __names.append(na)
1222                 __thevalue.append(va)
1223                 __bounds.append((mi,ma))
1224         #
1225         __names      = tuple(__names)
1226         __thevalue = numpy.array(__thevalue)
1227         __bounds     = tuple(__bounds)
1228         #
1229         return (__names, __thevalue, __bounds)
1230
1231 # ==============================================================================
1232 class EficasGUI(object):
1233     """
1234     Lancement autonome de l'interface EFICAS/ADAO
1235     """
1236     __slots__ = ("__msg", "__path_settings_ok")
1237     #
1238     def __init__(self, __addpath = None):
1239         # Chemin pour l'installation (ordre important)
1240         self.__msg = ""
1241         self.__path_settings_ok = False
1242         #----------------
1243         if "EFICAS_TOOLS_ROOT" in os.environ:
1244             __EFICAS_TOOLS_ROOT = os.environ["EFICAS_TOOLS_ROOT"]
1245             __path_ok = True
1246         elif "EFICAS_NOUVEAU_ROOT" in os.environ:
1247             __EFICAS_TOOLS_ROOT = os.environ["EFICAS_NOUVEAU_ROOT"]
1248             __path_ok = True
1249         else:
1250             self.__msg += "\nKeyError:\n"+\
1251                 "  the required environment variable EFICAS_TOOLS_ROOT is unknown.\n"+\
1252                 "  You have either to be in SALOME environment, or to set this\n"+\
1253                 "  variable in your environment to the right path \"<...>\" to\n"+\
1254                 "  find an installed EFICAS application. For example:\n"+\
1255                 "      EFICAS_TOOLS_ROOT=\"<...>\" command\n"
1256             __path_ok = False
1257         try:
1258             import adao
1259             __path_ok = True and __path_ok
1260         except ImportError:
1261             self.__msg += "\nImportError:\n"+\
1262                 "  the required ADAO library can not be found to be imported.\n"+\
1263                 "  You have either to be in ADAO environment, or to be in SALOME\n"+\
1264                 "  environment, or to set manually in your Python 3 environment the\n"+\
1265                 "  right path \"<...>\" to find an installed ADAO application. For\n"+\
1266                 "  example:\n"+\
1267                 "      PYTHONPATH=\"<...>:${PYTHONPATH}\" command\n"
1268             __path_ok = False
1269         try:
1270             import PyQt5
1271             __path_ok = True and __path_ok
1272         except ImportError:
1273             self.__msg += "\nImportError:\n"+\
1274                 "  the required PyQt5 library can not be found to be imported.\n"+\
1275                 "  You have either to have a raisonable up-to-date Python 3\n"+\
1276                 "  installation (less than 5 years), or to be in SALOME environment.\n"
1277             __path_ok = False
1278         #----------------
1279         if not __path_ok:
1280             self.__msg += "\nWarning:\n"+\
1281                 "  It seems you have some troubles with your installation.\n"+\
1282                 "  Be aware that some other errors may exist, that are not\n"+\
1283                 "  explained as above, like some incomplete or obsolete\n"+\
1284                 "  Python 3, or incomplete module installation.\n"+\
1285                 "  \n"+\
1286                 "  Please correct the above error(s) before launching the\n"+\
1287                 "  standalone EFICAS/ADAO interface.\n"
1288             logging.debug("Some of the ADAO/EFICAS/QT5 paths have not been found")
1289             self.__path_settings_ok = False
1290         else:
1291             logging.debug("All the ADAO/EFICAS/QT5 paths have been found")
1292             self.__path_settings_ok = True
1293         #----------------
1294         if self.__path_settings_ok:
1295             sys.path.insert(0,__EFICAS_TOOLS_ROOT)
1296             sys.path.insert(0,os.path.join(adao.adao_py_dir,"daEficas"))
1297             if __addpath is not None and os.path.exists(os.path.abspath(__addpath)):
1298                 sys.path.insert(0,os.path.abspath(__addpath))
1299             logging.debug("All the paths have been correctly set up")
1300         else:
1301             print(self.__msg)
1302             logging.debug("Errors in path settings have been found")
1303     #
1304     def gui(self):
1305         if self.__path_settings_ok:
1306             logging.debug("Launching standalone EFICAS/ADAO interface...")
1307             from daEficas import prefs
1308             from InterfaceQT4 import eficas_go
1309             eficas_go.lanceEficas(code=prefs.code)
1310         else:
1311             logging.debug("Can not launch standalone EFICAS/ADAO interface for path errors.")
1312
1313 # ==============================================================================
1314 if __name__ == "__main__":
1315     print('\n AUTODIAGNOSTIC\n')