ATLAS Offline Software
Loading...
Searching...
No Matches
DecayGraphHelper.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
3*/
4
5// ======================================================================
6// DecayGraphHelper.h
7// James.Catmore@cern.ch
8// Helper struct which implements two simple recursive functions;
9// descends or ascends through a decay from a head particle provided by
10// the user, and records all particles and vertices it encounters in the
11// masks
12//
13// Also contains functions shared by TruthDressing tool and
14// TruthIsolationTool.
15// ======================================================================
16#pragma once
17
23#include <unordered_set>
24
25namespace DerivationFramework {
29
30 // Immediate relatives (parents, siblings, children)
32 std::vector<bool> &particleMask,
33 std::vector<bool> &vertexMask,
34 bool keepHadVtx) {
35
36 // Save the particle position in the mask
37 int headIndex = pHead->index();
38 particleMask[headIndex] = true;
39
40 // Get the production and decay vertex for the particle
41 const xAOD::TruthVertex* decayVtx(0);
42 const xAOD::TruthVertex* prodVtx(0);
43
44 if (pHead->hasDecayVtx()) {
45 decayVtx = pHead->decayVtx();
46 int decayIndex = decayVtx->index();
47 vertexMask[decayIndex] = true;
48 unsigned int nParents = decayVtx->nIncomingParticles();
49 unsigned int nChildren = decayVtx->nOutgoingParticles();
50
51 // Hadronization vertex? (quarks,gluons -> hadrons)
52 bool isHadVtx = true;
53 for (unsigned int i=0; i<nParents; ++i) {
54 if (decayVtx->incomingParticle(i)==nullptr) continue;
55 int idabs = std::abs(decayVtx->incomingParticle(i)->pdgId());
56 isHadVtx = isHadVtx && (idabs<6 || idabs==21);
57 }
58 for (unsigned int i=0; i<nChildren; ++i) {
59 if (decayVtx->outgoingParticle(i)==nullptr) continue;
60 int idabs = std::abs(decayVtx->outgoingParticle(i)->pdgId());
61 isHadVtx = isHadVtx && ((idabs>=80 && idabs<1000000) ||
62 idabs>9000000);
63 }
64
65 if( !isHadVtx || keepHadVtx ){
66 // Get the particles leaving the decay vertex (CHILDREN)
67 for (unsigned int i=0; i<nChildren; ++i) {
68 if (decayVtx->outgoingParticle(i)==nullptr) continue;
69 int childIndex = decayVtx->outgoingParticle(i)->index();
70 particleMask[childIndex] = true;
71 }
72 }
73 }
74
75 if (pHead->hasProdVtx()) {
76 prodVtx = pHead->prodVtx();
77 int prodIndex = prodVtx->index();
78 vertexMask[prodIndex] = true;
79 unsigned int nParents = prodVtx->nIncomingParticles();
80 unsigned int nSiblings = prodVtx->nOutgoingParticles();
81 unsigned int nChildren = nSiblings;
82
83 // Hadronization vertex? (quarks,gluons -> hadrons)
84 bool isHadVtx = true;
85 for (unsigned int i=0; i<nParents; ++i) {
86 if (prodVtx->incomingParticle(i)==nullptr) continue;
87 int idabs = std::abs(prodVtx->incomingParticle(i)->pdgId());
88 isHadVtx = isHadVtx && (idabs<6 || idabs==21);
89 }
90 for (unsigned int i=0; i<nChildren; ++i) {
91 if (prodVtx->outgoingParticle(i)==nullptr) continue;
92 int idabs = std::abs(prodVtx->outgoingParticle(i)->pdgId());
93 isHadVtx = isHadVtx && ((idabs>=80 && idabs<1000000) ||
94 idabs>9000000);
95 }
96
97 if( !isHadVtx || keepHadVtx ){
98 // Get the particles entering the production vertex (PARENTS)
99 for (unsigned int i=0; i<nParents; ++i) {
100 if (prodVtx->incomingParticle(i)==nullptr) continue;
101 int parentIndex = prodVtx->incomingParticle(i)->index();
102 particleMask[parentIndex] = true;
103 }
104 // Get the particles leaving the production vertex (SIBLINGS)
105 for (unsigned int i=0; i<nSiblings; ++i) {
106 if (prodVtx->outgoingParticle(i)==nullptr) continue;
107 int siblingIndex = prodVtx->outgoingParticle(i)->index();
108 particleMask[siblingIndex] = true;
109 }
110 }
111 }
112 return;
113 }
114
115 // descendants: starting from particle (simple listing version)
117 std::vector<int> &particleList,
118 std::unordered_set<int> &encounteredUniqueIDs) {
119
120 // Check that this unique ID hasn't been seen before (e.g. we are in a loop)
121 std::unordered_set<int>::const_iterator found = encounteredUniqueIDs.find(HepMC::uniqueID(pHead));
122 if (found!=encounteredUniqueIDs.end()) return;
123 encounteredUniqueIDs.insert(HepMC::uniqueID(pHead));
124
125 // Get the decay vertex
126 const xAOD::TruthVertex* decayVtx(0);
127 if (pHead->hasDecayVtx()) {decayVtx = pHead->decayVtx();}
128 else {return;}
129
130 // Save the PDG ID number of the particle
131 particleList.push_back(pHead->pdgId());
132
133 // Get children particles and self-call
134 int nChildren = decayVtx->nOutgoingParticles();
135 for (int i=0; i<nChildren; ++i) {
136 if (decayVtx->outgoingParticle(i)==nullptr) continue;
137 descendants(decayVtx->outgoingParticle(i),particleList,encounteredUniqueIDs);
138 }
139 return;
140 }
141
142 // descendants: starting from particle
144 std::vector<bool> &particleMask,
145 std::vector<bool> &vertexMask,
146 std::unordered_set<int> &encounteredUniqueIDs,
147 bool includeGeant) {
148
149 // Check that the particle exists
150 if (pHead==nullptr) return;
151
152 // Check that this unique ID hasn't been seen before (e.g. we are in a loop)
153 std::unordered_set<int>::const_iterator found = encounteredUniqueIDs.find(HepMC::uniqueID(pHead));
154 if (found!=encounteredUniqueIDs.end()) return;
155 encounteredUniqueIDs.insert(HepMC::uniqueID(pHead));
156
157 // Save the particle position in the mask
158 // If user doesn't want Geant, check and reject Geant particles
159 if (!includeGeant && HepMC::is_simulation_particle(pHead) ) return;
160 int headIndex = pHead->index();
161 particleMask[headIndex] = true;
162
163 // Get the decay vertex
164 const xAOD::TruthVertex* decayVtx(0);
165 if (pHead->hasDecayVtx()) {decayVtx = pHead->decayVtx();}
166 else {return;}
167
168 // Get children particles and self-call
169 int nChildren = decayVtx->nOutgoingParticles();
170 bool saveVertex = false;
171 for (int i=0; i<nChildren; ++i) {
172 if (decayVtx->outgoingParticle(i)==nullptr) continue;
173 descendants(decayVtx->outgoingParticle(i),particleMask,vertexMask,encounteredUniqueIDs,includeGeant);
174 saveVertex = saveVertex || includeGeant || !(HepMC::is_simulation_particle(decayVtx->outgoingParticle(i)));
175 }
176
177 // Save the decay vertex
178 if ( saveVertex ) {
179 int vtxIndex = decayVtx->index();
180 vertexMask[vtxIndex] = true;
181 }
182 return;
183 }
184
185 // ancestors: starting from particle
187 std::vector<bool> &particleMask,
188 std::vector<bool> &vertexMask,
189 std::unordered_set<int> &encounteredUniqueIDs ) {
190
191 // Check that the head particle exists
192 if (pHead==nullptr) return;
193
194 // Check that this unique ID hasn't been seen before (e.g. we are in a loop)
195 std::unordered_set<int>::const_iterator found = encounteredUniqueIDs.find(HepMC::uniqueID(pHead));
196 if (found!=encounteredUniqueIDs.end()) return;
197 encounteredUniqueIDs.insert(HepMC::uniqueID(pHead));
198
199 // Save particle position in the mask
200 int headIndex = pHead->index();
201 particleMask[headIndex] = true;
202
203 // Get the production vertex
204 const xAOD::TruthVertex* prodVtx(0);
205 if (pHead->hasProdVtx()) {prodVtx = pHead->prodVtx();}
206 else {return;}
207
208 // Save the production vertex
209 int vtxIndex = prodVtx->index();
210 vertexMask[vtxIndex] = true;
211
212 // Get children particles and self-call
213 int nParents = prodVtx->nIncomingParticles();
214 for (int i=0; i<nParents; ++i) ancestors(prodVtx->incomingParticle(i),particleMask,vertexMask,encounteredUniqueIDs);
215 return;
216 }
217
219 std::vector<const xAOD::TruthParticle*> &selectedlist,
220 const std::vector<int> &pdgId, bool allowFromHadron = false,
221 bool chargedOnly = false) const {
222 //fill the vector selectedlist with only particles with abs(ID) in the list
223 //pdgID that are 'good' for dressing: considered stable by the generator, produced during evgen (for the
224 //photons), not from hadron decay,
225 //skip pdgId check if pdgId is an empty vector,
226 //ignore particles coming from hadrons if allowFromHadron=false,
227 //only use charged particles if chargedOnly=true
228
229 bool skipPdgCheck = (pdgId.size()==0);
230 //bypass the hadron veto?
231 static const SG::AuxElement::ConstAccessor<unsigned int> acc_class{"Classification"};
232 for (xAOD::TruthParticleContainer::const_iterator pItr=allParticles->begin(); pItr!=allParticles->end(); ++pItr) {
233 const xAOD::TruthParticle *particle = *pItr;
234
235 if (!MC::isStable(particle) ) continue;
236 if (!skipPdgCheck && find(pdgId.begin(), pdgId.end(), abs(particle->pdgId())) == pdgId.end()) continue;
237
238 //ensure particles are not from GEANT
239 if ( HepMC::is_simulation_particle(particle)) continue;
240
241 //check if we have a neutral particle (threeCharge returns int)
242 if (chargedOnly && MC::threeCharge(particle->pdgId()) == 0) continue;
243
244 //if we have a particle from hadron decay, and allowFromHadron=false, skip this particle
245 if (!allowFromHadron) {
246 if (!acc_class.isAvailable(*particle)) return false;
247 unsigned int result = acc_class(*particle);
249 if (!isPrompt) continue;
250 }
251
252 //good particle, add to list
253 selectedlist.push_back(particle);
254 }
255 return true;
256 }
257
258 };
259}
260
261
ATLAS-specific HepMC functions.
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
SG::ConstAccessor< T, ALLOC > ConstAccessor
Definition AuxElement.h:569
size_t index() const
Return the index of this element within its container.
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
int pdgId() const
PDG ID code.
const TruthVertex_v1 * decayVtx() const
The decay vertex of this particle.
bool hasProdVtx() const
Check for a production vertex on this particle.
bool hasDecayVtx() const
Check for a decay vertex on this particle.
const TruthVertex_v1 * prodVtx() const
The production vertex of this 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.
std::string find(const std::string &s)
return a remapped string
Definition hcg.cxx:138
THE reconstruction tool.
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...
int isPrompt(const unsigned int classify, bool allow_prompt_tau_decays=true)
double threeCharge(const T &p)
bool isStable(const T &p)
Identify if the particle is stable, i.e. has not decayed.
TruthVertex_v1 TruthVertex
Typedef to implementation.
Definition TruthVertex.h:15
TruthParticle_v1 TruthParticle
Typedef to implementation.
TruthParticleContainer_v1 TruthParticleContainer
Declare the latest version of the truth particle container.
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 descendants(const xAOD::TruthParticle *pHead, std::vector< bool > &particleMask, std::vector< bool > &vertexMask, std::unordered_set< int > &encounteredUniqueIDs, bool includeGeant)
void immediateRelatives(const xAOD::TruthParticle *pHead, std::vector< bool > &particleMask, std::vector< bool > &vertexMask, bool keepHadVtx)
bool constructListOfFinalParticles(const xAOD::TruthParticleContainer *allParticles, std::vector< const xAOD::TruthParticle * > &selectedlist, const std::vector< int > &pdgId, bool allowFromHadron=false, bool chargedOnly=false) const