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);
118 if (spec_option && !spec_option->empty()) {
119 const std::string& spec = *spec_option;
120 const auto dash = spec.find(
'-');
121 std::string n_part = dash == std::string::npos ? spec : spec.substr(0, dash);
122 std::string nth_part = dash == std::string::npos ? std::string() : spec.substr(dash + 1);
125 int nthreads =
goptions->getRequiredScalarInt(
"nthreads");
126 const int ncores = G4Threading::G4GetNumberOfCores();
127 if (nthreads == 0 || nthreads > ncores) nthreads = ncores;
130 if (!to_non_negative_int(n_part, n) || n == 0) {
133 " : N must be a positive integer.");
135 else if (dash != std::string::npos) {
137 if (!to_non_negative_int(nth_part, nth) || nth >= nthreads) {
140 " : thread id must be in [0, ", nthreads - 1,
"].");
144 log_every_thread = nth;
147 else { log_every_n = n; }
187 if (run_action ==
nullptr) {
189 " run_action is null - cannot access digitization routines or streamers.");
194 run_action->increment_run_events_processed();
196 const auto thread_id = G4Threading::G4GetThreadId();
197 const auto event_id =
event->GetEventID();
199 auto gevent_header = std::make_unique<GEventHeader>(
goptions, event_id, thread_id);
200 auto eventDataCollection = std::make_shared<GEventDataCollection>(
goptions, std::move(gevent_header));
201 eventDataCollection->setGeneratedParticles(
203 eventDataCollection->setGeneratedTrackedParticles(
206 auto*
const hcs_this_event =
event->GetHCofThisEvent();
207 if (hcs_this_event ==
nullptr) {
208 if (!eventDataCollection->getGeneratedParticles().empty() ||
209 !eventDataCollection->getGeneratedTrackedParticles().empty()) {
210 publish_event_data(eventDataCollection);
215 const auto digi_map = run_action->get_digitization_routines_map();
216 if (digi_map ==
nullptr) {
218 " no digitization routines map available in thread ", thread_id);
222 bool has_event_mode_payload =
false;
223 bool has_run_mode_payload =
false;
224 const bool also_reject_true_info = scalar_bool_option_enabled(
goptions,
"also_reject_true_info");
225 std::unordered_set<int> ancestor_track_ids;
229 for (G4int hci = 0; hci < hcs_this_event->GetNumberOfCollections(); ++hci) {
230 auto*
const this_ghc =
static_cast<GHitsCollection*
>(hcs_this_event->GetHC(hci));
231 if (this_ghc ==
nullptr) {
235 const std::string hcSDName = this_ghc->GetSDname();
240 " for event number ", event_id,
241 " for collection number ", hci + 1,
242 " collection name: ", hcSDName);
245 const auto it = digi_map->find(hcSDName);
246 if (it == digi_map->end()) {
248 " no digitization routine registered for collection ", hcSDName,
249 " in thread ", thread_id);
253 const auto& digitization_routine = it->second;
254 if (digitization_routine ==
nullptr) {
256 " digitization routine is null for collection ", hcSDName,
257 " in thread ", thread_id);
261 const auto collection_mode = digitization_routine->collection_mode();
262 size_t accepted_hit_index = 0;
266 for (
size_t hitIndex = 0; hitIndex < this_ghc->GetSize(); ++hitIndex) {
268 auto*
const this_hit =
static_cast<GHit*
>(this_ghc->GetHit(hitIndex));
269 if (this_hit ==
nullptr) {
272 if (save_all_ancestors) {
273 const auto track_ids = this_hit->getTids();
274 ancestor_track_ids.insert(track_ids.begin(), track_ids.end());
277 auto digi_data = no_digitized ? nullptr : digitization_routine->digitizeHit(this_hit, hitIndex);
278 bool hit_accepted = digi_data !=
nullptr;
284 const bool skip_threshold = digitization_routine->apply_thresholds(this_hit, digi_data.get());
285 const bool skip_efficiency = digitization_routine->apply_efficiency(this_hit, digi_data.get());
286 if (skip_threshold || skip_efficiency) {
288 hit_accepted =
false;
292 if (collection_mode == CollectionMode::event) {
294 ++accepted_hit_index;
295 digi_data->includeVariable(
"hitn",
static_cast<int>(accepted_hit_index));
296 run_action->record_analysis_digitized(hcSDName, *digi_data);
297 eventDataCollection->addDetectorDigitizedData(hcSDName, std::move(digi_data));
298 has_event_mode_payload =
true;
301 else if (collection_mode == CollectionMode::run) {
303 run_action->record_analysis_digitized(hcSDName, *digi_data);
304 run_action->collect_event_data_collections(
306 std::move(digi_data));
307 has_run_mode_payload =
true;
313 const bool collect_true = !no_true_info &&
314 (no_digitized || hit_accepted || !also_reject_true_info) &&
315 (collection_mode == CollectionMode::event || run_action->analysis_enabled());
317 const size_t output_hit_index = collection_mode == CollectionMode::event && hit_accepted
318 ? accepted_hit_index : hitIndex + 1;
319 auto true_data = digitization_routine->collectTrueInformation(this_hit, output_hit_index);
320 if (save_original_track && track_provenance !=
nullptr && true_data !=
nullptr) {
321 const int tid = this_hit->getTid();
322 const G4ThreeVector op = track_provenance->originalTrackMomentum(tid);
323 true_data->includeVariable(
"otid", track_provenance->originalTrackId(tid));
324 true_data->includeVariable(
"opid", track_provenance->originalTrackPid(tid));
325 true_data->includeVariable(
"opx", op.getX());
326 true_data->includeVariable(
"opy", op.getY());
327 true_data->includeVariable(
"opz", op.getZ());
329 if (true_data !=
nullptr) { run_action->record_analysis_true(hcSDName, *true_data); }
330 if (collection_mode == CollectionMode::event) {
331 eventDataCollection->addDetectorTrueInfoData(hcSDName, std::move(true_data));
332 has_event_mode_payload =
true;
338 if (save_all_ancestors && track_provenance !=
nullptr) {
339 eventDataCollection->setAncestors(
340 make_ancestor_bank(track_provenance->ancestorsForTracks(ancestor_track_ids)));
344 if (has_run_mode_payload) {
345 run_action->increment_run_events_with_payload();
349 if (has_event_mode_payload ||
350 !eventDataCollection->getAncestors().empty() ||
351 !eventDataCollection->getGeneratedParticles().empty() ||
352 !eventDataCollection->getGeneratedTrackedParticles().empty()) {
353 publish_event_data(eventDataCollection);
std::vector< GParticleRecord > GParticleRecordEvent