LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
AddGenieEventsToArt_module.cc
Go to the documentation of this file.
7 
9 
11 
13 
17 // for sim::GetRandomNumberSeed()
19 
23 
24 // GENIE includes
25 #ifdef GENIE_PRE_R3
26  #include "Conventions/GVersion.h"
27  #include "Ntuple/NtpMCEventRecord.h"
28  #include "Ntuple/NtpMCTreeHeader.h"
29  #include "PDG/PDGLibrary.h"
30  // -- GENIE Messenger conflict LOG_INFO w/ ART messagefacility
31  //#include "Messenger/Messenger.h"
32  #include "GHEP/GHepRecord.h"
33  #include "GHEP/GHepParticle.h"
34 
35  #include "FluxDrivers/GNuMIFlux.h"
36  #include "FluxDrivers/GSimpleNtpFlux.h"
37 #else
38  #include "GENIE/Framework/Conventions/GVersion.h"
39  #include "GENIE/Framework/GHEP/GHepRecord.h"
40  #include "GENIE/Framework/GHEP/GHepParticle.h"
41  #include "GENIE/Framework/Ntuple/NtpMCFormat.h"
42  #include "GENIE/Framework/Ntuple/NtpWriter.h"
43  #include "GENIE/Framework/Ntuple/NtpMCEventRecord.h"
44  // #include "GENIE/Framework/Ntuple/NtpMCTreeHeader.h"
45  #include "GENIE/Framework/Messenger/Messenger.h"
46  // careful: potential conflict LOG_INFO w/ messagefacility
47 
48  #include "GENIE/Tools/Flux/GNuMIFlux.h"
49  #include "GENIE/Tools/Flux/GSimpleNtpFlux.h"
50 #endif
51 
52 #include "dk2nu/tree/dk2nu.h"
53 #include "dk2nu/tree/NuChoice.h"
54 
55 // ROOT includes
56 #include "TChain.h"
57 #include "TBranchElement.h"
58 #include "TBranchObject.h"
59 
60 // CLHEP
61 #include "CLHEP/Random/RandFlat.h"
62 #include "CLHEP/Random/RandPoissonT.h"
63 #include "CLHEP/Random/RandGauss.h"
64 
65 #include <memory>
66 #include <vector>
67 #include <string>
68 #include <algorithm>
69 #include <utility>
70 
71 #include <fstream>
72 #include <cstdio>
73 #include <iomanip>
74 #include <sstream>
75 
77 
78 #include "fhiclcpp/types/Atom.h"
80 #include "fhiclcpp/types/Table.h"
81 
82 namespace evg {
83  class AddGenieEventsToArt;
84 
86  // hold/document fcl parameters
87  template<class T> using Atom = fhicl::Atom<T>;
88  template<class T> using Sequence = fhicl::Sequence<T>;
89  template<class T> using Table = fhicl::Table<T>;
91  using Name = fhicl::Name;
92 
94  Name("fileList"),
95  Comment("list of input gntp.*.ghep.root files"),
96  // no default { " " } // no default
97  };
99  Name("countConfig"),
100  Comment("how many events to pull \"<form>: <value> [<value>]\""
101  " known functional forms:\n"
102  " \"fixed: <n>\"\n"
103  " \"flat: <nmin> <nmax>\"\n"
104  " \"poisson: <mean>\"\n"
105  " \"poisson-1: <mean>\" use Poisson, then subtract 1 (floor 0)\n"
106  " \"gauss: <mean> <rms>\" (floor 0)"),
107  "fixed: 1" // default
108  };
110  Name("globalTimeOffset"),
111  Comment("fixed offset to add (in ns)"),
112  0.0
113  };
115  Name("timeConfig"),
116  Comment("time distribution beyond globalTimeOffset (in ns)\n"
117  " e.g. \"flat: 1000\"\n"
118  " \"numi: \"\n"
119  " see: https://cdcvs.fnal.gov/redmine/projects/nutools/wiki/GENIEHelper#EvtTimeFNALBeam"),
120  "numi:"
121  };
122  struct VtxOffsets {
123  Atom<double> xlo { Name("xlo"), Comment("min x addition"), 0.0 };
124  Atom<double> ylo { Name("ylo"), Comment("min y addition"), 0.0 };
125  Atom<double> zlo { Name("zlo"), Comment("min z addition"), 0.0 };
126  Atom<double> xhi { Name("xhi"), Comment("max x addition"), 0.0 };
127  Atom<double> yhi { Name("yhi"), Comment("max y addition"), 0.0 };
128  Atom<double> zhi { Name("zhi"), Comment("max z addition"), 0.0 };
129  };
131  Name("vtxOffsets"),
132  Comment("allow module to offset global vertex (genie vtx units = m)")
133  };
135  Name("addMCFlux"),
136  Comment("attempt to fetch and fill MCFlux for each genie::EventRecord"),
137  true
138  };
140  Name("outputPrintLevel"),
141  Comment("print fetched genie::EventRecord -1=no, 13=max info\n"
142  "see GENIE manual for legal values"),
143  -1
144  };
146  Name("outputDumpFileName"),
147  Comment("name of file to print to (if outputPrintLevel >= 0)\n"
148  "\"std::cout\" for standard out\n"
149  "otherwise string with %l replaced by module_label"),
150  "AddGenieEventsToArt_%l.txt"
151  };
153  Name("randomEntries"),
154  Comment("use random sets of entries from input files\n"
155  "rather than go through the files sequentially"),
156  false
157  };
159  Name("numberToSkip"),
160  Comment("Skip the first N entries, starting on the entry \n"
161  "specified in this variable"),
162  0
163  };
164  // want this to be optional ...
166  Name("seed"),
167  Comment("random number seed"),
168  0
169  };
170 
172  Name("inputGenieVersion"),
173  Comment("Version of GENIE used previously to generate the input events (default"),
174  "unknown"
175  };
176 
178  Name("inputGenieTune"),
179  Comment("GENIE Comprehensive Model Configuration (CMC/'tune') used to generate the input events for GENIE 3.0+"),
180  ""
181  };
182 
184  Name("addGenieVtxTime"),
185  Comment("include GENIE's vertex time to MCTruth particle times"),
186  false // false = old behaviour by default
187  };
188 
189 
190  }; // AddGenieEventsToArtParams
191 }
192 
194 public:
195 
196  // Allow 'art --print-description' to work
198 
199  //explicit AddGenieEventsToArt(fhicl::ParameterSet const & p);
200  explicit AddGenieEventsToArt(const Parameters & p);
201 
202  // The destructor generated by the compiler is fine for classes
203  // without bare pointers or other resource use.
205 
206  // Plugins should not be copied or assigned.
207  AddGenieEventsToArt(AddGenieEventsToArt const &) = delete;
209  AddGenieEventsToArt & operator = (AddGenieEventsToArt const &) = delete;
210  AddGenieEventsToArt & operator = (AddGenieEventsToArt &&) = delete;
211 
212  // Required functions.
213  void produce(art::Event & e) override;
214 
215  //void reconfigure(const Parameters & params) override;
216 
217  // Selected optional functions.
218  /*
219  void beginJob() override;
220  void beginRun(art::Run & r) override;
221  void beginSubRun(art::SubRun & sr) override;
222  void endJob() override;
223  void endRun(art::Run & r) override;
224  void endSubRun(art::SubRun & sr) override;
225  void respondToCloseInputFile(art::FileBlock const & fb) override;
226  void respondToCloseOutputFiles(art::FileBlock const & fb) override;
227  void respondToOpenInputFile(art::FileBlock const & fb) override;
228  void respondToOpenOutputFiles(art::FileBlock const & fb) override;
229  */
230 
231 private:
232 
233  typedef enum EDistrib { kUnknownDist,
239  kRootino } RndDist_t;
240 
241  // Private member functions here.
242  void ParseCountConfig();
243  size_t GetNumToAdd() const;
244  void ParseTimeConfig();
245  void ParseVtxOffsetConfig();
246 
248 
249  // member data here.
250 
251  std::vector<std::string> fFileList;
254  double fXlo; // vtx offset ranges
255  double fYlo;
256  double fZlo;
257  double fXhi;
258  double fYhi;
259  double fZhi;
262 
263  std::string fMyModuleType;
264  std::string fMyModuleLabel;
266  std::string fOutputDumpFileName;
267  //< use %l to substitute in module_label
268  //< use "", "--", "cout" or "std::cout" for using that instead of file
269  std::ostream* fOutputStream;
270 
271  // parsed NumToAddString parameters
272  std::string fDistName;
273  RndDist_t fRndDist;
274  double fRndP1;
275  double fRndP2;
276 
277  TChain* fGTreeChain;
278  genie::NtpMCEventRecord* fMCRec;
279  size_t fNumMCRec;
280  size_t fLastUsedMCRec; // if going sequentially
281 
282  // possible flux branches
283 
284  genie::flux::GNuMIFluxPassThroughInfo* fGNuMIFluxPassThroughInfo;
285 
286  genie::flux::GSimpleNtpEntry* fGSimpleNtpEntry;
287  genie::flux::GSimpleNtpNuMI* fGSimpleNtpNuMI;
288  genie::flux::GSimpleNtpAux* fGSimpleNtpAux;
289 
290  bsim::Dk2Nu* fDk2Nu;
291  bsim::NuChoice* fNuChoice;
292  unsigned int const fSeed;
293  CLHEP::HepRandomEngine& fEngine;
294 
295  // selection order - sequential-round, sequential-1time, random-1?
296 
297 };
298 
300  : EDProducer(params)
301  , fParams(params)
302  , fGlobalTimeOffset(0)
303  , fTimeShifter(0)
304  , fXlo(0), fYlo(0), fZlo(0)
305  , fXhi(0), fYhi(0), fZhi(0)
306  , fAddMCFlux(false)
307  , fRandomEntries(false)
308  , fOutputPrintLevel(-1)
309  , fOutputStream(0)
310  //
311  , fDistName("")
312  , fRndDist(kUnknownDist)
313  , fRndP1(-1)
314  , fRndP2(-1)
315  , fGTreeChain(new TChain("gtree"))
316  , fMCRec(new genie::NtpMCEventRecord)
317  , fNumMCRec(0)
318  , fLastUsedMCRec(0)
319  , fGNuMIFluxPassThroughInfo(0)
320  , fGSimpleNtpEntry(0)
321  , fGSimpleNtpNuMI(0)
322  , fGSimpleNtpAux(0)
323  , fDk2Nu(0)
324  , fNuChoice(0)
325  // get the random number seed, use a random default if not specified
326  // in the configuration file.
327  , fSeed{fParams().seed() == 0 ? evgb::GetRandomNumberSeed() : fParams().seed()}
328  // only need sub-label if using more than one engine for each
329  // instance of this module (already tagged by equiv of fMyModuleLabel)
330  , fEngine{createEngine(fSeed/*, "HepJamesRandom", sub-label*/)}
331 {
332 
333 #ifdef GENIE_PRE_R3
334  // trigger early initialization of PDG database & GENIE message service
335  // just to get it out of the way and not intermixed with other output
336  genie::PDGLibrary::Instance();
337 #else
338  // get the GENIE banner out of the way
339  // no longer can use genie::PDGLibrary::Instance() to do this
340  // because that must happen, in some cases in v3_02_xx, after the tune
341  // is determined
342  // banner is triggered by first use of GENIE Messenger
343  // avoid using GENIE macros (possible conflict with mf macros)
344  // LOG("GENIE",pInfo) << "Trigger GENIE banner";
345  (*genie::Messenger::Instance())("GENIE") << log4cpp::Priority::INFO
346  << "Trigger GENIE banner";
347 #endif
348 
349  fMyModuleType = fParams.get_PSet().get<std::string>("module_type");
350  fMyModuleLabel = fParams.get_PSet().get<std::string>("module_label");
351 
352  mf::LogDebug("AddGenieEventsToArt")
353  << " ctor start " << fMyModuleLabel
354  << " (" << fMyModuleType << ") " << std::endl << std::flush;
355 
356  fFileList = fParams().fileList();
357  fGlobalTimeOffset = fParams().globalTimeOffset();
358  fAddMCFlux = fParams().addMCFlux();
359  fRandomEntries = fParams().randomEntries();
360 
363  ParseTimeConfig();
364 
365  produces< std::vector<simb::MCTruth> >();
366  produces< std::vector<simb::GTruth> >();
367  produces< art::Assns<simb::MCTruth, simb::GTruth> >();
368  if ( fAddMCFlux ) {
369  produces< std::vector<simb::MCFlux> >();
370  // Associate every truth with the flux it came from
371  produces< art::Assns<simb::MCTruth, simb::MCFlux> >();
372  }
373 
374  //produces< sumdata::SpillData >();
375  //produces< sumdata::POTSum, art::InSubRun >();
376  //produces< sumdata::RunData, art::InRun >();
377 
378  std::string outFileList = "adding file pattern: ";
379  for (size_t i=0; i < fFileList.size(); ++i) {
380  outFileList += "\n\t";
381  outFileList += fFileList[i];
382  fGTreeChain->Add(fFileList[i].c_str());
383  }
384  mf::LogDebug("AddGenieEventsToArt") << outFileList;
385 
386  fNumMCRec = fGTreeChain->GetEntries();
387  // fLastUsedMCRec is size_t so, unsigned we can't set it to -1
388  // which we'd like to so that the first pre-increment gives us "0"
389  size_t skip = fParams().numberToSkip();
390  fLastUsedMCRec = (skip==0) ? fNumMCRec : skip - 1;
391 
392  // attach flux branches ...
409  TObjArray* blist = fGTreeChain->GetListOfBranches();
410  TIter next(blist);
411  TObject* obj;
412  while ( ( obj = next() ) ) {
413  std::string bname = obj->GetName();
414  // should be a list of TBranchElement or TBranchObject items
415  // TBranchObject are ancient ... should have been replaced by Elements
416  const TBranchElement* belement = dynamic_cast<const TBranchElement*>(obj);
417  const TBranchObject* bobject = dynamic_cast<const TBranchObject*>(obj);
418  if ( ! belement && ! bobject ) {
419  std::string reallyIsA = obj->ClassName();
420  mf::LogError("AddGenieEventsToArt")
421  << "### supposed branch element '" << bname
422  << "' wasn't a TBranchElement/TBranchObject but instead a "
423  << reallyIsA << std::endl;
424  if ( bname == "gmcrec" ) {
425  mf::LogError("AddGenieEventsToArt")
426  << "### since this is '" << bname
427  << "' this is likely to end very badly badly" << std::endl;
428  }
429  continue;
430  }
431  std::string bclass = (belement) ? belement->GetClassName()
432  : bobject->GetClassName();
433  if ( bclass == "genie::NtpMCEventRecord" ) {
434  fGTreeChain->SetBranchAddress(bname.c_str(),&fMCRec);
435  } else if ( bclass == "genie::flux::GNuMIFluxPassThroughInfo" ) {
436  fGNuMIFluxPassThroughInfo = new genie::flux::GNuMIFluxPassThroughInfo;
437  fGTreeChain->SetBranchAddress(bname.c_str(),&fGNuMIFluxPassThroughInfo);
438  } else if ( bclass == "genie::flux::GSimpleNtpEntry" ) {
439  fGSimpleNtpEntry = new genie::flux::GSimpleNtpEntry;
440  fGTreeChain->SetBranchAddress(bname.c_str(),&fGSimpleNtpEntry);
441  } else if ( bclass == "genie::flux::GSimpleNtpNuMI" ) {
442  fGSimpleNtpNuMI = new genie::flux::GSimpleNtpNuMI;
443  fGTreeChain->SetBranchAddress(bname.c_str(),&fGSimpleNtpNuMI);
444  } else if ( bclass == "genie::flux::GSimpleNtpAux" ) {
445  fGSimpleNtpAux = new genie::flux::GSimpleNtpAux;
446  fGTreeChain->SetBranchAddress(bname.c_str(),&fGSimpleNtpAux);
447  } else if ( bclass == "bsim::Dk2Nu" ) {
448  fDk2Nu = new bsim::Dk2Nu;
449  fGTreeChain->SetBranchAddress(bname.c_str(),&fDk2Nu);
450  } else if ( bclass == "bsim::NuChoice" ) {
451  fNuChoice = new bsim::NuChoice;
452  fGTreeChain->SetBranchAddress(bname.c_str(),&fNuChoice);
453  } else {
454  mf::LogError("AddGenieEventsToArt")
455  << "### branch element '" << bname
456  << "' was unhandled '" << bclass << "' class" << std::endl;
457  }
458  } // while ( next )
459 
460  mf::LogInfo("AddGenieEventsToArt")
461  << fMyModuleLabel
462  << " (" << fMyModuleType << ") "
463  << "chain has " << fNumMCRec << " entries"
464  << std::endl;
465  if ( fNumMCRec == 0 ) {
466  throw cet::exception("badInput")
467  << "input files have zero entries "
468  << __FILE__ << ":" << __LINE__;
469  }
470 
471  // setup to write out file, if requested
472  if ( fOutputPrintLevel > 0 ) {
473  if ( fOutputDumpFileName == "" ||
474  fOutputDumpFileName == "--" ||
475  fOutputDumpFileName == "cout" ||
476  fOutputDumpFileName == "std::cout" ) {
477  // standardize so we don't check all these again
478  fOutputDumpFileName = "std::cout";
479  fOutputStream = &(std::cout);
480  } else {
481  size_t posl = fOutputDumpFileName.find("%l");
482  if ( posl != std::string::npos ) {
483  fOutputDumpFileName.replace(posl,2,fMyModuleLabel);
484  }
485  mf::LogDebug("AddGenieEventToArt")
486  << "#### AddGenieEventsToArt::ctor open "
488  << std::endl << std::flush;
489  fOutputStream =
490  new std::ofstream(fOutputDumpFileName.c_str(),
491  std::ios_base::trunc|std::ios_base::out);
492  }
493  } // if ( fOutputPrintLevel > 0 )
494 
495 }
496 
498 {
499  // release resources
500  if ( fGTreeChain ) delete fGTreeChain;
501  if ( fOutputStream && ( fOutputDumpFileName != "std::cout" ) ) {
502  std::ofstream* ofs = dynamic_cast<std::ofstream*>(fOutputStream);
503  if ( ofs ) {
504  mf::LogDebug("AddGenieEventToArt")
505  << "#### AddGenieEventsToArt::dtor close "
507  << std::endl << std::flush;
508  ofs->flush();
509  ofs->close();
510  }
511  delete fOutputStream;
512  }
513 }
514 
516 {
517 
518  //std::cerr << "AddGenieEventsToArt::produce start" << std::endl << std::flush;
519 
520  std::unique_ptr< std::vector<simb::MCTruth> >
521  mctruthcol(new std::vector<simb::MCTruth>);
522 
523  std::unique_ptr< std::vector<simb::GTruth> >
524  gtruthcol(new std::vector<simb::GTruth>);
525 
526  std::unique_ptr< std::vector<simb::MCFlux> >
527  mcfluxcol(new std::vector<simb::MCFlux>);
528 
529  std::unique_ptr< art::Assns<simb::MCTruth, simb::MCFlux> >
531  std::unique_ptr< art::Assns<simb::MCTruth, simb::GTruth> >
533 
534  // number of interactions to add to _this_ record/"event"
535  size_t n = GetNumToAdd();
536 
537  // make a list of entries in TChain to use for this overlay
538  // same entry should never be in the list twice ...
539  std::vector<size_t> entries;
540 
541  CLHEP::RandFlat flat(fEngine);
542 
543  mf::LogDebug("AddGeniEventsToArt") << "#### AddGenieEventsToArt::produce "
544  << "attempt to get " << n << " entries "
545  << "from " << fDistName << " distribution";
546  //std::ostringstream msg;
547  //msg << "add indx to list: \n";
548  while ( entries.size() != n ) {
549  if ( ! fRandomEntries ) {
550  // going through file sequentially
551  ++fLastUsedMCRec;
552  // fLsatUseMCRec is size_t so never less than zero
554  entries.push_back(fLastUsedMCRec);
555  //msg << " [" << entries.size()-1 << "] = "
556  // << fLastUsedMCRec << '\n';
557  } else {
558  size_t indx = flat.fireInt(fNumMCRec);
559  // ensure it isn't already there ..
560  if ( std::find(entries.begin(),entries.end(),indx) != entries.end() ) {
561  // mf::LogInfo("AddGeniEventsToArt") << "rejecting "
562  // << indx << " as already there";
563  } else {
564  entries.push_back(indx);
565  //msg << " [" << entries.size()-1 << "] = "
566  // << indx << '\n';
567  }
568  }
569  }
570  //mf::LogInfo("AddGeniEventsToArt") << "entries.size " << entries.size()
571  // << " " << msg.str();
572 
573  for (size_t i=0; i<n; ++i) {
574  simb::MCTruth mctruth;
575  simb::GTruth gtruth;
576  simb::MCFlux mcflux;
577 
578  size_t ientry = entries[i];
579  mf::LogDebug("AddGenieEventsToArt")
580  << "Event: " << i << " - Using entry " << ientry << std::endl;
581  fMCRec->Clear(); // don't leak previously fetched info
582  // fetch a single entry from GENIE input file
583  fGTreeChain->GetEntry(ientry);
584  genie::EventRecord* grec = fMCRec->event;
585 
586  if (fRndDist == kRootino) {
587  // check for end-condition
588  // exactly 1 particle which is a rootino (pdg=0)
589  if ( grec->GetEntries() == 1 ) {
590  genie::GHepParticle* p = grec->Particle(0);
591  if ( p && p->Pdg() == 0 ) {
592  // update where we left off
593  fLastUsedMCRec = ientry;
594  // we're done with the loop, don't go on
595  // and don't add this marker to the art event record
596  break;
597  }
598  }
599  }
600 
601  /*
602  mf::LogInfo("AddGenieEventsToArt")
603  << "#### AddGenieEventsToArt::produce " << i+1 << " of " << n
604  << " using entry " << ientry
605  << std::endl;
606  */
607 
608  if ( fOutputStream ) {
609  // alas not currently able to get current setting
610 #if __GENIE_RELEASE_CODE__ >= GRELCODE(3,0,2)
611  int plevel = genie::GHepRecord::GetPrintLevel(); //
612 #endif
613  genie::GHepRecord::SetPrintLevel(fOutputPrintLevel); //
614  //std::cerr << "#### AddGenieEventsToArt::produce() writing to "
615  // << fOutputDumpFileName
616  // << std::endl << std::flush;
617  *fOutputStream << *fMCRec;
618  fOutputStream->flush();
619 #if __GENIE_RELEASE_CODE__ >= GRELCODE(3,0,2)
620  genie::GHepRecord::SetPrintLevel(plevel);
621 #endif
622  }
623 
624  // generate offset in time
625  double evtTimeOffset = fGlobalTimeOffset + fTimeShifter->TimeOffset();
626 
627  // offset vertex position
628  double xoff = flat.fire(fXlo,fXhi);
629  double yoff = flat.fire(fYlo,fYhi);
630  double zoff = flat.fire(fZlo,fZhi);
631 
632  TLorentzVector vtxOffset(xoff,yoff,zoff,evtTimeOffset);
633 
634  // convert to simb:: ART objects using GENIE2ART functions
635  evgb::FillMCTruth(grec,vtxOffset,mctruth,
636  fParams().inputGenieVersion(),
637  fParams().inputGenieTune(),
638  fParams().addGenieVtxTime());
639  evgb::FillGTruth(grec,gtruth);
640 
641  if ( fAddMCFlux ) {
643  double dk2gen = -99999.;
645  } else if ( fGSimpleNtpEntry ) {
646  // cheat at meta data for now ...
647  // should be pulling this from input file ... no sure that
648  // it is being copied correctly
649  // (TChain isn't made of GSimpleNtpMeta objs ... )
650  // we need to know how to interpret the Aux variablees
651  static genie::flux::GSimpleNtpMeta* meta = 0;
652  if ( ! meta ) {
653  meta = new genie::flux::GSimpleNtpMeta;
654  // hopefully this is the layout
655  // aux ints: tgen
656  // aux doubles: fgXYWgt nimpwt muparpx muparpy muparpz mupare necm
657  meta->auxintname.push_back("tgen");
658  meta->auxdblname.push_back("fgXYWgt");
659  meta->auxdblname.push_back("nimpwt");
660  meta->auxdblname.push_back("muparpx");
661  meta->auxdblname.push_back("muparpy");
662  meta->auxdblname.push_back("muparpz");
663  meta->auxdblname.push_back("mupare");
664  meta->auxdblname.push_back("necm");
665  }
667  fGSimpleNtpAux,meta,mcflux);
668  } else if ( fDk2Nu ) {
670  }
671  }
672 
673  /*
674  genie::NtpMCRecHeader rec_header = fMCRec->hdr;
675  //LOG("gevdump", pNOTICE)
676  std::cout
677  << " ** Event: " << rec_header.ievent // implicit newline in print
678  << *grec;
679  // add to our collections
680  */
681 
682  mctruthcol->push_back(mctruth);
683  gtruthcol->push_back(gtruth);
684  if (fAddMCFlux) {
685  // deterimine if there is something to fetch
686  mcfluxcol->push_back(mcflux);
687  }
688 
689  // LArSoft #include "lardata/Utilities/AssociationUtil.h"
690  // NOVA #include "Utilities/AssociationUtil.h"
691  // these util::CreateAssn are taken from LArSoft's GENIEGen_module
692  // ~/Work/DUNE/code/larsim/larsim/EventGenerator/GENIE/GENIEGen_module.cc
693  // this seems to be MARK CreateAssn_07 ?? but that's one-to-many
694  // implicit in this is a indx=UNIT_MAX arg so this is only acting
695  // on the last element of truthcol
696 
697  evgb::util::CreateAssn(*this, evt, *mctruthcol, *gtruthcol, *tgassn,
698  gtruthcol->size()-1, gtruthcol->size());
699 
700  if (fAddMCFlux) {
701  evgb::util::CreateAssn(*this, evt, *mctruthcol, *mcfluxcol, *tfassn,
702  mcfluxcol->size()-1, mcfluxcol->size());
703  }
704  //
705 
706  } // done collecting input
707 
708  //std::cerr << "AddGenieEventsToArt::produce put into event"
709  // << std::endl << std::flush;
710 
711  // put the collections in the event
712  evt.put(std::move(mctruthcol));
713  evt.put(std::move(gtruthcol));
714  evt.put(std::move(tgassn));
715  if ( fAddMCFlux ) {
716  evt.put(std::move(mcfluxcol));
717  evt.put(std::move(tfassn));
718  }
719 
720 }
721 
722 //-------------------------------------------------------------------------
724 {
725  // Parse countConfig to get parameters on how many to add
726  // Should be one of these:
727  // "fixed:" <N>
728  // "flat: <Nmin> <Nmax>"
729  // "poisson: <Nmean>"
730  // "poisson-1: <Nmean>"
731  // "gauss: <mean> <rms>"
732  // "rootino: <maxentries>" # pick an upper limit
733 
734  std::string str = fParams().countConfig();
735 
736  // let user use whatever case they like
737  std::transform(str.begin(),str.end(),str.begin(),::tolower);
738  // trim any leading whitespace
739  if( str.find_first_not_of(" \t\n") != 0)
740  str.erase( 0, str.find_first_not_of(" \t\n") );
741 
742  size_t i = str.find_first_of(" \t\n");
743  fDistName = str.substr(0,i);
744  str.erase(0,i);
745 
746  // now 'str' should have 1 or 2 numerical values
747  // special case rootino allowed to have no numerical values
748 
749  int nf = sscanf(str.c_str(),"%lf %lf",&fRndP1,&fRndP2);
750 
751  if ( nf == 0 && fDistName.find("rootino") != 0 ) {
752  mf::LogError("AddGenieEventsToArt")
753  << "ParseCountConfig " << str
754  << " had " << nf << " args, expected something '"
755  << str << "'"<< std::endl;
756  throw cet::exception("badDist countConfig")
757  << __FILE__ << ":" << __LINE__
758  << " badDist '" << str << "'";
759  }
760 
761  if ( fDistName.find("fix") == 0 || fDistName == "n" || fDistName == "n:" ) {
762  fRndDist = kFixed;
763  if ( nf != 1 ) {
764  mf::LogError("AddGenieEventsToArt")
765  << "ParseCountConfig " << fDistName
766  << " had 2 args, expected 1: '"
767  << str << "', ignoring 2nd" << std::endl;
768  }
769  } else if ( fDistName.find("flat") == 0 ) {
770  fRndDist = kFlat;
771  if ( nf == 1 ) fRndP2 = fRndP1;
772  // make sure they're ordered
773  if ( fRndP2 < fRndP1 ) std::swap(fRndP1,fRndP2);
774 
775  } else if ( fDistName.find("poiss") == 0 ) {
776  fRndDist = kPoisson;
777  if ( fDistName.find("-1") != std::string::npos ) fRndDist = kPoissonMinus1;
778  if ( nf != 1 ) {
779  mf::LogError("AddGenieEventsToArt")
780  << "ParseCountConfig " << fDistName
781  << " had 2 args, expected 1: '"
782  << str << "', ignoring 2nd" << std::endl;
783  }
784  } else if ( fDistName.find("gaus") == 0 ) {
786  if ( nf != 2 ) {
787  mf::LogError("AddGenieEventsToArt")
788  << "ParseCountConfig " << fDistName
789  << " had " << nf << " args, expected 2: '"
790  << str << "'"<< std::endl;
791  throw cet::exception("badDist countConfig")
792  << __FILE__ << ":" << __LINE__
793  << " badDist '" << fDistName << "'";
794  }
795  } else if ( fDistName.find("rootino") == 0 ) {
796  fRndDist = kRootino;
797  if ( fRndP1 < 1 ) fRndP1 = 9999;
798  if ( fRandomEntries ) {
799  mf::LogError("AddGenieEventsToArt")
800  << "ParseCountConfig " << fDistName
801  << " 'distribution' is incompatible with randomEntries=true"
802  << std::endl;
803  throw cet::exception("badDist incompatible DistConfig")
804  << __FILE__ << ":" << __LINE__
805  << " badDist '" << fDistName << "' w/ randomEntries=true";
806  }
807  } else {
808  mf::LogError("AddGenieEventsToArt")
809  << "ParseCountConfig unknown fDistName " << fDistName
810  << " had' " << nf << " args '"
811  << str << "'"<< std::endl;
812  throw cet::exception("unknownDist countConfig")
813  << __FILE__ << ":" << __LINE__
814  << " unknown '" << fDistName << "'";
815  }
816 
817  mf::LogInfo("AddGenieEventsToArt")
818  << "ParseCountConfig label='" << fMyModuleLabel << "'"
819  << " fDistName='" << fDistName << "' (int)"
820  << (int)fRndDist << "; cfgstr '" << str << "' --> "
821  << " p1 " << fRndP1 << " p2 " << fRndP2 << " nf " << nf
822  << std::endl;
823 
824 #if 0
825  // test how fireInt() works ...
826  static bool first = true;
827  if ( first ) {
828  CLHEP::RandFlat flatTest(fEngine); // pass by ref, doesn't own
829  first = false;
830  for (int rtest = 0; rtest < 5; ++rtest ) {
831  std::cout << " ======= testing CLHEP::RandFlat::fireInt("
832  << rtest << ") =======" << std::endl;
833  for (int i=0; i<100; ++i)
834  std::cout << " " << flatTest.fireInt(rtest);
835  std::cout << std::endl;
836  }
837  }
838 #endif
839 
840 }
841 
843 {
844 
845  size_t nchosen = 0;
846 
847  switch ( fRndDist ) {
848  case kFixed:
849  {
850  nchosen = fRndP1; // nothing random about it
851  }
852  break;
853  case kFlat:
854  {
855  CLHEP::RandFlat flat(fEngine); // pass by ref, doesn't own
856  // couldn't find good documentation on how this worked ... empirically
857  // fireInt(0) & fireInt(1) give 0 always
858  // fireInt(2) gives 0 or 1
859  // fireInt(3) gives 0, 1, 2
860  // fireInt(4) gives 0, 1, 2, 3
861  // ...
862  // so for p1=5, p2=7 we want 5 + [0:2] i.e 5+0=5, 5+1=6, 5+2=7
863  // and thus range should be 3
864  int range = (int)(fRndP2-fRndP1) + 1;
865  nchosen = fRndP1 + flat.fireInt(range);
866  }
867  break;
868  case kPoisson:
869  case kPoissonMinus1:
870  {
871  CLHEP::RandPoisson poisson(fEngine);
872  nchosen = poisson.fire(fRndP1);
873  if ( fRndDist == kPoissonMinus1 ) {
874  if ( nchosen > 0 ) --nchosen;
875  else {
876  mf::LogError("AddGenieEventsToArt")
877  << "fRndDist[type=" << (int)fRndDist
878  << "] '" << fParams().timeConfig() << "' "
879  << " nchosen " << nchosen
880  << " can't subtract 1 for kPoissonMinus1"
881  << std::endl;
882  }
883  }
884  }
885  break;
886  case kGaussian:
887  {
888  CLHEP::RandGauss gauss(fEngine);
889  double tmp = gauss.fire(fRndP1,fRndP2);
890  if ( tmp > 0 ) nchosen = (size_t)(tmp);
891  else {
892  nchosen = 0;
893  mf::LogError("AddGenieEventsToArt")
894  << "fRndDist[type=" << (int)fRndDist
895  << "] '" << fParams().timeConfig() << "' "
896  << " tmp " << tmp
897  << "; can't return < 0 for kGaussian, return 0"
898  << std::endl;
899  }
900  }
901  break;
902  case kRootino:
903  {
904  nchosen = fRndP1; // pre-chosen maximum
905  }
906  break;
907  default:
908  {
909  nchosen = 0;
910  mf::LogError("AddGenieEventsToArt")
911  << "fRndDist[type=" << (int)fRndDist
912  << "] '" << fParams().timeConfig() << "' not handled"
913  << std::endl;
914  }
915  }
916 
917  /*
918  mf::LogInfo("AddGenieEventsToArt")
919  << "fRndDist[type=" << (int)fRndDist
920  << "] '" << fParams().timeConfig() << "' "
921  << " nchosen " << nchosen << std::endl;
922  */
923 
924  return nchosen;
925 }
926 
927 //-------------------------------------------------------------------------
929 {
930  std::string timeConfig = fParams().timeConfig();
931  // trim any leading whitespace
932  if( timeConfig.find_first_not_of(" \t\n") != 0)
933  timeConfig.erase( 0, timeConfig.find_first_not_of(" \t\n") );
934 
935  size_t i = timeConfig.find_first_of(": \t\n");
936  std::string timeName = timeConfig.substr(0,i);
937  timeConfig.erase(0,i);
938 
939  mf::LogInfo("AddGenieEventsToArt")
940  << "ParseTimeConfig label='" << fMyModuleLabel << "'"
941  << " name='" << timeName << "'"
942  << " cfg='" << timeConfig << "'" << std::endl;
943  if ( timeName == "none" ) timeName = "evgb::EvtTimeNone";
944  if ( timeName == "flat" ) timeName = "evgb::EvtTimeFlat";
945  if ( timeName == "numi" || timeName == "NuMI" ||
946  timeName == "fnal" || timeName == "FNAL" )
947  timeName = "evgb::EvtTimeFNALBeam";
948  if ( timeName == "Booster" || timeName == "booster" )
949  timeName = "evgb::EvtTimeFNALBeam Booster";
950 
951  evgb::EvtTimeShiftFactory& timeFactory =
953  fTimeShifter = timeFactory.GetEvtTimeShift(timeName,timeConfig);
954 
955  if ( fTimeShifter ) {
957  } else {
958  timeFactory.Print();
959  throw cet::exception("BAD TimeShifter")
960  << __FILE__ << ":" << __LINE__
961  << " unknown '" << timeName << "'";
962  }
963 }
964 
965 //-------------------------------------------------------------------------
967 {
968  fXlo = fParams().vtxOffsets().xlo();
969  fYlo = fParams().vtxOffsets().ylo();
970  fZlo = fParams().vtxOffsets().zlo();
971  fXhi = fParams().vtxOffsets().xhi();
972  fYhi = fParams().vtxOffsets().yhi();
973  fZhi = fParams().vtxOffsets().zhi();
974 
975  if ( fXlo != 0 && fYlo != 0 && fZlo != 0 &&
976  fXhi != 0 && fYhi != 0 && fZhi != 0 ) {
977  mf::LogInfo("AddGenieEventsToArt")
978  << "ParseVtxOffsetConfig label='" << fMyModuleLabel << "' \n"
979  << " x [" << std::setw(11) << fXlo << " "
980  << std::setw(11) << fXhi << " ]\n"
981  << " y [" << std::setw(11) << fYlo << " "
982  << std::setw(11) << fYhi << " ]\n"
983  << " z [" << std::setw(11) << fZlo << " "
984  << std::setw(11) << fZhi << " ]";
985  }
986 
987 }
988 //-------------------------------------------------------------------------
989 
990 /*
991 void evg::AddGenieEventsToArt::reconfigure(const Parameters & params)
992 {
993  fParams = params;
994 }
995 */
996 
997 /*
998 void evg::AddGenieEventsToArt::beginJob()
999 {
1000  // Implementation of optional member function here.
1001 }
1002 
1003 void evg::AddGenieEventsToArt::beginRun(art::Run & r)
1004 {
1005  // Implementation of optional member function here.
1006 }
1007 
1008 void evg::AddGenieEventsToArt::beginSubRun(art::SubRun & sr)
1009 {
1010  // Implementation of optional member function here.
1011 }
1012 
1013 void evg::AddGenieEventsToArt::endJob()
1014 {
1015  // Implementation of optional member function here.
1016 }
1017 
1018 void evg::AddGenieEventsToArt::endRun(art::Run & r)
1019 {
1020  // Implementation of optional member function here.
1021 }
1022 
1023 void evg::AddGenieEventsToArt::endSubRun(art::SubRun & sr)
1024 {
1025  // Implementation of optional member function here.
1026 }
1027 
1028 void evg::AddGenieEventsToArt::reconfigure(fhicl::ParameterSet const & p)
1029 {
1030  // Implementation of optional member function here.
1031  std::cerr << "evg::AddGenieEventsToArt::reconfigure() not implemented"
1032  << std::endl;
1033  abort();
1034 }
1035 
1036 void evg::AddGenieEventsToArt::respondToCloseInputFile(art::FileBlock const & fb)
1037 {
1038  // Implementation of optional member function here.
1039 }
1040 
1041 void evg::AddGenieEventsToArt::respondToCloseOutputFiles(art::FileBlock const & fb)
1042 {
1043  // Implementation of optional member function here.
1044 }
1045 
1046 void evg::AddGenieEventsToArt::respondToOpenInputFile(art::FileBlock const & fb)
1047 {
1048  // Implementation of optional member function here.
1049 }
1050 
1051 void evg::AddGenieEventsToArt::respondToOpenOutputFiles(art::FileBlock const & fb)
1052 {
1053  // Implementation of optional member function here.
1054 }
1055 */
1056 
base_engine_t & createEngine(seed_t seed)
void FillMCTruth(const genie::EventRecord *grec, double spillTime, simb::MCTruth &mctruth, const std::string &genieVersion="unknown", const std::string &genieTune="unknown", bool addGenieVtxTime=false, const std::unordered_map< std::string, std::string > genConfig={})
Definition: GENIE2ART.cxx:182
std::vector< std::string > fFileList
GENIE neutrino interaction simulation objects.
Definition: GENIE2ART.h:19
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
void FillMCFlux(genie::GFluxI *fdriver, simb::MCFlux &mcflux)
Definition: GENIE2ART.cxx:834
genie::flux::GSimpleNtpEntry * fGSimpleNtpEntry
enum evg::AddGenieEventsToArt::EDistrib RndDist_t
unsigned int GetRandomNumberSeed()
Definition: evgenbase.h:22
Functions for transforming GENIE objects into ART objects (and back)
Float_t tmp
Definition: plot.C:35
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
CLHEP::HepRandomEngine & fEngine
object containing MC flux information
interface for event time distribution
Definition: EvtTimeShiftI.h:29
PutHandle< PROD > put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
Definition: Event.h:77
AddGenieEventsToArt(const Parameters &p)
genie::flux::GSimpleNtpAux * fGSimpleNtpAux
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:65
bool CreateAssn(PRODUCER const &prod, art::Event &evt, std::vector< T > const &a, art::Ptr< U > const &b, art::Assns< U, T > &assn, std::string a_instance, size_t indx=UINT_MAX)
Creates a single one-to-one association.
virtual void PrintConfig(bool verbose=true)=0
provide a means of printing the configuration
auto const & get_PSet() const
Definition: ProducerTable.h:47
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
genie::NtpMCEventRecord * fMCRec
A class for generating concrete EvtTimeShiftI derived classes based on the factory pattern...
genie::flux::GSimpleNtpNuMI * fGSimpleNtpNuMI
static EvtTimeShiftFactory & Instance()
Char_t n[5]
virtual double TimeOffset()=0
void FillGTruth(const genie::EventRecord *grec, simb::GTruth &gtruth)
Definition: GENIE2ART.cxx:391
TCEvent evt
Definition: DataStructs.cxx:8
Event generator information.
Definition: MCTruth.h:32
Float_t e
Definition: plot.C:35
void produce(art::Event &e) override
genie::flux::GNuMIFluxPassThroughInfo * fGNuMIFluxPassThroughInfo
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
evgb::EvtTimeShiftI * GetEvtTimeShift(const std::string &name, const std::string &config="") const