]> SALOME platform Git repositories - modules/adao.git/blob - src/daComposant/daCore/Interfaces.py
Salome HOME
Documentation corrections and code performance update
[modules/adao.git] / src / daComposant / daCore / Interfaces.py
1 # -*- coding: utf-8 -*-
2 #
3 # Copyright (C) 2008-2024 EDF R&D
4 #
5 # This library is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU Lesser General Public
7 # License as published by the Free Software Foundation; either
8 # version 2.1 of the License.
9 #
10 # This library is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 # Lesser General Public License for more details.
14 #
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with this library; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18 #
19 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #
21 # Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
22
23 """
24     Définit les outils d'interfaces normalisées de cas.
25 """
26 __author__ = "Jean-Philippe ARGAUD"
27 __all__ = []
28
29 import os
30 import sys
31 import numpy
32 import mimetypes
33 import logging
34 import copy
35 from daCore import Persistence
36 from daCore import PlatformInfo
37 from daCore import Templates
38 from daCore import Reporting
39 from daCore import version
40
41 # ==============================================================================
42 class GenericCaseViewer(object):
43     """
44     Gestion des commandes de création d'une vue de cas
45     """
46     __slots__ = (
47         "_name", "_objname", "_lineSerie", "_switchoff", "_content",
48         "_numobservers", "_object", "_missing",
49     )
50
51     def __init__(self, __name="", __objname="case", __content=None, __object=None):
52         "Initialisation et enregistrement de l'entete"
53         self._name         = str(__name)
54         self._objname      = str(__objname)
55         self._lineSerie    = []
56         self._switchoff    = False
57         self._numobservers = 2
58         self._content      = __content
59         self._object       = __object
60         self._missing = """raise ValueError("This case requires beforehand to import or define the variable named <%s>. When corrected, remove this command, correct and uncomment the following one.")\n# """
61
62     def _append(self, *args):
63         "Transformation d'une commande individuelle en un enregistrement"
64         raise NotImplementedError()
65
66     def _extract(self, *args):
67         "Transformation d'enregistrement(s) en commande(s) individuelle(s)"
68         raise NotImplementedError()
69
70     def _initialize(self, __multilines):
71         "Permet des pré-conversions automatiques simples de commandes ou clés"
72         __translation = {
73             "Study_name"           : "StudyName",                  # noqa: E203
74             "Study_repertory"      : "StudyRepertory",             # noqa: E203
75             "MaximumNumberOfSteps" : "MaximumNumberOfIterations",  # noqa: E203
76             "EnableMultiProcessing": "EnableWiseParallelism",
77             "FunctionDict"         : "ScriptWithSwitch",           # noqa: E203
78             "FUNCTIONDICT_FILE"    : "SCRIPTWITHSWITCH_FILE",      # noqa: E203
79         }
80         for k, v in __translation.items():
81             __multilines = __multilines.replace(k, v)
82         return __multilines
83
84     def _finalize(self, __upa=None):
85         "Enregistrement du final"
86         __hasNotExecute = True
87         for __l in self._lineSerie:
88             if "%s.execute"%(self._objname,) in __l:
89                 __hasNotExecute = False
90         if __hasNotExecute:
91             self._lineSerie.append("%s.execute()"%(self._objname,))
92         if __upa is not None and len(__upa) > 0:
93             __upa = __upa.replace("ADD", str(self._objname))
94             self._lineSerie.append(__upa)
95
96     def _addLine(self, line=""):
97         "Ajoute un enregistrement individuel"
98         self._lineSerie.append(line)
99
100     def _get_objname(self):
101         return self._objname
102
103     def dump(self, __filename=None, __upa=None):
104         "Restitution normalisée des commandes"
105         self._finalize(__upa)
106         __text = "\n".join(self._lineSerie)
107         __text += "\n"
108         if __filename is not None:
109             __file = os.path.abspath(__filename)
110             __fid = open(__file, "w")
111             __fid.write(__text)
112             __fid.close()
113         return __text
114
115     def load(self, __filename=None, __content=None, __object=None):
116         "Chargement normalisé des commandes"
117         if __filename is not None and os.path.exists(__filename):
118             self._content = open(__filename, 'r').read()
119             self._content = self._initialize(self._content)
120         elif __content is not None and type(__content) is str:
121             self._content = self._initialize(__content)
122         elif __object is not None and type(__object) is dict:
123             self._object = copy.deepcopy(__object)
124         else:
125             pass  # use "self._content" from initialization
126         __commands = self._extract(self._content, self._object)
127         return __commands
128
129 class _TUIViewer(GenericCaseViewer):
130     """
131     Établissement des commandes d'un cas ADAO TUI (Cas<->TUI)
132     """
133     __slots__ = ()
134
135     def __init__(self, __name="", __objname="case", __content=None, __object=None):
136         "Initialisation et enregistrement de l'entete"
137         GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
138         self._addLine("# -*- coding: utf-8 -*-")
139         self._addLine("#\n# Python script using ADAO TUI\n#")
140         self._addLine("from numpy import array, matrix")
141         self._addLine("from adao import adaoBuilder")
142         self._addLine("%s = adaoBuilder.New('%s')"%(self._objname, self._name))
143         if self._content is not None:
144             for command in self._content:
145                 self._append(*command)
146
147     def _append(self, __command=None, __keys=None, __local=None, __pre=None, __switchoff=False):
148         "Transformation d'une commande individuelle en un enregistrement"
149         if __command is not None and __keys is not None and __local is not None:
150             if "Concept" in __keys:
151                 logging.debug("TUI Order processed: %s"%(__local["Concept"],))
152             __text  = ""
153             if __pre is not None:
154                 __text += "%s = "%__pre
155             __text += "%s.%s( "%(self._objname, str(__command))
156             if "self" in __keys:
157                 __keys.remove("self")
158             if __command not in ("set", "get") and "Concept" in __keys:
159                 __keys.remove("Concept")
160             for k in __keys:
161                 if k not in __local: continue                           # noqa: E701
162                 __v = __local[k]
163                 if __v is None: continue                                # noqa: E701
164                 if   k == "Checked"              and not __v: continue  # noqa: E241,E271,E272,E701
165                 if   k == "Stored"               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 == "InputFunctionAsMulti" and not __v: continue  # noqa: E241,E271,E272,E701
168                 if   k == "nextStep"             and not __v: continue  # noqa: E241,E271,E272,E701
169                 if   k == "PerformanceProfile"   and     __v: continue  # noqa: E241,E271,E272,E701
170                 if   k == "noDetails":                        continue  # noqa: E241,E271,E272,E701
171                 if isinstance(__v, Persistence.Persistence):
172                     __v = __v.values()
173                 if callable(__v):
174                     __text = self._missing%__v.__name__ + __text
175                 if isinstance(__v, dict):
176                     for val in __v.values():
177                         if callable(val):
178                             __text = self._missing%val.__name__ + __text
179                 numpy.set_printoptions(precision=15, threshold=1000000, linewidth=1000 * 15)
180                 __text += "%s=%s, "%(k, repr(__v))
181                 numpy.set_printoptions(precision=8, threshold=1000, linewidth=75)
182             __text = __text.rstrip(", ")
183             __text += " )"
184             self._addLine(__text)
185
186     def _extract(self, __multilines="", __object=None):
187         "Transformation d'enregistrement(s) en commande(s) individuelle(s)"
188         __is_case = False
189         __commands = []
190         __multilines = __multilines.replace("\r\n", "\n")
191         for line in __multilines.split("\n"):
192             if "adaoBuilder.New" in line and "=" in line:
193                 self._objname = line.split("=")[0].strip()
194                 __is_case = True
195                 logging.debug("TUI Extracting commands of '%s' object..."%(self._objname,))
196             if not __is_case:
197                 continue
198             else:
199                 if self._objname + ".set" in line:
200                     __commands.append( line.replace(self._objname + ".", "", 1) )
201                     logging.debug("TUI Extracted command: %s"%(__commands[-1],))
202         return __commands
203
204 class _COMViewer(GenericCaseViewer):
205     """
206     Établissement des commandes d'un cas COMM (Eficas Native Format/Cas<-COM)
207     """
208     __slots__ = ("_observerIndex", "_objdata")
209
210     def __init__(self, __name="", __objname="case", __content=None, __object=None):
211         "Initialisation et enregistrement de l'entete"
212         GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
213         self._observerIndex = 0
214         self._addLine("# -*- coding: utf-8 -*-")
215         self._addLine("#\n# Python script using ADAO COMM\n#")
216         self._addLine("from numpy import array, matrix")
217         self._addLine("#")
218         self._addLine("%s = {}"%__objname)
219         if self._content is not None:
220             for command in self._content:
221                 self._append(*command)
222
223     def _extract(self, __multilines=None, __object=None):
224         "Transformation d'enregistrement(s) en commande(s) individuelle(s)"
225         __suppparameters = {}
226         if __multilines is not None:
227             if 'adaoBuilder' in __multilines:
228                 raise ValueError("Impossible to load given content as an ADAO COMM one (Hint: it's perhaps not a COMM input, but a TUI one).")
229             if "ASSIMILATION_STUDY" in __multilines:
230                 __suppparameters.update({'StudyType': "ASSIMILATION_STUDY"})
231                 __multilines = __multilines.replace("ASSIMILATION_STUDY", "dict")
232             elif "OPTIMIZATION_STUDY" in __multilines:
233                 __suppparameters.update({'StudyType': "ASSIMILATION_STUDY"})
234                 __multilines = __multilines.replace("OPTIMIZATION_STUDY", "dict")
235             elif "REDUCTION_STUDY" in __multilines:
236                 __suppparameters.update({'StudyType': "ASSIMILATION_STUDY"})
237                 __multilines = __multilines.replace("REDUCTION_STUDY", "dict")
238             elif "CHECKING_STUDY" in __multilines:
239                 __suppparameters.update({'StudyType': "CHECKING_STUDY"})
240                 __multilines = __multilines.replace("CHECKING_STUDY", "dict")
241             else:
242                 __multilines = __multilines.replace("ASSIMILATION_STUDY", "dict")
243             #
244             __multilines = __multilines.replace("_F(", "dict(")
245             __multilines = __multilines.replace(",),);", ",),)")
246         __fulllines = ""
247         for line in __multilines.split("\n"):
248             if len(line) < 1:
249                 continue
250             __fulllines += line + "\n"
251         __multilines = __fulllines
252         self._objname = "case"
253         self._objdata = None
254         exec("self._objdata = " + __multilines)
255         #
256         if self._objdata is None or not (type(self._objdata) is dict) or not ('AlgorithmParameters' in self._objdata):
257             raise ValueError("Impossible to load given content as an ADAO COMM one (no dictionnary or no 'AlgorithmParameters' key found).")
258         # ----------------------------------------------------------------------
259         logging.debug("COMM Extracting commands of '%s' object..."%(self._objname,))
260         __commands = []
261         __UserPostAnalysis = ""
262         for k, r in self._objdata.items():
263             __command = k
264             logging.debug("COMM Extracted command: %s:%s"%(k, r))
265             if __command   == "StudyName" and len(str(r)) > 0:
266                 __commands.append( "set( Concept='Name', String='%s')"%(str(r),) )
267             elif __command == "StudyRepertory":
268                 __commands.append( "set( Concept='Directory', String='%s')"%(str(r),) )
269             elif __command == "Debug" and str(r) == "0":
270                 __commands.append( "set( Concept='NoDebug' )" )
271             elif __command == "Debug" and str(r) == "1":
272                 __commands.append( "set( Concept='Debug' )" )
273             elif __command == "ExecuteInContainer":
274                 __suppparameters.update({'ExecuteInContainer': r})
275             #
276             elif __command == "UserPostAnalysis" and type(r) is dict:
277                 if 'STRING' in r:
278                     __UserPostAnalysis = r['STRING'].replace("ADD", str(self._objname))
279                     __commands.append( "set( Concept='UserPostAnalysis', String=\"\"\"%s\"\"\" )"%(__UserPostAnalysis,) )
280                 elif 'SCRIPT_FILE' in r and os.path.exists(r['SCRIPT_FILE']):
281                     __UserPostAnalysis = open(r['SCRIPT_FILE'], 'r').read()
282                     __commands.append( "set( Concept='UserPostAnalysis', Script='%s' )"%(r['SCRIPT_FILE'],) )
283                 elif 'Template' in r and 'ValueTemplate' not in r:
284                     # AnalysisPrinter...
285                     if r['Template'] not in Templates.UserPostAnalysisTemplates:
286                         raise ValueError("User post-analysis template \"%s\" does not exist."%(r['Template'],))
287                     else:
288                         __UserPostAnalysis = Templates.UserPostAnalysisTemplates[r['Template']]
289                     __commands.append( "set( Concept='UserPostAnalysis', Template='%s' )"%(r['Template'],) )
290                 elif 'Template' in r and 'ValueTemplate' in r:
291                     # Le template ayant pu être modifié, donc on ne prend que le ValueTemplate...
292                     __UserPostAnalysis = r['ValueTemplate']
293                     __commands.append( "set( Concept='UserPostAnalysis', String=\"\"\"%s\"\"\" )"%(__UserPostAnalysis,) )
294                 else:
295                     __UserPostAnalysis = ""
296             #
297             elif __command == "AlgorithmParameters" and type(r) is dict and 'Algorithm' in r:
298                 if 'data' in r and r['Parameters'] == 'Dict':
299                     __from = r['data']
300                     if 'STRING' in __from:
301                         __parameters = ", Parameters=%s"%(repr(eval(__from['STRING'])),)
302                     elif 'SCRIPT_FILE' in __from:  # Pas de test d'existence du fichier pour accepter un fichier relatif
303                         __parameters = ", Script='%s'"%(__from['SCRIPT_FILE'],)
304                 else:  # if 'Parameters' in r and r['Parameters'] == 'Defaults':
305                     __Dict = copy.deepcopy(r)
306                     __Dict.pop('Algorithm', '')
307                     __Dict.pop('Parameters', '')
308                     if 'SetSeed' in __Dict:
309                         __Dict['SetSeed'] = int(__Dict['SetSeed'])
310                     if 'Bounds' in __Dict and type(__Dict['Bounds']) is str:
311                         __Dict['Bounds'] = eval(__Dict['Bounds'])
312                     if 'BoxBounds' in __Dict and type(__Dict['BoxBounds']) is str:
313                         __Dict['BoxBounds'] = eval(__Dict['BoxBounds'])
314                     if len(__Dict) > 0:
315                         __parameters = ', Parameters=%s'%(repr(__Dict),)
316                     else:
317                         __parameters = ""
318                 __commands.append( "set( Concept='AlgorithmParameters', Algorithm='%s'%s )"%(r['Algorithm'], __parameters) )
319             #
320             elif __command == "Observers" and type(r) is dict and 'SELECTION' in r:
321                 if type(r['SELECTION']) is str:
322                     __selection = (r['SELECTION'],)
323                 else:
324                     __selection = tuple(r['SELECTION'])
325                 for sk in __selection:
326                     __idata = r['%s_data'%sk]
327                     if __idata['NodeType'] == 'Template' and 'Template' in __idata:
328                         __template = __idata['Template']
329                         if 'Info' in __idata:
330                             __info = ", Info=\"\"\"%s\"\"\""%(__idata['Info'],)
331                         else:
332                             __info = ""
333                         __commands.append( "set( Concept='Observer', Variable='%s', Template=\"\"\"%s\"\"\"%s )"%(sk, __template, __info) )
334                     if __idata['NodeType'] == 'String' and 'Value' in __idata:
335                         __value = __idata['Value']
336                         __commands.append( "set( Concept='Observer', Variable='%s', String=\"\"\"%s\"\"\" )"%(sk, __value) )
337             #
338             # Background, ObservationError, ObservationOperator...
339             elif type(r) is dict:
340                 __argumentsList = []
341                 if 'Stored' in r and bool(r['Stored']):
342                     __argumentsList.append(['Stored', True])
343                 if 'INPUT_TYPE' in r and 'data' in r:
344                     # Vector, Matrix, ScalarSparseMatrix, DiagonalSparseMatrix, Function
345                     __itype = r['INPUT_TYPE']
346                     __idata = r['data']
347                     if 'FROM' in __idata:
348                         # String, Script, DataFile, Template, ScriptWithOneFunction, ScriptWithFunctions
349                         __ifrom = __idata['FROM']
350                         __idata.pop('FROM', '')
351                         if __ifrom == 'String' or __ifrom == 'Template':
352                             __argumentsList.append([__itype, __idata['STRING']])
353                         if __ifrom == 'Script':
354                             __argumentsList.append([__itype, True])
355                             __argumentsList.append(['Script', __idata['SCRIPT_FILE']])
356                         if __ifrom == 'DataFile':
357                             __argumentsList.append([__itype, True])
358                             __argumentsList.append(['DataFile', __idata['DATA_FILE']])
359                         if __ifrom == 'ScriptWithOneFunction':
360                             __argumentsList.append(['OneFunction', True])
361                             __argumentsList.append(['Script', __idata.pop('SCRIPTWITHONEFUNCTION_FILE')])
362                             if len(__idata) > 0:
363                                 __argumentsList.append(['Parameters', __idata])
364                         if __ifrom == 'ScriptWithFunctions':
365                             __argumentsList.append(['ThreeFunctions', True])
366                             __argumentsList.append(['Script', __idata.pop('SCRIPTWITHFUNCTIONS_FILE')])
367                             if len(__idata) > 0:
368                                 __argumentsList.append(['Parameters', __idata])
369                 __arguments = ["%s = %s"%(k, repr(v)) for k, v in __argumentsList]
370                 __commands.append( "set( Concept='%s', %s )"%(__command, ", ".join(__arguments)))
371         #
372         __commands.append( "set( Concept='%s', Parameters=%s )"%('SupplementaryParameters', repr(__suppparameters)))
373         #
374         # ----------------------------------------------------------------------
375         __commands.sort()  # Pour commencer par 'AlgorithmParameters'
376         __commands.append(__UserPostAnalysis)
377         return __commands
378
379 class _SCDViewer(GenericCaseViewer):
380     """
381     Établissement des commandes d'un cas SCD (Study Config Dictionary/Cas->SCD)
382
383     Remarque : le fichier généré est différent de celui obtenu par EFICAS
384     """
385     __slots__ = (
386         "__DebugCommandNotSet", "__ObserverCommandNotSet",
387         "__UserPostAnalysisNotSet", "__hasAlgorithm")
388
389     def __init__(self, __name="", __objname="case", __content=None, __object=None):
390         "Initialisation et enregistrement de l'entête"
391         GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
392         #
393         if __content is not None:
394             for command in __content:
395                 if command[0] == "set":
396                     __command = command[2]["Concept"]
397                 else:
398                     __command = command[0].replace("set", "", 1)
399                 if __command == 'Name':
400                     self._name = command[2]["String"]
401         #
402         self.__DebugCommandNotSet = True
403         self.__ObserverCommandNotSet = True
404         self.__UserPostAnalysisNotSet = True
405         #
406         self._addLine("# -*- coding: utf-8 -*-")
407         self._addLine("#\n# Input for ADAO converter to SCD\n#")
408         self._addLine("#")
409         self._addLine("study_config = {}")
410         self._addLine("study_config['Name'] = '%s'"%self._name)
411         self._addLine("#")
412         self._addLine("inputvariables_config = {}")
413         self._addLine("inputvariables_config['Order'] =['adao_default']")
414         self._addLine("inputvariables_config['adao_default'] = -1")
415         self._addLine("study_config['InputVariables'] = inputvariables_config")
416         self._addLine("#")
417         self._addLine("outputvariables_config = {}")
418         self._addLine("outputvariables_config['Order'] = ['adao_default']")
419         self._addLine("outputvariables_config['adao_default'] = -1")
420         self._addLine("study_config['OutputVariables'] = outputvariables_config")
421         if __content is not None:
422             for command in __content:
423                 self._append(*command)
424
425     def _append(self, __command=None, __keys=None, __local=None, __pre=None, __switchoff=False):
426         "Transformation d'une commande individuelle en un enregistrement"
427         if __command == "set":
428             __command = __local["Concept"]
429         else:
430             __command = __command.replace("set", "", 1)
431         logging.debug("SCD Order processed: %s"%(__command))
432         #
433         __text  = None
434         if __command in (None, 'execute', 'executePythonScheme', 'executeYACSScheme', 'get', 'Name'):
435             return
436         elif __command in ['Directory',]:
437             __text  = "#\nstudy_config['Repertory'] = %s"%(repr(__local['String']))
438         elif __command in ['Debug', 'setDebug']:
439             __text  = "#\nstudy_config['Debug'] = '1'"
440             self.__DebugCommandNotSet = False
441         elif __command in ['NoDebug', 'setNoDebug']:
442             __text  = "#\nstudy_config['Debug'] = '0'"
443             self.__DebugCommandNotSet = False
444         elif __command in ['Observer', 'setObserver']:
445             if self.__ObserverCommandNotSet:
446                 self._addLine("observers = {}")
447                 self._addLine("study_config['Observers'] = observers")
448                 self.__ObserverCommandNotSet = False
449             __obs   = __local['Variable']
450             self._numobservers += 1
451             __text  = "#\n"
452             __text += "observers['%s'] = {}\n"%__obs
453             if __local['String'] is not None:
454                 __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'String')
455                 __text += "observers['%s']['String'] = \"\"\"%s\"\"\"\n"%(__obs, __local['String'])
456             if __local['Script'] is not None:
457                 __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'Script')
458                 __text += "observers['%s']['Script'] = \"%s\"\n"%(__obs, __local['Script'])
459             if __local['Template'] is not None and __local['Template'] in Templates.ObserverTemplates:
460                 __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'String')
461                 __text += "observers['%s']['String'] = \"\"\"%s\"\"\"\n"%(__obs, Templates.ObserverTemplates[__local['Template']])
462             if __local['Info'] is not None:
463                 __text += "observers['%s']['info'] = \"\"\"%s\"\"\"\n"%(__obs, __local['Info'])
464             else:
465                 __text += "observers['%s']['info'] = \"\"\"%s\"\"\"\n"%(__obs, __obs)
466             __text += "observers['%s']['number'] = %s"%(__obs, self._numobservers)
467         elif __command in ['UserPostAnalysis', 'setUserPostAnalysis']:
468             __text  = "#\n"
469             __text += "Analysis_config = {}\n"
470             if __local['String'] is not None:
471                 __text += "Analysis_config['From'] = 'String'\n"
472                 __text += "Analysis_config['Data'] = \"\"\"%s\"\"\"\n"%(__local['String'],)
473             if __local['Script'] is not None:
474                 __text += "Analysis_config['From'] = 'Script'\n"
475                 __text += "Analysis_config['Data'] = \"\"\"%s\"\"\"\n"%(__local['Script'],)
476             if __local['Template'] is not None and __local['Template'] in Templates.UserPostAnalysisTemplates:
477                 __text += "Analysis_config['From'] = 'String'\n"
478                 __text += "Analysis_config['Data'] = \"\"\"%s\"\"\"\n"%(Templates.UserPostAnalysisTemplates[__local['Template']],)
479             __text += "study_config['UserPostAnalysis'] = Analysis_config"
480             self.__UserPostAnalysisNotSet = False
481         elif __local is not None:  # __keys is not None and
482             numpy.set_printoptions(precision=15, threshold=1000000, linewidth=1000 * 15)
483             __text  = "#\n"
484             __text += "%s_config = {}\n"%__command
485             __local.pop('self', '')
486             __to_be_removed = []
487             __vectorIsDataFile = False
488             __vectorIsScript = False
489             for __k, __v in __local.items():
490                 if __v is None:
491                     __to_be_removed.append(__k)
492             for __k in __to_be_removed:
493                 __local.pop(__k)
494             for __k, __v in __local.items():
495                 if __k == "Concept":
496                     continue
497                 if __k in ['ScalarSparseMatrix', 'DiagonalSparseMatrix', 'Matrix', 'OneFunction', 'ThreeFunctions'] \
498                         and 'Script' in __local \
499                         and __local['Script'] is not None:
500                     continue
501                 if __k in ['Vector', 'VectorSerie'] \
502                         and 'DataFile' in __local \
503                         and __local['DataFile'] is not None:
504                     continue
505                 if __k == 'Parameters' and not (__command in ['AlgorithmParameters', 'SupplementaryParameters']):
506                     continue
507                 if __k == 'Algorithm':
508                     __text += "study_config['Algorithm'] = %s\n"%(repr(__v))
509                 elif __k == 'DataFile':
510                     __k = 'Vector'
511                     __f = 'DataFile'
512                     __v = "'" + repr(__v) + "'"
513                     for __lk in ['Vector', 'VectorSerie']:
514                         if __lk in __local and __local[__lk]:
515                             __k = __lk
516                     __text += "%s_config['Type'] = '%s'\n"%(__command, __k)
517                     __text += "%s_config['From'] = '%s'\n"%(__command, __f)
518                     __text += "%s_config['Data'] = %s\n"%(__command, __v)
519                     __text = __text.replace("''", "'")
520                     __vectorIsDataFile = True
521                 elif __k == 'Script':
522                     __k = 'Vector'
523                     __f = 'Script'
524                     __v = "'" + repr(__v) + "'"
525                     for __lk in ['ScalarSparseMatrix', 'DiagonalSparseMatrix', 'Matrix']:
526                         if __lk in __local and __local[__lk]:
527                             __k = __lk
528                     if __command == "AlgorithmParameters":
529                         __k = "Dict"
530                     if 'OneFunction' in __local and __local['OneFunction']:
531                         __text += "%s_ScriptWithOneFunction = {}\n"%(__command,)
532                         __text += "%s_ScriptWithOneFunction['Function'] = ['Direct', 'Tangent', 'Adjoint']\n"%(__command,)
533                         __text += "%s_ScriptWithOneFunction['Script'] = {}\n"%(__command,)
534                         __text += "%s_ScriptWithOneFunction['Script']['Direct'] = %s\n"%(__command, __v)
535                         __text += "%s_ScriptWithOneFunction['Script']['Tangent'] = %s\n"%(__command, __v)
536                         __text += "%s_ScriptWithOneFunction['Script']['Adjoint'] = %s\n"%(__command, __v)
537                         __text += "%s_ScriptWithOneFunction['DifferentialIncrement'] = 1e-06\n"%(__command,)
538                         __text += "%s_ScriptWithOneFunction['CenteredFiniteDifference'] = 0\n"%(__command,)
539                         __k = 'Function'
540                         __f = 'ScriptWithOneFunction'
541                         __v = '%s_ScriptWithOneFunction'%(__command,)
542                     if 'ThreeFunctions' in __local and __local['ThreeFunctions']:
543                         __text += "%s_ScriptWithFunctions = {}\n"%(__command,)
544                         __text += "%s_ScriptWithFunctions['Function'] = ['Direct', 'Tangent', 'Adjoint']\n"%(__command,)
545                         __text += "%s_ScriptWithFunctions['Script'] = {}\n"%(__command,)
546                         __text += "%s_ScriptWithFunctions['Script']['Direct'] = %s\n"%(__command, __v)
547                         __text += "%s_ScriptWithFunctions['Script']['Tangent'] = %s\n"%(__command, __v)
548                         __text += "%s_ScriptWithFunctions['Script']['Adjoint'] = %s\n"%(__command, __v)
549                         __k = 'Function'
550                         __f = 'ScriptWithFunctions'
551                         __v = '%s_ScriptWithFunctions'%(__command,)
552                     __text += "%s_config['Type'] = '%s'\n"%(__command, __k)
553                     __text += "%s_config['From'] = '%s'\n"%(__command, __f)
554                     __text += "%s_config['Data'] = %s\n"%(__command, __v)
555                     __text = __text.replace("''", "'")
556                     __vectorIsScript = True
557                 elif __k in ('Stored', 'Checked', 'ColMajor', 'InputFunctionAsMulti', 'nextStep'):
558                     if bool(__v):
559                         __text += "%s_config['%s'] = '%s'\n"%(__command, __k, int(bool(__v)))
560                 elif __k in ('PerformanceProfile', 'noDetails'):
561                     if not bool(__v):
562                         __text += "%s_config['%s'] = '%s'\n"%(__command, __k, int(bool(__v)))
563                 else:
564                     if __k == 'Vector' and __vectorIsScript:
565                         continue
566                     if __k == 'Vector' and __vectorIsDataFile:
567                         continue
568                     if __k == 'Parameters':
569                         __k = "Dict"
570                     if isinstance(__v, Persistence.Persistence):
571                         __v = __v.values()
572                     if callable(__v):
573                         __text = self._missing%__v.__name__ + __text
574                     if isinstance(__v, dict):
575                         for val in __v.values():
576                             if callable(val):
577                                 __text = self._missing%val.__name__ + __text
578                     __text += "%s_config['Type'] = '%s'\n"%(__command, __k)
579                     __text += "%s_config['From'] = '%s'\n"%(__command, 'String')
580                     __text += "%s_config['Data'] = \"\"\"%s\"\"\"\n"%(__command, repr(__v))
581             __text += "study_config['%s'] = %s_config"%(__command, __command)
582             numpy.set_printoptions(precision=8, threshold=1000, linewidth=75)
583             if __switchoff:
584                 self._switchoff = True
585         if __text is not None:
586             self._addLine(__text)
587         if not __switchoff:
588             self._switchoff = False
589
590     def _finalize(self, *__args):
591         self.__loadVariablesByScript()
592         if self.__DebugCommandNotSet:
593             self._addLine("#\nstudy_config['Debug'] = '0'")
594         if self.__UserPostAnalysisNotSet:
595             self._addLine("#")
596             self._addLine("Analysis_config = {}")
597             self._addLine("Analysis_config['From'] = 'String'")
598             self._addLine("Analysis_config['Data'] = \"\"\"import numpy")
599             self._addLine("xa=ADD.get('Analysis')[-1]")
600             self._addLine("print('Analysis:',xa)\"\"\"")
601             self._addLine("study_config['UserPostAnalysis'] = Analysis_config")
602
603     def __loadVariablesByScript(self):
604         __ExecVariables = {}  # Necessaire pour recuperer la variable
605         exec("\n".join(self._lineSerie), __ExecVariables)
606         study_config = __ExecVariables['study_config']
607         # Pour Python 3 : self.__hasAlgorithm = bool(study_config['Algorithm'])
608         if 'Algorithm' in study_config:
609             self.__hasAlgorithm = True
610         else:
611             self.__hasAlgorithm = False
612         if not self.__hasAlgorithm and \
613                 "AlgorithmParameters" in study_config and \
614                 isinstance(study_config['AlgorithmParameters'], dict) and \
615                 "From" in study_config['AlgorithmParameters'] and \
616                 "Data" in study_config['AlgorithmParameters'] and \
617                 study_config['AlgorithmParameters']['From'] == 'Script':
618             __asScript = study_config['AlgorithmParameters']['Data']
619             __var = ImportFromScript(__asScript).getvalue( "Algorithm" )
620             __text = "#\nstudy_config['Algorithm'] = '%s'"%(__var,)
621             self._addLine(__text)
622         if self.__hasAlgorithm and \
623                 "AlgorithmParameters" in study_config and \
624                 isinstance(study_config['AlgorithmParameters'], dict) and \
625                 "From" not in study_config['AlgorithmParameters'] and \
626                 "Data" not in study_config['AlgorithmParameters']:
627             __text  = "#\n"
628             __text += "AlgorithmParameters_config['Type'] = 'Dict'\n"
629             __text += "AlgorithmParameters_config['From'] = 'String'\n"
630             __text += "AlgorithmParameters_config['Data'] = '{}'\n"
631             self._addLine(__text)
632         if 'SupplementaryParameters' in study_config and \
633                 isinstance(study_config['SupplementaryParameters'], dict) and \
634                 "From" in study_config['SupplementaryParameters'] and \
635                 study_config['SupplementaryParameters']["From"] == 'String' and \
636                 "Data" in study_config['SupplementaryParameters']:
637             __dict = eval(study_config['SupplementaryParameters']["Data"])
638             if 'ExecuteInContainer' in __dict:
639                 self._addLine("#\nstudy_config['ExecuteInContainer'] = '%s'"%__dict['ExecuteInContainer'])
640             else:
641                 self._addLine("#\nstudy_config['ExecuteInContainer'] = 'No'")
642             if 'StudyType' in __dict:
643                 self._addLine("#\nstudy_config['StudyType'] = '%s'"%__dict['StudyType'])
644             if 'StudyType' in __dict and __dict['StudyType'] != "ASSIMILATION_STUDY":
645                 self.__UserPostAnalysisNotSet = False
646         del study_config
647
648 class _YACSViewer(GenericCaseViewer):
649     """
650     Etablissement des commandes d'un cas YACS (Cas->SCD->YACS)
651     """
652     __slots__ = ("__internalSCD", "_append")
653
654     def __init__(self, __name="", __objname="case", __content=None, __object=None):
655         "Initialisation et enregistrement de l'entete"
656         GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
657         self.__internalSCD = _SCDViewer(__name, __objname, __content, __object)
658         self._append       = self.__internalSCD._append
659
660     def dump(self, __filename=None, __upa=None):
661         "Restitution normalisée des commandes"
662         # -----
663         if __filename is None:
664             raise ValueError("A file name has to be given for YACS XML output.")
665         else:
666             __file    = os.path.abspath(__filename)
667             if os.path.isfile(__file) or os.path.islink(__file):
668                 os.remove(__file)
669         # -----
670         if not PlatformInfo.has_salome or \
671                 not PlatformInfo.has_adao:
672             raise ImportError(
673                 "Unable to get SALOME (%s) or ADAO (%s) environnement for YACS conversion.\n"%(PlatformInfo.has_salome, PlatformInfo.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"]    = PlatformInfo.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 PlatformInfo.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")