ATLAS Offline Software
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 
25 namespace DerivationFramework {
28  }
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)
116  void descendants(const xAOD::TruthParticle* pHead,
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
143  void descendants(const xAOD::TruthParticle* pHead,
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
186  void ancestors(const xAOD::TruthParticle* pHead,
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);
248  const bool isPrompt = MCTruthPartClassifier::isPrompt(result, true);
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 
xAOD::TruthVertex_v1::nOutgoingParticles
size_t nOutgoingParticles() const
Get the number of outgoing particles.
DataModel_detail::const_iterator
Const iterator class for DataVector/DataList.
Definition: DVLIterator.h:82
Trk::ParticleSwitcher::particle
constexpr ParticleHypothesis particle[PARTICLEHYPOTHESES]
the array of masses
Definition: ParticleHypothesis.h:76
get_generator_info.result
result
Definition: get_generator_info.py:21
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
TruthVertexContainer.h
TruthParticleContainer.h
threeCharge
double threeCharge(const T &p)
Definition: AtlasPID.h:762
SG::ConstAccessor
Helper class to provide constant type-safe access to aux data.
Definition: ConstAccessor.h:55
MCTruthClassifier.h
DerivationFramework::DecayGraphHelper::constructListOfFinalParticles
bool constructListOfFinalParticles(const xAOD::TruthParticleContainer *allParticles, std::vector< const xAOD::TruthParticle * > &selectedlist, const std::vector< int > &pdgId, bool allowFromHadron=false, bool chargedOnly=false) const
Definition: DecayGraphHelper.h:218
DerivationFramework::DecayGraphHelper::immediateRelatives
void immediateRelatives(const xAOD::TruthParticle *pHead, std::vector< bool > &particleMask, std::vector< bool > &vertexMask, bool keepHadVtx)
Definition: DecayGraphHelper.h:31
DerivationFramework::DecayGraphHelper::descendants
void descendants(const xAOD::TruthParticle *pHead, std::vector< int > &particleList, std::unordered_set< int > &encounteredUniqueIDs)
Definition: DecayGraphHelper.h:116
xAOD::TruthParticle_v1::hasDecayVtx
bool hasDecayVtx() const
Check for a decay vertex on this particle.
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:355
lumiFormat.i
int i
Definition: lumiFormat.py:85
xAOD::TruthParticle_v1
Class describing a truth particle in the MC record.
Definition: TruthParticle_v1.h:37
xAOD::TruthParticle_v1::hasProdVtx
bool hasProdVtx() const
Check for a production vertex on this particle.
Definition: TruthParticle_v1.cxx:74
HepMC::uniqueID
int uniqueID(const T &p)
Definition: MagicNumbers.h:116
DerivationFramework
THE reconstruction tool.
Definition: ParticleSortingAlg.h:24
xAOD::TruthVertex_v1::incomingParticle
const TruthParticle_v1 * incomingParticle(size_t index) const
Get one of the incoming particles.
Definition: TruthVertex_v1.cxx:69
SG::AuxElement::index
size_t index() const
Return the index of this element within its container.
DataVector
Derived DataVector<T>.
Definition: DataVector.h:794
xAOD::TruthParticle_v1::decayVtx
const TruthVertex_v1 * decayVtx() const
The decay vertex of this particle.
xAOD::TruthParticle_v1::prodVtx
const TruthVertex_v1 * prodVtx() const
The production vertex of this particle.
Definition: TruthParticle_v1.cxx:80
xAOD::TruthVertex_v1
Class describing a truth vertex in the MC record.
Definition: TruthVertex_v1.h:37
MagicNumbers.h
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
DerivationFramework::DecayGraphHelper
Definition: DecayGraphHelper.h:26
DataVector::end
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
MC::isStable
bool isStable(const T &p)
Identify if the particle is stable, i.e. has not decayed.
Definition: HepMCHelpers.h:45
DerivationFramework::DecayGraphHelper::descendants
void descendants(const xAOD::TruthParticle *pHead, std::vector< bool > &particleMask, std::vector< bool > &vertexMask, std::unordered_set< int > &encounteredUniqueIDs, bool includeGeant)
Definition: DecayGraphHelper.h:143
XMLtoHeader.childIndex
childIndex
Definition: XMLtoHeader.py:67
CondAlgsOpts.found
int found
Definition: CondAlgsOpts.py:101
MCTruthPartClassifier::isPrompt
int isPrompt(const unsigned int classify, bool allow_prompt_tau_decays=true)
Definition: TruthClassifiers.h:180
xAOD::TruthVertex_v1::nIncomingParticles
size_t nIncomingParticles() const
Get the number of incoming particles.
Definition: TruthVertex_v1.cxx:47
xAOD::TruthParticle_v1::pdgId
int pdgId() const
PDG ID code.
DerivationFramework::DecayGraphHelper::DecayGraphHelper
DecayGraphHelper()
Definition: DecayGraphHelper.h:27
xAOD::TruthVertex_v1::outgoingParticle
const TruthParticle_v1 * outgoingParticle(size_t index) const
Get one of the outgoing particles.
Definition: TruthVertex_v1.cxx:119
HepMCHelpers.h
DataVector::begin
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.