SingleGen_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 /// \file SingleGen_plugin.cc
3 /// \brief Generator for cosmic-rays
4 ///
5 /// Module designed to produce a set list of particles for a MC event
6 ///
7 /// \version $Id: SingleGen.cxx,v 1.4 2010/03/29 09:54:01 brebel Exp $
8 /// \author brebel@fnal.gov
9 ////////////////////////////////////////////////////////////////////////
10 #ifndef EVGEN_SINGLEGEN
11 #define EVGEN_SINGLEGEN
12 
13 // C++ includes.
14 #include <iostream>
15 #include <sstream>
16 #include <string>
17 #include <cmath>
18 #include <memory>
19 #include <iterator>
20 #include <vector>
21 
22 
23 // Framework includes
26 #include "fhiclcpp/ParameterSet.h"
29 #include "art_root_io/TFileService.h"
30 #include "art_root_io/TFileDirectory.h"
34 #include "cetlib_except/exception.h"
35 
36 // art extensions
37 
38 // nutools includes
41 #include "nugen/EventGeneratorBase/evgenbase.h"
42 #include "nurandom/RandomUtils/NuRandomService.h"
43 
44 // gar includes
45 #include "Geometry/GeometryGAr.h"
47 #include "CoreUtils/ServiceUtil.h"
48 
49 #include "TVector3.h"
50 #include "TDatabasePDG.h"
51 #include "TMath.h"
52 
53 #include "CLHEP/Random/RandFlat.h"
54 #include "CLHEP/Random/RandGaussQ.h"
55 
56 namespace simb { class MCTruth; }
57 
58 namespace gar{
59  namespace evgen {
60 
61  /// module to produce single or multiple specified particles in the detector
62  class SingleGen : public ::art::EDProducer {
63 
64  public:
65  explicit SingleGen(fhicl::ParameterSet const& pset);
66  virtual ~SingleGen();
67 
68  // This is called for each event.
69  void produce(::art::Event& evt);
70  void beginRun(::art::Run& run);
71  void reconfigure(fhicl::ParameterSet const& p);
72 
73  private:
74 
75  void SampleOne(unsigned int i,
76  simb::MCTruth & mct);
77  void Sample(simb::MCTruth & mct);
78  void printVecs(std::vector<std::string> const& list);
79  bool PadVector(std::vector<double> &vec);
80 
81  static const int kUNIF = 0;
82  static const int kGAUS = 1;
83 
84  int fMode; ///< Particle Selection Mode
85  ///< 0--generate a list of all particles,
86  ///< 1--generate a single particle selected randomly from the list
87  bool fPadOutVectors; ///< Select to pad out configuration vectors if they are not of
88  ///< of the same length as PDG
89  ///< false: don't pad out - all values need to specified
90  ///< true: pad out - default values assumed and printed out
91  std::vector<int> fPDG; ///< PDG code of particles to generate
92  std::vector<double> fP0; ///< Central momentum (GeV/c) to generate
93  std::vector<double> fSigmaP; ///< Variation in momenta (GeV/c)
94  int fPDist; ///< How to distribute momenta (gaus or uniform)
95  std::vector<double> fX0; ///< Central x position (cm) in world coordinates
96  std::vector<double> fY0; ///< Central y position (cm) in world coordinates
97  std::vector<double> fZ0; ///< Central z position (cm) in world coordinates
98  std::vector<double> fT0; ///< Central t position (s) in world coordinates
99  std::vector<double> fSigmaX; ///< Variation in x position (cm)
100  std::vector<double> fSigmaY; ///< Variation in y position (cm)
101  std::vector<double> fSigmaZ; ///< Variation in z position (cm)
102  std::vector<double> fSigmaT; ///< Variation in t position (s)
103  int fPosDist; ///< How to distribute xyz (gaus, or uniform)
104  int fTDist; ///< How to distribute t (gaus, or uniform)
105  std::vector<double> fTheta0XZ; ///< Angle in XZ plane (degrees)
106  std::vector<double> fTheta0YZ; ///< Angle in YZ plane (degrees)
107  std::vector<double> fSigmaThetaXZ; ///< Variation in angle in XZ plane
108  std::vector<double> fSigmaThetaYZ; ///< Variation in angle in YZ plane
109  int fAngleDist; ///< How to distribute angles (gaus, uniform)
110 
111  CLHEP::HepRandomEngine &fEngine;
112 
113  };
114 
115  //____________________________________________________________________________
116  SingleGen::SingleGen(fhicl::ParameterSet const& pset) :
117  art::EDProducer{pset},
119  {
120 
121  this->reconfigure(pset);
122 
123  produces< std::vector<simb::MCTruth> >();
124  produces< sumdata::RunData, ::art::InRun >();
125 
126  }
127 
128  //____________________________________________________________________________
130  {
131  }
132 
133  //____________________________________________________________________________
135  {
136 
137  fPadOutVectors = p.get< bool >("PadOutVectors");
138  fMode = p.get< int >("ParticleSelectionMode");
139  fPDG = p.get< std::vector<int> >("PDG");
140  fP0 = p.get< std::vector<double> >("P0");
141  fSigmaP = p.get< std::vector<double> >("SigmaP");
142  fPDist = p.get< int >("PDist");
143  fTDist = p.get< int >("TDist");
144  fX0 = p.get< std::vector<double> >("X0");
145  fY0 = p.get< std::vector<double> >("Y0");
146  fZ0 = p.get< std::vector<double> >("Z0");
147  fT0 = p.get< std::vector<double> >("T0");
148  fSigmaX = p.get< std::vector<double> >("SigmaX");
149  fSigmaY = p.get< std::vector<double> >("SigmaY");
150  fSigmaZ = p.get< std::vector<double> >("SigmaZ");
151  fSigmaT = p.get< std::vector<double> >("SigmaT");
152  fPosDist = p.get< int >("PosDist");
153  fTheta0XZ = p.get< std::vector<double> >("Theta0XZ");
154  fTheta0YZ = p.get< std::vector<double> >("Theta0YZ");
155  fSigmaThetaXZ = p.get< std::vector<double> >("SigmaThetaXZ");
156  fSigmaThetaYZ = p.get< std::vector<double> >("SigmaThetaYZ");
157  fAngleDist = p.get< int >("AngleDist");
158 
159  std::vector<std::string> vlist(15);
160  vlist[0] = "PDG";
161  vlist[1] = "P0";
162  vlist[2] = "SigmaP";
163  vlist[3] = "X0";
164  vlist[4] = "Y0";
165  vlist[5] = "Z0";
166  vlist[6] = "SigmaX";
167  vlist[7] = "SigmaY";
168  vlist[8] = "SigmaZ";
169  vlist[9] = "Theta0XZ";
170  vlist[10] = "Theta0YZ";
171  vlist[11] = "SigmaThetaXZ";
172  vlist[12] = "SigmaThetaYZ";
173  vlist[13] = "T0";
174  vlist[14] = "SigmaT";
175 
176 
177  // begin tests for multiple particle error possibilities
178  std::string list;
179  if( !this->PadVector(fP0 ) ) list.append(vlist[1] .append(", \n"));
180  if( !this->PadVector(fSigmaP ) ) list.append(vlist[2] .append(", \n"));
181  if( !this->PadVector(fX0 ) ) list.append(vlist[3] .append(", \n"));
182  if( !this->PadVector(fY0 ) ) list.append(vlist[4] .append(", \n"));
183  if( !this->PadVector(fZ0 ) ) list.append(vlist[5] .append(", \n"));
184  if( !this->PadVector(fSigmaX ) ) list.append(vlist[6] .append(", \n"));
185  if( !this->PadVector(fSigmaY ) ) list.append(vlist[7] .append(", \n"));
186  if( !this->PadVector(fSigmaZ ) ) list.append(vlist[8] .append(", \n"));
187  if( !this->PadVector(fTheta0XZ ) ) list.append(vlist[9] .append(", \n"));
188  if( !this->PadVector(fTheta0YZ ) ) list.append(vlist[10].append(", \n"));
189  if( !this->PadVector(fSigmaThetaXZ) ) list.append(vlist[11].append(", \n"));
190  if( !this->PadVector(fSigmaThetaYZ) ) list.append(vlist[12].append(" \n"));
191  if( !this->PadVector(fT0 ) ) list.append(vlist[13].append(", \n"));
192  if( !this->PadVector(fSigmaT ) ) list.append(vlist[14].append(", \n"));
193 
194  if(list.size() > 0)
195  throw cet::exception("SingleGen") << "The "<< list
196  << "\n vector(s) defined in the fhicl files has/have "
197  << "a different size than the PDG vector "
198  << "\n and it has (they have) more than one value, "
199  << "\n disallowing sensible padding "
200  << " and/or you have set fPadOutVectors to false. \n";
201 
202  if(fPDG.size() > 1 && fPadOutVectors) this->printVecs(vlist);
203 
204  return;
205  }
206 
207  //____________________________________________________________________________
208  bool SingleGen::PadVector(std::vector<double> &vec)
209  {
210  // check if the vec has the same size as fPDG
211  if( vec.size() != fPDG.size() ){
212  // if not padding out the vectors always cause an
213  // exception to be thrown if the vector in question
214  // is not the same size as the fPDG vector
215  // the exception is thrown in the reconfigure method
216  // that calls this one
217  if (!fPadOutVectors) return false;
218  else {
219  // if padding of vectors is desired but the vector in
220  // question has more than one entry it isn't clear
221  // what the padded values should be so cause
222  // an exception
223  if(vec.size() != 1) return false;
224 
225  // pad it out
226  vec.resize(fPDG.size(), vec[0]);
227 
228  }// end if padding out vectors
229  }// end if the vector size is not the same as fPDG
230 
231  return true;
232  }
233 
234  //____________________________________________________________________________
236  {
237 
238  // grab the geometry object to see what geometry we are using
239  auto geo = gar::providerFrom<geo::GeometryGAr>();
240  std::string name(geo->DetectorName());
241  std::unique_ptr<gar::sumdata::RunData> runcol(new gar::sumdata::RunData(name));
242 
243  run.put(std::move(runcol));
244 
245  return;
246  }
247 
248  //____________________________________________________________________________
250  {
251 
252  ///unique_ptr allows ownership to be transferred to the ::art::Event after the put statement
253  std::unique_ptr< std::vector<simb::MCTruth> > truthcol(new std::vector<simb::MCTruth>);
254 
255  simb::MCTruth truth;
257  Sample(truth);
258 
259  MF_LOG_DEBUG("SingleGen") << truth;
260 
261  truthcol->push_back(truth);
262 
263  evt.put(std::move(truthcol));
264 
265  return;
266  }
267 
268  //____________________________________________________________________________
269  // Draw the type, momentum and position of a single particle from the
270  // FCIHL description
271  void SingleGen::SampleOne(unsigned int i,
272  simb::MCTruth & mct){
273 
274  // get the random number generator service and make some CLHEP generators
275  CLHEP::RandFlat flat(fEngine);
276  CLHEP::RandGaussQ gauss(fEngine);
277 
278  // Choose momentum
279  double p = 0.0;
280  double m = 0.0;
281  if (fPDist == kGAUS) {
282  p = gauss.fire(fP0[i], fSigmaP[i]);
283  }
284  else {
285  p = fP0[i] + fSigmaP[i]*(2.0*flat.fire()-1.0);
286  }
287 
288  static TDatabasePDG pdgt;
289  TParticlePDG* pdgp = pdgt.GetParticle(fPDG[i]);
290  if (pdgp) m = pdgp->Mass();
291 
292  // Choose position
293  TVector3 x;
294  if (fPosDist == kGAUS) {
295  x[0] = gauss.fire(fX0[i], fSigmaX[i]);;
296  x[1] = gauss.fire(fY0[i], fSigmaY[i]);
297  x[2] = gauss.fire(fZ0[i], fSigmaZ[i]);
298  }
299  else {
300  x[0] = fX0[i] + fSigmaX[i]*(2.0*flat.fire()-1.0);
301  x[1] = fY0[i] + fSigmaY[i]*(2.0*flat.fire()-1.0);
302  x[2] = fZ0[i] + fSigmaZ[i]*(2.0*flat.fire()-1.0);
303  }
304 
305  double t = 0.;
306  if(fTDist==kGAUS){
307  t = gauss.fire(fT0[i], fSigmaT[i]);
308  }
309  else{
310  t = fT0[i] + fSigmaT[i]*(2.0*flat.fire()-1.0);
311  }
312 
313  TLorentzVector pos(x[0], x[1], x[2], t);
314 
315  // Choose angles
316  double thxz = 0;
317  double thyz = 0;
318 
319  double thyzrads = 0;
320  double thyzradsplussigma = 0;
321  double thyzradsminussigma = 0;
322 
323  if (fAngleDist == kGAUS) {
324  thxz = gauss.fire(fTheta0XZ[i], fSigmaThetaXZ[i]);
325  thyz = gauss.fire(fTheta0YZ[i], fSigmaThetaYZ[i]);
326  }
327  else {
328 
329  // Choose angles flat in phase space, which is flat in theta_xz
330  // and flat in sin(theta_yz).
331 
332  thxz = fTheta0XZ[i] + fSigmaThetaXZ[i]*(2.0*flat.fire()-1.0);
333 
334  //Taking asin of sin gives value between -Pi/2 and Pi/2 regardless of user input
335  thyzrads = std::asin(std::sin((M_PI/180.)*(fTheta0YZ[i])));
336  thyzradsplussigma = TMath::Min((thyzrads + ((M_PI/180.)*fabs(fSigmaThetaYZ[i]))), M_PI/2.);
337  thyzradsminussigma = TMath::Max((thyzrads - ((M_PI/180.)*fabs(fSigmaThetaYZ[i]))), -M_PI/2.);
338 
339  double sinthyzmin = std::sin(thyzradsminussigma);
340  double sinthyzmax = std::sin(thyzradsplussigma);
341  double sinthyz = sinthyzmin + flat.fire() * (sinthyzmax - sinthyzmin);
342  thyz = (180. / M_PI) * std::asin(sinthyz);
343  }
344 
345  double thxzrad = thxz*M_PI/180.0;
346  double thyzrad = thyz*M_PI/180.0;
347 
348  TLorentzVector pvec(p*std::cos(thyzrad)*std::sin(thxzrad),
349  p*std::sin(thyzrad),
350  p*std::cos(thxzrad)*std::cos(thyzrad),
351  std::sqrt(p*p+m*m));
352 
353  // set track id to -i as these are all primary particles and have id <= 0
354  int trackid = -1 * (i + 1);
355  std::string primary("primary");
356 
357  simb::MCParticle part(trackid, fPDG[i], primary);
358  part.AddTrajectoryPoint(pos, pvec);
359 
360  mct.Add(part);
361  }
362 
363  //____________________________________________________________________________
365  {
366 
367  switch (fMode) {
368  case 0: // List generation mode: every event will have one of each
369  // particle species in the fPDG array
370  for (unsigned int i=0; i<fPDG.size(); ++i) {
371  SampleOne(i,mct);
372  }//end loop over particles
373  break;
374  case 1: // Random selection mode: every event will exactly one particle
375  // selected randomly from the fPDG array
376  {
377  CLHEP::RandFlat flat(fEngine);
378 
379  unsigned int i=flat.fireInt(fPDG.size());
380  SampleOne(i,mct);
381  }
382  break;
383  default:
384  MF_LOG_WARNING("UnrecognizeOption")
385  << "SingleGen does not recognize ParticleSelectionMode "
386  << fMode;
387  break;
388  } // switch on fMode
389 
390  return;
391  }
392 
393  //____________________________________________________________________________
394  void SingleGen::printVecs(std::vector<std::string> const& list)
395  {
396 
397  MF_LOG_INFO("SingleGen")
398  << " You are using vector values for SingleGen configuration.\n "
399  << " Some of the configuration vectors may have been padded out ,"
400  << " because they (weren't) as long as the pdg vector"
401  << " in your configuration. \n"
402  << " The new input particle configuration is:\n" ;
403 
405  for(size_t i = 0; i < list.size(); ++i){
406 
407  values.append(list[i]);
408  values.append(": [ ");
409 
410  for(size_t e = 0; e < fPDG.size(); ++e){
411  std::stringstream buf;
412  buf.width(10);
413  if(i == 0 ) buf << fPDG[e] << ", ";
414  buf.precision(5);
415  if(i == 1 ) buf << fP0[e] << ", ";
416  if(i == 2 ) buf << fSigmaP[e] << ", ";
417  if(i == 3 ) buf << fX0[e] << ", ";
418  if(i == 4 ) buf << fY0[e] << ", ";
419  if(i == 5 ) buf << fZ0[e] << ", ";
420  if(i == 6 ) buf << fSigmaX[e] << ", ";
421  if(i == 7 ) buf << fSigmaY[e] << ", ";
422  if(i == 8 ) buf << fSigmaZ[e] << ", ";
423  if(i == 9 ) buf << fTheta0XZ[e] << ", ";
424  if(i == 10) buf << fTheta0YZ[e] << ", ";
425  if(i == 11) buf << fSigmaThetaXZ[e] << ", ";
426  if(i == 12) buf << fSigmaThetaYZ[e] << ", ";
427  if(i == 13) buf << fT0[e] << ", ";
428  if(i == 14) buf << fSigmaT[e] << ", ";
429  values.append(buf.str());
430  }
431 
432  values.erase(values.find_last_of(","));
433  values.append(" ] \n");
434 
435  }// end loop over vector names in list
436 
437  MF_LOG_INFO("SingleGen") << values;
438 
439  return;
440  }
441 
443 
444  }//end namespace evgen
445 }// namespace gar
446 
447 #endif
448 ////////////////////////////////////////////////////////////////////////
static QCString name
Definition: declinfo.cpp:673
base_engine_t & createEngine(seed_t seed)
module to produce single or multiple specified particles in the detector
void AddTrajectoryPoint(TLorentzVector const &position, TLorentzVector const &momentum)
Definition: MCParticle.h:257
void SetOrigin(simb::Origin_t origin)
Definition: MCTruth.h:82
std::string string
Definition: nybbler.cc:12
void Sample(simb::MCTruth &mct)
std::vector< double > fZ0
Central z position (cm) in world coordinates.
std::vector< double > fTheta0YZ
Angle in YZ plane (degrees)
int fTDist
How to distribute t (gaus, or uniform)
void beginRun(::art::Run &run)
int fAngleDist
How to distribute angles (gaus, uniform)
Particle class.
Definition: Run.h:17
const double e
std::vector< double > fY0
Central y position (cm) in world coordinates.
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
std::vector< int > fPDG
PDG code of particles to generate.
virtual void reconfigure(fhicl::ParameterSet const &pset)
CLHEP::HepRandomEngine & fEngine
single particles thrown at the detector
Definition: MCTruth.h:26
def move(depos, offset)
Definition: depos.py:107
T get(std::string const &key) const
Definition: ParameterSet.h:271
std::vector< double > fT0
Central t position (s) in world coordinates.
int fPDist
How to distribute momenta (gaus or uniform)
static const int kGAUS
p
Definition: test.py:223
std::vector< double > fSigmaZ
Variation in z position (cm)
ProductID put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
Definition: DataViewImpl.h:686
std::vector< double > fSigmaThetaYZ
Variation in angle in YZ plane.
Q_UINT16 values[128]
#define MF_LOG_INFO(category)
Base utilities and modules for event generation and detector simulation.
void SampleOne(unsigned int i, simb::MCTruth &mct)
void reconfigure(fhicl::ParameterSet const &p)
std::vector< double > fSigmaP
Variation in momenta (GeV/c)
#define M_PI
Definition: includeROOT.h:54
int fPosDist
How to distribute xyz (gaus, or uniform)
std::vector< double > fTheta0XZ
Angle in XZ plane (degrees)
General GArSoft Utilities.
std::vector< double > fSigmaThetaXZ
Variation in angle in XZ plane.
void Add(simb::MCParticle const &part)
Definition: MCTruth.h:80
std::vector< double > fSigmaT
Variation in t position (s)
std::vector< double > fSigmaX
Variation in x position (cm)
#define MF_LOG_DEBUG(id)
list x
Definition: train.py:276
void printVecs(std::vector< std::string > const &list)
TCEvent evt
Definition: DataStructs.cxx:7
Event generator information.
Definition: MCTruth.h:32
#define MF_LOG_WARNING(category)
LArSoft geometry interface.
Definition: ChannelGeo.h:16
art framework interface to geometry description
Event Generation using GENIE, cosmics or single particles.
bool PadVector(std::vector< double > &vec)
std::vector< double > fSigmaY
Variation in y position (cm)
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
std::vector< double > fP0
Central momentum (GeV/c) to generate.
std::vector< double > fX0
Central x position (cm) in world coordinates.
void produce(::art::Event &evt)