Salome HOME
Improvement and extension of EnKF algorithm (EnKS)
[modules/adao.git] / src / daComposant / daCore / Aidsm.py
index 8c8960a41be59bc1cbb4d035037a59fc018c778d..a981db1b3330e1a1e0e4af1020af85a952e71c4e 100644 (file)
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2008-2018 EDF R&D
+# Copyright (C) 2008-2021 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
@@ -31,7 +31,8 @@ import sys
 #
 from daCore.BasicObjects import State, Covariance, FullOperator, Operator
 from daCore.BasicObjects import AlgorithmAndParameters, DataObserver
-from daCore.BasicObjects import CaseLogger
+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
@@ -49,32 +50,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",
+            "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 ("Observer", "UserPostAnalysis"):
             self.__adaoObject[ename]   = []
-            self.__StoredInputs[ename] = []
+            self.__StoredInputs[ename] = [] # Vide par defaut
+        self.__StoredInputs["Name"] = self.__name
+        self.__StoredInputs["Directory"] = self.__directory
         #
         # Récupère le chemin du répertoire parent et l'ajoute au path
         # (Cela complète l'action de la classe PathManagement dans PlatformInfo,
@@ -89,8 +95,13 @@ class Aidsm(object):
             AppliedInXb          = None,
             AvoidRC              = True,
             Checked              = False,
+            ColMajor             = False,
+            ColNames             = None,
+            DataFile             = None,
             DiagonalSparseMatrix = None,
+            ExtraArguments       = None,
             Info                 = None,
+            InputFunctionAsMulti = False,
             Matrix               = None,
             ObjectFunction       = None,
             ObjectMatrix         = None,
@@ -112,13 +123,15 @@ class Aidsm(object):
         try:
             if   Concept in ("Background", "CheckingPoint", "ControlInput", "Observation"):
                 commande = getattr(self,"set"+Concept)
-                commande(Vector, VectorSerie, Script, Stored, Scheduler, Checked )
+                commande(Vector, VectorSerie, Script, DataFile, ColNames, ColMajor, Stored, Scheduler, Checked )
             elif Concept in ("BackgroundError", "ObservationError", "EvolutionError"):
                 commande = getattr(self,"set"+Concept)
                 commande(Matrix, ScalarSparseMatrix, DiagonalSparseMatrix,
                          Script, Stored, ObjectMatrix, Checked )
             elif Concept == "AlgorithmParameters":
                 self.setAlgorithmParameters( Algorithm, Parameters, Script )
+            elif Concept == "RegulationParameters":
+                self.setRegulationParameters( Algorithm, Parameters, Script )
             elif Concept == "Name":
                 self.setName(String)
             elif Concept == "Directory":
@@ -129,16 +142,21 @@ 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, Stored, AvoidRC, Checked )
+                    Parameters, Script, ExtraArguments,
+                    Stored, AvoidRC, InputFunctionAsMulti, Checked )
             elif Concept in ("EvolutionModel", "ControlModel"):
                 commande = getattr(self,"set"+Concept)
                 commande(
                     Matrix, OneFunction, ThreeFunctions,
-                    Parameters, Script, Scheduler, Stored, AvoidRC, Checked )
-
+                    Parameters, Script, Scheduler, ExtraArguments,
+                    Stored, AvoidRC, InputFunctionAsMulti, Checked )
             else:
                 raise ValueError("the variable named '%s' is not allowed."%str(Concept))
         except Exception as e:
@@ -155,6 +173,9 @@ class Aidsm(object):
             Vector         = None,
             VectorSerie    = None,
             Script         = None,
+            DataFile       = None,
+            ColNames       = None,
+            ColMajor       = False,
             Stored         = False,
             Scheduler      = None,
             Checked        = False):
@@ -165,7 +186,10 @@ class Aidsm(object):
             name               = Concept,
             asVector           = Vector,
             asPersistentVector = VectorSerie,
-            asScript           = self.with_directory(Script),
+            asScript           = self.__with_directory(Script),
+            asDataFile         = DataFile,
+            colNames           = ColNames,
+            colMajor           = ColMajor,
             scheduledBy        = Scheduler,
             toBeChecked        = Checked,
             )
@@ -177,6 +201,9 @@ class Aidsm(object):
             Vector         = None,
             VectorSerie    = None,
             Script         = None,
+            DataFile       = None,
+            ColNames       = None,
+            ColMajor       = False,
             Stored         = False,
             Scheduler      = None,
             Checked        = False):
@@ -187,7 +214,10 @@ class Aidsm(object):
             name               = Concept,
             asVector           = Vector,
             asPersistentVector = VectorSerie,
