8#include "G4Threading.hh"
10std::mutex GRunAction::completed_run_data_mutex;
11GRunAction::CompletedRunData GRunAction::completed_worker_run_data;
17 std::shared_ptr<gdynamicdigitization::dRoutinesMap> digi_map,
20 digitization_routines_map(std::move(digi_map)),
21 analysis_accumulator(std::move(analyzer)) {
22 const auto desc = std::to_string(G4Threading::G4GetThreadId());
28G4Run *GRunAction::GenerateRun() {
36void GRunAction::BeginOfRunAction(
const G4Run *aRun) {
37 const auto thread_id = G4Threading::G4GetThreadId();
38 const auto run = aRun->GetRunID();
40 auto run_header = std::make_unique<GRunHeader>(goptions, run, thread_id);
41 run_data = std::make_unique<GRunDataCollection>(goptions, std::move(run_header));
42 if (analysis_accumulator !=
nullptr) {
43 analysis_run_number = analysis_accumulator->currentRunNumber();
44 analysis_shard = std::make_unique<GAnalysisShard>();
47 const auto neventsThisRun = aRun->GetNumberOfEventToBeProcessed();
50 need_a_thread_streamer =
false;
51 need_a_run_streamer =
false;
55 if (digitization_routines_map !=
nullptr) {
56 for (
const auto &[plugin, digiRoutine]: *digitization_routines_map) {
57 if (digiRoutine ==
nullptr) {
59 " null digitization routine registered for plugin ", plugin);
62 if (digiRoutine->collection_mode() == CollectionMode::event) {
63 need_a_thread_streamer =
true;
64 }
else if (digiRoutine->collection_mode() == CollectionMode::run) {
65 to_normalize[plugin] = digiRoutine->variables_to_normalize();
66 need_a_run_streamer =
true;
71 " digitization_routines_map is null - streamer mode detection skipped.");
75 if (streamer_definition.type ==
"event") {
76 need_a_thread_streamer =
true;
84 if (!IsMaster() && need_a_thread_streamer) {
85 if (gstreamer_threads_map ==
nullptr) {
86 log->info(1,
"Defining thread gstreamers for run ", run,
" in thread ", thread_id);
90 if (gstreamer_threads_map ==
nullptr) {
91 log->error(1, FUNCTION_NAME,
" gstreamer_threads_map is null in thread ", thread_id,
92 " - cannot open connections.");
95 for (
const auto &[name, gstreamer]: *gstreamer_threads_map) {
96 if (gstreamer ==
nullptr) {
98 "Null GStreamer entry ", name,
" in thread ", thread_id);
101 if (!gstreamer->openConnection()) {
103 "Failed to open connection for GStreamer ", name,
104 " in thread ", thread_id);
107 log->info(2, FUNCTION_NAME,
"Worker thread [", thread_id,
"]: opening connection for ",
109 " for run ", run,
". Number of events to be processed: ", neventsThisRun);
114 else if (IsMaster() && need_a_run_streamer) {
115 if (gstreamer_run_map ==
nullptr) {
116 log->info(1,
"Defining run gstreamers for run ", run);
120 if (gstreamer_run_map ==
nullptr) {
121 log->error(1, FUNCTION_NAME,
" gstreamer_run_map is null in master thread ",
122 " - cannot open connections.");
125 for (
const auto &[name, gstreamer]: *gstreamer_run_map) {
126 if (gstreamer ==
nullptr) {
128 "Null GStreamer entry ", name,
" in master thread");
131 if (!gstreamer->openConnection()) {
133 "Failed to open connection for GStreamer in master thread ", name);
136 log->info(2, FUNCTION_NAME,
"Master Thread: opening connection for ",
138 " for run ", run,
". Number of events to be processed: ", neventsThisRun);
145void GRunAction::EndOfRunAction(
const G4Run *aRun) {
146 const auto thread_id = G4Threading::G4GetThreadId();
147 const auto runNumber = aRun->GetRunID();
148 const std::string what_am_i = IsMaster() ?
"Master" :
"Worker";
150 if (!IsMaster() && need_a_thread_streamer) {
151 if (gstreamer_threads_map ==
nullptr) {
153 " gstreamer_map is null in thread ", thread_id,
154 " - cannot close connections.");
156 for (
const auto &[name, gstreamer]: *gstreamer_threads_map) {
157 log->info(2, FUNCTION_NAME,
" ", what_am_i,
" [", thread_id,
"], for run ", runNumber,
158 " closing connection for gstreamer ", name);
160 if (gstreamer ==
nullptr) {
162 "Null GStreamer entry ", name,
" in thread ", thread_id);
165 if (!gstreamer->closeConnection()) {
166 log->error(1,
"Failed to close connection for GStreamer ", name,
" in thread ", thread_id);
173 if (analysis_accumulator !=
nullptr && analysis_shard !=
nullptr) {
174 if (!analysis_shard->empty()) { analysis_accumulator->merge(std::move(*analysis_shard)); }
175 analysis_shard.reset();
183 if (need_a_run_streamer) { stash_worker_run_data(); }
187 if (IsMaster() && need_a_run_streamer) {
190 auto completed_run_data = take_completed_worker_run_data();
191 log->info(2, FUNCTION_NAME,
192 " master collected ",
static_cast<int>(completed_run_data.size()),
193 " worker run_data object(s) for run ", runNumber);
195 std::shared_ptr<GRunDataCollection> merged_run_data;
197 for (
auto &worker_run_data: completed_run_data) {
198 if (worker_run_data ==
nullptr) {
204 if (merged_run_data ==
nullptr) {
205 auto merged_header = std::make_unique<GRunHeader>(goptions, runNumber, thread_id);
206 merged_run_data = std::make_shared<GRunDataCollection>(goptions, std::move(merged_header));
209 merged_run_data->merge(*worker_run_data);
213 if (merged_run_data !=
nullptr) {
214 publish_run_data(merged_run_data);
217 if (gstreamer_run_map ==
nullptr) {
219 " gstreamer_map is null in master thread - cannot close connections.");
222 for (
const auto &[name, gstreamer]: *gstreamer_run_map) {
223 log->info(2, FUNCTION_NAME,
" ", what_am_i,
" for run ", runNumber,
224 " closing connection for gstreamer ", name);
226 if (gstreamer ==
nullptr) {
228 "Null GStreamer entry ", name,
" in master thread");
231 if (!gstreamer->closeConnection()) {
232 log->error(1,
"Failed to close connection for GStreamer ", name,
" in master thread");
241void GRunAction::stash_worker_run_data() {
242 if (run_data ==
nullptr) {
246 std::scoped_lock lock(completed_run_data_mutex);
247 completed_worker_run_data.emplace_back(std::move(run_data));
251auto GRunAction::take_completed_worker_run_data() -> CompletedRunData {
252 std::scoped_lock lock(completed_run_data_mutex);
254 auto result = std::move(completed_worker_run_data);
255 completed_worker_run_data.clear();
262void GRunAction::publish_run_data(
const std::shared_ptr<GRunDataCollection> &run_data_collaction)
const {
263 if (run_data_collaction ==
nullptr) {
265 " run_data is null - cannot publish merged run data.");
268 if (gstreamer_run_map ==
nullptr) {
270 " no run streamer map available - run data will not be published.");
276 normalize_run_data(run_data_collaction);
278 for (
const auto &[name, gstreamer]: *gstreamer_run_map) {
279 if (gstreamer ==
nullptr) {
281 " null gstreamer instance for run streamer ", name);
284 gstreamer->publishRunData(run_data_collaction);
289void GRunAction::normalize_run_data(
const std::shared_ptr<GRunDataCollection> &run_data_collaction)
const {
290 if (run_data_collaction ==
nullptr) {
292 " run_data_collaction is null - cannot normalize run data.");
295 const int events_processed = run_data_collaction->get_events_processed();
296 if (events_processed <= 0) {
297 log->warning(FUNCTION_NAME,
298 " events_processed is ", events_processed,
299 " - skipping normalization.");
303 const double norm =
static_cast<double>(events_processed);
305 for (
auto &[sdName, dataCollection]: run_data_collaction->getMutableDataCollectionMap()) {
306 if (dataCollection ==
nullptr) {
307 log->warning(FUNCTION_NAME,
308 " detector ", sdName,
309 " has null data collection - skipping.");
313 auto &digitizedData = dataCollection->getMutableDigitizedData();
314 if (digitizedData.empty() || digitizedData.front() ==
nullptr) {
318 auto &digitized = digitizedData.front();
322 auto it = to_normalize.find(sdName);
323 if (it != to_normalize.end()) {
324 for (
const auto &varName: it->second) {
325 const auto intVars = digitized->getIntObservablesMap(0);
326 const auto intIt = intVars.find(varName);
327 if (intIt != intVars.end()) {
328 digitized->includeVariable(varName,
static_cast<double>(intIt->second) / norm);
332 const auto dblVars = digitized->getDblObservablesMap(0);
333 const auto dblIt = dblVars.find(varName);
334 if (dblIt != dblVars.end()) {
335 digitized->includeVariable(varName, dblIt->second / norm);
GBase(const std::shared_ptr< GOptions > &gopt, std::string logger_name="")
std::shared_ptr< GLogger > log
GRunAction(std::shared_ptr< GOptions > gopts, std::shared_ptr< gdynamicdigitization::dRoutinesMap > digi_map, std::shared_ptr< GAnalysisAccumulator > analysis_accumulator=nullptr)
Constructs the run action.
Thread-local run object created by the GEMC run action.
Declares GRunAction, the run-lifecycle action for the GEMC actions module.
constexpr const char * GRUNACTION_LOGGER
Declares GRun, the thread-local run container used by the GEMC actions module.
Defines error codes used by the GEMC actions module.
#define ERR_GDIGIMAP_NOT_EXISTING
#define ERR_GRUNACTION_NOT_EXISTING
#define ERR_STREAMERMAP_NOT_EXISTING
std::shared_ptr< const gstreamersMap > gstreamersMapPtr(const std::shared_ptr< GOptions > &gopts, int thread_id=-1)
vector< GStreamerDefinition > getGStreamerDefinition(const std::shared_ptr< GOptions > &gopts)