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 random
2 
3 from PhysicsTools.Heppy.analyzers.core.Analyzer import Analyzer
4 from PhysicsTools.Heppy.analyzers.core.AutoHandle import AutoHandle
5 from PhysicsTools.Heppy.physicsobjects.PhysicsObjects import Jet, GenJet
6 
7 from PhysicsTools.HeppyCore.utils.deltar import cleanObjectCollection, matchObjectCollection
8 from PhysicsTools.HeppyCore.statistics.counter import Counter, Counters
9 from PhysicsTools.HeppyCore.utils.deltar import deltaR2
10 
11 from PhysicsTools.Heppy.physicsutils.btagsf_lowercase import BTagSF
12 from PhysicsTools.Heppy.physicsobjects.PhysicsObjects import GenParticle
13 from PhysicsTools.Heppy.utils.cmsswRelease import isNewerThan
14 
16  """Analyze jets ;-)
17 
18  This analyzer filters the jets that do not correspond to the leptons
19  stored in event.selectedLeptons, and puts in the event:
20  - jets: all jets passing the pt and eta cuts
21  - cleanJets: the collection of jets away from the leptons
22  - cleanBJets: the jets passing testBJet, and away from the leptons
23 
24  Example configuration:
25 
26  jetAna = cfg.Analyzer(
27  'JetAnalyzer',
28  jetCol = 'slimmedJets'
29  # cmg jet input collection
30  # pt threshold
31  jetPt = 30,
32  # eta range definition
33  jetEta = 5.0,
34  # seed for the btag scale factor
35  btagSFseed = 0xdeadbeef,
36  # if True, the PF and PU jet ID are not applied, and the jets get flagged
37  relaxJetId = False,
38  )
39  """
40 
41  def __init__(self, cfg_ana, cfg_comp, looperName):
42  super(JetAnalyzer,self).__init__(cfg_ana, cfg_comp, looperName)
43  self.btagSF = BTagSF (cfg_ana.btagSFseed)
44  self.is2012 = isNewerThan('CMSSW_5_2_0')
45 
46  def declareHandles(self):
47  super(JetAnalyzer, self).declareHandles()
48 
49  self.handles['jets'] = AutoHandle( self.cfg_ana.jetCol,
50  'std::vector<pat::Jet>' )
51  if self.cfg_comp.isMC:
52  # and ("BB" in self.cfg_comp.name):
53  self.mchandles['genParticles'] = AutoHandle( 'packedGenParticles',
54  'std::vector<pat::PackedGenParticle>' )
55  self.mchandles['genJets'] = AutoHandle('slimmedGenJets',
56  'std::vector<reco::GenJet>')
57 
58  def beginLoop(self):
59  super(JetAnalyzer,self).beginLoop()
60  self.counters.addCounter('jets')
61  count = self.counters.counter('jets')
62  count.register('all events')
63  count.register('at least 2 good jets')
64  count.register('at least 2 clean jets')
65  count.register('at least 1 b jet')
66  count.register('at least 2 b jets')
67 
68  def process(self, event):
69 
70  self.readCollections( event.input )
71  miniaodjets = self.handles['jets'].product()
72 
73  allJets = []
74  event.jets = []
75  event.bJets = []
76  event.cleanJets = []
77  event.cleanBJets = []
78 
79  leptons = []
80  if hasattr(event, 'selectedLeptons'):
81  leptons = event.selectedLeptons
82 
83  genJets = None
84  if self.cfg_comp.isMC:
85  genJets = map( GenJet, self.mchandles['genJets'].product() )
86 
87  for maodjet in miniaodjets:
88  jet = Jet( maodjet )
89  allJets.append( jet )
90  if self.cfg_comp.isMC and hasattr( self.cfg_comp, 'jetScale'):
91  scale = random.gauss( self.cfg_comp.jetScale,
92  self.cfg_comp.jetSmear )
93  jet.scaleEnergy( scale )
94  if genJets:
95  # Use DeltaR = 0.25 matching like JetMET
96  pairs = matchObjectCollection( [jet], genJets, 0.25*0.25)
97  if pairs[jet] is None:
98  pass
99  else:
100  jet.matchedGenJet = pairs[jet]
101  #Add JER correction for MC jets. Requires gen-jet matching.
102  if self.cfg_comp.isMC and hasattr(self.cfg_ana, 'jerCorr') and self.cfg_ana.jerCorr:
103  self.jerCorrection(jet)
104  #Add JES correction for MC jets.
105  if self.cfg_comp.isMC and hasattr(self.cfg_ana, 'jesCorr'):
106  self.jesCorrection(jet, self.cfg_ana.jesCorr)
107  if self.testJet( jet ):
108  event.jets.append(jet)
109  if self.testBJet(jet):
110  event.bJets.append(jet)
111 
112  self.counters.counter('jets').inc('all events')
113 
114  event.cleanJets, dummy = cleanObjectCollection( event.jets,
115  masks = leptons,
116  deltaRMin = 0.5 )
117  event.cleanBJets, dummy = cleanObjectCollection( event.bJets,
118  masks = leptons,
119  deltaRMin = 0.5 )
120 
121  pairs = matchObjectCollection( leptons, allJets, 0.5*0.5)
122  # associating a jet to each lepton
123  for lepton in leptons:
124  jet = pairs[lepton]
125  if jet is None:
126  lepton.jet = lepton
127  else:
128  lepton.jet = jet
129 
130  # associating a leg to each clean jet
131  invpairs = matchObjectCollection( event.cleanJets, leptons, 99999. )
132  for jet in event.cleanJets:
133  leg = invpairs[jet]
134  jet.leg = leg
135 
136  for jet in event.cleanJets:
137  jet.matchGenParton=999.0
138 
139  if self.cfg_comp.isMC and "BB" in self.cfg_comp.name:
140  genParticles = self.mchandles['genParticles'].product()
141  event.genParticles = map( GenParticle, genParticles)
142  for gen in genParticles:
143  if abs(gen.pdgId())==5 and gen.mother() and abs(gen.mother().pdgId())==21:
144  for jet in event.cleanJets:
145  dR=deltaR2(jet.eta(), jet.phi(), gen.eta(), gen.phi() )
146  if dR<jet.matchGenParton:
147  jet.matchGenParton=dR
148 
149  event.jets30 = [jet for jet in event.jets if jet.pt()>30]
150  event.cleanJets30 = [jet for jet in event.cleanJets if jet.pt()>30]
151  if len( event.jets30 )>=2:
152  self.counters.counter('jets').inc('at least 2 good jets')
153  if len( event.cleanJets30 )>=2:
154  self.counters.counter('jets').inc('at least 2 clean jets')
155  if len(event.cleanBJets)>0:
156  self.counters.counter('jets').inc('at least 1 b jet')
157  if len(event.cleanBJets)>1:
158  self.counters.counter('jets').inc('at least 2 b jets')
159  return True
160 
161  def jerCorrection(self, jet):
162  ''' Adds JER correction according to first method at
163  https://twiki.cern.ch/twiki/bin/view/CMS/JetResolution
164 
165  Requires some attention when genJet matching fails.
166  '''
167  if not hasattr(jet, 'matchedGenJet'):
168  return
169  #import pdb; pdb.set_trace()
170  corrections = [0.052, 0.057, 0.096, 0.134, 0.288]
171  maxEtas = [0.5, 1.1, 1.7, 2.3, 5.0]
172  eta = abs(jet.eta())
173  for i, maxEta in enumerate(maxEtas):
174  if eta < maxEta:
175  pt = jet.pt()
176  deltaPt = (pt - jet.matchedGenJet.pt()) * corrections[i]
177  totalScale = (pt + deltaPt) / pt
178 
179  if totalScale < 0.:
180  totalScale = 0.
181  jet.scaleEnergy(totalScale)
182  break
183 
184  def jesCorrection(self, jet, scale=0.):
185  ''' Adds JES correction in number of sigmas (scale)
186  '''
187  # Do nothing if nothing to change
188  if scale == 0.:
189  return
190  unc = jet.uncOnFourVectorScale()
191  totalScale = 1. + scale * unc
192  if totalScale < 0.:
193  totalScale = 0.
194  jet.scaleEnergy(totalScale)
195 
196  def testJetID(self, jet):
197  jet.puJetIdPassed = jet.puJetId()
198  jet.pfJetIdPassed = jet.jetID("POG_PFID_Loose")
199  if self.cfg_ana.relaxJetId:
200  return True
201  else:
202  return jet.puJetIdPassed and jet.pfJetIdPassed
203 
204 
205  def testJet( self, jet ):
206  return jet.pt() > self.cfg_ana.jetPt and \
207  abs( jet.eta() ) < self.cfg_ana.jetEta and \
208  self.testJetID(jet)
209 
210  def testBJet(self, jet):
211  # medium csv working point
212  # https://twiki.cern.ch/twiki/bin/viewauth/CMS/BTagPerformanceOP#B_tagging_Operating_Points_for_3
213  jet.btagMVA = jet.btag("combinedSecondaryVertexBJetTags")
214  jet.btagFlag = self.btagSF.BTagSFcalc.isbtagged(
215  jet.pt(),
216  jet.eta(),
217  jet.btag("combinedSecondaryVertexBJetTags"),
218  abs(jet.partonFlavour()),
219  not self.cfg_comp.isMC,
220  0,0,
221  self.is2012
222  )
223  return jet.pt()>20 and \
224  abs( jet.eta() ) < 2.4 and \
225  self.testJetID(jet)
def cleanObjectCollection
Definition: deltar.py:65
def matchObjectCollection
Definition: deltar.py:98
Definition: Jet.py:1
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double deltaR2(const T1 &t1, const T2 &t2)
Definition: deltaR.h:36