X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FdaComposant%2FdaCore%2FPersistence.py;h=f155146926ee0f3295cff795c97cbd168e91ebc0;hb=61f19963a2e2ed620bdf577c5a01808586dd938d;hp=612963ba7d44f0776b5a539e2c2a8069b3c90581;hpb=594d352d9eb06a60f938a1a6cc12e91a44eebbec;p=modules%2Fadao.git diff --git a/src/daComposant/daCore/Persistence.py b/src/daComposant/daCore/Persistence.py index 612963b..f155146 100644 --- a/src/daComposant/daCore/Persistence.py +++ b/src/daComposant/daCore/Persistence.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2008-2019 EDF R&D +# Copyright (C) 2008-2022 EDF R&D # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -21,14 +21,14 @@ # Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D """ - Définit des outils de persistence et d'enregistrement de séries de valeurs + Définit des outils de persistance et d'enregistrement de séries de valeurs pour analyse ultérieure ou utilisation de calcul. """ __author__ = "Jean-Philippe ARGAUD" __all__ = [] -import os, sys, numpy, copy -import gzip, bz2 +import os, numpy, copy, math +import gzip, bz2, pickle from daCore.PlatformInfo import PathManagement ; PathManagement() from daCore.PlatformInfo import has_gnuplot, PlatformInfo @@ -36,18 +36,10 @@ mfp = PlatformInfo().MaximumPrecision() if has_gnuplot: import Gnuplot -if sys.version_info.major < 3: - range = xrange - iLong = long - import cPickle as pickle -else: - iLong = int - import pickle - # ============================================================================== class Persistence(object): """ - Classe générale de persistence définissant les accesseurs nécessaires + Classe générale de persistance définissant les accesseurs nécessaires (Template) """ def __init__(self, name="", unit="", basetype=str): @@ -105,7 +97,7 @@ class Persistence(object): def pop(self, item=None): """ - Retire une valeur enregistree par son index de stockage. Sans argument, + Retire une valeur enregistrée par son index de stockage. Sans argument, retire le dernier objet enregistre. """ if item is not None: @@ -255,18 +247,18 @@ class Persistence(object): return allKeys # --------------------------------------------------------- - # Pour compatibilite + # Pour compatibilité def stepnumber(self): "Nombre de pas" return len(self.__values) - # Pour compatibilite + # Pour compatibilité def stepserie(self, **kwargs): "Nombre de pas filtrés" __indexOfFilteredItems = self.__filteredIndexes(**kwargs) return __indexOfFilteredItems - # Pour compatibilite + # Pour compatibilité def steplist(self, **kwargs): "Nombre de pas filtrés" __indexOfFilteredItems = self.__filteredIndexes(**kwargs) @@ -280,7 +272,7 @@ class Persistence(object): élémentaires numpy. """ try: - return [numpy.mean(item, dtype=mfp) for item in self.__values] + return [numpy.mean(item, dtype=mfp).astype('float') for item in self.__values] except: raise TypeError("Base type is incompatible with numpy") @@ -295,9 +287,9 @@ class Persistence(object): """ try: if numpy.version.version >= '1.1.0': - return [numpy.array(item).std(ddof=ddof) for item in self.__values] + return [numpy.array(item).std(ddof=ddof, dtype=mfp).astype('float') for item in self.__values] else: - return [numpy.array(item).std() for item in self.__values] + return [numpy.array(item).std(dtype=mfp).astype('float') for item in self.__values] except: raise TypeError("Base type is incompatible with numpy") @@ -334,6 +326,108 @@ class Persistence(object): except: raise TypeError("Base type is incompatible with numpy") + def norms(self, _ord=None): + """ + Norm (_ord : voir numpy.linalg.norm) + + Renvoie la série, contenant à chaque pas, la norme des données au pas. + Il faut que le type de base soit compatible avec les types élémentaires + numpy. + """ + try: + return [numpy.linalg.norm(item, _ord) for item in self.__values] + except: + raise TypeError("Base type is incompatible with numpy") + + def maes(self, _predictor=None): + """ + Mean Absolute Error (MAE) + mae(dX) = 1/n sum(dX_i) + + Renvoie la série, contenant à chaque pas, la MAE des données au pas. + Il faut que le type de base soit compatible avec les types élémentaires + numpy. C'est réservé aux variables d'écarts ou d'incréments si le + prédicteur est None, sinon c'est appliqué à l'écart entre les données + au pas et le prédicteur au même pas. + """ + if _predictor is None: + try: + return [numpy.mean(numpy.abs(item)) for item in self.__values] + except: + raise TypeError("Base type is incompatible with numpy") + else: + if len(_predictor) != len(self.__values): + raise ValueError("Predictor number of steps is incompatible with the values") + for i, item in enumerate(self.__values): + if numpy.asarray(_predictor[i]).size != numpy.asarray(item).size: + raise ValueError("Predictor size at step %i is incompatible with the values"%i) + try: + return [numpy.mean(numpy.abs(numpy.ravel(item) - numpy.ravel(_predictor[i]))) for i, item in enumerate(self.__values)] + except: + raise TypeError("Base type is incompatible with numpy") + + def mses(self, _predictor=None): + """ + Mean-Square Error (MSE) ou Mean-Square Deviation (MSD) + mse(dX) = 1/n sum(dX_i**2) + + Renvoie la série, contenant à chaque pas, la MSE des données au pas. Il + faut que le type de base soit compatible avec les types élémentaires + numpy. C'est réservé aux variables d'écarts ou d'incréments si le + prédicteur est None, sinon c'est appliqué à l'écart entre les données + au pas et le prédicteur au même pas. + """ + if _predictor is None: + try: + __n = self.shape()[0] + return [(numpy.linalg.norm(item)**2 / __n) for item in self.__values] + except: + raise TypeError("Base type is incompatible with numpy") + else: + if len(_predictor) != len(self.__values): + raise ValueError("Predictor number of steps is incompatible with the values") + for i, item in enumerate(self.__values): + if numpy.asarray(_predictor[i]).size != numpy.asarray(item).size: + raise ValueError("Predictor size at step %i is incompatible with the values"%i) + try: + __n = self.shape()[0] + return [(numpy.linalg.norm(numpy.ravel(item) - numpy.ravel(_predictor[i]))**2 / __n) for i, item in enumerate(self.__values)] + except: + raise TypeError("Base type is incompatible with numpy") + + msds=mses # Mean-Square Deviation (MSD=MSE) + + def rmses(self, _predictor=None): + """ + Root-Mean-Square Error (RMSE) ou Root-Mean-Square Deviation (RMSD) + rmse(dX) = sqrt( 1/n sum(dX_i**2) ) = sqrt( mse(dX) ) + + Renvoie la série, contenant à chaque pas, la RMSE des données au pas. + Il faut que le type de base soit compatible avec les types élémentaires + numpy. C'est réservé aux variables d'écarts ou d'incréments si le + prédicteur est None, sinon c'est appliqué à l'écart entre les données + au pas et le prédicteur au même pas. + """ + if _predictor is None: + try: + __n = self.shape()[0] + return [(numpy.linalg.norm(item) / math.sqrt(__n)) for item in self.__values] + except: + raise TypeError("Base type is incompatible with numpy") + else: + if len(_predictor) != len(self.__values): + raise ValueError("Predictor number of steps is incompatible with the values") + for i, item in enumerate(self.__values): + if numpy.asarray(_predictor[i]).size != numpy.asarray(item).size: + raise ValueError("Predictor size at step %i is incompatible with the values"%i) + try: + __n = self.shape()[0] + return [(numpy.linalg.norm(numpy.ravel(item) - numpy.ravel(_predictor[i])) / math.sqrt(__n)) for i, item in enumerate(self.__values)] + except: + raise TypeError("Base type is incompatible with numpy") + + rmsds = rmses # Root-Mean-Square Deviation (RMSD=RMSE) + def __preplots(self, title = "", xlabel = "", @@ -472,10 +566,7 @@ class Persistence(object): les types élémentaires numpy. """ try: - if self.__basetype in [int, float]: - return float( numpy.mean(self.__values, dtype=mfp) ) - else: - return numpy.mean(self.__values, axis=0, dtype=mfp) + return numpy.mean(self.__values, axis=0, dtype=mfp).astype('float') except: raise TypeError("Base type is incompatible with numpy") @@ -490,9 +581,9 @@ class Persistence(object): """ try: if numpy.version.version >= '1.1.0': - return numpy.array(self.__values).std(ddof=ddof,axis=0) + return numpy.asarray(self.__values).std(ddof=ddof,axis=0).astype('float') else: - return numpy.array(self.__values).std(axis=0) + return numpy.asarray(self.__values).std(axis=0).astype('float') except: raise TypeError("Base type is incompatible with numpy") @@ -503,7 +594,7 @@ class Persistence(object): les types élémentaires numpy. """ try: - return numpy.array(self.__values).sum(axis=0) + return numpy.asarray(self.__values).sum(axis=0) except: raise TypeError("Base type is incompatible with numpy") @@ -514,7 +605,7 @@ class Persistence(object): les types élémentaires numpy. """ try: - return numpy.array(self.__values).min(axis=0) + return numpy.asarray(self.__values).min(axis=0) except: raise TypeError("Base type is incompatible with numpy") @@ -525,7 +616,7 @@ class Persistence(object): les types élémentaires numpy. """ try: - return numpy.array(self.__values).max(axis=0) + return numpy.asarray(self.__values).max(axis=0) except: raise TypeError("Base type is incompatible with numpy") @@ -536,7 +627,7 @@ class Persistence(object): les types élémentaires numpy. """ try: - return numpy.array(self.__values).cumsum(axis=0) + return numpy.asarray(self.__values).cumsum(axis=0) except: raise TypeError("Base type is incompatible with numpy") @@ -630,7 +721,7 @@ class Persistence(object): elif isinstance(Scheduler,range): # Considéré comme un itérateur Schedulers = Scheduler elif isinstance(Scheduler,(list,tuple)): # Considéré comme des index explicites - Schedulers = [iLong(i) for i in Scheduler] # map( long, Scheduler ) + Schedulers = [int(i) for i in Scheduler] # map( long, Scheduler ) else: # Dans tous les autres cas, activé par défaut Schedulers = range( 0, maxiter ) # @@ -714,15 +805,15 @@ class OneVector(Persistence): class OneMatrix(Persistence): """ - Classe de stockage d'une matrice de valeurs (numpy.matrix) par pas. + Classe de stockage d'une matrice de valeurs homogènes par pas. """ def __init__(self, name="", unit="", basetype = numpy.matrix): Persistence.__init__(self, name, unit, basetype) class OneList(Persistence): """ - Classe de stockage d'une liste de valeurs hétérogènes (list) par pas. Ne pas - utiliser cette classe pour des données numériques homogènes, mais + Classe de stockage d'une liste de valeurs hétérogènes (list) par pas. Ne + pas utiliser cette classe pour des données numériques homogènes, mais "OneVector". """ def __init__(self, name="", unit="", basetype = list): @@ -736,8 +827,8 @@ class OneNoType(Persistence): """ Classe de stockage d'un objet sans modification (cast) de type. Attention, selon le véritable type de l'objet stocké à chaque pas, les opérations - arithmétiques à base de numpy peuvent être invalides ou donner des résultats - inattendus. Cette classe n'est donc à utiliser qu'à bon escient + arithmétiques à base de numpy peuvent être invalides ou donner des + résultats inattendus. Cette classe n'est donc à utiliser qu'à bon escient volontairement, et pas du tout par défaut. """ def __init__(self, name="", unit="", basetype = NoType): @@ -756,9 +847,9 @@ class CompositePersistence(object): """ 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) : + La gestion interne des données est exclusivement basée sur les + variables initialisées ici (qui ne sont pas accessibles depuis + l'extérieur des objets comme des attributs) : __StoredObjects : objets de type persistence collectés dans cet objet """ self.__name = str(name) @@ -794,8 +885,8 @@ class CompositePersistence(object): def add_object(self, name=None, persistenceType=Persistence, basetype=None ): """ - Ajoute dans les objets stockables un nouvel objet défini par son nom, son - type de Persistence et son type de base à chaque pas. + Ajoute dans les objets stockables un nouvel objet défini par son nom, + son type de Persistence et son type de base à chaque pas. """ if name is None: raise ValueError("Object name is required for adding an object.") if name in self.__StoredObjects.keys():