Salome HOME
Minor documentation and code review corrections (25)
[modules/adao.git] / src / daComposant / daCore / Aidsm.py
index ce8912d9747b1004ebc42103516f41e02ba4d071..3aa0c20e835bb64958b4f7425609d10f8971fa9b 100644 (file)
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2008-2020 EDF R&D
+# Copyright (C) 2008-2022 EDF R&D
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
 # Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
 
 """
-    Normalized interface for ADAO scripting (generic API)
+    Normalized interface for ADAO scripting (generic API).
 """
 __author__ = "Jean-Philippe ARGAUD"
 __all__ = ["Aidsm"]
 
 import os
 import sys
+import inspect
 #
 from daCore.BasicObjects import State, Covariance, FullOperator, Operator
 from daCore.BasicObjects import AlgorithmAndParameters, DataObserver
 from daCore.BasicObjects import RegulationAndParameters, CaseLogger
+from daCore.BasicObjects import UserScript, ExternalParameters
 from daCore import PlatformInfo
 #
 from daCore import ExtendedLogging ; ExtendedLogging.ExtendedLogging() # A importer en premier
@@ -41,7 +43,8 @@ import logging
 class Aidsm(object):
     """ ADAO Internal Data Structure Model """
     def __init__(self, name = "", addViewers=None):
-        self.__name = str(name)
+        self.__name         = str(name)
+        self.__objname      = None
         self.__directory    = None
         self.__case = CaseLogger(self.__name, "case", addViewers)
         #
@@ -49,32 +52,37 @@ class Aidsm(object):
         self.__StoredInputs = {}
         self.__PostAnalysis = []
         #
-        self.__Concepts = [
         self.__Concepts = [ # Liste exhaustive
             "AlgorithmParameters",
             "Background",
+            "BackgroundError",
             "CheckingPoint",
             "ControlInput",
-            "Observation",
-            "BackgroundError",
-            "ObservationError",
+            "ControlModel",
+            "Debug",
+            "Directory",
             "EvolutionError",
-            "ObservationOperator",
             "EvolutionModel",
-            "ControlModel",
             "Name",
-            "Directory",
-            "Debug",
             "NoDebug",
-            "RegulationParameters",
+            "Observation",
+            "ObservationError",
+            "ObservationOperator",
             "Observer",
+            "RegulationParameters",
+            "SupplementaryParameters",
+            "UserPostAnalysis",
             ]
         #
         for ename in self.__Concepts:
             self.__adaoObject[ename] = None
         for ename in ("ObservationOperator", "EvolutionModel", "ControlModel"):
             self.__adaoObject[ename] = {}
-        for ename in ("Observer",):
+        for ename in ("BackgroundError", "ObservationError"):
+            self.__adaoObject[ename] = Covariance(ename, asEyeByScalar = 1.)
+        for ename in ("EvolutionError",):
+            self.__adaoObject[ename] = Covariance(ename, asEyeByScalar = 1.e-16)
+        for ename in ("Observer", "UserPostAnalysis"):
             self.__adaoObject[ename]   = []
             self.__StoredInputs[ename] = [] # Vide par defaut
         self.__StoredInputs["Name"] = self.__name
@@ -91,7 +99,6 @@ class Aidsm(object):
             Concept              = None, # Premier argument
             Algorithm            = None,
             AppliedInXb          = None,
-            AvoidRC              = True,
             Checked              = False,
             ColMajor             = False,
             ColNames             = None,
@@ -105,6 +112,7 @@ class Aidsm(object):
             ObjectMatrix         = None,
             OneFunction          = None,
             Parameters           = None,
+            PerformanceProfile   = None,
             ScalarSparseMatrix   = None,
             Scheduler            = None,
             Script               = None,
@@ -140,24 +148,28 @@ class Aidsm(object):
                 self.setNoDebug()
             elif Concept == "Observer":
                 self.setObserver( Variable, Template, String, Script, Info, ObjectFunction, Scheduler )
+            elif Concept == "UserPostAnalysis":
+                self.setUserPostAnalysis( Template, String, Script )
+            elif Concept == "SupplementaryParameters":
+                self.setSupplementaryParameters( Parameters, Script )
             elif Concept == "ObservationOperator":
                 self.setObservationOperator(
                     Matrix, OneFunction, ThreeFunctions, AppliedInXb,
                     Parameters, Script, ExtraArguments,
-                    Stored, AvoidRC, InputFunctionAsMulti, Checked )
+                    Stored, PerformanceProfile, InputFunctionAsMulti, Checked )
             elif Concept in ("EvolutionModel", "ControlModel"):
                 commande = getattr(self,"set"+Concept)
                 commande(
                     Matrix, OneFunction, ThreeFunctions,
                     Parameters, Script, Scheduler, ExtraArguments,
-                    Stored, AvoidRC, InputFunctionAsMulti, Checked )
+                    Stored, PerformanceProfile, InputFunctionAsMulti, Checked )
             else:
                 raise ValueError("the variable named '%s' is not allowed."%str(Concept))
         except Exception as e:
