gFNALExptEvGen.cxx
Go to the documentation of this file.
1 //______________________________________________________________________________
2 /*!
3 
4 \program gevgen_fnal
5 
6 \brief A GENIE event generation driver `customized' for the FNAL neutrino
7  experiments using flux drivers for file types used by those expts.
8  This program was adapted from gevgen_t2k used at T2K.
9 
10  This driver can use either the FNAL-supported neutrino flux ntuples
11  (generated by gNuMI, g4numi, g4numi_flugg), or "dk2nu" format,
12  or plain flux histograms for all neutrino species you are considering.
13  You can specify either a ROOT-based detailed detector geometry
14  description or a simple target mix. See below for further details.
15 
16  Users should note that the generic GENIE event generation driver
17  (gevgen) may still be a more appropriate tool to use for the simpler
18  event generation casesrequired for many 4-vector level / systematic
19  studies.
20  Please see the GENIE documentation (http://www.genie-mc.org) and
21  contact me <constantinos.andreopoulos \at cern.ch> if in doubt.
22 
23  *** Synopsis :
24 
25  gevgen_fnal [-h]
26  [-r run#]
27  -f flux
28  -g geometry
29  [-t top_volume_name_at_geom || -t +Vol1-Vol2...]
30  [-m max_path_lengths_xml_file]
31  [-L length_units_at_geom]
32  [-D density_units_at_geom]
33  [-n n_of_events]
34  [-e exposure_in_POTs]
35  [-o output_event_file_prefix]
36  [-F fid_cut_string]
37  [-S nrays]
38  [-z zmin]
39  [-d debug flags]
40  [--seed random_number_seed]
41  --cross-sections xml_file
42  [--event-generator-list list_name]
43  [--tune genie_tune]
44  [--message-thresholds xml_file]
45  [--unphysical-event-mask mask]
46  [--event-record-print-level level]
47  [--mc-job-status-refresh-rate rate]
48  [--cache-file root_file]
49 
50  *** Options :
51 
52  [] Denotes an optional argument
53 
54  -h
55  Prints out the gevgen_fnal syntax and exits.
56  -r
57  Specifies the MC run number [default: 1000]
58  -g
59  Input 'geometry'.
60  This option can be used to specify any of:
61  1 > A ROOT file containing a ROOT/GEANT geometry description
62  [Examples]
63  - To use the master volume from the ROOT geometry stored
64  in the /some/path/nova-geom.root file, type:
65  '-g /some/path/nova-geom.root'
66  2 > A mix of target materials, each with its corresponding weight,
67  typed as a comma-separated list of nuclear PDG codes (in the
68  std PDG2006 convention: 10LZZZAAAI) with the weight fractions
69  in brackets, eg code1[fraction1],code2[fraction2],...
70  If that option is used (no detailed input geometry description)
71  then the interaction vertices are distributed in the detector
72  by the detector MC.
73  [Examples]
74  - To use a target mix of 95% O16 and 5% H type:
75  '-g 1000080160[0.95],1000010010[0.05]'
76  - To use a target which is 100% C12, type:
77  '-g 1000060120'
78  -t
79  Input 'top volume' for event generation -
80  can be used to force event generation in given sub-detector.
81  [default: the 'master volume' of the input geometry]
82  You can also use the -t option to switch generation on/off at
83  multiple volumes as, for example, in:
84  `-t +Vol1-Vol2+Vol3-Vol4',
85  `-t "+Vol1 -Vol2 +Vol3 -Vol4"',
86  `-t -Vol2-Vol4+Vol1+Vol3',
87  `-t "-Vol2 -Vol4 +Vol1 +Vol3"'m
88  where:
89  "+Vol1" and "+Vol3" tells GENIE to `switch on' Vol1 and Vol3, while
90  "-Vol2" and "-Vol4" tells GENIE to `switch off' Vol2 and Vol4.
91  If the very first character is a '+', GENIE will neglect all volumes
92  except the ones explicitly turned on. Vice versa, if the very first
93  character is a `-', GENIE will keep all volumes except the ones
94  explicitly turned off (feature contributed by J.Holeczek).
95  -m
96  An XML file (generated by gmxpl) with the max (density weighted)
97  path-lengths for each target material in the input ROOT geometry.
98  If no file is input, then the geometry will be scanned at MC job
99  initialization to determine those max path lengths.
100  Supplying this file can speed-up the MC job initialization.
101  -L
102  Input geometry length units, eg "m", "cm", "mm", ...
103  [default: mm]
104  -D
105  Input geometry density units, eg "g_cm3", "clhep_def_density_unit",...
106  [default: g_cm3]
107  -f
108  Input 'neutrino flux'.
109  This option can be used to specify any of:
110  1 > A g[4][numi|lbne][_flugg] beam simulation output file
111  and the detector location
112  The general sytax is:
113  -f /full/path/flux_file.root,detector,flavor1,flavor2...
114  [Notes]
115  - For more information on the flux ntuples, see the gNuMI doc.
116  - The original hbook ntuples need to be converted to a ROOT
117  format using the h2root ROOT utility.
118  - If flavors aren't specified then use default (12,-12,14,-14)
119  - See GNuMIFlux.xml or Dk2Nu.xml for all supported detector
120  locations
121  - The g[4][NuMI|LBNE][_flugg] flux ntuples are read via GENIE's
122  GNuMIFlux driver, and dk2nu file via an external
123  product w/ the GDk2NuFlux driver (if it can be found).
124  This customized GENIE event generation driver passes-through
125  the complete gNuMI input flux information (eg parent decay
126  kinematics / position etc) for each neutrino event it
127  generates (as an additional 'flux' branch is added on the
128  output event tree).
129  [Examples]
130  - To use the gNuMI flux ntuple flux.root at MINOS near
131  detector location, type:
132  '-f /path/flux.root,MINOS-NearDet'
133  1a> Similar to 1 above, but filename contains "dk2nu", then use
134  the GDk2NuFlux driver
135  1b> Similar to 1 above, but filename contains "gsimple", then
136  use GSimpleNtpFlux driver
137  2 > A set of histograms stored in a ROOT file.
138  The general syntax is:
139  -f /path/histogram_file.root,neutrino_code[histo_name],...
140  [Notes]
141  - The neutrino codes are the PDG ones.
142  - The 'neutrino_code[histogram_name]' part of the option can
143  be repeated multiple times (separated by commas), once for
144  each flux neutrino species you want to consider, eg
145  '-f somefile.root,12[nuehst],-12[nuebarhst],14[numuhst]'
146  - When using flux from histograms then there is no point in
147  using a 'detailed detector geometry description' as your
148  flux input contains no directional information for those
149  flux neutrinos.
150  The neutrino direction is conventionally set to be
151  +z {x=0,y=0}.
152  So, when using this option you must be using a simple
153  'target mix'
154  See the -g option for possible geometry settings.
155  If you want to use the detailed detector geometry
156  description then you should be using a driver that
157  supplies a detailed simulated beam flux.
158  - When using flux from histograms there is no branch with
159  neutrino parent information added in the output event
160  tree as your flux input contains no such information.
161  - Note that the relative normalization of the flux histograms
162  is taken into account and is reflected in the relative
163  frequency of flux neutrinos thrown by the flux driver
164  [Examples]
165  - To use the histogram 'h100' (representing the nu_mu flux)
166  and the histogram 'h300' (representing the nu_e flux) and
167  the histogram 'h301' (representing the nu_e_bar flux) from
168  the flux.root file in /path/ type:
169  '-f /path/flux.root,14[h100],12[h300],-12[h301]
170 
171  -e
172  Specifies how many POTs to generate.
173  -n
174  Specifies how many events to generate.
175 
176  -------
177  [Note on exposure / statistics]
178  Both -e and -n options can be used to set the exposure.
179  - If the input flux is a non-histogram driver then any of these
180  options can be used (one at a time).
181  - If the input flux is described with histograms then only the -n
182  option is available.
183  -------
184 
185  -F
186  Apply a fiducial cut (for now hard coded ... generalize)
187  Only used with ROOTGeomAnalyzer
188  if string starts with "-" then reverses sense (ie. anti-fiducial)
189  -S
190  Number of rays to use to scan geometry for max path length
191  Only used with ROOTGeomAnalyzer & { GNuMIFlux, GSimpleNtpFlux, GDk2NuFlux }
192  +N Use flux to scan geometry for max path length
193  -N Use N rays x N points on each face of a box
194  -z
195  Z from which to start flux ray in user world coordinates
196  Only use with ROOTGeomAnalyzer & { GNuMIFlux, GSimpleNtpFlux, GDk2NuFlux }
197  If left unset then flux originates on the flux window
198  [No longer attempts to determine z from geometry, generally
199  got this wrong]
200  -o
201  Sets the prefix of the output event file.
202  The output filename is built as:
203  [prefix].[run_number].[event_tree_format].[file_format]
204  The default output filename is:
205  gntp.[run_number].ghep.root
206  This cmd line arguments lets you override 'gntp'
207  --seed
208  Random number seed.
209  --cross-sections
210  Name (incl. full path) of an XML file with pre-computed
211  cross-section values used for constructing splines.
212  --tune
213  Specifies a GENIE comprehensive neutrino interaction model tune.
214  [default: "Default"].
215  --message-thresholds
216  Allows users to customize the message stream thresholds.
217  The thresholds are specified using an XML file.
218  See $GENIE/config/Messenger.xml for the XML schema.
219  --unphysical-event-mask
220  Allows users to specify a 16-bit mask to allow certain types of
221  unphysical events to be written in the output file.
222  [default: all unphysical events are rejected]
223  --event-record-print-level
224  Allows users to set the level of information shown when the event
225  record is printed in the screen. See GHepRecord::Print().
226  --mc-job-status-refresh-rate
227  Allows users to customize the refresh rate of the status file.
228  --cache-file
229  Allows users to specify a cache file so that the cache can be
230  re-used in subsequent MC jobs.
231 
232  *** Examples:
233 
234  (1) shell% gevgen_fnal
235  -r 1001
236  -f /data/mc_inputs/flux/flux_00001.root,MINOS-NearDet,12,-12
237  -g /data/mc_inputs/geom/minos.root
238  -L mm -D g_cm3
239  -e 5E+17
240  --cross-sections /data/xsec.xml
241 
242  Generate events (run number 1001) using the flux ntuple in
243  /data/mc_inputs/flux/v1/flux_00001.root
244  The job will load the MINOS near detector detector geometry
245  description from /data/mc_inputs/geom/minos.root and interpret it
246  using 'mm' as the length unit and 'g/cm^3' as the density unit.
247  The job will stop as it accumulates a sample corresponding to
248  5E+17 POT.
249  Pre-computed cross-section data are loaded from /data/xsec.xml
250 
251  (2) shell% gevgen_fnal
252  -r 1001
253  -f /data/t2k/flux/hst/flux.root,12[h100],-12[h101],14[h200]
254  -g 1000080160[0.95],1000010010[0.05]
255  -n 50000
256  --cross-sections /data/xsec.xml
257 
258  Please read the GENIE user manual for more information.
259 
260 \author Costas Andreopoulos <constantinos.andreopoulos \at cern.ch>
261  University of Liverpool & STFC Rutherford Appleton Laboratory
262 
263  Robert Hatcher <rhatcher \at fnal.gov>
264  Fermi National Accelerator Laboratory
265 
266 \created August 20, 2008
267 
268 \cpright Copyright (c) 2003-2020, The GENIE Collaboration
269  For the full text of the license visit http://copyright.genie-mc.org
270 
271 */
272 //_________________________________________________________________________________________
273 
274 #include <cassert>
275 #include <cstdlib>
276 #include <csignal>
277 
278 #include <string>
279 #include <sstream>
280 #include <vector>
281 #include <map>
282 #include <algorithm> // for transform()
283 #include <fstream>
284 
285 #include <TSystem.h>
286 #include <TError.h> // for gErrorIgnoreLevel
287 #include <TTree.h>
288 #include <TFile.h>
289 #include <TH1D.h>
290 #include <TMath.h>
291 #include <TGeoVolume.h>
292 #include <TGeoShape.h>
293 
309 #include "Framework/Utils/AppInit.h"
310 #include "Framework/Utils/RunOpt.h"
314 
315 #ifdef __GENIE_FLUX_DRIVERS_ENABLED__
320 
321 //#include "Tools/Flux/GNuMIFlux.h"
322 //#include "Tools/Flux/GSimpleNtpFlux.h"
323 // #ifdef __DK2NU_FLUX_DRIVER_AVAILABLE__
324 // #include "dk2nu/tree/dk2nu.h"
325 // #include "dk2nu/tree/dkmeta.h"
326 // #include "dk2nu/tree/NuChoice.h"
327 // #include "dk2nu/genie/GDk2NuFlux.h"
328 // #endif
329 
330 #endif
331 
332 #ifdef __GENIE_GEOM_DRIVERS_ENABLED__
333 #include "Tools/Geometry/GeoUtils.h"
338 #endif
339 
340 using std::string;
341 using std::vector;
342 using std::map;
343 using std::ostringstream;
344 
345 using namespace genie;
346 
347 // Forward function declarations
348 //
349 void LoadExtraOptions (void);
350 void GetCommandLineArgs (int argc, char ** argv);
351 void PrintSyntax (void);
352 void CreateFidSelection (string fidcut, GeomAnalyzerI* geom_driver);
353 void CreateRockBoxSelection (string fidcut, GeomAnalyzerI* geom_driver);
354 void DetermineFluxDriver(string fopt);
355 void ParseFluxHst (string fopt);
356 void ParseFluxFileConfig(string fopt);
357 
358 // Default options (override them using the command line arguments):
359 //
360 string kDefOptGeomLUnits = "mm"; // default geometry length units
361 string kDefOptGeomDUnits = "g_cm3"; // default geometry density units
362 NtpMCFormat_t kDefOptNtpFormat = kNFGHEP; // default event tree format
363 string kDefOptEvFilePrefix = "gntp";
364 
365 // User-specified options:
366 //
367 Long_t gOptRunNu; // run number
368 bool gOptUsingRootGeom = false; // using root geom or target mix?
369 bool gOptUsingHistFlux = false; // using beam flux ntuples or flux from histograms?
370 string gOptFluxDriver = ""; // flux driver class to use
371 map<string,string> gOptFluxShortNames;
372 PDGCodeList gOptFluxPdg; // list of neutrino flavors to accept
373 map<int,double> gOptTgtMix; // target mix (tgt pdg -> wght frac) / if not using detailed root geom
374 map<int,TH1D*> gOptFluxHst; // flux histos (nu pdg -> spectrum) / if not using beam sim ntuples
375 string gOptRootGeom; // input ROOT file with realistic detector geometry
376 string gOptRootGeomTopVol = ""; // input geometry top event generation volume
377 string gOptRootGeomMasterVol = ""; // (highest level of geometry)
378 double gOptGeomLUnits = 0; // input geometry length units
379 double gOptGeomDUnits = 0; // input geometry density units
380 string gOptExtMaxPlXml = ""; // max path lengths XML file for input geometry
381 bool gOptWriteMaxPlXml = false; // rather than read file, write the file
382  // triggered by leading '+' on given ofilename
383 string gOptFluxFile; // ROOT file with beam flux ntuple
384 string gOptDetectorLocation; // detector location (see GNuMIFlux.xml for supported locations))
385 int gOptNev; // number of events to generate
386 double gOptPOT; // exposure (in POT)
387 string gOptFidCut; // fiducial cut selection
388 int gOptNScan = 0; // # of geometry scan rays
389 double gOptZmin = -2.0e30; // starting z position [ if abs() < 1e30 ]
390 string gOptEvFilePrefix; // event file prefix
391 int gOptDebug = 0; // debug flags
392 long int gOptRanSeed; // random number seed
393 string gOptInpXSecFile; // cross-section splines
394 
395 bool gSigTERM = false; // was TERM signal sent?
396 
397 static void gsSIGTERMhandler(int /* s */)
398 {
399  gSigTERM = true;
400  std::cerr << "Caught SIGTERM" << std::endl;
401 }
402 
403 //____________________________________________________________________________
404 int main(int argc, char ** argv)
405 {
407  GetCommandLineArgs(argc,argv);
408 
409  if ( ! RunOpt::Instance()->Tune() ) {
410  LOG("gmkspl", pFATAL) << " No TuneId in RunOption";
411  exit(-1);
412  }
414 
415  // Initialization of random number generators, cross-section table,
416  // messenger thresholds, cache file
417  utils::app_init::MesgThresholds(RunOpt::Instance()->MesgThresholdFiles());
421 
422  // Set GHEP print level
423  int print_level = RunOpt::Instance()->EventRecordPrintLevel();
424  GHepRecord::SetPrintLevel(print_level);
425 
426  // *************************************************************************
427  // * Create / configure the geometry driver
428  // *************************************************************************
429  GeomAnalyzerI * geom_driver = 0;
430 
431  if(gOptUsingRootGeom) {
432  //
433  // *** Using a realistic root-based detector geometry description
434  //
435 
436  // creating & configuring a root geometry driver
439  TGeoVolume * topvol = rgeom->GetGeometry()->GetTopVolume();
440  if ( ! topvol ) {
441  LOG("gevgen_fnal", pFATAL) << "Null top ROOT geometry volume!";
442  exit(1);
443  }
444  // retrieve the master volume name
445  gOptRootGeomMasterVol = topvol->GetName();
446 
447  rgeom -> SetLengthUnits (gOptGeomLUnits);
448  rgeom -> SetDensityUnits (gOptGeomDUnits);
449  rgeom -> SetTopVolName (gOptRootGeomTopVol); // set user defined "topvol"
450 
451  // getting the bounding box dimensions along z so as to set the
452  // appropriate upstream generation surface for the NuMI flux driver
453 
454  // RWH 2010-07-16: do not try to automatically get zmin from geometry, rather
455  // by default let the flux start from the window. If the user wants to
456  // override this then they need to explicitly set a "zmin". Trying to use
457  // the geometry is fraught with problems in local vs. global coordinates and
458  // units where it can appear to work in some cases but it actually isn't really
459  // universally correct.
460  //was// TGeoShape * bounding_box = topvol->GetShape();
461  //was// bounding_box->GetAxisRange(3, zmin, zmax);
462  //was// zmin *= rgeom->LengthUnits();
463  //was// zmax *= rgeom->LengthUnits();
464 
465  // switch on/off volumes as requested
466  if ( (gOptRootGeomTopVol[0] == '+') || (gOptRootGeomTopVol[0] == '-') ) {
467  bool exhaust = (*gOptRootGeomTopVol.c_str() == '+');
469  }
470 
471  // casting to the GENIE geometry driver interface
472  geom_driver = dynamic_cast<GeomAnalyzerI *> (rgeom);
473 
474  // user specifid a fiducial volume cut ... parse that out
475  if ( gOptFidCut.find("rock") != std::string::npos )
477  else if ( gOptFidCut != "" ) CreateFidSelection(gOptFidCut,rgeom);
478 
479  }
480  else {
481  //
482  // *** Using a 'point' geometry with the specified target mix
483  // *** ( = a list of targets with their corresponding weight fraction)
484  //
485 
486  // creating & configuring a point geometry driver
488  new geometry::PointGeomAnalyzer(gOptTgtMix);
489  // casting to the GENIE geometry driver interface
490  geom_driver = dynamic_cast<GeomAnalyzerI *> (pgeom);
491  }
492 
493  // *************************************************************************
494  // * Create / configure the flux driver
495  // *************************************************************************
496  GFluxI * flux_driver =
498  if ( ! flux_driver ) {
499  // couldn't get the requested flux driver ?
500  std::ostringstream s;
501  s << "Known FluxDrivers:\n";
502  const std::vector<std::string>& known =
504  std::vector<std::string>::const_iterator itr = known.begin();
505  for ( ; itr != known.end(); ++itr ) s << " " << (*itr) << "\n";
506  LOG("gevgen_fnal", pFATAL)
507  << "Failed to get any flux driver from GFluxDriverFactory\n"
508  << "when using \"" << gOptFluxDriver << "\"\n" << s.str();
509  exit(1);
510  }
511 
512  if ( ! gOptUsingHistFlux ) {
513  genie::flux::GFluxFileConfigI* flux_file_config =
514  dynamic_cast<genie::flux::GFluxFileConfigI*>(flux_driver);
515  if ( ! flux_file_config ) {
516  LOG("gevgen_fnal", pFATAL)
517  << "Failed to get GFluxFileConfigI driver from GFluxDriverFactory\n"
518  << "when using \"" << gOptFluxDriver << "\"";
519  exit(1);
520  }
521 
522  //
523  // *** Using the detailed ntuple neutrino flux description
524  //
526  flux_file_config->SetUpstreamZ(gOptZmin); // was "zmin" from bounding_box
527  flux_file_config->SetNumOfCycles(0);
528 
529  if ( gOptFluxPdg.size() > 0 ) {
530  // user specified list of neutrino PDGs
531  flux_file_config->SetFluxParticles(gOptFluxPdg);
532  std::ostringstream s;
533  PDGCodeList::const_iterator itr = gOptFluxPdg.begin();
534  for ( ; itr != gOptFluxPdg.end(); ++itr) s << (*itr) << " ";
535  LOG("gevgen_fnal", pNOTICE)
536  << "Limiting to nu PDGs: " << s.str();
537  }
538  }
539  else {
540  //
541  // *** Using fluxes from histograms (for all specified neutrino species)
542  //
543  genie::flux::GCylindTH1Flux * hist_flux_driver =
544  dynamic_cast<genie::flux::GCylindTH1Flux*>(flux_driver);
545  if ( ! hist_flux_driver ) {
546  LOG("gevgen_fnal", pFATAL)
547  << "Failed to get GCylinderTH1Flux driver from GFluxDriverFactory\n"
548  << "when using " << gOptFluxDriver;
549  exit(1);
550  }
551 
552  // creating & configuring a generic GCylindTH1Flux flux driver
553  TVector3 bdir (0,0,1); // dir along +z
554  TVector3 bspot(0,0,0);
555 
556  hist_flux_driver->SetNuDirection (bdir);
557  hist_flux_driver->SetBeamSpot (bspot);
558  hist_flux_driver->SetTransverseRadius (-1);
559  map<int,TH1D*>::iterator it = gOptFluxHst.begin();
560  for( ; it != gOptFluxHst.end(); ++it) {
561  int pdg_code = it->first;
562  TH1D * spectrum = it->second;
563  hist_flux_driver->AddEnergySpectrum(pdg_code, spectrum);
564  // once the histogram has been added to the GCylindTH1Flux driver
565  // it is owned by the driver and it is up to the the driver
566  // to clean up (i.e. delete it).
567  // remove it from this map to avoid double deletion.
568  it->second = 0;
569  }
570  }
571 
572  // these might come in handy ... avoid repeated dynamic_cast<> calls
573  genie::flux::GFluxExposureI* fluxExposureI =
574  dynamic_cast<genie::flux::GFluxExposureI*>(flux_driver);
575  genie::flux::GFluxFileConfigI* fluxFileConfigI =
576  dynamic_cast<genie::flux::GFluxFileConfigI*>(flux_driver);
577 
578 
579  // *************************************************************************
580  // * Handle chicken/egg problem: geom analyzer vs. flux.
581  // * Need both at this point change geom scan defaults.
582  // *************************************************************************
584 
586  dynamic_cast<geometry::ROOTGeomAnalyzer *>(geom_driver);
587  if ( ! rgeom ) assert(0);
588 
589  rgeom -> SetDebugFlags(gOptDebug);
590 
591  // even if user doesn't specify gOptNScan configure to scan using flux
592  if ( gOptNScan >= 0 ) {
593  LOG("gevgen_fnal", pNOTICE)
594  << "Using ROOTGeomAnalyzer: geom scan using flux: nparticles=" << gOptNScan;
595  rgeom->SetScannerFlux(flux_driver);
596  if ( gOptNScan > 0 ) rgeom->SetScannerNParticles(gOptNScan);
597  } else {
598  int nabs = TMath::Abs(gOptNScan);
599  LOG("gevgen_fnal", pNOTICE)
600  << "Using ROOTGeomAnalyzer: geom scan using box: npoints=nrays=" << nabs;
601  rgeom->SetScannerNPoints(nabs);
602  rgeom->SetScannerNRays(nabs);
603  }
604  }
605 
606  // *************************************************************************
607  // * Create/configure the event generation driver
608  // *************************************************************************
609  GMCJDriver * mcj_driver = new GMCJDriver;
611  mcj_driver->UseFluxDriver(flux_driver);
612  mcj_driver->UseGeomAnalyzer(geom_driver);
613  if ( ( gOptExtMaxPlXml != "" ) && ! gOptWriteMaxPlXml ) {
614  mcj_driver->UseMaxPathLengths(gOptExtMaxPlXml);
615  }
616  mcj_driver->Configure();
617  mcj_driver->UseSplines();
618  mcj_driver->ForceSingleProbScale();
619 
620  if ( ( gOptExtMaxPlXml != "" ) && gOptWriteMaxPlXml ) {
622  dynamic_cast<geometry::ROOTGeomAnalyzer *>(geom_driver);
623  if ( rgeom ) {
624  const genie::PathLengthList& maxpath = rgeom->GetMaxPathLengths();
625  std::string maxplfile = gOptExtMaxPlXml;
626  maxpath.SaveAsXml(maxplfile);
627  // append extra info to file
628  std::ofstream mpfile(maxplfile.c_str(), std::ios_base::app);
629  mpfile
630  << std::endl
631  << "<!-- this file is only relevant for a setup compatible with:"
632  << std::endl
633  << "geom: " << gOptRootGeom << " top: \"" << gOptRootGeomTopVol << "\""
634  << std::endl
635  << "flux: " << gOptFluxFile
636  << std::endl
637  << "location: " << gOptDetectorLocation
638  << std::endl
639  << "fidcut: " << gOptFidCut
640  << std::endl
641  << "nscan: " << gOptNScan << " (0>= use flux, <0 use box |nscan| points/rays)"
642  << std::endl
643  << "zmin: " << gOptZmin << " (if |zmin| > 1e30, leave ray on flux window)"
644  << std::endl
645  << "-->"
646  << std::endl;
647  mpfile.close();
648  }
649  }
650 
651  // *************************************************************************
652  // * Prepare for writing the output event tree & status file
653  // *************************************************************************
654 
655  // Initialize an Ntuple Writer to save GHEP records into a TTree
658  ntpw.Initialize();
659 
660 
661  std::vector<TBranch*> extraBranches;
662  std::vector<std::string> branchNames;
663  std::vector<std::string> branchClassNames;
664  std::vector<void**> branchObjPointers;
665 
666  // Add custom branch(s) to the standard GENIE event tree so that
667  // info on the flux neutrino parent particle can be passed-through
668  if ( fluxFileConfigI ) {
669  fluxFileConfigI->GetBranchInfo(branchNames,branchClassNames,
670  branchObjPointers);
671  size_t nn = branchNames.size();
672  size_t nc = branchClassNames.size();
673  size_t np = branchObjPointers.size();
674  if ( nn != nc || nc != np ) {
675  LOG("gevgen_fnal", pERROR)
676  << "Inconsistent info back from \"" << gOptFluxDriver << "\" "
677  << "for branch info: " << nn << " " << nc << " " << np;
678  } else {
679  for (size_t ii = 0; ii < nn; ++ii) {
680  const char* bname = branchNames[ii].c_str();
681  const char* cname = branchClassNames[ii].c_str();
682  void**& optr = branchObjPointers[ii]; // note critical '&' !
683  if ( ! optr || ! *optr ) continue; // no pointer supplied, skip it
684  int split = 99; // 1
685  LOG("gevgen_fnal", pNOTICE)
686  << "Adding extra branch \"" << bname << "\" of type \""
687  << cname << "\" (" << optr << ") to output tree";
688  TBranch* bptr = ntpw.EventTree()->Branch(bname,cname,optr,32000,split);
689  extraBranches.push_back(bptr);
690 
691  if ( bptr ) {
692  // don't delete this !!! we're sharing
693  bptr->SetAutoDelete(false);
694  } else {
695  LOG("gevgen_fnal", pERROR)
696  << "FAILED to add extra branch \"" << bname << "\" of type \""
697  << cname << "\" to output tree";
698  }
699  } // loop over additions
700  } // same # of entries
701  } // of genie::flux::GFluxFileConfigI type
702 
703  // Create a MC job monitor for a periodically updated status file
704  GMCJMonitor mcjmonitor(gOptRunNu);
705  mcjmonitor.SetRefreshRate(RunOpt::Instance()->MCJobStatusRefreshRate());
706 
707  // *************************************************************************
708  // * Event generation loop
709  // *************************************************************************
710 
711  // define handler to allow signal to end job gracefully
712  signal(SIGTERM,gsSIGTERMhandler);
713 
714  int ievent = 0;
715  while ( ! gSigTERM )
716  {
717  LOG("gevgen_fnal", pINFO)
718  << " *** Generating event............ " << ievent;
719 
720  // In case the required statistics was expressed as 'number of events'
721  // then quit if that number has been generated
722  if ( ievent == gOptNev ) break;
723 
724  // In case the required statistics was expressed as 'number of POT'
725  // then exit the event loop if the requested POT has been generated.
726  if ( gOptPOT > 0 && fluxExposureI ) {
727  double fpot = fluxExposureI->GetTotalExposure(); // current POTs used
728  double psc = mcj_driver->GlobProbScale(); // interaction prob. scale
729  double pot = fpot / psc; // POTs for generated sample
730  if ( pot >= gOptPOT ) break;
731  }
732 
733  // Generate a single event using neutrinos coming from the specified flux
734  // and hitting the specified geometry or target mix
735  EventRecord * event = mcj_driver->GenerateEvent();
736 
737  // Check whether a null event was returned due to the flux driver reaching
738  // the end of the input flux ntuple - exit the event generation loop
739  if ( ! event && flux_driver->End() ) {
740  LOG("gevgen_fnal", pWARN)
741  << "** The flux driver read all the input flux entries: End()==true";
742  break;
743  }
744  if ( ! event ) {
745  LOG("gevgen_fnal", pERROR)
746  << "Got a null generated neutino event! Retrying ...";
747  continue;
748  }
749  if ( print_level >= 0 ) {
750  LOG("gevgen_fnal", pINFO)
751  << "Generated event: " << *event;
752  }
753  // A valid event was generated: flux info (parent decay/prod
754  // position/kinematics) for that simulated event should already
755  // be connected to the right output tree branch
756 
757  // Add event at the output ntuple, refresh the mc job monitor & clean-up
758  ntpw.AddEventRecord(ievent, event);
759  mcjmonitor.Update(ievent,event);
760  delete event;
761  ievent++;
762 
763  } //1
764 
765  // Copy metadata tree, if available
766  if ( fluxFileConfigI ) {
767  TTree* t1 = fluxFileConfigI->GetMetaDataTree();
768  if ( t1 ) {
769  size_t nmeta = t1->GetEntries();
770  TTree* t2 = (TTree*)t1->Clone(0);
771  for (size_t i = 0; i < nmeta; ++i) {
772  t1->GetEntry(i);
773  t2->Fill();
774  }
775  t2->Write();
776  }
777  }
778 
779  LOG("gevgen_fnal", pINFO)
780  << "The GENIE MC job is done generating events - Cleaning up & exiting...";
781 
782  // *************************************************************************
783  // * Print job statistics &
784  // * calculate normalization factor for the generated sample
785  // *************************************************************************
787  // POT normalization will only be calculated if event generation was based
788  // on beam simulation ntuples (not just histograms) & a detailed detector
789  // geometry description.
790  // Get nunber of flux neutrinos read-in by flux driver, number of flux
791  // neutrinos actually thrown to the event generation driver and number
792  // of neutrino interactions actually generated
793  long int nflx = 0;
794  long int nflx_evg = mcj_driver-> NFluxNeutrinos();
795  double fpot = 0;
796  const char* exposureUnits = "(unknown units)";
797  if ( fluxExposureI ) {
798  fpot = fluxExposureI->GetTotalExposure(); // POTs used so far
799  nflx = fluxExposureI->NFluxNeutrinos();
800  //genie::flux::Exposure_t etype = fluxExposureI->GetExposureType();
801  //exposureUnits = genie::flux::GFluxExposureI::AsString(etype);
802  exposureUnits = fluxExposureI->GetExposureUnits();
803  }
804  if ( fluxFileConfigI ) {
805  fluxFileConfigI->PrintConfig();
806  }
807  double psc = mcj_driver->GlobProbScale(); // interaction prob. scale
808  if ( psc <= 0.0 ) {
809  LOG("gevgen_fnal", pFATAL) << "MCJobDriver GlobalProbScale was " << psc;
810  }
811  double pot = fpot / psc; // POT for generated sample
812  long int nev = ievent;
813 
814  LOG("gevgen_fnal", pNOTICE)
815  << "\n >> Interaction probability scaling factor: " << psc
816  << "\n >> using: " << gOptFluxDriver
817  << "\n >> N of flux v read-in by flux driver: " << nflx
818  << "\n >> N of flux v thrown to event gen driver: " << nflx_evg
819  << "\n >> N of generated v interactions: " << nev
820  << "\n ** Normalization for generated sample: " << pot
821  << " " << exposureUnits << " * detector";
822 
823  ntpw.EventTree()->SetWeight(pot); // store POT
824 
825  }
826 
827  // *************************************************************************
828  // * Save & clean-up
829  // *************************************************************************
830 
831  // Save the generated event tree & close the output file
832  ntpw.Save();
833 
834  // Clean-up
835  delete geom_driver;
836  delete flux_driver;
837  delete mcj_driver;
838  // this list should only be histograms that have (for some reason)
839  // not been handed over to the GCylindTH1Flux driver.
840  map<int,TH1D*>::iterator it = gOptFluxHst.begin();
841  for( ; it != gOptFluxHst.end(); ++it) {
842  TH1D * spectrum = it->second;
843  if(spectrum) delete spectrum;
844  }
845  gOptFluxHst.clear();
846 
847  LOG("gevgen_fnal", pNOTICE) << "Done!";
848 
849  return 0;
850 }
851 
852 //____________________________________________________________________________
854 {
855  /// potentially load extra libraries that might extend the list of
856  /// potential flux drivers, and how to map short names to classes ...
857  // we really should at this point read some external file to get
858  // an expandable list of libraries ... but for now just hard code it
859 
860  vector<string> extraLibs;
861 
862  ///***** this part should come from reading an external file
863  /// placeholder file $GENIE/config/FluxDriverExpansion.xml
864 
865  extraLibs.push_back("libdk2nuTree");
866  extraLibs.push_back("libdk2nuGenie");
867 
868  // what one might expect to find at the beginning of -f <arg>
869 
870  gOptFluxShortNames["histo"] = "genie::flux::GCylindTH1Flux";
871  gOptFluxShortNames["hist"] = "genie::flux::GCylindTH1Flux";
872 
873  gOptFluxShortNames["simple"] = "genie::flux::GSimpleNtpFlux";
874  gOptFluxShortNames["numi"] = "genie::flux::GNuMIFlux";
875  gOptFluxShortNames["dk2nu"] = "genie::flux::GDk2NuFlux";
876 
877  ///******* done with fake "read"
878 
879  // see if there are any libraries to load
880  // just let ROOT do it ... check error code on return
881  // but tweak ROOT's ERROR message output so we don't see huge messages
882  // for failures
883  // gErrorIgnoreLevel to kError (from TError.h)
884 
885  Int_t prevErrorLevel = gErrorIgnoreLevel;
886  gErrorIgnoreLevel = kFatal;
887  for (size_t ilib=0; ilib < extraLibs.size(); ++ilib) {
888  // library names should be like libXYZZY without extension [e.g. .so]
889  // but with the leading "lib"
890  int loadStatus = gSystem->Load(extraLibs[ilib].c_str());
891  const char* statWords = "failed to load";
892  if ( loadStatus == 0 ) { statWords = "successfully loaded"; }
893  else if ( loadStatus == 1 ) { statWords = "already had loaded"; }
894  else if ( loadStatus == -1 ) { statWords = "couldn't find library"; }
895  else if ( loadStatus == -2 ) { statWords = "mismatched version"; }
896 
897  LOG("gevgen_fnal",pNOTICE)
898  << statWords << " (" << loadStatus << ") " << extraLibs[ilib];
899  }
900  // restore the ROOT error message level
901  gErrorIgnoreLevel = prevErrorLevel;
902 
903 }
904 
905 //____________________________________________________________________________
906 void GetCommandLineArgs(int argc, char ** argv)
907 {
908  LOG("gevgen_fnal", pINFO) << "Parsing command line arguments";
909 
910  // Common run options. Set defaults and read.
913 
914  // Parse run options for this app
915 
916  CmdLnArgParser parser(argc,argv);
917 
918  // help?
919  bool help = parser.OptionExists('h');
920  if(help) {
921  PrintSyntax();
922  exit(0);
923  }
924 
925  // run number:
926  if ( parser.OptionExists('r') ) {
927  LOG("gevgen_fnal", pDEBUG) << "Reading MC run number";
928  gOptRunNu = parser.ArgAsLong('r');
929  } else {
930  LOG("gevgen_fnal", pDEBUG)
931  << "Unspecified run number - Using default";
932  gOptRunNu = 0;
933  } //-r
934 
935  //
936  // *** geometry
937  //
938 
939  string geom = "";
940  string lunits, dunits;
941  if( parser.OptionExists('g') ) {
942  LOG("gevgen_fnal", pDEBUG) << "Getting input geometry";
943  geom = parser.ArgAsString('g');
944 
945  // is it a ROOT file that contains a ROOT geometry?
946  bool accessible_geom_file =
947  ! (gSystem->AccessPathName(geom.c_str()));
948  if (accessible_geom_file) {
949  gOptRootGeom = geom;
950  gOptUsingRootGeom = true;
951  }
952  } else {
953  LOG("gevgen_fnal", pFATAL)
954  << "No geometry option specified - Exiting";
955  PrintSyntax();
956  exit(1);
957  } //-g
958 
959  if(gOptUsingRootGeom) {
960  // using a ROOT geometry - get requested geometry units
961 
962  // legth units:
963  if( parser.OptionExists('L') ) {
964  LOG("gevgen_fnal", pDEBUG)
965  << "Checking for input geometry length units";
966  lunits = parser.ArgAsString('L');
967  } else {
968  LOG("gevgen_fnal", pDEBUG) << "Using default geometry length units";
969  lunits = kDefOptGeomLUnits;
970  } // -L
971  // density units:
972  if( parser.OptionExists('D') ) {
973  LOG("gevgen_fnal", pDEBUG)
974  << "Checking for input geometry density units";
975  dunits = parser.ArgAsString('D');
976  } else {
977  LOG("gevgen_fnal", pDEBUG) << "Using default geometry density units";
978  dunits = kDefOptGeomDUnits;
979  } // -D
982 
983  // check whether an event generation volume name has been
984  // specified -- default is the 'top volume'
985  if( parser.OptionExists('t') ) {
986  LOG("gevgen_fnal", pDEBUG) << "Checking for input volume name";
987  gOptRootGeomTopVol = parser.ArgAsString('t');
988  } else {
989  LOG("gevgen_fnal", pDEBUG) << "Using the <master volume>";
990  } // -t
991 
992  // check whether an XML file with the maximum (density weighted)
993  // path lengths for each detector material is specified -
994  // otherwise will compute the max path lengths at job init
995  // if passed name starts with '+', then compute max at job init, but write out the result
996  if ( parser.OptionExists('m') ) {
997  LOG("gevgen_fnal", pDEBUG)
998  << "Checking for maximum path lengths XML file";
999  gOptExtMaxPlXml = parser.ArgAsString('m');
1000  gOptWriteMaxPlXml = false;
1001  if ( gOptExtMaxPlXml[0] == '+' ) {
1002  gOptExtMaxPlXml = gOptExtMaxPlXml.substr(1,std::string::npos);
1003  gOptWriteMaxPlXml = true;
1004  LOG("gevgen_fnal", pINFO)
1005  << "Will write maximum path lengths XML file: " << gOptExtMaxPlXml;
1006  }
1007  } else {
1008  LOG("gevgen_fnal", pDEBUG)
1009  << "Will compute the maximum path lengths at job init";
1010  gOptExtMaxPlXml = "";
1011  } // -m
1012 
1013  // fidcut:
1014  if( parser.OptionExists('F') ) {
1015  LOG("gevgen_fnal", pDEBUG) << "Using Fiducial cut?";
1016  gOptFidCut = parser.ArgAsString('F');
1017  } else {
1018  LOG("gevgen_fnal", pDEBUG) << "No fiducial volume cut";
1019  gOptFidCut = "";
1020  } //-F
1021 
1022  if(!gOptUsingHistFlux) {
1023  // how to scan the geometry (if relevant)
1024  if( parser.OptionExists('S') ) {
1025  LOG("gevgen_fnal", pDEBUG) << "Reading requested geom scan count";
1026  gOptNScan = parser.ArgAsInt('S');
1027  } else {
1028  LOG("gevgen_fnal", pDEBUG) << "No geom scan count was requested";
1029  gOptNScan = 0;
1030  } //-S
1031 
1032  // z for flux rays to start
1033  if( parser.OptionExists('z') ) {
1034  LOG("gevgen_fnal", pDEBUG) << "Reading requested zmin";
1035  gOptZmin = parser.ArgAsDouble('z');
1036  } else {
1037  LOG("gevgen_fnal", pDEBUG) << "No zmin was requested";
1038  gOptZmin = -2.0e30; // < -1.0e30 ==> leave it on flux window
1039  } //-z
1040 
1041  // debug flags
1042  if ( parser.OptionExists('d') ) {
1043  LOG("gevgen_fnal", pDEBUG) << "Reading debug flag value";
1044  gOptDebug = parser.ArgAsInt('d');
1045  } else {
1046  LOG("gevgen_fnal", pDEBUG) << "Unspecified debug flags - Using default";
1047  gOptDebug = 0;
1048  } //-d
1049 
1050  } // root geom && gnumi flux
1051 
1052  } // using root geom?
1053 
1054  else {
1055  // User has specified a target mix.
1056  // Decode the list of target pdf codes & their corresponding weight fraction
1057  // (specified as 'pdg_code_1[fraction_1],pdg_code_2[fraction_2],...')
1058  // See documentation on top section of this file.
1059  //
1060  gOptTgtMix.clear();
1061  vector<string> tgtmix = utils::str::Split(geom,",");
1062  if(tgtmix.size()==1) {
1063  int pdg = atoi(tgtmix[0].c_str());
1064  double wgt = 1.0;
1065  gOptTgtMix.insert(map<int, double>::value_type(pdg, wgt));
1066  } else {
1067  vector<string>::const_iterator tgtmix_iter = tgtmix.begin();
1068  for( ; tgtmix_iter != tgtmix.end(); ++tgtmix_iter) {
1069  string tgt_with_wgt = *tgtmix_iter;
1070  string::size_type open_bracket = tgt_with_wgt.find("[");
1071  string::size_type close_bracket = tgt_with_wgt.find("]");
1072  if (open_bracket ==string::npos ||
1073  close_bracket==string::npos)
1074  {
1075  LOG("gevgen_fnal", pFATAL)
1076  << "You made an error in specifying the target mix";
1077  PrintSyntax();
1078  exit(1);
1079  }
1080  string::size_type ibeg = 0;
1081  string::size_type iend = open_bracket;
1082  string::size_type jbeg = open_bracket+1;
1083  string::size_type jend = close_bracket;
1084  int pdg = atoi(tgt_with_wgt.substr(ibeg,iend-ibeg).c_str());
1085  double wgt = atof(tgt_with_wgt.substr(jbeg,jend-jbeg).c_str());
1086  LOG("gevgen_fnal", pDEBUG)
1087  << "Adding to target mix: pdg = " << pdg << ", wgt = " << wgt;
1088  gOptTgtMix.insert(map<int, double>::value_type(pdg, wgt));
1089 
1090  }// tgtmix_iter
1091  } // >1 materials in mix
1092  } // using tgt mix?
1093 
1094  //
1095  // *** flux
1096  //
1097  if ( parser.OptionExists('f') ) {
1098  LOG("gevgen_fnal", pDEBUG) << "Getting input flux";
1099  DetermineFluxDriver(parser.ArgAsString('f'));
1100  } else {
1101  LOG("gevgen_fnal", pFATAL) << "No flux info was specified - Exiting";
1102  PrintSyntax();
1103  exit(1);
1104  }
1105 
1106  // number of events to generate
1107  if( parser.OptionExists('n') ) {
1108  LOG("gevgen_fnal", pDEBUG)
1109  << "Reading limit on number of events to generate";
1110  gOptNev = parser.ArgAsInt('n');
1111  } else {
1112  LOG("gevgen_fnal", pDEBUG)
1113  << "Will keep on generating events till the flux driver stops";
1114  gOptNev = -1;
1115  } //-n
1116 
1117  // statistics to generate in terms of POT
1118  if( parser.OptionExists('e') ) {
1119  LOG("gevgen_fnal", pDEBUG) << "Reading requested exposure in POT";
1120  gOptPOT = parser.ArgAsDouble('e');
1121  } else {
1122  LOG("gevgen_fnal", pDEBUG) << "No POT exposure was requested";
1123  gOptPOT = -1;
1124  } //-e
1125 
1126  // event file prefix
1127  if( parser.OptionExists('o') ) {
1128  LOG("gevgen_fnal", pDEBUG) << "Reading the event filename prefix";
1129  gOptEvFilePrefix = parser.ArgAsString('o');
1130  } else {
1131  LOG("gevgen_fnal", pDEBUG)
1132  << "Will set the default event filename prefix";
1134  } //-o
1135 
1136 
1137  // random number seed
1138  if( parser.OptionExists("seed") ) {
1139  LOG("gevgen_fnal", pINFO) << "Reading random number seed";
1140  gOptRanSeed = parser.ArgAsLong("seed");
1141  } else {
1142  LOG("gevgen_fnal", pINFO) << "Unspecified random number seed - Using default";
1143  gOptRanSeed = -1;
1144  }
1145 
1146  // input cross-section file
1147  if( parser.OptionExists("cross-sections") ) {
1148  LOG("gevgen_fnal", pINFO) << "Reading cross-section file";
1149  gOptInpXSecFile = parser.ArgAsString("cross-sections");
1150  } else {
1151  LOG("gevgen_fnal", pINFO) << "Unspecified cross-section file";
1152  gOptInpXSecFile = "";
1153  }
1154 
1155 
1156  //
1157  // >>> perform 'sanity' checks on command line arguments
1158  //
1159 
1160  // Tthe 'exposure' may be set either as:
1161  // - a number of POTs
1162  // - a number of generated events
1163  // Only one of those options can be set.
1164  if(!gOptUsingHistFlux) {
1165  int nset=0;
1166  if(gOptPOT > 0) nset++;
1167  if(gOptNev > 0) nset++;
1168  if(nset==0) {
1169  LOG("gevgen_fnal", pFATAL)
1170  << "** To use a gNuMI flux ntuple you need to specify an exposure, "
1171  << "either via the -e or -n options";
1172  PrintSyntax();
1173  exit(1);
1174  }
1175  if(nset>1) {
1176  LOG("gevgen_fnal", pFATAL)
1177  << "You can not specify more than one of the -e or -n options";
1178  PrintSyntax();
1179  exit(1);
1180  }
1181  }
1182  // If we use a flux histograms (not flux ntuples) then -currently- the
1183  // only way to control exposure is via a number of events
1184  if(gOptUsingHistFlux) {
1185  if(gOptNev < 0) {
1186  LOG("gevgen_fnal", pFATAL)
1187  << "If you're using flux from histograms you need to specify the -n option";
1188  PrintSyntax();
1189  exit(1);
1190  }
1191  }
1192  // If we don't use a detailed ROOT detector geometry (but just a target mix)
1193  // then don't accept POT as a way to control job statistics (not enough info
1194  // is passed in the target mix to compute POT & the calculation can be easily
1195  // done offline)
1196  if(!gOptUsingRootGeom) {
1197  if(gOptPOT > 0) {
1198  LOG("gevgen_fnal", pFATAL)
1199  << "You may not use the -e option without a detector geometry description";
1200  exit(1);
1201  }
1202  }
1203 
1204  //
1205  // >>> print the command line options
1206  //
1207 
1208  PDGLibrary * pdglib = PDGLibrary::Instance();
1209 
1210  ostringstream gminfo;
1211  if (gOptUsingRootGeom) {
1212  gminfo << "Using ROOT geometry - file = " << gOptRootGeom
1213  << ", top volume = "
1214  << ((gOptRootGeomTopVol.size()==0) ? "<master volume>" : gOptRootGeomTopVol)
1215  << ", max{PL} file = "
1216  << ((gOptExtMaxPlXml.size()==0) ? "<none>" : gOptExtMaxPlXml)
1217  << ", length units = " << lunits
1218  << ", density units = " << dunits;
1219  } else {
1220  gminfo << "Using target mix: ";
1222  for(iter = gOptTgtMix.begin(); iter != gOptTgtMix.end(); ++iter) {
1223  int pdg_code = iter->first;
1224  double wgt = iter->second;
1225  TParticlePDG * p = pdglib->Find(pdg_code);
1226  if(p) {
1227  string name = p->GetName();
1228  gminfo << "(" << name << ") -> " << 100*wgt << "% / ";
1229  }//p?
1230  }
1231  }
1232 
1233  ostringstream fluxinfo;
1234  if (gOptUsingHistFlux) {
1235  fluxinfo << "Using histograms: ";
1237  for(iter = gOptFluxHst.begin(); iter != gOptFluxHst.end(); ++iter) {
1238  int pdg_code = iter->first;
1239  TH1D * spectrum = iter->second;
1240  TParticlePDG * p = pdglib->Find(pdg_code);
1241  if(p) {
1242  string name = p->GetName();
1243  fluxinfo << "(" << name << ") -> " << spectrum->GetName() << " / ";
1244  }//p?
1245  }
1246  } else {
1247  fluxinfo << "Using " << gOptFluxDriver << " flux driver- "
1248  << "file = " << gOptFluxFile
1249  << ", location = " << gOptDetectorLocation;
1250  }
1251 
1252  ostringstream exposure;
1253  if(gOptPOT > 0)
1254  exposure << "Number of POTs = " << gOptPOT;
1255  if(gOptNev > 0)
1256  exposure << "Number of events = " << gOptNev;
1257 
1258 
1259  LOG("gevgen_fnal", pNOTICE)
1260  << "\n\n"
1261  << utils::print::PrintFramedMesg("FNAL expt. event generation job configuration");
1262 
1263  LOG("gevgen_fnal", pNOTICE)
1264  << "\n - Run number: " << gOptRunNu
1265  << "\n - Random number seed: " << gOptRanSeed
1266  << "\n - Using cross-section file: " << gOptInpXSecFile
1267  << "\n - Flux @ " << fluxinfo.str()
1268  << "\n - Geometry @ " << gminfo.str()
1269  << "\n - Exposure @ " << exposure.str();
1270 
1271  LOG("gevgen_fnal", pNOTICE) << *RunOpt::Instance();
1272 }
1273 //____________________________________________________________________________
1274 void PrintSyntax(void)
1275 {
1276  LOG("gevgen_fnal", pFATAL)
1277  << "\n **Syntax**"
1278  << "\n gevgen_fnal [-h] [-r run#]"
1279  << "\n -f flux -g geometry"
1280  << "\n [-t top_volume_name_at_geom] [-m max_path_lengths_xml_file]"
1281  << "\n [-L length_units_at_geom] [-D density_units_at_geom]"
1282  << "\n [-n n_of_events] [-e exposure_in_POTs]"
1283  << "\n [-o output_event_file_prefix]"
1284  << "\n [-F fid_cut_string] [-S nrays_scan]"
1285  << "\n [-z zmin_start]"
1286  << "\n [--seed random_number_seed]"
1287  << "\n --cross-sections xml_file"
1288  << "\n [--event-generator-list list_name]"
1289  << "\n [--message-thresholds xml_file]"
1290  << "\n [--unphysical-event-mask mask]"
1291  << "\n [--event-record-print-level level]"
1292  << "\n [--mc-job-status-refresh-rate rate]"
1293  << "\n [--cache-file root_file]"
1294  << "\n"
1295  << " Please also read the detailed documentation at "
1296  << "$GENIE/src/Apps/gFNALExptEvGen.cxx"
1297  << "\n";
1298 }
1299 //____________________________________________________________________________
1300 void CreateFidSelection (string fidcut, GeomAnalyzerI* geom_driver)
1301 {
1302  ///
1303  /// User defined fiducial volume cut
1304  /// [0][M]<SHAPE>:val1,val2,...
1305  /// "0" means reverse the cut (i.e. exclude the volume)
1306  /// "M" means the coordinates are given in the ROOT geometry
1307  /// "master" system and need to be transformed to "top vol" system
1308  /// <SHAPE> can be any of "zcyl" "box" "zpoly" "sphere"
1309  /// [each takes different # of args]
1310  /// This must be followed by a ":" and a list of values separated by punctuation
1311  /// (allowed separators: commas , parentheses () braces {} or brackets [] )
1312  /// Value mapping:
1313  /// zcyl:x0,y0,radius,zmin,zmax - cylinder along z at (x0,y0) capped at z's
1314  /// xcyl:y0,z0,radius,xmin,ymax - cylinder along x
1315  /// ycyl:x0,z0,radius,ymin,ymax - cylinder along y
1316  /// gcyl:{x0,y0,z0}{dx,dy,dz},radius,{plane1}{plane2} -- generic cylinder w/ arbitrary orientation and caps
1317  /// {planeX} = 4 values to define plane and orientation
1318  /// box:xmin,ymin,zmin,xmax,ymax,zmax - box w/ upper & lower extremes
1319  /// zpoly:nfaces,x0,y0,r_in,phi,zmin,zmax - nfaces sided polygon in x-y plane
1320  // sphere:x0,y0,z0,radius - sphere of fixed radius at (x0,y0,z0)
1321  /// Examples:
1322  /// 1) 0mbox:0,0,0.25,1,1,8.75
1323  /// exclude (i.e. reverse) a box in master coordinates w/ corners (0,0,0.25) (1,1,8.75)
1324  /// 2) mzpoly:6,(2,-1),1.75,0,{0.25,8.75}
1325  /// six sided polygon in x-y plane, centered at x,y=(2,-1) w/ inscribed radius 1.75
1326  /// no rotation (so first face is in y-z plane +r from center, i.e. hex sits on point)
1327  /// limited to the z range of {0.25,8.75} in the master ROOT geom coordinates
1328  /// 3) zcyl:(3,4),5.5,-2,10
1329  /// a cylinder oriented parallel to the z axis in the "top vol" coordinates
1330  /// at x,y=(3,4) with radius 5.5 and z range of {-2,10}
1331  ///
1332  geometry::ROOTGeomAnalyzer * rgeom =
1333  dynamic_cast<geometry::ROOTGeomAnalyzer *>(geom_driver);
1334  if ( ! rgeom ) {
1335  LOG("gevgen_fnal", pWARN)
1336  << "Can not create GeomVolSelectorFiduction,"
1337  << " geometry driver is not ROOTGeomAnalyzer";
1338  return;
1339  }
1340 
1341  LOG("gevgen_fnal", pNOTICE) << "-F " << fidcut;
1342 
1345 
1346  fidsel->SetRemoveEntries(true); // drop segments that won't be considered
1347 
1348  // convert string to lowercase
1349  std::transform(fidcut.begin(),fidcut.end(),fidcut.begin(),::tolower);
1350 
1351  vector<string> strtok = genie::utils::str::Split(fidcut,":");
1352  if ( strtok.size() != 2 ) {
1353  LOG("gevgen_fnal", pWARN)
1354  << "Can not create GeomVolSelectorFiduction,"
1355  << " no \":\" separating type from values. nsplit=" << strtok.size();
1356  for ( unsigned int i=0; i < strtok.size(); ++i )
1357  LOG("gevgen_fnal",pNOTICE)
1358  << "strtok[" << i << "] = \"" << strtok[i] << "\"";
1359  return;
1360  }
1361 
1362  // parse out optional "x" and "m"
1363  string stype = strtok[0];
1364  bool reverse = ( stype.find("0") != string::npos );
1365  bool master = ( stype.find("m") != string::npos ); // action after values are set
1366 
1367  // parse out values
1368  vector<double> vals;
1369  vector<string> valstrs = genie::utils::str::Split(strtok[1]," ,;(){}[]");
1370  vector<string>::const_iterator iter = valstrs.begin();
1371  for ( ; iter != valstrs.end(); ++iter ) {
1372  const string& valstr1 = *iter;
1373  if ( valstr1 != "" ) vals.push_back(atof(valstr1.c_str()));
1374  }
1375  size_t nvals = vals.size();
1376 
1377  std::cout << "ivals = [";
1378  for (unsigned int i=0; i < nvals; ++i) {
1379  if (i>0) cout << ",";
1380  std::cout << vals[i];
1381  }
1382  std::cout << "]" << std::endl;
1383 
1384  // std::vector elements are required to be adjacent so we can treat address as ptr
1385 
1386  if ( stype.find("zcyl") != string::npos ) {
1387  // cylinder along z direction at (x0,y0) radius zmin zmax
1388  if ( nvals < 5 )
1389  LOG("gevgen_fnal", pFATAL) << "MakeZCylinder needs 5 values, not " << nvals
1390  << " fidcut=\"" << fidcut << "\"";
1391  fidsel->MakeZCylinder(vals[0],vals[1],vals[2],vals[3],vals[4]);
1392 
1393  } else if ( stype.find("xcyl") != string::npos ) {
1394  // cylinder along x direction at (y0,z0) radius xmin xmax
1395  if ( nvals < 5 )
1396  LOG("gevgen_fnal", pFATAL) << "MakeXCylinder needs 5 values, not " << nvals
1397  << " fidcut=\"" << fidcut << "\"";
1398  fidsel->MakeXCylinder(vals[0],vals[1],vals[2],vals[3],vals[4]);
1399 
1400  } else if ( stype.find("ycyl") != string::npos ) {
1401  // cylinder along y direction at (x0,z0) radius ymin ymax
1402  if ( nvals < 5 )
1403  LOG("gevgen_fnal", pFATAL) << "MakeYCylinder needs 5 values, not " << nvals
1404  << " fidcut=\"" << fidcut << "\"";
1405  fidsel->MakeYCylinder(vals[0],vals[1],vals[2],vals[3],vals[4]);
1406 
1407  } else if ( stype.find("gcyl") != string::npos ) {
1408  // cylinder along arbitrary direction at (x0,y0,z0) radius {plane1} {plane2}
1409  if ( nvals < 14 )
1410  LOG("gevgen_fnal", pFATAL) << "MakeYCylinder needs 14 values, not " << nvals
1411  << " fidcut=\"" << fidcut << "\"";
1412  Double_t base[3] = { vals[0], vals[1], vals[2] };
1413  Double_t axis[3] = { vals[3], vals[4], vals[5] };
1414  Double_t radius = vals[6];
1415  Double_t cap1[4] = { vals[ 7], vals[ 8], vals[ 9], vals[10] };
1416  Double_t cap2[4] = { vals[11], vals[12], vals[13], vals[14] };
1417 
1418  fidsel->MakeCylinder(base,axis,radius,cap1,cap2);
1419 
1420  } else if ( stype.find("box") != string::npos ) {
1421  // box (xmin,ymin,zmin) (xmax,ymax,zmax)
1422  if ( nvals < 6 )
1423  LOG("gevgen_fnal", pFATAL) << "MakeBox needs 6 values, not " << nvals
1424  << " fidcut=\"" << fidcut << "\"";
1425  double xyzmin[3] = { vals[0], vals[1], vals[2] };
1426  double xyzmax[3] = { vals[3], vals[4], vals[5] };
1427  fidsel->MakeBox(xyzmin,xyzmax);
1428 
1429  } else if ( stype.find("zpoly") != string::npos ) {
1430  // polygon along z direction nfaces at (x0,y0) radius phi zmin zmax
1431  if ( nvals < 7 )
1432  LOG("gevgen_fnal", pFATAL) << "MakeZPolygon needs 7 values, not " << nvals
1433  << " fidcut=\"" << fidcut << "\"";
1434  int nfaces = (int)vals[0];
1435  if ( nfaces < 3 )
1436  LOG("gevgen_fnal", pFATAL) << "MakeZPolygon needs nfaces>=3, not " << nfaces
1437  << " fidcut=\"" << fidcut << "\"";
1438  fidsel->MakeZPolygon(nfaces,vals[1],vals[2],vals[3],vals[4],vals[5],vals[6]);
1439 
1440  } else if ( stype.find("sphere") != string::npos ) {
1441  // sphere at (x0,y0,z0) radius
1442  if ( nvals < 4 )
1443  LOG("gevgen_fnal", pFATAL) << "MakeZSphere needs 4 values, not " << nvals
1444  << " fidcut=\"" << fidcut << "\"";
1445  fidsel->MakeSphere(vals[0],vals[1],vals[2],vals[3]);
1446 
1447  } else {
1448  LOG("gevgen_fnal", pFATAL)
1449  << "Can not create GeomVolSelectorFiduction for shape \"" << stype << "\"";
1450  }
1451 
1452  if ( master ) {
1453  fidsel->ConvertShapeMaster2Top(rgeom);
1454  LOG("gevgen_fnal", pNOTICE) << "Convert fiducial volume from master to topvol coords";
1455  }
1456  if ( reverse ) {
1457  fidsel->SetReverseFiducial(true);
1458  LOG("gevgen_fnal", pNOTICE) << "Reverse sense of fiducial volume cut";
1459  }
1460  rgeom->AdoptGeomVolSelector(fidsel);
1461 
1462 }
1463 //____________________________________________________________________________
1464 void CreateRockBoxSelection (string fidcut, GeomAnalyzerI* geom_driver)
1465 {
1466 
1467  if( fidcut.find_first_not_of(" \t\n") != 0) // trim any leading whitespace
1468  fidcut.erase( 0, fidcut.find_first_not_of(" \t\n") );
1469 
1470  // convert string to lowercase
1471  std::transform(fidcut.begin(),fidcut.end(),fidcut.begin(),::tolower);
1472 
1474  dynamic_cast<genie::geometry::ROOTGeomAnalyzer *>(geom_driver);
1475  if ( ! rgeom ) {
1476  LOG("gevgen_fnal", pWARN)
1477  << "Can not create GeomVolSelectorRockBox,"
1478  << " geometry driver is not ROOTGeomAnalyzer";
1479  return;
1480  }
1481 
1482  LOG("gevgen_fnal", pWARN) << "fiducial (rock) cut: " << fidcut;
1483 
1484  // for now, only fiducial no "rock box"
1487 
1488  vector<string> strtok = genie::utils::str::Split(fidcut,":");
1489  if ( strtok.size() != 2 ) {
1490  LOG("gevgen_fnal", pWARN)
1491  << "Can not create GeomVolSelectorRockBox,"
1492  << " no \":\" separating type from values. nsplit=" << strtok.size();
1493  for ( unsigned int i=0; i < strtok.size(); ++i )
1494  LOG("gevgen_fnal", pWARN)
1495  << "strtok[" << i << "] = \"" << strtok[i] << "\"";
1496  return;
1497  }
1498 
1499  string stype = strtok[0];
1500 
1501  // parse out values
1502  vector<double> vals;
1503  vector<string> valstrs = genie::utils::str::Split(strtok[1]," ,;(){}[]\t\n\r");
1504  vector<string>::const_iterator iter = valstrs.begin();
1505  for ( ; iter != valstrs.end(); ++iter ) {
1506  const string& valstr1 = *iter;
1507  if ( valstr1 != "" ) {
1508  double aval = atof(valstr1.c_str());
1509  LOG("gevgen_fnal", pWARN) << "rock value [" << vals.size() << "] "
1510  << aval;
1511  vals.push_back(aval);
1512  }
1513  }
1514  size_t nvals = vals.size();
1515 
1516  rocksel->SetRemoveEntries(true); // drop segments that won't be considered
1517 
1518  // assume coordinates are in the *master* (not "top volume") system
1519  // need to set fTopVolume to fWorldVolume
1520  //fTopVolume = fWorldVolume;
1521  //rgeom->SetTopVolName(fTopVolume.c_str());
1523  rgeom->SetTopVolName(gOptRootGeomMasterVol);
1524 
1525  if ( nvals < 6 ) {
1526  LOG("gevgen_fnal", pFATAL) << "rockbox needs at "
1527  << "least 6 values, found "
1528  << nvals << "in \""
1529  << strtok[1] << "\"";
1530  exit(1);
1531 
1532  }
1533  double xyzmin[3] = { vals[0], vals[1], vals[2] };
1534  double xyzmax[3] = { vals[3], vals[4], vals[5] };
1535 
1536  bool rockonly = true;
1537  double wallmin = 800.; // geometry in cm, ( 8 meter buffer)
1538  double dedx = 2.5 * 1.7e-3; // GeV/cm, rho=2.5, 1.7e-3 ~ rock like loss
1539  double fudge = 1.05;
1540 
1541  if ( nvals >= 7 ) rockonly = vals[6];
1542  if ( nvals >= 8 ) wallmin = vals[7];
1543  if ( nvals >= 9 ) dedx = vals[8];
1544  if ( nvals >= 10 ) fudge = vals[9];
1545 
1546  rocksel->SetRockBoxMinimal(xyzmin,xyzmax);
1547  rocksel->SetMinimumWall(wallmin);
1548  rocksel->SetDeDx(dedx/fudge);
1549 
1550  if ( nvals >= 11 ) rocksel->SetExpandFromInclusion((int)vals[10]);
1551 
1552  // if not rock-only then make a tiny exclusion bubble
1553  // call to MakeBox shouldn't be necessary
1554  // should be done by SetRockBoxMinimal but for some GENIE versions isn't
1555  if ( ! rockonly ) rocksel->MakeSphere(0,0,0,1.0e-10);
1556  else rocksel->MakeBox(xyzmin,xyzmax);
1557 
1558  rgeom->AdoptGeomVolSelector(rocksel);
1559 
1560 }
1561 
1562 //____________________________________________________________________________
1563 void DetermineFluxDriver(string fopt)
1564 {
1565  // based on the -f option string determine which flux driver to use
1566  // this may take some guessing
1567 
1568  // first look for strings that look like "<proto>:..."
1569  // or ....<proto>.root,....
1570  // where "<proto>" is a key the gOptFluxShortNames map
1571 
1572  map<string,string>::const_iterator mitr = gOptFluxShortNames.begin();
1573  map<string,string>::const_iterator mitr_end = gOptFluxShortNames.end();
1574  for ( ; mitr != mitr_end; ++mitr ) {
1575  string proto = mitr->first + string(":");
1576  string gproto = string("g") + proto;
1577  string protor = proto + ".root,";
1578  string full = mitr->second;
1579  if ( fopt.find(proto) == 0 ) {
1580  fopt.erase(0,proto.size());
1581  gOptFluxDriver = full;
1582  break;
1583  } else if ( fopt.find(gproto) == 0 ) {
1584  fopt.erase(0,gproto.size());
1585  gOptFluxDriver = full;
1586  break;
1587  } else if ( fopt.find(protor) != std::string::npos ) {
1588  gOptFluxDriver = full;
1589  break;
1590  }
1591  }
1592  // tested all cases where user might have specified explicitly
1593  // or been part of an extended file extension
1594  // this is where it gets messy
1595  if ( gOptFluxDriver == "" ) {
1596 
1597  // not specified ? guess from file name itself
1598  if ( fopt.find("gsimple") != std::string::npos ) {
1599  // put dk2nu after gsimple in case simple files are derived from dk2nu
1600  // then both are in name we should choose gsimple
1601  gOptFluxDriver = "genie::flux::GSimpleNtpFlux";
1602  } else if ( fopt.find("dk2nu") != std::string::npos ) {
1603  gOptFluxDriver = "genie::flux::GDk2NuFlux";
1604  } else {
1605  // does it look like the histogram format
1606  const char* hstrings[] = { ",12[", ",+12[", ",-12[",
1607  ",14[", ",+14[", ",-14[",
1608  ",16[", ",+16[", ",-16[" };
1609  size_t nh = sizeof(hstrings)/sizeof(const char*);
1610  for (size_t ih=0; ih<nh; ++ih) {
1611  if ( fopt.find(hstrings[ih]) != std::string::npos ) {
1612  // hey!
1613  gOptFluxDriver = "genie::flux::GCylindTH1Flux";
1614  break;
1615  }
1616  } // loop over possible histogram specifiers
1617  }
1618 
1619  // fall through default ... hope it works
1620  if ( gOptFluxDriver == "" ) {
1621  gOptFluxDriver = "genie::flux::GNuMIFlux";
1622  }
1623  }
1624 
1625  gOptUsingHistFlux = ( gOptFluxDriver == "genie::flux::GCylindTH1Flux" );
1626  if ( gOptUsingHistFlux ) ParseFluxHst(fopt);
1627  else ParseFluxFileConfig(fopt);
1628 }
1629 //____________________________________________________________________________
1630 void ParseFluxHst(string flux)
1631 {
1632  // Using flux from histograms
1633  // Extract the root file name & the list of histogram names & neutrino
1634  // species (specified as 'filename,histo1[species1],histo2[species2],...')
1635  // See documentation on top section of this file.
1636  //
1637 
1638  vector<string> fluxv = utils::str::Split(flux,",");
1639  if(fluxv.size()<2) {
1640  LOG("gevgen_fnal", pFATAL)
1641  << "You need to specify both a flux ntuple ROOT file "
1642  << " _AND_ a detector location";
1643  PrintSyntax();
1644  exit(1);
1645  }
1646  gOptFluxFile = fluxv[0];
1647  bool accessible_flux_file = !(gSystem->AccessPathName(gOptFluxFile.c_str()));
1648  if (!accessible_flux_file) {
1649  LOG("gevgen_fnal", pFATAL)
1650  << "Can not access flux file: " << gOptFluxFile;
1651  PrintSyntax();
1652  exit(1);
1653  }
1654  // Extract energy spectra for all specified neutrino species
1655  TFile flux_file(gOptFluxFile.c_str(), "read");
1656  for(unsigned int inu=1; inu<fluxv.size(); inu++) {
1657  string nutype_and_histo = fluxv[inu];
1658  string::size_type open_bracket = nutype_and_histo.find("[");
1659  string::size_type close_bracket = nutype_and_histo.find("]");
1660  if (open_bracket ==string::npos ||
1661  close_bracket==string::npos)
1662  {
1663  LOG("gevgen_fnal", pFATAL)
1664  << "You made an error in specifying the flux histograms";
1665  PrintSyntax();
1666  exit(1);
1667  }
1668  string::size_type ibeg = 0;
1669  string::size_type iend = open_bracket;
1670  string::size_type jbeg = open_bracket+1;
1671  string::size_type jend = close_bracket;
1672  string nutype = nutype_and_histo.substr(ibeg,iend-ibeg);
1673  string histo = nutype_and_histo.substr(jbeg,jend-jbeg);
1674  // access specified histogram from the input root file
1675  TH1D * ihst = (TH1D*) flux_file.Get(histo.c_str());
1676  if(!ihst) {
1677  LOG("gevgen_fnal", pFATAL)
1678  << "Can not find histogram: " << histo
1679  << " in flux file: " << gOptFluxFile;
1680  PrintSyntax();
1681  exit(1);
1682  }
1683 
1684  // Copy in the flux histogram from the root file
1685  // use Clone rather than assuming fix bin widths and rebooking
1686  TH1D* spectrum = (TH1D*)ihst->Clone();
1687  spectrum->SetNameTitle("spectrum","neutrino_flux");
1688  spectrum->SetDirectory(0);
1689  //// and remove bins outside the emin,emax range (not for gFNALExptEvGen)
1690  //for(int ibin = 1; ibin <= hst->GetNbinsX(); ibin++) {
1691  // if(hst->GetBinLowEdge(ibin) + hst->GetBinWidth(ibin) > emax ||
1692  // hst->GetBinLowEdge(ibin) < emin) {
1693  // spectrum->SetBinContent(ibin, 0);
1694  // }
1695  //}
1696 
1697  // get rid of original
1698  delete ihst;
1699 
1700  // convert neutrino name -> pdg code
1701  int pdg = atoi(nutype.c_str());
1702  if(!pdg::IsNeutrino(pdg) && !pdg::IsAntiNeutrino(pdg)) {
1703  LOG("gevgen_fnal", pFATAL)
1704  << "Unknown neutrino type: " << nutype;
1705  PrintSyntax();
1706  exit(1);
1707  }
1708  // store flux neutrino code / energy spectrum
1709  LOG("gevgen_fnal", pDEBUG)
1710  << "Adding energy spectrum for flux neutrino: pdg = " << pdg;
1711  gOptFluxHst.insert(map<int, TH1D*>::value_type(pdg, spectrum));
1712  }//inu
1713 
1714  if(gOptFluxHst.size()<1) {
1715  LOG("gevgen_fnal", pFATAL)
1716  << "You have not specified any flux histogram!";
1717  PrintSyntax();
1718  exit(1);
1719  }
1720 
1721  flux_file.Close();
1722 }
1723 
1724 //____________________________________________________________________________
1725 void ParseFluxFileConfig(string flux)
1726 {
1727  // Using gnumi/gsimple/dk2nu beam flux ntuples
1728  // Extract beam flux (root) file name & detector location
1729  //
1730  vector<string> fluxv = utils::str::Split(flux,",");
1731  if(fluxv.size()<2) {
1732  LOG("gevgen_fnal", pFATAL)
1733  << "You need to specify both a flux ntuple ROOT file "
1734  << " _AND_ a detector location";
1735  PrintSyntax();
1736  exit(1);
1737  }
1738  gOptFluxFile = fluxv[0];
1739  gOptDetectorLocation = fluxv[1];
1740 
1741  for ( size_t j = 2; j < fluxv.size(); ++j ) {
1742  int ipdg = atoi(fluxv[j].c_str());
1743  gOptFluxPdg.push_back(ipdg);
1744  }
1745 
1746 }
1747 
1748 //____________________________________________________________________________
static QCString name
Definition: declinfo.cpp:673
string gOptFluxFile
void MakeSphere(Double_t x0, Double_t y0, Double_t z0, Double_t radius)
void RandGen(long int seed)
Definition: AppInit.cxx:30
intermediate_table::iterator iterator
static void SetPrintLevel(int print_level)
Definition: GHepRecord.cxx:948
const char * GetExposureUnits() const
what units are returned by GetTotalExposure?
GENIE Interface for user-defined volume selector functors Trim path segments based on the intersectio...
void XSecTable(string inpfile, bool require_table)
Definition: AppInit.cxx:38
virtual GeomVolSelectorI * AdoptGeomVolSelector(GeomVolSelectorI *selector)
configure processing to perform path segment trimming
long ArgAsLong(char opt)
PDGCodeList gOptFluxPdg
double ArgAsDouble(char opt)
void ParseFluxFileConfig(string fopt)
string kDefOptEvFilePrefix
virtual void LoadBeamSimData(const std::vector< std::string > &filenames, const std::string &det_loc)=0
bool IsNeutrino(int pdgc)
Definition: PDGUtils.cxx:107
string ArgAsString(char opt)
THE MAIN GENIE PROJECT NAMESPACE
Definition: AlgCmp.h:25
#define pERROR
Definition: Messenger.h:59
void LoadExtraOptions(void)
void MakeZCylinder(Double_t x0, Double_t y0, Double_t radius, Double_t zmin, Double_t zmax)
void SetEventGeneratorList(string listname)
Definition: GMCJDriver.cxx:66
void GetCommandLineArgs(int argc, char **argv)
std::string string
Definition: nybbler.cc:12
virtual void PrintConfig()=0
print the current configuration
bool gOptUsingRootGeom
void ReadFromCommandLine(int argc, char **argv)
Definition: RunOpt.cxx:99
#define pFATAL
Definition: Messenger.h:56
string gOptDetectorLocation
void MakeCylinder(Double_t *base, Double_t *axis, Double_t radius, Double_t *cap1, Double_t *cap2)
string gOptFidCut
virtual const PathLengthList & GetMaxPathLengths(void) const
void CreateRockBoxSelection(string fidcut, GeomAnalyzerI *geom_driver)
void MakeXCylinder(Double_t y0, Double_t z0, Double_t radius, Double_t xmin, Double_t xmax)
struct vector vector
virtual void ConvertShapeMaster2Top(const ROOTGeomAnalyzer *rgeom)
void Update(int iev, const EventRecord *event)
Definition: GMCJMonitor.cxx:48
double gOptGeomDUnits
const std::vector< std::string > & AvailableFluxDrivers() const
intermediate_table::const_iterator const_iterator
bool gSigTERM
int gOptNev
static void gsSIGTERMhandler(int)
virtual void SetNumOfCycles(long int ncycle)
limit cycling through input files
string gOptRootGeomMasterVol
virtual void SetScannerNParticles(int np)
bool gOptWriteMaxPlXml
void DetermineFluxDriver(string fopt)
virtual long int NFluxNeutrinos() const =0
of rays generated
long int gOptRanSeed
int gOptNScan
A list of PDG codes.
Definition: PDGCodeList.h:32
NtpMCFormat_t kDefOptNtpFormat
virtual void SetUpstreamZ(double z0)
void SetRefreshRate(int rate)
Definition: GMCJMonitor.cxx:43
void UseFluxDriver(GFluxI *flux)
Definition: GMCJDriver.cxx:83
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.
Simple class to create & update MC job status files and env. vars. This is used to be able to keep tr...
Definition: GMCJMonitor.h:31
A GENIE `MC Job Driver&#39;. Can be used for setting up complicated event generation cases involving deta...
Definition: GMCJDriver.h:46
double GlobProbScale(void) const
Definition: GMCJDriver.h:76
void SaveAsXml(string filename) const
const double e
TTree * EventTree(void)
Definition: NtpWriter.h:55
#define LOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a string (using the FILE...
Definition: Messenger.h:96
string kDefOptGeomDUnits
void MakeYCylinder(Double_t x0, Double_t z0, Double_t radius, Double_t ymin, Double_t ymax)
void ForceSingleProbScale(void)
Definition: GMCJDriver.cxx:172
void ParseFluxHst(string fopt)
virtual void SetScannerNRays(int nr)
A generic GENIE flux driver. Generates a &#39;cylindrical&#39; neutrino beam along the input direction...
bool IsAntiNeutrino(int pdgc)
Definition: PDGUtils.cxx:115
bool UseMaxPathLengths(string xml_filename)
Definition: GMCJDriver.cxx:99
double UnitFromString(string u)
Definition: UnitUtils.cxx:18
double gOptGeomLUnits
GENIE interface for uniform flux exposure iterface.
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...
void Configure(bool calc_prob_scales=true)
Definition: GMCJDriver.cxx:399
p
Definition: test.py:223
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.
map< string, string > gOptFluxShortNames
void Save(void)
get the even tree
Definition: NtpWriter.cxx:225
General LArSoft Utilities.
#define pINFO
Definition: Messenger.h:62
map< int, double > gOptTgtMix
string gOptRootGeomTopVol
string gOptExtMaxPlXml
void AddEventRecord(int ievent, const EventRecord *ev_rec)
save the event tree
Definition: NtpWriter.cxx:57
void SetTransverseRadius(double Rt)
void SetNuDirection(const TVector3 &direction)
void BuildTune()
build tune and inform XSecSplineList
Definition: RunOpt.cxx:92
#define pWARN
Definition: Messenger.h:60
EventRecord * GenerateEvent(void)
Definition: GMCJDriver.cxx:812
virtual void GetBranchInfo(std::vector< std::string > &branchNames, std::vector< std::string > &branchClassNames, std::vector< void ** > &branchObjPointers)
Generated Event Record. It is a GHepRecord object that can accept / be visited by EventRecordVisitorI...
Definition: EventRecord.h:37
Long_t gOptRunNu
void CustomizeFilenamePrefix(string prefix)
Definition: NtpWriter.cxx:133
void PrintSyntax(void)
string gOptInpXSecFile
void Initialize(void)
add event
Definition: NtpWriter.cxx:83
int main(int argc, char **argv)
static PDGLibrary * Instance(void)
Definition: PDGLibrary.cxx:57
static RunOpt * Instance(void)
Definition: RunOpt.cxx:54
vector< string > Split(string input, string delim)
Definition: StringUtils.cxx:36
int gOptDebug
A utility class to facilitate creating the GENIE MC Ntuple from the output GENIE GHEP event records...
Definition: NtpWriter.h:39
Singleton class to load & serve a TDatabasePDG.
Definition: PDGLibrary.h:32
static unsigned int reverse(QString &chars, unsigned char *level, unsigned int a, unsigned int b)
Definition: qstring.cpp:11649
string gOptEvFilePrefix
string gOptRootGeom
virtual void SetScannerNPoints(int np)
set geometry driver&#39;s configuration options
virtual void SetScannerFlux(GFluxI *f)
virtual double GetTotalExposure() const =0
static GFluxDriverFactory & Instance()
virtual bool End(void)=0
true if no more flux nu&#39;s can be thrown (eg reaching end of beam sim ntuples)
string PrintFramedMesg(string mesg, unsigned int nl=1, const char f='*')
Definition: PrintUtils.cxx:164
A vector of EventGeneratorI objects.
virtual void SetFluxParticles(const PDGCodeList &particles)
specify list of flux neutrino species
string kDefOptGeomLUnits
void SetBeamSpot(const TVector3 &spot)
void MesgThresholds(string inpfile)
Definition: AppInit.cxx:99
void split(std::string const &s, char c, OutIter dest)
Definition: split.h:35
void AddEnergySpectrum(int nu_pdgc, TH1D *spectrum)
TParticlePDG * Find(int pdgc, bool must_exist=true)
Definition: PDGLibrary.cxx:75
Command line argument parser.
enum genie::ENtpMCFormat NtpMCFormat_t
#define pNOTICE
Definition: Messenger.h:61
void SetRockBoxMinimal(Double_t *xyzmin, Double_t *xyzmax)
void MakeBox(Double_t *xyzmin, Double_t *xyzmax)
double gOptPOT
Defines the GENIE Geometry Analyzer Interface.
Definition: GeomAnalyzerI.h:29
int EventRecordPrintLevel(void) const
Definition: RunOpt.h:49
void CreateFidSelection(string fidcut, GeomAnalyzerI *geom_driver)
void RecursiveExhaust(TGeoVolume *topvol, string volnames, bool exhaust)
Definition: GeoUtils.cxx:16
Most commonly used PDG codes. A set of utility functions to handle PDG codes is provided in PDGUtils...
void UseGeomAnalyzer(GeomAnalyzerI *geom)
Definition: GMCJDriver.cxx:88
void UseSplines(bool useLogE=true)
Definition: GMCJDriver.cxx:93
The PointGeomAnalyzer class is the simplest implementation of the GeomAnalyserI interface and defines...
bool OptionExists(char opt)
was option set?
static QCString * s
Definition: config.cpp:1042
void CacheFile(string inpfile)
Definition: AppInit.cxx:117
double gOptZmin
void EnableBareXSecPreCalc(bool flag)
Definition: RunOpt.h:60
QTextStream & endl(QTextStream &s)
void push_back(int pdg_code)
Definition: PDGCodeList.cxx:58
map< int, TH1D * > gOptFluxHst
Event finding and building.
virtual TGeoManager * GetGeometry(void) const
genie::GFluxI * GetFluxDriver(const std::string &)
#define pDEBUG
Definition: Messenger.h:63
GENIE Interface for user-defined flux classes.
Definition: GFluxI.h:29
string gOptFluxDriver
bool gOptUsingHistFlux