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