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