10 """Pickle python data into a root file, preserving references to root objects.
12 This module allows pickling python
13 objects into a root file. The python objects may contain
14 references to named root objects. If one has set up a structure
15 of python objects to hold root histograms, this provides a
16 convenient way of saving and restoring your histograms.
17 The pickled python data are stored in an additional string
18 object in the root file; any root objects are stored as usual.
19 (Thus, root files written by root_pickle can be
20 read just like any other root file if you don't care about the
23 Here's an example of writing a pickle:
26 from PyAnalysisUtils.root_pickle import dump_root
30 hlist.append (ROOT.TH1F (name, name, 10, 0, 10))
31 dump_root (hlist, 'test.root')
33 This writes a list of histograms to test.root.
34 The histograms may be read back like this:
37 from PyAnalysisUtils.root_pickle import load_root
38 hlist = load_root ('test.root')
41 The following additional notes apply.
43 - In addition to dump_root and
44 load_root, the module also provides
45 dump and load functions, which
46 take root file objects instead of file names.
48 - The present version of root_pickle will
49 not work correctly for the case of python objects deriving
50 from root objects. It will probably also not work for the
51 case of root objects which do not derive from
54 - When the pickled data are being read, if a class
55 doesn't exist, root_pickle will create a
56 dummy class with no methods and use that. This is
57 different from the standard pickle behavior (where it
58 would be an error), but it simplifies usage in the common
59 case where the class is being used to hold histograms, and
60 its methods are entirely concerned with filling the
63 - When restoring a reference to a root object, the default behavior
64 is to not read the root object itself, but instead to create a proxy.
65 The root object will then be read the first time the proxy is accessed.
66 This can help significantly with time and memory usage if you're
67 only accessing a small fraction of the root objects, but it does
68 mean that you need to keep the root file open. Pass use_proxy=0
69 to disable this behavior.
76 from six.moves
import intern
79 if hasattr (ROOT.TDirectory,
'CurrentDirectory'):
80 d = ROOT.TDirectory.CurrentDirectory()
81 if hasattr (d,
'load'):
84 return ROOT.gDirectory
88 ROOT.TDirectory.cd (d)
109 from StringIO
import StringIO
111 return s.replace (
'\377',
'\377\376').replace (
'\000',
'\377\001')
113 return s.replace (
'\377\001',
'\000').replace (
'\377\376',
'\377')
121 return self.
__s.write (_protect (s))
136 return self.
__s.read (i)
139 return self.
__s.readline ()
142 self.
__s = StringIO (_restore (s.GetName()))
146 self.
__s = StringIO()
179 self.
_s = ROOT.TObjString()
191 slen = len(self.
_str)
192 while i != 0
and self.
_pos < slen:
196 if self.
_pos >= slen:
211 slen = len(self.
_str)
212 while self.
_pos < slen:
216 if self.
_pos >= slen:
244 """Create a root pickler.
245 FILE should be a Root TFile. PROTO is the python pickle protocol
246 version to use. The python part will be pickled to a Root
247 TObjString called _pickle; it will contain references to the
260 """Write a pickled representation of o to the open TFile."""
267 s = self.
__io.getvalue()
278 """Clears the pickler's internal memo."""
285 if hasattr (o,
'_Root_Proxy__obj'):
286 o = o._Root_Proxy__obj()
287 if (isinstance (o, ROOT.TObject)):
307 k = self.
__keys.FindObject(nm)
310 k = self.
__file.GetKey (nm)
311 pid =
"%s;%d" % (nm, k.GetCycle())
338 __slots__ = (
'__f',
'__pid',
'__o')
347 if self.
__o.__class__.__module__ !=
'ROOT':
348 self.
__o.__class__.__module__ =
'ROOT'
349 return getattr (self.
__o, a)
353 if self.
__o.__class__.__module__ !=
'ROOT':
354 self.
__o.__class__.__module__ =
'ROOT'
357 def __init__ (self, file, use_proxy = True, use_hash = False):
358 """Create a root unpickler.
359 FILE should be a Root TFile.
364 pickle.Unpickler.__init__ (self, self.
__io)
372 for k
in file.GetListOfKeys():
376 if cy > ctab.get(nm,0):
393 ret = htab.get ((nm,cy),
None)
395 print (
"did't find", nm, cy, len(htab))
406 """Read a pickled object representation from the open file."""
411 save = _compat_hooks[0]()
414 s = self.
__file.Get (key +
';%d' % self.
__n)
415 self.
__io.setvalue (s)
416 o = pickle.Unpickler.load(self)
420 save = _compat_hooks[1](save)
425 o = Root_Proxy (self.
__file, pid)
434 if module ==
'copy_reg':
436 elif module ==
'__builtin__':
441 mod = sys.modules[module]
443 print (
"Making dummy module %s" % (module))
447 sys.modules[module] = mod
448 klass = getattr(mod, name)
450 except AttributeError:
451 print (
"Making dummy class %s.%s" % (module, name))
452 mod = sys.modules[module]
455 setattr (mod, name, Dummy)
462 """Set compatibility hooks.
463 If this is set, then hooks[0] is called before loading,
464 and hooks[1] is called after loading. hooks[1] is called with
465 the return value of hooks[0] as an argument. This is useful
466 for backwards compatibility in some situations."""
468 _compat_hooks = hooks
472 def dump (o, f, proto=0, key=None):
473 """Dump object O to the Root TFile F."""
476 def load (f, use_proxy = 1, key=None):
477 """Load an object from the Root TFile F."""
481 """Dump object O to the Root file named FNAME."""
482 f = ROOT.TFile (fname ,
"RECREATE")
483 dump (o, f, proto, key)
488 """Load an object from the Root file named FNAME."""
489 return load (ROOT.TFile (fname), use_proxy, key)