# -*- 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
# 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
+from daCore.PlatformInfo import has_gnuplot, PlatformInfo
+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):
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:
"x.__len__() <==> len(x)"
return len(self.__values)
+ def name(self):
+ return self.__name
+
def __getitem__(self, index=None ):
"x.__getitem__(y) <==> x[y]"
return copy.copy(self.__values[index])
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)
élémentaires numpy.
"""
try:
- return [numpy.matrix(item).mean() 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")
"""
try:
if numpy.version.version >= '1.1.0':
- return [numpy.matrix(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.matrix(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")
numpy.
"""
try:
- return [numpy.matrix(item).sum() for item in self.__values]
+ return [numpy.array(item).sum() for item in self.__values]
except:
raise TypeError("Base type is incompatible with numpy")
numpy.
"""
try:
- return [numpy.matrix(item).min() for item in self.__values]
+ return [numpy.array(item).min() for item in self.__values]
except:
raise TypeError("Base type is incompatible with numpy")
numpy.
"""
try:
- return [numpy.matrix(item).max() for item in self.__values]
+ return [numpy.array(item).max() for item in self.__values]
+ 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 = "",
eval(input('Please press return to continue...\n'))
# ---------------------------------------------------------
+ # On pourrait aussi utiliser d'autres attributs d'un "array" comme "tofile"
def mean(self):
"""
Renvoie la moyenne sur toutes les valeurs sans tenir compte de la
les types élémentaires numpy.
"""
try:
- if self.__basetype in [int, float]:
- return float( numpy.array(self.__values).mean() )
- else:
- return numpy.array(self.__values).mean(axis=0)
+ return numpy.mean(self.__values, axis=0, dtype=mfp).astype('float')
except:
raise TypeError("Base type is incompatible with numpy")
"""
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")
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")
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")
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")
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")
- # On pourrait aussi utiliser les autres attributs d'une "matrix", comme
- # "tofile", "min"...
-
def plot(self,
steps = None,
title = "",
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 )
#
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):
"""
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):
"""
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)
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():
# ==============================================================================
if __name__ == "__main__":
- print('\n AUTODIAGNOSTIC \n')
+ print('\n AUTODIAGNOSTIC\n')