1 #-*-coding:iso-8859-1-*-
3 # Copyright (C) 2008-2010 EDF R&D
5 # This library is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU Lesser General Public
7 # License as published by the Free Software Foundation; either
8 # version 2.1 of the License.
10 # This library is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 # Lesser General Public License for more details.
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with this library; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 Définit des outils de persistence et d'enregistrement de séries de valeurs
23 pour analyse ultérieure ou utilisation de calcul.
25 __author__ = "Jean-Philippe ARGAUD - Mars 2008"
29 from PlatformInfo import PathManagement ; PathManagement()
31 # ==============================================================================
34 Classe générale de persistence définissant les accesseurs nécessaires
37 def __init__(self, name="", unit="", basetype=str):
41 basetype : type de base de l'objet stocké à chaque pas
43 La gestion interne des données est exclusivement basée sur les variables
44 initialisées ici (qui ne sont pas accessibles depuis l'extérieur des
45 objets comme des attributs) :
46 __step : numérotation par défaut du pas courant
47 __basetype : le type de base de chaque valeur, sous la forme d'un type
48 permettant l'instanciation ou le casting Python
49 __steps : les pas de stockage. Par défaut, c'est __step
50 __values : les valeurs de stockage. Par défaut, c'est None
52 self.__name = str(name)
53 self.__unit = str(unit)
56 self.__basetype = basetype
61 self.__dynamic = False
63 self.__dataobservers = []
65 def basetype(self, basetype=None):
67 Renvoie ou met en place le type de base des objets stockés
70 return self.__basetype
72 self.__basetype = basetype
74 def store(self, value=None, step=None):
76 Stocke une valeur à un pas. Une instanciation est faite avec le type de
77 base pour stocker l'objet. Si le pas n'est pas fournit, on utilise
78 l'étape de stockage comme valeur de pas.
80 if value is None: raise ValueError("Value argument required")
83 self.__steps.append(step)
85 self.__steps.append(self.__step)
87 self.__values.append(self.__basetype(value))
89 if self.__dynamic: self.__replot()
90 for hook, parameters, scheduler in self.__dataobservers:
91 if self.__step in scheduler:
92 hook( self, parameters )
96 Renvoie la taille sous forme numpy du dernier objet stocké. Si c'est un
97 objet numpy, renvoie le shape. Si c'est un entier, un flottant, un
98 complexe, renvoie 1. Si c'est une liste ou un dictionnaire, renvoie la
99 longueur. Par défaut, renvoie 1.
101 if len(self.__values) > 0:
102 if self.__basetype in [numpy.matrix, numpy.array]:
103 return self.__values[-1].shape
104 elif self.__basetype in [int, float]:
106 elif self.__basetype in [list, dict]:
107 return (len(self.__values[-1]),)
111 raise ValueError("Object has no shape before its first storage")
115 Renvoie le nombre d'éléments dans un séquence ou la plus grande
116 dimension d'une matrice
118 return max( self.shape() )
120 # ---------------------------------------------------------
121 def stepserie(self, item=None, step=None):
123 Renvoie par défaut toute la liste des pas de temps. Si l'argument "step"
124 existe dans la liste des pas de stockage effectués, renvoie ce pas
125 "step". Si l'argument "item" est correct, renvoie le pas stockée au
128 if step is not None and step in self.__steps:
130 elif item is not None and item < len(self.__steps):
131 return self.__steps[item]
135 def valueserie(self, item=None, step=None):
137 Renvoie par défaut toute la liste des valeurs/objets. Si l'argument
138 "step" existe dans la liste des pas de stockage effectués, renvoie la
139 valeur stockée à ce pas "step". Si l'argument "item" est correct,
140 renvoie la valeur stockée au numéro "item".
142 if step is not None and step in self.__steps:
143 index = self.__steps.index(step)
144 return self.__values[index]
145 elif item is not None and item < len(self.__values):
146 return self.__values[item]
150 def stepnumber(self):
152 Renvoie le nombre de pas de stockage.
154 return len(self.__steps)
156 # ---------------------------------------------------------
157 # Méthodes d'accès de type dictionnaire
159 return self.stepserie()
162 return self.valueserie()
166 for i in xrange(self.stepnumber()):
167 pairs.append( (self.stepserie(item=i), self.valueserie(item=i)) )
170 # ---------------------------------------------------------
173 Renvoie la valeur moyenne des données à chaque pas. Il faut que le type
174 de base soit compatible avec les types élémentaires numpy.
177 return [numpy.matrix(item).mean() for item in self.__values]
179 raise TypeError("Base type is incompatible with numpy")
181 def std(self, ddof=0):
183 Renvoie l'écart-type des données à chaque pas. Il faut que le type de
184 base soit compatible avec les types élémentaires numpy.
186 ddof : c'est le nombre de degrés de liberté pour le calcul de
187 l'écart-type, qui est dans le diviseur. Inutile avant Numpy 1.1
190 if numpy.version.version >= '1.1.0':
191 return [numpy.matrix(item).std(ddof=ddof) for item in self.__values]
193 return [numpy.matrix(item).std() for item in self.__values]
195 raise TypeError("Base type is incompatible with numpy")
199 Renvoie la somme des données à chaque pas. Il faut que le type de
200 base soit compatible avec les types élémentaires numpy.
203 return [numpy.matrix(item).sum() for item in self.__values]
205 raise TypeError("Base type is incompatible with numpy")
209 Renvoie le minimum des données à chaque pas. Il faut que le type de
210 base soit compatible avec les types élémentaires numpy.
213 return [numpy.matrix(item).min() for item in self.__values]
215 raise TypeError("Base type is incompatible with numpy")
219 Renvoie le maximum des données à chaque pas. Il faut que le type de
220 base soit compatible avec les types élémentaires numpy.
223 return [numpy.matrix(item).max() for item in self.__values]
225 raise TypeError("Base type is incompatible with numpy")
232 geometry = "600x400",
238 # Vérification de la disponibilité du module Gnuplot
241 self.__gnuplot = Gnuplot
243 raise ImportError("The Gnuplot module is required to plot the object.")
245 # Vérification et compléments sur les paramètres d'entrée
247 self.__gnuplot.GnuplotOpts.gnuplot_command = 'gnuplot -persist -geometry '+geometry
249 self.__gnuplot.GnuplotOpts.gnuplot_command = 'gnuplot -geometry '+geometry
252 self.__g = self.__gnuplot.Gnuplot() # persist=1
253 self.__g('set terminal '+self.__gnuplot.GnuplotOpts.default_term)
254 self.__g('set style data lines')
256 self.__g('set autoscale')
257 self.__g('set xlabel "'+str(xlabel).encode('ascii','replace')+'"')
258 self.__g('set ylabel "'+str(ylabel).encode('ascii','replace')+'"')
260 self.__ltitle = ltitle
263 def plot(self, item=None, step=None,
269 geometry = "600x400",
276 Renvoie un affichage de la valeur à chaque pas, si elle est compatible
277 avec un affichage Gnuplot (donc essentiellement un vecteur). Si
278 l'argument "step" existe dans la liste des pas de stockage effectués,
279 renvoie l'affichage de la valeur stockée à ce pas "step". Si l'argument
280 "item" est correct, renvoie l'affichage de la valeur stockée au numéro
281 "item". Par défaut ou en l'absence de "step" ou "item", renvoie un
282 affichage successif de tous les pas.
285 - step : valeur du pas à afficher
286 - item : index de la valeur à afficher
287 - steps : liste unique des pas de l'axe des X, ou None si c'est
288 la numérotation par défaut
289 - title : base du titre général, qui sera automatiquement
290 complétée par la mention du pas
291 - xlabel : label de l'axe des X
292 - ylabel : label de l'axe des Y
293 - ltitle : titre associé au vecteur tracé
294 - geometry : taille en pixels de la fenêtre et position du coin haut
295 gauche, au format X11 : LxH+X+Y (défaut : 600x400)
296 - filename : base de nom de fichier Postscript pour une sauvegarde,
297 qui est automatiquement complétée par le numéro du
298 fichier calculé par incrément simple de compteur
299 - dynamic : effectue un affichage des valeurs à chaque stockage
300 (au-delà du second) La méthode "plot" permet de déclarer
301 l'affichage dynamique, et c'est la méthode "__replot"
302 qui est utilisée pour l'effectuer
303 - persist : booléen indiquant que la fenêtre affichée sera
304 conservée lors du passage au dessin suivant
305 Par défaut, persist = False
306 - pause : booléen indiquant une pause après chaque tracé, et
308 Par défaut, pause = True
311 if not self.__dynamic:
312 self.__preplot(title, xlabel, ylabel, ltitle, geometry, persist, pause )
314 self.__dynamic = True
315 if len(self.__values) == 0: return 0
317 # Tracé du ou des vecteurs demandés
319 if step is not None and step in self.__steps:
320 indexes.append(self.__steps.index(step))
321 elif item is not None and item < len(self.__values):
324 indexes = indexes + range(len(self.__values))
327 for index in indexes:
328 self.__g('set title "'+str(title).encode('ascii','replace')+' (pas '+str(index)+')"')
329 if ( type(steps) is type([]) ) or ( type(steps) is type(numpy.array([])) ):
332 Steps = range(len(self.__values[index]))
334 self.__g.plot( self.__gnuplot.Data( Steps, self.__values[index], title=ltitle ) )
338 stepfilename = "%s_%03i.ps"%(filename,i)
339 if os.path.isfile(stepfilename):
340 raise ValueError("Error: a file with this name \"%s\" already exists."%stepfilename)
341 self.__g.hardcopy(filename=stepfilename, color=1)
343 raw_input('Please press return to continue...\n')
347 Affichage dans le cas du suivi dynamique de la variable
349 if self.__dynamic and len(self.__values) < 2: return 0
352 self.__g('set title "'+str(self.__title).encode('ascii','replace'))
353 Steps = range(len(self.__values))
354 self.__g.plot( self.__gnuplot.Data( Steps, self.__values, title=self.__ltitle ) )
357 raw_input('Please press return to continue...\n')
359 # ---------------------------------------------------------
362 Renvoie la moyenne sur toutes les valeurs sans tenir compte de la
363 longueur des pas. Il faut que le type de base soit compatible avec
364 les types élémentaires numpy.
367 return numpy.matrix(self.__values).mean()
369 raise TypeError("Base type is incompatible with numpy")
371 def stepstd(self, ddof=0):
373 Renvoie l'écart-type de toutes les valeurs sans tenir compte de la
374 longueur des pas. Il faut que le type de base soit compatible avec
375 les types élémentaires numpy.
377 ddof : c'est le nombre de degrés de liberté pour le calcul de
378 l'écart-type, qui est dans le diviseur. Inutile avant Numpy 1.1
381 if numpy.version.version >= '1.1.0':
382 return numpy.matrix(self.__values).std(ddof=ddof)
384 return numpy.matrix(self.__values).std()
386 raise TypeError("Base type is incompatible with numpy")
390 Renvoie la somme de toutes les valeurs sans tenir compte de la
391 longueur des pas. Il faut que le type de base soit compatible avec
392 les types élémentaires numpy.
395 return numpy.matrix(self.__values).sum()
397 raise TypeError("Base type is incompatible with numpy")
401 Renvoie le minimum de toutes les valeurs sans tenir compte de la
402 longueur des pas. Il faut que le type de base soit compatible avec
403 les types élémentaires numpy.
406 return numpy.matrix(self.__values).min()
408 raise TypeError("Base type is incompatible with numpy")
412 Renvoie le maximum de toutes les valeurs sans tenir compte de la
413 longueur des pas. Il faut que le type de base soit compatible avec
414 les types élémentaires numpy.
417 return numpy.matrix(self.__values).max()
419 raise TypeError("Base type is incompatible with numpy")
423 Renvoie la somme cumulée de toutes les valeurs sans tenir compte de la
424 longueur des pas. Il faut que le type de base soit compatible avec
425 les types élémentaires numpy.
428 return numpy.matrix(self.__values).cumsum(axis=0)
430 raise TypeError("Base type is incompatible with numpy")
432 # On pourrait aussi utiliser les autres attributs d'une "matrix", comme
441 geometry = "600x400",
447 Renvoie un affichage unique pour l'ensemble des valeurs à chaque pas, si
448 elles sont compatibles avec un affichage Gnuplot (donc essentiellement
449 un vecteur). Si l'argument "step" existe dans la liste des pas de
450 stockage effectués, renvoie l'affichage de la valeur stockée à ce pas
451 "step". Si l'argument "item" est correct, renvoie l'affichage de la
452 valeur stockée au numéro "item".
455 - steps : liste unique des pas de l'axe des X, ou None si c'est
456 la numérotation par défaut
457 - title : base du titre général, qui sera automatiquement
458 complétée par la mention du pas
459 - xlabel : label de l'axe des X
460 - ylabel : label de l'axe des Y
461 - ltitle : titre associé au vecteur tracé
462 - geometry : taille en pixels de la fenêtre et position du coin haut
463 gauche, au format X11 : LxH+X+Y (défaut : 600x400)
464 - filename : nom de fichier Postscript pour une sauvegarde
465 - persist : booléen indiquant que la fenêtre affichée sera
466 conservée lors du passage au dessin suivant
467 Par défaut, persist = False
468 - pause : booléen indiquant une pause après chaque tracé, et
470 Par défaut, pause = True
474 # Vérification de la disponibilité du module Gnuplot
477 self.__gnuplot = Gnuplot
479 raise ImportError("The Gnuplot module is required to plot the object.")
481 # Vérification et compléments sur les paramètres d'entrée
483 self.__gnuplot.GnuplotOpts.gnuplot_command = 'gnuplot -persist -geometry '+geometry
485 self.__gnuplot.GnuplotOpts.gnuplot_command = 'gnuplot -geometry '+geometry
488 if ( type(steps) is type([]) ) or ( type(steps) is type(numpy.array([])) ):
491 Steps = range(len(self.__values[0]))
492 self.__g = self.__gnuplot.Gnuplot() # persist=1
493 self.__g('set terminal '+self.__gnuplot.GnuplotOpts.default_term)
494 self.__g('set style data lines')
496 self.__g('set autoscale')
497 self.__g('set title "'+str(title).encode('ascii','replace') +'"')
498 self.__g('set xlabel "'+str(xlabel).encode('ascii','replace')+'"')
499 self.__g('set ylabel "'+str(ylabel).encode('ascii','replace')+'"')
501 # Tracé du ou des vecteurs demandés
502 indexes = range(len(self.__values))
503 self.__g.plot( self.__gnuplot.Data( Steps, self.__values[indexes.pop(0)], title=ltitle+" (pas 0)" ) )
504 for index in indexes:
505 self.__g.replot( self.__gnuplot.Data( Steps, self.__values[index], title=ltitle+" (pas %i)"%index ) )
508 self.__g.hardcopy(filename=filename, color=1)
510 raw_input('Please press return to continue...\n')
512 # ---------------------------------------------------------
513 def setDataObserver(self,
515 HookParameters = None,
519 Méthode d'association à la variable d'un triplet définissant un observer
521 Le Scheduler attendu est une fréquence, une simple liste d'index ou un
525 # Vérification du Scheduler
526 # -------------------------
528 if type(Scheduler) is int: # Considéré comme une fréquence à partir de 0
529 Schedulers = xrange( 0, maxiter, int(Scheduler) )
530 elif type(Scheduler) is xrange: # Considéré comme un itérateur
531 Schedulers = Scheduler
532 elif type(Scheduler) is list: # Considéré comme des index explicites
533 Schedulers = map( long, Scheduler )
534 else: # Dans tous les autres cas, activé par défaut
535 Schedulers = xrange( 0, maxiter )
537 # Stockage interne de l'observer dans la variable
538 # -----------------------------------------------
539 self.__dataobservers.append( [HookFunction, HookParameters, Schedulers] )
541 # ==============================================================================
542 class OneScalar(Persistence):
544 Classe définissant le stockage d'une valeur unique réelle (float) par pas
546 Le type de base peut être changé par la méthode "basetype", mais il faut que
547 le nouveau type de base soit compatible avec les types par éléments de
548 numpy. On peut même utiliser cette classe pour stocker des vecteurs/listes
549 ou des matrices comme dans les classes suivantes, mais c'est déconseillé
550 pour conserver une signification claire des noms.
552 def __init__(self, name="", unit="", basetype = float):
553 Persistence.__init__(self, name, unit, basetype)
555 class OneVector(Persistence):
557 Classe définissant le stockage d'une liste (list) de valeurs homogènes par
558 hypothèse par pas. Pour éviter les confusions, ne pas utiliser la classe
559 "OneVector" pour des données hétérogènes, mais bien "OneList".
561 def __init__(self, name="", unit="", basetype = list):
562 Persistence.__init__(self, name, unit, basetype)
564 class OneMatrix(Persistence):
566 Classe définissant le stockage d'une matrice de valeurs (numpy.matrix) par
569 def __init__(self, name="", unit="", basetype = numpy.matrix):
570 Persistence.__init__(self, name, unit, basetype)
572 class OneList(Persistence):
574 Classe définissant le stockage d'une liste de valeurs potentiellement
575 hétérogènes (list) par pas. Pour éviter les confusions, ne pas utiliser la
576 classe "OneVector" pour des données hétérogènes, mais bien "OneList".
578 def __init__(self, name="", unit="", basetype = list):
579 Persistence.__init__(self, name, unit, basetype)
581 def NoType( value ): return value
583 class OneNoType(Persistence):
585 Classe définissant le stockage d'un objet sans modification (cast) de type.
586 Attention, selon le véritable type de l'objet stocké à chaque pas, les
587 opérations arithmétiques à base de numpy peuvent être invalides ou donner
588 des résultats inatendus. Cette classe n'est donc à utiliser qu'à bon escient
589 volontairement, et pas du tout par défaut.
591 def __init__(self, name="", unit="", basetype = NoType):
592 Persistence.__init__(self, name, unit, basetype)
594 # ==============================================================================
595 class CompositePersistence:
597 Structure de stockage permettant de rassembler plusieurs objets de
600 Des objets par défaut sont prévus, et des objets supplémentaires peuvent
603 def __init__(self, name=""):
607 La gestion interne des données est exclusivement basée sur les variables
608 initialisées ici (qui ne sont pas accessibles depuis l'extérieur des
609 objets comme des attributs) :
610 __StoredObjects : objets de type persistence collectés dans cet objet
612 self.__name = str(name)
614 self.__StoredObjects = {}
616 # Definition des objets par defaut
617 # --------------------------------
618 self.__StoredObjects["Background"] = OneVector("Background", basetype=numpy.array)
619 self.__StoredObjects["BackgroundError"] = OneMatrix("BackgroundError")
620 self.__StoredObjects["Observation"] = OneVector("Observation", basetype=numpy.array)
621 self.__StoredObjects["ObservationError"] = OneMatrix("ObservationError")
622 self.__StoredObjects["Analysis"] = OneVector("Analysis", basetype=numpy.array)
623 self.__StoredObjects["AnalysisError"] = OneMatrix("AnalysisError")
624 self.__StoredObjects["Innovation"] = OneVector("Innovation", basetype=numpy.array)
625 self.__StoredObjects["KalmanGainK"] = OneMatrix("KalmanGainK")
626 self.__StoredObjects["OperatorH"] = OneMatrix("OperatorH")
627 self.__StoredObjects["RmsOMA"] = OneScalar("RmsOMA")
628 self.__StoredObjects["RmsOMB"] = OneScalar("RmsOMB")
629 self.__StoredObjects["RmsBMA"] = OneScalar("RmsBMA")
632 def store(self, name=None, value=None, step=None):
634 Stockage d'une valeur "value" pour le "step" dans la variable "name".
636 if name is None: raise ValueError("Storable object name is required for storage.")
637 if name not in self.__StoredObjects.keys():
638 raise ValueError("No such name '%s' exists in storable objects."%name)
639 self.__StoredObjects[name].store( value=value, step=step )
641 def add_object(self, name=None, persistenceType=Persistence, basetype=numpy.array ):
643 Ajoute dans les objets stockables un nouvel objet défini par son nom, son
644 type de Persistence et son type de base à chaque pas.
646 if name is None: raise ValueError("Object name is required for adding an object.")
647 if name in self.__StoredObjects.keys():
648 raise ValueError("An object with the same name '%s' already exists in storable objects. Choose another one."%name)
649 self.__StoredObjects[name] = persistenceType( name=str(name), basetype=basetype )
651 def get_object(self, name=None ):
653 Renvoie l'objet de type Persistence qui porte le nom demandé.
655 if name is None: raise ValueError("Object name is required for retrieving an object.")
656 if name not in self.__StoredObjects.keys():
657 raise ValueError("No such name '%s' exists in stored objects."%name)
658 return self.__StoredObjects[name]
660 def set_object(self, name=None, objet=None ):
662 Affecte directement un 'objet' qui porte le nom 'name' demandé.
663 Attention, il n'est pas effectué de vérification sur le type, qui doit
664 comporter les méthodes habituelles de Persistence pour que cela
667 if name is None: raise ValueError("Object name is required for setting an object.")
668 if name in self.__StoredObjects.keys():
669 raise ValueError("An object with the same name '%s' already exists in storable objects. Choose another one."%name)
670 self.__StoredObjects[name] = objet
672 def del_object(self, name=None ):
674 Supprime un objet de la liste des objets stockables.
676 if name is None: raise ValueError("Object name is required for retrieving an object.")
677 if name not in self.__StoredObjects.keys():
678 raise ValueError("No such name '%s' exists in stored objects."%name)
679 del self.__StoredObjects[name]
681 # ---------------------------------------------------------
682 # Méthodes d'accès de type dictionnaire
683 def __getitem__(self, name=None ):
684 return self.get_object( name )
686 def __setitem__(self, name=None, objet=None ):
687 self.set_object( name, objet )
690 return self.get_stored_objects(hideVoidObjects = False)
693 return self.__StoredObjects.values()
696 return self.__StoredObjects.items()
698 # ---------------------------------------------------------
699 def get_stored_objects(self, hideVoidObjects = False):
700 objs = self.__StoredObjects.keys()
705 if len(self.__StoredObjects[k]) > 0: usedObjs.append( k )
712 # ---------------------------------------------------------
713 def save_composite(self, filename=None, mode="pickle"):
715 Enregistre l'objet dans le fichier indiqué selon le "mode" demandé,
716 et renvoi le nom du fichier
720 filename = os.tempnam( os.getcwd(), 'dacp' ) + ".pkl"
722 filename = os.path.abspath( filename )
726 output = open( filename, 'wb')
727 cPickle.dump(self, output)
730 raise ValueError("Save mode '%s' unknown. Choose another one."%mode)
734 def load_composite(self, filename=None, mode="pickle"):
736 Recharge un objet composite sauvé en fichier
740 raise ValueError("A file name if requested to load a composite.")
742 filename = os.path.abspath( filename )
746 pkl_file = open(filename, 'rb')
747 output = cPickle.load(pkl_file)
748 for k in output.keys():
751 raise ValueError("Load mode '%s' unknown. Choose another one."%mode)
755 # ==============================================================================
756 if __name__ == "__main__":
757 print '\n AUTODIAGNOSTIC \n'
759 print "======> Un flottant"
760 OBJET_DE_TEST = OneScalar("My float", unit="cm")
761 OBJET_DE_TEST.store( 5.)
762 OBJET_DE_TEST.store(-5.)
763 OBJET_DE_TEST.store( 1.)
764 print "Les pas de stockage :", OBJET_DE_TEST.stepserie()
765 print "Les valeurs :", OBJET_DE_TEST.valueserie()
766 print "La 2ème valeur :", OBJET_DE_TEST.valueserie(1)
767 print "La dernière valeur :", OBJET_DE_TEST.valueserie(-1)
768 print "Valeurs par pas :"
769 print " La moyenne :", OBJET_DE_TEST.mean()
770 print " L'écart-type :", OBJET_DE_TEST.std()
771 print " La somme :", OBJET_DE_TEST.sum()
772 print " Le minimum :", OBJET_DE_TEST.min()
773 print " Le maximum :", OBJET_DE_TEST.max()
774 print "Valeurs globales :"
775 print " La moyenne :", OBJET_DE_TEST.stepmean()
776 print " L'écart-type :", OBJET_DE_TEST.stepstd()
777 print " La somme :", OBJET_DE_TEST.stepsum()
778 print " Le minimum :", OBJET_DE_TEST.stepmin()
779 print " Le maximum :", OBJET_DE_TEST.stepmax()
780 print " La somme cumulée :", OBJET_DE_TEST.cumsum()
781 print "Taille \"shape\" :", OBJET_DE_TEST.shape()
782 print "Taille \"len\" :", len(OBJET_DE_TEST)
786 print "======> Un entier"
787 OBJET_DE_TEST = OneScalar("My int", unit="cm", basetype=int)
788 OBJET_DE_TEST.store( 5 )
789 OBJET_DE_TEST.store(-5 )
790 OBJET_DE_TEST.store( 1.)
791 print "Les pas de stockage :", OBJET_DE_TEST.stepserie()
792 print "Les valeurs :", OBJET_DE_TEST.valueserie()
793 print "La 2ème valeur :", OBJET_DE_TEST.valueserie(1)
794 print "La dernière valeur :", OBJET_DE_TEST.valueserie(-1)
795 print "Valeurs par pas :"
796 print " La moyenne :", OBJET_DE_TEST.mean()
797 print " L'écart-type :", OBJET_DE_TEST.std()
798 print " La somme :", OBJET_DE_TEST.sum()
799 print " Le minimum :", OBJET_DE_TEST.min()
800 print " Le maximum :", OBJET_DE_TEST.max()
801 print "Valeurs globales :"
802 print " La moyenne :", OBJET_DE_TEST.stepmean()
803 print " L'écart-type :", OBJET_DE_TEST.stepstd()
804 print " La somme :", OBJET_DE_TEST.stepsum()
805 print " Le minimum :", OBJET_DE_TEST.stepmin()
806 print " Le maximum :", OBJET_DE_TEST.stepmax()
807 print " La somme cumulée :", OBJET_DE_TEST.cumsum()
808 print "Taille \"shape\" :", OBJET_DE_TEST.shape()
809 print "Taille \"len\" :", len(OBJET_DE_TEST)
813 print "======> Un booléen"
814 OBJET_DE_TEST = OneScalar("My bool", unit="", basetype=bool)
815 OBJET_DE_TEST.store( True )
816 OBJET_DE_TEST.store( False )
817 OBJET_DE_TEST.store( True )
818 print "Les pas de stockage :", OBJET_DE_TEST.stepserie()
819 print "Les valeurs :", OBJET_DE_TEST.valueserie()
820 print "La 2ème valeur :", OBJET_DE_TEST.valueserie(1)
821 print "La dernière valeur :", OBJET_DE_TEST.valueserie(-1)
822 print "Taille \"shape\" :", OBJET_DE_TEST.shape()
823 print "Taille \"len\" :", len(OBJET_DE_TEST)
827 print "======> Un vecteur de flottants"
828 OBJET_DE_TEST = OneVector("My float vector", unit="cm")
829 OBJET_DE_TEST.store( (5 , -5) )
830 OBJET_DE_TEST.store( (-5, 5 ) )
831 OBJET_DE_TEST.store( (1., 1.) )
832 print "Les pas de stockage :", OBJET_DE_TEST.stepserie()
833 print "Les valeurs :", OBJET_DE_TEST.valueserie()
834 print "La 2ème valeur :", OBJET_DE_TEST.valueserie(1)
835 print "La dernière valeur :", OBJET_DE_TEST.valueserie(-1)
836 print "Valeurs par pas :"
837 print " La moyenne :", OBJET_DE_TEST.mean()
838 print " L'écart-type :", OBJET_DE_TEST.std()
839 print " La somme :", OBJET_DE_TEST.sum()
840 print " Le minimum :", OBJET_DE_TEST.min()
841 print " Le maximum :", OBJET_DE_TEST.max()
842 print "Valeurs globales :"
843 print " La moyenne :", OBJET_DE_TEST.stepmean()
844 print " L'écart-type :", OBJET_DE_TEST.stepstd()
845 print " La somme :", OBJET_DE_TEST.stepsum()
846 print " Le minimum :", OBJET_DE_TEST.stepmin()
847 print " Le maximum :", OBJET_DE_TEST.stepmax()
848 print " La somme cumulée :", OBJET_DE_TEST.cumsum()
849 print "Taille \"shape\" :", OBJET_DE_TEST.shape()
850 print "Taille \"len\" :", len(OBJET_DE_TEST)
854 print "======> Une liste hétérogène"
855 OBJET_DE_TEST = OneList("My list", unit="bool/cm")
856 OBJET_DE_TEST.store( (True , -5) )
857 OBJET_DE_TEST.store( (False, 5 ) )
858 OBJET_DE_TEST.store( (True , 1.) )
859 print "Les pas de stockage :", OBJET_DE_TEST.stepserie()
860 print "Les valeurs :", OBJET_DE_TEST.valueserie()
861 print "La 2ème valeur :", OBJET_DE_TEST.valueserie(1)
862 print "La dernière valeur :", OBJET_DE_TEST.valueserie(-1)
863 print "Valeurs par pas : attention, on peut les calculer car True=1, False=0, mais cela n'a pas de sens"
864 print " La moyenne :", OBJET_DE_TEST.mean()
865 print " L'écart-type :", OBJET_DE_TEST.std()
866 print " La somme :", OBJET_DE_TEST.sum()
867 print " Le minimum :", OBJET_DE_TEST.min()
868 print " Le maximum :", OBJET_DE_TEST.max()
869 print "Valeurs globales : attention, on peut les calculer car True=1, False=0, mais cela n'a pas de sens"
870 print " La moyenne :", OBJET_DE_TEST.stepmean()
871 print " L'écart-type :", OBJET_DE_TEST.stepstd()
872 print " La somme :", OBJET_DE_TEST.stepsum()
873 print " Le minimum :", OBJET_DE_TEST.stepmin()
874 print " Le maximum :", OBJET_DE_TEST.stepmax()
875 print " La somme cumulée :", OBJET_DE_TEST.cumsum()
876 print "Taille \"shape\" :", OBJET_DE_TEST.shape()
877 print "Taille \"len\" :", len(OBJET_DE_TEST)
881 print "======> Utilisation directe de la classe Persistence"
882 OBJET_DE_TEST = Persistence("My object", unit="", basetype=int )
883 OBJET_DE_TEST.store( 1 )
884 OBJET_DE_TEST.store( 3 )
885 OBJET_DE_TEST.store( 7 )
886 print "Les pas de stockage :", OBJET_DE_TEST.stepserie()
887 print "Les valeurs :", OBJET_DE_TEST.valueserie()
888 print "La 2ème valeur :", OBJET_DE_TEST.valueserie(1)
889 print "La dernière valeur :", OBJET_DE_TEST.valueserie(-1)
890 print "Taille \"shape\" :", OBJET_DE_TEST.shape()
891 print "Taille \"len\" :", len(OBJET_DE_TEST)
895 print "======> Utilisation des méthodes d'accès de type dictionnaire"
896 OBJET_DE_TEST = OneScalar("My int", unit="cm", basetype=int)
898 OBJET_DE_TEST.store( 7+i )
899 print "Taille \"len\" :", len(OBJET_DE_TEST)
900 print "Les pas de stockage :", OBJET_DE_TEST.keys()
901 print "Les valeurs :", OBJET_DE_TEST.values()
902 print "Les paires :", OBJET_DE_TEST.items()
906 print "======> Persistence composite"
907 OBJET_DE_TEST = CompositePersistence("My CompositePersistence")
908 print "Objets stockables :", OBJET_DE_TEST.get_stored_objects()
909 print "Objets actifs :", OBJET_DE_TEST.get_stored_objects( hideVoidObjects = True )
910 print "--> Stockage d'une valeur de Background"
911 OBJET_DE_TEST.store("Background",numpy.zeros(5))
912 print "Objets actifs :", OBJET_DE_TEST.get_stored_objects( hideVoidObjects = True )
913 print "--> Ajout d'un objet nouveau par defaut, de type vecteur numpy par pas"
914 OBJET_DE_TEST.add_object("ValeursVectorielles")
915 OBJET_DE_TEST.store("ValeursVectorielles",numpy.zeros(5))
916 print "Objets actifs :", OBJET_DE_TEST.get_stored_objects( hideVoidObjects = True )
917 print "--> Ajout d'un objet nouveau de type liste par pas"
918 OBJET_DE_TEST.add_object("ValeursList", persistenceType=OneList )
919 OBJET_DE_TEST.store("ValeursList",range(5))
920 print "Objets actifs :", OBJET_DE_TEST.get_stored_objects( hideVoidObjects = True )
921 print "--> Ajout d'un objet nouveau, de type vecteur string par pas"
922 OBJET_DE_TEST.add_object("ValeursStr", persistenceType=Persistence, basetype=str )
923 OBJET_DE_TEST.store("ValeursStr","c020")
924 OBJET_DE_TEST.store("ValeursStr","c021")
925 print "Les valeurs :", OBJET_DE_TEST.get_object("ValeursStr").valueserie()
926 print "Acces comme dict :", OBJET_DE_TEST["ValeursStr"].stepserie()
927 print "Acces comme dict :", OBJET_DE_TEST["ValeursStr"].valueserie()
928 print "Objets actifs :", OBJET_DE_TEST.get_stored_objects( hideVoidObjects = True )
929 print "--> Suppression d'un objet"
930 OBJET_DE_TEST.del_object("ValeursVectorielles")
931 print "Objets actifs :", OBJET_DE_TEST.get_stored_objects( hideVoidObjects = True )
932 print "--> Enregistrement de l'objet complet de Persistence composite"
933 OBJET_DE_TEST.save_composite("composite.pkl")
936 print "======> Affichage graphique d'objets stockés"
937 OBJET_DE_TEST = Persistence("My object", unit="", basetype=numpy.array)
939 vect1 = [1, 2, 1, 2, 1]
940 vect2 = [-3, -3, 0, -3, -3]
941 vect3 = [-1, 1, -5, 1, -1]
942 vect4 = 100*[0.29, 0.97, 0.73, 0.01, 0.20]
943 print "Stockage de 3 vecteurs de longueur identique"
947 print "Affichage graphique de l'ensemble du stockage sur une même image"
949 title = "Tous les vecteurs",
950 filename="vecteurs.ps",
954 print "Stockage d'un quatrième vecteur de longueur différente"
956 print "Affichage graphique séparé du dernier stockage"
960 filename = "vecteur",
964 print "Les images ont été stockées en fichiers Postscript"
965 print "Taille \"shape\" du dernier objet stocké",OBJET_DE_TEST.shape()
966 print "Taille \"len\" du dernier objet stocké",len(OBJET_DE_TEST)
970 print "======> Affichage graphique dynamique d'objets"
971 OBJET_DE_TEST = Persistence("My object", unit="", basetype=float)
975 title = "Valeur suivie",
980 for i in range(1,11):
982 print "Taille \"shape\" du dernier objet stocké",OBJET_DE_TEST.shape()
983 print "Taille \"len\" du dernier objet stocké",len(OBJET_DE_TEST)
984 print "Nombre d'objets stockés",OBJET_DE_TEST.stepnumber()
988 print "======> Affectation simple d'observateurs dynamiques"
989 def obs(var=None,info=None):
990 print " ---> Mise en oeuvre de l'observer"
991 print " var =",var.valueserie(-1)
993 OBJET_DE_TEST = Persistence("My object", unit="", basetype=list)
995 D.setDataObserver( HookFunction = obs )
998 print "Action de 1 observer sur la variable observée, étape :",i
1003 print "======> Affectation multiple d'observateurs dynamiques"
1004 def obs(var=None,info=None):
1005 print " ---> Mise en oeuvre de l'observer"
1006 print " var =",var.valueserie(-1)
1007 print " info =",info
1008 OBJET_DE_TEST = Persistence("My object", unit="", basetype=list)
1013 HookParameters = "Second observer",
1017 Scheduler = xrange(1,3),
1018 HookParameters = "Troisième observer",
1022 print "Action de 2 observers sur la variable observée, étape :",i
1023 D.store( [i, i, i] )