101template <
typename MapType>
102static std::string map_to_string(
const MapType& m) {
103 std::ostringstream os;
106 for (
const auto& [k, v] : m) {
107 if (!first) os <<
", ";
134static void dump_event(
const std::shared_ptr<GEventDataCollection>& edc,
const std::shared_ptr<GLogger>& log) {
135 log->info(0,
"------------------------------------------------------------");
136 log->info(0,
"Dumping event: local event number = %1", edc->getEventNumber());
137 log->info(0,
"------------------------------------------------------------");
139 const auto& dcm = edc->getDataCollectionMap();
141 log->info(0,
"Event contains no detector data.");
145 for (
const auto& [sdName, det] : dcm) {
147 log->info(0,
"Detector <%1> has a null GDataCollection pointer (unexpected).", sdName);
151 const auto& truthHits = det->getTrueInfoData();
152 const auto& digiHits = det->getDigitizedData();
154 log->info(0,
"Detector <%1>: truthHits=%2 digitizedHits=%3", sdName, truthHits.size(), digiHits.size());
157 for (
size_t i = 0; i < truthHits.size(); ++i) {
158 const auto& th = truthHits[i];
161 const auto doubles = th->getDoubleVariablesMap();
162 const auto strings = th->getStringVariablesMap();
166 log->info(0,
" [truth hit %1] id={%2}", i, idString);
167 log->info(0,
" doubles: %1", map_to_string(doubles));
170 if (!strings.empty()) {
171 log->info(0,
" strings: %1", map_to_string(strings));
174 log->info(0,
" strings: {} (none)");
179 for (
size_t i = 0; i < digiHits.size(); ++i) {
180 const auto& dh = digiHits[i];
183 const auto ints_non_sro = dh->getIntObservablesMap(0);
184 const auto ints_sro = dh->getIntObservablesMap(1);
185 const auto dbls_non_sro = dh->getDblObservablesMap(0);
186 const auto dbls_sro_only = dh->getDblObservablesMap(1);
190 log->info(0,
" [digi hit %1] id={%2}", i, idString);
191 log->info(0,
" int non-SRO: %1", map_to_string(ints_non_sro));
192 log->info(0,
" int SRO: %1", map_to_string(ints_sro));
193 log->info(0,
" dbl non-SRO: %1", map_to_string(dbls_non_sro));
194 log->info(0,
" dbl SRO: %1", map_to_string(dbls_sro_only));
197 const auto electronicsTime = dh->getTimeAtElectronics();
199 0,
" timeAtElectronics() = %1",
200 electronicsTime ? std::to_string(*electronicsTime) :
"not available");
220static void validate_event_structure(
const std::shared_ptr<GEventDataCollection>& edc,
221 const std::shared_ptr<GLogger>& log) {
222 const auto& dcm = edc->getDataCollectionMap();
225 0,
"VALIDATION: event %1 has no detectors (unexpected in this example).", edc->getEventNumber());
229 for (
const auto& [sdName, det] : dcm) {
231 log->info(0,
"VALIDATION: detector <%1> has null GDataCollection pointer.", sdName);
235 const auto& truthHits = det->getTrueInfoData();
236 const auto& digiHits = det->getDigitizedData();
238 for (
size_t i = 0; i < truthHits.size(); ++i) {
239 if (!truthHits[i]) log->info(0,
"VALIDATION: detector <%1> truth hit %2 is null.", sdName, i);
241 for (
size_t i = 0; i < digiHits.size(); ++i) {
242 if (!digiHits[i]) log->info(0,
"VALIDATION: detector <%1> digitized hit %2 is null.", sdName, i);
246 if (truthHits.size() != digiHits.size()) {
248 0,
"VALIDATION: detector <%1> truthHits(%2) != digitizedHits(%3) in event %4", sdName,
249 truthHits.size(), digiHits.size(), edc->getEventNumber());
274 const std::shared_ptr<GOptions>& gopt,
275 const std::shared_ptr<GLogger>& log)
276 -> std::vector<std::shared_ptr<GEventDataCollection>> {
277 std::mutex collectorMtx;
278 std::vector<std::shared_ptr<GEventDataCollection>> collected;
279 collected.reserve(
static_cast<size_t>(nevents));
282 std::atomic<int> next{1};
285 std::vector<jthread_alias> pool;
286 pool.reserve(nthreads);
288 for (
int tid = 0; tid < nthreads; ++tid) {
289 pool.emplace_back([&, tid] {
290 log->info(0,
"worker %1 started", tid);
295 thread_local std::vector<std::shared_ptr<GEventDataCollection>> localEvents;
299 int evn = next.fetch_add(1, std::memory_order_relaxed);
300 if (evn > nevents) {
break; }
315 localEvents.emplace_back(edc);
320 std::scoped_lock lk(collectorMtx);
321 for (
auto& evt : localEvents) { collected.emplace_back(evt); }
325 log->info(0,
"worker %1 processed %2 events", tid, localCount);
349int main(
int argc,
char* argv[]) {
357 constexpr int nevents = 5;
358 constexpr int nthreads = 4;
363 for (
const auto& edc : events) {
365 validate_event_structure(edc, log);
366 dump_event(edc, log);
369 log->info(0,
"Generated %1 event containers.", events.size());
static std::unique_ptr< GDigitizedData > create(const std::shared_ptr< GOptions > &gopts)
Creates deterministic example data for tests and examples.
static auto create(const std::shared_ptr< GOptions > &gopts) -> std::shared_ptr< GEventDataCollection >
Creates a minimal example event containing one detector entry and one hit pair.
static std::unique_ptr< GTrueInfoData > create(const std::shared_ptr< GOptions > &gopts)
Creates deterministic example data for tests and examples.
Defines GEventDataCollection, the event-level aggregation of detector hit data.
constexpr const char * GEVENTDATA_LOGGER
std::string getIdentityString(std::vector< GIdentifier > gidentity)
auto defineOptions() -> GOptions
Aggregates the option groups needed by event-level data containers.
auto run_simulation_in_threads(int nevents, int nthreads, const std::shared_ptr< GOptions > &gopt, const std::shared_ptr< GLogger > &log, const std::shared_ptr< const gdynamicdigitization::dRoutinesMap > &dynamicRoutinesMap) -> std::vector< std::unique_ptr< GEventDataCollection > >
int main(int argc, char *argv[])