ATLAS Offline Software
Loading...
Searching...
No Matches
TruthNavigationDecorator.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// TruthNavigationDecorator.cxx
7// Add navigation information to small truth collections
8
11#include <algorithm> //for std::find
12
13// Initialise
15
16 // Initialise input keys
17 ATH_CHECK( m_inputKeys.initialize() );
18 ATH_CHECK( m_truthEventKey.initialize() );
19 ATH_CHECK( m_parentLinksDecorKeys.initialize() );
20 ATH_CHECK( m_childLinksDecorKeys.initialize() );
21
22 return StatusCode::SUCCESS;
23
24}
25
26// Function to do dressing, implements interface in IAugmentationTool
27StatusCode DerivationFramework::TruthNavigationDecorator::addBranches(const EventContext& ctx) const
28{
29 // Event context
30
31 // Retrieve the truth collections
33 if (!truthEvents.isValid()) {
34 ATH_MSG_ERROR("Couldn't retrieve TruthEvent collection with name " << m_truthEventKey);
35 return StatusCode::FAILURE;
36 }
37
38 // Retrieve all the individual particle collections
39 std::vector<SG::ReadHandle<xAOD::TruthParticleContainer> > inputParticles;
40 inputParticles.reserve(m_inputKeys.size());
42 inputParticles.push_back(SG::ReadHandle<xAOD::TruthParticleContainer>(inputKey, ctx));
43 }
44
45 // Build a dictionary of uniqueIDs and element links
46 std::map<int,ElementLink<xAOD::TruthParticleContainer> > linkMap;
47 for (auto& coll : inputParticles){
48 for (size_t p=0;p<coll.ptr()->size();++p){
49 if (!coll.ptr()->at(p)) continue; // Protection against null ptrs
50 if (linkMap.find(HepMC::uniqueID(coll.ptr()->at(p))) != linkMap.end()) continue; // Particle in multiple collections
51 linkMap[HepMC::uniqueID(coll.ptr()->at(p))] = ElementLink<xAOD::TruthParticleContainer>(*coll,p);
52 } // Loop over particles in the collection
53 } // Loop over collections
54
55 // Now loop over the collections and for each one decorate children and parents
56 // The list of particles we keep is small-ish, and the list of particles in the
57 // original truth record is large-ish, so I think it will be more efficient to
58 // do a loop (O(N)) over the big record and a search (O(Nlog(N))) over the small
59 // container. Future performance optimization is welcome...
60
61 // Keep maps, do the decoration last. This ensures that duplicates all get decorated.
62 std::map< int , std::vector<ElementLink<xAOD::TruthParticleContainer> > > parentMap;
63 std::map< int , std::vector<ElementLink<xAOD::TruthParticleContainer> > > childMap;
64
65 // Loop protection
66 std::vector<int> seen_particles(20);
67 // As usual, only consider the first truth event
68 const xAOD::TruthEvent * event = truthEvents->at(0);
69 for (size_t p=0;p<event->nTruthParticles();++p){
70 if (!event->truthParticle(p)) continue; // Protection against null ptrs
71 if (linkMap.find(HepMC::uniqueID(event->truthParticle(p))) == linkMap.end()) continue; // Not a particle we are interested in
72 // Make parent and child lists
73 std::vector<ElementLink<xAOD::TruthParticleContainer> > parents;
74 std::vector<ElementLink<xAOD::TruthParticleContainer> > children;
75 // Populate the lists - include loop protection
76 seen_particles.clear();
77 find_parents( event->truthParticle(p) , parents , linkMap , seen_particles );
78 seen_particles.clear();
79 find_children( event->truthParticle(p) , children , linkMap , seen_particles );
80 // Set the maps, so that we can decorate later
81 parentMap[HepMC::uniqueID(event->truthParticle(p))] = std::move(parents);
82 childMap[HepMC::uniqueID(event->truthParticle(p))] = std::move(children);
83 } // Loop over truth particles in the big truth collection
84
85 // Now final loop over the collections and setting all the decorators
86 auto parent_decorator = m_parentLinksDecorKeys.makeHandles (ctx);
87 auto child_decorator = m_childLinksDecorKeys.makeHandles (ctx);
88 unsigned int pCntr{0};
89 for (auto coll : inputParticles){
90 if (parent_decorator.at(pCntr).isAvailable()) {
91 ++pCntr;
92 continue;
93 }
94 for (size_t p=0;p<coll.ptr()->size();++p){
95 if (!coll.ptr()->at(p)) continue; // Protection against null ptrs
96 parent_decorator.at(pCntr)(*coll.ptr()->at(p)) = parentMap[ HepMC::uniqueID(coll->at(p)) ];
97 child_decorator.at(pCntr)(*coll.ptr()->at(p)) = childMap[ HepMC::uniqueID(coll->at(p)) ];
98 } // Loop over the particles in each collection
99 ++pCntr;
100 } // Loop over the collections
101
102 return StatusCode::SUCCESS;
103}
104
106 std::vector<ElementLink<xAOD::TruthParticleContainer> >& parents ,
107 std::map<int,ElementLink<xAOD::TruthParticleContainer> >& linkMap ,
108 std::vector<int>& seen_particles ) const {
109 // Null pointer protection
110 if (!part) return;
111 // Check if we've seen the particle before, otherwise add it to our list
112 if (std::find(seen_particles.begin(), seen_particles.end(), HepMC::uniqueID(part)) != seen_particles.end()) return;
113 seen_particles.push_back(HepMC::uniqueID(part));
114 // Loop through the parents and see if we know about them; otherwise iterate through the list
115 for (size_t parent=0;parent<part->nParents();++parent){
116 if (!part->parent(parent)) continue; // Null pointer check
117 if (linkMap.find(HepMC::uniqueID(part->parent(parent))) != linkMap.end()){
118 // Hit! Add it to the list
119 parents.push_back( linkMap[HepMC::uniqueID(part->parent(parent))] );
120 } else {
121 // Not a hit yet, keep iterating
122 find_parents( part->parent(parent) , parents , linkMap , seen_particles );
123 }
124 } // Loop over parents
125}
126
128 std::vector<ElementLink<xAOD::TruthParticleContainer> >& children ,
129 std::map<int,ElementLink<xAOD::TruthParticleContainer> >& linkMap ,
130 std::vector<int>& seen_particles ) const {
131 // Null pointer protection
132 if (!part) return;
133 // Check if we've seen the particle before, otherwise add it to our list
134 if (std::find(seen_particles.begin(),seen_particles.end(),HepMC::uniqueID(part)) != seen_particles.end()) return;
135 seen_particles.push_back(HepMC::uniqueID(part));
136 // Look through the children and see if we know about them; otherwise iterate through the list
137 for (size_t child=0;child<part->nChildren();++child){
138 if (!part->child(child)) continue; // Null pointer check
139 if (linkMap.find(HepMC::uniqueID(part->child(child))) != linkMap.end()){
140 // Hit! Add it to the list
141 children.push_back( linkMap[HepMC::uniqueID(part->child(child))] );
142 } else {
143 // Not a hit yet, keep iterating
144 find_children( part->child(child) , children , linkMap , seen_particles );
145 }
146 } // Loop over parents
147}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
void find_parents(const xAOD::TruthParticle *part, std::vector< ElementLink< xAOD::TruthParticleContainer > > &parents, std::map< int, ElementLink< xAOD::TruthParticleContainer > > &linkMap, std::vector< int > &seen_particles) const
Helper function for finding all the parents of a particle.
void find_children(const xAOD::TruthParticle *part, std::vector< ElementLink< xAOD::TruthParticleContainer > > &parents, std::map< int, ElementLink< xAOD::TruthParticleContainer > > &linkMap, std::vector< int > &seen_particles) const
Helper function for finding all the children of a particle.
SG::ReadHandleKeyArray< xAOD::TruthParticleContainer > m_inputKeys
Parameter: input particle collections.
virtual StatusCode addBranches(const EventContext &ctx) const override final
SG::ReadHandleKey< xAOD::TruthEventContainer > m_truthEventKey
SG::WriteDecorHandleKeyArray< xAOD::TruthParticleContainer, std::vector< ElementLink< xAOD::TruthParticleContainer > > > m_childLinksDecorKeys
SG::WriteDecorHandleKeyArray< xAOD::TruthParticleContainer, std::vector< ElementLink< xAOD::TruthParticleContainer > > > m_parentLinksDecorKeys
Decor keys.
Property holding a SG store/key/clid from which a ReadHandle is made.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
int uniqueID(const T &p)
TruthEvent_v1 TruthEvent
Typedef to implementation.
Definition TruthEvent.h:17
TruthParticle_v1 TruthParticle
Typedef to implementation.