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