1 from PhysicsTools.Heppy.analyzers.core.Analyzer
import Analyzer
2 from PhysicsTools.Heppy.analyzers.core.AutoHandle
import AutoHandle
7 return id
in [6,7,8,17,18]
or (includeLeptons
and 11 <= id
and id < 16)
or (22 <= id
and id < 40)
or id > 1000000
10 """Save the hard-scattering final state of the event: top quarks, gauge & higgs bosons and BSM
11 particles, plus their immediate decay products, and their siblings (in order to get the jets
12 from matched X+jets generation.
13 Incoming partons are not included, by design.
15 In the default configuration, leptons, light quarks and gluons are saved before FSR (a la status 3).
16 Everything else is saved after any radiation, i.e. immediately before the decay.
18 Particles are saved in a list event.generatorSummary, with the index of their mothers ('motherIndex')
19 if the mother is also in the list, and with the pdgId of the mother ('motherId') and grand-mother
20 ('grandmotherId'). Particles also carry their index in the miniAOD genparticles collection ('rawIndex')
21 In addition, a 'sourceId' is set to the pdgId of the heaviest ancestor (or of the particle itself)
22 i.e. in top -> W -> lepton: the lepton sourceId will be 6
23 in tt+W with W -> lepton, the sourceId of the lepton will be 24.
24 sourceId will be 99 for paricles from hard scattering whose mother is light
26 If requested, the full list of genParticles is also produced in event.genParticles (with indices
27 aligned to the miniAOD one). For particles that are in the generatorSummary, the same object is used.
28 An extra index 'genSummaryIndex' will be added to all particles, with the index in the generatorSummary
29 or -1 if the particle is not in the generatorSummary.
31 Also, if requested it creates the splitted collections:
32 event.genHiggsBosons = []
34 event.gennus = [] # prompt neutrinos
35 event.gennusFromTop = [] # Neutrinos from t->W decay
36 event.genleps = [] # leptons from direct decays
37 event.gentauleps = [] # leptons from prompt taus
38 event.gentaus = [] # hadronically-decaying taus (if allGenTaus is False) or all taus (if allGenTaus is True)
39 event.gentopquarks = []
40 event.genbquarks = [] # b quarks from hard event (e.g. from top decays)
41 event.genwzquarks = [] # quarks from W,Z decays
42 event.genbquarksFromTop = []
43 event.genbquarksFromH = []
44 event.genlepsFromTop = [] #mu/ele that have a t->W chain as ancestor, also contained in event.genleps
45 event.genwzquarks and event.genbquarks, might have overlaps
46 event.genbquarksFromTop and event.genbquarksFromH are all contained in event.genbquarks
50 def __init__(self, cfg_ana, cfg_comp, looperName ):
51 super(GeneratorAnalyzer,self).
__init__(cfg_ana,cfg_comp,looperName)
60 self.mchandles[
'genParticles'] = AutoHandle(
'prunedGenParticles',
'std::vector<reco::GenParticle>' )
63 super(GeneratorAnalyzer,self).
beginLoop(setup)
66 verbose = getattr(self.cfg_ana,
'verbose',
False)
67 rawGenParticles = self.mchandles[
'genParticles'].product()
68 good = []; keymap = {};
70 for rawIndex,p
in enumerate(rawGenParticles):
86 if any((p.mother(j).
pdgId() == p.pdgId())
for j
in xrange(p.numberOfMothers())):
91 if any((p.daughter(j).
pdgId() == p.pdgId()
and p.daughter(j).
status() > 2)
for j
in xrange(p.numberOfDaughters())):
112 if not any(mom.daughter(j2).
pdgId() == mom.pdgId()
for j2
in xrange(mom.numberOfDaughters())):
116 elif mom.pdgId() == 25
and any(mom.daughter(j2).
pdgId() == 25
and mom.daughter(j2).numberOfDaughters()==0
for j2
in range(mom.numberOfDaughters())):
118 if abs(mom.pdgId()) == 15:
128 gp.rawIndex = rawIndex
129 keymap[rawIndex] = len(good)
132 for igp,gp
in enumerate(good):
135 gp.genSummaryIndex = igp
136 ancestor =
None if gp.numberOfMothers() == 0
else gp.motherRef(0)
137 while ancestor !=
None and ancestor.isNonnull():
138 if ancestor.key()
in keymap:
139 gp.motherIndex = keymap[ancestor.key()]
140 if ancestor.pdgId() != good[gp.motherIndex].
pdgId():
141 print "Error keying %d: motherIndex %d, ancestor.pdgId %d, good[gp.motherIndex].pdgId() %d " % (igp, gp.motherIndex, ancestor.pdgId(), good[gp.motherIndex].
pdgId())
143 ancestor =
None if ancestor.numberOfMothers() == 0
else ancestor.motherRef(0)
144 if abs(gp.pdgId())
not in [1,2,3,4,5,11,12,13,14,15,16,21]:
145 gp.sourceId = gp.pdgId()
146 if gp.motherIndex != -1:
147 ancestor = good[gp.motherIndex]
148 if ancestor.sourceId != 99
and (ancestor.mass() > gp.mass()
or gp.sourceId == 99):
149 gp.sourceId = ancestor.sourceId
150 event.generatorSummary = good
152 for ip,p
in enumerate(good):
158 p.motherId = moms[0].
pdgId()
160 p.grandmotherId = (gmoms[0].
pdgId()
if len(gmoms)==1
else (0
if len(gmoms)==0
else -9999))
164 p.grandmotherId = -9999
166 print "%3d {%6d}: %+8d %3d : %8.2f %+5.2f %+5.2f : %d %2d : %+8d {%3d}: %s" % ( ip,p.rawIndex,
167 p.pdgId(), p.status(), p.pt(), p.eta(), p.phi(), len(moms), p.numberOfDaughters(),
168 p.motherId, p.motherIndex,
169 " ".
join(
"%d[%d]" % (p.daughter(i).
pdgId(), p.daughter(i).
status())
for i
in xrange(p.numberOfDaughters())))
174 event.genParticles = allGenParticles
177 event.genHiggsBosons = []
178 event.genVBosons = []
180 event.gennusFromTop = []
182 event.gentauleps = []
184 event.gentopquarks = []
185 event.genbquarks = []
186 event.genwzquarks = []
187 event.genbquarksFromTop = []
188 event.genbquarksFromH = []
189 event.genlepsFromTop = []
190 for p
in event.generatorSummary:
193 event.genHiggsBosons.append(p)
195 event.genVBosons.append(p)
196 elif id
in {12,14,16}:
197 event.gennus.append(p)
202 for mom, momid
in momids:
209 event.gennusFromTop.append(p)
213 if abs(p.motherId) == 15:
214 event.gentauleps.append(p)
217 event.genleps.append(p)
221 for mom, momid
in momids:
228 event.genlepsFromTop.append(p)
231 event.gentaus.append(p)
233 event.gentopquarks.append(p)
235 event.genbquarks.append(p)
237 if 6
in momids: event.genbquarksFromTop.append(p)
238 if 25
in momids: event.genbquarksFromH.append(p)
240 event.genwzquarks.append(p)
243 self.readCollections( event.input )
246 if not self.cfg_comp.isMC:
252 import PhysicsTools.HeppyCore.framework.config
as cfg
253 setattr(GeneratorAnalyzer,
"defaultConfig",
254 cfg.Analyzer(GeneratorAnalyzer,
256 stableBSMParticleIds = [ 1000022 ],
260 savePreFSRParticleIds = [ 1,2,3,4,5, 11,12,13,14,15,16, 21 ],
262 makeAllGenParticles =
True,
264 makeSplittedGenLists =
True,
def isNotFromHadronicShower
bool any(const std::vector< T > &v, const T &what)
Abs< T >::type abs(const T &t)
static std::string join(char **cmd)