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<GOptions>& gopt,
39 const std::shared_ptr<const gdynamicdigitization::dRoutinesMap>& gdynamicDigitizationMap,
40 std::shared_ptr<GAnalysisAccumulator> analyzer)
42 analysisAccumulator(std::move(analyzer)) {
44 string filename = gopt->getScalarString(
"run_weights");
45 userRunno = gopt->getScalarInt(
"run");
46 neventsToProcess = gopt->getScalarInt(
"n");
50 if (gopt->doesOptionExist(
"g4view")) {
51 auto driverNode = gopt->getOptionMapInNode(
"g4view",
"driver");
52 if (!driverNode.IsNull() && driverNode.IsDefined()) {
53 offscreen_screenshots = (driverNode.as<std::string>() ==
"TOOLSSG_OFFSCREEN");
58 if (neventsToProcess == 0)
return;
62 runEvents[userRunno] = neventsToProcess;
67 ifstream in(filename.c_str());
71 "Error: can't open run weights input file >", filename,
"<. Check your spelling. Exiting.");
74 log->info(1,
"Loading run weights from ", filename);
80 while (in >>
run >> weight) {
81 listOfRuns.push_back(
run);
82 runWeights[
run] = weight;
87 distributeEvents(neventsToProcess);
92 log->info(0,
"EventDispenser initialized with ", neventsToProcess,
" events distributed among ",
93 runWeights.size(),
" runs:");
94 log->info(0,
" run\t weight\t n. events");
95 for (
const auto& weight : runWeights) {
96 log->info(0,
" ", weight.first,
"\t ", weight.second,
"\t ", runEvents[weight.first]);
106 runEvents[userRunno] = nevents_to_process;
116void EventDispenser::distributeEvents(
int nevents_to_process) {
118 random_device randomDevice;
119 mt19937 generator(randomDevice());
120 uniform_real_distribution<> randomDistribution(0, 1);
124 double totalWeight = 0;
125 for (
const auto& weight : runWeights) { totalWeight += weight.second; }
126 if (totalWeight <= 0) {
128 "Run weights sum to ", totalWeight,
" (must be > 0). Check your run weights file.");
133 for (
int i = 0; i < nevents_to_process; i++) {
134 double randomNumber = randomDistribution(generator) * totalWeight;
136 double cumulativeWeight = 0;
137 for (
const auto& weight : runWeights) {
138 cumulativeWeight += weight.second;
139 if (randomNumber <= cumulativeWeight) {
140 runEvents[weight.first]++;
152 for (
auto rEvents : runEvents) { totalEvents += rEvents.second; }
163 G4UImanager* g4uim = G4UImanager::GetUIpointer();
166 for (
auto&
run : runEvents) {
167 int runNumber =
run.first;
168 int nevents =
run.second;
171 if (runNumber != currentRunno) {
174 for (
const auto& [plugin, digiRoutine] : *gDigitizationMap) {
177 const std::string& variation = digiRoutine->getDigitizationVariation();
180 " with variation ", variation);
181 if (digiRoutine->loadConstants(runNumber, variation) ==
false) {
183 "Failed to load constants for ", plugin,
" for run ", runNumber,
" with variation ",
188 if (digiRoutine->loadTT(runNumber, variation) ==
false) {
190 "Failed to load translation table for ", plugin,
" for run ", runNumber,
191 " with variation ", variation);
194 currentRunno = runNumber;
197 log->info(1,
"Starting run ", runNumber,
" with ", nevents,
" events.");
198 if (analysisAccumulator !=
nullptr) { analysisAccumulator->setCurrentRunNumber(runNumber); }
201 if (G4RunManager* g4rm = G4RunManager::GetRunManager()) { g4rm->SetRunIDCounter(runNumber); }
205 log->info(1,
"Processing ", nevents,
" events in one go");
206 closeOpenGeometryBeforeBeamOn(
log);
208 if (!beamOnTime.has_value()) { beamOnTime = std::chrono::steady_clock::now(); }
209 g4uim->ApplyCommand(
"/run/beamOn " +
to_string(nevents));
215 if (offscreen_screenshots) {
216 g4uim->ApplyCommand(
"/vis/tsg/offscreen/set/size 3000 2000");
217 g4uim->ApplyCommand(
"/vis/tsg/offscreen/set/file gemc_run_" +
to_string(runNumber) +
".png");
218 g4uim->ApplyCommand(
"/vis/viewer/rebuild");
221 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, std::shared_ptr< GAnalysisAccumulator > analysisAccumulator=nullptr)
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.
GBase(const std::shared_ptr< GOptions > &gopt, std::string logger_name="")
std::shared_ptr< GLogger > log
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