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
48 In addition to genParticles, if makeLHEweights is set to True, the list WeightsInfo objects of the LHE branch
49 is stored in event.LHE_weights
53 def __init__(self, cfg_ana, cfg_comp, looperName ):
54 super(GeneratorAnalyzer,self).
__init__(cfg_ana,cfg_comp,looperName)
60 self.makeLHEweights = cfg_ana.makeLHEweights
64 self.mchandles[
'genParticles'] = AutoHandle(
'prunedGenParticles',
'std::vector<reco::GenParticle>' )
65 if self.makeLHEweights:
66 self.mchandles[
'LHEweights'] = AutoHandle(
'source',
'LHEEventProduct', mayFail =
True, lazy =
False )
69 super(GeneratorAnalyzer,self).
beginLoop(setup)
72 verbose = getattr(self.cfg_ana,
'verbose',
False)
73 rawGenParticles = self.mchandles[
'genParticles'].product()
74 good = []; keymap = {};
76 for rawIndex,p
in enumerate(rawGenParticles):
92 if any((p.mother(j).
pdgId() == p.pdgId())
for j
in xrange(p.numberOfMothers())):
97 if any((p.daughter(j).
pdgId() == p.pdgId()
and p.daughter(j).
status() > 2)
for j
in xrange(p.numberOfDaughters())):
118 if not any(mom.daughter(j2).
pdgId() == mom.pdgId()
for j2
in xrange(mom.numberOfDaughters())):
122 elif mom.pdgId() == 25
and any(mom.daughter(j2).
pdgId() == 25
and mom.daughter(j2).numberOfDaughters()==0
for j2
in range(mom.numberOfDaughters())):
124 if abs(mom.pdgId()) == 15:
134 gp.rawIndex = rawIndex
135 keymap[rawIndex] = len(good)
138 for igp,gp
in enumerate(good):
141 gp.genSummaryIndex = igp
142 ancestor =
None if gp.numberOfMothers() == 0
else gp.motherRef(0)
143 while ancestor !=
None and ancestor.isNonnull():
144 if ancestor.key()
in keymap:
145 gp.motherIndex = keymap[ancestor.key()]
146 if ancestor.pdgId() != good[gp.motherIndex].
pdgId():
147 print "Error keying %d: motherIndex %d, ancestor.pdgId %d, good[gp.motherIndex].pdgId() %d " % (igp, gp.motherIndex, ancestor.pdgId(), good[gp.motherIndex].
pdgId())
149 ancestor =
None if ancestor.numberOfMothers() == 0
else ancestor.motherRef(0)
150 if abs(gp.pdgId())
not in [1,2,3,4,5,11,12,13,14,15,16,21]:
151 gp.sourceId = gp.pdgId()
152 if gp.motherIndex != -1:
153 ancestor = good[gp.motherIndex]
154 if ancestor.sourceId != 99
and (ancestor.mass() > gp.mass()
or gp.sourceId == 99):
155 gp.sourceId = ancestor.sourceId
156 event.generatorSummary = good
158 for ip,p
in enumerate(good):
164 p.motherId = moms[0].
pdgId()
166 p.grandmotherId = (gmoms[0].
pdgId()
if len(gmoms)==1
else (0
if len(gmoms)==0
else -9999))
170 p.grandmotherId = -9999
172 print "%3d {%6d}: %+8d %3d : %8.2f %+5.2f %+5.2f : %d %2d : %+8d {%3d}: %s" % ( ip,p.rawIndex,
173 p.pdgId(), p.status(), p.pt(), p.eta(), p.phi(), len(moms), p.numberOfDaughters(),
174 p.motherId, p.motherIndex,
175 " ".
join(
"%d[%d]" % (p.daughter(i).
pdgId(), p.daughter(i).
status())
for i
in xrange(p.numberOfDaughters())))
180 event.genParticles = allGenParticles
183 event.genHiggsBosons = []
184 event.genVBosons = []
186 event.gennusFromTop = []
188 event.gentauleps = []
190 event.gentopquarks = []
191 event.genbquarks = []
192 event.genwzquarks = []
193 event.genbquarksFromTop = []
194 event.genbquarksFromH = []
195 event.genlepsFromTop = []
196 for p
in event.generatorSummary:
199 event.genHiggsBosons.append(p)
201 event.genVBosons.append(p)
202 elif id
in {12,14,16}:
203 event.gennus.append(p)
208 for mom, momid
in momids:
215 event.gennusFromTop.append(p)
219 if abs(p.motherId) == 15:
220 event.gentauleps.append(p)
223 event.genleps.append(p)
227 for mom, momid
in momids:
234 event.genlepsFromTop.append(p)
237 event.gentaus.append(p)
239 event.gentopquarks.append(p)
241 event.genbquarks.append(p)
243 if 6
in momids: event.genbquarksFromTop.append(p)
244 if 25
in momids: event.genbquarksFromH.append(p)
246 event.genwzquarks.append(p)
249 event.LHE_weights = []
250 if self.makeLHEweights:
251 if self.mchandles[
'LHEweights'].isValid():
252 for w
in self.mchandles[
'LHEweights'].product().
weights():
253 event.LHE_weights.append(w)
256 self.readCollections( event.input )
259 if not self.cfg_comp.isMC:
265 import PhysicsTools.HeppyCore.framework.config
as cfg
266 setattr(GeneratorAnalyzer,
"defaultConfig",
267 cfg.Analyzer(GeneratorAnalyzer,
269 stableBSMParticleIds = [ 1000022 ],
273 savePreFSRParticleIds = [ 1,2,3,4,5, 11,12,13,14,15,16, 21 ],
275 makeAllGenParticles =
True,
277 makeSplittedGenLists =
True,
280 makeLHEweights =
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)