1 # -*- coding: utf-8 -*-
3 # Copyright (C) 2008-2019 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 RegulationAndParameters, 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 = {}
50 self.__PostAnalysis = []
53 "AlgorithmParameters",
61 "ObservationOperator",
68 "RegulationParameters",
72 for ename in self.__Concepts:
73 self.__adaoObject[ename] = None
74 for ename in ("ObservationOperator", "EvolutionModel", "ControlModel"):
75 self.__adaoObject[ename] = {}
76 for ename in ("Observer",):
77 self.__adaoObject[ename] = []
78 self.__StoredInputs[ename] = []
80 # Récupère le chemin du répertoire parent et l'ajoute au path
81 # (Cela complète l'action de la classe PathManagement dans PlatformInfo,
82 # qui est activée dans Persistence)
83 self.__parent = os.path.abspath(os.path.join(os.path.dirname(__file__),".."))
84 sys.path.insert(0, self.__parent)
85 sys.path = PlatformInfo.uniq( sys.path ) # Conserve en unique exemplaire chaque chemin
88 Concept = None, # Premier argument
96 DiagonalSparseMatrix = None,
101 ObjectFunction = None,
105 ScalarSparseMatrix = None,
111 ThreeFunctions = None,
116 "Interface unique de definition de variables d'entrees par argument"
117 self.__case.register("set",dir(),locals(),None,True)
119 if Concept in ("Background", "CheckingPoint", "ControlInput", "Observation"):
120 commande = getattr(self,"set"+Concept)
121 commande(Vector, VectorSerie, Script, DataFile, ColNames, ColMajor, Stored, Scheduler, Checked )
122 elif Concept in ("BackgroundError", "ObservationError", "EvolutionError"):
123 commande = getattr(self,"set"+Concept)
124 commande(Matrix, ScalarSparseMatrix, DiagonalSparseMatrix,
125 Script, Stored, ObjectMatrix, Checked )
126 elif Concept == "AlgorithmParameters":
127 self.setAlgorithmParameters( Algorithm, Parameters, Script )
128 elif Concept == "RegulationParameters":
129 self.setRegulationParameters( Algorithm, Parameters, Script )
130 elif Concept == "Name":
132 elif Concept == "Directory":
133 self.setDirectory(String)
134 elif Concept == "Debug":
136 elif Concept == "NoDebug":
138 elif Concept == "Observer":
139 self.setObserver( Variable, Template, String, Script, Info, ObjectFunction, Scheduler )
140 elif Concept == "ObservationOperator":
141 self.setObservationOperator(
142 Matrix, OneFunction, ThreeFunctions, AppliedInXb,
143 Parameters, Script, ExtraArgs,
144 Stored, AvoidRC, InputAsMF, Checked )
145 elif Concept in ("EvolutionModel", "ControlModel"):
146 commande = getattr(self,"set"+Concept)
148 Matrix, OneFunction, ThreeFunctions,
149 Parameters, Script, Scheduler, ExtraArgs,
150 Stored, AvoidRC, InputAsMF, Checked )
152 raise ValueError("the variable named '%s' is not allowed."%str(Concept))
153 except Exception as e:
154 if isinstance(e, SyntaxError): msg = "at %s: %s"%(e.offset, e.text)
156 raise ValueError(("during settings, the following error occurs:\n"+\
157 "\n%s %s\n\nSee also the potential messages, "+\
158 "which can show the origin of the above error, "+\
159 "in the launching terminal.")%(str(e),msg))
161 # -----------------------------------------------------------
163 def setBackground(self,
173 "Definition d'un concept de calcul"
174 Concept = "Background"
175 self.__case.register("set"+Concept, dir(), locals())
176 self.__adaoObject[Concept] = State(
179 asPersistentVector = VectorSerie,
180 asScript = self.__with_directory(Script),
181 asDataFile = DataFile,
184 scheduledBy = Scheduler,
185 toBeChecked = Checked,
188 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
191 def setCheckingPoint(self,
201 "Definition d'un concept de calcul"
202 Concept = "CheckingPoint"
203 self.__case.register("set"+Concept, dir(), locals())
204 self.__adaoObject[Concept] = State(
207 asPersistentVector = VectorSerie,
208 asScript = self.__with_directory(Script),
209 asDataFile = DataFile,
212 scheduledBy = Scheduler,
213 toBeChecked = Checked,
216 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
219 def setControlInput(self,
229 "Definition d'un concept de calcul"
230 Concept = "ControlInput"
231 self.__case.register("set"+Concept, dir(), locals())
232 self.__adaoObject[Concept] = State(
235 asPersistentVector = VectorSerie,
236 asScript = self.__with_directory(Script),
237 asDataFile = DataFile,
240 scheduledBy = Scheduler,
241 toBeChecked = Checked,
244 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
247 def setObservation(self,
257 "Definition d'un concept de calcul"
258 Concept = "Observation"
259 self.__case.register("set"+Concept, dir(), locals())
260 self.__adaoObject[Concept] = State(
263 asPersistentVector = VectorSerie,
264 asScript = self.__with_directory(Script),
265 asDataFile = DataFile,
268 scheduledBy = Scheduler,
269 toBeChecked = Checked,
272 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
275 def setBackgroundError(self,
277 ScalarSparseMatrix = None,
278 DiagonalSparseMatrix = None,
283 "Definition d'un concept de calcul"
284 Concept = "BackgroundError"
285 self.__case.register("set"+Concept, dir(), locals())
286 self.__adaoObject[Concept] = Covariance(
288 asCovariance = Matrix,
289 asEyeByScalar = ScalarSparseMatrix,
290 asEyeByVector = DiagonalSparseMatrix,
291 asCovObject = ObjectMatrix,
292 asScript = self.__with_directory(Script),
293 toBeChecked = Checked,
296 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
299 def setObservationError(self,
301 ScalarSparseMatrix = None,
302 DiagonalSparseMatrix = None,
307 "Definition d'un concept de calcul"
308 Concept = "ObservationError"
309 self.__case.register("set"+Concept, dir(), locals())
310 self.__adaoObject[Concept] = Covariance(
312 asCovariance = Matrix,
313 asEyeByScalar = ScalarSparseMatrix,
314 asEyeByVector = DiagonalSparseMatrix,
315 asCovObject = ObjectMatrix,
316 asScript = self.__with_directory(Script),
317 toBeChecked = Checked,
320 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
323 def setEvolutionError(self,
325 ScalarSparseMatrix = None,
326 DiagonalSparseMatrix = None,
331 "Definition d'un concept de calcul"
332 Concept = "EvolutionError"
333 self.__case.register("set"+Concept, dir(), locals())
334 self.__adaoObject[Concept] = Covariance(
336 asCovariance = Matrix,
337 asEyeByScalar = ScalarSparseMatrix,
338 asEyeByVector = DiagonalSparseMatrix,
339 asCovObject = ObjectMatrix,
340 asScript = self.__with_directory(Script),
341 toBeChecked = Checked,
344 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
347 def setObservationOperator(self,
350 ThreeFunctions = None,
359 "Definition d'un concept de calcul"
360 Concept = "ObservationOperator"
361 self.__case.register("set"+Concept, dir(), locals())
362 self.__adaoObject[Concept] = FullOperator(
365 asOneFunction = OneFunction,
366 asThreeFunctions = ThreeFunctions,
367 asScript = self.__with_directory(Script),
369 appliedInX = AppliedInXb,
370 extraArguments = ExtraArgs,
372 inputAsMF = InputAsMF,
374 toBeChecked = Checked,
377 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
380 def setEvolutionModel(self,
383 ThreeFunctions = None,
392 "Definition d'un concept de calcul"
393 Concept = "EvolutionModel"
394 self.__case.register("set"+Concept, dir(), locals())
395 self.__adaoObject[Concept] = FullOperator(
398 asOneFunction = OneFunction,
399 asThreeFunctions = ThreeFunctions,
400 asScript = self.__with_directory(Script),
403 extraArguments = ExtraArgs,
405 inputAsMF = InputAsMF,
406 scheduledBy = Scheduler,
407 toBeChecked = Checked,
410 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
413 def setControlModel(self,
416 ThreeFunctions = None,
425 "Definition d'un concept de calcul"
426 Concept = "ControlModel"
427 self.__case.register("set"+Concept, dir(), locals())
428 self.__adaoObject[Concept] = FullOperator(
431 asOneFunction = OneFunction,
432 asThreeFunctions = ThreeFunctions,
433 asScript = self.__with_directory(Script),
436 extraArguments = ExtraArgs,
438 inputAsMF = InputAsMF,
439 scheduledBy = Scheduler,
440 toBeChecked = Checked,
443 self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
446 def setName(self, String=None):
447 "Definition d'un concept de calcul"
448 self.__case.register("setName",dir(),locals())
449 if String is not None:
450 self.__name = str(String)
453 self.__StoredInputs["Name"] = self.__name
455 def setDirectory(self, String=None):
456 "Definition d'un concept de calcul"
457 self.__case.register("setDirectory",dir(),locals())
458 if os.path.isdir(os.path.abspath(str(String))):
459 self.__directory = os.path.abspath(str(String))
461 self.__directory = None
462 self.__StoredInputs["Directory"] = self.__directory
464 def setDebug(self, __level = 10):
465 "NOTSET=0 < DEBUG=10 < INFO=20 < WARNING=30 < ERROR=40 < CRITICAL=50"
466 self.__case.register("setDebug",dir(),locals())
467 log = logging.getLogger()
468 log.setLevel( __level )
469 self.__StoredInputs["Debug"] = __level
470 self.__StoredInputs["NoDebug"] = False
473 def setNoDebug(self):
474 "NOTSET=0 < DEBUG=10 < INFO=20 < WARNING=30 < ERROR=40 < CRITICAL=50"
475 self.__case.register("setNoDebug",dir(),locals())
476 log = logging.getLogger()
477 log.setLevel( logging.WARNING )
478 self.__StoredInputs["Debug"] = logging.WARNING
479 self.__StoredInputs["NoDebug"] = True
482 def setAlgorithmParameters(self,
486 "Definition d'un concept de calcul"
487 Concept = "AlgorithmParameters"
488 self.__case.register("set"+Concept, dir(), locals())
489 self.__adaoObject[Concept] = AlgorithmAndParameters(
491 asAlgorithm = Algorithm,
493 asScript = self.__with_directory(Script),
497 def updateAlgorithmParameters(self,
500 "Mise a jour d'un concept de calcul"
501 if "AlgorithmParameters" not in self.__adaoObject:
502 raise ValueError("No algorithm registred, ask for one before updating parameters")
503 self.__adaoObject["AlgorithmParameters"].updateParameters(
505 asScript = self.__with_directory(Script),
509 def setRegulationParameters(self,
513 "Definition d'un concept de calcul"
514 Concept = "RegulationParameters"
515 self.__case.register("set"+Concept, dir(), locals())
516 self.__adaoObject[Concept] = RegulationAndParameters(
518 asAlgorithm = Algorithm,
520 asScript = self.__with_directory(Script),
524 def setObserver(self,
530 ObjectFunction = None,
532 "Definition d'un concept de calcul"
534 self.__case.register("set"+Concept, dir(), locals())
535 self.__adaoObject[Concept].append( DataObserver(
537 onVariable = Variable,
538 asTemplate = Template,
540 asScript = self.__with_directory(Script),
541 asObsObject = ObjectFunction,
543 scheduledBy = Scheduler,
544 withAlgo = self.__adaoObject["AlgorithmParameters"]
548 def removeObserver(self,
550 ObjectFunction = None,
552 "Permet de retirer un observer à une ou des variable nommée"
553 if "AlgorithmParameters" not in self.__adaoObject:
554 raise ValueError("No algorithm registred, ask for one before removing observers")
556 # Vérification du nom de variable et typage
557 # -----------------------------------------
558 if isinstance(Variable, str):
559 VariableNames = (Variable,)
560 elif isinstance(Variable, list):
561 VariableNames = tuple(map( str, Variable ))
563 raise ValueError("The observer requires a name or a list of names of variables.")
565 # Association interne de l'observer à la variable
566 # -----------------------------------------------
567 for ename in VariableNames:
568 if ename not in self.__adaoObject["AlgorithmParameters"]:
569 raise ValueError("An observer requires to be removed on a variable named %s which does not exist."%ename)
571 return self.__adaoObject["AlgorithmParameters"].removeObserver( ename, ObjectFunction )
573 # -----------------------------------------------------------
575 def get(self, Concept=None, noDetails=True ):
576 "Recuperation d'une sortie du calcul"
577 if Concept is not None:
579 self.__case.register("get", dir(), locals(), Concept) # Break pickle in Python 2
582 if Concept in self.__StoredInputs:
583 return self.__StoredInputs[Concept]
585 elif self.__adaoObject["AlgorithmParameters"] is not None and Concept == "AlgorithmParameters":
586 return self.__adaoObject["AlgorithmParameters"].get()
588 elif self.__adaoObject["AlgorithmParameters"] is not None and Concept in self.__adaoObject["AlgorithmParameters"]:
589 return self.__adaoObject["AlgorithmParameters"].get( Concept )
591 elif Concept == "AlgorithmRequiredParameters" and self.__adaoObject["AlgorithmParameters"] is not None:
592 return self.__adaoObject["AlgorithmParameters"].getAlgorithmRequiredParameters(noDetails)
595 raise ValueError("The requested key \"%s\" does not exists as an input or a stored variable."%Concept)
598 allvariables.update( {"AlgorithmParameters":self.__adaoObject["AlgorithmParameters"].get()} )
599 # allvariables.update( self.__adaoObject["AlgorithmParameters"].get() )
600 allvariables.update( self.__StoredInputs )
601 allvariables.pop('Observer', None)
604 # -----------------------------------------------------------
606 def get_available_variables(self):
608 Renvoie les variables potentiellement utilisables pour l'étude,
609 initialement stockées comme données d'entrées ou dans les algorithmes,
610 identifiés par les chaînes de caractères. L'algorithme doit avoir été
611 préalablement choisi sinon la méthode renvoie "None".
613 if len(list(self.__adaoObject["AlgorithmParameters"].keys())) == 0 and \
614 len(list(self.__StoredInputs.keys())) == 0:
618 if len(list(self.__adaoObject["AlgorithmParameters"].keys())) > 0:
619 variables.extend(list(self.__adaoObject["AlgorithmParameters"].keys()))
620 if len(list(self.__StoredInputs.keys())) > 0:
621 variables.extend( list(self.__StoredInputs.keys()) )
622 variables.remove('Observer')
626 def get_available_algorithms(self):
628 Renvoie la liste des algorithmes potentiellement utilisables, identifiés
629 par les chaînes de caractères.
632 for directory in sys.path:
633 trypath = os.path.join(directory,"daAlgorithms")
634 if os.path.isdir(trypath):
635 for fname in os.listdir(trypath):
636 if os.path.isfile(os.path.join(trypath,fname)):
637 fc = open(os.path.join(trypath,fname)).read()
638 iselal = bool("class ElementaryAlgorithm" in fc)
639 root, ext = os.path.splitext(fname)
640 if iselal and ext == '.py' and root != '__init__':
645 def get_algorithms_main_path(self):
647 Renvoie le chemin pour le répertoire principal contenant les algorithmes
651 def add_algorithms_path(self, Path=None):
653 Ajoute au chemin de recherche des algorithmes un répertoire dans lequel
654 se trouve un sous-répertoire "daAlgorithms"
656 if not os.path.isdir(Path):
657 raise ValueError("The given "+Path+" argument must exist as a directory")
658 if not os.path.isdir(os.path.join(Path,"daAlgorithms")):
659 raise ValueError("The given \""+Path+"\" argument must contain a subdirectory named \"daAlgorithms\"")
660 if not os.path.isfile(os.path.join(Path,"daAlgorithms","__init__.py")):
661 raise ValueError("The given \""+Path+"/daAlgorithms\" path must contain a file named \"__init__.py\"")
662 sys.path.insert(0, os.path.abspath(Path))
663 sys.path = PlatformInfo.uniq( sys.path ) # Conserve en unique exemplaire chaque chemin
666 # -----------------------------------------------------------
668 def execute(self, Executor=None, SaveCaseInFile=None):
669 "Lancement du calcul"
670 self.__case.register("execute",dir(),locals(),None,True)
671 Operator.CM.clearCache()
673 if Executor == "YACS": self.__executeYACSScheme( SaveCaseInFile )
674 else: self.__executePythonScheme( SaveCaseInFile )
675 except Exception as e:
676 if isinstance(e, SyntaxError): msg = "at %s: %s"%(e.offset, e.text)
678 raise ValueError(("during execution, the following error occurs:\n"+\
679 "\n%s %s\n\nSee also the potential messages, "+\
680 "which can show the origin of the above error, "+\
681 "in the launching terminal.\n")%(str(e),msg))
684 def __executePythonScheme(self, FileName=None):
685 "Lancement du calcul"
686 self.__case.register("executePythonScheme", dir(), locals())
687 if FileName is not None:
688 self.dump( FileName, "TUI")
689 self.__adaoObject["AlgorithmParameters"].executePythonScheme( self.__adaoObject )
692 def __executeYACSScheme(self, FileName=None):
693 "Lancement du calcul"
694 self.__case.register("executeYACSScheme", dir(), locals())
695 self.dump( FileName, "YACS")
696 self.__adaoObject["AlgorithmParameters"].executeYACSScheme( FileName )
699 # -----------------------------------------------------------
701 def dump(self, FileName=None, Formater="TUI"):
702 "Restitution normalisée des commandes"
703 __Upa = "\n".join(self.__PostAnalysis)
704 return self.__case.dump(FileName, Formater, __Upa)
706 def load(self, FileName=None, Content=None, Object=None, Formater="TUI"):
707 "Chargement normalisé des commandes"
708 __commands = self.__case.load(FileName, Content, Object, Formater)
709 from numpy import array, matrix
710 for __command in __commands:
711 if __command.find("set")>-1 and __command.find("set_")<0:
712 exec("self."+__command)
714 self.__PostAnalysis.append(__command)
718 FileNameFrom=None, ContentFrom=None, ObjectFrom=None, FormaterFrom="TUI",
719 FileNameTo=None, FormaterTo="TUI",
721 "Conversion normalisée des commandes"
723 FileName=FileNameFrom, Content=ContentFrom, Object=ObjectFrom, Formater=FormaterFrom
725 FileName=FileNameTo, Formater=FormaterTo
729 "Effacement du contenu du cas en cours"
730 self.__init__(self.__name)
732 # -----------------------------------------------------------
734 def __with_directory(self, __filename=None):
735 if os.path.exists(str(__filename)):
736 __fullpath = __filename
737 elif os.path.exists(os.path.join(str(self.__directory), str(__filename))):
738 __fullpath = os.path.join(self.__directory, str(__filename))
740 __fullpath = __filename
744 "Clarifie la visibilité des méthodes"
745 return ['set', 'get', 'execute', 'dump', 'load', '__doc__', '__init__', '__module__']
747 def prepare_to_pickle(self):
748 "Retire les variables non pickelisables, avec recopie efficace"
749 if self.__adaoObject['AlgorithmParameters'] is not None:
750 for k in self.__adaoObject['AlgorithmParameters'].keys():
751 if k == "Algorithm": continue
752 if k in self.__StoredInputs:
753 raise ValueError("the key \"%s\s to be transfered for pickling will overwrite an existing one.")
754 if self.__adaoObject['AlgorithmParameters'].hasObserver( k ):
755 self.__adaoObject['AlgorithmParameters'].removeObserver( k, "", True )
756 self.__StoredInputs[k] = self.__adaoObject['AlgorithmParameters'].pop(k, None)
757 if sys.version_info[0] == 2:
758 del self.__adaoObject # Because it breaks pickle in Python 2. Not required for Python 3
759 del self.__case # Because it breaks pickle in Python 2. Not required for Python 3
760 if sys.version_info.major < 3:
763 return self.__StoredInputs
765 # ==============================================================================
766 if __name__ == "__main__":
767 print('\n AUTODIAGNOSTIC \n')