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