LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
GENIEHelper.cxx
Go to the documentation of this file.
1 
11 // C/C++ includes
12 #include <math.h>
13 #include <map>
14 #include <fstream>
15 #include <iomanip>
16 #include <algorithm>
17 #include <sstream>
18 #include <glob.h>
19 #include <cstdlib> // for unsetenv()
20 
21 //ROOT includes
22 #include "TH1.h"
23 #include "TH2.h" //used by GAtmoFlux
24 #include "TF1.h"
25 #include "TFile.h"
26 #include "TDirectory.h"
27 #include "TVector3.h"
28 #include "TLorentzVector.h"
29 #include "TCollection.h"
30 #include "TSystem.h"
31 #include "TString.h"
32 #include "TRandom.h" //needed for gRandom to be defined
33 #include "TRegexp.h"
34 #include "TMath.h"
35 #include "TStopwatch.h"
36 #include "TRotation.h"
37 
38 //GENIE includes
39 #include "GENIE/Conventions/GVersion.h"
40 #include "GENIE/Conventions/Units.h"
41 #include "GENIE/EVGCore/EventRecord.h"
42 #include "GENIE/EVGDrivers/GMCJDriver.h"
43 #include "GENIE/GHEP/GHepUtils.h"
44 #include "GENIE/FluxDrivers/GCylindTH1Flux.h"
45 #include "GENIE/FluxDrivers/GMonoEnergeticFlux.h"
46 #include "GENIE/FluxDrivers/GNuMIFlux.h"
47 #include "GENIE/FluxDrivers/GSimpleNtpFlux.h"
48 #include "GENIE/FluxDrivers/GFluxDriverFactory.h"
49 #if __GENIE_RELEASE_CODE__ >= GRELCODE(2,11,0)
50  #include "GENIE/FluxDrivers/GBGLRSAtmoFlux.h" //for atmo nu generation
51  #include "GENIE/FluxDrivers/GFLUKAAtmoFlux.h" //for atmo nu generation
52 #else
53  #include "GENIE/FluxDrivers/GBartolAtmoFlux.h" //for atmo nu generation
54  #include "GENIE/FluxDrivers/GFlukaAtmo3DFlux.h" //for atmo nu generation
55 #endif
56 #if __GENIE_RELEASE_CODE__ >= GRELCODE(2,12,2)
57  #include "GENIE/FluxDrivers/GHAKKMAtmoFlux.h" // for atmo nu generation
58 #endif
59 #include "GENIE/FluxDrivers/GAtmoFlux.h" //for atmo nu generation
60 
61 #pragma GCC diagnostic push
62 #pragma GCC diagnostic ignored "-Wunused-variable"
63 #include "GENIE/Conventions/Constants.h" //for calculating event kinematics
64 #pragma GCC diagnostic pop
65 
66 #include "GENIE/PDG/PDGCodes.h"
67 #ifndef GENIE_USE_ENVVAR
68  #include "GENIE/Utils/AppInit.h"
69  #include "GENIE/Utils/RunOpt.h"
70 #endif
71 
72 #include "GENIE/Geo/ROOTGeomAnalyzer.h"
73 #include "GENIE/Geo/GeomVolSelectorFiducial.h"
74 #include "GENIE/Geo/GeomVolSelectorRockBox.h"
75 #include "GENIE/Utils/StringUtils.h"
76 #include "GENIE/Utils/XmlParserUtils.h"
77 #include "GENIE/Interaction/InitialState.h"
78 #include "GENIE/Interaction/Interaction.h"
79 #include "GENIE/Interaction/Kinematics.h"
80 #include "GENIE/Interaction/KPhaseSpace.h"
81 #include "GENIE/Interaction/ProcessInfo.h"
82 #include "GENIE/Interaction/XclsTag.h"
83 #include "GENIE/GHEP/GHepParticle.h"
84 #include "GENIE/PDG/PDGCodeList.h"
85 
86 #include "GENIE/FluxDrivers/GFluxBlender.h"
87 #include "GENIE/FluxDrivers/GFlavorMixerI.h"
88 #include "GENIE/FluxDrivers/GFlavorMap.h"
89 #include "GENIE/FluxDrivers/GFlavorMixerFactory.h"
90 
91 // dk2nu flux
92 #include "dk2nu/tree/dk2nu.h"
93 #include "dk2nu/tree/dkmeta.h"
94 #include "dk2nu/tree/NuChoice.h"
95 #include "dk2nu/genie/GDk2NuFlux.h"
96 
97 // NuTools includes
100 
104 
105 // nusimdata includes
111 
112 // Framework includes
114 #include "cetlib/search_path.h"
115 #include "cetlib/getenv.h"
116 #include "cetlib/split_path.h"
117 #include "cetlib_except/exception.h"
118 #include "fhiclcpp/ParameterSet.h"
120 
121 #include "cetlib_except/exception.h"
122 
123 // can't find IFDH_service.h header ... unless ups depends on ifdh_art
124 //
125 // #undef USE_IFDH_SERVICE
126 
127 #ifndef NO_IFDH_LIB
128  #define USE_IFDH_SERVICE 1
129  // IFDHC
130  #ifdef USE_IFDH_SERVICE
131  #include "IFDH_service.h"
132  #else
133  // bare IFDHC
134  #include "ifdh.h"
135  #endif
136 #else
137  #undef USE_IFDH_SERVICE
138  // nothing doing ... use ifdef to hide any reference that might need header
139  #include <cassert>
140 #endif
141 
142 namespace evgb {
143 
144  static const int kNue = 0;
145  static const int kNueBar = 1;
146  static const int kNuMu = 2;
147  static const int kNuMuBar = 3;
148  static const int kNuTau = 4;
149  static const int kNuTauBar = 5;
150 
151  //--------------------------------------------------
153  TGeoManager* geoManager,
154  std::string const& rootFile,
155  double const& detectorMass)
156  : fGeoManager (geoManager)
157  , fGeoFile (rootFile)
158  , fGenieEventRecord (0)
159  , fGeomD (0)
160  , fFluxD (0)
161  , fFluxD2GMCJD (0)
162  , fDriver (0)
163  , fIFDH (0)
164  , fHelperRandom (0)
165  , fUseHelperRndGen4GENIE(pset.get< bool >("UseHelperRndGen4GENIE",true))
166  , fTimeShifter (0)
167  , fFluxType (pset.get< std::string >("FluxType") )
168  , fFluxSearchPaths (pset.get< std::string >("FluxSearchPaths","") )
169  , fFluxFilePatterns (pset.get< std::vector<std::string> >("FluxFiles") )
170  , fMaxFluxFileMB (pset.get< int >("MaxFluxFileMB", 2000) ) // 2GB max default
171  , fMaxFluxFileNumber (pset.get< int >("MaxFluxFileNumber",9999) ) // at most 9999 files
172  , fFluxCopyMethod (pset.get< std::string >("FluxCopyMethod","DIRECT")) // "DIRECT" = old direct access method
173  , fFluxCleanup (pset.get< std::string >("FluxCleanup","/var/tmp") ) // "ALWAYS", "NEVER", "/var/tmp"
174  , fBeamName (pset.get< std::string >("BeamName") )
175  , fFluxRotCfg (pset.get< std::string >("FluxRotCfg","none") )
176  , fFluxRotValues (pset.get< std::vector<double> >("FluxRotValues", {} ) ) // default empty vector
177  , fFluxRotation (0)
178  , fTopVolume (pset.get< std::string >("TopVolume") )
179  , fWorldVolume ("volWorld")
180  , fDetLocation (pset.get< std::string >("DetectorLocation") )
181  , fFluxUpstreamZ (pset.get< double >("FluxUpstreamZ", -2.e30) )
182  , fEventsPerSpill (pset.get< double >("EventsPerSpill", 0) )
183  , fPOTPerSpill (pset.get< double >("POTPerSpill", 5.e13) )
184  , fHistEventsPerSpill(0.)
185  , fSpillEvents (0)
186  , fSpillExposure (0.)
187  , fTotalExposure (0.)
188  , fMonoEnergy (pset.get< double >("MonoEnergy", 2.0) )
189  , fFunctionalFlux (pset.get< std::string >("FunctionalFlux", "x") )
190  , fFunctionalBinning (pset.get< int >("FunctionalBinning", 10000) )
191  , fEmin (pset.get< double >("FluxEmin", 0) )
192  , fEmax (pset.get< double >("FluxEmax", 10) )
193  , fBeamRadius (pset.get< double >("BeamRadius", 3.0) )
194  , fDetectorMass (detectorMass)
195  , fSurroundingMass (pset.get< double >("SurroundingMass", 0.) )
196  , fGlobalTimeOffset (pset.get< double >("GlobalTimeOffset", 1.e4) )
197  , fRandomTimeOffset (pset.get< double >("RandomTimeOffset", 1.e4) )
198  , fSpillTimeConfig (pset.get< std::string >("SpillTimeConfig", "") )
199  , fGenFlavors (pset.get< std::vector<int> >("GenFlavors") )
200  , fAtmoEmin (pset.get< double >("AtmoEmin", 0.1) )
201  , fAtmoEmax (pset.get< double >("AtmoEmax", 10.0) )
202  , fAtmoRl (pset.get< double >("Rl", 20.0) )
203  , fAtmoRt (pset.get< double >("Rt", 20.0) )
204  , fEnvironment (pset.get< std::vector<std::string> >("Environment") )
205  , fXSecTable (pset.get< std::string >("XSecTable", "") ) //e.g. "gxspl-FNALsmall.xml"
206  , fEventGeneratorList(pset.get< std::string >("EventGeneratorList", "") ) // "Default"
207  , fGXMLPATH (pset.get< std::string >("GXMLPATH", "") )
208  , fGMSGLAYOUT (pset.get< std::string >("GMSGLAYOUT", "") ) // [BASIC] or SIMPLE
209  , fGENIEMsgThresholds(pset.get< std::string >("GENIEMsgThresholds", "") ) // : separate list of files
210  , fGHepPrintLevel (pset.get< int >("GHepPrintLevel", -1) ) // see GHepRecord::SetPrintLevel() -1=no-print
211  , fMixerConfig (pset.get< std::string >("MixerConfig", "none") )
212  , fMixerBaseline (pset.get< double >("MixerBaseline", 0.) )
213  , fFiducialCut (pset.get< std::string >("FiducialCut", "none") )
214  , fGeomScan (pset.get< std::string >("GeomScan", "default") )
215  , fDebugFlags (pset.get< unsigned int >("DebugFlags", 0) )
216  {
217 
218  // for histogram, mono-energetic, functional form fluxes ...
219  std::vector<double> beamCenter (pset.get< std::vector<double> >("BeamCenter") );
220  std::vector<double> beamDirection(pset.get< std::vector<double> >("BeamDirection"));
221  fBeamCenter.SetXYZ(beamCenter[0], beamCenter[1], beamCenter[2]);
222  fBeamDirection.SetXYZ(beamDirection[0], beamDirection[1], beamDirection[2]);
223 
224  // special processing of GSEED (GENIE's random seed)... priority:
225  // if set in .fcl file RandomSeed variable, use that
226  // else if already set in environment use that
227  // else use evgb::GetRandomNumberSeed()
228  int dfltseed;
229  const char* gseedstr = std::getenv("GSEED");
230  if ( gseedstr ) {
231  dfltseed = strtol(gseedstr,NULL,0);
232  } else {
233  dfltseed = evgb::GetRandomNumberSeed();
234  }
235  int seedval = pset.get< int >("RandomSeed", dfltseed);
236  // initialize random # generator for use within GENIEHelper
237  mf::LogInfo("GENIEHelper") << "Init HelperRandom with seed " << seedval;
238  fHelperRandom = new TRandom3(seedval);
239 
240  // regularize fFluxType string ...
241  // remove lead/trailing whitespace
242  size_t ftlead = fFluxType.find_first_not_of(" \t\n");
243  if ( ftlead ) fFluxType.erase( 0, ftlead );
244  size_t ftlen = fFluxType.length();
245  size_t fttrail = fFluxType.find_last_not_of(" \t\n");
246  if ( fttrail != ftlen ) fFluxType.erase( fttrail+1, ftlen );
247 
248  if ( fFluxType.find("simple") != std::string::npos ) fFluxType = "simple";
249  if ( fFluxType.find("ntuple") != std::string::npos ) fFluxType = "numi";
250  if ( fFluxType.find("numi") != std::string::npos ) fFluxType = "numi";
251 
254 
255  // for "numi" (nee "ntuple"), "simple" and "dk2nu" squeeze the patterns so there
256  // are no duplicates; for the others we want to preserve order
257  if ( fFluxType.compare("numi") == 0 ||
258  fFluxType.compare("simple") == 0 ||
259  fFluxType.compare("dk2nu") == 0 ) {
260  // convert vector<> to a set<> and back to vector<>
261  // to avoid having duplicate patterns in the list
262  std::set<std::string> fluxpattset(fFluxFilePatterns.begin(),fFluxFilePatterns.end());
264  //std::copy(fFluxFilePatterns.begin(),fFluxFilePatterns.end(),std::inserter(fluxpattset,fluxpattset.begin()));
265  fFluxFilePatterns.clear(); // clear vector, copy unique set back
266  std::copy(fluxpattset.begin(),fluxpattset.end(),
267  std::back_inserter(fFluxFilePatterns));
268  }
269  ExpandFluxPaths();
272 
275 
278  // they should come in pairs of variable name key, then value
279 
280  // Process GXMLPATH extensions first, so they are available
281  // when GENIE starts to get initialized; these might be
282  // alternative locations for configurations (including
283  // the GENIE Messenger system).
284  SetGXMLPATH();
285 
286  // Also set GENIE log4cpp Messenger layout format before
287  // initializing GENIE (can't be changed after singleton is created)
288  SetGMSGLAYOUT();
289 
290  // Now initialize GENIE Messenger service
291  StartGENIEMessenger(pset.get<std::string>("ProductionMode","false"));
292 
293  // Determine EventGeneratorList to use
295 
296  // Figure out which cross section file to use
297  // post R-2_8_0 this actually triggers reading the file
298  ReadXSecTable();
299 
300 #ifndef GENIE_USE_ENVVAR
301  // In case we're printing the event record, how verbose should it be
302  genie::GHepRecord::SetPrintLevel(fGHepPrintLevel);
303 
304  // Set GENIE's random # seed
305  mf::LogInfo("GENIEHelper") << "Init genie::utils::app_init::RandGen() with seed " << seedval;
306  genie::utils::app_init::RandGen(seedval);
307 #else
308  // pre GENIE R-2_8_0 needs random # seed GSEED set in the environment
309  // determined the seed to use above, now make sure it is set externally
310  std::string seedstr = std::to_string(seedval); // part of C++11 <string>
311  mf::LogInfo("GENIEHelper") << "Init GSEED env with seed " << seedval;
312  fEnvironment.push_back("GSEED");
313  fEnvironment.push_back(seedstr);
314 
315  // pre R-2_8_0 uses environment variables to configure how GENIE runs
316  std::ostringstream envlisttext;
317  envlisttext << "setting GENIE environment: ";
318  for (size_t i = 0; i < fEnvironment.size(); i += 2) {
319  std::string& key = fEnvironment[i];
320  std::string& val = fEnvironment[i+1];
321  gSystem->Setenv(key.c_str(), val.c_str());
322  envlisttext << "\n " << key << " to \"" << val <<"\"";
323  }
324  mf::LogInfo("GENIEHelper") << envlisttext.str();
325 #endif
326 
327  if ( fFluxType.find("atmo") == 0 ) {
328 
329  if(fGenFlavors.size() != fSelectedFluxFiles.size()){
330  mf::LogInfo("GENIEHelper") << "ERROR: The number of generated neutrino flavors ("
331  << fGenFlavors.size() << ") doesn't correspond to the number of files ("
332  << fSelectedFluxFiles.size() << ")!!!";
333  exit(1);
334  } else {
335  std::ostringstream atmofluxmatch;
336  for (size_t indx=0; indx < fGenFlavors.size(); ++indx ) {
337  atmofluxmatch << " " << std::setw(3) << fGenFlavors[indx] << " " << fSelectedFluxFiles[indx] << "\n";
338  }
339  mf::LogInfo("GENIEHelper")
340  << "atmo flux assignment : \n"
341  << atmofluxmatch.str();
342  }
343 
344  if(fEventsPerSpill !=1){
345  mf::LogInfo("GENIEHelper")
346  << "ERROR: For Atmosphric Neutrino generation, EventPerSpill need to be 1!!";
347  exit(1);
348  }
349 
350  std::ostringstream atmofluxinfo;
351 
352  if (fFluxType.find("FLUKA") != std::string::npos ){
353  atmofluxinfo << " The fluxes are from FLUKA";
354  }
355  else if (fFluxType.find("BARTOL") != std::string::npos ||
356  fFluxType.find("BGLRS") != std::string::npos ){
357  atmofluxinfo << " The fluxes are from BARTOL/BGLRS";
358  }
359  else if (fFluxType.find("HONDA") != std::string::npos ||
360  fFluxType.find("HAKKM") != std::string::npos ){
361  atmofluxinfo << " The fluxes are from HONDA/HAKKM";
362  }
363  else {
364  mf::LogInfo("GENIEHelper") << "Unknown atmo flux simulation: " << fFluxType;
365  exit(1);
366  }
367 
368  atmofluxinfo << '\n'
369  << " The energy range is between: " << fAtmoEmin << " GeV and "
370  << fAtmoEmax << " GeV.";
371 
372  atmofluxinfo << '\n'
373  << " Generation surface of: (" << fAtmoRl << ","
374  << fAtmoRt << ")";
375 
376  mf::LogInfo("GENIEHelper") << atmofluxinfo.str();
377 
378  }// end if atmospheric fluxes
379 
380  // make the histograms
381  if ( fFluxType.compare("histogram") == 0 ){
382  mf::LogInfo("GENIEHelper") << "setting beam direction and center at "
383  << fBeamDirection.X() << " " << fBeamDirection.Y() << " " << fBeamDirection.Z()
384  << " (" << fBeamCenter.X() << "," << fBeamCenter.Y() << "," << fBeamCenter.Z()
385  << ") with radius " << fBeamRadius;
386 
387  TDirectory *savedir = gDirectory;
388 
389  fFluxHistograms.clear();
390 
391  TFile tf((*fSelectedFluxFiles.begin()).c_str());
392  tf.ls();
393 
394  for(std::vector<int>::iterator flvitr = fGenFlavors.begin(); flvitr != fGenFlavors.end(); flvitr++){
395  if(*flvitr == 12) fFluxHistograms.push_back(dynamic_cast<TH1D *>(tf.Get("nue")));
396  if(*flvitr == -12) fFluxHistograms.push_back(dynamic_cast<TH1D *>(tf.Get("nuebar")));
397  if(*flvitr == 14) fFluxHistograms.push_back(dynamic_cast<TH1D *>(tf.Get("numu")));
398  if(*flvitr == -14) fFluxHistograms.push_back(dynamic_cast<TH1D *>(tf.Get("numubar")));
399  if(*flvitr == 16) fFluxHistograms.push_back(dynamic_cast<TH1D *>(tf.Get("nutau")));
400  if(*flvitr == -16) fFluxHistograms.push_back(dynamic_cast<TH1D *>(tf.Get("nutaubar")));
401  }
402 
403  for(unsigned int i = 0; i < fFluxHistograms.size(); ++i){
404  fFluxHistograms[i]->SetDirectory(savedir);
405  fTotalHistFlux += fFluxHistograms[i]->Integral();
406  }
407 
408  mf::LogInfo("GENIEHelper") << "total histogram flux over desired flavors = "
409  << fTotalHistFlux;
410 
411  }//end if getting fluxes from histograms
412 
413  std::string flvlist;
414  for ( std::vector<int>::iterator itr = fGenFlavors.begin(); itr != fGenFlavors.end(); itr++ )
415  flvlist += Form(" %d",*itr);
416 
417  if ( fFluxType.compare("mono") == 0 ||
418  fFluxType.compare("function") == 0 ) {
419  fEventsPerSpill = 1;
420  mf::LogInfo("GENIEHelper")
421  << "Generating monoenergetic (" << fMonoEnergy
422  << " GeV) neutrinos with the following flavors: "
423  << flvlist;
424  }
425  else{
426 
427  std::string fileliststr;
428  if ( fSelectedFluxFiles.empty() ) {
429  fileliststr = "NO FLUX FILES FOUND!";
430  mf::LogWarning("GENIEHelper") << fileliststr;
431  }
432  else {
434  for ( ; sitr != fSelectedFluxFiles.end(); sitr++) {
435  fileliststr += "\n\t";
436  fileliststr += *sitr;
437  }
438  }
439  mf::LogInfo("GENIEHelper")
440  << "Generating flux with the following flavors: " << flvlist
441  << "\nand these file patterns: " << fileliststr;
442 
443  }
444 
445  if ( fEventsPerSpill != 0 ) {
446  mf::LogInfo("GENIEHelper") << "Generating " << fEventsPerSpill
447  << " events for each spill";
448  } else {
449  mf::LogInfo("GENIEHelper") << "Using " << fPOTPerSpill << " pot for each spill";
450  }
451 
452  if ( fSpillTimeConfig != "" ) {
454  fTimeShifter = timeShiftFactory.GetEvtTimeShift(fSpillTimeConfig);
455  if ( fTimeShifter ) {
457  } else {
458  timeShiftFactory.Print();
459  }
460  }
461 
462  return;
463  }
464 
465  //--------------------------------------------------
467  {
468  // user request writing out the scan of the geometry
469  if ( fGeomD && fMaxPathOutInfo != "" ) {
470  genie::geometry::ROOTGeomAnalyzer* rgeom =
471  dynamic_cast<genie::geometry::ROOTGeomAnalyzer*>(fGeomD);
472 
473  string filename = "maxpathlength.xml";
474  mf::LogInfo("GENIEHelper")
475  << "Saving MaxPathLengths as: \"" << filename << "\"";
476 
477  const genie::PathLengthList& maxpath = rgeom->GetMaxPathLengths();
478 
479  maxpath.SaveAsXml(filename);
480  // append extra info to file
481  std::ofstream mpfile(filename.c_str(), std::ios_base::app);
482  mpfile
483  << std::endl
484  << "<!-- this file is only relevant for a setup compatible with:"
485  << std::endl
486  << fMaxPathOutInfo
487  << std::endl
488  << "-->"
489  << std::endl;
490  mpfile.close();
491  } // finished writing max path length XML file (if requested)
492 
493  // protect against lack of driver due to not getting to Initialize()
494  // (called from module's beginRun() method)
495  if ( ! fDriver || ! fFluxD ) {
496  mf::LogInfo("GENIEHelper")
497  << "~GENIEHelper called, but previously failed to construct "
498  << ( (fDriver) ? "":" genie::GMCJDriver" )
499  << ( (fFluxD) ? "":" genie::GFluxI" );
500  } else {
501 
502  double probscale = fDriver->GlobProbScale();
503  double rawpots = 0;
504 #if __GENIE_RELEASE_CODE__ >= GRELCODE(2,11,0)
505  // rather than ask individual flux drivers for info
506  // use the unified interface
507 
508  genie::flux::GFluxExposureI* fexposure =
509  dynamic_cast<genie::flux::GFluxExposureI*>(fFluxD);
510  if ( fexposure ) {
511  rawpots = fexposure->GetTotalExposure();
512  }
513  genie::flux::GFluxFileConfigI* ffileconfig =
514  dynamic_cast<genie::flux::GFluxFileConfigI*>(fFluxD);
515  if ( ffileconfig ) {
516  ffileconfig->PrintConfig();
517  }
518 #else
519  if ( fFluxType.compare("numi") == 0 ) {
520  genie::flux::GNuMIFlux* numiFlux = dynamic_cast<genie::flux::GNuMIFlux *>(fFluxD);
521  rawpots = numiFlux->UsedPOTs();
522  numiFlux->PrintConfig();
523  }
524  else if ( fFluxType.compare("simple") == 0 ) {
525  genie::flux::GSimpleNtpFlux* simpleFlux = dynamic_cast<genie::flux::GSimpleNtpFlux *>(fFluxD);
526  rawpots = simpleFlux->UsedPOTs();
527  simpleFlux->PrintConfig();
528  }
529  else if ( fFluxType.compare("dk2nu") == 0 ) {
530  genie::flux::GDk2NuFlux* dk2nuFlux = dynamic_cast<genie::flux::GDk2NuFlux *>(fFluxD);
531  rawpots = dk2nuFlux->UsedPOTs();
532  dk2nuFlux->PrintConfig();
533  }
534 #endif
535 
536  mf::LogInfo("GENIEHelper")
537  << " Total Exposure " << fTotalExposure
538  << " GMCJDriver GlobProbScale " << probscale
539  << " FluxDriver base pots " << rawpots
540  << " corrected POTS " << rawpots/TMath::Max(probscale,1.0e-100);
541  }
542 
543  // clean up owned genie object (other genie obj are ref ptrs)
544  delete fGenieEventRecord;
545  delete fDriver;
546  delete fHelperRandom;
547 
548 #ifndef NO_IFDH_LIB
549  #ifdef USE_IFDH_SERVICE
551  if ( fFluxCleanup.find("ALWAYS") == 0 ) {
552  ifdhp->cleanup();
553  } else if ( fFluxCleanup.find("/var/tmp") == 0 ) {
554  auto ffitr = fSelectedFluxFiles.begin();
555  for ( ; ffitr != fSelectedFluxFiles.end(); ++ffitr ) {
556  std::string ff = *ffitr;
557  if ( ff.find("/var/tmp") == 0 ) {
558  mf::LogDebug("GENIEHelper") << "delete " << ff;
559  ifdhp->rm(ff);
560  }
561  }
562  }
563  #else
564  if ( fIFDH ) {
565  if ( fFluxCleanup.find("ALWAYS") == 0 ) {
566  fIFDH->cleanup();
567  } else if ( fFluxCleanup.find("/var/tmp") == 0 ) {
568  auto ffitr = fSelectedFluxFiles.begin();
569  for ( ; ffitr != fSelectedFluxFiles.end(); ++ffitr ) {
570  std::string ff = *ffitr;
571  if ( ff.find("/var/tmp") == 0 ) {
572  mf::LogDebug("GENIEHelper") << "delete " << ff;
573  fIFDH->rm(ff);
574  }
575  }
576  }
577  delete fIFDH;
578  fIFDH = 0;
579  }
580  #endif
581 #endif
582 
583  }
584 
585  //--------------------------------------------------
587  {
588  if ( fFluxType.compare("mono") == 0 ||
589  fFluxType.compare("function") == 0 ||
590  fFluxType.compare("numi") == 0 ||
591  fFluxType.compare("simple") == 0 ||
592  fFluxType.compare("dk2nu") == 0 ) {
593  // shouldn't be asking for this for any of the above
594  return -999.;
595  }
596 
597  return fTotalHistFlux;
598  }
599 
600  //--------------------------------------------------
602  {
603  fDriver = new genie::GMCJDriver(); // needs to be before ConfigGeomScan
604 #ifndef GENIE_USE_ENVVAR
605  // this configuration happened via $GEVGL beore R-2_8_0
606  fDriver->SetEventGeneratorList(fEventGeneratorList);
607 #endif
608 
609  // initialize the Geometry and Flux drivers
612 
613  fDriver->UseFluxDriver(fFluxD2GMCJD);
614  fDriver->UseGeomAnalyzer(fGeomD);
615 
616  // must come after creation of Geom, Flux and GMCJDriver
617  ConfigGeomScan(); // could trigger fDriver->UseMaxPathLengths(*xmlfile*)
618 
619  fDriver->Configure(); // trigger GeomDriver::ComputeMaxPathLengths()
620  fDriver->UseSplines();
621  fDriver->ForceSingleProbScale();
622 
623  if ( fFluxType.compare("histogram") == 0 && fEventsPerSpill < 0.01 ) {
624  // fluxes are assumed to be given in units of neutrinos/cm^2/1e20POT/energy
625  // integral over all fluxes removes energy dependence
626  // histograms should have bin width that reflects the value of the /energy bit
627  // ie if /energy = /50MeV then the bin width should be 50 MeV
628 
629  // determine product of pot/spill, mass, and cross section
630  // events = flux * pot * 10^-38 cm^2 (xsec) * (mass detector (in kg) / nucleon mass (in kg))
631  fXSecMassPOT = 1.e-38*1.e-20;
633 
634  mf::LogInfo("GENIEHelper") << "Number of events per spill will be based on poisson mean of "
636 
637  fHistEventsPerSpill = fHelperRandom->Poisson(fXSecMassPOT*fTotalHistFlux);
638  }
639 
640  // set the pot/event counters to zero
641  fSpillEvents = 0;
642  fSpillExposure = 0.;
643  fTotalExposure = 0.;
644 
645  // If the flux driver knows how to keep track of exposure (time,pots)
646  // reset it now as some might have been used in determining
647  // the geometry maxpathlength or internally scanning for weights.
648  // This should not be necessary (GENIE should do it automagically)
649  // but the current version (as of 3665) doesn't.
650 
651  // alas, at this time there is no "unified" interface for Clear()
652  // as there is for GetTotalExposure (replacing UsedPOTs())
653  double preUsedFluxPOTs = 0;
654  bool wasCleared = true;
655  bool doprintpre = false;
656  if( fFluxType.compare("numi") == 0 ) {
657  genie::flux::GNuMIFlux* gnumiflux =
658  dynamic_cast<genie::flux::GNuMIFlux *>(fFluxD);
659  preUsedFluxPOTs = gnumiflux->UsedPOTs();
660  if ( preUsedFluxPOTs > 0 ) {
661  doprintpre = true;
662  gnumiflux->Clear("CycleHistory");
663  if ( gnumiflux->UsedPOTs() != 0 ) wasCleared = false;
664  }
665  } else if ( fFluxType.compare("simple") == 0 ) {
666  genie::flux::GSimpleNtpFlux* gsimpleflux =
667  dynamic_cast<genie::flux::GSimpleNtpFlux *>(fFluxD);
668  preUsedFluxPOTs = gsimpleflux->UsedPOTs();
669  if ( preUsedFluxPOTs > 0 ) {
670  doprintpre = true;
671  gsimpleflux->Clear("CycleHistory");
672  if ( gsimpleflux->UsedPOTs() != 0 ) wasCleared = false;
673  }
674 #if __GENIE_RELEASE_CODE__ >= GRELCODE(2,11,0)
675  } else if ( fFluxType.compare("dk2nu") == 0 ) {
676  genie::flux::GDk2NuFlux* dk2nuflux =
677  dynamic_cast<genie::flux::GDk2NuFlux *>(fFluxD);
678  preUsedFluxPOTs = dk2nuflux->UsedPOTs();
679  if ( preUsedFluxPOTs > 0 ) {
680  doprintpre = true;
681  dk2nuflux->Clear("CycleHistory");
682  if ( dk2nuflux->UsedPOTs() != 0 ) wasCleared = false;
683  }
684 #endif
685  }
686  if ( doprintpre ) {
687  double probscale = fDriver->GlobProbScale();
688  mf::LogInfo("GENIEHelper")
689  << "Pre-Event Generation: "
690  << " FluxDriver base " << preUsedFluxPOTs
691  << " / GMCJDriver GlobProbScale " << probscale
692  << " = used POTS " << preUsedFluxPOTs/TMath::Max(probscale,1.0e-100)
693  << " "
694  << (wasCleared?"successfully":"failed to") << " cleared count for "
695  << fFluxType;
696  }
697  return;
698  }
699 
700  //--------------------------------------------------
702  {
703  genie::geometry::ROOTGeomAnalyzer *rgeom =
704  new genie::geometry::ROOTGeomAnalyzer(fGeoManager);
705 
706  // pass some of the debug flag bits on to the geometry manager
707  int geomFlags = ( fDebugFlags >> 16 ) & 0xFF ;
708  if ( geomFlags ) {
709  int keep = ( geomFlags >> 7 );
710  mf::LogInfo("GENIEHelper")
711  << "InitializeGeometry set debug 0x"
712  << std::hex << geomFlags << std::dec
713  << " keepSegPath " << keep;
714  rgeom->SetDebugFlags(geomFlags);
715  if ( keep ) rgeom->SetKeepSegPath(true);
716  }
717 
718  // get the world volume name from the geometry
719  fWorldVolume = fGeoManager->GetTopVolume()->GetName();
720 
721  // the detector geometry uses cgs units.
722  rgeom->SetLengthUnits(genie::units::centimeter);
723  rgeom->SetDensityUnits(genie::units::gram_centimeter3);
724  rgeom->SetTopVolName(fTopVolume.c_str());
725  rgeom->SetMixtureWeightsSum(1.);
726  mf::LogInfo("GENIEHelper")
727  << "GENIEHelper::InitializeGeometry using TopVolume '"
728  << fTopVolume << "'";
729  // casting to the GENIE geometry driver interface
730  fGeomD = rgeom; // dynamic_cast<genie::GeomAnalyzerI *>(rgeom);
732 
733  return;
734  }
735 
736  //--------------------------------------------------
738  {
739  genie::GeomAnalyzerI* geom_driver = fGeomD; // GENIEHelper name -> gNuMIExptEvGen name
740  std::string fidcut = fFiducialCut; // ditto
741 
742  if( fidcut.find_first_not_of(" \t\n") != 0) // trim any leading whitespace
743  fidcut.erase( 0, fidcut.find_first_not_of(" \t\n") );
744 
745  // convert string to lowercase
746  std::transform(fidcut.begin(),fidcut.end(),fidcut.begin(),::tolower);
747 
748  if ( "" == fidcut || "none" == fidcut ) return;
749 
750  if ( fidcut.find("rock") != string::npos ) {
751  // deal with RockBox separately than basic shapes
753  return;
754  }
755 
756  // below is as it is in $GENIE/src/support/numi/EvGen/gNuMIExptEvGen
757  // except the change in message logger from log4cpp (GENIE) to cet's MessageLogger used by art
758 
773  // sphere:x0,y0,z0,radius - sphere of fixed radius at (x0,y0,z0)
785  genie::geometry::ROOTGeomAnalyzer * rgeom =
786  dynamic_cast<genie::geometry::ROOTGeomAnalyzer *>(geom_driver);
787  if ( ! rgeom ) {
788  mf::LogWarning("GENIEHelpler")
789  << "Can not create GeomVolSelectorFiduction,"
790  << " geometry driver is not ROOTGeomAnalyzer";
791  return;
792  }
793 
794  mf::LogInfo("GENIEHelper") << "fiducial cut: " << fidcut;
795 
796  // for now, only fiducial no "rock box"
797  genie::geometry::GeomVolSelectorFiducial* fidsel =
798  new genie::geometry::GeomVolSelectorFiducial();
799 
800  fidsel->SetRemoveEntries(true); // drop segments that won't be considered
801 
802  vector<string> strtok = genie::utils::str::Split(fidcut,":");
803  if ( strtok.size() != 2 ) {
804  mf::LogWarning("GENIEHelper")
805  << "Can not create GeomVolSelectorFiduction,"
806  << " no \":\" separating type from values. nsplit=" << strtok.size();
807  for ( unsigned int i=0; i < strtok.size(); ++i )
808  mf::LogWarning("GENIEHelper")
809  << "strtok[" << i << "] = \"" << strtok[i] << "\"";
810  return;
811  }
812 
813  // parse out optional "x" and "m"
814  string stype = strtok[0];
815  bool reverse = ( stype.find("0") != string::npos );
816  bool master = ( stype.find("m") != string::npos ); // action after values are set
817 
818  // parse out values
819  vector<double> vals;
820  vector<string> valstrs = genie::utils::str::Split(strtok[1]," ,;(){}[]");
821  vector<string>::const_iterator iter = valstrs.begin();
822  for ( ; iter != valstrs.end(); ++iter ) {
823  const string& valstr1 = *iter;
824  if ( valstr1 != "" ) vals.push_back(atof(valstr1.c_str()));
825  }
826  size_t nvals = vals.size();
827  // pad it out to at least 7 entries to avoid index issues if used
828  for ( size_t nadd = 0; nadd < 7-nvals; ++nadd ) vals.push_back(0);
829 
830  //std::cout << "ivals = [";
831  //for (unsigned int i=0; i < nvals; ++i) {
832  // if (i>0) cout << ",";
833  // std::cout << vals[i];
834  //}
835  //std::cout << "]" << std::endl;
836 
837  // std::vector elements are required to be adjacent so we can treat address as ptr
838 
839  if ( stype.find("zcyl") != string::npos ) {
840  // cylinder along z direction at (x0,y0) radius zmin zmax
841  if ( nvals < 5 )
842  mf::LogError("GENIEHelper") << "MakeZCylinder needs 5 values, not " << nvals
843  << " fidcut=\"" << fidcut << "\"";
844  fidsel->MakeZCylinder(vals[0],vals[1],vals[2],vals[3],vals[4]);
845 
846  } else if ( stype.find("box") != string::npos ) {
847  // box (xmin,ymin,zmin) (xmax,ymax,zmax)
848  if ( nvals < 6 )
849  mf::LogError("GENIEHelper") << "MakeBox needs 6 values, not " << nvals
850  << " fidcut=\"" << fidcut << "\"";
851  double xyzmin[3] = { vals[0], vals[1], vals[2] };
852  double xyzmax[3] = { vals[3], vals[4], vals[5] };
853  fidsel->MakeBox(xyzmin,xyzmax);
854 
855  } else if ( stype.find("zpoly") != string::npos ) {
856  // polygon along z direction nfaces at (x0,y0) radius phi zmin zmax
857  if ( nvals < 7 )
858  mf::LogError("GENIEHelper") << "MakeZPolygon needs 7 values, not " << nvals
859  << " fidcut=\"" << fidcut << "\"";
860  int nfaces = (int)vals[0];
861  if ( nfaces < 3 )
862  mf::LogError("GENIEHelper") << "MakeZPolygon needs nfaces>=3, not " << nfaces
863  << " fidcut=\"" << fidcut << "\"";
864  fidsel->MakeZPolygon(nfaces,vals[1],vals[2],vals[3],vals[4],vals[5],vals[6]);
865 
866  } else if ( stype.find("sphere") != string::npos ) {
867  // sphere at (x0,y0,z0) radius
868  if ( nvals < 4 )
869  mf::LogError("GENIEHelper") << "MakeZSphere needs 4 values, not " << nvals
870  << " fidcut=\"" << fidcut << "\"";
871  fidsel->MakeSphere(vals[0],vals[1],vals[2],vals[3]);
872 
873  } else {
874  mf::LogError("GENIEHelper")
875  << "Can not create GeomVolSelectorFiduction for shape \"" << stype << "\"";
876  }
877 
878  if ( master ) {
879  fidsel->ConvertShapeMaster2Top(rgeom);
880  mf::LogInfo("GENIEHelper") << "Convert fiducial volume from master to topvol coords";
881  }
882  if ( reverse ) {
883  fidsel->SetReverseFiducial(true);
884  mf::LogInfo("GENIEHelper") << "Reverse sense of fiducial volume cut";
885  }
886 
887  rgeom->AdoptGeomVolSelector(fidsel);
888 
889  }
890 
891  //--------------------------------------------------
893  {
894  genie::GeomAnalyzerI* geom_driver = fGeomD; // GENIEHelper name -> gNuMIExptEvGen name
895  std::string fidcut = fFiducialCut; // ditto
896 
897  if( fidcut.find_first_not_of(" \t\n") != 0) // trim any leading whitespace
898  fidcut.erase( 0, fidcut.find_first_not_of(" \t\n") );
899 
900  // convert string to lowercase
901  std::transform(fidcut.begin(),fidcut.end(),fidcut.begin(),::tolower);
902 
903  genie::geometry::ROOTGeomAnalyzer * rgeom =
904  dynamic_cast<genie::geometry::ROOTGeomAnalyzer *>(geom_driver);
905  if ( ! rgeom ) {
906  mf::LogWarning("GENIEHelpler")
907  << "Can not create GeomVolSelectorRockBox,"
908  << " geometry driver is not ROOTGeomAnalyzer";
909  return;
910  }
911 
912  mf::LogInfo("GENIEHelper") << "fiducial (rock) cut: " << fidcut;
913 
914  // for now, only fiducial no "rock box"
915  genie::geometry::GeomVolSelectorRockBox* rocksel =
916  new genie::geometry::GeomVolSelectorRockBox();
917 
918  vector<string> strtok = genie::utils::str::Split(fidcut,":");
919  if ( strtok.size() != 2 ) {
920  mf::LogWarning("GENIEHelper")
921  << "Can not create GeomVolSelectorRockBox,"
922  << " no \":\" separating type from values. nsplit=" << strtok.size();
923  for ( unsigned int i=0; i < strtok.size(); ++i )
924  mf::LogWarning("GENIEHelper")
925  << "strtok[" << i << "] = \"" << strtok[i] << "\"";
926  return;
927  }
928 
929  string stype = strtok[0];
930 
931  // parse out values
932  vector<double> vals;
933  vector<string> valstrs = genie::utils::str::Split(strtok[1]," ,;(){}[]\t\n\r");
934  vector<string>::const_iterator iter = valstrs.begin();
935  for ( ; iter != valstrs.end(); ++iter ) {
936  const string& valstr1 = *iter;
937  if ( valstr1 != "" ) {
938  double aval = atof(valstr1.c_str());
939  mf::LogDebug("GENIEHelper") << "rock value [" << vals.size() << "] "
940  << aval;
941  vals.push_back(aval);
942  }
943  }
944  size_t nvals = vals.size();
945 
946  rocksel->SetRemoveEntries(true); // drop segments that won't be considered
947 
948  // assume coordinates are in the *master* (not "top volume") system
949  // need to set fTopVolume to fWorldVolume as Sample() will keep setting it
951  rgeom->SetTopVolName(fTopVolume.c_str());
952 
953  if ( nvals < 6 ) {
954  throw cet::exception("GENIEHelper") << "rockbox needs at "
955  << "least 6 values, found "
956  << nvals << "in \""
957  << strtok[1] << "\"";
958 
959  }
960  double xyzmin[3] = { vals[0], vals[1], vals[2] };
961  double xyzmax[3] = { vals[3], vals[4], vals[5] };
962 
963  bool rockonly = true;
964  double wallmin = 800.; // geometry in cm, ( 8 meter buffer)
965  double dedx = 2.5 * 1.7e-3; // GeV/cm, rho=2.5, 1.7e-3 ~ rock like loss
966  double fudge = 1.05;
967 
968  if ( nvals >= 7 ) rockonly = vals[6];
969  if ( nvals >= 8 ) wallmin = vals[7];
970  if ( nvals >= 9 ) dedx = vals[8];
971  if ( nvals >= 10 ) fudge = vals[9];
972 
973  rocksel->SetRockBoxMinimal(xyzmin,xyzmax);
974  rocksel->SetMinimumWall(wallmin);
975  rocksel->SetDeDx(dedx/fudge);
976 
977  // if not rock-only then make a tiny exclusion bubble
978  // call to MakeBox shouldn't be necessary
979  // should be done by SetRockBoxMinimal but for some GENIE versions isn't
980  if ( ! rockonly ) rocksel->MakeSphere(0,0,0,1.0e-10);
981  else rocksel->MakeBox(xyzmin,xyzmax);
982 
983  rgeom->AdoptGeomVolSelector(rocksel);
984  }
985 
986  //--------------------------------------------------
988  {
989 
990 #if __GENIE_RELEASE_CODE__ >= GRELCODE(2,11,0)
991  // simplify a lot of things ... but for now only handle the 3 ntuple styles
992  // that support the GFluxFileConfig mix-in
993  // not the atmos, histo or mono versions
994  std::string fluxName = "";
995  // what looks like the start of a fully qualified class name
996  if ( fFluxType.find("genie::flux::") != std::string::npos )
997  fluxName = fFluxType;
998  else if ( fFluxType.compare("numi") == 0 )
999  fluxName = "genie::flux::GNuMIFlux";
1000  else if ( fFluxType.compare("simple") == 0 )
1001  fluxName = "genie::flux::GSimpleNtpFlux";
1002  else if ( fFluxType.compare("dk2nu") == 0 )
1003  fluxName = "genie::flux::GDk2NuFlux";
1004  if ( fluxName != "" ) {
1005  // fall through to hopefully be handled below ...
1006  genie::flux::GFluxDriverFactory& fluxDFactory =
1007  genie::flux::GFluxDriverFactory::Instance();
1008  fFluxD = fluxDFactory.GetFluxDriver(fluxName);
1009  if ( ! fFluxD ) {
1010  mf::LogInfo("GENIEHelper")
1011  << "genie::flux::GFluxDriverFactory had not result for '"
1012  << fluxName << "' (fFluxType was '" << fFluxType << "'";
1013  // fall through in hopes someone later picks it up
1014  } else {
1015  // got something
1016  // for the ones that support GFluxFileConfigI (numi,simple,dk2nu)
1017  // initialize them
1018  genie::flux::GFluxFileConfigI* ffileconfig =
1019  dynamic_cast<genie::flux::GFluxFileConfigI*>(fFluxD);
1020  if ( ffileconfig ) {
1021  ffileconfig->LoadBeamSimData(fSelectedFluxFiles,fDetLocation);
1022  ffileconfig->PrintConfig();
1023  // initialize to only use neutrino flavors requested by user
1024  genie::PDGCodeList probes;
1025  for ( std::vector<int>::iterator flvitr = fGenFlavors.begin(); flvitr != fGenFlavors.end(); flvitr++ )
1026  probes.push_back(*flvitr);
1027  ffileconfig->SetFluxParticles(probes);
1028  if ( TMath::Abs(fFluxUpstreamZ) < 1.0e30 ) ffileconfig->SetUpstreamZ(fFluxUpstreamZ);
1029  }
1030  }
1031  }
1032 #else
1033  if ( fFluxType.compare("numi") == 0 ) {
1034 
1035  genie::flux::GNuMIFlux* numiFlux = new genie::flux::GNuMIFlux();
1036 
1037 #ifndef GFLUX_MISSING_SETORVECTOR
1038  mf::LogDebug("GENIEHelper") << "LoadBeamSimData w/ vector of size " << fSelectedFluxFiles.size();
1039  numiFlux->LoadBeamSimData(fSelectedFluxFiles,fDetLocation);
1040 #else
1041  // older code can only take one file name (wildcard pattern)
1042  if ( fSelectedFluxFiles.empty() ) fSelectedFluxFiles.push_back("empty-fluxfile-set");
1043  if ( fSelectedFluxFiles.size() > 1 )
1044  mf::LogWarning("GENIEHelper")
1045  << "LoadBeamSimData could use only first of "
1046  << fSelectedFluxFiles.size() << " patterns";
1047  numiFlux->LoadBeamSimData(fSelectedFluxFiles[0], fDetLocation);
1048 #endif
1049 
1050  // initialize to only use neutrino flavors requested by user
1051  genie::PDGCodeList probes;
1052  for ( std::vector<int>::iterator flvitr = fGenFlavors.begin(); flvitr != fGenFlavors.end(); flvitr++ )
1053  probes.push_back(*flvitr);
1054  numiFlux->SetFluxParticles(probes);
1055 
1056  if ( TMath::Abs(fFluxUpstreamZ) < 1.0e30 ) numiFlux->SetUpstreamZ(fFluxUpstreamZ);
1057 
1058  // set the number of cycles to run
1059  // +++++++++this is stupid - to really set it i have to get a
1060  // value from the MCJDriver and i am not even sure what i have
1061  // below is approximately correct.
1062  // for now just run on a set number of events that is kept track of
1063  // in the sample method
1064  // numiFlux->SetNumOfCycles(int(fPOT/fFluxNormalization));
1065 
1066  fFluxD = numiFlux; // dynamic_cast<genie::GFluxI *>(numiFlux);
1067  } //end if using ntuple flux files
1068  else if ( fFluxType.compare("simple") == 0 ) {
1069 
1070  genie::flux::GSimpleNtpFlux* simpleFlux =
1071  new genie::flux::GSimpleNtpFlux();
1072 
1073 #ifndef GFLUX_MISSING_SETORVECTOR
1074  mf::LogDebug("GENIEHelper") << "LoadBeamSimData w/ vector of size " << fSelectedFluxFiles.size();
1075  simpleFlux->LoadBeamSimData(fSelectedFluxFiles,fDetLocation);
1076 #else
1077  // older code can only take one file name (wildcard pattern)
1078  if ( fSelectedFluxFiles.empty() ) fSelectedFluxFiles.push_back("empty-fluxfile-set");
1079  if ( fSelectedFluxFiles.size() > 1 )
1080  mf::LogWarning("GENIEHelper")
1081  << "LoadBeamSimData could use only first of "
1082  << fSelectedFluxFiles.size() << " patterns";
1083  simpleFlux->LoadBeamSimData(fSelectedFluxFiles[0], fDetLocation);
1084 #endif
1085 
1086  // initialize to only use neutrino flavors requested by user
1087  genie::PDGCodeList probes;
1088  for ( std::vector<int>::iterator flvitr = fGenFlavors.begin(); flvitr != fGenFlavors.end(); flvitr++ )
1089  probes.push_back(*flvitr);
1090  simpleFlux->SetFluxParticles(probes);
1091 
1092  if ( TMath::Abs(fFluxUpstreamZ) < 1.0e30 ) simpleFlux->SetUpstreamZ(fFluxUpstreamZ);
1093 
1094  fFluxD = simpleFlux; // dynamic_cast<genie::GFluxI *>(simpleFlux);
1095 
1096  } //end if using simple_flux flux files
1097 #endif
1098  if ( fFluxType.compare("histogram") == 0 ) {
1099 
1100  genie::flux::GCylindTH1Flux* histFlux = new genie::flux::GCylindTH1Flux();
1101 
1102  // now add the different fluxes - fluxes were added to the vector in the same
1103  // order that the flavors appear in fGenFlavors
1104  int ctr = 0;
1105  for ( std::vector<int>::iterator i = fGenFlavors.begin(); i != fGenFlavors.end(); i++ ) {
1106  histFlux->AddEnergySpectrum(*i, fFluxHistograms[ctr]);
1107  ++ctr;
1108  } //end loop to add flux histograms to driver
1109 
1110  histFlux->SetNuDirection(fBeamDirection);
1111  histFlux->SetBeamSpot(fBeamCenter);
1112  histFlux->SetTransverseRadius(fBeamRadius);
1113 
1114  fFluxD = histFlux; // dynamic_cast<genie::GFluxI *>(histFlux);
1115  } // end if using a histogram
1116  else if ( fFluxType.compare("mono") == 0 ) {
1117 
1118  // weight each species equally in the generation
1119  double weight = 1./(1.*fGenFlavors.size());
1120  //make a map of pdg to weight codes
1121  std::map<int, double> pdgwmap;
1122  for ( std::vector<int>::iterator i = fGenFlavors.begin(); i != fGenFlavors.end(); i++ )
1123  pdgwmap[*i] = weight;
1124 
1125  genie::flux::GMonoEnergeticFlux *monoflux = new genie::flux::GMonoEnergeticFlux(fMonoEnergy, pdgwmap);
1126  monoflux->SetDirectionCos(fBeamDirection.X(), fBeamDirection.Y(), fBeamDirection.Z());
1127  monoflux->SetRayOrigin(fBeamCenter.X(), fBeamCenter.Y(), fBeamCenter.Z());
1128  fFluxD = monoflux; // dynamic_cast<genie::GFluxI *>(monoflux);
1129  } //end if using monoenergetic beam
1130  else if ( fFluxType.compare("function") == 0 ) {
1131 
1132  genie::flux::GCylindTH1Flux* histFlux = new genie::flux::GCylindTH1Flux();
1133  TF1* input_func = new TF1("input_func", fFunctionalFlux.c_str(), fEmin, fEmax);
1134  TH1D* spectrum = new TH1D("spectrum", "neutrino flux", fFunctionalBinning, fEmin, fEmax);
1135  spectrum->Add(input_func);
1136 
1137  for ( std::vector<int>::iterator i = fGenFlavors.begin(); i != fGenFlavors.end(); i++ ) {
1138  histFlux->AddEnergySpectrum(*i, spectrum);
1139  } //end loop to add flux histograms to driver
1140 
1141  histFlux->SetNuDirection(fBeamDirection);
1142  histFlux->SetBeamSpot(fBeamCenter);
1143  histFlux->SetTransverseRadius(fBeamRadius);
1144 
1145  fFluxD = histFlux; // dynamic_cast<genie::GFluxI *>(histFlux);
1146  delete input_func;
1147  } //end if using monoenergetic beam
1148 
1149 
1150  //Using the atmospheric fluxes
1151  else if ( fFluxType.find("FLUKA") != std::string::npos ||
1152  fFluxType.find("BARTOL") != std::string::npos ||
1153  fFluxType.find("BGLRS") != std::string::npos ||
1154  fFluxType.find("HONDA") != std::string::npos ||
1155  fFluxType.find("HAKKM") != std::string::npos ) {
1156 
1157  // Instantiate appropriate concrete flux driver
1158  genie::flux::GAtmoFlux *atmo_flux_driver = 0;
1159 
1160  if ( fFluxType.compare("atmo_FLUKA") == 0 ) {
1161 #if __GENIE_RELEASE_CODE__ >= GRELCODE(2,11,0)
1162  genie::flux::GFLUKAAtmoFlux * fluka_flux =
1163  new genie::flux::GFLUKAAtmoFlux;
1164 #else
1165  genie::flux::GFlukaAtmo3DFlux * fluka_flux =
1166  new genie::flux::GFlukaAtmo3DFlux;
1167 #endif
1168  atmo_flux_driver = dynamic_cast<genie::flux::GAtmoFlux *>(fluka_flux);
1169  }
1170  if ( fFluxType.compare("atmo_BARTOL") == 0 ||
1171  fFluxType.compare("atmo_BGLRS") == 0 ) {
1172 #if __GENIE_RELEASE_CODE__ >= GRELCODE(2,11,0)
1173  genie::flux::GBGLRSAtmoFlux * bartol_flux =
1174  new genie::flux::GBGLRSAtmoFlux;
1175 #else
1176  genie::flux::GBartolAtmoFlux * bartol_flux =
1177  new genie::flux::GBartolAtmoFlux;
1178 #endif
1179  atmo_flux_driver = dynamic_cast<genie::flux::GAtmoFlux *>(bartol_flux);
1180  }
1181 #if __GENIE_RELEASE_CODE__ >= GRELCODE(2,12,2)
1182  if (fFluxType.compare("atmo_HONDA") == 0 ||
1183  fFluxType.compare("atmo_HAKKM") == 0 ) {
1184  genie::flux::GHAKKMAtmoFlux * honda_flux =
1185  new genie::flux::GHAKKMAtmoFlux;
1186  atmo_flux_driver = dynamic_cast<genie::flux::GAtmoFlux *>(honda_flux);
1187  }
1188 #endif
1189 
1190  atmo_flux_driver->ForceMinEnergy(fAtmoEmin);
1191  atmo_flux_driver->ForceMaxEnergy(fAtmoEmax);
1192  if ( fFluxRotation ) atmo_flux_driver->SetUserCoordSystem(*fFluxRotation);
1193 
1194  std::ostringstream atmoCfgText;
1195  atmoCfgText << "Configuration for " << fFluxType
1196  << ", Rl " << fAtmoRl << " Rt " << fAtmoRt;
1197  for ( size_t j = 0; j < fGenFlavors.size(); ++j ) {
1198  int flavor = fGenFlavors[j];
1199  std::string flxfile = fSelectedFluxFiles[j];
1200  atmo_flux_driver->AddFluxFile(flavor,flxfile); // pre-R-2_11_0 was SetFluxFile()
1201  atmoCfgText << "\n FLAVOR: " << std::setw(3) << flavor
1202  << " FLUX FILE: " << flxfile;
1203  }
1204  if ( fFluxRotation ) {
1205  const int w=13, p=6;
1206  auto old_p = atmoCfgText.precision(p);
1207  atmoCfgText << "\n UserCoordSystem rotation:\n"
1208  << " [ "
1209  << std::setw(w) << fFluxRotation->XX() << " "
1210  << std::setw(w) << fFluxRotation->XY() << " "
1211  << std::setw(w) << fFluxRotation->XZ() << " ]\n"
1212  << " [ "
1213  << std::setw(w) << fFluxRotation->YX() << " "
1214  << std::setw(w) << fFluxRotation->YY() << " "
1215  << std::setw(w) << fFluxRotation->YZ() << " ]\n"
1216  << " [ "
1217  << std::setw(w) << fFluxRotation->ZX() << " "
1218  << std::setw(w) << fFluxRotation->ZY() << " "
1219  << std::setw(w) << fFluxRotation->ZZ() << " ]\n";
1220  atmoCfgText.precision(old_p);
1221  }
1222  mf::LogInfo("GENIEHelper") << atmoCfgText.str();
1223 
1224  atmo_flux_driver->LoadFluxData();
1225 
1226  // configure flux generation surface:
1227  atmo_flux_driver->SetRadii(fAtmoRl, fAtmoRt);
1228 
1229  fFluxD = atmo_flux_driver;//dynamic_cast<genie::GFluxI *>(atmo_flux_driver);
1230  } //end if using atmospheric fluxes
1231 
1232  if ( ! fFluxD ) {
1233  mf::LogError("GENIEHelper")
1234  << "Failed to contruct base flux driver for FluxType '"
1235  << fFluxType << "'";
1236  throw cet::exception("GENIEHelper")
1237  << "Failed to contruct base flux driver for FluxType '"
1238  << fFluxType << "'\n"
1239  << __FILE__ << ":" << __LINE__ << "\n";
1240  }
1241 
1242  //
1243  // Is the user asking to do flavor mixing?
1244  //
1245  fFluxD2GMCJD = fFluxD; // default: genie's GMCJDriver uses the bare flux generator
1246  if( fMixerConfig.find_first_not_of(" \t\n") != 0) // trim any leading whitespace
1247  fMixerConfig.erase( 0, fMixerConfig.find_first_not_of(" \t\n") );
1248  std::string keyword = fMixerConfig.substr(0,fMixerConfig.find_first_of(" \t\n"));
1249  if ( keyword != "none" ) {
1250  // Wrap the true flux driver up in the adapter to allow flavor mixing
1251  genie::flux::GFlavorMixerI* mixer = 0;
1252  // here is where we map MixerConfig string keyword to actual class
1253  // first is a special case that is part of GENIE proper
1254  if ( keyword == "map" || keyword == "swap" || keyword == "fixedfrac" )
1255  mixer = new genie::flux::GFlavorMap();
1256  // if it wasn't one of the predefined known mixers then
1257  // see if the factory knows about it and can create one
1258  // assuming the keyword (first token) is the class name
1259  if ( ! mixer ) {
1260  genie::flux::GFlavorMixerFactory& mixerFactory =
1261  genie::flux::GFlavorMixerFactory::Instance();
1262  mixer = mixerFactory.GetFlavorMixer(keyword);
1263  if ( mixer ) {
1264  // remove class name from config string
1265  fMixerConfig.erase(0,keyword.size());
1266  // trim any leading whitespace
1267  if ( fMixerConfig.find_first_not_of(" \t\n") != 0 )
1268  fMixerConfig.erase( 0, fMixerConfig.find_first_not_of(" \t\n") );
1269  } else {
1270  const std::vector<std::string>& knownMixers =
1271  mixerFactory.AvailableFlavorMixers();
1272  mf::LogWarning("GENIEHelper")
1273  << " GFlavorMixerFactory known mixers: ";
1274  for (unsigned int j=0; j < knownMixers.size(); ++j ) {
1275  mf::LogWarning("GENIEHelper")
1276  << " [" << std::setw(2) << j << "] " << knownMixers[j];
1277  }
1278  }
1279  }
1280  // configure the mixer
1281  if ( mixer ) mixer->Config(fMixerConfig);
1282  else {
1283  mf::LogWarning("GENIEHelper")
1284  << "GENIEHelper MixerConfig keyword was \"" << keyword
1285  << "\" but that did not map to a class; " << std::endl
1286  << "GFluxBlender in use, but no mixer";
1287  }
1288 
1289  genie::GFluxI* realFluxD = fFluxD;
1290  genie::flux::GFluxBlender* blender = new genie::flux::GFluxBlender();
1291  blender->SetBaselineDist(fMixerBaseline);
1292  blender->AdoptFluxGenerator(realFluxD);
1293  blender->AdoptFlavorMixer(mixer);
1294  fFluxD2GMCJD = blender;
1295  if ( fDebugFlags & 0x01 ) {
1296  if ( mixer ) mixer->PrintConfig();
1297  blender->PrintConfig();
1298  std::cout << std::flush;
1299  }
1300  }
1301 
1302  return;
1303  }
1304 
1305  //--------------------------------------------------
1307  {
1308 
1309  // trim any leading whitespace
1310  if( fGeomScan.find_first_not_of(" \t\n") != 0)
1311  fGeomScan.erase( 0, fGeomScan.find_first_not_of(" \t\n") );
1312 
1313  if ( fGeomScan.find("default") == 0 ) return;
1314 
1315  genie::geometry::ROOTGeomAnalyzer* rgeom =
1316  dynamic_cast<genie::geometry::ROOTGeomAnalyzer*>(fGeomD);
1317 
1318  if ( !rgeom ) {
1319  throw cet::exception("GENIEHelper") << "fGeomD wasn't of type "
1320  << "genie::geometry::ROOTGeomAnalyzer*";
1321  }
1322 
1323  // convert string to lowercase
1324 
1325  // parse out string
1326  vector<string> strtok = genie::utils::str::Split(fGeomScan," ");
1327  // first value is a string, others should be numbers unless "file:"
1328  string scanmethod = strtok[0];
1329 
1330  // convert key string to lowercase (but not potential file name)
1331  std::transform(scanmethod.begin(),scanmethod.end(),scanmethod.begin(),::tolower);
1332 
1333  if ( scanmethod.find("file") == 0 ) {
1334  // xml expand path before passing in
1335  string filename = strtok[1];
1336  string fullname = genie::utils::xml::GetXMLFilePath(filename);
1337  mf::LogInfo("GENIEHelper")
1338  << "ConfigGeomScan getting MaxPathLengths from \"" << fullname << "\"";
1339  fDriver->UseMaxPathLengths(fullname);
1340  return;
1341  }
1342 
1343  vector<double> vals;
1344  for ( size_t indx=1; indx < strtok.size(); ++indx ) {
1345  const string& valstr1 = strtok[indx];
1346  if ( valstr1 != "" ) vals.push_back(atof(valstr1.c_str()));
1347  }
1348  size_t nvals = vals.size();
1349  // pad it out to at least 4 entries to avoid index issues
1350  for ( size_t nadd = 0; nadd < 4-nvals; ++nadd ) vals.push_back(0);
1351 
1352  double safetyfactor = 0;
1353  int writeout = 0;
1354  if ( scanmethod.find("box") == 0 ) {
1355  // use box method
1356  int np = (int)vals[0];
1357  int nr = (int)vals[1];
1358  if ( nvals >= 3 ) safetyfactor = vals[2];
1359  if ( nvals >= 4 ) writeout = vals[3];
1360  // protect against too small values
1361  if ( np <= 10 ) np = rgeom->ScannerNPoints();
1362  if ( nr <= 10 ) nr = rgeom->ScannerNRays();
1363  mf::LogInfo("GENIEHelper")
1364  << "ConfigGeomScan scan using box " << np << " points, "
1365  << nr << " rays";
1366  rgeom->SetScannerNPoints(np);
1367  rgeom->SetScannerNRays(nr);
1368  } else if ( scanmethod.find("flux") == 0 ) {
1369  // use flux method
1370  int np = (int)vals[0];
1371  if ( nvals >= 2 ) safetyfactor = vals[1];
1372  if ( nvals >= 3 ) writeout = vals[2];
1373  // sanity check, need some number of rays to explore the geometry
1374  // negative now means adjust rays to enu_max (GENIE svn 3676)
1375  if ( abs(np) <= 100 ) {
1376  int npnew = rgeom->ScannerNParticles();
1377  if ( np < 0 ) npnew = -abs(npnew);
1378  mf::LogWarning("GENIEHelper")
1379  << "Too few rays requested for geometry scan: " << np
1380  << ", use: " << npnew << "instead";
1381  np = npnew;
1382  }
1383  mf::LogInfo("GENIEHelper")
1384  << "ConfigGeomScan scan using " << np << " flux particles"
1385  << ( (np>0) ? "" : " with ray energy pushed to flux driver maximum" );
1386  rgeom->SetScannerFlux(fFluxD);
1387  rgeom->SetScannerNParticles(np);
1388  }
1389  else{
1390  // unknown
1391  throw cet::exception("GENIEHelper") << "fGeomScan unknown method: \""
1392  << fGeomScan << "\"";
1393  }
1394  if ( safetyfactor > 0 ) {
1395  mf::LogInfo("GENIEHelper")
1396  << "ConfigGeomScan setting safety factor to " << safetyfactor;
1397  rgeom->SetMaxPlSafetyFactor(safetyfactor);
1398  }
1399  if ( writeout != 0 ) SetMaxPathOutInfo();
1400  }
1401 
1402  //--------------------------------------------------
1404  {
1405  // create an info string based on:
1406  // ROOT geometry, TopVolume, FiducialCut, GeomScan, Flux
1407 
1408  mf::LogInfo("GENIEHelper") << "about to create MaxPathOutInfo";
1409 
1410  fMaxPathOutInfo = "\n";
1411  fMaxPathOutInfo += " FluxType: " + fFluxType + "\n";
1412  fMaxPathOutInfo += " BeamName: " + fBeamName + "\n";
1413  fMaxPathOutInfo += " FluxFiles: ";
1415  for ( ; ffitr != fSelectedFluxFiles.end() ; ++ffitr )
1416  fMaxPathOutInfo += "\n " + *ffitr;
1417  fMaxPathOutInfo += "\n";
1418  fMaxPathOutInfo += " DetLocation: " + fDetLocation + "\n";
1419  fMaxPathOutInfo += " ROOTFile: " + fGeoFile + "\n";
1420  fMaxPathOutInfo += " WorldVolume: " + fWorldVolume + "\n";
1421  fMaxPathOutInfo += " TopVolume: " + fTopVolume + "\n";
1422  fMaxPathOutInfo += " FiducialCut: " + fFiducialCut + "\n";
1423  fMaxPathOutInfo += " GeomScan: " + fGeomScan + "\n";
1424 
1425  mf::LogInfo("GENIEHelper") << "MaxPathOutInfo: \""
1426  << fMaxPathOutInfo << "\"";
1427 
1428  }
1429 
1430  //--------------------------------------------------
1432  {
1433  // std::cout << "in GENIEHelper::Stop(), fEventsPerSpill = " << fEventsPerSpill
1434  // << " fPOTPerSpill = " << fPOTPerSpill << " fSpillExposure = " << fSpillExposure
1435  // << " fSpillEvents = " << fSpillEvents
1436  // << " fHistEventsPerSpill = " << fHistEventsPerSpill << std::endl;
1437 
1438  // determine if we should keep throwing neutrinos for
1439  // this spill or move on
1440 
1441  if ( fFluxType.compare("atmo_FLUKA") == 0 || fFluxType.compare("atmo_BARTOL") == 0 ||
1442  fFluxType.compare("atmo_HONDA") == 0 || fFluxType.compare("atmo_HAKKM") == 0 ) {
1443  if ( (fEventsPerSpill > 0) && (fSpillEvents < fEventsPerSpill) ) {
1444  return false;
1445  }
1446  }
1447 
1448  else if ( fEventsPerSpill > 0 ) {
1449  if ( fSpillEvents < fEventsPerSpill )
1450  return false;
1451  } else {
1452  if ( ( fFluxType.compare("numi") == 0 ||
1453  fFluxType.compare("simple") == 0 ||
1454  fFluxType.compare("dk2nu") == 0 ) &&
1455  fSpillExposure < fPOTPerSpill ) return false;
1456  else if ( fFluxType.compare("histogram") == 0 ){
1457  if ( fSpillEvents < fHistEventsPerSpill ) return false;
1459  }
1460  }
1461 
1462  // made it to here, means need to reset the counters
1463 
1464  if(fFluxType.compare("atmo_FLUKA") == 0 || fFluxType.compare("atmo_BARTOL") == 0 ||
1465  fFluxType.compare("atmo_HONDA") == 0 || fFluxType.compare("atmo_HAKKM") == 0 ){
1466  //the exposure for atmo is in SECONDS. In order to get seconds, it needs to
1467  //be normalized by 1e4 to take into account the units discrepency between
1468  //AtmoFluxDriver(/m2) and Generate(/cm2) and it need to be normalized by
1469  //the generation surface area since it's not taken into accoutn in the flux driver
1470  fTotalExposure = (1e4 * (dynamic_cast<genie::flux::GAtmoFlux *>(fFluxD)->NFluxNeutrinos())) / (TMath::Pi() * fAtmoRt*fAtmoRt);
1471 
1472  LOG_DEBUG("GENIEHelper") << "===> Atmo EXPOSURE = " << fTotalExposure << " seconds";
1473  }
1474 
1475  else{
1477  }
1478 
1479  fSpillEvents = 0;
1480  fSpillExposure = 0.;
1482  return true;
1483  }
1484 
1485  //--------------------------------------------------
1487  {
1488  // set the top volume for the geometry
1489  fGeoManager->SetTopVolume(fGeoManager->FindVolumeFast(fTopVolume.c_str()));
1490 
1491  if ( fGenieEventRecord ) delete fGenieEventRecord;
1492 
1493  // ART Framework plays games with gRandom, undo that if requested
1494  TRandom* old_gRandom = gRandom;
1495  if (fUseHelperRndGen4GENIE) gRandom = fHelperRandom;
1496 
1497  fGenieEventRecord = fDriver->GenerateEvent();
1498 
1499  if (fUseHelperRndGen4GENIE) gRandom = old_gRandom;
1500 
1501  // now check if we produced a viable event record
1502  bool viableInteraction = true;
1503  if ( ! fGenieEventRecord ) viableInteraction = false;
1504 
1505  // update the spill total information, then check to see
1506  // if we got an event record that was valid
1507 
1508 
1509 #if __GENIE_RELEASE_CODE__ >= GRELCODE(2,11,0)
1510  genie::flux::GFluxExposureI* fexposure =
1511  dynamic_cast<genie::flux::GFluxExposureI*>(fFluxD);
1512  if ( fexposure ) {
1513  fSpillExposure =
1514  (fexposure->GetTotalExposure()/fDriver->GlobProbScale()) - fTotalExposure;
1515  }
1516  // use GENIE2ART code to fill MCFlux
1517  evgb::FillMCFlux(fFluxD,flux);
1518 #else
1519  // pack the flux information no support for dk2nu
1520  if ( fFluxType.compare("numi") == 0){
1521  fSpillExposure = (dynamic_cast<genie::flux::GNuMIFlux *>(fFluxD)->UsedPOTs()/fDriver->GlobProbScale() - fTotalExposure);
1522  flux.fFluxType = simb::kNtuple;
1523  PackNuMIFlux(flux);
1524  }
1525  else if ( fFluxType.compare("simple")==0 ) {
1526  // pack the flux information
1527  fSpillExposure = (dynamic_cast<genie::flux::GSimpleNtpFlux *>(fFluxD)->UsedPOTs()/fDriver->GlobProbScale() - fTotalExposure);
1529  PackSimpleFlux(flux);
1530  }
1531 #endif
1532 
1533  // if no interaction generated return false
1534  if ( ! viableInteraction ) return false;
1535 
1536 #if __GENIE_RELEASE_CODE__ >= GRELCODE(2,11,0)
1537  // fill the MCTruth & GTruth information as we have a good interaction
1538  // these two objects are enough to reconstruct the GENIE record
1539  // use the new external functions in GENIE2ART
1540 
1541  //choose a spill time (ns) to shift the vertex times by:
1542  double spilltime = fGlobalTimeOffset;
1543  if ( ! fTimeShifter ) {
1544  spilltime += fHelperRandom->Uniform()*fRandomTimeOffset;
1545  } else {
1546  spilltime += fTimeShifter->TimeOffset();
1547  }
1548 
1549  evgb::FillMCTruth(fGenieEventRecord, spilltime, truth);
1551 #else
1552  // fill the MC truth information as we have a good interaction
1554  // fill the Generator (genie) truth information
1555  PackGTruth(fGenieEventRecord, gtruth);
1556 #endif
1557 
1558  // check to see if we are using flux ntuples but want to
1559  // make n events per spill
1560  if ( fEventsPerSpill > 0 &&
1561  ( fFluxType.compare("numi") == 0 ||
1562  fFluxType.compare("simple") == 0 ||
1563  fFluxType.compare("dk2nu") == 0 )
1564  ) ++fSpillEvents;
1565 
1566  // now check if using either histogram or mono fluxes, using
1567  // either n events per spill or basing events on POT per spill for the
1568  // histogram case
1569  if(fFluxType.compare("histogram") == 0){
1570  // set the flag in the parent object that says the
1571  // fluxes came from histograms and fill related values
1573 
1574  // save the fluxes - fluxes were added to the vector in the same
1575  // order that the flavors appear in fGenFlavors
1576  int ctr = 0;
1577  int bin = fFluxHistograms[0]->FindBin(truth.GetNeutrino().Nu().E());
1578  std::vector<double> fluxes(6, 0.);
1579  for(std::vector<int>::iterator i = fGenFlavors.begin(); i != fGenFlavors.end(); i++){
1580  if(*i == 12) fluxes[kNue] = fFluxHistograms[ctr]->GetBinContent(bin);
1581  if(*i == -12) fluxes[kNueBar] = fFluxHistograms[ctr]->GetBinContent(bin);
1582  if(*i == 14) fluxes[kNuMu] = fFluxHistograms[ctr]->GetBinContent(bin);
1583  if(*i == -14) fluxes[kNuMuBar] = fFluxHistograms[ctr]->GetBinContent(bin);
1584  if(*i == 16) fluxes[kNuTau] = fFluxHistograms[ctr]->GetBinContent(bin);
1585  if(*i == -16) fluxes[kNuTauBar] = fFluxHistograms[ctr]->GetBinContent(bin);
1586  ++ctr;
1587  }
1588 
1589  // get the flux for each neutrino flavor of this energy
1590  flux.SetFluxGen(fluxes[kNue], fluxes[kNueBar],
1591  fluxes[kNuMu], fluxes[kNuMuBar],
1592  fluxes[kNuTau], fluxes[kNuTauBar]);
1593 
1594  ++fSpillEvents;
1595  }
1596  else if(fFluxType.compare("mono") == 0 || fFluxType.compare("function") == 0){
1597  ++fSpillEvents;
1598  }
1599 
1600  else if(fFluxType.compare("atmo_FLUKA") == 0 || fFluxType.compare("atmo_BARTOL") == 0 ||
1601  fFluxType.compare("atmo_HAKKM") == 0 || fFluxType.compare("atmo_HONDA") == 0 ){
1602  if(fEventsPerSpill > 0) ++fSpillEvents;
1604  }
1605 
1606 
1607  // fill these after the Pack[NuMI|Simple]Flux because those
1608  // will Reset() the values at the start
1609  TLorentzVector *vertex = fGenieEventRecord->Vertex();
1610  TLorentzVector nuray_pos = fFluxD->Position();
1611  TVector3 ray2vtx = nuray_pos.Vect() - vertex->Vect();
1612  flux.fgenx = nuray_pos.X();
1613  flux.fgeny = nuray_pos.Y();
1614  flux.fgenz = nuray_pos.Z();
1615  flux.fgen2vtx = ray2vtx.Mag();
1616 
1617  genie::flux::GFluxBlender* blender =
1618  dynamic_cast<genie::flux::GFluxBlender*>(fFluxD2GMCJD);
1619  if ( blender ) {
1620  flux.fdk2gen = blender->TravelDist();
1621  // / if mixing flavors print the state of the blender
1622  if ( fDebugFlags & 0x02 ) blender->PrintState();
1623  }
1624 
1625  if ( fDebugFlags & 0x04 ) {
1626  mf::LogInfo("GENIEHelper") << "vertex loc " << vertex->X() << ","
1627  << vertex->Y() << "," << vertex->Z() << std::endl
1628  << " flux ray start " << nuray_pos.X() << ","
1629  << nuray_pos.Y() << "," << nuray_pos.Z() << std::endl
1630  << " ray2vtx = " << flux.fgen2vtx
1631  << " dk2ray = " << flux.fdk2gen;
1632  }
1633  if ( fGHepPrintLevel >= 0 ) {
1634  std::cout << *fGenieEventRecord;
1635  }
1636 
1637  // set the top volume of the geometry back to the world volume
1638  fGeoManager->SetTopVolume(fGeoManager->FindVolumeFast(fWorldVolume.c_str()));
1639 
1640  return true;
1641  }
1642 
1643  //--------------------------------------------------
1645  {
1646  flux.Reset();
1647 
1648  // cast the fFluxD pointer to be of the right type
1649  genie::flux::GNuMIFlux *gnf = dynamic_cast<genie::flux::GNuMIFlux *>(fFluxD);
1650  const genie::flux::GNuMIFluxPassThroughInfo& nflux = gnf->PassThroughInfo();
1651 
1652  // check the particle codes and the units passed through
1653  // nflux.pcodes: 0=original GEANT particle codes, 1=converted to PDG
1654  // nflux.units: 0=original GEANT cm, 1=meters
1655  if(nflux.pcodes != 1 && nflux.units != 0)
1656  mf::LogWarning("GENIEHelper") << "either wrong particle codes or units "
1657  << "from flux object - beware!!";
1658 
1659  // maintained variable names from gnumi ntuples
1660  // see http://www.hep.utexas.edu/~zarko/wwwgnumi/v19/[/v19/output_gnumi.html]
1661 
1662  flux.frun = nflux.run;
1663  flux.fevtno = nflux.evtno;
1664  flux.fndxdz = nflux.ndxdz;
1665  flux.fndydz = nflux.ndydz;
1666  flux.fnpz = nflux.npz;
1667  flux.fnenergy = nflux.nenergy;
1668  flux.fndxdznea = nflux.ndxdznea;
1669  flux.fndydznea = nflux.ndydznea;
1670  flux.fnenergyn = nflux.nenergyn;
1671  flux.fnwtnear = nflux.nwtnear;
1672  flux.fndxdzfar = nflux.ndxdzfar;
1673  flux.fndydzfar = nflux.ndydzfar;
1674  flux.fnenergyf = nflux.nenergyf;
1675  flux.fnwtfar = nflux.nwtfar;
1676  flux.fnorig = nflux.norig;
1677  flux.fndecay = nflux.ndecay;
1678  flux.fntype = nflux.ntype;
1679  flux.fvx = nflux.vx;
1680  flux.fvy = nflux.vy;
1681  flux.fvz = nflux.vz;
1682  flux.fpdpx = nflux.pdpx;
1683  flux.fpdpy = nflux.pdpy;
1684  flux.fpdpz = nflux.pdpz;
1685  flux.fppdxdz = nflux.ppdxdz;
1686  flux.fppdydz = nflux.ppdydz;
1687  flux.fpppz = nflux.pppz;
1688  flux.fppenergy = nflux.ppenergy;
1689  flux.fppmedium = nflux.ppmedium;
1690  flux.fptype = nflux.ptype; // converted to PDG
1691  flux.fppvx = nflux.ppvx;
1692  flux.fppvy = nflux.ppvy;
1693  flux.fppvz = nflux.ppvz;
1694  flux.fmuparpx = nflux.muparpx;
1695  flux.fmuparpy = nflux.muparpy;
1696  flux.fmuparpz = nflux.muparpz;
1697  flux.fmupare = nflux.mupare;
1698  flux.fnecm = nflux.necm;
1699  flux.fnimpwt = nflux.nimpwt;
1700  flux.fxpoint = nflux.xpoint;
1701  flux.fypoint = nflux.ypoint;
1702  flux.fzpoint = nflux.zpoint;
1703  flux.ftvx = nflux.tvx;
1704  flux.ftvy = nflux.tvy;
1705  flux.ftvz = nflux.tvz;
1706  flux.ftpx = nflux.tpx;
1707  flux.ftpy = nflux.tpy;
1708  flux.ftpz = nflux.tpz;
1709  flux.ftptype = nflux.tptype; // converted to PDG
1710  flux.ftgen = nflux.tgen;
1711  flux.ftgptype = nflux.tgptype; // converted to PDG
1712  flux.ftgppx = nflux.tgppx;
1713  flux.ftgppy = nflux.tgppy;
1714  flux.ftgppz = nflux.tgppz;
1715  flux.ftprivx = nflux.tprivx;
1716  flux.ftprivy = nflux.tprivy;
1717  flux.ftprivz = nflux.tprivz;
1718  flux.fbeamx = nflux.beamx;
1719  flux.fbeamy = nflux.beamy;
1720  flux.fbeamz = nflux.beamz;
1721  flux.fbeampx = nflux.beampx;
1722  flux.fbeampy = nflux.beampy;
1723  flux.fbeampz = nflux.beampz;
1724 
1725  flux.fdk2gen = gnf->GetDecayDist();
1726 
1727  return;
1728  }
1729 
1730  //--------------------------------------------------
1731  void GENIEHelper::PackMCTruth(genie::EventRecord *record,
1732  simb::MCTruth &truth)
1733  {
1734 
1735  TLorentzVector *vertex = record->Vertex();
1736 
1737  // get the Interaction object from the record - this is the object
1738  // that talks to the event information objects and is in m
1739  genie::Interaction *inter = record->Summary();
1740 
1741  // get the different components making up the interaction
1742  const genie::InitialState &initState = inter->InitState();
1743  const genie::ProcessInfo &procInfo = inter->ProcInfo();
1744  //const genie::Kinematics &kine = inter->Kine();
1745  //const genie::XclsTag &exclTag = inter->ExclTag();
1746  //const genie::KPhaseSpace &phaseSpace = inter->PhaseSpace();
1747 
1748  //choose a spill time (ns) to shift the vertex times by:
1749 
1750  double spillTime = fGlobalTimeOffset + fHelperRandom->Uniform()*fRandomTimeOffset;
1751 
1752  // add the particles from the interaction
1753  TIter partitr(record);
1754  genie::GHepParticle *part = 0;
1755  // GHepParticles return units of GeV/c for p. the V_i are all in fermis
1756  // and are relative to the center of the struck nucleus.
1757  // add the vertex X/Y/Z to the V_i for status codes 0 and 1
1758  int trackid = 0;
1759  std::string primary("primary");
1760 
1761  while( (part = dynamic_cast<genie::GHepParticle *>(partitr.Next())) ){
1762 
1763  simb::MCParticle tpart(trackid,
1764  part->Pdg(),
1765  primary,
1766  part->FirstMother(),
1767  part->Mass(),
1768  part->Status());
1769  double vtx[4] = {part->Vx(), part->Vy(), part->Vz(), part->Vt()};
1770  tpart.SetGvtx(vtx);
1771  tpart.SetRescatter(part->RescatterCode());
1772 
1773  // set the vertex location for the neutrino, nucleus and everything
1774  // that is to be tracked. vertex returns values in meters.
1775  if(part->Status() == 0 || part->Status() == 1){
1776  vtx[0] = 100.*(part->Vx()*1.e-15 + vertex->X());
1777  vtx[1] = 100.*(part->Vy()*1.e-15 + vertex->Y());
1778  vtx[2] = 100.*(part->Vz()*1.e-15 + vertex->Z());
1779  vtx[3] = part->Vt() + spillTime;
1780  }
1781  TLorentzVector pos(vtx[0], vtx[1], vtx[2], vtx[3]);
1782  TLorentzVector mom(part->Px(), part->Py(), part->Pz(), part->E());
1783  tpart.AddTrajectoryPoint(pos,mom);
1784  if(part->PolzIsSet()) {
1785  TVector3 polz;
1786  part->GetPolarization(polz);
1787  tpart.SetPolarization(polz);
1788  }
1789  truth.Add(tpart);
1790 
1791  ++trackid;
1792  }// end loop to convert GHepParticles to MCParticles
1793 
1794  // is the interaction NC or CC
1795  int CCNC = simb::kCC;
1796  if(procInfo.IsWeakNC()) CCNC = simb::kNC;
1797 
1798  // what is the interaction type
1799  int mode = simb::kUnknownInteraction;
1800 
1801  if (procInfo.IsQuasiElastic() ) mode = simb::kQE;
1802  else if(procInfo.IsDeepInelastic() ) mode = simb::kDIS;
1803  else if(procInfo.IsResonant() ) mode = simb::kRes;
1804  else if(procInfo.IsCoherent() ) mode = simb::kCoh;
1805  else if(procInfo.IsCoherentElas() ) mode = simb::kCohElastic;
1806  else if(procInfo.IsElectronScattering() ) mode = simb::kElectronScattering;
1807  else if(procInfo.IsNuElectronElastic() ) mode = simb::kNuElectronElastic;
1808  else if(procInfo.IsInverseMuDecay() ) mode = simb::kInverseMuDecay;
1809  else if(procInfo.IsIMDAnnihilation() ) mode = simb::kIMDAnnihilation;
1810  else if(procInfo.IsInverseBetaDecay() ) mode = simb::kInverseBetaDecay;
1811  else if(procInfo.IsGlashowResonance() ) mode = simb::kGlashowResonance;
1812  else if(procInfo.IsAMNuGamma() ) mode = simb::kAMNuGamma;
1813  else if(procInfo.IsMEC() ) mode = simb::kMEC;
1814  else if(procInfo.IsDiffractive() ) mode = simb::kDiffractive;
1815  else if(procInfo.IsEM() ) mode = simb::kEM;
1816  else if(procInfo.IsWeakMix() ) mode = simb::kWeakMix;
1817 
1818  int itype = simb::kNuanceOffset + genie::utils::ghep::NuanceReactionCode(record);
1819 
1820  // set the neutrino information in MCTruth
1822 
1823 #ifdef OLD_KINE_CALC
1824  // The genie event kinematics are subtle different from the event
1825  // kinematics that a experimentalist would calculate
1826  // Instead of retriving the genie values for these kinematic variables
1827  // calcuate them from the the final state particles
1828  // while ingnoring the fermi momentum and the off-shellness of the bound nucleon.
1829  genie::GHepParticle * hitnucl = record->HitNucleon();
1830  TLorentzVector pdummy(0, 0, 0, 0);
1831  const TLorentzVector & k1 = *((record->Probe())->P4());
1832  const TLorentzVector & k2 = *((record->FinalStatePrimaryLepton())->P4());
1833  //const TLorentzVector & p1 = (hitnucl) ? *(hitnucl->P4()) : pdummy;
1834 
1835  double M = genie::constants::kNucleonMass;
1836  TLorentzVector q = k1-k2; // q=k1-k2, 4-p transfer
1837  double Q2 = -1 * q.M2(); // momemtum transfer
1838  double v = (hitnucl) ? q.Energy() : -1; // v (E transfer to the nucleus)
1839  double x = (hitnucl) ? 0.5*Q2/(M*v) : -1; // Bjorken x
1840  double y = (hitnucl) ? v/k1.Energy() : -1; // Inelasticity, y = q*P1/k1*P1
1841  double W2 = (hitnucl) ? M*M + 2*M*v - Q2 : -1; // Hadronic Invariant mass ^ 2
1842  double W = (hitnucl) ? std::sqrt(W2) : -1;
1843 #else
1844  // The internal GENIE event kinematics are subtly different from the event
1845  // kinematics that a experimentalist would calculate.
1846  // Instead of retriving the genie values for these kinematic variables ,
1847  // calculate them from the the final state particles
1848  // while ignoring the Fermi momentum and the off-shellness of the bound nucleon.
1849  // (same strategy as in gNtpConv.cxx::ConvertToGST().)
1850  genie::GHepParticle * hitnucl = record->HitNucleon();
1851  const TLorentzVector & k1 = *((record->Probe())->P4());
1852  const TLorentzVector & k2 = *((record->FinalStatePrimaryLepton())->P4());
1853 
1854  // also note that since most of these variables are calculated purely from the leptonic system,
1855  // they have meaning reactions that didn't strike a nucleon (or even a hadron) as well.
1856  TLorentzVector q = k1-k2; // q=k1-k2, 4-p transfer
1857 
1858  double Q2 = -1 * q.M2(); // momemtum transfer
1859  double v = q.Energy(); // v (E transfer to the had system)
1860  double y = v/k1.Energy(); // Inelasticity, y = q*P1/k1*P1
1861  double x, W2, W;
1862  x = W2 = W = -1;
1863 
1864  if ( hitnucl || procInfo.IsCoherent() ) {
1865  const double M = genie::constants::kNucleonMass;
1866  // Bjorken x.
1867  // Rein & Sehgal use this same formulation of x even for Coherent
1868  x = 0.5*Q2/(M*v);
1869  // Hadronic Invariant mass ^ 2.
1870  // ("wrong" for Coherent, but it's "experimental", so ok?)
1871  W2 = M*M + 2*M*v - Q2;
1872  W = std::sqrt(W2);
1873  }
1874 #endif
1875 
1876  truth.SetNeutrino(CCNC,
1877  mode,
1878  itype,
1879  initState.Tgt().Pdg(),
1880  initState.Tgt().HitNucPdg(),
1881  initState.Tgt().HitQrkPdg(),
1882  W,
1883  x,
1884  y,
1885  Q2);
1886  return;
1887  }
1888 
1889  //--------------------------------------------------
1890  void GENIEHelper::PackGTruth(genie::EventRecord *record,
1891  simb::GTruth &truth) {
1892 
1893  // interactions info
1894  genie::Interaction *inter = record->Summary();
1895  const genie::ProcessInfo &procInfo = inter->ProcInfo();
1896  truth.fGint = (int)procInfo.InteractionTypeId();
1897  truth.fGscatter = (int)procInfo.ScatteringTypeId();
1898 
1899  // Event info
1900  truth.fweight = record->Weight();
1901  truth.fprobability = record->Probability();
1902  truth.fXsec = record->XSec();
1903  truth.fDiffXsec = record->DiffXSec();
1904 
1905  TLorentzVector vtx;
1906  TLorentzVector *erVtx = record->Vertex();
1907  vtx.SetXYZT(erVtx->X(), erVtx->Y(), erVtx->Z(), erVtx->T() );
1908  truth.fVertex = vtx;
1909 
1910  // true reaction information and byproducts
1911  // (PRE FSI)
1912  const genie::XclsTag &exclTag = inter->ExclTag();
1913  truth.fIsCharm = exclTag.IsCharmEvent();
1914  truth.fResNum = (int)exclTag.Resonance();
1915 
1916  // count hadrons from the particle record.
1917  // note that in principle this information could come from the XclsTag,
1918  // but that object isn't completely filled for most reactions
1919  // truth.fNumPiPlus = exclTag.NPiPlus();
1920  // truth.fNumPiMinus = exclTag.NPiMinus();
1921  // truth.fNumPi0 = exclTag.NPi0();
1922  // truth.fNumProton = exclTag.NProtons();
1923  // truth.fNumNeutron = exclTag.NNucleons();
1924  truth.fNumPiPlus = truth.fNumPiMinus = truth.fNumPi0 = truth.fNumProton = truth.fNumNeutron = 0;
1925  for (int idx = 0; idx < record->GetEntries(); idx++) {
1926  // want hadrons that are about to be sent to the FSI model
1927  const genie::GHepParticle * particle = record->Particle(idx);
1928  if (particle->Status() != genie::kIStHadronInTheNucleus)
1929  continue;
1930 
1931  int pdg = particle->Pdg();
1932  if (pdg == genie::kPdgPi0)
1933  truth.fNumPi0++;
1934  else if (pdg == genie::kPdgPiP)
1935  truth.fNumPiPlus++;
1936  else if (pdg == genie::kPdgPiM)
1937  truth.fNumPiMinus++;
1938  else if (pdg == genie::kPdgNeutron)
1939  truth.fNumNeutron++;
1940  else if (pdg == genie::kPdgProton)
1941  truth.fNumProton++;
1942  } // for (idx)
1943 
1944 
1945  //kinematics info
1946  const genie::Kinematics &kine = inter->Kine();
1947 
1948  truth.fgQ2 = kine.Q2(true);
1949  truth.fgq2 = kine.q2(true);
1950  truth.fgW = kine.W(true);
1951  if ( kine.KVSet(genie::kKVSelt) ) {
1952  // only get this if it is set in the Kinematics class
1953  // to avoid a warning message
1954  truth.fgT = kine.t(true);
1955  }
1956  truth.fgX = kine.x(true);
1957  truth.fgY = kine.y(true);
1958 
1959  /*
1960  truth.fgQ2 = kine.Q2(false);
1961  truth.fgW = kine.W(false);
1962  truth.fgT = kine.t(false);
1963  truth.fgX = kine.x(false);
1964  truth.fgY = kine.y(false);
1965  */
1966  truth.fFShadSystP4 = kine.HadSystP4();
1967 
1968  //Initial State info
1969  const genie::InitialState &initState = inter->InitState();
1970  truth.fProbePDG = initState.ProbePdg();
1971  truth.fProbeP4 = *initState.GetProbeP4();
1972 
1973  //Target info
1974  const genie::Target &tgt = initState.Tgt();
1975  truth.fIsSeaQuark = tgt.HitSeaQrk();
1976  truth.fHitNucP4 = tgt.HitNucP4();
1977  truth.ftgtZ = tgt.Z();
1978  truth.ftgtA = tgt.A();
1979  truth.ftgtPDG = tgt.Pdg();
1980 
1981  return;
1982 
1983  }
1984 
1985  //----------------------------------------------------------------------
1987  {
1988  flux.Reset();
1989 
1990  // cast the fFluxD pointer to be of the right type
1991  genie::flux::GSimpleNtpFlux *gsf = dynamic_cast<genie::flux::GSimpleNtpFlux *>(fFluxD);
1992 
1993  // maintained variable names from gnumi ntuples
1994  // see http://www.hep.utexas.edu/~zarko/wwwgnumi/v19/[/v19/output_gnumi.html]
1995 
1996  const genie::flux::GSimpleNtpEntry* nflux_entry = gsf->GetCurrentEntry();
1997  const genie::flux::GSimpleNtpNuMI* nflux_numi = gsf->GetCurrentNuMI();
1998 
1999  flux.fntype = nflux_entry->pdg;
2000  flux.fnimpwt = nflux_entry->wgt;
2001  flux.fdk2gen = nflux_entry->dist;
2002  flux.fnenergyn = flux.fnenergyf = nflux_entry->E;
2003 
2004  if ( nflux_numi ) {
2005  flux.frun = nflux_numi->run;
2006  flux.fevtno = nflux_numi->evtno;
2007  flux.ftpx = nflux_numi->tpx;
2008  flux.ftpy = nflux_numi->tpy;
2009  flux.ftpz = nflux_numi->tpz;
2010  flux.ftptype = nflux_numi->tptype; // converted to PDG
2011  flux.fvx = nflux_numi->vx;
2012  flux.fvy = nflux_numi->vy;
2013  flux.fvz = nflux_numi->vz;
2014 
2015  flux.fndecay = nflux_numi->ndecay;
2016  flux.fppmedium = nflux_numi->ppmedium;
2017 
2018  flux.fpdpx = nflux_numi->pdpx;
2019  flux.fpdpy = nflux_numi->pdpy;
2020  flux.fpdpz = nflux_numi->pdpz;
2021 
2022  double apppz = nflux_numi->pppz;
2023  if ( TMath::Abs(nflux_numi->pppz) < 1.0e-30 ) apppz = 1.0e-30;
2024  flux.fppdxdz = nflux_numi->pppx / apppz;
2025  flux.fppdydz = nflux_numi->pppy / apppz;
2026  flux.fpppz = nflux_numi->pppz;
2027 
2028  flux.fptype = nflux_numi->ptype;
2029 
2030  }
2031 
2032  // anything useful stuffed into vdbl or vint?
2033  // need to check the metadata auxintname, auxdblname
2034 
2035  const genie::flux::GSimpleNtpAux* nflux_aux = gsf->GetCurrentAux();
2036  const genie::flux::GSimpleNtpMeta* nflux_meta = gsf->GetCurrentMeta();
2037  if ( nflux_aux && nflux_meta ) {
2038 
2039  // references just for reducing complexity
2040  const std::vector<std::string>& auxdblname = nflux_meta->auxdblname;
2041  const std::vector<std::string>& auxintname = nflux_meta->auxintname;
2042  const std::vector<int>& auxint = nflux_aux->auxint;
2043  const std::vector<double>& auxdbl = nflux_aux->auxdbl;
2044 
2045  for (size_t id=0; id<auxdblname.size(); ++id) {
2046  if ("muparpx" == auxdblname[id]) flux.fmuparpx = auxdbl[id];
2047  if ("muparpy" == auxdblname[id]) flux.fmuparpy = auxdbl[id];
2048  if ("muparpz" == auxdblname[id]) flux.fmuparpz = auxdbl[id];
2049  if ("mupare" == auxdblname[id]) flux.fmupare = auxdbl[id];
2050  if ("necm" == auxdblname[id]) flux.fnecm = auxdbl[id];
2051  if ("nimpwt" == auxdblname[id]) flux.fnimpwt = auxdbl[id];
2052  if ("fgXYWgt" == auxdblname[id]) {
2053  flux.fnwtnear = flux.fnwtfar = auxdbl[id];
2054  }
2055  }
2056  for (size_t ii=0; ii<auxintname.size(); ++ii) {
2057  if ("tgen" == auxintname[ii]) flux.ftgen = auxint[ii];
2058  if ("tgptype" == auxintname[ii]) flux.ftgptype = auxint[ii];
2059  }
2060 
2061  }
2062 
2063 #define RWH_TEST
2064 #ifdef RWH_TEST
2065  static bool first = true;
2066  if (first) {
2067  first = false;
2068  mf::LogDebug("GENIEHelper")
2069  << "GSimpleNtpMeta:\n"
2070  << *nflux_meta << "\n";
2071  }
2072  mf::LogDebug("GENIEHelper")
2073  << "simb::MCFlux:\n"
2074  << flux << "\n"
2075  << "GSimpleNtpFlux:\n"
2076  << *nflux_entry << "\n"
2077  << *nflux_numi << "\n"
2078  << *nflux_aux << "\n";
2079 #endif
2080 
2081  // flux.fndxdz = nflux.ndxdz;
2082  // flux.fndydz = nflux.ndydz;
2083  // flux.fnpz = nflux.npz;
2084  // flux.fnenergy = nflux.nenergy;
2085  // flux.fndxdznea = nflux.ndxdznea;
2086  // flux.fndydznea = nflux.ndydznea;
2087  // flux.fnenergyn = nflux.nenergyn;
2088  // flux.fnwtnear = nflux.nwtnear;
2089  // flux.fndxdzfar = nflux.ndxdzfar;
2090  // flux.fndydzfar = nflux.ndydzfar;
2091  // flux.fnenergyf = nflux.nenergyf;
2092  // flux.fnwtfar = nflux.nwtfar;
2093  // flux.fnorig = nflux.norig;
2094  // in numi // flux.fndecay = nflux.ndecay;
2095  // flux.fntype = nflux.ntype;
2096  // in numi // flux.fvx = nflux.vx;
2097  // in numi // flux.fvy = nflux.vy;
2098  // in numi // flux.fvz = nflux.vz;
2099  // flux.fppenergy = nflux.ppenergy;
2100  // in numi // flux.fppmedium = nflux.ppmedium;
2101  // flux.fppvx = nflux.ppvx;
2102  // flux.fppvy = nflux.ppvy;
2103  // flux.fppvz = nflux.ppvz;
2104  // see above // flux.fmuparpx = nflux.muparpx;
2105  // see above // flux.fmuparpy = nflux.muparpy;
2106  // see above // flux.fmuparpz = nflux.muparpz;
2107  // see above // flux.fmupare = nflux.mupare;
2108  // see above // flux.fnecm = nflux.necm;
2109  // see above // flux.fnimpwt = nflux.nimpwt;
2110  // flux.fxpoint = nflux.xpoint;
2111  // flux.fypoint = nflux.ypoint;
2112  // flux.fzpoint = nflux.zpoint;
2113  // flux.ftvx = nflux.tvx;
2114  // flux.ftvy = nflux.tvy;
2115  // flux.ftvz = nflux.tvz;
2116  // see above // flux.ftgen = nflux.tgen;
2117  // see above // flux.ftgptype = nflux.tgptype; // converted to PDG
2118  // flux.ftgppx = nflux.tgppx;
2119  // flux.ftgppy = nflux.tgppy;
2120  // flux.ftgppz = nflux.tgppz;
2121  // flux.ftprivx = nflux.tprivx;
2122  // flux.ftprivy = nflux.tprivy;
2123  // flux.ftprivz = nflux.tprivz;
2124  // flux.fbeamx = nflux.beamx;
2125  // flux.fbeamy = nflux.beamy;
2126  // flux.fbeamz = nflux.beamz;
2127  // flux.fbeampx = nflux.beampx;
2128  // flux.fbeampy = nflux.beampy;
2129  // flux.fbeampz = nflux.beampz;
2130 
2131  flux.fdk2gen = gsf->GetDecayDist();
2132 
2133  return;
2134  }
2135 
2136  //---------------------------------------------------------
2138  {
2139  // construct fFluxRotation matrix
2140  // from fFluxRotCfg + fFluxRotValues
2141  if ( fFluxRotCfg == "" ||
2142  ( fFluxRotCfg.find("none") != std::string::npos ) ) return;
2143 
2144  size_t nval = fFluxRotValues.size();
2145 
2146  bool verbose = ( fFluxRotCfg.find("verbose") != std::string::npos );
2147  if (verbose) {
2148  std::ostringstream indata;
2149  indata << "BuildFluxRotation: Cfg \"" << fFluxRotCfg << "\"\n"
2150  << " " << nval << " values\n";
2151  for (size_t i=0; i<nval; ++i) {
2152  indata << " [" << std::setw(2) << i << "] " << fFluxRotValues[i] << "\n";
2153  }
2154  mf::LogInfo("GENIEHelper") << indata.str();
2155  }
2156 
2157  // interpret as a full 3x3 array
2158  if ( fFluxRotCfg.find("newxyz") != std::string::npos ||
2159  fFluxRotCfg.find("3x3") != std::string::npos ) {
2160  if ( nval == 9 ) {
2161  TRotation fTempRot;
2162  TVector3 newX = TVector3(fFluxRotValues[0],
2163  fFluxRotValues[1],
2164  fFluxRotValues[2]);
2165  TVector3 newY = TVector3(fFluxRotValues[3],
2166  fFluxRotValues[4],
2167  fFluxRotValues[5]);
2168  TVector3 newZ = TVector3(fFluxRotValues[6],
2169  fFluxRotValues[7],
2170  fFluxRotValues[8]);
2171  fTempRot.RotateAxes(newX,newY,newZ);
2172  // weirdly necessary; frame vs. obj rotation
2173  fFluxRotation = new TRotation(fTempRot.Inverse());
2174  return;
2175  } else {
2176  throw cet::exception("BadFluxRotation")
2177  << "specified: " << fFluxRotCfg << "\n"
2178  << " but nval=" << nval << ", need 9";
2179  }
2180  }
2181 
2182  // another possibility ... series of rotations around particular axes
2183  if ( fFluxRotCfg.find("series") != std::string::npos ) {
2184  TRotation fTempRot;
2185  // if series then cfg should also have series of rot{X|Y|Z}{deg|rad}
2186  std::vector<std::string> strs = genie::utils::str::Split(fFluxRotCfg," ,;(){}[]");
2187  size_t nrot = -1;
2188  for (size_t j=0; j<strs.size(); ++j) {
2189  std::string what = strs[j];
2190  if ( what == "" ) continue;
2191  // lower case for convenience
2192  std::transform(what.begin(),what.end(),what.begin(),::tolower);
2193  if ( what == "series" ) continue;
2194  if ( what == "verbose" ) continue;
2195  if ( what.find("rot") != 0 ) {
2196  mf::LogWarning("GENIEHelper")
2197  << "processing series rotation saw keyword \"" << what << "\" -- ignoring";
2198  continue;
2199  }
2200  char axis = what[3];
2201  // check that axis is sensibly x, y or z
2202  if ( axis != 'x' && axis != 'y' && axis != 'z' ) {
2203  throw cet::exception("BadFluxRotation")
2204  << "specified: " << fFluxRotCfg << "\n"
2205  << " keyword '" << what << "': bad axis '" << axis << "'";
2206  }
2207  std::string units = what.substr(4);
2208  // don't worry if written fully as "radians" or "degrees"
2209  if (units.size() > 3) units.erase(3);
2210  if ( units != "" && units != "rad" && units != "deg" ) {
2211  throw cet::exception("BadFluxRotation")
2212  << "specified: " << fFluxRotCfg << "\n"
2213  << " keyword '" << what << "': bad units '" << units << "'";
2214  }
2215  // no units? assume degrees
2216  double scale = (( units == "rad" ) ? 1.0 : TMath::DegToRad() );
2217 
2218  ++nrot;
2219  if ( nrot >= nval ) {
2220  // not enough values
2221  throw cet::exception("BadFluxRotation")
2222  << "specified: " << fFluxRotCfg << "\n"
2223  << " asking for rotation [" << nrot << "] "
2224  << what << " but nval=" << nval;
2225  }
2226  double rot = scale * fFluxRotValues[nrot];
2227  if ( axis == 'x' ) fTempRot.RotateX(rot);
2228  if ( axis == 'y' ) fTempRot.RotateY(rot);
2229  if ( axis == 'z' ) fTempRot.RotateZ(rot);
2230 
2231  } // loop over tokens in cfg string
2232 
2233  // weirdly necessary; frame vs. obj rotation
2234  fFluxRotation = new TRotation(fTempRot.Inverse());
2235 
2236  if ( nrot+1 != nval ) {
2237  // call out possible user mistake
2238  mf::LogWarning("GENIEHelper")
2239  << "BuildFluxRotation only used " << nrot+1 << " of "
2240  << nval << " FluxRotValues";
2241  }
2242  return;
2243  }
2244 
2245  // could put other interpretations here ...
2246 
2247  throw cet::exception("BadFluxRotation")
2248  << "specified: " << fFluxRotCfg << "\n"
2249  << " nval=" << nval << ", but don't know how to interpret that";
2250 
2251  }
2252  //---------------------------------------------------------
2254  {
2255  // expand any wildcards in the paths variable
2256  // if unset and using the old DIRECT method allow it to fall back
2257  // to using FW_SEARCH_PATH ... but not for the new ifdhc approach
2258 
2259  std::string initial = fFluxSearchPaths;
2260 
2261  if ( fFluxCopyMethod == "DIRECT" && fFluxSearchPaths == "" ) {
2262  fFluxSearchPaths = cet::getenv("FW_SEARCH_PATH");
2263  }
2264  fFluxSearchPaths = gSystem->ExpandPathName(fFluxSearchPaths.c_str());
2265 
2266  mf::LogInfo("GENIEHelper")
2267  << "ExpandFluxPaths initially: \"" << initial << "\"\n"
2268  << " final result: \"" << fFluxSearchPaths << "\"\n"
2269  << " using: \"" << fFluxCopyMethod << "\" method";
2270  }
2271  //---------------------------------------------------------
2273  {
2274  // Using the the fFluxSearchPaths list of directories, apply the
2275  // user supplied pattern as a suffix to find the flux files.
2276  // The userpattern might include simple wildcard globs (in contrast
2277  // to proper regexp patterns).
2278 
2279  // After expanding the list to individual files, randomize them
2280  // and start selecting until a size limit is about to be
2281  // exceeded (though a minimum there needs to be one file, not
2282  // matter the limit).
2283 
2284  // older GENIE (pre r3669) can't handle vectors/sets of file names
2285  // but an only accept a pattern that will resolve to files. This
2286  // collection could exceed the desired size threshold, but for
2287  // pick the collection that expands to the largest list
2288 
2289 #ifndef GFLUX_MISSING_SETORVECTOR
2290  // no extra handling if we can pass a list
2291 #else
2292  // need to keep track of patterns that that resolve, and who has most
2293  std::vector<std::string> patternsWithFiles;
2294  std::vector<int> nfilesForPattern;
2295  int nfilesSoFar = 0;
2296 #endif
2297 
2298  bool randomizeFiles = false;
2299  if ( fFluxType.compare("numi") == 0 ||
2300  fFluxType.compare("simple") == 0 ||
2301  fFluxType.compare("dk2nu") == 0 ) randomizeFiles = true;
2302 
2303  std::vector<std::string> dirs;
2304  cet::split_path(fFluxSearchPaths,dirs);
2305  if ( dirs.empty() ) dirs.push_back(std::string()); // at least null string
2306 
2307  glob_t g;
2308  int flags = GLOB_TILDE; // expand ~ home directories
2309 
2310  std::ostringstream patterntext; // for info/error messages
2311  std::ostringstream dirstext; // for info/error messages
2312 
2314  int ipatt = 0;
2315 
2316  for ( ; uitr != fFluxFilePatterns.end(); ++uitr, ++ipatt ) {
2317  std::string userpattern = *uitr;
2318  patterntext << "\n\t" << userpattern;
2319 
2320  std::vector<std::string>::const_iterator ditr = dirs.begin();
2321  for ( ; ditr != dirs.end(); ++ditr ) {
2322  std::string dalt = *ditr;
2323  // if non-null, does it end with a "/"? if not add one
2324  size_t len = dalt.size();
2325  if ( len > 0 && dalt.rfind('/') != len-1 ) dalt.append("/");
2326  if ( uitr == fFluxFilePatterns.begin() ) dirstext << "\n\t" << dalt;
2327 
2328  std::string filepatt = dalt + userpattern;
2329 
2330  glob(filepatt.c_str(),flags,NULL,&g);
2331  if ( g.gl_pathc > 0 ) flags |= GLOB_APPEND; // next glob() will append to list
2332 
2333 #ifndef GFLUX_MISSING_SETORVECTOR
2334  // nothing special since we can use any files we want
2335 #else
2336  // keep track of pattern with most files ... we'll use that
2337  int nresolved = g.gl_pathc - nfilesSoFar;
2338  nfilesSoFar = g.gl_pathc;
2339  if ( nresolved > 0 ) {
2340  patternsWithFiles.push_back(filepatt);
2341  nfilesForPattern.push_back(nresolved);
2342  }
2343 #endif
2344 
2345  } // loop over FluxSearchPaths dirs
2346  } // loop over user patterns
2347 
2348  std::ostringstream paretext;
2349  std::ostringstream flisttext;
2350 
2351 #ifndef GFLUX_MISSING_SETORVECTOR
2352  int nfiles = g.gl_pathc;
2353 
2354  if ( nfiles == 0 ) {
2355  paretext << "\n expansion resulted in a null list for flux files";
2356 
2357  } else if ( ! randomizeFiles ) {
2358  // some sets of files should be left in order
2359  // and no size limitations imposed ... just copy the list
2360 
2361  paretext << "\n list of files will be processed in order";
2362  for (int i=0; i<nfiles; ++i) {
2363  std::string afile(g.gl_pathv[i]);
2364  fSelectedFluxFiles.push_back(afile);
2365 
2366  flisttext << "[" << setw(3) << i << "] "
2367  << afile << "\n";
2368  }
2369  } else {
2370 
2371  // now pull from the list randomly
2372  // do this by assigning a random number to each;
2373  // ordering that list; and pulling in that order
2374 
2375  paretext << "list of " << nfiles
2376  << " will be randomized and pared down to "
2377  << fMaxFluxFileMB << " MB or "
2378  << fMaxFluxFileNumber << " files";
2379 
2380  double* order = new double[nfiles];
2381  int* indices = new int[nfiles];
2382  fHelperRandom->RndmArray(nfiles,order);
2383  // assign random # for their relative order
2384 
2385  TMath::Sort((int)nfiles,order,indices,false);
2386 
2387  long long int sumBytes = 0; // accumulated size in bytes
2388  long long int maxBytes = (long long int)fMaxFluxFileMB * 1024ll * 1024ll;
2389 
2390  FileStat_t fstat;
2391  for (int i=0; i < TMath::Min(nfiles,fMaxFluxFileNumber); ++i) {
2392  int indx = indices[i];
2393  std::string afile(g.gl_pathv[indx]);
2394  bool keep = true;
2395 
2396  gSystem->GetPathInfo(afile.c_str(),fstat);
2397  sumBytes += fstat.fSize;
2398  // skip those that would push sum above total
2399  // but always accept at least one (the first)
2400  if ( sumBytes > maxBytes && i != 0 ) keep = false;
2401 
2402  flisttext << "[" << setw(3) << i << "] "
2403  << "=> g[" << setw(3) << indx << "] "
2404  << ((keep)?"keep":"skip") << " "
2405  << setw(6) << (sumBytes/(1024ll*1024ll)) << " "
2406  << afile << "\n";
2407 
2408  if ( keep ) fSelectedFluxFiles.push_back(afile);
2409  else break; // <voice name=Scotty> Captain, she can't take any more</voice>
2410 
2411  }
2412  delete [] order;
2413  delete [] indices;
2414 
2415  }
2416 #else
2417  // This version of GENIE can't handle a list of files,
2418  // so only pass it patterns. Later code will pick the first
2419  // in the list, so list them in decreasing order of # of files
2420  int npatt = patternsWithFiles.size();
2421  if ( npatt > 0 ) {
2422  flisttext << "ExpandFluxFilePatternsDirect: " << npatt
2423  << " user patterns resolved to files:\n";
2424  // std::vector is contiguous, so take address of 0-th element
2425  const int* nf = &(nfilesForPattern[0]);
2426  int* indices = new int[npatt];
2427  TMath::Sort(npatt,nf,indices,true); // descending order
2428  for (int i=0; i<npatt; ++i) {
2429  int indx = indices[i];
2430  flisttext << "[" << i << "] " << nfilesForPattern[indx]
2431  << " files in " << patternsWithFiles[indx] << "\n";
2432  fSelectedFluxFiles.push_back(patternsWithFiles[indx]);
2433  }
2434  delete [] indices;
2435  }
2436 #endif
2437 
2438  mf::LogInfo("GENIEHelper")
2439  << "ExpandFluxFilePatternsDirect initially found " << nfiles
2440  << " files for user patterns:"
2441  << patterntext.str() << "\n using FluxSearchPaths of: "
2442  << dirstext.str() << "\n" << paretext.str();
2443  //<< "\"" << cet::getenv("FW_SEARCH_PATH") << "\"";
2444 
2445  mf::LogDebug("GENIEHelper") << "\n" << flisttext.str();
2446 
2447  // done with glob list
2448  globfree(&g);
2449 
2450  // no null path allowed for at least these
2451  if ( fFluxType.compare("numi") == 0 ||
2452  fFluxType.compare("simple") == 0 ||
2453  fFluxType.compare("dk2nu") == 0 ) {
2454  size_t nfiles = fSelectedFluxFiles.size();
2455  if ( nfiles == 0 ) {
2456  mf::LogError("GENIEHelper")
2457  << "For \"dk2nu\', \"ntuple\" (\"numi\") or \"simple_flux\","
2458  << " specification must resolve to at least one file"
2459  << "\n none were found user pattern: "
2460  << patterntext.str()
2461  << "\n using FluxSearchPaths of: "
2462  << dirstext.str();
2463  //\"" << cet::getenv("FW_SEARCH_PATH") << "\"";
2464  throw cet::exception("NoFluxFiles")
2465  << "no flux files found for: " << patterntext.str() << "\n"
2466  << " in: " << dirstext.str();
2467 
2468  }
2469  }
2470 
2471  } // ExpandFluxFilePatternsDirect
2472 
2473  //---------------------------------------------------------
2475  {
2476  // Using the the FluxSearchPaths list of directories, apply the
2477  // user supplied pattern as a suffix to find the flux files.
2478  // The userpattern might include simple wildcard globs (in contrast
2479  // to proper regexp patterns).
2480 
2481  // After expanding the list to individual files, randomize them
2482  // and start selecting until a size limit is about to be
2483  // exceeded (though a minimum there needs to be one file, not
2484  // matter the limit).
2485 
2486  // Use the IFDH interface to get the list of files and sizes;
2487  // after sorting/selecting use IFDH to make a local copy
2488 
2489 #ifdef NO_IFDH_LIB
2490  std::ostringstream fmesg;
2491  std::string marker = "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
2492  fmesg << marker
2493  << __FILE__ << ":" << __LINE__
2494  << "\nno IFDH implemented on this platform\n"
2495  << marker;
2496  // make sure the message goes everywhere
2497  std::cout << fmesg.str() << std::flush;
2498  std::cerr << fmesg.str();
2499  throw cet::exception("Attempt to use ifdh class") << fmesg.str();
2500  assert(0);
2501 #else
2502  // if "method" just an identifier and not a scheme then clear it
2503  if ( fFluxCopyMethod.find("IFDH") == 0 ) fFluxCopyMethod = "";
2504 
2505  bool randomizeFiles = false;
2506  if ( fFluxType.compare("numi") == 0 ||
2507  fFluxType.compare("simple") == 0 ||
2508  fFluxType.compare("dk2nu") == 0 ) randomizeFiles = true;
2509 
2510  #ifdef USE_IFDH_SERVICE
2512  #else
2513  if ( ! fIFDH ) fIFDH = new ifdh_ns::ifdh;
2514  #endif
2515 
2516  std::string spaths = fFluxSearchPaths;
2517 
2518  const char* ifdh_debug_env = std::getenv("IFDH_DEBUG_LEVEL");
2519  if ( ifdh_debug_env ) {
2520  mf::LogInfo("GENIEHelper") << "IFDH_DEBUG_LEVEL: " << ifdh_debug_env;
2521  fIFDH->set_debug(ifdh_debug_env);
2522  }
2523 
2524  // filenames + size
2525  std::vector<std::pair<std::string,long>>
2526  partiallist, fulllist, selectedlist, locallist;
2527 
2528  std::ostringstream patterntext; // stringification of vector of patterns
2529  std::ostringstream fulltext; // for info on full list of matches
2530  std::ostringstream selectedtext; // for info on selected files
2531  std::ostringstream localtext; // for info on local files
2532  fulltext << "search paths: " << spaths;
2533 
2534  //std::vector<std::string>::const_iterator uitr = fFluxFilePatterns.begin();
2535 
2536  // loop over possible patterns
2537  // IFDH handles various stems but done a list of globs
2538  size_t ipatt=0;
2539  auto uitr = fFluxFilePatterns.begin();
2540  for ( ; uitr != fFluxFilePatterns.end(); ++uitr, ++ipatt ) {
2541  std::string userpattern = *uitr;
2542  patterntext << "\npattern [" << std::setw(3) << ipatt << "] " << userpattern;
2543  fulltext << "\npattern [" << std::setw(3) << ipatt << "] " << userpattern;
2544 
2545  #ifdef USE_IFDH_SERVICE
2546  partiallist = ifdhp->findMatchingFiles(spaths,userpattern);
2547  #else
2548  partiallist = fIFDH->findMatchingFiles(spaths,userpattern);
2549  #endif
2550  fulllist.insert(fulllist.end(),partiallist.begin(),partiallist.end());
2551 
2552  // make a complete list ...
2553  fulltext << " found " << partiallist.size() << " files";
2554  for (auto pitr = partiallist.begin(); pitr != partiallist.end(); ++pitr) {
2555  fulltext << "\n " << std::setw(10) << pitr->second << " " << pitr->first;
2556  }
2557 
2558  partiallist.clear();
2559  } // loop over user patterns
2560 
2561  size_t nfiles = fulllist.size();
2562 
2563  mf::LogInfo("GENIEHelper")
2564  << "ExpandFluxFilePatternsIFDH initially found " << nfiles << " files";
2565  mf::LogDebug("GENIEHelper")
2566  << fulltext.str();
2567 
2568  if ( nfiles == 0 ) {
2569  selectedtext << "\n expansion resulted in a null list for flux files";
2570  } else if ( ! randomizeFiles ) {
2571  // some sets of files should be left in order
2572  // and no size limitations imposed ... just copy the list
2573 
2574  selectedtext << "\n list of files will be processed in order";
2575  selectedlist.insert(selectedlist.end(),fulllist.begin(),fulllist.end());
2576 
2577  } else {
2578 
2579  // for list needing size based trimming and randomization ...
2580  // pull from the list randomly until a cummulative limit is reached
2581  // do this by assigning a random number to each;
2582  // ordering that list; and pulling in that order
2583 
2584  selectedtext << "list of " << nfiles
2585  << " will be randomized and pared down to "
2586  << fMaxFluxFileMB << " MB or "
2587  << fMaxFluxFileNumber << " files";
2588 
2589  double* order = new double[nfiles];
2590  int* indices = new int[nfiles];
2591  fHelperRandom->RndmArray(nfiles,order);
2592  // assign random # for their relative order
2593 
2594  TMath::Sort((int)nfiles,order,indices,false);
2595 
2596  long long int sumBytes = 0; // accumulated size in bytes
2597  long long int maxBytes = (long long int)fMaxFluxFileMB * 1024ll * 1024ll;
2598 
2599  for (size_t i=0; i < TMath::Min(nfiles,size_t(fMaxFluxFileNumber)); ++i) {
2600  int indx = indices[i];
2601  bool keep = true;
2602 
2603  auto p = fulllist[indx]; // this pair <name,size>
2604  sumBytes += p.second;
2605  // skip those that would push sum above total
2606  // but always accept at least one (the first)
2607  if ( sumBytes > maxBytes && i != 0 ) keep = false;
2608 
2609  selectedtext << "\n[" << setw(3) << i << "] "
2610  << "=> [" << setw(3) << indx << "] "
2611  << ((keep)?"keep":"SKIP") << " "
2612  << std::setw(6) << (sumBytes/(1024ll*1024ll)) << " MB "
2613  << p.first;
2614 
2615  if ( keep ) selectedlist.push_back(p);
2616  else break; // <voice name=Scotty> Captain, she can't take any more</voice>
2617 
2618  }
2619  delete [] order;
2620  delete [] indices;
2621  }
2622 
2623  mf::LogInfo("GENIEHelper")
2624  << selectedtext.str();
2625 
2626  // have a selected list of remote files
2627  // get paths to local copies
2628  #ifdef USE_IFDH_SERVICE
2629  locallist = ifdhp->fetchSharedFiles(selectedlist,fFluxCopyMethod);
2630  #else
2631  locallist = fIFDH->fetchSharedFiles(selectedlist,fFluxCopyMethod);
2632  #endif
2633 
2634  localtext << "final list of files:";
2635  size_t i=0;
2636  for (auto litr = locallist.begin(); litr != locallist.end(); ++litr, ++i) {
2637  fSelectedFluxFiles.push_back(litr->first);
2638  localtext << "\n\t[" << std::setw(3) << i << "]\t" << litr->first;
2639  }
2640 
2641  mf::LogInfo("GENIEHelper")
2642  << localtext.str();
2643 
2644  // no null path allowed for at least these
2645  if ( fFluxType.compare("numi") == 0 ||
2646  fFluxType.compare("simple") == 0 ||
2647  fFluxType.compare("dk2nu") == 0 ) {
2648  size_t nfiles = fSelectedFluxFiles.size();
2649  if ( nfiles == 0 ) {
2650  mf::LogError("GENIEHelper")
2651  << "For \"ntuple\" or \"simple_flux\", specification "
2652  << "must resolve to at least one file"
2653  << "\n none were found user pattern(s): "
2654  << patterntext.str()
2655  << "\n using FW_SEARCH_PATH of: "
2656  << spaths;
2657 
2658  throw cet::exception("NoFluxFiles")
2659  << "no flux files found for: " << patterntext.str();
2660 
2661  }
2662  }
2663 #endif // 'else' code only if NO_IFDH_LIB not defined
2664  } // ExpandFluxFilePatternsIFDH
2665 
2666  //---------------------------------------------------------
2668  {
2671 
2672  // priority order
2673  // (fcl file paths):(existing user environment):(FW_SEARCH_PATH)
2674  //
2675  // fcl parameters might be the explicit GXMLPATH value
2676  // or a pair in the fEnvironment vector
2677  // but the final "official result" should the fGXMLPATH
2678 
2679  // start with fGXMLPATH set from pset "GXMLPATH" value
2680 
2681  // find it in the vector, if it exists
2682  int indxGXMLPATH = -1;
2683  for (size_t i = 0; i < fEnvironment.size(); i += 2) {
2684  if ( fEnvironment[i].compare("GXMLPATH") == 0 ) {
2685  if ( fGXMLPATH != "" ) fGXMLPATH += ":";
2686  fGXMLPATH += fEnvironment[i+1];
2687  indxGXMLPATH = i;
2688  break;
2689  }
2690  }
2691 
2692  const char* gxmlpath_env = std::getenv("GXMLPATH");
2693  if ( gxmlpath_env ) {
2694  if ( fGXMLPATH != "" ) fGXMLPATH += ":";
2695  fGXMLPATH += gxmlpath_env;
2696  }
2697  const char* fwpath_env = std::getenv("FW_SEARCH_PATH");
2698  if ( fwpath_env ) {
2699  if ( fGXMLPATH != "" ) fGXMLPATH += ":";
2700  fGXMLPATH += fwpath_env;
2701  }
2702 
2703  // refresh fEnvironment (in case fEnvironment is still being used)
2704  if ( indxGXMLPATH < 0 ) {
2705  // nothing in fcl parameters
2706  indxGXMLPATH=fEnvironment.size();
2707  fEnvironment.push_back("GXMLPATH");
2708  fEnvironment.push_back(fGXMLPATH);
2709  } else {
2710  // update value
2711  fEnvironment[indxGXMLPATH+1] = fGXMLPATH;
2712  }
2713 
2714  // now set it externally for use by GENIE
2715  gSystem->Setenv("GXMLPATH",fGXMLPATH.c_str());
2716 
2717  }
2718 
2719  //---------------------------------------------------------
2721  {
2725 
2726  // start with GMSGLAYOUT set from pset "GMSGLAYOUT" value
2727 
2728  // find it in the vector, if it exists
2729  // this will override the top level fcl value
2730  for (size_t i = 0; i < fEnvironment.size(); i += 2) {
2731  if ( fEnvironment[i].compare("GMSGLAYOUT") == 0 ) {
2732  fGMSGLAYOUT = fEnvironment[i+1];
2733  break;
2734  }
2735  }
2736 
2737  // now set it externally, if we have a value
2738  if ( fGMSGLAYOUT != "" ) {
2739  gSystem->Setenv("GMSGLAYOUT",fGMSGLAYOUT.c_str());
2740  }
2741  }
2742 
2743  //---------------------------------------------------------
2744  void GENIEHelper::StartGENIEMessenger(std::string prodmodestr)
2745  {
2750 
2753 
2754  int indxGPRODMODE = -1;
2755  int indxGMSGCONF = -1;
2756 
2757  for (size_t i = 0; i < fEnvironment.size(); i += 2) {
2758  if ( fEnvironment[i].compare("GPRODMODE") == 0 ) {
2759  indxGPRODMODE = i;
2760  continue;
2761  }
2762  if ( fEnvironment[i].compare("GMSGCONF") == 0 ) {
2763  indxGMSGCONF = i;
2764  continue;
2765  }
2766  }
2767  // GMSGCONF set in fEnvironment tack it on to current setting
2768  if ( indxGMSGCONF >= 0 ) {
2769  if ( fGENIEMsgThresholds != "" ) fGENIEMsgThresholds += ":";
2770  fGENIEMsgThresholds += fEnvironment[indxGMSGCONF+1];
2771  } else {
2772  // nothing in fcl parameters, make a placeholder
2773  indxGMSGCONF = fEnvironment.size();
2774  fEnvironment.push_back("GMSGCONF");
2775  fEnvironment.push_back("");
2776  }
2777 
2778  bool prodmode = StringToBool(prodmodestr);
2779  if ( indxGPRODMODE >= 0 ) {
2780  // user tried to set GPRODMODE via Environment fcl values
2781  prodmode |= StringToBool(fEnvironment[indxGPRODMODE+1]);
2782  }
2783 
2784  if ( prodmode ) {
2785  // okay they really meant it
2786  // PREpend "Messenger_whisper.xml" to existing value
2787  // don't forget the colon if necessary
2788 #if __GENIE_RELEASE_CODE__ >= GRELCODE(2,9,0)
2789  std::string newval = "Messenger_whisper.xml";
2790 #else
2791  std::string newval = "Messenger_production.xml";
2792 #endif
2793  if ( fGENIEMsgThresholds != "" ) {
2794  newval += ":";
2795  newval += fGENIEMsgThresholds;
2796  }
2797  fGENIEMsgThresholds = newval;
2798  }
2799 
2800  // update fEnvironment value
2801  if ( indxGMSGCONF >= 0 ) {
2802  fEnvironment[indxGMSGCONF+1] = fGENIEMsgThresholds;
2803  }
2804 
2805  mf::LogInfo("GENIEHelper")
2806  << "StartGENIEMessenger ProdMode=" << ((prodmode)?"yes":"no")
2807  << " read from: " << fGENIEMsgThresholds;
2808 #ifndef GENIE_USE_ENVVAR
2809  genie::utils::app_init::MesgThresholds(fGENIEMsgThresholds);
2810 #else
2811  gSystem->Setenv("GMSGCONF",fGENIEMsgThresholds.c_str());
2812  if ( prodmode ) gSystem->Setenv("GPRODMODE","YES");
2813 #endif
2814 
2815  }
2816 
2817  //---------------------------------------------------------
2819  {
2821  // new location, fcl parameter "EventGeneratorList"
2822  // old location fEvironment key="GEVGL" (if unset by direct pset value)
2823  // if neither then use "Default"
2824 
2825  if ( fEventGeneratorList == "" ) {
2826  // find GEVGL in the vector, if it exists
2827  for (size_t i = 0; i < fEnvironment.size(); i += 2) {
2828  if ( fEnvironment[i].compare("GEVGL") == 0 ) {
2830  break;
2831  }
2832  }
2833  }
2834  if ( fEventGeneratorList == "" ) fEventGeneratorList = "Default";
2835 
2836  mf::LogInfo("GENIEHelper") << "GENIE EventGeneratorList using \""
2837  << fEventGeneratorList << "\"";
2838 #ifndef GENIE_USE_ENVVAR
2839  // just save it away because post R-2_8_0 this needs to get
2840  // passed to the GMCJDriver explicitly
2841 #else
2842  gSystem->Setenv("GEVGL",fEventGeneratorList.c_str());
2843 #endif
2844 
2845  }
2846 
2847  //---------------------------------------------------------
2849  {
2852 
2853  // priority order:
2854  // fcl fEnvironment GSPLOAD
2855  // fcl XSecTable
2856  // $GSPLOAD in environment
2857  // default 'gxspl-FNALsmall.xml'
2858 
2859  if ( fXSecTable == "" ) {
2860  // stand-alone value is not set
2861  const char* gspload_alt = std::getenv("GSPLOAD");
2862  if ( ! gspload_alt ) {
2863  const char* gspload_dflt = "gxspl-FNALsmall.xml"; // fall back
2864  gspload_alt = gspload_dflt;
2865  }
2866  fXSecTable = std::string(gspload_alt);
2867  }
2868 
2869  // find GSPLOAD in the vector, if it exists
2870  int indxGSPLOAD = -1;
2871  for (size_t i = 0; i < fEnvironment.size(); i += 2) {
2872  if ( fEnvironment[i].compare("GSPLOAD") == 0 ) {
2873  indxGSPLOAD = i;
2874  continue;
2875  }
2876  }
2877 
2878  if ( indxGSPLOAD < 0 ) {
2879  // nothing in fcl parameters
2880  indxGSPLOAD=fEnvironment.size();
2881  fEnvironment.push_back("GSPLOAD");
2882  fEnvironment.push_back(fXSecTable);
2883  } else {
2884  fXSecTable = fEnvironment[indxGSPLOAD+1]; // get two in sync
2885  }
2886 
2887  // currently GENIE doesn't internally use GXMLPATH when looking for
2888  // spline files, but instead wants a fully expanded path.
2889  // Do the expansion here using the extended GXMLPATH list
2890  // of locations (which included $FW_SEARCH_PATH)
2891  mf::LogDebug("GENIEHelper") << "GSPLOAD as originally: " << fXSecTable;
2892 
2893  // RWH cet::search_path returns "" if the input string is actually
2894  // the full path to the file .. this is not really what one wants,
2895  // one just wan't the full path to the file; seems to work if
2896  // "/" is made to be another possible PATH
2897  cet::search_path spGXML( "/:" + fGXMLPATH );
2898  std::string fullpath;
2899  spGXML.find_file(fXSecTable, fullpath);
2900 
2901  if ( fullpath == "" ) {
2902  mf::LogError("GENIEHelper")
2903  << "could not resolve full path for spline file XSecTable/GSPLOAD "
2904  << "\"" << fXSecTable << "\" using: "
2905  << fGXMLPATH;
2906  throw cet::exception("UnresolvedGSPLOAD")
2907  << "can't find XSecTable/GSPLOAD file: " << fXSecTable;
2908  }
2909  fXSecTable = fullpath;
2910  fEnvironment[indxGSPLOAD+1] = fXSecTable; // get two in sync
2911 
2912  mf::LogInfo("GENIEHelper")
2913  << "XSecTable/GSPLOAD full path \"" << fXSecTable << "\"";
2914 
2915 #ifndef GENIE_USE_ENVVAR
2916  TStopwatch xtime;
2917  xtime.Start();
2918 
2919  // can't use gSystem->Unsetenv() as it is really gSystem->Setenv(name,"")
2920  unsetenv("GSPLOAD"); // MUST!!! ensure that it isn't set externally
2921  genie::utils::app_init::XSecTable(fXSecTable,true);
2922 
2923  xtime.Stop();
2924  mf::LogInfo("GENIEHelper")
2925  << "Time to read GENIE XSecTable: "
2926  << " Real " << xtime.RealTime() << " s,"
2927  << " CPU " << xtime.CpuTime() << " s"
2928  << " from " << fXSecTable;
2929 #else
2930  // pre R-2_8_0 uses $GSPLOAD to indicate x-sec table
2931  gSystem->Setenv("GSPLOAD", fXSecTable.c_str());
2932 #endif
2933 
2934  }
2935 
2936  //---------------------------------------------------------
2937  bool GENIEHelper::StringToBool(std::string v)
2938  {
2939  if (v == "true") return true; // C++ style
2940  if (v == "false") return false;
2941  if (v == "kTRUE") return true; // ROOT style
2942  if (v == "kFALSE") return false;
2943  if (v == "TRUE") return true; // Some other reasonable variations...
2944  if (v == "FALSE") return false;
2945  if (v == "True") return true;
2946  if (v == "False") return false;
2947  if (v == "on") return true;
2948  if (v == "off") return false;
2949  if (v == "On") return true;
2950  if (v == "Off") return false;
2951  if (v == "ON") return true;
2952  if (v == "OFF") return false;
2953  if (v == "YES") return true;
2954  if (v == "NO") return false;
2955  if (v == "Yes") return true;
2956  if (v == "No") return false;
2957  if (v == "yes") return true;
2958  if (v == "no") return false;
2959  if (v == "1") return true;
2960  if (v == "0") return false;
2961 
2962  return false; // by default invalid strings are false
2963  }
2964 
2965 } // namespace evgb
2966 
double fgW
Definition: GTruth.h:48
Float_t x
Definition: compare.C:6
double E(const int i=0) const
Definition: MCParticle.h:237
int fGint
interaction code
Definition: GTruth.h:25
double fgenz
Definition: MCFlux.h:102
std::vector< std::string > fFluxFilePatterns
wildcard patterns files containing histograms or ntuples, or txt
Definition: GENIEHelper.h:136
int frun
Definition: MCFlux.h:35
static const int kNuTauBar
bool fUseHelperRndGen4GENIE
use fHelperRandom for gRandom during Sample()
Definition: GENIEHelper.h:129
double fgq2
Definition: GTruth.h:47
double fnenergy
Definition: MCFlux.h:40
double fEventsPerSpill
Definition: GENIEHelper.h:153
const simb::MCNeutrino & GetNeutrino() const
Definition: MCTruth.h:74
double ftgppy
Definition: MCFlux.h:86
double fgX
Definition: GTruth.h:50
int ftgtA
Definition: GTruth.h:58
double fpdpx
Definition: MCFlux.h:55
std::string fDetLocation
name of flux window location
Definition: GENIEHelper.h:149
double fAtmoEmax
atmo: Maximum energy of neutrinos in GeV
Definition: GENIEHelper.h:178
int fMaxFluxFileNumber
maximum # of flux files
Definition: GENIEHelper.h:139
double fMixerBaseline
baseline distance if genie flux can&#39;t calculate it
Definition: GENIEHelper.h:190
double ftpx
Definition: MCFlux.h:79
double fgeny
Definition: MCFlux.h:101
double ftprivy
Definition: MCFlux.h:89
Full flux simulation ntuple.
Definition: MCFlux.h:21
void SetOrigin(simb::Origin_t origin)
Definition: MCTruth.h:78
neutrino electron elastic scatter
Definition: MCNeutrino.h:144
int fppmedium
Definition: MCFlux.h:62
double fTotalHistFlux
total flux of neutrinos from flux histograms for used flavors
Definition: GENIEHelper.h:166
double fgen2vtx
distance from ray origin to event vtx
Definition: MCFlux.h:104
intermediate_table::iterator iterator
void PackSimpleFlux(simb::MCFlux &flux)
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
double fbeamx
Definition: MCFlux.h:91
ifdh_ns::ifdh * fIFDH
(optional) flux file handling
Definition: GENIEHelper.h:126
void FillMCFlux(genie::GFluxI *fdriver, simb::MCFlux &mcflux)
Definition: GENIE2ART.cxx:635
std::string fGXMLPATH
locations for GENIE XML files
Definition: GENIEHelper.h:185
double fbeampy
Definition: MCFlux.h:95
int ftptype
Definition: MCFlux.h:82
std::string fFiducialCut
configuration for geometry selector
Definition: GENIEHelper.h:191
void PackNuMIFlux(simb::MCFlux &flux)
Float_t y
Definition: compare.C:6
const simb::MCParticle & Nu() const
Definition: MCNeutrino.h:150
double fgenx
origin of ray from flux generator
Definition: MCFlux.h:100
bool Sample(simb::MCTruth &truth, simb::MCFlux &flux, simb::GTruth &gtruth)
simb::flux_code_ fFluxType
Definition: MCFlux.h:98
static const int kNuTau
unsigned int GetRandomNumberSeed()
Definition: evgenbase.h:22
double fRandomTimeOffset
additional random time shift (ns) added to every particle time
Definition: GENIEHelper.h:174
TVector3 fBeamCenter
center of beam for histogram fluxes - must be in meters
Definition: GENIEHelper.h:168
double fGlobalTimeOffset
overall time shift (ns) added to every particle time
Definition: GENIEHelper.h:173
int fNumNeutron
number of neutrons after reaction, before FSI
Definition: GTruth.h:40
std::string fSpillTimeConfig
alternative to flat spill distribution
Definition: GENIEHelper.h:175
double fvx
Definition: MCFlux.h:52
std::string fEventGeneratorList
control over event topologies, was $GEVGL [Default]
Definition: GENIEHelper.h:184
TGeoManager * fGeoManager
pointer to ROOT TGeoManager
Definition: GENIEHelper.h:116
double fnwtfar
Definition: MCFlux.h:48
static const int kNue
double TotalHistFlux()
int ftgtZ
Definition: GTruth.h:57
double fXsec
cross section of interaction
Definition: GTruth.h:32
void FindEventGeneratorList()
STL namespace.
Functions for transforming GENIE objects into ART objects (and back)
std::string fGENIEMsgThresholds
additional XML file setting Messager level thresholds (":" separated)
Definition: GENIEHelper.h:187
int fNumPiPlus
number of pi pluses after reaction, before FSI
Definition: GTruth.h:36
offset to account for adding in Nuance codes to this enum
Definition: MCNeutrino.h:99
int fNumPiMinus
number of pi minuses after reaction, before FSI
Definition: GTruth.h:37
double fppdxdz
Definition: MCFlux.h:58
std::vector< int > fGenFlavors
pdg codes for flavors to generate
Definition: GENIEHelper.h:176
void SetNeutrino(int CCNC, int mode, int interactionType, int target, int nucleon, int quark, double w, double x, double y, double qsqr)
Definition: MCTruth.cxx:30
int ftgen
Definition: MCFlux.h:83
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
evgb::EvtTimeShiftI * fTimeShifter
generator for time offset within a spill
Definition: GENIEHelper.h:130
double fdk2gen
distance from decay to ray origin
Definition: MCFlux.h:103
Definition: tf_graph.h:23
Particle class.
void Add(simb::MCParticle &part)
Definition: MCTruth.h:77
genie::GMCJDriver * fDriver
Definition: GENIEHelper.h:123
double fXSecMassPOT
product of cross section, mass and POT/spill for histogram fluxes
Definition: GENIEHelper.h:165
double ftprivx
Definition: MCFlux.h:88
void ExpandFluxFilePatternsDirect()
std::vector< std::string > fSelectedFluxFiles
flux files selected after wildcard expansion and subset selection
Definition: GENIEHelper.h:137
object containing MC flux information
genie::EventRecord * fGenieEventRecord
last generated event
Definition: GENIEHelper.h:119
TLorentzVector fProbeP4
Definition: GTruth.h:63
std::string fXSecTable
cross section file (was $GSPLOAD)
Definition: GENIEHelper.h:183
double fFluxUpstreamZ
z where flux starts from (if non-default, simple/ntuple only)
Definition: GENIEHelper.h:152
std::vector< TH1D * > fFluxHistograms
histograms for each nu species
Definition: GENIEHelper.h:150
Flux for positive horn focus.
Definition: MCFlux.h:18
double fndydzfar
Definition: MCFlux.h:46
int ftgptype
Definition: MCFlux.h:84
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
int fResNum
resonance number
Definition: GTruth.h:42
double fSurroundingMass
Definition: GENIEHelper.h:171
int fNumProton
number of protons after reaction, before FSI
Definition: GTruth.h:39
Double_t scale
Definition: plot.C:25
double fprobability
interaction probability
Definition: GTruth.h:31
double fnenergyf
Definition: MCFlux.h:47
void Reset()
Definition: MCFlux.cxx:94
double ftprivz
Definition: MCFlux.h:90
double fbeamz
Definition: MCFlux.h:93
double fnwtnear
Definition: MCFlux.h:44
intermediate_table::const_iterator const_iterator
int fptype
Definition: MCFlux.h:63
int fProbePDG
Definition: GTruth.h:62
double ftvx
Definition: MCFlux.h:76
int fGHepPrintLevel
GHepRecord::SetPrintLevel(), -1=no-print.
Definition: GENIEHelper.h:188
std::string fFluxRotCfg
how to interpret fFluxRotValues
Definition: GENIEHelper.h:143
TVector3 fBeamDirection
direction of the beam for histogram fluxes
Definition: GENIEHelper.h:167
std::string fBeamName
name of the beam we are simulating
Definition: GENIEHelper.h:142
std::string fWorldVolume
name of the world volume in the ROOT geometry
Definition: GENIEHelper.h:148
int fGscatter
neutrino scattering code
Definition: GTruth.h:26
int fndecay
Definition: MCFlux.h:50
double fndydz
Definition: MCFlux.h:38
int fnorig
Definition: MCFlux.h:49
void InitializeFluxDriver()
double fTotalExposure
pot used from flux ntuple
Definition: GENIEHelper.h:159
double fbeamy
Definition: MCFlux.h:92
double ftgppz
Definition: MCFlux.h:87
TRandom3 * fHelperRandom
random # generator for GENIEHelper
Definition: GENIEHelper.h:128
double fpdpz
Definition: MCFlux.h:57
int fNumPi0
number of pi0 after reaction, before FSI
Definition: GTruth.h:38
std::string fTopVolume
top volume in the ROOT geometry in which to generate events
Definition: GENIEHelper.h:147
TString part[npart]
Definition: Style.C:32
constexpr std::array< std::size_t, geo::vect::dimension< Vector >)> indices()
Returns a sequence of indices valid for a vector of the specified type.
virtual void PrintConfig(bool verbose=true)=0
provide a means of printing the configuration
bool fIsCharm
did the interaction produce a charmed hadron?
Definition: GTruth.h:41
double fmuparpz
Definition: MCFlux.h:69
double fweight
event interaction weight (genie internal)
Definition: GTruth.h:30
static const int kNuMuBar
double ftgppx
Definition: MCFlux.h:85
int fevtno
Definition: MCFlux.h:36
genie::GeomAnalyzerI * fGeomD
Definition: GENIEHelper.h:120
double fppdydz
Definition: MCFlux.h:59
double ftpz
Definition: MCFlux.h:81
double ftvy
Definition: MCFlux.h:77
std::string fFluxSearchPaths
colon separated set of path stems
Definition: GENIEHelper.h:135
Wrapper for generating neutrino interactions with GENIE.
std::string fGMSGLAYOUT
format for GENIE log message [BASIC]|SIMPLE (SIMPLE=no timestamps)
Definition: GENIEHelper.h:186
float bin[41]
Definition: plottest35.C:14
TLorentzVector fHitNucP4
Definition: GTruth.h:56
double fbeampz
Definition: MCFlux.h:96
double fndxdzfar
Definition: MCFlux.h:45
double fpdpy
Definition: MCFlux.h:56
double fBeamRadius
radius of cylindar for histogram fluxes - must be in meters
Definition: GENIEHelper.h:169
double fnpz
Definition: MCFlux.h:39
std::string fMixerConfig
configuration string for genie GFlavorMixerI
Definition: GENIEHelper.h:189
bool StringToBool(std::string v)
double fzpoint
Definition: MCFlux.h:75
genie::GFluxI * fFluxD
real flux driver
Definition: GENIEHelper.h:121
void StartGENIEMessenger(std::string prodmode)
double fvy
Definition: MCFlux.h:53
double fmupare
Definition: MCFlux.h:70
double fxpoint
Definition: MCFlux.h:73
void SetFluxGen(double nue, double nuebar, double numu, double numubar, double nutau, double nutaubar)
Definition: MCFlux.cxx:214
TFile ff[ntarg]
Definition: Style.C:26
double fndxdznea
Definition: MCFlux.h:41
double Vx(const int i=0) const
Definition: MCParticle.h:225
double weight
Definition: plottest35.C:25
double fMonoEnergy
energy of monoenergetic neutrinos
Definition: GENIEHelper.h:160
double fDetectorMass
mass of the detector in kg
Definition: GENIEHelper.h:170
std::vector< double > fFluxRotValues
parameters for rotation
Definition: GENIEHelper.h:144
void FillMCTruth(const genie::EventRecord *grec, double spillTime, simb::MCTruth &mctruth)
Definition: GENIE2ART.cxx:73
void PackGTruth(genie::EventRecord *record, simb::GTruth &truth)
n.b.: this group is similar but not quite, entirely unlike GENIE ScatteringType convention ...
Definition: MCNeutrino.h:84
void InitializeFiducialSelection()
std::string to_string(Flag_t< Storage > const flag)
Convert a flag into a stream (shows its index).
Definition: BitMask.h:187
double fppenergy
Definition: MCFlux.h:61
std::vector< std::string > fEnvironment
environmental variables and settings used by genie
Definition: GENIEHelper.h:182
int fntype
Definition: MCFlux.h:51
int ftgtPDG
PDG of Target Nucleus, nucleon only if free.
Definition: GTruth.h:59
double fgQ2
< these are for the internal (on shell) genie kinematics
Definition: GTruth.h:46
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
double fnecm
Definition: MCFlux.h:71
inverse muon decay
Definition: MCNeutrino.h:145
std::string fMaxPathOutInfo
output info if writing PathLengthList from GeomScan
Definition: GENIEHelper.h:193
double fSpillExposure
total exposure (i.e. pot) for this spill
Definition: GENIEHelper.h:158
A class for generating concrete EvtTimeShiftI derived classes based on the factory pattern...
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
TLorentzVector fFShadSystP4
Definition: GTruth.h:52
double fAtmoEmin
atmo: Minimum energy of neutrinos in GeV
Definition: GENIEHelper.h:177
static EvtTimeShiftFactory & Instance()
std::string fGeoFile
name of file containing the Geometry description
Definition: GENIEHelper.h:117
void InitializeRockBoxSelection()
double fAtmoRl
atmo: radius of the sphere on where the neutrinos are generated
Definition: GENIEHelper.h:179
double fndydznea
Definition: MCFlux.h:42
double fypoint
Definition: MCFlux.h:74
double fmuparpy
Definition: MCFlux.h:68
double fppvx
Definition: MCFlux.h:64
#define LOG_DEBUG(id)
double fpppz
Definition: MCFlux.h:60
double fppvy
Definition: MCFlux.h:65
void ExpandFluxFilePatternsIFDH()
unsigned int fDebugFlags
set bits to enable debug info
Definition: GENIEHelper.h:194
double fbeampx
Definition: MCFlux.h:94
double fppvz
Definition: MCFlux.h:66
virtual double TimeOffset()=0
double fgT
Definition: GTruth.h:49
Physics generators for neutrinos, cosmic rays, and others.
Definition: CRYHelper.cxx:33
std::string fFluxCopyMethod
"DIRECT" = old direct access method, otherwise = ifdh approach schema ("" okay)
Definition: GENIEHelper.h:140
double ftpy
Definition: MCFlux.h:80
void FillGTruth(const genie::EventRecord *grec, simb::GTruth &gtruth)
Definition: GENIE2ART.cxx:243
std::string fFluxCleanup
"ALWAYS", "/var/tmp", "NEVER"
Definition: GENIEHelper.h:141
double fndxdz
Definition: MCFlux.h:37
Event generator information.
Definition: MCTruth.h:30
double fvz
Definition: MCFlux.h:54
double fHistEventsPerSpill
number of events per spill for histogram fluxes - changes each spill
Definition: GENIEHelper.h:156
TRotation * fFluxRotation
rotation for atmos / astro flux coord systems
Definition: GENIEHelper.h:145
Float_t e
Definition: plot.C:34
std::string fGeomScan
configuration for geometry scan to determine max pathlengths
Definition: GENIEHelper.h:192
int fSpillEvents
total events for this spill
Definition: GENIEHelper.h:157
Float_t w
Definition: plot.C:23
bool fIsSeaQuark
Definition: GTruth.h:55
TLorentzVector fVertex
Definition: GTruth.h:64
genie::GFluxI * fFluxD2GMCJD
flux driver passed to genie GMCJDriver, might be GFluxBlender
Definition: GENIEHelper.h:122
double fgY
Definition: GTruth.h:51
double fDiffXsec
differential cross section of interaction
Definition: GTruth.h:33
static const int kNueBar
std::string fFunctionalFlux
Definition: GENIEHelper.h:161
double fmuparpx
Definition: MCFlux.h:67
int fMaxFluxFileMB
maximum size of flux files (MB)
Definition: GENIEHelper.h:138
static const int kNuMu
void PackMCTruth(genie::EventRecord *record, simb::MCTruth &truth)
double fPOTPerSpill
number of pot per spill
Definition: GENIEHelper.h:155
A simplified flux ntuple for quick running.
Definition: MCFlux.h:22
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
std::string fFluxType
Definition: GENIEHelper.h:132
GENIEHelper(fhicl::ParameterSet const &pset, TGeoManager *rootGeom, std::string const &rootFile, double const &detectorMass)
Beam neutrinos.
Definition: MCTruth.h:21
double fnenergyn
Definition: MCFlux.h:43
double ftvz
Definition: MCFlux.h:78
double fnimpwt
Definition: MCFlux.h:72
evgb::EvtTimeShiftI * GetEvtTimeShift(const std::string &name, const std::string &config="") const
vertex reconstruction