CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
JetAnalyzer.py
Go to the documentation of this file.
1 import math
2 from PhysicsTools.Heppy.analyzers.core.Analyzer import Analyzer
3 from PhysicsTools.Heppy.analyzers.core.AutoHandle import AutoHandle
4 from PhysicsTools.Heppy.physicsobjects.PhysicsObjects import Jet
5 from PhysicsTools.HeppyCore.utils.deltar import deltaR2, deltaPhi, matchObjectCollection, matchObjectCollection2, bestMatch
6 from PhysicsTools.Heppy.physicsutils.JetReCalibrator import JetReCalibrator
8 
9 from PhysicsTools.Heppy.physicsutils.QGLikelihoodCalculator import QGLikelihoodCalculator
10 
11 def cleanNearestJetOnly(jets,leptons,deltaR):
12  dr2 = deltaR**2
13  good = [ True for j in jets ]
14  for l in leptons:
15  ibest, d2m = -1, dr2
16  for i,j in enumerate(jets):
17  d2i = deltaR2(l.eta(),l.phi(), j.eta(),j.phi())
18  if d2i < d2m:
19  ibest, d2m = i, d2i
20  if ibest != -1: good[ibest] = False
21  return [ j for (i,j) in enumerate(jets) if good[i] == True ]
22 
23 
24 class JetAnalyzer( Analyzer ):
25  """Taken from RootTools.JetAnalyzer, simplified, modified, added corrections """
26  def __init__(self, cfg_ana, cfg_comp, looperName):
27  super(JetAnalyzer,self).__init__(cfg_ana, cfg_comp, looperName)
28  mcGT = cfg_ana.mcGT if hasattr(cfg_ana,'mcGT') else "PHYS14_25_V2"
29  dataGT = cfg_ana.dataGT if hasattr(cfg_ana,'dataGT') else "GR_70_V2_AN1"
30  self.shiftJEC = self.cfg_ana.shiftJEC if hasattr(self.cfg_ana, 'shiftJEC') else 0
31  self.recalibrateJets = self.cfg_ana.recalibrateJets
32  if self.recalibrateJets == "MC" : self.recalibrateJets = self.cfg_comp.isMC
33  elif self.recalibrateJets == "Data": self.recalibrateJets = not self.cfg_comp.isMC
34  elif self.recalibrateJets not in [True,False]: raise RuntimeError, "recalibrateJets must be any of { True, False, 'MC', 'Data' }, while it is %r " % self.recalibrateJets
35  self.doJEC = self.recalibrateJets or (self.shiftJEC != 0)
36  if self.doJEC:
37  if self.cfg_comp.isMC:
38  self.jetReCalibrator = JetReCalibrator(mcGT,"AK4PFchs", False,cfg_ana.jecPath)
39  else:
40  self.jetReCalibrator = JetReCalibrator(dataGT,"AK4PFchs", True,cfg_ana.jecPath)
41  self.doPuId = self.cfg_ana.doPuId if hasattr(self.cfg_ana, 'doPuId') else True
42  self.jetLepDR = self.cfg_ana.jetLepDR if hasattr(self.cfg_ana, 'jetLepDR') else 0.5
43  self.lepPtMin = self.cfg_ana.minLepPt if hasattr(self.cfg_ana, 'minLepPt') else -1
44  self.jetGammaDR = self.cfg_ana.jetGammaDR if hasattr(self.cfg_ana, 'jetGammaDR') else 0.4
45  if(self.cfg_ana.doQG):
46  self.qglcalc = QGLikelihoodCalculator("/afs/cern.ch/user/t/tomc/public/QG_pdfs_13TeV_2014-10-12/pdfQG_AK4chs_antib_NoQC_13TeV.root")
47 
48  def declareHandles(self):
49  super(JetAnalyzer, self).declareHandles()
50  self.handles['jets'] = AutoHandle( self.cfg_ana.jetCol, 'std::vector<pat::Jet>' )
51  self.handles['genJet'] = AutoHandle( 'slimmedGenJets', 'vector<reco::GenJet>' )
52  self.shiftJER = self.cfg_ana.shiftJER if hasattr(self.cfg_ana, 'shiftJER') else 0
53  self.handles['rho'] = AutoHandle( ('fixedGridRhoFastjetAll','',''), 'double' )
54 
55  def beginLoop(self, setup):
56  super(JetAnalyzer,self).beginLoop(setup)
57 
58  def process(self, event):
59  self.readCollections( event.input )
60  rho = float(self.handles['rho'].product()[0])
61  event.rho = rho
62 
63  ## Read jets, if necessary recalibrate and shift MET
64  allJets = map(Jet, self.handles['jets'].product())
65 
66  event.deltaMetFromJEC = [0.,0.]
67  if self.doJEC:
68  #print "\nCalibrating jets %s for lumi %d, event %d" % (self.cfg_ana.jetCol, event.lumi, event.eventId)
69  self.jetReCalibrator.correctAll(allJets, rho, delta=self.shiftJEC, metShift=event.deltaMetFromJEC)
70  event.allJetsUsedForMET = allJets
71 
72  if self.cfg_comp.isMC:
73  event.genJets = [ x for x in self.handles['genJet'].product() ]
74  self.matchJets(event, allJets)
75  if getattr(self.cfg_ana, 'smearJets', False):
76  self.smearJets(event, allJets)
77 
78  ## Apply jet selection
79  event.jets = []
80  event.jetsFailId = []
81  event.jetsAllNoID = []
82  event.jetsIdOnly = []
83  for jet in allJets:
84  if self.testJetNoID( jet ):
85  event.jetsAllNoID.append(jet)
86  if self.testJetID (jet ):
87 
88  if(self.cfg_ana.doQG):
89  self.computeQGvars(jet)
90  jet.qgl = self.qglcalc.computeQGLikelihood(jet, rho)
91 
92 
93  event.jets.append(jet)
94  event.jetsIdOnly.append(jet)
95  else:
96  event.jetsFailId.append(jet)
97  elif self.testJetID (jet ):
98  event.jetsIdOnly.append(jet)
99 
100  ## Clean Jets from leptons
101  leptons = []
102  if hasattr(event, 'selectedLeptons'):
103  leptons = [ l for l in event.selectedLeptons if l.pt() > self.lepPtMin ]
104  if self.cfg_ana.cleanJetsFromTaus and hasattr(event, 'selectedTaus'):
105  leptons = leptons[:] + event.selectedTaus
106  if self.cfg_ana.cleanJetsFromIsoTracks and hasattr(event, 'selectedIsoCleanTrack'):
107  leptons = leptons[:] + event.selectedIsoCleanTrack
108  event.cleanJetsAll = cleanNearestJetOnly(event.jets, leptons, self.jetLepDR)
109  event.cleanJets = [j for j in event.cleanJetsAll if abs(j.eta()) < self.cfg_ana.jetEtaCentral ]
110  event.cleanJetsFwd = [j for j in event.cleanJetsAll if abs(j.eta()) >= self.cfg_ana.jetEtaCentral ]
111 
112  ## Clean Jets from photons
113  photons = []
114  if hasattr(event, 'selectedPhotons'):
115  photons = [ g for g in event.selectedPhotons ]
116  event.gamma_cleanJetsAll = cleanNearestJetOnly(event.cleanJetsAll, photons, self.jetGammaDR)
117  event.gamma_cleanJets = [j for j in event.gamma_cleanJetsAll if abs(j.eta()) < self.cfg_ana.jetEtaCentral ]
118  event.gamma_cleanJetsFwd = [j for j in event.gamma_cleanJetsAll if abs(j.eta()) >= self.cfg_ana.jetEtaCentral ]
119  ###
120 
121 
122  ## Associate jets to leptons
123  leptons = event.inclusiveLeptons if hasattr(event, 'inclusiveLeptons') else event.selectedLeptons
124  jlpairs = matchObjectCollection( leptons, allJets, self.jetLepDR**2)
125 
126  for jet in allJets:
127  jet.leptons = [l for l in jlpairs if jlpairs[l] == jet ]
128 
129  for lep in leptons:
130  jet = jlpairs[lep]
131  if jet is None:
132  lep.jet = lep
133  else:
134  lep.jet = jet
135 
136  if self.cfg_comp.isMC:
137  event.deltaMetFromJetSmearing = [0, 0]
138  for j in event.cleanJetsAll:
139  if hasattr(j, 'deltaMetFromJetSmearing'):
140  event.deltaMetFromJetSmearing[0] += j.deltaMetFromJetSmearing[0]
141  event.deltaMetFromJetSmearing[1] += j.deltaMetFromJetSmearing[1]
142  event.cleanGenJets = cleanNearestJetOnly(event.genJets, event.selectedLeptons, 0.5)
143 
144  #event.nGenJets25 = 0
145  #event.nGenJets25Cen = 0
146  #event.nGenJets25Fwd = 0
147  #for j in event.cleanGenJets:
148  # event.nGenJets25 += 1
149  # if abs(j.eta()) <= 2.4: event.nGenJets25Cen += 1
150  # else: event.nGenJets25Fwd += 1
151 
152  self.jetFlavour(event)
153 
154 
155  return True
156 
157 
158 
159  def testJetID(self, jet):
160  jet.puJetIdPassed = jet.puJetId()
161  jet.pfJetIdPassed = jet.jetID('POG_PFID_Loose')
162  if self.cfg_ana.relaxJetId:
163  return True
164  else:
165  return jet.pfJetIdPassed and (jet.puJetIdPassed or not(self.doPuId))
166 
167  def testJetNoID( self, jet ):
168  # 2 is loose pile-up jet id
169  return jet.pt() > self.cfg_ana.jetPt and \
170  abs( jet.eta() ) < self.cfg_ana.jetEta;
171 
172  def computeQGvars(self, jet):
173 
174  jet.mult = 0
175  sum_weight = 0.
176  sum_pt = 0.
177  sum_deta = 0.
178  sum_dphi = 0.
179  sum_deta2 = 0.
180  sum_detadphi = 0.
181  sum_dphi2 = 0.
182 
183 
184 
185  for ii in range(0, jet.numberOfDaughters()) :
186 
187  part = jet.daughter(ii)
188 
189  usePart = True
190 
191  if part.charge() == 0 : # neutral particles
192 
193  if part.pt() > 1.: jet.mult += 1
194 
195  else : # charged particles
196 
197  jet.mult += 1
198 
199  if part.trackHighPurity()==False: usePart=False
200  if part.fromPV()<=1: usePart=False
201 
202 
203 
204  if usePart:
205  deta = part.eta() - jet.eta()
206  dphi = deltaPhi(part.phi(), jet.phi())
207  partPt = part.pt()
208  weight = partPt*partPt
209  sum_weight += weight
210  sum_pt += partPt
211  sum_deta += deta*weight
212  sum_dphi += dphi*weight
213  sum_deta2 += deta*deta*weight
214  sum_detadphi += deta*dphi*weight
215  sum_dphi2 += dphi*dphi*weight
216 
217 
218 
219 
220  a = 0.
221  b = 0.
222  c = 0.
223 
224  if sum_weight > 0 :
225  jet.ptd = math.sqrt(sum_weight)/sum_pt
226  ave_deta = sum_deta/sum_weight
227  ave_dphi = sum_dphi/sum_weight
228  ave_deta2 = sum_deta2/sum_weight
229  ave_dphi2 = sum_dphi2/sum_weight
230  a = ave_deta2 - ave_deta*ave_deta
231  b = ave_dphi2 - ave_dphi*ave_dphi
232  c = -(sum_detadphi/sum_weight - ave_deta*ave_dphi)
233  else: jet.ptd = 0.
234 
235  delta = math.sqrt(math.fabs((a-b)*(a-b)+4.*c*c))
236 
237  if a+b-delta > 0: jet.axis2 = -math.log(math.sqrt(0.5*(a+b-delta)))
238  else: jet.axis2 = -1.
239 
240 
241  def jetFlavour(self,event):
242  def isFlavour(x,f):
243  id = abs(x.pdgId())
244  if id > 999: return (id/1000)%10 == f
245  if id > 99: return (id/100)%10 == f
246  return id % 100 == f
247 
248 
249 
250  event.bqObjects = [ p for p in event.genParticles if (p.status() == 2 and isFlavour(p,5)) ]
251  event.cqObjects = [ p for p in event.genParticles if (p.status() == 2 and isFlavour(p,4)) ]
252 
253  event.partons = [ p for p in event.genParticles if ((p.status() == 23 or p.status() == 3) and abs(p.pdgId())>0 and (abs(p.pdgId()) in [1,2,3,4,5,21]) ) ]
254  match = matchObjectCollection2(event.cleanJetsAll,
255  event.partons,
256  deltaRMax = 0.3)
257 
258  for jet in event.cleanJetsAll:
259  parton = match[jet]
260  jet.partonId = (parton.pdgId() if parton != None else 0)
261  jet.partonMotherId = (parton.mother(0).pdgId() if parton != None and parton.numberOfMothers()>0 else 0)
262 
263  for jet in event.jets:
264  (bmatch, dr) = bestMatch(jet, event.bqObjects)
265  if dr < 0.4:
266  jet.mcFlavour = 5
267  else:
268  (cmatch, dr) = bestMatch(jet, event.cqObjects)
269  if dr < 0.4:
270  jet.mcFlavour = 4
271  else:
272  jet.mcFlavour = 0
273 
274  event.heaviestQCDFlavour = 5 if len(event.bqObjects) else (4 if len(event.cqObjects) else 1);
275 
276 
277  def matchJets(self, event, jets):
278  match = matchObjectCollection2(jets,
279  event.genbquarks + event.genwzquarks,
280  deltaRMax = 0.3)
281  for jet in jets:
282  gen = match[jet]
283  jet.mcParton = gen
284  jet.mcMatchId = (gen.sourceId if gen != None else 0)
285  jet.mcMatchFlav = (abs(gen.pdgId()) if gen != None else 0)
286 
287  match = matchObjectCollection2(jets,
288  event.genJets,
289  deltaRMax = 0.3)
290  for jet in jets:
291  jet.mcJet = match[jet]
292 
293 
294 
295  def smearJets(self, event, jets):
296  # https://twiki.cern.ch/twiki/bin/viewauth/CMS/TWikiTopRefSyst#Jet_energy_resolution
297  for jet in jets:
298  gen = jet.mcJet
299  if gen != None:
300  genpt, jetpt, aeta = gen.pt(), jet.pt(), abs(jet.eta())
301  # from https://twiki.cern.ch/twiki/bin/view/CMS/JetResolution
302  factor = 1.052 + self.shiftJER*math.hypot(0.012,0.062);
303  if aeta > 2.3: factor = 1.288 + self.shiftJER*math.hypot(0.127,0.154)
304  elif aeta > 1.7: factor = 1.134 + self.shiftJER*math.hypot(0.035,0.066)
305  elif aeta > 1.1: factor = 1.096 + self.shiftJER*math.hypot(0.017,0.063)
306  elif aeta > 0.5: factor = 1.057 + self.shiftJER*math.hypot(0.012,0.056)
307  ptscale = max(0.0, (jetpt + (factor-1)*(jetpt-genpt))/jetpt)
308  #print "get with pt %.1f (gen pt %.1f, ptscale = %.3f)" % (jetpt,genpt,ptscale)
309  jet.deltaMetFromJetSmearing = [ -(ptscale-1)*jet.rawFactor()*jet.px(), -(ptscale-1)*jet.rawFactor()*jet.py() ]
310  if ptscale != 0:
311  jet.setP4(jet.p4()*ptscale)
312  # leave the uncorrected unchanged for sync
313  jet._rawFactorMultiplier *= (1.0/ptscale) if ptscale != 0 else 1
314  #else: print "jet with pt %.1d, eta %.2f is unmatched" % (jet.pt(), jet.eta())
315 
316 
317 
318 setattr(JetAnalyzer,"defaultConfig", cfg.Analyzer(
319  class_object = JetAnalyzer,
320  jetCol = 'slimmedJets',
321  jetPt = 25.,
322  jetEta = 4.7,
323  jetEtaCentral = 2.4,
324  jetLepDR = 0.4,
325  minLepPt = 10,
326  relaxJetId = False,
327  doPuId = False, # Not commissioned in 7.0.X
328  doQG = False,
329  recalibrateJets = False,
330  shiftJEC = 0, # set to +1 or -1 to get +/-1 sigma shifts
331  smearJets = True,
332  shiftJER = 0, # set to +1 or -1 to get +/-1 sigma shifts
333  cleanJetsFromTaus = False,
334  cleanJetsFromIsoTracks = False,
335  jecPath = ""
336  )
337 )
def bestMatch
Definition: deltar.py:133
def matchObjectCollection
Definition: deltar.py:146
def matchObjectCollection2
Definition: deltar.py:161
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double deltaR2(const T1 &t1, const T2 &t2)
Definition: deltaR.h:36
if(conf.exists("allCellsPositionCalc"))