-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
name = "Minimizer",
default = "LBFGSB",
typecast = str,
- message = "Minimiseur utilisé",
+ message = "Minimiseur utilisé",
listval = ["LBFGSB","TNC", "CG", "NCG", "BFGS"],
)
self.defineRequiredParameter(
name = "CostDecrementTolerance",
default = 1.e-7,
typecast = float,
- message = "Diminution relative minimale du cout lors de l'arrêt",
+ message = "Diminution relative minimale du cout lors de l'arrêt",
)
self.defineRequiredParameter(
name = "ProjectedGradientTolerance",
default = -1,
typecast = float,
- message = "Maximum des composantes du gradient projeté lors de l'arrêt",
+ message = "Maximum des composantes du gradient projeté lors de l'arrêt",
minval = -1,
)
self.defineRequiredParameter(
name = "GradientNormTolerance",
default = 1.e-05,
typecast = float,
- message = "Maximum des composantes du gradient lors de l'arrêt",
+ message = "Maximum des composantes du gradient lors de l'arrêt",
)
self.defineRequiredParameter(
name = "StoreInternalVariables",
default = False,
typecast = bool,
- message = "Stockage des variables internes ou intermédiaires du calcul",
+ message = "Stockage des variables internes ou intermédiaires du calcul",
)
self.defineRequiredParameter(
name = "StoreSupplementaryCalculations",
default = [],
typecast = tuple,
- message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
+ message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
listval = ["APosterioriCorrelations", "APosterioriCovariance", "APosterioriStandardDeviations", "APosterioriVariances", "BMA", "OMA", "OMB", "CostFunctionJ", "CostFunctionJb", "CostFunctionJo", "CurrentState", "CurrentOptimum", "IndexOfOptimum", "Innovation", "InnovationAtCurrentState", "CostFunctionJAtCurrentOptimum", "SigmaObs2", "MahalanobisConsistency", "SimulationQuantiles", "SimulatedObservationAtBackground", "SimulatedObservationAtCurrentState", "SimulatedObservationAtOptimum", "SimulatedObservationAtCurrentOptimum"]
)
self.defineRequiredParameter(
self.defineRequiredParameter(
name = "SetSeed",
typecast = numpy.random.seed,
- message = "Graine fixée pour le générateur aléatoire",
+ message = "Graine fixée pour le générateur aléatoire",
)
self.defineRequiredParameter(
name = "NumberOfSamplesForQuantiles",
default = 100,
typecast = int,
- message = "Nombre d'échantillons simulés pour le calcul des quantiles",
+ message = "Nombre d'échantillons simulés pour le calcul des quantiles",
minval = 1,
)
self.defineRequiredParameter(
if "Minimizer" in self._parameters and self._parameters["Minimizer"] == "TNC":
self.setParameterValue("StoreInternalVariables",True)
#
- # Opérateurs
+ # Opérateurs
# ----------
Hm = HO["Direct"].appliedTo
Ha = HO["Adjoint"].appliedInXTo
#
- # Utilisation éventuelle d'un vecteur H(Xb) précalculé
+ # Utilisation éventuelle d'un vecteur H(Xb) précalculé
# ----------------------------------------------------
- if HO["AppliedToX"] is not None and "HXb" in HO["AppliedToX"]:
- HXb = Hm( Xb, HO["AppliedToX"]["HXb"])
+ if HO["AppliedInX"] is not None and "HXb" in HO["AppliedInX"]:
+ HXb = Hm( Xb, HO["AppliedInX"]["HXb"])
else:
HXb = Hm( Xb )
HXb = numpy.asmatrix(numpy.ravel( HXb )).T
if max(Y.shape) != max(HXb.shape):
raise ValueError("The shapes %s of observations Y and %s of observed calculation H(X) are different, they have to be identical."%(Y.shape,HXb.shape))
#
- # Précalcul des inversions de B et R
+ # Précalcul des inversions de B et R
# ----------------------------------
BI = B.getI()
RI = R.getI()
#
- # Définition de la fonction-coût
+ # Définition de la fonction-coût
# ------------------------------
def CostFunction(x):
_X = numpy.asmatrix(numpy.ravel( x )).T
GradJ = numpy.asmatrix( numpy.ravel( GradJb ) + numpy.ravel( GradJo ) ).T
return GradJ.A1
#
- # Point de démarrage de l'optimisation : Xini = Xb
+ # Point de démarrage de l'optimisation : Xini = Xb
# ------------------------------------
Xini = numpy.ravel(Xb)
#
raise ValueError("The %s a posteriori covariance matrix A is not symmetric positive-definite. Please check your a priori covariances and your observation operator."%(self._name,))
self.StoredVariables["APosterioriCovariance"].store( A )
#
- # Calculs et/ou stockages supplémentaires
+ # Calculs et/ou stockages supplémentaires
# ---------------------------------------
if "Innovation" in self._parameters["StoreSupplementaryCalculations"] or \
"SigmaObs2" in self._parameters["StoreSupplementaryCalculations"] or \
if "MahalanobisConsistency" in self._parameters["StoreSupplementaryCalculations"]:
self.StoredVariables["MahalanobisConsistency"].store( float( 2.*MinJ/d.size ) )
if "SimulationQuantiles" in self._parameters["StoreSupplementaryCalculations"]:
- Qtls = map(float, self._parameters["Quantiles"])
nech = self._parameters["NumberOfSamplesForQuantiles"]
HXa = numpy.matrix(numpy.ravel( HXa )).T
YfQ = None
YfQ = numpy.hstack((YfQ,Yr))
YfQ.sort(axis=-1)
YQ = None
- for quantile in Qtls:
- if not (0. <= quantile <= 1.): continue
- indice = int(nech * quantile - 1./nech)
+ for quantile in self._parameters["Quantiles"]:
+ if not (0. <= float(quantile) <= 1.): continue
+ indice = int(nech * float(quantile) - 1./nech)
if YQ is None: YQ = YfQ[:,indice]
else: YQ = numpy.hstack((YQ,YfQ[:,indice]))
self.StoredVariables["SimulationQuantiles"].store( YQ )
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
name = "Minimizer",
default = "LBFGSB",
typecast = str,
- message = "Minimiseur utilisé",
+ message = "Minimiseur utilisé",
listval = ["LBFGSB","TNC", "CG", "NCG", "BFGS"],
)
self.defineRequiredParameter(
name = "CostDecrementTolerance",
default = 1.e-7,
typecast = float,
- message = "Diminution relative minimale du cout lors de l'arrêt",
+ message = "Diminution relative minimale du cout lors de l'arrêt",
)
self.defineRequiredParameter(
name = "ProjectedGradientTolerance",
default = -1,
typecast = float,
- message = "Maximum des composantes du gradient projeté lors de l'arrêt",
+ message = "Maximum des composantes du gradient projeté lors de l'arrêt",
minval = -1,
)
self.defineRequiredParameter(
name = "GradientNormTolerance",
default = 1.e-05,
typecast = float,
- message = "Maximum des composantes du gradient lors de l'arrêt",
+ message = "Maximum des composantes du gradient lors de l'arrêt",
)
self.defineRequiredParameter(
name = "StoreInternalVariables",
default = False,
typecast = bool,
- message = "Stockage des variables internes ou intermédiaires du calcul",
+ message = "Stockage des variables internes ou intermédiaires du calcul",
)
self.defineRequiredParameter(
name = "StoreSupplementaryCalculations",
default = [],
typecast = tuple,
- message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
+ message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
listval = ["BMA", "CurrentState", "CostFunctionJ", "CostFunctionJb", "CostFunctionJo", "IndexOfOptimum", "CurrentOptimum", "CostFunctionJAtCurrentOptimum"]
)
self.defineRequiredParameter( # Pas de type
if "Minimizer" in self._parameters and self._parameters["Minimizer"] == "TNC":
self.setParameterValue("StoreInternalVariables",True)
#
- # Opérateurs
+ # Opérateurs
# ----------
Hm = HO["Direct"].appliedControledFormTo
#
_CmUn = 0.
return _CmUn
#
- # Remarque : les observations sont exploitées à partir du pas de temps
- # numéro 1, et sont utilisées dans Yo comme rangées selon ces indices.
- # Donc le pas 0 n'est pas utilisé puisque la première étape commence
- # avec l'observation du pas 1.
+ # Remarque : les observations sont exploitées à partir du pas de temps
+ # numéro 1, et sont utilisées dans Yo comme rangées selon ces indices.
+ # Donc le pas 0 n'est pas utilisé puisque la première étape commence
+ # avec l'observation du pas 1.
#
# Nombre de pas identique au nombre de pas d'observations
# -------------------------------------------------------
else:
duration = 2
#
- # Précalcul des inversions de B et R
+ # Précalcul des inversions de B et R
# ----------------------------------
BI = B.getI()
RI = R.getI()
#
- # Définition de la fonction-coût
+ # Définition de la fonction-coût
# ------------------------------
- self.DirectCalculation = [None,] # Le pas 0 n'est pas observé
- self.DirectInnovation = [None,] # Le pas 0 n'est pas observé
+ self.DirectCalculation = [None,] # Le pas 0 n'est pas observé
+ self.DirectInnovation = [None,] # Le pas 0 n'est pas observé
def CostFunction(x):
_X = numpy.asmatrix(numpy.ravel( x )).T
if self._parameters["StoreInternalVariables"] or \
_Ynpu = numpy.asmatrix(numpy.ravel( Y )).T
_Un = Un(step)
#
- # Etape d'évolution
+ # Etape d'évolution
if self._parameters["EstimationOf"] == "State":
_Xn = Mm( (_Xn, _Un) ) + CmUn(_Xn, _Un)
elif self._parameters["EstimationOf"] == "Parameters":
_Xn = numpy.max(numpy.hstack((_Xn,numpy.asmatrix(self._parameters["Bounds"])[:,0])),axis=1)
_Xn = numpy.min(numpy.hstack((_Xn,numpy.asmatrix(self._parameters["Bounds"])[:,1])),axis=1)
#
- # Etape de différence aux observations
+ # Etape de différence aux observations
if self._parameters["EstimationOf"] == "State":
_YmHMX = _Ynpu - numpy.asmatrix(numpy.ravel( Hm( (_Xn, None) ) )).T
elif self._parameters["EstimationOf"] == "Parameters":
GradJb = BI * (_X - Xb)
GradJo = 0.
for step in range(duration-1,0,-1):
- # Etape de récupération du dernier stockage de l'évolution
+ # Etape de récupération du dernier stockage de l'évolution
_Xn = self.DirectCalculation.pop()
- # Etape de récupération du dernier stockage de l'innovation
+ # Etape de récupération du dernier stockage de l'innovation
_YmHMX = self.DirectInnovation.pop()
# Calcul des adjoints
Ha = HO["Adjoint"].asMatrix(ValueForMethodForm = _Xn)
Ma = EM["Adjoint"].asMatrix(ValueForMethodForm = _Xn)
Ma = Ma.reshape(_Xn.size,_Xn.size) # ADAO & check shape
# Calcul du gradient par etat adjoint
- GradJo = GradJo + Ha * RI * _YmHMX # Equivaut pour Ha lineaire à : Ha( (_Xn, RI * _YmHMX) )
- GradJo = Ma * GradJo # Equivaut pour Ma lineaire à : Ma( (_Xn, GradJo) )
+ GradJo = GradJo + Ha * RI * _YmHMX # Equivaut pour Ha lineaire à : Ha( (_Xn, RI * _YmHMX) )
+ GradJo = Ma * GradJo # Equivaut pour Ma lineaire à : Ma( (_Xn, GradJo) )
GradJ = numpy.asmatrix( numpy.ravel( GradJb ) - numpy.ravel( GradJo ) ).T
return GradJ.A1
#
- # Point de démarrage de l'optimisation : Xini = Xb
+ # Point de démarrage de l'optimisation : Xini = Xb
# ------------------------------------
- if type(Xb) is type(numpy.matrix([])):
+ if isinstance(Xb, type(numpy.matrix([]))):
Xini = Xb.A1.tolist()
else:
Xini = list(Xb)
#
self.StoredVariables["Analysis"].store( Xa.A1 )
#
- # Calculs et/ou stockages supplémentaires
+ # Calculs et/ou stockages supplémentaires
# ---------------------------------------
if "BMA" in self._parameters["StoreSupplementaryCalculations"]:
self.StoredVariables["BMA"].store( numpy.ravel(Xb) - numpy.ravel(Xa) )
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
#
# Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
-import logging
+import sys, logging
from daCore import BasicObjects, PlatformInfo
import numpy
mpr = PlatformInfo.PlatformInfo().MachinePrecision()
+if sys.version_info.major > 2:
+ unicode = str
# ==============================================================================
class ElementaryAlgorithm(BasicObjects.Algorithm):
name = "ResiduFormula",
default = "ScalarProduct",
typecast = str,
- message = "Formule de résidu utilisée",
+ message = "Formule de résidu utilisée",
listval = ["ScalarProduct"],
)
self.defineRequiredParameter(
name = "EpsilonMinimumExponent",
default = -8,
typecast = int,
- message = "Exposant minimal en puissance de 10 pour le multiplicateur d'incrément",
+ message = "Exposant minimal en puissance de 10 pour le multiplicateur d'incrément",
minval = -20,
maxval = 0,
)
name = "InitialDirection",
default = [],
typecast = list,
- message = "Direction initiale de la dérivée directionnelle autour du point nominal",
+ message = "Direction initiale de la dérivée directionnelle autour du point nominal",
)
self.defineRequiredParameter(
name = "AmplitudeOfInitialDirection",
default = 1.,
typecast = float,
- message = "Amplitude de la direction initiale de la dérivée directionnelle autour du point nominal",
+ message = "Amplitude de la direction initiale de la dérivée directionnelle autour du point nominal",
)
self.defineRequiredParameter(
name = "SetSeed",
typecast = numpy.random.seed,
- message = "Graine fixée pour le générateur aléatoire",
+ message = "Graine fixée pour le générateur aléatoire",
)
self.defineRequiredParameter(
name = "ResultTitle",
name = "StoreSupplementaryCalculations",
default = [],
typecast = tuple,
- message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
+ message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
listval = ["CurrentState", "Residu", "SimulatedObservationAtCurrentState"]
)
#
# Entete des resultats
# --------------------
- __marge = 12*" "
- __precision = """
+ __marge = 12*u" "
+ __precision = u"""
Remarque : les nombres inferieurs a %.0e (environ) representent un zero
a la precision machine.\n"""%mpr
if self._parameters["ResiduFormula"] == "ScalarProduct":
- __entete = " i Alpha ||X|| ||Y|| ||dX|| R(Alpha) "
- __msgdoc = """
+ __entete = u" i Alpha ||X|| ||Y|| ||dX|| R(Alpha) "
+ __msgdoc = u"""
On observe le residu qui est la difference de deux produits scalaires :
R(Alpha) = | < TangentF_X(dX) , Y > - < dX , AdjointF_X(Y) > |
""" + __precision
#
if len(self._parameters["ResultTitle"]) > 0:
- msgs = "\n"
- msgs += __marge + "====" + "="*len(self._parameters["ResultTitle"]) + "====\n"
- msgs += __marge + " " + self._parameters["ResultTitle"] + "\n"
- msgs += __marge + "====" + "="*len(self._parameters["ResultTitle"]) + "====\n"
+ __rt = unicode(self._parameters["ResultTitle"])
+ msgs = u"\n"
+ msgs += __marge + "====" + "="*len(__rt) + "====\n"
+ msgs += __marge + " " + __rt + "\n"
+ msgs += __marge + "====" + "="*len(__rt) + "====\n"
else:
- msgs = ""
+ msgs = u""
msgs += __msgdoc
#
__nbtirets = len(__entete)
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
name = "StoreInternalVariables",
default = False,
typecast = bool,
- message = "Stockage des variables internes ou intermédiaires du calcul",
+ message = "Stockage des variables internes ou intermédiaires du calcul",
)
self.defineRequiredParameter(
name = "StoreSupplementaryCalculations",
default = [],
typecast = tuple,
- message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
+ message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
listval = ["APosterioriCorrelations", "APosterioriCovariance", "APosterioriStandardDeviations", "APosterioriVariances", "BMA", "OMA", "OMB", "CurrentState", "CostFunctionJ", "CostFunctionJb", "CostFunctionJo", "Innovation", "SigmaBck2", "SigmaObs2", "MahalanobisConsistency", "SimulationQuantiles", "SimulatedObservationAtBackground", "SimulatedObservationAtCurrentState", "SimulatedObservationAtOptimum"]
)
self.defineRequiredParameter(
self.defineRequiredParameter(
name = "SetSeed",
typecast = numpy.random.seed,
- message = "Graine fixée pour le générateur aléatoire",
+ message = "Graine fixée pour le générateur aléatoire",
)
self.defineRequiredParameter(
name = "NumberOfSamplesForQuantiles",
default = 100,
typecast = int,
- message = "Nombre d'échantillons simulés pour le calcul des quantiles",
+ message = "Nombre d'échantillons simulés pour le calcul des quantiles",
minval = 1,
)
self.defineRequiredParameter(
Ha = HO["Adjoint"].asMatrix(Xb)
Ha = Ha.reshape(Xb.size,Y.size) # ADAO & check shape
#
- # Utilisation éventuelle d'un vecteur H(Xb) précalculé (sans cout)
+ # Utilisation éventuelle d'un vecteur H(Xb) précalculé (sans cout)
# ----------------------------------------------------------------
- if HO["AppliedToX"] is not None and "HXb" in HO["AppliedToX"]:
- HXb = HO["AppliedToX"]["HXb"]
+ if HO["AppliedInX"] is not None and "HXb" in HO["AppliedInX"]:
+ HXb = HO["AppliedInX"]["HXb"]
else:
HXb = Hm * Xb
HXb = numpy.asmatrix(numpy.ravel( HXb )).T
if max(Y.shape) != max(HXb.shape):
raise ValueError("The shapes %s of observations Y and %s of observed calculation H(X) are different, they have to be identical."%(Y.shape,HXb.shape))
#
- # Précalcul des inversions de B et R
+ # Précalcul des inversions de B et R
# ----------------------------------
BI = B.getI()
RI = R.getI()
Xa = Xb + _u
self.StoredVariables["Analysis"].store( Xa.A1 )
#
- # Calcul de la fonction coût
+ # Calcul de la fonction coût
# --------------------------
if self._parameters["StoreInternalVariables"] or \
"CostFunctionJ" in self._parameters["StoreSupplementaryCalculations"] or \
raise ValueError("The %s a posteriori covariance matrix A is not symmetric positive-definite. Please check your a priori covariances and your observation operator."%(self._name,))
self.StoredVariables["APosterioriCovariance"].store( A )
#
- # Calculs et/ou stockages supplémentaires
+ # Calculs et/ou stockages supplémentaires
# ---------------------------------------
if self._parameters["StoreInternalVariables"] or "CurrentState" in self._parameters["StoreSupplementaryCalculations"]:
self.StoredVariables["CurrentState"].store( numpy.ravel(Xa) )
if "MahalanobisConsistency" in self._parameters["StoreSupplementaryCalculations"]:
self.StoredVariables["MahalanobisConsistency"].store( float( 2.*J/d.size ) )
if "SimulationQuantiles" in self._parameters["StoreSupplementaryCalculations"]:
- Qtls = map(float, self._parameters["Quantiles"])
nech = self._parameters["NumberOfSamplesForQuantiles"]
YfQ = None
for i in range(nech):
YfQ = numpy.hstack((YfQ,Yr))
YfQ.sort(axis=-1)
YQ = None
- for quantile in Qtls:
- if not (0. <= quantile <= 1.): continue
- indice = int(nech * quantile - 1./nech)
+ for quantile in self._parameters["Quantiles"]:
+ if not (0. <= float(quantile) <= 1.): continue
+ indice = int(nech * float(quantile) - 1./nech)
if YQ is None: YQ = YfQ[:,indice]
else: YQ = numpy.hstack((YQ,YfQ[:,indice]))
self.StoredVariables["SimulationQuantiles"].store( YQ )
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
name = "Minimizer",
default = "BOBYQA",
typecast = str,
- message = "Minimiseur utilisé",
+ message = "Minimiseur utilisé",
listval = ["BOBYQA", "COBYLA", "NEWUOA", "POWELL", "SIMPLEX", "SUBPLEX"],
)
self.defineRequiredParameter(
name = "MaximumNumberOfFunctionEvaluations",
default = 15000,
typecast = int,
- message = "Nombre maximal d'évaluations de la fonction",
+ message = "Nombre maximal d'évaluations de la fonction",
minval = -1,
)
self.defineRequiredParameter(
name = "StateVariationTolerance",
default = 1.e-4,
typecast = float,
- message = "Variation relative maximale de l'état lors de l'arrêt",
+ message = "Variation relative maximale de l'état lors de l'arrêt",
)
self.defineRequiredParameter(
name = "CostDecrementTolerance",
default = 1.e-7,
typecast = float,
- message = "Diminution relative minimale du cout lors de l'arrêt",
+ message = "Diminution relative minimale du cout lors de l'arrêt",
)
self.defineRequiredParameter(
name = "QualityCriterion",
default = "AugmentedWeightedLeastSquares",
typecast = str,
- message = "Critère de qualité utilisé",
+ message = "Critère de qualité utilisé",
listval = ["AugmentedWeightedLeastSquares","AWLS","DA",
"WeightedLeastSquares","WLS",
"LeastSquares","LS","L2",
name = "StoreInternalVariables",
default = False,
typecast = bool,
- message = "Stockage des variables internes ou intermédiaires du calcul",
+ message = "Stockage des variables internes ou intermédiaires du calcul",
)
self.defineRequiredParameter(
name = "StoreSupplementaryCalculations",
default = [],
typecast = tuple,
- message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
+ message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
listval = ["CurrentState", "CostFunctionJ", "CostFunctionJb", "CostFunctionJo", "CostFunctionJAtCurrentOptimum", "CurrentOptimum", "IndexOfOptimum", "InnovationAtCurrentState", "BMA", "OMA", "OMB", "SimulatedObservationAtBackground", "SimulatedObservationAtCurrentOptimum", "SimulatedObservationAtCurrentState", "SimulatedObservationAtOptimum"]
)
self.defineRequiredParameter( # Pas de type
if not PlatformInfo.has_nlopt and not self._parameters["Minimizer"] in ["COBYLA", "POWELL", "SIMPLEX"]:
self._parameters["Minimizer"] = "SIMPLEX"
#
- # Opérateurs
+ # Opérateurs
# ----------
Hm = HO["Direct"].appliedTo
#
- # Précalcul des inversions de B et R
+ # Précalcul des inversions de B et R
# ----------------------------------
BI = B.getI()
RI = R.getI()
#
- # Définition de la fonction-coût
+ # Définition de la fonction-coût
# ------------------------------
def CostFunction(x, QualityMeasure="AugmentedWeightedLeastSquares"):
_X = numpy.asmatrix(numpy.ravel( x )).T
self.StoredVariables["CostFunctionJAtCurrentOptimum" ].store( self.StoredVariables["CostFunctionJ" ][IndexMin] )
return J
#
- # Point de démarrage de l'optimisation : Xini = Xb
+ # Point de démarrage de l'optimisation : Xini = Xb
# ------------------------------------
Xini = numpy.ravel(Xb)
if len(Xini) < 2 and self._parameters["Minimizer"] == "NEWUOA":
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
name = "StoreInternalVariables",
default = False,
typecast = bool,
- message = "Stockage des variables internes ou intermédiaires du calcul",
+ message = "Stockage des variables internes ou intermédiaires du calcul",
)
self.defineRequiredParameter(
name = "StoreSupplementaryCalculations",
default = [],
typecast = tuple,
- message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
+ message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
listval = ["CurrentState", "Innovation", "SimulatedObservationAtBackground", "SimulatedObservationAtCurrentState", "SimulatedObservationAtOptimum"]
)
self.defineRequiredParameter(
name = "SetSeed",
typecast = numpy.random.seed,
- message = "Graine fixée pour le générateur aléatoire",
+ message = "Graine fixée pour le générateur aléatoire",
)
def run(self, Xb=None, Y=None, U=None, HO=None, EM=None, CM=None, R=None, B=None, Q=None, Parameters=None):
self._pre_run(Parameters)
#
- # Précalcul des inversions de B et R
+ # Précalcul des inversions de B et R
# ----------------------------------
BI = B.getI()
RI = R.getI()
#
- # Nombre d'ensemble pour l'ébauche
+ # Nombre d'ensemble pour l'ébauche
# --------------------------------
nb_ens = Xb.stepnumber()
#
- # Construction de l'ensemble des observations, par génération a partir
+ # Construction de l'ensemble des observations, par génération a partir
# de la diagonale de R
# --------------------------------------------------------------------
DiagonaleR = R.diag(Y.size)
EnsembleY[npar,:] = Y[npar] + bruit
EnsembleY = numpy.matrix(EnsembleY)
#
- # Initialisation des opérateurs d'observation et de la matrice gain
+ # Initialisation des opérateurs d'observation et de la matrice gain
# -----------------------------------------------------------------
Hm = HO["Tangent"].asMatrix(None)
Hm = Hm.reshape(Y.size,Xb[0].size) # ADAO & check shape
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
name = "StoreInternalVariables",
default = False,
typecast = bool,
- message = "Stockage des variables internes ou intermédiaires du calcul",
+ message = "Stockage des variables internes ou intermédiaires du calcul",
)
self.defineRequiredParameter(
name = "StoreSupplementaryCalculations",
default = [],
typecast = tuple,
- message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
+ message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
listval = ["APosterioriCorrelations", "APosterioriCovariance", "APosterioriStandardDeviations", "APosterioriVariances", "BMA", "OMA", "OMB", "CurrentState", "CostFunctionJ", "CostFunctionJb", "CostFunctionJo", "Innovation", "SigmaBck2", "SigmaObs2", "MahalanobisConsistency", "SimulationQuantiles", "SimulatedObservationAtBackground", "SimulatedObservationAtCurrentState", "SimulatedObservationAtOptimum"]
)
self.defineRequiredParameter(
self.defineRequiredParameter(
name = "SetSeed",
typecast = numpy.random.seed,
- message = "Graine fixée pour le générateur aléatoire",
+ message = "Graine fixée pour le générateur aléatoire",
)
self.defineRequiredParameter(
name = "NumberOfSamplesForQuantiles",
default = 100,
typecast = int,
- message = "Nombre d'échantillons simulés pour le calcul des quantiles",
+ message = "Nombre d'échantillons simulés pour le calcul des quantiles",
minval = 1,
)
self.defineRequiredParameter(
Ha = Ha.reshape(Xb.size,Y.size) # ADAO & check shape
H = HO["Direct"].appliedTo
#
- # Utilisation éventuelle d'un vecteur H(Xb) précalculé
+ # Utilisation éventuelle d'un vecteur H(Xb) précalculé
# ----------------------------------------------------
- if HO["AppliedToX"] is not None and "HXb" in HO["AppliedToX"]:
- HXb = H( Xb, HO["AppliedToX"]["HXb"])
+ if HO["AppliedInX"] is not None and "HXb" in HO["AppliedInX"]:
+ HXb = H( Xb, HO["AppliedInX"]["HXb"])
else:
HXb = H( Xb )
HXb = numpy.asmatrix(numpy.ravel( HXb )).T
#
- # Précalcul des inversions de B et R
+ # Précalcul des inversions de B et R
# ----------------------------------
BI = B.getI()
RI = R.getI()
Xa = Xb + _u
self.StoredVariables["Analysis"].store( Xa.A1 )
#
- # Calcul de la fonction coût
+ # Calcul de la fonction coût
# --------------------------
if self._parameters["StoreInternalVariables"] or \
"CostFunctionJ" in self._parameters["StoreSupplementaryCalculations"] or \
raise ValueError("The %s a posteriori covariance matrix A is not symmetric positive-definite. Please check your a priori covariances and your observation operator."%(self._name,))
self.StoredVariables["APosterioriCovariance"].store( A )
#
- # Calculs et/ou stockages supplémentaires
+ # Calculs et/ou stockages supplémentaires
# ---------------------------------------
if self._parameters["StoreInternalVariables"] or "CurrentState" in self._parameters["StoreSupplementaryCalculations"]:
self.StoredVariables["CurrentState"].store( numpy.ravel(Xa) )
if "MahalanobisConsistency" in self._parameters["StoreSupplementaryCalculations"]:
self.StoredVariables["MahalanobisConsistency"].store( float( 2.*J/d.size ) )
if "SimulationQuantiles" in self._parameters["StoreSupplementaryCalculations"]:
- Qtls = map(float, self._parameters["Quantiles"])
nech = self._parameters["NumberOfSamplesForQuantiles"]
HtM = HO["Tangent"].asMatrix(ValueForMethodForm = Xa)
HtM = HtM.reshape(Y.size,Xa.size) # ADAO & check shape
YfQ = numpy.hstack((YfQ,Yr))
YfQ.sort(axis=-1)
YQ = None
- for quantile in Qtls:
- if not (0. <= quantile <= 1.): continue
- indice = int(nech * quantile - 1./nech)
+ for quantile in self._parameters["Quantiles"]:
+ if not (0. <= float(quantile) <= 1.): continue
+ indice = int(nech * float(quantile) - 1./nech)
if YQ is None: YQ = YfQ[:,indice]
else: YQ = numpy.hstack((YQ,YfQ[:,indice]))
self.StoredVariables["SimulationQuantiles"].store( YQ )
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
name = "StoreInternalVariables",
default = False,
typecast = bool,
- message = "Stockage des variables internes ou intermédiaires du calcul",
+ message = "Stockage des variables internes ou intermédiaires du calcul",
)
self.defineRequiredParameter(
name = "StoreSupplementaryCalculations",
default = [],
typecast = tuple,
- message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
+ message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
listval = ["APosterioriCorrelations", "APosterioriCovariance", "APosterioriStandardDeviations", "APosterioriVariances", "BMA", "CurrentState", "CostFunctionJ", "CostFunctionJb", "CostFunctionJo", "Innovation"]
)
self.defineRequiredParameter( # Pas de type
if self._parameters["EstimationOf"] == "Parameters":
self._parameters["StoreInternalVariables"] = True
#
- # Opérateurs
+ # Opérateurs
# ----------
if B is None:
raise ValueError("Background error covariance matrix has to be properly defined!")
else:
duration = 2
#
- # Précalcul des inversions de B et R
+ # Précalcul des inversions de B et R
# ----------------------------------
if self._parameters["StoreInternalVariables"]:
BI = B.getI()
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
#
# Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
-import logging
+import sys, logging
from daCore import BasicObjects, PlatformInfo
import numpy, copy
mpr = PlatformInfo.PlatformInfo().MachinePrecision()
mfp = PlatformInfo.PlatformInfo().MaximumPrecision()
+if sys.version_info.major > 2:
+ unicode = str
# ==============================================================================
class ElementaryAlgorithm(BasicObjects.Algorithm):
name = "NumberOfPrintedDigits",
default = 5,
typecast = int,
- message = "Nombre de chiffres affichés pour les impressions de réels",
+ message = "Nombre de chiffres affichés pour les impressions de réels",
minval = 0,
)
self.defineRequiredParameter(
name = "NumberOfRepetition",
default = 1,
typecast = int,
- message = "Nombre de fois où l'exécution de la fonction est répétée",
+ message = "Nombre de fois où l'exécution de la fonction est répétée",
minval = 1,
)
self.defineRequiredParameter(
name = "SetDebug",
default = False,
typecast = bool,
- message = "Activation du mode debug lors de l'exécution",
+ message = "Activation du mode debug lors de l'exécution",
)
self.defineRequiredParameter(
name = "StoreSupplementaryCalculations",
default = [],
typecast = tuple,
- message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
+ message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
listval = ["CurrentState", "SimulatedObservationAtCurrentState"]
)
Xn = copy.copy( Xb )
#
# ----------
+ __marge = 5*u" "
_p = self._parameters["NumberOfPrintedDigits"]
if len(self._parameters["ResultTitle"]) > 0:
- msg = " ====" + "="*len(self._parameters["ResultTitle"]) + "====\n"
- msg += " " + self._parameters["ResultTitle"] + "\n"
- msg += " ====" + "="*len(self._parameters["ResultTitle"]) + "====\n"
- print("%s"%msg)
+ __rt = unicode(self._parameters["ResultTitle"])
+ msgs = u"\n"
+ msgs += __marge + "====" + "="*len(__rt) + "====\n"
+ msgs += __marge + " " + __rt + "\n"
+ msgs += __marge + "====" + "="*len(__rt) + "====\n"
+ print("%s"%msgs)
#
- msg = ("===> Information before launching:\n")
- msg += (" -----------------------------\n")
- msg += (" Characteristics of input vector X, internally converted:\n")
- msg += (" Type...............: %s\n")%type( Xn )
- msg += (" Lenght of vector...: %i\n")%max(numpy.matrix( Xn ).shape)
- msg += (" Minimum value......: %."+str(_p)+"e\n")%numpy.min( Xn )
- msg += (" Maximum value......: %."+str(_p)+"e\n")%numpy.max( Xn )
- msg += (" Mean of vector.....: %."+str(_p)+"e\n")%numpy.mean( Xn, dtype=mfp )
- msg += (" Standard error.....: %."+str(_p)+"e\n")%numpy.std( Xn, dtype=mfp )
- msg += (" L2 norm of vector..: %."+str(_p)+"e\n")%numpy.linalg.norm( Xn )
- print(msg)
+ msgs = ("===> Information before launching:\n")
+ msgs += (" -----------------------------\n")
+ msgs += (" Characteristics of input vector X, internally converted:\n")
+ msgs += (" Type...............: %s\n")%type( Xn )
+ msgs += (" Lenght of vector...: %i\n")%max(numpy.matrix( Xn ).shape)
+ msgs += (" Minimum value......: %."+str(_p)+"e\n")%numpy.min( Xn )
+ msgs += (" Maximum value......: %."+str(_p)+"e\n")%numpy.max( Xn )
+ msgs += (" Mean of vector.....: %."+str(_p)+"e\n")%numpy.mean( Xn, dtype=mfp )
+ msgs += (" Standard error.....: %."+str(_p)+"e\n")%numpy.std( Xn, dtype=mfp )
+ msgs += (" L2 norm of vector..: %."+str(_p)+"e\n")%numpy.linalg.norm( Xn )
+ print(msgs)
#
if self._parameters["SetDebug"]:
CUR_LEVEL = logging.getLogger().getEffectiveLevel()
#
print("\n===> End of direct operator evaluation\n")
#
- msg = ("===> Information after evaluation:\n")
- msg += ("\n Characteristics of simulated output vector Y=H(X), to compare to others:\n")
- msg += (" Type...............: %s\n")%type( Yn )
- msg += (" Lenght of vector...: %i\n")%max(numpy.matrix( Yn ).shape)
- msg += (" Minimum value......: %."+str(_p)+"e\n")%numpy.min( Yn )
- msg += (" Maximum value......: %."+str(_p)+"e\n")%numpy.max( Yn )
- msg += (" Mean of vector.....: %."+str(_p)+"e\n")%numpy.mean( Yn, dtype=mfp )
- msg += (" Standard error.....: %."+str(_p)+"e\n")%numpy.std( Yn, dtype=mfp )
- msg += (" L2 norm of vector..: %."+str(_p)+"e\n")%numpy.linalg.norm( Yn )
- print(msg)
+ msgs = ("===> Information after evaluation:\n")
+ msgs += ("\n Characteristics of simulated output vector Y=H(X), to compare to others:\n")
+ msgs += (" Type...............: %s\n")%type( Yn )
+ msgs += (" Lenght of vector...: %i\n")%max(numpy.matrix( Yn ).shape)
+ msgs += (" Minimum value......: %."+str(_p)+"e\n")%numpy.min( Yn )
+ msgs += (" Maximum value......: %."+str(_p)+"e\n")%numpy.max( Yn )
+ msgs += (" Mean of vector.....: %."+str(_p)+"e\n")%numpy.mean( Yn, dtype=mfp )
+ msgs += (" Standard error.....: %."+str(_p)+"e\n")%numpy.std( Yn, dtype=mfp )
+ msgs += (" L2 norm of vector..: %."+str(_p)+"e\n")%numpy.linalg.norm( Yn )
+ print(msgs)
if "SimulatedObservationAtCurrentState" in self._parameters["StoreSupplementaryCalculations"]:
self.StoredVariables["SimulatedObservationAtCurrentState"].store( numpy.ravel(Yn) )
#
logging.getLogger().setLevel(CUR_LEVEL)
#
if self._parameters["NumberOfRepetition"] > 1:
- msg = (" %s\n"%("-"*75,))
- msg += ("\n===> Statistical analysis of the outputs obtained throught repeated evaluations\n")
- msg += ("\n (Remark: numbers that are (about) under %.0e represent 0 to machine precision)\n"%mpr)
+ msgs = (" %s\n"%("-"*75,))
+ msgs += ("\n===> Statistical analysis of the outputs obtained throught repeated evaluations\n")
+ msgs += ("\n (Remark: numbers that are (about) under %.0e represent 0 to machine precision)\n"%mpr)
Yy = numpy.array( Ys )
- msg += ("\n Characteristics of the whole set of outputs Y:\n")
- msg += (" Number of evaluations.........................: %i\n")%len( Ys )
- msg += (" Minimum value of the whole set of outputs.....: %."+str(_p)+"e\n")%numpy.min( Yy )
- msg += (" Maximum value of the whole set of outputs.....: %."+str(_p)+"e\n")%numpy.max( Yy )
- msg += (" Mean of vector of the whole set of outputs....: %."+str(_p)+"e\n")%numpy.mean( Yy, dtype=mfp )
- msg += (" Standard error of the whole set of outputs....: %."+str(_p)+"e\n")%numpy.std( Yy, dtype=mfp )
+ msgs += ("\n Characteristics of the whole set of outputs Y:\n")
+ msgs += (" Number of evaluations.........................: %i\n")%len( Ys )
+ msgs += (" Minimum value of the whole set of outputs.....: %."+str(_p)+"e\n")%numpy.min( Yy )
+ msgs += (" Maximum value of the whole set of outputs.....: %."+str(_p)+"e\n")%numpy.max( Yy )
+ msgs += (" Mean of vector of the whole set of outputs....: %."+str(_p)+"e\n")%numpy.mean( Yy, dtype=mfp )
+ msgs += (" Standard error of the whole set of outputs....: %."+str(_p)+"e\n")%numpy.std( Yy, dtype=mfp )
Ym = numpy.mean( numpy.array( Ys ), axis=0, dtype=mfp )
- msg += ("\n Characteristics of the vector Ym, mean of the outputs Y:\n")
- msg += (" Size of the mean of the outputs...............: %i\n")%Ym.size
- msg += (" Minimum value of the mean of the outputs......: %."+str(_p)+"e\n")%numpy.min( Ym )
- msg += (" Maximum value of the mean of the outputs......: %."+str(_p)+"e\n")%numpy.max( Ym )
- msg += (" Mean of the mean of the outputs...............: %."+str(_p)+"e\n")%numpy.mean( Ym, dtype=mfp )
- msg += (" Standard error of the mean of the outputs.....: %."+str(_p)+"e\n")%numpy.std( Ym, dtype=mfp )
+ msgs += ("\n Characteristics of the vector Ym, mean of the outputs Y:\n")
+ msgs += (" Size of the mean of the outputs...............: %i\n")%Ym.size
+ msgs += (" Minimum value of the mean of the outputs......: %."+str(_p)+"e\n")%numpy.min( Ym )
+ msgs += (" Maximum value of the mean of the outputs......: %."+str(_p)+"e\n")%numpy.max( Ym )
+ msgs += (" Mean of the mean of the outputs...............: %."+str(_p)+"e\n")%numpy.mean( Ym, dtype=mfp )
+ msgs += (" Standard error of the mean of the outputs.....: %."+str(_p)+"e\n")%numpy.std( Ym, dtype=mfp )
Ye = numpy.mean( numpy.array( Ys ) - Ym, axis=0, dtype=mfp )
- msg += "\n Characteristics of the mean of the differences between the outputs Y and their mean Ym:\n"
- msg += (" Size of the mean of the differences...........: %i\n")%Ym.size
- msg += (" Minimum value of the mean of the differences..: %."+str(_p)+"e\n")%numpy.min( Ye )
- msg += (" Maximum value of the mean of the differences..: %."+str(_p)+"e\n")%numpy.max( Ye )
- msg += (" Mean of the mean of the differences...........: %."+str(_p)+"e\n")%numpy.mean( Ye, dtype=mfp )
- msg += (" Standard error of the mean of the differences.: %."+str(_p)+"e\n")%numpy.std( Ye, dtype=mfp )
- msg += ("\n %s\n"%("-"*75,))
- print(msg)
+ msgs += "\n Characteristics of the mean of the differences between the outputs Y and their mean Ym:\n"
+ msgs += (" Size of the mean of the differences...........: %i\n")%Ym.size
+ msgs += (" Minimum value of the mean of the differences..: %."+str(_p)+"e\n")%numpy.min( Ye )
+ msgs += (" Maximum value of the mean of the differences..: %."+str(_p)+"e\n")%numpy.max( Ye )
+ msgs += (" Mean of the mean of the differences...........: %."+str(_p)+"e\n")%numpy.mean( Ye, dtype=mfp )
+ msgs += (" Standard error of the mean of the differences.: %."+str(_p)+"e\n")%numpy.std( Ye, dtype=mfp )
+ msgs += ("\n %s\n"%("-"*75,))
+ print(msgs)
#
self._post_run(HO)
return 0
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
#
# Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
-import logging
+import sys, logging
from daCore import BasicObjects, PlatformInfo
import numpy, math
mpr = PlatformInfo.PlatformInfo().MachinePrecision()
+if sys.version_info.major > 2:
+ unicode = str
# ==============================================================================
class ElementaryAlgorithm(BasicObjects.Algorithm):
name = "ResiduFormula",
default = "Taylor",
typecast = str,
- message = "Formule de résidu utilisée",
+ message = "Formule de résidu utilisée",
listval = ["Norm", "TaylorOnNorm", "Taylor"],
)
self.defineRequiredParameter(
name = "EpsilonMinimumExponent",
default = -8,
typecast = int,
- message = "Exposant minimal en puissance de 10 pour le multiplicateur d'incrément",
+ message = "Exposant minimal en puissance de 10 pour le multiplicateur d'incrément",
minval = -20,
maxval = 0,
)
name = "InitialDirection",
default = [],
typecast = list,
- message = "Direction initiale de la dérivée directionnelle autour du point nominal",
+ message = "Direction initiale de la dérivée directionnelle autour du point nominal",
)
self.defineRequiredParameter(
name = "AmplitudeOfInitialDirection",
default = 1.,
typecast = float,
- message = "Amplitude de la direction initiale de la dérivée directionnelle autour du point nominal",
+ message = "Amplitude de la direction initiale de la dérivée directionnelle autour du point nominal",
)
self.defineRequiredParameter(
name = "AmplitudeOfTangentPerturbation",
self.defineRequiredParameter(
name = "SetSeed",
typecast = numpy.random.seed,
- message = "Graine fixée pour le générateur aléatoire",
+ message = "Graine fixée pour le générateur aléatoire",
)
self.defineRequiredParameter(
name = "PlotAndSave",
default = False,
typecast = bool,
- message = "Trace et sauve les résultats",
+ message = "Trace et sauve les résultats",
)
self.defineRequiredParameter(
name = "ResultFile",
default = self._name+"_result_file",
typecast = str,
- message = "Nom de base (hors extension) des fichiers de sauvegarde des résultats",
+ message = "Nom de base (hors extension) des fichiers de sauvegarde des résultats",
)
self.defineRequiredParameter(
name = "ResultTitle",
name = "ResultLabel",
default = "",
typecast = str,
- message = "Label de la courbe tracée dans la figure",
+ message = "Label de la courbe tracée dans la figure",
)
self.defineRequiredParameter(
name = "StoreSupplementaryCalculations",
default = [],
typecast = tuple,
- message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
+ message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
listval = ["CurrentState", "Residu", "SimulatedObservationAtCurrentState"]
)
#
# Entete des resultats
# --------------------
- __marge = 12*" "
- __precision = """
+ __marge = 12*u" "
+ __precision = u"""
Remarque : les nombres inferieurs a %.0e (environ) representent un zero
a la precision machine.\n"""%mpr
if self._parameters["ResiduFormula"] == "Taylor":
- __entete = " i Alpha ||X|| ||F(X)|| ||F(X+dX)|| ||dX|| ||F(X+dX)-F(X)|| ||F(X+dX)-F(X)||/||dX|| R(Alpha) log( R ) "
- __msgdoc = """
- On observe le résidu issu du développement de Taylor de la fonction F,
- normalisé par la valeur au point nominal :
+ __entete = u" i Alpha ||X|| ||F(X)|| ||F(X+dX)|| ||dX|| ||F(X+dX)-F(X)|| ||F(X+dX)-F(X)||/||dX|| R(Alpha) log( R ) "
+ __msgdoc = u"""
+ On observe le residu issu du developpement de Taylor de la fonction F,
+ normalise par la valeur au point nominal :
|| F(X+Alpha*dX) - F(X) - Alpha * GradientF_X(dX) ||
R(Alpha) = ----------------------------------------------------
|| F(X) ||
- Si le résidu décroit et que la décroissance se fait en Alpha**2 selon Alpha,
- cela signifie que le gradient est bien calculé jusqu'à la précision d'arrêt
- de la décroissance quadratique, et que F n'est pas linéaire.
+ Si le residu decroit et que la decroissance se fait en Alpha**2 selon Alpha,
+ cela signifie que le gradient est bien calcule jusqu'a la precision d'arret
+ de la decroissance quadratique, et que F n'est pas lineaire.
- Si le résidu décroit et que la décroissance se fait en Alpha selon Alpha,
- jusqu'à un certain seuil aprés lequel le résidu est faible et constant, cela
- signifie que F est linéaire et que le résidu décroit à partir de l'erreur
+ Si le residu decroit et que la decroissance se fait en Alpha selon Alpha,
+ jusqu'a un certain seuil apres lequel le residu est faible et constant, cela
+ signifie que F est lineaire et que le residu decroit a partir de l'erreur
faite dans le calcul du terme GradientF_X.
On prend dX0 = Normal(0,X) et dX = Alpha*dX0. F est le code de calcul.
""" + __precision
if self._parameters["ResiduFormula"] == "TaylorOnNorm":
- __entete = " i Alpha ||X|| ||F(X)|| ||F(X+dX)|| ||dX|| ||F(X+dX)-F(X)|| ||F(X+dX)-F(X)||/||dX|| R(Alpha) log( R ) "
- __msgdoc = """
- On observe le résidu issu du développement de Taylor de la fonction F,
- rapporté au paramètre Alpha au carré :
+ __entete = u" i Alpha ||X|| ||F(X)|| ||F(X+dX)|| ||dX|| ||F(X+dX)-F(X)|| ||F(X+dX)-F(X)||/||dX|| R(Alpha) log( R ) "
+ __msgdoc = u"""
+ On observe le residu issu du developpement de Taylor de la fonction F,
+ rapporte au parametre Alpha au carre :
|| F(X+Alpha*dX) - F(X) - Alpha * GradientF_X(dX) ||
R(Alpha) = ----------------------------------------------------
Alpha**2
- C'est un résidu essentiellement similaire au critère classique de Taylor,
- mais son comportement peut différer selon les propriétés numériques des
- calculs de ses différents termes.
+ C'est un residu essentiellement similaire au critere classique de Taylor,
+ mais son comportement peut differer selon les proprietes numeriques des
+ calculs de ses differents termes.
- Si le résidu est constant jusqu'à un certain seuil et croissant ensuite,
- cela signifie que le gradient est bien calculé jusqu'à cette précision
- d'arrêt, et que F n'est pas linéaire.
+ Si le residu est constant jusqu'a un certain seuil et croissant ensuite,
+ cela signifie que le gradient est bien calcule jusqu'a cette precision
+ d'arret, et que F n'est pas lineaire.
- Si le résidu est systématiquement croissant en partant d'une valeur faible
- par rapport à ||F(X)||, cela signifie que F est (quasi-)linéaire et que le
- calcul du gradient est correct jusqu'au moment où le résidu est de l'ordre de
+ Si le residu est systematiquement croissant en partant d'une valeur faible
+ par rapport a ||F(X)||, cela signifie que F est (quasi-)lineaire et que le
+ calcul du gradient est correct jusqu'au moment ou le residu est de l'ordre de
grandeur de ||F(X)||.
On prend dX0 = Normal(0,X) et dX = Alpha*dX0. F est le code de calcul.
""" + __precision
if self._parameters["ResiduFormula"] == "Norm":
- __entete = " i Alpha ||X|| ||F(X)|| ||F(X+dX)|| ||dX|| ||F(X+dX)-F(X)|| ||F(X+dX)-F(X)||/||dX|| R(Alpha) log( R ) "
- __msgdoc = """
- On observe le résidu, qui est basé sur une approximation du gradient :
+ __entete = u" i Alpha ||X|| ||F(X)|| ||F(X+dX)|| ||dX|| ||F(X+dX)-F(X)|| ||F(X+dX)-F(X)||/||dX|| R(Alpha) log( R ) "
+ __msgdoc = u"""
+ On observe le residu, qui est base sur une approximation du gradient :
|| F(X+Alpha*dX) - F(X) ||
R(Alpha) = ---------------------------
Alpha
- qui doit rester constant jusqu'à ce que l'on atteigne la précision du calcul.
+ qui doit rester constant jusqu'a ce que l'on atteigne la precision du calcul.
On prend dX0 = Normal(0,X) et dX = Alpha*dX0. F est le code de calcul.
""" + __precision
#
if len(self._parameters["ResultTitle"]) > 0:
- msgs = "\n"
- msgs += __marge + "====" + "="*len(self._parameters["ResultTitle"]) + "====\n"
- msgs += __marge + " " + self._parameters["ResultTitle"] + "\n"
- msgs += __marge + "====" + "="*len(self._parameters["ResultTitle"]) + "====\n"
+ __rt = unicode(self._parameters["ResultTitle"])
+ msgs = u"\n"
+ msgs += __marge + "====" + "="*len(__rt) + "====\n"
+ msgs += __marge + " " + __rt + "\n"
+ msgs += __marge + "====" + "="*len(__rt) + "====\n"
else:
- msgs = ""
+ msgs = u""
msgs += __msgdoc
#
__nbtirets = len(__entete)
# Residu Norm
NormedFXsAm = NormedFX/amplitude
#
- # if numpy.abs(NormedFX) < 1.e-20:
- # break
+ #Â if numpy.abs(NormedFX) < 1.e-20:
+ #Â break
#
NormesdX.append( NormedX )
NormesFXdX.append( NormeFXdX )
PerturbationsCarre = [ 10**(2*i) for i in range(-len(NormesdFXGdX)+1,1) ]
PerturbationsCarre.reverse()
dessiner(
- Perturbations,
+ Perturbations,
Residus,
titre = self._parameters["ResultTitle"],
label = self._parameters["ResultLabel"],
)
elif self._parameters["ResiduFormula"] == "Norm":
dessiner(
- Perturbations,
+ Perturbations,
Residus,
titre = self._parameters["ResultTitle"],
label = self._parameters["ResultLabel"],
return 0
# ==============================================================================
-
+
def dessiner(
X,
Y,
filename = "",
pause = False,
YRef = None, # Vecteur de reference a comparer a Y
- recalYRef = True, # Decalage du point 0 de YRef à Y[0]
+ recalYRef = True, # Decalage du point 0 de YRef a Y[0]
normdY0 = 0., # Norme de DeltaY[0]
):
import Gnuplot
__g('set grid')
__g('set autoscale')
__g('set title "'+titre+'"')
- # __g('set range [] reverse')
- # __g('set yrange [0:2]')
+ # __g('set range []Â reverse')
+ #Â __g('set yrange [0:2]')
#
if logX:
steps = numpy.log10( X )
if filename != "":
__g.hardcopy( filename, color=1)
if pause:
- raw_input('Please press return to continue...\n')
+ eval(input('Please press return to continue...\n'))
# ==============================================================================
if __name__ == "__main__":
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
name = "StoreInternalVariables",
default = False,
typecast = bool,
- message = "Stockage des variables internes ou intermédiaires du calcul",
+ message = "Stockage des variables internes ou intermédiaires du calcul",
)
self.defineRequiredParameter(
name = "StoreSupplementaryCalculations",
default = [],
typecast = tuple,
- message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
+ message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
listval = ["APosterioriCorrelations", "APosterioriCovariance", "APosterioriStandardDeviations", "APosterioriVariances", "BMA", "CurrentState", "CostFunctionJ", "CostFunctionJb", "CostFunctionJo", "Innovation"]
)
if self._parameters["EstimationOf"] == "Parameters":
self._parameters["StoreInternalVariables"] = True
#
- # Opérateurs
+ # Opérateurs
# ----------
if B is None:
raise ValueError("Background error covariance matrix has to be properly defined!")
else:
duration = 2
#
- # Précalcul des inversions de B et R
+ # Précalcul des inversions de B et R
# ----------------------------------
if self._parameters["StoreInternalVariables"]:
BI = B.getI()
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
name = "StoreInternalVariables",
default = False,
typecast = bool,
- message = "Stockage des variables internes ou intermédiaires du calcul",
+ message = "Stockage des variables internes ou intermédiaires du calcul",
)
self.defineRequiredParameter(
name = "StoreSupplementaryCalculations",
default = [],
typecast = tuple,
- message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
+ message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
listval = ["OMA", "CurrentState", "CostFunctionJ", "CostFunctionJb", "CostFunctionJo", "SimulatedObservationAtCurrentState", "SimulatedObservationAtOptimum"]
)
Xa = K * Y
self.StoredVariables["Analysis"].store( Xa.A1 )
#
- # Calcul de la fonction coût
+ # Calcul de la fonction coût
# --------------------------
if self._parameters["StoreInternalVariables"] or \
"CostFunctionJ" in self._parameters["StoreSupplementaryCalculations"] or \
self.StoredVariables["CostFunctionJo"].store( Jo )
self.StoredVariables["CostFunctionJ" ].store( J )
#
- # Calculs et/ou stockages supplémentaires
+ # Calculs et/ou stockages supplémentaires
# ---------------------------------------
if self._parameters["StoreInternalVariables"] or "CurrentState" in self._parameters["StoreSupplementaryCalculations"]:
self.StoredVariables["CurrentState"].store( numpy.ravel(Xa) )
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
#
# Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
-import logging
+import sys, logging
from daCore import BasicObjects, PlatformInfo
import numpy, math
mpr = PlatformInfo.PlatformInfo().MachinePrecision()
+if sys.version_info.major > 2:
+ unicode = str
# ==============================================================================
class ElementaryAlgorithm(BasicObjects.Algorithm):
name = "ResiduFormula",
default = "CenteredDL",
typecast = str,
- message = "Formule de résidu utilisée",
+ message = "Formule de résidu utilisée",
listval = ["CenteredDL", "Taylor", "NominalTaylor", "NominalTaylorRMS"],
)
self.defineRequiredParameter(
name = "EpsilonMinimumExponent",
default = -8,
typecast = int,
- message = "Exposant minimal en puissance de 10 pour le multiplicateur d'incrément",
+ message = "Exposant minimal en puissance de 10 pour le multiplicateur d'incrément",
minval = -20,
maxval = 0,
)
name = "InitialDirection",
default = [],
typecast = list,
- message = "Direction initiale de la dérivée directionnelle autour du point nominal",
+ message = "Direction initiale de la dérivée directionnelle autour du point nominal",
)
self.defineRequiredParameter(
name = "AmplitudeOfInitialDirection",
default = 1.,
typecast = float,
- message = "Amplitude de la direction initiale de la dérivée directionnelle autour du point nominal",
+ message = "Amplitude de la direction initiale de la dérivée directionnelle autour du point nominal",
)
self.defineRequiredParameter(
name = "AmplitudeOfTangentPerturbation",
self.defineRequiredParameter(
name = "SetSeed",
typecast = numpy.random.seed,
- message = "Graine fixée pour le générateur aléatoire",
+ message = "Graine fixée pour le générateur aléatoire",
)
self.defineRequiredParameter(
name = "ResultTitle",
name = "StoreSupplementaryCalculations",
default = [],
typecast = tuple,
- message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
+ message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
listval = ["CurrentState", "Residu", "SimulatedObservationAtCurrentState"]
)
import math
return math.sqrt( ((numpy.ravel(V2) - numpy.ravel(V1))**2).sum() / float(numpy.ravel(V1).size) )
#
- # Opérateurs
+ # Operateurs
# ----------
Hm = HO["Direct"].appliedTo
if self._parameters["ResiduFormula"] in ["Taylor", "NominalTaylor", "NominalTaylorRMS"]:
if "SimulatedObservationAtCurrentState" in self._parameters["StoreSupplementaryCalculations"]:
self.StoredVariables["SimulatedObservationAtCurrentState"].store( numpy.ravel(FX) )
#
- # Fabrication de la direction de l'incrément dX
- # ----------------------------------------------
+ # Fabrication de la direction de l'increment dX
+ # ---------------------------------------------
if len(self._parameters["InitialDirection"]) == 0:
dX0 = []
for v in Xn.A1:
#
dX0 = float(self._parameters["AmplitudeOfInitialDirection"]) * numpy.matrix( dX0 ).T
#
- # Calcul du gradient au point courant X pour l'incrément dX
+ # Calcul du gradient au point courant X pour l'increment dX
# ---------------------------------------------------------
if self._parameters["ResiduFormula"] in ["Taylor", "NominalTaylor", "NominalTaylorRMS"]:
dX1 = float(self._parameters["AmplitudeOfTangentPerturbation"]) * dX0
#
# Entete des resultats
# --------------------
- __marge = 12*" "
- __precision = """
+ __marge = 12*u" "
+ __precision = u"""
Remarque : les nombres inferieurs a %.0e (environ) representent un zero
a la precision machine.\n"""%mpr
if self._parameters["ResiduFormula"] == "CenteredDL":
- __entete = " i Alpha ||X|| ||F(X)|| | R(Alpha) log10( R ) "
- __msgdoc = """
- On observe le résidu provenant de la différence centrée des valeurs de F
- au point nominal et aux points perturbés, normalisée par la valeur au
+ __entete = u" i Alpha ||X|| ||F(X)|| | R(Alpha) log10( R ) "
+ __msgdoc = u"""
+ On observe le residu provenant de la difference centree des valeurs de F
+ au point nominal et aux points perturbes, normalisee par la valeur au
point nominal :
|| F(X+Alpha*dX) + F(X-Alpha*dX) - 2*F(X) ||
R(Alpha) = --------------------------------------------
|| F(X) ||
- S'il reste constamment trés faible par rapport à 1, l'hypothèse de linéarité
- de F est vérifiée.
+ S'il reste constamment tres faible par rapport a 1, l'hypothese de linearite
+ de F est verifiee.
- Si le résidu varie, ou qu'il est de l'ordre de 1 ou plus, et qu'il n'est
- faible qu'à partir d'un certain ordre d'incrément, l'hypothèse de linéarité
- de F n'est pas vérifiée.
+ Si le residu varie, ou qu'il est de l'ordre de 1 ou plus, et qu'il n'est
+ faible qu'a partir d'un certain ordre d'increment, l'hypothese de linearite
+ de F n'est pas verifiee.
- Si le résidu décroit et que la décroissance se fait en Alpha**2 selon Alpha,
- cela signifie que le gradient est calculable jusqu'à la précision d'arrêt
- de la décroissance quadratique.
+ Si le residu decroit et que la decroissance se fait en Alpha**2 selon Alpha,
+ cela signifie que le gradient est calculable jusqu'a la precision d'arret
+ de la decroissance quadratique.
On prend dX0 = Normal(0,X) et dX = Alpha*dX0. F est le code de calcul.
""" + __precision
if self._parameters["ResiduFormula"] == "Taylor":
- __entete = " i Alpha ||X|| ||F(X)|| | R(Alpha) log10( R ) "
- __msgdoc = """
- On observe le résidu issu du développement de Taylor de la fonction F,
- normalisée par la valeur au point nominal :
+ __entete = u" i Alpha ||X|| ||F(X)|| | R(Alpha) log10( R ) "
+ __msgdoc = u"""
+ On observe le residu issu du developpement de Taylor de la fonction F,
+ normalisee par la valeur au point nominal :
|| F(X+Alpha*dX) - F(X) - Alpha * GradientF_X(dX) ||
R(Alpha) = ----------------------------------------------------
|| F(X) ||
- S'il reste constamment trés faible par rapport à 1, l'hypothèse de linéarité
- de F est vérifiée.
+ S'il reste constamment tres faible par rapport a 1, l'hypothese de linearite
+ de F est verifiee.
- Si le résidu varie, ou qu'il est de l'ordre de 1 ou plus, et qu'il n'est
- faible qu'à partir d'un certain ordre d'incrément, l'hypothèse de linéarité
- de F n'est pas vérifiée.
+ Si le residu varie, ou qu'il est de l'ordre de 1 ou plus, et qu'il n'est
+ faible qu'a partir d'un certain ordre d'increment, l'hypothese de linearite
+ de F n'est pas verifiee.
- Si le résidu décroit et que la décroissance se fait en Alpha**2 selon Alpha,
- cela signifie que le gradient est bien calculé jusqu'à la précision d'arrêt
- de la décroissance quadratique.
+ Si le residu decroit et que la decroissance se fait en Alpha**2 selon Alpha,
+ cela signifie que le gradient est bien calcule jusqu'a la precision d'arret
+ de la decroissance quadratique.
On prend dX0 = Normal(0,X) et dX = Alpha*dX0. F est le code de calcul.
""" + __precision
if self._parameters["ResiduFormula"] == "NominalTaylor":
- __entete = " i Alpha ||X|| ||F(X)|| | R(Alpha) |R-1| en % "
- __msgdoc = """
- On observe le résidu obtenu à partir de deux approximations d'ordre 1 de F(X),
- normalisées par la valeur au point nominal :
+ __entete = u" i Alpha ||X|| ||F(X)|| | R(Alpha) |R-1| en % "
+ __msgdoc = u"""
+ On observe le residu obtenu a partir de deux approximations d'ordre 1 de F(X),
+ normalisees par la valeur au point nominal :
R(Alpha) = max(
|| F(X+Alpha*dX) - Alpha * F(dX) || / || F(X) ||,
|| F(X-Alpha*dX) + Alpha * F(dX) || / || F(X) ||,
)
- S'il reste constamment égal à 1 à moins de 2 ou 3 pourcents prés (c'est-à-dire
- que |R-1| reste égal à 2 ou 3 pourcents), c'est que l'hypothèse de linéarité
- de F est vérifiée.
+ S'il reste constamment egal a 1 a moins de 2 ou 3 pourcents pres (c'est-a-dire
+ que |R-1| reste egal a 2 ou 3 pourcents), c'est que l'hypothese de linearite
+ de F est verifiee.
- S'il est égal à 1 sur une partie seulement du domaine de variation de
- l'incrément Alpha, c'est sur cette partie que l'hypothèse de linéarité de F
- est vérifiée.
+ S'il est egal a 1 sur une partie seulement du domaine de variation de
+ l'increment Alpha, c'est sur cette partie que l'hypothese de linearite de F
+ est verifiee.
On prend dX0 = Normal(0,X) et dX = Alpha*dX0. F est le code de calcul.
""" + __precision
if self._parameters["ResiduFormula"] == "NominalTaylorRMS":
- __entete = " i Alpha ||X|| ||F(X)|| | R(Alpha) |R| en % "
- __msgdoc = """
- On observe le résidu obtenu à partir de deux approximations d'ordre 1 de F(X),
- normalisées par la valeur au point nominal :
+ __entete = u" i Alpha ||X|| ||F(X)|| | R(Alpha) |R| en % "
+ __msgdoc = u"""
+ On observe le residu obtenu a partir de deux approximations d'ordre 1 de F(X),
+ normalisees par la valeur au point nominal :
R(Alpha) = max(
RMS( F(X), F(X+Alpha*dX) - Alpha * F(dX) ) / || F(X) ||,
RMS( F(X), F(X-Alpha*dX) + Alpha * F(dX) ) / || F(X) ||,
)
- S'il reste constamment égal à 0 à moins de 1 ou 2 pourcents prés, c'est
- que l'hypothèse de linéarité de F est vérifiée.
+ S'il reste constamment egal a 0 a moins de 1 ou 2 pourcents pres, c'est
+ que l'hypothese de linearite de F est verifiee.
- S'il est égal à 0 sur une partie seulement du domaine de variation de
- l'incrément Alpha, c'est sur cette partie que l'hypothèse de linéarité de F
- est vérifiée.
+ S'il est egal a 0 sur une partie seulement du domaine de variation de
+ l'increment Alpha, c'est sur cette partie que l'hypothese de linearite de F
+ est verifiee.
On prend dX0 = Normal(0,X) et dX = Alpha*dX0. F est le code de calcul.
""" + __precision
#
if len(self._parameters["ResultTitle"]) > 0:
- msgs = "\n"
- msgs += __marge + "====" + "="*len(self._parameters["ResultTitle"]) + "====\n"
- msgs += __marge + " " + self._parameters["ResultTitle"] + "\n"
- msgs += __marge + "====" + "="*len(self._parameters["ResultTitle"]) + "====\n"
+ __rt = unicode(self._parameters["ResultTitle"])
+ msgs = u"\n"
+ msgs += __marge + "====" + "="*len(__rt) + "====\n"
+ msgs += __marge + " " + __rt + "\n"
+ msgs += __marge + "====" + "="*len(__rt) + "====\n"
else:
- msgs = ""
+ msgs = u""
msgs += __msgdoc
#
__nbtirets = len(__entete)
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
name = "Minimizer",
default = "LBFGSB",
typecast = str,
- message = "Minimiseur utilisé",
+ message = "Minimiseur utilisé",
listval = ["LBFGSB","TNC", "CG", "NCG", "BFGS", "LM"],
)
self.defineRequiredParameter(
name = "CostDecrementTolerance",
default = 1.e-7,
typecast = float,
- message = "Diminution relative minimale du cout lors de l'arrêt",
+ message = "Diminution relative minimale du cout lors de l'arrêt",
)
self.defineRequiredParameter(
name = "ProjectedGradientTolerance",
default = -1,
typecast = float,
- message = "Maximum des composantes du gradient projeté lors de l'arrêt",
+ message = "Maximum des composantes du gradient projeté lors de l'arrêt",
minval = -1,
)
self.defineRequiredParameter(
name = "GradientNormTolerance",
default = 1.e-05,
typecast = float,
- message = "Maximum des composantes du gradient lors de l'arrêt",
+ message = "Maximum des composantes du gradient lors de l'arrêt",
)
self.defineRequiredParameter(
name = "StoreInternalVariables",
default = False,
typecast = bool,
- message = "Stockage des variables internes ou intermédiaires du calcul",
+ message = "Stockage des variables internes ou intermédiaires du calcul",
)
self.defineRequiredParameter(
name = "StoreSupplementaryCalculations",
default = [],
typecast = tuple,
- message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
+ message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
listval = ["BMA", "OMA", "OMB", "CostFunctionJ", "CostFunctionJb", "CostFunctionJo", "CurrentState", "CurrentOptimum", "IndexOfOptimum", "Innovation", "InnovationAtCurrentState", "CostFunctionJAtCurrentOptimum", "SimulatedObservationAtBackground", "SimulatedObservationAtCurrentState", "SimulatedObservationAtOptimum", "SimulatedObservationAtCurrentOptimum"]
)
self.defineRequiredParameter( # Pas de type
if "Minimizer" in self._parameters and self._parameters["Minimizer"] == "TNC":
self.setParameterValue("StoreInternalVariables",True)
#
- # Opérateurs
+ # Opérateurs
# ----------
Hm = HO["Direct"].appliedTo
Ha = HO["Adjoint"].appliedInXTo
#
- # Utilisation éventuelle d'un vecteur H(Xb) précalculé
+ # Utilisation éventuelle d'un vecteur H(Xb) précalculé
# ----------------------------------------------------
- if HO["AppliedToX"] is not None and "HXb" in HO["AppliedToX"]:
- HXb = Hm( Xb, HO["AppliedToX"]["HXb"])
+ if HO["AppliedInX"] is not None and "HXb" in HO["AppliedInX"]:
+ HXb = Hm( Xb, HO["AppliedInX"]["HXb"])
else:
HXb = Hm( Xb )
HXb = numpy.asmatrix(numpy.ravel( HXb )).T
if max(Y.shape) != max(HXb.shape):
raise ValueError("The shapes %s of observations Y and %s of observed calculation H(X) are different, they have to be identical."%(Y.shape,HXb.shape))
#
- # Précalcul des inversions de B et R
+ # Précalcul des inversions de B et R
# ----------------------------------
RI = R.getI()
if self._parameters["Minimizer"] == "LM":
RdemiI = R.choleskyI()
#
- # Définition de la fonction-coût
+ # Définition de la fonction-coût
# ------------------------------
def CostFunction(x):
_X = numpy.asmatrix(numpy.ravel( x )).T
GradJ = numpy.asmatrix( numpy.ravel( GradJb ) + numpy.ravel( GradJo ) ).T
return - RdemiI*HO["Tangent"].asMatrix( _X )
#
- # Point de démarrage de l'optimisation : Xini = Xb
+ # Point de démarrage de l'optimisation : Xini = Xb
# ------------------------------------
Xini = numpy.ravel(Xb)
#
HXa = Hm(Xa)
#
#
- # Calculs et/ou stockages supplémentaires
+ # Calculs et/ou stockages supplémentaires
# ---------------------------------------
if "Innovation" in self._parameters["StoreSupplementaryCalculations"] or \
"OMB" in self._parameters["StoreSupplementaryCalculations"]:
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
name = "MaximumNumberOfFunctionEvaluations",
default = 15000,
typecast = int,
- message = "Nombre maximal d'évaluations de la fonction",
+ message = "Nombre maximal d'évaluations de la fonction",
minval = -1,
)
self.defineRequiredParameter(
name = "SetSeed",
typecast = numpy.random.seed,
- message = "Graine fixée pour le générateur aléatoire",
+ message = "Graine fixée pour le générateur aléatoire",
)
self.defineRequiredParameter(
name = "NumberOfInsects",
name = "SwarmVelocity",
default = 1.,
typecast = float,
- message = "Vitesse de groupe imposée par l'essaim",
+ message = "Vitesse de groupe imposée par l'essaim",
minval = 0.,
)
self.defineRequiredParameter(
name = "QualityCriterion",
default = "AugmentedWeightedLeastSquares",
typecast = str,
- message = "Critère de qualité utilisé",
+ message = "Critère de qualité utilisé",
listval = ["AugmentedWeightedLeastSquares","AWLS","AugmentedPonderatedLeastSquares","APLS","DA",
"WeightedLeastSquares","WLS","PonderatedLeastSquares","PLS",
"LeastSquares","LS","L2",
name = "StoreInternalVariables",
default = False,
typecast = bool,
- message = "Stockage des variables internes ou intermédiaires du calcul",
+ message = "Stockage des variables internes ou intermédiaires du calcul",
)
self.defineRequiredParameter(
name = "StoreSupplementaryCalculations",
default = [],
typecast = tuple,
- message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
+ message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
listval = ["BMA", "OMA", "OMB", "CurrentState", "CostFunctionJ", "CostFunctionJb", "CostFunctionJo", "Innovation", "SimulatedObservationAtBackground", "SimulatedObservationAtCurrentState", "SimulatedObservationAtOptimum"]
)
self.defineRequiredParameter( # Pas de type
name = "BoxBounds",
- message = "Liste des valeurs de bornes d'incréments de paramètres",
+ message = "Liste des valeurs de bornes d'incréments de paramètres",
)
def run(self, Xb=None, Y=None, U=None, HO=None, EM=None, CM=None, R=None, B=None, Q=None, Parameters=None):
self._pre_run(Parameters)
#
- if "BoxBounds" in self._parameters and (type(self._parameters["BoxBounds"]) is type([]) or type(self._parameters["BoxBounds"]) is type(())) and (len(self._parameters["BoxBounds"]) > 0):
+ if ("BoxBounds" in self._parameters) and isinstance(self._parameters["BoxBounds"], (list, tuple)) and (len(self._parameters["BoxBounds"]) > 0):
BoxBounds = self._parameters["BoxBounds"]
- logging.debug("%s Prise en compte des bornes d'incréments de paramètres effectuee"%(self._name,))
+ logging.debug("%s Prise en compte des bornes d'incréments de paramètres effectuee"%(self._name,))
else:
raise ValueError("Particle Swarm Optimization requires bounds on all variables to be given.")
BoxBounds = numpy.array(BoxBounds)
#
Phig = float( self._parameters["GroupRecallRate"] )
Phip = 1. - Phig
- logging.debug("%s Taux de rappel au meilleur insecte du groupe (entre 0 et 1) = %s et à la meilleure position précédente (son complémentaire à 1) = %s"%(self._name, str(Phig), str(Phip)))
+ logging.debug("%s Taux de rappel au meilleur insecte du groupe (entre 0 et 1) = %s et à la meilleure position précédente (son complémentaire à 1) = %s"%(self._name, str(Phig), str(Phip)))
#
- # Opérateur d'observation
+ # Opérateur d'observation
# -----------------------
Hm = HO["Direct"].appliedTo
#
- # Précalcul des inversions de B et R
+ # Précalcul des inversions de B et R
# ----------------------------------
BI = B.getI()
RI = R.getI()
#
- # Définition de la fonction-coût
+ # Définition de la fonction-coût
# ------------------------------
def CostFunction(x, QualityMeasure="AugmentedWeightedLeastSquares"):
_X = numpy.asmatrix(numpy.ravel( x )).T
#
return J
#
- # Point de démarrage de l'optimisation : Xini = Xb
+ # Point de démarrage de l'optimisation : Xini = Xb
# ------------------------------------
- if type(Xb) is type(numpy.matrix([])):
+ if isinstance(Xb, type(numpy.matrix([]))):
Xini = Xb.A1.tolist()
elif Xb is not None:
Xini = list(Xb)
if quality < qBest:
Best = copy.copy( insect )
qBest = copy.copy( quality )
- logging.debug("%s Initialisation, Insecte = %s, Qualité = %s"%(self._name, str(Best), str(qBest)))
+ logging.debug("%s Initialisation, Insecte = %s, Qualité = %s"%(self._name, str(Best), str(qBest)))
#
if self._parameters["StoreInternalVariables"] or "CurrentState" in self._parameters["StoreSupplementaryCalculations"]:
self.StoredVariables["CurrentState"].store( Best )
if quality < qBest :
Best = copy.copy( insect )
qBest = copy.copy( quality )
- logging.debug("%s Etape %i, Insecte = %s, Qualité = %s"%(self._name, n, str(Best), str(qBest)))
+ logging.debug("%s Etape %i, Insecte = %s, Qualité = %s"%(self._name, n, str(Best), str(qBest)))
#
if self._parameters["StoreInternalVariables"] or "CurrentState" in self._parameters["StoreSupplementaryCalculations"]:
self.StoredVariables["CurrentState"].store( Best )
"SimulatedObservationAtOptimum" in self._parameters["StoreSupplementaryCalculations"]:
HXa = Hm(Xa)
#
- # Calculs et/ou stockages supplémentaires
+ # Calculs et/ou stockages supplémentaires
# ---------------------------------------
if "Innovation" in self._parameters["StoreSupplementaryCalculations"]:
self.StoredVariables["Innovation"].store( numpy.ravel(d) )
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
name = "Minimizer",
default = "MMQR",
typecast = str,
- message = "Minimiseur utilisé",
+ message = "Minimiseur utilisé",
listval = ["MMQR"],
)
self.defineRequiredParameter(
name = "CostDecrementTolerance",
default = 1.e-6,
typecast = float,
- message = "Maximum de variation de la fonction d'estimation lors de l'arrêt",
+ message = "Maximum de variation de la fonction d'estimation lors de l'arrêt",
)
self.defineRequiredParameter(
name = "StoreInternalVariables",
default = False,
typecast = bool,
- message = "Stockage des variables internes ou intermédiaires du calcul",
+ message = "Stockage des variables internes ou intermédiaires du calcul",
)
self.defineRequiredParameter(
name = "StoreSupplementaryCalculations",
default = [],
typecast = tuple,
- message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
+ message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
listval = ["BMA", "OMA", "OMB", "CurrentState", "CostFunctionJ", "CostFunctionJb", "CostFunctionJo", "Innovation", "SimulatedObservationAtBackground", "SimulatedObservationAtCurrentState", "SimulatedObservationAtOptimum"]
)
self.defineRequiredParameter( # Pas de type
#
Hm = HO["Direct"].appliedTo
#
- # Utilisation éventuelle d'un vecteur H(Xb) précalculé
+ # Utilisation éventuelle d'un vecteur H(Xb) précalculé
# ----------------------------------------------------
- if HO["AppliedToX"] is not None and "HXb" in HO["AppliedToX"]:
- HXb = Hm( Xb, HO["AppliedToX"]["HXb"])
+ if HO["AppliedInX"] is not None and "HXb" in HO["AppliedInX"]:
+ HXb = Hm( Xb, HO["AppliedInX"]["HXb"])
else:
HXb = Hm( Xb )
HXb = numpy.asmatrix(numpy.ravel( HXb )).T
raise ValueError("The shapes %s of observations Y and %s of observed calculation H(X) are different, they have to be identical."%(Y.shape,HXb.shape))
d = Y - HXb
#
- # Définition de la fonction-coût
+ # Définition de la fonction-coût
# ------------------------------
def CostFunction(x):
_X = numpy.asmatrix(numpy.ravel( x )).T
Hg = HO["Tangent"].asMatrix( _X )
return Hg
#
- # Point de démarrage de l'optimisation : Xini = Xb
+ # Point de démarrage de l'optimisation : Xini = Xb
# ------------------------------------
- if type(Xb) is type(numpy.matrix([])):
+ if isinstance(Xb, type(numpy.matrix([]))):
Xini = Xb.A1.tolist()
else:
Xini = list(Xb)
"SimulatedObservationAtOptimum" in self._parameters["StoreSupplementaryCalculations"]:
HXa = Hm(Xa)
#
- # Calculs et/ou stockages supplémentaires
+ # Calculs et/ou stockages supplémentaires
# ---------------------------------------
if "Innovation" in self._parameters["StoreSupplementaryCalculations"]:
self.StoredVariables["Innovation"].store( numpy.ravel(d) )
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
name = "SampleAsnUplet",
default = [],
typecast = tuple,
- message = "Points de calcul définis par une liste de n-uplet",
+ message = "Points de calcul définis par une liste de n-uplet",
)
self.defineRequiredParameter(
name = "SampleAsExplicitHyperCube",
default = [],
typecast = tuple,
- message = "Points de calcul définis par un hyper-cube dont on donne la liste des échantillonages de chaque variable comme une liste",
+ message = "Points de calcul définis par un hyper-cube dont on donne la liste des échantillonages de chaque variable comme une liste",
)
self.defineRequiredParameter(
name = "SampleAsMinMaxStepHyperCube",
default = [],
typecast = tuple,
- message = "Points de calcul définis par un hyper-cube dont on donne la liste des échantillonages de chaque variable par un triplet [min,max,step]",
+ message = "Points de calcul définis par un hyper-cube dont on donne la liste des échantillonages de chaque variable par un triplet [min,max,step]",
)
self.defineRequiredParameter(
name = "SampleAsIndependantRandomVariables",
default = [],
typecast = tuple,
- message = "Points de calcul définis par un hyper-cube dont les points sur chaque axe proviennent de l'échantillonage indépendant de la variable selon la spécification ['distribution',[parametres],nombre]",
+ message = "Points de calcul définis par un hyper-cube dont les points sur chaque axe proviennent de l'échantillonage indépendant de la variable selon la spécification ['distribution',[parametres],nombre]",
)
self.defineRequiredParameter(
name = "QualityCriterion",
default = "AugmentedWeightedLeastSquares",
typecast = str,
- message = "Critère de qualité utilisé",
+ message = "Critère de qualité utilisé",
listval = ["AugmentedWeightedLeastSquares","AWLS","AugmentedPonderatedLeastSquares","APLS","DA",
"WeightedLeastSquares","WLS","PonderatedLeastSquares","PLS",
"LeastSquares","LS","L2",
name = "SetDebug",
default = False,
typecast = bool,
- message = "Activation du mode debug lors de l'exécution",
+ message = "Activation du mode debug lors de l'exécution",
)
self.defineRequiredParameter(
name = "StoreSupplementaryCalculations",
default = [],
typecast = tuple,
- message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
+ message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
listval = ["CostFunctionJ", "CostFunctionJb", "CostFunctionJo","CurrentState","InnovationAtCurrentState","SimulatedObservationAtCurrentState"]
)
self.defineRequiredParameter(
name = "SetSeed",
typecast = numpy.random.seed,
- message = "Graine fixée pour le générateur aléatoire",
+ message = "Graine fixée pour le générateur aléatoire",
)
def run(self, Xb=None, Y=None, U=None, HO=None, EM=None, CM=None, R=None, B=None, Q=None, Parameters=None):
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
self.defineRequiredParameter(
name = "SetSeed",
typecast = numpy.random.seed,
- message = "Graine fixée pour le générateur aléatoire",
+ message = "Graine fixée pour le générateur aléatoire",
)
self.defineRequiredParameter(
name = "LengthOfTabuList",
name = "NumberOfElementaryPerturbations",
default = 1,
typecast = int,
- message = "Nombre de perturbations élémentaires pour choisir une perturbation d'état",
+ message = "Nombre de perturbations élémentaires pour choisir une perturbation d'état",
minval = 1,
)
self.defineRequiredParameter(
name = "NoiseDistribution",
default = "Uniform",
typecast = str,
- message = "Distribution pour générer les perturbations d'état",
+ message = "Distribution pour générer les perturbations d'état",
listval = ["Gaussian","Uniform"],
)
self.defineRequiredParameter(
name = "QualityCriterion",
default = "AugmentedWeightedLeastSquares",
typecast = str,
- message = "Critère de qualité utilisé",
+ message = "Critère de qualité utilisé",
listval = ["AugmentedWeightedLeastSquares","AWLS","DA",
"WeightedLeastSquares","WLS",
"LeastSquares","LS","L2",
name = "NoiseHalfRange",
default = [],
typecast = numpy.matrix,
- message = "Demi-amplitude des perturbations uniformes centrées d'état pour chaque composante de l'état",
+ message = "Demi-amplitude des perturbations uniformes centrées d'état pour chaque composante de l'état",
)
self.defineRequiredParameter(
name = "StandardDeviation",
default = [],
typecast = numpy.matrix,
- message = "Ecart-type des perturbations gaussiennes d'état pour chaque composante de l'état",
+ message = "Ecart-type des perturbations gaussiennes d'état pour chaque composante de l'état",
)
self.defineRequiredParameter(
name = "NoiseAddingProbability",
default = 1.,
typecast = float,
- message = "Probabilité de perturbation d'une composante de l'état",
+ message = "Probabilité de perturbation d'une composante de l'état",
minval = 0.,
maxval = 1.,
)
name = "StoreInternalVariables",
default = False,
typecast = bool,
- message = "Stockage des variables internes ou intermédiaires du calcul",
+ message = "Stockage des variables internes ou intermédiaires du calcul",
)
self.defineRequiredParameter(
name = "StoreSupplementaryCalculations",
default = [],
typecast = tuple,
- message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
+ message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
listval = ["BMA", "OMA", "OMB", "CurrentState", "CostFunctionJ", "CostFunctionJb", "CostFunctionJo", "Innovation", "SimulatedObservationAtBackground", "SimulatedObservationAtCurrentState", "SimulatedObservationAtOptimum"]
)
self.defineRequiredParameter( # Pas de type
if sigma.size != Xb.size:
raise ValueError("Noise generation by Gaussian distribution requires standard deviation for all variable increments. The actual standard deviation vector is:\n%s"%sigma)
#
- # Opérateur d'observation
+ # Opérateur d'observation
# -----------------------
Hm = HO["Direct"].appliedTo
#
- # Précalcul des inversions de B et R
+ # Précalcul des inversions de B et R
# ----------------------------------
BI = B.getI()
RI = R.getI()
#
- # Définition de la fonction de deplacement
+ # Définition de la fonction de deplacement
# ----------------------------------------
def Tweak( x, NoiseDistribution, NoiseAddingProbability ):
_X = numpy.matrix(numpy.ravel( x )).T
for i in range(_X.size):
if NoiseAddingProbability >= numpy.random.uniform():
_increment = numpy.random.uniform(low=-nrange[i], high=nrange[i])
- # On ne traite pas encore le dépassement des bornes ici
+ # On ne traite pas encore le dépassement des bornes ici
_X[i] += _increment
elif NoiseDistribution == "Gaussian":
for i in range(_X.size):
if NoiseAddingProbability >= numpy.random.uniform():
_increment = numpy.random.normal(loc=0., scale=sigma[i])
- # On ne traite pas encore le dépassement des bornes ici
+ # On ne traite pas encore le dépassement des bornes ici
_X[i] += _increment
#
return _X
)
for nbt in range(self._parameters["NumberOfElementaryPerturbations"]-1):
_W = Tweak( _S, self._parameters["NoiseDistribution"], self._parameters["NoiseAddingProbability"] )
- # _qualityW = CostFunction( _W, self._parameters["QualityCriterion"] )
+ #Â _qualityW = CostFunction( _W, self._parameters["QualityCriterion"] )
_qualityW = BasicObjects.CostFunction3D(
_W,
_Hm = Hm,
"SimulatedObservationAtOptimum" in self._parameters["StoreSupplementaryCalculations"]:
HXa = Hm(Xa)
#
- # Calculs et/ou stockages supplémentaires
+ # Calculs et/ou stockages supplémentaires
# ---------------------------------------
if "Innovation" in self._parameters["StoreSupplementaryCalculations"]:
self.StoredVariables["Innovation"].store( numpy.ravel(d) )
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
#
# Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
-import logging
+import sys, logging
from daCore import BasicObjects, PlatformInfo
import numpy, math
mpr = PlatformInfo.PlatformInfo().MachinePrecision()
+if sys.version_info.major > 2:
+ unicode = str
# ==============================================================================
class ElementaryAlgorithm(BasicObjects.Algorithm):
name = "ResiduFormula",
default = "Taylor",
typecast = str,
- message = "Formule de résidu utilisée",
+ message = "Formule de résidu utilisée",
listval = ["Taylor"],
)
self.defineRequiredParameter(
name = "EpsilonMinimumExponent",
default = -8,
typecast = int,
- message = "Exposant minimal en puissance de 10 pour le multiplicateur d'incrément",
+ message = "Exposant minimal en puissance de 10 pour le multiplicateur d'incrément",
minval = -20,
maxval = 0,
)
name = "InitialDirection",
default = [],
typecast = list,
- message = "Direction initiale de la dérivée directionnelle autour du point nominal",
+ message = "Direction initiale de la dérivée directionnelle autour du point nominal",
)
self.defineRequiredParameter(
name = "AmplitudeOfInitialDirection",
default = 1.,
typecast = float,
- message = "Amplitude de la direction initiale de la dérivée directionnelle autour du point nominal",
+ message = "Amplitude de la direction initiale de la dérivée directionnelle autour du point nominal",
)
self.defineRequiredParameter(
name = "AmplitudeOfTangentPerturbation",
self.defineRequiredParameter(
name = "SetSeed",
typecast = numpy.random.seed,
- message = "Graine fixée pour le générateur aléatoire",
+ message = "Graine fixée pour le générateur aléatoire",
)
self.defineRequiredParameter(
name = "ResultTitle",
name = "StoreSupplementaryCalculations",
default = [],
typecast = tuple,
- message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
+ message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
listval = ["CurrentState", "Residu", "SimulatedObservationAtCurrentState"]
)
if "SimulatedObservationAtCurrentState" in self._parameters["StoreSupplementaryCalculations"]:
self.StoredVariables["SimulatedObservationAtCurrentState"].store( numpy.ravel(FX) )
#
- # Fabrication de la direction de l'incrément dX
- # ----------------------------------------------
+ # Fabrication de la direction de l'increment dX
+ # ---------------------------------------------
if len(self._parameters["InitialDirection"]) == 0:
dX0 = []
for v in Xn.A1:
#
dX0 = float(self._parameters["AmplitudeOfInitialDirection"]) * numpy.matrix( dX0 ).T
#
- # Calcul du gradient au point courant X pour l'incrément dX
- # qui est le tangent en X multiplié par dX
+ # Calcul du gradient au point courant X pour l'increment dX
+ # qui est le tangent en X multiplie par dX
# ---------------------------------------------------------
dX1 = float(self._parameters["AmplitudeOfTangentPerturbation"]) * dX0
GradFxdX = Ht( (Xn, dX1) )
#
# Entete des resultats
# --------------------
- __marge = 12*" "
- __precision = """
+ __marge = 12*u" "
+ __precision = u"""
Remarque : les nombres inferieurs a %.0e (environ) representent un zero
a la precision machine.\n"""%mpr
if self._parameters["ResiduFormula"] == "Taylor":
- __entete = " i Alpha ||X|| ||F(X)|| | R(Alpha) |R-1|/Alpha "
- __msgdoc = """
- On observe le résidu provenant du rapport d'incréments utilisant le
- linéaire tangent :
+ __entete = u" i Alpha ||X|| ||F(X)|| | R(Alpha) |R-1|/Alpha "
+ __msgdoc = u"""
+ On observe le residu provenant du rapport d'increments utilisant le
+ lineaire tangent :
|| F(X+Alpha*dX) - F(X) ||
R(Alpha) = -----------------------------
|| Alpha * TangentF_X * dX ||
- qui doit rester stable en 1+O(Alpha) jusqu'à ce que l'on atteigne la
- précision du calcul.
-
- Lorsque |R-1|/Alpha est inférieur ou égal à une valeur stable
- lorsque Alpha varie, le tangent est valide, jusqu'à ce que l'on
- atteigne la précision du calcul.
-
- Si |R-1|/Alpha est très faible, le code F est vraisemblablement
- linéaire ou quasi-linéaire, et le tangent est valide jusqu'à ce que
- l'on atteigne la précision du calcul.
+ qui doit rester stable en 1+O(Alpha) jusqu'a ce que l'on atteigne la
+ precision du calcul.
+
+ Lorsque |R-1|/Alpha est inferieur ou egal a une valeur stable
+ lorsque Alpha varie, le tangent est valide, jusqu'a ce que l'on
+ atteigne la precision du calcul.
+
+ Si |R-1|/Alpha est tres faible, le code F est vraisemblablement
+ lineaire ou quasi-lineaire, et le tangent est valide jusqu'a ce que
+ l'on atteigne la precision du calcul.
On prend dX0 = Normal(0,X) et dX = Alpha*dX0. F est le code de calcul.
""" + __precision
#
if len(self._parameters["ResultTitle"]) > 0:
- msgs = "\n"
- msgs += __marge + "====" + "="*len(self._parameters["ResultTitle"]) + "====\n"
- msgs += __marge + " " + self._parameters["ResultTitle"] + "\n"
- msgs += __marge + "====" + "="*len(self._parameters["ResultTitle"]) + "====\n"
+ __rt = unicode(self._parameters["ResultTitle"])
+ msgs = u"\n"
+ msgs += __marge + "====" + "="*len(__rt) + "====\n"
+ msgs += __marge + " " + __rt + "\n"
+ msgs += __marge + "====" + "="*len(__rt) + "====\n"
else:
- msgs = ""
+ msgs = u""
msgs += __msgdoc
#
__nbtirets = len(__entete)
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
name = "StoreInternalVariables",
default = False,
typecast = bool,
- message = "Stockage des variables internes ou intermédiaires du calcul",
+ message = "Stockage des variables internes ou intermédiaires du calcul",
)
self.defineRequiredParameter(
name = "StoreSupplementaryCalculations",
default = [],
typecast = tuple,
- message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
+ message = "Liste de calculs supplémentaires à stocker et/ou effectuer",
listval = ["APosterioriCorrelations", "APosterioriCovariance", "APosterioriStandardDeviations", "APosterioriVariances", "BMA", "CurrentState", "CostFunctionJ", "CostFunctionJb", "CostFunctionJo", "Innovation"]
)
self.defineRequiredParameter( # Pas de type
Wc = numpy.array( Ww )
Wc[0] = Lambda / (L + Lambda) + (1. - Alpha**2 + Beta)
#
- # Opérateurs
+ # Opérateurs
# ----------
if B is None:
raise ValueError("Background error covariance matrix has to be properly defined!")
else:
duration = 2
#
- # Précalcul des inversions de B et R
+ # Précalcul des inversions de B et R
# ----------------------------------
if self._parameters["StoreInternalVariables"]:
BI = B.getI()
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
--- /dev/null
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2008-2017 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
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+# Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
+
+"""
+ Normalized interface for ADAO scripting (generic API)
+"""
+__author__ = "Jean-Philippe ARGAUD"
+__all__ = ["Aidsm"]
+
+import os, sys
+from daCore import ExtendedLogging ; ExtendedLogging.ExtendedLogging() # A importer en premier
+import logging
+#
+from daCore.BasicObjects import State, Covariance, FullOperator, Operator
+from daCore.BasicObjects import AlgorithmAndParameters, DataObserver
+from daCore.BasicObjects import DiagnosticAndParameters, ImportFromScript
+from daCore.Templates import ObserverTemplates
+from daCore import PlatformInfo
+
+# ==============================================================================
+class Aidsm(object):
+ """ ADAO Internal Data Structure Model """
+ def __init__(self, name = ""):
+ self.__name = str(name)
+ self.__case = _CaseLogger(self.__name)
+ #
+ self.__adaoObject = {}
+ self.__StoredInputs = {}
+ #
+ self.__Concepts = [
+ "AlgorithmParameters",
+ "Background",
+ "CheckingPoint",
+ "ControlInput",
+ "Observation",
+ "Controls",
+ "BackgroundError",
+ "ObservationError",
+ "EvolutionError",
+ "ObservationOperator",
+ "EvolutionModel",
+ "ControlModel",
+ "Debug",
+ "NoDebug",
+ "Observer",
+ ]
+ #
+ for ename in self.__Concepts:
+ self.__adaoObject[ename] = None
+ for ename in ("ObservationOperator", "EvolutionModel", "ControlModel", "Observer"):
+ self.__adaoObject[ename] = {}
+ for ename in ("Diagnostic", "Observer"):
+ self.__adaoObject[ename] = []
+ self.__StoredInputs[ename] = []
+ #
+ # 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,
+ # qui est activée dans Persistence)
+ self.__parent = os.path.abspath(os.path.join(os.path.dirname(__file__),".."))
+ sys.path.insert(0, self.__parent)
+ sys.path = PlatformInfo.uniq( sys.path ) # Conserve en unique exemplaire chaque chemin
+
+ def set(self,
+ Concept = None, # Premier argument
+ Algorithm = None,
+ AppliedInXb = None,
+ AvoidRC = True,
+ BaseType = None,
+ Checked = False,
+ Diagnostic = None,
+ DiagonalSparseMatrix = None,
+ Identifier = None,
+ Info = None,
+ Matrix = None,
+ ObjectFunction = None,
+ ObjectMatrix = None,
+ OneFunction = None,
+ Parameters = None,
+ ScalarSparseMatrix = None,
+ Scheduler = None,
+ Script = None,
+ Stored = False,
+ String = None,
+ Template = None,
+ ThreeFunctions = None,
+ Unit = None,
+ Variable = None,
+ Vector = None,
+ VectorSerie = None,
+ ):
+ "Interface unique de definition de variables d'entrees par argument"
+ self.__case.register("set",dir(),locals(),None,True)
+ try:
+ if Concept in ("Background", "CheckingPoint", "ControlInput", "Observation", "Controls"):
+ commande = getattr(self,"set"+Concept)
+ commande(Vector, VectorSerie, Script, Scheduler, Stored, Checked )
+ elif Concept in ("BackgroundError", "ObservationError", "EvolutionError"):
+ commande = getattr(self,"set"+Concept)
+ commande(Matrix, ScalarSparseMatrix, DiagonalSparseMatrix,
+ ObjectMatrix, Script, Stored, Checked )
+ elif Concept == "AlgorithmParameters":
+ self.setAlgorithmParameters( Algorithm, Parameters, Script )
+ elif Concept == "Debug":
+ self.setDebug()
+ elif Concept == "NoDebug":
+ self.setNoDebug()
+ elif Concept == "Observer":
+ self.setObserver( Variable, Template, String, Script, ObjectFunction, Scheduler, Info )
+ elif Concept == "Diagnostic":
+ self.setDiagnostic( Diagnostic, Identifier, Parameters, Script, Unit, BaseType )
+ elif Concept == "ObservationOperator":
+ self.setObservationOperator(
+ Matrix, OneFunction, ThreeFunctions, AppliedInXb,
+ Parameters, Script, AvoidRC, Stored, Checked )
+ elif Concept in ("EvolutionModel", "ControlModel"):
+ commande = getattr(self,"set"+Concept)
+ commande(
+ Matrix, OneFunction, ThreeFunctions,
+ Parameters, Script, Scheduler, AvoidRC, Stored, 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)
+ else: msg = ""
+ raise ValueError("during settings, the following error occurs:\n\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))
+
+ # -----------------------------------------------------------
+
+ def setBackground(self,
+ Vector = None,
+ VectorSerie = None,
+ Script = None,
+ Scheduler = None,
+ Stored = False,
+ Checked = False):
+ "Definition d'un concept de calcul"
+ Concept = "Background"
+ self.__case.register("set"+Concept, dir(), locals())
+ self.__adaoObject[Concept] = State(
+ name = Concept,
+ asVector = Vector,
+ asPersistentVector = VectorSerie,
+ asScript = Script,
+ scheduledBy = Scheduler,
+ toBeChecked = Checked,
+ )
+ if Stored:
+ self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
+ return 0
+
+ def setCheckingPoint(self,
+ Vector = None,
+ VectorSerie = None,
+ Script = None,
+ Scheduler = None,
+ Stored = False,
+ Checked = False):
+ "Definition d'un concept de calcul"
+ Concept = "CheckingPoint"
+ self.__case.register("set"+Concept, dir(), locals())
+ self.__adaoObject[Concept] = State(
+ name = Concept,
+ asVector = Vector,
+ asPersistentVector = VectorSerie,
+ asScript = Script,
+ scheduledBy = Scheduler,
+ toBeChecked = Checked,
+ )
+ if Stored:
+ self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
+ return 0
+
+ def setControlInput(self,
+ Vector = None,
+ VectorSerie = None,
+ Script = None,
+ Scheduler = None,
+ Stored = False,
+ Checked = False):
+ "Definition d'un concept de calcul"
+ Concept = "ControlInput"
+ self.__case.register("set"+Concept, dir(), locals())
+ self.__adaoObject[Concept] = State(
+ name = Concept,
+ asVector = Vector,
+ asPersistentVector = VectorSerie,
+ asScript = Script,
+ scheduledBy = Scheduler,
+ toBeChecked = Checked,
+ )
+ if Stored:
+ self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
+ return 0
+
+ def setObservation(self,
+ Vector = None,
+ VectorSerie = None,
+ Script = None,
+ Scheduler = None,
+ Stored = False,
+ Checked = False):
+ "Definition d'un concept de calcul"
+ Concept = "Observation"
+ self.__case.register("set"+Concept, dir(), locals())
+ self.__adaoObject[Concept] = State(
+ name = Concept,
+ asVector = Vector,
+ asPersistentVector = VectorSerie,
+ asScript = Script,
+ scheduledBy = Scheduler,
+ toBeChecked = Checked,
+ )
+ if Stored:
+ self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
+ return 0
+
+ def setControls(self,
+ Vector = (), # Valeur par defaut pour un vecteur vide
+ VectorSerie = None,
+ Script = None,
+ Scheduler = None,
+ Stored = False,
+ Checked = False):
+ "Definition d'un concept de calcul"
+ Concept = "Controls"
+ self.__case.register("set"+Concept, dir(), locals())
+ self.__adaoObject[Concept] = State(
+ name = Concept,
+ asVector = Vector,
+ asPersistentVector = VectorSerie,
+ asScript = Script,
+ scheduledBy = Scheduler,
+ toBeChecked = Checked,
+ )
+ if Stored:
+ self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
+ return 0
+
+ def setBackgroundError(self,
+ Matrix = None,
+ ScalarSparseMatrix = None,
+ DiagonalSparseMatrix = None,
+ ObjectMatrix = None,
+ Script = None,
+ Stored = False,
+ Checked = False):
+ "Definition d'un concept de calcul"
+ Concept = "BackgroundError"
+ self.__case.register("set"+Concept, dir(), locals())
+ self.__adaoObject[Concept] = Covariance(
+ name = Concept,
+ asCovariance = Matrix,
+ asEyeByScalar = ScalarSparseMatrix,
+ asEyeByVector = DiagonalSparseMatrix,
+ asCovObject = ObjectMatrix,
+ asScript = Script,
+ toBeChecked = Checked,
+ )
+ if Stored:
+ self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
+ return 0
+
+ def setObservationError(self,
+ Matrix = None,
+ ScalarSparseMatrix = None,
+ DiagonalSparseMatrix = None,
+ ObjectMatrix = None,
+ Script = None,
+ Stored = False,
+ Checked = False):
+ "Definition d'un concept de calcul"
+ Concept = "ObservationError"
+ self.__case.register("set"+Concept, dir(), locals())
+ self.__adaoObject[Concept] = Covariance(
+ name = Concept,
+ asCovariance = Matrix,
+ asEyeByScalar = ScalarSparseMatrix,
+ asEyeByVector = DiagonalSparseMatrix,
+ asCovObject = ObjectMatrix,
+ asScript = Script,
+ toBeChecked = Checked,
+ )
+ if Stored:
+ self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
+ return 0
+
+ def setEvolutionError(self,
+ Matrix = None,
+ ScalarSparseMatrix = None,
+ DiagonalSparseMatrix = None,
+ ObjectMatrix = None,
+ Script = None,
+ Stored = False,
+ Checked = False):
+ "Definition d'un concept de calcul"
+ Concept = "EvolutionError"
+ self.__case.register("set"+Concept, dir(), locals())
+ self.__adaoObject[Concept] = Covariance(
+ name = Concept,
+ asCovariance = Matrix,
+ asEyeByScalar = ScalarSparseMatrix,
+ asEyeByVector = DiagonalSparseMatrix,
+ asCovObject = ObjectMatrix,
+ asScript = Script,
+ toBeChecked = Checked,
+ )
+ if Stored:
+ self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
+ return 0
+
+ def setObservationOperator(self,
+ Matrix = None,
+ OneFunction = None,
+ ThreeFunctions = None,
+ AppliedInXb = None,
+ Parameters = None,
+ Script = None,
+ AvoidRC = True,
+ Stored = False,
+ Checked = False):
+ "Definition d'un concept de calcul"
+ Concept = "ObservationOperator"
+ self.__case.register("set"+Concept, dir(), locals())
+ self.__adaoObject[Concept] = FullOperator(
+ name = Concept,
+ asMatrix = Matrix,
+ asOneFunction = OneFunction,
+ asThreeFunctions = ThreeFunctions,
+ asScript = Script,
+ asDict = Parameters,
+ appliedInX = AppliedInXb,
+ avoidRC = AvoidRC,
+ scheduledBy = None,
+ toBeChecked = Checked,
+ )
+ if Stored:
+ self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
+ return 0
+
+ def setEvolutionModel(self,
+ Matrix = None,
+ OneFunction = None,
+ ThreeFunctions = None,
+ Parameters = None,
+ Script = None,
+ Scheduler = None,
+ AvoidRC = True,
+ Stored = False,
+ Checked = False):
+ "Definition d'un concept de calcul"
+ Concept = "EvolutionModel"
+ self.__case.register("set"+Concept, dir(), locals())
+ self.__adaoObject[Concept] = FullOperator(
+ name = Concept,
+ asMatrix = Matrix,
+ asOneFunction = OneFunction,
+ asThreeFunctions = ThreeFunctions,
+ asScript = Script,
+ asDict = Parameters,
+ appliedInX = None,
+ avoidRC = AvoidRC,
+ scheduledBy = Scheduler,
+ toBeChecked = Checked,
+ )
+ if Stored:
+ self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
+ return 0
+
+ def setControlModel(self,
+ Matrix = None,
+ OneFunction = None,
+ ThreeFunctions = None,
+ Parameters = None,
+ Script = None,
+ Scheduler = None,
+ AvoidRC = True,
+ Stored = False,
+ Checked = False):
+ "Definition d'un concept de calcul"
+ Concept = "ControlModel"
+ self.__case.register("set"+Concept, dir(), locals())
+ self.__adaoObject[Concept] = FullOperator(
+ name = Concept,
+ asMatrix = Matrix,
+ asOneFunction = OneFunction,
+ asThreeFunctions = ThreeFunctions,
+ asScript = Script,
+ asDict = Parameters,
+ appliedInX = None,
+ avoidRC = AvoidRC,
+ scheduledBy = Scheduler,
+ toBeChecked = Checked,
+ )
+ if Stored:
+ self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
+ return 0
+
+ def setDebug(self, level = 10):
+ "NOTSET=0 < DEBUG=10 < INFO=20 < WARNING=30 < ERROR=40 < CRITICAL=50"
+ self.__case.register("setDebug",dir(),locals())
+ log = logging.getLogger()
+ log.setLevel( level )
+ self.__StoredInputs["Debug"] = level
+ self.__StoredInputs["NoDebug"] = False
+ return 0
+
+ def setNoDebug(self):
+ "NOTSET=0 < DEBUG=10 < INFO=20 < WARNING=30 < ERROR=40 < CRITICAL=50"
+ self.__case.register("setNoDebug",dir(),locals())
+ log = logging.getLogger()
+ log.setLevel( logging.WARNING )
+ self.__StoredInputs["Debug"] = logging.WARNING
+ self.__StoredInputs["NoDebug"] = True
+ return 0
+
+ def setAlgorithmParameters(self,
+ Algorithm = None,
+ Parameters = None,
+ Script = None):
+ "Definition d'un concept de calcul"
+ Concept = "AlgorithmParameters"
+ self.__case.register("set"+Concept, dir(), locals())
+ self.__adaoObject[Concept] = AlgorithmAndParameters(
+ name = Concept,
+ asAlgorithm = Algorithm,
+ asDict = Parameters,
+ asScript = Script,
+ )
+ return 0
+
+ def updateAlgorithmParameters(self,
+ 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(
+ asDict = Parameters,
+ asScript = Script,
+ )
+ return 0
+
+ def setObserver(self,
+ Variable = None,
+ Template = None,
+ String = None,
+ Script = None,
+ ObjectFunction = None,
+ Scheduler = None,
+ Info = None):
+ "Definition d'un concept de calcul"
+ Concept = "Observer"
+ self.__case.register("set"+Concept, dir(), locals())
+ self.__adaoObject[Concept].append( DataObserver(
+ name = Concept,
+ onVariable = Variable,
+ asTemplate = Template,
+ asString = String,
+ asScript = Script,
+ asObsObject = ObjectFunction,
+ withInfo = Info,
+ scheduledBy = Scheduler,
+ withAlgo = self.__adaoObject["AlgorithmParameters"]
+ ))
+ return 0
+
+ def removeObserver(self,
+ Variable = None,
+ ObjectFunction = None,
+ ):
+ """
+ Permet de retirer un observer à une ou des variable nommée.
+ """
+ if "AlgorithmParameters" not in self.__adaoObject:
+ raise ValueError("No algorithm registred, ask for one before removing observers")
+ #
+ # Vérification du nom de variable et typage
+ # -----------------------------------------
+ if isinstance(Variable, str):
+ VariableNames = (Variable,)
+ elif isinstance(Variable, list):
+ VariableNames = tuple(map( str, Variable ))
+ else:
+ raise ValueError("The observer requires a name or a list of names of variables.")
+ #
+ # Association interne de l'observer à la variable
+ # -----------------------------------------------
+ for ename in VariableNames:
+ if ename not in self.__adaoObject["AlgorithmParameters"]:
+ raise ValueError("An observer requires to be removed on a variable named %s which does not exist."%ename)
+ else:
+ return self.__adaoObject["AlgorithmParameters"].removeObserver( ename, ObjectFunction )
+
+ # -----------------------------------------------------------
+
+ def setDiagnostic(self,
+ Diagnostic = None,
+ Identifier = None,
+ Parameters = None,
+ Script = None,
+ Unit = None,
+ BaseType = None):
+ "Definition d'un concept de calcul"
+ Concept = "Diagnostic"
+ self.__case.register("set"+Concept, dir(), locals())
+ self.__adaoObject[Concept].append( DiagnosticAndParameters(
+ name = Concept,
+ asDiagnostic = Diagnostic,
+ asIdentifier = Identifier,
+ asDict = Parameters,
+ asScript = Script,
+ asUnit = Unit,
+ asBaseType = BaseType,
+ asExistingDiags = self.__StoredInputs[Concept],
+ ))
+ self.__StoredInputs[Concept].append(str(Identifier))
+ return 0
+
+ def get(self, Concept=None, noDetails=True ):
+ "Recuperation d'une sortie du calcul"
+ """
+ Permet d'accéder aux informations stockées, diagnostics et résultats
+ disponibles après l'exécution du calcul. Attention, quand un diagnostic
+ porte le même nom qu'une variable stockée (paramètre ou résultat),
+ c'est la variable stockée qui est renvoyée, et le diagnostic est
+ inatteignable.
+ """
+ if Concept is not None:
+ try:
+ self.__case.register("get", dir(), locals(), Concept) # Break pickle in Python 2
+ except:
+ pass
+ if Concept in self.__StoredInputs:
+ return self.__StoredInputs[Concept]
+ #
+ elif self.__adaoObject["AlgorithmParameters"] is not None and Concept == "AlgorithmParameters":
+ return self.__adaoObject["AlgorithmParameters"].get()
+ #
+ elif self.__adaoObject["AlgorithmParameters"] is not None and Concept in self.__adaoObject["AlgorithmParameters"]:
+ return self.__adaoObject["AlgorithmParameters"].get( Concept )
+ #
+ elif Concept == "AlgorithmRequiredParameters" and self.__adaoObject["AlgorithmParameters"] is not None:
+ return self.__adaoObject["AlgorithmParameters"].getAlgorithmRequiredParameters(noDetails)
+ #
+ elif Concept in self.__StoredInputs["Diagnostic"]:
+ indice = self.__StoredInputs["Diagnostic"].index(Concept)
+ return self.__adaoObject["Diagnostic"][indice].get()
+ #
+ else:
+ raise ValueError("The requested key \"%s\" does not exists as an input, a diagnostic or a stored variable."%Concept)
+ else:
+ allvariables = {}
+ allvariables.update( {"AlgorithmParameters":self.__adaoObject["AlgorithmParameters"].get()} )
+ allvariables.update( self.__adaoObject["AlgorithmParameters"].get() )
+ allvariables.update( self.__StoredInputs )
+ allvariables.pop('Diagnostic', None)
+ allvariables.pop('Observer', None)
+ return allvariables
+
+ # -----------------------------------------------------------
+
+ def get_available_variables(self):
+ """
+ Renvoie les variables potentiellement utilisables pour l'étude,
+ initialement stockées comme données d'entrées ou dans les algorithmes,
+ identifiés par les chaînes de caractères. L'algorithme doit avoir été
+ préalablement choisi sinon la méthode renvoie "None".
+ """
+ if len(list(self.__adaoObject["AlgorithmParameters"].keys())) == 0 and \
+ len(list(self.__StoredInputs.keys())) == 0:
+ return None
+ else:
+ variables = []
+ if len(list(self.__adaoObject["AlgorithmParameters"].keys())) > 0:
+ variables.extend(list(self.__adaoObject["AlgorithmParameters"].keys()))
+ if len(list(self.__StoredInputs.keys())) > 0:
+ variables.extend( list(self.__StoredInputs.keys()) )
+ variables.remove('Diagnostic')
+ variables.remove('Observer')
+ variables.sort()
+ return variables
+
+ def get_available_algorithms(self):
+ """
+ Renvoie la liste des algorithmes potentiellement utilisables, identifiés
+ par les chaînes de caractères.
+ """
+ files = []
+ for directory in sys.path:
+ if os.path.isdir(os.path.join(directory,"daAlgorithms")):
+ for fname in os.listdir(os.path.join(directory,"daAlgorithms")):
+ root, ext = os.path.splitext(fname)
+ if ext == '.py' and root != '__init__':
+ files.append(root)
+ files.sort()
+ return files
+
+ def get_available_diagnostics(self):
+ """
+ Renvoie la liste des diagnostics potentiellement utilisables, identifiés
+ par les chaînes de caractères.
+ """
+ files = []
+ for directory in sys.path:
+ if os.path.isdir(os.path.join(directory,"daDiagnostics")):
+ for fname in os.listdir(os.path.join(directory,"daDiagnostics")):
+ root, ext = os.path.splitext(fname)
+ if ext == '.py' and root != '__init__':
+ files.append(root)
+ files.sort()
+ return files
+
+ # -----------------------------------------------------------
+
+ def get_algorithms_main_path(self):
+ """
+ Renvoie le chemin pour le répertoire principal contenant les algorithmes
+ dans un sous-répertoire "daAlgorithms"
+ """
+ return self.__parent
+
+ def add_algorithms_path(self, Path=None):
+ """
+ Ajoute au chemin de recherche des algorithmes un répertoire dans lequel
+ se trouve un sous-répertoire "daAlgorithms"
+
+ Remarque : si le chemin a déjà été ajouté pour les diagnostics, il n'est
+ pas indispensable de le rajouter ici.
+ """
+ if not os.path.isdir(Path):
+ raise ValueError("The given "+Path+" argument must exist as a directory")
+ if not os.path.isdir(os.path.join(Path,"daAlgorithms")):
+ raise ValueError("The given \""+Path+"\" argument must contain a subdirectory named \"daAlgorithms\"")
+ if not os.path.isfile(os.path.join(Path,"daAlgorithms","__init__.py")):
+ raise ValueError("The given \""+Path+"/daAlgorithms\" path must contain a file named \"__init__.py\"")
+ sys.path.insert(0, os.path.abspath(Path))
+ sys.path = PlatformInfo.uniq( sys.path ) # Conserve en unique exemplaire chaque chemin
+ return 0
+
+ def get_diagnostics_main_path(self):
+ """
+ Renvoie le chemin pour le répertoire principal contenant les diagnostics
+ dans un sous-répertoire "daDiagnostics"
+ """
+ return self.__parent
+
+ def add_diagnostics_path(self, Path=None):
+ """
+ Ajoute au chemin de recherche des algorithmes un répertoire dans lequel
+ se trouve un sous-répertoire "daDiagnostics"
+
+ Remarque : si le chemin a déjà été ajouté pour les algorithmes, il n'est
+ pas indispensable de le rajouter ici.
+ """
+ if not os.path.isdir(Path):
+ raise ValueError("The given "+Path+" argument must exist as a directory")
+ if not os.path.isdir(os.path.join(Path,"daDiagnostics")):
+ raise ValueError("The given \""+Path+"\" argument must contain a subdirectory named \"daDiagnostics\"")
+ if not os.path.isfile(os.path.join(Path,"daDiagnostics","__init__.py")):
+ raise ValueError("The given \""+Path+"/daDiagnostics\" path must contain a file named \"__init__.py\"")
+ sys.path.insert(0, os.path.abspath(Path))
+ sys.path = PlatformInfo.uniq( sys.path ) # Conserve en unique exemplaire chaque chemin
+ return 0
+
+ # -----------------------------------------------------------
+
+ def execute(self, Executor=None, FileName=None):
+ "Lancement du calcul"
+ self.__case.register("execute",dir(),locals(),None,True)
+ Operator.CM.clearCache()
+ #~ try:
+ if Executor == "YACS": self.__executeYACSScheme( FileName )
+ else: self.__executePythonScheme()
+ #~ except Exception as e:
+ #~ if isinstance(e, SyntaxError): msg = "at %s: %s"%(e.offset, e.text)
+ #~ else: msg = ""
+ #~ raise ValueError("during execution, the following error occurs:\n\n%s %s\n\nSee also the potential messages, which can show the origin of the above error, in the launching terminal.\n"%(str(e),msg))
+ return 0
+
+ def __executePythonScheme(self, FileName=None):
+ "Lancement du calcul"
+ self.__case.register("executePythonScheme", dir(), locals())
+ if FileName is not None:
+ self.dump( FileName, "TUI")
+ self.__adaoObject["AlgorithmParameters"].executePythonScheme( self.__adaoObject )
+ return 0
+
+ def __executeYACSScheme(self, FileName=None):
+ "Lancement du calcul"
+ self.__case.register("executeYACSScheme", dir(), locals())
+ if FileName is not None:
+ self.dump( FileName, "DIC")
+ self.__adaoObject["AlgorithmParameters"].executeYACSScheme( FileName )
+ return 0
+
+ # -----------------------------------------------------------
+
+ def dump(self, FileName=None, Formater="TUI"):
+ "Récupération normalisée de la liste des commandes"
+ return self.__case.dump(FileName, Formater)
+
+ def __dir__(self):
+ "Clarifie la visibilité des méthodes"
+ return ['set', 'get', 'execute', '__doc__', '__init__', '__module__']
+
+ def prepare_to_pickle(self):
+ "Retire les variables non pickelisables, avec recopie efficace"
+ if self.__adaoObject['AlgorithmParameters'] is not None:
+ 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.")
+ if self.__adaoObject['AlgorithmParameters'].hasObserver( k ):
+ self.__adaoObject['AlgorithmParameters'].removeObserver( k, "", True )
+ self.__StoredInputs[k] = self.__adaoObject['AlgorithmParameters'].pop(k, None)
+ del self.__adaoObject # Break pickle in Python 2
+ del self.__case # Break pickle in Python 2
+ return 0
+
+# ==============================================================================
+class _CaseLogger(object):
+ """
+ Conservation des commandes de creation d'un cas
+ """
+ def __init__(self, __name="", __objname="case"):
+ self.__name = str(__name)
+ self.__objname = str(__objname)
+ self.__logSerie = []
+ self.__switchoff = False
+
+ def register(self, __command=None, __keys=None, __local=None, __pre=None, __switchoff=False):
+ "Enregistrement d'une commande individuelle"
+ if __command is not None and __keys is not None and __local is not None and not self.__switchoff:
+ if "self" in __keys: __keys.remove("self")
+ self.__logSerie.append( (str(__command), __keys, __local, __pre, __switchoff) )
+ if __switchoff:
+ self.__switchoff = True
+ if not __switchoff:
+ self.__switchoff = False
+
+ def dump(self, __filename=None, __format="TUI"):
+ """
+ Récupération normalisée de la liste des commandes selon le Formater :
+ - TUI (API de référence)
+ - DIC (Transitoire, pour passer vers XML YACS)
+ - XML (Experimental. Structured AIDSM)
+ """
+ if __format == "TUI":
+ self.__dumper = _TUIViewer(self.__name, self.__objname, self.__logSerie)
+ __text = self.__dumper.dump(__filename)
+ elif __format == "DIC":
+ self.__dumper = _DICViewer(self.__name, self.__objname, self.__logSerie)
+ __text = self.__dumper.dump(__filename)
+ elif __format == "XML":
+ self.__dumper = _XMLViewer(self.__name, self.__objname, self.__logSerie)
+ __text = self.__dumper.dump(__filename)
+ else:
+ raise ValueError("Dumping as \"%s\" is not available"%__format)
+ return __text
+
+# ==============================================================================
+class _GenericCaseViewer(object):
+ """
+ Etablissement des commandes de creation d'une vue
+ """
+ def __init__(self, __name="", __objname="case", __content=None):
+ "Initialisation et enregistrement de l'entete"
+ self._name = str(__name)
+ self._objname = str(__objname)
+ self._lineSerie = []
+ self._switchoff = False
+ self._numobservers = 2
+ def _addLine(self, line=""):
+ "Ajoute un enregistrement individuel"
+ self._lineSerie.append(line)
+ def _finalize(self):
+ "Enregistrement du final"
+ pass
+ def _append(self):
+ "Transformation d'une commande individuelle en un enregistrement"
+ raise NotImplementedError()
+ def dump(self, __filename=None):
+ "Restitution de la liste des commandes de creation d'un cas"
+ self._finalize()
+ __text = "\n".join(self._lineSerie)
+ if __filename is not None:
+ __file = os.path.abspath(__filename)
+ fid = open(__file,"w")
+ fid.write(__text)
+ fid.close()
+ return __text
+
+class _TUIViewer(_GenericCaseViewer):
+ """
+ Etablissement des commandes de creation d'un cas TUI
+ """
+ def __init__(self, __name="", __objname="case", __content=None):
+ "Initialisation et enregistrement de l'entete"
+ _GenericCaseViewer.__init__(self, __name, __objname, __content)
+ self._addLine("#\n# Python script for ADAO TUI\n#")
+ self._addLine("from numpy import array, matrix")
+ self._addLine("import adaoBuilder")
+ self._addLine("%s = adaoBuilder.New('%s')"%(self._objname, self._name))
+ if __content is not None:
+ for command in __content:
+ self._append(*command)
+ def _append(self, __command=None, __keys=None, __local=None, __pre=None, __switchoff=False):
+ "Transformation d'une commande individuelle en un enregistrement"
+ if __command is not None and __keys is not None and __local is not None:
+ __text = ""
+ if __pre is not None:
+ __text += "%s = "%__pre
+ __text += "%s.%s( "%(self._objname,str(__command))
+ if "self" in __keys: __keys.remove("self")
+ if __command not in ("set","get") and "Concept" in __keys: __keys.remove("Concept")
+ for k in __keys:
+ __v = __local[k]
+ if __v is None: continue
+ if k == "Checked" and not __v: continue
+ if k == "Stored" and not __v: continue
+ if k == "AvoidRC" and __v: continue
+ if k == "noDetails": continue
+ __text += "%s=%s, "%(k,repr(__v))
+ __text.rstrip(", ")
+ __text += ")"
+ self._addLine(__text)
+
+class _DICViewer(_GenericCaseViewer):
+ """
+ Etablissement des commandes de creation d'un cas DIC
+ """
+ def __init__(self, __name="", __objname="case", __content=None):
+ "Initialisation et enregistrement de l'entete"
+ _GenericCaseViewer.__init__(self, __name, __objname, __content)
+ self._addLine("# -*- coding: utf-8 -*-")
+ self._addLine("#\n# Input for ADAO converter to YACS\n#")
+ self._addLine("from numpy import array, matrix")
+ self._addLine("#")
+ self._addLine("study_config = {}")
+ self._addLine("study_config['StudyType'] = 'ASSIMILATION_STUDY'")
+ self._addLine("study_config['Name'] = '%s'"%self._name)
+ self._addLine("observers = {}")
+ self._addLine("study_config['Observers'] = observers")
+ self._addLine("#")
+ self._addLine("inputvariables_config = {}")
+ self._addLine("inputvariables_config['Order'] =['adao_default']")
+ self._addLine("inputvariables_config['adao_default'] = -1")
+ self._addLine("study_config['InputVariables'] = inputvariables_config")
+ self._addLine("#")
+ self._addLine("outputvariables_config = {}")
+ self._addLine("outputvariables_config['Order'] = ['adao_default']")
+ self._addLine("outputvariables_config['adao_default'] = -1")
+ self._addLine("study_config['OutputVariables'] = outputvariables_config")
+ if __content is not None:
+ for command in __content:
+ self._append(*command)
+ def _append(self, __command=None, __keys=None, __local=None, __pre=None, __switchoff=False):
+ "Transformation d'une commande individuelle en un enregistrement"
+ if __command == "set": __command = __local["Concept"]
+ else: __command = __command.replace("set", "", 1)
+ #
+ __text = None
+ if __command in (None, 'execute', 'executePythonScheme', 'executeYACSScheme', 'get'):
+ return
+ elif __command in ['Debug', 'setDebug']:
+ __text = "#\nstudy_config['Debug'] = '1'"
+ elif __command in ['NoDebug', 'setNoDebug']:
+ __text = "#\nstudy_config['Debug'] = '0'"
+ elif __command in ['Observer', 'setObserver']:
+ __obs = __local['Variable']
+ self._numobservers += 1
+ __text = "#\n"
+ __text += "observers['%s'] = {}\n"%__obs
+ if __local['String'] is not None:
+ __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'String')
+ __text += "observers['%s']['String'] = \"\"\"%s\"\"\"\n"%(__obs, __local['String'])
+ if __local['Script'] is not None:
+ __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'Script')
+ __text += "observers['%s']['Script'] = \"%s\"\n"%(__obs, __local['Script'])
+ if __local['Template'] is not None:
+ __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'String')
+ __text += "observers['%s']['String'] = \"\"\"%s\"\"\"\n"%(__obs, ObserverTemplates[__local['Template']])
+ if __local['Info'] is not None:
+ __text += "observers['%s']['info'] = \"\"\"%s\"\"\"\n"%(__obs, __local['Info'])
+ else:
+ __text += "observers['%s']['info'] = \"\"\"%s\"\"\"\n"%(__obs, __obs)
+ __text += "observers['%s']['number'] = %s"%(__obs, self._numobservers)
+ elif __local is not None: # __keys is not None and
+ __text = "#\n"
+ __text += "%s_config = {}\n"%__command
+ if 'self' in __local: __local.pop('self')
+ __to_be_removed = []
+ for __k,__v in __local.items():
+ if __v is None: __to_be_removed.append(__k)
+ for __k in __to_be_removed:
+ __local.pop(__k)
+ for __k,__v in __local.items():
+ if __k == "Concept": continue
+ if __k in ['ScalarSparseMatrix','DiagonalSparseMatrix','Matrix'] and 'Script' in __local: continue
+ if __k == 'Algorithm':
+ __text += "study_config['Algorithm'] = %s\n"%(repr(__v))
+ elif __k == 'Script':
+ __k = 'Vector'
+ for __lk in ['ScalarSparseMatrix','DiagonalSparseMatrix','Matrix']:
+ if __lk in __local and __local[__lk]: __k = __lk
+ if __command == "AlgorithmParameters": __k = "Dict"
+ __text += "%s_config['Type'] = '%s'\n"%(__command,__k)
+ __text += "%s_config['From'] = '%s'\n"%(__command,'Script')
+ __text += "%s_config['Data'] = '%s'\n"%(__command,repr(__v))
+ __text = __text.replace("''","'")
+ elif __k in ('Stored', 'Checked'):
+ if bool(__v):
+ __text += "%s_config['%s'] = '%s'\n"%(__command,__k,int(bool(__v)))
+ elif __k in ('AvoidRC', 'noDetails'):
+ if not bool(__v):
+ __text += "%s_config['%s'] = '%s'\n"%(__command,__k,int(bool(__v)))
+ else:
+ if __k is 'Parameters': __k = "Dict"
+ __text += "%s_config['Type'] = '%s'\n"%(__command,__k)
+ __text += "%s_config['From'] = '%s'\n"%(__command,'String')
+ __text += "%s_config['Data'] = \"\"\"%s\"\"\"\n"%(__command,repr(__v))
+ __text += "study_config['%s'] = %s_config"%(__command,__command)
+ if __switchoff:
+ self._switchoff = True
+ if __text is not None: self._addLine(__text)
+ if not __switchoff:
+ self._switchoff = False
+ def _finalize(self):
+ self.__loadVariablesByScript()
+ self._addLine("#")
+ self._addLine("Analysis_config = {}")
+ self._addLine("Analysis_config['From'] = 'String'")
+ self._addLine("Analysis_config['Data'] = \"\"\"import numpy")
+ self._addLine("xa=numpy.ravel(ADD.get('Analysis')[-1])")
+ self._addLine("print 'Analysis:',xa\"\"\"")
+ self._addLine("study_config['UserPostAnalysis'] = Analysis_config")
+ def __loadVariablesByScript(self):
+ exec("\n".join(self._lineSerie))
+ if "Algorithm" in study_config and len(study_config['Algorithm'])>0:
+ self.__hasAlgorithm = True
+ else:
+ self.__hasAlgorithm = False
+ if not self.__hasAlgorithm and \
+ "AlgorithmParameters" in study_config and \
+ isinstance(study_config['AlgorithmParameters'], dict) and \
+ "From" in study_config['AlgorithmParameters'] and \
+ "Data" in study_config['AlgorithmParameters'] and \
+ study_config['AlgorithmParameters']['From'] == 'Script':
+ __asScript = study_config['AlgorithmParameters']['Data']
+ __var = ImportFromScript(__asScript).getvalue( "Algorithm" )
+ __text = "#\nstudy_config['Algorithm'] = '%s'"%(__var,)
+ self._addLine(__text)
+ if self.__hasAlgorithm and \
+ "AlgorithmParameters" in study_config and \
+ isinstance(study_config['AlgorithmParameters'], dict) and \
+ "From" not in study_config['AlgorithmParameters'] and \
+ "Data" not in study_config['AlgorithmParameters']:
+ __text = "#\n"
+ __text += "AlgorithmParameters_config['Type'] = 'Dict'\n"
+ __text += "AlgorithmParameters_config['From'] = 'String'\n"
+ __text += "AlgorithmParameters_config['Data'] = '{}'\n"
+ self._addLine(__text)
+ del study_config
+
+class _XMLViewer(_GenericCaseViewer):
+ """
+ Etablissement des commandes de creation d'un cas DIC
+ """
+ def __init__(self, __name="", __objname="case", __content=None):
+ "Initialisation et enregistrement de l'entete"
+ _GenericCaseViewer.__init__(self, __name, __objname, __content)
+ raise NotImplementedError()
+
+# ==============================================================================
+if __name__ == "__main__":
+ print('\n AUTODIAGNOSTIC \n')
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
# Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
"""
- Classe principale pour la préparation, la réalisation et la restitution de
- calculs d'assimilation de données.
-
- Ce module est destiné à être appelé par AssimilationStudy pour constituer
- les objets élémentaires de l'étude.
+ Normalized interface for ADAO
"""
__author__ = "Jean-Philippe ARGAUD"
__all__ = ["AssimilationStudy"]
-import os, sys
-import numpy
-from daCore import ExtendedLogging ; ExtendedLogging.ExtendedLogging() # A importer en premier
-import logging
-try:
- import scipy.optimize
- logging.debug("Succeed initial import of scipy.optimize with Scipy %s", scipy.version.version)
-except ImportError:
- logging.debug("Fail initial import of scipy.optimize")
-from daCore import Persistence
-from daCore.BasicObjects import Operator, Covariance
-from daCore import PlatformInfo
+from daCore.Aidsm import Aidsm
# ==============================================================================
-class AssimilationStudy:
+class AssimilationStudy(Aidsm):
"""
- Cette classe sert d'interface pour l'utilisation de l'assimilation de
- données. Elle contient les méthodes ou accesseurs nécessaires à la
- construction d'un calcul d'assimilation.
+ Generic ADAO TUI builder
"""
- def __init__(self, name=""):
- """
- Prévoit de conserver l'ensemble des variables nécssaires à un algorithme
- élémentaire. Ces variables sont ensuite disponibles pour implémenter un
- algorithme élémentaire particulier.
-
- - Background : vecteur Xb
- - Observation : vecteur Y (potentiellement temporel) d'observations
- - State : vecteur d'état dont une partie est le vecteur de contrôle.
- Cette information n'est utile que si l'on veut faire des calculs sur
- l'état complet, mais elle n'est pas indispensable pour l'assimilation.
- - Control : vecteur X contenant toutes les variables de contrôle, i.e.
- les paramètres ou l'état dont on veut estimer la valeur pour obtenir
- les observations
- - ObservationOperator...: opérateur d'observation H
-
- Les observations présentent une erreur dont la matrice de covariance est
- R. L'ébauche du vecteur de contrôle présente une erreur dont la matrice
- de covariance est B.
- """
- self.__name = str(name)
- self.__Xb = None
- self.__Y = None
- self.__U = None
- self.__B = None
- self.__R = None
- self.__Q = None
- self.__HO = {}
- self.__EM = {}
- self.__CM = {}
- #
- self.__X = Persistence.OneVector()
- self.__Parameters = {}
- self.__StoredDiagnostics = {}
- self.__StoredInputs = {}
- #
- # Variables temporaires
- self.__algorithm = {}
- self.__algorithmFile = None
- self.__algorithmName = None
- self.__diagnosticFile = None
- #
- # 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,
- # qui est activée dans Persistence)
- self.__parent = os.path.abspath(os.path.join(os.path.dirname(__file__),".."))
- sys.path.insert(0, self.__parent)
- sys.path = PlatformInfo.uniq( sys.path ) # Conserve en unique exemplaire chaque chemin
-
- # ---------------------------------------------------------
- def setBackground(self,
- asVector = None,
- asPersistentVector = None,
- Scheduler = None,
- toBeStored = False,
- ):
- """
- Permet de définir l'estimation a priori :
- - asVector : entrée des données, comme un vecteur compatible avec le
- constructeur de numpy.matrix
- - asPersistentVector : entrée des données, comme un vecteur de type
- persistent contruit avec la classe ad-hoc "Persistence"
- - Scheduler est le contrôle temporel des données
- - toBeStored : booléen indiquant si la donnée d'entrée est sauvée pour
- être rendue disponible au même titre que les variables de calcul
- """
- if asVector is not None:
- self.__Xb = numpy.matrix( numpy.ravel(numpy.matrix(asVector)), numpy.float ).T
- elif asPersistentVector is not None:
- if type(asPersistentVector) in [type([]),type(()),type(numpy.array([])),type(numpy.matrix([]))]:
- self.__Xb = Persistence.OneVector("Background", basetype=numpy.matrix)
- for member in asPersistentVector:
- self.__Xb.store( numpy.matrix( numpy.asmatrix(member).A1, numpy.float ).T )
- else:
- self.__Xb = asPersistentVector
- else:
- raise ValueError("Error: improperly defined background, it requires at minima either a vector, a list/tuple of vectors or a persistent object")
- if toBeStored:
- self.__StoredInputs["Background"] = self.__Xb
- return 0
-
- def setBackgroundError(self,
- asCovariance = None,
- asEyeByScalar = None,
- asEyeByVector = None,
- asCovObject = None,
- toBeStored = False,
- toBeChecked = False,
- ):
- """
- Permet de définir la covariance des erreurs d'ébauche :
- - asCovariance : entrée des données, comme une matrice compatible avec
- le constructeur de numpy.matrix
- - asEyeByScalar : entrée des données comme un seul scalaire de variance,
- multiplicatif d'une matrice de corrélation identité, aucune matrice
- n'étant donc explicitement à donner
- - asEyeByVector : entrée des données comme un seul vecteur de variance,
- à mettre sur la diagonale d'une matrice de corrélation, aucune matrice
- n'étant donc explicitement à donner
- - asCovObject : entrée des données comme un objet ayant des méthodes
- particulieres de type matriciel
- - toBeStored : booléen indiquant si la donnée d'entrée est sauvée pour
- être rendue disponible au même titre que les variables de calcul
- """
- self.__B = Covariance(
- name = "BackgroundError",
- asCovariance = asCovariance,
- asEyeByScalar = asEyeByScalar,
- asEyeByVector = asEyeByVector,
- asCovObject = asCovObject,
- toBeChecked = toBeChecked,
- )
- if toBeStored:
- self.__StoredInputs["BackgroundError"] = self.__B
- return 0
-
- # -----------------------------------------------------------
- def setObservation(self,
- asVector = None,
- asPersistentVector = None,
- Scheduler = None,
- toBeStored = False,
- ):
- """
- Permet de définir les observations :
- - asVector : entrée des données, comme un vecteur compatible avec le
- constructeur de numpy.matrix
- - asPersistentVector : entrée des données, comme un vecteur de type
- persistent contruit avec la classe ad-hoc "Persistence"
- - Scheduler est le contrôle temporel des données disponibles
- - toBeStored : booléen indiquant si la donnée d'entrée est sauvée pour
- être rendue disponible au même titre que les variables de calcul
- """
- if asVector is not None:
- self.__Y = numpy.matrix( numpy.ravel(numpy.matrix(asVector)), numpy.float ).T
- elif asPersistentVector is not None:
- if type(asPersistentVector) in [type([]),type(()),type(numpy.array([])),type(numpy.matrix([]))]:
- self.__Y = Persistence.OneVector("Observation", basetype=numpy.matrix)
- for member in asPersistentVector:
- self.__Y.store( numpy.matrix( numpy.asmatrix(member).A1, numpy.float ).T )
- else:
- self.__Y = asPersistentVector
- else:
- raise ValueError("Error: improperly defined observations, it requires at minima either a vector, a list/tuple of vectors or a persistent object")
- if toBeStored:
- self.__StoredInputs["Observation"] = self.__Y
- return 0
-
- def setObservationError(self,
- asCovariance = None,
- asEyeByScalar = None,
- asEyeByVector = None,
- asCovObject = None,
- toBeStored = False,
- toBeChecked = False,
- ):
- """
- Permet de définir la covariance des erreurs d'observations :
- - asCovariance : entrée des données, comme une matrice compatible avec
- le constructeur de numpy.matrix
- - asEyeByScalar : entrée des données comme un seul scalaire de variance,
- multiplicatif d'une matrice de corrélation identité, aucune matrice
- n'étant donc explicitement à donner
- - asEyeByVector : entrée des données comme un seul vecteur de variance,
- à mettre sur la diagonale d'une matrice de corrélation, aucune matrice
- n'étant donc explicitement à donner
- - asCovObject : entrée des données comme un objet ayant des méthodes
- particulieres de type matriciel
- - toBeStored : booléen indiquant si la donnée d'entrée est sauvée pour
- être rendue disponible au même titre que les variables de calcul
- """
- self.__R = Covariance(
- name = "ObservationError",
- asCovariance = asCovariance,
- asEyeByScalar = asEyeByScalar,
- asEyeByVector = asEyeByVector,
- asCovObject = asCovObject,
- toBeChecked = toBeChecked,
- )
- if toBeStored:
- self.__StoredInputs["ObservationError"] = self.__R
- return 0
-
- def setObservationOperator(self,
- asFunction = None,
- asMatrix = None,
- appliedToX = None,
- toBeStored = False,
- avoidRC = True,
- ):
- """
- Permet de définir un opérateur d'observation H. L'ordre de priorité des
- définitions et leur sens sont les suivants :
- - si asFunction["Tangent"] et asFunction["Adjoint"] ne sont pas None
- alors on définit l'opérateur à l'aide de fonctions. Si la fonction
- "Direct" n'est pas définie, on prend la fonction "Tangent".
- Si "useApproximatedDerivatives" est vrai, on utilise une approximation
- des opérateurs tangents et adjoints. On utilise par défaut des
- différences finies non centrées ou centrées (si "withCenteredDF" est
- vrai) avec un incrément multiplicatif "withIncrement" de 1% autour
- du point courant ou sur le point fixe "withdX".
- - si les fonctions ne sont pas disponibles et si asMatrix n'est pas
- None, alors on définit l'opérateur "Direct" et "Tangent" à l'aide de
- la matrice, et l'opérateur "Adjoint" à l'aide de la transposée. La
- matrice fournie doit être sous une forme compatible avec le
- constructeur de numpy.matrix.
- - si l'argument "appliedToX" n'est pas None, alors on définit, pour des
- X divers, l'opérateur par sa valeur appliquée à cet X particulier,
- sous la forme d'un dictionnaire appliedToX[NAME] avec NAME un nom.
- L'opérateur doit néanmoins déjà avoir été défini comme d'habitude.
- - toBeStored : booléen indiquant si la donnée d'entrée est sauvée pour
- être rendue disponible au même titre que les variables de calcul
- L'argument "asFunction" peut prendre la forme complète suivante, avec
- les valeurs par défaut standards :
- asFunction = {"Direct":None, "Tangent":None, "Adjoint":None,
- "useApproximatedDerivatives":False,
- "withCenteredDF" :False,
- "withIncrement" :0.01,
- "withdX" :None,
- "withAvoidingRedundancy" :True,
- "withToleranceInRedundancy" :1.e-18,
- "withLenghtOfRedundancy" :-1,
- "withmpEnabled" :False,
- "withmpWorkers" :None,
- }
- """
- if isinstance(asFunction, dict) and \
- ("useApproximatedDerivatives" in asFunction) and bool(asFunction["useApproximatedDerivatives"]) and \
- ("Direct" in asFunction) and (asFunction["Direct"] is not None):
- if "withCenteredDF" not in asFunction: asFunction["withCenteredDF"] = False
- if "withIncrement" not in asFunction: asFunction["withIncrement"] = 0.01
- if "withdX" not in asFunction: asFunction["withdX"] = None
- if "withAvoidingRedundancy" not in asFunction: asFunction["withAvoidingRedundancy"] = True
- if "withToleranceInRedundancy" not in asFunction: asFunction["withToleranceInRedundancy"] = 1.e-18
- if "withLenghtOfRedundancy" not in asFunction: asFunction["withLenghtOfRedundancy"] = -1
- if "withmpEnabled" not in asFunction: asFunction["withmpEnabled"] = False
- if "withmpWorkers" not in asFunction: asFunction["withmpWorkers"] = None
- from daNumerics.ApproximatedDerivatives import FDApproximation
- FDA = FDApproximation(
- Function = asFunction["Direct"],
- centeredDF = asFunction["withCenteredDF"],
- increment = asFunction["withIncrement"],
- dX = asFunction["withdX"],
- avoidingRedundancy = asFunction["withAvoidingRedundancy"],
- toleranceInRedundancy = asFunction["withToleranceInRedundancy"],
- lenghtOfRedundancy = asFunction["withLenghtOfRedundancy"],
- mpEnabled = asFunction["withmpEnabled"],
- mpWorkers = asFunction["withmpWorkers"],
- )
- self.__HO["Direct"] = Operator( fromMethod = FDA.DirectOperator, avoidingRedundancy = avoidRC )
- self.__HO["Tangent"] = Operator( fromMethod = FDA.TangentOperator, avoidingRedundancy = avoidRC )
- self.__HO["Adjoint"] = Operator( fromMethod = FDA.AdjointOperator, avoidingRedundancy = avoidRC )
- elif isinstance(asFunction, dict) and \
- ("Tangent" in asFunction) and ("Adjoint" in asFunction) and \
- (asFunction["Tangent"] is not None) and (asFunction["Adjoint"] is not None):
- if ("Direct" not in asFunction) or (asFunction["Direct"] is None):
- self.__HO["Direct"] = Operator( fromMethod = asFunction["Tangent"], avoidingRedundancy = avoidRC )
- else:
- self.__HO["Direct"] = Operator( fromMethod = asFunction["Direct"], avoidingRedundancy = avoidRC )
- self.__HO["Tangent"] = Operator( fromMethod = asFunction["Tangent"], avoidingRedundancy = avoidRC )
- self.__HO["Adjoint"] = Operator( fromMethod = asFunction["Adjoint"], avoidingRedundancy = avoidRC )
- elif asMatrix is not None:
- matrice = numpy.matrix( asMatrix, numpy.float )
- self.__HO["Direct"] = Operator( fromMatrix = matrice, avoidingRedundancy = avoidRC )
- self.__HO["Tangent"] = Operator( fromMatrix = matrice, avoidingRedundancy = avoidRC )
- self.__HO["Adjoint"] = Operator( fromMatrix = matrice.T, avoidingRedundancy = avoidRC )
- del matrice
- else:
- raise ValueError("Improperly defined observation operator, it requires at minima either a matrix, a Direct for approximate derivatives or a Tangent/Adjoint pair.")
- #
- if appliedToX is not None:
- self.__HO["AppliedToX"] = {}
- if type(appliedToX) is not dict:
- raise ValueError("Error: observation operator defined by \"appliedToX\" need a dictionary as argument.")
- for key in list(appliedToX.keys()):
- if type( appliedToX[key] ) is type( numpy.matrix([]) ):
- # Pour le cas où l'on a une vraie matrice
- self.__HO["AppliedToX"][key] = numpy.matrix( appliedToX[key].A1, numpy.float ).T
- elif type( appliedToX[key] ) is type( numpy.array([]) ) and len(appliedToX[key].shape) > 1:
- # Pour le cas où l'on a un vecteur représenté en array avec 2 dimensions
- self.__HO["AppliedToX"][key] = numpy.matrix( appliedToX[key].reshape(len(appliedToX[key]),), numpy.float ).T
- else:
- self.__HO["AppliedToX"][key] = numpy.matrix( appliedToX[key], numpy.float ).T
- else:
- self.__HO["AppliedToX"] = None
- #
- if toBeStored:
- self.__StoredInputs["ObservationOperator"] = self.__HO
- return 0
-
- # -----------------------------------------------------------
- def setEvolutionModel(self,
- asFunction = None,
- asMatrix = None,
- Scheduler = None,
- toBeStored = False,
- avoidRC = True,
- ):
- """
- Permet de définir un opérateur d'évolution M. L'ordre de priorité des
- définitions et leur sens sont les suivants :
- - si asFunction["Tangent"] et asFunction["Adjoint"] ne sont pas None
- alors on définit l'opérateur à l'aide de fonctions. Si la fonction
- "Direct" n'est pas définie, on prend la fonction "Tangent".
- Si "useApproximatedDerivatives" est vrai, on utilise une approximation
- des opérateurs tangents et adjoints. On utilise par défaut des
- différences finies non centrées ou centrées (si "withCenteredDF" est
- vrai) avec un incrément multiplicatif "withIncrement" de 1% autour
- du point courant ou sur le point fixe "withdX".
- - si les fonctions ne sont pas disponibles et si asMatrix n'est pas
- None, alors on définit l'opérateur "Direct" et "Tangent" à l'aide de
- la matrice, et l'opérateur "Adjoint" à l'aide de la transposée. La
- matrice fournie doit être sous une forme compatible avec le
- constructeur de numpy.matrix.
- - toBeStored : booléen indiquant si la donnée d'entrée est sauvée pour
- être rendue disponible au même titre que les variables de calcul
- L'argument "asFunction" peut prendre la forme complète suivante, avec
- les valeurs par défaut standards :
- asFunction = {"Direct":None, "Tangent":None, "Adjoint":None,
- "useApproximatedDerivatives":False,
- "withCenteredDF" :False,
- "withIncrement" :0.01,
- "withdX" :None,
- "withAvoidingRedundancy" :True,
- "withToleranceInRedundancy" :1.e-18,
- "withLenghtOfRedundancy" :-1,
- "withmpEnabled" :False,
- "withmpWorkers" :None,
- }
- """
- if isinstance(asFunction, dict) and \
- ("useApproximatedDerivatives" in asFunction) and bool(asFunction["useApproximatedDerivatives"]) and \
- ("Direct" in asFunction) and (asFunction["Direct"] is not None):
- if "withCenteredDF" not in asFunction: asFunction["withCenteredDF"] = False
- if "withIncrement" not in asFunction: asFunction["withIncrement"] = 0.01
- if "withdX" not in asFunction: asFunction["withdX"] = None
- if "withAvoidingRedundancy" not in asFunction: asFunction["withAvoidingRedundancy"] = True
- if "withToleranceInRedundancy" not in asFunction: asFunction["withToleranceInRedundancy"] = 1.e-18
- if "withLenghtOfRedundancy" not in asFunction: asFunction["withLenghtOfRedundancy"] = -1
- if "withmpEnabled" not in asFunction: asFunction["withmpEnabled"] = False
- if "withmpWorkers" not in asFunction: asFunction["withmpWorkers"] = None
- from daNumerics.ApproximatedDerivatives import FDApproximation
- FDA = FDApproximation(
- Function = asFunction["Direct"],
- centeredDF = asFunction["withCenteredDF"],
- increment = asFunction["withIncrement"],
- dX = asFunction["withdX"],
- avoidingRedundancy = asFunction["withAvoidingRedundancy"],
- toleranceInRedundancy = asFunction["withToleranceInRedundancy"],
- lenghtOfRedundancy = asFunction["withLenghtOfRedundancy"],
- mpEnabled = asFunction["withmpEnabled"],
- mpWorkers = asFunction["withmpWorkers"],
- )
- self.__EM["Direct"] = Operator( fromMethod = FDA.DirectOperator, avoidingRedundancy = avoidRC )
- self.__EM["Tangent"] = Operator( fromMethod = FDA.TangentOperator, avoidingRedundancy = avoidRC )
- self.__EM["Adjoint"] = Operator( fromMethod = FDA.AdjointOperator, avoidingRedundancy = avoidRC )
- elif isinstance(asFunction, dict) and \
- ("Tangent" in asFunction) and ("Adjoint" in asFunction) and \
- (asFunction["Tangent"] is not None) and (asFunction["Adjoint"] is not None):
- if ("Direct" not in asFunction) or (asFunction["Direct"] is None):
- self.__EM["Direct"] = Operator( fromMethod = asFunction["Tangent"], avoidingRedundancy = avoidRC )
- else:
- self.__EM["Direct"] = Operator( fromMethod = asFunction["Direct"], avoidingRedundancy = avoidRC )
- self.__EM["Tangent"] = Operator( fromMethod = asFunction["Tangent"], avoidingRedundancy = avoidRC )
- self.__EM["Adjoint"] = Operator( fromMethod = asFunction["Adjoint"], avoidingRedundancy = avoidRC )
- elif asMatrix is not None:
- matrice = numpy.matrix( asMatrix, numpy.float )
- self.__EM["Direct"] = Operator( fromMatrix = matrice, avoidingRedundancy = avoidRC )
- self.__EM["Tangent"] = Operator( fromMatrix = matrice, avoidingRedundancy = avoidRC )
- self.__EM["Adjoint"] = Operator( fromMatrix = matrice.T, avoidingRedundancy = avoidRC )
- del matrice
- else:
- raise ValueError("Improperly defined evolution model, it requires at minima either a matrix, a Direct for approximate derivatives or a Tangent/Adjoint pair.")
- #
- if toBeStored:
- self.__StoredInputs["EvolutionModel"] = self.__EM
- return 0
-
- def setEvolutionError(self,
- asCovariance = None,
- asEyeByScalar = None,
- asEyeByVector = None,
- asCovObject = None,
- toBeStored = False,
- toBeChecked = False,
- ):
- """
- Permet de définir la covariance des erreurs de modèle :
- - asCovariance : entrée des données, comme une matrice compatible avec
- le constructeur de numpy.matrix
- - asEyeByScalar : entrée des données comme un seul scalaire de variance,
- multiplicatif d'une matrice de corrélation identité, aucune matrice
- n'étant donc explicitement à donner
- - asEyeByVector : entrée des données comme un seul vecteur de variance,
- à mettre sur la diagonale d'une matrice de corrélation, aucune matrice
- n'étant donc explicitement à donner
- - asCovObject : entrée des données comme un objet ayant des méthodes
- particulieres de type matriciel
- - toBeStored : booléen indiquant si la donnée d'entrée est sauvée pour
- être rendue disponible au même titre que les variables de calcul
- """
- self.__Q = Covariance(
- name = "EvolutionError",
- asCovariance = asCovariance,
- asEyeByScalar = asEyeByScalar,
- asEyeByVector = asEyeByVector,
- asCovObject = asCovObject,
- toBeChecked = toBeChecked,
- )
- if toBeStored:
- self.__StoredInputs["EvolutionError"] = self.__Q
- return 0
-
- # -----------------------------------------------------------
- def setControlModel(self,
- asFunction = None,
- asMatrix = None,
- Scheduler = None,
- toBeStored = False,
- avoidRC = True,
- ):
- """
- Permet de définir un opérateur de controle C. L'ordre de priorité des
- définitions et leur sens sont les suivants :
- - si asFunction["Tangent"] et asFunction["Adjoint"] ne sont pas None
- alors on définit l'opérateur à l'aide de fonctions. Si la fonction
- "Direct" n'est pas définie, on prend la fonction "Tangent".
- Si "useApproximatedDerivatives" est vrai, on utilise une approximation
- des opérateurs tangents et adjoints. On utilise par défaut des
- différences finies non centrées ou centrées (si "withCenteredDF" est
- vrai) avec un incrément multiplicatif "withIncrement" de 1% autour
- du point courant ou sur le point fixe "withdX".
- - si les fonctions ne sont pas disponibles et si asMatrix n'est pas
- None, alors on définit l'opérateur "Direct" et "Tangent" à l'aide de
- la matrice, et l'opérateur "Adjoint" à l'aide de la transposée. La
- matrice fournie doit être sous une forme compatible avec le
- constructeur de numpy.matrix.
- - toBeStored : booléen indiquant si la donnée d'entrée est sauvée pour
- être rendue disponible au même titre que les variables de calcul
- L'argument "asFunction" peut prendre la forme complète suivante, avec
- les valeurs par défaut standards :
- asFunction = {"Direct":None, "Tangent":None, "Adjoint":None,
- "useApproximatedDerivatives":False,
- "withCenteredDF" :False,
- "withIncrement" :0.01,
- "withdX" :None,
- "withAvoidingRedundancy" :True,
- "withToleranceInRedundancy" :1.e-18,
- "withLenghtOfRedundancy" :-1,
- "withmpEnabled" :False,
- "withmpWorkers" :None,
- }
- """
- if isinstance(asFunction, dict) and \
- ("useApproximatedDerivatives" in asFunction) and bool(asFunction["useApproximatedDerivatives"]) and \
- ("Direct" in asFunction) and (asFunction["Direct"] is not None):
- if "withCenteredDF" not in asFunction: asFunction["withCenteredDF"] = False
- if "withIncrement" not in asFunction: asFunction["withIncrement"] = 0.01
- if "withdX" not in asFunction: asFunction["withdX"] = None
- if "withAvoidingRedundancy" not in asFunction: asFunction["withAvoidingRedundancy"] = True
- if "withToleranceInRedundancy" not in asFunction: asFunction["withToleranceInRedundancy"] = 1.e-18
- if "withLenghtOfRedundancy" not in asFunction: asFunction["withLenghtOfRedundancy"] = -1
- if "withmpEnabled" not in asFunction: asFunction["withmpEnabled"] = False
- if "withmpWorkers" not in asFunction: asFunction["withmpWorkers"] = None
- from daNumerics.ApproximatedDerivatives import FDApproximation
- FDA = FDApproximation(
- Function = asFunction["Direct"],
- centeredDF = asFunction["withCenteredDF"],
- increment = asFunction["withIncrement"],
- dX = asFunction["withdX"],
- avoidingRedundancy = asFunction["withAvoidingRedundancy"],
- toleranceInRedundancy = asFunction["withToleranceInRedundancy"],
- lenghtOfRedundancy = asFunction["withLenghtOfRedundancy"],
- mpEnabled = asFunction["withmpEnabled"],
- mpWorkers = asFunction["withmpWorkers"],
- )
- self.__CM["Direct"] = Operator( fromMethod = FDA.DirectOperator, avoidingRedundancy = avoidRC )
- self.__CM["Tangent"] = Operator( fromMethod = FDA.TangentOperator, avoidingRedundancy = avoidRC )
- self.__CM["Adjoint"] = Operator( fromMethod = FDA.AdjointOperator, avoidingRedundancy = avoidRC )
- elif isinstance(asFunction, dict) and \
- ("Tangent" in asFunction) and ("Adjoint" in asFunction) and \
- (asFunction["Tangent"] is not None) and (asFunction["Adjoint"] is not None):
- if ("Direct" not in asFunction) or (asFunction["Direct"] is None):
- self.__CM["Direct"] = Operator( fromMethod = asFunction["Tangent"], avoidingRedundancy = avoidRC )
- else:
- self.__CM["Direct"] = Operator( fromMethod = asFunction["Direct"], avoidingRedundancy = avoidRC )
- self.__CM["Tangent"] = Operator( fromMethod = asFunction["Tangent"], avoidingRedundancy = avoidRC )
- self.__CM["Adjoint"] = Operator( fromMethod = asFunction["Adjoint"], avoidingRedundancy = avoidRC )
- elif asMatrix is not None:
- matrice = numpy.matrix( asMatrix, numpy.float )
- self.__CM["Direct"] = Operator( fromMatrix = matrice, avoidingRedundancy = avoidRC )
- self.__CM["Tangent"] = Operator( fromMatrix = matrice, avoidingRedundancy = avoidRC )
- self.__CM["Adjoint"] = Operator( fromMatrix = matrice.T, avoidingRedundancy = avoidRC )
- del matrice
- else:
- raise ValueError("Improperly defined input control model, it requires at minima either a matrix, a Direct for approximate derivatives or a Tangent/Adjoint pair.")
- #
- if toBeStored:
- self.__StoredInputs["ControlModel"] = self.__CM
- return 0
-
- def setControlInput(self,
- asVector = None,
- asPersistentVector = None,
- Scheduler = None,
- toBeStored = False,
- ):
- """
- Permet de définir le controle en entree :
- - asVector : entrée des données, comme un vecteur compatible avec le
- constructeur de numpy.matrix
- - asPersistentVector : entrée des données, comme un vecteur de type
- persistent contruit avec la classe ad-hoc "Persistence"
- - Scheduler est le contrôle temporel des données disponibles
- - toBeStored : booléen indiquant si la donnée d'entrée est sauvée pour
- être rendue disponible au même titre que les variables de calcul
- """
- if asVector is not None:
- self.__U = numpy.matrix( numpy.ravel(numpy.matrix(asVector)), numpy.float ).T
- elif asPersistentVector is not None:
- if type(asPersistentVector) in [type([]),type(()),type(numpy.array([])),type(numpy.matrix([]))]:
- self.__U = Persistence.OneVector("ControlInput", basetype=numpy.matrix)
- for member in asPersistentVector:
- self.__U.store( numpy.matrix( numpy.asmatrix(member).A1, numpy.float ).T )
- else:
- self.__U = asPersistentVector
- else:
- raise ValueError("Error: improperly defined control input, it requires at minima either a vector, a list/tuple of vectors or a persistent object")
- if toBeStored:
- self.__StoredInputs["ControlInput"] = self.__U
- return 0
-
- # -----------------------------------------------------------
- def setControls (self,
- asVector = None,
- toBeStored = False,
- ):
- """
- Permet de définir la valeur initiale du vecteur X contenant toutes les
- variables de contrôle, i.e. les paramètres ou l'état dont on veut
- estimer la valeur pour obtenir les observations. C'est utile pour un
- algorithme itératif/incrémental.
- - asVector : entrée des données, comme un vecteur compatible avec le
- constructeur de numpy.matrix.
- - toBeStored : booléen indiquant si la donnée d'entrée est sauvée pour
- être rendue disponible au même titre que les variables de calcul
- """
- if asVector is not None:
- self.__X.store( asVector )
- if toBeStored:
- self.__StoredInputs["Controls"] = self.__X
- return 0
-
- # -----------------------------------------------------------
- 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 fichier contenu dans "../daAlgorithms" et réalisant l'opération
- d'assimilation 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\" was found in a \"%s\" subdirectory\n The search path is %s"%(choice, daDirectory, 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(), [])
- 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()
- self.__StoredInputs["AlgorithmName"] = self.__algorithmName
- return 0
-
- def setAlgorithmParameters(self, asDico=None):
- """
- Permet de définir les paramètres de l'algorithme, sous la forme d'un
- dictionnaire.
- """
- if asDico is not None:
- self.__Parameters.update( dict( asDico ) )
- #
- self.__StoredInputs["AlgorithmParameters"] = self.__Parameters
- return 0
-
- def getAlgorithmParameters(self, noDetails=True):
- """
- Renvoie la liste des paramètres requis selon l'algorithme
- """
- return self.__algorithm.getRequiredParameters(noDetails)
-
- # -----------------------------------------------------------
- def setDiagnostic(self, choice = None, name = "", unit = "", basetype = None, parameters = {} ):
- """
- Permet de sélectionner un diagnostic a effectuer.
- """
- if choice is None:
- raise ValueError("Error: diagnostic choice has to be given")
- daDirectory = "daDiagnostics"
- #
- # 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 diagnostic module named \"%s\" was found in a \"%s\" subdirectory\n The search path is %s"%(choice, daDirectory, sys.path))
- #
- # Importe le fichier complet comme un module
- # ------------------------------------------
- try:
- sys_path_tmp = sys.path ; sys.path.insert(0,module_path)
- self.__diagnosticFile = __import__(str(choice), globals(), locals(), [])
- 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
- # -------------------------------------------------
- if name in self.__StoredInputs:
- raise ValueError("A default input with the same name \"%s\" already exists."%str(name))
- elif name in self.__StoredDiagnostics:
- raise ValueError("A diagnostic with the same name \"%s\" already exists."%str(name))
- else:
- self.__StoredDiagnostics[name] = self.__diagnosticFile.ElementaryDiagnostic(
- name = name,
- unit = unit,
- basetype = basetype,
- parameters = parameters )
- 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(type(self.__HO) is type({})) 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(type(self.__HO) is type({})) 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(type(self.__HO) is type({})) 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(type(self.__HO) is type({})) 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.__StoredInputs["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(type(self.__EM) is type({})) 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(type(self.__CM) is type({})) 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 ("AlgorithmParameters" in self.__StoredInputs) \
- and ("Bounds" in self.__StoredInputs["AlgorithmParameters"]) \
- and (isinstance(self.__StoredInputs["AlgorithmParameters"]["Bounds"], list) or isinstance(self.__StoredInputs["AlgorithmParameters"]["Bounds"], tuple)) \
- and (len(self.__StoredInputs["AlgorithmParameters"]["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.__StoredInputs["AlgorithmParameters"]["Bounds"]),max(__Xb_shape)))
- #
- return 1
-
- # -----------------------------------------------------------
- def analyze(self):
- """
- Permet de lancer le calcul d'assimilation.
-
- Le nom de la méthode à activer est toujours "run". Les paramètres en
- arguments de la méthode sont fixés. En sortie, on obtient les résultats
- dans la variable de type dictionnaire "StoredVariables", qui contient en
- particulier des objets de Persistence pour les analyses, OMA...
- """
- Operator.CM.clearCache()
- 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.__Parameters,
- )
- return 0
-
- # -----------------------------------------------------------
- def get(self, key=None):
- """
- Renvoie les résultats disponibles après l'exécution de la méthode
- d'assimilation, ou les diagnostics disponibles. Attention, quand un
- diagnostic porte le même nom qu'une variable stockée, c'est la variable
- stockée qui est renvoyée, et le diagnostic est inatteignable.
- """
- if key is not None:
- if key in self.__algorithm:
- return self.__algorithm.get( key )
- elif key in self.__StoredInputs:
- return self.__StoredInputs[key]
- elif key in self.__StoredDiagnostics:
- return self.__StoredDiagnostics[key]
- else:
- raise ValueError("The requested key \"%s\" does not exists as an input, a diagnostic or a stored variable."%key)
- else:
- allvariables = self.__algorithm.get()
- allvariables.update( self.__StoredDiagnostics )
- allvariables.update( self.__StoredInputs )
- return allvariables
-
- def get_available_variables(self):
- """
- Renvoie les variables potentiellement utilisables pour l'étude,
- initialement stockées comme données d'entrées ou dans les algorithmes,
- identifiés par les chaînes de caractères. L'algorithme doit avoir été
- préalablement choisi sinon la méthode renvoie "None".
- """
- if len(list(self.__algorithm.keys())) == 0 and len(list(self.__StoredInputs.keys())) == 0:
- return None
- else:
- variables = []
- if len( list(self.__algorithm.keys())) > 0:
- variables.extend( list(self.__algorithm.get().keys()) )
- if len( list(self.__StoredInputs.keys()) ) > 0:
- variables.extend( list(self.__StoredInputs.keys()) )
- variables.sort()
- return variables
-
- def get_available_algorithms(self):
- """
- Renvoie la liste des algorithmes potentiellement utilisables, identifiés
- par les chaînes de caractères.
- """
- files = []
- for directory in sys.path:
- if os.path.isdir(os.path.join(directory,"daAlgorithms")):
- for fname in os.listdir(os.path.join(directory,"daAlgorithms")):
- root, ext = os.path.splitext(fname)
- if ext == '.py' and root != '__init__':
- files.append(root)
- files.sort()
- return files
-
- def get_available_diagnostics(self):
- """
- Renvoie la liste des diagnostics potentiellement utilisables, identifiés
- par les chaînes de caractères.
- """
- files = []
- for directory in sys.path:
- if os.path.isdir(os.path.join(directory,"daDiagnostics")):
- for fname in os.listdir(os.path.join(directory,"daDiagnostics")):
- root, ext = os.path.splitext(fname)
- if ext == '.py' and root != '__init__':
- files.append(root)
- files.sort()
- return files
-
- # -----------------------------------------------------------
- def get_algorithms_main_path(self):
- """
- Renvoie le chemin pour le répertoire principal contenant les algorithmes
- dans un sous-répertoire "daAlgorithms"
- """
- return self.__parent
-
- def add_algorithms_path(self, asPath=None):
- """
- Ajoute au chemin de recherche des algorithmes un répertoire dans lequel
- se trouve un sous-répertoire "daAlgorithms"
-
- Remarque : si le chemin a déjà été ajouté pour les diagnostics, il n'est
- pas indispensable de le rajouter ici.
- """
- if not os.path.isdir(asPath):
- raise ValueError("The given "+asPath+" argument must exist as a directory")
- if not os.path.isdir(os.path.join(asPath,"daAlgorithms")):
- raise ValueError("The given \""+asPath+"\" argument must contain a subdirectory named \"daAlgorithms\"")
- if not os.path.isfile(os.path.join(asPath,"daAlgorithms","__init__.py")):
- raise ValueError("The given \""+asPath+"/daAlgorithms\" path must contain a file named \"__init__.py\"")
- sys.path.insert(0, os.path.abspath(asPath))
- sys.path = PlatformInfo.uniq( sys.path ) # Conserve en unique exemplaire chaque chemin
- return 1
-
- def get_diagnostics_main_path(self):
- """
- Renvoie le chemin pour le répertoire principal contenant les diagnostics
- dans un sous-répertoire "daDiagnostics"
- """
- return self.__parent
-
- def add_diagnostics_path(self, asPath=None):
- """
- Ajoute au chemin de recherche des algorithmes un répertoire dans lequel
- se trouve un sous-répertoire "daDiagnostics"
-
- Remarque : si le chemin a déjà été ajouté pour les algorithmes, il n'est
- pas indispensable de le rajouter ici.
- """
- if not os.path.isdir(asPath):
- raise ValueError("The given "+asPath+" argument must exist as a directory")
- if not os.path.isdir(os.path.join(asPath,"daDiagnostics")):
- raise ValueError("The given \""+asPath+"\" argument must contain a subdirectory named \"daDiagnostics\"")
- if not os.path.isfile(os.path.join(asPath,"daDiagnostics","__init__.py")):
- raise ValueError("The given \""+asPath+"/daDiagnostics\" path must contain a file named \"__init__.py\"")
- sys.path.insert(0, os.path.abspath(asPath))
- sys.path = PlatformInfo.uniq( sys.path ) # Conserve en unique exemplaire chaque chemin
- return 1
-
- # -----------------------------------------------------------
- def setDataObserver(self,
- VariableName = None,
- HookFunction = None,
- HookParameters = None,
- Scheduler = None,
- ):
- """
- Permet d'associer un observer à une ou des variables nommées gérées en
- interne, activable selon des règles définies dans le Scheduler. A chaque
- pas demandé dans le Scheduler, il effectue la fonction HookFunction avec
- les arguments (variable persistante VariableName, paramètres HookParameters).
- """
- #
- if isinstance(self.__algorithm, dict):
- raise ValueError("No observer can be build before choosing an algorithm.")
- #
- # Vérification du nom de variable et typage
- # -----------------------------------------
- if isinstance(VariableName, str):
- VariableNames = [VariableName,]
- elif isinstance(VariableName, list):
- VariableNames = list(map( str, VariableName ))
- else:
- raise ValueError("The observer requires a name or a list of names of variables.")
- #
- # Association interne de l'observer à la variable
- # -----------------------------------------------
- for n in VariableNames:
- if n not in self.__algorithm:
- raise ValueError("An observer requires to be set on a variable named %s which does not exist."%n)
- else:
- self.__algorithm.StoredVariables[ n ].setDataObserver(
- Scheduler = Scheduler,
- HookFunction = HookFunction,
- HookParameters = HookParameters,
- )
-
- def removeDataObserver(self,
- VariableName = None,
- HookFunction = None,
- ):
- """
- Permet de retirer un observer à une ou des variable nommée.
- """
- #
- if isinstance(self.__algorithm, dict):
- raise ValueError("No observer can be removed before choosing an algorithm.")
- #
- # Vérification du nom de variable et typage
- # -----------------------------------------
- if isinstance(VariableName, str):
- VariableNames = [VariableName,]
- elif isinstance(VariableName, list):
- VariableNames = list(map( str, VariableName ))
- else:
- raise ValueError("The observer requires a name or a list of names of variables.")
- #
- # Association interne de l'observer à la variable
- # -----------------------------------------------
- for n in VariableNames:
- if n not in self.__algorithm:
- raise ValueError("An observer requires to be removed on a variable named %s which does not exist."%n)
- else:
- self.__algorithm.StoredVariables[ n ].removeDataObserver(
- HookFunction = HookFunction,
- )
-
- # -----------------------------------------------------------
- def setDebug(self, level=10):
- """
- Utiliser par exemple "import logging ; level = logging.DEBUG" avant cet
- appel pour changer le niveau de verbosité, avec :
- NOTSET=0 < DEBUG=10 < INFO=20 < WARNING=30 < ERROR=40 < CRITICAL=50
- """
- log = logging.getLogger()
- log.setLevel( level )
-
- def unsetDebug(self):
- """
- Remet le logger au niveau par défaut
- """
- log = logging.getLogger()
- log.setLevel( logging.WARNING )
-
- def __dir__(self):
- # return set(self.__dict__.keys() + dir(self.__class__))
- return ['get', '__doc__', '__init__', '__module__']
-
- def prepare_to_pickle(self):
- """
- Retire les variables non pickelisables
- """
- del self.__B
- del self.__CM # non pickelisable
- del self.__EM # non pickelisable
- del self.__HO # non pickelisable
- del self.__Parameters
- del self.__Q
- del self.__R
- del self.__U
- del self.__X
- del self.__Xb
- del self.__Y
- del self.__algorithmFile # non pickelisable
- del self.__algorithmName
- del self.__diagnosticFile # non pickelisable
- self.__class__.__doc__ = ""
+ def __init__(self, name = ""):
+ Aidsm.__init__(self, name)
# ==============================================================================
if __name__ == "__main__":
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
# Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
"""
- Définit les outils généraux élémentaires.
+ Définit les outils généraux élémentaires.
- Ce module est destiné à être appelée par AssimilationStudy.
+ Ce module est destiné à être appelée par AssimilationStudy.
"""
__author__ = "Jean-Philippe ARGAUD"
__all__ = []
-import logging, copy, os
+import os, sys, logging, copy
import numpy
from daCore import Persistence
from daCore import PlatformInfo
+from daCore import Templates
# ==============================================================================
class CacheManager(object):
"""
- Classe générale de gestion d'un cache de calculs
+ Classe générale de gestion d'un cache de calculs
"""
def __init__(self,
toleranceInRedundancy = 1.e-18,
lenghtOfRedundancy = -1,
):
"""
- Les caractéristiques de tolérance peuvent être modifées à la création.
+ Les caractéristiques de tolérance peuvent être modifées à la création.
"""
self.__tolerBP = float(toleranceInRedundancy)
self.__lenghtOR = int(lenghtOfRedundancy)
# logging.debug("CM Tolerance de determination des doublons : %.2e", self.__tolerBP)
def wasCalculatedIn(self, xValue ): #, info="" ):
- "Vérifie l'existence d'un calcul correspondant à la valeur"
+ "Vérifie l'existence d'un calcul correspondant à la valeur"
__alc = False
__HxV = None
for i in range(min(len(self.__listOPCV),self.__lenghtOR)-1,-1,-1):
if xValue.size != self.__listOPCV[i][0].size:
- # logging.debug("CM Différence de la taille %s de X et de celle %s du point %i déjà calculé", xValue.shape,i,self.__listOPCP[i].shape)
+ # logging.debug("CM Différence de la taille %s de X et de celle %s du point %i déjà calculé", xValue.shape,i,self.__listOPCP[i].shape)
continue
if numpy.linalg.norm(numpy.ravel(xValue) - self.__listOPCV[i][0]) < self.__tolerBP * self.__listOPCV[i][2]:
__alc = True
__HxV = self.__listOPCV[i][1]
- # logging.debug("CM Cas%s déja calculé, portant le numéro %i", info, i)
+ # logging.debug("CM Cas%s déja calculé, portant le numéro %i", info, i)
break
return __alc, __HxV
def storeValueInX(self, xValue, HxValue ):
- "Stocke un calcul correspondant à la valeur"
+ "Stocke un calcul correspondant à la valeur"
if self.__lenghtOR < 0:
self.__lenghtOR = 2 * xValue.size + 2
self.__initlnOR = self.__lenghtOR
while len(self.__listOPCV) > self.__lenghtOR:
- # logging.debug("CM Réduction de la liste des cas à %i éléments par suppression du premier", self.__lenghtOR)
+ # logging.debug("CM Réduction de la liste des cas à %i éléments par suppression du premier", self.__lenghtOR)
self.__listOPCV.pop(0)
self.__listOPCV.append( (
copy.copy(numpy.ravel(xValue)),
# ==============================================================================
class Operator(object):
"""
- Classe générale d'interface de type opérateur
+ Classe générale d'interface de type opérateur simple
"""
NbCallsAsMatrix = 0
NbCallsAsMethod = 0
#
def __init__(self, fromMethod=None, fromMatrix=None, avoidingRedundancy = True):
"""
- On construit un objet de ce type en fournissant à l'aide de l'un des
- deux mots-clé, soit une fonction python, soit une matrice.
+ On construit un objet de ce type en fournissant à l'aide de l'un des
+ deux mots-clé, soit une fonction python, soit une matrice.
Arguments :
- fromMethod : argument de type fonction Python
- - fromMatrix : argument adapté au constructeur numpy.matrix
- - avoidingRedundancy : évite ou pas les calculs redondants
+ - fromMatrix : argument adapté au constructeur numpy.matrix
+ - avoidingRedundancy : évite ou pas les calculs redondants
"""
self.__NbCallsAsMatrix, self.__NbCallsAsMethod, self.__NbCallsOfCached = 0, 0, 0
self.__AvoidRC = bool( avoidingRedundancy )
def appliedTo(self, xValue, HValue = None):
"""
- Permet de restituer le résultat de l'application de l'opérateur à un
- argument xValue. Cette méthode se contente d'appliquer, son argument
- devant a priori être du bon type.
+ Permet de restituer le résultat de l'application de l'opérateur à un
+ argument xValue. Cette méthode se contente d'appliquer, son argument
+ devant a priori être du bon type.
Arguments :
- - xValue : argument adapté pour appliquer l'opérateur
+ - xValue : argument adapté pour appliquer l'opérateur
"""
if HValue is not None:
HxValue = numpy.asmatrix( numpy.ravel( HValue ) ).T
def appliedControledFormTo(self, paire ):
"""
- Permet de restituer le résultat de l'application de l'opérateur à une
- paire (xValue, uValue). Cette méthode se contente d'appliquer, son
- argument devant a priori être du bon type. Si la uValue est None,
- on suppose que l'opérateur ne s'applique qu'à xValue.
+ Permet de restituer le résultat de l'application de l'opérateur à une
+ paire (xValue, uValue). Cette méthode se contente d'appliquer, son
+ argument devant a priori être du bon type. Si la uValue est None,
+ on suppose que l'opérateur ne s'applique qu'à xValue.
Arguments :
- - xValue : argument X adapté pour appliquer l'opérateur
- - uValue : argument U adapté pour appliquer l'opérateur
+ - xValue : argument X adapté pour appliquer l'opérateur
+ - uValue : argument U adapté pour appliquer l'opérateur
"""
assert len(paire) == 2, "Incorrect number of arguments"
xValue, uValue = paire
def appliedInXTo(self, paire ):
"""
- Permet de restituer le résultat de l'application de l'opérateur à un
- argument xValue, sachant que l'opérateur est valable en xNominal.
- Cette méthode se contente d'appliquer, son argument devant a priori
- être du bon type. Si l'opérateur est linéaire car c'est une matrice,
- alors il est valable en tout point nominal et il n'est pas nécessaire
+ Permet de restituer le résultat de l'application de l'opérateur à un
+ argument xValue, sachant que l'opérateur est valable en xNominal.
+ Cette méthode se contente d'appliquer, son argument devant a priori
+ être du bon type. Si l'opérateur est linéaire car c'est une matrice,
+ alors il est valable en tout point nominal et il n'est pas nécessaire
d'utiliser xNominal.
Arguments : une liste contenant
- - xNominal : argument permettant de donner le point où l'opérateur
- est construit pour etre ensuite appliqué
- - xValue : argument adapté pour appliquer l'opérateur
+ - xNominal : argument permettant de donner le point où l'opérateur
+ est construit pour etre ensuite appliqué
+ - xValue : argument adapté pour appliquer l'opérateur
"""
assert len(paire) == 2, "Incorrect number of arguments"
xNominal, xValue = paire
def asMatrix(self, ValueForMethodForm = "UnknownVoidValue"):
"""
- Permet de renvoyer l'opérateur sous la forme d'une matrice
+ Permet de renvoyer l'opérateur sous la forme d'une matrice
"""
if self.__Matrix is not None:
self.__addOneMatrixCall()
def shape(self):
"""
- Renvoie la taille sous forme numpy si l'opérateur est disponible sous
+ Renvoie la taille sous forme numpy si l'opérateur est disponible sous
la forme d'une matrice
"""
if self.__Matrix is not None:
def nbcalls(self, which=None):
"""
- Renvoie les nombres d'évaluations de l'opérateur
+ Renvoie les nombres d'évaluations de l'opérateur
"""
__nbcalls = (
self.__NbCallsAsMatrix+self.__NbCallsAsMethod,
self.__NbCallsOfCached += 1 # Decompte local
Operator.NbCallsOfCached += 1 # Decompte global
+# ==============================================================================
+class FullOperator(object):
+ """
+ Classe générale d'interface de type opérateur complet
+ (Direct, Linéaire Tangent, Adjoint)
+ """
+ def __init__(self,
+ name = "GenericFullOperator",
+ asMatrix = None,
+ asOneFunction = None, # Fonction
+ asThreeFunctions = None, # Dictionnaire de fonctions
+ asScript = None,
+ asDict = None, # Parameters
+ appliedInX = None,
+ avoidRC = True,
+ scheduledBy = None,
+ toBeChecked = False,
+ ):
+ ""
+ self.__name = str(name)
+ self.__check = bool(toBeChecked)
+ #
+ self.__FO = {}
+ #
+ __Parameters = {}
+ if (asDict is not None) and isinstance(asDict, dict):
+ __Parameters.update( asDict )
+ if "DifferentialIncrement" in asDict:
+ __Parameters["withIncrement"] = asDict["DifferentialIncrement"]
+ if "CenteredFiniteDifference" in asDict:
+ __Parameters["withCenteredDF"] = asDict["CenteredFiniteDifference"]
+ if "EnableMultiProcessing" in asDict:
+ __Parameters["withmpEnabled"] = asDict["EnableMultiProcessing"]
+ if "NumberOfProcesses" in asDict:
+ __Parameters["withmpWorkers"] = asDict["NumberOfProcesses"]
+ #
+ if asScript is not None:
+ __Matrix, __Function = None, None
+ if asMatrix:
+ __Matrix = ImportFromScript(asScript).getvalue( self.__name )
+ elif asOneFunction:
+ __Function = { "Direct":ImportFromScript(asScript).getvalue( "DirectOperator" ) }
+ __Function.update({"useApproximatedDerivatives":True})
+ __Function.update(__Parameters)
+ elif asThreeFunctions:
+ __Function = {
+ "Direct" :ImportFromScript(asScript).getvalue( "DirectOperator" ),
+ "Tangent":ImportFromScript(asScript).getvalue( "TangentOperator" ),
+ "Adjoint":ImportFromScript(asScript).getvalue( "AdjointOperator" ),
+ }
+ __Function.update(__Parameters)
+ else:
+ __Matrix = asMatrix
+ if asOneFunction is not None:
+ if isinstance(asOneFunction, dict) and "Direct" in asOneFunction:
+ if asOneFunction["Direct"] is not None:
+ __Function = asOneFunction
+ else:
+ raise ValueError("The function has to be given in a dictionnary which have 1 key (\"Direct\")")
+ else:
+ __Function = { "Direct":asOneFunction }
+ __Function.update({"useApproximatedDerivatives":True})
+ __Function.update(__Parameters)
+ elif asThreeFunctions is not None:
+ if isinstance(asThreeFunctions, dict) and \
+ ("Tangent" in asThreeFunctions) and (asThreeFunctions["Tangent"] is not None) and \
+ ("Adjoint" in asThreeFunctions) and (asThreeFunctions["Adjoint"] is not None) and \
+ (("useApproximatedDerivatives" not in asThreeFunctions) or not bool(asThreeFunctions["useApproximatedDerivatives"])):
+ __Function = asThreeFunctions
+ elif isinstance(asThreeFunctions, dict) and \
+ ("Direct" in asThreeFunctions) and (asThreeFunctions["Direct"] is not None):
+ __Function = asThreeFunctions
+ __Function.update({"useApproximatedDerivatives":True})
+ else:
+ raise ValueError("The functions has to be given in a dictionnary which have either 1 key (\"Direct\") or 3 keys (\"Direct\" (optionnal), \"Tangent\" and \"Adjoint\")")
+ if "Direct" not in asThreeFunctions:
+ __Function["Direct"] = asThreeFunctions["Tangent"]
+ __Function.update(__Parameters)
+ else:
+ __Function = None
+ #
+ # if sys.version_info[0] < 3 and isinstance(__Function, dict):
+ # for k in ("Direct", "Tangent", "Adjoint"):
+ # if k in __Function and hasattr(__Function[k],"__class__"):
+ # if type(__Function[k]) is type(self.__init__):
+ # raise TypeError("can't use a class method (%s) as a function for the \"%s\" operator. Use a real function instead."%(type(__Function[k]),k))
+ #
+ if appliedInX is not None and isinstance(appliedInX, dict):
+ __appliedInX = appliedInX
+ elif appliedInX is not None:
+ __appliedInX = {"HXb":appliedInX}
+ else:
+ __appliedInX = None
+ #
+ if scheduledBy is not None:
+ self.__T = scheduledBy
+ #
+ if isinstance(__Function, dict) and \
+ ("useApproximatedDerivatives" in __Function) and bool(__Function["useApproximatedDerivatives"]) and \
+ ("Direct" in __Function) and (__Function["Direct"] is not None):
+ if "withCenteredDF" not in __Function: __Function["withCenteredDF"] = False
+ if "withIncrement" not in __Function: __Function["withIncrement"] = 0.01
+ if "withdX" not in __Function: __Function["withdX"] = None
+ if "withAvoidingRedundancy" not in __Function: __Function["withAvoidingRedundancy"] = True
+ if "withToleranceInRedundancy" not in __Function: __Function["withToleranceInRedundancy"] = 1.e-18
+ if "withLenghtOfRedundancy" not in __Function: __Function["withLenghtOfRedundancy"] = -1
+ if "withmpEnabled" not in __Function: __Function["withmpEnabled"] = False
+ if "withmpWorkers" not in __Function: __Function["withmpWorkers"] = None
+ from daNumerics.ApproximatedDerivatives import FDApproximation
+ FDA = FDApproximation(
+ Function = __Function["Direct"],
+ centeredDF = __Function["withCenteredDF"],
+ increment = __Function["withIncrement"],
+ dX = __Function["withdX"],
+ avoidingRedundancy = __Function["withAvoidingRedundancy"],
+ toleranceInRedundancy = __Function["withToleranceInRedundancy"],
+ lenghtOfRedundancy = __Function["withLenghtOfRedundancy"],
+ mpEnabled = __Function["withmpEnabled"],
+ mpWorkers = __Function["withmpWorkers"],
+ )
+ self.__FO["Direct"] = Operator( fromMethod = FDA.DirectOperator, avoidingRedundancy = avoidRC )
+ self.__FO["Tangent"] = Operator( fromMethod = FDA.TangentOperator, avoidingRedundancy = avoidRC )
+ self.__FO["Adjoint"] = Operator( fromMethod = FDA.AdjointOperator, avoidingRedundancy = avoidRC )
+ elif isinstance(__Function, dict) and \
+ ("Direct" in __Function) and ("Tangent" in __Function) and ("Adjoint" in __Function) and \
+ (__Function["Direct"] is not None) and (__Function["Tangent"] is not None) and (__Function["Adjoint"] is not None):
+ self.__FO["Direct"] = Operator( fromMethod = __Function["Direct"], avoidingRedundancy = avoidRC )
+ self.__FO["Tangent"] = Operator( fromMethod = __Function["Tangent"], avoidingRedundancy = avoidRC )
+ self.__FO["Adjoint"] = Operator( fromMethod = __Function["Adjoint"], avoidingRedundancy = avoidRC )
+ elif asMatrix is not None:
+ __matrice = numpy.matrix( asMatrix, numpy.float )
+ self.__FO["Direct"] = Operator( fromMatrix = __matrice, avoidingRedundancy = avoidRC )
+ self.__FO["Tangent"] = Operator( fromMatrix = __matrice, avoidingRedundancy = avoidRC )
+ self.__FO["Adjoint"] = Operator( fromMatrix = __matrice.T, avoidingRedundancy = avoidRC )
+ del __matrice
+ else:
+ raise ValueError("Improperly defined observation operator, it requires at minima either a matrix, a Direct for approximate derivatives or a Tangent/Adjoint pair.")
+ #
+ if __appliedInX is not None:
+ self.__FO["AppliedInX"] = {}
+ if type(__appliedInX) is not dict:
+ raise ValueError("Error: observation operator defined by \"AppliedInX\" need a dictionary as argument.")
+ for key in list(__appliedInX.keys()):
+ if type( __appliedInX[key] ) is type( numpy.matrix([]) ):
+ # Pour le cas où l'on a une vraie matrice
+ self.__FO["AppliedInX"][key] = numpy.matrix( __appliedInX[key].A1, numpy.float ).T
+ elif type( __appliedInX[key] ) is type( numpy.array([]) ) and len(__appliedInX[key].shape) > 1:
+ # Pour le cas où l'on a un vecteur représenté en array avec 2 dimensions
+ self.__FO["AppliedInX"][key] = numpy.matrix( __appliedInX[key].reshape(len(__appliedInX[key]),), numpy.float ).T
+ else:
+ self.__FO["AppliedInX"][key] = numpy.matrix( __appliedInX[key], numpy.float ).T
+ else:
+ self.__FO["AppliedInX"] = None
+
+ def getO(self):
+ return self.__FO
+
+ def __repr__(self):
+ "x.__repr__() <==> repr(x)"
+ return repr(self.__V)
+
+ def __str__(self):
+ "x.__str__() <==> str(x)"
+ return str(self.__V)
+
# ==============================================================================
class Algorithm(object):
"""
- Classe générale d'interface de type algorithme
+ Classe générale d'interface de type algorithme
- Elle donne un cadre pour l'écriture d'une classe élémentaire d'algorithme
+ Elle donne un cadre pour l'écriture d'une classe élémentaire d'algorithme
d'assimilation, en fournissant un container (dictionnaire) de variables
- persistantes initialisées, et des méthodes d'accès à ces variables stockées.
+ persistantes initialisées, et des méthodes d'accès à ces variables stockées.
- Une classe élémentaire d'algorithme doit implémenter la méthode "run".
+ Une classe élémentaire d'algorithme doit implémenter la méthode "run".
"""
def __init__(self, name):
"""
- L'initialisation présente permet de fabriquer des variables de stockage
- disponibles de manière générique dans les algorithmes élémentaires. Ces
- variables de stockage sont ensuite conservées dans un dictionnaire
- interne à l'objet, mais auquel on accède par la méthode "get".
+ L'initialisation présente permet de fabriquer des variables de stockage
+ disponibles de manière générique dans les algorithmes élémentaires. Ces
+ variables de stockage sont ensuite conservées dans un dictionnaire
+ interne à l'objet, mais auquel on accède par la méthode "get".
- Les variables prévues sont :
+ Les variables prévues sont :
- CostFunctionJ : fonction-cout globale, somme des deux parties suivantes
- - CostFunctionJb : partie ébauche ou background de la fonction-cout
+ - CostFunctionJb : partie ébauche ou background de la fonction-cout
- CostFunctionJo : partie observations de la fonction-cout
- GradientOfCostFunctionJ : gradient de la fonction-cout globale
- - GradientOfCostFunctionJb : gradient de la partie ébauche de la fonction-cout
+ - GradientOfCostFunctionJb : gradient de la partie ébauche de la fonction-cout
- GradientOfCostFunctionJo : gradient de la partie observations de la fonction-cout
- - CurrentState : état courant lors d'itérations
+ - CurrentState : état courant lors d'itérations
- Analysis : l'analyse Xa
- - SimulatedObservationAtBackground : l'état observé H(Xb) à l'ébauche
- - SimulatedObservationAtCurrentState : l'état observé H(X) à l'état courant
- - SimulatedObservationAtOptimum : l'état observé H(Xa) à l'optimum
+ - SimulatedObservationAtBackground : l'état observé H(Xb) à l'ébauche
+ - SimulatedObservationAtCurrentState : l'état observé H(X) à l'état courant
+ - SimulatedObservationAtOptimum : l'état observé H(Xa) à l'optimum
- Innovation : l'innovation : d = Y - H(X)
- - InnovationAtCurrentState : l'innovation à l'état courant : dn = Y - H(Xn)
+ - InnovationAtCurrentState : l'innovation à l'état courant : dn = Y - H(Xn)
- SigmaObs2 : indicateur de correction optimale des erreurs d'observation
- - SigmaBck2 : indicateur de correction optimale des erreurs d'ébauche
+ - SigmaBck2 : indicateur de correction optimale des erreurs d'ébauche
- MahalanobisConsistency : indicateur de consistance des covariances
- OMA : Observation moins Analysis : Y - Xa
- OMB : Observation moins Background : Y - Xb
- AMB : Analysis moins Background : Xa - Xb
- APosterioriCovariance : matrice A
- APosterioriVariances : variances de la matrice A
- - APosterioriStandardDeviations : écart-types de la matrice A
+ - APosterioriStandardDeviations : écart-types de la matrice A
- APosterioriCorrelations : correlations de la matrice A
- - Residu : dans le cas des algorithmes de vérification
- On peut rajouter des variables à stocker dans l'initialisation de
- l'algorithme élémentaire qui va hériter de cette classe
+ - Residu : dans le cas des algorithmes de vérification
+ On peut rajouter des variables à stocker dans l'initialisation de
+ l'algorithme élémentaire qui va hériter de cette classe
"""
logging.debug("%s Initialisation", str(name))
self._m = PlatformInfo.SystemUsage()
self.StoredVariables["Residu"] = Persistence.OneScalar(name = "Residu")
def _pre_run(self, Parameters ):
- "Pré-calcul"
+ "Pré-calcul"
logging.debug("%s Lancement", self._name)
- logging.debug("%s Taille mémoire utilisée de %.0f Mio", self._name, self._m.getUsedMemory("Mio"))
+ logging.debug("%s Taille mémoire utilisée de %.0f Mio", self._name, self._m.getUsedMemory("Mio"))
#
# Mise a jour de self._parameters avec Parameters
self.__setParameters(Parameters)
#
# Corrections et complements
- if "Bounds" in self._parameters and (type(self._parameters["Bounds"]) is type([]) or type(self._parameters["Bounds"]) is type(())) and (len(self._parameters["Bounds"]) > 0):
+ if ("Bounds" in self._parameters) and isinstance(self._parameters["Bounds"], (list, tuple)) and (len(self._parameters["Bounds"]) > 0):
logging.debug("%s Prise en compte des bornes effectuee"%(self._name,))
else:
self._parameters["Bounds"] = None
_C = numpy.dot(_EI, numpy.dot(_A, _EI))
self.StoredVariables["APosterioriCorrelations"].store( _C )
if _oH is not None:
- logging.debug("%s Nombre d'évaluation(s) de l'opérateur d'observation direct/tangent/adjoint.: %i/%i/%i", self._name, _oH["Direct"].nbcalls(0),_oH["Tangent"].nbcalls(0),_oH["Adjoint"].nbcalls(0))
- logging.debug("%s Nombre d'appels au cache d'opérateur d'observation direct/tangent/adjoint..: %i/%i/%i", self._name, _oH["Direct"].nbcalls(3),_oH["Tangent"].nbcalls(3),_oH["Adjoint"].nbcalls(3))
- logging.debug("%s Taille mémoire utilisée de %.0f Mio", self._name, self._m.getUsedMemory("Mio"))
- logging.debug("%s Terminé", self._name)
+ logging.debug("%s Nombre d'évaluation(s) de l'opérateur d'observation direct/tangent/adjoint.: %i/%i/%i", self._name, _oH["Direct"].nbcalls(0),_oH["Tangent"].nbcalls(0),_oH["Adjoint"].nbcalls(0))
+ logging.debug("%s Nombre d'appels au cache d'opérateur d'observation direct/tangent/adjoint..: %i/%i/%i", self._name, _oH["Direct"].nbcalls(3),_oH["Tangent"].nbcalls(3),_oH["Adjoint"].nbcalls(3))
+ logging.debug("%s Taille mémoire utilisée de %.0f Mio", self._name, self._m.getUsedMemory("Mio"))
+ logging.debug("%s Terminé", self._name)
return 0
def get(self, key=None):
"""
- Renvoie l'une des variables stockées identifiée par la clé, ou le
+ Renvoie l'une des variables stockées identifiée par la clé, ou le
dictionnaire de l'ensemble des variables disponibles en l'absence de
- clé. Ce sont directement les variables sous forme objet qui sont
- renvoyées, donc les méthodes d'accès à l'objet individuel sont celles
+ clé. Ce sont directement les variables sous forme objet qui sont
+ renvoyées, donc les méthodes d'accès à l'objet individuel sont celles
des classes de persistance.
"""
if key is not None:
def keys(self):
"D.keys() -> list of D's keys"
- return self.StoredVariables.keys()
+ if hasattr(self, "StoredVariables"):
+ return self.StoredVariables.keys()
+ else:
+ return []
+
+ def pop(self, k, d):
+ "D.pop(k[,d]) -> v, remove specified key and return the corresponding value"
+ if hasattr(self, "StoredVariables"):
+ return self.StoredVariables.pop(k, d)
+ else:
+ try:
+ msg = "'%s'"%k
+ except:
+ raise TypeError("pop expected at least 1 arguments, got 0")
+ "If key is not found, d is returned if given, otherwise KeyError is raised"
+ try:
+ return d
+ except:
+ raise KeyError(msg)
def run(self, Xb=None, Y=None, H=None, M=None, R=None, B=None, Q=None, Parameters=None):
"""
- Doit implémenter l'opération élémentaire de calcul d'assimilation sous
- sa forme mathématique la plus naturelle possible.
+ Doit implémenter l'opération élémentaire de calcul d'assimilation sous
+ sa forme mathématique la plus naturelle possible.
"""
raise NotImplementedError("Mathematical assimilation calculation has not been implemented!")
def defineRequiredParameter(self, name = None, default = None, typecast = None, message = None, minval = None, maxval = None, listval = None):
"""
- Permet de définir dans l'algorithme des paramètres requis et leurs
- caractéristiques par défaut.
+ Permet de définir dans l'algorithme des paramètres requis et leurs
+ caractéristiques par défaut.
"""
if name is None:
raise ValueError("A name is mandatory to define a required parameter.")
"listval" : listval,
"message" : message,
}
- logging.debug("%s %s (valeur par défaut = %s)", self._name, message, self.setParameterValue(name))
+ logging.debug("%s %s (valeur par défaut = %s)", self._name, message, self.setParameterValue(name))
def getRequiredParameters(self, noDetails=True):
"""
- Renvoie la liste des noms de paramètres requis ou directement le
- dictionnaire des paramètres requis.
+ Renvoie la liste des noms de paramètres requis ou directement le
+ dictionnaire des paramètres requis.
"""
if noDetails:
- ks = list(self.__required_parameters.keys())
- ks.sort()
- return ks
+ return sorted(self.__required_parameters.keys())
else:
return self.__required_parameters
def setParameterValue(self, name=None, value=None):
"""
- Renvoie la valeur d'un paramètre requis de manière contrôlée
+ Renvoie la valeur d'un paramètre requis de manière contrôlée
"""
default = self.__required_parameters[name]["default"]
typecast = self.__required_parameters[name]["typecast"]
def __setParameters(self, fromDico={}):
"""
- Permet de stocker les paramètres reçus dans le dictionnaire interne.
+ Permet de stocker les paramètres reçus dans le dictionnaire interne.
"""
self._parameters.update( fromDico )
for k in self.__required_parameters.keys():
# ==============================================================================
class Diagnostic(object):
"""
- Classe générale d'interface de type diagnostic
+ Classe générale d'interface de type diagnostic
- Ce template s'utilise de la manière suivante : il sert de classe "patron" en
- même temps que l'une des classes de persistance, comme "OneScalar" par
+ Ce template s'utilise de la manière suivante : il sert de classe "patron" en
+ même temps que l'une des classes de persistance, comme "OneScalar" par
exemple.
- Une classe élémentaire de diagnostic doit implémenter ses deux méthodes, la
- méthode "_formula" pour écrire explicitement et proprement la formule pour
- l'écriture mathématique du calcul du diagnostic (méthode interne non
- publique), et "calculate" pour activer la précédente tout en ayant vérifié
- et préparé les données, et pour stocker les résultats à chaque pas (méthode
+ Une classe élémentaire de diagnostic doit implémenter ses deux méthodes, la
+ méthode "_formula" pour écrire explicitement et proprement la formule pour
+ l'écriture mathématique du calcul du diagnostic (méthode interne non
+ publique), et "calculate" pour activer la précédente tout en ayant vérifié
+ et préparé les données, et pour stocker les résultats à chaque pas (méthode
externe d'activation).
"""
def __init__(self, name = "", parameters = {}):
def _formula(self, *args):
"""
- Doit implémenter l'opération élémentaire de diagnostic sous sa forme
- mathématique la plus naturelle possible.
+ Doit implémenter l'opération élémentaire de diagnostic sous sa forme
+ mathématique la plus naturelle possible.
"""
raise NotImplementedError("Diagnostic mathematical formula has not been implemented!")
def calculate(self, *args):
"""
- Active la formule de calcul avec les arguments correctement rangés
+ Active la formule de calcul avec les arguments correctement rangés
"""
raise NotImplementedError("Diagnostic activation method has not been implemented!")
# ==============================================================================
-class ParameterDictionary(object):
+class DiagnosticAndParameters(object):
"""
- Classe générale d'interface de type dictionnaire de paramètres
+ Classe générale d'interface d'interface de type diagnostic
"""
def __init__(self,
- name = "GenericParamDict",
+ name = "GenericDiagnostic",
+ asDiagnostic = None,
+ asIdentifier = None,
+ asDict = None,
+ asScript = None,
+ asUnit = None,
+ asBaseType = None,
+ asExistingDiags = None,
+ ):
+ """
+ """
+ self.__name = str(name)
+ self.__D = None
+ self.__I = None
+ self.__P = {}
+ self.__U = ""
+ self.__B = None
+ self.__E = tuple(asExistingDiags)
+ self.__TheDiag = None
+ #
+ if asScript is not None:
+ __Diag = ImportFromScript(asScript).getvalue( "Diagnostic" )
+ __Iden = ImportFromScript(asScript).getvalue( "Identifier" )
+ __Dict = ImportFromScript(asScript).getvalue( self.__name, "Parameters" )
+ __Unit = ImportFromScript(asScript).getvalue( "Unit" )
+ __Base = ImportFromScript(asScript).getvalue( "BaseType" )
+ else:
+ __Diag = asDiagnostic
+ __Iden = asIdentifier
+ __Dict = asDict
+ __Unit = asUnit
+ __Base = asBaseType
+ #
+ if __Diag is not None:
+ self.__D = str(__Diag)
+ if __Iden is not None:
+ self.__I = str(__Iden)
+ else:
+ self.__I = str(__Diag)
+ if __Dict is not None:
+ self.__P.update( dict(__Dict) )
+ if __Unit is None or __Unit == "None":
+ self.__U = ""
+ if __Base is None or __Base == "None":
+ self.__B = None
+ #
+ self.__setDiagnostic( self.__D, self.__I, self.__U, self.__B, self.__P, self.__E )
+
+ def get(self):
+ "Renvoie l'objet"
+ return self.__TheDiag
+
+ def __setDiagnostic(self, __choice = None, __name = "", __unit = "", __basetype = None, __parameters = {}, __existings = () ):
+ """
+ Permet de sélectionner un diagnostic a effectuer
+ """
+ if __choice is None:
+ raise ValueError("Error: diagnostic choice has to be given")
+ __daDirectory = "daDiagnostics"
+ #
+ # 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 diagnostic module named \"%s\" was found in a \"%s\" subdirectory\n The search path is %s"%(__choice, __daDirectory, sys.path))
+ #
+ # Importe le fichier complet comme un module
+ # ------------------------------------------
+ try:
+ __sys_path_tmp = sys.path ; sys.path.insert(0,__module_path)
+ self.__diagnosticFile = __import__(str(__choice), globals(), locals(), [])
+ 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
+ # -------------------------------------------------
+ if __name in __existings:
+ raise ValueError("A default input with the same name \"%s\" already exists."%str(__name))
+ else:
+ self.__TheDiag = self.__diagnosticFile.ElementaryDiagnostic(
+ name = __name,
+ unit = __unit,
+ basetype = __basetype,
+ parameters = __parameters )
+ return 0
+
+# ==============================================================================
+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.__D = None
+ self.__P = {}
+ #
+ self.__algorithm = {}
+ self.__algorithmFile = None
+ self.__algorithmName = None
+ #
+ self.updateParameters( asDict, asScript )
#
if asScript is not None:
__Algo = ImportFromScript(asScript).getvalue( "Algorithm" )
- __Dict = ImportFromScript(asScript).getvalue( self.__name, "Parameters" )
else:
__Algo = asAlgorithm
- __Dict = asDict
#
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 asScript is not None:
+ __Dict = ImportFromScript(asScript).getvalue( self.__name, "Parameters" )
+ else:
+ __Dict = asDict
+ #
if __Dict is not None:
- self.__D = dict(__Dict)
+ 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 has to be given as a dictionnary, and is 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 existing DIC Python file name has to be given for YACS execution.\n")
+ if not os.environ.has_key("ADAO_ROOT_DIR"):
+ raise ImportError("Unable to get ADAO_ROOT_DIR environnement variable. Please launch SALOME to add ADAO_ROOT_DIR to your environnement.\n")
+ #
+ __converterExe = os.path.join(os.environ["ADAO_ROOT_DIR"], "bin/salome", "AdaoYacsSchemaCreator.py")
+ __inputFile = os.path.abspath(FileName)
+ __outputFile = __inputFile[:__inputFile.rfind(".")] + '.xml'
+ #
+ __args = ["python", __converterExe, __inputFile, __outputFile]
+ import subprocess
+ __p = subprocess.Popen(__args)
+ (__stdoutdata, __stderrdata) = __p.communicate()
+ if not os.path.exists(__outputFile):
+ __msg = "An error occured during the execution of the ADAO YACS Schema\n"
+ __msg += "Creator applied on the input file:\n"
+ __msg += " %s\n"%__outputFile
+ __msg += "If SALOME GUI is launched by command line, see errors\n"
+ __msg += "details in your terminal.\n"
+ raise ValueError(__msg)
+ #
+ try:
+ import pilot
+ import SALOMERuntime
+ import loader
+ SALOMERuntime.RuntimeSALOME_setRuntime()
+
+ r = pilot.getRuntime()
+ xmlLoader = loader.YACSLoader()
+ xmlLoader.registerProcCataLoader()
+ try:
+ catalogAd = r.loadCatalog("proc", __outputFile)
+ except:
+ pass
+ r.addCatalog(catalogAd)
+
+ try:
+ p = xmlLoader.load(__outputFile)
+ except IOError as ex:
+ print("IO exception: %s"%(ex,))
+
+ logger = p.getLogger("parser")
+ if not logger.isEmpty():
+ print("The imported file has errors :")
+ print(logger.getStr())
+
+ if not p.isValid():
+ print("Le schéma n'est pas valide et ne peut pas être exécuté")
+ print(p.getErrorReport())
+
+ info=pilot.LinkInfo(pilot.LinkInfo.ALL_DONT_STOP)
+ p.checkConsistency(info)
+ if info.areWarningsOrErrors():
+ print("Le schéma n'est pas cohérent et ne peut pas être exécuté")
+ print(info.getGlobalRepr())
+
+ e = pilot.ExecutorSwig()
+ e.RunW(p)
+ if p.getEffectiveState() != pilot.DONE:
+ print(p.getErrorReport())
+ except:
+ raise ValueError("execution error of YACS scheme")
+ #
+ 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)+"\n"+repr(self.__D)
+ return repr(self.__A)+", "+repr(self.__P)
def __str__(self):
"x.__str__() <==> str(x)"
- return str(self.__A)+"\n"+str(self.__D)
+ 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 fichier contenu dans "../daAlgorithms" et réalisant l'opération
+ d'assimilation 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\" was found in a \"%s\" subdirectory\n The search path is %s"%(choice, daDirectory, 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(), [])
+ 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(type(self.__HO) is type({})) 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(type(self.__HO) is type({})) 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(type(self.__HO) is type({})) 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(type(self.__HO) is type({})) 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(type(self.__EM) is type({})) 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(type(self.__CM) is type({})) 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
# ==============================================================================
class DataObserver(object):
"""
- Classe générale d'interface de type observer
+ Classe générale d'interface de type observer
"""
def __init__(self,
- name = "GenericObserver",
- onVariable = None,
- asTemplate = None,
- asString = None,
- asScript = None,
- withInfo = None,
+ name = "GenericObserver",
+ onVariable = None,
+ asTemplate = None,
+ asString = None,
+ asScript = None,
+ asObsObject = None,
+ withInfo = None,
+ scheduledBy = None,
+ withAlgo = None,
):
+ """
+ """
self.__name = str(name)
self.__V = None
self.__O = None
self.__I = None
#
if onVariable is None:
- raise ValueError("setting an observer has to be done over a variable name, not over None.")
- else:
- self.__V = str(onVariable)
- #
- if withInfo is None:
- self.__I = str(onVariable)
+ raise ValueError("setting an observer has to be done over a variable name or a list of variable names, not over None.")
+ elif type(onVariable) in (tuple, list):
+ self.__V = tuple(map( str, onVariable ))
+ if withInfo is None:
+ self.__I = self.__V
+ else:
+ self.__I = (str(withInfo),)*len(self.__V)
+ elif isinstance(onVariable, str):
+ self.__V = (onVariable,)
+ if withInfo is None:
+ self.__I = (onVariable,)
+ else:
+ self.__I = (str(withInfo),)
else:
- self.__I = str(withInfo)
+ raise ValueError("setting an observer has to be done over a variable name or a list of variable names.")
#
if asString is not None:
__FunctionText = asString
- elif (asTemplate is not None) and (asTemplate in ObserverTemplates):
- __FunctionText = ObserverTemplates[asTemplate]
+ elif (asTemplate is not None) and (asTemplate in Templates.ObserverTemplates):
+ __FunctionText = Templates.ObserverTemplates[asTemplate]
elif asScript is not None:
__FunctionText = ImportFromScript(asScript).getstring()
else:
__FunctionText = ""
__Function = ObserverF(__FunctionText)
#
- self.__O = __Function.getfunc()
+ if asObsObject is not None:
+ self.__O = asObsObject
+ else:
+ self.__O = __Function.getfunc()
#
- return {self.__V:(self.__O, self.__I)}
+ for k in range(len(self.__V)):
+ ename = self.__V[k]
+ einfo = self.__I[k]
+ if ename not in withAlgo:
+ raise ValueError("An observer is asked to be set on a variable named %s which does not exist."%ename)
+ else:
+ withAlgo.setObserver(ename, self.__O, einfo, scheduledBy)
def __repr__(self):
"x.__repr__() <==> repr(x)"
# ==============================================================================
class State(object):
"""
- Classe générale d'interface de type état
+ Classe générale d'interface de type état
"""
def __init__(self,
name = "GenericVector",
asVector = None,
asPersistentVector = None,
asScript = None,
- Scheduler = None,
+ scheduledBy = None,
toBeChecked = False,
):
"""
- Permet de définir un vecteur :
- - asVector : entrée des données, comme un vecteur compatible avec le
- constructeur de numpy.matrix, ou "True" si entrée par script.
- - asPersistentVector : entrée des données, comme une série de vecteurs
+ Permet de définir un vecteur :
+ - asVector : entrée des données, comme un vecteur compatible avec le
+ constructeur de numpy.matrix, ou "True" si entrée par script.
+ - asPersistentVector : entrée des données, comme une série de vecteurs
compatible avec le constructeur de numpy.matrix, ou comme un objet de
- type Persistence, ou "True" si entrée par script.
- - asScript : si un script valide est donné contenant une variable
- nommée "name", la variable est de type "asVector" (par défaut) ou
- "asPersistentVector" selon que l'une de ces variables est placée à
+ type Persistence, ou "True" si entrée par script.
+ - asScript : si un script valide est donné contenant une variable
+ nommée "name", la variable est de type "asVector" (par défaut) ou
+ "asPersistentVector" selon que l'une de ces variables est placée à
"True".
"""
self.__name = str(name)
#
if __Vector is not None:
self.__is_vector = True
- self.__V = numpy.matrix( numpy.ravel(numpy.matrix(asVector)), numpy.float ).T
+ self.__V = numpy.matrix( numpy.asmatrix(__Vector).A1, numpy.float ).T
self.shape = self.__V.shape
self.size = self.__V.size
elif __Series is not None:
self.__is_series = True
- if type(__Series) in [tuple, list, numpy.ndarray, numpy.matrix]:
+ if type(__Series) in (tuple, list, numpy.ndarray, numpy.matrix):
self.__V = Persistence.OneVector(self.__name, basetype=numpy.matrix)
for member in __Series:
self.__V.store( numpy.matrix( numpy.asmatrix(member).A1, numpy.float ).T )
self.shape = self.__V.shape
else:
self.shape = self.__V.shape()
+ if len(self.shape) == 1:
+ self.shape = (self.shape[0],1)
self.size = self.shape[0] * self.shape[1]
else:
raise ValueError("The %s object is improperly defined, it requires at minima either a vector, a list/tuple of vectors or a persistent object. Please check your vector input."%self.__name)
#
- if Scheduler is not None:
- self.__T = Scheduler
+ if scheduledBy is not None:
+ self.__T = scheduledBy
+
+ def getO(self, withScheduler=False):
+ if withScheduler:
+ return self.__V, self.__T
+ elif self.__T is None:
+ return self.__V
+ else:
+ return self.__V
def isvector(self):
- "Vérification du type interne"
+ "Vérification du type interne"
return self.__is_vector
def isseries(self):
- "Vérification du type interne"
+ "Vérification du type interne"
return self.__is_series
def __repr__(self):
# ==============================================================================
class Covariance(object):
"""
- Classe générale d'interface de type covariance
+ Classe générale d'interface de type covariance
"""
def __init__(self,
name = "GenericCovariance",
toBeChecked = False,
):
"""
- Permet de définir une covariance :
- - asCovariance : entrée des données, comme une matrice compatible avec
+ Permet de définir une covariance :
+ - asCovariance : entrée des données, comme une matrice compatible avec
le constructeur de numpy.matrix
- - asEyeByScalar : entrée des données comme un seul scalaire de variance,
- multiplicatif d'une matrice de corrélation identité, aucune matrice
- n'étant donc explicitement à donner
- - asEyeByVector : entrée des données comme un seul vecteur de variance,
- à mettre sur la diagonale d'une matrice de corrélation, aucune matrice
- n'étant donc explicitement à donner
- - asCovObject : entrée des données comme un objet python, qui a les
+ - asEyeByScalar : entrée des données comme un seul scalaire de variance,
+ multiplicatif d'une matrice de corrélation identité, aucune matrice
+ n'étant donc explicitement à donner
+ - asEyeByVector : entrée des données comme un seul vecteur de variance,
+ à mettre sur la diagonale d'une matrice de corrélation, aucune matrice
+ n'étant donc explicitement à donner
+ - asCovObject : entrée des données comme un objet python, qui a les
methodes obligatoires "getT", "getI", "diag", "trace", "__add__",
"__sub__", "__neg__", "__mul__", "__rmul__" et facultatives "shape",
"size", "cholesky", "choleskyI", "asfullmatrix", "__repr__", "__str__"
- - toBeChecked : booléen indiquant si le caractère SDP de la matrice
- pleine doit être vérifié
+ - toBeChecked : booléen indiquant si le caractère SDP de la matrice
+ pleine doit être vérifié
"""
self.__name = str(name)
self.__check = bool(toBeChecked)
if asScript is not None:
__Matrix, __Scalar, __Vector, __Object = None, None, None, None
if asEyeByScalar:
- __Scalar = _ImportFromScript(asScript).getvalue( "BackgroundError" )
+ __Scalar = ImportFromScript(asScript).getvalue( self.__name )
elif asEyeByVector:
- __Vector = _ImportFromScript(asScript).getvalue( "BackgroundError" )
+ __Vector = ImportFromScript(asScript).getvalue( self.__name )
elif asCovObject:
- __Object = _ImportFromScript(asScript).getvalue( "BackgroundError" )
+ __Object = ImportFromScript(asScript).getvalue( self.__name )
else:
- __Matrix = _ImportFromScript(asScript).getvalue( "BackgroundError" )
+ __Matrix = ImportFromScript(asScript).getvalue( self.__name )
else:
__Matrix, __Scalar, __Vector, __Object = asCovariance, asEyeByScalar, asEyeByVector, asCovObject
#
raise ValueError("The %s covariance object is not symmetric positive-definite. Please check your matrix input."%(self.__name,))
def isscalar(self):
- "Vérification du type interne"
+ "Vérification du type interne"
return self.__is_scalar
def isvector(self):
- "Vérification du type interne"
+ "Vérification du type interne"
return self.__is_vector
def ismatrix(self):
- "Vérification du type interne"
+ "Vérification du type interne"
return self.__is_matrix
def isobject(self):
- "Vérification du type interne"
+ "Vérification du type interne"
return self.__is_object
def getI(self):
return Covariance(self.__name+"T", asCovObject = self.__C.getT() )
def cholesky(self):
- "Décomposition de Cholesky"
+ "Décomposition de Cholesky"
if self.ismatrix():
return Covariance(self.__name+"C", asCovariance = numpy.linalg.cholesky(self.__C) )
elif self.isvector():
return Covariance(self.__name+"C", asCovObject = self.__C.cholesky() )
def choleskyI(self):
- "Inversion de la décomposition de Cholesky"
+ "Inversion de la décomposition de Cholesky"
if self.ismatrix():
return Covariance(self.__name+"H", asCovariance = numpy.linalg.cholesky(self.__C).I )
elif self.isvector():
elif self.isobject():
return self.__C.trace()
+ def getO(self):
+ return self
+
def __repr__(self):
"x.__repr__() <==> repr(x)"
return repr(self.__C)
"""
def __init__(self, __filename=None):
"Verifie l'existence et importe le script"
- __filename = __filename.rstrip(".py")
- if __filename is None:
+ self.__filename = __filename.rstrip(".py")
+ if self.__filename is None:
raise ValueError("The name of the file containing the variable to be imported has to be specified.")
- if not os.path.isfile(str(__filename)+".py"):
- raise ValueError("The file containing the variable to be imported doesn't seem to exist. The given file name is:\n \"%s\""%__filename)
- self.__scriptfile = __import__(__filename, globals(), locals(), [])
- self.__scriptstring = open(__filename+".py",'r').read()
+ if not os.path.isfile(str(self.__filename)+".py"):
+ raise ValueError("The file containing the variable to be imported doesn't seem to exist. The given file name is:\n \"%s\""%self.__filename)
+ self.__scriptfile = __import__(self.__filename, globals(), locals(), [])
+ self.__scriptstring = open(self.__filename+".py",'r').read()
def getvalue(self, __varname=None, __synonym=None ):
"Renvoie la variable demandee"
if __varname is None:
raise ValueError("The name of the variable to be imported has to be specified.")
if not hasattr(self.__scriptfile, __varname):
if __synonym is None:
- raise ValueError("The imported script file doesn't contain the specified variable \"%s\"."%__varname)
+ raise ValueError("The imported script file \"%s\" doesn't contain the specified variable \"%s\"."%(str(self.__filename)+".py",__varname))
elif not hasattr(self.__scriptfile, __synonym):
- raise ValueError("The imported script file doesn't contain the specified variable \"%s\"."%__synonym)
+ raise ValueError("The imported script file \"%s\" doesn't contain the specified variable \"%s\"."%(str(self.__filename)+".py",__synonym))
else:
return getattr(self.__scriptfile, __synonym)
else:
# ==============================================================================
def CostFunction3D(_x,
_Hm = None, # Pour simuler Hm(x) : HO["Direct"].appliedTo
- _HmX = None, # Simulation déjà faite de Hm(x)
+ _HmX = None, # Simulation déjà faite de Hm(x)
_arg = None, # Arguments supplementaires pour Hm, sous la forme d'un tuple
_BI = None,
_RI = None,
_Xb = None,
_Y = None,
- _SIV = False, # A résorber pour la 8.0
+ _SIV = False, # A résorber pour la 8.0
_SSC = [], # self._parameters["StoreSupplementaryCalculations"]
_nPS = 0, # nbPreviousSteps
_QM = "DA", # QualityMeasure
- _SSV = {}, # Entrée et/ou sortie : self.StoredVariables
- _fRt = False, # Restitue ou pas la sortie étendue
+ _SSV = {}, # Entrée et/ou sortie : self.StoredVariables
+ _fRt = False, # Restitue ou pas la sortie étendue
_sSc = True, # Stocke ou pas les SSC
):
"""
- Fonction-coût générale utile pour les algorithmes statiques/3D : 3DVAR, BLUE
- et dérivés, Kalman et dérivés, LeastSquares, SamplingTest, PSO, SA, Tabu,
+ Fonction-coût générale utile pour les algorithmes statiques/3D : 3DVAR, BLUE
+ et dérivés, Kalman et dérivés, LeastSquares, SamplingTest, PSO, SA, Tabu,
DFO, QuantileRegression
"""
if not _sSc:
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
"""
Ce module permet de mettre en place un logging utilisable partout dans
- l'application, par défaut à la console, et si nécessaire dans un fichier.
+ l'application, par défaut à la console, et si nécessaire dans un fichier.
- Il doit être appelé en premier dans AssimilationStudy (mais pas directement
+ Il doit être appelé en premier dans AssimilationStudy (mais pas directement
dans les applications utilisateurs), en l'important et en instanciant un
objet :
import ExtendedLogging ; ExtendedLogging.ExtendedLogging()
- Par défaut, seuls les messages du niveau WARNING ou au-delà sont disponibles
+ Par défaut, seuls les messages du niveau WARNING ou au-delà sont disponibles
(donc les simples messages d'info ne sont pas disponibles), ce que l'on peut
- changer à l'instanciation avec le mot-clé "level" :
+ changer à l'instanciation avec le mot-clé "level" :
import ExtendedLogging ; ExtendedLogging.ExtendedLogging(level=20)
- On peut éventuellement demander à l'objet de sortir aussi les messages dans
- un fichier (noms par défaut : AssimilationStudy.log, niveau NOTSET) :
+ On peut éventuellement demander à l'objet de sortir aussi les messages dans
+ un fichier (noms par défaut : AssimilationStudy.log, niveau NOTSET) :
import ExtendedLogging ; ExtendedLogging.ExtendedLogging().setLogfile()
Si on veut changer le nom du fichier ou le niveau global de message, il faut
- récupérer l'instance et appliquer les méthodes :
+ récupérer l'instance et appliquer les méthodes :
import ExtendedLogging
log = ExtendedLogging.ExtendedLogging()
import logging
log.setLevel(logging.DEBUG)
log.setLogfile(filename="toto.log", filemode="a", level=logging.WARNING)
- et on change éventuellement le niveau avec :
+ et on change éventuellement le niveau avec :
log.setLogfileLevel(logging.INFO)
- Ensuite, n'importe où dans les applications, il suffit d'utiliser le module
+ Ensuite, n'importe où dans les applications, il suffit d'utiliser le module
"logging" (avec un petit "l") :
import logging
- log = logging.getLogger(NAME) # Avec rien (recommandé) ou un nom NAME
+ log = logging.getLogger(NAME) # Avec rien (recommandé) ou un nom NAME
log.critical("...")
log.error("...")
log.warning("...")
import logging
logging.info("...")
- Dans une application, à n'importe quel endroit et autant de fois qu'on veut,
+ Dans une application, à n'importe quel endroit et autant de fois qu'on veut,
on peut changer le niveau global de message en utilisant par exemple :
import logging
- log = logging.getLogger(NAME) # Avec rien (recommandé) ou un nom NAME
+ log = logging.getLogger(NAME) # Avec rien (recommandé) ou un nom NAME
log.setLevel(logging.DEBUG)
On rappelle les niveaux (attributs de "logging") et leur ordre :
# ==============================================================================
class ExtendedLogging(object):
"""
- Logger général pour disposer conjointement de la sortie standard et de la
+ Logger général pour disposer conjointement de la sortie standard et de la
sortie sur fichier
"""
def __init__(self, level=logging.WARNING):
"""
- Initialise un logging à la console pour TOUS les niveaux de messages.
+ Initialise un logging à la console pour TOUS les niveaux de messages.
"""
logging.basicConfig(
format = '%(levelname)-8s %(message)s',
Permet de disposer des messages dans un fichier EN PLUS de la console.
"""
if self.__logfile is not None:
- # Supprime le précédent mode de stockage fichier s'il exsitait
+ # Supprime le précédent mode de stockage fichier s'il exsitait
logging.getLogger().removeHandler(self.__logfile)
self.__logfile = logging.FileHandler(filename, filemode)
self.__logfile.setLevel(level)
def setLogfileLevel(self, level=logging.NOTSET ):
"""
- Permet de changer le niveau des messages stockés en fichier. Il ne sera
- pris en compte que s'il est supérieur au niveau global.
+ Permet de changer le niveau des messages stockés en fichier. Il ne sera
+ pris en compte que s'il est supérieur au niveau global.
"""
self.__logfile.setLevel(level)
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
# Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
"""
- Définit des outils de persistence et d'enregistrement de séries de valeurs
- pour analyse ultérieure ou utilisation de calcul.
+ Définit des outils de persistence et d'enregistrement de séries de valeurs
+ pour analyse ultérieure ou utilisation de calcul.
"""
__author__ = "Jean-Philippe ARGAUD"
__all__ = []
from daCore.PlatformInfo import PathManagement ; PathManagement()
+if sys.version_info.major < 3:
+ range = xrange
+ iLong = long
+ import cPickle as pickle
+else:
+ iLong = int
+ import pickle
+
# ==============================================================================
class Persistence(object):
"""
- Classe générale de persistence définissant les accesseurs nécessaires
+ Classe générale de persistence définissant les accesseurs nécessaires
(Template)
"""
def __init__(self, name="", unit="", basetype=str):
"""
name : nom courant
- unit : unité
- basetype : type de base de l'objet stocké à chaque pas
+ unit : unité
+ basetype : type de base de l'objet stocké à chaque pas
- La gestion interne des données est exclusivement basée sur les variables
- initialisées ici (qui ne sont pas accessibles depuis l'extérieur des
+ La gestion interne des données est exclusivement basée sur les variables
+ initialisées ici (qui ne sont pas accessibles depuis l'extérieur des
objets comme des attributs) :
__basetype : le type de base de chaque valeur, sous la forme d'un type
permettant l'instanciation ou le casting Python
- __values : les valeurs de stockage. Par défaut, c'est None
+ __values : les valeurs de stockage. Par défaut, c'est None
"""
self.__name = str(name)
self.__unit = str(unit)
def basetype(self, basetype=None):
"""
- Renvoie ou met en place le type de base des objets stockés
+ Renvoie ou met en place le type de base des objets stockés
"""
if basetype is None:
return self.__basetype
def shape(self):
"""
- Renvoie la taille sous forme numpy du dernier objet stocké. Si c'est un
+ Renvoie la taille sous forme numpy du dernier objet stocké. Si c'est un
objet numpy, renvoie le shape. Si c'est un entier, un flottant, un
complexe, renvoie 1. Si c'est une liste ou un dictionnaire, renvoie la
- longueur. Par défaut, renvoie 1.
+ longueur. Par défaut, renvoie 1.
"""
if len(self.__values) > 0:
if self.__basetype in [numpy.matrix, numpy.ndarray, numpy.array, numpy.ravel]:
"D.tagkeys() -> list of D's tag keys"
__allKeys = []
for dicotags in self.__tags:
- __allKeys.extend( dicotags.keys() )
- __allKeys = list(set(__allKeys))
- __allKeys.sort()
+ __allKeys.extend( list(dicotags.keys()) )
+ __allKeys = sorted(set(__allKeys))
return __allKeys
# def valueserie(self, item=None, allSteps=True, **kwargs):
else:
__indexOfFilteredItems = [item,]
#
- # Dans le cas où la sortie donne les valeurs d'un "outputTag"
+ # Dans le cas où la sortie donne les valeurs d'un "outputTag"
if outputTag is not None and isinstance(outputTag,str) :
outputValues = []
for index in __indexOfFilteredItems:
if outputTag in self.__tags[index].keys():
outputValues.append( self.__tags[index][outputTag] )
- outputValues = list(set(outputValues))
- outputValues.sort()
+ outputValues = sorted(set(outputValues))
return outputValues
#
- # Dans le cas où la sortie donne les tags satisfaisants aux conditions
+ # Dans le cas où la sortie donne les tags satisfaisants aux conditions
else:
if withValues:
return [self.__tags[index] for index in __indexOfFilteredItems]
allTags = {}
for index in __indexOfFilteredItems:
allTags.update( self.__tags[index] )
- allKeys = list(allTags.keys())
- allKeys.sort()
+ allKeys = sorted(allTags.keys())
return allKeys
# ---------------------------------------------------------
# Pour compatibilite
def stepserie(self, **kwargs):
- "Nombre de pas filtrés"
+ "Nombre de pas filtrés"
__indexOfFilteredItems = self.__filteredIndexes(**kwargs)
return __indexOfFilteredItems
+ # Pour compatibilite
+ def steplist(self, **kwargs):
+ "Nombre de pas filtrés"
+ __indexOfFilteredItems = self.__filteredIndexes(**kwargs)
+ return list(__indexOfFilteredItems)
+
# ---------------------------------------------------------
def means(self):
"""
- Renvoie la série, contenant à chaque pas, la valeur moyenne des données
+ Renvoie la série, contenant à chaque pas, la valeur moyenne des données
au pas. Il faut que le type de base soit compatible avec les types
- élémentaires numpy.
+ élémentaires numpy.
"""
try:
return [numpy.matrix(item).mean() for item in self.__values]
def stds(self, ddof=0):
"""
- Renvoie la série, contenant à chaque pas, l'écart-type des données
+ Renvoie la série, contenant à chaque pas, l'écart-type des données
au pas. Il faut que le type de base soit compatible avec les types
- élémentaires numpy.
+ élémentaires numpy.
- ddof : c'est le nombre de degrés de liberté pour le calcul de
- l'écart-type, qui est dans le diviseur. Inutile avant Numpy 1.1
+ ddof : c'est le nombre de degrés de liberté pour le calcul de
+ l'écart-type, qui est dans le diviseur. Inutile avant Numpy 1.1
"""
try:
if numpy.version.version >= '1.1.0':
def sums(self):
"""
- Renvoie la série, contenant à chaque pas, la somme des données au pas.
- Il faut que le type de base soit compatible avec les types élémentaires
+ Renvoie la série, contenant à chaque pas, la somme des données au pas.
+ Il faut que le type de base soit compatible avec les types élémentaires
numpy.
"""
try:
def mins(self):
"""
- Renvoie la série, contenant à chaque pas, le minimum des données au pas.
- Il faut que le type de base soit compatible avec les types élémentaires
+ Renvoie la série, contenant à chaque pas, le minimum des données au pas.
+ Il faut que le type de base soit compatible avec les types élémentaires
numpy.
"""
try:
def maxs(self):
"""
- Renvoie la série, contenant à chaque pas, la maximum des données au pas.
- Il faut que le type de base soit compatible avec les types élémentaires
+ Renvoie la série, contenant à chaque pas, la maximum des données au pas.
+ Il faut que le type de base soit compatible avec les types élémentaires
numpy.
"""
try:
persist = False,
pause = True,
):
- "Préparation des plots"
+ "Préparation des plots"
#
- # Vérification de la disponibilité du module Gnuplot
+ # Vérification de la disponibilité du module Gnuplot
try:
import Gnuplot
self.__gnuplot = Gnuplot
except:
raise ImportError("The Gnuplot module is required to plot the object.")
#
- # Vérification et compléments sur les paramètres d'entrée
+ # Vérification et compléments sur les paramètres d'entrée
if persist:
self.__gnuplot.GnuplotOpts.gnuplot_command = 'gnuplot -persist -geometry '+geometry
else:
self.__g('set style data lines')
self.__g('set grid')
self.__g('set autoscale')
- self.__g('set xlabel "'+str(xlabel).encode('ascii','replace')+'"')
- self.__g('set ylabel "'+str(ylabel).encode('ascii','replace')+'"')
+ self.__g('set xlabel "'+str(xlabel)+'"')
+ self.__g('set ylabel "'+str(ylabel)+'"')
self.__title = title
self.__ltitle = ltitle
self.__pause = pause
pause = True,
):
"""
- Renvoie un affichage de la valeur à chaque pas, si elle est compatible
+ Renvoie un affichage de la valeur à chaque pas, si elle est compatible
avec un affichage Gnuplot (donc essentiellement un vecteur). Si
- l'argument "step" existe dans la liste des pas de stockage effectués,
- renvoie l'affichage de la valeur stockée à ce pas "step". Si l'argument
- "item" est correct, renvoie l'affichage de la valeur stockée au numéro
- "item". Par défaut ou en l'absence de "step" ou "item", renvoie un
+ l'argument "step" existe dans la liste des pas de stockage effectués,
+ renvoie l'affichage de la valeur stockée à ce pas "step". Si l'argument
+ "item" est correct, renvoie l'affichage de la valeur stockée au numéro
+ "item". Par défaut ou en l'absence de "step" ou "item", renvoie un
affichage successif de tous les pas.
Arguments :
- - step : valeur du pas à afficher
- - item : index de la valeur à afficher
+ - step : valeur du pas à afficher
+ - item : index de la valeur à afficher
- steps : liste unique des pas de l'axe des X, ou None si c'est
- la numérotation par défaut
- - title : base du titre général, qui sera automatiquement
- complétée par la mention du pas
+ la numérotation par défaut
+ - title : base du titre général, qui sera automatiquement
+ complétée par la mention du pas
- xlabel : label de l'axe des X
- ylabel : label de l'axe des Y
- - ltitle : titre associé au vecteur tracé
- - geometry : taille en pixels de la fenêtre et position du coin haut
- gauche, au format X11 : LxH+X+Y (défaut : 600x400)
+ - ltitle : titre associé au vecteur tracé
+ - geometry : taille en pixels de la fenêtre et position du coin haut
+ gauche, au format X11 : LxH+X+Y (défaut : 600x400)
- filename : base de nom de fichier Postscript pour une sauvegarde,
- qui est automatiquement complétée par le numéro du
- fichier calculé par incrément simple de compteur
- - dynamic : effectue un affichage des valeurs à chaque stockage
- (au-delà du second). La méthode "plots" permet de
- déclarer l'affichage dynamique, et c'est la méthode
- "__replots" qui est utilisée pour l'effectuer
- - persist : booléen indiquant que la fenêtre affichée sera
- conservée lors du passage au dessin suivant
- Par défaut, persist = False
- - pause : booléen indiquant une pause après chaque tracé, et
+ qui est automatiquement complétée par le numéro du
+ fichier calculé par incrément simple de compteur
+ - dynamic : effectue un affichage des valeurs à chaque stockage
+ (au-delà du second). La méthode "plots" permet de
+ déclarer l'affichage dynamique, et c'est la méthode
+ "__replots" qui est utilisée pour l'effectuer
+ - persist : booléen indiquant que la fenêtre affichée sera
+ conservée lors du passage au dessin suivant
+ Par défaut, persist = False
+ - pause : booléen indiquant une pause après chaque tracé, et
attendant un Return
- Par défaut, pause = True
+ Par défaut, pause = True
"""
import os
if not self.__dynamic:
self.__dynamic = True
if len(self.__values) == 0: return 0
#
- # Tracé du ou des vecteurs demandés
+ # Tracé du ou des vecteurs demandés
indexes = []
if step is not None and step < len(self.__values):
indexes.append(step)
elif item is not None and item < len(self.__values):
indexes.append(item)
else:
- indexes = indexes + range(len(self.__values))
+ indexes = indexes + list(range(len(self.__values)))
#
i = -1
for index in indexes:
- self.__g('set title "'+str(title).encode('ascii','replace')+' (pas '+str(index)+')"')
+ self.__g('set title "'+str(title)+' (pas '+str(index)+')"')
if isinstance(steps,list) or isinstance(steps,numpy.ndarray):
Steps = list(steps)
else:
- Steps = range(len(self.__values[index]))
+ Steps = list(range(len(self.__values[index])))
#
self.__g.plot( self.__gnuplot.Data( Steps, self.__values[index], title=ltitle ) )
#
raise ValueError("Error: a file with this name \"%s\" already exists."%stepfilename)
self.__g.hardcopy(filename=stepfilename, color=1)
if self.__pause:
- raw_input('Please press return to continue...\n')
+ eval(input('Please press return to continue...\n'))
def __replots(self):
"""
"""
if self.__dynamic and len(self.__values) < 2: return 0
#
- self.__g('set title "'+str(self.__title).encode('ascii','replace'))
- Steps = range(len(self.__values))
+ self.__g('set title "'+str(self.__title))
+ Steps = list(range(len(self.__values)))
self.__g.plot( self.__gnuplot.Data( Steps, self.__values, title=self.__ltitle ) )
#
if self.__pause:
- raw_input('Please press return to continue...\n')
+ eval(input('Please press return to continue...\n'))
# ---------------------------------------------------------
def mean(self):
"""
Renvoie la moyenne sur toutes les valeurs sans tenir compte de la
longueur des pas. Il faut que le type de base soit compatible avec
- les types élémentaires numpy.
+ les types élémentaires numpy.
"""
try:
if self.__basetype in [int, float]:
def std(self, ddof=0):
"""
- Renvoie l'écart-type de toutes les valeurs sans tenir compte de la
+ Renvoie l'écart-type de toutes les valeurs sans tenir compte de la
longueur des pas. Il faut que le type de base soit compatible avec
- les types élémentaires numpy.
+ les types élémentaires numpy.
- ddof : c'est le nombre de degrés de liberté pour le calcul de
- l'écart-type, qui est dans le diviseur. Inutile avant Numpy 1.1
+ ddof : c'est le nombre de degrés de liberté pour le calcul de
+ l'écart-type, qui est dans le diviseur. Inutile avant Numpy 1.1
"""
try:
if numpy.version.version >= '1.1.0':
"""
Renvoie la somme de toutes les valeurs sans tenir compte de la
longueur des pas. Il faut que le type de base soit compatible avec
- les types élémentaires numpy.
+ les types élémentaires numpy.
"""
try:
return numpy.array(self.__values).sum(axis=0)
"""
Renvoie le minimum de toutes les valeurs sans tenir compte de la
longueur des pas. Il faut que le type de base soit compatible avec
- les types élémentaires numpy.
+ les types élémentaires numpy.
"""
try:
return numpy.array(self.__values).min(axis=0)
"""
Renvoie le maximum de toutes les valeurs sans tenir compte de la
longueur des pas. Il faut que le type de base soit compatible avec
- les types élémentaires numpy.
+ les types élémentaires numpy.
"""
try:
return numpy.array(self.__values).max(axis=0)
def cumsum(self):
"""
- Renvoie la somme cumulée de toutes les valeurs sans tenir compte de la
+ Renvoie la somme cumulée de toutes les valeurs sans tenir compte de la
longueur des pas. Il faut que le type de base soit compatible avec
- les types élémentaires numpy.
+ les types élémentaires numpy.
"""
try:
return numpy.array(self.__values).cumsum(axis=0)
pause = True,
):
"""
- Renvoie un affichage unique pour l'ensemble des valeurs à chaque pas, si
+ Renvoie un affichage unique pour l'ensemble des valeurs à chaque pas, si
elles sont compatibles avec un affichage Gnuplot (donc essentiellement
un vecteur). Si l'argument "step" existe dans la liste des pas de
- stockage effectués, renvoie l'affichage de la valeur stockée à ce pas
+ stockage effectués, renvoie l'affichage de la valeur stockée à ce pas
"step". Si l'argument "item" est correct, renvoie l'affichage de la
- valeur stockée au numéro "item".
+ valeur stockée au numéro "item".
Arguments :
- steps : liste unique des pas de l'axe des X, ou None si c'est
- la numérotation par défaut
- - title : base du titre général, qui sera automatiquement
- complétée par la mention du pas
+ la numérotation par défaut
+ - title : base du titre général, qui sera automatiquement
+ complétée par la mention du pas
- xlabel : label de l'axe des X
- ylabel : label de l'axe des Y
- - ltitle : titre associé au vecteur tracé
- - geometry : taille en pixels de la fenêtre et position du coin haut
- gauche, au format X11 : LxH+X+Y (défaut : 600x400)
+ - ltitle : titre associé au vecteur tracé
+ - geometry : taille en pixels de la fenêtre et position du coin haut
+ gauche, au format X11 : LxH+X+Y (défaut : 600x400)
- filename : nom de fichier Postscript pour une sauvegarde
- - persist : booléen indiquant que la fenêtre affichée sera
- conservée lors du passage au dessin suivant
- Par défaut, persist = False
- - pause : booléen indiquant une pause après chaque tracé, et
+ - persist : booléen indiquant que la fenêtre affichée sera
+ conservée lors du passage au dessin suivant
+ Par défaut, persist = False
+ - pause : booléen indiquant une pause après chaque tracé, et
attendant un Return
- Par défaut, pause = True
+ Par défaut, pause = True
"""
#
- # Vérification de la disponibilité du module Gnuplot
+ # Vérification de la disponibilité du module Gnuplot
try:
import Gnuplot
self.__gnuplot = Gnuplot
except:
raise ImportError("The Gnuplot module is required to plot the object.")
#
- # Vérification et compléments sur les paramètres d'entrée
+ # Vérification et compléments sur les paramètres d'entrée
if persist:
self.__gnuplot.GnuplotOpts.gnuplot_command = 'gnuplot -persist -geometry '+geometry
else:
if isinstance(steps,list) or isinstance(steps, numpy.ndarray):
Steps = list(steps)
else:
- Steps = range(len(self.__values[0]))
+ Steps = list(range(len(self.__values[0])))
self.__g = self.__gnuplot.Gnuplot() # persist=1
self.__g('set terminal '+self.__gnuplot.GnuplotOpts.default_term)
self.__g('set style data lines')
self.__g('set grid')
self.__g('set autoscale')
- self.__g('set title "'+str(title).encode('ascii','replace') +'"')
- self.__g('set xlabel "'+str(xlabel).encode('ascii','replace')+'"')
- self.__g('set ylabel "'+str(ylabel).encode('ascii','replace')+'"')
+ self.__g('set title "'+str(title) +'"')
+ self.__g('set xlabel "'+str(xlabel)+'"')
+ self.__g('set ylabel "'+str(ylabel)+'"')
#
- # Tracé du ou des vecteurs demandés
+ # Tracé du ou des vecteurs demandés
indexes = list(range(len(self.__values)))
self.__g.plot( self.__gnuplot.Data( Steps, self.__values[indexes.pop(0)], title=ltitle+" (pas 0)" ) )
for index in indexes:
if filename != "":
self.__g.hardcopy(filename=filename, color=1)
if pause:
- raw_input('Please press return to continue...\n')
+ eval(input('Please press return to continue...\n'))
# ---------------------------------------------------------
def setDataObserver(self, HookFunction = None, HookParameters = None, Scheduler = None):
"""
- Association à la variable d'un triplet définissant un observer
+ Association à la variable d'un triplet définissant un observer
- Le Scheduler attendu est une fréquence, une simple liste d'index ou un
+ Le Scheduler attendu est une fréquence, une simple liste d'index ou un
range des index.
"""
#
- # Vérification du Scheduler
+ # Vérification du Scheduler
# -------------------------
maxiter = int( 1e9 )
- if sys.version.split()[0] < '3':
- if isinstance(Scheduler,int): # Considéré comme une fréquence à partir de 0
- Schedulers = xrange( 0, maxiter, int(Scheduler) )
- elif isinstance(Scheduler,xrange): # Considéré comme un itérateur
- Schedulers = Scheduler
- elif isinstance(Scheduler,(list,tuple)): # Considéré comme des index explicites
- Schedulers = [long(i) for i in Scheduler] # map( long, Scheduler )
- else: # Dans tous les autres cas, activé par défaut
- Schedulers = xrange( 0, maxiter )
- else:
- if isinstance(Scheduler,int): # Considéré comme une fréquence à partir de 0
- Schedulers = range( 0, maxiter, int(Scheduler) )
- elif sys.version.split()[0] > '3' and isinstance(Scheduler,range): # Considéré comme un itérateur
- Schedulers = Scheduler
- elif isinstance(Scheduler,(list,tuple)): # Considéré comme des index explicites
- Schedulers = [int(i) for i in Scheduler] # map( int, Scheduler )
- else: # Dans tous les autres cas, activé par défaut
- Schedulers = range( 0, maxiter )
+ if isinstance(Scheduler,int): # Considéré comme une fréquence à partir de 0
+ Schedulers = range( 0, maxiter, int(Scheduler) )
+ elif isinstance(Scheduler,range): # Considéré comme un itérateur
+ Schedulers = Scheduler
+ elif isinstance(Scheduler,(list,tuple)): # Considéré comme des index explicites
+ Schedulers = [iLong(i) for i in Scheduler] # map( long, Scheduler )
+ else: # Dans tous les autres cas, activé par défaut
+ Schedulers = range( 0, maxiter )
#
# Stockage interne de l'observer dans la variable
# -----------------------------------------------
self.__dataobservers.append( [HookFunction, HookParameters, Schedulers] )
- def removeDataObserver(self, HookFunction = None):
+ def removeDataObserver(self, HookFunction = None, AllObservers = False):
"""
- Suppression d'un observer nommé sur la variable.
+ Suppression d'un observer nommé sur la variable.
On peut donner dans HookFunction la meme fonction que lors de la
- définition, ou un simple string qui est le nom de la fonction.
+ définition, ou un simple string qui est le nom de la fonction. Si
+ AllObservers est vrai, supprime tous les observers enregistrés.
"""
if hasattr(HookFunction,"func_name"):
name = str( HookFunction.func_name )
+ elif hasattr(HookFunction,"__name__"):
+ name = str( HookFunction.__name__ )
elif isinstance(HookFunction,str):
name = str( HookFunction )
else:
index_to_remove = []
for [hf, hp, hs] in self.__dataobservers:
i = i + 1
- if name is hf.__name__: index_to_remove.append( i )
+ if name is hf.__name__ or AllObservers: index_to_remove.append( i )
index_to_remove.reverse()
for i in index_to_remove:
self.__dataobservers.pop( i )
+ return len(index_to_remove)
+
+ def hasDataObserver(self):
+ return bool(len(self.__dataobservers) > 0)
# ==============================================================================
class OneScalar(Persistence):
"""
- Classe définissant le stockage d'une valeur unique réelle (float) par pas.
+ Classe définissant le stockage d'une valeur unique réelle (float) par pas.
- Le type de base peut être changé par la méthode "basetype", mais il faut que
- le nouveau type de base soit compatible avec les types par éléments de
- numpy. On peut même utiliser cette classe pour stocker des vecteurs/listes
- ou des matrices comme dans les classes suivantes, mais c'est déconseillé
+ Le type de base peut être changé par la méthode "basetype", mais il faut que
+ le nouveau type de base soit compatible avec les types par éléments de
+ numpy. On peut même utiliser cette classe pour stocker des vecteurs/listes
+ ou des matrices comme dans les classes suivantes, mais c'est déconseillé
pour conserver une signification claire des noms.
"""
def __init__(self, name="", unit="", basetype = float):
class OneIndex(Persistence):
"""
- Classe définissant le stockage d'une valeur unique entière (int) par pas.
+ Classe définissant le stockage d'une valeur unique entière (int) par pas.
"""
def __init__(self, name="", unit="", basetype = int):
Persistence.__init__(self, name, unit, basetype)
class OneVector(Persistence):
"""
- Classe de stockage d'une liste de valeurs numériques homogènes par pas. Ne
- pas utiliser cette classe pour des données hétérogènes, mais "OneList".
+ Classe de stockage d'une liste de valeurs numériques homogènes par pas. Ne
+ pas utiliser cette classe pour des données hétérogènes, mais "OneList".
"""
def __init__(self, name="", unit="", basetype = numpy.ravel):
Persistence.__init__(self, name, unit, basetype)
class OneList(Persistence):
"""
- Classe de stockage d'une liste de valeurs hétérogènes (list) par pas. Ne pas
- utiliser cette classe pour des données numériques homogènes, mais
+ Classe de stockage d'une liste de valeurs hétérogènes (list) par pas. Ne pas
+ utiliser cette classe pour des données numériques homogènes, mais
"OneVector".
"""
def __init__(self, name="", unit="", basetype = list):
class OneNoType(Persistence):
"""
Classe de stockage d'un objet sans modification (cast) de type. Attention,
- selon le véritable type de l'objet stocké à chaque pas, les opérations
- arithmétiques à base de numpy peuvent être invalides ou donner des résultats
- inattendus. Cette classe n'est donc à utiliser qu'à bon escient
- volontairement, et pas du tout par défaut.
+ selon le véritable type de l'objet stocké à chaque pas, les opérations
+ arithmétiques à base de numpy peuvent être invalides ou donner des résultats
+ inattendus. Cette classe n'est donc à utiliser qu'à bon escient
+ volontairement, et pas du tout par défaut.
"""
def __init__(self, name="", unit="", basetype = NoType):
Persistence.__init__(self, name, unit, basetype)
Structure de stockage permettant de rassembler plusieurs objets de
persistence.
- Des objets par défaut sont prévus, et des objets supplémentaires peuvent
- être ajoutés.
+ Des objets par défaut sont prévus, et des objets supplémentaires peuvent
+ être ajoutés.
"""
def __init__(self, name="", defaults=True):
"""
name : nom courant
- La gestion interne des données est exclusivement basée sur les variables
- initialisées ici (qui ne sont pas accessibles depuis l'extérieur des
+ La gestion interne des données est exclusivement basée sur les variables
+ initialisées ici (qui ne sont pas accessibles depuis l'extérieur des
objets comme des attributs) :
- __StoredObjects : objets de type persistence collectés dans cet objet
+ __StoredObjects : objets de type persistence collectés dans cet objet
"""
self.__name = str(name)
#
def add_object(self, name=None, persistenceType=Persistence, basetype=None ):
"""
- Ajoute dans les objets stockables un nouvel objet défini par son nom, son
- type de Persistence et son type de base à chaque pas.
+ Ajoute dans les objets stockables un nouvel objet défini par son nom, son
+ type de Persistence et son type de base à chaque pas.
"""
if name is None: raise ValueError("Object name is required for adding an object.")
if name in self.__StoredObjects.keys():
def get_object(self, name=None ):
"""
- Renvoie l'objet de type Persistence qui porte le nom demandé.
+ Renvoie l'objet de type Persistence qui porte le nom demandé.
"""
if name is None: raise ValueError("Object name is required for retrieving an object.")
if name not in self.__StoredObjects.keys():
def set_object(self, name=None, objet=None ):
"""
- Affecte directement un 'objet' qui porte le nom 'name' demandé.
- Attention, il n'est pas effectué de vérification sur le type, qui doit
- comporter les méthodes habituelles de Persistence pour que cela
+ Affecte directement un 'objet' qui porte le nom 'name' demandé.
+ Attention, il n'est pas effectué de vérification sur le type, qui doit
+ comporter les méthodes habituelles de Persistence pour que cela
fonctionne.
"""
if name is None: raise ValueError("Object name is required for setting an object.")
del self.__StoredObjects[name]
# ---------------------------------------------------------
- # Méthodes d'accès de type dictionnaire
+ # Méthodes d'accès de type dictionnaire
def __getitem__(self, name=None ):
"x.__getitem__(y) <==> x[y]"
return self.get_object( name )
# ---------------------------------------------------------
def get_stored_objects(self, hideVoidObjects = False):
- "Renvoie la liste des objets présents"
+ "Renvoie la liste des objets présents"
objs = self.__StoredObjects.keys()
if hideVoidObjects:
usedObjs = []
finally:
pass
objs = usedObjs
- objs = list(objs)
- objs.sort()
+ objs = sorted(objs)
return objs
# ---------------------------------------------------------
def save_composite(self, filename=None, mode="pickle", compress="gzip"):
"""
- Enregistre l'objet dans le fichier indiqué selon le "mode" demandé,
+ Enregistre l'objet dans le fichier indiqué selon le "mode" demandé,
et renvoi le nom du fichier
"""
import os
else:
filename = os.path.abspath( filename )
#
- if sys.version.split()[0] < '3':
- import cPickle as lPickle
- else:
- import pickle as lPickle
if mode == "pickle":
if compress == "gzip":
import gzip
output = bz2.BZ2File( filename, 'wb')
else:
output = open( filename, 'wb')
- lPickle.dump(self, output)
+ pickle.dump(self, output)
output.close()
else:
raise ValueError("Save mode '%s' unknown. Choose another one."%mode)
def load_composite(self, filename=None, mode="pickle", compress="gzip"):
"""
- Recharge un objet composite sauvé en fichier
+ Recharge un objet composite sauvé en fichier
"""
import os
if filename is None:
else:
filename = os.path.abspath( filename )
#
- if sys.version.split()[0] < '3':
- import cPickle as lPickle
- else:
- import pickle as lPickle
if mode == "pickle":
if compress == "gzip":
import gzip
pkl_file = bz2.BZ2File( filename, 'rb')
else:
pkl_file = open(filename, 'rb')
- output = lPickle.load(pkl_file)
+ output = pickle.load(pkl_file)
for k in output.keys():
self[k] = output[k]
else:
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
# Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
"""
- Informations sur le code et la plateforme, et mise à jour des chemins
+ Informations sur le code et la plateforme, et mise à jour des chemins
- La classe "PlatformInfo" permet de récupérer les informations générales sur
+ La classe "PlatformInfo" permet de récupérer les informations générales sur
le code et la plateforme sous forme de strings, ou d'afficher directement
- les informations disponibles par les méthodes. L'impression directe d'un
+ les informations disponibles par les méthodes. L'impression directe d'un
objet de cette classe affiche les informations minimales. Par exemple :
print PlatformInfo()
print PlatformInfo().getVersion()
created = PlatformInfo().getDate()
- La classe "PathManagement" permet de mettre à jour les chemins système pour
- ajouter les outils numériques, matrices... On l'utilise en instanciant
- simplement cette classe, sans meme récupérer d'objet :
+ La classe "PathManagement" permet de mettre à jour les chemins système pour
+ ajouter les outils numériques, matrices... On l'utilise en instanciant
+ simplement cette classe, sans meme récupérer d'objet :
PathManagement()
"""
__author__ = "Jean-Philippe ARGAUD"
return dav.name
def getVersion(self):
- "Retourne le numéro de la version"
+ "Retourne le numéro de la version"
import daCore.version as dav
return dav.version
def getDate(self):
- "Retourne la date de création de la version"
+ "Retourne la date de création de la version"
import daCore.version as dav
return dav.date
return "0.0.0"
def getCurrentMemorySize(self):
- "Retourne la taille mémoire courante utilisée"
+ "Retourne la taille mémoire courante utilisée"
return 1
def MaximumPrecision(self):
# ==============================================================================
def uniq(sequence):
"""
- Fonction pour rendre unique chaque élément d'une liste, en préservant l'ordre
+ Fonction pour rendre unique chaque élément d'une liste, en préservant l'ordre
"""
__seen = set()
return [x for x in sequence if x not in __seen and not __seen.add(x)]
# ==============================================================================
class PathManagement(object):
"""
- Mise à jour du path système pour les répertoires d'outils
+ Mise à jour du path système pour les répertoires d'outils
"""
def __init__(self):
- "Déclaration des répertoires statiques"
+ "Déclaration des répertoires statiques"
parent = os.path.abspath(os.path.join(os.path.dirname(__file__),".."))
self.__paths = {}
self.__paths["daExternals"] = os.path.join(parent,"daExternals")
def getpaths(self):
"""
- Renvoie le dictionnaire des chemins ajoutés
+ Renvoie le dictionnaire des chemins ajoutés
"""
return self.__paths
# ==============================================================================
class SystemUsage(object):
"""
- Permet de récupérer les différentes tailles mémoires du process courant
+ Permet de récupérer les différentes tailles mémoires du process courant
"""
#
- # Le module resource renvoie 0 pour les tailles mémoire. On utilise donc
- # plutôt : http://code.activestate.com/recipes/286222/ et Wikipedia
+ # Le module resource renvoie 0 pour les tailles mémoire. On utilise donc
+ # plutôt : http://code.activestate.com/recipes/286222/ et Wikipedia
#
_proc_status = '/proc/%d/status' % os.getpid()
_memo_status = '/proc/meminfo'
pass
#
def _VmA(self, VmKey, unit):
- "Lecture des paramètres mémoire de la machine"
+ "Lecture des paramètres mémoire de la machine"
try:
t = open(self._memo_status)
v = t.read()
return mem / self._scale[unit]
#
def getAvailablePhysicalMemory(self, unit="o"):
- "Renvoie la mémoire physique utilisable en octets"
+ "Renvoie la mémoire physique utilisable en octets"
return self._VmA('MemTotal:', unit)
#
def getAvailableSwapMemory(self, unit="o"):
- "Renvoie la mémoire swap utilisable en octets"
+ "Renvoie la mémoire swap utilisable en octets"
return self._VmA('SwapTotal:', unit)
#
def getAvailableMemory(self, unit="o"):
- "Renvoie la mémoire totale (physique+swap) utilisable en octets"
+ "Renvoie la mémoire totale (physique+swap) utilisable en octets"
return self._VmA('MemTotal:', unit) + self._VmA('SwapTotal:', unit)
#
def getUsableMemory(self, unit="o"):
- """Renvoie la mémoire utilisable en octets
- Rq : il n'est pas sûr que ce décompte soit juste...
+ """Renvoie la mémoire utilisable en octets
+ Rq : il n'est pas sûr que ce décompte soit juste...
"""
return self._VmA('MemFree:', unit) + self._VmA('SwapFree:', unit) + \
self._VmA('Cached:', unit) + self._VmA('SwapCached:', unit)
#
def _VmB(self, VmKey, unit):
- "Lecture des paramètres mémoire du processus"
+ "Lecture des paramètres mémoire du processus"
try:
t = open(self._proc_status)
v = t.read()
return mem / self._scale[unit]
#
def getUsedMemory(self, unit="o"):
- "Renvoie la mémoire résidente utilisée en octets"
+ "Renvoie la mémoire résidente utilisée en octets"
return self._VmB('VmRSS:', unit)
#
def getVirtualMemory(self, unit="o"):
- "Renvoie la mémoire totale utilisée en octets"
+ "Renvoie la mémoire totale utilisée en octets"
return self._VmB('VmSize:', unit)
#
def getUsedStacksize(self, unit="o"):
- "Renvoie la taille du stack utilisé en octets"
+ "Renvoie la taille du stack utilisé en octets"
return self._VmB('VmStk:', unit)
#
def getMaxUsedMemory(self, unit="o"):
- "Renvoie la mémoire résidente maximale mesurée"
+ "Renvoie la mémoire résidente maximale mesurée"
return self._VmB('VmHWM:', unit)
#
def getMaxVirtualMemory(self, unit="o"):
- "Renvoie la mémoire totale maximale mesurée"
+ "Renvoie la mémoire totale maximale mesurée"
return self._VmB('VmPeak:', unit)
# ==============================================================================
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
# Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
"""
- Modèles généraux pour les observers, le post-processing
+ Modèles généraux pour les observers, le post-processing
"""
__author__ = "Jean-Philippe ARGAUD"
__all__ = ["ObserverTemplates"]
# ==============================================================================
class TemplateStorage(object):
"""
- Classe générale de stockage de type dictionnaire étendu
+ Classe générale de stockage de type dictionnaire étendu
(Template)
"""
def __init__( self, language = "fr_FR" ):
def keys(self):
"D.keys() -> list of D's keys"
- __keys = list(self.__values.keys())
- __keys.sort()
+ __keys = sorted(self.__values.keys())
return __keys
# def has_key(self, name):
ObserverTemplates.store(
name = "ValueSeriePrinter",
content = """print(str(info)+" "+str(var[:]))""",
- fr_FR = "Imprime sur la sortie standard la série des valeurs de la variable",
+ fr_FR = "Imprime sur la sortie standard la série des valeurs de la variable",
en_EN = "Print on standard output the value series of the variable",
order = "next",
)
ObserverTemplates.store(
name = "ValueSaver",
content = """import numpy, re\nv=numpy.array(var[-1], ndmin=1)\nglobal istep\ntry:\n istep += 1\nexcept:\n istep = 0\nf='/tmp/value_%s_%05i.txt'%(info,istep)\nf=re.sub('\\s','_',f)\nprint('Value saved in \"%s\"'%f)\nnumpy.savetxt(f,v)""",
- fr_FR = "Enregistre la valeur courante de la variable dans un fichier du répertoire '/tmp' nommé 'value...txt' selon le nom de la variable et l'étape d'enregistrement",
+ fr_FR = "Enregistre la valeur courante de la variable dans un fichier du répertoire '/tmp' nommé 'value...txt' selon le nom de la variable et l'étape d'enregistrement",
en_EN = "Save the current value of the variable in a file of the '/tmp' directory named 'value...txt' from the variable name and the saving step",
order = "next",
)
ObserverTemplates.store(
name = "ValueSerieSaver",
content = """import numpy, re\nv=numpy.array(var[:], ndmin=1)\nglobal istep\ntry:\n istep += 1\nexcept:\n istep = 0\nf='/tmp/value_%s_%05i.txt'%(info,istep)\nf=re.sub('\\s','_',f)\nprint('Value saved in \"%s\"'%f)\nnumpy.savetxt(f,v)""",
- fr_FR = "Enregistre la série des valeurs de la variable dans un fichier du répertoire '/tmp' nommé 'value...txt' selon le nom de la variable et l'étape",
+ fr_FR = "Enregistre la série des valeurs de la variable dans un fichier du répertoire '/tmp' nommé 'value...txt' selon le nom de la variable et l'étape",
en_EN = "Save the value series of the variable in a file of the '/tmp' directory named 'value...txt' from the variable name and the saving step",
order = "next",
)
ObserverTemplates.store(
name = "ValuePrinterAndSaver",
content = """import numpy, re\nv=numpy.array(var[-1], ndmin=1)\nprint(str(info)+" "+str(v))\nglobal istep\ntry:\n istep += 1\nexcept:\n istep = 0\nf='/tmp/value_%s_%05i.txt'%(info,istep)\nf=re.sub('\\s','_',f)\nprint('Value saved in \"%s\"'%f)\nnumpy.savetxt(f,v)""",
- fr_FR = "Imprime sur la sortie standard et, en même temps enregistre dans un fichier, la valeur courante de la variable",
+ fr_FR = "Imprime sur la sortie standard et, en même temps enregistre dans un fichier, la valeur courante de la variable",
en_EN = "Print on standard output and, in the same time save in a file, the current value of the variable",
order = "next",
)
ObserverTemplates.store(
name = "ValueIndexPrinterAndSaver",
content = """import numpy, re\nv=numpy.array(var[-1], ndmin=1)\nprint(str(info)+(" index %i:"%(len(var)-1))+" "+str(v))\nglobal istep\ntry:\n istep += 1\nexcept:\n istep = 0\nf='/tmp/value_%s_%05i.txt'%(info,istep)\nf=re.sub('\\s','_',f)\nprint('Value saved in \"%s\"'%f)\nnumpy.savetxt(f,v)""",
- fr_FR = "Imprime sur la sortie standard et, en même temps enregistre dans un fichier, la valeur courante de la variable, en ajoutant son index",
+ fr_FR = "Imprime sur la sortie standard et, en même temps enregistre dans un fichier, la valeur courante de la variable, en ajoutant son index",
en_EN = "Print on standard output and, in the same time save in a file, the current value of the variable, adding its index",
order = "next",
)
ObserverTemplates.store(
name = "ValueSeriePrinterAndSaver",
content = """import numpy, re\nv=numpy.array(var[:], ndmin=1)\nprint(str(info)+" "+str(v))\nglobal istep\ntry:\n istep += 1\nexcept:\n istep = 0\nf='/tmp/value_%s_%05i.txt'%(info,istep)\nf=re.sub('\\s','_',f)\nprint('Value saved in \"%s\"'%f)\nnumpy.savetxt(f,v)""",
- fr_FR = "Imprime sur la sortie standard et, en même temps, enregistre dans un fichier la série des valeurs de la variable",
+ fr_FR = "Imprime sur la sortie standard et, en même temps, enregistre dans un fichier la série des valeurs de la variable",
en_EN = "Print on standard output and, in the same time, save in a file the value series of the variable",
order = "next",
)
ObserverTemplates.store(
name = "ValueSerieGnuPlotter",
content = """import numpy, Gnuplot\nv=numpy.array(var[:], ndmin=1)\nglobal ifig, gp\ntry:\n ifig += 1\n gp(' set style data lines')\nexcept:\n ifig = 0\n gp = Gnuplot.Gnuplot(persist=1)\n gp(' set style data lines')\ngp('set title \"%s (Figure %i)\"'%(info,ifig))\ngp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )""",
- fr_FR = "Affiche graphiquement avec Gnuplot la série des valeurs de la variable",
+ fr_FR = "Affiche graphiquement avec Gnuplot la série des valeurs de la variable",
en_EN = "Graphically plot with Gnuplot the value series of the variable",
order = "next",
)
ObserverTemplates.store(
name = "ValuePrinterAndGnuPlotter",
content = """print(str(info)+" "+str(var[-1]))\nimport numpy, Gnuplot\nv=numpy.array(var[-1], ndmin=1)\nglobal ifig,gp\ntry:\n ifig += 1\n gp(' set style data lines')\nexcept:\n ifig = 0\n gp = Gnuplot.Gnuplot(persist=1)\n gp(' set style data lines')\ngp('set title \"%s (Figure %i)\"'%(info,ifig))\ngp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )""",
- fr_FR = "Imprime sur la sortie standard et, en même temps, affiche graphiquement avec Gnuplot la valeur courante de la variable",
+ fr_FR = "Imprime sur la sortie standard et, en même temps, affiche graphiquement avec Gnuplot la valeur courante de la variable",
en_EN = "Print on standard output and, in the same time, graphically plot with Gnuplot the current value of the variable",
order = "next",
)
ObserverTemplates.store(
name = "ValueSeriePrinterAndGnuPlotter",
content = """print(str(info)+" "+str(var[:]))\nimport numpy, Gnuplot\nv=numpy.array(var[:], ndmin=1)\nglobal ifig,gp\ntry:\n ifig += 1\n gp(' set style data lines')\nexcept:\n ifig = 0\n gp = Gnuplot.Gnuplot(persist=1)\n gp(' set style data lines')\ngp('set title \"%s (Figure %i)\"'%(info,ifig))\ngp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )""",
- fr_FR = "Imprime sur la sortie standard et, en même temps, affiche graphiquement avec Gnuplot la série des valeurs de la variable",
+ fr_FR = "Imprime sur la sortie standard et, en même temps, affiche graphiquement avec Gnuplot la série des valeurs de la variable",
en_EN = "Print on standard output and, in the same time, graphically plot with Gnuplot the value series of the variable",
order = "next",
)
ObserverTemplates.store(
name = "ValuePrinterSaverAndGnuPlotter",
content = """print(str(info)+" "+str(var[-1]))\nimport numpy, re\nv=numpy.array(var[-1], ndmin=1)\nglobal istep\ntry:\n istep += 1\nexcept:\n istep = 0\nf='/tmp/value_%s_%05i.txt'%(info,istep)\nf=re.sub('\\s','_',f)\nprint('Value saved in \"%s\"'%f)\nnumpy.savetxt(f,v)\nimport Gnuplot\nglobal ifig,gp\ntry:\n ifig += 1\n gp(' set style data lines')\nexcept:\n ifig = 0\n gp = Gnuplot.Gnuplot(persist=1)\n gp(' set style data lines')\ngp('set title \"%s (Figure %i)\"'%(info,ifig))\ngp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )""",
- fr_FR = "Imprime sur la sortie standard et, en même temps, enregistre dans un fichier et affiche graphiquement la valeur courante de la variable ",
+ fr_FR = "Imprime sur la sortie standard et, en même temps, enregistre dans un fichier et affiche graphiquement la valeur courante de la variable ",
en_EN = "Print on standard output and, in the same, time save in a file and graphically plot the current value of the variable",
order = "next",
)
ObserverTemplates.store(
name = "ValueSeriePrinterSaverAndGnuPlotter",
content = """print(str(info)+" "+str(var[:]))\nimport numpy, re\nv=numpy.array(var[:], ndmin=1)\nglobal istep\ntry:\n istep += 1\nexcept:\n istep = 0\nf='/tmp/value_%s_%05i.txt'%(info,istep)\nf=re.sub('\\s','_',f)\nprint('Value saved in \"%s\"'%f)\nnumpy.savetxt(f,v)\nimport Gnuplot\nglobal ifig,gp\ntry:\n ifig += 1\n gp(' set style data lines')\nexcept:\n ifig = 0\n gp = Gnuplot.Gnuplot(persist=1)\n gp(' set style data lines')\ngp('set title \"%s (Figure %i)\"'%(info,ifig))\ngp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )""",
- fr_FR = "Imprime sur la sortie standard et, en même temps, enregistre dans un fichier et affiche graphiquement la série des valeurs de la variable",
+ fr_FR = "Imprime sur la sortie standard et, en même temps, enregistre dans un fichier et affiche graphiquement la série des valeurs de la variable",
en_EN = "Print on standard output and, in the same, time save in a file and graphically plot the value series of the variable",
order = "next",
)
ObserverTemplates.store(
name = "ValueStandardError",
content = """import numpy\nprint(str(info)+" "+str(numpy.nanstd(var[-1])))""",
- fr_FR = "Imprime sur la sortie standard l'écart-type de la valeur courante de la variable",
+ fr_FR = "Imprime sur la sortie standard l'écart-type de la valeur courante de la variable",
en_EN = "Print on standard output the standard error of the current value of the variable",
order = "next",
)
ObserverTemplates.store(
name = "ValueRMS",
content = """import numpy\nv = numpy.matrix( numpy.ravel( var[-1] ) )\nprint(str(info)+" "+str(float( numpy.sqrt((1./v.size)*(v*v.T)) )))""",
- fr_FR = "Imprime sur la sortie standard la racine de la moyenne des carrés (RMS), ou moyenne quadratique, de la valeur courante de la variable",
+ fr_FR = "Imprime sur la sortie standard la racine de la moyenne des carrés (RMS), ou moyenne quadratique, de la valeur courante de la variable",
en_EN = "Print on standard output the root mean square (RMS), or quadratic mean, of the current value of the variable",
order = "next",
)
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
# ==============================================================================
class ElementaryDiagnostic(BasicObjects.Diagnostic):
"""
- Classe pour tracer simplement un vecteur à chaque pas
+ Classe pour tracer simplement un vecteur à chaque pas
"""
def __init__(self, name = "", unit = "", basetype = None, parameters = {}):
BasicObjects.Diagnostic.__init__(self, name, parameters)
persist,
pause ):
"""
- Trace en gnuplot le vecteur Vector, avec une légende générale, en X et
+ Trace en gnuplot le vecteur Vector, avec une légende générale, en X et
en Y
"""
if persist:
if filename != "":
self.__g.hardcopy(filename=filename, color=1)
if pause:
- raw_input('Please press return to continue...\n')
+ eval(input('Please press return to continue...\n'))
#
return 1
pause = True ):
"""
Arguments :
- - vector : le vecteur à tracer, en liste ou en numpy.array
+ - vector : le vecteur à tracer, en liste ou en numpy.array
- steps : liste unique des pas de l'axe des X, ou None si c'est
- la numérotation par défaut
- - title : titre général du dessin
+ la numérotation par défaut
+ - title : titre général du dessin
- xlabel : label de l'axe des X
- ylabel : label de l'axe des Y
- - ltitle : titre associé au vecteur tracé
- - geometry : taille en pixels de la fenêtre et position du coin haut
- gauche, au format X11 : LxH+X+Y (défaut : 600x400)
- - filename : nom de fichier Postscript pour une sauvegarde à 1 pas
- Attention, il faut changer le nom à l'appel pour
+ - ltitle : titre associé au vecteur tracé
+ - geometry : taille en pixels de la fenêtre et position du coin haut
+ gauche, au format X11 : LxH+X+Y (défaut : 600x400)
+ - filename : nom de fichier Postscript pour une sauvegarde à 1 pas
+ Attention, il faut changer le nom à l'appel pour
plusieurs pas de sauvegarde
- - persist : booléen indiquant que la fenêtre affichée sera
- conservée lors du passage au dessin suivant
- Par défaut, persist = False
- - pause : booléen indiquant une pause après chaque tracé, et
+ - persist : booléen indiquant que la fenêtre affichée sera
+ conservée lors du passage au dessin suivant
+ Par défaut, persist = False
+ - pause : booléen indiquant une pause après chaque tracé, et
attendant un Return
- Par défaut, pause = True
+ Par défaut, pause = True
"""
if vector is None:
raise ValueError("One vector must be given to plot it.")
if Vector.size < 1:
raise ValueError("The given vector must not be empty")
if steps is None:
- Steps = range(len( vector ))
- elif not ( type(steps) is type([]) or type(steps) is not type(numpy.array([])) ):
+ Steps = list(range(len( vector )))
+ elif not ( isinstance(steps, type([])) or not isinstance(steps, type(numpy.array([]))) ):
raise ValueError("The steps must be given as a list/tuple.")
else:
Steps = list(steps)
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
# ==============================================================================
class ElementaryDiagnostic(BasicObjects.Diagnostic):
"""
- Classe pour tracer simplement une liste de vecteurs à chaque pas
+ Classe pour tracer simplement une liste de vecteurs à chaque pas
"""
def __init__(self, name = "", unit = "", basetype = None, parameters = {}):
BasicObjects.Diagnostic.__init__(self, name, parameters)
persist,
pause ):
"""
- Trace en gnuplot chaque vecteur de la liste Vector, avec une légende
- générale, en X et en Y
+ Trace en gnuplot chaque vecteur de la liste Vector, avec une légende
+ générale, en X et en Y
"""
if persist:
self.__gnuplot.GnuplotOpts.gnuplot_command = 'gnuplot -persist -geometry '+geometry
if filename != "":
self.__g.hardcopy(filename=filename, color=1)
if pause:
- raw_input('Please press return to continue...\n')
+ eval(input('Please press return to continue...\n'))
#
return 1
pause = True ):
"""
Arguments :
- - vector : liste des vecteurs à tracer, chacun étant en liste ou
+ - vector : liste des vecteurs à tracer, chacun étant en liste ou
en numpy.array
- - steps : liste unique des pas, ou None si c'est la numérotation
- par défaut
- - title : titre général du dessin
+ - steps : liste unique des pas, ou None si c'est la numérotation
+ par défaut
+ - title : titre général du dessin
- xlabel : label de l'axe des X
- ylabel : label de l'axe des Y
- - ltitle : liste des titres associés à chaque vecteur, dans le
- même ordre que les vecteurs eux-mêmes
- - geometry : taille en pixels de la fenêtre et position du coin haut
- gauche, au format X11 : LxH+X+Y (défaut : 600x400)
- - filename : nom de fichier Postscript pour une sauvegarde à 1 pas
- Attention, il faut changer le nom à l'appel pour
+ - ltitle : liste des titres associés à chaque vecteur, dans le
+ même ordre que les vecteurs eux-mêmes
+ - geometry : taille en pixels de la fenêtre et position du coin haut
+ gauche, au format X11 : LxH+X+Y (défaut : 600x400)
+ - filename : nom de fichier Postscript pour une sauvegarde à 1 pas
+ Attention, il faut changer le nom à l'appel pour
plusieurs pas de sauvegarde
- - persist : booléen indiquant que la fenêtre affichée sera
- conservée lors du passage au dessin suivant
- Par défaut, persist = False
- - pause : booléen indiquant une pause après chaque tracé, et
+ - persist : booléen indiquant que la fenêtre affichée sera
+ conservée lors du passage au dessin suivant
+ Par défaut, persist = False
+ - pause : booléen indiquant une pause après chaque tracé, et
attendant un Return
- Par défaut, pause = True
+ Par défaut, pause = True
"""
if vector is None:
raise ValueError("One vector must be given to plot it.")
- if type(vector) is not type([]) and type(vector) is not type(()):
+ if not isinstance(vector, (list, tuple)):
raise ValueError("The vector(s) must be given as a list/tuple.")
if ltitle is None or len(ltitle) != len(vector):
ltitle = ["" for i in range(len(vector))]
if VectorList[-1].size < 1:
raise ValueError("Each given vector must not be empty.")
if steps is None:
- Steps = range(len(vector[0]))
- elif not ( type(steps) is type([]) or type(steps) is not type(numpy.array([])) ):
+ Steps = list(range(len(vector[0])))
+ elif not ( isinstance(steps, type([])) or not isinstance(steps, type(numpy.array([]))) ):
raise ValueError("The steps must be given as a list/tuple.")
else:
Steps = list(steps)
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
def _formula(self, V1, V2):
"""
- Fait un écart RMS entre deux vecteurs V1 et V2
+ Fait un écart RMS entre deux vecteurs V1 et V2
"""
rms = math.sqrt( ((V2 - V1)**2).sum() / float(V1.size) )
#
def calculate(self, vector1 = None, vector2 = None, step = None):
"""
- Teste les arguments, active la formule de calcul et stocke le résultat
+ Teste les arguments, active la formule de calcul et stocke le résultat
"""
if vector1 is None or vector2 is None:
raise ValueError("Two vectors must be given to calculate their RMS")
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
def _formula(self, V1, V2):
"""
- Vérification de la reduction de variance sur les écarts entre OMB et OMA
+ Vérification de la reduction de variance sur les écarts entre OMB et OMA
lors de l'analyse
"""
- varianceOMB = V1.var()
- varianceOMA = V2.var()
+ varianceOMB = V1.var()
+ varianceOMA = V2.var()
#
- if varianceOMA > varianceOMB:
+ if varianceOMA > varianceOMB:
reducevariance = False
else :
reducevariance = True
def calculate(self, vectorOMB = None, vectorOMA = None, step = None):
"""
- Teste les arguments, active la formule de calcul et stocke le résultat
+ Teste les arguments, active la formule de calcul et stocke le résultat
Arguments :
- - vectorOMB : vecteur d'écart entre les observations et l'ébauche
- - vectorOMA : vecteur d'écart entre les observations et l'analyse
+ - vectorOMB : vecteur d'écart entre les observations et l'ébauche
+ - vectorOMA : vecteur d'écart entre les observations et l'analyse
"""
if ( (vectorOMB is None) or (vectorOMA is None) ):
raise ValueError("Two vectors must be given to test the reduction of the variance after analysis")
# ----------------------
x1 = numpy.matrix(([3. , 4., 5. ]))
x2 = numpy.matrix(([1.5, 2., 2.5]))
- print(" L'écart entre les observations et l'ébauche est OMB : %s"%(x1,))
+ print(" L'écart entre les observations et l'ébauche est OMB : %s"%(x1,))
print(" La moyenne de OMB (i.e. le biais) est de............: %s"%(x1.mean(),))
print(" La variance de OMB est de...........................: %s"%(x1.var(),))
- print(" L'écart entre les observations et l'analyse est OMA : %s"%(x2,))
+ print(" L'écart entre les observations et l'analyse est OMA : %s"%(x2,))
print(" La moyenne de OMA (i.e. le biais) est de............: %s"%(x2.mean(),))
print(" La variance de OMA est de...........................: %s"%(x2.var(),))
#
D.calculate( vectorOMB = x1, vectorOMA = x2)
if not D[0] :
- print(" Résultat : l'analyse NE RÉDUIT PAS la variance")
+ print(" Résultat : l'analyse NE RÉDUIT PAS la variance")
else :
- print(" Résultat : l'analyse RÉDUIT la variance")
+ print(" Résultat : l'analyse RÉDUIT la variance")
print("")
#
# Vecteur de type array
# ---------------------
x1 = numpy.array(range(11))
x2 = numpy.matrix(range(-10,12,2))
- print(" L'écart entre les observations et l'ébauche est OMB : %s"%(x1,))
+ print(" L'écart entre les observations et l'ébauche est OMB : %s"%(x1,))
print(" La moyenne de OMB (i.e. le biais) est de............: %s"%(x1.mean(),))
print(" La variance de OMB est de...........................: %s"%(x1.var(),))
- print(" L'écart entre les observations et l'analyse est OMA : %s"%(x2,))
+ print(" L'écart entre les observations et l'analyse est OMA : %s"%(x2,))
print(" La moyenne de OMA (i.e. le biais) est de............: %s"%(x2.mean(),))
print(" La variance de OMA est de...........................: %s"%(x2.var(),))
#
D.calculate( vectorOMB = x1, vectorOMA = x2)
if not D[1] :
- print(" Résultat : l'analyse NE RÉDUIT PAS la variance")
+ print(" Résultat : l'analyse NE RÉDUIT PAS la variance")
else :
- print(" Résultat : l'analyse RÉDUIT la variance")
+ print(" Résultat : l'analyse RÉDUIT la variance")
print("")
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
# Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
__doc__ = """
- Définit les versions approximées des opérateurs tangents et adjoints.
+ Définit les versions approximées des opérateurs tangents et adjoints.
"""
__author__ = "Jean-Philippe ARGAUD"
# ==============================================================================
class FDApproximation(object):
"""
- Cette classe sert d'interface pour définir les opérateurs approximés. A la
- création d'un objet, en fournissant une fonction "Function", on obtient un
- objet qui dispose de 3 méthodes "DirectOperator", "TangentOperator" et
- "AdjointOperator". On contrôle l'approximation DF avec l'incrément
- multiplicatif "increment" valant par défaut 1%, ou avec l'incrément fixe
- "dX" qui sera multiplié par "increment" (donc en %), et on effectue de DF
- centrées si le booléen "centeredDF" est vrai.
+ Cette classe sert d'interface pour définir les opérateurs approximés. A la
+ création d'un objet, en fournissant une fonction "Function", on obtient un
+ objet qui dispose de 3 méthodes "DirectOperator", "TangentOperator" et
+ "AdjointOperator". On contrôle l'approximation DF avec l'incrément
+ multiplicatif "increment" valant par défaut 1%, ou avec l'incrément fixe
+ "dX" qui sera multiplié par "increment" (donc en %), et on effectue de DF
+ centrées si le booléen "centeredDF" est vrai.
"""
def __init__(self,
Function = None,
try:
mod = os.path.join(Function.__globals__['filepath'],Function.__globals__['filename'])
except:
- mod = os.path.abspath(Function.im_func.__globals__['__file__'])
+ mod = os.path.abspath(Function.__func__.__globals__['__file__'])
if not os.path.isfile(mod):
raise ImportError("No user defined function or method found with the name %s"%(mod,))
self.__userFunction__modl = os.path.basename(mod).replace('.pyc','').replace('.pyo','').replace('.py','')
self.__increment = float(increment)
else:
self.__increment = 0.01
- if dX is None:
+ if dX is None:
self.__dX = None
else:
self.__dX = numpy.asmatrix(numpy.ravel( dX )).T
for i in range(len(l)-1,-1,-1):
if numpy.linalg.norm(e - l[i]) < self.__tolerBP * n[i]:
__ac, __iac = True, i
- if v is not None: logging.debug("FDA Cas%s déja calculé, récupération du doublon %i"%(v,__iac))
+ if v is not None: logging.debug("FDA Cas%s déja calculé, récupération du doublon %i"%(v,__iac))
break
return __ac, __iac
# ---------------------------------------------------------
def DirectOperator(self, X ):
"""
- Calcul du direct à l'aide de la fonction fournie.
+ Calcul du direct à l'aide de la fonction fournie.
"""
logging.debug("FDA Calcul DirectOperator (explicite)")
_X = numpy.asmatrix(numpy.ravel( X )).T
# ---------------------------------------------------------
def TangentMatrix(self, X ):
"""
- Calcul de l'opérateur tangent comme la Jacobienne par différences finies,
- c'est-à-dire le gradient de H en X. On utilise des différences finies
+ Calcul de l'opérateur tangent comme la Jacobienne par différences finies,
+ c'est-à-dire le gradient de H en X. On utilise des différences finies
directionnelles autour du point X. X est un numpy.matrix.
-
- Différences finies centrées (approximation d'ordre 2):
- 1/ Pour chaque composante i de X, on ajoute et on enlève la perturbation
- dX[i] à la composante X[i], pour composer X_plus_dXi et X_moins_dXi, et
- on calcule les réponses HX_plus_dXi = H( X_plus_dXi ) et HX_moins_dXi =
+
+ Différences finies centrées (approximation d'ordre 2):
+ 1/ Pour chaque composante i de X, on ajoute et on enlève la perturbation
+ dX[i] à la composante X[i], pour composer X_plus_dXi et X_moins_dXi, et
+ on calcule les réponses HX_plus_dXi = H( X_plus_dXi ) et HX_moins_dXi =
H( X_moins_dXi )
- 2/ On effectue les différences (HX_plus_dXi-HX_moins_dXi) et on divise par
+ 2/ On effectue les différences (HX_plus_dXi-HX_moins_dXi) et on divise par
le pas 2*dXi
- 3/ Chaque résultat, par composante, devient une colonne de la Jacobienne
-
- Différences finies non centrées (approximation d'ordre 1):
- 1/ Pour chaque composante i de X, on ajoute la perturbation dX[i] à la
- composante X[i] pour composer X_plus_dXi, et on calcule la réponse
+ 3/ Chaque résultat, par composante, devient une colonne de la Jacobienne
+
+ Différences finies non centrées (approximation d'ordre 1):
+ 1/ Pour chaque composante i de X, on ajoute la perturbation dX[i] à la
+ composante X[i] pour composer X_plus_dXi, et on calcule la réponse
HX_plus_dXi = H( X_plus_dXi )
2/ On calcule la valeur centrale HX = H(X)
- 3/ On effectue les différences (HX_plus_dXi-HX) et on divise par
+ 3/ On effectue les différences (HX_plus_dXi-HX) et on divise par
le pas dXi
- 4/ Chaque résultat, par composante, devient une colonne de la Jacobienne
-
+ 4/ Chaque résultat, par composante, devient une colonne de la Jacobienne
+
"""
logging.debug("FDA Calcul de la Jacobienne")
- logging.debug("FDA Incrément de............: %s*X"%float(self.__increment))
- logging.debug("FDA Approximation centrée...: %s"%(self.__centeredDF))
+ logging.debug("FDA Incrément de............: %s*X"%float(self.__increment))
+ logging.debug("FDA Approximation centrée...: %s"%(self.__centeredDF))
#
if X is None or len(X)==0:
raise ValueError("Nominal point X for approximate derivatives can not be None or void (X=%s)."%(str(X),))
__bidon, __alreadyCalculatedI = self.__doublon__(_dX, self.__listJPCI, self.__listJPIN, None)
if __alreadyCalculatedP == __alreadyCalculatedI > -1:
__alreadyCalculated, __i = True, __alreadyCalculatedP
- logging.debug("FDA Cas J déja calculé, récupération du doublon %i"%__i)
+ logging.debug("FDA Cas J déja calculé, récupération du doublon %i"%__i)
#
if __alreadyCalculated:
- logging.debug("FDA Calcul Jacobienne (par récupération du doublon %i)"%__i)
+ logging.debug("FDA Calcul Jacobienne (par récupération du doublon %i)"%__i)
_Jacobienne = self.__listJPCR[__i]
else:
logging.debug("FDA Calcul Jacobienne (explicite)")
# ---------------------------------------------------------
def TangentOperator(self, paire ):
"""
- Calcul du tangent à l'aide de la Jacobienne.
+ Calcul du tangent à l'aide de la Jacobienne.
"""
assert len(paire) == 2, "Incorrect number of arguments"
X, dX = paire
return _Jacobienne
else:
#
- # Calcul de la valeur linéarisée de H en X appliqué à dX
+ # Calcul de la valeur linéarisée de H en X appliqué à dX
# ------------------------------------------------------
_dX = numpy.asmatrix(numpy.ravel( dX )).T
_HtX = numpy.dot(_Jacobienne, _dX)
# ---------------------------------------------------------
def AdjointOperator(self, paire ):
"""
- Calcul de l'adjoint à l'aide de la Jacobienne.
+ Calcul de l'adjoint à l'aide de la Jacobienne.
"""
assert len(paire) == 2, "Incorrect number of arguments"
X, Y = paire
return _JacobienneT
else:
#
- # Calcul de la valeur de l'adjoint en X appliqué à Y
+ # Calcul de la valeur de l'adjoint en X appliqué à Y
# --------------------------------------------------
_Y = numpy.asmatrix(numpy.ravel( Y )).T
_HaY = numpy.dot(_JacobienneT, _Y)
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2017 EDF R&D
#
# Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
__doc__ = """
- Implémentation informatique de l'algorithme MMQR, basée sur la publication :
+ Implémentation informatique de l'algorithme MMQR, basée sur la publication :
David R. Hunter, Kenneth Lange, "Quantile Regression via an MM Algorithm",
Journal of Computational and Graphical Statistics, 9, 1, pp.60-77, 2000.
"""
veps = 1. - 2. * quantile - residus * poids
lastsurrogate = -sum(residus * veps) - (1.-2.*quantile)*sum(residus)
#
- # Mesure d'écart : q*Sum(residus)-sum(residus negatifs)
+ # Mesure d'écart : q*Sum(residus)-sum(residus negatifs)
# ----------------
Ecart = quantile * sum(residus) - sum( residus[residus<0] )
#