-            if isinstance(e, SyntaxError): msg = "at %s: %s"%(e.offset, e.text)
+            if isinstance(e, SyntaxError): msg = " at %s: %s"%(e.offset, e.text)
             else: msg = ""
             raise ValueError(("during settings, the following error occurs:\n"+\
-                              "\n%s %s\n\nSee also the potential messages, "+\
+                              "\n%s%s\n\nSee also the potential messages, "+\
                               "which can show the origin of the above error, "+\
                               "in the launching terminal.")%(str(e),msg))
 
@@ -356,7 +368,7 @@ class Aidsm(object):
             Script               = None,
             ExtraArguments       = None,
             Stored               = False,
-            AvoidRC              = True,
+            PerformanceProfile   = None,
             InputFunctionAsMulti = False,
             Checked              = False):
         "Definition d'un concept de calcul"
@@ -371,7 +383,7 @@ class Aidsm(object):
             asDict           = Parameters,
             appliedInX       = AppliedInXb,
             extraArguments   = ExtraArguments,
-            avoidRC          = AvoidRC,
+            performancePrf   = PerformanceProfile,
             inputAsMF        = InputFunctionAsMulti,
             scheduledBy      = None,
             toBeChecked      = Checked,
@@ -389,7 +401,7 @@ class Aidsm(object):
             Scheduler            = None,
             ExtraArguments       = None,
             Stored               = False,
-            AvoidRC              = True,
+            PerformanceProfile   = None,
             InputFunctionAsMulti = False,
             Checked              = False):
         "Definition d'un concept de calcul"
@@ -404,7 +416,7 @@ class Aidsm(object):
             asDict           = Parameters,
             appliedInX       = None,
             extraArguments   = ExtraArguments,
-            avoidRC          = AvoidRC,
+            performancePrf   = PerformanceProfile,
             inputAsMF        = InputFunctionAsMulti,
             scheduledBy      = Scheduler,
             toBeChecked      = Checked,
@@ -422,7 +434,7 @@ class Aidsm(object):
             Scheduler            = None,
             ExtraArguments       = None,
             Stored               = False,
-            AvoidRC              = True,
+            PerformanceProfile   = None,
             InputFunctionAsMulti = False,
             Checked              = False):
         "Definition d'un concept de calcul"
@@ -437,7 +449,7 @@ class Aidsm(object):
             asDict           = Parameters,
             appliedInX       = None,
             extraArguments   = ExtraArguments,
-            avoidRC          = AvoidRC,
+            performancePrf   = PerformanceProfile,
             inputAsMF        = InputFunctionAsMulti,
             scheduledBy      = Scheduler,
             toBeChecked      = Checked,
@@ -501,12 +513,14 @@ class Aidsm(object):
             Parameters = None,
             Script     = None):
         "Mise a jour d'un concept de calcul"
