CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
PhotonAnalyzer.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.Photon import Photon
13 
14 from PhysicsTools.HeppyCore.utils.deltar import deltaR, deltaPhi, bestMatch, matchObjectCollection3
15 
16 import PhysicsTools.HeppyCore.framework.config as cfg
17 
18 
19 class PhotonAnalyzer( Analyzer ):
20 
21 
22  def __init__(self, cfg_ana, cfg_comp, looperName ):
23  super(PhotonAnalyzer,self).__init__(cfg_ana,cfg_comp,looperName)
24  self.etaCentral = self.cfg_ana.etaCentral if hasattr(self.cfg_ana, 'etaCentral') else 9999
25 
26  def declareHandles(self):
27  super(PhotonAnalyzer, self).declareHandles()
28 
29  #----------------------------------------
30  # DECLARATION OF HANDLES OF PHOTONS STUFF
31  #----------------------------------------
32 
33  self.handles['photons'] = AutoHandle( self.cfg_ana.photons,'std::vector<pat::Photon>')
34  self.mchandles['packedGen'] = AutoHandle( 'packedGenParticles', 'std::vector<pat::PackedGenParticle>' )
35  self.handles['packedCandidates'] = AutoHandle( 'packedPFCandidates', 'std::vector<pat::PackedCandidate>')
36  self.handles['jets'] = AutoHandle( "slimmedJets", 'std::vector<pat::Jet>' )
37 
38 
39  def beginLoop(self, setup):
40  super(PhotonAnalyzer,self).beginLoop(setup)
41  self.counters.addCounter('events')
42  count = self.counters.counter('events')
43  count.register('all events')
44  count.register('has >=1 gamma at preselection')
45  count.register('has >=1 selected gamma')
46 
47  def makePhotons(self, event):
48  event.allphotons = map( Photon, self.handles['photons'].product() )
49  event.allphotons.sort(key = lambda l : l.pt(), reverse = True)
50 
51  event.selectedPhotons = []
52  event.selectedPhotonsCentral = []
53 
54  foundPhoton = False
55  for gamma in event.allphotons:
56  if gamma.pt() < self.cfg_ana.ptMin: continue
57  if abs(gamma.eta()) > self.cfg_ana.etaMax: continue
58  foundPhoton = True
59 
60  def idWP(gamma,X):
61  """Create an integer equal to 1-2-3 for (loose,medium,tight)"""
62 
63  id=0
64  if gamma.photonID(X%"Loose"):
65  id=1
66  #if gamma.photonID(X%"Medium"):
67  # id=2
68  if gamma.photonID(X%"Tight"):
69  id=3
70  return id
71 
72  gamma.idCutBased = idWP(gamma, "PhotonCutBasedID%s")
73 
74 
75  keepThisPhoton = True
76  if self.cfg_ana.gammaID=="PhotonCutBasedIDLoose_CSA14" :
77  keepThisPhoton = gamma.photonIDCSA14("PhotonCutBasedIDLoose_CSA14")
78  gamma.idCutBased = keepThisPhoton
79  # we're keeing sigmaietaieta sidebands, but the id is false for them:
80 
81  if abs(gamma.eta())< 1.479 and gamma.full5x5_sigmaIetaIeta()>0.010 :
82  gamma.idCutBased = False
83  if abs(gamma.eta())>=1.479 and gamma.full5x5_sigmaIetaIeta()>0.0321 :
84  gamma.idCutBased = False
85  if gamma.hasPixelSeed():
86  keepThisPhoton = False
87  gamma.idCutBased = 0
88  else:
89  # Reading from miniAOD directly
90  # keepThisPhoton = gamma.photonID(self.cfg_ana.gammaID)
91 
92  # implement cut based ID with CMGTools
93  keepThisPhoton = gamma.passPhotonID(self.cfg_ana.gammaID)
94 
95  if keepThisPhoton:
96  event.selectedPhotons.append(gamma)
97 
98  if keepThisPhoton and abs(gamma.eta()) < self.etaCentral:
99  event.selectedPhotonsCentral.append(gamma)
100 
101  event.selectedPhotons.sort(key = lambda l : l.pt(), reverse = True)
102  event.selectedPhotonsCentral.sort(key = lambda l : l.pt(), reverse = True)
103 
104  self.counters.counter('events').inc('all events')
105  if foundPhoton: self.counters.counter('events').inc('has >=1 gamma at preselection')
106  if len(event.selectedPhotons): self.counters.counter('events').inc('has >=1 selected gamma')
107 
108  def matchPhotons(self, event):
109  event.genPhotons = [ x for x in event.genParticles if x.status() == 1 and abs(x.pdgId()) == 22 ]
110  event.genPhotonsWithMom = [ x for x in event.genPhotons if x.numberOfMothers()>0 ]
111  event.genPhotonsWithoutMom = [ x for x in event.genPhotons if x.numberOfMothers()==0 ]
112  event.genPhotonsMatched = [ x for x in event.genPhotonsWithMom if abs(x.mother(0).pdgId())<23 or x.mother(0).pdgId()==2212 ]
113  match = matchObjectCollection3(event.allphotons, event.genPhotonsMatched, deltaRMax = 0.1)
114  matchNoMom = matchObjectCollection3(event.allphotons, event.genPhotonsWithoutMom, deltaRMax = 0.1)
115  packedGenParts = [ p for p in self.mchandles['packedGen'].product() if abs(p.eta()) < 3.1 ]
116  for gamma in event.allphotons:
117  gen = match[gamma]
118  gamma.mcGamma = gen
119  if gen and gen.pt()>=0.5*gamma.pt() and gen.pt()<=2.*gamma.pt():
120  gamma.mcMatchId = 22
121  sumPt03 = 0.;
122  sumPt04 = 0.;
123  for part in packedGenParts:
124  if abs(part.pdgId())==12: continue # exclude neutrinos
125  if abs(part.pdgId())==14: continue
126  if abs(part.pdgId())==16: continue
127  if abs(part.pdgId())==18: continue
128  deltar = deltaR(gen.eta(), gen.phi(), part.eta(), part.phi())
129  if deltar <= 0.3:
130  sumPt03 += part.pt()
131  if deltar <= 0.4:
132  sumPt04 += part.pt()
133  sumPt03 -= gen.pt()
134  sumPt04 -= gen.pt()
135  if sumPt03<0. : sumPt03=0.
136  if sumPt04<0. : sumPt04=0.
137  gamma.genIso03 = sumPt03
138  gamma.genIso04 = sumPt04
139  else:
140  genNoMom = matchNoMom[gamma]
141  if genNoMom:
142  gamma.mcMatchId = 7
143  sumPt03 = 0.;
144  sumPt04 = 0.;
145  for part in packedGenParts:
146  if abs(part.pdgId())==12: continue # exclude neutrinos
147  if abs(part.pdgId())==14: continue
148  if abs(part.pdgId())==16: continue
149  if abs(part.pdgId())==18: continue
150  deltar = deltaR(genNoMom.eta(), genNoMom.phi(), part.eta(), part.phi());
151  if deltar <= 0.3:
152  sumPt03 += part.pt()
153  if deltar <= 0.4:
154  sumPt04 += part.pt()
155  sumPt03 -= genNoMom.pt()
156  sumPt04 -= genNoMom.pt()
157  if sumPt03<0. : sumPt03=0.
158  if sumPt04<0. : sumPt04=0.
159  gamma.genIso03 = sumPt03
160  gamma.genIso04 = sumPt04
161  else:
162  gamma.mcMatchId = 0
163  gamma.genIso03 = -1.
164  gamma.genIso04 = -1.
165 
166 
167 
168 
169 
170  def checkMatch( self, eta, phi, particles, deltar ):
171 
172  for part in particles:
173  if deltaR(eta, phi, part.eta(), part.phi()) < deltar:
174  return True
175 
176  return False
177 
178 
179 
180 
181 
182  def computeRandomCone( self, event, eta, phi, deltarmax, charged, jets, photons ):
183 
184  if self.checkMatch( eta, phi, jets, 2.*deltarmax ):
185  return -1.
186 
187  if self.checkMatch( eta, phi, photons, 2.*deltarmax ):
188  return -1.
189 
190  if self.checkMatch( eta, phi, event.selectedLeptons, deltarmax ):
191  return -1.
192 
193  iso = 0.
194 
195  for part in charged:
196  if deltaR(eta, phi, part.eta(), part.phi()) > deltarmax : continue
197  #if deltaR(eta, phi, part.eta(), part.phi()) < 0.02: continue
198  iso += part.pt()
199 
200  return iso
201 
202 
203 
204 
205 
206 
207  def randomCone( self, event ):
208 
209  patcands = self.handles['packedCandidates'].product()
210  jets = self.handles['jets'].product()
211 
212  charged = [ p for p in patcands if ( p.charge() != 0 and abs(p.pdgId())>20 and abs(p.dz())<=0.1 and p.fromPV()>1 and p.trackHighPurity() ) ]
213  photons10 = [ p for p in patcands if ( p.pdgId() == 22 and p.pt()>10. ) ]
214  jets20 = [ j for j in jets if j.pt() > 20 and abs(j.eta())<2.5 ]
215 
216  for gamma in event.allphotons:
217 
218  etaPhot = gamma.eta()
219  phiPhot = gamma.eta()
220  pi = 3.14159
221  phiRC = phiPhot + 0.5*pi
222  while phiRC>pi:
223  phiRC -= 2.*pi
224 
225 
226  gamma.chHadIsoRC03 = self.computeRandomCone( event, etaPhot, phiRC, 0.3, charged, jets20, photons10 )
227  gamma.chHadIsoRC04 = self.computeRandomCone( event, etaPhot, phiRC, 0.4, charged, jets20, photons10 )
228 
229 
230  #try other side
231  phiRC = phiPhot - 0.5*pi
232  while phiRC<-pi:
233  phiRC += 2.*pi
234 
235  if gamma.chHadIsoRC03<0. : gamma.chHadIsoRC03 = self.computeRandomCone( event, etaPhot, phiRC, 0.3, charged, jets20, photons10 )
236  if gamma.chHadIsoRC04<0. : gamma.chHadIsoRC04 = self.computeRandomCone( event, etaPhot, phiRC, 0.4, charged, jets20, photons10 )
237 
238 
239 
240 
241  def printInfo(self, event):
242  print '----------------'
243  if len(event.selectedPhotons)>0:
244  print 'lenght: ',len(event.selectedPhotons)
245  print 'gamma candidate pt: ',event.selectedPhotons[0].pt()
246  print 'gamma candidate eta: ',event.selectedPhotons[0].eta()
247  print 'gamma candidate phi: ',event.selectedPhotons[0].phi()
248  print 'gamma candidate mass: ',event.selectedPhotons[0].mass()
249  print 'gamma candidate HoE: ',event.selectedPhotons[0].hOVERe()
250  print 'gamma candidate r9: ',event.selectedPhotons[0].full5x5_r9()
251  print 'gamma candidate sigmaIetaIeta: ',event.selectedPhotons[0].full5x5_sigmaIetaIeta()
252  print 'gamma candidate had iso: ',event.selectedPhotons[0].chargedHadronIso()
253  print 'gamma candidate neu iso: ',event.selectedPhotons[0].neutralHadronIso()
254  print 'gamma candidate gamma iso: ',event.selectedPhotons[0].photonIso()
255  print 'gamma idCutBased',event.selectedPhotons[0].idCutBased
256 
257 
258  def process(self, event):
259  self.readCollections( event.input )
260  self.makePhotons(event)
261 # self.printInfo(event)
262 
263  if self.cfg_ana.do_randomCone:
264  self.randomCone(event)
265 
266  if not self.cfg_comp.isMC:
267  return True
268 
269  if self.cfg_ana.do_mc_match and hasattr(event, 'genParticles'):
270  self.matchPhotons(event)
271 
272 
273  return True
274 
275 
276 setattr(PhotonAnalyzer,"defaultConfig",cfg.Analyzer(
277  class_object=PhotonAnalyzer,
278  photons='slimmedPhotons',
279  ptMin = 20,
280  etaMax = 2.5,
281  gammaID = "PhotonCutBasedIDLoose_CSA14",
282  do_mc_match = True,
283  do_randomCone = False,
284  )
285 )
286 
T eta() const
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double deltaR(double eta1, double eta2, double phi1, double phi2)
Definition: TreeUtility.cc:17
def matchObjectCollection3
Definition: deltar.py:41
Definition: DDAxes.h:10