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