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 def removeDataObserver(self,
545 Méthode de suppression d'un observer sur la variable.
547 On peut donner dans HookFunction la meme fonction que lors de la
548 définition, ou un simple string qui est le nom de la fonction.
551 if hasattr(HookFunction,"func_name"):
552 name = str( HookFunction.func_name )
553 elif type(HookFunction) is str:
554 name = str( HookFunction )
560 for [hf, hp, hs] in self.__dataobservers:
562 if name is hf.func_name: index_to_remove.append( i )
563 index_to_remove.reverse()
564 for i in index_to_remove:
565 self.__dataobservers.pop( i )
567 # ==============================================================================
568 class OneScalar(Persistence):
570 Classe définissant le stockage d'une valeur unique réelle (float) par pas
572 Le type de base peut être changé par la méthode "basetype", mais il faut que
573 le nouveau type de base soit compatible avec les types par éléments de
574 numpy. On peut même utiliser cette classe pour stocker des vecteurs/listes
575 ou des matrices comme dans les classes suivantes, mais c'est déconseillé
576 pour conserver une signification claire des noms.
578 def __init__(self, name="", unit="", basetype = float):
579 Persistence.__init__(self, name, unit, basetype)
581 class OneVector(Persistence):
583 Classe définissant le stockage d'une liste (list) de valeurs homogènes par
584 hypothèse par pas. Pour éviter les confusions, ne pas utiliser la classe
585 "OneVector" pour des données hétérogènes, mais bien "OneList".
587 def __init__(self, name="", unit="", basetype = list):
588 Persistence.__init__(self, name, unit, basetype)
590 class OneMatrix(Persistence):
592 Classe définissant le stockage d'une matrice de valeurs (numpy.matrix) par
595 def __init__(self, name="", unit="", basetype = numpy.matrix):
596 Persistence.__init__(self, name, unit, basetype)
598 class OneList(Persistence):
600 Classe définissant le stockage d'une liste de valeurs potentiellement
601 hétérogènes (list) par pas. Pour éviter les confusions, ne pas utiliser la
602 classe "OneVector" pour des données hétérogènes, mais bien "OneList".
604 def __init__(self, name="", unit="", basetype = list):
605 Persistence.__init__(self, name, unit, basetype)
607 def NoType( value ): return value
609 class OneNoType(Persistence):
611 Classe définissant le stockage d'un objet sans modification (cast) de type.
612 Attention, selon le véritable type de l'objet stocké à chaque pas, les
613 opérations arithmétiques à base de numpy peuvent être invalides ou donner
614 des résultats inatendus. Cette classe n'est donc à utiliser qu'à bon escient
615 volontairement, et pas du tout par défaut.
617 def __init__(self, name="", unit="", basetype = NoType):
618 Persistence.__init__(self, name, unit, basetype)
620 # ==============================================================================
621 class CompositePersistence:
623 Structure de stockage permettant de rassembler plusieurs objets de
626 Des objets par défaut sont prévus, et des objets supplémentaires peuvent
629 def __init__(self, name=""):
633 La gestion interne des données est exclusivement basée sur les variables
634 initialisées ici (qui ne sont pas accessibles depuis l'extérieur des
635 objets comme des attributs) :
636 __StoredObjects : objets de type persistence collectés dans cet objet
638 self.__name = str(name)
640 self.__StoredObjects = {}
642 # Definition des objets par defaut
643 # --------------------------------
644 self.__StoredObjects["Background"] = OneVector("Background", basetype=numpy.array)
645 self.__StoredObjects["BackgroundError"] = OneMatrix("BackgroundError")
646 self.__StoredObjects["Observation"] = OneVector("Observation", basetype=numpy.array)
647 self.__StoredObjects["ObservationError"] = OneMatrix("ObservationError")
648 self.__StoredObjects["Analysis"] = OneVector("Analysis", basetype=numpy.array)
649 self.__StoredObjects["AnalysisError"] = OneMatrix("AnalysisError")
650 self.__StoredObjects["Innovation"] = OneVector("Innovation", basetype=numpy.array)
651 self.__StoredObjects["KalmanGainK"] = OneMatrix("KalmanGainK")
652 self.__StoredObjects["OperatorH"] = OneMatrix("OperatorH")
653 self.__StoredObjects["RmsOMA"] = OneScalar("RmsOMA")
654 self.__StoredObjects["RmsOMB"] = OneScalar("RmsOMB")
655 self.__StoredObjects["RmsBMA"] = OneScalar("RmsBMA")
658 def store(self, name=None, value=None, step=None):
660 Stockage d'une valeur "value" pour le "step" dans la variable "name".
662 if name is None: raise ValueError("Storable object name is required for storage.")
663 if name not in self.__StoredObjects.keys():
664 raise ValueError("No such name '%s' exists in storable objects."%name)
665 self.__StoredObjects[name].store( value=value, step=step )
667 def add_object(self, name=None, persistenceType=Persistence, basetype=numpy.array ):
669 Ajoute dans les objets stockables un nouvel objet défini par son nom, son
670 type de Persistence et son type de base à chaque pas.
672 if name is None: raise ValueError("Object name is required for adding an object.")
673 if name in self.__StoredObjects.keys():
674 raise ValueError("An object with the same name '%s' already exists in storable objects. Choose another one."%name)
675 self.__StoredObjects[name] = persistenceType( name=str(name), basetype=basetype )
677 def get_object(self, name=None ):
679 Renvoie l'objet de type Persistence qui porte le nom demandé.
681 if name is None: raise ValueError("Object name is required for retrieving an object.")
682 if name not in self.__StoredObjects.keys():
683 raise ValueError("No such name '%s' exists in stored objects."%name)
684 return self.__StoredObjects[name]
686 def set_object(self, name=None, objet=None ):
688 Affecte directement un 'objet' qui porte le nom 'name' demandé.
689 Attention, il n'est pas effectué de vérification sur le type, qui doit
690 comporter les méthodes habituelles de Persistence pour que cela
693 if name is None: raise ValueError("Object name is required for setting an object.")
694 if name in self.__StoredObjects.keys():
695 raise ValueError("An object with the same name '%s' already exists in storable objects. Choose another one."%name)
696 self.__StoredObjects[name] = objet
698 def del_object(self, name=None ):
700 Supprime un objet de la liste des objets stockables.
702 if name is None: raise ValueError("Object name is required for retrieving an object.")
703 if name not in self.__StoredObjects.keys():
704 raise ValueError("No such name '%s' exists in stored objects."%name)
705 del self.__StoredObjects[name]
707 # ---------------------------------------------------------
708 # Méthodes d'accès de type dictionnaire
709 def __getitem__(self, name=None ):
710 return self.get_object( name )
712 def __setitem__(self, name=None, objet=None ):
713 self.set_object( name, objet )
716 return self.get_stored_objects(hideVoidObjects = False)
719 return self.__StoredObjects.values()
722 return self.__StoredObjects.items()
724 # ---------------------------------------------------------
725 def get_stored_objects(self, hideVoidObjects = False):
726 objs = self.__StoredObjects.keys()
731 if len(self.__StoredObjects[k]) > 0: usedObjs.append( k )
738 # ---------------------------------------------------------
739 def save_composite(self, filename=None, mode="pickle"):
741 Enregistre l'objet dans le fichier indiqué selon le "mode" demandé,
742 et renvoi le nom du fichier
746 filename = os.tempnam( os.getcwd(), 'dacp' ) + ".pkl"
748 filename = os.path.abspath( filename )
752 output = open( filename, 'wb')
753 cPickle.dump(self, output)
756 raise ValueError("Save mode '%s' unknown. Choose another one."%mode)
760 def load_composite(self, filename=None, mode="pickle"):
762 Recharge un objet composite sauvé en fichier
766 raise ValueError("A file name if requested to load a composite.")
768 filename = os.path.abspath( filename )
772 pkl_file = open(filename, 'rb')
773 output = cPickle.load(pkl_file)
774 for k in output.keys():
777 raise ValueError("Load mode '%s' unknown. Choose another one."%mode)
781 # ==============================================================================
782 if __name__ == "__main__":
783 print '\n AUTODIAGNOSTIC \n'
785 print "======> Un flottant"
786 OBJET_DE_TEST = OneScalar("My float", unit="cm")
787 OBJET_DE_TEST.store( 5.)
788 OBJET_DE_TEST.store(-5.)
789 OBJET_DE_TEST.store( 1.)
790 print "Les pas de stockage :", OBJET_DE_TEST.stepserie()
791 print "Les valeurs :", OBJET_DE_TEST.valueserie()
792 print "La 2ème valeur :", OBJET_DE_TEST.valueserie(1)
793 print "La dernière valeur :", OBJET_DE_TEST.valueserie(-1)
794 print "Valeurs par pas :"
795 print " La moyenne :", OBJET_DE_TEST.mean()
796 print " L'écart-type :", OBJET_DE_TEST.std()
797 print " La somme :", OBJET_DE_TEST.sum()
798 print " Le minimum :", OBJET_DE_TEST.min()
799 print " Le maximum :", OBJET_DE_TEST.max()
800 print "Valeurs globales :"
801 print " La moyenne :", OBJET_DE_TEST.stepmean()
802 print " L'écart-type :", OBJET_DE_TEST.stepstd()
803 print " La somme :", OBJET_DE_TEST.stepsum()
804 print " Le minimum :", OBJET_DE_TEST.stepmin()
805 print " Le maximum :", OBJET_DE_TEST.stepmax()
806 print " La somme cumulée :", OBJET_DE_TEST.cumsum()
807 print "Taille \"shape\" :", OBJET_DE_TEST.shape()
808 print "Taille \"len\" :", len(OBJET_DE_TEST)
812 print "======> Un entier"
813 OBJET_DE_TEST = OneScalar("My int", unit="cm", basetype=int)
814 OBJET_DE_TEST.store( 5 )
815 OBJET_DE_TEST.store(-5 )
816 OBJET_DE_TEST.store( 1.)
817 print "Les pas de stockage :", OBJET_DE_TEST.stepserie()
818 print "Les valeurs :", OBJET_DE_TEST.valueserie()
819 print "La 2ème valeur :", OBJET_DE_TEST.valueserie(1)
820 print "La dernière valeur :", OBJET_DE_TEST.valueserie(-1)
821 print "Valeurs par pas :"
822 print " La moyenne :", OBJET_DE_TEST.mean()
823 print " L'écart-type :", OBJET_DE_TEST.std()
824 print " La somme :", OBJET_DE_TEST.sum()
825 print " Le minimum :", OBJET_DE_TEST.min()
826 print " Le maximum :", OBJET_DE_TEST.max()
827 print "Valeurs globales :"
828 print " La moyenne :", OBJET_DE_TEST.stepmean()
829 print " L'écart-type :", OBJET_DE_TEST.stepstd()
830 print " La somme :", OBJET_DE_TEST.stepsum()
831 print " Le minimum :", OBJET_DE_TEST.stepmin()
832 print " Le maximum :", OBJET_DE_TEST.stepmax()
833 print " La somme cumulée :", OBJET_DE_TEST.cumsum()
834 print "Taille \"shape\" :", OBJET_DE_TEST.shape()
835 print "Taille \"len\" :", len(OBJET_DE_TEST)
839 print "======> Un booléen"
840 OBJET_DE_TEST = OneScalar("My bool", unit="", basetype=bool)
841 OBJET_DE_TEST.store( True )
842 OBJET_DE_TEST.store( False )
843 OBJET_DE_TEST.store( True )
844 print "Les pas de stockage :", OBJET_DE_TEST.stepserie()
845 print "Les valeurs :", OBJET_DE_TEST.valueserie()
846 print "La 2ème valeur :", OBJET_DE_TEST.valueserie(1)
847 print "La dernière valeur :", OBJET_DE_TEST.valueserie(-1)
848 print "Taille \"shape\" :", OBJET_DE_TEST.shape()
849 print "Taille \"len\" :", len(OBJET_DE_TEST)
853 print "======> Un vecteur de flottants"
854 OBJET_DE_TEST = OneVector("My float vector", unit="cm")
855 OBJET_DE_TEST.store( (5 , -5) )
856 OBJET_DE_TEST.store( (-5, 5 ) )
857 OBJET_DE_TEST.store( (1., 1.) )
858 print "Les pas de stockage :", OBJET_DE_TEST.stepserie()
859 print "Les valeurs :", OBJET_DE_TEST.valueserie()
860 print "La 2ème valeur :", OBJET_DE_TEST.valueserie(1)
861 print "La dernière valeur :", OBJET_DE_TEST.valueserie(-1)
862 print "Valeurs par pas :"
863 print " La moyenne :", OBJET_DE_TEST.mean()
864 print " L'écart-type :", OBJET_DE_TEST.std()
865 print " La somme :", OBJET_DE_TEST.sum()
866 print " Le minimum :", OBJET_DE_TEST.min()
867 print " Le maximum :", OBJET_DE_TEST.max()
868 print "Valeurs globales :"
869 print " La moyenne :", OBJET_DE_TEST.stepmean()
870 print " L'écart-type :", OBJET_DE_TEST.stepstd()
871 print " La somme :", OBJET_DE_TEST.stepsum()
872 print " Le minimum :", OBJET_DE_TEST.stepmin()
873 print " Le maximum :", OBJET_DE_TEST.stepmax()
874 print " La somme cumulée :", OBJET_DE_TEST.cumsum()
875 print "Taille \"shape\" :", OBJET_DE_TEST.shape()
876 print "Taille \"len\" :", len(OBJET_DE_TEST)
880 print "======> Une liste hétérogène"
881 OBJET_DE_TEST = OneList("My list", unit="bool/cm")
882 OBJET_DE_TEST.store( (True , -5) )
883 OBJET_DE_TEST.store( (False, 5 ) )
884 OBJET_DE_TEST.store( (True , 1.) )
885 print "Les pas de stockage :", OBJET_DE_TEST.stepserie()
886 print "Les valeurs :", OBJET_DE_TEST.valueserie()
887 print "La 2ème valeur :", OBJET_DE_TEST.valueserie(1)
888 print "La dernière valeur :", OBJET_DE_TEST.valueserie(-1)
889 print "Valeurs par pas : attention, on peut les calculer car True=1, False=0, mais cela n'a pas de sens"
890 print " La moyenne :", OBJET_DE_TEST.mean()
891 print " L'écart-type :", OBJET_DE_TEST.std()
892 print " La somme :", OBJET_DE_TEST.sum()
893 print " Le minimum :", OBJET_DE_TEST.min()
894 print " Le maximum :", OBJET_DE_TEST.max()
895 print "Valeurs globales : attention, on peut les calculer car True=1, False=0, mais cela n'a pas de sens"
896 print " La moyenne :", OBJET_DE_TEST.stepmean()
897 print " L'écart-type :", OBJET_DE_TEST.stepstd()
898 print " La somme :", OBJET_DE_TEST.stepsum()
899 print " Le minimum :", OBJET_DE_TEST.stepmin()
900 print " Le maximum :", OBJET_DE_TEST.stepmax()
901 print " La somme cumulée :", OBJET_DE_TEST.cumsum()
902 print "Taille \"shape\" :", OBJET_DE_TEST.shape()
903 print "Taille \"len\" :", len(OBJET_DE_TEST)
907 print "======> Utilisation directe de la classe Persistence"
908 OBJET_DE_TEST = Persistence("My object", unit="", basetype=int )
909 OBJET_DE_TEST.store( 1 )
910 OBJET_DE_TEST.store( 3 )
911 OBJET_DE_TEST.store( 7 )
912 print "Les pas de stockage :", OBJET_DE_TEST.stepserie()
913 print "Les valeurs :", OBJET_DE_TEST.valueserie()
914 print "La 2ème valeur :", OBJET_DE_TEST.valueserie(1)
915 print "La dernière valeur :", OBJET_DE_TEST.valueserie(-1)
916 print "Taille \"shape\" :", OBJET_DE_TEST.shape()
917 print "Taille \"len\" :", len(OBJET_DE_TEST)
921 print "======> Utilisation des méthodes d'accès de type dictionnaire"
922 OBJET_DE_TEST = OneScalar("My int", unit="cm", basetype=int)
924 OBJET_DE_TEST.store( 7+i )
925 print "Taille \"len\" :", len(OBJET_DE_TEST)
926 print "Les pas de stockage :", OBJET_DE_TEST.keys()
927 print "Les valeurs :", OBJET_DE_TEST.values()
928 print "Les paires :", OBJET_DE_TEST.items()
932 print "======> Persistence composite"
933 OBJET_DE_TEST = CompositePersistence("My CompositePersistence")
934 print "Objets stockables :", OBJET_DE_TEST.get_stored_objects()
935 print "Objets actifs :", OBJET_DE_TEST.get_stored_objects( hideVoidObjects = True )
936 print "--> Stockage d'une valeur de Background"
937 OBJET_DE_TEST.store("Background",numpy.zeros(5))
938 print "Objets actifs :", OBJET_DE_TEST.get_stored_objects( hideVoidObjects = True )
939 print "--> Ajout d'un objet nouveau par defaut, de type vecteur numpy par pas"
940 OBJET_DE_TEST.add_object("ValeursVectorielles")
941 OBJET_DE_TEST.store("ValeursVectorielles",numpy.zeros(5))
942 print "Objets actifs :", OBJET_DE_TEST.get_stored_objects( hideVoidObjects = True )
943 print "--> Ajout d'un objet nouveau de type liste par pas"
944 OBJET_DE_TEST.add_object("ValeursList", persistenceType=OneList )
945 OBJET_DE_TEST.store("ValeursList",range(5))
946 print "Objets actifs :", OBJET_DE_TEST.get_stored_objects( hideVoidObjects = True )
947 print "--> Ajout d'un objet nouveau, de type vecteur string par pas"
948 OBJET_DE_TEST.add_object("ValeursStr", persistenceType=Persistence, basetype=str )
949 OBJET_DE_TEST.store("ValeursStr","c020")
950 OBJET_DE_TEST.store("ValeursStr","c021")
951 print "Les valeurs :", OBJET_DE_TEST.get_object("ValeursStr").valueserie()
952 print "Acces comme dict :", OBJET_DE_TEST["ValeursStr"].stepserie()
953 print "Acces comme dict :", OBJET_DE_TEST["ValeursStr"].valueserie()
954 print "Objets actifs :", OBJET_DE_TEST.get_stored_objects( hideVoidObjects = True )
955 print "--> Suppression d'un objet"
956 OBJET_DE_TEST.del_object("ValeursVectorielles")
957 print "Objets actifs :", OBJET_DE_TEST.get_stored_objects( hideVoidObjects = True )
958 print "--> Enregistrement de l'objet complet de Persistence composite"
959 OBJET_DE_TEST.save_composite("composite.pkl")
962 print "======> Affichage graphique d'objets stockés"
963 OBJET_DE_TEST = Persistence("My object", unit="", basetype=numpy.array)
965 vect1 = [1, 2, 1, 2, 1]
966 vect2 = [-3, -3, 0, -3, -3]
967 vect3 = [-1, 1, -5, 1, -1]
968 vect4 = 100*[0.29, 0.97, 0.73, 0.01, 0.20]
969 print "Stockage de 3 vecteurs de longueur identique"
973 print "Affichage graphique de l'ensemble du stockage sur une même image"
975 title = "Tous les vecteurs",
976 filename="vecteurs.ps",
980 print "Stockage d'un quatrième vecteur de longueur différente"
982 print "Affichage graphique séparé du dernier stockage"
986 filename = "vecteur",
990 print "Les images ont été stockées en fichiers Postscript"
991 print "Taille \"shape\" du dernier objet stocké",OBJET_DE_TEST.shape()
992 print "Taille \"len\" du dernier objet stocké",len(OBJET_DE_TEST)
996 print "======> Affichage graphique dynamique d'objets"
997 OBJET_DE_TEST = Persistence("My object", unit="", basetype=float)
1001 title = "Valeur suivie",
1006 for i in range(1,11):
1008 print "Taille \"shape\" du dernier objet stocké",OBJET_DE_TEST.shape()
1009 print "Taille \"len\" du dernier objet stocké",len(OBJET_DE_TEST)
1010 print "Nombre d'objets stockés",OBJET_DE_TEST.stepnumber()
1014 print "======> Affectation simple d'observateurs dynamiques"
1015 def obs(var=None,info=None):
1016 print " ---> Mise en oeuvre de l'observer"
1017 print " var =",var.valueserie(-1)
1018 print " info =",info
1019 OBJET_DE_TEST = Persistence("My object", unit="", basetype=list)
1021 D.setDataObserver( HookFunction = obs )
1024 print "Action de 1 observer sur la variable observée, étape :",i
1025 D.store( [i, i, i] )
1029 print "======> Affectation multiple d'observateurs dynamiques"
1030 def obs(var=None,info=None):
1031 print " ---> Mise en oeuvre de l'observer"
1032 print " var =",var.valueserie(-1)
1033 print " info =",info
1034 def obs_bis(var=None,info=None):
1035 print " ---> Mise en oeuvre de l'observer"
1036 print " var =",var.valueserie(-1)
1037 print " info =",info
1038 OBJET_DE_TEST = Persistence("My object", unit="", basetype=list)
1043 HookParameters = "Premier observer",
1047 Scheduler = xrange(1,3),
1048 HookParameters = "Second observer",
1051 HookFunction = obs_bis,
1052 Scheduler = range(1,3)+range(7,9),
1053 HookParameters = "Troisième observer",
1056 print "Action de 3 observers sur la variable observée, étape :",i
1057 D.store( [i, i, i] )
1058 D.removeDataObserver(
1061 for i in range(5,10):
1062 print "Action d'un seul observer sur la variable observée, étape :",i
1063 D.store( [i, i, i] )