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.__directory = None
46 self.__case = CaseLogger(self.__name, "case", addViewers)
48 self.__adaoObject = {}
49 self.__StoredInputs = {}
52 "AlgorithmParameters",
61 "ObservationOperator",
69 for ename in self.__Concepts:
70 self.__adaoObject[ename] = None
71 for ename in ("ObservationOperator", "EvolutionModel", "ControlModel"):
72 self.__adaoObject[ename] = {}
73 for ename in ("Observer",):
74 self.__adaoObject[ename] = []
75 self.__StoredInputs[ename] = []
77 # Récupère le chemin du répertoire parent et l'ajoute au path
78 # (Cela complète l'action de la classe PathManagement dans PlatformInfo,
79 # qui est activée dans Persistence)
80 self.__parent = os.path.abspath(os.path.join(os.path.dirname(__file__),".."))
81 sys.path.insert(0, self.__parent)
82 sys.path = PlatformInfo.uniq( sys.path ) # Conserve en unique exemplaire chaque chemin
85 Concept = None, # Premier argument
90 DiagonalSparseMatrix = None,
93 ObjectFunction = None,
97 ScalarSparseMatrix = None,
103 ThreeFunctions = None,
108 "Interface unique de definition de variables d'entrees par argument"
109 self.__case.register("set",dir(),locals(),None,True)
111 if Concept in ("Background", "CheckingPoint", "ControlInput", "Observation", "Controls"):
112 commande = getattr(self,"set"+Concept)
113 commande(Vector, VectorSerie, Script, Stored, Scheduler, Checked )
114 elif Concept in ("BackgroundError", "ObservationError", "EvolutionError"):
115 commande = getattr(self,"set"+Concept)
116 commande(Matrix, ScalarSparseMatrix, DiagonalSparseMatrix,
117 Script, Stored, ObjectMatrix, Checked )
118 elif Concept == "AlgorithmParameters":
119 self.setAlgorithmParameters( Algorithm, Parameters, Script )
120 elif Concept == "Debug":
122 elif Concept == "NoDebug":
124 elif Concept == "Observer":
125 self.setObserver( Variable, Template, String, Script, Info, ObjectFunction, Scheduler )
126 elif Concept == "ObservationOperator":
127 self.setObservationOperator(
128 Matrix, OneFunction, ThreeFunctions, AppliedInXb,
129 Parameters, Script, Stored, AvoidRC, Checked )
130 elif Concept in ("EvolutionModel", "ControlModel"):
131 commande = getattr(self,"set"+Concept)
133 Matrix, OneFunction, ThreeFunctions,
134 Parameters, Script, Scheduler, Stored, AvoidRC, Checked )
137 raise ValueError("the variable named '%s' is not allowed."%str(Concept))
138 except Exception as e:
139 if isinstance(e, SyntaxError): msg = "at %s: %s"%(e.offset, e.text)
141 raise ValueError(("during settings, the following error occurs:\n"+\
142 "\n%s %s\n\nSee also the potential messages, "+\
143 "which can show the origin of the above error, "+\
144 "in the launching terminal.")%(str(e),msg))
146 # -----------------------------------------------------------
148 def setBackground(self,
155 "Definition d'un concept de calcul"
156 Concept = "Background"
157 self.__case.register("set"+Concept, dir(), locals())
158 self.__adaoObject[Concept] = State(
161 asPersistentVector = VectorSerie,
163 scheduledBy = Scheduler,
164 toBeChecked = Checked,
167 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
170 def setCheckingPoint(self,
177 "Definition d'un concept de calcul"
178 Concept = "CheckingPoint"
179 self.__case.register("set"+Concept, dir(), locals())
180 self.__adaoObject[Concept] = State(
183 asPersistentVector = VectorSerie,
185 scheduledBy = Scheduler,
186 toBeChecked = Checked,
189 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
192 def setControlInput(self,
199 "Definition d'un concept de calcul"
200 Concept = "ControlInput"
201 self.__case.register("set"+Concept, dir(), locals())
202 self.__adaoObject[Concept] = State(
205 asPersistentVector = VectorSerie,
207 scheduledBy = Scheduler,
208 toBeChecked = Checked,
211 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
214 def setObservation(self,
221 "Definition d'un concept de calcul"
222 Concept = "Observation"
223 self.__case.register("set"+Concept, dir(), locals())
224 self.__adaoObject[Concept] = State(
227 asPersistentVector = VectorSerie,
228 asScript = self.with_directory(Script),
229 scheduledBy = Scheduler,
230 toBeChecked = Checked,
233 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
236 def setBackgroundError(self,
238 ScalarSparseMatrix = None,
239 DiagonalSparseMatrix = None,
244 "Definition d'un concept de calcul"
245 Concept = "BackgroundError"
246 self.__case.register("set"+Concept, dir(), locals())
247 self.__adaoObject[Concept] = Covariance(
249 asCovariance = Matrix,
250 asEyeByScalar = ScalarSparseMatrix,
251 asEyeByVector = DiagonalSparseMatrix,
252 asCovObject = ObjectMatrix,
254 toBeChecked = Checked,
257 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
260 def setObservationError(self,
262 ScalarSparseMatrix = None,
263 DiagonalSparseMatrix = None,
268 "Definition d'un concept de calcul"
269 Concept = "ObservationError"
270 self.__case.register("set"+Concept, dir(), locals())
271 self.__adaoObject[Concept] = Covariance(
273 asCovariance = Matrix,
274 asEyeByScalar = ScalarSparseMatrix,
275 asEyeByVector = DiagonalSparseMatrix,
276 asCovObject = ObjectMatrix,
278 toBeChecked = Checked,
281 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
284 def setEvolutionError(self,
286 ScalarSparseMatrix = None,
287 DiagonalSparseMatrix = None,
292 "Definition d'un concept de calcul"
293 Concept = "EvolutionError"
294 self.__case.register("set"+Concept, dir(), locals())
295 self.__adaoObject[Concept] = Covariance(
297 asCovariance = Matrix,
298 asEyeByScalar = ScalarSparseMatrix,
299 asEyeByVector = DiagonalSparseMatrix,
300 asCovObject = ObjectMatrix,
302 toBeChecked = Checked,
305 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
308 def setObservationOperator(self,
311 ThreeFunctions = None,
318 "Definition d'un concept de calcul"
319 Concept = "ObservationOperator"
320 self.__case.register("set"+Concept, dir(), locals())
321 self.__adaoObject[Concept] = FullOperator(
324 asOneFunction = OneFunction,
325 asThreeFunctions = ThreeFunctions,
328 appliedInX = AppliedInXb,
331 toBeChecked = Checked,
334 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
337 def setEvolutionModel(self,
340 ThreeFunctions = None,
347 "Definition d'un concept de calcul"
348 Concept = "EvolutionModel"
349 self.__case.register("set"+Concept, dir(), locals())
350 self.__adaoObject[Concept] = FullOperator(
353 asOneFunction = OneFunction,
354 asThreeFunctions = ThreeFunctions,
359 scheduledBy = Scheduler,
360 toBeChecked = Checked,
363 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
366 def setControlModel(self,
369 ThreeFunctions = None,
376 "Definition d'un concept de calcul"
377 Concept = "ControlModel"
378 self.__case.register("set"+Concept, dir(), locals())
379 self.__adaoObject[Concept] = FullOperator(
382 asOneFunction = OneFunction,
383 asThreeFunctions = ThreeFunctions,
388 scheduledBy = Scheduler,
389 toBeChecked = Checked,
392 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
395 def setDebug(self, __level = 10):
396 "NOTSET=0 < DEBUG=10 < INFO=20 < WARNING=30 < ERROR=40 < CRITICAL=50"
397 self.__case.register("setDebug",dir(),locals())
398 log = logging.getLogger()
399 log.setLevel( __level )
400 self.__StoredInputs["Debug"] = __level
401 self.__StoredInputs["NoDebug"] = False
404 def setNoDebug(self):
405 "NOTSET=0 < DEBUG=10 < INFO=20 < WARNING=30 < ERROR=40 < CRITICAL=50"
406 self.__case.register("setNoDebug",dir(),locals())
407 log = logging.getLogger()
408 log.setLevel( logging.WARNING )
409 self.__StoredInputs["Debug"] = logging.WARNING
410 self.__StoredInputs["NoDebug"] = True
413 def setAlgorithmParameters(self,
417 "Definition d'un concept de calcul"
418 Concept = "AlgorithmParameters"
419 self.__case.register("set"+Concept, dir(), locals())
420 self.__adaoObject[Concept] = AlgorithmAndParameters(
422 asAlgorithm = Algorithm,
428 def updateAlgorithmParameters(self,
431 "Mise a jour d'un concept de calcul"
432 if "AlgorithmParameters" not in self.__adaoObject:
433 raise ValueError("No algorithm registred, ask for one before updating parameters")
434 self.__adaoObject["AlgorithmParameters"].updateParameters(
440 def setObserver(self,
446 ObjectFunction = None,
448 "Definition d'un concept de calcul"
450 self.__case.register("set"+Concept, dir(), locals())
451 self.__adaoObject[Concept].append( DataObserver(
453 onVariable = Variable,
454 asTemplate = Template,
457 asObsObject = ObjectFunction,
459 scheduledBy = Scheduler,
460 withAlgo = self.__adaoObject["AlgorithmParameters"]
464 def removeObserver(self,
466 ObjectFunction = None,
468 "Permet de retirer un observer à une ou des variable nommée"
469 if "AlgorithmParameters" not in self.__adaoObject:
470 raise ValueError("No algorithm registred, ask for one before removing observers")
472 # Vérification du nom de variable et typage
473 # -----------------------------------------
474 if isinstance(Variable, str):
475 VariableNames = (Variable,)
476 elif isinstance(Variable, list):
477 VariableNames = tuple(map( str, Variable ))
479 raise ValueError("The observer requires a name or a list of names of variables.")
481 # Association interne de l'observer à la variable
482 # -----------------------------------------------
483 for ename in VariableNames:
484 if ename not in self.__adaoObject["AlgorithmParameters"]:
485 raise ValueError("An observer requires to be removed on a variable named %s which does not exist."%ename)
487 return self.__adaoObject["AlgorithmParameters"].removeObserver( ename, ObjectFunction )
489 # -----------------------------------------------------------
491 def get(self, Concept=None, noDetails=True ):
492 "Recuperation d'une sortie du calcul"
493 if Concept is not None:
495 self.__case.register("get", dir(), locals(), Concept) # Break pickle in Python 2
498 if Concept in self.__StoredInputs:
499 return self.__StoredInputs[Concept]
501 elif self.__adaoObject["AlgorithmParameters"] is not None and Concept == "AlgorithmParameters":
502 return self.__adaoObject["AlgorithmParameters"].get()
504 elif self.__adaoObject["AlgorithmParameters"] is not None and Concept in self.__adaoObject["AlgorithmParameters"]:
505 return self.__adaoObject["AlgorithmParameters"].get( Concept )
507 elif Concept == "AlgorithmRequiredParameters" and self.__adaoObject["AlgorithmParameters"] is not None:
508 return self.__adaoObject["AlgorithmParameters"].getAlgorithmRequiredParameters(noDetails)
511 raise ValueError("The requested key \"%s\" does not exists as an input or a stored variable."%Concept)
514 allvariables.update( {"AlgorithmParameters":self.__adaoObject["AlgorithmParameters"].get()} )
515 # allvariables.update( self.__adaoObject["AlgorithmParameters"].get() )
516 allvariables.update( self.__StoredInputs )
517 allvariables.pop('Observer', None)
520 # -----------------------------------------------------------
522 def get_available_variables(self):
524 Renvoie les variables potentiellement utilisables pour l'étude,
525 initialement stockées comme données d'entrées ou dans les algorithmes,
526 identifiés par les chaînes de caractères. L'algorithme doit avoir été
527 préalablement choisi sinon la méthode renvoie "None".
529 if len(list(self.__adaoObject["AlgorithmParameters"].keys())) == 0 and \
530 len(list(self.__StoredInputs.keys())) == 0:
534 if len(list(self.__adaoObject["AlgorithmParameters"].keys())) > 0:
535 variables.extend(list(self.__adaoObject["AlgorithmParameters"].keys()))
536 if len(list(self.__StoredInputs.keys())) > 0:
537 variables.extend( list(self.__StoredInputs.keys()) )
538 variables.remove('Observer')
542 def get_available_algorithms(self):
544 Renvoie la liste des algorithmes potentiellement utilisables, identifiés
545 par les chaînes de caractères.
548 for directory in sys.path:
549 trypath = os.path.join(directory,"daAlgorithms")
550 if os.path.isdir(trypath):
551 for fname in os.listdir(trypath):
552 if os.path.isfile(os.path.join(trypath,fname)):
553 fc = open(os.path.join(trypath,fname)).read()
554 iselal = bool("class ElementaryAlgorithm" in fc)
555 root, ext = os.path.splitext(fname)
556 if iselal and ext == '.py' and root != '__init__':
562 def get_algorithms_main_path(self):
564 Renvoie le chemin pour le répertoire principal contenant les algorithmes
568 def add_algorithms_path(self, Path=None):
570 Ajoute au chemin de recherche des algorithmes un répertoire dans lequel
571 se trouve un sous-répertoire "daAlgorithms"
573 if not os.path.isdir(Path):
574 raise ValueError("The given "+Path+" argument must exist as a directory")
575 if not os.path.isdir(os.path.join(Path,"daAlgorithms")):
576 raise ValueError("The given \""+Path+"\" argument must contain a subdirectory named \"daAlgorithms\"")
577 if not os.path.isfile(os.path.join(Path,"daAlgorithms","__init__.py")):
578 raise ValueError("The given \""+Path+"/daAlgorithms\" path must contain a file named \"__init__.py\"")
579 sys.path.insert(0, os.path.abspath(Path))
580 sys.path = PlatformInfo.uniq( sys.path ) # Conserve en unique exemplaire chaque chemin
583 # -----------------------------------------------------------
585 def execute(self, Executor=None, SaveCaseInFile=None):
586 "Lancement du calcul"
587 self.__case.register("execute",dir(),locals(),None,True)
588 Operator.CM.clearCache()
590 if Executor == "YACS": self.__executeYACSScheme( SaveCaseInFile )
591 else: self.__executePythonScheme( SaveCaseInFile )
592 except Exception as e:
593 if isinstance(e, SyntaxError): msg = "at %s: %s"%(e.offset, e.text)
595 raise ValueError(("during execution, the following error occurs:\n"+\
596 "\n%s %s\n\nSee also the potential messages, "+\
597 "which can show the origin of the above error, "+\
598 "in the launching terminal.\n")%(str(e),msg))
601 def __executePythonScheme(self, FileName=None):
602 "Lancement du calcul"
603 self.__case.register("executePythonScheme", dir(), locals())
604 if FileName is not None:
605 self.dump( FileName, "TUI")
606 self.__adaoObject["AlgorithmParameters"].executePythonScheme( self.__adaoObject )
609 def __executeYACSScheme(self, FileName=None):
610 "Lancement du calcul"
611 self.__case.register("executeYACSScheme", dir(), locals())
612 self.dump( FileName, "YACS")
613 self.__adaoObject["AlgorithmParameters"].executeYACSScheme( FileName )
616 # -----------------------------------------------------------
618 def dump(self, FileName=None, Formater="TUI"):
619 "Restitution normalisée des commandes"
620 return self.__case.dump(FileName, Formater)
622 def load(self, FileName=None, Formater="TUI"):
623 "Chargement normalisé des commandes"
624 __commands = self.__case.load(FileName, Formater)
625 from numpy import array, matrix
626 for __command in __commands:
627 exec("self."+__command)
631 "Effacement du contenu du cas en cours"
632 self.__init__(self.__name)
634 # -----------------------------------------------------------
637 "Clarifie la visibilité des méthodes"
638 return ['set', 'get', 'execute', '__doc__', '__init__', '__module__']
640 def prepare_to_pickle(self):
641 "Retire les variables non pickelisables, avec recopie efficace"
642 if self.__adaoObject['AlgorithmParameters'] is not None:
643 for k in self.__adaoObject['AlgorithmParameters'].keys():
644 if k == "Algorithm": continue
645 if k in self.__StoredInputs:
646 raise ValueError("the key \"%s\s to be transfered for pickling will overwrite an existing one.")
647 if self.__adaoObject['AlgorithmParameters'].hasObserver( k ):
648 self.__adaoObject['AlgorithmParameters'].removeObserver( k, "", True )
649 self.__StoredInputs[k] = self.__adaoObject['AlgorithmParameters'].pop(k, None)
650 if sys.version_info[0] == 2:
651 del self.__adaoObject # Because it breaks pickle in Python 2. Not required for Python 3
652 del self.__case # Because it breaks pickle in Python 2. Not required for Python 3
655 # ==============================================================================
656 if __name__ == "__main__":
657 print('\n AUTODIAGNOSTIC \n')