-            asScript           = self.with_directory(Script),
+            asScript           = self.__with_directory(Script),
+            asDataFile         = DataFile,
+            colNames           = ColNames,
+            colMajor           = ColMajor,
             scheduledBy        = Scheduler,
             toBeChecked        = Checked,
             )
@@ -199,6 +229,9 @@ class Aidsm(object):
             Vector         = None,
             VectorSerie    = None,
             Script         = None,
+            DataFile       = None,
+            ColNames       = None,
+            ColMajor       = False,
             Stored         = False,
             Scheduler      = None,
             Checked        = False):
@@ -209,7 +242,10 @@ class Aidsm(object):
             name               = Concept,
             asVector           = Vector,
             asPersistentVector = VectorSerie,
-            asScript           = self.with_directory(Script),
+            asScript           = self.__with_directory(Script),
+            asDataFile         = DataFile,
+            colNames           = ColNames,
+            colMajor           = ColMajor,
             scheduledBy        = Scheduler,
             toBeChecked        = Checked,
             )
@@ -221,6 +257,9 @@ class Aidsm(object):
             Vector         = None,
             VectorSerie    = None,
             Script         = None,
+            DataFile       = None,
+            ColNames       = None,
+            ColMajor       = False,
             Stored         = False,
             Scheduler      = None,
             Checked        = False):
@@ -231,7 +270,10 @@ class Aidsm(object):
             name               = Concept,
             asVector           = Vector,
             asPersistentVector = VectorSerie,
-            asScript           = self.with_directory(Script),
+            asScript           = self.__with_directory(Script),
+            asDataFile         = DataFile,
+            colNames           = ColNames,
+            colMajor           = ColMajor,
             scheduledBy        = Scheduler,
             toBeChecked        = Checked,
             )
@@ -256,7 +298,7 @@ class Aidsm(object):
             asEyeByScalar = ScalarSparseMatrix,
             asEyeByVector = DiagonalSparseMatrix,
             asCovObject   = ObjectMatrix,
-            asScript      = self.with_directory(Script),
+            asScript      = self.__with_directory(Script),
             toBeChecked   = Checked,
             )
         if Stored:
@@ -280,7 +322,7 @@ class Aidsm(object):
             asEyeByScalar = ScalarSparseMatrix,
             asEyeByVector = DiagonalSparseMatrix,
             asCovObject   = ObjectMatrix,
-            asScript      = self.with_directory(Script),
+            asScript      = self.__with_directory(Script),
             toBeChecked   = Checked,
             )
         if Stored:
@@ -304,7 +346,7 @@ class Aidsm(object):
             asEyeByScalar = ScalarSparseMatrix,
             asEyeByVector = DiagonalSparseMatrix,
             asCovObject   = ObjectMatrix,
-            asScript      = self.with_directory(Script),
+            asScript      = self.__with_directory(Script),
             toBeChecked   = Checked,
             )
         if Stored:
@@ -312,15 +354,17 @@ class Aidsm(object):
         return 0
 
     def setObservationOperator(self,
-            Matrix         = None,
-            OneFunction    = None,
-            ThreeFunctions = None,
-            AppliedInXb    = None,
-            Parameters     = None,
-            Script         = None,
-            Stored         = False,
-            AvoidRC        = True,
-            Checked        = False):
+            Matrix               = None,
+            OneFunction          = None,
+            ThreeFunctions       = None,
+            AppliedInXb          = None,
+            Parameters           = None,
+            Script               = None,
+            ExtraArguments       = None,
+            Stored               = False,
+            AvoidRC              = True,
+            InputFunctionAsMulti = False,
+            Checked              = False):
         "Definition d'un concept de calcul"
         Concept = "ObservationOperator"
         self.__case.register("set"+Concept, dir(), locals())
@@ -329,10 +373,12 @@ class Aidsm(object):
             asMatrix         = Matrix,
             asOneFunction    = OneFunction,
             asThreeFunctions = ThreeFunctions,
-            asScript         = self.with_directory(Script),
+            asScript         = self.__with_directory(Script),
             asDict           = Parameters,
             appliedInX       = AppliedInXb,
+            extraArguments   = ExtraArguments,
             avoidRC          = AvoidRC,
+            inputAsMF        = InputFunctionAsMulti,
             scheduledBy      = None,
             toBeChecked      = Checked,
             )
