LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
LightSource_module.cc
Go to the documentation of this file.
1 
58 #ifndef EVGEN_LIGHTSOURCE_H
59 #define EVGEN_LIGHTSOURCE_H
60 
61 // C++ includes.
62 #include <iostream>
63 #include <string>
64 #include <cmath>
65 #include <memory>
66 #include <fstream>
67 
68 // ART includes
71 #include "fhiclcpp/ParameterSet.h"
79 #include "cetlib_except/exception.h"
80 
81 // art extensions
83 
84 // nutools includes
88 
89 // lar includes
95 
96 #include "TVector3.h"
97 #include "TLorentzVector.h"
98 #include "TTree.h"
99 
100 #include "CLHEP/Random/RandFlat.h"
101 #include "CLHEP/Random/RandGaussQ.h"
102 
103 namespace evgen {
104 
106  class LightSource : public art::EDProducer {
107  public:
108  explicit LightSource(fhicl::ParameterSet const& pset);
109 
110  void produce(art::Event & evt);
111  void beginRun(art::Run& run);
112 
113  private:
114 
115  void Sample(simb::MCTruth &truth);
116 
117  // for c2: fSeed is unused
118  //int fSeed; //random number seed
119  std::string fVersion; //version of the configuration
120 
121  // Flags to mark module modes
122  static const int kUNIF = 0;
123  static const int kGAUS = 1;
124  static const int kFILE = 0;
125  static const int kSCAN = 1;
126 
127  // File stream, filename and empty string for file processing
128  std::ifstream fInputFile;
129  std::string fFileName;
130  char fDummyString[256];
131 
132  // A ttree to keep track of where particles have been shot - ends up in histos.root
134  TLorentzVector fShotPos;
135  TLorentzVector fShotMom;
136  Int_t fEvID;
137 
138  // Parameters loaded from config - both modes
139  int fSourceMode; // Mode to run in - scan or file
140  bool fFillTree; // Do we want to create a TTree of shot particles?
141  int fPosDist; //
142  int fTDist; // Random distributions to use : 1= gauss, 0= uniform
143  int fPDist; //
144 
145  //Scan mode specific parameters
146  int fXSteps; //
147  int fYSteps; // Number of steps to take in each dimension
148  int fZSteps; //
149 
150  sim::PhotonVoxelDef fThePhotonVoxelDef; // The photon voxel definition object for scan mode
151 
152  int fVoxelCount; // Total number of voxels
153  int fCurrentVoxel; // Counter to keep track of vox ID
154 
155 
156  // TPC Measurements
157  TVector3 fTPCCenter;
158  TVector3 fTPCDimensions;
159  std::vector<double> fRegionMin;
160  std::vector<double> fRegionMax;
162 
163 
164  // Parameters used to shoot in distributions
165  double fX; // central x position of source
166  double fY; // central y position of source
167  double fZ; // central z position of source
168  double fT; // central t position of source
169  double fSigmaX; // x width
170  double fSigmaY; // y width
171  double fSigmaZ; // z width
172  double fSigmaT; // t width
173  double fP; // central momentm of photon
174  double fSigmaP; // mom width;
175 
176  // Number of photons per event
177  int fN; // number of photons per event
178 
181  };
182 }
183 
184 namespace evgen{
185 
186  //----------------------------------------------------------------
188  {
189 
190  // get the random number seed, use a random default if not specified
191  // in the configuration file.
192 
193  fSourceMode = (pset.get<int >("SourceMode") );
194  fFillTree = (pset.get<bool>("FillTree") );
195  fPosDist = (pset.get<int >("PosDist") );
196  fPDist = (pset.get<int >("PDist") );
197  fTDist = (pset.get<int >("TDist") );
198 
199  // create a default random engine; obtain the random seed from NuRandomService,
200  // unless overridden in configuration with key "Seed"
202  ->createEngine(*this, pset, "Seed");
203 
204  // load optional parameters in function
205  produces< sumdata::RunData, art::InRun >();
206  produces< std::vector<simb::MCTruth> >();
207 
208  if(fSourceMode==kFILE)
209  {
210  fFileName = pset.get<std::string>("SteeringFile");
211  fInputFile.open(fFileName.c_str());
212  fInputFile.getline(fDummyString,256);
213 
214  }
215  else if (fSourceMode==kSCAN)
216  {
217  fT = pset.get<double>("T0");
218  fSigmaT = pset.get<double>("SigmaT");
219  fN = pset.get<int >("N");
220 
221  fFirstVoxel = pset.get<int >("FirstVoxel");
222  fLastVoxel = pset.get<int >("LastVoxel");
223 
224  fP = pset.get<double>("P");
225  fSigmaP = pset.get<double>("SigmaP");
226 
227  fUseCustomRegion = pset.get<bool>("UseCustomRegion");
228 
229  if(fUseCustomRegion)
230  {
231  fRegionMin = pset.get< std::vector<double> >("RegionMin");
232  fRegionMax = pset.get< std::vector<double> >("RegionMax");
233  fXSteps = pset.get<int >("XSteps");
234  fYSteps = pset.get<int >("YSteps");
235  fZSteps = pset.get<int >("ZSteps");
236  }
237 
239  // get TPC dimensions removed. -TA
240 
241 
242  fCurrentVoxel=0;
243 
244  // define voxelization based on parameters read from config.
245  // There are two modes - either read the dimensions of the TPC from
246  // the geometry, or use values specified by the user.
247  if(!fUseCustomRegion)
248  {
251  }
252  else
253  {
255  fRegionMax[0],
256  fXSteps,
257  fRegionMin[1],
258  fRegionMax[1],
259  fYSteps,
260  fRegionMin[2],
261  fRegionMax[2],
262  fZSteps);
263  }
264 
265 
266  // Set distribution widths to voxel size
267 
271 
272  // Get number of voxels we will step through
273 
275 
276  if(fLastVoxel<0) fLastVoxel = fVoxelCount;
277 
278  mf::LogVerbatim("LightSource") << "Light Source : Determining voxel params : "
279  << fVoxelCount << " "
280  << fSigmaX << " "
281  << fSigmaY << " "
282  <<fSigmaZ;
283 
284  }
285  else{
286  throw cet::exception("LightSource") << "EVGEN Light Source : Unrecognised light source mode\n";
287  }
288 
289 
290 
291 
292  if(fFillTree)
293  {
295  fPhotonsGenerated = tfs->make<TTree>("PhotonsGenerated","PhotonsGenerated");
296  fPhotonsGenerated->Branch("X",&(fShotPos[0]),"X/D");
297  fPhotonsGenerated->Branch("Y",&(fShotPos[1]),"Y/D");
298  fPhotonsGenerated->Branch("Z",&(fShotPos[2]),"Z/D");
299  fPhotonsGenerated->Branch("T",&(fShotPos[3]),"T/D");
300  fPhotonsGenerated->Branch("PX",&(fShotMom[0]),"PX/D");
301  fPhotonsGenerated->Branch("PY",&(fShotMom[1]),"PY/D");
302  fPhotonsGenerated->Branch("PZ",&(fShotMom[2]),"PZ/D");
303  fPhotonsGenerated->Branch("PT",&(fShotMom[3]),"PT/D");
304  fPhotonsGenerated->Branch("EventID",&fEvID,"EventID/I");
305  }
306  }
307 
308 
309  //____________________________________________________________________________
311  {
312 
313  // grab the geometry object to see what geometry we are using
315  std::unique_ptr<sumdata::RunData> runcol(new sumdata::RunData(geo->DetectorName()));
316 
317  run.put(std::move(runcol));
318 
320 
321  return;
322  }
323 
324  //----------------------------------------------------------------
326  {
327 
328  // FILE MODE -
329  // Each event, read coordinates of gun and number of photons to shoot from file
330 
331  if(fSourceMode==kFILE)
332  {
333  // Loop file if required
334  if(fInputFile.eof()){
335  mf::LogWarning("LightSource") << "EVGEN Light Source : Warning, reached end of file,"
336  << " looping back to beginning";
337  fInputFile.seekg(0,std::ios::beg);
338  fInputFile.clear();
339  }
340 
341  if(!fInputFile.is_open() || fInputFile.fail() ){
342  throw cet::exception("LightSource") << "EVGEN Light Source : File error in "
343  << fFileName << "\n";
344  }
345  else{
346  // read in one line
347  fInputFile >> fX >> fY >> fZ >> fT
348  >> fSigmaX >> fSigmaY >> fSigmaZ >> fSigmaT
349  >> fP >> fSigmaP >> fN;
350  fInputFile.getline(fDummyString,256);
352  fX + fSigmaX,
353  1,
354  fY - fSigmaY,
355  fY + fSigmaY,
356  1,
357  fZ - fSigmaZ,
358  fZ + fSigmaZ,
359  1);
360 
361  fCurrentVoxel=0;
362  }
363  }
364 
365 
366  // SCAN MODE -
367  // Step through detector using a number of steps provided in the config file
368  // firing a constant number of photons from each point
369  else if(fSourceMode==kSCAN)
370  {
371 
372 
373  TVector3 VoxelCenter = fThePhotonVoxelDef.GetPhotonVoxel(fCurrentVoxel).GetCenter();
374 
375  fX = VoxelCenter.X();
376  fY = VoxelCenter.Y();
377  fZ = VoxelCenter.Z();
378 
379  }
380 
381 
382  // UNRECOGNISED MODE
383  // - neither file or scan mode, probably a config file error
384 
385  else{
386  throw cet::exception("LightSource") <<"EVGEN : Light Source, unrecognised source mode\n";
387  }
388 
389 
390 
391  // std::cout<<"EVGEN Light source to be placed at (x, y, z, t, dx, dy, dz, dt, n) " <<
392  // fX << " " << fY << " " <<fZ << " " << fT << " " <<
393  // fSigmaX << " " << fSigmaY << " " << fSigmaZ << " " << fSigmaT << " " <<
394  // fN << std::endl<<std::endl;
395 
396 
397  std::unique_ptr< std::vector<simb::MCTruth> > truthcol(new std::vector<simb::MCTruth>);
398 
399  simb::MCTruth truth;
401  Sample(truth);
402 
403  // std::cout << "put mctruth into the vector" << std::endl;
404  truthcol->push_back(truth);
405 
406  // std::cout << "add vector to the event " << truthcol->size() << std::endl;
407  evt.put(std::move(truthcol));
408 
409  phot::PhotonVisibilityService* vis = nullptr;
410  try {
412  }
413  catch (art::Exception const& e) {
414  // if the service is not configured, then this is not a build job
415  // (it is a simple generation job instead)
416  if (e.categoryCode() != art::errors::ServiceNotFound) throw;
417  }
418 
419  if(vis && vis->IsBuildJob())
420  {
421  mf::LogVerbatim("LightSource") << "Light source : Stowing voxel params ";
423  }
424 
426  {
427  ++fCurrentVoxel;
428  }
429  else
430  {
431  mf::LogVerbatim("LightSource") << "EVGEN Light Source fully scanned detector. Starting over.";
433  }
434 
435  return;
436 
437 
438  }
439 
440 
442  {
443  mf::LogVerbatim("LightSource") <<"Light source debug : Shooting at " << fX <<" " << fY<<" "<< fZ;
444 
445  // get the random number generator service and make some CLHEP generators
447  CLHEP::HepRandomEngine &engine = rng->getEngine();
448  CLHEP::RandFlat flat(engine);
449  CLHEP::RandGaussQ gauss(engine);
450 
451  for(int j=0; j!=fN; ++j){
452  // Choose momentum (supplied in eV, convert to GeV)
453  double p = fP;
454  if (fPDist == kGAUS) {
455  p = gauss.fire(fP, fSigmaP);
456  }
457  else {
458  p = fP + fSigmaP*(2.0*flat.fire()-1.0);
459  }
460  p /= 1000000000.;
461 
462  // Choose position
463  TVector3 x;
464  if (fPosDist == kGAUS) {
465  x[0] = gauss.fire(fX, fSigmaX);
466  x[1] = gauss.fire(fY, fSigmaY);
467  x[2] = gauss.fire(fZ, fSigmaZ);
468  }
469  else {
470  x[0] = fX + fSigmaX*(2.0*flat.fire()-1.0);
471  x[1] = fY + fSigmaY*(2.0*flat.fire()-1.0);
472  x[2] = fZ + fSigmaZ*(2.0*flat.fire()-1.0);
473  }
474 
475  // Choose time
476  double t;
477  if (fTDist == kGAUS) {
478  t = gauss.fire(fT, fSigmaT);
479  }
480  else {
481  t = fT + fSigmaT * (2.0 * flat.fire()-1.0);
482  }
483 
484 
485  //assume the position is relative to the center of the TPC
486  //x += fTPCCenter;
487 
488  fShotPos = TLorentzVector(x[0], x[1], x[2], t);
489 
490 
491  // Choose angles
492  double costh = 2 * flat.fire() - 1;
493  double sinth = pow(1-pow(costh,2),0.5);
494  double phi = 2 * M_PI * flat.fire();
495 
496  // Generate momentum 4-vector
497 
498  fShotMom = TLorentzVector( p*sinth*cos(phi),
499  p*sinth*sin(phi),
500  p*costh,
501  p );
502 
503  int trackid = -1*(j+1); // set track id to -i as these are all primary particles and have id <= 0
504  std::string primary("primary");
505  int PDG=0; //optical photons have PDG 0
506 
507  simb::MCParticle part(trackid, PDG, primary);
509 
510  if(fFillTree)
511  fPhotonsGenerated->Fill();
512 
513  mct.Add(part);
514  }
515 
516  }
517 
518 
519 }
520 
521 
522 namespace evgen{
523 
525 
526 }//end namespace evgen
527 
528 
529 #endif // EVGEN_LIGHTSOURCE_H
530 
532 
Float_t x
Definition: compare.C:6
std::vector< double > fRegionMin
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
LightSource(fhicl::ParameterSet const &pset)
void AddTrajectoryPoint(TLorentzVector const &position, TLorentzVector const &momentum)
Definition: MCParticle.h:261
void SetOrigin(simb::Origin_t origin)
Definition: MCTruth.h:78
static const int kSCAN
static const int kGAUS
std::vector< double > fRegionMax
art::ProductID put(std::unique_ptr< PROD > &&)
Definition: Run.h:148
TVector3 GetCenter() const
Particle class.
void Add(simb::MCParticle &part)
Definition: MCTruth.h:77
Definition: Run.h:30
void produce(art::Event &evt)
int GetNVoxels() const
ProductID put(std::unique_ptr< PROD > &&product)
Definition: Event.h:102
base_engine_t & getEngine() const
base_engine_t & createEngine(seed_t seed)
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:42
std::string DetectorName() const
Returns a string with the name of the detector, as configured.
single particles thrown at the detector
Definition: MCTruth.h:24
T get(std::string const &key) const
Definition: ParameterSet.h:231
TString part[npart]
Definition: Style.C:32
TVector3 GetVoxelSize() const
An art service to assist in the distribution of guaranteed unique seeds to all engines within an art ...
void beginRun(art::Run &run)
sim::PhotonVoxelDef fThePhotonVoxelDef
void Sample(simb::MCTruth &truth)
static const int kUNIF
const sim::PhotonVoxelDef & GetVoxelDef() const
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
T * make(ARGS...args) const
static art::ServiceHandle< art::RandomNumberGenerator > & rng()
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
static const int kFILE
A module for optical MC testing and library building.
Event generator information.
Definition: MCTruth.h:30
Float_t e
Definition: plot.C:34
Namespace collecting geometry-related classes utilities.
Event Generation using GENIE, cosmics or single particles.
art framework interface to geometry description
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
PhotonVoxel GetPhotonVoxel(int ID) const