]> SALOME platform Git repositories - modules/adao.git/blob - src/daComposant/daCore/Persistence.py
Salome HOME
- Nouvelle version de Jean-Philippe ARGAUD
[modules/adao.git] / src / daComposant / daCore / Persistence.py
1 #-*-coding:iso-8859-1-*-
2 #
3 #  Copyright (C) 2008-2010  EDF R&D
4 #
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.
9 #
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.
14 #
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
18 #
19 #  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #
21 __doc__ = """
22     Définit des outils de persistence et d'enregistrement de séries de valeurs
23     pour analyse ultérieure ou utilisation de calcul.
24 """
25 __author__ = "Jean-Philippe ARGAUD - Mars 2008"
26
27 import numpy
28
29 from PlatformInfo import PathManagement ; PathManagement()
30
31 # ==============================================================================
32 class Persistence:
33     """
34     Classe générale de persistence définissant les accesseurs nécessaires
35     (Template)
36     """
37     def __init__(self, name="", unit="", basetype=str):
38         """
39         name : nom courant
40         unit : unité
41         basetype : type de base de l'objet stocké à chaque pas
42         
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
51         """
52         self.__name = str(name)
53         self.__unit = str(unit)
54         #
55         self.__step     = -1
56         self.__basetype = basetype
57         #
58         self.__steps    = []
59         self.__values   = []
60         #
61         self.__dynamic  = False
62         #
63         self.__dataobservers = []
64     
65     def basetype(self, basetype=None):
66         """
67         Renvoie ou met en place le type de base des objets stockés
68         """
69         if basetype is None:
70             return self.__basetype
71         else:
72             self.__basetype = basetype
73
74     def store(self, value=None, step=None):
75         """
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.
79         """
80         if value is None: raise ValueError("Value argument required")
81         self.__step += 1
82         if step is not None:
83             self.__steps.append(step)
84         else:
85             self.__steps.append(self.__step)
86         #
87         self.__values.append(self.__basetype(value))
88         #
89         if self.__dynamic: self.__replot()
90         for hook, parameters, scheduler in self.__dataobservers:
91             if self.__step in scheduler:
92                 hook( self, parameters )
93
94     def shape(self):
95         """
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.
100         """
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]:
105                 return (1,)
106             elif self.__basetype in [list, dict]:
107                 return (len(self.__values[-1]),)
108             else:
109                 return (1,)
110         else:
111             raise ValueError("Object has no shape before its first storage")
112
113     def __len__(self):
114         """
115         Renvoie le nombre d'éléments dans un séquence ou la plus grande
116         dimension d'une matrice
117         """
118         return max( self.shape() )
119
120     # ---------------------------------------------------------
121     def stepserie(self, item=None, step=None):
122         """
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
126         numéro "item".
127         """
128         if step is not None and step in self.__steps:
129             return step
130         elif item is not None and item < len(self.__steps):
131             return self.__steps[item]
132         else:
133             return self.__steps
134
135     def valueserie(self, item=None, step=None):
136         """
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".
141         """
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]
147         else:
148             return self.__values
149     
150     def stepnumber(self):
151         """
152         Renvoie le nombre de pas de stockage.
153         """
154         return len(self.__steps)
155
156     # ---------------------------------------------------------
157     def mean(self):
158         """
159         Renvoie la valeur moyenne des données à chaque pas. Il faut que le type
160         de base soit compatible avec les types élémentaires numpy.
161         """
162         try:
163             return [numpy.matrix(item).mean() for item in self.__values]
164         except:
165             raise TypeError("Base type is incompatible with numpy")
166
167     def std(self, ddof=0):
168         """
169         Renvoie l'écart-type des données à chaque pas. Il faut que le type de
170         base soit compatible avec les types élémentaires numpy.
171         
172         ddof : c'est le nombre de degrés de liberté pour le calcul de
173                l'écart-type, qui est dans le diviseur. Inutile avant Numpy 1.1
174         """
175         try:
176             if numpy.version.version >= '1.1.0':
177                 return [numpy.matrix(item).std(ddof=ddof) for item in self.__values]
178             else:
179                 return [numpy.matrix(item).std() for item in self.__values]
180         except:
181             raise TypeError("Base type is incompatible with numpy")
182
183     def sum(self):
184         """
185         Renvoie la somme des données à chaque pas. Il faut que le type de
186         base soit compatible avec les types élémentaires numpy.
187         """
188         try:
189             return [numpy.matrix(item).sum() for item in self.__values]
190         except:
191             raise TypeError("Base type is incompatible with numpy")
192
193     def min(self):
194         """
195         Renvoie le minimum des données à chaque pas. Il faut que le type de
196         base soit compatible avec les types élémentaires numpy.
197         """
198         try:
199             return [numpy.matrix(item).min() for item in self.__values]
200         except:
201             raise TypeError("Base type is incompatible with numpy")
202
203     def max(self):
204         """
205         Renvoie le maximum des données à chaque pas. Il faut que le type de
206         base soit compatible avec les types élémentaires numpy.
207         """
208         try:
209             return [numpy.matrix(item).max() for item in self.__values]
210         except:
211             raise TypeError("Base type is incompatible with numpy")
212
213     def __preplot(self,
214             title    = "",
215             xlabel   = "",
216             ylabel   = "",
217             ltitle   = None,
218             geometry = "600x400",
219             persist  = False,
220             pause    = True,
221             ):
222         import os
223         #
224         # Vérification de la disponibilité du module Gnuplot
225         try:
226             import Gnuplot
227             self.__gnuplot = Gnuplot
228         except:
229             raise ImportError("The Gnuplot module is required to plot the object.")
230         #
231         # Vérification et compléments sur les paramètres d'entrée
232         if persist:
233             self.__gnuplot.GnuplotOpts.gnuplot_command = 'gnuplot -persist -geometry '+geometry
234         else:
235             self.__gnuplot.GnuplotOpts.gnuplot_command = 'gnuplot -geometry '+geometry
236         if ltitle is None:
237             ltitle = ""
238         self.__g = self.__gnuplot.Gnuplot() # persist=1
239         self.__g('set terminal '+self.__gnuplot.GnuplotOpts.default_term)
240         self.__g('set style data lines')
241         self.__g('set grid')
242         self.__g('set autoscale')
243         self.__g('set xlabel "'+str(xlabel).encode('ascii','replace')+'"')
244         self.__g('set ylabel "'+str(ylabel).encode('ascii','replace')+'"')
245         self.__title  = title
246         self.__ltitle = ltitle
247         self.__pause  = pause
248
249     def plot(self, item=None, step=None,
250             steps    = None,
251             title    = "",
252             xlabel   = "",
253             ylabel   = "",
254             ltitle   = None,
255             geometry = "600x400",
256             filename = "",
257             dynamic  = False,
258             persist  = False,
259             pause    = True,
260             ):
261         """
262         Renvoie un affichage de la valeur à chaque pas, si elle est compatible
263         avec un affichage Gnuplot (donc essentiellement un vecteur). Si
264         l'argument "step" existe dans la liste des pas de stockage effectués,
265         renvoie l'affichage de la valeur stockée à ce pas "step". Si l'argument
266         "item" est correct, renvoie l'affichage de la valeur stockée au numéro
267         "item". Par défaut ou en l'absence de "step" ou "item", renvoie un
268         affichage successif de tous les pas.
269
270         Arguments :
271             - step     : valeur du pas à afficher
272             - item     : index de la valeur à afficher
273             - steps    : liste unique des pas de l'axe des X, ou None si c'est
274                          la numérotation par défaut
275             - title    : base du titre général, qui sera automatiquement
276                          complétée par la mention du pas
277             - xlabel   : label de l'axe des X
278             - ylabel   : label de l'axe des Y
279             - ltitle   : titre associé au vecteur tracé
280             - geometry : taille en pixels de la fenêtre et position du coin haut
281                          gauche, au format X11 : LxH+X+Y (défaut : 600x400)
282             - filename : base de nom de fichier Postscript pour une sauvegarde,
283                          qui est automatiquement complétée par le numéro du
284                          fichier calculé par incrément simple de compteur
285             - dynamic  : effectue un affichage des valeurs à chaque stockage
286                          (au-delà du second) La méthode "plot" permet de déclarer
287                          l'affichage dynamique, et c'est la méthode "__replot"
288                          qui est utilisée pour l'effectuer
289             - persist  : booléen indiquant que la fenêtre affichée sera
290                          conservée lors du passage au dessin suivant
291                          Par défaut, persist = False
292             - pause    : booléen indiquant une pause après chaque tracé, et
293                          attendant un Return
294                          Par défaut, pause = True
295         """
296         import os
297         if not self.__dynamic:
298             self.__preplot(title, xlabel, ylabel, ltitle, geometry, persist, pause )
299             if dynamic:
300                 self.__dynamic = True
301                 if len(self.__values) == 0: return 0
302         #
303         # Tracé du ou des vecteurs demandés
304         indexes = []
305         if step is not None and step in self.__steps:
306             indexes.append(self.__steps.index(step))
307         elif item is not None and item < len(self.__values):
308             indexes.append(item)
309         else:
310             indexes = indexes + range(len(self.__values))
311         #
312         i = -1
313         for index in indexes:
314             self.__g('set title  "'+str(title).encode('ascii','replace')+' (pas '+str(index)+')"')
315             if ( type(steps) is type([]) ) or ( type(steps) is type(numpy.array([])) ):
316                 Steps = list(steps)
317             else:
318                 Steps = range(len(self.__values[index]))
319             #
320             self.__g.plot( self.__gnuplot.Data( Steps, self.__values[index], title=ltitle ) )
321             #
322             if filename != "":
323                 i += 1
324                 stepfilename = "%s_%03i.ps"%(filename,i)
325                 if os.path.isfile(stepfilename):
326                     raise ValueError("Error: a file with this name \"%s\" already exists."%stepfilename)
327                 self.__g.hardcopy(filename=stepfilename, color=1)
328             if self.__pause:
329                 raw_input('Please press return to continue...\n')
330
331     def __replot(self):
332         """
333         Affichage dans le cas du suivi dynamique de la variable
334         """
335         if self.__dynamic and len(self.__values) < 2: return 0
336         #
337         import os
338         self.__g('set title  "'+str(self.__title).encode('ascii','replace'))
339         Steps = range(len(self.__values))
340         self.__g.plot( self.__gnuplot.Data( Steps, self.__values, title=self.__ltitle ) )
341         #
342         if self.__pause:
343             raw_input('Please press return to continue...\n')
344
345     # ---------------------------------------------------------
346     def stepmean(self):
347         """
348         Renvoie la moyenne sur toutes les valeurs sans tenir compte de la
349         longueur des pas. Il faut que le type de base soit compatible avec
350         les types élémentaires numpy.
351         """
352         try:
353             return numpy.matrix(self.__values).mean()
354         except:
355             raise TypeError("Base type is incompatible with numpy")
356
357     def stepstd(self, ddof=0):
358         """
359         Renvoie l'écart-type de toutes les valeurs sans tenir compte de la
360         longueur des pas. Il faut que le type de base soit compatible avec
361         les types élémentaires numpy.
362         
363         ddof : c'est le nombre de degrés de liberté pour le calcul de
364                l'écart-type, qui est dans le diviseur. Inutile avant Numpy 1.1
365         """
366         try:
367             if numpy.version.version >= '1.1.0':
368                 return numpy.matrix(self.__values).std(ddof=ddof)
369             else:
370                 return numpy.matrix(self.__values).std()
371         except:
372             raise TypeError("Base type is incompatible with numpy")
373
374     def stepsum(self):
375         """
376         Renvoie la somme de 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.
379         """
380         try:
381             return numpy.matrix(self.__values).sum()
382         except:
383             raise TypeError("Base type is incompatible with numpy")
384
385     def stepmin(self):
386         """
387         Renvoie le minimum 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.
390         """
391         try:
392             return numpy.matrix(self.__values).min()
393         except:
394             raise TypeError("Base type is incompatible with numpy")
395
396     def stepmax(self):
397         """
398         Renvoie le maximum de toutes les valeurs sans tenir compte de la
399         longueur des pas. Il faut que le type de base soit compatible avec
400         les types élémentaires numpy.
401         """
402         try:
403             return numpy.matrix(self.__values).max()
404         except:
405             raise TypeError("Base type is incompatible with numpy")
406
407     def cumsum(self):
408         """
409         Renvoie la somme cumulée de toutes les valeurs sans tenir compte de la
410         longueur des pas. Il faut que le type de base soit compatible avec
411         les types élémentaires numpy.
412         """
413         try:
414             return numpy.matrix(self.__values).cumsum(axis=0)
415         except:
416             raise TypeError("Base type is incompatible with numpy")
417
418     # On pourrait aussi utiliser les autres attributs d'une "matrix", comme
419     # "tofile", "min"...
420
421     def stepplot(self,
422             steps    = None,
423             title    = "",
424             xlabel   = "",
425             ylabel   = "",
426             ltitle   = None,
427             geometry = "600x400",
428             filename = "",
429             persist  = False,
430             pause    = True,
431             ):
432         """
433         Renvoie un affichage unique pour l'ensemble des valeurs à chaque pas, si
434         elles sont compatibles avec un affichage Gnuplot (donc essentiellement
435         un vecteur). Si l'argument "step" existe dans la liste des pas de
436         stockage effectués, renvoie l'affichage de la valeur stockée à ce pas
437         "step". Si l'argument "item" est correct, renvoie l'affichage de la
438         valeur stockée au numéro "item".
439
440         Arguments :
441             - steps    : liste unique des pas de l'axe des X, ou None si c'est
442                          la numérotation par défaut
443             - title    : base du titre général, qui sera automatiquement
444                          complétée par la mention du pas
445             - xlabel   : label de l'axe des X
446             - ylabel   : label de l'axe des Y
447             - ltitle   : titre associé au vecteur tracé
448             - geometry : taille en pixels de la fenêtre et position du coin haut
449                          gauche, au format X11 : LxH+X+Y (défaut : 600x400)
450             - filename : nom de fichier Postscript pour une sauvegarde
451             - persist  : booléen indiquant que la fenêtre affichée sera
452                          conservée lors du passage au dessin suivant
453                          Par défaut, persist = False
454             - pause    : booléen indiquant une pause après chaque tracé, et
455                          attendant un Return
456                          Par défaut, pause = True
457         """
458         import os
459         #
460         # Vérification de la disponibilité du module Gnuplot
461         try:
462             import Gnuplot
463             self.__gnuplot = Gnuplot
464         except:
465             raise ImportError("The Gnuplot module is required to plot the object.")
466         #
467         # Vérification et compléments sur les paramètres d'entrée
468         if persist:
469             self.__gnuplot.GnuplotOpts.gnuplot_command = 'gnuplot -persist -geometry '+geometry
470         else:
471             self.__gnuplot.GnuplotOpts.gnuplot_command = 'gnuplot -geometry '+geometry
472         if ltitle is None:
473             ltitle = ""
474         if ( type(steps) is type([]) ) or ( type(steps) is type(numpy.array([])) ):
475             Steps = list(steps)
476         else:
477             Steps = range(len(self.__values[0]))
478         self.__g = self.__gnuplot.Gnuplot() # persist=1
479         self.__g('set terminal '+self.__gnuplot.GnuplotOpts.default_term)
480         self.__g('set style data lines')
481         self.__g('set grid')
482         self.__g('set autoscale')
483         self.__g('set title  "'+str(title).encode('ascii','replace') +'"')
484         self.__g('set xlabel "'+str(xlabel).encode('ascii','replace')+'"')
485         self.__g('set ylabel "'+str(ylabel).encode('ascii','replace')+'"')
486         #
487         # Tracé du ou des vecteurs demandés
488         indexes = range(len(self.__values))
489         self.__g.plot( self.__gnuplot.Data( Steps, self.__values[indexes.pop(0)], title=ltitle+" (pas 0)" ) )
490         for index in indexes:
491             self.__g.replot( self.__gnuplot.Data( Steps, self.__values[index], title=ltitle+" (pas %i)"%index ) )
492         #
493         if filename != "":
494             self.__g.hardcopy(filename=filename, color=1)
495         if pause:
496             raw_input('Please press return to continue...\n')
497
498     # ---------------------------------------------------------
499     def setDataObserver(self,
500         HookFunction   = None,
501         HookParameters = None,
502         Scheduler      = None,
503         ):
504         """
505         Méthode d'association à la variable d'un triplet définissant un observer
506         
507         Le Scheduler attendu est une fréquence, une simple liste d'index ou un
508         xrange des index.
509         """
510         #
511         # Vérification du Scheduler
512         # -------------------------
513         maxiter = int( 1e9 )
514         if type(Scheduler) is int:    # Considéré comme une fréquence à partir de 0
515             Schedulers = xrange( 0, maxiter, int(Scheduler) )
516         elif type(Scheduler) is xrange: # Considéré comme un itérateur
517             Schedulers = Scheduler
518         elif type(Scheduler) is list: # Considéré comme des index explicites
519             Schedulers = map( long, Scheduler )
520         else:                         # Dans tous les autres cas, activé par défaut
521             Schedulers = xrange( 0, maxiter )
522         #
523         # Stockage interne de l'observer dans la variable
524         # -----------------------------------------------
525         self.__dataobservers.append( [HookFunction, HookParameters, Schedulers] )
526
527 # ==============================================================================
528 class OneScalar(Persistence):
529     """
530     Classe définissant le stockage d'une valeur unique réelle (float) par pas
531     
532     Le type de base peut être changé par la méthode "basetype", mais il faut que
533     le nouveau type de base soit compatible avec les types par éléments de 
534     numpy. On peut même utiliser cette classe pour stocker des vecteurs/listes
535     ou des matrices comme dans les classes suivantes, mais c'est déconseillé
536     pour conserver une signification claire des noms.
537     """
538     def __init__(self, name="", unit="", basetype = float):
539         Persistence.__init__(self, name, unit, basetype)
540
541 class OneVector(Persistence):
542     """
543     Classe définissant le stockage d'une liste (list) de valeurs homogènes par
544     hypothèse par pas. Pour éviter les confusions, ne pas utiliser la classe
545     "OneVector" pour des données hétérogènes, mais bien "OneList".
546     """
547     def __init__(self, name="", unit="", basetype = list):
548         Persistence.__init__(self, name, unit, basetype)
549
550 class OneMatrix(Persistence):
551     """
552     Classe définissant le stockage d'une matrice de valeurs (numpy.matrix) par
553     pas
554     """
555     def __init__(self, name="", unit="", basetype = numpy.matrix):
556         Persistence.__init__(self, name, unit, basetype)
557
558 class OneList(Persistence):
559     """
560     Classe définissant le stockage d'une liste de valeurs potentiellement
561     hétérogènes (list) par pas. Pour éviter les confusions, ne pas utiliser la
562     classe "OneVector" pour des données hétérogènes, mais bien "OneList".
563     """
564     def __init__(self, name="", unit="", basetype = list):
565         Persistence.__init__(self, name, unit, basetype)
566
567 # ==============================================================================
568 if __name__ == "__main__":
569     print '\n AUTODIAGNOSTIC \n'
570
571     print "======> Un flottant"
572     OBJET_DE_TEST = OneScalar("My float", unit="cm")
573     OBJET_DE_TEST.store( 5.)
574     OBJET_DE_TEST.store(-5.)
575     OBJET_DE_TEST.store( 1.)
576     print "Les pas de stockage :", OBJET_DE_TEST.stepserie()
577     print "Les valeurs         :", OBJET_DE_TEST.valueserie()
578     print "La 2ème valeur      :", OBJET_DE_TEST.valueserie(1)
579     print "La dernière valeur  :", OBJET_DE_TEST.valueserie(-1)
580     print "Valeurs par pas :"
581     print "  La moyenne        :", OBJET_DE_TEST.mean()
582     print "  L'écart-type      :", OBJET_DE_TEST.std()
583     print "  La somme          :", OBJET_DE_TEST.sum()
584     print "  Le minimum        :", OBJET_DE_TEST.min()
585     print "  Le maximum        :", OBJET_DE_TEST.max()
586     print "Valeurs globales :"
587     print "  La moyenne        :", OBJET_DE_TEST.stepmean()
588     print "  L'écart-type      :", OBJET_DE_TEST.stepstd()
589     print "  La somme          :", OBJET_DE_TEST.stepsum()
590     print "  Le minimum        :", OBJET_DE_TEST.stepmin()
591     print "  Le maximum        :", OBJET_DE_TEST.stepmax()
592     print "  La somme cumulée  :", OBJET_DE_TEST.cumsum()
593     print "Taille \"shape\"      :", OBJET_DE_TEST.shape()
594     print "Taille \"len\"        :", len(OBJET_DE_TEST)
595     del OBJET_DE_TEST
596     print
597
598     print "======> Un entier"
599     OBJET_DE_TEST = OneScalar("My int", unit="cm", basetype=int)
600     OBJET_DE_TEST.store( 5 )
601     OBJET_DE_TEST.store(-5 )
602     OBJET_DE_TEST.store( 1.)
603     print "Les pas de stockage :", OBJET_DE_TEST.stepserie()
604     print "Les valeurs         :", OBJET_DE_TEST.valueserie()
605     print "La 2ème valeur      :", OBJET_DE_TEST.valueserie(1)
606     print "La dernière valeur  :", OBJET_DE_TEST.valueserie(-1)
607     print "Valeurs par pas :"
608     print "  La moyenne        :", OBJET_DE_TEST.mean()
609     print "  L'écart-type      :", OBJET_DE_TEST.std()
610     print "  La somme          :", OBJET_DE_TEST.sum()
611     print "  Le minimum        :", OBJET_DE_TEST.min()
612     print "  Le maximum        :", OBJET_DE_TEST.max()
613     print "Valeurs globales :"
614     print "  La moyenne        :", OBJET_DE_TEST.stepmean()
615     print "  L'écart-type      :", OBJET_DE_TEST.stepstd()
616     print "  La somme          :", OBJET_DE_TEST.stepsum()
617     print "  Le minimum        :", OBJET_DE_TEST.stepmin()
618     print "  Le maximum        :", OBJET_DE_TEST.stepmax()
619     print "  La somme cumulée  :", OBJET_DE_TEST.cumsum()
620     print "Taille \"shape\"      :", OBJET_DE_TEST.shape()
621     print "Taille \"len\"        :", len(OBJET_DE_TEST)
622     del OBJET_DE_TEST
623     print
624
625     print "======> Un booléen"
626     OBJET_DE_TEST = OneScalar("My bool", unit="", basetype=bool)
627     OBJET_DE_TEST.store( True  )
628     OBJET_DE_TEST.store( False )
629     OBJET_DE_TEST.store( True  )
630     print "Les pas de stockage :", OBJET_DE_TEST.stepserie()
631     print "Les valeurs         :", OBJET_DE_TEST.valueserie()
632     print "La 2ème valeur      :", OBJET_DE_TEST.valueserie(1)
633     print "La dernière valeur  :", OBJET_DE_TEST.valueserie(-1)
634     print "Taille \"shape\"      :", OBJET_DE_TEST.shape()
635     print "Taille \"len\"        :", len(OBJET_DE_TEST)
636     del OBJET_DE_TEST
637     print
638
639     print "======> Un vecteur de flottants"
640     OBJET_DE_TEST = OneVector("My float vector", unit="cm")
641     OBJET_DE_TEST.store( (5 , -5) )
642     OBJET_DE_TEST.store( (-5, 5 ) )
643     OBJET_DE_TEST.store( (1., 1.) )
644     print "Les pas de stockage :", OBJET_DE_TEST.stepserie()
645     print "Les valeurs         :", OBJET_DE_TEST.valueserie()
646     print "La 2ème valeur      :", OBJET_DE_TEST.valueserie(1)
647     print "La dernière valeur  :", OBJET_DE_TEST.valueserie(-1)
648     print "Valeurs par pas :"
649     print "  La moyenne        :", OBJET_DE_TEST.mean()
650     print "  L'écart-type      :", OBJET_DE_TEST.std()
651     print "  La somme          :", OBJET_DE_TEST.sum()
652     print "  Le minimum        :", OBJET_DE_TEST.min()
653     print "  Le maximum        :", OBJET_DE_TEST.max()
654     print "Valeurs globales :"
655     print "  La moyenne        :", OBJET_DE_TEST.stepmean()
656     print "  L'écart-type      :", OBJET_DE_TEST.stepstd()
657     print "  La somme          :", OBJET_DE_TEST.stepsum()
658     print "  Le minimum        :", OBJET_DE_TEST.stepmin()
659     print "  Le maximum        :", OBJET_DE_TEST.stepmax()
660     print "  La somme cumulée  :", OBJET_DE_TEST.cumsum()
661     print "Taille \"shape\"      :", OBJET_DE_TEST.shape()
662     print "Taille \"len\"        :", len(OBJET_DE_TEST)
663     del OBJET_DE_TEST
664     print
665
666     print "======> Une liste hétérogène"
667     OBJET_DE_TEST = OneList("My list", unit="bool/cm")
668     OBJET_DE_TEST.store( (True , -5) )
669     OBJET_DE_TEST.store( (False,  5 ) )
670     OBJET_DE_TEST.store( (True ,  1.) )
671     print "Les pas de stockage :", OBJET_DE_TEST.stepserie()
672     print "Les valeurs         :", OBJET_DE_TEST.valueserie()
673     print "La 2ème valeur      :", OBJET_DE_TEST.valueserie(1)
674     print "La dernière valeur  :", OBJET_DE_TEST.valueserie(-1)
675     print "Valeurs par pas : attention, on peut les calculer car True=1, False=0, mais cela n'a pas de sens"
676     print "  La moyenne        :", OBJET_DE_TEST.mean()
677     print "  L'écart-type      :", OBJET_DE_TEST.std()
678     print "  La somme          :", OBJET_DE_TEST.sum()
679     print "  Le minimum        :", OBJET_DE_TEST.min()
680     print "  Le maximum        :", OBJET_DE_TEST.max()
681     print "Valeurs globales : attention, on peut les calculer car True=1, False=0, mais cela n'a pas de sens"
682     print "  La moyenne        :", OBJET_DE_TEST.stepmean()
683     print "  L'écart-type      :", OBJET_DE_TEST.stepstd()
684     print "  La somme          :", OBJET_DE_TEST.stepsum()
685     print "  Le minimum        :", OBJET_DE_TEST.stepmin()
686     print "  Le maximum        :", OBJET_DE_TEST.stepmax()
687     print "  La somme cumulée  :", OBJET_DE_TEST.cumsum()
688     print "Taille \"shape\"      :", OBJET_DE_TEST.shape()
689     print "Taille \"len\"        :", len(OBJET_DE_TEST)
690     del OBJET_DE_TEST
691     print
692
693     print "======> Utilisation directe de la classe Persistence"
694     OBJET_DE_TEST = Persistence("My object", unit="", basetype=int )
695     OBJET_DE_TEST.store( 1  )
696     OBJET_DE_TEST.store( 3 )
697     OBJET_DE_TEST.store( 7  )
698     print "Les pas de stockage :", OBJET_DE_TEST.stepserie()
699     print "Les valeurs         :", OBJET_DE_TEST.valueserie()
700     print "La 2ème valeur      :", OBJET_DE_TEST.valueserie(1)
701     print "La dernière valeur  :", OBJET_DE_TEST.valueserie(-1)
702     print "Taille \"shape\"      :", OBJET_DE_TEST.shape()
703     print "Taille \"len\"        :", len(OBJET_DE_TEST)
704     del OBJET_DE_TEST
705     print
706
707     print "======> Affichage d'objets stockés"
708     OBJET_DE_TEST = Persistence("My object", unit="", basetype=numpy.array)
709     D = OBJET_DE_TEST
710     vect1 = [1, 2, 1, 2, 1]
711     vect2 = [-3, -3, 0, -3, -3]
712     vect3 = [-1, 1, -5, 1, -1]
713     vect4 = 100*[0.29, 0.97, 0.73, 0.01, 0.20]
714     print "Stockage de 3 vecteurs de longueur identique"
715     D.store(vect1)
716     D.store(vect2)
717     D.store(vect3)
718     print "Affichage de l'ensemble du stockage sur une même image"
719     D.stepplot(
720         title = "Tous les vecteurs",
721         filename="vecteurs.ps",
722         xlabel = "Axe X",
723         ylabel = "Axe Y",
724         pause = False )
725     print "Stockage d'un quatrième vecteur de longueur différente"
726     D.store(vect4)
727     print "Affichage séparé du dernier stockage"
728     D.plot(
729         item  = 3,
730         title = "Vecteurs",
731         filename = "vecteur",
732         xlabel = "Axe X",
733         ylabel = "Axe Y",
734         pause = False )
735     print "Les images ont été stockées en fichiers Postscript"
736     print "Taille \"shape\" du dernier objet stocké",OBJET_DE_TEST.shape()
737     print "Taille \"len\" du dernier objet stocké",len(OBJET_DE_TEST)
738     del OBJET_DE_TEST
739     print
740
741     print "======> Affichage dynamique d'objets"
742     OBJET_DE_TEST = Persistence("My object", unit="", basetype=float)
743     D = OBJET_DE_TEST
744     D.plot(
745         dynamic = True,
746         title   = "Valeur suivie",
747         xlabel  = "Pas",
748         ylabel  = "Valeur",
749         pause   = False,
750         )
751     for i in range(1,11):
752         D.store( i*i )
753     print "Taille \"shape\" du dernier objet stocké",OBJET_DE_TEST.shape()
754     print "Taille \"len\" du dernier objet stocké",len(OBJET_DE_TEST)
755     print "Nombre d'objets stockés",OBJET_DE_TEST.stepnumber()
756     del OBJET_DE_TEST
757     print
758
759     print "======> Affectation simple d'observateurs dynamiques"
760     def obs(var=None,info=None):
761         print "  ---> Mise en oeuvre de l'observer"
762         print "       var  =",var.valueserie(-1)
763         print "       info =",info
764     OBJET_DE_TEST = Persistence("My object", unit="", basetype=list)
765     D = OBJET_DE_TEST
766     D.setDataObserver( HookFunction = obs )
767     for i in range(5):
768         # print
769         print "Action de 1 observer sur la variable observée, étape :",i
770         D.store( [i, i, i] )
771     del OBJET_DE_TEST
772     print
773
774     print "======> Affectation multiple d'observateurs dynamiques"
775     def obs(var=None,info=None):
776         print "  ---> Mise en oeuvre de l'observer"
777         print "       var  =",var.valueserie(-1)
778         print "       info =",info
779     OBJET_DE_TEST = Persistence("My object", unit="", basetype=list)
780     D = OBJET_DE_TEST
781     D.setDataObserver(
782         HookFunction   = obs,
783         Scheduler      = [2, 4],
784         HookParameters = "Second observer",
785         )
786     D.setDataObserver(
787         HookFunction   = obs,
788         Scheduler      = xrange(1,3),
789         HookParameters = "Troisième observer",
790         )
791     for i in range(5):
792         # print
793         print "Action de 2 observers sur la variable observée, étape :",i
794         D.store( [i, i, i] )
795     del OBJET_DE_TEST
796     print