EventGeneratorTest_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // brebel@fnal.gov
4 //
5 ////////////////////////////////////////////////////////////////////////
6 #ifndef EVGEN_TEST_H
7 #define EVGEN_TEST_H
8 
9 #include <cstdlib>
10 #include <string>
11 #include <sstream>
12 #include <vector>
13 #include <map>
14 #include <unistd.h>
15 
16 // Framework includes
19 #include "fhiclcpp/ParameterSet.h"
23 #include "cetlib_except/exception.h"
24 #include "cetlib/search_path.h"
25 
32 
34 #include "nutools/EventGeneratorBase/GENIE/GENIEHelper.h"
35 
36 #include "TStopwatch.h"
37 #include "TGeoManager.h"
38 
39 namespace art { class Event; }
40 namespace simb { class MCParticle; }
41 
42 ///Monte Carlo event generation
43 namespace evgen {
44 
45  /// A module to check the results from the Monte Carlo generator
47 
48  public:
49 
50  explicit EventGeneratorTest(fhicl::ParameterSet const &pset);
51 
52  void analyze(art::Event const& evt);
53 
54  private:
55 
56  fhicl::ParameterSet GENIEParameterSet(std::string fluxType,
57  bool usePOTPerSpill);
58 
59  void GENIETest(fhicl::ParameterSet const& pset);
60  void GENIEHistogramFluxTest();
61  void GENIESimpleFluxTest();
62  void GENIEMonoFluxTest();
63  void GENIEAtmoFluxTest();
64  void GENIENtupleFluxTest();
65 
66  fhicl::ParameterSet CRYParameterSet();
67  void CRYTest();
68  bool IntersectsDetector(simb::MCParticle const& part);
69  void ProjectToSurface(TLorentzVector pos,
70  TLorentzVector mom,
71  int axis,
72  double surfaceLoc,
73  double* xyz);
74 
75 
76  double fTotalGENIEPOT; ///< number of POT to generate with GENIE when
77  ///< in total POT mode
78  double fTotalGENIEInteractions; ///< number of interactions to generate with
79  ///< GENIE when in EventsPerSpill mode
80  double fTotalCRYSpills; ///< number of spills to use when testing CRY
81  std::string fTopVolume; ///< Top Volume used by GENIE
82  std::string fGeometryFile; ///< location of Geometry GDML file to test
83  double fCryDetLength; ///< length of detector to test CRY, units of cm
84  double fCryDetWidth; ///< width of detector to test CRY, units of cm
85  double fCryDetHeight; ///< height of detector to test CRY, units of cm
86  CLHEP::HepRandomEngine& fEngine; ///< art-owned engine used in generation random numbers
87  };
88 }
89 
90 namespace evgen {
91 
92  //____________________________________________________________________________
93  EventGeneratorTest::EventGeneratorTest(fhicl::ParameterSet const& pset)
94  : EDAnalyzer (pset)
95  , fTotalGENIEPOT ( pset.get< double >("TotalGENIEPOT", 5e18))
96  , fTotalGENIEInteractions( pset.get< double >("TotalGENIEInteractions", 100) )
97  , fTotalCRYSpills ( pset.get< double >("TotalCRYSpills", 1000))
98  , fTopVolume ( pset.get< std::string >("TopVolume" ))
99  , fGeometryFile ( pset.get< std::string >("GeometryFile" ))
100  , fCryDetLength (1000.)
101  , fCryDetWidth (500.)
102  , fCryDetHeight (500.)
103  , fEngine{createEngine(pset.get< int >("Seed", evgb::GetRandomNumberSeed()))}
104  {}
105 
106  //____________________________________________________________________________
108  {
109  mf::LogWarning("EventGeneratorTest") << "testing GENIE...";
110  mf::LogWarning("EventGeneratorTest") << "\t histogram flux...";
111  this->GENIEHistogramFluxTest();
112  mf::LogWarning("EventGeneratorTest") << "\t \t done."
113  << "\t simple flux...";
114  this->GENIESimpleFluxTest();
115  mf::LogWarning("EventGeneratorTest") << "\t \t done."
116  << "\t atmo flux...";
117  this->GENIEAtmoFluxTest();
118  mf::LogWarning("EventGeneratorTest") << "\t \t done."
119  << "\t mono flux...";
120  this->GENIEMonoFluxTest();
121  mf::LogWarning("EventGeneratorTest") << "\t \t done.\n"
122  << "GENIE tests done";
123 
124  mf::LogWarning("EventGeneratorTest") << "testing CRY...";
125  this->CRYTest();
126  mf::LogWarning("EventGeneratorTest") << "\t CRY test done.";
127  }
128 
129  //____________________________________________________________________________
131  bool usePOTPerSpill)
132  {
133  // make a parameter set first so that we can pass it to the GENIEHelper
134  // object we are going to make
135  std::vector<double> beamCenter;
136  beamCenter.push_back(0.0); beamCenter.push_back(0.); beamCenter.push_back(0.0);
137 
138  std::vector<double> beamDir;
139  beamDir.push_back(0.); beamDir.push_back(0.); beamDir.push_back(1.);
140 
141  std::vector<int> flavors;
142  if(fluxType.compare("atmo_FLUKA") == 0){
143  flavors.push_back(14);
144  }
145  else{
146  flavors.push_back(12); flavors.push_back(14); flavors.push_back(-12); flavors.push_back(-14);
147  }
148 
149 
150  std::vector<std::string> env;
151  env.push_back("GPRODMODE"); env.push_back("YES");
152  env.push_back("GEVGL"); env.push_back("Default");
153 
154  double potPerSpill = 5.e13;
155  double eventsPerSpill = 0;
156  if(!usePOTPerSpill) eventsPerSpill = 1;
157 
158  std::vector<std::string> fluxFiles;
159  fluxFiles.push_back("samples_for_geniehelper/L010z185i_lowthr_ipndshed.root");
160  if(fluxType.compare("simple_flux") == 0){
161  fluxFiles.clear();
162  fluxFiles.push_back("samples_for_geniehelper/gsimple_NOvA-NDOS_le010z185i_20100521_RHC_lowth_s_00001.root");
163  }
164  else if(fluxType.compare("atmo_FLUKA") == 0){
165  fluxFiles.clear();
166  // at FNAL this is installed relative to in /nusoft/data/flux
167  fluxFiles.push_back("atmospheric/battistoni/sdave_numu07.dat");
168  }
169 
170  else if(fluxType.compare("ntuple") == 0){
171  throw cet::exception("EventGeneratorTest") <<"No ntuple flux file "
172  << "exists, bail ungracefully";
173  }
174 
175  fhicl::ParameterSet pset;
176  pset.put("FluxType", fluxType);
177  pset.put("FluxFiles", fluxFiles);
178  pset.put("BeamName", "numi");
179  pset.put("TopVolume", fTopVolume);
180  pset.put("EventsPerSpill", eventsPerSpill);
181  pset.put("POTPerSpill", potPerSpill);
182  pset.put("BeamCenter", beamCenter);
183  pset.put("BeamDirection", beamDir);
184  pset.put("GenFlavors", flavors);
185  pset.put("Environment", env);
186  pset.put("DetectorLocation", "NOvA-ND");
187 
188  mf::LogWarning("EventGeneratorTest") << pset.to_string();
189 
190  return pset;
191  }
192 
193  //____________________________________________________________________________
195  {
196  // use cet::search_path to get the Geometry file path
197  cet::search_path sp("FW_SEARCH_PATH");
198  std::string geometryFile = fGeometryFile;
199  if( !sp.find_file(geometryFile, fGeometryFile) )
200  throw cet::exception("EventGeneratorTest") << "cannot find geometry file:\n "
201  << geometryFile
202  << "\n to test GENIE";
203 
204  TGeoManager::Import(geometryFile.c_str());
205 
206  // make the GENIEHelper object
207  evgb::GENIEHelper help(pset,
208  gGeoManager,
209  geometryFile,
210  gGeoManager->FindVolumeFast(pset.get< std::string>("TopVolume").c_str())->Weight());
211  help.Initialize();
212 
213  int interactionCount = 0;
214 
215  int nspill = 0;
216  int spillLimit = 0;
217 
218  // decide if we are in POT/Spill or Events/Spill mode
219  double eps = pset.get<double>("EventsPerSpill");
220  if(eps > 0.) spillLimit = TMath::Nint(fTotalGENIEInteractions/eps);
221  else spillLimit = 1000;
222 
223  while(nspill < spillLimit){
224  ++nspill;
225  while( !help.Stop() ){
226 
227  simb::MCTruth truth;
228  simb::MCFlux flux;
229  simb::GTruth gTruth;
230 
231  if( help.Sample(truth, flux, gTruth) )
232  ++interactionCount;
233 
234  } // end creation loop for this spill
235 
236  } // end loop over spills
237 
238  // count the POT used and the number of events made
239  mf::LogWarning("EventGeneratorTest") << "made " << interactionCount << " interactions with "
240  << help.TotalExposure() << " POTs";
241 
242  // compare to a simple expectation
243  double totalExp = 0.;
244  if(help.FluxType().compare("histogram") == 0 && pset.get<double>("EventsPerSpill") == 0){
245  std::vector<TH1D*> fluxhist = help.FluxHistograms();
246 
247  if(fluxhist.size() < 1){
248  throw cet::exception("EventGeneratorTest") << "using histogram fluxes but no histograms provided!";
249  }
250 
251  // see comments in GENIEHelper::Initialize() for how this calculation was done.
252  totalExp = 1.e-38*1.e-20*help.TotalHistFlux();
253  totalExp *= help.TotalExposure()*help.TotalMass()/(1.67262158e-27);
254 
255  mf::LogWarning("EventGeneratorTest") << "expected " << totalExp << " interactions";
256  if(std::abs(interactionCount - totalExp) > 3.*std::sqrt(totalExp) ){
257  throw cet::exception("EventGeneratorTest") << "generated count is more than "
258  << "3 sigma off expectation";
259  }
260 
261  }// end if histogram fluxes
262 
263 
264  return;
265 
266  }
267 
268  //____________________________________________________________________________
270  {
271 
272  mf::LogWarning("EventGeneratorTest") << "\t\t\t 1 event per spill...\n";
273 
274  // make the parameter set
275  fhicl::ParameterSet pset1(this->GENIEParameterSet("histogram", false));
276 
277  this->GENIETest(pset1);
278 
279  mf::LogWarning("EventGeneratorTest") <<"\t\t\t events based on POT per spill...\n";
280 
281  fhicl::ParameterSet pset2(this->GENIEParameterSet("histogram", true));
282  this->GENIETest(pset2);
283 
284  return;
285  }
286 
287  //____________________________________________________________________________
289  {
290 
291  // make the parameter set
292  mf::LogWarning("EventGeneratorTest") << "testing GENIEHelper in simple_flux mode with \n"
293  << "\t 1 event per spill...\n";
294 
295  fhicl::ParameterSet pset1 = this->GENIEParameterSet("simple_flux", false);
296  this->GENIETest(pset1);
297 
298  mf::LogWarning("EventGeneratorTest") <<"\t events based on POT per spill...\n";
299 
300  fhicl::ParameterSet pset2 = this->GENIEParameterSet("simple_flux", true);
301  this->GENIETest(pset2);
302 
303  return;
304  }
305 
306  //____________________________________________________________________________
308  {
309 
310  // make the parameter set
311  fhicl::ParameterSet pset1 = this->GENIEParameterSet("mono", false);
312 
313  mf::LogWarning("EventGeneratorTest") << "\t\t 1 event per spill...\n";
314 
315  this->GENIETest(pset1);
316 
317  return;
318 
319  }
320 
321  //____________________________________________________________________________
323  {
324 
325  // make the parameter set
326  fhicl::ParameterSet pset1 = this->GENIEParameterSet("atmo_FLUKA", false);
327 
328  mf::LogWarning("EventGeneratorTest") << "\t\t 1 event per spill...\n";
329 
330  this->GENIETest(pset1);
331 
332  return;
333 
334  }
335 
336 
337  //____________________________________________________________________________
338 
339 
341  {
342  fhicl::ParameterSet pset;
343  pset.put("SampleTime", 600e-6 );
344  pset.put("TimeOffset", -30e-6 );
345  pset.put("EnergyThreshold", 50e-3 );
346  pset.put("Latitude", "latitude 41.8 " );
347  pset.put("Altitude", "altitude 0 " );
348  pset.put("SubBoxLength", "subboxLength 75 ");
349 
350  mf::LogWarning("EventGeneratorTest") << pset.to_string();
351 
352  return pset;
353  }
354 
355  //____________________________________________________________________________
357  {
358  // make the parameter set
359  fhicl::ParameterSet pset = this->CRYParameterSet();
360 
361  // make the CRYHelper
363 
364  int nspill = 0;
365  double avPartPerSpill = 0.;
366  double avPartIntersectPerSpill = 0.;
367  double avMuonIntersectPerSpill = 0.;
368  double avEIntersectPerSpill = 0.;
369  while(nspill < TMath::Nint(fTotalCRYSpills) ){
370 
371  simb::MCTruth mct;
372 
373  help.Sample(mct,
374  1.,
375  100.,
376  0);
377 
378  avPartPerSpill += mct.NParticles();
379 
380  // now check to see if the particles go through the
381  // detector enclosure
382  for(int p = 0; p < mct.NParticles(); ++p){
383  if(this->IntersectsDetector(mct.GetParticle(p)) ){
384  avPartIntersectPerSpill += 1.;
385  if(TMath::Abs(mct.GetParticle(p).PdgCode()) == 13)
386  avMuonIntersectPerSpill += 1.;
387  else if(TMath::Abs(mct.GetParticle(p).PdgCode()) == 11)
388  avEIntersectPerSpill += 1.;
389  }
390  }
391 
392 
393 
394  ++nspill;
395  }
396 
397  mf::LogWarning("EventGeneratorTest") << "there are " << avPartPerSpill/(1.*nspill)
398  << " cosmic rays made per spill \n"
399  << avPartIntersectPerSpill/(1.*nspill)
400  << " intersect the detector per spill"
401  << "\n\t "
402  << avMuonIntersectPerSpill/(1.*nspill)
403  << " muons \n\t"
404  << avEIntersectPerSpill/(1.*nspill)
405  << " electrons";
406 
407 
408  return;
409  }
410 
411  //____________________________________________________________________________
413  {
414 
415  // the particle's initial position and momentum
416  TLorentzVector pos = part.Position();
417  TLorentzVector mom = part.Momentum();
418 
419  if(TMath::Abs(mom.P()) == 0){
420  mf::LogWarning("EventGeneratorTest") << "particle has no momentum!!! bail";
421  return false;
422  }
423 
424  double xyz[3] = {0.};
425 
426  // Checking intersection with 6 planes
427 
428  // 1. Check intersection with the y = +halfheight plane
429  this->ProjectToSurface(pos, mom, 1, 0.5*fCryDetHeight, xyz);
430 
431  if( TMath::Abs(xyz[0]) <= 0.5*fCryDetWidth
432  && xyz[2] > 0.
433  && TMath::Abs(xyz[2]) <= fCryDetLength ) return true;
434 
435 
436  // 2. Check intersection with the +x plane
437  this->ProjectToSurface(pos, mom, 0, 0.5*fCryDetWidth, xyz);
438 
439  if( TMath::Abs(xyz[1]) <= 0.5*fCryDetHeight
440  && xyz[2] > 0.
441  && TMath::Abs(xyz[2]) <= fCryDetLength ) return true;
442 
443  // 3. Check intersection with the -x plane
444  this->ProjectToSurface(pos, mom, 0, -0.5*fCryDetWidth, xyz);
445 
446  if( TMath::Abs(xyz[1]) <= 0.5*fCryDetHeight
447  && xyz[2] > 0.
448  && TMath::Abs(xyz[2]) <= fCryDetLength ) return true;
449 
450  // 4. Check intersection with the z=0 plane
451  this->ProjectToSurface(pos, mom, 2, 0., xyz);
452 
453  if( TMath::Abs(xyz[0]) <= 0.5*fCryDetWidth
454  && TMath::Abs(xyz[1]) <= 0.5*fCryDetHeight ) return true;
455 
456  // 5. Check intersection with the z=detlength plane
457  this->ProjectToSurface(pos, mom, 2, fCryDetLength, xyz);
458 
459  if( TMath::Abs(xyz[0]) <= 0.5*fCryDetWidth
460  && TMath::Abs(xyz[1]) <= 0.5*fCryDetHeight ) return true;
461 
462  return false;
463  }
464 
465  //____________________________________________________________________________
467  TLorentzVector mom,
468  int axis,
469  double surfaceLoc,
470  double* xyz)
471  {
472  double momDir = 0.;
473  double posDir = 0.;
474  if(axis == 0){
475  momDir = mom.Px();
476  posDir = pos.X();
477  }
478  else if(axis == 1){
479  momDir = mom.Py();
480  posDir = pos.X();
481  }
482  else if(axis == 2){
483  momDir = mom.Pz();
484  posDir = pos.X();
485  }
486 
487  double ddS = (momDir/mom.P());
488  double length1Dim = (posDir - surfaceLoc);
489 
490  if(TMath::Abs(ddS) > 0.){
491  length1Dim /= ddS;
492  xyz[0] = pos.X() + length1Dim*mom.Px()/mom.P();
493  xyz[1] = pos.Y() + length1Dim*mom.Py()/mom.P();
494  xyz[2] = pos.Z() + length1Dim*mom.Pz()/mom.P();
495  }
496 
497  return;
498  }
499 
500 }// namespace
501 
502 namespace evgen{
503 
505 
506 }
507 
508 #endif // EVGEN_TEST_H
def analyze(root, level, gtrees, gbranches, doprint)
Definition: rootstat.py:67
base_engine_t & createEngine(seed_t seed)
Interface to the CRY cosmic-ray generator.
Definition: CRYHelper.h:26
const TLorentzVector & Position(const int i=0) const
Definition: MCParticle.h:218
int PdgCode() const
Definition: MCParticle.h:211
std::string fGeometryFile
location of Geometry GDML file to test
void analyze(art::Event const &evt)
fhicl::ParameterSet GENIEParameterSet(std::string fluxType, bool usePOTPerSpill)
std::string string
Definition: nybbler.cc:12
unsigned int GetRandomNumberSeed()
Definition: evgenbase.h:22
void GENIETest(fhicl::ParameterSet const &pset)
CLHEP::HepRandomEngine & fEngine
art-owned engine used in generation random numbers
STL namespace.
A module to check the results from the Monte Carlo generator.
double fCryDetLength
length of detector to test CRY, units of cm
int NParticles() const
Definition: MCTruth.h:75
Particle class.
object containing MC flux information
double fTotalCRYSpills
number of spills to use when testing CRY
T abs(T value)
double Sample(simb::MCTruth &mctruth, double const &surfaceY, double const &detectorLength, double *w, double rantime=0)
Definition: CRYHelper.cxx:97
const double e
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:69
Interface to the CRY cosmic ray generator.
#define Import
T get(std::string const &key) const
Definition: ParameterSet.h:231
std::string fTopVolume
Top Volume used by GENIE.
double fCryDetHeight
height of detector to test CRY, units of cm
Base utilities and modules for event generation and detector simulation.
const simb::MCParticle & GetParticle(int i) const
Definition: MCTruth.h:76
p
Definition: test.py:223
Definition: types.h:32
const TLorentzVector & Momentum(const int i=0) const
Definition: MCParticle.h:219
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
std::string find_file(std::string const &filename) const
Definition: search_path.cc:94
bool IntersectsDetector(simb::MCParticle const &part)
void ProjectToSurface(TLorentzVector pos, TLorentzVector mom, int axis, double surfaceLoc, double *xyz)
TCEvent evt
Definition: DataStructs.cxx:7
Event generator information.
Definition: MCTruth.h:32
auto const & get(AssnsNode< L, R, D > const &r)
Definition: AssnsNode.h:115
double fCryDetWidth
width of detector to test CRY, units of cm
Event Generation using GENIE, cosmics or single particles.
void put(std::string const &key)
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
std::string to_string() const
Definition: ParameterSet.h:137