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