CMS 3D CMS Logo

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