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 const auto filename = gopt->getOptionalScalarString(
"run_weights");
45 userRunno = gopt->getRequiredScalarInt(
"run");
46 neventsToProcess = gopt->getRequiredScalarInt(
"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;
61 if (!filename && neventsToProcess > 0) {
62 runEvents[userRunno] = neventsToProcess;
67 ifstream in(filename->c_str());
72 "Error: can't open run weights input file >%1<. Check your spelling. Exiting.", *filename);
75 log->info(1,
"Loading run weights from %1", *filename);
81 while (in >>
run >> weight) {
82 listOfRuns.push_back(
run);
83 runWeights[
run] = weight;
88 distributeEvents(neventsToProcess);
94 0,
"EventDispenser initialized with %1 events distributed among %2 runs:", neventsToProcess,
96 log->info(0,
" run\t weight\t n. events");
97 for (
const auto& weight : runWeights) {
98 log->info(0,
" %1\t %2\t %3", weight.first, weight.second, runEvents[weight.first]);
108 runEvents[userRunno] = nevents_to_process;
112 currentRunno.reset();
118void EventDispenser::distributeEvents(
int nevents_to_process) {
120 random_device randomDevice;
121 mt19937 generator(randomDevice());
122 uniform_real_distribution<> randomDistribution(0, 1);
126 double totalWeight = 0;
127 for (
const auto& weight : runWeights) { totalWeight += weight.second; }
128 if (totalWeight <= 0) {
131 "Run weights sum to %1 (must be > 0). Check your run weights file.", totalWeight);
136 for (
int i = 0; i < nevents_to_process; i++) {
137 double randomNumber = randomDistribution(generator) * totalWeight;
139 double cumulativeWeight = 0;
140 for (
const auto& weight : runWeights) {
141 cumulativeWeight += weight.second;
142 if (randomNumber <= cumulativeWeight) {
143 runEvents[weight.first]++;
155 for (
auto rEvents : runEvents) { totalEvents += rEvents.second; }
162 if (!currentRunno || runNumber != *currentRunno) {
165 for (
const auto& [plugin, digiRoutine] : *gDigitizationMap) {
168 const std::string& variation = digiRoutine->getDigitizationVariation();
172 runNumber, variation);
173 if (digiRoutine->loadConstants(runNumber, variation) ==
false) {
176 plugin, runNumber, variation);
180 if (digiRoutine->loadTT(runNumber, variation) ==
false) {
182 ERR_LOADTTFAIL,
"Failed to load translation table for %1 for run %2 with variation %3",
183 plugin, runNumber, variation);
186 currentRunno = runNumber;
189 if (analysisAccumulator !=
nullptr) { analysisAccumulator->setCurrentRunNumber(runNumber); }
192 if (G4RunManager* g4rm = G4RunManager::GetRunManager()) { g4rm->SetRunIDCounter(runNumber); }
194 closeOpenGeometryBeforeBeamOn(
log);
204 G4UImanager* g4uim = G4UImanager::GetUIpointer();
207 for (
auto&
run : runEvents) {
208 int runNumber =
run.first;
209 int nevents =
run.second;
212 log->info(1,
"Starting run %1 with %2 events.", runNumber, nevents);
216 log->info(1,
"Processing %1 events in one go", nevents);
218 if (!beamOnTime.has_value()) { beamOnTime = std::chrono::steady_clock::now(); }
219 g4uim->ApplyCommand(
"/run/beamOn " +
to_string(nevents));
225 if (offscreen_screenshots) {
226 g4uim->ApplyCommand(
"/vis/tsg/offscreen/set/size 3000 2000");
227 g4uim->ApplyCommand(
"/vis/tsg/offscreen/set/file gemc_run_" +
to_string(runNumber) +
".png");
228 g4uim->ApplyCommand(
"/vis/viewer/rebuild");
231 log->info(1,
"Run %1 done with %2 events", runNumber, nevents);
void prepareRun(int runNumber)
Load detector conditions and set the run context before an externally issued beamOn.
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.
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
constexpr int ERR_EVENTDISTRIBUTIONFILENOTFOUND
Run-weight file could not be opened/read.
constexpr const char * to_string(randomModel m) noexcept