Salome HOME
76aea8824bf3000c3e45e98a88e75f030dfa346e
[modules/adao.git] / src / daComposant / daCore / Interfaces.py
1 # -*- coding: utf-8 -*-
2 #
3 # Copyright (C) 2008-2018 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 logging
32 import copy
33 import numpy
34 import mimetypes
35 from daCore import Persistence
36 from daCore import PlatformInfo
37 from daCore import Templates
38
39 # ==============================================================================
40 class GenericCaseViewer(object):
41     """
42     Gestion des commandes de creation d'une vue de cas
43     """
44     def __init__(self, __name="", __objname="case", __content=None, __object=None):
45         "Initialisation et enregistrement de l'entete"
46         self._name         = str(__name)
47         self._objname      = str(__objname)
48         self._lineSerie    = []
49         self._switchoff    = False
50         self._numobservers = 2
51         self._content      = __content
52         self._object       = __object
53         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# """
54     def _append(self, *args):
55         "Transformation de commande individuelle en enregistrement"
56         raise NotImplementedError()
57     def _extract(self, *args):
58         "Transformation d'enregistrement en commande individuelle"
59         raise NotImplementedError()
60     def _finalize(self, __upa=None):
61         "Enregistrement du final"
62         if __upa is not None and len(__upa)>0:
63             self._lineSerie.append("%s.execute()"%(self._objname,))
64             self._lineSerie.append(__upa)
65     def _addLine(self, line=""):
66         "Ajoute un enregistrement individuel"
67         self._lineSerie.append(line)
68     def _get_objname(self):
69         return self._objname
70     def dump(self, __filename=None, __upa=None):
71         "Restitution normalisée des commandes"
72         self._finalize(__upa)
73         __text = "\n".join(self._lineSerie)
74         __text +="\n"
75         if __filename is not None:
76             __file = os.path.abspath(__filename)
77             __fid = open(__file,"w")
78             __fid.write(__text)
79             __fid.close()
80         return __text
81     def load(self, __filename=None, __content=None, __object=None):
82         "Chargement normalisé des commandes"
83         if __filename is not None and os.path.exists(__filename):
84             self._content = open(__filename, 'r').read()
85         elif __content is not None and type(__content) is str:
86             self._content = __content
87         elif __object is not None and type(__object) is dict:
88             self._object = copy.deepcopy(__object)
89         else:
90             pass # use "self._content" from initialization
91         __commands = self._extract(self._content, self._object)
92         return __commands
93
94 class _TUIViewer(GenericCaseViewer):
95     """
96     Etablissement des commandes d'un cas ADAO TUI (Cas<->TUI)
97     """
98     def __init__(self, __name="", __objname="case", __content=None, __object=None):
99         "Initialisation et enregistrement de l'entete"
100         GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
101         self._addLine("# -*- coding: utf-8 -*-")
102         self._addLine("#\n# Python script using ADAO TUI\n#")
103         self._addLine("from numpy import array, matrix")
104         self._addLine("import adaoBuilder")
105         self._addLine("%s = adaoBuilder.New('%s')"%(self._objname, self._name))
106         if self._content is not None:
107             for command in self._content:
108                 self._append(*command)
109     def _append(self, __command=None, __keys=None, __local=None, __pre=None, __switchoff=False):
110         "Transformation d'une commande individuelle en un enregistrement"
111         if __command is not None and __keys is not None and __local is not None:
112             __text  = ""
113             if __pre is not None:
114                 __text += "%s = "%__pre
115             __text += "%s.%s( "%(self._objname,str(__command))
116             if "self" in __keys: __keys.remove("self")
117             if __command not in ("set","get") and "Concept" in __keys: __keys.remove("Concept")
118             for k in __keys:
119                 __v = __local[k]
120                 if __v is None: continue
121                 if   k == "Checked" and not __v: continue
122                 if   k == "Stored"  and not __v: continue
123                 if   k == "AvoidRC" and __v: continue
124                 if   k == "noDetails": continue
125                 if isinstance(__v,Persistence.Persistence): __v = __v.values()
126                 if callable(__v): __text = self._missing%__v.__name__+__text
127                 if isinstance(__v,dict):
128                     for val in __v.values():
129                         if callable(val): __text = self._missing%val.__name__+__text
130                 numpy.set_printoptions(precision=15,threshold=1000000,linewidth=1000*15)
131                 __text += "%s=%s, "%(k,repr(__v))
132                 numpy.set_printoptions(precision=8,threshold=1000,linewidth=75)
133             __text.rstrip(", ")
134             __text += ")"
135             self._addLine(__text)
136     def _extract(self, __multilines="", __object=None):
137         "Transformation un enregistrement en une commande individuelle"
138         __is_case = False
139         __commands = []
140         __multilines = __multilines.replace("\r\n","\n")
141         for line in __multilines.split("\n"):
142             if "adaoBuilder.New" in line and "=" in line:
143                 self._objname = line.split("=")[0].strip()
144                 __is_case = True
145                 logging.debug("TUI Extracting commands of '%s' object..."%(self._objname,))
146             if not __is_case:
147                 continue
148             else:
149                 if self._objname+".set" in line:
150                     __commands.append( line.replace(self._objname+".","",1) )
151                     logging.debug("TUI Extracted command: %s"%(__commands[-1],))
152         return __commands
153
154 class _COMViewer(GenericCaseViewer):
155     """
156     Etablissement des commandes d'un cas COMM (Eficas Native Format/Cas<-COM)
157     """
158     def __init__(self, __name="", __objname="case", __content=None, __object=None):
159         "Initialisation et enregistrement de l'entete"
160         GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
161         self._observerIndex = 0
162         self._addLine("# -*- coding: utf-8 -*-")
163         self._addLine("#\n# Python script using ADAO COMM\n#")
164         self._addLine("from numpy import array, matrix")
165         self._addLine("#")
166         self._addLine("%s = {}"%__objname)
167         if self._content is not None:
168             for command in self._content:
169                 self._append(*command)
170     def _extract(self, __multilines=None, __object=None):
171         "Transformation un enregistrement en une commande individuelle"
172         if __multilines is not None:
173             __multilines = __multilines.replace("ASSIMILATION_STUDY","dict")
174             __multilines = __multilines.replace("CHECKING_STUDY",    "dict")
175             __multilines = __multilines.replace("_F(",               "dict(")
176             __multilines = __multilines.replace(",),);",             ",),)")
177         __fulllines = ""
178         for line in __multilines.split("\n"):
179             if len(line) < 1: continue
180             __fulllines += line + "\n"
181         __multilines = __fulllines
182         self._objname = "case"
183         self._objdata = None
184         exec("self._objdata = "+__multilines)
185         #
186         if self._objdata is None or not(type(self._objdata) is dict) or not('AlgorithmParameters' in self._objdata):
187             raise ValueError("Impossible to load given content as an ADAO COMM one (no dictionnary or no 'AlgorithmParameters' key found).")
188         # ----------------------------------------------------------------------
189         logging.debug("COMM Extracting commands of '%s' object..."%(self._objname,))
190         __commands = []
191         __UserPostAnalysis = ""
192         for k,r in self._objdata.items():
193             __command = k
194             logging.debug("COMM Extracted command: %s:%s"%(k, r))
195             if   __command == "StudyName" and len(str(r))>0:
196                 __commands.append( "set( Concept='Name', String='%s')"%(str(r),) )
197             elif   __command == "StudyRepertory":
198                 __commands.append( "set( Concept='Directory', String='%s')"%(str(r),) )
199             #
200             elif __command == "UserPostAnalysis" and type(r) is dict:
201                 if 'STRING' in r:
202                     __UserPostAnalysis = r['STRING']
203                 elif 'SCRIPT_FILE' in r and os.path.exists(r['SCRIPT_FILE']):
204                     __UserPostAnalysis = open(r['SCRIPT_FILE'],'r').read()
205                 elif 'Template' in r and 'ValueTemplate' in r:
206                     # AnalysisPrinter...
207                     __UserPostAnalysis = r['ValueTemplate']
208                 else:
209                     __UserPostAnalysis = ""
210                 __UserPostAnalysis = __UserPostAnalysis.replace("ADD",self._objname)
211             #
212             elif __command == "AlgorithmParameters" and type(r) is dict and 'Algorithm' in r:
213                 if 'data' in r and r['Parameters'] == 'Dict':
214                     __from = r['data']
215                     if 'STRING' in __from:
216                         __parameters = ", Parameters=%s"%(repr(eval(__from['STRING'])),)
217                     elif 'SCRIPT_FILE' in __from and os.path.exists(__from['SCRIPT_FILE']):
218                         __parameters = ", Script='%s'"%(__from['SCRIPT_FILE'],)
219                 else: # if 'Parameters' in r and r['Parameters'] == 'Defaults':
220                     __Dict = copy.deepcopy(r)
221                     __Dict.pop('Algorithm','')
222                     __Dict.pop('Parameters','')
223                     if 'SetSeed' in __Dict:__Dict['SetSeed'] = int(__Dict['SetSeed'])
224                     if 'BoxBounds' in __Dict and type(__Dict['BoxBounds']) is str:
225                         __Dict['BoxBounds'] = eval(__Dict['BoxBounds'])
226                     if len(__Dict) > 0:
227                         __parameters = ', Parameters=%s'%(repr(__Dict),)
228                     else:
229                         __parameters = ""
230                 __commands.append( "set( Concept='AlgorithmParameters', Algorithm='%s'%s )"%(r['Algorithm'],__parameters) )
231             #
232             elif __command == "Observers" and type(r) is dict and 'SELECTION' in r:
233                 if type(r['SELECTION']) is str:
234                     __selection = (r['SELECTION'],)
235                 else:
236                     __selection = tuple(r['SELECTION'])
237                 for sk in __selection:
238                     __idata = r['%s_data'%sk]
239                     if __idata['NodeType'] == 'Template' and 'Template' in __idata:
240                         __template = __idata['Template']
241                         if 'Info' in __idata:
242                             __info = ", Info='%s'"%(__idata['Info'],)
243                         else:
244                             __info = ""
245                         __commands.append( "set( Concept='Observer', Variable='%s', Template='%s'%s )"%(sk,__template,__info) )
246                     if __idata['NodeType'] == 'String' and 'Value' in __idata:
247                         __value =__idata['Value']
248                         __commands.append( "set( Concept='Observer', Variable='%s', String='%s' )"%(sk,__value) )
249             #
250             # Background, ObservationError, ObservationOperator...
251             elif type(r) is dict:
252                 __argumentsList = []
253                 if 'Stored' in r and bool(r['Stored']):
254                     __argumentsList.append(['Stored',True])
255                 if 'INPUT_TYPE' in r and 'data' in r:
256                     # Vector, Matrix, ScalarSparseMatrix, DiagonalSparseMatrix, Function
257                     __itype = r['INPUT_TYPE']
258                     __idata = r['data']
259                     if 'FROM' in __idata:
260                         # String, Script, Template, ScriptWithOneFunction, ScriptWithFunctions
261                         __ifrom = __idata['FROM']
262                         __idata.pop('FROM','')
263                         if __ifrom == 'String' or __ifrom == 'Template':
264                             __argumentsList.append([__itype,__idata['STRING']])
265                         if __ifrom == 'Script':
266                             __argumentsList.append([__itype,True])
267                             __argumentsList.append(['Script',__idata['SCRIPT_FILE']])
268                         if __ifrom == 'ScriptWithOneFunction':
269                             __argumentsList.append(['OneFunction',True])
270                             __argumentsList.append(['Script',__idata.pop('SCRIPTWITHONEFUNCTION_FILE')])
271                             if len(__idata)>0:
272                                 __argumentsList.append(['Parameters',__idata])
273                         if __ifrom == 'ScriptWithFunctions':
274                             __argumentsList.append(['ThreeFunctions',True])
275                             __argumentsList.append(['Script',__idata.pop('SCRIPTWITHFUNCTIONS_FILE')])
276                             if len(__idata)>0:
277                                 __argumentsList.append(['Parameters',__idata])
278                 __arguments = ["%s = %s"%(k,repr(v)) for k,v in __argumentsList]
279                 __commands.append( "set( Concept='%s', %s )"%(__command, ", ".join(__arguments)))
280         #
281         # ----------------------------------------------------------------------
282         __commands.sort() # Pour commencer par 'AlgorithmParameters'
283         __commands.append(__UserPostAnalysis)
284         return __commands
285
286 class _SCDViewer(GenericCaseViewer):
287     """
288     Etablissement des commandes d'un cas SCD (Study Config Dictionary/Cas->SCD)
289     """
290     def __init__(self, __name="", __objname="case", __content=None, __object=None):
291         "Initialisation et enregistrement de l'entete"
292         GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
293         self._addLine("# -*- coding: utf-8 -*-")
294         self._addLine("#\n# Input for ADAO converter to YACS\n#")
295         self._addLine("from numpy import array, matrix")
296         self._addLine("#")
297         self._addLine("study_config = {}")
298         self._addLine("study_config['StudyType'] = 'ASSIMILATION_STUDY'")
299         self._addLine("study_config['Name'] = '%s'"%self._name)
300         self._addLine("observers = {}")
301         self._addLine("study_config['Observers'] = observers")
302         self._addLine("#")
303         self._addLine("inputvariables_config = {}")
304         self._addLine("inputvariables_config['Order'] =['adao_default']")
305         self._addLine("inputvariables_config['adao_default'] = -1")
306         self._addLine("study_config['InputVariables'] = inputvariables_config")
307         self._addLine("#")
308         self._addLine("outputvariables_config = {}")
309         self._addLine("outputvariables_config['Order'] = ['adao_default']")
310         self._addLine("outputvariables_config['adao_default'] = -1")
311         self._addLine("study_config['OutputVariables'] = outputvariables_config")
312         if __content is not None:
313             for command in __content:
314                 self._append(*command)
315     def _append(self, __command=None, __keys=None, __local=None, __pre=None, __switchoff=False):
316         "Transformation d'une commande individuelle en un enregistrement"
317         if __command == "set": __command = __local["Concept"]
318         else:                  __command = __command.replace("set", "", 1)
319         #
320         __text  = None
321         if __command in (None, 'execute', 'executePythonScheme', 'executeYACSScheme', 'get', 'Name'):
322             return
323         elif __command in ['Debug', 'setDebug']:
324             __text  = "#\nstudy_config['Debug'] = '1'"
325         elif __command in ['NoDebug', 'setNoDebug']:
326             __text  = "#\nstudy_config['Debug'] = '0'"
327         elif __command in ['Observer', 'setObserver']:
328             __obs   = __local['Variable']
329             self._numobservers += 1
330             __text  = "#\n"
331             __text += "observers['%s'] = {}\n"%__obs
332             if __local['String'] is not None:
333                 __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'String')
334                 __text += "observers['%s']['String'] = \"\"\"%s\"\"\"\n"%(__obs, __local['String'])
335             if __local['Script'] is not None:
336                 __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'Script')
337                 __text += "observers['%s']['Script'] = \"%s\"\n"%(__obs, __local['Script'])
338             if __local['Template'] is not None and __local['Template'] in Templates.ObserverTemplates:
339                 __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'String')
340                 __text += "observers['%s']['String'] = \"\"\"%s\"\"\"\n"%(__obs, Templates.ObserverTemplates[__local['Template']])
341             if __local['Info'] is not None:
342                 __text += "observers['%s']['info'] = \"\"\"%s\"\"\"\n"%(__obs, __local['Info'])
343             else:
344                 __text += "observers['%s']['info'] = \"\"\"%s\"\"\"\n"%(__obs, __obs)
345             __text += "observers['%s']['number'] = %s"%(__obs, self._numobservers)
346         elif __local is not None: # __keys is not None and
347             numpy.set_printoptions(precision=15,threshold=1000000,linewidth=1000*15)
348             __text  = "#\n"
349             __text += "%s_config = {}\n"%__command
350             __local.pop('self','')
351             __to_be_removed = []
352             for __k,__v in __local.items():
353                 if __v is None: __to_be_removed.append(__k)
354             for __k in __to_be_removed:
355                 __local.pop(__k)
356             for __k,__v in __local.items():
357                 if __k == "Concept": continue
358                 if __k in ['ScalarSparseMatrix','DiagonalSparseMatrix','Matrix','OneFunction','ThreeFunctions'] and 'Script' in __local: continue
359                 if __k == 'Algorithm':
360                     __text += "study_config['Algorithm'] = %s\n"%(repr(__v))
361                 elif __k == 'Script':
362                     __k = 'Vector'
363                     __f = 'Script'
364                     __v = "'"+repr(__v)+"'"
365                     for __lk in ['ScalarSparseMatrix','DiagonalSparseMatrix','Matrix']:
366                         if __lk in __local and __local[__lk]: __k = __lk
367                     if __command == "AlgorithmParameters": __k = "Dict"
368                     if 'OneFunction' in __local and __local['OneFunction']:
369                         __text += "%s_ScriptWithOneFunction = {}\n"%(__command,)
370                         __text += "%s_ScriptWithOneFunction['Function'] = ['Direct', 'Tangent', 'Adjoint']\n"%(__command,)
371                         __text += "%s_ScriptWithOneFunction['Script'] = {}\n"%(__command,)
372                         __text += "%s_ScriptWithOneFunction['Script']['Direct'] = %s\n"%(__command,__v)
373                         __text += "%s_ScriptWithOneFunction['Script']['Tangent'] = %s\n"%(__command,__v)
374                         __text += "%s_ScriptWithOneFunction['Script']['Adjoint'] = %s\n"%(__command,__v)
375                         __text += "%s_ScriptWithOneFunction['DifferentialIncrement'] = 1e-06\n"%(__command,)
376                         __text += "%s_ScriptWithOneFunction['CenteredFiniteDifference'] = 0\n"%(__command,)
377                         __k = 'Function'
378                         __f = 'ScriptWithOneFunction'
379                         __v = '%s_ScriptWithOneFunction'%(__command,)
380                     if 'ThreeFunctions' in __local and __local['ThreeFunctions']:
381                         __text += "%s_ScriptWithFunctions = {}\n"%(__command,)
382                         __text += "%s_ScriptWithFunctions['Function'] = ['Direct', 'Tangent', 'Adjoint']\n"%(__command,)
383                         __text += "%s_ScriptWithFunctions['Script'] = {}\n"%(__command,)
384                         __text += "%s_ScriptWithFunctions['Script']['Direct'] = %s\n"%(__command,__v)
385                         __text += "%s_ScriptWithFunctions['Script']['Tangent'] = %s\n"%(__command,__v)
386                         __text += "%s_ScriptWithFunctions['Script']['Adjoint'] = %s\n"%(__command,__v)
387                         __k = 'Function'
388                         __f = 'ScriptWithFunctions'
389                         __v = '%s_ScriptWithFunctions'%(__command,)
390                     __text += "%s_config['Type'] = '%s'\n"%(__command,__k)
391                     __text += "%s_config['From'] = '%s'\n"%(__command,__f)
392                     __text += "%s_config['Data'] = %s\n"%(__command,__v)
393                     __text = __text.replace("''","'")
394                 elif __k in ('Stored', 'Checked'):
395                     if bool(__v):
396                         __text += "%s_config['%s'] = '%s'\n"%(__command,__k,int(bool(__v)))
397                 elif __k in ('AvoidRC', 'noDetails'):
398                     if not bool(__v):
399                         __text += "%s_config['%s'] = '%s'\n"%(__command,__k,int(bool(__v)))
400                 else:
401                     if __k == 'Parameters': __k = "Dict"
402                     if isinstance(__v,Persistence.Persistence): __v = __v.values()
403                     if callable(__v): __text = self._missing%__v.__name__+__text
404                     if isinstance(__v,dict):
405                         for val in __v.values():
406                             if callable(val): __text = self._missing%val.__name__+__text
407                     __text += "%s_config['Type'] = '%s'\n"%(__command,__k)
408                     __text += "%s_config['From'] = '%s'\n"%(__command,'String')
409                     __text += "%s_config['Data'] = \"\"\"%s\"\"\"\n"%(__command,repr(__v))
410             __text += "study_config['%s'] = %s_config"%(__command,__command)
411             numpy.set_printoptions(precision=8,threshold=1000,linewidth=75)
412             if __switchoff:
413                 self._switchoff = True
414         if __text is not None: self._addLine(__text)
415         if not __switchoff:
416             self._switchoff = False
417     def _finalize(self, *__args):
418         self.__loadVariablesByScript()
419         self._addLine("#")
420         self._addLine("Analysis_config = {}")
421         self._addLine("Analysis_config['From'] = 'String'")
422         self._addLine("Analysis_config['Data'] = \"\"\"import numpy")
423         self._addLine("xa=numpy.ravel(ADD.get('Analysis')[-1])")
424         self._addLine("print 'Analysis:',xa\"\"\"")
425         self._addLine("study_config['UserPostAnalysis'] = Analysis_config")
426     def __loadVariablesByScript(self):
427         __ExecVariables = {} # Necessaire pour recuperer la variable
428         exec("\n".join(self._lineSerie), __ExecVariables)
429         study_config = __ExecVariables['study_config']
430         # Pour Python 3 : self.__hasAlgorithm = bool(study_config['Algorithm'])
431         if 'Algorithm' in study_config:
432             self.__hasAlgorithm = True
433         else:
434             self.__hasAlgorithm = False
435         if not self.__hasAlgorithm and \
436                 "AlgorithmParameters" in study_config and \
437                 isinstance(study_config['AlgorithmParameters'], dict) and \
438                 "From" in study_config['AlgorithmParameters'] and \
439                 "Data" in study_config['AlgorithmParameters'] and \
440                 study_config['AlgorithmParameters']['From'] == 'Script':
441             __asScript = study_config['AlgorithmParameters']['Data']
442             __var = ImportFromScript(__asScript).getvalue( "Algorithm" )
443             __text = "#\nstudy_config['Algorithm'] = '%s'"%(__var,)
444             self._addLine(__text)
445         if self.__hasAlgorithm and \
446                 "AlgorithmParameters" in study_config and \
447                 isinstance(study_config['AlgorithmParameters'], dict) and \
448                 "From" not in study_config['AlgorithmParameters'] and \
449                 "Data" not in study_config['AlgorithmParameters']:
450             __text  = "#\n"
451             __text += "AlgorithmParameters_config['Type'] = 'Dict'\n"
452             __text += "AlgorithmParameters_config['From'] = 'String'\n"
453             __text += "AlgorithmParameters_config['Data'] = '{}'\n"
454             self._addLine(__text)
455         del study_config
456
457 class _YACSViewer(GenericCaseViewer):
458     """
459     Etablissement des commandes d'un cas YACS (Cas->SCD->YACS)
460     """
461     def __init__(self, __name="", __objname="case", __content=None, __object=None):
462         "Initialisation et enregistrement de l'entete"
463         GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
464         self.__internalSCD = _SCDViewer(__name, __objname, __content, __object)
465         self._append       = self.__internalSCD._append
466     def dump(self, __filename=None, __upa=None):
467         "Restitution normalisée des commandes"
468         # -----
469         if __filename is None:
470             raise ValueError("A file name has to be given for YACS XML output.")
471         else:
472             __file    = os.path.abspath(__filename)
473             if os.path.isfile(__file) or os.path.islink(__file):
474                 os.remove(__file)
475         # -----
476         if not PlatformInfo.has_salome or \
477             not PlatformInfo.has_adao:
478             raise ImportError(
479                 "Unable to get SALOME or ADAO environnement variables for YACS conversion.\n"+\
480                 "Please load the right environnement before trying to use it.")
481         else:
482             from daYacsSchemaCreator.run import create_schema_from_content
483         # -----
484         self.__internalSCD._finalize(__upa)
485         __SCDdump = self.__internalSCD.dump()
486         create_schema_from_content(__SCDdump, __file)
487         # -----
488         if not os.path.exists(__file):
489             __msg  = "An error occured during the ADAO YACS Schema build for\n"
490             __msg += "the target output file:\n"
491             __msg += "  %s\n"%__file
492             __msg += "See errors details in your launching terminal log.\n"
493             raise ValueError(__msg)
494         # -----
495         __fid = open(__file,"r")
496         __text = __fid.read()
497         __fid.close()
498         return __text
499
500 # ==============================================================================
501 class ImportFromScript(object):
502     """
503     Obtention d'une variable nommee depuis un fichier script importé
504     """
505     __slots__ = ("__basename", "__filenspace", "__filestring")
506     def __init__(self, __filename=None):
507         "Verifie l'existence et importe le script"
508         if __filename is None:
509             raise ValueError("The name of the file, containing the variable to be read, has to be specified.")
510         if not os.path.isfile(__filename):
511             raise ValueError("The file containing the variable to be imported doesn't seem to exist. Please check the file. The given file name is:\n  \"%s\""%str(__filename))
512         if os.path.dirname(__filename) != '':
513             sys.path.insert(0, os.path.dirname(__filename))
514             __basename = os.path.basename(__filename).rstrip(".py")
515         else:
516             __basename = __filename.rstrip(".py")
517         self.__basename = __basename
518         self.__filenspace = __import__(__basename, globals(), locals(), [])
519         self.__filestring = open(__filename,'r').read()
520     def getvalue(self, __varname=None, __synonym=None ):
521         "Renvoie la variable demandee par son nom ou son synonyme"
522         if __varname is None:
523             raise ValueError("The name of the variable to be read has to be specified. Please check the content of the file and the syntax.")
524         if not hasattr(self.__filenspace, __varname):
525             if __synonym is None:
526                 raise ValueError("The imported script file \"%s\" doesn't contain the mandatory variable \"%s\" to be read. Please check the content of the file and the syntax."%(str(self.__basename)+".py",__varname))
527             elif not hasattr(self.__filenspace, __synonym):
528                 raise ValueError("The imported script file \"%s\" doesn't contain the mandatory variable \"%s\" to be read. Please check the content of the file and the syntax."%(str(self.__basename)+".py",__synonym))
529             else:
530                 return getattr(self.__filenspace, __synonym)
531         else:
532             return getattr(self.__filenspace, __varname)
533     def getstring(self):
534         "Renvoie le script complet"
535         return self.__filestring
536
537 # ==============================================================================
538 class ImportDetector(object):
539     """
540     Détection des caractéristiques de fichiers ou objets en entrée
541     """
542     __slots__ = (
543         "__url", "__usr", "__root", "__end")
544     def __enter__(self): return self
545     def __exit__(self, exc_type, exc_val, exc_tb): return False
546     #
547     def __init__(self, __url, UserMime=""):
548         if __url is None:
549             raise ValueError("The name or url of the file object has to be specified.")
550         if __url is bytes:
551             self.__url = __url.decode()
552         else:
553             self.__url = str(__url)
554         if UserMime is bytes:
555             self.__usr = UserMime.decode().lower()
556         else:
557             self.__usr = str(UserMime).lower()
558         (self.__root, self.__end) = os.path.splitext(self.__url)
559         #
560         mimetypes.add_type('application/numpy.npy', '.npy')
561         mimetypes.add_type('application/numpy.npz', '.npz')
562     #
563     # File related f
564     # ------------------
565     def is_local_file(self):
566         if os.path.isfile(os.path.realpath(self.__url)):
567             return True
568         else:
569             return False
570     def is_not_local_file(self):
571         if not os.path.isfile(os.path.realpath(self.__url)):
572             return True
573         else:
574             return False
575     def raise_error_if_not_local_file(self):
576         if not os.path.isfile(os.path.realpath(self.__url)):
577             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))
578         else:
579             return False
580     # Directory related tests
581     # -----------------------
582     def is_local_dir(self):
583         if os.path.isdir(self.__url):
584             return True
585         else:
586             return False
587     def is_not_local_dir(self):
588         if not os.path.isdir(self.__url):
589             return True
590         else:
591             return False
592     def raise_error_if_not_local_dir(self):
593         if not os.path.isdir(self.__url):
594             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))
595         else:
596             return False
597     # Mime related functions
598     # ------------------------
599     def get_standard_mime(self):
600         (__mtype, __encoding) = mimetypes.guess_type(self.__url, strict=False)
601         return __mtype
602     def get_user_mime(self):
603         __fake = "fake."+self.__usr.lower()
604         (__mtype, __encoding) = mimetypes.guess_type(__fake, strict=False)
605         return __mtype
606     def get_comprehensive_mime(self):
607         if self.get_standard_mime() is not None:
608             return self.get_standard_mime()
609         elif self.get_user_mime() is not None:
610             return self.get_user_mime()
611         else:
612             return None
613     # Name related functions
614     # ----------------------
615     def get_user_name(self):
616         return self.__url
617     def get_absolute_name(self):
618         return os.path.abspath(os.path.realpath(self.__url))
619     def get_extension(self):
620         return self.__end
621
622 # ==============================================================================
623 class ImportFromFile(object):
624     """
625     Obtention de variables disrétisées en 1D, définies par une ou des variables
626     nommées, et sous la forme d'une série de points éventuellement indexés. La
627     lecture d'un fichier au format spécifié (ou intuité) permet de charger ces
628     fonctions depuis :
629         - des fichiers textes en colonnes de type TXT, CSV, TSV...
630         - des fichiers de données binaires NPY, NPZ...
631     La lecture du fichier complet ne se fait que si nécessaire, pour assurer la
632     performance tout en disposant de l'interprétation du contenu. Les fichiers
633     textes doivent présenter en première ligne (hors commentaire ou ligne vide)
634     les noms des variables de colonnes. Les commentaires commencent par un "#".
635     """
636     __slots__ = (
637         "_filename", "_colnames", "_colindex", "_varsline", "_format",
638         "_delimiter", "_skiprows", "__url", "__filestring", "__header",
639         "__allowvoid")
640     def __enter__(self): return self
641     def __exit__(self, exc_type, exc_val, exc_tb): return False
642     #
643     def __init__(self, Filename=None, ColNames=None, ColIndex=None, Format="Guess", AllowVoidNameList=True):
644         """
645         Verifie l'existence et les informations de définition du fichier. Les
646         noms de colonnes ou de variables sont ignorées si le format ne permet
647         pas de les indiquer.
648         Arguments :
649             - Filename : nom du fichier
650             - ColNames : noms de la ou des colonnes/variables à lire
651             - ColIndex : nom unique de la colonne/variable servant d'index
652             - Format : format du fichier et/ou des données inclues
653             - AllowVoidNameList : permet, si la liste de noms est vide, de
654               prendre par défaut toutes les colonnes
655         """
656         self.__url = ImportDetector( Filename, Format)
657         self.__url.raise_error_if_not_local_file()
658         self._filename = self.__url.get_absolute_name()
659         #
660         self._format = self.__url.get_comprehensive_mime()
661         #
662         self.__header, self._varsline, self._skiprows = self.__getentete()
663         #
664         if self._format == "text/csv" or Format.upper() == "CSV":
665             self.__filestring = "".join(self.__header)
666             if self.__filestring.count(",") > 1:
667                 self._delimiter = ","
668             elif self.__filestring.count(";") > 1:
669                 self._delimiter = ";"
670         elif self._format == "text/tab-separated-values" or Format.upper() == "TSV":
671             self._delimiter = "\t"
672         else:
673             self._delimiter = None
674         #
675         if ColNames is not None: self._colnames = tuple(ColNames)
676         else:                    self._colnames = None
677         #
678         if ColIndex is not None: self._colindex = str(ColIndex)
679         else:                    self._colindex = None
680         #
681         self.__allowvoid = bool(AllowVoidNameList)
682
683     def __getentete(self, __nblines = 3):
684         "Lit l'entête du fichier pour trouver la définition des variables"
685         __header, __varsline, __skiprows = [], "", 1
686         if self._format in ("application/numpy.npy", "application/numpy.npz"):
687             pass
688         else:
689             with open(self._filename,'r') as fid:
690                 __line = fid.readline().strip()
691                 while "#" in __line or len(__line) < 1:
692                     __header.append(__line)
693                     __skiprows += 1
694                     __line = fid.readline().strip()
695                 __varsline = __line # Première ligne non commentée non vide
696                 for i in range(max(0,__nblines)):
697                     __header.append(fid.readline())
698         return (__header, __varsline, __skiprows)
699
700     def __getindices(self, __colnames, __colindex, __delimiter=None ):
701         "Indices de colonnes correspondants à l'index et aux variables"
702         if __delimiter is None:
703             __varserie = self._varsline.strip('#').strip().split()
704         else:
705             __varserie = self._varsline.strip('#').strip().split(str(__delimiter))
706         #
707         if __colnames is not None:
708             __usecols = []
709             __colnames = tuple(__colnames)
710             for v in __colnames:
711                 for i, n in enumerate(__varserie):
712                     if v == n: __usecols.append(i)
713             __usecols = tuple(__usecols)
714             if len(__usecols) == 0:
715                 if self.__allowvoid:
716                     __usecols = None
717                 else:
718                     raise ValueError("Can not found any column corresponding to the required names %s"%(__colnames,))
719         else:
720             __usecols = None
721         #
722         if __colindex is not None:
723             __useindex = None
724             __colindex = str(__colindex)
725             for i, n in enumerate(__varserie):
726                 if __colindex == n: __useindex = i
727         else:
728             __useindex = None
729         #
730         return (__usecols, __useindex)
731
732     def getvalue(self, ColNames=None, ColIndex=None ):
733         "Renvoie la ou les variables demandees par la liste de leurs noms"
734         # Uniquement si mise à jour
735         if ColNames is not None: self._colnames = tuple(ColNames)
736         if ColIndex is not None: self._colindex = str(ColIndex)
737         #
738         __index = None
739         if self._format == "application/numpy.npy":
740             __columns = numpy.load(self._filename)
741         elif self._format == "application/numpy.npz":
742             __columns = None
743             with numpy.load(self._filename) as __allcolumns:
744                 if self._colnames is None:
745                     self._colnames = __allcolumns.files
746                 for nom in self._colnames:
747                     if nom in __allcolumns.files:
748                         if __columns is not None:
749                             # Attention : toutes les variables doivent avoir la même taille
750                             __columns = numpy.vstack((__columns, numpy.reshape(__allcolumns[nom], (1,-1))))
751                         else:
752                             # Première colonne
753                             __columns = numpy.reshape(__allcolumns[nom], (1,-1))
754                 if self._colindex is not None and self._colindex in __allcolumns.files:
755                     __index = numpy.array(numpy.reshape(__allcolumns[self._colindex], (1,-1)), dtype=bytes)
756         elif self._format == "text/plain":
757             __usecols, __useindex = self.__getindices(self._colnames, self._colindex)
758             __columns = numpy.loadtxt(self._filename, usecols = __usecols, skiprows=self._skiprows)
759             if __useindex is not None:
760                 __index = numpy.loadtxt(self._filename, dtype = bytes, usecols = (__useindex,), skiprows=self._skiprows)
761         #
762         elif self._format == "text/csv":
763             __usecols, __useindex = self.__getindices(self._colnames, self._colindex, self._delimiter)
764             __columns = numpy.loadtxt(self._filename, usecols = __usecols, delimiter = self._delimiter, skiprows=self._skiprows)
765             if __useindex is not None:
766                 __index = numpy.loadtxt(self._filename, dtype = bytes, usecols = (__useindex,), delimiter = self._delimiter, skiprows=self._skiprows)
767         #
768         elif self._format == "text/tab-separated-values":
769             __usecols, __useindex = self.__getindices(self._colnames, self._colindex, self._delimiter)
770             __columns = numpy.loadtxt(self._filename, usecols = __usecols, delimiter = self._delimiter, skiprows=self._skiprows)
771             if __useindex is not None:
772                 __index = numpy.loadtxt(self._filename, dtype = bytes, usecols = (__useindex,), delimiter = self._delimiter, skiprows=self._skiprows)
773         else:
774             raise ValueError("Unkown file format \"%s\""%self._format)
775         #
776         def toString(value):
777             try:
778                 return value.decode()
779             except ValueError:
780                 return value
781         if __index is not None:
782             __index = tuple([toString(v) for v in __index])
783         #
784         return (self._colnames, __columns, self._colindex, __index)
785
786     def getstring(self):
787         "Renvoie le fichier complet"
788         with open(self._filename,'r') as fid:
789             return fid.read()
790
791 # ==============================================================================
792 class ImportScalarLinesFromFile(ImportFromFile):
793     """
794     Importation de fichier contenant des variables scalaires nommées. Le
795     fichier comporte soit 2, soit 4 colonnes, obligatoirement nommées "Name",
796     "Value", "Minimum", "Maximum" si les noms sont précisés. Sur chaque ligne
797     est indiqué le nom, la valeur, et éventuelement deux bornes min et max (ou
798     None si nécessaire pour une borne).
799
800     Seule la méthode "getvalue" est changée.
801     """
802     def __enter__(self): return self
803     def __exit__(self, exc_type, exc_val, exc_tb): return False
804     #
805     def __init__(self, Filename=None, ColNames=None, ColIndex=None, Format="Guess"):
806         ImportFromFile.__init__(self, Filename, ColNames, ColIndex, Format)
807         if self._format not in ["text/plain", "text/csv", "text/tab-separated-values"]:
808             raise ValueError("Unkown file format \"%s\""%self._format)
809     #
810     def getvalue(self, VarNames = None, HeaderNames=()):
811         "Renvoie la ou les variables demandees par la liste de leurs noms"
812         if VarNames is not None: __varnames = tuple(VarNames)
813         else:                    __varnames = None
814         #
815         if "Name" in self._varsline and "Value" in self._varsline and "Minimum" in self._varsline and "Maximum" in self._varsline:
816             __ftype = "NamValMinMax"
817             __dtypes   = {'names'  : ('Name', 'Value', 'Minimum', 'Maximum'),
818                           'formats': ('S128', 'g', 'g', 'g')}
819             __usecols  = (0, 1, 2, 3)
820             def __replaceNoneN( s ):
821                 if s.strip() == b'None': return numpy.NINF
822                 else:                    return s
823             def __replaceNoneP( s ):
824                 if s.strip() == b'None': return numpy.PINF
825                 else:                    return s
826             __converters = {2: __replaceNoneN, 3: __replaceNoneP}
827         elif "Name" in self._varsline and "Value" in self._varsline and ("Minimum" not in self._varsline or "Maximum" not in self._varsline):
828             __ftype = "NamVal"
829             __dtypes   = {'names'  : ('Name', 'Value'),
830                           'formats': ('S128', 'g')}
831             __converters = None
832             __usecols  = (0, 1)
833         elif len(HeaderNames)>0 and numpy.all([kw in self._varsline for kw in HeaderNames]):
834             __ftype = "NamLotOfVals"
835             __dtypes   = {'names'  : HeaderNames,
836                           'formats': tuple(['S128',]+['g']*(len(HeaderNames)-1))}
837             __usecols  = tuple(range(len(HeaderNames)))
838             def __replaceNone( s ):
839                 if s.strip() == b'None': return numpy.NAN
840                 else:                    return s
841             __converters = dict()
842             for i in range(1,len(HeaderNames)):
843                 __converters[i] = __replaceNone
844         else:
845             raise ValueError("Can not find names of columns for initial values. Wrong first line is:\n            \"%s\""%__firstline)
846         #
847         if self._format == "text/plain":
848             __content = numpy.loadtxt(self._filename, dtype = __dtypes, usecols = __usecols, skiprows = self._skiprows, converters = __converters)
849         elif self._format in ["text/csv", "text/tab-separated-values"]:
850             __content = numpy.loadtxt(self._filename, dtype = __dtypes, usecols = __usecols, skiprows = self._skiprows, converters = __converters, delimiter = self._delimiter)
851         else:
852             raise ValueError("Unkown file format \"%s\""%self._format)
853         #
854         __names, __background, __bounds = [], [], []
855         for sub in __content:
856             if len(__usecols) == 4:
857                 na, va, mi, ma = sub
858                 if numpy.isneginf(mi): mi = None # Réattribue les variables None
859                 elif numpy.isnan(mi):  mi = None # Réattribue les variables None
860                 if numpy.isposinf(ma): ma = None # Réattribue les variables None
861                 elif numpy.isnan(ma):  ma = None # Réattribue les variables None
862             elif len(__usecols) == 2 and __ftype == "NamVal":
863                 na, va = sub
864                 mi, ma = None, None
865             else:
866                 nsub = list(sub)
867                 na = sub[0]
868                 for i, v in enumerate(nsub[1:]):
869                     if numpy.isnan(v): nsub[i+1] = None
870                 va = nsub[1:]
871                 mi, ma = None, None
872             na = na.decode()
873             if (__varnames is None or na in __varnames) and (na not in __names):
874                 # Ne stocke que la premiere occurence d'une variable
875                 __names.append(na)
876                 __background.append(va)
877                 __bounds.append((mi,ma))
878         #
879         __names      = tuple(__names)
880         __background = numpy.array(__background)
881         __bounds     = tuple(__bounds)
882         #
883         return (__names, __background, __bounds)
884
885 # ==============================================================================
886 if __name__ == "__main__":
887     print('\n AUTODIAGNOSTIC \n')