ATLAS Offline Software
GenParticleSimAcceptList.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // class header include
7 
8 // HepMC includes
10 #include "AtlasHepMC/GenVertex.h"
11 
12 // Helper function
14 
15 // For finding that file
17 
18 // Units
19 #include <fstream>
20 #include <cstdlib>
21 
24  const std::string& n,
25  const IInterface* p )
26  : base_class(t,n,p)
27 {
28 }
29 
30 // Athena algtool's Hooks
32 {
33  ATH_MSG_VERBOSE("Initializing ...");
34 
35  // Initialize the list
36  m_pdgId.clear();
37 
38  for (auto &acceptList : m_acceptLists) {
39  // Get the appropriate file handle
40  std::string resolvedFilename = PathResolver::find_file( acceptList , "DATAPATH" );
41  std::ifstream white_list;
42  white_list.open( resolvedFilename );
43  if (!white_list.is_open()){
44  ATH_MSG_ERROR("Could not find accept list " << acceptList);
45  return StatusCode::FAILURE;
46  }
47 
48  // Parse the list into the vector
49  std::string a_line;
50  char * pEnd;
51  while (!white_list.eof()){
52  getline( white_list , a_line );
53  long int pdg = strtol( a_line.c_str() , &pEnd , 10 );
54  if (std::find(m_pdgId.begin(), m_pdgId.end(), pdg) == m_pdgId.end()) {
55  m_pdgId.push_back(pdg);
56  } else {
57  ATH_MSG_DEBUG("pdgId " << pdg << " already in acceptlist. Will not add it again.");
58  }
59  }
60 
61  // Sort the list for use later
62  std::sort( m_pdgId.begin() , m_pdgId.end() );
63  }
64 
65  // All done!
66  return StatusCode::SUCCESS;
67 }
68 
70 #ifdef HEPMC3
72 {
73 
74  ATH_MSG_VERBOSE( "Checking whether " << particle << " passes the filter." );
75 
76  std::vector<int> vertices(500);
77  bool so_far_so_good = pass( particle , vertices );
78 
79  // Test all parent particles
80  const int id_of_particle = particle->id();
81  if (so_far_so_good && particle->production_vertex() && m_qs){
82  for (auto& pit: particle->production_vertex()->particles_in()){
83  // Loop breaker
84  if ( pit->id() == id_of_particle ) continue;
85  // Check this particle
86  vertices.clear();
87  bool parent_all_clear = pass( pit , vertices );
88  ATH_MSG_VERBOSE( "Parent all clear: " << parent_all_clear <<
89  "\nIf true, will not pass the daughter because it should have been picked up through the parent already (to avoid multi-counting)." );
90  so_far_so_good = so_far_so_good && !parent_all_clear;
91  } // Loop over parents
92  } // particle had parents
93 
94  return so_far_so_good;
95 }
96 #else
98 {
99 
100  ATH_MSG_VERBOSE( "Checking whether " << particle << " passes the filter." );
101 
102  std::vector<int> vertices(500);
103  bool so_far_so_good = pass( particle , vertices );
104 
105  // Test all parent particles
106  if (so_far_so_good && particle.production_vertex() && m_qs){
107  for (HepMC::GenVertex::particle_iterator it = particle.production_vertex()->particles_begin(HepMC::parents);
108  it != particle.production_vertex()->particles_end(HepMC::parents); ++it){
109  // Loop breaker
110  if ( HepMC::is_same_particle(*it,particle) ) continue;
111  // Check this particle
112  vertices.clear();
113  bool parent_all_clear = pass( **it , vertices );
114  ATH_MSG_VERBOSE( "Parent all clear: " << parent_all_clear <<
115  "\nIf true, will not pass the daughter because it should have been picked up through the parent already (to avoid multi-counting)." );
116  so_far_so_good = so_far_so_good && !parent_all_clear;
117  } // Loop over parents
118  } // particle had parents
119 
120  return so_far_so_good;
121 }
122 #endif
123 
125 #ifdef HEPMC3
126 bool ISF::GenParticleSimAcceptList::pass(const HepMC::ConstGenParticlePtr& particle , std::vector<int> & used_vertices ) const
127 {
128  // See if the particle is in the accept list
129  bool passFilter = std::binary_search( m_pdgId.begin() , m_pdgId.end() , particle->pdg_id() ) || MC::isNucleus( particle->pdg_id() );
130  // Remove documentation particles
132  // Test all daughter particles
133  if (particle->end_vertex() && m_qs && passFilter){
134  // Primarily interested in passing particles decaying outside
135  // m_minDecayRadiusQS (nomimally the inner radius of the
136  // beampipe). However, it is also interesting to pass particles
137  // which start outside m_minDecayRadiusQS, but decay inside it.
138  passFilter = passFilter && ( (m_minDecayRadiusQS < particle->end_vertex()->position().perp()) || (m_minDecayRadiusQS < particle->production_vertex()->position().perp()) );
139  if (passFilter) {
140  // Break loops
141  if ( std::find( used_vertices.begin() , used_vertices.end() , particle->end_vertex()->id() )==used_vertices.end() ){
142  used_vertices.push_back( particle->end_vertex()->id() );
143  for (auto& pit: particle->end_vertex()->particles_out()){
144  passFilter = passFilter && pass( pit , used_vertices );
145  if (!passFilter) {
146  ATH_MSG_VERBOSE( "Daughter particle " << pit << " does not pass." );
147  break;
148  }
149  } // Loop over daughters
150  } // Break loops
151  } // particle decayed before the min radius to be considered for simulation
152  else {
153  ATH_MSG_VERBOSE( "Particle " << particle << " was produced and decayed within a radius of " << m_minDecayRadiusQS << " mm.");
154  }
155  } // particle had daughters
156  if (!m_useShadowEvent && !particle->end_vertex() && MC::isDecayed(particle)) { // no daughters... No end vertex... Check if this isn't trouble
157  ATH_MSG_ERROR( "Found a particle with no end vertex that does not appear in the accept list." );
158  ATH_MSG_ERROR( "This is VERY likely pointing to a problem with either the configuration you ");
159  ATH_MSG_ERROR( "are using, or a bug in the generator. Either way it should be fixed. The");
160  ATH_MSG_ERROR( "particle will come next, and then we will throw.");
162  throw std::runtime_error("GenParticleSimAcceptList: Particle with no end vertex and not in acceptlist");
163  }
164 
165  return passFilter;
166 }
167 #else
168 bool ISF::GenParticleSimAcceptList::pass(const HepMC::GenParticle& particle , std::vector<int> & used_vertices ) const
169 {
170  // See if the particle is in the accept list
171  bool passFilter = std::binary_search( m_pdgId.begin() , m_pdgId.end() , particle.pdg_id() ) || MC::isNucleus( particle.pdg_id() );
172  // Remove documentation particles
174  // Test all daughter particles
175  if (particle.end_vertex() && m_qs && passFilter){
176  // Primarily interested in passing particles decaying outside
177  // m_minDecayRadiusQS (nomimally the inner radius of the
178  // beampipe). However, it is also interesting to pass particles
179  // which start outside m_minDecayRadiusQS, but decay inside it.
180  passFilter = passFilter && ( (m_minDecayRadiusQS < particle.end_vertex()->position().perp()) || (m_minDecayRadiusQS < particle.production_vertex()->position().perp()) );
181  if (passFilter) {
182  // Break loops
183  if ( std::find( used_vertices.begin() , used_vertices.end() , HepMC::uniqueID(particle.end_vertex()) )==used_vertices.end() ){
184  used_vertices.push_back( HepMC::uniqueID(particle.end_vertex()) );
185  for (HepMC::GenVertex::particle_iterator it = particle.end_vertex()->particles_begin(HepMC::children);
186  it != particle.end_vertex()->particles_end(HepMC::children); ++it){
187  passFilter = passFilter && pass( **it , used_vertices );
188  if (!passFilter) {
189  ATH_MSG_VERBOSE( "Daughter particle " << **it << " does not pass." );
190  break;
191  }
192  } // Loop over daughters
193  } // Break loops
194  } // particle decayed before the min radius to be considered for simulation
195  else {
196  ATH_MSG_VERBOSE( "Particle " << particle << " was produced and decayed within a radius of " << m_minDecayRadiusQS << " mm.");
197  }
198  } // particle had daughters
199  if (!m_useShadowEvent && !particle.end_vertex() && MC::isDecayed(&particle)) { // no daughters... No end vertex... Check if this isn't trouble
200  ATH_MSG_ERROR( "Found a particle with no end vertex that does not appear in the accept list." );
201  ATH_MSG_ERROR( "This is VERY likely pointing to a problem with either the configuration you ");
202  ATH_MSG_ERROR( "are using, or a bug in the generator. Either way it should be fixed. The");
203  ATH_MSG_ERROR( "particle will come next, and then we will throw.");
205  throw std::runtime_error("GenParticleSimAcceptList: Particle with no end vertex and not in acceptlist");
206  }
207 
208  return passFilter;
209 }
210 #endif
211 
213 {
214  ATH_MSG_VERBOSE("Finalizing ...");
215  return StatusCode::SUCCESS;
216 }
Trk::ParticleSwitcher::particle
constexpr ParticleHypothesis particle[PARTICLEHYPOTHESES]
the array of masses
Definition: ParticleHypothesis.h:76
isNucleus
bool isNucleus(const T &p)
PDG rule 16: Nuclear codes are given as 10-digit numbersĀ±10LZZZAAAI.
Definition: AtlasPID.h:583
GenParticleSimAcceptList.h
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
PathResolver::find_file
static std::string find_file(const std::string &logical_file_name, const std::string &search_path, SearchType search_type=LocalSearch)
Definition: PathResolver.cxx:251
python.DecayParser.parents
parents
print ("==> buf:",buf)
Definition: DecayParser.py:31
GenVertex.h
ISF::GenParticleSimAcceptList::finalize
virtual StatusCode finalize() override final
Definition: GenParticleSimAcceptList.cxx:212
skel.it
it
Definition: skel.GENtoEVGEN.py:396
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
covarianceTool.passFilter
bool passFilter
Definition: covarianceTool.py:604
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
ISF::GenParticleSimAcceptList::pass
virtual bool pass(const HepMC::GenParticle &particle) const override
passes through to the private version
Definition: GenParticleSimAcceptList.cxx:97
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:367
GenParticle.h
ISF::GenParticleSimAcceptList::GenParticleSimAcceptList
GenParticleSimAcceptList(const std::string &t, const std::string &n, const IInterface *p)
Constructor.
Definition: GenParticleSimAcceptList.cxx:23
MC::isPhysical
bool isPhysical(const T &p)
Identify if the particle is physical, i.e. is stable or decayed.
Definition: HepMCHelpers.h:51
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
beamspotman.n
n
Definition: beamspotman.py:731
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
HepMC::uniqueID
int uniqueID(const T &p)
Definition: MagicNumbers.h:116
HepMC::ConstGenParticlePtr
const GenParticle * ConstGenParticlePtr
Definition: GenParticle.h:38
PathResolver.h
ISF::GenParticleSimAcceptList::initialize
virtual StatusCode initialize() override final
Athena algtool's Hooks.
Definition: GenParticleSimAcceptList.cxx:31
MC::isDecayed
bool isDecayed(const T &p)
Identify if the particle decayed.
Definition: HepMCHelpers.h:42
python.DecayParser.children
children
Definition: DecayParser.py:32
HepMCHelpers.h
GenParticle
@ GenParticle
Definition: TruthClasses.h:30