1 #-*-coding:iso-8859-1-*-
3 # Copyright (C) 2008-2011 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"
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, allSteps = False):
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". Si "allSteps" est vrai,
141 renvoie l'ensemble des valeurs et non pas seulement la première.
143 if step is not None and step in self.__steps:
148 while self.__steps.index(step,searchFrom) >= 0:
149 searchFrom = self.__steps.index(step,searchFrom)
150 allIndexes.append( searchFrom )
152 except ValueError, e:
154 allValues = [self.__values[index] for index in allIndexes]
157 index = self.__steps.index(step)
158 return self.__values[index]
159 elif item is not None and item < len(self.__values):
160 return self.__values[item]
164 def stepnumber(self):
166 Renvoie le nombre de pas de stockage.
168 return len(self.__steps)
170 # ---------------------------------------------------------
171 # Méthodes d'accès de type dictionnaire
173 return self.stepserie()
176 return self.valueserie()
180 for i in xrange(self.stepnumber()):
181 pairs.append( (self.stepserie(item=i), self.valueserie(item=i)) )
184 # ---------------------------------------------------------
187 Renvoie la valeur moyenne des données à chaque pas. Il faut que le type
188 de base soit compatible avec les types élémentaires numpy.
191 return [numpy.matrix(item).mean() for item in self.__values]
193 raise TypeError("Base type is incompatible with numpy")
195 def std(self, ddof=0):
197 Renvoie l'écart-type des données à chaque pas. Il faut que le type de
198 base soit compatible avec les types élémentaires numpy.
200 ddof : c'est le nombre de degrés de liberté pour le calcul de
201 l'écart-type, qui est dans le diviseur. Inutile avant Numpy 1.1
204 if numpy.version.version >= '1.1.0':
205 return [numpy.matrix(item).std(ddof=ddof) for item in self.__values]
207 return [numpy.matrix(item).std() for item in self.__values]
209 raise TypeError("Base type is incompatible with numpy")
213 Renvoie la somme des données à chaque pas. Il faut que le type de
214 base soit compatible avec les types élémentaires numpy.
217 return [numpy.matrix(item).sum() for item in self.__values]
219 raise TypeError("Base type is incompatible with numpy")
223 Renvoie le minimum des données à chaque pas. Il faut que le type de
224 base soit compatible avec les types élémentaires numpy.
227 return [numpy.matrix(item).min() for item in self.__values]
229 raise TypeError("Base type is incompatible with numpy")
233 Renvoie le maximum des données à chaque pas. Il faut que le type de
234 base soit compatible avec les types élémentaires numpy.
237 return [numpy.matrix(item).max() for item in self.__values]
239 raise TypeError("Base type is incompatible with numpy")
246 geometry = "600x400",
252 # Vérification de la disponibilité du module Gnuplot
255 self.__gnuplot = Gnuplot
257 raise ImportError("The Gnuplot module is required to plot the object.")
259 # Vérification et compléments sur les paramètres d'entrée
261 self.__gnuplot.GnuplotOpts.gnuplot_command = 'gnuplot -persist -geometry '+geometry
263 self.__gnuplot.GnuplotOpts.gnuplot_command = 'gnuplot -geometry '+geometry
266 self.__g = self.__gnuplot.Gnuplot() # persist=1
267 self.__g('set terminal '+self.__gnuplot.GnuplotOpts.default_term)
268 self.__g('set style data lines')
270 self.__g('set autoscale')
271 self.__g('set xlabel "'+str(xlabel).encode('ascii','replace')+'"')
272 self.__g('set ylabel "'+str(ylabel).encode('ascii','replace')+'"')
274 self.__ltitle = ltitle
277 def plot(self, item=None, step=None,
283 geometry = "600x400",
290 Renvoie un affichage de la valeur à chaque pas, si elle est compatible
291 avec un affichage Gnuplot (donc essentiellement un vecteur). Si
292 l'argument "step" existe dans la liste des pas de stockage effectués,
293 renvoie l'affichage de la valeur stockée à ce pas "step". Si l'argument
294 "item" est correct, renvoie l'affichage de la valeur stockée au numéro
295 "item". Par défaut ou en l'absence de "step" ou "item", renvoie un
296 affichage successif de tous les pas.
299 - step : valeur du pas à afficher
300 - item : index de la valeur à afficher
301 - steps : liste unique des pas de l'axe des X, ou None si c'est
302 la numérotation par défaut
303 - title : base du titre général, qui sera automatiquement
304 complétée par la mention du pas
305 - xlabel : label de l'axe des X
306 - ylabel : label de l'axe des Y
307 - ltitle : titre associé au vecteur tracé
308 - geometry : taille en pixels de la fenêtre et position du coin haut
309 gauche, au format X11 : LxH+X+Y (défaut : 600x400)
310 - filename : base de nom de fichier Postscript pour une sauvegarde,
311 qui est automatiquement complétée par le numéro du
312 fichier calculé par incrément simple de compteur
313 - dynamic : effectue un affichage des valeurs à chaque stockage
314 (au-delà du second) La méthode "plot" permet de déclarer
315 l'affichage dynamique, et c'est la méthode "__replot"
316 qui est utilisée pour l'effectuer
317 - persist : booléen indiquant que la fenêtre affichée sera
318 conservée lors du passage au dessin suivant
319 Par défaut, persist = False
320 - pause : booléen indiquant une pause après chaque tracé, et
322 Par défaut, pause = True
325 if not self.__dynamic:
326 self.__preplot(title, xlabel, ylabel, ltitle, geometry, persist, pause )
328 self.__dynamic = True
329 if len(self.__values) == 0: return 0
331 # Tracé du ou des vecteurs demandés
333 if step is not None and step in self.__steps:
334 indexes.append(self.__steps.index(step))
335 elif item is not None and item < len(self.__values):
338 indexes = indexes + range(len(self.__values))
341 for index in indexes:
342 self.__g('set title "'+str(title).encode('ascii','replace')+' (pas '+str(index)+')"')
343 if ( type(steps) is type([]) ) or ( type(steps) is type(numpy.array([])) ):
346 Steps = range(len(self.__values[index]))
348 self.__g.plot( self.__gnuplot.Data( Steps, self.__values[index], title=ltitle ) )
352 stepfilename = "%s_%03i.ps"%(filename,i)
353 if os.path.isfile(stepfilename):
354 raise ValueError("Error: a file with this name \"%s\" already exists."%stepfilename)
355 self.__g.hardcopy(filename=stepfilename, color=1)
357 raw_input('Please press return to continue...\n')
361 Affichage dans le cas du suivi dynamique de la variable
363 if self.__dynamic and len(self.__values) < 2: return 0
366 self.__g('set title "'+str(self.__title).encode('ascii','replace'))
367 Steps = range(len(self.__values))
368 self.__g.plot( self.__gnuplot.Data( Steps, self.__values, title=self.__ltitle ) )
371 raw_input('Please press return to continue...\n')
373 # ---------------------------------------------------------
376 Renvoie la moyenne sur toutes les valeurs sans tenir compte de la
377 longueur des pas. Il faut que le type de base soit compatible avec
378 les types élémentaires numpy.
381 return numpy.matrix(self.__values).mean()
383 raise TypeError("Base type is incompatible with numpy")
385 def stepstd(self, ddof=0):
387 Renvoie l'écart-type de toutes les valeurs sans tenir compte de la
388 longueur des pas. Il faut que le type de base soit compatible avec
389 les types élémentaires numpy.
391 ddof : c'est le nombre de degrés de liberté pour le calcul de
392 l'écart-type, qui est dans le diviseur. Inutile avant Numpy 1.1
395 if numpy.version.version >= '1.1.0':
396 return numpy.matrix(self.__values).std(ddof=ddof)
398 return numpy.matrix(self.__values).std()
400 raise TypeError("Base type is incompatible with numpy")
404 Renvoie la somme de toutes les valeurs sans tenir compte de la
405 longueur des pas. Il faut que le type de base soit compatible avec
406 les types élémentaires numpy.
409 return numpy.matrix(self.__values).sum()
411 raise TypeError("Base type is incompatible with numpy")
415 Renvoie le minimum de toutes les valeurs sans tenir compte de la
416 longueur des pas. Il faut que le type de base soit compatible avec
417 les types élémentaires numpy.
420 return numpy.matrix(self.__values).min()
422 raise TypeError("Base type is incompatible with numpy")
426 Renvoie le maximum de toutes les valeurs sans tenir compte de la
427 longueur des pas. Il faut que le type de base soit compatible avec
428 les types élémentaires numpy.
431 return numpy.matrix(self.__values).max()
433 raise TypeError("Base type is incompatible with numpy")
437 Renvoie la somme cumulée de toutes les valeurs sans tenir compte de la
438 longueur des pas. Il faut que le type de base soit compatible avec
439 les types élémentaires numpy.
442 return numpy.matrix(self.__values).cumsum(axis=0)
444 raise TypeError("Base type is incompatible with numpy")
446 # On pourrait aussi utiliser les autres attributs d'une "matrix", comme
455 geometry = "600x400",
461 Renvoie un affichage unique pour l'ensemble des valeurs à chaque pas, si
462 elles sont compatibles avec un affichage Gnuplot (donc essentiellement
463 un vecteur). Si l'argument "step" existe dans la liste des pas de
464 stockage effectués, renvoie l'affichage de la valeur stockée à ce pas
465 "step". Si l'argument "item" est correct, renvoie l'affichage de la
466 valeur stockée au numéro "item".
469 - steps : liste unique des pas de l'axe des X, ou None si c'est
470 la numérotation par défaut
471 - title : base du titre général, qui sera automatiquement
472 complétée par la mention du pas
473 - xlabel : label de l'axe des X
474 - ylabel : label de l'axe des Y
475 - ltitle : titre associé au vecteur tracé
476 - geometry : taille en pixels de la fenêtre et position du coin haut
477 gauche, au format X11 : LxH+X+Y (défaut : 600x400)
478 - filename : nom de fichier Postscript pour une sauvegarde
479 - persist : booléen indiquant que la fenêtre affichée sera
480 conservée lors du passage au dessin suivant
481 Par défaut, persist = False
482 - pause : booléen indiquant une pause après chaque tracé, et
484 Par défaut, pause = True
488 # Vérification de la disponibilité du module Gnuplot
491 self.__gnuplot = Gnuplot
493 raise ImportError("The Gnuplot module is required to plot the object.")
495 # Vérification et compléments sur les paramètres d'entrée
497 self.__gnuplot.GnuplotOpts.gnuplot_command = 'gnuplot -persist -geometry '+geometry
499 self.__gnuplot.GnuplotOpts.gnuplot_command = 'gnuplot -geometry '+geometry
502 if ( type(steps) is type([]) ) or ( type(steps) is type(numpy.array([])) ):
505 Steps = range(len(self.__values[0]))
506 self.__g = self.__gnuplot.Gnuplot() # persist=1
507 self.__g('set terminal '+self.__gnuplot.GnuplotOpts.default_term)
508 self.__g('set style data lines')
510 self.__g('set autoscale')
511 self.__g('set title "'+str(title).encode('ascii','replace') +'"')
512 self.__g('set xlabel "'+str(xlabel).encode('ascii','replace')+'"')
513 self.__g('set ylabel "'+str(ylabel).encode('ascii','replace')+'"')
515 # Tracé du ou des vecteurs demandés
516 indexes = range(len(self.__values))
517 self.__g.plot( self.__gnuplot.Data( Steps, self.__values[indexes.pop(0)], title=ltitle+" (pas 0)" ) )
518 for index in indexes:
519 self.__g.replot( self.__gnuplot.Data( Steps, self.__values[index], title=ltitle+" (pas %i)"%index ) )
522 self.__g.hardcopy(filename=filename, color=1)
524 raw_input('Please press return to continue...\n')
526 # ---------------------------------------------------------
527 def setDataObserver(self,
529 HookParameters = None,
533 Méthode d'association à la variable d'un triplet définissant un observer
535 Le Scheduler attendu est une fréquence, une simple liste d'index ou un
539 # Vérification du Scheduler
540 # -------------------------
542 if type(Scheduler) is int: # Considéré comme une fréquence à partir de 0
543 Schedulers = xrange( 0, maxiter, int(Scheduler) )
544 elif type(Scheduler) is xrange: # Considéré comme un itérateur
545 Schedulers = Scheduler
546 elif type(Scheduler) is list: # Considéré comme des index explicites
547 Schedulers = map( long, Scheduler )
548 else: # Dans tous les autres cas, activé par défaut
549 Schedulers = xrange( 0, maxiter )
551 # Stockage interne de l'observer dans la variable
552 # -----------------------------------------------
553 self.__dataobservers.append( [HookFunction, HookParameters, Schedulers] )
555 def removeDataObserver(self,
559 Méthode de suppression d'un observer sur la variable.
561 On peut donner dans HookFunction la meme fonction que lors de la
562 définition, ou un simple string qui est le nom de la fonction.
565 if hasattr(HookFunction,"func_name"):
566 name = str( HookFunction.func_name )
567 elif type(HookFunction) is str:
568 name = str( HookFunction )
574 for [hf, hp, hs] in self.__dataobservers:
576 if name is hf.func_name: index_to_remove.append( i )
577 index_to_remove.reverse()
578 for i in index_to_remove:
579 self.__dataobservers.pop( i )
581 # ==============================================================================
582 class OneScalar(Persistence):
584 Classe définissant le stockage d'une valeur unique réelle (float) par pas
586 Le type de base peut être changé par la méthode "basetype", mais il faut que
587 le nouveau type de base soit compatible avec les types par éléments de
588 numpy. On peut même utiliser cette classe pour stocker des vecteurs/listes
589 ou des matrices comme dans les classes suivantes, mais c'est déconseillé
590 pour conserver une signification claire des noms.
592 def __init__(self, name="", unit="", basetype = float):
593 Persistence.__init__(self, name, unit, basetype)
595 class OneVector(Persistence):
597 Classe définissant le stockage d'une liste (list) de valeurs homogènes par
598 hypothèse par pas. Pour éviter les confusions, ne pas utiliser la classe
599 "OneVector" pour des données hétérogènes, mais bien "OneList".
601 def __init__(self, name="", unit="", basetype = list):
602 Persistence.__init__(self, name, unit, basetype)
604 class OneMatrix(Persistence):
606 Classe définissant le stockage d'une matrice de valeurs (numpy.matrix) par
609 def __init__(self, name="", unit="", basetype = numpy.matrix):
610 Persistence.__init__(self, name, unit, basetype)
612 class OneList(Persistence):
614 Classe définissant le stockage d'une liste de valeurs potentiellement
615 hétérogènes (list) par pas. Pour éviter les confusions, ne pas utiliser la
616 classe "OneVector" pour des données hétérogènes, mais bien "OneList".
618 def __init__(self, name="", unit="", basetype = list):
619 Persistence.__init__(self, name, unit, basetype)
621 def NoType( value ): return value
623 class OneNoType(Persistence):
625 Classe définissant le stockage d'un objet sans modification (cast) de type.
626 Attention, selon le véritable type de l'objet stocké à chaque pas, les
627 opérations arithmétiques à base de numpy peuvent être invalides ou donner
628 des résultats inatendus. Cette classe n'est donc à utiliser qu'à bon escient
629 volontairement, et pas du tout par défaut.
631 def __init__(self, name="", unit="", basetype = NoType):
632 Persistence.__init__(self, name, unit, basetype)
634 # ==============================================================================
635 class CompositePersistence:
637 Structure de stockage permettant de rassembler plusieurs objets de
640 Des objets par défaut sont prévus, et des objets supplémentaires peuvent
643 def __init__(self, name=""):
647 La gestion interne des données est exclusivement basée sur les variables
648 initialisées ici (qui ne sont pas accessibles depuis l'extérieur des
649 objets comme des attributs) :
650 __StoredObjects : objets de type persistence collectés dans cet objet
652 self.__name = str(name)
654 self.__StoredObjects = {}
656 # Definition des objets par defaut
657 # --------------------------------
658 self.__StoredObjects["Informations"] = OneNoType("Informations")
659 self.__StoredObjects["Background"] = OneVector("Background", basetype=numpy.array)
660 self.__StoredObjects["BackgroundError"] = OneMatrix("BackgroundError")
661 self.__StoredObjects["Observation"] = OneVector("Observation", basetype=numpy.array)
662 self.__StoredObjects["ObservationError"] = OneMatrix("ObservationError")
663 self.__StoredObjects["Analysis"] = OneVector("Analysis", basetype=numpy.array)
664 self.__StoredObjects["AnalysisError"] = OneMatrix("AnalysisError")
665 self.__StoredObjects["Innovation"] = OneVector("Innovation", basetype=numpy.array)
666 self.__StoredObjects["KalmanGainK"] = OneMatrix("KalmanGainK")
667 self.__StoredObjects["OperatorH"] = OneMatrix("OperatorH")
668 self.__StoredObjects["RmsOMA"] = OneScalar("RmsOMA")
669 self.__StoredObjects["RmsOMB"] = OneScalar("RmsOMB")
670 self.__StoredObjects["RmsBMA"] = OneScalar("RmsBMA")
673 def store(self, name=None, value=None, step=None):
675 Stockage d'une valeur "value" pour le "step" dans la variable "name".
677 if name is None: raise ValueError("Storable object name is required for storage.")
678 if name not in self.__StoredObjects.keys():
679 raise ValueError("No such name '%s' exists in storable objects."%name)
680 self.__StoredObjects[name].store( value=value, step=step )
682 def add_object(self, name=None, persistenceType=Persistence, basetype=numpy.array ):
684 Ajoute dans les objets stockables un nouvel objet défini par son nom, son
685 type de Persistence et son type de base à chaque pas.
687 if name is None: raise ValueError("Object name is required for adding an object.")
688 if name in self.__StoredObjects.keys():
689 raise ValueError("An object with the same name '%s' already exists in storable objects. Choose another one."%name)
690 self.__StoredObjects[name] = persistenceType( name=str(name), basetype=basetype )
692 def get_object(self, name=None ):
694 Renvoie l'objet de type Persistence qui porte le nom demandé.
696 if name is None: raise ValueError("Object name is required for retrieving an object.")
697 if name not in self.__StoredObjects.keys():
698 raise ValueError("No such name '%s' exists in stored objects."%name)
699 return self.__StoredObjects[name]
701 def set_object(self, name=None, objet=None ):
703 Affecte directement un 'objet' qui porte le nom 'name' demandé.
704 Attention, il n'est pas effectué de vérification sur le type, qui doit
705 comporter les méthodes habituelles de Persistence pour que cela
708 if name is None: raise ValueError("Object name is required for setting an object.")
709 if name in self.__StoredObjects.keys():
710 raise ValueError("An object with the same name '%s' already exists in storable objects. Choose another one."%name)
711 self.__StoredObjects[name] = objet
713 def del_object(self, name=None ):
715 Supprime un objet de la liste des objets stockables.
717 if name is None: raise ValueError("Object name is required for retrieving an object.")
718 if name not in self.__StoredObjects.keys():
719 raise ValueError("No such name '%s' exists in stored objects."%name)
720 del self.__StoredObjects[name]
722 # ---------------------------------------------------------
723 # Méthodes d'accès de type dictionnaire
724 def __getitem__(self, name=None ):
725 return self.get_object( name )
727 def __setitem__(self, name=None, objet=None ):
728 self.set_object( name, objet )
731 return self.get_stored_objects(hideVoidObjects = False)
734 return self.__StoredObjects.values()
737 return self.__StoredObjects.items()
739 # ---------------------------------------------------------
740 def get_stored_objects(self, hideVoidObjects = False):
741 objs = self.__StoredObjects.keys()
746 if len(self.__StoredObjects[k]) > 0: usedObjs.append( k )
753 # ---------------------------------------------------------
754 def save_composite(self, filename=None, mode="pickle"):
756 Enregistre l'objet dans le fichier indiqué selon le "mode" demandé,
757 et renvoi le nom du fichier
761 filename = os.tempnam( os.getcwd(), 'dacp' ) + ".pkl"
763 filename = os.path.abspath( filename )
767 output = open( filename, 'wb')
768 cPickle.dump(self, output)
771 raise ValueError("Save mode '%s' unknown. Choose another one."%mode)
775 def load_composite(self, filename=None, mode="pickle"):
777 Recharge un objet composite sauvé en fichier
781 raise ValueError("A file name if requested to load a composite.")
783 filename = os.path.abspath( filename )
787 pkl_file = open(filename, 'rb')
788 output = cPickle.load(pkl_file)
789 for k in output.keys():
792 raise ValueError("Load mode '%s' unknown. Choose another one."%mode)
796 # ==============================================================================
797 if __name__ == "__main__":
798 print '\n AUTODIAGNOSTIC \n'
800 print "======> Un flottant"
801 OBJET_DE_TEST = OneScalar("My float", unit="cm")
802 OBJET_DE_TEST.store( 5.)
803 OBJET_DE_TEST.store(-5.)
804 OBJET_DE_TEST.store( 1.)
805 print "Les pas de stockage :", OBJET_DE_TEST.stepserie()
806 print "Les valeurs :", OBJET_DE_TEST.valueserie()
807 print "La 2ème valeur :", OBJET_DE_TEST.valueserie(1)
808 print "La dernière valeur :", OBJET_DE_TEST.valueserie(-1)
809 print "Valeurs par pas :"
810 print " La moyenne :", OBJET_DE_TEST.mean()
811 print " L'écart-type :", OBJET_DE_TEST.std()
812 print " La somme :", OBJET_DE_TEST.sum()
813 print " Le minimum :", OBJET_DE_TEST.min()
814 print " Le maximum :", OBJET_DE_TEST.max()
815 print "Valeurs globales :"
816 print " La moyenne :", OBJET_DE_TEST.stepmean()
817 print " L'écart-type :", OBJET_DE_TEST.stepstd()
818 print " La somme :", OBJET_DE_TEST.stepsum()
819 print " Le minimum :", OBJET_DE_TEST.stepmin()
820 print " Le maximum :", OBJET_DE_TEST.stepmax()
821 print " La somme cumulée :", OBJET_DE_TEST.cumsum()
822 print "Taille \"shape\" :", OBJET_DE_TEST.shape()
823 print "Taille \"len\" :", len(OBJET_DE_TEST)
827 print "======> Un flottant"
828 OBJET_DE_TEST = OneScalar("My float", unit="cm")
829 OBJET_DE_TEST.store( 5., step="azerty")
830 OBJET_DE_TEST.store(-5., step="poiuyt")
831 OBJET_DE_TEST.store( 1., step="azerty")
832 OBJET_DE_TEST.store( 0., step="xxxxxx")
833 OBJET_DE_TEST.store( 5., step="poiuyt")
834 OBJET_DE_TEST.store(-5., step="azerty")
835 OBJET_DE_TEST.store( 1., step="poiuyt")
836 print "Les pas de stockage :", OBJET_DE_TEST.stepserie()
837 print "Les valeurs :", OBJET_DE_TEST.valueserie()
838 print "La 2ème valeur :", OBJET_DE_TEST.valueserie(1)
839 print "La dernière valeur :", OBJET_DE_TEST.valueserie(-1)
840 print "Premier index :", OBJET_DE_TEST.valueserie( step = "azerty", allSteps = False )
841 print "Valeurs identiques :", OBJET_DE_TEST.valueserie( step = "azerty", allSteps = True )
842 print "Premier index :", OBJET_DE_TEST.valueserie( step = "poiuyt", allSteps = False )
843 print "Valeurs identiques :", OBJET_DE_TEST.valueserie( step = "poiuyt", allSteps = True )
847 print "======> Un entier"
848 OBJET_DE_TEST = OneScalar("My int", unit="cm", basetype=int)
849 OBJET_DE_TEST.store( 5 )
850 OBJET_DE_TEST.store(-5 )
851 OBJET_DE_TEST.store( 1.)
852 print "Les pas de stockage :", OBJET_DE_TEST.stepserie()
853 print "Les valeurs :", OBJET_DE_TEST.valueserie()
854 print "La 2ème valeur :", OBJET_DE_TEST.valueserie(1)
855 print "La dernière valeur :", OBJET_DE_TEST.valueserie(-1)
856 print "Valeurs par pas :"
857 print " La moyenne :", OBJET_DE_TEST.mean()
858 print " L'écart-type :", OBJET_DE_TEST.std()
859 print " La somme :", OBJET_DE_TEST.sum()
860 print " Le minimum :", OBJET_DE_TEST.min()
861 print " Le maximum :", OBJET_DE_TEST.max()
862 print "Valeurs globales :"
863 print " La moyenne :", OBJET_DE_TEST.stepmean()
864 print " L'écart-type :", OBJET_DE_TEST.stepstd()
865 print " La somme :", OBJET_DE_TEST.stepsum()
866 print " Le minimum :", OBJET_DE_TEST.stepmin()
867 print " Le maximum :", OBJET_DE_TEST.stepmax()
868 print " La somme cumulée :", OBJET_DE_TEST.cumsum()
869 print "Taille \"shape\" :", OBJET_DE_TEST.shape()
870 print "Taille \"len\" :", len(OBJET_DE_TEST)
874 print "======> Un booléen"
875 OBJET_DE_TEST = OneScalar("My bool", unit="", basetype=bool)
876 OBJET_DE_TEST.store( True )
877 OBJET_DE_TEST.store( False )
878 OBJET_DE_TEST.store( True )
879 print "Les pas de stockage :", OBJET_DE_TEST.stepserie()
880 print "Les valeurs :", OBJET_DE_TEST.valueserie()
881 print "La 2ème valeur :", OBJET_DE_TEST.valueserie(1)
882 print "La dernière valeur :", OBJET_DE_TEST.valueserie(-1)
883 print "Taille \"shape\" :", OBJET_DE_TEST.shape()
884 print "Taille \"len\" :", len(OBJET_DE_TEST)
888 print "======> Un vecteur de flottants"
889 OBJET_DE_TEST = OneVector("My float vector", unit="cm")
890 OBJET_DE_TEST.store( (5 , -5) )
891 OBJET_DE_TEST.store( (-5, 5 ) )
892 OBJET_DE_TEST.store( (1., 1.) )
893 print "Les pas de stockage :", OBJET_DE_TEST.stepserie()
894 print "Les valeurs :", OBJET_DE_TEST.valueserie()
895 print "La 2ème valeur :", OBJET_DE_TEST.valueserie(1)
896 print "La dernière valeur :", OBJET_DE_TEST.valueserie(-1)
897 print "Valeurs par pas :"
898 print " La moyenne :", OBJET_DE_TEST.mean()
899 print " L'écart-type :", OBJET_DE_TEST.std()
900 print " La somme :", OBJET_DE_TEST.sum()
901 print " Le minimum :", OBJET_DE_TEST.min()
902 print " Le maximum :", OBJET_DE_TEST.max()
903 print "Valeurs globales :"
904 print " La moyenne :", OBJET_DE_TEST.stepmean()
905 print " L'écart-type :", OBJET_DE_TEST.stepstd()
906 print " La somme :", OBJET_DE_TEST.stepsum()
907 print " Le minimum :", OBJET_DE_TEST.stepmin()
908 print " Le maximum :", OBJET_DE_TEST.stepmax()
909 print " La somme cumulée :", OBJET_DE_TEST.cumsum()
910 print "Taille \"shape\" :", OBJET_DE_TEST.shape()
911 print "Taille \"len\" :", len(OBJET_DE_TEST)
915 print "======> Une liste hétérogène"
916 OBJET_DE_TEST = OneList("My list", unit="bool/cm")
917 OBJET_DE_TEST.store( (True , -5) )
918 OBJET_DE_TEST.store( (False, 5 ) )
919 OBJET_DE_TEST.store( (True , 1.) )
920 print "Les pas de stockage :", OBJET_DE_TEST.stepserie()
921 print "Les valeurs :", OBJET_DE_TEST.valueserie()
922 print "La 2ème valeur :", OBJET_DE_TEST.valueserie(1)
923 print "La dernière valeur :", OBJET_DE_TEST.valueserie(-1)
924 print "Valeurs par pas : attention, on peut les calculer car True=1, False=0, mais cela n'a pas de sens"
925 print " La moyenne :", OBJET_DE_TEST.mean()
926 print " L'écart-type :", OBJET_DE_TEST.std()
927 print " La somme :", OBJET_DE_TEST.sum()
928 print " Le minimum :", OBJET_DE_TEST.min()
929 print " Le maximum :", OBJET_DE_TEST.max()
930 print "Valeurs globales : attention, on peut les calculer car True=1, False=0, mais cela n'a pas de sens"
931 print " La moyenne :", OBJET_DE_TEST.stepmean()
932 print " L'écart-type :", OBJET_DE_TEST.stepstd()
933 print " La somme :", OBJET_DE_TEST.stepsum()
934 print " Le minimum :", OBJET_DE_TEST.stepmin()
935 print " Le maximum :", OBJET_DE_TEST.stepmax()
936 print " La somme cumulée :", OBJET_DE_TEST.cumsum()
937 print "Taille \"shape\" :", OBJET_DE_TEST.shape()
938 print "Taille \"len\" :", len(OBJET_DE_TEST)
942 print "======> Utilisation directe de la classe Persistence"
943 OBJET_DE_TEST = Persistence("My object", unit="", basetype=int )
944 OBJET_DE_TEST.store( 1 )
945 OBJET_DE_TEST.store( 3 )
946 OBJET_DE_TEST.store( 7 )
947 print "Les pas de stockage :", OBJET_DE_TEST.stepserie()
948 print "Les valeurs :", OBJET_DE_TEST.valueserie()
949 print "La 2ème valeur :", OBJET_DE_TEST.valueserie(1)
950 print "La dernière valeur :", OBJET_DE_TEST.valueserie(-1)
951 print "Taille \"shape\" :", OBJET_DE_TEST.shape()
952 print "Taille \"len\" :", len(OBJET_DE_TEST)
956 print "======> Utilisation des méthodes d'accès de type dictionnaire"
957 OBJET_DE_TEST = OneScalar("My int", unit="cm", basetype=int)
959 OBJET_DE_TEST.store( 7+i )
960 print "Taille \"len\" :", len(OBJET_DE_TEST)
961 print "Les pas de stockage :", OBJET_DE_TEST.keys()
962 print "Les valeurs :", OBJET_DE_TEST.values()
963 print "Les paires :", OBJET_DE_TEST.items()
967 print "======> Persistence composite"
968 OBJET_DE_TEST = CompositePersistence("My CompositePersistence")
969 print "Objets stockables :", OBJET_DE_TEST.get_stored_objects()
970 print "Objets actifs :", OBJET_DE_TEST.get_stored_objects( hideVoidObjects = True )
971 print "--> Stockage d'une valeur de Background"
972 OBJET_DE_TEST.store("Background",numpy.zeros(5))
973 print "Objets actifs :", OBJET_DE_TEST.get_stored_objects( hideVoidObjects = True )
974 print "--> Ajout d'un objet nouveau par defaut, de type vecteur numpy par pas"
975 OBJET_DE_TEST.add_object("ValeursVectorielles")
976 OBJET_DE_TEST.store("ValeursVectorielles",numpy.zeros(5))
977 print "Objets actifs :", OBJET_DE_TEST.get_stored_objects( hideVoidObjects = True )
978 print "--> Ajout d'un objet nouveau de type liste par pas"
979 OBJET_DE_TEST.add_object("ValeursList", persistenceType=OneList )
980 OBJET_DE_TEST.store("ValeursList",range(5))
981 print "Objets actifs :", OBJET_DE_TEST.get_stored_objects( hideVoidObjects = True )
982 print "--> Ajout d'un objet nouveau, de type vecteur string par pas"
983 OBJET_DE_TEST.add_object("ValeursStr", persistenceType=Persistence, basetype=str )
984 OBJET_DE_TEST.store("ValeursStr","c020")
985 OBJET_DE_TEST.store("ValeursStr","c021")
986 print "Les valeurs :", OBJET_DE_TEST.get_object("ValeursStr").valueserie()
987 print "Acces comme dict :", OBJET_DE_TEST["ValeursStr"].stepserie()
988 print "Acces comme dict :", OBJET_DE_TEST["ValeursStr"].valueserie()
989 print "Objets actifs :", OBJET_DE_TEST.get_stored_objects( hideVoidObjects = True )
990 print "--> Suppression d'un objet"
991 OBJET_DE_TEST.del_object("ValeursVectorielles")
992 print "Objets actifs :", OBJET_DE_TEST.get_stored_objects( hideVoidObjects = True )
993 print "--> Enregistrement de l'objet complet de Persistence composite"
994 OBJET_DE_TEST.save_composite("composite.pkl")
997 print "======> Affichage graphique d'objets stockés"
998 OBJET_DE_TEST = Persistence("My object", unit="", basetype=numpy.array)
1000 vect1 = [1, 2, 1, 2, 1]
1001 vect2 = [-3, -3, 0, -3, -3]
1002 vect3 = [-1, 1, -5, 1, -1]
1003 vect4 = 100*[0.29, 0.97, 0.73, 0.01, 0.20]
1004 print "Stockage de 3 vecteurs de longueur identique"
1008 print "Affichage graphique de l'ensemble du stockage sur une même image"
1010 title = "Tous les vecteurs",
1011 filename="vecteurs.ps",
1015 print "Stockage d'un quatrième vecteur de longueur différente"
1017 print "Affichage graphique séparé du dernier stockage"
1021 filename = "vecteur",
1025 print "Les images ont été stockées en fichiers Postscript"
1026 print "Taille \"shape\" du dernier objet stocké",OBJET_DE_TEST.shape()
1027 print "Taille \"len\" du dernier objet stocké",len(OBJET_DE_TEST)
1031 print "======> Affichage graphique dynamique d'objets"
1032 OBJET_DE_TEST = Persistence("My object", unit="", basetype=float)
1036 title = "Valeur suivie",
1041 for i in range(1,11):
1043 print "Taille \"shape\" du dernier objet stocké",OBJET_DE_TEST.shape()
1044 print "Taille \"len\" du dernier objet stocké",len(OBJET_DE_TEST)
1045 print "Nombre d'objets stockés",OBJET_DE_TEST.stepnumber()
1049 print "======> Affectation simple d'observateurs dynamiques"
1050 def obs(var=None,info=None):
1051 print " ---> Mise en oeuvre de l'observer"
1052 print " var =",var.valueserie(-1)
1053 print " info =",info
1054 OBJET_DE_TEST = Persistence("My object", unit="", basetype=list)
1056 D.setDataObserver( HookFunction = obs )
1059 print "Action de 1 observer sur la variable observée, étape :",i
1060 D.store( [i, i, i] )
1064 print "======> Affectation multiple d'observateurs dynamiques"
1065 def obs(var=None,info=None):
1066 print " ---> Mise en oeuvre de l'observer"
1067 print " var =",var.valueserie(-1)
1068 print " info =",info
1069 def obs_bis(var=None,info=None):
1070 print " ---> Mise en oeuvre de l'observer"
1071 print " var =",var.valueserie(-1)
1072 print " info =",info
1073 OBJET_DE_TEST = Persistence("My object", unit="", basetype=list)
1078 HookParameters = "Premier observer",
1082 Scheduler = xrange(1,3),
1083 HookParameters = "Second observer",
1086 HookFunction = obs_bis,
1087 Scheduler = range(1,3)+range(7,9),
1088 HookParameters = "Troisième observer",
1091 print "Action de 3 observers sur la variable observée, étape :",i
1092 D.store( [i, i, i] )
1093 D.removeDataObserver(
1096 for i in range(5,10):
1097 print "Action d'un seul observer sur la variable observée, étape :",i
1098 D.store( [i, i, i] )