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