From 626aae11fbe0767caed94fbe1dcb6fd5fd7ae844 Mon Sep 17 00:00:00 2001 From: Jean-Philippe ARGAUD Date: Fri, 25 Sep 2015 22:02:31 +0200 Subject: [PATCH] Documentation and source minor corrections and improvements --- doc/en/ref_algorithm_3DVAR.rst | 2 +- doc/en/ref_operator_requirements.rst | 6 +- doc/en/tui.rst | 27 +-- doc/fr/ref_algorithm_3DVAR.rst | 2 +- doc/fr/ref_operator_requirements.rst | 6 +- doc/fr/tui.rst | 29 +--- src/daComposant/daAlgorithms/4DVAR.py | 13 +- src/daComposant/daCore/BasicObjects.py | 143 ++++++++++------ src/daComposant/daCore/ExtendedLogging.py | 6 +- src/daComposant/daCore/Persistence.py | 160 ++++++++++-------- src/daComposant/daCore/PlatformInfo.py | 63 ++++--- src/daComposant/daCore/Templates.py | 14 +- src/daSalome/adaoBuilder.py | 56 +++--- .../daYacsSchemaCreator/infos_daComposant.py | 7 + 14 files changed, 307 insertions(+), 227 deletions(-) diff --git a/doc/en/ref_algorithm_3DVAR.rst b/doc/en/ref_algorithm_3DVAR.rst index ef532d4..3cce818 100644 --- a/doc/en/ref_algorithm_3DVAR.rst +++ b/doc/en/ref_algorithm_3DVAR.rst @@ -33,7 +33,7 @@ Description This algorithm performs a state estimation by variational minimization of the classical :math:`J` function in static data assimilation: -.. math:: J(\mathbf{x})=(\mathbf{x}-\mathbf{x}^b)^T.\mathbf{B}^{-1}.(\mathbf{x}-\mathbf{x}^b)+(\mathbf{y}^o-\mathbf{H}.\mathbf{x})^T.\mathbf{R}^{-1}.(\mathbf{y}^o-\mathbf{H}.\mathbf{x}) +.. math:: J(\mathbf{x})=(\mathbf{x}-\mathbf{x}^b)^T.\mathbf{B}^{-1}.(\mathbf{x}-\mathbf{x}^b)+(\mathbf{y}^o-H(\mathbf{x}))^T.\mathbf{R}^{-1}.(\mathbf{y}^o-H(\mathbf{x})) which is usually designed as the "*3D-VAR*" function (see for example [Talagrand97]_). diff --git a/doc/en/ref_operator_requirements.rst b/doc/en/ref_operator_requirements.rst index f0d946d..60df256 100644 --- a/doc/en/ref_operator_requirements.rst +++ b/doc/en/ref_operator_requirements.rst @@ -104,9 +104,9 @@ uncentered schema of first order (which is the default value), and with 1 for a centered schema of second order (of twice the first order computational cost). If necessary and if possible, :ref:`subsection_ref_parallel_df` can be used. In all cases, an internal cache mechanism is used to restrict the number of -operator evaluations to avoid redundant calculations, at the minimum possible in -a sequential or parallel execution scheme for numerical approximations of the -tangent and adjoint operators. +operator evaluations at the minimum possible in a sequential or parallel +execution scheme for numerical approximations of the tangent and adjoint +operators, to avoid redundant calculations. This first operator definition form allows easily to test the functional form before its use in an ADAO case, greatly reducing the complexity of operator diff --git a/doc/en/tui.rst b/doc/en/tui.rst index c262142..d10371e 100644 --- a/doc/en/tui.rst +++ b/doc/en/tui.rst @@ -30,11 +30,6 @@ **[DocR]** Textual Application Programming Interface for the user (API/TUI) ================================================================================ -.. warning:: - - in its present version, this text programming interface (TUI) is experimental, - and so changes can be required in forthcoming versions. - This section presents advanced usage of the ADAO module using its text programming interface (API/TUI). This interface gives ability to create a calculation object in a similar way than the case building obtained through the @@ -473,20 +468,14 @@ Setting the calculation, outputs, etc. **setObserver** (*Variable, Template, String, Script, Info*) This command allows to set an *observer* on the current or final calculation - variable. Reference should be made to the description of the way of - ':ref:`section_advanced_observer`, and to the :ref:`section_reference` to - know what are the observable quantities. One defines as "*String*" the - *observer* body, using a string including if necessary line breaks. It is - recommended to use the patterns available by the argument "*Template*". - There exist the following simple patterns: "ValuePrinter", - "ValueSeriePrinter", "ValueSaver", "ValueSerieSaver", - "ValuePrinterAndSaver", "ValueSeriePrinterAndSaver", "ValueGnuPlotter", - "ValueSerieGnuPlotter", "ValuePrinterAndGnuPlotter", - "ValueSeriePrinterAndGnuPlotter", "ValuePrinterSaverAndGnuPlotter", - "ValueSeriePrinterSaverAndGnuPlotter", "ValueMean", "ValueStandardError", - "ValueVariance", "ValueRMS". In the case of a definition as "*Script*", the - file must contain only the body of the function, as described in the way of - :ref:`section_advanced_observer`. + variable. Reference should be made to the description of the + ':ref:`ref_observers_requirements` for their list and content, and to the + :ref:`section_reference` to know what are the observable quantities. One + defines as "*String*" the *observer* body, using a string including if + necessary line breaks. It is recommended to use the patterns available by + the argument "*Template*". In the case of a definition as "*Script*", the + file must contain only the body of the function, as described in the + :ref:`ref_observers_requirements`. Perform the calculation +++++++++++++++++++++++ diff --git a/doc/fr/ref_algorithm_3DVAR.rst b/doc/fr/ref_algorithm_3DVAR.rst index 4bac5e4..6fc8671 100644 --- a/doc/fr/ref_algorithm_3DVAR.rst +++ b/doc/fr/ref_algorithm_3DVAR.rst @@ -34,7 +34,7 @@ Cet algorithme r la fonctionnelle :math:`J` d'écart classique en assimilation de données statique: -.. math:: J(\mathbf{x})=(\mathbf{x}-\mathbf{x}^b)^T.\mathbf{B}^{-1}.(\mathbf{x}-\mathbf{x}^b)+(\mathbf{y}^o-\mathbf{H}.\mathbf{x})^T.\mathbf{R}^{-1}.(\mathbf{y}^o-\mathbf{H}.\mathbf{x}) +.. math:: J(\mathbf{x})=(\mathbf{x}-\mathbf{x}^b)^T.\mathbf{B}^{-1}.(\mathbf{x}-\mathbf{x}^b)+(\mathbf{y}^o-H(\mathbf{x}))^T.\mathbf{R}^{-1}.(\mathbf{y}^o-H(\mathbf{x})) qui est usuellement désignée comme la fonctionnelle "*3D-VAR*" (voir par exemple [Talagrand97]_). diff --git a/doc/fr/ref_operator_requirements.rst b/doc/fr/ref_operator_requirements.rst index c4f93e0..741eb90 100644 --- a/doc/fr/ref_operator_requirements.rst +++ b/doc/fr/ref_operator_requirements.rst @@ -109,9 +109,9 @@ premier ordre (qui est la valeur par d second ordre (qui coûte numériquement deux fois plus cher que le premier ordre). Si nécessaire et si possible, on peut :ref:`subsection_ref_parallel_df`. Dans tous les cas, un mécanisme de cache interne permet de limiter le nombre -d'évaluations de l'opérateur pour éviter des calculs redondants, au minimum -possible du point de vue de l'exécution séquentielle ou parallèle des -approximations numériques des opérateurs tangent et adjoint. +d'évaluations de l'opérateur au minimum possible du point de vue de l'exécution +séquentielle ou parallèle des approximations numériques des opérateurs tangent +et adjoint, pour éviter des calculs redondants. Cette première forme de définition de l'opérateur permet aisément de tester la forme fonctionnelle avant son usage dans un cas ADAO, réduisant notablement la diff --git a/doc/fr/tui.rst b/doc/fr/tui.rst index 072bb73..5928c60 100644 --- a/doc/fr/tui.rst +++ b/doc/fr/tui.rst @@ -30,12 +30,6 @@ **[DocR]** Interface de programmation textuelle pour l'utilisateur (API/TUI) ================================================================================ -.. warning:: - - dans sa présente version, cette interface de programmation textuelle (TUI) est - expérimentale, et reste donc susceptible de changements dans les prochaines - versions. - Cette section présente des méthodes avancées d'usage du module ADAO à l'aide de son interface de programmation textuelle (API/TUI). Cette interface permet de créer un objet de calcul de manière similaire à la construction d'un cas par @@ -493,20 +487,15 @@ Param **setObserver** (*Variable, Template, String, Script, Info*) Cette commande permet de définir un *observer* sur une variable courante ou - finale du calcul. On se reportera à la description de la manière - d':ref:`section_advanced_observer`, et à la :ref:`section_reference` pour - savoir quelles sont les quantités observables. On définit comme un - "*String*" le corps de l'*observer*, en utilisant une chaine de caractères - incluant si nécessaire des sauts de lignes. On recommande d'utiliser les - patrons disponibles par l'argument "*Template*". On dispose des patrons - simples suivants : "ValuePrinter", "ValueSeriePrinter", "ValueSaver", - "ValueSerieSaver", "ValuePrinterAndSaver", "ValueSeriePrinterAndSaver", - "ValueGnuPlotter", "ValueSerieGnuPlotter", "ValuePrinterAndGnuPlotter", - "ValueSeriePrinterAndGnuPlotter", "ValuePrinterSaverAndGnuPlotter", - "ValueSeriePrinterSaverAndGnuPlotter", "ValueMean", "ValueStandardError", - "ValueVariance", "ValueRMS". Dans le cas d'une définition par "*Script*", le - fichier indiqué doit contenir uniquement le corps de la fonction, comme - décrit dans la manière d':ref:`section_advanced_observer`. + finale du calcul. On se reportera à la description des + :ref:`ref_observers_requirements` pour avoir leur liste et leur format, et à + la :ref:`section_reference` pour savoir quelles sont les quantités + observables. On définit comme un "*String*" le corps de l'*observer*, en + utilisant une chaine de caractères incluant si nécessaire des sauts de + lignes. On recommande d'utiliser les patrons disponibles par l'argument + "*Template*". Dans le cas d'une définition par "*Script*", le fichier + indiqué doit contenir uniquement le corps de la fonction, comme décrit dans + les :ref:`ref_observers_requirements`. Effectuer le calcul +++++++++++++++++++ diff --git a/src/daComposant/daAlgorithms/4DVAR.py b/src/daComposant/daAlgorithms/4DVAR.py index 3c6a439..f05163a 100644 --- a/src/daComposant/daAlgorithms/4DVAR.py +++ b/src/daComposant/daAlgorithms/4DVAR.py @@ -86,7 +86,7 @@ class ElementaryAlgorithm(BasicObjects.Algorithm): default = [], typecast = tuple, message = "Liste de calculs supplémentaires à stocker et/ou effectuer", - listval = ["BMA", "CurrentState", "CostFunctionJ"] + listval = ["BMA", "CurrentState", "CostFunctionJ", "IndexOfOptimum", "CurrentOptimum"] ) self.defineRequiredParameter( # Pas de type name = "Bounds", @@ -169,7 +169,9 @@ class ElementaryAlgorithm(BasicObjects.Algorithm): 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 "CurrentState" in self._parameters["StoreSupplementaryCalculations"]: + if self._parameters["StoreInternalVariables"] or \ + "CurrentState" in self._parameters["StoreSupplementaryCalculations"] or \ + "CurrentOptimum" in self._parameters["StoreSupplementaryCalculations"]: self.StoredVariables["CurrentState"].store( _X ) Jb = 0.5 * (_X - Xb).T * BI * (_X - Xb) self.DirectCalculation = [None,] @@ -207,6 +209,13 @@ class ElementaryAlgorithm(BasicObjects.Algorithm): self.StoredVariables["CostFunctionJb"].store( Jb ) self.StoredVariables["CostFunctionJo"].store( Jo ) self.StoredVariables["CostFunctionJ" ].store( J ) + if "IndexOfOptimum" in self._parameters["StoreSupplementaryCalculations"] or \ + "CurrentOptimum" in self._parameters["StoreSupplementaryCalculations"]: + IndexMin = numpy.argmin( self.StoredVariables["CostFunctionJ"][nbPreviousSteps:] ) + nbPreviousSteps + if "IndexOfOptimum" in self._parameters["StoreSupplementaryCalculations"]: + self.StoredVariables["IndexOfOptimum"].store( IndexMin ) + if "CurrentOptimum" in self._parameters["StoreSupplementaryCalculations"]: + self.StoredVariables["CurrentOptimum"].store( self.StoredVariables["CurrentState"][IndexMin] ) return J # def GradientOfCostFunction(x): diff --git a/src/daComposant/daCore/BasicObjects.py b/src/daComposant/daCore/BasicObjects.py index 57d4e41..ff6f140 100644 --- a/src/daComposant/daCore/BasicObjects.py +++ b/src/daComposant/daCore/BasicObjects.py @@ -35,14 +35,14 @@ import Persistence import PlatformInfo # ============================================================================== -class CacheManager: +class CacheManager(object): """ Classe générale de gestion d'un cache de calculs """ def __init__(self, - toleranceInRedundancy = 1.e-18, - lenghtOfRedundancy = -1, - ): + toleranceInRedundancy = 1.e-18, + lenghtOfRedundancy = -1, + ): """ Les caractéristiques de tolérance peuvent être modifées à la création. """ @@ -52,29 +52,32 @@ class CacheManager: self.clearCache() def clearCache(self): + "Vide le cache" self.__listOPCV = [] # Operator Previous Calculated Points, Results, Point Norms - # logging.debug("CM Tolerance de determination des doublons : %.2e"%self.__tolerBP) + # 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" __alc = False __HxV = None for i in xrange(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" 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)), @@ -83,14 +86,16 @@ class CacheManager: ) ) def disable(self): + "Inactive le cache" self.__initlnOR = self.__lenghtOR self.__lenghtOR = 0 def enable(self): + "Active le cache" self.__lenghtOR = self.__initlnOR # ============================================================================== -class Operator: +class Operator(object): """ Classe générale d'interface de type opérateur """ @@ -124,15 +129,18 @@ class Operator: self.__Type = None def disableAvoidingRedundancy(self): + "Inactive le cache" Operator.CM.disable() def enableAvoidingRedundancy(self): + "Active le cache" if self.__AvoidRC: Operator.CM.enable() else: Operator.CM.disable() def isType(self): + "Renvoie le type" return self.__Type def appliedTo(self, xValue): @@ -244,19 +252,22 @@ class Operator: else: return __nbcalls[which] def __addOneMatrixCall(self): + "Comptabilise un appel" self.__NbCallsAsMatrix += 1 # Decompte local Operator.NbCallsAsMatrix += 1 # Decompte global def __addOneMethodCall(self): + "Comptabilise un appel" self.__NbCallsAsMethod += 1 # Decompte local Operator.NbCallsAsMethod += 1 # Decompte global def __addOneCacheCall(self): + "Comptabilise un appel" self.__NbCallsOfCached += 1 # Decompte local Operator.NbCallsOfCached += 1 # Decompte global # ============================================================================== -class Algorithm: +class Algorithm(object): """ Classe générale d'interface de type algorithme @@ -300,7 +311,7 @@ class Algorithm: 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)) + logging.debug("%s Initialisation", str(name)) self._m = PlatformInfo.SystemUsage() # self._name = str( name ) @@ -337,11 +348,13 @@ class Algorithm: self.StoredVariables["SimulationQuantiles"] = Persistence.OneMatrix(name = "SimulationQuantiles") def _pre_run(self): - logging.debug("%s Lancement"%self._name) - logging.debug("%s Taille mémoire utilisée de %.1f Mio"%(self._name, self._m.getUsedMemory("Mio"))) + "Pré-calcul" + logging.debug("%s Lancement", self._name) + logging.debug("%s Taille mémoire utilisée de %.1f Mio", self._name, self._m.getUsedMemory("Mio")) return 0 def _post_run(self,_oH=None): + "Post-calcul" if ("StoreSupplementaryCalculations" in self._parameters) and \ "APosterioriCovariance" in self._parameters["StoreSupplementaryCalculations"]: for _A in self.StoredVariables["APosterioriCovariance"]: @@ -354,10 +367,10 @@ class Algorithm: _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 %.1f 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 %.1f Mio", self._name, self._m.getUsedMemory("Mio")) + logging.debug("%s Terminé", self._name) return 0 def get(self, key=None): @@ -374,15 +387,11 @@ class Algorithm: return self.StoredVariables def __contains__(self, key=None): - """ - Vérifie si l'une des variables stockées est identifiée par la clé. - """ - return (key in self.StoredVariables) + "D.__contains__(k) -> True if D has a key k, else False" + return key in self.StoredVariables def keys(self): - """ - Renvoie la liste des clés de variables stockées. - """ + "D.keys() -> list of D's keys" return self.StoredVariables.keys() def run(self, Xb=None, Y=None, H=None, M=None, R=None, B=None, Q=None, Parameters=None): @@ -408,7 +417,7 @@ class Algorithm: "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): """ @@ -446,7 +455,7 @@ class Algorithm: if maxval is not None and (numpy.array(__val, float) > maxval).any(): raise ValueError("The parameter named \"%s\" of value \"%s\" can not be greater than %s."%(name, __val, maxval)) if listval is not None: - if typecast is list or typecast is tuple or type(__val) is list or type(__val) is tuple: + if typecast is list or typecast is tuple or isinstance(__val,list) or isinstance(__val,tuple): for v in __val: if v not in listval: raise ValueError("The value \"%s\" of the parameter named \"%s\" is not allowed, it has to be in the list %s."%(v, name, listval)) @@ -464,10 +473,10 @@ class Algorithm: self._parameters[k] = self.setParameterValue(k,fromDico[k]) else: self._parameters[k] = self.setParameterValue(k) - logging.debug("%s %s : %s"%(self._name, self.__required_parameters[k]["message"], self._parameters[k])) + logging.debug("%s %s : %s", self._name, self.__required_parameters[k]["message"], self._parameters[k]) # ============================================================================== -class Diagnostic: +class Diagnostic(object): """ Classe générale d'interface de type diagnostic @@ -483,6 +492,7 @@ class Diagnostic: externe d'activation). """ def __init__(self, name = "", parameters = {}): + "Initialisation" self.name = str(name) self.parameters = dict( parameters ) @@ -500,18 +510,18 @@ class Diagnostic: raise NotImplementedError("Diagnostic activation method has not been implemented!") # ============================================================================== -class Covariance: +class Covariance(object): """ Classe générale d'interface de type covariance """ def __init__(self, - name = "GenericCovariance", - asCovariance = None, - asEyeByScalar = None, - asEyeByVector = None, - asCovObject = None, - toBeChecked = False, - ): + name = "GenericCovariance", + asCovariance = None, + asEyeByScalar = None, + asEyeByVector = None, + asCovObject = None, + toBeChecked = False, + ): """ Permet de définir une covariance : - asCovariance : entrée des données, comme une matrice compatible avec @@ -573,6 +583,7 @@ class Covariance: self.__validate() def __validate(self): + "Validation" if self.ismatrix() and min(self.shape) != max(self.shape): raise ValueError("The given matrix for %s is not a square one, its shape is %s. Please check your matrix input."%(self.__name,self.shape)) if self.isobject() and min(self.shape) != max(self.shape): @@ -593,18 +604,23 @@ class Covariance: 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" return self.__is_scalar def isvector(self): + "Vérification du type interne" return self.__is_vector def ismatrix(self): + "Vérification du type interne" return self.__is_matrix def isobject(self): + "Vérification du type interne" return self.__is_object def getI(self): + "Inversion" if self.ismatrix(): return Covariance(self.__name+"I", asCovariance = self.__C.I ) elif self.isvector(): @@ -617,6 +633,7 @@ class Covariance: return None # Indispensable def getT(self): + "Transposition" if self.ismatrix(): return Covariance(self.__name+"T", asCovariance = self.__C.T ) elif self.isvector(): @@ -627,6 +644,7 @@ class Covariance: return Covariance(self.__name+"T", asCovObject = self.__C.getT() ) def cholesky(self): + "Décomposition de Cholesky" if self.ismatrix(): return Covariance(self.__name+"C", asCovariance = numpy.linalg.cholesky(self.__C) ) elif self.isvector(): @@ -637,6 +655,7 @@ class Covariance: return Covariance(self.__name+"C", asCovObject = self.__C.cholesky() ) def choleskyI(self): + "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(): @@ -647,6 +666,7 @@ class Covariance: return Covariance(self.__name+"H", asCovObject = self.__C.choleskyI() ) def diag(self, msize=None): + "Diagonale de la matrice" if self.ismatrix(): return numpy.diag(self.__C) elif self.isvector(): @@ -660,6 +680,7 @@ class Covariance: return self.__C.diag() def asfullmatrix(self, msize=None): + "Matrice pleine" if self.ismatrix(): return self.__C elif self.isvector(): @@ -673,6 +694,7 @@ class Covariance: return self.__C.asfullmatrix() def trace(self, msize=None): + "Trace de la matrice" if self.ismatrix(): return numpy.trace(self.__C) elif self.isvector(): @@ -686,12 +708,15 @@ class Covariance: return self.__C.trace() def __repr__(self): + "x.__repr__() <==> repr(x)" return repr(self.__C) def __str__(self): + "x.__str__() <==> str(x)" return str(self.__C) def __add__(self, other): + "x.__add__(y) <==> x+y" if self.ismatrix() or self.isobject(): return self.__C + numpy.asmatrix(other) elif self.isvector() or self.isscalar(): @@ -700,9 +725,11 @@ class Covariance: return numpy.asmatrix(_A) def __radd__(self, other): + "x.__radd__(y) <==> y+x" raise NotImplementedError("%s covariance matrix __radd__ method not available for %s type!"%(self.__name,type(other))) def __sub__(self, other): + "x.__sub__(y) <==> x-y" if self.ismatrix() or self.isobject(): return self.__C - numpy.asmatrix(other) elif self.isvector() or self.isscalar(): @@ -711,12 +738,15 @@ class Covariance: return numpy.asmatrix(_A) def __rsub__(self, other): + "x.__rsub__(y) <==> y-x" raise NotImplementedError("%s covariance matrix __rsub__ method not available for %s type!"%(self.__name,type(other))) def __neg__(self): + "x.__neg__() <==> -x" return - self.__C def __mul__(self, other): + "x.__mul__(y) <==> x*y" if self.ismatrix() and isinstance(other,numpy.matrix): return self.__C * other elif self.ismatrix() and (isinstance(other,numpy.ndarray) \ @@ -753,6 +783,7 @@ class Covariance: raise NotImplementedError("%s covariance matrix __mul__ method not available for %s type!"%(self.__name,type(other))) def __rmul__(self, other): + "x.__rmul__(y) <==> y*x" if self.ismatrix() and isinstance(other,numpy.matrix): return other * self.__C elif self.isvector() and isinstance(other,numpy.matrix): @@ -770,26 +801,26 @@ class Covariance: raise NotImplementedError("%s covariance matrix __rmul__ method not available for %s type!"%(self.__name,type(other))) def __len__(self): + "x.__len__() <==> len(x)" return self.shape[0] # ============================================================================== -def CostFunction3D( - _x, - _Hm = None, # Pour simuler Hm(x) : HO["Direct"].appliedTo - _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 - _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 - _sSc = True, # Stocke ou pas les SSC - ): +def CostFunction3D(_x, + _Hm = None, # Pour simuler Hm(x) : HO["Direct"].appliedTo + _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 + _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 + _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, @@ -803,11 +834,11 @@ def CostFunction3D( "CostFunctionJb", "CostFunctionJo", "CurrentOptimum", - "CurrentState", + "CurrentState", "IndexOfOptimum", "SimulatedObservationAtCurrentOptimum", "SimulatedObservationAtCurrentState", - ]: + ]: if k not in _SSV: _SSV[k] = [] if hasattr(_SSV[k],"store"): @@ -821,7 +852,7 @@ def CostFunction3D( _HX = _HmX else: if _Hm is None: - raise ValueError("%s Operator has to be defined."%(self.__name,)) + raise ValueError("COSTFUNCTION3D Operator has to be defined.") if _arg is None: _HX = _Hm( _X ) else: diff --git a/src/daComposant/daCore/ExtendedLogging.py b/src/daComposant/daCore/ExtendedLogging.py index f83e659..aefcf17 100644 --- a/src/daComposant/daCore/ExtendedLogging.py +++ b/src/daComposant/daCore/ExtendedLogging.py @@ -81,7 +81,11 @@ import PlatformInfo LOGFILE = os.path.join(os.path.abspath(os.curdir),"AssimilationStudy.log") # ============================================================================== -class ExtendedLogging: +class ExtendedLogging(object): + """ + 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. diff --git a/src/daComposant/daCore/Persistence.py b/src/daComposant/daCore/Persistence.py index 19ab915..82df72b 100644 --- a/src/daComposant/daCore/Persistence.py +++ b/src/daComposant/daCore/Persistence.py @@ -32,7 +32,7 @@ import numpy, copy from PlatformInfo import PathManagement ; PathManagement() # ============================================================================== -class Persistence: +class Persistence(object): """ Classe générale de persistence définissant les accesseurs nécessaires (Template) @@ -42,12 +42,12 @@ class Persistence: name : nom courant 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 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 + permettant l'instanciation ou le casting Python __values : les valeurs de stockage. Par défaut, c'est None """ self.__name = str(name) @@ -55,13 +55,18 @@ class Persistence: # self.__basetype = basetype # - self.__values = [] - self.__tags = [] + self.__values = [] + self.__tags = [] # self.__dynamic = False + self.__gnuplot = None + self.__g = None + self.__title = None + self.__ltitle = None + self.__pause = None # self.__dataobservers = [] - + def basetype(self, basetype=None): """ Renvoie ou met en place le type de base des objets stockés @@ -98,7 +103,7 @@ class Persistence: else: self.__values.pop() self.__tags.pop() - + def shape(self): """ Renvoie la taille sous forme numpy du dernier objet stocké. Si c'est un @@ -120,26 +125,32 @@ class Persistence: # --------------------------------------------------------- def __str__(self): + "x.__str__() <==> str(x)" msg = " Index Value Tags\n" for i,v in enumerate(self.__values): msg += " i=%05i %10s %s\n"%(i,v,self.__tags[i]) return msg - + def __len__(self): + "x.__len__() <==> len(x)" return len(self.__values) - + def __getitem__(self, index=None ): + "x.__getitem__(y) <==> x[y]" return copy.copy(self.__values[index]) - + def count(self, value): + "L.count(value) -> integer -- return number of occurrences of value" return self.__values.count(value) - + def index(self, value, start=0, stop=None): + "L.index(value, [start, [stop]]) -> integer -- return first index of value." if stop is None : stop = len(self.__values) return self.__values.index(value, start, stop) # --------------------------------------------------------- def __filteredIndexes(self, **kwargs): + "Function interne filtrant les index" __indexOfFilteredItems = range(len(self.__tags)) __filteringKwTags = kwargs.keys() if len(__filteringKwTags) > 0: @@ -157,10 +168,12 @@ class Persistence: # --------------------------------------------------------- def values(self, **kwargs): + "D.values() -> list of D's values" __indexOfFilteredItems = self.__filteredIndexes(**kwargs) return [self.__values[i] for i in __indexOfFilteredItems] def keys(self, keyword=None , **kwargs): + "D.keys() -> list of D's keys" __indexOfFilteredItems = self.__filteredIndexes(**kwargs) __keys = [] for i in __indexOfFilteredItems: @@ -171,16 +184,18 @@ class Persistence: return __keys def items(self, keyword=None , **kwargs): + "D.items() -> list of D's (key, value) pairs, as 2-tuples" __indexOfFilteredItems = self.__filteredIndexes(**kwargs) __pairs = [] for i in __indexOfFilteredItems: if keyword in self.__tags[i]: - __pairs.append( [self.__tags[i][keyword], self.__values[i]] ) + __pairs.append( (self.__tags[i][keyword], self.__values[i]) ) else: - __pairs.append( [None, self.__values[i]] ) + __pairs.append( (None, self.__values[i]) ) return __pairs def tagkeys(self): + "D.tagkeys() -> list of D's tag keys" __allKeys = [] for dicotags in self.__tags: __allKeys.extend( dicotags.keys() ) @@ -199,13 +214,14 @@ class Persistence: # return [self.__values[i] for i in __indexOfFilteredItems] def tagserie(self, item=None, withValues=False, outputTag=None, **kwargs): + "D.tagserie() -> list of D's tag serie" if item is None: __indexOfFilteredItems = self.__filteredIndexes(**kwargs) else: __indexOfFilteredItems = [item,] # # Dans le cas où la sortie donne les valeurs d'un "outputTag" - if outputTag is not None and type(outputTag) is str : + if outputTag is not None and isinstance(outputTag,str) : outputValues = [] for index in __indexOfFilteredItems: if outputTag in self.__tags[index].keys(): @@ -229,10 +245,12 @@ class Persistence: # --------------------------------------------------------- # Pour compatibilite def stepnumber(self): + "Nombre de pas" return len(self.__values) # Pour compatibilite def stepserie(self, **kwargs): + "Nombre de pas filtrés" __indexOfFilteredItems = self.__filteredIndexes(**kwargs) return __indexOfFilteredItems @@ -253,7 +271,7 @@ class Persistence: 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. - + 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 """ @@ -299,14 +317,15 @@ class Persistence: raise TypeError("Base type is incompatible with numpy") def __preplots(self, - title = "", - xlabel = "", - ylabel = "", - ltitle = None, - geometry = "600x400", - persist = False, - pause = True, - ): + title = "", + xlabel = "", + ylabel = "", + ltitle = None, + geometry = "600x400", + persist = False, + pause = True, + ): + "Préparation des plots" # # Vérification de la disponibilité du module Gnuplot try: @@ -333,18 +352,20 @@ class Persistence: self.__ltitle = ltitle self.__pause = pause - def plots(self, item=None, step=None, - steps = None, - title = "", - xlabel = "", - ylabel = "", - ltitle = None, - geometry = "600x400", - filename = "", - dynamic = False, - persist = False, - pause = True, - ): + def plots(self, + item = None, + step = None, + steps = None, + title = "", + xlabel = "", + ylabel = "", + ltitle = None, + geometry = "600x400", + filename = "", + dynamic = False, + persist = False, + pause = True, + ): """ Renvoie un affichage de la valeur à chaque pas, si elle est compatible avec un affichage Gnuplot (donc essentiellement un vecteur). Si @@ -399,7 +420,7 @@ class Persistence: i = -1 for index in indexes: self.__g('set title "'+str(title).encode('ascii','replace')+' (pas '+str(index)+')"') - if ( type(steps) is list ) or ( type(steps) is type(numpy.array([])) ): + if isinstance(steps,list) or isinstance(steps,numpy.ndarray): Steps = list(steps) else: Steps = range(len(self.__values[index])) @@ -448,7 +469,7 @@ class Persistence: 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. - + 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 """ @@ -508,15 +529,15 @@ class Persistence: # "tofile", "min"... def plot(self, - steps = None, - title = "", - xlabel = "", - ylabel = "", - ltitle = None, - geometry = "600x400", - filename = "", - persist = False, - pause = True, + steps = None, + title = "", + xlabel = "", + ylabel = "", + ltitle = None, + geometry = "600x400", + filename = "", + persist = False, + pause = True, ): """ Renvoie un affichage unique pour l'ensemble des valeurs à chaque pas, si @@ -559,7 +580,7 @@ class Persistence: self.__gnuplot.GnuplotOpts.gnuplot_command = 'gnuplot -geometry '+geometry if ltitle is None: ltitle = "" - if ( type(steps) is list ) or ( type(steps) is type(numpy.array([])) ): + if isinstance(steps,list) or isinstance(steps, numpy.ndarray): Steps = list(steps) else: Steps = range(len(self.__values[0])) @@ -584,14 +605,10 @@ class Persistence: raw_input('Please press return to continue...\n') # --------------------------------------------------------- - def setDataObserver(self, - HookFunction = None, - HookParameters = None, - Scheduler = None, - ): + def setDataObserver(self, HookFunction = None, HookParameters = None, Scheduler = None): """ Association à la variable d'un triplet définissant un observer - + Le Scheduler attendu est une fréquence, une simple liste d'index ou un xrange des index. """ @@ -599,32 +616,29 @@ class Persistence: # Vérification du Scheduler # ------------------------- maxiter = int( 1e9 ) - if type(Scheduler) is int: # Considéré comme une fréquence à partir de 0 + if isinstance(Scheduler,int): # Considéré comme une fréquence à partir de 0 Schedulers = xrange( 0, maxiter, int(Scheduler) ) - elif type(Scheduler) is xrange: # Considéré comme un itérateur + elif isinstance(Scheduler,xrange): # Considéré comme un itérateur Schedulers = Scheduler - elif type(Scheduler) is list: # Considéré comme des index explicites - Schedulers = map( long, Scheduler ) - else: # Dans tous les autres cas, activé par défaut + elif isinstance(Scheduler,list): # 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 ) # # Stockage interne de l'observer dans la variable # ----------------------------------------------- self.__dataobservers.append( [HookFunction, HookParameters, Schedulers] ) - def removeDataObserver(self, - HookFunction = None, - ): + def removeDataObserver(self, HookFunction = None): """ 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. - """ if hasattr(HookFunction,"func_name"): name = str( HookFunction.func_name ) - elif type(HookFunction) is str: + elif isinstance(HookFunction,str): name = str( HookFunction ) else: name = None @@ -636,7 +650,7 @@ class Persistence: if name is hf.func_name: index_to_remove.append( i ) index_to_remove.reverse() for i in index_to_remove: - self.__dataobservers.pop( i ) + self.__dataobservers.pop( i ) # ============================================================================== class OneScalar(Persistence): @@ -683,7 +697,9 @@ class OneList(Persistence): def __init__(self, name="", unit="", basetype = list): Persistence.__init__(self, name, unit, basetype) -def NoType( value ): return value +def NoType( value ): + "Fonction transparente, sans effet sur son argument" + return value class OneNoType(Persistence): """ @@ -697,18 +713,18 @@ class OneNoType(Persistence): Persistence.__init__(self, name, unit, basetype) # ============================================================================== -class CompositePersistence: +class CompositePersistence(object): """ 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. """ 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 objets comme des attributs) : @@ -791,22 +807,28 @@ class CompositePersistence: # --------------------------------------------------------- # Méthodes d'accès de type dictionnaire def __getitem__(self, name=None ): + "x.__getitem__(y) <==> x[y]" return self.get_object( name ) def __setitem__(self, name=None, objet=None ): + "x.__setitem__(i, y) <==> x[i]=y" self.set_object( name, objet ) def keys(self): + "D.keys() -> list of D's keys" return self.get_stored_objects(hideVoidObjects = False) def values(self): + "D.values() -> list of D's values" return self.__StoredObjects.values() def items(self): + "D.items() -> list of D's (key, value) pairs, as 2-tuples" return self.__StoredObjects.items() # --------------------------------------------------------- def get_stored_objects(self, hideVoidObjects = False): + "Renvoie la liste des objets présents" objs = self.__StoredObjects.keys() if hideVoidObjects: usedObjs = [] diff --git a/src/daComposant/daCore/PlatformInfo.py b/src/daComposant/daCore/PlatformInfo.py index d6cc771..f93c993 100644 --- a/src/daComposant/daCore/PlatformInfo.py +++ b/src/daComposant/daCore/PlatformInfo.py @@ -42,29 +42,33 @@ __all__ = [] import os # ============================================================================== -class PlatformInfo: +class PlatformInfo(object): """ Rassemblement des informations sur le code et la plateforme """ + def __init__(self): + "Sans effet" + pass + def getName(self): "Retourne le nom de l'application" - import version - return version.name + import version as dav + return dav.name def getVersion(self): "Retourne le numéro de la version" - import version - return version.version + import version as dav + return dav.version def getDate(self): "Retourne la date de création de la version" - import version - return version.date - + import version as dav + return dav.date + def getPythonVersion(self): "Retourne la version de python disponible" import sys - return ".".join(map(str,sys.version_info[0:3])) + return ".".join([str(x) for x in sys.version_info[0:3]]) # map(str,sys.version_info[0:3])) def getNumpyVersion(self): "Retourne la version de numpy disponible" @@ -81,7 +85,7 @@ class PlatformInfo: try: import matplotlib return matplotlib.__version__ - except: + except ImportError: return "0.0.0" def getGnuplotVersion(self): @@ -89,7 +93,7 @@ class PlatformInfo: try: import Gnuplot return Gnuplot.__version__ - except: + except ImportError: return "0.0" def getSphinxVersion(self): @@ -97,7 +101,7 @@ class PlatformInfo: try: import sphinx return sphinx.__version__ - except: + except ImportError: return "0.0.0" def getCurrentMemorySize(self): @@ -105,8 +109,8 @@ class PlatformInfo: return 1 def __str__(self): - import version - return "%s %s (%s)"%(version.name,version.version,version.date) + import version as dav + return "%s %s (%s)"%(dav.name,dav.version,dav.date) # ============================================================================== def uniq(sequence): @@ -117,11 +121,12 @@ def uniq(sequence): return [x for x in sequence if x not in __seen and not __seen.add(x)] # ============================================================================== -class PathManagement: +class PathManagement(object): """ Mise à jour du path système pour les répertoires d'outils """ def __init__(self): + "Déclaration des répertoires statiques" import sys parent = os.path.abspath(os.path.join(os.path.dirname(__file__),"..")) self.__paths = {} @@ -143,7 +148,7 @@ class PathManagement: return self.__paths # ============================================================================== -class SystemUsage: +class SystemUsage(object): """ Permet de récupérer les différentes tailles mémoires du process courant """ @@ -154,17 +159,30 @@ class SystemUsage: _proc_status = '/proc/%d/status' % os.getpid() _memo_status = '/proc/meminfo' _scale = { - 'o': 1.0, 'ko' : 1.e3, 'Mo' : 1.e6, 'Go' : 1.e9, # Multiples SI de l'octet - 'kio': 1024.0, 'Mio': 1024.0*1024.0, 'Gio': 1024.0*1024.0*1024.0, # Multiples binaires de l'octet - 'B': 1.0, 'kB' : 1024.0, 'MB' : 1024.0*1024.0, 'GB' : 1024.0*1024.0*1024.0, # Multiples binaires du byte=octet - } + 'o' : 1.0, # Multiples SI de l'octet + 'ko' : 1.e3, + 'Mo' : 1.e6, + 'Go' : 1.e9, + 'kio': 1024.0, # Multiples binaires de l'octet + 'Mio': 1024.0*1024.0, + 'Gio': 1024.0*1024.0*1024.0, + 'B': 1.0, # Multiples binaires du byte=octet + 'kB' : 1024.0, + 'MB' : 1024.0*1024.0, + 'GB' : 1024.0*1024.0*1024.0, + } + # + def __init__(self): + "Sans effet" + pass # def _VmA(self, VmKey, unit): + "Lecture des paramètres mémoire de la machine" try: t = open(self._memo_status) v = t.read() t.close() - except: + except IOError: return 0.0 # non-Linux? i = v.index(VmKey) # get VmKey line e.g. 'VmRSS: 9999 kB\n ...' v = v[i:].split(None, 3) # whitespace @@ -194,11 +212,12 @@ class SystemUsage: self._VmA('Cached:', unit) + self._VmA('SwapCached:', unit) # def _VmB(self, VmKey, unit): + "Lecture des paramètres mémoire du processus" try: t = open(self._proc_status) v = t.read() t.close() - except: + except IOError: return 0.0 # non-Linux? i = v.index(VmKey) # get VmKey line e.g. 'VmRSS: 9999 kB\n ...' v = v[i:].split(None, 3) # whitespace diff --git a/src/daComposant/daCore/Templates.py b/src/daComposant/daCore/Templates.py index aa84de7..ca71bac 100644 --- a/src/daComposant/daCore/Templates.py +++ b/src/daComposant/daCore/Templates.py @@ -40,6 +40,7 @@ class TemplateStorage(object): self.__order = -1 def store( self, name = None, content = None, fr_FR = "", en_EN = "", order = "next" ): + "D.store(k, c, fr_FR, en_EN, o) -> Store template k and its main characteristics" if name is None or content is None: raise ValueError("To be consistent, the storage of a template must provide a name and a content.") if order == "next": @@ -54,25 +55,34 @@ class TemplateStorage(object): } def keys(self): + "D.keys() -> list of D's keys" __keys = self.__values.keys() __keys.sort() return __keys def has_key(self, name): - return self.__values.has_key(name) + "D.has_key(k) -> True if D has a key k, else False" + return name in self.__values + + def __contains__(self, name): + "D.__contains__(k) -> True if D has a key k, else False" + return name in self.__values def __len__(self): + "x.__len__() <==> len(x)" return len(self.__values) def __getitem__(self, name=None ): + "x.__getitem__(y) <==> x[y]" return self.__values[name]['content'] def getdoc(self, name = None, lang = "fr_FR"): + "D.getdoc(k, l) -> Return documentation of key k in language l" if lang not in self.__values[name]: lang = self.__preferedLanguage return self.__values[name][lang] def keys_in_presentation_order(self): - "Restitue l'ordre de présentation requis" + "D.keys_in_presentation_order() -> list of D's keys in presentation order" __orders = [] for k in self.keys(): __orders.append( self.__values[k]['order'] ) diff --git a/src/daSalome/adaoBuilder.py b/src/daSalome/adaoBuilder.py index 8aa1bab..56c569b 100644 --- a/src/daSalome/adaoBuilder.py +++ b/src/daSalome/adaoBuilder.py @@ -98,7 +98,7 @@ class New(object): else: raise ValueError("the variable named '%s' is not allowed."%str(Concept)) except Exception as e: - if type(e) == type(SyntaxError()): msg = "at %s: %s"%(e.offset, e.text) + if isinstance(e, SyntaxError): msg = "at %s: %s"%(e.offset, e.text) else: msg = "" raise ValueError("during settings, the following error occurs:\n\n%s %s\n\nSee also the potential messages, which can show the origin of the above error, in the launching terminal."%(str(e),msg)) @@ -188,10 +188,10 @@ class New(object): "Définition d'une entrée de calcul" self.__dumper.register("setControlModel", dir(), locals()) __Parameters = {} - if Parameters is not None and type(Parameters) == type({}): - if Parameters.has_key("DifferentialIncrement"): + if (Parameters is not None) and isinstance(Parameters, dict): + if "DifferentialIncrement" in Parameters: __Parameters["withIncrement"] = Parameters["DifferentialIncrement"] - if Parameters.has_key("CenteredFiniteDifference"): + if "CenteredFiniteDifference" in Parameters: __Parameters["withCenteredDF"] = Parameters["CenteredFiniteDifference"] if Script is not None: __Matrix, __Function = None, None @@ -215,10 +215,10 @@ class New(object): __Function.update({"useApproximatedDerivatives":True}) __Function.update(__Parameters) elif ThreeFunctions is not None: - if (type(ThreeFunctions) is not type({})) or \ - not ThreeFunctions.has_key("Direct") or \ - not ThreeFunctions.has_key("Tangent") or \ - not ThreeFunctions.has_key("Adjoint"): + if (not isinstance(ThreeFunctions, dict)) or \ + "Direct" not in ThreeFunctions or \ + "Tangent" not in ThreeFunctions or \ + "Adjoint" not in ThreeFunctions: raise ValueError("ThreeFunctions has to be a dictionnary and to have the 3 keys Direct, Tangent, Adjoint") __Function = ThreeFunctions __Function.update(__Parameters) @@ -292,14 +292,14 @@ class New(object): "Définition d'une entrée de calcul" self.__dumper.register("setEvolutionModel", dir(), locals()) __Parameters = {} - if Parameters is not None and type(Parameters) == type({}): - if Parameters.has_key("DifferentialIncrement"): + if (Parameters is not None) and isinstance(Parameters, dict): + if "DifferentialIncrement" in Parameters: __Parameters["withIncrement"] = Parameters["DifferentialIncrement"] - if Parameters.has_key("CenteredFiniteDifference"): + if "CenteredFiniteDifference" in Parameters: __Parameters["withCenteredDF"] = Parameters["CenteredFiniteDifference"] - if Parameters.has_key("EnableMultiProcessing"): + if "EnableMultiProcessing" in Parameters: __Parameters["withmpEnabled"] = Parameters["EnableMultiProcessing"] - if Parameters.has_key("NumberOfProcesses"): + if "NumberOfProcesses" in Parameters: __Parameters["withmpWorkers"] = Parameters["NumberOfProcesses"] if Script is not None: __Matrix, __Function = None, None @@ -323,10 +323,10 @@ class New(object): __Function.update({"useApproximatedDerivatives":True}) __Function.update(__Parameters) elif ThreeFunctions is not None: - if (type(ThreeFunctions) is not type({})) or \ - not ThreeFunctions.has_key("Direct") or \ - not ThreeFunctions.has_key("Tangent") or \ - not ThreeFunctions.has_key("Adjoint"): + if (not isinstance(ThreeFunctions, dict)) or \ + "Direct" not in ThreeFunctions or \ + "Tangent" not in ThreeFunctions or \ + "Adjoint" not in ThreeFunctions: raise ValueError("ThreeFunctions has to be a dictionnary and to have the 3 keys Direct, Tangent, Adjoint") __Function = ThreeFunctions __Function.update(__Parameters) @@ -400,15 +400,15 @@ class New(object): "Définition d'une entrée de calcul" self.__dumper.register("setObservationOperator", dir(), locals()) __Parameters = {} - if Parameters is not None and type(Parameters) == type({}): - if Parameters.has_key("DifferentialIncrement"): + if (Parameters is not None) and isinstance(Parameters, dict): + if "DifferentialIncrement" in Parameters: __Parameters["withIncrement"] = Parameters["DifferentialIncrement"] - if Parameters.has_key("CenteredFiniteDifference"): + if "CenteredFiniteDifference" in Parameters: __Parameters["withCenteredDF"] = Parameters["CenteredFiniteDifference"] - if Parameters.has_key("EnableMultiProcessing"): + if "EnableMultiProcessing" in Parameters: __Parameters["EnableMultiProcessing"] = Parameters["EnableMultiProcessing"] __Parameters["withmpEnabled"] = Parameters["EnableMultiProcessing"] - if Parameters.has_key("NumberOfProcesses"): + if "NumberOfProcesses" in Parameters: __Parameters["NumberOfProcesses"] = Parameters["NumberOfProcesses"] __Parameters["withmpWorkers"] = Parameters["NumberOfProcesses"] if Script is not None: @@ -433,10 +433,10 @@ class New(object): __Function.update({"useApproximatedDerivatives":True}) __Function.update(__Parameters) elif ThreeFunctions is not None: - if (type(ThreeFunctions) is not type({})) or \ - not ThreeFunctions.has_key("Direct") or \ - not ThreeFunctions.has_key("Tangent") or \ - not ThreeFunctions.has_key("Adjoint"): + if (not isinstance(ThreeFunctions, dict)) or \ + "Direct" not in ThreeFunctions or \ + "Tangent" not in ThreeFunctions or \ + "Adjoint" not in ThreeFunctions: raise ValueError("ThreeFunctions has to be a dictionnary and to have the 3 keys Direct, Tangent, Adjoint") __Function = ThreeFunctions __Function.update(__Parameters) @@ -497,7 +497,7 @@ class New(object): # if String is not None: __FunctionText = String - elif (Template is not None) and Templates.ObserverTemplates.has_key(Template): + elif (Template is not None) and (Template in Templates.ObserverTemplates): __FunctionText = Templates.ObserverTemplates[Template] elif Script is not None: __FunctionText = _ImportFromScript(Script).getstring() @@ -519,7 +519,7 @@ class New(object): try: self.__adaoStudy.analyze() except Exception as e: - if type(e) == type(SyntaxError()): msg = "at %s: %s"%(e.offset, e.text) + if isinstance(e, SyntaxError): msg = "at %s: %s"%(e.offset, e.text) else: msg = "" raise ValueError("during 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."%(str(e),msg)) diff --git a/src/daSalome/daYacsSchemaCreator/infos_daComposant.py b/src/daSalome/daYacsSchemaCreator/infos_daComposant.py index e82a5f0..2adb260 100644 --- a/src/daSalome/daYacsSchemaCreator/infos_daComposant.py +++ b/src/daSalome/daYacsSchemaCreator/infos_daComposant.py @@ -61,6 +61,7 @@ FromNumpyList["Dict"] = ["String", "Script"] # -- Infos from daAlgorithms -- AssimAlgos = [ "3DVAR", + "4DVAR", "Blue", "ExtendedBlue", "EnsembleBlue", @@ -88,6 +89,11 @@ AlgoDataRequirements["3DVAR"] = [ "Observation", "ObservationError", "ObservationOperator", ] +AlgoDataRequirements["4DVAR"] = [ + "Background", "BackgroundError", + "Observation", "ObservationError", + "ObservationOperator", + ] AlgoDataRequirements["Blue"] = [ "Background", "BackgroundError", "Observation", "ObservationError", @@ -168,6 +174,7 @@ AlgoDataRequirements["SamplingTest"] = [ AlgoType = {} AlgoType["3DVAR"] = "Optim" +AlgoType["4DVAR"] = "Optim" AlgoType["Blue"] = "Optim" AlgoType["ExtendedBlue"] = "Optim" AlgoType["EnsembleBlue"] = "Optim" -- 2.39.2