ATLAS Offline Software
Loading...
Searching...
No Matches
MenuTruthThinning.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6// MenuTruthThinning.cxx, (c) ATLAS Detector software
8// Translated into xAOD by James Catmore (James.Catmore@cern.ch)
9// from orignal D3PD code by Snyder, Marshall, Boonekamp et al:
10// TruthD3PDAnalysis/src/TruthParticleFilterTool.cxx
11// Provides user with a menu of options for thinning truth particles
12// from xAOD. Tool sets up a mask which is then passed to the
13// thinning service.
14// DOES NOT PRESERVE GRAPH INTEGRITY
15
20#include "GaudiKernel/SystemOfUnits.h"
22#include "GaudiKernel/ThreadLocalContext.h"
24#include <vector>
25#include <string>
26
27using Gaudi::Units::GeV;
28
29// Constructor
31 const std::string& n,
32 const IInterface* p ) :
33base_class(t,n,p),
35m_totpart(0),
37{
38 declareProperty ("WritePartons",
39 m_writePartons = true,
40 "Keep partons?");
41
42 declareProperty ("WriteHadrons",
43 m_writeHadrons = false,
44 "Keep hadrons?");
45
46 declareProperty ("WriteBHadrons",
47 m_writeBHadrons = true,
48 "Keep b-hadrons?");
49
50 declareProperty ("WriteCHadrons",
51 m_writeCHadrons = true,
52 "Keep c-hadrons?");
53
54 declareProperty ("WriteGeant",
55 m_writeGeant = false,
56 "Keep Geant particles?");
57
58 declareProperty ("GeantPhotonPtThresh",
60 "Write Geant photons with Pt above this threshold. "
61 "Set to < 0 to not write any.");
62
63 declareProperty ("WriteTauHad",
64 m_writeTauHad = false,
65 "Keep hadronic taus?");
66
67 declareProperty ("PartonPtThresh",
69 "Write partons with Pt above this threshold.");
70
71 declareProperty ("WriteBSM",
72 m_writeBSM = false,
73 "Keep BSM particles?");
74
75 declareProperty ("WriteBosons",
76 m_writeBosons = false,
77 "Keep bosons?");
78
79 declareProperty ("PhotonPtThresh",
80 m_photonPtCut = 3000.,
81 "Photon pt cut with WriteBosons");
82
83 declareProperty ("WriteBSMProducts",
84 m_writeBSMProducts = false,
85 "Keep BSM particle decay products?");
86
87 declareProperty ("WriteBosonProducts",
89 "Keep boson decay products?");
90
91 declareProperty ("WriteTopAndDecays",
92 m_writeTopAndDecays = false,
93 "Keep top partons and immediate decay products?");
94
95 declareProperty("WriteEverything",
96 m_writeEverything = false,
97 "Keep absolutely everything (overrides all other flags)");
98
99 declareProperty("WriteAllLeptons",
100 m_writeAllLeptons = false,
101 "Keep absolutely all leptons");
102
103 declareProperty("WriteLeptonsNotFromHadrons",
105 "Keep leptons not from hadron decays");
106
107 declareProperty("WriteAllStable",
108 m_writeAllStable = false,
109 "Keep all stable particles");
110
111 declareProperty("WriteNotPhysical",
112 m_writeNotPhysical = false,
113 "Save also non-physical particles");
114
115 declareProperty("WriteFirstN",
116 m_writeFirstN = -1,
117 "Keep first N particles in record");
118
119 declareProperty("PreserveDescendants",
120 m_preserveDescendants = false,
121 "Preserve descendants of retained particles");
122
123 declareProperty("PreserveGeneratorDescendants",
125 "Preserve descendants of retained particles excluding Geant particles");
126
127 declareProperty("PreserveAncestors",
128 m_preserveAncestors = false,
129 "Preserve ancestors of retained particles");
130
131 declareProperty ("PreserveParentsSiblingsChildren",
132 m_preserveImmediate = false,
133 "Preserve the parents, siblings and children of retained particles");
134
135 declareProperty ("PreserveHadronizationVertices",
136 m_preserveHadVtx = false,
137 "Preserve hadronization vertices with parents/children.");
138
139 declareProperty ("WritettHFHadrons",
140 m_writettHFHadrons = false,
141 "Keep tt+HF hadrons?");
142
143 declareProperty ("PDGIDsToKeep",
145 "List of PDG IDs to always keep");
146
147 declareProperty ("LongLivedPDGIDs",
149 "List of PDG IDs of long lived particles so that one can store their children");
150}
151
152// Destructor
155
156// Athena initialize and finalize
158{
160 ATH_MSG_FATAL("You are asking to keep both all descendants, and only those from the event generator. Please check your job options.");
161 return StatusCode::FAILURE;
162 }
164 ATH_MSG_FATAL("You are asking to preserve only parents/children/siblings of retained states, and also more distant relatives. Please check your job options.");
165 return StatusCode::FAILURE;
166 }
167 m_totpart = 0;
168 m_removedpart = 0;
169 m_eventCount = 0;
170
171 ATH_CHECK( m_particlesKey.initialize (m_streamName) );
172 ATH_CHECK( m_verticesKey.initialize (m_streamName) );
173 return StatusCode::SUCCESS;
174}
175
177{
178 ATH_MSG_VERBOSE("finalize() ...");
179 ATH_MSG_INFO("Total of " << m_totpart << " truth particles");
180 ATH_MSG_INFO("Removed "<< m_removedpart << " truth particles");
181 return StatusCode::SUCCESS;
182}
183
184// The thinning itself
186{
187 const EventContext& ctx = Gaudi::Hive::currentContext();
188
189 // Retrieve the truth collections
191 (m_particlesKey, ctx);
192 m_totpart += importedTruthParticles->size();
193
195 (m_verticesKey, ctx);
196
197 // Print events
198 //if( m_eventCount < 20 ){
199 // printxAODTruth(m_eventCount, importedTruthParticles);
200 //}
201 ++m_eventCount;
202
203 // Set up a mask with the same number of entries as the full TruthParticle collection
204 std::vector<bool> particleMask, vertexMask;
205 int nTruthParticles = importedTruthParticles->size();
206 int nTruthVertices = importedTruthVertices->size();
207 particleMask.assign(nTruthParticles,true); // default: keep all particles
208 vertexMask.assign(nTruthVertices,false); // throw all vertices: to be discussed
209
210 // Standard particle loop
211 for (int particleCounter = 0; particleCounter < nTruthParticles; ++particleCounter) {
212 const xAOD::TruthParticle* particle = (*importedTruthParticles)[particleCounter];
213 // Keep first N particles
214 if ( (particleCounter > m_writeFirstN) && (!isAccepted(particle)) ){
215 // Particle removal - note mask is true by default
216 particleMask[particleCounter] = false;
218 }
219 }
220
221 // If user requested preservation of descendants/ancestors:
222 // - loop over the masks and work out which particles need to be descended/ascended from
223 // - do the recursive loop
224 // - update the masks including the descendants/ancestors
225 // To ensure graph completeness, this over-rides anything set by the special treatment
226 // of taus in the section above
228 std::unordered_set<int> encounteredUniqueIDs; // For loop handling
230 for (int i=0; i<nTruthParticles; ++i) {
231 bool toKeep = particleMask[i];
232 if (!toKeep) continue;
233 const xAOD::TruthParticle* particle = (*importedTruthParticles)[i];
234 encounteredUniqueIDs.clear();
235 if (m_preserveDescendants) decayHelper.descendants(particle,particleMask,vertexMask,encounteredUniqueIDs,true);
236 encounteredUniqueIDs.clear();
237 if (m_preserveGeneratorDescendants) decayHelper.descendants(particle,particleMask,vertexMask,encounteredUniqueIDs,false);
238 encounteredUniqueIDs.clear();
239 if (m_preserveAncestors) decayHelper.ancestors(particle,particleMask,vertexMask,encounteredUniqueIDs);
240 encounteredUniqueIDs.clear();
241 }
242 }
243 // User only wants to keep parents, siblings and children of retained states
244 // Much simpler case - no recursion so no need for uniqueIDs etc
246 // Make a copy of the particle mask to avoid changes being propagated
247 // down the chain
248 std::vector<bool> particleMaskCopy = particleMask;
249 for (int i=0; i<nTruthParticles; ++i) {
250 bool toKeep = particleMask[i]; // still loop over the orginal list, not the copy
251 if (!toKeep) continue;
252 const xAOD::TruthParticle* particle = (*importedTruthParticles)[i];
253 decayHelper.immediateRelatives(particle,particleMaskCopy,vertexMask,
254 m_preserveHadVtx); // but only update the copy
255 }
256 particleMask = particleMaskCopy; // Now update the original list in one go
257 }
258
259 // Execute the thinning service based on the mask. Finish.
260 importedTruthParticles.keep (particleMask);
261 importedTruthVertices.keep (vertexMask);
262
263 return StatusCode::SUCCESS;
264}
265
266// Test to see if we want to keep a particle
268{
269 bool ok = false;
270
271 int pdg_id = p->absPdgId();
272
273 // All explicitly requested PDG IDs of long lived particles, this is needed
274 // because their childrens uniqueIDs can be above the cut off m_geantOffset
275 if(!m_longLivedPdgIds.empty() && parentIsLongLived(p)) ok = true;
276
277
279 if (!(MC::isPhoton(pdg_id) && m_geantPhotonPtThresh >= 0 && p->pt() > m_geantPhotonPtThresh) )
280 return false;
281 }
282
283 // Do we want to save everything?
284 if (m_writeEverything) ok = true;
285
286 // Save NotPhysical particles
287 if (m_writeNotPhysical && !MC::isPhysical(p)) ok = true;
288
289 // OK if we select partons and are at beginning of event record
290 if( m_writePartons && !MC::isHadron(pdg_id) &&
292 ok = true;
293
294 // OK if we should select hadrons and are in hadron range
295 // JRC: cut changed from PHOTOSMIN to m_geantOffset
296 if( m_writeHadrons && MC::isHadron (pdg_id) && !HepMC::is_simulation_particle(p) ) ok = true;
297
298 // OK if we should select b hadrons and are in hadron range
299 // JRC: cut changed from PHOTOSMIN to m_geantOffset
300 if( m_writeBHadrons && !HepMC::is_simulation_particle(p) && MC::isBottomHadron (pdg_id)) ok = true;
301
302 // OK if we should select c hadrons and are in hadron range
303 // JRC: cut changed from PHOTOSMIN to m_geantOffset
304 if( m_writeCHadrons && !HepMC::is_simulation_particle(p) && MC::isCharmHadron (pdg_id)) ok = true;
305
306 // PHOTOS range: check whether photons come from parton range or
307 // hadron range
308 int motherPDGID = 999999999;
309 // AV: dropped the HepMC::PHOTOSMIN condition
310 if ( !HepMC::is_simulation_particle(p) && p->hasProdVtx() )
311 {
312 const xAOD::TruthVertex* vprod = p->prodVtx();
313 if (vprod->nIncomingParticles() > 0) {
314 const xAOD::TruthParticle* mother = vprod->incomingParticle(0);
315 if (mother) motherPDGID = mother->pdgId();
316 }
317 if( m_writePartons && !MC::isHadron( motherPDGID ) ) ok = true;
318 if( m_writeHadrons && MC::isHadron( motherPDGID ) ) ok = true;
319 }
320
321 // OK if we should select G4 particles and are in G4 range
322 if( m_writeGeant && HepMC::is_simulation_particle(p) ) ok = true;
323
324 if(isLeptonFromTau(p)) ok = true;
325
326 if(isFsrFromLepton(p)) ok = true;
327
328 // Hadronic tau decays
329 if(m_writeTauHad){
330 std::unordered_set<int> uniqueID_trace;
331 if (isFromTau(p, uniqueID_trace))
332 ok = true;
333 }
334
335 // Bosons
336 if(m_writeBosons && (MC::isZ(p)||MC::isW(p)||MC::isHiggs(p) || (MC::isPhoton(p) && p->pt()>m_photonPtCut) )) ok = true;
337
338 // BSM particles
339 if(m_writeBSM && MC::isBSM(p)) ok = true;
340
341 // tt+HF hadrons
342 if (m_writettHFHadrons && isttHFHadron(p)) ok = true;
343
344 // Top quarks
345 if(m_writeTopAndDecays && MC::isTop(p)) ok = true;
346
347 // All leptons
348 if(m_writeAllLeptons && MC::isLepton(p))ok = true; // Include 4th generation...
349
350 // All stable
352
353 // All leptons not from hadron decays
354 if(!ok && m_writeLeptonsNotFromHadrons && MC::isLepton(p) && MC::isStable(p)) {// Include 4th generation...
356 }
357
358 if ((m_writeBSMProducts || m_writeBosonProducts || m_writeTopAndDecays) && p->hasProdVtx()){ // Either way we have to go through parents
359 const xAOD::TruthVertex* prodVtx = p->prodVtx();
360 unsigned int nIncoming = prodVtx->nIncomingParticles();
361 for(unsigned int itr=0; itr<nIncoming; ++itr) {
362 const xAOD::TruthParticle* incomingParticle = prodVtx->incomingParticle(itr);
363 if (!incomingParticle) continue;
364 if ((m_writeBSMProducts && MC::isBSM(incomingParticle)) ||
365 (m_writeBosonProducts && (MC::isZ(incomingParticle)||MC::isW(incomingParticle)||MC::isHiggs(incomingParticle) || (MC::isPhoton(incomingParticle) && incomingParticle->pt()>m_photonPtCut) )) ||
366 (m_writeTopAndDecays && MC::isTop(incomingParticle)) ){
367 ok = true;
368 break;
369 }
370 }
371
372 }
373
374 // All explicitly requested PDG IDs
375 for (const auto id : m_pdgIdsToKeep){
376 if (pdg_id==id) ok=true;
377 } // Loop over PDG IDs
378
379 return ok;
380}
381
383 //check if part descends from a hadron, possibly passing through a tau decay
384 //ported from TopFiducial
385 std::vector<int> hadrons = std::vector<int>{111};
386 std::vector<int> taus = std::vector<int>{15,-15};
387 return matchGenParticle(part, hadrons, taus, true);
388}
389
391 //check if part descends from a hadron, possibly passing through a tau decay
392 //ported from TopFiducial
393 std::vector<int> quarks = std::vector<int>{1,6};
394 std::vector<int> taus = std::vector<int>{15,-15};
395 return matchGenParticle(part, quarks, taus, true);
396}
397
399 //check if part descends from nothing, possibly passing through a tau decay
400 //(indicating a broken truth record)
401 //ported from TopFiducial
402
403 int pdgId = part->pdgId();
404
405 if (!part->hasProdVtx()) return true;
406
407 const xAOD::TruthVertex* prodVtx = part->prodVtx();
408 unsigned int nIncoming = prodVtx->nIncomingParticles();
409 unsigned int itrParent = 0;
410
411 // Simple loop catch
412 if (prodVtx==part->decayVtx()) return false;
413
414 //0 incoming-> orphan
415 if(nIncoming == 0) return true;
416
417 unsigned int nParents = 0;
418 while(nParents==0 && itrParent<nIncoming) {
419 const xAOD::TruthParticle* incomingParticle = prodVtx->incomingParticle(itrParent);
420
421 // If the parent is itself migrate up the generator record
422 if(incomingParticle->pdgId() == pdgId) {
423 if(!isOrphanIncTau(incomingParticle)) nParents++;
424 }
425 else if(MC::isTau(incomingParticle)) {
426 if(!isOrphanIncTau(incomingParticle)) nParents++;
427 }
428 else {
429 nParents++;
430 }
431 ++itrParent;
432 }
433 return (nParents==0);
434}
435
437 std::vector<int> &intermediatePdgIds, bool targetsAreRange) const {
438 //check if part descends from a particle, possibly passing through an intermediate decay
439 //ported from TopFiducial
440
441 int pdgId = part->pdgId();
442
443 bool found = false;
444
445 // Iterators for the target pdg or the intermediate pdg ids
446 std::vector<int>::const_iterator itrPdgId, itrPdgIdEnd;
447
448 if (!part->hasProdVtx()) return false;
449
450 // Loop over the parents
451 const xAOD::TruthVertex* prodVtx = part->prodVtx();
452 unsigned int nIncoming = prodVtx->nIncomingParticles();
453
454 // Simple loop catch
455 if (prodVtx==part->decayVtx()) return false;
456
457 unsigned int itrParent = 0;
458 while(!found && itrParent<nIncoming) {
459 const xAOD::TruthParticle* incomingParticle = prodVtx->incomingParticle(itrParent);
460
461 if(!targetsAreRange) {
462
463 // If the parent is one of the particles in the target pdg list
464 itrPdgId = targetPdgIds.begin();
465 itrPdgIdEnd = targetPdgIds.end();
466 for(;itrPdgId != itrPdgIdEnd; ++itrPdgId) {
467 if(incomingParticle->pdgId() == (*itrPdgId)) return true;
468 }
469 }
470 else {
471 int absPdgId = incomingParticle->absPdgId();
472
473 // If the parent is within the range given in the target pdg list
474 if(targetPdgIds.size() == 1) {
475 if(absPdgId >= targetPdgIds.at(0)) return true;
476 }
477 else if(targetPdgIds.size() >= 2) {
478 if(absPdgId >= targetPdgIds.at(0) &&
479 absPdgId <= targetPdgIds.at(1)) return true;
480 }
481 }
482
483 // If the parent is itself migrate up the generator record
484 if(incomingParticle->pdgId() == pdgId) {
485 found = matchGenParticle(incomingParticle, targetPdgIds, intermediatePdgIds, targetsAreRange);
486 }
487 else {
488 // If the parent is in the intermediatePdgIds list migrate up the generator record
489 itrPdgId = intermediatePdgIds.begin();
490 itrPdgIdEnd = intermediatePdgIds.end();
491 bool foundIntermediate = false;
492 while(!foundIntermediate && itrPdgId != itrPdgIdEnd) {
493 if(incomingParticle->pdgId() == (*itrPdgId)) foundIntermediate = true;
494 else ++itrPdgId;
495 }
496 if(foundIntermediate) {
497 found = matchGenParticle(incomingParticle, targetPdgIds, intermediatePdgIds, targetsAreRange);
498 }
499 }
500
501 ++itrParent;
502 }
503 return found;
504}
505
507
508 int pdg = part->pdgId();
509
510 if(!MC::isSMLepton(part)) return false; // all leptons including tau.
511
512 const xAOD::TruthVertex* prod = part->prodVtx();
513 if(!prod) return false; // no parent.
514
515 // Simple loop catch
516 if (prod==part->decayVtx()) return false;
517
518 // Loop over the parents of this particle.
519 unsigned int nIncoming = prod->nIncomingParticles();
520 for(unsigned int itr = 0; itr<nIncoming; ++itr){
521 int parentId = prod->incomingParticle(itr)->pdgId();
522 if( MC::isTau(parentId) ) {
523 ATH_MSG_DEBUG("Particle with pdgId = " << pdg << ", matched to tau");
524 return true; // Has tau parent
525 }
526
527 if(parentId == pdg) { // Same particle just a different MC status
528 // Go up the generator record until a tau is found or not.
529 // Note that this requires a connected *lepton* chain, while calling
530 // isFromTau would allow leptons from hadrons from taus
531 if(isLeptonFromTau(prod->incomingParticle(itr))) {
532 return true;
533 }
534 }
535 }
536
537 return false;
538}
539
541 std::unordered_set<int>& uniqueID_trace) const {
542
543 int pdg = part->pdgId();
544
545 const xAOD::TruthVertex* prod = part->prodVtx();
546 if(!prod) return false; // no parent.
547
548 // Simple loop catch
549 if (prod==part->decayVtx()) return false;
550
551 // More complex loop catch
552 std::unordered_set<int>::const_iterator foundVtx = uniqueID_trace.find( HepMC::uniqueID(prod) );
553 if( foundVtx != uniqueID_trace.end() ) {
554 ATH_MSG_DEBUG( "Found a loop (a la Sherpa sample). Backing out." );
555 return false;
556 }
557 uniqueID_trace.insert(HepMC::uniqueID(prod));
558
559 // Loop over the parents of this particle.
560 unsigned int nIncoming = prod->nIncomingParticles();
561 for (unsigned int pitr = 0; pitr<nIncoming; ++pitr){
562 const xAOD::TruthParticle* itrParent = prod->incomingParticle(pitr);
563 if (!itrParent) continue;
564 if (pitr>2) break; // No point in trying - this vertex does not have a quantum meaning...
565
566 if( MC::isTau(itrParent) ) {
567 // Check if one of the children of this parent was a tau - if it is, then it is
568 // photon radiation, and we already cover that under FSR
569 bool has_fsr = false;
570 if ( itrParent->hasDecayVtx() ){
571 unsigned int nChildren = itrParent->decayVtx()->nOutgoingParticles();
572 for (unsigned int citr = 0; citr<nChildren; ++citr) {
573 const xAOD::TruthParticle* itrChild = itrParent->decayVtx()->outgoingParticle(citr);
574 if (!itrChild) continue;
575 if (MC::isTau(itrChild)){
576 has_fsr = true;
577 break;
578 } // Caught FSR check
579 } // loop over immediate children
580 } // Parent has an end vertex
581 if (has_fsr) return false;
582 ATH_MSG_DEBUG("Particle with pdgId = " << pdg << ", matched to tau");
583 return true; // Has tau parent
584 }
585
586 // Go up the generator record until a tau is found or not.
587 if(isFromTau(itrParent, uniqueID_trace)) {
588 return true;
589 }
590 }
591
592 return false;
593}
594
595
596
598
599 int ttHFClassification=6;
600
601 static const SG::ConstAccessor<int> TopHadronOriginFlagAcc("TopHadronOriginFlag");
602 if (TopHadronOriginFlagAcc.isAvailable(*part)){
603 ttHFClassification = TopHadronOriginFlagAcc(*part);
604 }
605 else{
606 return false;
607 }
608
609 if (ttHFClassification < 6 ) // useful Hadrons
610 return true;
611
612 return false;
613}
614
615
617 int pdg = part->pdgId();
618 if(!MC::isPhoton(part)) return false;
619 if(HepMC::is_simulation_particle(part) ) return false; // Geant photon
620 const xAOD::TruthVertex* prod = part->prodVtx();
621 if(!prod) return false; // no parent.
622 // Simple loop check
623 if (prod==part->decayVtx()) return false;
624 // Loop over the parents of this particle.
625 unsigned int nIncoming = prod->nIncomingParticles();
626 for(unsigned int pitr=0; pitr<nIncoming; ++pitr){
627 const xAOD::TruthParticle* itrParent = prod->incomingParticle(pitr);
628 int parentId = itrParent->pdgId();
629 if(MC::isElectron(parentId) ||
630 MC::isMuon(parentId) ||
631 MC::isTau(parentId)) {
632 ATH_MSG_DEBUG("Photon with uniqueID " << HepMC::uniqueID(part) << " matched to particle with pdgId = " << parentId );
633 return true; // Has lepton parent
634 }
635 if(parentId == pdg) { // Same particle just a different MC status
636 // Go up the generator record until a tau is found or not.
637 if(isFsrFromLepton(itrParent)) return true;
638 }
639 }
640 return false;
641}
642
644 //loop over the parents of the truth particle, if the parent is in the list of long lived particles
645 //store this truth particle.
646 for(size_t parent_itr = 0; parent_itr < part->nParents(); parent_itr++){
647 if(!part->parent(parent_itr)) continue;
648 const xAOD::TruthParticle* parent = part->parent(parent_itr);
649 const int parent_abs_pdgid = abs(parent->pdgId());
650 if(std::find(m_longLivedPdgIds.begin(), m_longLivedPdgIds.end(), parent_abs_pdgid) != m_longLivedPdgIds.end() ){
651 return true;
652 }
653 }
654 return false;
655}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
Helper class to provide constant type-safe access to aux data.
Helpers for checking error return status codes and reporting errors.
ATLAS-specific HepMC functions.
static Double_t taus
Handle for requesting thinning for a data object.
static bool isttHFHadron(const xAOD::TruthParticle *)
bool matchQuarkIncTau(const xAOD::TruthParticle *part) const
std::atomic< unsigned int > m_removedpart
bool matchGenParticle(const xAOD::TruthParticle *part, std::vector< int > &targetIDs, std::vector< int > &intermediateIDs, bool targetsAreRange) const
std::atomic< unsigned int > m_totpart
float m_geantPhotonPtThresh
Parameter: Write Geant photons with Pt above this threshold.
bool isAccepted(const xAOD::TruthParticle *) const
bool m_writeGeant
Parameter: Keep geant particles?
bool m_writeTauHad
Parameter: Keep hadronic tau decays?
std::vector< int > m_longLivedPdgIds
Parameter: List of PDG IDs of long lived particles so that one can keep their children.
bool m_writeNotPhysical
Parameter: Write particles with status code 3.
SG::ThinningHandleKey< xAOD::TruthParticleContainer > m_particlesKey
bool parentIsLongLived(const xAOD::TruthParticle *) const
bool m_writeTopAndDecays
Parameter: Write top and decay products.
bool m_writeBHadrons
Parameter: Keep b-hadrons?
bool m_writeLeptonsNotFromHadrons
Parameter: Write all leptons.
virtual StatusCode finalize() override
bool m_writePartons
Parameter: Keep partons?
bool m_preserveDescendants
Parameter: preserve descendant/ancestor graph completeness.
float m_partonPtThresh
Parameter: Write partons with Pt above this threshold.
bool m_writeEverything
Parameter: Write absolutely everything.
SG::ThinningHandleKey< xAOD::TruthVertexContainer > m_verticesKey
int m_writeFirstN
Parameter: First N particles to write.
bool matchHadronIncTau(const xAOD::TruthParticle *part) const
bool isOrphanIncTau(const xAOD::TruthParticle *part) const
virtual StatusCode doThinning() const override
MenuTruthThinning(const std::string &t, const std::string &n, const IInterface *p)
bool m_writettHFHadrons
Parameter: Write particles for tt+HF classification.
bool m_writeHadrons
Parameter: Keep hadrons?
std::vector< int > m_pdgIdsToKeep
Parameter: List of PDG IDs to always keep.
bool m_writeBSMProducts
Parameter: Write BSM decay products.
bool m_writeBSM
Parameter: Keep BSM particles?
bool m_writeBosons
Parameter: Keep bosons?
bool m_writeAllLeptons
Parameter: Write all leptons.
bool isFsrFromLepton(const xAOD::TruthParticle *) const
virtual StatusCode initialize() override
bool m_writeBosonProducts
Parameter: Write boson decay products.
bool m_writeCHadrons
Parameter: Keep c-hadrons?
bool isLeptonFromTau(const xAOD::TruthParticle *) const
bool isFromTau(const xAOD::TruthParticle *, std::unordered_set< int > &barcode_trace) const
Helper class to provide constant type-safe access to aux data.
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
void keep(size_t ndx)
Mark that index ndx in the container should be kept (not thinned away).
Handle for requesting thinning for a data object.
int pdgId() const
PDG ID code.
const TruthVertex_v1 * decayVtx() const
The decay vertex of this particle.
int absPdgId() const
Absolute PDG ID code (often useful)
bool hasDecayVtx() const
Check for a decay vertex on this particle.
virtual double pt() const override final
The transverse momentum ( ) of the particle.
const TruthParticle_v1 * outgoingParticle(size_t index) const
Get one of the outgoing particles.
const TruthParticle_v1 * incomingParticle(size_t index) const
Get one of the incoming particles.
size_t nOutgoingParticles() const
Get the number of outgoing particles.
size_t nIncomingParticles() const
Get the number of incoming particles.
int uniqueID(const T &p)
bool is_simulation_particle(const T &p)
Method to establish if a particle (or barcode) was created during the simulation (TODO update to be s...
bool isZ(const T &p)
bool isCharmHadron(const T &p)
bool isSMLepton(const T &p)
APID: the fourth generation leptons are not standard model leptons.
bool isPhoton(const T &p)
bool isW(const T &p)
bool isBottomHadron(const T &p)
bool isElectron(const T &p)
bool isStable(const T &p)
Identify if the particle is stable, i.e. has not decayed.
bool isTop(const T &p)
bool isMuon(const T &p)
bool isHiggs(const T &p)
APID: HIGGS boson is only one particle.
bool isHadron(const T &p)
bool isLepton(const T &p)
APID: the fourth generation leptons are leptons.
bool isTau(const T &p)
bool isPhysical(const T &p)
Identify if the particle is physical, i.e. is stable or decayed.
bool isBSM(const T &p)
APID: graviton and all Higgs extensions are BSM.
TruthVertex_v1 TruthVertex
Typedef to implementation.
Definition TruthVertex.h:15
TruthParticle_v1 TruthParticle
Typedef to implementation.
void descendants(const xAOD::TruthParticle *pHead, std::vector< int > &particleList, std::unordered_set< int > &encounteredUniqueIDs)
void ancestors(const xAOD::TruthParticle *pHead, std::vector< bool > &particleMask, std::vector< bool > &vertexMask, std::unordered_set< int > &encounteredUniqueIDs)
void immediateRelatives(const xAOD::TruthParticle *pHead, std::vector< bool > &particleMask, std::vector< bool > &vertexMask, bool keepHadVtx)