gNeutralHeavyLeptonEvGen.cxx
Go to the documentation of this file.
1 //________________________________________________________________________________________
2 /*!
3 
4 \program gevgen_nhl
5 
6 \brief A GENIE-based neutral heavy lepton event generation application.
7 
8  *** Synopsis :
9 
10  gevgen_nhl [-h]
11  [-r run#]
12  -n n_of_events
13  -E nhl_energy (temporary)
14  --mass nhl_mass
15  -m decay_mode
16  -f nhl_flux
17  [-g geometry]
18  [-L geometry_length_units]
19  [-t geometry_top_volume_name]
20  [-o output_event_file_prefix]
21  [--seed random_number_seed]
22  [--message-thresholds xml_file]
23  [--event-record-print-level level]
24  [--mc-job-status-refresh-rate rate]
25 
26  *** Options :
27 
28  [] Denotes an optional argument
29 
30  -h
31  Prints out the gevgen_ndcy syntax and exits.
32  -r
33  Specifies the MC run number [default: 1000].
34  -n
35  Specifies how many events to generate.
36  --mass
37  Specifies the NHL mass (in GeV)
38  -m
39  NHL decay mode ID:
40  -f
41  Input NHL flux.
42  *** not implemented for gevgen_nhl yet ***
43  -g
44  Input detector geometry.
45  *** not implemented for gevgen_nhl yet ***
46  If a geometry is specified, NHL decay vertices will be distributed
47  in the desired detector volume.
48  Using this argument, you can pass a ROOT file containing your
49  detector geometry description.
50  -L
51  Input geometry length units, eg 'm', 'cm', 'mm', ...
52  [default: 'mm']
53  -t
54  Input 'top volume' for event generation.
55  The option be used to force event generation in given sub-detector.
56  [default: the 'master volume' of the input geometry]
57  You can also use the -t option to switch generation on/off at
58  multiple volumes as, for example, in:
59  `-t +Vol1-Vol2+Vol3-Vol4',
60  `-t "+Vol1 -Vol2 +Vol3 -Vol4"',
61  `-t -Vol2-Vol4+Vol1+Vol3',
62  `-t "-Vol2 -Vol4 +Vol1 +Vol3"'m
63  where:
64  "+Vol1" and "+Vol3" tells GENIE to `switch on' Vol1 and Vol3, while
65  "-Vol2" and "-Vol4" tells GENIE to `switch off' Vol2 and Vol4.
66  If the very first character is a '+', GENIE will neglect all volumes
67  except the ones explicitly turned on. Vice versa, if the very first
68  character is a `-', GENIE will keep all volumes except the ones
69  explicitly turned off (feature contributed by J.Holeczek).
70  -o
71  Sets the prefix of the output event file.
72  The output filename is built as:
73  [prefix].[run_number].[event_tree_format].[file_format]
74  The default output filename is:
75  gntp.[run_number].ghep.root
76  This cmd line arguments lets you override 'gntp'
77  --seed
78  Random number seed.
79 
80 \author Costas Andreopoulos <constantinos.andreopoulos \at cern.ch>
81  University of Liverpool & STFC Rutherford Appleton Laboratory
82 
83 \created February 11, 2020
84 
85 \cpright Copyright (c) 2003-2020, The GENIE Collaboration
86  For the full text of the license visit http://copyright.genie-mc.org
87 
88 */
89 //_________________________________________________________________________________________
90 
91 #include <cassert>
92 #include <cstdlib>
93 #include <string>
94 #include <vector>
95 #include <sstream>
96 
97 #include <TSystem.h>
98 #include <TGeoVolume.h>
99 #include <TGeoManager.h>
100 #include <TGeoShape.h>
101 #include <TGeoBBox.h>
102 
119 #include "Framework/Utils/AppInit.h"
120 #include "Framework/Utils/RunOpt.h"
122 
123 using std::string;
124 using std::vector;
125 using std::ostringstream;
126 
127 using namespace genie;
128 
129 // function prototypes
130 void GetCommandLineArgs (int argc, char ** argv);
131 void PrintSyntax (void);
132 void InitBoundingBox (void);
133 TLorentzVector GeneratePosition(void);
134 const EventRecordVisitorI * NHLGenerator(void);
135 
136 //
137 string kDefOptGeomLUnits = "mm"; // default geometry length units
138 string kDefOptGeomDUnits = "g_cm3"; // default geometry density units
139 NtpMCFormat_t kDefOptNtpFormat = kNFGHEP; // default event tree format
140 string kDefOptEvFilePrefix = "gntp";
141 
142 //
143 Long_t gOptRunNu = 1000; // run number
144 int gOptNev = 10; // number of events to generate
145 double gOptEnergyNHL = -1; // NHL mass
146 double gOptMassNHL = -1; // NHL mass
148 string gOptEvFilePrefix = kDefOptEvFilePrefix; // event file prefix
149 bool gOptUsingRootGeom = false; // using root geom or target mix?
150 string gOptRootGeom; // input ROOT file with realistic detector geometry
151 string gOptRootGeomTopVol = ""; // input geometry top event generation volume
152 double gOptGeomLUnits = 0; // input geometry length units
153 long int gOptRanSeed = -1; // random number seed
154 
155 // Geometry bounding box and origin - read from the input geometry file (if any)
156 double fdx = 0; // half-length - x
157 double fdy = 0; // half-length - y
158 double fdz = 0; // half-length - z
159 double fox = 0; // origin - x
160 double foy = 0; // origin - y
161 double foz = 0; // origin - z
162 
163 //_________________________________________________________________________________________
164 int main(int argc, char ** argv)
165 {
166  // Parse command line arguments
167  GetCommandLineArgs(argc,argv);
168 
169  // Init messenger and random number seed
170  utils::app_init::MesgThresholds(RunOpt::Instance()->MesgThresholdFiles());
172 
173  // Initialize an Ntuple Writer to save GHEP records into a TTree
176  ntpw.Initialize();
177 
178  // Create a MC job monitor for a periodically updated status file
179  GMCJMonitor mcjmonitor(gOptRunNu);
180  mcjmonitor.SetRefreshRate(RunOpt::Instance()->MCJobStatusRefreshRate());
181 
182  // Set GHEP print level
183  GHepRecord::SetPrintLevel(RunOpt::Instance()->EventRecordPrintLevel());
184 
185  // Read geometry bounding box - for vertex position generation
186  InitBoundingBox();
187 
188  // Get the nucleon decay generator
189  const EventRecordVisitorI * mcgen = NHLGenerator();
190 
191  // Event loop
192  int ievent = 0;
193  while (1)
194  {
195  if(ievent == gOptNev) break;
196 
197  LOG("gevgen_nhl", pNOTICE)
198  << " *** Generating event............ " << ievent;
199 
200  EventRecord * event = new EventRecord;
201  // int target = SelectInitState();
202  int decay = (int)gOptDecayMode;
204  event->AttachSummary(interaction);
205 
206  // Simulate decay
207  mcgen->ProcessEventRecord(event);
208 
209  // Generate a position within the geometry bounding box
210  TLorentzVector x4 = GeneratePosition();
211  event->SetVertex(x4);
212 
213  LOG("gevgen_nhl", pINFO)
214  << "Generated event: " << *event;
215 
216  // Add event at the output ntuple, refresh the mc job monitor & clean-up
217  ntpw.AddEventRecord(ievent, event);
218  mcjmonitor.Update(ievent,event);
219  delete event;
220 
221  ievent++;
222  } // event loop
223 
224  // Save the generated event tree & close the output file
225  ntpw.Save();
226 
227  LOG("gevgen_nhl", pNOTICE) << "Done!";
228 
229  return 0;
230 }
231 //_________________________________________________________________________________________
232 void InitBoundingBox(void)
233 {
234 // Initialise geometry bounding box, used for generating NHL vertex positions
235 
236  fdx = 0; // half-length - x
237  fdy = 0; // half-length - y
238  fdz = 0; // half-length - z
239  fox = 0; // origin - x
240  foy = 0; // origin - y
241  foz = 0; // origin - z
242 
243  if(!gOptUsingRootGeom) return;
244 
245  bool geom_is_accessible = ! (gSystem->AccessPathName(gOptRootGeom.c_str()));
246  if (!geom_is_accessible) {
247  LOG("gevgen_nhl", pFATAL)
248  << "The specified ROOT geometry doesn't exist! Initialization failed!";
249  exit(1);
250  }
251 
252  TGeoManager * gm = TGeoManager::Import(gOptRootGeom.c_str());
253  TGeoVolume * top_volume = gm->GetTopVolume();
254  TGeoShape * ts = top_volume->GetShape();
255  TGeoBBox * box = (TGeoBBox *)ts;
256  //get box origin and dimensions (in the same units as the geometry)
257  fdx = box->GetDX(); // half-length
258  fdy = box->GetDY(); // half-length
259  fdz = box->GetDZ(); // half-length
260  fox = (box->GetOrigin())[0];
261  foy = (box->GetOrigin())[1];
262  foz = (box->GetOrigin())[2];
263 
264  // Convert from local to SI units
265  fdx *= gOptGeomLUnits;
266  fdy *= gOptGeomLUnits;
267  fdz *= gOptGeomLUnits;
268  fox *= gOptGeomLUnits;
269  foy *= gOptGeomLUnits;
270  foz *= gOptGeomLUnits;
271 }
272 //_________________________________________________________________________________________
273 TLorentzVector GeneratePosition(void)
274 {
275  RandomGen * rnd = RandomGen::Instance();
276  TRandom3 & rnd_geo = rnd->RndGeom();
277 
278  double rndx = 2 * (rnd_geo.Rndm() - 0.5); // [-1,1]
279  double rndy = 2 * (rnd_geo.Rndm() - 0.5); // [-1,1]
280  double rndz = 2 * (rnd_geo.Rndm() - 0.5); // [-1,1]
281 
282  double t_gen = 0;
283  double x_gen = fox + rndx * fdx;
284  double y_gen = foy + rndy * fdy;
285  double z_gen = foz + rndz * fdz;
286 
287  TLorentzVector pos(x_gen, y_gen, z_gen, t_gen);
288  return pos;
289 }
290 //_________________________________________________________________________________________
292 {
293  string sname = "genie::EventGenerator";
294  string sconfig = "NeutralHeavyLepton";
295  AlgFactory * algf = AlgFactory::Instance();
296  const EventRecordVisitorI * mcgen =
297  dynamic_cast<const EventRecordVisitorI *> (algf->GetAlgorithm(sname,sconfig));
298  if(!mcgen) {
299  LOG("gevgen_nhl", pFATAL) << "Couldn't instantiate the NHL generator";
300  gAbortingInErr = true;
301  exit(1);
302  }
303  return mcgen;
304 }
305 //_________________________________________________________________________________________
306 void GetCommandLineArgs(int argc, char ** argv)
307 {
308  LOG("gevgen_nhl", pINFO) << "Parsing command line arguments";
309 
310  // Common run options.
312 
313  // Parse run options for this app
314 
315  CmdLnArgParser parser(argc,argv);
316 
317  // help?
318  bool help = parser.OptionExists('h');
319  if(help) {
320  PrintSyntax();
321  exit(0);
322  }
323 
324  // run number
325  if( parser.OptionExists('r') ) {
326  LOG("gevgen_nhl", pDEBUG) << "Reading MC run number";
327  gOptRunNu = parser.ArgAsLong('r');
328  } else {
329  LOG("gevgen_nhl", pDEBUG) << "Unspecified run number - Using default";
330  gOptRunNu = 1000;
331  } //-r
332 
333  // number of events
334  if( parser.OptionExists('n') ) {
335  LOG("gevgen_nhl", pDEBUG)
336  << "Reading number of events to generate";
337  gOptNev = parser.ArgAsInt('n');
338  } else {
339  LOG("gevgen_nhl", pFATAL)
340  << "You need to specify the number of events";
341  PrintSyntax();
342  exit(0);
343  } //-n
344 
345  // NHL mass
346  gOptMassNHL = -1;
347  if( parser.OptionExists("mass") ) {
348  LOG("gevgen_nhl", pDEBUG)
349  << "Reading NHL mass";
350  gOptMassNHL = parser.ArgAsDouble("mass");
351  } else {
352  LOG("gevgen_nhl", pFATAL)
353  << "You need to specify the NHL mass";
354  PrintSyntax();
355  exit(0);
356  } //--mass
357  PDGLibrary * pdglib = PDGLibrary::Instance();
358  pdglib->AddNHL(gOptMassNHL);
359 
360  // NHL energy (temporary - will disappear once we add an option to read a flux)
361  gOptEnergyNHL = -1;
362  if( parser.OptionExists('E') ) {
363  LOG("gevgen_nhl", pDEBUG)
364  << "Reading NHL energy";
365  gOptEnergyNHL = parser.ArgAsDouble('E');
366  } else {
367  LOG("gevgen_nhl", pFATAL)
368  << "You need to specify the NHL energy";
369  PrintSyntax();
370  exit(0);
371  } //-E
372  assert(gOptEnergyNHL > gOptMassNHL);
373 
374  // NHL decay mode
375  int mode = -1;
376  if( parser.OptionExists('m') ) {
377  LOG("gevgen_nhl", pDEBUG)
378  << "Reading NHL decay mode";
379  mode = parser.ArgAsInt('m');
380  } else {
381  LOG("gevgen_nhl", pFATAL)
382  << "You need to specify the decay mode";
383  PrintSyntax();
384  exit(0);
385  } //-m
386  gOptDecayMode = (NHLDecayMode_t) mode;
387 
389  if(!allowed) {
390  LOG("gevgen_nhl", pFATAL)
391  << "Specified decay is not allowed kinematically for the given NHL mass";
392  PrintSyntax();
393  exit(0);
394  }
395 
396  //
397  // geometry
398  //
399 
400  string geom = "";
401  string lunits;
402  // string dunits;
403  if( parser.OptionExists('g') ) {
404  LOG("gevgen_nhl", pDEBUG) << "Getting input geometry";
405  geom = parser.ArgAsString('g');
406 
407  // is it a ROOT file that contains a ROOT geometry?
408  bool accessible_geom_file =
409  ! (gSystem->AccessPathName(geom.c_str()));
410  if (accessible_geom_file) {
411  gOptRootGeom = geom;
412  gOptUsingRootGeom = true;
413  }
414  } else {
415  // LOG("gevgen_nhl", pFATAL)
416  // << "No geometry option specified - Exiting";
417  // PrintSyntax();
418  // exit(1);
419  } //-g
420 
421  if(gOptUsingRootGeom) {
422  // using a ROOT geometry - get requested geometry units
423 
424  // legth units:
425  if( parser.OptionExists('L') ) {
426  LOG("gevgen_nhl", pDEBUG)
427  << "Checking for input geometry length units";
428  lunits = parser.ArgAsString('L');
429  } else {
430  LOG("gevgen_nhl", pDEBUG) << "Using default geometry length units";
431  lunits = kDefOptGeomLUnits;
432  } // -L
433  // // density units:
434  // if( parser.OptionExists('D') ) {
435  // LOG("gevgen_nhl", pDEBUG)
436  // << "Checking for input geometry density units";
437  // dunits = parser.ArgAsString('D');
438  // } else {
439  // LOG("gevgen_nhl", pDEBUG) << "Using default geometry density units";
440  // dunits = kDefOptGeomDUnits;
441  // } // -D
443  // gOptGeomDUnits = utils::units::UnitFromString(dunits);
444 
445  // check whether an event generation volume name has been
446  // specified -- default is the 'top volume'
447  if( parser.OptionExists('t') ) {
448  LOG("gevgen_nhl", pDEBUG) << "Checking for input volume name";
449  gOptRootGeomTopVol = parser.ArgAsString('t');
450  } else {
451  LOG("gevgen_nhl", pDEBUG) << "Using the <master volume>";
452  } // -t
453 
454  } // using root geom?
455 
456  // event file prefix
457  if( parser.OptionExists('o') ) {
458  LOG("gevgen_nhl", pDEBUG) << "Reading the event filename prefix";
459  gOptEvFilePrefix = parser.ArgAsString('o');
460  } else {
461  LOG("gevgen_nhl", pDEBUG)
462  << "Will set the default event filename prefix";
464  } //-o
465 
466  // random number seed
467  if( parser.OptionExists("seed") ) {
468  LOG("gevgen_nhl", pINFO) << "Reading random number seed";
469  gOptRanSeed = parser.ArgAsLong("seed");
470  } else {
471  LOG("gevgen_nhl", pINFO) << "Unspecified random number seed - Using default";
472  gOptRanSeed = -1;
473  }
474 
475  //
476  // >>> print the command line options
477  //
478 
479  ostringstream gminfo;
480  if (gOptUsingRootGeom) {
481  gminfo << "Using ROOT geometry - file: " << gOptRootGeom
482  << ", top volume: "
483  << ((gOptRootGeomTopVol.size()==0) ? "<master volume>" : gOptRootGeomTopVol)
484  << ", length units: " << lunits;
485  // << ", density units: " << dunits;
486  }
487 
488  LOG("gevgen_nhl", pNOTICE)
489  << "\n\n"
490  << utils::print::PrintFramedMesg("gevgen_nhl job configuration");
491 
492  LOG("gevgen_nhl", pNOTICE)
493  << "\n @@ Run number : " << gOptRunNu
494  << "\n @@ Random seed : " << gOptRanSeed
495  << "\n @@ NHL mass : " << gOptMassNHL << " GeV"
496  << "\n @@ Decay channel : " << utils::nhl::AsString(gOptDecayMode)
497  << "\n @@ Geometry : " << gminfo.str()
498  << "\n @@ Statistics : " << gOptNev << " events";
499 }
500 //_________________________________________________________________________________________
501 void PrintSyntax(void)
502 {
503  LOG("gevgen_nhl", pFATAL)
504  << "\n **Syntax**"
505  << "\n gevgen_nhl [-h] "
506  << "\n [-r run#]"
507  << "\n -E nhl_energy (temporary)"
508  << "\n --mass nhl_mass"
509  << "\n -m decay_mode"
510  << "\n -f flux ** not installed yet **"
511  << "\n [-g geometry]"
512  << "\n [-t top_volume_name_at_geom]"
513  << "\n [-L length_units_at_geom]"
514  << "\n -n n_of_events "
515  << "\n [-o output_event_file_prefix]"
516  << "\n [--seed random_number_seed]"
517  << "\n [--message-thresholds xml_file]"
518  << "\n [--event-record-print-level level]"
519  << "\n [--mc-job-status-refresh-rate rate]"
520  << "\n"
521  << " Please also read the detailed documentation at http://www.genie-mc.org"
522  << " or look at the source code: $GENIE/src/Apps/gNeutralHeavyLeptonEvGen.cxx"
523  << "\n";
524 }
525 //_________________________________________________________________________________________
void RandGen(long int seed)
Definition: AppInit.cxx:30
static void SetPrintLevel(int print_level)
Definition: GHepRecord.cxx:948
long ArgAsLong(char opt)
double ArgAsDouble(char opt)
string kDefOptGeomLUnits
TLorentzVector GeneratePosition(void)
string ArgAsString(char opt)
THE MAIN GENIE PROJECT NAMESPACE
Definition: AlgCmp.h:25
virtual void ProcessEventRecord(GHepRecord *event_rec) const =0
static RandomGen * Instance()
Access instance.
Definition: RandomGen.cxx:71
string gOptRootGeomTopVol
Defines the EventRecordVisitorI interface. Concrete implementations of this interface use the &#39;Visito...
Long_t gOptRunNu
std::string string
Definition: nybbler.cc:12
NtpMCFormat_t kDefOptNtpFormat
void ReadFromCommandLine(int argc, char **argv)
Definition: RunOpt.cxx:99
#define pFATAL
Definition: Messenger.h:56
struct vector vector
double gOptMassNHL
double gOptEnergyNHL
void Update(int iev, const EventRecord *event)
Definition: GMCJMonitor.cxx:48
const EventRecordVisitorI * NHLGenerator(void)
A singleton holding random number generator classes. All random number generation in GENIE should tak...
Definition: RandomGen.h:29
void SetRefreshRate(int rate)
Definition: GMCJMonitor.cxx:43
Summary information for an interaction.
Definition: Interaction.h:56
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
double gOptGeomLUnits
void AddNHL(double mass)
Definition: PDGLibrary.cxx:165
#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 GetCommandLineArgs(int argc, char **argv)
#define Import
double UnitFromString(string u)
Definition: UnitUtils.cxx:18
const Algorithm * GetAlgorithm(const AlgId &algid)
Definition: AlgFactory.cxx:75
void InitBoundingBox(void)
void Save(void)
get the even tree
Definition: NtpWriter.cxx:225
#define pINFO
Definition: Messenger.h:62
TRandom3 & RndGeom(void) const
rnd number generator used by geometry drivers
Definition: RandomGen.h:68
void AddEventRecord(int ievent, const EventRecord *ev_rec)
save the event tree
Definition: NtpWriter.cxx:57
string kDefOptEvFilePrefix
string gOptEvFilePrefix
bool gOptUsingRootGeom
void PrintSyntax(void)
Generated Event Record. It is a GHepRecord object that can accept / be visited by EventRecordVisitorI...
Definition: EventRecord.h:37
void CustomizeFilenamePrefix(string prefix)
Definition: NtpWriter.cxx:133
void Initialize(void)
add event
Definition: NtpWriter.cxx:83
static PDGLibrary * Instance(void)
Definition: PDGLibrary.cxx:57
static RunOpt * Instance(void)
Definition: RunOpt.cxx:54
static AlgFactory * Instance()
Definition: AlgFactory.cxx:64
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
string PrintFramedMesg(string mesg, unsigned int nl=1, const char f='*')
Definition: PrintUtils.cxx:164
void MesgThresholds(string inpfile)
Definition: AppInit.cxx:99
Command line argument parser.
enum genie::ENtpMCFormat NtpMCFormat_t
#define pNOTICE
Definition: Messenger.h:61
The GENIE Algorithm Factory.
Definition: AlgFactory.h:39
static Interaction * NHL(double E=0, int decayed_mode=-1)
string gOptRootGeom
bool gAbortingInErr
Definition: Messenger.cxx:34
string AsString(NHLDecayMode_t nhldm)
long int gOptRanSeed
NHLDecayMode_t gOptDecayMode
Most commonly used PDG codes. A set of utility functions to handle PDG codes is provided in PDGUtils...
int main(int argc, char **argv)
bool OptionExists(char opt)
was option set?
enum genie::ENHLDecayMode NHLDecayMode_t
bool IsKinematicallyAllowed(NHLDecayMode_t nhldm, double Mnhl)
Event finding and building.
#define pDEBUG
Definition: Messenger.h:63