CMS 3D CMS Logo

tree.py
Go to the documentation of this file.
1 import numpy
2 from ROOT import TTree
3 import ROOT
4 import six
5 
6 class Tree(object):
7 
8  def __init__(self, name, title, defaultFloatType="D", defaultIntType="I"):
9  self.vars = {}
10  self.vecvars = {}
11  self.tree = TTree(name, title)
12  self.defaults = {}
13  self.vecdefaults = {}
14  self.defaultFloatType = defaultFloatType
15  self.defaultIntType = defaultIntType
16  self.fillers = {}
17 
18  def setDefaultFloatType(self, defaultFloatType):
19  self.defaultFloatType = defaultFloatType
20 
21  def setDefaultIntType(self, defaultIntType):
22  self.defaultIntType = defaultIntType
23 
24  def copyStructure(self, tree):
25  for branch in tree.GetListOfBranches():
26  name = branch.GetName()
27  typeName = branch.GetListOfLeaves()[0].GetTypeName()
28  type = float
29  if typeName == 'Int_t':
30  type = int
31  self.var(name, type)
32 
33  def branch_(self, selfmap, varName, type, len, postfix="", storageType="default", title=None):
34  """Backend function used to create scalar and vector branches.
35  Users should call "var" and "vector", not this function directly."""
36  if storageType == "default":
37  storageType = self.defaultIntType if type is int else self.defaultFloatType
38  if type is float :
39  if storageType == "F":
40  selfmap[varName]=numpy.zeros(len,numpy.float32)
41  self.tree.Branch(varName,selfmap[varName],varName+postfix+'/F')
42  elif storageType == "D":
43  selfmap[varName]=numpy.zeros(len,numpy.float64)
44  self.tree.Branch(varName,selfmap[varName],varName+postfix+'/D')
45  else:
46  raise RuntimeError('Unknown storage type %s for branch %s' % (storageType, varName))
47  elif type is int:
48  dtypes = {
49  "i" : numpy.uint32,
50  "s" : numpy.uint16,
51  "b" : numpy.uint8,
52  "l" : numpy.uint64,
53  "I" : numpy.int32,
54  "S" : numpy.int16,
55  "B" : numpy.int8,
56  "L" : numpy.int64,
57  }
58  if storageType not in dtypes:
59  raise RuntimeError('Unknown storage type %s for branch %s' % (storageType, varName))
60  selfmap[varName]=numpy.zeros(len,dtypes[storageType])
61  self.tree.Branch(varName,selfmap[varName],varName+postfix+'/'+storageType)
62  else:
63  raise RuntimeError('Unknown type %s for branch %s' % (type, varName))
64  if title:
65  self.tree.GetBranch(varName).SetTitle(title)
66 
67  def var(self, varName,type=float, default=-99, title=None, storageType="default", filler=None ):
68  if type in [int, float]:
69  self.branch_(self.vars, varName, type, 1, title=title, storageType=storageType)
70  self.defaults[varName] = default
71  elif __builtins__['type'](type) == str:
72  # create a value, looking up the type from ROOT and calling the default constructor
73  self.vars[varName] = getattr(ROOT,type)()
74  if type in [ "TLorentzVector" ]: # custom streamer classes
75  self.tree.Branch(varName+".", type, self.vars[varName], 8000,-1)
76  else:
77  self.tree.Branch(varName+".", type, self.vars[varName])
78  if filler is None:
79  raise RuntimeError("Error: when brancing with an object, filler should be set to a function that takes as argument an object instance and a value, and set the instance to the value (as otherwise python assignment of objects changes the address as well)")
80  self.fillers[varName] = filler
81  else:
82  raise RuntimeError('Unknown type %s for branch %s: it is not int, float or a string' % (type, varName))
83  self.defaults[varName] = default
84 
85  def vector(self, varName, lenvar, maxlen=None, type=float, default=-99, title=None, storageType="default", filler=None ):
86  """either lenvar is a string, and maxlen an int (variable size array), or lenvar is an int and maxlen is not specified (fixed array)"""
87  if type in [int, float]:
88  if __builtins__['type'](lenvar) == int: # need the __builtins__ since 'type' is a variable here :-/
89  self.branch_(self.vecvars, varName, type, lenvar, postfix="[%d]" % lenvar, title=title, storageType=storageType)
90  else:
91  if maxlen == None: RuntimeError, 'You must specify a maxlen if making a dynamic array';
92  self.branch_(self.vecvars, varName, type, maxlen, postfix="[%s]" % lenvar, title=title, storageType=storageType)
93  elif __builtins__['type'](type) == str:
94  self.vecvars[varName] = ROOT.TClonesArray(type,(lenvar if __builtins__['type'](lenvar) == int else maxlen))
95  if type in [ "TLorentzVector" ]: # custom streamer classes
96  self.tree.Branch(varName+".", self.vecvars[varName], 32000, -1)
97  else:
98  self.tree.Branch(varName+".", self.vecvars[varName])
99  if filler is None:
100  raise RuntimeError("Error: when brancing with an object, filler should be set to a function that takes as argument an object instance and a value, and set the instance to the value (as otherwise python assignment of objects changes the address as well)")
101  self.fillers[varName] = filler
102  self.vecdefaults[varName] = default
103 
104  def reset(self):
105  for name,value in six.iteritems(self.vars):
106  if name in self.fillers:
107  self.fillers[name](value, self.defaults[name])
108  else:
109  value[0]=self.defaults[name]
110  for name,value in six.iteritems(self.vecvars):
111  if isinstance(value, numpy.ndarray):
112  value.fill(self.vecdefaults[name])
113  else:
114  if isinstance(value, ROOT.TObject) and value.ClassName() == "TClonesArray":
115  value.ExpandCreateFast(0)
116 
117  def fill(self, varName, value ):
118  if isinstance(self.vars[varName], numpy.ndarray):
119  self.vars[varName][0]=value
120  else:
121  self.fillers[varName](self.vars[varName],value)
122 
123  def vfill(self, varName, values ):
124  a = self.vecvars[varName]
125  if isinstance(a, numpy.ndarray):
126  for (i,v) in enumerate(values):
127  a[i]=v
128  else:
129  if isinstance(a, ROOT.TObject) and a.ClassName() == "TClonesArray":
130  a.ExpandCreateFast(len(values))
131  fillit = self.fillers[varName]
132  for (i,v) in enumerate(values):
133  fillit(a[i],v)
Definition: tree.py:6
def vector(self, varName, lenvar, maxlen=None, type=float, default=-99, title=None, storageType="default", filler=None)
Definition: tree.py:85
def var(self, varName, type=float, default=-99, title=None, storageType="default", filler=None)
Definition: tree.py:67
vecvars
Definition: tree.py:10
def branch_(self, selfmap, varName, type, len, postfix="", storageType="default", title=None)
Definition: tree.py:33
def __init__(self, name, title, defaultFloatType="D", defaultIntType="I")
Definition: tree.py:8
def setDefaultIntType(self, defaultIntType)
Definition: tree.py:21
def vfill(self, varName, values)
Definition: tree.py:123
def copyStructure(self, tree)
Definition: tree.py:24
vars
Definition: tree.py:9
def reset(self)
Definition: tree.py:104
def setDefaultFloatType(self, defaultFloatType)
Definition: tree.py:18
tree
Definition: tree.py:11
vecdefaults
Definition: tree.py:13
defaults
Definition: tree.py:12
def fill(self, varName, value)
Definition: tree.py:117
defaultIntType
Definition: tree.py:15
fillers
Definition: tree.py:16
defaultFloatType
Definition: tree.py:14