ATLAS Offline Software
Loading...
Searching...
No Matches
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
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
97bool ISF::GenParticleSimAcceptList::pass(const HepMC::GenParticle& particle) const
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
126bool 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
131 passFilter = passFilter && MC::isPhysical(particle);
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.");
161 ATH_MSG_ERROR( particle );
162 throw std::runtime_error("GenParticleSimAcceptList: Particle with no end vertex and not in acceptlist");
163 }
164
165 return passFilter;
166}
167#else
168bool 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
173 passFilter = passFilter && MC::isPhysical(&particle);
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.");
204 ATH_MSG_ERROR( particle );
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}
Scalar perp() const
perp method - perpendicular length
#define ATH_MSG_ERROR(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
ATLAS-specific HepMC functions.
virtual StatusCode finalize() override final
virtual StatusCode initialize() override final
Athena algtool's Hooks.
BooleanProperty m_qs
Switch for quasi-stable particle simulation.
StringArrayProperty m_acceptLists
The location of the accept lists.
virtual bool pass(const HepMC::GenParticle &particle) const override
passes through to the private version
GenParticleSimAcceptList(const std::string &t, const std::string &n, const IInterface *p)
Constructor.
std::vector< long int > m_pdgId
Allowed PDG IDs.
DoubleProperty m_minDecayRadiusQS
Decay radius below which QS particles should be ignored.
static std::string find_file(const std::string &logical_file_name, const std::string &search_path)
int uniqueID(const T &p)
bool is_same_particle(const T1 &p1, const T2 &p2)
Method to establish if two particles in the GenEvent actually represent the same particle.
const GenParticle * ConstGenParticlePtr
Definition GenParticle.h:38
bool isDecayed(const T &p)
Identify if the particle decayed.
bool isNucleus(const T &p)
PDG rule 16 Nuclear codes are given as 10-digit numbers ±10LZZZAAAI.
bool isPhysical(const T &p)
Identify if the particle is physical, i.e. is stable or decayed.
constexpr ParticleHypothesis particle[PARTICLEHYPOTHESES]
the array of masses
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.