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