CMS 3D CMS Logo

autovars.py
Go to the documentation of this file.
1 #!/bin/env python
2 #
3 # Objects to be used with AutoFillTreeProducer
4 #
5 # the variable declaration contains both the booking information and a function to fill the variable
6 #
7 # TODO: more documentation needed here!
8 
10  """Branch containing an individual variable (either of the event or of an object), created with a name and a function to compute it
11  - name, type, help, default: obvious
12  - function: a function that taken an object computes the value to fill (e.g. lambda event : len(event.goodVertices))
13  """
14  def __init__(self, name, function, type=float, help="", default=-99, mcOnly=False, filler=None):
15  self.name = name
16  self.function = function
17  self.type = type
18  self.help = help
19  self.default = default
20  self.mcOnly = mcOnly
21  self.filler = filler
22  def __call__(self,object):
23  ret = self.function(object)
24  return ret
25  def makeBranch(self,treeNumpy,isMC):
26  if self.mcOnly and not isMC: return
27  treeNumpy.var(self.name, type=self.type, default=self.default, title=self.help, filler=self.filler)
28  def fillBranch(self,treeNumpy,object,isMC):
29  if self.mcOnly and not isMC: return
30  treeNumpy.fill(self.name, self(object))
31  def __repr__(self):
32  return "<NTupleVariable[%s]>" % self.name
33 
34 
36  """Type defining a collection of variables associated to a single object. Contans NTupleVariable and NTupleSubObject"""
37  def __init__(self,name,baseObjectTypes=[],mcOnly=[],variables=[]):
38  self.name = name
39  self.baseObjectTypes = baseObjectTypes
40  self.mcOnly = mcOnly
41  self.variables = []
42  self.subObjects = []
43  for v in variables:
44  if issubclass(v.__class__,NTupleSubObject):
45  self.subObjects.append(v)
46  else:
47  self.variables.append(v)
48  self._subObjectVars = {}
49  def ownVars(self,isMC):
50  """Return only my vars, not including the ones from the bases"""
51  vars = [ v for v in self.variables if (isMC or not v.mcOnly) ]
52  if self.subObjects:
53  if isMC not in self._subObjectVars:
54  subvars = []
55  for so in self.subObjects:
56  if so.mcOnly and not isMC: continue
57  for subvar in so.objectType.allVars(isMC):
58  subvars.append(NTupleVariable(so.name+"_"+subvar.name,
59  #DebugComposer(so,subvar),#lambda object : subvar(so(object)),
60  lambda object, subvar=subvar, so=so : subvar(so(object)),
61  # ^-- lambda object : subvar(so(object)) doesn't work due to scoping, see
62  # http://stackoverflow.com/questions/2295290/what-do-lambda-function-closures-capture-in-python/2295372#2295372
63  type = subvar.type, help = subvar.help, default = subvar.default, mcOnly = subvar.mcOnly,
64  filler = subvar.filler))
65  self._subObjectVars[isMC] = subvars
66  vars += self._subObjectVars[isMC]
67  return vars
68  def allVars(self,isMC):
69  """Return all vars, including the base ones. Duplicate bases are not added twice"""
70  ret = []; names = {}
71  if not isMC and self.mcOnly: return []
72  for base in self.allBases():
73  if not isMC and base.mcOnly: continue
74  for var in base.ownVars(isMC):
75  if var.name in names: raise RuntimeError("Duplicate definition of variable %s from %s and %s" % (var.name, base.name, names[var.name]))
76  names[var.name] = base.name
77  ret.append(var)
78  for var in self.ownVars(isMC):
79  if var.name in names: raise RuntimeError("Duplicate definition of variable %s from %s and %s" % (var.name, self.name, names[var.name]))
80  names[var.name] = self.name
81  ret.append(var)
82  return ret
83  def allBases(self):
84  ret = []
85  for b in self.baseObjectTypes:
86  if b not in ret:
87  ret.append(b)
88  for b2 in b.allBases():
89  if b2 not in ret:
90  ret.append(b2)
91  return ret
92  def addVariables(self,newvars):
93  currentnames = [v.name for v in self.allVars(True)] # require no conflict with all variables, including mcOnly ones
94  uniquenewvars = []
95  for var in newvars:
96  if var.name in uniquenewvars: raise RuntimeError("Duplicate definition of variable %s while adding variables to object type %s" % (var.name,self.name))
97  uniquenewvars.append(var.name)
98  if var.name not in currentnames:
99  self.variables.append(var)
100  else:
101  raise RuntimeError("Variable %s is already present in object type %s" % (var.name,self.name))
102  def addSubObjects(self,sos):
103  currentnames = [v.name for v in self.subObjects]
104  uniquenewobjs = []
105  for ob in sos:
106  if ob.name in uniquenewobjs: raise RuntimeError("Duplicate definition of sub-object %s while adding it to object type %s" % (ob.name,self.name))
107  uniquenewobjs.append(ob.name)
108  if ob.name not in currentnames:
109  self.subObjects.append(ob)
110  else:
111  raise RuntimeError("Sub-object %s is already present in object type %s" % (ob.name,self.name))
112  self._subObjectVars.clear() # clear and update cache of subobj variables
113  mynewvars = self.allVars(True)
114  mynewvars = self.allVars(False)
115  def removeVariable(self,name):
116  self.variables = [ v for v in self.variables if v.name != name]
117  def __repr__(self):
118  return "<NTupleObjectType[%s]>" % self.name
119 
120 
121 
122 
124  """Type to add a sub-object within an NTupleObjectType, given a name (used as prefix), a function to extract the sub-object and NTupleObjectType to define tye type"""
125  def __init__(self,name,function,objectType,mcOnly=False):
126  self.name = name
127  self.function = function
128  self.objectType = objectType
129  self.mcOnly = mcOnly
130  def __call__(self,object):
131  return self.function(object)
132 
134  """Type defining a set of branches associated to a single object (i.e. an instance of NTupleObjectType)"""
135  def __init__(self, name, objectType, help="", mcOnly=False):
136  self.name = name
137  self.objectType = objectType
138  self.mcOnly = mcOnly
139  self.help = ""
140  def makeBranches(self,treeNumpy,isMC):
141  if not isMC and self.mcOnly: return
142  allvars = self.objectType.allVars(isMC)
143  for v in allvars:
144  h = v.help
145  if self.help: h = "%s for %s" % ( h if h else v.name, self.help )
146  treeNumpy.var("%s_%s" % (self.name, v.name), type=v.type, default=v.default, title=h, filler=v.filler)
147  def fillBranches(self,treeNumpy,object,isMC):
148  if self.mcOnly and not isMC: return
149  allvars = self.objectType.allVars(isMC)
150  for v in allvars:
151  treeNumpy.fill("%s_%s" % (self.name, v.name), v(object))
152  def __repr__(self):
153  return "<NTupleObject[%s]>" % self.name
154 
155 
157  """Type defining a set of branches associated to a list of objects (i.e. an instance of NTupleObjectType)"""
158  def __init__(self, name, objectType, maxlen, help="", mcOnly=False, sortAscendingBy=None, sortDescendingBy=None, filter=None):
159  self.name = name
160  self.objectType = objectType
161  self.maxlen = maxlen
162  self.help = help
163  if objectType.mcOnly and mcOnly == False:
164  #print "collection %s is set to mcOnly since the type %s is mcOnly" % (name, objectType.name)
165  mcOnly = True
166  self.mcOnly = mcOnly
167  if sortAscendingBy != None and sortDescendingBy != None:
168  raise RuntimeError("Cannot specify two sort conditions")
169  self.filter = filter
170  self.sortAscendingBy = sortAscendingBy
171  self.sortDescendingBy = sortDescendingBy
172  def makeBranchesScalar(self,treeNumpy,isMC):
173  if not isMC and self.objectType.mcOnly: return
174  treeNumpy.var("n"+self.name, int)
175  allvars = self.objectType.allVars(isMC)
176  for v in allvars:
177  for i in xrange(1,self.maxlen+1):
178  h = v.help
179  if self.help: h = "%s for %s [%d]" % ( h if h else v.name, self.help, i-1 )
180  treeNumpy.var("%s%d_%s" % (self.name, i, v.name), type=v.type, default=v.default, title=h, filler=v.filler)
181  def makeBranchesVector(self,treeNumpy,isMC):
182  if not isMC and self.objectType.mcOnly: return
183  treeNumpy.var("n"+self.name, int)
184  allvars = self.objectType.allVars(isMC)
185  for v in allvars:
186  h = v.help
187  if self.help: h = "%s for %s" % ( h if h else v.name, self.help )
188  name="%s_%s" % (self.name, v.name) if v.name != "" else self.name
189  treeNumpy.vector(name, "n"+self.name, self.maxlen, type=v.type, default=v.default, title=h, filler=v.filler)
190  def fillBranchesScalar(self,treeNumpy,collection,isMC):
191  if not isMC and self.objectType.mcOnly: return
192  if self.filter != None: collection = [ o for o in collection if self.filter(o) ]
193  if self.sortAscendingBy != None: collection = sorted(collection, key=self.sortAscendingBy)
194  if self.sortDescendingBy != None: collection = sorted(collection, key=self.sortDescendingBy, reverse=True)
195  num = min(self.maxlen,len(collection))
196  treeNumpy.fill("n"+self.name, num)
197  allvars = self.objectType.allVars(isMC)
198  for i in xrange(num):
199  o = collection[i]
200  for v in allvars:
201  treeNumpy.fill("%s%d_%s" % (self.name, i+1, v.name), v(o))
202  def fillBranchesVector(self,treeNumpy,collection,isMC):
203  if not isMC and self.objectType.mcOnly: return
204  if self.filter != None: collection = [ o for o in collection if self.filter(o) ]
205  if self.sortAscendingBy != None: collection = sorted(collection, key=self.sortAscendingBy)
206  if self.sortDescendingBy != None: collection = sorted(collection, key=self.sortDescendingBy, reverse=True)
207  num = min(self.maxlen,len(collection))
208  treeNumpy.fill("n"+self.name, num)
209  allvars = self.objectType.allVars(isMC)
210  for v in allvars:
211  name="%s_%s" % (self.name, v.name) if v.name != "" else self.name
212  treeNumpy.vfill(name, [ v(collection[i]) for i in xrange(num) ])
213  def __repr__(self):
214  return "<NTupleCollection[%s]>" % self.name
215 
216  def get_cpp_declaration(self, isMC):
217  s = []
218  for v in self.objectType.allVars(isMC):
219  s += ["{0} {1}__{2}[{3}];".format(v.type.__name__, self.name, v.name, self.maxlen)]
220  return "\n".join(s)
221 
222  def get_cpp_wrapper_class(self, isMC):
223  s = "class %s {\n" % self.name
224  s += "public:\n"
225  for v in self.objectType.allVars(isMC):
226  s += " {0} {1};\n".format(v.type.__name__, v.name)
227  s += "};\n"
228  return s
229 
230  def get_py_wrapper_class(self, isMC):
231  s = "class %s:\n" % self.name
232  s += " def __init__(self, tree, n):\n"
233  for v in self.objectType.allVars(isMC):
234  if len(v.name)>0:
235  s += " self.{0} = tree.{1}_{2}[n];\n".format(v.name, self.name, v.name)
236  else:
237  s += " self.{0} = tree.{0}[n];\n".format(self.name)
238 
239  s += " @staticmethod\n"
240  s += " def make_array(event):\n"
241  s += " return [{0}(event.input, i) for i in range(event.input.n{0})]\n".format(self.name)
242  return s
243 
244 
def allVars(self, isMC)
Definition: autovars.py:68
def makeBranchesVector(self, treeNumpy, isMC)
Definition: autovars.py:181
def get_cpp_wrapper_class(self, isMC)
Definition: autovars.py:222
def __init__(self, name, objectType, help="", mcOnly=False)
Definition: autovars.py:135
def makeBranchesScalar(self, treeNumpy, isMC)
Definition: autovars.py:172
def fillBranchesScalar(self, treeNumpy, collection, isMC)
Definition: autovars.py:190
def fillBranchesVector(self, treeNumpy, collection, isMC)
Definition: autovars.py:202
def addVariables(self, newvars)
Definition: autovars.py:92
def fillBranches(self, treeNumpy, object, isMC)
Definition: autovars.py:147
def fillBranch(self, treeNumpy, object, isMC)
Definition: autovars.py:28
def removeVariable(self, name)
Definition: autovars.py:115
def __init__(self, name, baseObjectTypes=[], mcOnly=[], variables=[])
Definition: autovars.py:37
def makeBranches(self, treeNumpy, isMC)
Definition: autovars.py:140
T min(T a, T b)
Definition: MathUtil.h:58
def __call__(self, object)
Definition: autovars.py:22
static std::string join(char **cmd)
Definition: RemoteFile.cc:18
def __init__(self, name, function, type=float, help="", default=-99, mcOnly=False, filler=None)
Definition: autovars.py:14
def __init__(self, name, objectType, maxlen, help="", mcOnly=False, sortAscendingBy=None, sortDescendingBy=None, filter=None)
Definition: autovars.py:158
def makeBranch(self, treeNumpy, isMC)
Definition: autovars.py:25
def ownVars(self, isMC)
Definition: autovars.py:49
def get_py_wrapper_class(self, isMC)
Definition: autovars.py:230
def addSubObjects(self, sos)
Definition: autovars.py:102
def __call__(self, object)
Definition: autovars.py:130
def get_cpp_declaration(self, isMC)
Definition: autovars.py:216
def __init__(self, name, function, objectType, mcOnly=False)
Definition: autovars.py:125