CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
IsoTrackAnalyzer.py
Go to the documentation of this file.
1 import operator
2 import itertools
3 import copy
4 import types
5 
6 from ROOT import TLorentzVector
7 
8 from PhysicsTools.Heppy.analyzers.core.Analyzer import Analyzer
9 from PhysicsTools.HeppyCore.framework.event import Event
10 from PhysicsTools.HeppyCore.statistics.counter import Counter, Counters
11 from PhysicsTools.Heppy.analyzers.core.AutoHandle import AutoHandle
12 from PhysicsTools.Heppy.physicsobjects.Lepton import Lepton
13 from PhysicsTools.Heppy.physicsobjects.Tau import Tau
14 from PhysicsTools.Heppy.physicsobjects.IsoTrack import IsoTrack
15 
16 from PhysicsTools.HeppyCore.utils.deltar import deltaR, deltaPhi, bestMatch , matchObjectCollection3
17 
18 import PhysicsTools.HeppyCore.framework.config as cfg
19 
20 from ROOT import heppy
21 
22 
23 
24 
25 def mtw(x1,x2):
26  import math
27  return math.sqrt(2*x1.pt()*x2.pt()*(1-math.cos(x1.phi()-x2.phi())))
28 
29 def makeNearestLeptons(leptons,track, event):
30 
31  minDeltaR = 99999
32 
33  nearestLepton = []
34  ibest=-1
35  for i,lepton in enumerate(leptons):
36  minDeltaRtemp=deltaR(lepton.eta(),lepton.phi(),track.eta(),track.phi())
37  if minDeltaRtemp < minDeltaR:
38  minDeltaR = minDeltaRtemp
39  ibest=i
40 
41  if len(leptons) > 0 and ibest!=-1:
42  nearestLepton.append(leptons[ibest])
43 
44  return nearestLepton
45 
46 class IsoTrackAnalyzer( Analyzer ):
47 
48  def __init__(self, cfg_ana, cfg_comp, looperName ):
49  super(IsoTrackAnalyzer,self).__init__(cfg_ana,cfg_comp,looperName)
51 
52  self.doIsoAnnulus = getattr(cfg_ana, 'doIsoAnnulus', False)
53 
54 
55  #----------------------------------------
56  # DECLARATION OF HANDLES OF LEPTONS STUFF
57  #----------------------------------------
58  def declareHandles(self):
59  super(IsoTrackAnalyzer, self).declareHandles()
60  self.handles['met'] = AutoHandle( 'slimmedMETs', 'std::vector<pat::MET>' )
61  self.handles['packedCandidates'] = AutoHandle( 'packedPFCandidates', 'std::vector<pat::PackedCandidate>')
62 
63  def beginLoop(self, setup):
64  super(IsoTrackAnalyzer,self).beginLoop(setup)
65  self.counters.addCounter('events')
66  count = self.counters.counter('events')
67  count.register('all events')
68  count.register('has >=1 selected Track')
69  count.register('has >=1 selected Iso Track')
70 
71  #------------------
72  # MAKE LIST
73  #------------------
74  def makeIsoTrack(self, event):
75 
76  event.selectedIsoTrack = []
77  event.selectedIsoCleanTrack = []
78  #event.preIsoTrack = []
79 
80  patcands = self.handles['packedCandidates'].product()
81 
82  charged = [ p for p in patcands if ( p.charge() != 0 and p.fromPV() > 1 ) ]
83 
84  self.IsoTrackIsolationComputer.setPackedCandidates(patcands, 1, 9999, 9999.)
85 
86 
87  alltrack = map( IsoTrack, charged )
88 
89 
90  for track in alltrack:
91 
92  if ( abs(track.dz()) > self.cfg_ana.dzMax ): continue
93  if ( (abs(track.pdgId())!=11) and (abs(track.pdgId())!=13) and (track.pt() < self.cfg_ana.ptMin) ): continue
94  if ( track.pt() < self.cfg_ana.ptMinEMU ): continue
95 
96  foundNonIsoTrack = False
97 
98 ## ===> require is not the leading lepton and opposite to the leading lepton
99  if( (self.cfg_ana.doSecondVeto) and len(event.selectedLeptons)>0) :
100  if( deltaR(event.selectedLeptons[0].eta(), event.selectedLeptons[0].phi(), track.eta(), track.phi()) <0.01) : continue
101  if ( (abs(track.pdgId())!=11) and (abs(track.pdgId())!=13) and (track.charge()*event.selectedLeptons[0].charge()) ): continue
102 
103 
104 ## ===> Redundant:: require the Track Candidate with a minimum dz
105  track.associatedVertex = event.goodVertices[0] if len(event.goodVertices)>0 else event.vertices[0]
106 
107 ## ===> compute the isolation and find the most isolated track
108 
109  isoSum = self.IsoTrackIsolationComputer.chargedAbsIso(track.physObj, self.cfg_ana.isoDR, 0., self.cfg_ana.ptPartMin)
110  if( abs(track.pdgId())==211 ): isoSum = isoSum - track.pt() #BM: this is an ugly hack and it is error prone. It needs to be fixed using the addVeto method properly
111 
112  if self.cfg_ana.doRelIsolation:
113  relIso = (isoSum)/track.pt()
114  if ( (abs(track.pdgId())!=11) and (abs(track.pdgId())!=13) and (relIso > self.cfg_ana.MaxIsoSum) ): continue
115  elif((relIso > self.cfg_ana.MaxIsoSumEMU)): continue
116  else:
117  if(isoSum > (self.cfg_ana.maxAbsIso)): continue
118 
119  if self.doIsoAnnulus:
120  self.attachIsoAnnulus04(track)
121 
122  track.absIso = isoSum
123 
124  #### store a preIso track
125  #event.preIsoTrack.append(track)
126 
127 # if (isoSum < minIsoSum ) :
128  if self.cfg_ana.doRelIsolation or (track.absIso < min(0.2*track.pt(), self.cfg_ana.maxAbsIso)):
129  event.selectedIsoTrack.append(track)
130 
131  if self.cfg_ana.doPrune:
132  myMet = self.handles['met'].product()[0]
133  mtwIsoTrack = mtw(track, myMet)
134  if mtwIsoTrack < 100:
135  if abs(track.pdgId()) == 11 or abs(track.pdgId()) == 13:
136  if track.pt()>5 and track.absIso/track.pt()<0.2:
137 
138  myLeptons = [ l for l in event.selectedLeptons if l.pt() > 10 ]
139  nearestSelectedLeptons = makeNearestLeptons(myLeptons,track, event)
140  if len(nearestSelectedLeptons) > 0:
141  for lep in nearestSelectedLeptons:
142  if deltaR(lep.eta(), lep.phi(), track.eta(), track.phi()) > 0.01:
143  event.selectedIsoCleanTrack.append(track)
144  else:
145  event.selectedIsoCleanTrack.append(track)
146 
147 
148 
149 ## alltrack = map( IsoTrack, charged )
150 
151 ## for track in alltrack:
152 ##
153 ## foundNonIsoTrack = False
154 ##
155 #### ===> require Track Candidate above some pt and charged
156 ## if ( (abs(track.pdgId())!=11) and (abs(track.pdgId())!=13) and (track.pt() < self.cfg_ana.ptMin) ): continue
157 ## if ( track.pt() < self.cfg_ana.ptMinEMU ): continue
158 ##
159 ##
160 #### ===> require is not the leading lepton and opposite to the leading lepton
161 ## if( (self.cfg_ana.doSecondVeto) and len(event.selectedLeptons)>0) :
162 ## if( deltaR(event.selectedLeptons[0].eta(), event.selectedLeptons[0].phi(), track.eta(), track.phi()) <0.01) : continue
163 ## if ( (abs(track.pdgId())!=11) and (abs(track.pdgId())!=13) and (track.charge()*event.selectedLeptons[0].charge()) ): continue
164 ##
165 #### ===> Redundant:: require the Track Candidate with a minimum dz
166 ## track.associatedVertex = event.goodVertices[0]
167 ##
168 #### ===> compute the isolation and find the most isolated track
169 ##
170 ## othertracks = [ p for p in charged if( deltaR(p.eta(), p.phi(), track.eta(), track.phi()) < self.cfg_ana.isoDR and p.pt()>self.cfg_ana.ptPartMin ) ]
171 ## #othertracks = alltrack
172 ##
173 ## isoSum=0
174 ## for part in othertracks:
175 ## #### ===> skip pfcands with a pt min (this should be 0)
176 ## #if part.pt()<self.cfg_ana.ptPartMin : continue
177 ## #### ===> skip pfcands outside the cone (this should be 0.3)
178 ## #if deltaR(part.eta(), part.phi(), track.eta(), track.phi()) > self.cfg_ana.isoDR : continue
179 ## isoSum += part.pt()
180 ## ### break the loop to save time
181 ## if(isoSum > (self.cfg_ana.maxAbsIso + track.pt())):
182 ## foundNonIsoTrack = True
183 ## break
184 ##
185 ## if foundNonIsoTrack: continue
186 ##
187 ## ## reset
188 ## #isoSum=0
189 ## #for part in othertracks :
190 ## #### ===> skip pfcands with a pt min (this should be 0)
191 ## # if part.pt()<self.cfg_ana.ptPartMin : continue
192 ## #### ===> skip pfcands outside the cone (this should be 0.3)
193 ## # if deltaR(part.eta(), part.phi(), track.eta(), track.phi()) > self.cfg_ana.isoDR : continue
194 ## # isoSum += part.pt()
195 ##
196 ## # ### isoSum = isoSum/track.pt() ## <--- this is for relIso
197 ##
198 ## ### ===> the sum should not contain the track candidate
199 ##
200 ## track.absIso = isoSum - track.pt()
201 ##
202 ## #### store a preIso track
203 ## #event.preIsoTrack.append(track)
204 ##
205 ### if (isoSum < minIsoSum ) :
206 ## if(track.absIso < min(0.2*track.pt(), self.cfg_ana.maxAbsIso)):
207 ## event.selectedIsoTrack.append(track)
208 ##
209 ## if self.cfg_ana.doPrune:
210 ## myMet = self.handles['met'].product()[0]
211 ## mtwIsoTrack = mtw(track, myMet)
212 ## if mtwIsoTrack < 100:
213 ## if abs(track.pdgId()) == 11 or abs(track.pdgId()) == 13:
214 ## if track.pt()>5 and track.absIso/track.pt()<0.2:
215 ##
216 ## myLeptons = [ l for l in event.selectedLeptons if l.pt() > 10 ]
217 ## nearestSelectedLeptons = makeNearestLeptons(myLeptons,track, event)
218 ## if len(nearestSelectedLeptons) > 0:
219 ## for lep in nearestSelectedLeptons:
220 ## if deltaR(lep.eta(), lep.phi(), track.eta(), track.phi()) > 0.1:
221 ## event.selectedIsoCleanTrack.append(track)
222 ## else:
223 ## event.selectedIsoCleanTrack.append(track)
224 
225  event.selectedIsoTrack.sort(key = lambda l : l.pt(), reverse = True)
226  event.selectedIsoCleanTrack.sort(key = lambda l : l.pt(), reverse = True)
227 
228  self.counters.counter('events').inc('all events')
229  #if(len(event.preIsoTrack)): self.counters.counter('events').inc('has >=1 selected Track')
230  if(len(event.selectedIsoTrack)): self.counters.counter('events').inc('has >=1 selected Iso Track')
231 
232 
233  def attachIsoAnnulus04(self, mu):
234  mu.absIsoAnCharged = self.IsoTrackIsolationComputer.chargedAbsIso (mu.physObj, 0.4, self.cfg_ana.isoDR, 0.0,self.IsoTrackIsolationComputer.selfVetoNone)
235  mu.absIsoAnPho = self.IsoTrackIsolationComputer.photonAbsIsoRaw (mu.physObj, 0.4, self.cfg_ana.isoDR, 0.0,self.IsoTrackIsolationComputer.selfVetoNone)
236  mu.absIsoAnNHad = self.IsoTrackIsolationComputer.neutralHadAbsIsoRaw(mu.physObj, 0.4, self.cfg_ana.isoDR, 0.0,self.IsoTrackIsolationComputer.selfVetoNone)
237  mu.absIsoAnPU = self.IsoTrackIsolationComputer.puAbsIso (mu.physObj, 0.4, self.cfg_ana.isoDR, 0.0,self.IsoTrackIsolationComputer.selfVetoNone)
238  mu.absIsoAnNeutral = max(0.0, mu.absIsoAnPho + mu.absIsoAnNHad - 0.5*mu.absIsoAnPU)
239 
240  mu.absIsoAn04 = mu.absIsoAnCharged + mu.absIsoAnNeutral
241  mu.relIsoAn04 = mu.absIsoAn04/mu.pt()
242 
243 
244  def matchIsoTrack(self, event):
245  matchTau = matchObjectCollection3(event.selectedIsoTrack, event.gentaus + event.gentauleps + event.genleps, deltaRMax = 0.5)
246  for lep in event.selectedIsoTrack:
247  gen = matchTau[lep]
248  lep.mcMatchId = 1 if gen else 0
249 
250 
251  def printInfo(self, event):
252  print 'event to Veto'
253  print '----------------'
254 
255  if len(event.selectedIsoTrack)>0:
256  print 'lenght: ',len(event.selectedIsoTrack)
257  print 'track candidate pt: ',event.selectedIsoTrack[0].pt()
258  print 'track candidate eta: ',event.selectedIsoTrack[0].eta()
259  print 'track candidate phi: ',event.selectedIsoTrack[0].phi()
260  print 'track candidate mass: ',event.selectedIsoTrack[0].mass()
261  print 'pdgId candidate : ',event.selectedIsoTrack[0].pdgId()
262  print 'dz: ',event.selectedIsoTrack[0].dz()
263  print 'iso: ',event.selectedIsoTrack[0].absIso
264  print 'matchId: ',event.selectedIsoTrack[0].mcMatchId
265 
266 # for lepton in event.selectedLeptons:
267 # print 'good lepton type: ',lepton.pdgId()
268 # print 'pt: ',lepton.pt()
269 
270 # for tau in event.selectedTaus:
271 # print 'good lepton type: ',tau.pdgId()
272 # print 'pt: ',tau.pt()
273 
274  print '----------------'
275 
276 
277  def process(self, event):
278 
279  if self.cfg_ana.setOff:
280  return True
281 
282  self.readCollections( event.input )
283  self.makeIsoTrack(event)
284 
285  if len(event.selectedIsoTrack)==0 : return True
286 
287 ## event.pdgIdIsoTrack.append(event.selectedIsoTrack[0].pdgId())
288 ## event.isoIsoTrack.append(minIsoSum)
289 ## event.dzIsoTrack.append(abs(dz(event.selectedIsoTrack[0])))
290 
291 ### ===> do matching
292 
293  if not self.cfg_comp.isMC:
294  return True
295 
296  if hasattr(event, 'gentaus') and hasattr(event, 'gentauleps') and hasattr(event, 'genleps') and self.cfg_ana.do_mc_match :
297  self.matchIsoTrack(event)
298 
299 ### self.printInfo(event)
300 
301 ### ===> do veto if needed
302 
303 # if (self.cfg_ana.doSecondVeto and (event.selectedIsoTrack[0].pdgId()!=11) and (event.selectedIsoTrack[0].pdgId()!=12) and event.isoIsoTrack < self.cfg_ana.MaxIsoSum ) :
304 ### self.printInfo(event)
305 # return False
306 
307 # if ((self.cfg_ana.doSecondVeto and event.selectedIsoTrack[0].pdgId()==11 or event.selectedIsoTrack[0].pdgId()==12) and event.isoIsoTrack < self.cfg_ana.MaxIsoSumEMU ) :
308 ## self.printInfo(event)
309 # return False
310 
311 
312  return True
313 
314 
315 setattr(IsoTrackAnalyzer,"defaultConfig",cfg.Analyzer(
316  class_object=IsoTrackAnalyzer,
317  setOff=True,
318  #####
319  candidates='packedPFCandidates',
320  candidatesTypes='std::vector<pat::PackedCandidate>',
321  ptMin = 5, # for pion
322  ptMinEMU = 5, # for EMU
323  dzMax = 0.1,
324  #####
325  isoDR = 0.3,
326  ptPartMin = 0,
327  dzPartMax = 0.1,
328  maxAbsIso = 8,
329  #####
330  doRelIsolation = False,
331  MaxIsoSum = 0.1, ### unused
332  MaxIsoSumEMU = 0.2, ### unused
333  doSecondVeto = False,
334  #####
335  doIsoAnnulus= False,
336  ###
337  doPrune = True,
338  do_mc_match = True, # note: it will in any case try it only on MC, not on data
339  )
340 )
def attachIsoAnnulus04
alltrack = map( IsoTrack, charged )
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
T min(T a, T b)
Definition: MathUtil.h:58
double deltaR(double eta1, double eta2, double phi1, double phi2)
Definition: TreeUtility.cc:17
if(dp >Float(M_PI)) dp-
def matchObjectCollection3
Definition: deltar.py:41