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