1 # -*- coding: utf-8 -*-
3 # Copyright (C) 2008-2018 EDF R&D
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.
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.
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
19 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 # Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
24 Normalized interface for ADAO scripting (generic API)
26 __author__ = "Jean-Philippe ARGAUD"
32 from daCore.BasicObjects import State, Covariance, FullOperator, Operator
33 from daCore.BasicObjects import AlgorithmAndParameters, DataObserver
34 from daCore.BasicObjects import CaseLogger
35 from daCore import PlatformInfo
37 from daCore import ExtendedLogging ; ExtendedLogging.ExtendedLogging() # A importer en premier
40 # ==============================================================================
42 """ ADAO Internal Data Structure Model """
43 def __init__(self, name = "", addViewers=None):
44 self.__name = str(name)
45 self.__case = CaseLogger(self.__name, "case", addViewers)
47 self.__adaoObject = {}
48 self.__StoredInputs = {}
51 "AlgorithmParameters",
60 "ObservationOperator",
68 for ename in self.__Concepts:
69 self.__adaoObject[ename] = None
70 for ename in ("ObservationOperator", "EvolutionModel", "ControlModel"):
71 self.__adaoObject[ename] = {}
72 for ename in ("Observer",):
73 self.__adaoObject[ename] = []
74 self.__StoredInputs[ename] = []
76 # Récupère le chemin du répertoire parent et l'ajoute au path
77 # (Cela complète l'action de la classe PathManagement dans PlatformInfo,
78 # qui est activée dans Persistence)
79 self.__parent = os.path.abspath(os.path.join(os.path.dirname(__file__),".."))
80 sys.path.insert(0, self.__parent)
81 sys.path = PlatformInfo.uniq( sys.path ) # Conserve en unique exemplaire chaque chemin
84 Concept = None, # Premier argument
89 DiagonalSparseMatrix = None,
92 ObjectFunction = None,
96 ScalarSparseMatrix = None,
102 ThreeFunctions = None,
107 "Interface unique de definition de variables d'entrees par argument"
108 self.__case.register("set",dir(),locals(),None,True)
110 if Concept in ("Background", "CheckingPoint", "ControlInput", "Observation", "Controls"):
111 commande = getattr(self,"set"+Concept)
112 commande(Vector, VectorSerie, Script, Stored, Scheduler, Checked )
113 elif Concept in ("BackgroundError", "ObservationError", "EvolutionError"):
114 commande = getattr(self,"set"+Concept)
115 commande(Matrix, ScalarSparseMatrix, DiagonalSparseMatrix,
116 Script, Stored, ObjectMatrix, Checked )
117 elif Concept == "AlgorithmParameters":
118 self.setAlgorithmParameters( Algorithm, Parameters, Script )
119 elif Concept == "Debug":
121 elif Concept == "NoDebug":
123 elif Concept == "Observer":
124 self.setObserver( Variable, Template, String, Script, Info, ObjectFunction, Scheduler )
125 elif Concept == "ObservationOperator":
126 self.setObservationOperator(
127 Matrix, OneFunction, ThreeFunctions, AppliedInXb,
128 Parameters, Script, Stored, AvoidRC, Checked )
129 elif Concept in ("EvolutionModel", "ControlModel"):
130 commande = getattr(self,"set"+Concept)
132 Matrix, OneFunction, ThreeFunctions,
133 Parameters, Script, Scheduler, Stored, AvoidRC, Checked )
136 raise ValueError("the variable named '%s' is not allowed."%str(Concept))
137 except Exception as e:
138 if isinstance(e, SyntaxError): msg = "at %s: %s"%(e.offset, e.text)
140 raise ValueError("during settings, the following error occurs:\n"+\
141 "\n%s %s\n\nSee also the potential messages, "+\
142 "which can show the origin of the above error, "+\
143 "in the launching terminal."%(str(e),msg))
145 # -----------------------------------------------------------
147 def setBackground(self,
154 "Definition d'un concept de calcul"
155 Concept = "Background"
156 self.__case.register("set"+Concept, dir(), locals())
157 self.__adaoObject[Concept] = State(
160 asPersistentVector = VectorSerie,
162 scheduledBy = Scheduler,
163 toBeChecked = Checked,
166 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
169 def setCheckingPoint(self,
176 "Definition d'un concept de calcul"
177 Concept = "CheckingPoint"
178 self.__case.register("set"+Concept, dir(), locals())
179 self.__adaoObject[Concept] = State(
182 asPersistentVector = VectorSerie,
184 scheduledBy = Scheduler,
185 toBeChecked = Checked,
188 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
191 def setControlInput(self,
198 "Definition d'un concept de calcul"
199 Concept = "ControlInput"
200 self.__case.register("set"+Concept, dir(), locals())
201 self.__adaoObject[Concept] = State(
204 asPersistentVector = VectorSerie,
206 scheduledBy = Scheduler,
207 toBeChecked = Checked,
210 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
213 def setObservation(self,
220 "Definition d'un concept de calcul"
221 Concept = "Observation"
222 self.__case.register("set"+Concept, dir(), locals())
223 self.__adaoObject[Concept] = State(
226 asPersistentVector = VectorSerie,
228 scheduledBy = Scheduler,
229 toBeChecked = Checked,
232 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
235 def setControls(self,
236 Vector = (), # Valeur par defaut pour un vecteur vide
242 "Definition d'un concept de calcul"
244 self.__case.register("set"+Concept, dir(), locals())
245 self.__adaoObject[Concept] = State(
248 asPersistentVector = VectorSerie,
250 scheduledBy = Scheduler,
251 toBeChecked = Checked,
254 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
257 def setBackgroundError(self,
259 ScalarSparseMatrix = None,
260 DiagonalSparseMatrix = None,
265 "Definition d'un concept de calcul"
266 Concept = "BackgroundError"
267 self.__case.register("set"+Concept, dir(), locals())
268 self.__adaoObject[Concept] = Covariance(
270 asCovariance = Matrix,
271 asEyeByScalar = ScalarSparseMatrix,
272 asEyeByVector = DiagonalSparseMatrix,
273 asCovObject = ObjectMatrix,
275 toBeChecked = Checked,
278 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
281 def setObservationError(self,
283 ScalarSparseMatrix = None,
284 DiagonalSparseMatrix = None,
289 "Definition d'un concept de calcul"
290 Concept = "ObservationError"
291 self.__case.register("set"+Concept, dir(), locals())
292 self.__adaoObject[Concept] = Covariance(
294 asCovariance = Matrix,
295 asEyeByScalar = ScalarSparseMatrix,
296 asEyeByVector = DiagonalSparseMatrix,
297 asCovObject = ObjectMatrix,
299 toBeChecked = Checked,
302 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
305 def setEvolutionError(self,
307 ScalarSparseMatrix = None,
308 DiagonalSparseMatrix = None,
313 "Definition d'un concept de calcul"
314 Concept = "EvolutionError"
315 self.__case.register("set"+Concept, dir(), locals())
316 self.__adaoObject[Concept] = Covariance(
318 asCovariance = Matrix,
319 asEyeByScalar = ScalarSparseMatrix,
320 asEyeByVector = DiagonalSparseMatrix,
321 asCovObject = ObjectMatrix,
323 toBeChecked = Checked,
326 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
329 def setObservationOperator(self,
332 ThreeFunctions = None,
339 "Definition d'un concept de calcul"
340 Concept = "ObservationOperator"
341 self.__case.register("set"+Concept, dir(), locals())
342 self.__adaoObject[Concept] = FullOperator(
345 asOneFunction = OneFunction,
346 asThreeFunctions = ThreeFunctions,
349 appliedInX = AppliedInXb,
352 toBeChecked = Checked,
355 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
358 def setEvolutionModel(self,
361 ThreeFunctions = None,
368 "Definition d'un concept de calcul"
369 Concept = "EvolutionModel"
370 self.__case.register("set"+Concept, dir(), locals())
371 self.__adaoObject[Concept] = FullOperator(
374 asOneFunction = OneFunction,
375 asThreeFunctions = ThreeFunctions,
380 scheduledBy = Scheduler,
381 toBeChecked = Checked,
384 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
387 def setControlModel(self,
390 ThreeFunctions = None,
397 "Definition d'un concept de calcul"
398 Concept = "ControlModel"
399 self.__case.register("set"+Concept, dir(), locals())
400 self.__adaoObject[Concept] = FullOperator(
403 asOneFunction = OneFunction,
404 asThreeFunctions = ThreeFunctions,
409 scheduledBy = Scheduler,
410 toBeChecked = Checked,
413 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
416 def setDebug(self, level = 10):
417 "NOTSET=0 < DEBUG=10 < INFO=20 < WARNING=30 < ERROR=40 < CRITICAL=50"
418 self.__case.register("setDebug",dir(),locals())
419 log = logging.getLogger()
420 log.setLevel( level )
421 self.__StoredInputs["Debug"] = level
422 self.__StoredInputs["NoDebug"] = False
425 def setNoDebug(self):
426 "NOTSET=0 < DEBUG=10 < INFO=20 < WARNING=30 < ERROR=40 < CRITICAL=50"
427 self.__case.register("setNoDebug",dir(),locals())
428 log = logging.getLogger()
429 log.setLevel( logging.WARNING )
430 self.__StoredInputs["Debug"] = logging.WARNING
431 self.__StoredInputs["NoDebug"] = True
434 def setAlgorithmParameters(self,
438 "Definition d'un concept de calcul"
439 Concept = "AlgorithmParameters"
440 self.__case.register("set"+Concept, dir(), locals())
441 self.__adaoObject[Concept] = AlgorithmAndParameters(
443 asAlgorithm = Algorithm,
449 def updateAlgorithmParameters(self,
452 "Mise a jour d'un concept de calcul"
453 if "AlgorithmParameters" not in self.__adaoObject:
454 raise ValueError("No algorithm registred, ask for one before updating parameters")
455 self.__adaoObject["AlgorithmParameters"].updateParameters(
461 def setObserver(self,
467 ObjectFunction = None,
469 "Definition d'un concept de calcul"
471 self.__case.register("set"+Concept, dir(), locals())
472 self.__adaoObject[Concept].append( DataObserver(
474 onVariable = Variable,
475 asTemplate = Template,
478 asObsObject = ObjectFunction,
480 scheduledBy = Scheduler,
481 withAlgo = self.__adaoObject["AlgorithmParameters"]
485 def removeObserver(self,
487 ObjectFunction = None,
489 "Permet de retirer un observer à une ou des variable nommée"
490 if "AlgorithmParameters" not in self.__adaoObject:
491 raise ValueError("No algorithm registred, ask for one before removing observers")
493 # Vérification du nom de variable et typage
494 # -----------------------------------------
495 if isinstance(Variable, str):
496 VariableNames = (Variable,)
497 elif isinstance(Variable, list):
498 VariableNames = tuple(map( str, Variable ))
500 raise ValueError("The observer requires a name or a list of names of variables.")
502 # Association interne de l'observer à la variable
503 # -----------------------------------------------
504 for ename in VariableNames:
505 if ename not in self.__adaoObject["AlgorithmParameters"]:
506 raise ValueError("An observer requires to be removed on a variable named %s which does not exist."%ename)
508 return self.__adaoObject["AlgorithmParameters"].removeObserver( ename, ObjectFunction )
510 # -----------------------------------------------------------
512 def get(self, Concept=None, noDetails=True ):
513 "Recuperation d'une sortie du calcul"
514 if Concept is not None:
516 self.__case.register("get", dir(), locals(), Concept) # Break pickle in Python 2
519 if Concept in self.__StoredInputs:
520 return self.__StoredInputs[Concept]
522 elif self.__adaoObject["AlgorithmParameters"] is not None and Concept == "AlgorithmParameters":
523 return self.__adaoObject["AlgorithmParameters"].get()
525 elif self.__adaoObject["AlgorithmParameters"] is not None and Concept in self.__adaoObject["AlgorithmParameters"]:
526 return self.__adaoObject["AlgorithmParameters"].get( Concept )
528 elif Concept == "AlgorithmRequiredParameters" and self.__adaoObject["AlgorithmParameters"] is not None:
529 return self.__adaoObject["AlgorithmParameters"].getAlgorithmRequiredParameters(noDetails)
532 raise ValueError("The requested key \"%s\" does not exists as an input or a stored variable."%Concept)
535 allvariables.update( {"AlgorithmParameters":self.__adaoObject["AlgorithmParameters"].get()} )
536 # allvariables.update( self.__adaoObject["AlgorithmParameters"].get() )
537 allvariables.update( self.__StoredInputs )
538 allvariables.pop('Observer', None)
541 # -----------------------------------------------------------
543 def get_available_variables(self):
545 Renvoie les variables potentiellement utilisables pour l'étude,
546 initialement stockées comme données d'entrées ou dans les algorithmes,
547 identifiés par les chaînes de caractères. L'algorithme doit avoir été
548 préalablement choisi sinon la méthode renvoie "None".
550 if len(list(self.__adaoObject["AlgorithmParameters"].keys())) == 0 and \
551 len(list(self.__StoredInputs.keys())) == 0:
555 if len(list(self.__adaoObject["AlgorithmParameters"].keys())) > 0:
556 variables.extend(list(self.__adaoObject["AlgorithmParameters"].keys()))
557 if len(list(self.__StoredInputs.keys())) > 0:
558 variables.extend( list(self.__StoredInputs.keys()) )
559 variables.remove('Observer')
563 def get_available_algorithms(self):
565 Renvoie la liste des algorithmes potentiellement utilisables, identifiés
566 par les chaînes de caractères.
569 for directory in sys.path:
570 trypath = os.path.join(directory,"daAlgorithms")
571 if os.path.isdir(trypath):
572 for fname in os.listdir(trypath):
573 if os.path.isfile(os.path.join(trypath,fname)):
574 fc = open(os.path.join(trypath,fname)).read()
575 iselal = bool("class ElementaryAlgorithm" in fc)
576 root, ext = os.path.splitext(fname)
577 if iselal and ext == '.py' and root != '__init__':
582 # -----------------------------------------------------------
584 def get_algorithms_main_path(self):
586 Renvoie le chemin pour le répertoire principal contenant les algorithmes
590 def add_algorithms_path(self, Path=None):
592 Ajoute au chemin de recherche des algorithmes un répertoire dans lequel
593 se trouve un sous-répertoire "daAlgorithms"
595 if not os.path.isdir(Path):
596 raise ValueError("The given "+Path+" argument must exist as a directory")
597 if not os.path.isdir(os.path.join(Path,"daAlgorithms")):
598 raise ValueError("The given \""+Path+"\" argument must contain a subdirectory named \"daAlgorithms\"")
599 if not os.path.isfile(os.path.join(Path,"daAlgorithms","__init__.py")):
600 raise ValueError("The given \""+Path+"/daAlgorithms\" path must contain a file named \"__init__.py\"")
601 sys.path.insert(0, os.path.abspath(Path))
602 sys.path = PlatformInfo.uniq( sys.path ) # Conserve en unique exemplaire chaque chemin
605 # -----------------------------------------------------------
607 def execute(self, Executor=None, SaveCaseInFile=None):
608 "Lancement du calcul"
609 self.__case.register("execute",dir(),locals(),None,True)
610 Operator.CM.clearCache()
612 if Executor == "YACS": self.__executeYACSScheme( SaveCaseInFile )
613 else: self.__executePythonScheme( SaveCaseInFile )
614 except Exception as e:
615 if isinstance(e, SyntaxError): msg = "at %s: %s"%(e.offset, e.text)
617 raise ValueError(("during execution, the following error occurs:\n"+\
618 "\n%s %s\n\nSee also the potential messages, "+\
619 "which can show the origin of the above error, "+\
620 "in the launching terminal.\n")%(str(e),msg))
623 def __executePythonScheme(self, FileName=None):
624 "Lancement du calcul"
625 self.__case.register("executePythonScheme", dir(), locals())
626 if FileName is not None:
627 self.dump( FileName, "TUI")
628 self.__adaoObject["AlgorithmParameters"].executePythonScheme( self.__adaoObject )
631 def __executeYACSScheme(self, FileName=None):
632 "Lancement du calcul"
633 self.__case.register("executeYACSScheme", dir(), locals())
634 self.dump( FileName, "YACS")
635 self.__adaoObject["AlgorithmParameters"].executeYACSScheme( FileName )
638 # -----------------------------------------------------------
640 def dump(self, FileName=None, Formater="TUI"):
641 "Restitution normalisée des commandes"
642 return self.__case.dump(FileName, Formater)
644 def load(self, FileName=None, Formater="TUI"):
645 "Chargement normalisé des commandes"
646 __commands = self.__case.load(FileName, Formater)
647 from numpy import array, matrix
648 for __command in __commands:
649 exec("self."+__command)
653 "Effacement du contenu du cas en cours"
654 self.__init__(self.__name)
656 # -----------------------------------------------------------
659 "Clarifie la visibilité des méthodes"
660 return ['set', 'get', 'execute', '__doc__', '__init__', '__module__']
662 def prepare_to_pickle(self):
663 "Retire les variables non pickelisables, avec recopie efficace"
664 if self.__adaoObject['AlgorithmParameters'] is not None:
665 for k in self.__adaoObject['AlgorithmParameters'].keys():
666 if k == "Algorithm": continue
667 if k in self.__StoredInputs:
668 raise ValueError("the key \"%s\s to be transfered for pickling will overwrite an existing one.")
669 if self.__adaoObject['AlgorithmParameters'].hasObserver( k ):
670 self.__adaoObject['AlgorithmParameters'].removeObserver( k, "", True )
671 self.__StoredInputs[k] = self.__adaoObject['AlgorithmParameters'].pop(k, None)
672 if sys.version_info[0] == 2:
673 del self.__adaoObject # Because it breaks pickle in Python 2. Not required for Python 3
674 del self.__case # Because it breaks pickle in Python 2. Not required for Python 3
677 # ==============================================================================
678 if __name__ == "__main__":
679 print('\n AUTODIAGNOSTIC \n')