1 from __future__
import print_function
2 from builtins
import range
3 from PhysicsTools.Heppy.analyzers.core.Analyzer
import Analyzer
4 from PhysicsTools.Heppy.analyzers.core.AutoHandle
import AutoHandle
9 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
12 """Save the hard-scattering final state of the event: top quarks, gauge & higgs bosons and BSM 13 particles, plus their immediate decay products, and their siblings (in order to get the jets 14 from matched X+jets generation. 15 Incoming partons are not included, by design. 17 In the default configuration, leptons, light quarks and gluons are saved before FSR (a la status 3). 18 Everything else is saved after any radiation, i.e. immediately before the decay. 20 Particles are saved in a list event.generatorSummary, with the index of their mothers ('motherIndex') 21 if the mother is also in the list, and with the pdgId of the mother ('motherId') and grand-mother 22 ('grandmotherId'). Particles also carry their index in the miniAOD genparticles collection ('rawIndex') 23 In addition, a 'sourceId' is set to the pdgId of the heaviest ancestor (or of the particle itself) 24 i.e. in top -> W -> lepton: the lepton sourceId will be 6 25 in tt+W with W -> lepton, the sourceId of the lepton will be 24. 26 sourceId will be 99 for paricles from hard scattering whose mother is light 28 If requested, the full list of genParticles is also produced in event.genParticles (with indices 29 aligned to the miniAOD one). For particles that are in the generatorSummary, the same object is used. 30 An extra index 'genSummaryIndex' will be added to all particles, with the index in the generatorSummary 31 or -1 if the particle is not in the generatorSummary. 33 Also, if requested it creates the splitted collections: 34 event.genHiggsBosons = [] 36 event.gennus = [] # prompt neutrinos 37 event.gennusFromTop = [] # Neutrinos from t->W decay 38 event.genleps = [] # leptons from direct decays 39 event.gentauleps = [] # leptons from prompt taus 40 event.gentaus = [] # hadronically-decaying taus (if allGenTaus is False) or all taus (if allGenTaus is True) 41 event.gentopquarks = [] 42 event.genbquarks = [] # b quarks from hard event (e.g. from top decays) 43 event.genwzquarks = [] # quarks from W,Z decays 44 event.genbquarksFromTop = [] 45 event.genbquarksFromH = [] 46 event.genlepsFromTop = [] #mu/ele that have a t->W chain as ancestor, also contained in event.genleps 47 event.genwzquarks and event.genbquarks, might have overlaps 48 event.genbquarksFromTop and event.genbquarksFromH are all contained in event.genbquarks 52 def __init__(self, cfg_ana, cfg_comp, looperName ):
53 super(GeneratorAnalyzer,self).
__init__(cfg_ana,cfg_comp,looperName)
62 self.mchandles[
'genParticles'] = AutoHandle(
'prunedGenParticles',
'std::vector<reco::GenParticle>' )
65 super(GeneratorAnalyzer,self).
beginLoop(setup)
68 verbose = getattr(self.cfg_ana,
'verbose',
False)
69 rawGenParticles = self.mchandles[
'genParticles'].product()
70 good = []; keymap = {};
72 for rawIndex,p
in enumerate(rawGenParticles):
88 if any((p.mother(j).
pdgId() == p.pdgId())
for j
in range(p.numberOfMothers())):
93 if any((p.daughter(j).
pdgId() == p.pdgId()
and p.daughter(j).
status() > 2)
for j
in range(p.numberOfDaughters())):
114 if not any(mom.daughter(j2).
pdgId() == mom.pdgId()
for j2
in range(mom.numberOfDaughters())):
118 elif mom.pdgId() == 25
and any(mom.daughter(j2).
pdgId() == 25
and mom.daughter(j2).numberOfDaughters()==0
for j2
in range(mom.numberOfDaughters())):
120 if abs(mom.pdgId()) == 15:
128 if not ok
and id
in [11, 13, 15]
and abs(mom.pdgId())
in [1,2,3,4,5,21]:
133 gp.rawIndex = rawIndex
134 keymap[rawIndex] = len(good)
137 for igp,gp
in enumerate(good):
140 gp.genSummaryIndex = igp
141 ancestor =
None if gp.numberOfMothers() == 0
else gp.motherRef(0)
142 while ancestor !=
None and ancestor.isNonnull():
143 if ancestor.key()
in keymap:
144 gp.motherIndex = keymap[ancestor.key()]
145 if ancestor.pdgId() != good[gp.motherIndex].
pdgId():
146 print(
"Error keying %d: motherIndex %d, ancestor.pdgId %d, good[gp.motherIndex].pdgId() %d " % (igp, gp.motherIndex, ancestor.pdgId(), good[gp.motherIndex].
pdgId()))
148 ancestor =
None if ancestor.numberOfMothers() == 0
else ancestor.motherRef(0)
149 if abs(gp.pdgId())
not in [1,2,3,4,5,11,12,13,14,15,16,21]:
150 gp.sourceId = gp.pdgId()
151 if gp.motherIndex != -1:
152 ancestor = good[gp.motherIndex]
153 if ancestor.sourceId != 99
and (ancestor.mass() > gp.mass()
or gp.sourceId == 99):
154 gp.sourceId = ancestor.sourceId
155 event.generatorSummary = good
157 for ip,p
in enumerate(good):
163 p.motherId = moms[0].
pdgId()
165 p.grandmotherId = (gmoms[0].
pdgId()
if len(gmoms)==1
else (0
if len(gmoms)==0
else -9999))
169 p.grandmotherId = -9999
171 print(
"%3d {%6d}: %+8d %3d : %8.2f %+5.2f %+5.2f : %d %2d : %+8d {%3d}: %s" % ( ip,p.rawIndex,
172 p.pdgId(), p.status(), p.pt(), p.eta(), p.phi(), len(moms), p.numberOfDaughters(),
173 p.motherId, p.motherIndex,
174 " ".
join(
"%d[%d]" % (p.daughter(i).
pdgId(), p.daughter(i).
status())
for i
in range(p.numberOfDaughters()))))
179 event.genParticles = allGenParticles
182 event.genHiggsBosons = []
183 event.genVBosons = []
185 event.gennusFromTop = []
187 event.gentauleps = []
189 event.gentopquarks = []
190 event.genbquarks = []
191 event.genwzquarks = []
192 event.genbquarksFromTop = []
193 event.genbquarksFromH = []
194 event.genlepsFromTop = []
195 for p
in event.generatorSummary:
198 event.genHiggsBosons.append(p)
200 event.genVBosons.append(p)
201 elif id
in {12,14,16}:
202 event.gennus.append(p)
207 for mom, momid
in momids:
214 event.gennusFromTop.append(p)
218 if abs(p.motherId) == 15:
219 event.gentauleps.append(p)
222 event.genleps.append(p)
226 for mom, momid
in momids:
233 event.genlepsFromTop.append(p)
236 event.gentaus.append(p)
238 event.gentopquarks.append(p)
240 event.genbquarks.append(p)
242 if 6
in momids: event.genbquarksFromTop.append(p)
243 if 25
in momids: event.genbquarksFromH.append(p)
245 event.genwzquarks.append(p)
248 self.readCollections( event.input )
251 if not self.cfg_comp.isMC:
257 import PhysicsTools.HeppyCore.framework.config
as cfg
258 setattr(GeneratorAnalyzer,
"defaultConfig",
259 cfg.Analyzer(GeneratorAnalyzer,
261 stableBSMParticleIds = [ 1000022 ],
265 savePreFSRParticleIds = [ 1,2,3,4,5, 11,12,13,14,15,16, 21 ],
267 makeAllGenParticles =
True,
269 makeSplittedGenLists =
True,
def interestingPdgId(id, includeLeptons=False)
def isNotFromHadronicShower(l)
bool any(const std::vector< T > &v, const T &what)
S & print(S &os, JobReport::InputFile const &f)
def makeMCInfo(self, event)
def beginLoop(self, setup)
def realGenDaughters(gp, excludeRadiation=True)
Abs< T >::type abs(const T &t)
static std::string join(char **cmd)
def __init__(self, cfg_ana, cfg_comp, looperName)