larg4Main_module.cc
Go to the documentation of this file.
1 // larg4Main is the main producer module for Geant.
2 
3 // larg4Main_module.cc replicates many GEANT programs' @main()@ driver. It
4 // creates and initializes the run manager, controls the beginning and end of
5 // events.
6 
9 
10 // Art includes
15 
16 // Local includes (like actions)
17 #include "artg4tk/geantInit/ArtG4DetectorConstruction.hh"
18 #include "artg4tk/geantInit/ArtG4RunManager.hh"
19 
20 // The actions
21 #include "artg4tk/geantInit/ArtG4EventAction.hh"
22 #include "artg4tk/geantInit/ArtG4PrimaryGeneratorAction.hh"
23 #include "artg4tk/geantInit/ArtG4StackingAction.hh"
24 #include "artg4tk/geantInit/ArtG4SteppingAction.hh"
25 #include "artg4tk/geantInit/ArtG4TrackingAction.hh"
26 #include "larg4/pluginActions/MCTruthEventAction_service.h" // combined actions.
27 #include "larg4/pluginActions/ParticleListAction_service.h" // combined actions.
28 
29 // Services
32 #include "artg4tk/services/ActionHolder_service.hh"
33 #include "artg4tk/services/DetectorHolder_service.hh"
34 #include "artg4tk/services/PhysicsListHolder_service.hh"
35 
36 // art extensions
39 #include "nug4/ParticleNavigation/ParticleList.h"
40 #include "nurandom/RandomUtils/NuRandomService.h"
41 
42 #include "Geant4/G4UImanager.hh"
43 #include "Geant4/G4UIterminal.hh"
44 
45 #include <string>
46 
47 using MCTruthCollection = std::vector<simb::MCTruth>;
48 
49 namespace larg4 {
50 
51  // Define the producer
52  class larg4Main : public art::EDProducer {
53  public:
54  explicit larg4Main(fhicl::ParameterSet const& p);
55  ~larg4Main();
56 
57  private:
58  void produce(art::Event& e) override;
59  void beginJob() override;
60  void beginRun(art::Run& r) override;
61  void endRun(art::Run&) override;
62 
63  std::vector<art::Handle<MCTruthCollection>> inputCollections(art::Event const& e) const;
64 
65  // Our custom run manager
66  static std::unique_ptr<artg4tk::ArtG4RunManager> runManager_;
67 
68  // G4 session and managers
69  G4UIsession* session_{nullptr};
70  G4UImanager* UI_{nullptr};
71 
72  // Pseudorandom engine seed (originally hardcoded to 12345),
73  // obtained from the configuration file.
74  // Note: the maximum seed value is 9e8, which is potentially larger
75  // than a long can hold.
76  long seed_;
77 
78  // Directory path(s), in colon-delimited list, in which we should look for
79  // macros, or the name of an environment variable containing that path.
80  // Contains only the $FW_SEARCH_PATH by default, which contains some basic
81  // macro files, but can be set by config file
83 
84  // And a tool to find files along that path
85  // Initialized based on macroPath_.
87 
88  // Name of the Geant4 macro file, if provided
90 
91  // Input tags used to specify which MCTruth collections to use during G4
92  std::vector<art::InputTag> inputCollectionTags_;
93 
94  // Boolean to determine whether we pause execution after each event
95  // If it's true, then we do. Otherwise, we pause only after all events
96  // have been produced.
97  // False by default, can be changed by afterEvent in FHICL
98  bool pauseAfterEvent_{false};
99 
100  // Run diagnostic level (verbosity)
102 
103  // When to pop up user interface
105  bool uiAtEndEvent_{false}; // set by afterEvent in FHiCL
106 
107  // What to do at the end of the event
108  // Choices are
109  // pass -- do nothing
110  // pause -- Let user press return at the end of each event
111  // ui -- show the UI at the end of the event
113 
114  static bool initializeDetectors_;
115  static std::atomic<int> processingRun_;
116  };
117 }
118 
119 std::unique_ptr<artg4tk::ArtG4RunManager> larg4::larg4Main::runManager_{nullptr};
121 std::atomic<int> larg4::larg4Main::processingRun_{0};
122 
123 // Constructor - set parameters
125  : EDProducer{p}
126  , seed_(p.get<long>("seed", -1))
127  , macroPath_(p.get<std::string>("macroPath", "FW_SEARCH_PATH"))
129  , g4MacroFile_(p.get<std::string>("visMacro", "larg4.mac"))
130  , inputCollectionTags_{p.get<std::vector<art::InputTag>>("inputCollections", {})}
131  , rmvlevel_(p.get<int>("rmvlevel", 0))
132  , uiAtBeginRun_(p.get<bool>("uiAtBeginRun", false))
133  , afterEvent_(p.get<std::string>("afterEvent", "pass"))
134 {
135  produces<std::vector<simb::MCParticle>>();
136  produces<art::Assns<simb::MCTruth, simb::MCParticle, sim::GeneratedParticleInfo>>();
137 
138  // We need all of the services to run @produces@ on the data they will store. We do this
139  // by retrieving the holder services.
142 
143  if (initializeDetectors_) {
144  detectorHolder->initialize();
145  // Build the detectors' logical volumes
146  detectorHolder->constructAllLVs();
147  initializeDetectors_ = false;
148  }
149 
150  // And running @callArtProduces@ on each
151  actionHolder->callArtProduces(producesCollector());
152  detectorHolder->callArtProduces(producesCollector());
153 
154  // -- Check for invalid seed value
155  if (seed_ > 900000000) {
156  throw cet::exception("largeant:BadSeedValue")
157  << "The provided largeant seed value: " << seed_ << " is invalid! Maximum seed value is 9E8.";
158  }
159  // Set up the random number engine.
160  // -- D.R.: Use the NuRandomService engine for additional control over the seed generation policy
161  (void)art::ServiceHandle<rndm::NuRandomService>()->createEngine(*this, "G4Engine", p, "seed");
162 
163  // Handle the afterEvent setting
164  if (afterEvent_ == "ui") { uiAtEndEvent_ = true; }
165  else if (afterEvent_ == "pause") {
166  pauseAfterEvent_ = true;
167  }
168 }
169 
171 {
172  if (runManager_) {
173  runManager_.reset();
174  }
175 }
176 
177 void
179 {
180  mf::LogDebug("Main_Run_Manager") << "In begin job";
181  if (runManager_) {
182  return;
183  }
184  runManager_.reset(new artg4tk::ArtG4RunManager);
185 }
186 
187 void
189 {
190  if (processingRun_++ != 0) {
191  return;
192  }
193 
194  // Get the physics list and pass it to Geant and initialize the list if necessary
196  runManager_->SetUserInitialization(physicsListHolder->makePhysicsList());
197 
198  // Get all of the detectors and initialize them
199  // Declare the detector construction to Geant
200  auto detectorHolder = art::ServiceHandle<artg4tk::DetectorHolderService>().get();
201  runManager_->SetUserInitialization(
202  new artg4tk::ArtG4DetectorConstruction{detectorHolder->worldPhysicalVolume()});
203 
204  // Get all of the actions and initialize them
205  auto actionHolder = art::ServiceHandle<artg4tk::ActionHolderService>().get();
206  actionHolder->initialize();
207 
208  // Store the run in the action holder
209  actionHolder->setCurrArtRun(r);
210 
211  // Declare the primary generator action to Geant
212  runManager_->SetUserAction(new artg4tk::ArtG4PrimaryGeneratorAction{actionHolder});
213 
214  // Note that these actions (and ArtG4PrimaryGeneratorAction above) are all
215  // generic actions that really don't do much on their own. Rather, to
216  // use the power of actions, one must create action objects (derived from
217  // @ActionBase@) and register them with the Art @ActionHolder@ service.
218  // See @ActionBase@ and/or @ActionHolderService@ for more information.
219  runManager_->SetUserAction(new artg4tk::ArtG4SteppingAction{actionHolder});
220  runManager_->SetUserAction(new artg4tk::ArtG4StackingAction{actionHolder});
221  runManager_->SetUserAction(new artg4tk::ArtG4EventAction{actionHolder, detectorHolder});
222  runManager_->SetUserAction(new artg4tk::ArtG4TrackingAction{actionHolder});
223 
224  runManager_->Initialize();
225  physicsListHolder->initializePhysicsList();
226 
227  //get the pointer to the User Interface manager
228  UI_ = G4UImanager::GetUIpointer();
229 
230  // Find the macro (or try to) along the directory path.
231  std::string macroLocation = "";
232  bool macroWasFound = pathFinder_.find_file(g4MacroFile_, macroLocation);
233  mf::LogInfo("larg4Main") << "Finding path for " << g4MacroFile_ << "...\nSearch "
234  << (macroWasFound ? "successful " : "unsuccessful ") << "and path is: \n"
235  << macroLocation;
236 
237  // Execute the macro if we were able to find it
238  if (macroWasFound) {
239  // Create the string containing the execution command
240  mf::LogInfo("larg4Main") << "Executing macro: " << g4MacroFile_;
241  std::string commandToExecute = "/control/execute ";
242  commandToExecute.append(macroLocation);
243  UI_->ApplyCommand(commandToExecute);
244  }
245  else {
246  mf::LogInfo("larg4Main") << "Unable to find " << g4MacroFile_ << " in the path(s) "
247  << macroPath_;
248  }
249 
250  // Open a UI if asked
251  if (uiAtBeginRun_) {
252  session_ = new G4UIterminal;
253  session_->SessionStart();
254  delete session_;
255  }
256 
257  // Start the Geant run!
258  runManager_->BeamOnBeginRun(r.id().run());
259 }
260 
261 // Produce the Geant event
262 void
264 {
265  // The holder services need the event
268 
269  auto const mclists = inputCollections(e);
270  art::ServiceHandle<larg4::MCTruthEventActionService>()->setInputCollections(mclists);
271 
273  pla->setInputCollections(mclists);
274  auto const pid = e.getProductID<std::vector<simb::MCParticle>>();
275  pla->setPtrInfo(pid, e.productGetter(pid));
276 
277  runManager_->BeamOnDoOneEvent(e.id().event());
278  runManager_->BeamOnEndEvent();
279 
280  e.put(pla->ParticleCollection());
281  e.put(pla->AssnsMCTruthToMCParticle());
282 }
283 
284 void
286 {
287  if (--processingRun_ != 0) {
288  return;
289  }
290 
291  runManager_->BeamOnEndRun();
292 }
293 
294 std::vector<art::Handle<MCTruthCollection>>
296 {
298  return e.getMany<std::vector<simb::MCTruth>>();
299  }
300 
301  std::vector<art::Handle<MCTruthCollection>> result;
302  for (auto const& tag : inputCollectionTags_) {
303  result.push_back(e.getHandle<MCTruthCollection>(tag));
304  }
305  return result;
306 }
307 
static bool initializeDetectors_
G4UImanager * UI_
static std::atomic< int > processingRun_
void endRun(art::Run &) override
RunID id() const
Definition: Run.cc:17
static QCString result
ProductID getProductID(std::string const &instance_name="") const
Definition: DataViewImpl.h:338
Handle< PROD > getHandle(SelectorBase const &) const
Definition: DataViewImpl.h:382
std::string string
Definition: nybbler.cc:12
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
static std::unique_ptr< artg4tk::ArtG4RunManager > runManager_
void produce(art::Event &e) override
std::vector< art::Handle< MCTruthCollection > > inputCollections(art::Event const &e) const
EDProducer(fhicl::ParameterSet const &pset)
Definition: EDProducer.h:20
G4UIsession * session_
cet::search_path pathFinder_
Geant4 interface.
std::unique_ptr< std::vector< simb::MCParticle > > ParticleCollection()
Particle class.
RunNumber_t run() const
Definition: RunID.h:64
Utility functions to print MC truth information.
Definition: Run.h:17
std::unique_ptr< art::Assns< simb::MCTruth, simb::MCParticle, sim::GeneratedParticleInfo > > AssnsMCTruthToMCParticle()
std::string afterEvent_
const double e
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
void beginJob() override
void setInputCollections(std::vector< art::Handle< std::vector< simb::MCTruth >>> const &mclists)
std::vector< Handle< PROD > > getMany(SelectorBase const &selector=MatchAllSelector{}) const
Definition: DataViewImpl.h:479
Use Geant4&#39;s user "hooks" to maintain a list of particles generated by Geant4.
EDProductGetter const * productGetter(ProductID const pid) const
p
Definition: test.py:223
std::vector< simb::MCTruth > MCTruthCollection
ProductID put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
Definition: DataViewImpl.h:686
std::string g4MacroFile_
std::vector< art::InputTag > inputCollectionTags_
ProducesCollector & producesCollector() noexcept
Contains data associated to particles from detector simulation.
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
std::string find_file(std::string const &filename) const
Definition: search_path.cc:96
EventNumber_t event() const
Definition: EventID.h:116
void beginRun(art::Run &r) override
larg4Main(fhicl::ParameterSet const &p)
std::string macroPath_
void setPtrInfo(art::ProductID pid, art::EDProductGetter const *productGetter)
EventID id() const
Definition: Event.cc:34
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
Definition: StdUtils.h:97