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"
31 from PlatformInfo import PathManagement ; PathManagement()
33 # ==============================================================================
36 Classe générale de persistence définissant les accesseurs nécessaires
39 def __init__(self, name="", unit="", basetype=str):
43 basetype : type de base de l'objet stocké à chaque pas
45 La gestion interne des données est exclusivement basée sur les variables
46 initialisées ici (qui ne sont pas accessibles depuis l'extérieur des
47 objets comme des attributs) :
48 __basetype : le type de base de chaque valeur, sous la forme d'un type
49 permettant l'instanciation ou le casting Python
50 __values : les valeurs de stockage. Par défaut, c'est None
52 self.__name = str(name)
53 self.__unit = str(unit)
55 self.__basetype = basetype
60 self.__dynamic = False
62 self.__dataobservers = []
64 def basetype(self, basetype=None):
66 Renvoie ou met en place le type de base des objets stockés
69 return self.__basetype
71 self.__basetype = basetype
73 def store(self, value=None, **kwargs):
75 Stocke une valeur avec ses informations de filtrage.
77 if value is None: raise ValueError("Value argument required")
79 self.__values.append(copy.copy(self.__basetype(value)))
80 self.__tags.append(kwargs)
82 if self.__dynamic: self.__replots()
83 __step = len(self.__values) - 1
84 for hook, parameters, scheduler in self.__dataobservers:
85 if __step in scheduler:
86 hook( self, parameters )
88 def pop(self, item=None):
90 Retire une valeur enregistree par son index de stockage. Sans argument,
91 retire le dernier objet enregistre.
95 self.__values.pop(__index)
96 self.__tags.pop(__index)
103 Renvoie la taille sous forme numpy du dernier objet stocké. Si c'est un
104 objet numpy, renvoie le shape. Si c'est un entier, un flottant, un
105 complexe, renvoie 1. Si c'est une liste ou un dictionnaire, renvoie la
106 longueur. Par défaut, renvoie 1.
108 if len(self.__values) > 0:
109 if self.__basetype in [numpy.matrix, numpy.array, numpy.ravel]:
110 return self.__values[-1].shape
111 elif self.__basetype in [int, float]:
113 elif self.__basetype in [list, dict]:
114 return (len(self.__values[-1]),)
118 raise ValueError("Object has no shape before its first storage")
120 # ---------------------------------------------------------
122 msg = " Index Value Tags\n"
123 for i,v in enumerate(self.__values):
124 msg += " i=%05i %10s %s\n"%(i,v,self.__tags[i])
128 return len(self.__values)
130 def __getitem__(self, index=None ):
131 return copy.copy(self.__values[index])
133 def count(self, value):
134 return self.__values.count(value)
136 def index(self, value, start=0, stop=None):
137 if stop is None : stop = len(self.__values)
138 return self.__values.index(value, start, stop)
140 # ---------------------------------------------------------
141 def __filteredIndexes(self, **kwargs):
142 __indexOfFilteredItems = range(len(self.__tags))
143 __filteringKwTags = kwargs.keys()
144 if len(__filteringKwTags) > 0:
145 for tagKey in __filteringKwTags:
147 for i in __indexOfFilteredItems:
148 if self.__tags[i].has_key(tagKey):
149 if self.__tags[i][tagKey] == kwargs[tagKey]:
151 elif isinstance(kwargs[tagKey],(list,tuple)) and self.__tags[i][tagKey] in kwargs[tagKey]:
153 __indexOfFilteredItems = __tmp
154 if len(__indexOfFilteredItems) == 0: break
155 return __indexOfFilteredItems
157 # ---------------------------------------------------------
158 def values(self, **kwargs):
159 __indexOfFilteredItems = self.__filteredIndexes(**kwargs)
160 return [self.__values[i] for i in __indexOfFilteredItems]
162 def keys(self, keyword=None , **kwargs):
163 __indexOfFilteredItems = self.__filteredIndexes(**kwargs)
165 for i in __indexOfFilteredItems:
166 if self.__tags[i].has_key( keyword ):
167 __keys.append( self.__tags[i][keyword] )
169 __keys.append( None )
172 def items(self, keyword=None , **kwargs):
173 __indexOfFilteredItems = self.__filteredIndexes(**kwargs)
175 for i in __indexOfFilteredItems:
176 if self.__tags[i].has_key( keyword ):
177 __pairs.append( [self.__tags[i][keyword], self.__values[i]] )
179 __pairs.append( [None, self.__values[i]] )
184 for dicotags in self.__tags:
185 __allKeys.extend( dicotags.keys() )
186 __allKeys = list(set(__allKeys))
190 # def valueserie(self, item=None, allSteps=True, **kwargs):
191 # if item is not None:
192 # return self.__values[item]
194 # __indexOfFilteredItems = self.__filteredIndexes(**kwargs)
195 # if not allSteps and len(__indexOfFilteredItems) > 0:
196 # return self.__values[__indexOfFilteredItems[0]]
198 # return [self.__values[i] for i in __indexOfFilteredItems]
200 def tagserie(self, item=None, withValues=False, outputTag=None, **kwargs):
202 __indexOfFilteredItems = self.__filteredIndexes(**kwargs)
204 __indexOfFilteredItems = [item,]
206 # Dans le cas où la sortie donne les valeurs d'un "outputTag"
207 if outputTag is not None and type(outputTag) is str :
209 for index in __indexOfFilteredItems:
210 if outputTag in self.__tags[index].keys():
211 outputValues.append( self.__tags[index][outputTag] )
212 outputValues = list(set(outputValues))
216 # Dans le cas où la sortie donne les tags satisfaisants aux conditions
219 return [self.__tags[index] for index in __indexOfFilteredItems]
222 for index in __indexOfFilteredItems:
223 allTags.update( self.__tags[index] )
224 allKeys = allTags.keys()
228 # ---------------------------------------------------------
230 def stepnumber(self):
231 return len(self.__values)
234 def stepserie(self, **kwargs):
235 __indexOfFilteredItems = self.__filteredIndexes(**kwargs)
236 return __indexOfFilteredItems
238 # ---------------------------------------------------------
241 Renvoie la série, contenant à chaque pas, la valeur moyenne des données
242 au pas. Il faut que le type de base soit compatible avec les types
246 return [numpy.matrix(item).mean() for item in self.__values]
248 raise TypeError("Base type is incompatible with numpy")
250 def stds(self, ddof=0):
252 Renvoie la série, contenant à chaque pas, l'écart-type des données
253 au pas. Il faut que le type de base soit compatible avec les types
256 ddof : c'est le nombre de degrés de liberté pour le calcul de
257 l'écart-type, qui est dans le diviseur. Inutile avant Numpy 1.1
260 if numpy.version.version >= '1.1.0':
261 return [numpy.matrix(item).std(ddof=ddof) for item in self.__values]
263 return [numpy.matrix(item).std() for item in self.__values]
265 raise TypeError("Base type is incompatible with numpy")
269 Renvoie la série, contenant à chaque pas, la somme des données au pas.
270 Il faut que le type de base soit compatible avec les types élémentaires
274 return [numpy.matrix(item).sum() for item in self.__values]
276 raise TypeError("Base type is incompatible with numpy")
280 Renvoie la série, contenant à chaque pas, le minimum des données au pas.
281 Il faut que le type de base soit compatible avec les types élémentaires
285 return [numpy.matrix(item).min() for item in self.__values]
287 raise TypeError("Base type is incompatible with numpy")
291 Renvoie la série, contenant à chaque pas, la maximum des données au pas.
292 Il faut que le type de base soit compatible avec les types élémentaires
296 return [numpy.matrix(item).max() for item in self.__values]
298 raise TypeError("Base type is incompatible with numpy")
305 geometry = "600x400",
310 # Vérification de la disponibilité du module Gnuplot
313 self.__gnuplot = Gnuplot
315 raise ImportError("The Gnuplot module is required to plot the object.")
317 # Vérification et compléments sur les paramètres d'entrée
319 self.__gnuplot.GnuplotOpts.gnuplot_command = 'gnuplot -persist -geometry '+geometry
321 self.__gnuplot.GnuplotOpts.gnuplot_command = 'gnuplot -geometry '+geometry
324 self.__g = self.__gnuplot.Gnuplot() # persist=1
325 self.__g('set terminal '+self.__gnuplot.GnuplotOpts.default_term)
326 self.__g('set style data lines')
328 self.__g('set autoscale')
329 self.__g('set xlabel "'+str(xlabel).encode('ascii','replace')+'"')
330 self.__g('set ylabel "'+str(ylabel).encode('ascii','replace')+'"')
332 self.__ltitle = ltitle
335 def plots(self, item=None, step=None,
341 geometry = "600x400",
348 Renvoie un affichage de la valeur à chaque pas, si elle est compatible
349 avec un affichage Gnuplot (donc essentiellement un vecteur). Si
350 l'argument "step" existe dans la liste des pas de stockage effectués,
351 renvoie l'affichage de la valeur stockée à ce pas "step". Si l'argument
352 "item" est correct, renvoie l'affichage de la valeur stockée au numéro
353 "item". Par défaut ou en l'absence de "step" ou "item", renvoie un
354 affichage successif de tous les pas.
357 - step : valeur du pas à afficher
358 - item : index de la valeur à afficher
359 - steps : liste unique des pas de l'axe des X, ou None si c'est
360 la numérotation par défaut
361 - title : base du titre général, qui sera automatiquement
362 complétée par la mention du pas
363 - xlabel : label de l'axe des X
364 - ylabel : label de l'axe des Y
365 - ltitle : titre associé au vecteur tracé
366 - geometry : taille en pixels de la fenêtre et position du coin haut
367 gauche, au format X11 : LxH+X+Y (défaut : 600x400)
368 - filename : base de nom de fichier Postscript pour une sauvegarde,
369 qui est automatiquement complétée par le numéro du
370 fichier calculé par incrément simple de compteur
371 - dynamic : effectue un affichage des valeurs à chaque stockage
372 (au-delà du second). La méthode "plots" permet de
373 déclarer l'affichage dynamique, et c'est la méthode
374 "__replots" qui est utilisée pour l'effectuer
375 - persist : booléen indiquant que la fenêtre affichée sera
376 conservée lors du passage au dessin suivant
377 Par défaut, persist = False
378 - pause : booléen indiquant une pause après chaque tracé, et
380 Par défaut, pause = True
383 if not self.__dynamic:
384 self.__preplots(title, xlabel, ylabel, ltitle, geometry, persist, pause )
386 self.__dynamic = True
387 if len(self.__values) == 0: return 0
389 # Tracé du ou des vecteurs demandés
391 if step is not None and step < len(self.__values):
393 elif item is not None and item < len(self.__values):
396 indexes = indexes + range(len(self.__values))
399 for index in indexes:
400 self.__g('set title "'+str(title).encode('ascii','replace')+' (pas '+str(index)+')"')
401 if ( type(steps) is list ) or ( type(steps) is type(numpy.array([])) ):
404 Steps = range(len(self.__values[index]))
406 self.__g.plot( self.__gnuplot.Data( Steps, self.__values[index], title=ltitle ) )
410 stepfilename = "%s_%03i.ps"%(filename,i)
411 if os.path.isfile(stepfilename):
412 raise ValueError("Error: a file with this name \"%s\" already exists."%stepfilename)
413 self.__g.hardcopy(filename=stepfilename, color=1)
415 raw_input('Please press return to continue...\n')
419 Affichage dans le cas du suivi dynamique de la variable
421 if self.__dynamic and len(self.__values) < 2: return 0
423 self.__g('set title "'+str(self.__title).encode('ascii','replace'))
424 Steps = range(len(self.__values))
425 self.__g.plot( self.__gnuplot.Data( Steps, self.__values, title=self.__ltitle ) )
428 raw_input('Please press return to continue...\n')
430 # ---------------------------------------------------------
433 Renvoie la moyenne sur toutes les valeurs sans tenir compte de la
434 longueur des pas. Il faut que le type de base soit compatible avec
435 les types élémentaires numpy.
438 if self.__basetype in [int, float]:
439 return float( numpy.array(self.__values).mean() )
441 return numpy.array(self.__values).mean(axis=0)
443 raise TypeError("Base type is incompatible with numpy")
445 def std(self, ddof=0):
447 Renvoie l'écart-type de toutes les valeurs sans tenir compte de la
448 longueur des pas. Il faut que le type de base soit compatible avec
449 les types élémentaires numpy.
451 ddof : c'est le nombre de degrés de liberté pour le calcul de
452 l'écart-type, qui est dans le diviseur. Inutile avant Numpy 1.1
455 if numpy.version.version >= '1.1.0':
456 return numpy.array(self.__values).std(ddof=ddof,axis=0)
458 return numpy.array(self.__values).std(axis=0)
460 raise TypeError("Base type is incompatible with numpy")
464 Renvoie la somme de toutes les valeurs sans tenir compte de la
465 longueur des pas. Il faut que le type de base soit compatible avec
466 les types élémentaires numpy.
469 return numpy.array(self.__values).sum(axis=0)
471 raise TypeError("Base type is incompatible with numpy")
475 Renvoie le minimum de toutes les valeurs sans tenir compte de la
476 longueur des pas. Il faut que le type de base soit compatible avec
477 les types élémentaires numpy.
480 return numpy.array(self.__values).min(axis=0)
482 raise TypeError("Base type is incompatible with numpy")
486 Renvoie le maximum de toutes les valeurs sans tenir compte de la
487 longueur des pas. Il faut que le type de base soit compatible avec
488 les types élémentaires numpy.
491 return numpy.array(self.__values).max(axis=0)
493 raise TypeError("Base type is incompatible with numpy")
497 Renvoie la somme cumulée de toutes les valeurs sans tenir compte de la
498 longueur des pas. Il faut que le type de base soit compatible avec
499 les types élémentaires numpy.
502 return numpy.array(self.__values).cumsum(axis=0)
504 raise TypeError("Base type is incompatible with numpy")
506 # On pourrait aussi utiliser les autres attributs d'une "matrix", comme
515 geometry = "600x400",
521 Renvoie un affichage unique pour l'ensemble des valeurs à chaque pas, si
522 elles sont compatibles avec un affichage Gnuplot (donc essentiellement
523 un vecteur). Si l'argument "step" existe dans la liste des pas de
524 stockage effectués, renvoie l'affichage de la valeur stockée à ce pas
525 "step". Si l'argument "item" est correct, renvoie l'affichage de la
526 valeur stockée au numéro "item".
529 - steps : liste unique des pas de l'axe des X, ou None si c'est
530 la numérotation par défaut
531 - title : base du titre général, qui sera automatiquement
532 complétée par la mention du pas
533 - xlabel : label de l'axe des X
534 - ylabel : label de l'axe des Y
535 - ltitle : titre associé au vecteur tracé
536 - geometry : taille en pixels de la fenêtre et position du coin haut
537 gauche, au format X11 : LxH+X+Y (défaut : 600x400)
538 - filename : nom de fichier Postscript pour une sauvegarde
539 - persist : booléen indiquant que la fenêtre affichée sera
540 conservée lors du passage au dessin suivant
541 Par défaut, persist = False
542 - pause : booléen indiquant une pause après chaque tracé, et
544 Par défaut, pause = True
547 # Vérification de la disponibilité du module Gnuplot
550 self.__gnuplot = Gnuplot
552 raise ImportError("The Gnuplot module is required to plot the object.")
554 # Vérification et compléments sur les paramètres d'entrée
556 self.__gnuplot.GnuplotOpts.gnuplot_command = 'gnuplot -persist -geometry '+geometry
558 self.__gnuplot.GnuplotOpts.gnuplot_command = 'gnuplot -geometry '+geometry
561 if ( type(steps) is list ) or ( type(steps) is type(numpy.array([])) ):
564 Steps = range(len(self.__values[0]))
565 self.__g = self.__gnuplot.Gnuplot() # persist=1
566 self.__g('set terminal '+self.__gnuplot.GnuplotOpts.default_term)
567 self.__g('set style data lines')
569 self.__g('set autoscale')
570 self.__g('set title "'+str(title).encode('ascii','replace') +'"')
571 self.__g('set xlabel "'+str(xlabel).encode('ascii','replace')+'"')
572 self.__g('set ylabel "'+str(ylabel).encode('ascii','replace')+'"')
574 # Tracé du ou des vecteurs demandés
575 indexes = range(len(self.__values))
576 self.__g.plot( self.__gnuplot.Data( Steps, self.__values[indexes.pop(0)], title=ltitle+" (pas 0)" ) )
577 for index in indexes:
578 self.__g.replot( self.__gnuplot.Data( Steps, self.__values[index], title=ltitle+" (pas %i)"%index ) )
581 self.__g.hardcopy(filename=filename, color=1)
583 raw_input('Please press return to continue...\n')
585 # ---------------------------------------------------------
586 def setDataObserver(self,
588 HookParameters = None,
592 Association à la variable d'un triplet définissant un observer
594 Le Scheduler attendu est une fréquence, une simple liste d'index ou un
598 # Vérification du Scheduler
599 # -------------------------
601 if type(Scheduler) is int: # Considéré comme une fréquence à partir de 0
602 Schedulers = xrange( 0, maxiter, int(Scheduler) )
603 elif type(Scheduler) is xrange: # Considéré comme un itérateur
604 Schedulers = Scheduler
605 elif type(Scheduler) is list: # Considéré comme des index explicites
606 Schedulers = map( long, Scheduler )
607 else: # Dans tous les autres cas, activé par défaut
608 Schedulers = xrange( 0, maxiter )
610 # Stockage interne de l'observer dans la variable
611 # -----------------------------------------------
612 self.__dataobservers.append( [HookFunction, HookParameters, Schedulers] )
614 def removeDataObserver(self,
618 Suppression d'un observer nommé sur la variable.
620 On peut donner dans HookFunction la meme fonction que lors de la
621 définition, ou un simple string qui est le nom de la fonction.
624 if hasattr(HookFunction,"func_name"):
625 name = str( HookFunction.func_name )
626 elif type(HookFunction) is str:
627 name = str( HookFunction )
633 for [hf, hp, hs] in self.__dataobservers:
635 if name is hf.func_name: index_to_remove.append( i )
636 index_to_remove.reverse()
637 for i in index_to_remove:
638 self.__dataobservers.pop( i )
640 # ==============================================================================
641 class OneScalar(Persistence):
643 Classe définissant le stockage d'une valeur unique réelle (float) par pas
645 Le type de base peut être changé par la méthode "basetype", mais il faut que
646 le nouveau type de base soit compatible avec les types par éléments de
647 numpy. On peut même utiliser cette classe pour stocker des vecteurs/listes
648 ou des matrices comme dans les classes suivantes, mais c'est déconseillé
649 pour conserver une signification claire des noms.
651 def __init__(self, name="", unit="", basetype = float):
652 Persistence.__init__(self, name, unit, basetype)
654 class OneVector(Persistence):
656 Classe définissant le stockage d'une liste (list) de valeurs homogènes par
657 hypothèse par pas. Pour éviter les confusions, ne pas utiliser la classe
658 "OneVector" pour des données hétérogènes, mais bien "OneList".
660 def __init__(self, name="", unit="", basetype = numpy.ravel):
661 Persistence.__init__(self, name, unit, basetype)
663 class OneMatrix(Persistence):
665 Classe définissant le stockage d'une matrice de valeurs (numpy.matrix) par
668 def __init__(self, name="", unit="", basetype = numpy.matrix):
669 Persistence.__init__(self, name, unit, basetype)
671 class OneList(Persistence):
673 Classe définissant le stockage d'une liste de valeurs potentiellement
674 hétérogènes (list) par pas. Pour éviter les confusions, ne pas utiliser la
675 classe "OneVector" pour des données hétérogènes, mais bien "OneList".
677 def __init__(self, name="", unit="", basetype = list):
678 Persistence.__init__(self, name, unit, basetype)
680 def NoType( value ): return value
682 class OneNoType(Persistence):
684 Classe définissant le stockage d'un objet sans modification (cast) de type.
685 Attention, selon le véritable type de l'objet stocké à chaque pas, les
686 opérations arithmétiques à base de numpy peuvent être invalides ou donner
687 des résultats inattendus. Cette classe n'est donc à utiliser qu'à bon escient
688 volontairement, et pas du tout par défaut.
690 def __init__(self, name="", unit="", basetype = NoType):
691 Persistence.__init__(self, name, unit, basetype)
693 # ==============================================================================
694 class CompositePersistence:
696 Structure de stockage permettant de rassembler plusieurs objets de
699 Des objets par défaut sont prévus, et des objets supplémentaires peuvent
702 def __init__(self, name="", defaults=True):
706 La gestion interne des données est exclusivement basée sur les variables
707 initialisées ici (qui ne sont pas accessibles depuis l'extérieur des
708 objets comme des attributs) :
709 __StoredObjects : objets de type persistence collectés dans cet objet
711 self.__name = str(name)
713 self.__StoredObjects = {}
715 # Definition des objets par defaut
716 # --------------------------------
718 self.__StoredObjects["Informations"] = OneNoType("Informations")
719 self.__StoredObjects["Background"] = OneVector("Background", basetype=numpy.array)
720 self.__StoredObjects["BackgroundError"] = OneMatrix("BackgroundError")
721 self.__StoredObjects["Observation"] = OneVector("Observation", basetype=numpy.array)
722 self.__StoredObjects["ObservationError"] = OneMatrix("ObservationError")
723 self.__StoredObjects["Analysis"] = OneVector("Analysis", basetype=numpy.array)
724 self.__StoredObjects["AnalysisError"] = OneMatrix("AnalysisError")
725 self.__StoredObjects["Innovation"] = OneVector("Innovation", basetype=numpy.array)
726 self.__StoredObjects["KalmanGainK"] = OneMatrix("KalmanGainK")
727 self.__StoredObjects["OperatorH"] = OneMatrix("OperatorH")
728 self.__StoredObjects["RmsOMA"] = OneScalar("RmsOMA")
729 self.__StoredObjects["RmsOMB"] = OneScalar("RmsOMB")
730 self.__StoredObjects["RmsBMA"] = OneScalar("RmsBMA")
733 def store(self, name=None, value=None, **kwargs):
735 Stockage d'une valeur "value" pour le "step" dans la variable "name".
737 if name is None: raise ValueError("Storable object name is required for storage.")
738 if name not in self.__StoredObjects.keys():
739 raise ValueError("No such name '%s' exists in storable objects."%name)
740 self.__StoredObjects[name].store( value=value, **kwargs )
742 def add_object(self, name=None, persistenceType=Persistence, basetype=None ):
744 Ajoute dans les objets stockables un nouvel objet défini par son nom, son
745 type de Persistence et son type de base à chaque pas.
747 if name is None: raise ValueError("Object name is required for adding an object.")
748 if name in self.__StoredObjects.keys():
749 raise ValueError("An object with the same name '%s' already exists in storable objects. Choose another one."%name)
751 self.__StoredObjects[name] = persistenceType( name=str(name) )
753 self.__StoredObjects[name] = persistenceType( name=str(name), basetype=basetype )
755 def get_object(self, name=None ):
757 Renvoie l'objet de type Persistence qui porte le nom demandé.
759 if name is None: raise ValueError("Object name is required for retrieving an object.")
760 if name not in self.__StoredObjects.keys():
761 raise ValueError("No such name '%s' exists in stored objects."%name)
762 return self.__StoredObjects[name]
764 def set_object(self, name=None, objet=None ):
766 Affecte directement un 'objet' qui porte le nom 'name' demandé.
767 Attention, il n'est pas effectué de vérification sur le type, qui doit
768 comporter les méthodes habituelles de Persistence pour que cela
771 if name is None: raise ValueError("Object name is required for setting an object.")
772 if name in self.__StoredObjects.keys():
773 raise ValueError("An object with the same name '%s' already exists in storable objects. Choose another one."%name)
774 self.__StoredObjects[name] = objet
776 def del_object(self, name=None ):
778 Supprime un objet de la liste des objets stockables.
780 if name is None: raise ValueError("Object name is required for retrieving an object.")
781 if name not in self.__StoredObjects.keys():
782 raise ValueError("No such name '%s' exists in stored objects."%name)
783 del self.__StoredObjects[name]
785 # ---------------------------------------------------------
786 # Méthodes d'accès de type dictionnaire
787 def __getitem__(self, name=None ):
788 return self.get_object( name )
790 def __setitem__(self, name=None, objet=None ):
791 self.set_object( name, objet )
794 return self.get_stored_objects(hideVoidObjects = False)
797 return self.__StoredObjects.values()
800 return self.__StoredObjects.items()
802 # ---------------------------------------------------------
803 def get_stored_objects(self, hideVoidObjects = False):
804 objs = self.__StoredObjects.keys()
809 if len(self.__StoredObjects[k]) > 0: usedObjs.append( k )
816 # ---------------------------------------------------------
817 def save_composite(self, filename=None, mode="pickle", compress="gzip"):
819 Enregistre l'objet dans le fichier indiqué selon le "mode" demandé,
820 et renvoi le nom du fichier
824 if compress == "gzip":
825 filename = os.tempnam( os.getcwd(), 'dacp' ) + ".pkl.gz"
826 elif compress == "bzip2":
827 filename = os.tempnam( os.getcwd(), 'dacp' ) + ".pkl.bz2"
829 filename = os.tempnam( os.getcwd(), 'dacp' ) + ".pkl"
831 filename = os.path.abspath( filename )
835 if compress == "gzip":
837 output = gzip.open( filename, 'wb')
838 elif compress == "bzip2":
840 output = bz2.BZ2File( filename, 'wb')
842 output = open( filename, 'wb')
843 cPickle.dump(self, output)
846 raise ValueError("Save mode '%s' unknown. Choose another one."%mode)
850 def load_composite(self, filename=None, mode="pickle", compress="gzip"):
852 Recharge un objet composite sauvé en fichier
856 raise ValueError("A file name if requested to load a composite.")
858 filename = os.path.abspath( filename )
862 if compress == "gzip":
864 pkl_file = gzip.open( filename, 'rb')
865 elif compress == "bzip2":
867 pkl_file = bz2.BZ2File( filename, 'rb')
869 pkl_file = open(filename, 'rb')
870 output = cPickle.load(pkl_file)
871 for k in output.keys():
874 raise ValueError("Load mode '%s' unknown. Choose another one."%mode)
878 # ==============================================================================
879 if __name__ == "__main__":
880 print '\n AUTODIAGNOSTIC \n'