@@ -341,15 +387,17 @@ class Aidsm(object):
         return 0
 
     def setEvolutionModel(self,
-            Matrix         = None,
-            OneFunction    = None,
-            ThreeFunctions = None,
-            Parameters     = None,
-            Script         = None,
-            Stored         = False,
-            Scheduler      = None,
-            AvoidRC        = True,
-            Checked        = False):
+            Matrix               = None,
+            OneFunction          = None,
+            ThreeFunctions       = None,
+            Parameters           = None,
+            Script               = None,
+            Scheduler            = None,
+            ExtraArguments       = None,
+            Stored               = False,
+            AvoidRC              = True,
+            InputFunctionAsMulti = False,
+            Checked              = False):
         "Definition d'un concept de calcul"
         Concept = "EvolutionModel"
         self.__case.register("set"+Concept, dir(), locals())
@@ -358,10 +406,12 @@ class Aidsm(object):
             asMatrix         = Matrix,
             asOneFunction    = OneFunction,
             asThreeFunctions = ThreeFunctions,
-            asScript         = self.with_directory(Script),
+            asScript         = self.__with_directory(Script),
             asDict           = Parameters,
             appliedInX       = None,
+            extraArguments   = ExtraArguments,
             avoidRC          = AvoidRC,
+            inputAsMF        = InputFunctionAsMulti,
             scheduledBy      = Scheduler,
             toBeChecked      = Checked,
             )
@@ -370,15 +420,17 @@ class Aidsm(object):
         return 0
 
     def setControlModel(self,
-            Matrix         = None,
-            OneFunction    = None,
-            ThreeFunctions = None,
-            Parameters     = None,
-            Script         = None,
-            Stored         = False,
-            Scheduler      = None,
-            AvoidRC        = True,
-            Checked        = False):
+            Matrix               = None,
+            OneFunction          = None,
+            ThreeFunctions       = None,
+            Parameters           = None,
+            Script               = None,
+            Scheduler            = None,
+            ExtraArguments       = None,
+            Stored               = False,
+            AvoidRC              = True,
+            InputFunctionAsMulti = False,
+            Checked              = False):
         "Definition d'un concept de calcul"
         Concept = "ControlModel"
         self.__case.register("set"+Concept, dir(), locals())
@@ -387,10 +439,12 @@ class Aidsm(object):
             asMatrix         = Matrix,
             asOneFunction    = OneFunction,
             asThreeFunctions = ThreeFunctions,
-            asScript         = self.with_directory(Script),
+            asScript         = self.__with_directory(Script),
             asDict           = Parameters,
             appliedInX       = None,
+            extraArguments   = ExtraArguments,
             avoidRC          = AvoidRC,
+            inputAsMF        = InputFunctionAsMulti,
             scheduledBy      = Scheduler,
             toBeChecked      = Checked,
             )
@@ -445,7 +499,7 @@ class Aidsm(object):
             name          = Concept,
             asAlgorithm   = Algorithm,
             asDict        = Parameters,
-            asScript      = self.with_directory(Script),
+            asScript      = self.__with_directory(Script),
             )
         return 0
 
@@ -453,11 +507,54 @@ class Aidsm(object):
             Parameters = None,
             Script     = None):
         "Mise a jour d'un concept de calcul"
-        if "AlgorithmParameters" not in self.__adaoObject:
-            raise ValueError("No algorithm registred, ask for one before updating parameters")
-        self.__adaoObject["AlgorithmParameters"].updateParameters(
+        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[Concept].updateParameters(
             asDict        = Parameters,
-            asScript      = self.with_directory(Script),
+            asScript      = self.__with_directory(Script),
+            )
+        # RaJ du register
+        return 0
+
+    def setRegulationParameters(self,
+            Algorithm  = None,
+            Parameters = None,
+            Script     = None):
+        "Definition d'un concept de calcul"
+        Concept = "RegulationParameters"
+        self.__case.register("set"+Concept, dir(), locals())
+        self.__adaoObject[Concept] = RegulationAndParameters(
+            name        = Concept,
+            asAlgorithm = Algorithm,
+            asDict      = Parameters,
+            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
 
@@ -477,7 +574,7 @@ class Aidsm(object):
             onVariable  = Variable,
             asTemplate  = Template,
             asString    = String,
-            asScript    = self.with_directory(Script),
+            asScript    = self.__with_directory(Script),
             asObsObject = ObjectFunction,
             withInfo    = Info,
             scheduledBy = Scheduler,
@@ -510,6 +607,20 @@ 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),
+            )))
+
     # -----------------------------------------------------------
 
     def get(self, Concept=None, noDetails=True ):
@@ -531,14 +642,29 @@ class Aidsm(object):
             elif Concept == "AlgorithmRequiredParameters" and self.__adaoObject["AlgorithmParameters"] is not None:
                 return self.__adaoObject["AlgorithmParameters"].getAlgorithmRequiredParameters(noDetails)
                 #
