104 std::shared_ptr<GTrackProvenance> provenance) :
108 track_provenance(std::move(provenance)) {
109 const auto thread_id = G4Threading::G4GetThreadId();
110 const auto desc =
"GEventAction " + std::to_string(thread_id);
119 const auto dash = spec.find(
'-');
120 std::string n_part = dash == std::string::npos ? spec : spec.substr(0, dash);
121 std::string nth_part = dash == std::string::npos ? std::string() : spec.substr(dash + 1);
124 int nthreads =
goptions->getScalarInt(
"nthreads");
125 const int ncores = G4Threading::G4GetNumberOfCores();
126 if (nthreads == 0 || nthreads > ncores) nthreads = ncores;
129 if (!to_non_negative_int(n_part, n) || n == 0) {
132 " : N must be a positive integer.");
134 else if (dash != std::string::npos) {
136 if (!to_non_negative_int(nth_part, nth) || nth >= nthreads) {
139 " : thread id must be in [0, ", nthreads - 1,
"].");
143 log_every_thread = nth;
146 else { log_every_n = n; }
186 if (run_action ==
nullptr) {
188 " run_action is null - cannot access digitization routines or streamers.");
193 run_action->increment_run_events_processed();
195 const auto thread_id = G4Threading::G4GetThreadId();
196 const auto event_id =
event->GetEventID();
198 auto gevent_header = std::make_unique<GEventHeader>(
goptions, event_id, thread_id);
199 auto eventDataCollection = std::make_shared<GEventDataCollection>(
goptions, std::move(gevent_header));
200 eventDataCollection->setGeneratedParticles(
202 eventDataCollection->setGeneratedTrackedParticles(
205 auto*
const hcs_this_event =
event->GetHCofThisEvent();
206 if (hcs_this_event ==
nullptr) {
207 if (!eventDataCollection->getGeneratedParticles().empty() ||
208 !eventDataCollection->getGeneratedTrackedParticles().empty()) {
209 publish_event_data(eventDataCollection);
214 const auto digi_map = run_action->get_digitization_routines_map();
215 if (digi_map ==
nullptr) {
217 " no digitization routines map available in thread ", thread_id);
221 bool has_event_mode_payload =
false;
222 bool has_run_mode_payload =
false;
223 const bool also_reject_true_info = scalar_bool_option_enabled(
goptions,
"also_reject_true_info");
224 std::unordered_set<int> ancestor_track_ids;
228 for (G4int hci = 0; hci < hcs_this_event->GetNumberOfCollections(); ++hci) {
229 auto*
const this_ghc =
static_cast<GHitsCollection*
>(hcs_this_event->GetHC(hci));
230 if (this_ghc ==
nullptr) {
234 const std::string hcSDName = this_ghc->GetSDname();
239 " for event number ", event_id,
240 " for collection number ", hci + 1,
241 " collection name: ", hcSDName);
244 const auto it = digi_map->find(hcSDName);
245 if (it == digi_map->end()) {
247 " no digitization routine registered for collection ", hcSDName,
248 " in thread ", thread_id);
252 const auto& digitization_routine = it->second;
253 if (digitization_routine ==
nullptr) {
255 " digitization routine is null for collection ", hcSDName,
256 " in thread ", thread_id);
260 const auto collection_mode = digitization_routine->collection_mode();
261 size_t accepted_hit_index = 0;
265 for (
size_t hitIndex = 0; hitIndex < this_ghc->GetSize(); ++hitIndex) {
267 auto*
const this_hit =
static_cast<GHit*
>(this_ghc->GetHit(hitIndex));
268 if (this_hit ==
nullptr) {
271 if (save_all_ancestors) {
272 const auto track_ids = this_hit->getTids();
273 ancestor_track_ids.insert(track_ids.begin(), track_ids.end());
276 auto digi_data = no_digitized ? nullptr : digitization_routine->digitizeHit(this_hit, hitIndex);
277 bool hit_accepted = digi_data !=
nullptr;
283 const bool skip_threshold = digitization_routine->apply_thresholds(this_hit, digi_data.get());
284 const bool skip_efficiency = digitization_routine->apply_efficiency(this_hit, digi_data.get());
285 if (skip_threshold || skip_efficiency) {
287 hit_accepted =
false;
291 if (collection_mode == CollectionMode::event) {
293 ++accepted_hit_index;
294 digi_data->includeVariable(
"hitn",
static_cast<int>(accepted_hit_index));
295 run_action->record_analysis_digitized(hcSDName, *digi_data);
296 eventDataCollection->addDetectorDigitizedData(hcSDName, std::move(digi_data));
297 has_event_mode_payload =
true;
300 else if (collection_mode == CollectionMode::run) {
302 run_action->record_analysis_digitized(hcSDName, *digi_data);
303 run_action->collect_event_data_collections(
305 std::move(digi_data));
306 has_run_mode_payload =
true;
312 const bool collect_true = !no_true_info &&
313 (no_digitized || hit_accepted || !also_reject_true_info) &&
314 (collection_mode == CollectionMode::event || run_action->analysis_enabled());
316 const size_t output_hit_index = collection_mode == CollectionMode::event && hit_accepted
317 ? accepted_hit_index : hitIndex + 1;
318 auto true_data = digitization_routine->collectTrueInformation(this_hit, output_hit_index);
319 if (save_original_track && track_provenance !=
nullptr && true_data !=
nullptr) {
320 const int tid = this_hit->getTid();
321 const G4ThreeVector op = track_provenance->originalTrackMomentum(tid);
322 true_data->includeVariable(
"otid", track_provenance->originalTrackId(tid));
323 true_data->includeVariable(
"opid", track_provenance->originalTrackPid(tid));
324 true_data->includeVariable(
"opx", op.getX());
325 true_data->includeVariable(
"opy", op.getY());
326 true_data->includeVariable(
"opz", op.getZ());
328 if (true_data !=
nullptr) { run_action->record_analysis_true(hcSDName, *true_data); }
329 if (collection_mode == CollectionMode::event) {
330 eventDataCollection->addDetectorTrueInfoData(hcSDName, std::move(true_data));
331 has_event_mode_payload =
true;
337 if (save_all_ancestors && track_provenance !=
nullptr) {
338 eventDataCollection->setAncestors(
339 make_ancestor_bank(track_provenance->ancestorsForTracks(ancestor_track_ids)));
343 if (has_run_mode_payload) {
344 run_action->increment_run_events_with_payload();
348 if (has_event_mode_payload ||
349 !eventDataCollection->getAncestors().empty() ||
350 !eventDataCollection->getGeneratedParticles().empty() ||
351 !eventDataCollection->getGeneratedTrackedParticles().empty()) {
352 publish_event_data(eventDataCollection);
std::vector< GParticleRecord > GParticleRecordEvent