ParticleList.h
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 /// \file ParticleList.h
3 /// \brief Particle list in DetSim contains Monte Carlo particle information.
4 ///
5 /// \version $Id: ParticleList.h,v 1.13 2010/05/13 16:12:20 seligman Exp $
6 /// \author seligman@nevis.columbia.edu
7 ////////////////////////////////////////////////////////////////////////
8 ///
9 /// A container for particles generated during an event simulation.
10 /// It acts like a map<int,Particle*> but with additional features:
11 ///
12 /// - A method Cut(double) that will remove all particles with energy
13 /// less than the argument.
14 ///
15 /// - Methods TrackId(int) and Particle(int) for those who are unfamiliar with the
16 /// concepts associated with STL maps:
17 /// sim::ParticleList* particleList = // ...;
18 /// int numberOfParticles = particleList->size();
19 /// for (int i=0; i<numberOfParticles; ++i)
20 /// {
21 /// int trackID = particleList->TrackId(i);
22 /// simb::MCParticle* particle = particleList->Particle(i);
23 /// }
24 /// The STL equivalent to the above statements (more efficient):
25 /// sim::ParticleList* particleList = // ...;
26 /// for ( auto i = particleList->begin();
27 /// i != particleList->end(); ++i )
28 /// {
29 /// const simb::MCParticle* particle = (*i).second;
30 /// int trackID = particle->TrackId(); // or...
31 /// int trackID = (*i).first;
32 /// }
33 /// or, more compact:
34 /// sim::ParticleList* particleList = // ...;
35 /// for ( const auto& i: *particleList)
36 /// {
37 /// const simb::MCParticle* particle = i.second;
38 /// int trackID = particle->TrackId(); // or...
39 /// int trackID = i.first;
40 /// }
41 /// If looping over all the particles, do prefer the second and third forms,
42 /// since the first one is unacceptably inefficient for large events.
43 ///
44 /// - Methods to access the list of primary particles in the event:
45 /// sim::ParticleList particleList = // ...;
46 /// int numberOfPrimaries = particleList->NumberOfPrimaries();
47 /// for ( int i = 0; i != numberOfPrimaries; ++i )
48 /// {
49 /// simb::MCParticle* particle = particleList->Primary(i);
50 /// ...
51 /// }
52 /// There's also a simple test:
53 /// int trackID = // ...;
54 /// if ( particleList->IsPrimary(trackID) ) {...}
55 ///
56 /// (Aside: note that particleList[i] does NOT give you the "i-th"
57 /// particle in the list; it gives you the particle whose trackID
58 /// is "i".)
59 /// Also this form becomes unacceptably inefficient when looping over all the
60 /// particles in a crowded event: prefer to do a bit more of typing as:
61 /// sim::ParticleList* particleList = // ...;
62 /// for ( const auto& i: *particleList)
63 /// {
64 /// int trackID = i.first;
65 /// if (!particleList->IsPrimary(trackID)) continue;
66 /// const simb::MCParticle* primary = i.second;
67 /// // ...
68 /// }
69 ///
70 ///
71 ///
72 
73 /// - A method EveId(int) to determine the "eve ID" (or ultimate
74 /// mother) for a given particle. For more information, including how
75 /// to supply your own eve ID calculation, see
76 /// Simulation/EveIdCalculator.h and Simulation/EmEveIdCalculator.h.
77 
78 /// - Two ParticleLists can be merged, which may be useful for
79 /// modeling overlays:
80 /// sim::ParticleList a,b;
81 /// a.Add(b);
82 /// There's also an operator+ that does the same thing:
83 /// sim::ParticleList c = a + b;
84 /// WARNING! If the track IDs of the two lists overlapped, then
85 /// the results would be garbage. Therefore, the track IDs of the
86 /// second operand are adjusted when the two lists are merged (without
87 /// actually changing the IDs in that second list). Don't rely
88 /// on the track IDs remaining unchanged!
89 ///
90 /// - The previous procedure requires that the track IDs for an entire
91 /// list be adjust by a fixed offset. In case this functionality is
92 /// useful for cases other than merging lists, it's been made
93 /// available via Add(int) and operator+(int) methods:
94 /// sim::ParticleList a,b,combinedAB;
95 /// sim::ParticleList c = b + 10000000; // add 1000000 to all the track IDs in list b
96 /// combinedAB = a + c;
97 ///
98 /// - If you use the clear() or erase() methods, the list will also
99 /// delete the underlying Particle*. (This means that if you use
100 /// insert() or Add() to add a particle to the list, the
101 /// ParticleList will take over management of it. Don't delete the
102 /// pointer yourself!)
103 ///
104 /// - Print() and operator<< methods for ROOT display and ease of
105 /// debugging.
106 
107 #ifndef SIM_PARTICLELIST_H
108 #define SIM_PARTICLELIST_H
109 
111 
112 #include <set>
113 #include <ostream>
114 #include <map>
115 #include <cstdlib> // std::abs()
116 
117 namespace sim {
118 
119  // Forward declarations.
120  class EveIdCalculator;
121 
122  class ParticleList {
123  public:
124  // Some type definitions to make life easier, and to help "hide"
125  // the implementation details. (If you're not familiar with STL,
126  // you can ignore these definitions.)
127  typedef std::map<int,simb::MCParticle*> list_type;
128  typedef list_type::key_type key_type;
129  typedef list_type::mapped_type mapped_type;
130  typedef list_type::value_type value_type;
133  typedef list_type::reverse_iterator reverse_iterator;
134  typedef list_type::const_reverse_iterator const_reverse_iterator;
135  typedef list_type::size_type size_type;
136  typedef list_type::difference_type difference_type;
137  typedef list_type::key_compare key_compare;
138  typedef list_type::allocator_type allocator_type;
139 
140  // Standard constructor, let compiler default the detector
141  ParticleList();
142  virtual ~ParticleList();
143 
144  private:
146  int parentID = 0;
147 
148  archived_info_type() = default;
149 
150  archived_info_type(int pid): parentID(pid) {}
152  : parentID(part.Mother())
153  {}
155  : parentID(part->Mother())
156  {}
157 
158  int Mother() const { return parentID; }
159 
160  friend std::ostream& operator<<
161  ( std::ostream& output, const ParticleList::archived_info_type& );
162  }; // archived_info_type
163 
164 
165  typedef std::set< int > primaries_type;
166  typedef std::map<int, archived_info_type> archive_type;
169 
170  list_type m_particleList; ///< Sorted list of particles in the event
171  primaries_type m_primaries; ///< Sorted list of the track IDs of
172  ///< primary particles.
173  archive_type m_archive; ///< archive of the particles no longer among us
174 
175 #ifndef __GCCXML__
176 
177  public:
178 
179  // Because this list contains pointers, we have to provide the
180  // copy and assignment constructors.
181  // ParticleList( const ParticleList& rhs );
182  // ParticleList& operator=( const ParticleList& rhs );
183 
184  // you know what? let's make it UNCOPIABLE instead!
185  // The cost of copying this buauty is such that we don't want it
186  // to happen unless really requested (copy())
187  ParticleList( const ParticleList& rhs ) = delete;
188  ParticleList& operator=( const ParticleList& rhs ) = delete;
189  ParticleList( ParticleList&& rhs ) = default;
190  ParticleList& operator=( ParticleList&& rhs ) = default;
191 
192  /// Returns a copy of this object
193  ParticleList MakeCopy() const;
194 
195  // The methods advertised above:
196 
197  // Apply an energy threshold cut to the particles in the list,
198  // removing all those that fall below the cut. (Be careful if
199  // you're playing with voxels; this method does not change the
200  // contents of a LArVoxelList.)
201  void Cut( const double& );
202 
203  const key_type& TrackId( const size_type ) const;
204  mapped_type const& Particle( const size_type ) const;
205  mapped_type Particle( const size_type );
206 
207  /// Returns whether we have this particle, live (with full information)
208  bool HasParticle( int trackID ) const
209  {
210  auto iParticle = find(trackID);
211  return (iParticle != end()) && (iParticle->second != nullptr);
212  }
213 
214  /// Returns whether we have had this particle, archived or live
215  bool KnownParticle( int trackID ) const
216  { return find(trackID) != end(); }
217 
218 
219  bool IsPrimary( int trackID ) const;
220  int NumberOfPrimaries() const;
221 
222  std::vector<const simb::MCParticle*> GetPrimaries() const;
223 
224  const simb::MCParticle* Primary( const int ) const;
225  simb::MCParticle* Primary( const int );
226 
227  // Standard STL methods, to make this class look like an STL map.
228  // Again, if you don't know STL, you can just ignore these
229  // methods.
230  iterator begin();
231  const_iterator begin() const;
232  iterator end();
233  const_iterator end() const;
234  reverse_iterator rbegin();
235  const_reverse_iterator rbegin() const;
236  reverse_iterator rend();
237  const_reverse_iterator rend() const;
238 
239  size_type size() const;
240  bool empty() const;
241  void swap( ParticleList& other );
242 
243  iterator find(const key_type& key);
244  const_iterator find(const key_type& key) const;
245  iterator upper_bound(const key_type& key);
246  const_iterator upper_bound(const key_type& key) const;
247  iterator lower_bound(const key_type& key);
248  const_iterator lower_bound(const key_type& key) const;
249 
250  // Be careful when using operator[] here! It takes the track ID as the argument:
251  // sim::ParticleList partList;
252  // const sim::Particle* = partList[3];
253  // The above line means the particle with trackID==3, NOT the third
254  // particle in the list! Use partList.Particle(3) if you want to
255  // get the particles by index number instead of track ID.
256  // Note that this only works in a const context. Use the insert()
257  // or Add() methods to add a new particle to the list.
258  mapped_type const& operator[]( const key_type& key ) const;
259  // This non-const version of operator[] does NOT permit you to insert
260  // Particles into the list. Use Add() or insert() for that.
261  mapped_type operator[]( const key_type& key );
262  mapped_type at(const key_type& key);
263  mapped_type const& at(const key_type& key) const;
264 
265  /// Extracts the key from the specified value
266  key_type key(mapped_type const& part) const;
267 
268  // These two methods do the same thing:
269  // - Add the Particle to the list, using the track ID as the key.
270  // - Update the list of primary particles as needed.
271  // Note that when you insert a Particle* into a ParticleList, it
272  // takes over management of the pointer. Don't delete it yourself!
273  void insert( simb::MCParticle* value );
274  void Add( simb::MCParticle* value );
275 
276  /// Removes the particle from the list, keeping minimal info of it
277  void Archive( const key_type& key );
278  void Archive( const mapped_type& key );
279 
280  /// This function seeks for the exact key, not its absolute value
281  int GetMotherOf( const key_type& key ) const;
282 
283  void clear();
284  size_type erase( const key_type& key );
285  iterator erase( iterator key );
286 
287  friend std::ostream& operator<< ( std::ostream& output, const ParticleList& );
288  friend std::ostream& operator<<
289  ( std::ostream& output, const ParticleList::archived_info_type& );
290 
291  // Methods associated with the eve ID calculation.
292  // Calculate the eve ID.
293  int EveId ( const int trackID ) const;
294  // Set a pointer to a different eve ID calculation. The name
295  // begins with "Adopt" because it accepts control of the ponters;
296  // do NOT delete the pointer yourself if you use this method.
297  static void AdoptEveIdCalculator( EveIdCalculator* );
298 
299 #endif
300  };
301 }
302 
303 #ifndef __GCCXML__
304 
314 inline bool sim::ParticleList::empty() const { return m_particleList.empty(); }
317 { m_particleList.swap( other.m_particleList ); m_archive.swap( other.m_archive ); m_primaries.swap( other.m_primaries); }
319 { return m_particleList.find(abs(key)); }
321 { return m_particleList.find(abs(key)); }
323 { return m_particleList.upper_bound(abs(key)); }
325 { return m_particleList.upper_bound(abs(key)); }
327 { return m_particleList.lower_bound(abs(key)); }
329 { return m_particleList.lower_bound(abs(key)); }
331 { return m_particleList.at(std::abs(key)); }
333 { return m_particleList.at(std::abs(key)); }
335 { return at(key); }
337 { return at(key); }
338 inline sim::ParticleList::key_type sim::ParticleList::key(mapped_type const& part) const { return part->TrackId(); }
339 
340 
341 #endif
342 
343 
344 #endif // SIM_PARTICLELIST_H
intermediate_table::iterator iterator
mapped_type const & operator[](const key_type &key) const
Definition: ParticleList.h:336
ParticleList & operator=(const ParticleList &rhs)=delete
bool empty() const
Definition: ParticleList.h:314
void insert(simb::MCParticle *value)
friend std::ostream & operator<<(std::ostream &output, const ParticleList::archived_info_type &)
ParticleList MakeCopy() const
Returns a copy of this object.
key_type key(mapped_type const &part) const
Extracts the key from the specified value.
Definition: ParticleList.h:338
const key_type & TrackId(const size_type) const
primaries_type m_primaries
Definition: ParticleList.h:171
list_type::value_type value_type
Definition: ParticleList.h:130
virtual ~ParticleList()
list_type::const_iterator const_iterator
Definition: ParticleList.h:132
mapped_type at(const key_type &key)
Definition: ParticleList.h:330
list_type::iterator iterator
Definition: ParticleList.h:131
void Add(simb::MCParticle *value)
Definition: ParticleList.h:315
list_type::reverse_iterator reverse_iterator
Definition: ParticleList.h:133
primaries_type::const_iterator primaries_const_iterator
Definition: ParticleList.h:168
intermediate_table::const_iterator const_iterator
primaries_type::iterator primaries_iterator
Definition: ParticleList.h:167
int EveId(const int trackID) const
Particle class.
std::map< int, simb::MCParticle * > list_type
Definition: ParticleList.h:127
list_type::difference_type difference_type
Definition: ParticleList.h:136
iterator upper_bound(const key_type &key)
Definition: ParticleList.h:322
std::set< int > primaries_type
Definition: ParticleList.h:165
iterator find(const key_type &key)
Definition: ParticleList.h:318
T abs(T value)
iterator lower_bound(const key_type &key)
Definition: ParticleList.h:326
mapped_type const & Particle(const size_type) const
std::map< int, archived_info_type > archive_type
Definition: ParticleList.h:166
bool IsPrimary(int trackID) const
reverse_iterator rbegin()
Definition: ParticleList.h:309
archived_info_type(simb::MCParticle const *part)
Definition: ParticleList.h:154
iterator begin()
Definition: ParticleList.h:305
list_type::const_reverse_iterator const_reverse_iterator
Definition: ParticleList.h:134
list_type::size_type size_type
Definition: ParticleList.h:135
Monte Carlo Simulation.
void Cut(const double &)
int GetMotherOf(const key_type &key) const
This function seeks for the exact key, not its absolute value.
list_type::key_type key_type
Definition: ParticleList.h:128
reverse_iterator rend()
Definition: ParticleList.h:311
archived_info_type(simb::MCParticle const &part)
Definition: ParticleList.h:151
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1225
list_type::allocator_type allocator_type
Definition: ParticleList.h:138
std::vector< const simb::MCParticle * > GetPrimaries() const
list_type::key_compare key_compare
Definition: ParticleList.h:137
const simb::MCParticle * Primary(const int) const
size_type erase(const key_type &key)
bool KnownParticle(int trackID) const
Returns whether we have had this particle, archived or live.
Definition: ParticleList.h:215
void swap(ParticleList &other)
Definition: ParticleList.h:316
list_type m_particleList
Sorted list of particles in the event.
Definition: ParticleList.h:170
static void AdoptEveIdCalculator(EveIdCalculator *)
archive_type m_archive
archive of the particles no longer among us
Definition: ParticleList.h:173
size_type size() const
Definition: ParticleList.h:313
int NumberOfPrimaries() const
list_type::mapped_type mapped_type
Definition: ParticleList.h:129
bool HasParticle(int trackID) const
Returns whether we have this particle, live (with full information)
Definition: ParticleList.h:208
void Archive(const key_type &key)
Removes the particle from the list, keeping minimal info of it.