17#include "G4GeometryManager.hh"
18#include "G4UImanager.hh"
19#include "G4RunManager.hh"
24void closeOpenGeometryBeforeBeamOn(
const std::shared_ptr<GLogger>& log) {
25 auto* geometryManager = G4GeometryManager::GetInstanceIfExist();
26 if (!geometryManager || geometryManager->IsGeometryClosed()) {
return; }
28 log->info(1,
"Geometry is open before BeamOn; closing it before event processing.");
29 geometryManager->CloseGeometry();
38 const std::shared_ptr<const gdynamicdigitization::dRoutinesMap>& gdynamicDigitizationMap)
41 string filename = gopt->getScalarString(
"run_weights");
42 userRunno = gopt->getScalarInt(
"run");
43 neventsToProcess = gopt->getScalarInt(
"n");
47 if (gopt->doesOptionExist(
"g4view")) {
48 auto driverNode = gopt->getOptionMapInNode(
"g4view",
"driver");
49 if (!driverNode.IsNull() && driverNode.IsDefined()) {
50 offscreen_screenshots = (driverNode.as<std::string>() ==
"TOOLSSG_OFFSCREEN");
55 if (neventsToProcess == 0)
return;
59 runEvents[userRunno] = neventsToProcess;
64 ifstream in(filename.c_str());
68 "Error: can't open run weights input file >", filename,
"<. Check your spelling. Exiting.");
71 log->
info(1,
"Loading run weights from ", filename);
77 while (in >>
run >> weight) {
78 listOfRuns.push_back(
run);
79 runWeights[
run] = weight;
84 distributeEvents(neventsToProcess);
89 log->
info(0,
"EventDispenser initialized with ", neventsToProcess,
" events distributed among ",
90 runWeights.size(),
" runs:");
91 log->
info(0,
" run\t weight\t n. events");
92 for (
const auto& weight : runWeights) {
93 log->
info(0,
" ", weight.first,
"\t ", weight.second,
"\t ", runEvents[weight.first]);
103 runEvents[userRunno] = nevents_to_process;
113void EventDispenser::distributeEvents(
int nevents_to_process) {
115 random_device randomDevice;
116 mt19937 generator(randomDevice());
117 uniform_real_distribution<> randomDistribution(0, 1);
121 double totalWeight = 0;
122 for (
const auto& weight : runWeights) { totalWeight += weight.second; }
123 if (totalWeight <= 0) {
125 "Run weights sum to ", totalWeight,
" (must be > 0). Check your run weights file.");
130 for (
int i = 0; i < nevents_to_process; i++) {
131 double randomNumber = randomDistribution(generator) * totalWeight;
133 double cumulativeWeight = 0;
134 for (
const auto& weight : runWeights) {
135 cumulativeWeight += weight.second;
136 if (randomNumber <= cumulativeWeight) {
137 runEvents[weight.first]++;
149 for (
auto rEvents : runEvents) { totalEvents += rEvents.second; }
160 G4UImanager* g4uim = G4UImanager::GetUIpointer();
163 for (
auto&
run : runEvents) {
164 int runNumber =
run.first;
165 int nevents =
run.second;
168 if (runNumber != currentRunno) {
171 for (
const auto& [plugin, digiRoutine] : *gDigitizationMap) {
174 const std::string& variation = digiRoutine->getDigitizationVariation();
177 " with variation ", variation);
178 if (digiRoutine->loadConstants(runNumber, variation) ==
false) {
180 "Failed to load constants for ", plugin,
" for run ", runNumber,
" with variation ",
185 if (digiRoutine->loadTT(runNumber, variation) ==
false) {
187 "Failed to load translation table for ", plugin,
" for run ", runNumber,
188 " with variation ", variation);
191 currentRunno = runNumber;
194 log->
info(1,
"Starting run ", runNumber,
" with ", nevents,
" events.");
197 if (G4RunManager* g4rm = G4RunManager::GetRunManager()) { g4rm->SetRunIDCounter(runNumber); }
201 log->
info(1,
"Processing ", nevents,
" events in one go");
202 closeOpenGeometryBeforeBeamOn(
log);
204 if (!beamOnTime.has_value()) { beamOnTime = std::chrono::steady_clock::now(); }
205 g4uim->ApplyCommand(
"/run/beamOn " +
to_string(nevents));
211 if (offscreen_screenshots) {
212 g4uim->ApplyCommand(
"/vis/tsg/offscreen/set/size 3000 2000");
213 g4uim->ApplyCommand(
"/vis/tsg/offscreen/set/file gemc_run_" +
to_string(runNumber) +
".png");
214 g4uim->ApplyCommand(
"/vis/viewer/rebuild");
217 log->
info(1,
"Run ", runNumber,
" done with ", nevents,
" events");
void resetRunContext()
Force per-run digitization setup to run again on the next event batch.
int processEvents()
Processes all runs by initializing digitization routines and dispatching events.
EventDispenser(const std::shared_ptr< GOptions > &gopt, const std::shared_ptr< const gdynamicdigitization::dRoutinesMap > &gdynamicDigitizationMap)
Constructs an EventDispenser and prepares the run event distribution.
void setNumberOfEvents(int nevts)
Sets the total number of events to process in single-run mode.
int getTotalNumberOfEvents() const
Computes the total number of events across all runs.
std::shared_ptr< GLogger > log
void debug(debug_type type, Args &&... args) const
void info(int level, Args &&... args) const
void error(int exit_code, Args &&... args) const
Event Dispenser module error-code conventions.
#define ERR_EVENTDISTRIBUTIONFILENOTFOUND
Run-weight file could not be opened/read.
Declares the EventDispenser class.
Public declaration of the Event Dispenser module command-line / configuration options.
constexpr const char * EVENTDISPENSER_LOGGER
Logger name used by this module when creating a GLogger through the base infrastructure.
constexpr int ERR_LOADCONSTANTFAIL
constexpr int ERR_LOADTTFAIL
#define UNINITIALIZEDSTRINGQUANTITY
constexpr const char * to_string(randomModel m) noexcept