ATLAS Offline Software
TruthDecayCollectionMaker.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 // TruthDecayCollectionMaker.cxx
7 // Removes all truth particles/vertices which do not pass a user-defined cut
8 // Based on TruthCollectionMaker (but simpler)
9 
11 #include "StoreGate/ReadHandle.h"
13 #include "StoreGate/WriteHandle.h"
20 
22 
23 // STL includes
24 #include <vector>
25 #include <string>
26 // For a find in the vector
27 #include <algorithm>
28 
29 // Constructor
31  const std::string& n,
32  const IInterface* p)
33  : base_class(t,n,p)
34 {
35 }
36 
37 // Destructor
39 }
40 
41 // Athena initialize
43 {
44  ATH_MSG_VERBOSE("initialize() ...");
45 
46  // Input truth particles
47  ATH_CHECK( m_particlesKey.initialize() );
48  ATH_MSG_INFO("Using " << m_particlesKey.key() << " as the input truth container key");
49 
50  // Accessors (ReadDecorHandleKeys) TODO Convert these to SG::ConstAccessor?
51  ATH_CHECK(m_originAccessorKey.initialize());
52  ATH_CHECK(m_typeAccessorKey.initialize());
53  ATH_CHECK(m_outcomeAccessorKey.initialize());
54  ATH_CHECK(m_classificationAccessorKey.initialize());
55 
56  // Output particle/vertex containers
57  ATH_CHECK(m_outputParticlesKey.initialize());
58  ATH_MSG_INFO("New truth particles container key: " << m_outputParticlesKey.key() );
59  ATH_CHECK(m_outputVerticesKey.initialize());
60  ATH_MSG_INFO("New truth vertices container key: " << m_outputVerticesKey.key() );
61 
62  if (m_pdgIdsToKeep.empty() && !m_keepBHadrons && !m_keepCHadrons && !m_keepBSM) {
63  ATH_MSG_FATAL("No PDG IDs provided, not keeping b- or c-hadrons or BSM particles -- what do you want?");
64  return StatusCode::FAILURE;
65  }
66 
67  // Decorators TODO Convert these to SG::Accessor?
68  ATH_CHECK(m_originDecoratorKey.initialize());
69  ATH_CHECK(m_typeDecoratorKey.initialize());
70  ATH_CHECK(m_outcomeDecoratorKey.initialize());
71  ATH_CHECK(m_classificationDecoratorKey.initialize());
72  ATH_CHECK(m_motherIDDecoratorKey.initialize());
73  ATH_CHECK(m_daughterIDDecoratorKey.initialize());
74 
75  return StatusCode::SUCCESS;
76 }
77 
78 
79 // Selection and collection creation
81 {
82  // Event context for AthenaMT
83  const EventContext& ctx = Gaudi::Hive::currentContext();
84 
85  // Retrieve truth collections
86  SG::ReadHandle<xAOD::TruthParticleContainer> truthParticles(m_particlesKey,ctx);
87  if (!truthParticles.isValid()) {
88  ATH_MSG_ERROR("Couldn't retrieve TruthParticle collection with name " << m_particlesKey);
89  return StatusCode::FAILURE;
90  }
91 
92  // Create the new particle containers and WriteHandles
93  SG::WriteHandle<xAOD::TruthParticleContainer> newParticlesWriteHandle(m_outputParticlesKey, ctx);
94  ATH_CHECK(newParticlesWriteHandle.record(std::make_unique<xAOD::TruthParticleContainer>(),
95  std::make_unique<xAOD::TruthParticleAuxContainer>()));
96  ATH_MSG_DEBUG( "Recorded new TruthParticleContainer with key: " << (m_outputParticlesKey.key()));
97  // Create the new vertex containers and WriteHandles
98  SG::WriteHandle<xAOD::TruthVertexContainer> newVerticesWriteHandle(m_outputVerticesKey, ctx);
99  ATH_CHECK(newVerticesWriteHandle.record(std::make_unique<xAOD::TruthVertexContainer>(),
100  std::make_unique<xAOD::TruthVertexAuxContainer>()));
101  ATH_MSG_DEBUG( "Recorded new TruthVertexContainer with key: " << (m_outputVerticesKey.key()));
102 
103  // List of unique IDs for particles in our collection already. Because of the way we recurse,
104  // adding more particles as we go, there should be no need to add (or help from adding) the
105  // unique IDs of particles that we are *not* going to keep
106  std::vector<int> seen_particles;
107  // Go through that list of particles!
108  for (const auto * part : *truthParticles){
109  // If this passes my cuts, keep it
110  if (id_ok(*part)){
111  addTruthParticle( ctx, *part, newParticlesWriteHandle.ptr(), newVerticesWriteHandle.ptr(), seen_particles , m_generations );
112  }
113  } // Loop over the initial truth particle collection
114  return StatusCode::SUCCESS;
115 }
116 
118  const xAOD::TruthParticle& old_part,
119  xAOD::TruthParticleContainer* part_cont,
120  xAOD::TruthVertexContainer* vert_cont,
121  std::vector<int>& seen_particles,
122  const int generations) const {
123  // See if we've seen it - note, could also do this with a unary function on the container itself
124  if (std::find(seen_particles.begin(),seen_particles.end(),HepMC::uniqueID(&old_part))!=seen_particles.end()){
125  for (size_t p=0;p<part_cont->size();++p){
126  // Was it a hit?
127  const xAOD::TruthParticle *theParticle = (*part_cont)[p];
128  if (HepMC::is_same_particle(theParticle,&old_part)) return p;
129  } // Look through the old container
130  } // Found it in the old container
131  // Now we have seen it
132  seen_particles.push_back(HepMC::uniqueID(&old_part));
133  // Set up decorators
134  SG::WriteDecorHandle<xAOD::TruthParticleContainer, unsigned int > originDecorator(m_originDecoratorKey, ctx);
135  SG::WriteDecorHandle<xAOD::TruthParticleContainer, unsigned int > typeDecorator(m_typeDecoratorKey, ctx);
136  SG::WriteDecorHandle<xAOD::TruthParticleContainer, unsigned int > outcomeDecorator(m_outcomeDecoratorKey, ctx);
137  SG::WriteDecorHandle<xAOD::TruthParticleContainer, unsigned int > classificationDecorator(m_classificationDecoratorKey, ctx);
138  SG::WriteDecorHandle< xAOD::TruthParticleContainer, int > motherIDDecorator(m_motherIDDecoratorKey, ctx);
139  SG::WriteDecorHandle< xAOD::TruthParticleContainer, int > daughterIDDecorator(m_daughterIDDecoratorKey, ctx);
140  // Make a truth particle and add it to the container
141  xAOD::TruthParticle* xTruthParticle = new xAOD::TruthParticle();
142  part_cont->push_back( xTruthParticle );
143  // Fill with numerical content
144  xTruthParticle->setPdgId(old_part.pdgId());
145  xTruthParticle->setUid(HepMC::uniqueID(&old_part));
146  xTruthParticle->setStatus(old_part.status());
147  xTruthParticle->setM(old_part.m());
148  xTruthParticle->setPx(old_part.px());
149  xTruthParticle->setPy(old_part.py());
150  xTruthParticle->setPz(old_part.pz());
151  xTruthParticle->setE(old_part.e());
152  // Copy over the polarization information if it's there
153  if (old_part.polarization().valid()){
156  }
157  // Make a link to this particle
158  int my_index = part_cont->size()-1;
159  ElementLink<xAOD::TruthParticleContainer> eltp(*part_cont, my_index);
160  // Decay vertex information
161  if (old_part.hasDecayVtx()) {
162  int vert_index = addTruthVertex( ctx, *old_part.decayVtx(), part_cont, vert_cont, seen_particles, generations);
163  ElementLink<xAOD::TruthVertexContainer> eltv( *vert_cont, vert_index );
164  xTruthParticle->setDecayVtxLink( eltv );
165  (*vert_cont)[vert_index]->addIncomingParticleLink( eltp );
166  }
167  // Copy over the decorations if they are available
168  SG::ReadDecorHandle<xAOD::TruthParticleContainer, unsigned int > classifierParticleTypeAcc(m_typeAccessorKey, ctx);
169  SG::ReadDecorHandle<xAOD::TruthParticleContainer, unsigned int > classifierParticleOriginAcc(m_originAccessorKey, ctx);
170  SG::ReadDecorHandle<xAOD::TruthParticleContainer, unsigned int > classifierParticleOutcomeAcc(m_outcomeAccessorKey, ctx);
171  SG::ReadDecorHandle<xAOD::TruthParticleContainer, unsigned int > ClassificationAcc(m_classificationAccessorKey, ctx);
172 
173  typeDecorator(*xTruthParticle) = classifierParticleTypeAcc.withDefault (old_part, 0);
174  originDecorator(*xTruthParticle) = classifierParticleOriginAcc.withDefault (old_part, 0);
175  outcomeDecorator(*xTruthParticle) = classifierParticleOutcomeAcc.withDefault (old_part, 0);
176  classificationDecorator(*xTruthParticle) = ClassificationAcc.withDefault (old_part, 0);
177 
178  // Return a link to this particle
179  return my_index;
180 }
181 
183  const xAOD::TruthVertex& old_vert,
184  xAOD::TruthParticleContainer* part_cont,
185  xAOD::TruthVertexContainer* vert_cont,
186  std::vector<int>& seen_particles,
187  const int generations) const {
188  // Make a new vertex and add it to the container
189  xAOD::TruthVertex* xTruthVertex = new xAOD::TruthVertex();
190  vert_cont->push_back( xTruthVertex );
191  // Get a link to this vertex -- will be used to set production vertices on all the next particles
192  int my_index = vert_cont->size()-1;
193  ElementLink<xAOD::TruthVertexContainer> eltv(*vert_cont, my_index);
194  // Set properties
195  xTruthVertex->setStatus(HepMC::status(old_vert));
196  xTruthVertex->setUid(HepMC::uniqueID(old_vert));
197  xTruthVertex->setX(old_vert.x());
198  xTruthVertex->setY(old_vert.y());
199  xTruthVertex->setZ(old_vert.z());
200  xTruthVertex->setT(old_vert.t());
201  // If we are done, then stop here
202  if (generations==0) return my_index;
203  // Add all the outgoing particles
204  for (size_t n=0;n<old_vert.nOutgoingParticles();++n){
205  if (!old_vert.outgoingParticle(n)) continue; // Just in case we removed some truth particles, e.g. G4 decays
206  if (m_rejectHadronChildren && old_vert.outgoingParticle(n)->isHadron()) { // Option to skip hadrons outright{
207  continue;
208  }
209  // Continue on the next generation; note that we only decrement the generation if this particle doesn't also pass our cuts
210  int part_index = addTruthParticle( ctx, *old_vert.outgoingParticle(n), part_cont, vert_cont, seen_particles,
211  generations-1+(id_ok(*old_vert.outgoingParticle(n))?1:0) );
212  ElementLink<xAOD::TruthParticleContainer> eltp( *part_cont, part_index);
213  xTruthVertex->addOutgoingParticleLink( eltp );
214  (*part_cont)[part_index]->setProdVtxLink( eltv );
215  }
216  // Return a link to this vertex
217  return my_index;
218 }
219 
221 {
222  // Check list of PDG IDs to keep
223  for (int id : m_pdgIdsToKeep){
224  if (part.absPdgId()==id){
225  return true;
226  } // Found a particle of interest!
227  } // Loop over the PDG IDs we want to keep
228  // Also check functions for B/C/BSM
229  return (m_keepBHadrons && part.isBottomHadron()) ||
230 
231  (m_keepCHadrons && part.isCharmHadron()) ||
232 
233  (m_keepBSM && part.isBSM());
234 }
LArG4FSStartPointFilter.part
part
Definition: LArG4FSStartPointFilter.py:21
xAOD::TruthVertex_v1::nOutgoingParticles
size_t nOutgoingParticles() const
Get the number of outgoing particles.
xAOD::TruthParticle_v1::setStatus
void setStatus(int value)
Set status code.
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
SG::ReadDecorHandle::withDefault
const_reference_type withDefault(size_t index, const D &deflt)
Fetch the variable for one element, as a const reference.
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
xAOD::TruthParticle_v1::pz
float pz() const
The z component of the particle's momentum.
SG::ReadHandle< xAOD::TruthParticleContainer >
xAOD::TruthParticle_v1::setE
void setE(float value)
Set the energy of the particle.
Definition: TruthParticle_v1.cxx:230
TruthVertexContainer.h
TruthParticleContainer.h
DerivationFramework::TruthDecayCollectionMaker::TruthDecayCollectionMaker
TruthDecayCollectionMaker(const std::string &t, const std::string &n, const IInterface *p)
Definition: TruthDecayCollectionMaker.cxx:30
xAOD::TruthParticle_v1::setPolarizationParameter
bool setPolarizationParameter(float value, PolParam parameter)
Set method for polarization parameter values.
Definition: TruthParticle_v1.cxx:348
xAOD::TruthParticle_v1::Polarization::valid
bool valid() const
Check if the stored values are valid.
Definition: TruthParticle_v1.h:374
xAOD::TruthParticle_v1::polarization
Polarization polarization() const
Retrieve a full Polarization with a single call.
Definition: TruthParticle_v1.cxx:380
xAOD::TruthParticle_v1::px
float px() const
The x component of the particle's momentum.
DerivationFramework::TruthDecayCollectionMaker::initialize
StatusCode initialize()
Definition: TruthDecayCollectionMaker.cxx:42
xAOD::TruthVertex_v1::setT
void setT(float value)
Set the vertex time.
xAOD::TruthParticle_v1::setPx
void setPx(float value)
Set the x component of the particle's momentum.
xAOD::TruthParticle_v1::py
float py() const
The y component of the particle's momentum.
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
xAOD::TruthVertex_v1::addOutgoingParticleLink
void addOutgoingParticleLink(const TPLink_t &link)
Add one outgoing particle.
Definition: TruthVertex_v1.cxx:138
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
xAOD::TruthVertex_v1::setY
void setY(float value)
Set the y displacement of the vertex.
HepMC::is_same_particle
bool is_same_particle(const T1 &p1, const T2 &p2)
Method to establish if two particles in the GenEvent actually represent the same particle.
Definition: MagicNumbers.h:366
xAOD::TruthVertex_v1::y
float y() const
Vertex y displacement.
HepMC::BarcodeBased::generations
int generations(const T &p)
Method to return how many interactions a particle has undergone during simulation (only to be used in...
Definition: MagicNumbers.h:211
xAOD::TruthVertex_v1::t
float t() const
Vertex time.
TruthParticleAuxContainer.h
WriteHandle.h
Handle class for recording to StoreGate.
xAOD::TruthParticle_v1::hasDecayVtx
bool hasDecayVtx() const
Check for a decay vertex on this particle.
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:209
xAOD::TruthParticle_v1::setM
void setM(float value)
Also store the mass.
Definition: TruthParticle_v1.cxx:236
TruthDecayCollectionMaker.h
DerivationFramework::TruthDecayCollectionMaker::addTruthVertex
int addTruthVertex(const EventContext &, const xAOD::TruthVertex &old_vert, xAOD::TruthParticleContainer *part_cont, xAOD::TruthVertexContainer *vert_cont, std::vector< int > &seen_particles, const int generations=-1) const
Definition: TruthDecayCollectionMaker.cxx:182
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
xAOD::TruthParticle_v1::e
virtual double e() const override final
The total energy of the particle.
SG::ReadDecorHandle
Handle class for reading a decoration on an object.
Definition: StoreGate/StoreGate/ReadDecorHandle.h:94
DerivationFramework::TruthDecayCollectionMaker::addTruthParticle
int addTruthParticle(const EventContext &ctx, const xAOD::TruthParticle &old_part, xAOD::TruthParticleContainer *part_cont, xAOD::TruthVertexContainer *vert_cont, std::vector< int > &seen_particles, const int generations=-1) const
Definition: TruthDecayCollectionMaker.cxx:117
beamspotman.n
n
Definition: beamspotman.py:727
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
SG::WriteHandle::ptr
pointer_type ptr()
Dereference the pointer.
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
xAOD::TruthParticle_v1
Class describing a truth particle in the MC record.
Definition: TruthParticle_v1.h:37
SG::WriteDecorHandle
Handle class for adding a decoration to an object.
Definition: StoreGate/StoreGate/WriteDecorHandle.h:100
WriteDecorHandle.h
Handle class for adding a decoration to an object.
xAOD::TruthParticle
TruthParticle_v1 TruthParticle
Typedef to implementation.
Definition: Event/xAOD/xAODTruth/xAODTruth/TruthParticle.h:15
HepMC::uniqueID
int uniqueID(const T &p)
Definition: MagicNumbers.h:116
xAOD::TruthParticle_v1::setPy
void setPy(float value)
Set the y component of the particle's momentum.
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
xAOD::TruthVertex
TruthVertex_v1 TruthVertex
Typedef to implementation.
Definition: TruthVertex.h:15
DataVector
Derived DataVector<T>.
Definition: DataVector.h:794
SG::ReadHandle::isValid
virtual bool isValid() override final
Can the handle be successfully dereferenced?
TruthVertexAuxContainer.h
xAOD::TruthParticle_v1::decayVtx
const TruthVertex_v1 * decayVtx() const
The decay vertex of this particle.
xAOD::TruthVertex_v1
Class describing a truth vertex in the MC record.
Definition: TruthVertex_v1.h:37
xAOD::TruthParticle_v1::setPdgId
void setPdgId(int pid)
Set PDG ID code.
xAOD::TruthParticle_v1::setUid
void setUid(int value)
Set unique ID.
DataVector::push_back
value_type push_back(value_type pElem)
Add an element to the end of the collection.
DerivationFramework::TruthDecayCollectionMaker::id_ok
bool id_ok(const xAOD::TruthParticle &part) const
Definition: TruthDecayCollectionMaker.cxx:220
xAOD::TruthParticle_v1::polarizationParameter
bool polarizationParameter(float &value, PolParam parameter) const
Accessor for polarization parameters.
Definition: TruthParticle_v1.cxx:325
xAOD::TruthVertex_v1::x
float x() const
Vertex x displacement.
xAOD::TruthVertex_v1::setZ
void setZ(float value)
Set the vertex's longitudinal distance from the origin.
SG::WriteHandle
Definition: StoreGate/StoreGate/WriteHandle.h:73
xAOD::TruthParticle_v1::status
int status() const
Status code.
SG::WriteHandle::record
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
xAOD::TruthVertex_v1::setUid
void setUid(int value)
Set the vertex unique ID.
xAOD::TruthParticle_v1::polarizationTheta
@ polarizationTheta
Polarization in ( )
Definition: TruthParticle_v1.h:318
xAOD::TruthParticle_v1::polarizationPhi
@ polarizationPhi
Polarization in ( )
Definition: TruthParticle_v1.h:317
xAOD::TruthVertex_v1::z
float z() const
Vertex longitudinal distance along the beam line form the origin.
xAOD::TruthParticle_v1::setPz
void setPz(float value)
Set the z component of the particle's momentum.
DerivationFramework::TruthDecayCollectionMaker::~TruthDecayCollectionMaker
~TruthDecayCollectionMaker()
Definition: TruthDecayCollectionMaker.cxx:38
ReadDecorHandle.h
Handle class for reading a decoration on an object.
xAOD::TruthParticle_v1::setDecayVtxLink
void setDecayVtxLink(const ElementLink< TruthVertexContainer > &link)
Set the decay vertex of the particle.
ConstAccessor.h
Helper class to provide constant type-safe access to aux data.
ReadHandle.h
Handle class for reading from StoreGate.
HepMC::status
int status(const T &p)
Definition: MagicNumbers.h:143
xAOD::TruthParticle_v1::pdgId
int pdgId() const
PDG ID code.
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
xAOD::TruthVertex_v1::outgoingParticle
const TruthParticle_v1 * outgoingParticle(size_t index) const
Get one of the outgoing particles.
Definition: TruthVertex_v1.cxx:120
xAOD::TruthParticle_v1::m
virtual double m() const override final
The mass of the particle.
xAOD::TruthVertex_v1::setStatus
void setStatus(int value)
Set the vertex status.
HepMCHelpers.h
xAOD::TruthParticle_v1::isHadron
bool isHadron() const
Whether the particle is a hadron.
xAOD::TruthVertex_v1::setX
void setX(float value)
Set the x displacement of the vertex.
DerivationFramework::TruthDecayCollectionMaker::addBranches
virtual StatusCode addBranches() const
Definition: TruthDecayCollectionMaker.cxx:80