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.genleps = [] # leptons from direct decays
36 event.gentauleps = [] # leptons from prompt taus
37 event.gentaus = [] # hadronically-decaying taus (if allGenTaus is False) or all taus (if allGenTaus is True)
38 event.gentopquarks = []
39 event.genbquarks = [] # b quarks from hard event (e.g. from top decays)
40 event.genwzquarks = [] # quarks from W,Z decays
41 event.genbquarksFromTop = []
42 event.genbquarksFromH = []
43 event.genwzquarks and event.genbquarks, might have overlaps
44 event.genbquarksFromTop and event.genbquarksFromH are all contained in event.genbquarks
48 def __init__(self, cfg_ana, cfg_comp, looperName ):
49 super(GeneratorAnalyzer,self).
__init__(cfg_ana,cfg_comp,looperName)
58 self.mchandles[
'genParticles'] = AutoHandle(
'prunedGenParticles',
'std::vector<reco::GenParticle>' )
61 super(GeneratorAnalyzer,self).
beginLoop(setup)
64 verbose = getattr(self.cfg_ana,
'verbose',
False)
65 rawGenParticles = self.mchandles[
'genParticles'].product()
66 good = []; keymap = {};
67 for rawIndex,p
in enumerate(rawGenParticles):
82 if any((p.mother(j).
pdgId() == p.pdgId())
for j
in xrange(p.numberOfMothers())):
87 if any((p.daughter(j).
pdgId() == p.pdgId()
and p.daughter(j).status > 2)
for j
in xrange(p.numberOfDaughters())):
108 if not any(mom.daughter(j2).
pdgId() == mom.pdgId()
for j2
in xrange(mom.numberOfDaughters())):
111 if abs(mom.pdgId()) == 15:
121 gp.rawIndex = rawIndex
122 keymap[rawIndex] = len(good)
125 for igp,gp
in enumerate(good):
128 gp.genSummaryIndex = igp
129 ancestor =
None if gp.numberOfMothers() == 0
else gp.motherRef(0)
130 while ancestor !=
None and ancestor.isNonnull():
131 if ancestor.key()
in keymap:
132 gp.motherIndex = keymap[ancestor.key()]
133 if ancestor.pdgId() != good[gp.motherIndex].
pdgId():
134 print "Error keying %d: motherIndex %d, ancestor.pdgId %d, good[gp.motherIndex].pdgId() %d " % (igp, gp.motherIndex, ancestor.pdgId(), good[gp.motherIndex].
pdgId())
136 ancestor =
None if ancestor.numberOfMothers() == 0
else ancestor.motherRef(0)
137 if abs(gp.pdgId())
not in {1,2,3,4,5,11,12,13,14,15,16,21}:
138 gp.sourceId = gp.pdgId()
139 if gp.motherIndex != -1:
140 ancestor = good[gp.motherIndex]
141 if ancestor.sourceId != 99
and (ancestor.mass() > gp.mass()
or gp.sourceId == 99):
142 gp.sourceId = ancestor.sourceId
143 event.generatorSummary = good
145 for ip,p
in enumerate(event.generatorSummary):
151 p.motherId = moms[0].
pdgId()
153 p.grandmotherId = (gmoms[0].
pdgId()
if len(gmoms)==1
else (0
if len(gmoms)==0
else -9999))
157 p.grandmotherId = -9999
159 print "%3d {%6d}: %+8d %3d : %8.2f %+5.2f %+5.2f : %d %2d : %+8d {%3d}: %s" % ( ip,p.rawIndex,
160 p.pdgId(), p.status(), p.pt(), p.eta(), p.phi(), len(moms), p.numberOfDaughters(),
161 p.motherId, p.motherIndex,
162 " ".
join(
"%d[%d]" % (p.daughter(i).
pdgId(), p.daughter(i).
status())
for i
in xrange(p.numberOfDaughters())))
167 event.genParticles = []
168 for rawIndex,p
in enumerate(rawGenParticles):
169 if rawIndex
in keymap:
170 gp = event.generatorSummary[keymap[rawIndex]]
173 gp.rawIndex = rawIndex
174 gp.genSummaryIndex = -1
175 event.genParticles.append(gp)
177 event.genHiggsBosons = []
178 event.genVBosons = []
181 event.gentauleps = []
183 event.gentopquarks = []
184 event.genbquarks = []
185 event.genwzquarks = []
186 event.genbquarksFromTop = []
187 event.genbquarksFromH = []
188 for p
in event.generatorSummary:
191 event.genHiggsBosons.append(p)
193 event.genVBosons.append(p)
194 elif id
in {12,14,16}:
195 event.gennus.append(p)
197 if abs(p.motherId) == 15:
198 event.gentauleps.append(p)
200 event.genleps.append(p)
203 event.gentaus.append(p)
205 event.gentopquarks.append(p)
207 event.genbquarks.append(p)
209 if 6
in momids: event.genbquarksFromTop.append(p)
210 if 25
in momids: event.genbquarksFromH.append(p)
212 event.genwzquarks.append(p)
215 self.readCollections( event.input )
218 if not self.cfg_comp.isMC:
225 setattr(GeneratorAnalyzer,
"defaultConfig",
226 cfg.Analyzer(GeneratorAnalyzer,
228 stableBSMParticleIds = { 1000022 },
232 savePreFSRParticleIds = { 1,2,3,4,5, 11,12,13,14,15,16, 21 },
234 makeAllGenParticles =
True,
236 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)