-        if "AlgorithmParameters" not in self.__adaoObject or self.__adaoObject["AlgorithmParameters"] is None:
+        Concept = "AlgorithmParameters"
+        if Concept not in self.__adaoObject or self.__adaoObject[Concept] is None:
             raise ValueError("\n\nNo algorithm registred, set one before updating parameters or executing\n")
-        self.__adaoObject["AlgorithmParameters"].updateParameters(
+        self.__adaoObject[Concept].updateParameters(
             asDict        = Parameters,
             asScript      = self.__with_directory(Script),
             )
+        # RaJ du register
         return 0
 
     def setRegulationParameters(self,
@@ -523,6 +537,30 @@ class Aidsm(object):
             asScript    = self.__with_directory(Script),
             )
         return 0
+
+    def setSupplementaryParameters(self,
+            Parameters = None,
+            Script     = None):
+        "Definition d'un concept de calcul"
+        Concept = "SupplementaryParameters"
+        self.__case.register("set"+Concept, dir(), locals())
+        self.__adaoObject[Concept] = ExternalParameters(
+            name     = Concept,
+            asDict   = Parameters,
+            asScript = self.__with_directory(Script),
+            )
+        return 0
+
+    def updateSupplementaryParameters(self,
+            Parameters = None,
+            Script     = None):
+        "Mise a jour d'un concept de calcul"
+        Concept = "SupplementaryParameters"
+        if Concept not in self.__adaoObject or self.__adaoObject[Concept] is None:
+            self.__adaoObject[Concept] = ExternalParameters(name = Concept)
+        self.__adaoObject[Concept].updateParameters(
+            asDict   = Parameters,
+            asScript = self.__with_directory(Script),
             )
         return 0
 
@@ -575,6 +613,21 @@ class Aidsm(object):
             else:
                 return self.__adaoObject["AlgorithmParameters"].removeObserver( ename, ObjectFunction )
 
+    def setUserPostAnalysis(self,
+            Template       = None,
+            String         = None,
+            Script         = None):
+        "Definition d'un concept de calcul"
+        Concept = "UserPostAnalysis"
+        self.__case.register("set"+Concept, dir(), locals())
+        self.__adaoObject[Concept].append( repr(UserScript(
+            name        = Concept,
+            asTemplate  = Template,
+            asString    = String,
+            asScript    = self.__with_directory(Script),
+            )))
+        return 0
+
     # -----------------------------------------------------------
 
     def get(self, Concept=None, noDetails=True ):
@@ -602,14 +655,23 @@ class Aidsm(object):
             elif Concept == "AlgorithmAttributes" and self.__adaoObject["AlgorithmParameters"] is not None:
                 return self.__adaoObject["AlgorithmParameters"].getAlgorithmAttributes()
                 #
+            elif self.__adaoObject["SupplementaryParameters"] is not None and Concept == "SupplementaryParameters":
+                return self.__adaoObject["SupplementaryParameters"].get()
+                #
+            elif self.__adaoObject["SupplementaryParameters"] is not None and Concept in self.__adaoObject["SupplementaryParameters"]:
+                return self.__adaoObject["SupplementaryParameters"].get( Concept )
+                #
             else:
                 raise ValueError("The requested key \"%s\" does not exists as an input or a stored variable."%Concept)
         else:
             allvariables = {}
             allvariables.update( {"AlgorithmParameters":self.__adaoObject["AlgorithmParameters"].get()} )
+            if self.__adaoObject["SupplementaryParameters"] is not None:
+                allvariables.update( {"SupplementaryParameters":self.__adaoObject["SupplementaryParameters"].get()} )
             # allvariables.update( self.__adaoObject["AlgorithmParameters"].get() )
             allvariables.update( self.__StoredInputs )
             allvariables.pop('Observer', None)
+            allvariables.pop('UserPostAnalysis', None)
             return allvariables
 
     # -----------------------------------------------------------
@@ -628,9 +690,13 @@ class Aidsm(object):
             variables = []
             if len(list(self.__adaoObject["AlgorithmParameters"].keys())) > 0:
                 variables.extend(list(self.__adaoObject["AlgorithmParameters"].keys()))
+            if self.__adaoObject["SupplementaryParameters"] is not None and \
+                len(list(self.__adaoObject["SupplementaryParameters"].keys())) > 0:
+                variables.extend(list(self.__adaoObject["SupplementaryParameters"].keys()))
             if len(list(self.__StoredInputs.keys())) > 0:
                 variables.extend( list(self.__StoredInputs.keys()) )
             variables.remove('Observer')
+            variables.remove('UserPostAnalysis')
             variables.sort()
             return variables
 
@@ -647,10 +713,10 @@ class Aidsm(object):
                     if os.path.isfile(os.path.join(trypath,fname)):
                         root, ext = os.path.splitext(fname)
                         if ext != ".py": continue
-                        fc = open(os.path.join(trypath,fname)).read()
-                        iselal = bool("class ElementaryAlgorithm" in fc)
-                        if iselal and ext == '.py' and root != '__init__':
-                            files.append(root)
+                        with open(os.path.join(trypath,fname)) as fc:
+                            iselal = bool("class ElementaryAlgorithm" in fc.read())
+                            if iselal and ext == '.py' and root != '__init__':
+                                files.append(root)
         files.sort()
         return files
 
@@ -700,6 +766,11 @@ class Aidsm(object):
         if FileName is not None:
             self.dump( FileName, "TUI")
         self.__adaoObject["AlgorithmParameters"].executePythonScheme( self.__adaoObject )
+        if "UserPostAnalysis" in self.__adaoObject and len(self.__adaoObject["UserPostAnalysis"])>0:
+            self.__objname = self.__retrieve_objname()
+            for __UpaOne in self.__adaoObject["UserPostAnalysis"]:
+                __UpaOne = eval(str(__UpaOne))
+                exec(__UpaOne, {}, {'self':self, 'ADD':self, 'case':self, 'adaopy':self, self.__objname:self})
         return 0
 
     def __executeYACSScheme(self, FileName=None):
@@ -721,8 +792,8 @@ class Aidsm(object):
         __commands = self.__case.load(FileName, Content, Object, Formater)
         from numpy import array, matrix
         for __command in __commands:
-            if __command.find("set")>-1 and __command.find("set_")<0:
-                exec("self."+__command)
+            if (__command.find("set")>-1 and __command.find("set_")<0) or 'UserPostAnalysis' in __command:
+                exec("self."+__command, {}, locals())
             else:
                 self.__PostAnalysis.append(__command)
         return self
@@ -753,10 +824,28 @@ class Aidsm(object):
             __fullpath = __filename
         return __fullpath
 
+    def __retrieve_objname(self):
+        "Ne pas utiliser dans le __init__, la variable appelante n'existe pas encore"
+        __names  = []
+        for level in reversed(inspect.stack()):
+            __names += [name for name, value in level.frame.f_locals.items() if value is self]
+        __names += [name for name, value in globals().items() if value is self]
+        while 'self' in __names: __names.remove('self') # Devrait toujours être trouvé, donc pas d'erreur
+        if len(__names) > 0:
+            self.__objname = __names[0]
+        else:
+            self.__objname = "ADD"
+        return self.__objname
+
     def __dir__(self):
         "Clarifie la visibilité des méthodes"
         return ['set', 'get', 'execute', 'dump', 'load', '__doc__', '__init__', '__module__']
 
+    def __str__(self):
+        "Représentation pour impression (mais pas repr)"
+        msg  = self.dump(None, "SimpleReportInPlainTxt")
+        return msg
+
     def prepare_to_pickle(self):
         "Retire les variables non pickelisables, avec recopie efficace"
         if self.__adaoObject['AlgorithmParameters'] is not None: