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