+ logging.debug("%s %s : %s", self._name, self.__required_parameters[k]["message"], self._parameters[k])
+
+# ==============================================================================
+class AlgorithmAndParameters(object):
+ """
+ Classe générale d'interface d'action pour l'algorithme et ses paramètres
+ """
+ def __init__(self,
+ name = "GenericAlgorithm",
+ asAlgorithm = None,
+ asDict = None,
+ asScript = None,
+ ):
+ """
+ """
+ self.__name = str(name)
+ self.__A = None
+ self.__P = {}
+ #
+ self.__algorithm = {}
+ self.__algorithmFile = None
+ self.__algorithmName = None
+ #
+ self.updateParameters( asDict, asScript )
+ #
+ if asAlgorithm is None and asScript is not None:
+ __Algo = ImportFromScript(asScript).getvalue( "Algorithm" )
+ else:
+ __Algo = asAlgorithm
+ #
+ if __Algo is not None:
+ self.__A = str(__Algo)
+ self.__P.update( {"Algorithm":self.__A} )
+ #
+ self.__setAlgorithm( self.__A )
+
+ def updateParameters(self,
+ asDict = None,
+ asScript = None,
+ ):
+ "Mise a jour des parametres"
+ if asDict is None and asScript is not None:
+ __Dict = ImportFromScript(asScript).getvalue( self.__name, "Parameters" )
+ else:
+ __Dict = asDict
+ #
+ if __Dict is not None:
+ self.__P.update( dict(__Dict) )
+
+ def executePythonScheme(self, asDictAO = None):
+ "Permet de lancer le calcul d'assimilation"
+ Operator.CM.clearCache()
+ #
+ if not isinstance(asDictAO, dict):
+ raise ValueError("The objects for algorithm calculation have to be given together as a dictionnary, and they are not")
+ if hasattr(asDictAO["Background"],"getO"): self.__Xb = asDictAO["Background"].getO()
+ elif hasattr(asDictAO["CheckingPoint"],"getO"): self.__Xb = asDictAO["CheckingPoint"].getO()
+ else: self.__Xb = None
+ if hasattr(asDictAO["Observation"],"getO"): self.__Y = asDictAO["Observation"].getO()
+ else: self.__Y = asDictAO["Observation"]
+ if hasattr(asDictAO["ControlInput"],"getO"): self.__U = asDictAO["ControlInput"].getO()
+ else: self.__U = asDictAO["ControlInput"]
+ if hasattr(asDictAO["ObservationOperator"],"getO"): self.__HO = asDictAO["ObservationOperator"].getO()
+ else: self.__HO = asDictAO["ObservationOperator"]
+ if hasattr(asDictAO["EvolutionModel"],"getO"): self.__EM = asDictAO["EvolutionModel"].getO()
+ else: self.__EM = asDictAO["EvolutionModel"]
+ if hasattr(asDictAO["ControlModel"],"getO"): self.__CM = asDictAO["ControlModel"].getO()
+ else: self.__CM = asDictAO["ControlModel"]
+ self.__B = asDictAO["BackgroundError"]
+ self.__R = asDictAO["ObservationError"]
+ self.__Q = asDictAO["EvolutionError"]
+ #
+ self.__shape_validate()
+ #
+ self.__algorithm.run(
+ Xb = self.__Xb,
+ Y = self.__Y,
+ U = self.__U,
+ HO = self.__HO,
+ EM = self.__EM,
+ CM = self.__CM,
+ R = self.__R,
+ B = self.__B,
+ Q = self.__Q,
+ Parameters = self.__P,
+ )
+ return 0
+
+ def executeYACSScheme(self, FileName=None):
+ "Permet de lancer le calcul d'assimilation"
+ if FileName is None or not os.path.exists(FileName):
+ raise ValueError("a YACS file name has to be given for YACS execution.\n")
+ else:
+ __file = os.path.abspath(FileName)
+ logging.debug("The YACS file name is \"%s\"."%__file)
+ if not PlatformInfo.has_salome or \
+ not PlatformInfo.has_yacs or \
+ not PlatformInfo.has_adao:
+ raise ImportError("\n\n"+\
+ "Unable to get SALOME, YACS or ADAO environnement variables.\n"+\
+ "Please load the right environnement before trying to use it.\n")
+ #
+ import pilot
+ import SALOMERuntime
+ import loader
+ SALOMERuntime.RuntimeSALOME_setRuntime()
+
+ r = pilot.getRuntime()
+ xmlLoader = loader.YACSLoader()
+ xmlLoader.registerProcCataLoader()
+ try:
+ catalogAd = r.loadCatalog("proc", __file)
+ r.addCatalog(catalogAd)
+ except:
+ pass
+
+ try:
+ p = xmlLoader.load(__file)
+ except IOError as ex:
+ print("The YACS XML schema file can not be loaded: %s"%(ex,))
+
+ logger = p.getLogger("parser")
+ if not logger.isEmpty():
+ print("The imported YACS XML schema has errors on parsing:")
+ print(logger.getStr())
+
+ if not p.isValid():
+ print("The YACS XML schema is not valid and will not be executed:")
+ print(p.getErrorReport())
+
+ info=pilot.LinkInfo(pilot.LinkInfo.ALL_DONT_STOP)
+ p.checkConsistency(info)
+ if info.areWarningsOrErrors():
+ print("The YACS XML schema is not coherent and will not be executed:")
+ print(info.getGlobalRepr())
+
+ e = pilot.ExecutorSwig()
+ e.RunW(p)
+ if p.getEffectiveState() != pilot.DONE:
+ print(p.getErrorReport())
+ #
+ return 0
+
+ def get(self, key = None):
+ "Vérifie l'existence d'une clé de variable ou de paramètres"
+ if key in self.__algorithm:
+ return self.__algorithm.get( key )
+ elif key in self.__P:
+ return self.__P[key]
+ else:
+ return self.__P
+
+ def pop(self, k, d):
+ "Necessaire pour le pickling"
+ return self.__algorithm.pop(k, d)
+
+ def getAlgorithmRequiredParameters(self, noDetails=True):
+ "Renvoie la liste des paramètres requis selon l'algorithme"
+ return self.__algorithm.getRequiredParameters(noDetails)
+
+ def setObserver(self, __V, __O, __I, __S):
+ if self.__algorithm is None \
+ or isinstance(self.__algorithm, dict) \
+ or not hasattr(self.__algorithm,"StoredVariables"):
+ raise ValueError("No observer can be build before choosing an algorithm.")
+ if __V not in self.__algorithm:
+ raise ValueError("An observer requires to be set on a variable named %s which does not exist."%__V)
+ else:
+ self.__algorithm.StoredVariables[ __V ].setDataObserver(
+ Scheduler = __S,
+ HookFunction = __O,
+ HookParameters = __I,
+ )
+
+ def removeObserver(self, __V, __O, __A = False):
+ if self.__algorithm is None \
+ or isinstance(self.__algorithm, dict) \
+ or not hasattr(self.__algorithm,"StoredVariables"):
+ raise ValueError("No observer can be removed before choosing an algorithm.")
+ if __V not in self.__algorithm:
+ raise ValueError("An observer requires to be removed on a variable named %s which does not exist."%__V)
+ else:
+ return self.__algorithm.StoredVariables[ __V ].removeDataObserver(
+ HookFunction = __O,
+ AllObservers = __A,
+ )
+
+ def hasObserver(self, __V):
+ if self.__algorithm is None \
+ or isinstance(self.__algorithm, dict) \
+ or not hasattr(self.__algorithm,"StoredVariables"):
+ return False
+ if __V not in self.__algorithm:
+ return False
+ return self.__algorithm.StoredVariables[ __V ].hasDataObserver()
+
+ def keys(self):
+ return list(self.__algorithm.keys()) + list(self.__P.keys())
+
+ def __contains__(self, key=None):
+ "D.__contains__(k) -> True if D has a key k, else False"
+ return key in self.__algorithm or key in self.__P
+
+ def __repr__(self):
+ "x.__repr__() <==> repr(x)"
+ return repr(self.__A)+", "+repr(self.__P)
+
+ def __str__(self):
+ "x.__str__() <==> str(x)"
+ return str(self.__A)+", "+str(self.__P)
+
+ def __setAlgorithm(self, choice = None ):
+ """
+ Permet de sélectionner l'algorithme à utiliser pour mener à bien l'étude
+ d'assimilation. L'argument est un champ caractère se rapportant au nom
+ d'un algorithme réalisant l'opération sur les arguments fixes.
+ """
+ if choice is None:
+ raise ValueError("Error: algorithm choice has to be given")
+ if self.__algorithmName is not None:
+ raise ValueError("Error: algorithm choice has already been done as \"%s\", it can't be changed."%self.__algorithmName)
+ daDirectory = "daAlgorithms"
+ #
+ # Recherche explicitement le fichier complet
+ # ------------------------------------------
+ module_path = None
+ for directory in sys.path:
+ if os.path.isfile(os.path.join(directory, daDirectory, str(choice)+'.py')):
+ module_path = os.path.abspath(os.path.join(directory, daDirectory))
+ if module_path is None:
+ raise ImportError("No algorithm module named \"%s\" has been found in the search path.\n The search path is %s"%(choice, sys.path))
+ #
+ # Importe le fichier complet comme un module
+ # ------------------------------------------
+ try:
+ sys_path_tmp = sys.path ; sys.path.insert(0,module_path)
+ self.__algorithmFile = __import__(str(choice), globals(), locals(), [])
+ if not hasattr(self.__algorithmFile, "ElementaryAlgorithm"):
+ raise ImportError("this module does not define a valid elementary algorithm.")
+ self.__algorithmName = str(choice)
+ sys.path = sys_path_tmp ; del sys_path_tmp
+ except ImportError as e:
+ raise ImportError("The module named \"%s\" was found, but is incorrect at the import stage.\n The import error message is: %s"%(choice,e))
+ #
+ # Instancie un objet du type élémentaire du fichier
+ # -------------------------------------------------
+ self.__algorithm = self.__algorithmFile.ElementaryAlgorithm()
+ return 0
+
+ def __shape_validate(self):
+ """
+ Validation de la correspondance correcte des tailles des variables et
+ des matrices s'il y en a.
+ """
+ if self.__Xb is None: __Xb_shape = (0,)
+ elif hasattr(self.__Xb,"size"): __Xb_shape = (self.__Xb.size,)
+ elif hasattr(self.__Xb,"shape"):
+ if isinstance(self.__Xb.shape, tuple): __Xb_shape = self.__Xb.shape
+ else: __Xb_shape = self.__Xb.shape()
+ else: raise TypeError("The background (Xb) has no attribute of shape: problem !")
+ #
+ if self.__Y is None: __Y_shape = (0,)
+ elif hasattr(self.__Y,"size"): __Y_shape = (self.__Y.size,)
+ elif hasattr(self.__Y,"shape"):
+ if isinstance(self.__Y.shape, tuple): __Y_shape = self.__Y.shape
+ else: __Y_shape = self.__Y.shape()
+ else: raise TypeError("The observation (Y) has no attribute of shape: problem !")
+ #
+ if self.__U is None: __U_shape = (0,)
+ elif hasattr(self.__U,"size"): __U_shape = (self.__U.size,)
+ elif hasattr(self.__U,"shape"):
+ if isinstance(self.__U.shape, tuple): __U_shape = self.__U.shape
+ else: __U_shape = self.__U.shape()
+ else: raise TypeError("The control (U) has no attribute of shape: problem !")
+ #
+ if self.__B is None: __B_shape = (0,0)
+ elif hasattr(self.__B,"shape"):
+ if isinstance(self.__B.shape, tuple): __B_shape = self.__B.shape
+ else: __B_shape = self.__B.shape()
+ else: raise TypeError("The a priori errors covariance matrix (B) has no attribute of shape: problem !")
+ #
+ if self.__R is None: __R_shape = (0,0)
+ elif hasattr(self.__R,"shape"):
+ if isinstance(self.__R.shape, tuple): __R_shape = self.__R.shape
+ else: __R_shape = self.__R.shape()
+ else: raise TypeError("The observation errors covariance matrix (R) has no attribute of shape: problem !")
+ #
+ if self.__Q is None: __Q_shape = (0,0)
+ elif hasattr(self.__Q,"shape"):
+ if isinstance(self.__Q.shape, tuple): __Q_shape = self.__Q.shape
+ else: __Q_shape = self.__Q.shape()
+ else: raise TypeError("The evolution errors covariance matrix (Q) has no attribute of shape: problem !")
+ #
+ if len(self.__HO) == 0: __HO_shape = (0,0)
+ elif isinstance(self.__HO, dict): __HO_shape = (0,0)
+ elif hasattr(self.__HO["Direct"],"shape"):
+ if isinstance(self.__HO["Direct"].shape, tuple): __HO_shape = self.__HO["Direct"].shape
+ else: __HO_shape = self.__HO["Direct"].shape()
+ else: raise TypeError("The observation operator (H) has no attribute of shape: problem !")
+ #
+ if len(self.__EM) == 0: __EM_shape = (0,0)
+ elif isinstance(self.__EM, dict): __EM_shape = (0,0)
+ elif hasattr(self.__EM["Direct"],"shape"):
+ if isinstance(self.__EM["Direct"].shape, tuple): __EM_shape = self.__EM["Direct"].shape
+ else: __EM_shape = self.__EM["Direct"].shape()
+ else: raise TypeError("The evolution model (EM) has no attribute of shape: problem !")
+ #
+ if len(self.__CM) == 0: __CM_shape = (0,0)
+ elif isinstance(self.__CM, dict): __CM_shape = (0,0)
+ elif hasattr(self.__CM["Direct"],"shape"):
+ if isinstance(self.__CM["Direct"].shape, tuple): __CM_shape = self.__CM["Direct"].shape
+ else: __CM_shape = self.__CM["Direct"].shape()
+ else: raise TypeError("The control model (CM) has no attribute of shape: problem !")
+ #
+ # Vérification des conditions
+ # ---------------------------
+ if not( len(__Xb_shape) == 1 or min(__Xb_shape) == 1 ):
+ raise ValueError("Shape characteristic of background (Xb) is incorrect: \"%s\"."%(__Xb_shape,))
+ if not( len(__Y_shape) == 1 or min(__Y_shape) == 1 ):
+ raise ValueError("Shape characteristic of observation (Y) is incorrect: \"%s\"."%(__Y_shape,))
+ #
+ if not( min(__B_shape) == max(__B_shape) ):
+ raise ValueError("Shape characteristic of a priori errors covariance matrix (B) is incorrect: \"%s\"."%(__B_shape,))
+ if not( min(__R_shape) == max(__R_shape) ):
+ raise ValueError("Shape characteristic of observation errors covariance matrix (R) is incorrect: \"%s\"."%(__R_shape,))
+ if not( min(__Q_shape) == max(__Q_shape) ):
+ raise ValueError("Shape characteristic of evolution errors covariance matrix (Q) is incorrect: \"%s\"."%(__Q_shape,))
+ if not( min(__EM_shape) == max(__EM_shape) ):
+ raise ValueError("Shape characteristic of evolution operator (EM) is incorrect: \"%s\"."%(__EM_shape,))
+ #
+ if len(self.__HO) > 0 and not isinstance(self.__HO, dict) and not( __HO_shape[1] == max(__Xb_shape) ):
+ raise ValueError("Shape characteristic of observation operator (H) \"%s\" and state (X) \"%s\" are incompatible."%(__HO_shape,__Xb_shape))
+ if len(self.__HO) > 0 and not isinstance(self.__HO, dict) and not( __HO_shape[0] == max(__Y_shape) ):
+ raise ValueError("Shape characteristic of observation operator (H) \"%s\" and observation (Y) \"%s\" are incompatible."%(__HO_shape,__Y_shape))
+ if len(self.__HO) > 0 and not isinstance(self.__HO, dict) and len(self.__B) > 0 and not( __HO_shape[1] == __B_shape[0] ):
+ raise ValueError("Shape characteristic of observation operator (H) \"%s\" and a priori errors covariance matrix (B) \"%s\" are incompatible."%(__HO_shape,__B_shape))
+ if len(self.__HO) > 0 and not isinstance(self.__HO, dict) and len(self.__R) > 0 and not( __HO_shape[0] == __R_shape[1] ):
+ raise ValueError("Shape characteristic of observation operator (H) \"%s\" and observation errors covariance matrix (R) \"%s\" are incompatible."%(__HO_shape,__R_shape))
+ #
+ if self.__B is not None and len(self.__B) > 0 and not( __B_shape[1] == max(__Xb_shape) ):
+ if self.__algorithmName in ["EnsembleBlue",]:
+ asPersistentVector = self.__Xb.reshape((-1,min(__B_shape)))
+ self.__Xb = Persistence.OneVector("Background", basetype=numpy.matrix)
+ for member in asPersistentVector:
+ self.__Xb.store( numpy.matrix( numpy.ravel(member), numpy.float ).T )
+ __Xb_shape = min(__B_shape)
+ else:
+ raise ValueError("Shape characteristic of a priori errors covariance matrix (B) \"%s\" and background (Xb) \"%s\" are incompatible."%(__B_shape,__Xb_shape))
+ #
+ if self.__R is not None and len(self.__R) > 0 and not( __R_shape[1] == max(__Y_shape) ):
+ raise ValueError("Shape characteristic of observation errors covariance matrix (R) \"%s\" and observation (Y) \"%s\" are incompatible."%(__R_shape,__Y_shape))
+ #
+ if self.__EM is not None and len(self.__EM) > 0 and not isinstance(self.__EM, dict) and not( __EM_shape[1] == max(__Xb_shape) ):
+ raise ValueError("Shape characteristic of evolution model (EM) \"%s\" and state (X) \"%s\" are incompatible."%(__EM_shape,__Xb_shape))
+ #
+ if self.__CM is not None and len(self.__CM) > 0 and not isinstance(self.__CM, dict) and not( __CM_shape[1] == max(__U_shape) ):
+ raise ValueError("Shape characteristic of control model (CM) \"%s\" and control (U) \"%s\" are incompatible."%(__CM_shape,__U_shape))
+ #
+ if ("Bounds" in self.__P) \
+ and (isinstance(self.__P["Bounds"], list) or isinstance(self.__P["Bounds"], tuple)) \
+ and (len(self.__P["Bounds"]) != max(__Xb_shape)):
+ raise ValueError("The number \"%s\" of bound pairs for the state (X) components is different of the size \"%s\" of the state itself." \
+ %(len(self.__P["Bounds"]),max(__Xb_shape)))
+ #
+ return 1