]> SALOME platform Git repositories - modules/adao.git/commitdiff
Salome HOME
Documentation and source minor corrections and improvements
authorJean-Philippe ARGAUD <jean-philippe.argaud@edf.fr>
Fri, 25 Sep 2015 20:02:31 +0000 (22:02 +0200)
committerJean-Philippe ARGAUD <jean-philippe.argaud@edf.fr>
Sun, 27 Sep 2015 12:45:21 +0000 (14:45 +0200)
14 files changed:
doc/en/ref_algorithm_3DVAR.rst
doc/en/ref_operator_requirements.rst
doc/en/tui.rst
doc/fr/ref_algorithm_3DVAR.rst
doc/fr/ref_operator_requirements.rst
doc/fr/tui.rst
src/daComposant/daAlgorithms/4DVAR.py
src/daComposant/daCore/BasicObjects.py
src/daComposant/daCore/ExtendedLogging.py
src/daComposant/daCore/Persistence.py
src/daComposant/daCore/PlatformInfo.py
src/daComposant/daCore/Templates.py
src/daSalome/adaoBuilder.py
src/daSalome/daYacsSchemaCreator/infos_daComposant.py

index ef532d4a4d97463257f7196bafd29293a77d10ec..3cce8182e7177304849c2a6bdf9d787445566ec3 100644 (file)
@@ -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]_).
index f0d946db2aa37856e0dc48a1299b47e4f9a3f0d6..60df2563d91936eb7c5de6156af0daac308eb6cb 100644 (file)
@@ -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
index c262142df4f4bdaac8818160e85361648b7c72d9..d10371efd537b5868aa004b3f6254e93d471a43c 100644 (file)
 **[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
 +++++++++++++++++++++++
index 4bac5e441b1fb90584b714322ca93d7af952b7ab..6fc8671b2139663ffb0b62a7ba8b1f5818ee8b8b 100644 (file)
@@ -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]_).
index c4f93e0095551ccdeb5f3aba3639db00417a7c39..741eb90660b0bd3d689f644acad4041413945b59 100644 (file)
@@ -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
index 072bb73744cbc63e22f9521bb82a20c62ca956aa..5928c60d06d36bfd9d9f05bab924ff73d3591765 100644 (file)
 **[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 
 +++++++++++++++++++
index 3c6a4398dba1221daf10abe86324beac7a2cbcbc..f05163aff06f6f9fa6003f5f547097d895f5dbae 100644 (file)
@@ -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):
index 57d4e4101a456ce28f82eabfe90909c139f52695..ff6f1405b81ec4861c4f2a199489415036d63552 100644 (file)
@@ -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:
index f83e6594b5b8f75ecc39fe4c71bb501051a0bfb7..aefcf176ca8941ba413bf556832d8f0bc022cf4c 100644 (file)
@@ -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.
index 19ab915438f640ecacde1ea37eb0f0431fe9230f..82df72bbfc7f7a526557a6a835a0e52b0cd6f71e 100644 (file)
@@ -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 = []
index d6cc7716d417b75cfb89c34e7c10edbf8c3cd0a1..f93c99392ee7be89fd0cfdbf49c2d843bdfa1c4d 100644 (file)
@@ -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
index aa84de77d8ae9d190edd0e2dbe90672f4b676eea..ca71bac060f785c5dcdeaef87583a95d35fd06ce 100644 (file)
@@ -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'] )
index 8aa1bab51513b0d8ef73b92acfb671a32f15f142..56c569b316ff5df5697d8ecba5c0dab22131c206 100644 (file)
@@ -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))
 
index e82a5f09ae5cedba8aec44858697ac99849cce03..2adb2602caff341912b167516252bf21356b5033 100644 (file)
@@ -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"