1 #-*-coding:iso-8859-1-*-
3 # Copyright (C) 2008-2015 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
21 # Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
24 Définit des outils de persistence et d'enregistrement de séries de valeurs
25 pour analyse ultérieure ou utilisation de calcul.
27 __author__ = "Jean-Philippe ARGAUD"
32 from PlatformInfo import PathManagement ; PathManagement()
34 # ==============================================================================
37 Classe générale de persistence définissant les accesseurs nécessaires
40 def __init__(self, name="", unit="", basetype=str):
44 basetype : type de base de l'objet stocké à chaque pas
46 La gestion interne des données est exclusivement basée sur les variables
47 initialisées ici (qui ne sont pas accessibles depuis l'extérieur des
48 objets comme des attributs) :
49 __basetype : le type de base de chaque valeur, sous la forme d'un type
50 permettant l'instanciation ou le casting Python
51 __values : les valeurs de stockage. Par défaut, c'est None
53 self.__name = str(name)
54 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, **kwargs):
76 Stocke une valeur avec ses informations de filtrage.
78 if value is None: raise ValueError("Value argument required")
80 self.__values.append(copy.copy(self.__basetype(value)))
81 self.__tags.append(kwargs)
83 if self.__dynamic: self.__replots()
84 __step = len(self.__values) - 1
85 for hook, parameters, scheduler in self.__dataobservers:
86 if __step in scheduler:
87 hook( self, parameters )
89 def pop(self, item=None):
91 Retire une valeur enregistree par son index de stockage. Sans argument,
92 retire le dernier objet enregistre.
96 self.__values.pop(__index)
97 self.__tags.pop(__index)
104 Renvoie la taille sous forme numpy du dernier objet stocké. Si c'est un
105 objet numpy, renvoie le shape. Si c'est un entier, un flottant, un
106 complexe, renvoie 1. Si c'est une liste ou un dictionnaire, renvoie la
107 longueur. Par défaut, renvoie 1.
109 if len(self.__values) > 0:
110 if self.__basetype in [numpy.matrix, numpy.array, numpy.ravel]:
111 return self.__values[-1].shape
112 elif self.__basetype in [int, float]:
114 elif self.__basetype in [list, dict]:
115 return (len(self.__values[-1]),)
119 raise ValueError("Object has no shape before its first storage")
121 # ---------------------------------------------------------
123 msg = " Index Value Tags\n"
124 for i,v in enumerate(self.__values):
125 msg += " i=%05i %10s %s\n"%(i,v,self.__tags[i])
129 return len(self.__values)
131 def __getitem__(self, index=None ):
132 return copy.copy(self.__values[index])
134 def count(self, value):
135 return self.__values.count(value)
137 def index(self, value, start=0, stop=None):
138 if stop is None : stop = len(self.__values)
139 return self.__values.index(value, start, stop)
141 # ---------------------------------------------------------
142 def __filteredIndexes(self, **kwargs):
143 __indexOfFilteredItems = range(len(self.__tags))
144 __filteringKwTags = kwargs.keys()
145 if len(__filteringKwTags) > 0:
146 for tagKey in __filteringKwTags:
148 for i in __indexOfFilteredItems:
149 if self.__tags[i].has_key(tagKey):
150 if self.__tags[i][tagKey] == kwargs[tagKey]:
152 elif isinstance(kwargs[tagKey],(list,tuple)) and self.__tags[i][tagKey] in kwargs[tagKey]:
154 __indexOfFilteredItems = __tmp
155 if len(__indexOfFilteredItems) == 0: break
156 return __indexOfFilteredItems
158 # ---------------------------------------------------------
159 def values(self, **kwargs):
160 __indexOfFilteredItems = self.__filteredIndexes(**kwargs)
161 return [self.__values[i] for i in __indexOfFilteredItems]
163 def keys(self, keyword=None , **kwargs):
164 __indexOfFilteredItems = self.__filteredIndexes(**kwargs)
166 for i in __indexOfFilteredItems:
167 if self.__tags[i].has_key( keyword ):
168 __keys.append( self.__tags[i][keyword] )
170 __keys.append( None )
173 def items(self, keyword=None , **kwargs):
174 __indexOfFilteredItems = self.__filteredIndexes(**kwargs)
176 for i in __indexOfFilteredItems:
177 if self.__tags[i].has_key( keyword ):
178 __pairs.append( [self.__tags[i][keyword], self.__values[i]] )
180 __pairs.append( [None, self.__values[i]] )
185 for dicotags in self.__tags:
186 __allKeys.extend( dicotags.keys() )
187 __allKeys = list(set(__allKeys))
191 # def valueserie(self, item=None, allSteps=True, **kwargs):
192 # if item is not None:
193 # return self.__values[item]
195 # __indexOfFilteredItems = self.__filteredIndexes(**kwargs)
196 # if not allSteps and len(__indexOfFilteredItems) > 0:
197 # return self.__values[__indexOfFilteredItems[0]]
199 # return [self.__values[i] for i in __indexOfFilteredItems]
201 def tagserie(self, item=None, withValues=False, outputTag=None, **kwargs):
203 __indexOfFilteredItems = self.__filteredIndexes(**kwargs)
205 __indexOfFilteredItems = [item,]
207 # Dans le cas où la sortie donne les valeurs d'un "outputTag"
208 if outputTag is not None and type(outputTag) is str :
210 for index in __indexOfFilteredItems:
211 if outputTag in self.__tags[index].keys():
212 outputValues.append( self.__tags[index][outputTag] )
213 outputValues = list(set(outputValues))
217 # Dans le cas où la sortie donne les tags satisfaisants aux conditions
220 return [self.__tags[index] for index in __indexOfFilteredItems]
223 for index in __indexOfFilteredItems:
224 allTags.update( self.__tags[index] )
225 allKeys = allTags.keys()
229 # ---------------------------------------------------------
231 def stepnumber(self):
232 return len(self.__values)
235 def stepserie(self, **kwargs):
236 __indexOfFilteredItems = self.__filteredIndexes(**kwargs)
237 return __indexOfFilteredItems
239 # ---------------------------------------------------------
242 Renvoie la série, contenant à chaque pas, la valeur moyenne des données
243 au pas. Il faut que le type de base soit compatible avec les types
247 return [numpy.matrix(item).mean() for item in self.__values]
249 raise TypeError("Base type is incompatible with numpy")
251 def stds(self, ddof=0):
253 Renvoie la série, contenant à chaque pas, l'écart-type des données
254 au pas. Il faut que le type de base soit compatible avec les types
257 ddof : c'est le nombre de degrés de liberté pour le calcul de
258 l'écart-type, qui est dans le diviseur. Inutile avant Numpy 1.1
261 if numpy.version.version >= '1.1.0':
262 return [numpy.matrix(item).std(ddof=ddof) for item in self.__values]
264 return [numpy.matrix(item).std() for item in self.__values]
266 raise TypeError("Base type is incompatible with numpy")
270 Renvoie la série, contenant à chaque pas, la somme des données au pas.
271 Il faut que le type de base soit compatible avec les types élémentaires
275 return [numpy.matrix(item).sum() for item in self.__values]
277 raise TypeError("Base type is incompatible with numpy")
281 Renvoie la série, contenant à chaque pas, le minimum des données au pas.
282 Il faut que le type de base soit compatible avec les types élémentaires
286 return [numpy.matrix(item).min() for item in self.__values]
288 raise TypeError("Base type is incompatible with numpy")
292 Renvoie la série, contenant à chaque pas, la maximum des données au pas.
293 Il faut que le type de base soit compatible avec les types élémentaires
297 return [numpy.matrix(item).max() for item in self.__values]
299 raise TypeError("Base type is incompatible with numpy")
306 geometry = "600x400",
311 # Vérification de la disponibilité du module Gnuplot
314 self.__gnuplot = Gnuplot
316 raise ImportError("The Gnuplot module is required to plot the object.")
318 # Vérification et compléments sur les paramètres d'entrée
320 self.__gnuplot.GnuplotOpts.gnuplot_command = 'gnuplot -persist -geometry '+geometry
322 self.__gnuplot.GnuplotOpts.gnuplot_command = 'gnuplot -geometry '+geometry
325 self.__g = self.__gnuplot.Gnuplot() # persist=1
326 self.__g('set terminal '+self.__gnuplot.GnuplotOpts.default_term)
327 self.__g('set style data lines')
329 self.__g('set autoscale')
330 self.__g('set xlabel "'+str(xlabel).encode('ascii','replace')+'"')
331 self.__g('set ylabel "'+str(ylabel).encode('ascii','replace')+'"')
333 self.__ltitle = ltitle
336 def plots(self, item=None, step=None,
342 geometry = "600x400",
349 Renvoie un affichage de la valeur à chaque pas, si elle est compatible
350 avec un affichage Gnuplot (donc essentiellement un vecteur). Si
351 l'argument "step" existe dans la liste des pas de stockage effectués,
352 renvoie l'affichage de la valeur stockée à ce pas "step". Si l'argument
353 "item" est correct, renvoie l'affichage de la valeur stockée au numéro
354 "item". Par défaut ou en l'absence de "step" ou "item", renvoie un
355 affichage successif de tous les pas.
358 - step : valeur du pas à afficher
359 - item : index de la valeur à afficher
360 - steps : liste unique des pas de l'axe des X, ou None si c'est
361 la numérotation par défaut
362 - title : base du titre général, qui sera automatiquement
363 complétée par la mention du pas
364 - xlabel : label de l'axe des X
365 - ylabel : label de l'axe des Y
366 - ltitle : titre associé au vecteur tracé
367 - geometry : taille en pixels de la fenêtre et position du coin haut
368 gauche, au format X11 : LxH+X+Y (défaut : 600x400)
369 - filename : base de nom de fichier Postscript pour une sauvegarde,
370 qui est automatiquement complétée par le numéro du
371 fichier calculé par incrément simple de compteur
372 - dynamic : effectue un affichage des valeurs à chaque stockage
373 (au-delà du second). La méthode "plots" permet de
374 déclarer l'affichage dynamique, et c'est la méthode
375 "__replots" qui est utilisée pour l'effectuer
376 - persist : booléen indiquant que la fenêtre affichée sera
377 conservée lors du passage au dessin suivant
378 Par défaut, persist = False
379 - pause : booléen indiquant une pause après chaque tracé, et
381 Par défaut, pause = True
384 if not self.__dynamic:
385 self.__preplots(title, xlabel, ylabel, ltitle, geometry, persist, pause )
387 self.__dynamic = True
388 if len(self.__values) == 0: return 0
390 # Tracé du ou des vecteurs demandés
392 if step is not None and step < len(self.__values):
394 elif item is not None and item < len(self.__values):
397 indexes = indexes + range(len(self.__values))
400 for index in indexes:
401 self.__g('set title "'+str(title).encode('ascii','replace')+' (pas '+str(index)+')"')
402 if ( type(steps) is list ) or ( type(steps) is type(numpy.array([])) ):
405 Steps = range(len(self.__values[index]))
407 self.__g.plot( self.__gnuplot.Data( Steps, self.__values[index], title=ltitle ) )
411 stepfilename = "%s_%03i.ps"%(filename,i)
412 if os.path.isfile(stepfilename):
413 raise ValueError("Error: a file with this name \"%s\" already exists."%stepfilename)
414 self.__g.hardcopy(filename=stepfilename, color=1)
416 raw_input('Please press return to continue...\n')
420 Affichage dans le cas du suivi dynamique de la variable
422 if self.__dynamic and len(self.__values) < 2: return 0
424 self.__g('set title "'+str(self.__title).encode('ascii','replace'))
425 Steps = range(len(self.__values))
426 self.__g.plot( self.__gnuplot.Data( Steps, self.__values, title=self.__ltitle ) )
429 raw_input('Please press return to continue...\n')
431 # ---------------------------------------------------------
434 Renvoie la moyenne sur toutes les valeurs sans tenir compte de la
435 longueur des pas. Il faut que le type de base soit compatible avec
436 les types élémentaires numpy.
439 if self.__basetype in [int, float]:
440 return float( numpy.array(self.__values).mean() )
442 return numpy.array(self.__values).mean(axis=0)
444 raise TypeError("Base type is incompatible with numpy")
446 def std(self, ddof=0):
448 Renvoie l'écart-type de toutes les valeurs sans tenir compte de la
449 longueur des pas. Il faut que le type de base soit compatible avec
450 les types élémentaires numpy.
452 ddof : c'est le nombre de degrés de liberté pour le calcul de
453 l'écart-type, qui est dans le diviseur. Inutile avant Numpy 1.1
456 if numpy.version.version >= '1.1.0':
457 return numpy.array(self.__values).std(ddof=ddof,axis=0)
459 return numpy.array(self.__values).std(axis=0)
461 raise TypeError("Base type is incompatible with numpy")
465 Renvoie la somme de toutes les valeurs sans tenir compte de la
466 longueur des pas. Il faut que le type de base soit compatible avec
467 les types élémentaires numpy.
470 return numpy.array(self.__values).sum(axis=0)
472 raise TypeError("Base type is incompatible with numpy")
476 Renvoie le minimum de toutes les valeurs sans tenir compte de la
477 longueur des pas. Il faut que le type de base soit compatible avec
478 les types élémentaires numpy.
481 return numpy.array(self.__values).min(axis=0)
483 raise TypeError("Base type is incompatible with numpy")
487 Renvoie le maximum de toutes les valeurs sans tenir compte de la
488 longueur des pas. Il faut que le type de base soit compatible avec
489 les types élémentaires numpy.
492 return numpy.array(self.__values).max(axis=0)
494 raise TypeError("Base type is incompatible with numpy")
498 Renvoie la somme cumulée de toutes les valeurs sans tenir compte de la
499 longueur des pas. Il faut que le type de base soit compatible avec
500 les types élémentaires numpy.
503 return numpy.array(self.__values).cumsum(axis=0)
505 raise TypeError("Base type is incompatible with numpy")
507 # On pourrait aussi utiliser les autres attributs d'une "matrix", comme
516 geometry = "600x400",
522 Renvoie un affichage unique pour l'ensemble des valeurs à chaque pas, si
523 elles sont compatibles avec un affichage Gnuplot (donc essentiellement
524 un vecteur). Si l'argument "step" existe dans la liste des pas de
525 stockage effectués, renvoie l'affichage de la valeur stockée à ce pas
526 "step". Si l'argument "item" est correct, renvoie l'affichage de la
527 valeur stockée au numéro "item".
530 - steps : liste unique des pas de l'axe des X, ou None si c'est
531 la numérotation par défaut
532 - title : base du titre général, qui sera automatiquement
533 complétée par la mention du pas
534 - xlabel : label de l'axe des X
535 - ylabel : label de l'axe des Y
536 - ltitle : titre associé au vecteur tracé
537 - geometry : taille en pixels de la fenêtre et position du coin haut
538 gauche, au format X11 : LxH+X+Y (défaut : 600x400)
539 - filename : nom de fichier Postscript pour une sauvegarde
540 - persist : booléen indiquant que la fenêtre affichée sera
541 conservée lors du passage au dessin suivant
542 Par défaut, persist = False
543 - pause : booléen indiquant une pause après chaque tracé, et
545 Par défaut, pause = True
548 # Vérification de la disponibilité du module Gnuplot
551 self.__gnuplot = Gnuplot
553 raise ImportError("The Gnuplot module is required to plot the object.")
555 # Vérification et compléments sur les paramètres d'entrée
557 self.__gnuplot.GnuplotOpts.gnuplot_command = 'gnuplot -persist -geometry '+geometry
559 self.__gnuplot.GnuplotOpts.gnuplot_command = 'gnuplot -geometry '+geometry
562 if ( type(steps) is list ) or ( type(steps) is type(numpy.array([])) ):
565 Steps = range(len(self.__values[0]))
566 self.__g = self.__gnuplot.Gnuplot() # persist=1
567 self.__g('set terminal '+self.__gnuplot.GnuplotOpts.default_term)
568 self.__g('set style data lines')
570 self.__g('set autoscale')
571 self.__g('set title "'+str(title).encode('ascii','replace') +'"')
572 self.__g('set xlabel "'+str(xlabel).encode('ascii','replace')+'"')
573 self.__g('set ylabel "'+str(ylabel).encode('ascii','replace')+'"')
575 # Tracé du ou des vecteurs demandés
576 indexes = range(len(self.__values))
577 self.__g.plot( self.__gnuplot.Data( Steps, self.__values[indexes.pop(0)], title=ltitle+" (pas 0)" ) )
578 for index in indexes:
579 self.__g.replot( self.__gnuplot.Data( Steps, self.__values[index], title=ltitle+" (pas %i)"%index ) )
582 self.__g.hardcopy(filename=filename, color=1)
584 raw_input('Please press return to continue...\n')
586 # ---------------------------------------------------------
587 def setDataObserver(self,
589 HookParameters = None,
593 Association à la variable d'un triplet définissant un observer
595 Le Scheduler attendu est une fréquence, une simple liste d'index ou un
599 # Vérification du Scheduler
600 # -------------------------
602 if type(Scheduler) is int: # Considéré comme une fréquence à partir de 0
603 Schedulers = xrange( 0, maxiter, int(Scheduler) )
604 elif type(Scheduler) is xrange: # Considéré comme un itérateur
605 Schedulers = Scheduler
606 elif type(Scheduler) is list: # Considéré comme des index explicites
607 Schedulers = map( long, Scheduler )
608 else: # Dans tous les autres cas, activé par défaut
609 Schedulers = xrange( 0, maxiter )
611 # Stockage interne de l'observer dans la variable
612 # -----------------------------------------------
613 self.__dataobservers.append( [HookFunction, HookParameters, Schedulers] )
615 def removeDataObserver(self,
619 Suppression d'un observer nommé sur la variable.
621 On peut donner dans HookFunction la meme fonction que lors de la
622 définition, ou un simple string qui est le nom de la fonction.
625 if hasattr(HookFunction,"func_name"):
626 name = str( HookFunction.func_name )
627 elif type(HookFunction) is str:
628 name = str( HookFunction )
634 for [hf, hp, hs] in self.__dataobservers:
636 if name is hf.func_name: index_to_remove.append( i )
637 index_to_remove.reverse()
638 for i in index_to_remove:
639 self.__dataobservers.pop( i )
641 # ==============================================================================
642 class OneScalar(Persistence):
644 Classe définissant le stockage d'une valeur unique réelle (float) par pas.
646 Le type de base peut être changé par la méthode "basetype", mais il faut que
647 le nouveau type de base soit compatible avec les types par éléments de
648 numpy. On peut même utiliser cette classe pour stocker des vecteurs/listes
649 ou des matrices comme dans les classes suivantes, mais c'est déconseillé
650 pour conserver une signification claire des noms.
652 def __init__(self, name="", unit="", basetype = float):
653 Persistence.__init__(self, name, unit, basetype)
655 class OneIndex(Persistence):
657 Classe définissant le stockage d'une valeur unique entière (int) par pas.
659 def __init__(self, name="", unit="", basetype = int):
660 Persistence.__init__(self, name, unit, basetype)
662 class OneVector(Persistence):
664 Classe de stockage d'une liste de valeurs numériques homogènes par pas. Ne
665 pas utiliser cette classe pour des données hétérogènes, mais "OneList".
667 def __init__(self, name="", unit="", basetype = numpy.ravel):
668 Persistence.__init__(self, name, unit, basetype)
670 class OneMatrix(Persistence):
672 Classe de stockage d'une matrice de valeurs (numpy.matrix) par pas.
674 def __init__(self, name="", unit="", basetype = numpy.matrix):
675 Persistence.__init__(self, name, unit, basetype)
677 class OneList(Persistence):
679 Classe de stockage d'une liste de valeurs hétérogènes (list) par pas. Ne pas
680 utiliser cette classe pour des données numériques homogènes, mais
683 def __init__(self, name="", unit="", basetype = list):
684 Persistence.__init__(self, name, unit, basetype)
686 def NoType( value ): return value
688 class OneNoType(Persistence):
690 Classe de stockage d'un objet sans modification (cast) de type. Attention,
691 selon le véritable type de l'objet stocké à chaque pas, les opérations
692 arithmétiques à base de numpy peuvent être invalides ou donner des résultats
693 inattendus. Cette classe n'est donc à utiliser qu'à bon escient
694 volontairement, et pas du tout par défaut.
696 def __init__(self, name="", unit="", basetype = NoType):
697 Persistence.__init__(self, name, unit, basetype)
699 # ==============================================================================
700 class CompositePersistence:
702 Structure de stockage permettant de rassembler plusieurs objets de
705 Des objets par défaut sont prévus, et des objets supplémentaires peuvent
708 def __init__(self, name="", defaults=True):
712 La gestion interne des données est exclusivement basée sur les variables
713 initialisées ici (qui ne sont pas accessibles depuis l'extérieur des
714 objets comme des attributs) :
715 __StoredObjects : objets de type persistence collectés dans cet objet
717 self.__name = str(name)
719 self.__StoredObjects = {}
721 # Definition des objets par defaut
722 # --------------------------------
724 self.__StoredObjects["Informations"] = OneNoType("Informations")
725 self.__StoredObjects["Background"] = OneVector("Background", basetype=numpy.array)
726 self.__StoredObjects["BackgroundError"] = OneMatrix("BackgroundError")
727 self.__StoredObjects["Observation"] = OneVector("Observation", basetype=numpy.array)
728 self.__StoredObjects["ObservationError"] = OneMatrix("ObservationError")
729 self.__StoredObjects["Analysis"] = OneVector("Analysis", basetype=numpy.array)
730 self.__StoredObjects["AnalysisError"] = OneMatrix("AnalysisError")
731 self.__StoredObjects["Innovation"] = OneVector("Innovation", basetype=numpy.array)
732 self.__StoredObjects["KalmanGainK"] = OneMatrix("KalmanGainK")
733 self.__StoredObjects["OperatorH"] = OneMatrix("OperatorH")
734 self.__StoredObjects["RmsOMA"] = OneScalar("RmsOMA")
735 self.__StoredObjects["RmsOMB"] = OneScalar("RmsOMB")
736 self.__StoredObjects["RmsBMA"] = OneScalar("RmsBMA")
739 def store(self, name=None, value=None, **kwargs):
741 Stockage d'une valeur "value" pour le "step" dans la variable "name".
743 if name is None: raise ValueError("Storable object name is required for storage.")
744 if name not in self.__StoredObjects.keys():
745 raise ValueError("No such name '%s' exists in storable objects."%name)
746 self.__StoredObjects[name].store( value=value, **kwargs )
748 def add_object(self, name=None, persistenceType=Persistence, basetype=None ):
750 Ajoute dans les objets stockables un nouvel objet défini par son nom, son
751 type de Persistence et son type de base à chaque pas.
753 if name is None: raise ValueError("Object name is required for adding an object.")
754 if name in self.__StoredObjects.keys():
755 raise ValueError("An object with the same name '%s' already exists in storable objects. Choose another one."%name)
757 self.__StoredObjects[name] = persistenceType( name=str(name) )
759 self.__StoredObjects[name] = persistenceType( name=str(name), basetype=basetype )
761 def get_object(self, name=None ):
763 Renvoie l'objet de type Persistence qui porte le nom demandé.
765 if name is None: raise ValueError("Object name is required for retrieving an object.")
766 if name not in self.__StoredObjects.keys():
767 raise ValueError("No such name '%s' exists in stored objects."%name)
768 return self.__StoredObjects[name]
770 def set_object(self, name=None, objet=None ):
772 Affecte directement un 'objet' qui porte le nom 'name' demandé.
773 Attention, il n'est pas effectué de vérification sur le type, qui doit
774 comporter les méthodes habituelles de Persistence pour que cela
777 if name is None: raise ValueError("Object name is required for setting an object.")
778 if name in self.__StoredObjects.keys():
779 raise ValueError("An object with the same name '%s' already exists in storable objects. Choose another one."%name)
780 self.__StoredObjects[name] = objet
782 def del_object(self, name=None ):
784 Supprime un objet de la liste des objets stockables.
786 if name is None: raise ValueError("Object name is required for retrieving an object.")
787 if name not in self.__StoredObjects.keys():
788 raise ValueError("No such name '%s' exists in stored objects."%name)
789 del self.__StoredObjects[name]
791 # ---------------------------------------------------------
792 # Méthodes d'accès de type dictionnaire
793 def __getitem__(self, name=None ):
794 return self.get_object( name )
796 def __setitem__(self, name=None, objet=None ):
797 self.set_object( name, objet )
800 return self.get_stored_objects(hideVoidObjects = False)
803 return self.__StoredObjects.values()
806 return self.__StoredObjects.items()
808 # ---------------------------------------------------------
809 def get_stored_objects(self, hideVoidObjects = False):
810 objs = self.__StoredObjects.keys()
815 if len(self.__StoredObjects[k]) > 0: usedObjs.append( k )
822 # ---------------------------------------------------------
823 def save_composite(self, filename=None, mode="pickle", compress="gzip"):
825 Enregistre l'objet dans le fichier indiqué selon le "mode" demandé,
826 et renvoi le nom du fichier
830 if compress == "gzip":
831 filename = os.tempnam( os.getcwd(), 'dacp' ) + ".pkl.gz"
832 elif compress == "bzip2":
833 filename = os.tempnam( os.getcwd(), 'dacp' ) + ".pkl.bz2"
835 filename = os.tempnam( os.getcwd(), 'dacp' ) + ".pkl"
837 filename = os.path.abspath( filename )
841 if compress == "gzip":
843 output = gzip.open( filename, 'wb')
844 elif compress == "bzip2":
846 output = bz2.BZ2File( filename, 'wb')
848 output = open( filename, 'wb')
849 cPickle.dump(self, output)
852 raise ValueError("Save mode '%s' unknown. Choose another one."%mode)
856 def load_composite(self, filename=None, mode="pickle", compress="gzip"):
858 Recharge un objet composite sauvé en fichier
862 raise ValueError("A file name if requested to load a composite.")
864 filename = os.path.abspath( filename )
868 if compress == "gzip":
870 pkl_file = gzip.open( filename, 'rb')
871 elif compress == "bzip2":
873 pkl_file = bz2.BZ2File( filename, 'rb')
875 pkl_file = open(filename, 'rb')
876 output = cPickle.load(pkl_file)
877 for k in output.keys():
880 raise ValueError("Load mode '%s' unknown. Choose another one."%mode)
884 # ==============================================================================
885 if __name__ == "__main__":
886 print '\n AUTODIAGNOSTIC \n'