All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ParticleMaker_module.cc
Go to the documentation of this file.
1 /**
2  * @file ParticleMaker_module.cc
3  * @brief Module creating simulated particles for a test.
4  * @author Gianluca Petrillo (petrillo@fnal.gov)
5  * @date December 27, 2017
6  * @ingroup TotallyCheatTracks
7  *
8  */
9 
10 // LArSoft libraries
13 #include "nusimdata/SimulationBase/MCParticle.h"
14 
15 // framework libraries
16 #include "art/Framework/Core/EDProducer.h"
17 #include "art/Framework/Core/ModuleMacros.h"
18 #include "art/Framework/Principal/Event.h"
19 #include "messagefacility/MessageLogger/MessageLogger.h"
20 #include "fhiclcpp/types/Atom.h"
21 #include "fhiclcpp/types/Sequence.h"
22 #include "fhiclcpp/types/Table.h"
23 
24 // ROOT libraries
25 #include "TVector3.h"
26 #include "TLorentzVector.h"
27 
28 // C/C++ standard libraries
29 #include <array>
30 #include <memory> // std::make_unique()
31 
32 
33 namespace lar {
34  namespace example {
35  namespace tests {
36 
37  // BEGIN TotallyCheatTracks group ----------------------------------------
38  /// @ingroup TotallyCheatTracks
39  /// @{
40 
41  /**
42  * @brief Creates a collection of simulated particles.
43  *
44  * A collection of `simb::MCParticle` is added to the event.
45  * The particles are one starting where the previous one ended (starting
46  * from the origin).
47  * The configuration specifies the number, type and energy of the
48  * particles, and their path length.
49  *
50  * Configuration parameters
51  * =========================
52  *
53  * * *particles* (list of structures, _mandatory_): each element in the
54  * list is a table with entries:
55  * * *length* (real, _mandatory_): particle path length [cm]
56  * * *energy* (real, _mandatory_): particle energy [GeV]
57  * * *type* (integer, _mandatory_): particle type as PDG ID
58  *
59  */
60  class ParticleMaker: public art::EDProducer {
61 
62  public:
63 
64  struct ParticleConfig {
65 
66  using Name = fhicl::Name;
67  using Comment = fhicl::Comment;
68 
69  fhicl::Atom<double> length {
70  Name("length"),
71  Comment("length of the particle path [cm]")
72  };
73 
74  fhicl::Atom<double> energy {
75  Name("energy"),
76  Comment("initial energy of the particle [GeV]")
77  };
78 
79  fhicl::Atom<int> type {
80  Name("type"),
81  Comment("particle type (as PDG ID)")
82  };
83 
84  }; // struct ParticleConfig
85 
86  struct Config {
87 
88  using Name = fhicl::Name;
89  using Comment = fhicl::Comment;
90 
91  fhicl::Sequence<fhicl::Table<ParticleConfig>> particles{
92  Name("particles"),
93  Comment("list of particle specification")
94  };
95 
96  }; // struct Config
97 
98  using Parameters = art::EDProducer::Table<Config>;
99 
100  /// Constructor; see the class documentation for the configuration.
101  explicit ParticleMaker(Parameters const& config);
102 
103  /// Create and add the particles (the same for all events).
104  virtual void produce(art::Event& event) override;
105 
106  private:
107 
108  struct ParticleSpecs {
109  double length;
110  double energy;
111  int type;
112 
114  : length(config.length())
115  , energy(config.energy())
116  , type(config.type())
117  {}
118  }; // ParticleSpecs
119 
120  std::vector<ParticleSpecs> fParticleSpecs; ///< Settings for particles.
121 
122 
123  }; // class ParticleMaker
124 
125  /// @}
126  // END TotallyCheatTracks group ------------------------------------------
127 
128 
129  } // namespace tests
130  } // namespace example
131 } // namespace lar
132 
133 
134 //------------------------------------------------------------------------------
135 //--- module implementation
136 //---
137 
139  : EDProducer{config}
140 {
141 
142  auto const& particleSpecs = config().particles();
143  fParticleSpecs.assign(particleSpecs.begin(), particleSpecs.end());
144 
145  // consumes: nothing
146 
147  // produces:
148  produces<std::vector<simb::MCParticle>>();
149 
150 } // lar::example::tests::ParticleMaker::ParticleMaker()
151 
152 
153 //------------------------------------------------------------------------------
155 
156  //
157  // set up
158  //
159 
160  // container for the data product
161  auto particles = std::make_unique<std::vector<simb::MCParticle>>();
162 
163  //
164  // creation of the particles
165  //
166  static std::array<TVector3, 6U> const Dirs = {{
167  geo::vect::rounded01( geo::Xaxis<TVector3>(), 1e-8),
168  geo::vect::rounded01( geo::Yaxis<TVector3>(), 1e-8),
169  geo::vect::rounded01( geo::Zaxis<TVector3>(), 1e-8),
170  geo::vect::rounded01(-geo::Xaxis<TVector3>(), 1e-8),
171  geo::vect::rounded01(-geo::Yaxis<TVector3>(), 1e-8),
172  geo::vect::rounded01(-geo::Zaxis<TVector3>(), 1e-8)
173  }}; // Dirs
174 
175  int trackID = 0;
176  TLorentzVector pos;
177  for (auto const& specs: fParticleSpecs) {
178 
179  int const motherID = trackID - 1;
180  if (motherID >= 0) (*particles)[motherID].AddDaughter(trackID);
181 
182  particles->emplace_back(
183  trackID // track ID
184  , specs.type // pdg
185  , "magic" // process
186  , motherID // mother
187  );
188  simb::MCParticle& particle = particles->back();
189 
190  auto const& dir = Dirs[trackID % 6];
191  TLorentzVector const mom{ specs.energy * dir, specs.energy };
192  unsigned int const nSteps = std::ceil(specs.length);
193  particle.AddTrajectoryPoint(pos, mom);
194  for (unsigned int i = 1; i <= nSteps; ++i) {
195  double const stepSize = std::min(specs.length - double(i - 1), 1.0);
196  pos += TLorentzVector{ dir * stepSize, 1.0 };
197  particle.AddTrajectoryPoint(pos, mom);
198  } // for
199 
200  ++trackID;
201 
202  } // for specs
203 
204  //
205  // result storage
206  //
207  mf::LogInfo("ParticleMaker")
208  << "Created " << particles->size() << " space points.";
209 
210  event.put(std::move(particles));
211 
212 } // lar::example::tests::ParticleMaker::produce()
213 
214 
215 //------------------------------------------------------------------------------
216 DEFINE_ART_MODULE(lar::example::tests::ParticleMaker)
217 
218 //------------------------------------------------------------------------------
virtual void produce(art::Event &event) override
Create and add the particles (the same for all events).
Creates a collection of simulated particles.
art::EDProducer::Table< Config > Parameters
ParticleMaker(Parameters const &config)
Constructor; see the class documentation for the configuration.
Definitions of geometry vector data types.
fhicl::Sequence< fhicl::Table< ParticleConfig > > particles
Utilities to extend the interface of geometry vectors.
BEGIN_PROLOG vertical distance to the surface Name
Vector rounded01(Vector const &v, Scalar tol)
Returns a vector with all components rounded if close to 0, -1 or +1.
tuple dir
Definition: dropbox.py:28
std::vector< ParticleSpecs > fParticleSpecs
Settings for particles.
do i e