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