gdata
Loading...
Searching...
No Matches
run_example.cc
Go to the documentation of this file.
1
57// gdata
60
61// gemc
62#include "glogger.h"
63#include "gthreads.h"
64
65// C++
66#include <atomic>
67#include <cstdlib>
68#include <map>
69#include <mutex>
70#include <sstream>
71#include <string>
72#include <vector>
73
87template <typename MapType>
88static std::string map_to_string(const MapType& m) {
89 std::ostringstream os;
90 os << "{";
91 bool first = true;
92 for (const auto& [k, v] : m) {
93 if (!first) os << ", ";
94 first = false;
95 os << k << "=" << v;
96 }
97 os << "}";
98 return os.str();
99}
100
112using PerDetectorDoubles = std::map<std::string, std::map<std::string, double>>;
113using PerDetectorInts = std::map<std::string, std::map<std::string, long long>>;
114
115static auto generate_events_in_threads(int nevents,
116 int nthreads,
117 const std::shared_ptr<GOptions>& gopt,
118 const std::shared_ptr<GLogger>& log)
119 -> std::vector<std::shared_ptr<GEventDataCollection>> {
120 std::mutex collectorMtx;
121 std::vector<std::shared_ptr<GEventDataCollection>> collected;
122 collected.reserve(static_cast<size_t>(nevents));
123
124 std::atomic<int> next{1};
125
126 std::vector<jthread_alias> pool;
127 pool.reserve(nthreads);
128
129 for (int tid = 0; tid < nthreads; ++tid) {
130 pool.emplace_back([&, tid] {
131 log->info(0, "worker ", tid, " started");
132
133 int localCount = 0;
134 thread_local std::vector<std::shared_ptr<GEventDataCollection>> localEvents;
135 localEvents.clear();
136
137 while (true) {
138 int evn = next.fetch_add(1, std::memory_order_relaxed);
139 if (evn > nevents) break;
140
141 auto edc = GEventDataCollection::create(gopt);
142
143 // Extend the event to ensure integration exercises multiple detectors/hits.
144 edc->addDetectorDigitizedData("ctof", GDigitizedData::create(gopt));
145 edc->addDetectorTrueInfoData("ctof", GTrueInfoData::create(gopt));
146
147 edc->addDetectorDigitizedData("ec", GDigitizedData::create(gopt));
148 edc->addDetectorTrueInfoData("ec", GTrueInfoData::create(gopt));
149
150 localEvents.emplace_back(edc);
151 ++localCount;
152 }
153
154 {
155 std::scoped_lock lk(collectorMtx);
156 for (auto& evt : localEvents) { collected.emplace_back(evt); }
157 localEvents.clear();
158 }
159
160 log->info(0, "worker ", tid, " processed ", localCount, " events");
161 });
162 }
163
164 return collected;
165}
166
167static void compute_reference_sums(const std::vector<std::shared_ptr<GEventDataCollection>>& events,
168 PerDetectorDoubles& truth_ref,
169 PerDetectorInts& digi_int_ref,
170 PerDetectorDoubles& digi_dbl_ref) {
171 for (const auto& edc : events) {
172 if (!edc) continue;
173
174 const auto& dcm = edc->getDataCollectionMap();
175 for (const auto& [sdName, det] : dcm) {
176 if (!det) continue;
177
178 // Truth: doubles
179 for (const auto& th : det->getTrueInfoData()) {
180 if (!th) continue;
181 for (const auto& [k, v] : th->getDoubleVariablesMap()) {
182 truth_ref[sdName][k] += v;
183 }
184 }
185
186 // Digitized: ints and doubles (non-SRO only, which=0)
187 for (const auto& dh : det->getDigitizedData()) {
188 if (!dh) continue;
189
190 for (const auto& [k, v] : dh->getIntObservablesMap(0)) {
191 digi_int_ref[sdName][k] += static_cast<long long>(v);
192 }
193 for (const auto& [k, v] : dh->getDblObservablesMap(0)) {
194 digi_dbl_ref[sdName][k] += v;
195 }
196 }
197 }
198 }
199}
200
201static auto integrate_into_run(const std::vector<std::shared_ptr<GEventDataCollection>>& events,
202 const std::shared_ptr<GOptions>& gopt)
203 -> std::shared_ptr<GRunDataCollection> {
204 auto grun_header = std::make_unique<GRunHeader>(gopt, 1); // run id 1, thread id default -1
205 auto run_data = std::make_shared<GRunDataCollection>(gopt, std::move(grun_header));
206
207 for (const auto& edc : events) {
208 if (!edc) continue;
209 run_data->collect_event_data_collection(edc);
210 }
211
212 return run_data;
213}
214
215static void validate_run_against_reference(const std::shared_ptr<GRunDataCollection>& run_data,
216 const PerDetectorDoubles& truth_ref,
217 const PerDetectorInts& digi_int_ref,
218 const PerDetectorDoubles& digi_dbl_ref,
219 const std::shared_ptr<GLogger>& log) {
220 log->info(0, "============================================================");
221 log->info(0, "RUN SUMMARY (integrated): runID=", run_data->getRunNumber());
222 log->info(0, "============================================================");
223
224 const auto& rmap = run_data->getDataCollectionMap();
225 if (rmap.empty()) {
226 log->info(0, "Run data map is empty (no detectors integrated).");
227 return;
228 }
229
230 for (const auto& [sdName, det] : rmap) {
231 if (!det) continue;
232
233 const auto& truthVec = det->getTrueInfoData();
234 const auto& digiVec = det->getDigitizedData();
235
236 log->info(0, "Detector <", sdName, ">: integrated truth entries=", truthVec.size(),
237 " integrated digitized entries=", digiVec.size());
238
239 // ---- Truth integrated entry
240 if (!truthVec.empty() && truthVec.front()) {
241 const auto integrated_truth = truthVec.front()->getDoubleVariablesMap();
242 log->info(0, " integrated truth doubles: ", map_to_string(integrated_truth));
243
244 const auto it_ref_det = truth_ref.find(sdName);
245 if (it_ref_det != truth_ref.end()) {
246 for (const auto& [k, refv] : it_ref_det->second) {
247 const auto itv = integrated_truth.find(k);
248 const double got = (itv == integrated_truth.end()) ? 0.0 : itv->second;
249 if (got != refv) {
250 log->info(0, " MISMATCH truth <", sdName, ">::", k, " got=", got, " ref=", refv);
251 }
252 }
253 }
254 else {
255 log->info(0, " NOTE: no reference truth sums found for detector <", sdName, ">.");
256 }
257 }
258 else {
259 log->info(0, " integrated truth: <none>");
260 }
261
262 // ---- Digitized integrated entry
263 if (!digiVec.empty() && digiVec.front()) {
264 const auto ints_non_sro = digiVec.front()->getIntObservablesMap(0);
265 const auto dbls_non_sro = digiVec.front()->getDblObservablesMap(0);
266
267 log->info(0, " integrated digi int non-SRO: ", map_to_string(ints_non_sro));
268 log->info(0, " integrated digi dbl non-SRO: ", map_to_string(dbls_non_sro));
269
270 const auto ints_sro = digiVec.front()->getIntObservablesMap(1);
271 const auto dbls_sro = digiVec.front()->getDblObservablesMap(1);
272 log->info(0, " integrated digi int SRO: ", map_to_string(ints_sro));
273 log->info(0, " integrated digi dbl SRO: ", map_to_string(dbls_sro));
274
275 const auto it_int_ref_det = digi_int_ref.find(sdName);
276 if (it_int_ref_det != digi_int_ref.end()) {
277 for (const auto& [k, refv] : it_int_ref_det->second) {
278 const auto itv = ints_non_sro.find(k);
279 const long long got = (itv == ints_non_sro.end()) ? 0LL : static_cast<long long>(itv->second);
280 if (got != refv) {
281 log->info(0, " MISMATCH digi-int <", sdName, ">::", k, " got=", got, " ref=", refv);
282 }
283 }
284 }
285 else {
286 log->info(0, " NOTE: no reference digitized-int sums found for detector <", sdName, ">.");
287 }
288
289 const auto it_dbl_ref_det = digi_dbl_ref.find(sdName);
290 if (it_dbl_ref_det != digi_dbl_ref.end()) {
291 for (const auto& [k, refv] : it_dbl_ref_det->second) {
292 const auto itv = dbls_non_sro.find(k);
293 const double got = (itv == dbls_non_sro.end()) ? 0.0 : itv->second;
294 if (got != refv) {
295 log->info(0, " MISMATCH digi-dbl <", sdName, ">::", k, " got=", got, " ref=", refv);
296 }
297 }
298 }
299 else {
300 log->info(0, " NOTE: no reference digitized-double sums found for detector <", sdName, ">.");
301 }
302 }
303 else {
304 log->info(0, " integrated digitized: <none>");
305 }
306 }
307}
308
309int main(int argc, char* argv[]) {
310 auto gopts = std::make_shared<GOptions>(argc, argv, grun_data::defineOptions());
311 auto log = std::make_shared<GLogger>(gopts, SFUNCTION_NAME, GRUNDATA_LOGGER);
312
313 constexpr int nevents = 20;
314 constexpr int nthreads = 4;
315
316 auto events = generate_events_in_threads(nevents, nthreads, gopts, log);
317 log->info(0, "Generated ", events.size(), " events.");
318
319 PerDetectorDoubles truth_ref;
320 PerDetectorInts digi_int_ref;
321 PerDetectorDoubles digi_dbl_ref;
322 compute_reference_sums(events, truth_ref, digi_int_ref, digi_dbl_ref);
323
324 auto runData = integrate_into_run(events, gopts);
325 validate_run_against_reference(runData, truth_ref, digi_int_ref, digi_dbl_ref, log);
326
327 return EXIT_SUCCESS;
328}
329
static std::unique_ptr< GDigitizedData > create(const std::shared_ptr< GOptions > &gopts)
Test/example factory: create a digitized hit with deterministic dummy data.
static auto create(const std::shared_ptr< GOptions > &gopts) -> std::shared_ptr< GEventDataCollection >
Test/example factory: create an event collection with one dummy hit for "ctof".
static std::unique_ptr< GTrueInfoData > create(const std::shared_ptr< GOptions > &gopts)
Test/example factory: create a true-hit object with deterministic dummy data.
Defines GEventDataCollection, event-level aggregation of per-detector hit data.
Defines GRunDataCollection, run-level aggregation of detector data.
constexpr const char * GRUNDATA_LOGGER
#define SFUNCTION_NAME
std::map< std::string, std::map< std::string, long long > > PerDetectorInts
std::map< std::string, std::map< std::string, double > > PerDetectorDoubles
Type alias for per-detector scalar accumulation maps used in this example.
auto defineOptions() -> GOptions
Aggregated options for run-level data collection.
int main(int argc, char *argv[])