1 from __future__
import print_function
2 from PhysicsTools.Heppy.analyzers.core.Analyzer
import Analyzer
3 from PhysicsTools.Heppy.analyzers.core.AutoHandle
import AutoHandle
8 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
11 """Save the hard-scattering final state of the event: top quarks, gauge & higgs bosons and BSM 12 particles, plus their immediate decay products, and their siblings (in order to get the jets 13 from matched X+jets generation. 14 Incoming partons are not included, by design. 16 In the default configuration, leptons, light quarks and gluons are saved before FSR (a la status 3). 17 Everything else is saved after any radiation, i.e. immediately before the decay. 19 Particles are saved in a list event.generatorSummary, with the index of their mothers ('motherIndex') 20 if the mother is also in the list, and with the pdgId of the mother ('motherId') and grand-mother 21 ('grandmotherId'). Particles also carry their index in the miniAOD genparticles collection ('rawIndex') 22 In addition, a 'sourceId' is set to the pdgId of the heaviest ancestor (or of the particle itself) 23 i.e. in top -> W -> lepton: the lepton sourceId will be 6 24 in tt+W with W -> lepton, the sourceId of the lepton will be 24. 25 sourceId will be 99 for paricles from hard scattering whose mother is light 27 If requested, the full list of genParticles is also produced in event.genParticles (with indices 28 aligned to the miniAOD one). For particles that are in the generatorSummary, the same object is used. 29 An extra index 'genSummaryIndex' will be added to all particles, with the index in the generatorSummary 30 or -1 if the particle is not in the generatorSummary. 32 Also, if requested it creates the splitted collections: 33 event.genHiggsBosons = [] 35 event.gennus = [] # prompt neutrinos 36 event.gennusFromTop = [] # Neutrinos from t->W decay 37 event.genleps = [] # leptons from direct decays 38 event.gentauleps = [] # leptons from prompt taus 39 event.gentaus = [] # hadronically-decaying taus (if allGenTaus is False) or all taus (if allGenTaus is True) 40 event.gentopquarks = [] 41 event.genbquarks = [] # b quarks from hard event (e.g. from top decays) 42 event.genwzquarks = [] # quarks from W,Z decays 43 event.genbquarksFromTop = [] 44 event.genbquarksFromH = [] 45 event.genlepsFromTop = [] #mu/ele that have a t->W chain as ancestor, also contained in event.genleps 46 event.genwzquarks and event.genbquarks, might have overlaps 47 event.genbquarksFromTop and event.genbquarksFromH are all contained in event.genbquarks 51 def __init__(self, cfg_ana, cfg_comp, looperName ):
52 super(GeneratorAnalyzer,self).
__init__(cfg_ana,cfg_comp,looperName)
61 self.mchandles[
'genParticles'] = AutoHandle(
'prunedGenParticles',
'std::vector<reco::GenParticle>' )
64 super(GeneratorAnalyzer,self).
beginLoop(setup)
67 verbose = getattr(self.cfg_ana,
'verbose',
False)
68 rawGenParticles = self.mchandles[
'genParticles'].product()
69 good = []; keymap = {};
71 for rawIndex,p
in enumerate(rawGenParticles):
87 if any((p.mother(j).
pdgId() == p.pdgId())
for j
in xrange(p.numberOfMothers())):
92 if any((p.daughter(j).
pdgId() == p.pdgId()
and p.daughter(j).
status() > 2)
for j
in xrange(p.numberOfDaughters())):
113 if not any(mom.daughter(j2).
pdgId() == mom.pdgId()
for j2
in xrange(mom.numberOfDaughters())):
117 elif mom.pdgId() == 25
and any(mom.daughter(j2).
pdgId() == 25
and mom.daughter(j2).numberOfDaughters()==0
for j2
in range(mom.numberOfDaughters())):
119 if abs(mom.pdgId()) == 15:
127 if not ok
and id
in [11, 13, 15]
and abs(mom.pdgId())
in [1,2,3,4,5,21]:
132 gp.rawIndex = rawIndex
133 keymap[rawIndex] = len(good)
136 for igp,gp
in enumerate(good):
139 gp.genSummaryIndex = igp
140 ancestor =
None if gp.numberOfMothers() == 0
else gp.motherRef(0)
141 while ancestor !=
None and ancestor.isNonnull():
142 if ancestor.key()
in keymap:
143 gp.motherIndex = keymap[ancestor.key()]
144 if ancestor.pdgId() != good[gp.motherIndex].
pdgId():
145 print(
"Error keying %d: motherIndex %d, ancestor.pdgId %d, good[gp.motherIndex].pdgId() %d " % (igp, gp.motherIndex, ancestor.pdgId(), good[gp.motherIndex].
pdgId()))
147 ancestor =
None if ancestor.numberOfMothers() == 0
else ancestor.motherRef(0)
148 if abs(gp.pdgId())
not in [1,2,3,4,5,11,12,13,14,15,16,21]:
149 gp.sourceId = gp.pdgId()
150 if gp.motherIndex != -1:
151 ancestor = good[gp.motherIndex]
152 if ancestor.sourceId != 99
and (ancestor.mass() > gp.mass()
or gp.sourceId == 99):
153 gp.sourceId = ancestor.sourceId
154 event.generatorSummary = good
156 for ip,p
in enumerate(good):
162 p.motherId = moms[0].
pdgId()
164 p.grandmotherId = (gmoms[0].
pdgId()
if len(gmoms)==1
else (0
if len(gmoms)==0
else -9999))
168 p.grandmotherId = -9999
170 print(
"%3d {%6d}: %+8d %3d : %8.2f %+5.2f %+5.2f : %d %2d : %+8d {%3d}: %s" % ( ip,p.rawIndex,
171 p.pdgId(), p.status(), p.pt(), p.eta(), p.phi(), len(moms), p.numberOfDaughters(),
172 p.motherId, p.motherIndex,
173 " ".
join(
"%d[%d]" % (p.daughter(i).
pdgId(), p.daughter(i).
status())
for i
in xrange(p.numberOfDaughters()))))
178 event.genParticles = allGenParticles
181 event.genHiggsBosons = []
182 event.genVBosons = []
184 event.gennusFromTop = []
186 event.gentauleps = []
188 event.gentopquarks = []
189 event.genbquarks = []
190 event.genwzquarks = []
191 event.genbquarksFromTop = []
192 event.genbquarksFromH = []
193 event.genlepsFromTop = []
194 for p
in event.generatorSummary:
197 event.genHiggsBosons.append(p)
199 event.genVBosons.append(p)
200 elif id
in {12,14,16}:
201 event.gennus.append(p)
206 for mom, momid
in momids:
213 event.gennusFromTop.append(p)
217 if abs(p.motherId) == 15:
218 event.gentauleps.append(p)
221 event.genleps.append(p)
225 for mom, momid
in momids:
232 event.genlepsFromTop.append(p)
235 event.gentaus.append(p)
237 event.gentopquarks.append(p)
239 event.genbquarks.append(p)
241 if 6
in momids: event.genbquarksFromTop.append(p)
242 if 25
in momids: event.genbquarksFromH.append(p)
244 event.genwzquarks.append(p)
247 self.readCollections( event.input )
250 if not self.cfg_comp.isMC:
256 import PhysicsTools.HeppyCore.framework.config
as cfg
257 setattr(GeneratorAnalyzer,
"defaultConfig",
258 cfg.Analyzer(GeneratorAnalyzer,
260 stableBSMParticleIds = [ 1000022 ],
264 savePreFSRParticleIds = [ 1,2,3,4,5, 11,12,13,14,15,16, 21 ],
266 makeAllGenParticles =
True,
268 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)