+            elif Concept == "AlgorithmRequiredInputs" and self.__adaoObject["AlgorithmParameters"] is not None:
+                return self.__adaoObject["AlgorithmParameters"].getAlgorithmInputArguments()
+                #
+            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
 
     # -----------------------------------------------------------
@@ -557,9 +683,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
 
@@ -574,11 +704,12 @@ class Aidsm(object):
             if os.path.isdir(trypath):
                 for fname in os.listdir(trypath):
                     if os.path.isfile(os.path.join(trypath,fname)):
-                        fc = open(os.path.join(trypath,fname)).read()
-                        iselal = bool("class ElementaryAlgorithm" in fc)
                         root, ext = os.path.splitext(fname)
-                        if iselal and ext == '.py' and root != '__init__':
-                            files.append(root)
+                        if ext != ".py": continue
+                        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
 
@@ -605,10 +736,11 @@ class Aidsm(object):
 
     # -----------------------------------------------------------
 
-    def execute(self, Executor=None, SaveCaseInFile=None):
+    def execute(self, Executor=None, SaveCaseInFile=None, nextStep=False):
         "Lancement du calcul"
         self.__case.register("execute",dir(),locals(),None,True)
-        Operator.CM.clearCache()
+        self.updateAlgorithmParameters(Parameters={"nextStep":bool(nextStep)})
+        if not nextStep: Operator.CM.clearCache()
         try:
             if   Executor == "YACS": self.__executeYACSScheme( SaveCaseInFile )
             else:                    self.__executePythonScheme( SaveCaseInFile )
@@ -648,19 +780,30 @@ 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:
-                # logging.debug('Command loaded: %s'%(__command,))
+            if (__command.find("set")>-1 and __command.find("set_")<0) or 'UserPostAnalysis' in __command:
                 exec("self."+__command)
             else:
-                # logging.debug('Command not loaded: %s'%(__command,))
                 self.__PostAnalysis.append(__command)
         return self
 
+    def convert(self,
+        FileNameFrom=None, ContentFrom=None, ObjectFrom=None, FormaterFrom="TUI",
+        FileNameTo=None, FormaterTo="TUI",
+        ):
+        "Conversion normalisée des commandes"
+        return self.load(
+            FileName=FileNameFrom, Content=ContentFrom, Object=ObjectFrom, Formater=FormaterFrom
+            ).dump(
+            FileName=FileNameTo, Formater=FormaterTo
+            )
+
     def clear(self):
         "Effacement du contenu du cas en cours"
         self.__init__(self.__name)
 
-    def with_directory(self, __filename=None):
+    # -----------------------------------------------------------
+
+    def __with_directory(self, __filename=None):
         if os.path.exists(str(__filename)):
             __fullpath = __filename
         elif os.path.exists(os.path.join(str(self.__directory), str(__filename))):
@@ -669,11 +812,9 @@ class Aidsm(object):
             __fullpath = __filename
         return __fullpath
 
-    # -----------------------------------------------------------
-
     def __dir__(self):
         "Clarifie la visibilité des méthodes"
-        return ['set', 'get', 'execute', '__doc__', '__init__', '__module__']
+        return ['set', 'get', 'execute', 'dump', 'load', '__doc__', '__init__', '__module__']
 
     def prepare_to_pickle(self):
         "Retire les variables non pickelisables, avec recopie efficace"
@@ -681,15 +822,18 @@ class Aidsm(object):
             for k in self.__adaoObject['AlgorithmParameters'].keys():
                 if k == "Algorithm": continue
                 if k in self.__StoredInputs:
-                    raise ValueError("the key \"%s\s to be transfered for pickling will overwrite an existing one.")
+                    raise ValueError("The key \"%s\" to be transfered for pickling will overwrite an existing one."%(k,))
                 if self.__adaoObject['AlgorithmParameters'].hasObserver( k ):
                     self.__adaoObject['AlgorithmParameters'].removeObserver( k, "", True )
                 self.__StoredInputs[k] = self.__adaoObject['AlgorithmParameters'].pop(k, None)
         if sys.version_info[0] == 2:
             del self.__adaoObject # Because it breaks pickle in Python 2. Not required for Python 3
             del self.__case       # Because it breaks pickle in Python 2. Not required for Python 3
-        return 0
+        if sys.version_info.major < 3:
+            return 0
+        else:
+            return self.__StoredInputs
 
 # ==============================================================================
 if __name__ == "__main__":
-    print('\n AUTODIAGNOSTIC \n')
+    print('\n AUTODIAGNOSTIC\n')