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 OneVector(Persistence):
657 Classe de stockage d'une liste de valeurs numériques homogènes par pas. Ne
658 pas utiliser cette classe pour des données hétérogènes, mais "OneList".
660 def __init__(self, name="", unit="", basetype = numpy.ravel):
661 Persistence.__init__(self, name, unit, basetype)
663 class OneMatrix(Persistence):
665 Classe de stockage d'une matrice de valeurs (numpy.matrix) par pas.
667 def __init__(self, name="", unit="", basetype = numpy.matrix):
668 Persistence.__init__(self, name, unit, basetype)
670 class OneList(Persistence):
672 Classe de stockage d'une liste de valeurs hétérogènes (list) par pas. Ne pas
673 utiliser cette classe pour des données numériques homogènes, mais
676 def __init__(self, name="", unit="", basetype = list):
677 Persistence.__init__(self, name, unit, basetype)
679 def NoType( value ): return value
681 class OneNoType(Persistence):
683 Classe de stockage d'un objet sans modification (cast) de type. Attention,
684 selon le véritable type de l'objet stocké à chaque pas, les opérations
685 arithmétiques à base de numpy peuvent être invalides ou donner des résultats
686 inattendus. Cette classe n'est donc à utiliser qu'à bon escient
687 volontairement, et pas du tout par défaut.
689 def __init__(self, name="", unit="", basetype = NoType):
690 Persistence.__init__(self, name, unit, basetype)
692 # ==============================================================================
693 class CompositePersistence:
695 Structure de stockage permettant de rassembler plusieurs objets de
698 Des objets par défaut sont prévus, et des objets supplémentaires peuvent
701 def __init__(self, name="", defaults=True):
705 La gestion interne des données est exclusivement basée sur les variables
706 initialisées ici (qui ne sont pas accessibles depuis l'extérieur des
707 objets comme des attributs) :
708 __StoredObjects : objets de type persistence collectés dans cet objet
710 self.__name = str(name)
712 self.__StoredObjects = {}
714 # Definition des objets par defaut
715 # --------------------------------
717 self.__StoredObjects["Informations"] = OneNoType("Informations")
718 self.__StoredObjects["Background"] = OneVector("Background", basetype=numpy.array)
719 self.__StoredObjects["BackgroundError"] = OneMatrix("BackgroundError")
720 self.__StoredObjects["Observation"] = OneVector("Observation", basetype=numpy.array)
721 self.__StoredObjects["ObservationError"] = OneMatrix("ObservationError")
722 self.__StoredObjects["Analysis"] = OneVector("Analysis", basetype=numpy.array)
723 self.__StoredObjects["AnalysisError"] = OneMatrix("AnalysisError")
724 self.__StoredObjects["Innovation"] = OneVector("Innovation", basetype=numpy.array)
725 self.__StoredObjects["KalmanGainK"] = OneMatrix("KalmanGainK")
726 self.__StoredObjects["OperatorH"] = OneMatrix("OperatorH")
727 self.__StoredObjects["RmsOMA"] = OneScalar("RmsOMA")
728 self.__StoredObjects["RmsOMB"] = OneScalar("RmsOMB")
729 self.__StoredObjects["RmsBMA"] = OneScalar("RmsBMA")
732 def store(self, name=None, value=None, **kwargs):
734 Stockage d'une valeur "value" pour le "step" dans la variable "name".
736 if name is None: raise ValueError("Storable object name is required for storage.")
737 if name not in self.__StoredObjects.keys():
738 raise ValueError("No such name '%s' exists in storable objects."%name)
739 self.__StoredObjects[name].store( value=value, **kwargs )
741 def add_object(self, name=None, persistenceType=Persistence, basetype=None ):
743 Ajoute dans les objets stockables un nouvel objet défini par son nom, son
744 type de Persistence et son type de base à chaque pas.
746 if name is None: raise ValueError("Object name is required for adding an object.")
747 if name in self.__StoredObjects.keys():
748 raise ValueError("An object with the same name '%s' already exists in storable objects. Choose another one."%name)
750 self.__StoredObjects[name] = persistenceType( name=str(name) )
752 self.__StoredObjects[name] = persistenceType( name=str(name), basetype=basetype )
754 def get_object(self, name=None ):
756 Renvoie l'objet de type Persistence qui porte le nom demandé.
758 if name is None: raise ValueError("Object name is required for retrieving an object.")
759 if name not in self.__StoredObjects.keys():
760 raise ValueError("No such name '%s' exists in stored objects."%name)
761 return self.__StoredObjects[name]
763 def set_object(self, name=None, objet=None ):
765 Affecte directement un 'objet' qui porte le nom 'name' demandé.
766 Attention, il n'est pas effectué de vérification sur le type, qui doit
767 comporter les méthodes habituelles de Persistence pour que cela
770 if name is None: raise ValueError("Object name is required for setting an object.")
771 if name in self.__StoredObjects.keys():
772 raise ValueError("An object with the same name '%s' already exists in storable objects. Choose another one."%name)
773 self.__StoredObjects[name] = objet
775 def del_object(self, name=None ):
777 Supprime un objet de la liste des objets stockables.
779 if name is None: raise ValueError("Object name is required for retrieving an object.")
780 if name not in self.__StoredObjects.keys():
781 raise ValueError("No such name '%s' exists in stored objects."%name)
782 del self.__StoredObjects[name]
784 # ---------------------------------------------------------
785 # Méthodes d'accès de type dictionnaire
786 def __getitem__(self, name=None ):
787 return self.get_object( name )
789 def __setitem__(self, name=None, objet=None ):
790 self.set_object( name, objet )
793 return self.get_stored_objects(hideVoidObjects = False)
796 return self.__StoredObjects.values()
799 return self.__StoredObjects.items()
801 # ---------------------------------------------------------
802 def get_stored_objects(self, hideVoidObjects = False):
803 objs = self.__StoredObjects.keys()
808 if len(self.__StoredObjects[k]) > 0: usedObjs.append( k )
815 # ---------------------------------------------------------
816 def save_composite(self, filename=None, mode="pickle", compress="gzip"):
818 Enregistre l'objet dans le fichier indiqué selon le "mode" demandé,
819 et renvoi le nom du fichier
823 if compress == "gzip":
824 filename = os.tempnam( os.getcwd(), 'dacp' ) + ".pkl.gz"
825 elif compress == "bzip2":
826 filename = os.tempnam( os.getcwd(), 'dacp' ) + ".pkl.bz2"
828 filename = os.tempnam( os.getcwd(), 'dacp' ) + ".pkl"
830 filename = os.path.abspath( filename )
834 if compress == "gzip":
836 output = gzip.open( filename, 'wb')
837 elif compress == "bzip2":
839 output = bz2.BZ2File( filename, 'wb')
841 output = open( filename, 'wb')
842 cPickle.dump(self, output)
845 raise ValueError("Save mode '%s' unknown. Choose another one."%mode)
849 def load_composite(self, filename=None, mode="pickle", compress="gzip"):
851 Recharge un objet composite sauvé en fichier
855 raise ValueError("A file name if requested to load a composite.")
857 filename = os.path.abspath( filename )
861 if compress == "gzip":
863 pkl_file = gzip.open( filename, 'rb')
864 elif compress == "bzip2":
866 pkl_file = bz2.BZ2File( filename, 'rb')
868 pkl_file = open(filename, 'rb')
869 output = cPickle.load(pkl_file)
870 for k in output.keys():
873 raise ValueError("Load mode '%s' unknown. Choose another one."%mode)
877 # ==============================================================================
878 if __name__ == "__main__":
879 print '\n AUTODIAGNOSTIC \n'