CbmRoot
Loading...
Searching...
No Matches
Reco.cxx
Go to the documentation of this file.
1/* Copyright (C) 2023-2025 FIAS Frankfurt Institute for Advanced Studies, Frankfurt / Main
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Felix Weiglhofer [committer], P.-A. Loizeau, Sergei Zharko */
4#include "algo/global/Reco.h"
5
7#include "CaTrack.h"
8#include "CbmDigiEvent.h"
9#include "CbmYaml.h"
11#include "algo/base/BuildInfo.h"
24// #include "algo/detectors/mvd/ChannelMaskSet.h" // TODO
25// #include "algo/detectors/mvd/HitfinderChain.h" // TODO
37#include "algo/evbuild/Config.h"
43#include "algo/qa/QaManager.h"
47// #include "algo/qa/unpack/MvdDigiQa.h" // TODO
50
51#include <Monitor.hpp>
52#include <System.hpp>
53
54#include <xpu/host.h>
55
56using namespace cbm::algo;
57using fles::Subsystem;
58
59namespace chron = std::chrono;
60
63
64// ---------------------------------------------------------------------------------------------------------------------
65//
66void Reco::Validate(const Options& opts) const
67{
68 if (!fs::exists(opts.ParamsDir())) throw FatalError("ParamsDir does not exist: {}", opts.ParamsDir().string());
69
70 bool hasOutputFile = !opts.OutputFile().empty();
71 bool hasOutputType = !opts.OutputTypes().empty();
72
73 if (!hasOutputFile && hasOutputType) {
74 throw FatalError("Output types specified, but no output file given: -o <file> missing");
75 }
76
77 if (hasOutputFile && !hasOutputType) {
78 throw FatalError("Output file specified, but no output types given: -O <types> missing");
79 }
80
82 throw FatalError("Archive compression enabled but compiled without Zstd: Remove --archive-compression flag");
83 }
84
85 if (opts.Has(Step::LocalReco) && !opts.Has(Step::Unpack)) {
86 throw FatalError("Local reco can't run without unpacking: Add 'Unpack' to the reco steps");
87 }
88
89 if (opts.Has(Step::Tracking) && !opts.Has(Step::LocalReco)) {
90 throw FatalError("Tracking can't run without local reco: Add 'LocalReco' to the reco steps");
91 }
92}
93
94// ---------------------------------------------------------------------------------------------------------------------
95//
96void Reco::Validate(const ParFiles& parFiles) const
97{
98 // Unpack
99 if (Opts().Has(Step::Unpack)) {
100 const auto& readout = parFiles.readout;
101 if (readout == std::nullopt) {
102 throw FatalError("Unpacking was required, but cannot run without readout parameters. Please specify the "
103 "\"readout\" node in the main config \""
104 + Opts().MainConfigPath().string() + "\"");
105 }
106
107 // Individual readout nodes for each detector subsystem
108 auto Check = [&](Subsystem subsystem, const auto& parNode) -> bool {
109 if (Opts().Has(subsystem) && parNode == std::nullopt) {
110 L_(error) << "Unpacking was required for " << subsystem << ", but the parameters are not found in readout node";
111 return false;
112 }
113 return true;
114 };
115
116 bool valid{true};
117 // FIXME: uncomment, when the parameters will be available!
118 valid = Check(Subsystem::MVD, readout->mvd) && valid;
119 valid = Check(Subsystem::STS, readout->sts) && valid;
120 //valid = Check(Subsystem::RICH, readout->rich) && valid;
121 valid = Check(Subsystem::MUCH, readout->much) && valid;
122 valid = Check(Subsystem::TRD, readout->trd) && valid;
123 valid = Check(Subsystem::TOF, readout->tof) && valid;
124 valid = Check(Subsystem::BMON, readout->bmon) && valid;
125 valid = Check(Subsystem::TRD2D, readout->trd2d) && valid;
126 //valid = Check(Subsystem::FSD, readout->fsd) && valid;
127
128 if (!valid) {
129 throw FatalError("Some of the readout parameters were not provided for required unpacking steps (see errors "
130 "above). Please specify the parameters in "
131 + Opts().MainConfigPath().string() + ". Stop execution.");
132 }
133 }
134
135 // Digi-timeslice reconstruction
136 if (Opts().Has(Step::LocalReco)) {
137 const auto& reco = parFiles.timesliceReco;
138 if (reco == std::nullopt) {
139 throw FatalError("Reconstruction of digi-timeslices was required, but cannot run without readout parameters. "
140 "Please specify the \"timesliceReco\" node in the main config "
141 + Opts().MainConfigPath().string() + ". Stop execution.");
142 }
143
144 // Individual readout nodes for each detector subsystem
145 auto Check = [&](Subsystem subsystem, const auto& parNode) -> bool {
146 if (Opts().Has(subsystem) && parNode == std::nullopt) {
147 L_(error) << "Local reconstruction of digi-timeslice was required for " << subsystem
148 << ", but the parameters"
149 " are not found in timesliceReco node";
150 return false;
151 }
152 return true;
153 };
154
155 bool valid{true};
156 valid = Check(Subsystem::STS, reco->sts) && valid;
157 valid = Check(Subsystem::TRD, reco->trd) && valid;
158 valid = Check(Subsystem::TRD, reco->trd2d) && valid;
159 valid = Check(Subsystem::TOF, reco->tof) && valid;
160 if (!valid) {
161 throw FatalError(
162 "Some of the parameters for local reconstruction of digi-timeslices were not provided (see errors "
163 "above). Please specify the parameters in "
164 + Opts().MainConfigPath().string() + ". Stop execution.");
165 }
166
167 if (Opts().Has(Step::Tracking) && reco->tracking == std::nullopt) {
168 throw FatalError(
169 "Parameters for tracking in timeslice were not provided (see errors above). Please specify the parameters in "
170 + Opts().MainConfigPath().string() + ". Stop execution.");
171 }
172 }
173
174 // NOTE: Temporary, must be redefined in https://git.cbm.gsi.de/computing/cbmroot/-/merge_requests/2094
175
176 // Digi-event reconstruction: local reconstruction
177 if (Opts().ReconstructDigiEvents()) {
178 const auto& reco = parFiles.eventReco;
179 if (reco == std::nullopt) {
180 throw FatalError("Reconstruction of digi-events was required, but cannot run without readout parameters. "
181 "Please specify the \"eventReco\" node in the main config "
182 + Opts().MainConfigPath().string() + ". Stop execution.");
183 }
184
185 // Individual readout nodes for each detector subsystem
186 auto Check = [&](Subsystem subsystem, const auto& parNode) -> bool {
187 if (Opts().Has(subsystem) && parNode == std::nullopt) {
188 L_(error) << "Local reconstruction of digi-events was required for " << subsystem
189 << ", but the parameters"
190 " are not found in eventReco node";
191 return false;
192 }
193 return true;
194 };
195
196 bool valid{true};
197 valid = Check(Subsystem::STS, reco->sts) && valid;
198 valid = Check(Subsystem::TRD, reco->trd) && valid;
199 valid = Check(Subsystem::TRD, reco->trd2d) && valid;
200 valid = Check(Subsystem::TOF, reco->tof) && valid;
201 if (reco->tracking == std::nullopt) {
202 LOG(error) << "Parameters for tracking in digi-events were not found in eventReco node";
203 }
204 if (!valid) {
205 throw FatalError("Some of the parameters for local reconstruction of digi-events were not provided (see errors "
206 "above). Please specify the parameters in "
207 + Opts().MainConfigPath().string() + ". Stop execution.");
208 }
209 }
210
211 // Reco-setup
212 // NOTE: at the moment is used in:
213 // - digi-event selector
214 // - tracking
215 // - digi-event reconstruction
216 if ((Opts().Has(Step::DigiTrigger) || Opts().Has(Step::Tracking) || Opts().ReconstructDigiEvents())
217 && parFiles.recoSetupPath == std::nullopt) {
218 throw FatalError("digi-trigger, tracking or digi-event reconstruction were required, but the recoSetupPath node"
219 "is not provided with the config "
220 + Opts().MainConfigPath().string()
221 + ". Please specify it. "
222 "Stop execution.");
223 }
224}
225
226
227// ---------------------------------------------------------------------------------------------------------------------
228//
229void Reco::Init(const Options& opts)
230{
231 if (fInitialized) throw std::runtime_error("Chain already initialized");
232
233 Validate(opts);
234
235 fContext.opts = opts;
237
238 if (Opts().HistogramUri() != "") {
239 fSender =
240 std::make_shared<HistogramSender>(Opts().HistogramUri(), Opts().HistogramHwm(), Opts().CompressHistograms());
241 // fContext.sender = fSender;
242
244 if (0 == fRunStartTimeNs) {
245 fRunStartTimeNs = chron::duration_cast<chron::nanoseconds>(chron::system_clock::now().time_since_epoch()).count();
246 L_(info) << "Start time for run " << opts.RunId() << " not provided => using current time";
247 }
248 }
249
250 bool bProcessQa = (fSender != nullptr) || Opts().DumpBatchQaHistograms();
251 if ((fSender != nullptr) && Opts().DumpBatchQaHistograms()) {
252 L_(warn) << "Storing of the histograms in the batch mode was required with option --batch-qa-output=<file>, but "
253 "the histogram server is available. Since the priority of sending the histograms on the histogram "
254 "server is higher, the option --batch-qa-output=<file> will be ignored.";
255 }
256
257 xpu::device_prop props{xpu::device::active()};
258 L_(info) << "Running CBM Reco on Device '" << props.name() << "' (Using " << openmp::GetMaxThreads()
259 << " OpenMP threads)";
260
261 if (!opts.MonitorUri().empty()) {
262 fContext.monitor = std::make_unique<cbm::Monitor>(opts.MonitorUri());
263 L_(info) << "Monitoring enabled, sending to " << opts.MonitorUri();
264 }
265
266 //* Parameters parsing
267 // TODO: wrap it into a class
268 auto mainConfigNode = YAML::LoadFile(Opts().MainConfigPath().string());
269
270 // Reco Params (at the moment only STS, it is to be reorganized in the next merge request)
271 // FIXME: RecoParams -> HitfindingParams/LocalRecoParams/....... needs to be renamed
272 fContext.recoParams.sts = yaml::Read<RecoParams::STS>(mainConfigNode["sts"]);
273
274 auto parFiles = yaml::Read<ParFiles>(mainConfigNode["parFiles"]);
275 Validate(parFiles);
276
277 // QA instantiation
278 if (bProcessQa) {
279 // QA manager
280 fQaManager = std::make_unique<qa::Manager>(fSender);
281 fQaManager->SetContext(&fContext);
282
283 // General QA
284 fGeneralQa = std::make_unique<qa::RecoGeneralQa>(fRunStartTimeNs, fSender);
285 fGeneralQaData = std::make_unique<qa::GeneralQaData>();
286 }
287
288 // Unpackers
289 if (Opts().Has(Subsystem::BMON) && Opts().Has(Step::Unpack)) {
290 bmon::ReadoutSetup readoutSetup =
291 yaml::ReadFromFile<bmon::ReadoutSetup>(Opts().ParamsDir() / parFiles.readout->bmon->readout);
292 bmon::ReadoutConfig cfg{readoutSetup};
293 fBmonUnpack = std::make_unique<bmon::Unpack>(cfg);
294 }
295
296 if (Opts().Has(Subsystem::MUCH) && Opts().Has(Step::Unpack)) {
297 much::ReadoutSetup readoutSetup;
298 bool bLoadingOk = false;
299 std::string sDefaultMessage = "MUCH params file not defined for this setup => using hardcoded values";
300 if (std::nullopt != parFiles.readout->much && "" != parFiles.readout->much->readout) {
301 try {
302 readoutSetup = yaml::ReadFromFile<much::ReadoutSetup>(Opts().ParamsDir() / parFiles.readout->much->readout);
303 bLoadingOk = true;
304 }
305 catch (YAML::BadFile&) {
306 bLoadingOk = false;
307 // Ignore error as if file is bad or missing
308 sDefaultMessage =
309 "MUCH param file not found at " + parFiles.readout->much->readout + " => using hardcoded values";
310 }
311 catch (YAML::ParserException& err) {
312 bLoadingOk = false;
313 // Ignore error as if file is bad or missing
314 sDefaultMessage = "Bad MUCH param file at " + parFiles.readout->much->readout + ": " + err.what()
315 + " => using hardcoded values";
316 }
317 }
318
319 if (bLoadingOk) {
320 much::ReadoutConfig cfg(readoutSetup);
321 fMuchUnpack = std::make_unique<much::Unpack>(cfg);
322 }
323 else {
324 L_(info) << sDefaultMessage;
326 fMuchUnpack = std::make_unique<much::Unpack>(cfg);
327 }
328 }
329
330 if (Opts().Has(Subsystem::RICH) && Opts().Has(Step::Unpack)) {
332 fRichUnpack = std::make_unique<rich::Unpack>(cfg);
333 }
334
335 if (Opts().Has(Subsystem::STS) && Opts().Has(Step::Unpack)) {
336 sts::ReadoutSetup readoutSetup =
337 yaml::ReadFromFile<sts::ReadoutSetup>(Opts().ParamsDir() / parFiles.readout->sts->readout);
338 auto chanMask = yaml::ReadFromFile<sts::ChannelMaskSet>(Opts().ParamsDir() / parFiles.readout->sts->channelMask);
339 auto walkMap = yaml::ReadFromFile<sts::WalkMap>(Opts().ParamsDir() / parFiles.readout->sts->walkMap);
340 bool bCollectAux = (fSender != nullptr && Opts().CollectAuxData());
341 sts::ReadoutConfig readout{readoutSetup, chanMask};
342 sts::Unpack::Config cfg{.readout = readout, .walkMap = walkMap, .bCollectAuxData = bCollectAux};
343 fStsUnpack = std::make_unique<sts::Unpack>(cfg);
344 if (bProcessQa && Opts().Has(QaStep::UnpackSts)) {
345 fStsDigiQa = std::make_unique<sts::DigiQa>(fSender);
346 fStsDigiQa->SetUseAuxData(bCollectAux);
347 fStsDigiQa->RegisterReadoutSetup(readoutSetup);
348 fStsDigiQa->Init();
349 }
350 }
351
352 if (Opts().Has(Subsystem::MVD) && Opts().Has(Step::Unpack)) {
353 mvd::ReadoutSetup readoutSetup;
354 bool bLoadingOk = false;
355 std::string sDefaultMessage = "MVD params file not defined for this setup => using hardcoded values";
356 if (std::nullopt != parFiles.readout->mvd && "" != parFiles.readout->mvd->readout) {
357 try {
358 readoutSetup = yaml::ReadFromFile<mvd::ReadoutSetup>(Opts().ParamsDir() / parFiles.readout->mvd->readout);
359 bLoadingOk = true;
360 }
361 catch (YAML::BadFile&) {
362 bLoadingOk = false;
363 // Ignore error as if file is bad or missing
364 sDefaultMessage =
365 "MVD param file not found at " + parFiles.readout->mvd->readout + " => using hardcoded values";
366 }
367 catch (YAML::ParserException& err) {
368 bLoadingOk = false;
369 // Ignore error as if file is bad or missing
370 sDefaultMessage =
371 "Bad MVD param file at " + parFiles.readout->mvd->readout + ": " + err.what() + " => using hardcoded values";
372 }
373 }
374
375 if (bLoadingOk) {
376 // auto pixMask = yaml::ReadFromFile<mvd::ChannelMaskSet>(Opts().ParamsDir() / parFiles.mvd.chanMask);
377 // mvd::ReadoutConfig readout{readoutSetup, pixMask};
378 mvd::ReadoutConfig cfg(readoutSetup);
379 fMvdUnpack = std::make_unique<mvd::Unpack>(cfg);
380 }
381 else {
382 L_(info) << sDefaultMessage;
383 mvd::ReadoutConfig cfg{};
384 fMvdUnpack = std::make_unique<mvd::Unpack>(cfg);
385 }
386 // if (bProcessQa && Opts().Has(QaStep::UnpackMvd)) {
387 // fMvdDigiQa = std::make_unique<mvd::DigiQa>(fSender);
388 // fMvdDigiQa->SetUseAuxData(bCollectAux);
389 // fMvdDigiQa->RegisterReadoutSetup(readoutSetup);
390 // fMvdDigiQa->Init();
391 // }
392 }
393
394 if (Opts().Has(Subsystem::TOF) && Opts().Has(Step::Unpack)) {
395 tof::ReadoutSetup readoutSetup =
396 yaml::ReadFromFile<tof::ReadoutSetup>(Opts().ParamsDir() / parFiles.readout->tof->readout);
397 tof::ReadoutConfig cfg{readoutSetup};
398 fTofUnpack = std::make_unique<tof::Unpack>(cfg);
399 }
400
401 if (Opts().Has(Subsystem::TRD) && Opts().Has(Step::Unpack)) {
402 auto cfg = yaml::ReadFromFile<trd::ReadoutConfig>(Opts().ParamsDir() / parFiles.readout->trd->readout);
403 fTrdUnpack = std::make_unique<trd::Unpack>(cfg);
404 }
405
406 if (Opts().Has(Subsystem::TRD2D) && Opts().Has(Step::Unpack)) {
407 auto setup = yaml::ReadFromFile<trd2d::ReadoutSetup>(Opts().ParamsDir() / parFiles.readout->trd2d->readout);
408 auto calib = yaml::ReadFromFile<trd2d::ReadoutCalib>(Opts().ParamsDir() / parFiles.readout->trd2d->fee);
409 trd2d::Unpack::Config cfg{.roSetup = setup, .roCalib = calib};
410 fTrd2dUnpack = std::make_unique<trd2d::Unpack>(cfg);
411 }
412
413 if (Opts().Has(Subsystem::FSD) && Opts().Has(Step::Unpack)) {
414 fFsdUnpack = std::make_unique<fsd::Unpack>();
415 }
416
417 // --- Reco setup
418 std::shared_ptr<RecoSetup> pRecoSetup{nullptr};
419 if (Opts().Has(Step::DigiTrigger) || Opts().Has(Step::Tracking) || Opts().ReconstructDigiEvents()) {
420 pRecoSetup = std::make_shared<RecoSetup>((Opts().ParamsDir() / parFiles.recoSetupPath.value()).string());
421 }
422
423 // TODO: Provide a uniform validation mechanism (check, if the setup unit exists)
424
425 // --- Event building
426 if (Opts().Has(Step::DigiTrigger)) {
427 evbuild::Config config(mainConfigNode); // NOTE: At the moment reads only selected nodes
429 std::make_unique<evbuild::EventbuildChain>(config, (Opts().Has(QaStep::EventBuilding) ? fSender : nullptr));
430 if (fQaManager != nullptr && Opts().Has(QaStep::V0Trigger)) {
431 // FIXME: Replace with a common function SetTriggerQa(fQaManager)
432 auto pTriggerQa = std::make_shared<evbuild::V0TriggerQa>(fQaManager);
433 pTriggerQa->Init();
434 fEventBuild->SetV0TriggerQa(pTriggerQa);
435 }
436 fEventBuild->RegisterSetup(pRecoSetup);
437 }
438
439 // STS Hitfinder
440 if (Opts().Has(fles::Subsystem::STS) && Opts().Has(Step::LocalReco)) {
441 sts::HitfinderPars hitFinderSetup =
442 yaml::ReadFromFile<sts::HitfinderPars>(opts.ParamsDir() / parFiles.timesliceReco->sts->hitfinder);
443 hitFinderSetup.landauTable = sts::LandauTable::FromFile(opts.ParamsDir() / "LandauWidthTable.txt");
444 // FIXME (?): Does the landau width table depend on the setup? Maybe, we should store it in algo/detectors/sts?
445 sts::HitfinderChainPars hitFinderPars;
446 hitFinderPars.setup = std::move(hitFinderSetup);
447 hitFinderPars.memory = Params().sts.memory;
448 fStsHitFinder = std::make_unique<sts::HitfinderChain>();
449 fStsHitFinder->SetContext(&fContext);
450 fStsHitFinder->SetParameters(hitFinderPars);
451 }
452
453 // TOF Hitfinder
454 if (Opts().Has(fles::Subsystem::TOF) && Opts().Has(Step::LocalReco)) {
455 auto calibSetup =
456 yaml::ReadFromFile<tof::CalibrateSetup>(opts.ParamsDir() / parFiles.timesliceReco->tof->calibrate);
457 fTofCalibrator = std::make_unique<tof::Calibrate>(calibSetup);
458
459 auto hitfindSetup =
460 yaml::ReadFromFile<tof::HitfindSetup>(opts.ParamsDir() / parFiles.timesliceReco->tof->hitfinder);
461 fTofHitFinder = std::make_unique<tof::Hitfind>(hitfindSetup);
462
463 if (fQaManager != nullptr && Opts().Has(QaStep::RecoTof)) {
464 fTofHitFinderQa = std::make_unique<tof::HitfindQa>(fQaManager, "TofHitfind");
465 fTofHitFinderQa->InitParameters(hitfindSetup);
466 fTofHitFinderQa->Init();
467 }
468 }
469
470 if (Opts().Has(fles::Subsystem::TRD) && Opts().Has(Step::LocalReco)) {
471 auto setup = yaml::ReadFromFile<trd::HitfindSetup>(opts.ParamsDir() / parFiles.timesliceReco->trd->hitfinder);
472 auto setup2d = yaml::ReadFromFile<trd::Hitfind2DSetup>(opts.ParamsDir() / parFiles.timesliceReco->trd2d->hitfinder);
473 fTrdHitfind = std::make_unique<trd::Hitfind>(setup, setup2d);
474 }
475
476 // Digi event reconstruction:
477 {
479 // It makes no sence to reconstruct an event, if there is no STS, TRD or TOF
480 fbReconstructDigiEvents &= Opts().Has(fles::Subsystem::STS);
481 fbReconstructDigiEvents &= Opts().Has(fles::Subsystem::TRD);
482 fbReconstructDigiEvents &= Opts().Has(fles::Subsystem::TOF);
483 fbReconstructDigiEvents &= Opts().Has(fles::Subsystem::BMON);
484 }
485
486 // Tracking
487 if (Opts().Has(Step::Tracking)) {
488 if (fQaManager != nullptr && Opts().Has(QaStep::Tracking)) {
489 fTracking = std::make_unique<TrackingChain>(ECbmRecoMode::Timeslice, fQaManager, "CaTimeslice");
490 }
491 else {
492 fTracking = std::make_unique<TrackingChain>(ECbmRecoMode::Timeslice);
493 }
494 fTracking->RegisterSetup(pRecoSetup);
495 fTracking->SetContext(&fContext);
496 std::string caParam = (Opts().ParamsDir() / parFiles.timesliceReco->tracking->capar).string();
497 fTracking->Init(caParam);
498 }
499
501 fEvSelectingMonitor.Reset();
502
503 // BMON hit finding in event reconstruction
504 auto bmonCalSetup =
505 yaml::ReadFromFile<bmon::CalibrateSetup>(opts.ParamsDir() / parFiles.eventReco->bmon->calibrate);
506 auto bmonHitSetup = yaml::ReadFromFile<bmon::HitfindSetup>(opts.ParamsDir() / parFiles.eventReco->bmon->hitfinder);
507 fBmonCalibrator = std::make_unique<bmon::Calibrate>(bmonCalSetup);
508 fBmonHitFinder = std::make_unique<bmon::Hitfind>(bmonHitSetup);
509 if (fQaManager != nullptr && Opts().Has(QaStep::RecoBmon)) {
510 fBmonHitFinderQa = std::make_unique<bmon::HitfindQa>(fQaManager, "BmonHitfindEvent");
511 fBmonHitFinderQa->InitParameters(bmonCalSetup, bmonHitSetup);
512 fBmonHitFinderQa->Init();
513 }
514
515 // Tracking in event reconstruction
516 if (fQaManager != nullptr && Opts().Has(QaStep::Tracking)) {
517 fTrackingEvent = std::make_unique<TrackingChain>(ECbmRecoMode::EventByEvent, fQaManager, "CaEvent");
518 }
519 else {
520 fTrackingEvent = std::make_unique<TrackingChain>(ECbmRecoMode::EventByEvent);
521 }
522 fTrackingEvent->RegisterSetup(pRecoSetup);
523 fTrackingEvent->SetContext(&fContext);
524 std::string caParam = (Opts().ParamsDir() / parFiles.eventReco->tracking->capar).string();
525 fTrackingEvent->Init(caParam);
526
527 if (fQaManager != nullptr && Opts().Has(QaStep::V0Finder)) {
528 fV0Finder = std::make_unique<V0FinderChain>(fQaManager);
529 }
530 else {
531 fV0Finder = std::make_unique<V0FinderChain>();
532 }
533 fV0Finder->SetContext(&fContext);
534 fV0Finder->SetBmonDefinedAddresses(fBmonHitFinder->GetDiamondAddresses());
535
536 auto config = yaml::Read<kfp::V0FinderConfig>(mainConfigNode["v0finder"]);
537 fV0Finder->Init(config);
538 }
539
540 // Initialize the QA manager
541 if (fQaManager != nullptr) {
542 fQaManager->Init();
543 }
544
545 fInitialized = true;
546
547 L_(debug) << "CBM Reco finished initialization";
548}
549
550// ---------------------------------------------------------------------------------------------------------------------
551//
552RecoResults Reco::Run(const fles::Timeslice& ts)
553{
554 if (!fInitialized) {
555 throw std::runtime_error("Chain not initialized");
556 }
557
558 ProcessingMonitor procMon;
560
561 RecoResults recoData;
562 RecoResults results;
563 {
564 xpu::scoped_timer t_(fmt::format("TS {}", ts.index()), &procMon.time);
565 xpu::t_add_bytes(ts_utils::SizeBytes(ts));
566
567 L_(info) << ">>> Processing TS " << ts.index();
568 xpu::set<cbm::algo::Params>(Params());
569
570 DigiData digis;
571 AuxDigiData auxDigis;
572
573 if (Opts().Has(Step::Unpack)) {
574 xpu::scoped_timer timerU("Unpack", &procMon.timeUnpack);
575 xpu::t_add_bytes(ts_utils::SizeBytes(ts));
576
577 std::tie(digis.fBmon, auxDigis.fBmon) = RunUnpacker(fBmonUnpack, ts);
578 std::tie(digis.fMuch, auxDigis.fMuch) = RunUnpacker(fMuchUnpack, ts);
579 std::tie(digis.fMvd, auxDigis.fMvd) = RunUnpacker(fMvdUnpack, ts);
580 std::tie(digis.fRich, auxDigis.fRich) = RunUnpacker(fRichUnpack, ts);
581 std::tie(digis.fSts, auxDigis.fSts) = RunUnpacker(fStsUnpack, ts);
582 std::tie(digis.fTof, auxDigis.fTof) = RunUnpacker(fTofUnpack, ts);
583 std::tie(digis.fTrd, auxDigis.fTrd) = RunUnpacker(fTrdUnpack, ts);
584 std::tie(digis.fTrd2d, auxDigis.fTrd2d) = RunUnpacker(fTrd2dUnpack, ts);
585 std::tie(digis.fFsd, auxDigis.fFsd) = RunUnpacker(fFsdUnpack, ts);
586
587 L_(info) << "TS contains Digis: STS=" << digis.fSts.size() << " MUCH=" << digis.fMuch.size()
588 << " TOF=" << digis.fTof.size() << " BMON=" << digis.fBmon.size() << " TRD=" << digis.fTrd.size()
589 << " TRD2D=" << digis.fTrd2d.size() << " RICH=" << digis.fRich.size() << " MVD=" << digis.fMvd.size()
590 << " FSD=" << digis.fFsd.size();
591
592
593 if (fGeneralQaData) {
594 fGeneralQaData->digis_nb["BMON"] = digis.fBmon.size();
595 // fGeneralQaData->digis_nb["MVD"] = digis.fMvd.size();
596 fGeneralQaData->digis_nb["STS"] = digis.fSts.size();
597 fGeneralQaData->digis_nb["RICH"] = digis.fRich.size();
598 fGeneralQaData->digis_nb["MUCH"] = digis.fMuch.size();
599 fGeneralQaData->digis_nb["TRD"] = digis.fTrd.size();
600 fGeneralQaData->digis_nb["TRD2D"] = digis.fTrd2d.size();
601 fGeneralQaData->digis_nb["TOF"] = digis.fTof.size();
602 fGeneralQaData->digis_nb["FSD"] = digis.fFsd.size();
603 }
604
605 // --- Raw digi QAs
606 if (fStsDigiQa != nullptr) {
607 fStsDigiQa->RegisterDigiData(&digis.fSts);
608 fStsDigiQa->RegisterAuxDigiData(&auxDigis.fSts);
609 fStsDigiQa->SetTimesliceIndex(ts.index());
610 fStsDigiQa->Exec();
611 }
612 }
613
614
615 sts::HitfinderMon stsHitfinderMonitor;
616 if (fStsHitFinder) {
617 xpu::scoped_timer timerSTS("STS Reco", &procMon.timeSTS);
618 xpu::t_add_bytes(digis.fSts.size() * sizeof(CbmStsDigi));
619 bool storeClusters = Opts().HasOutput(RecoData::Cluster);
620 auto stsResults = (*fStsHitFinder)(digis.fSts, storeClusters);
621 stsHitfinderMonitor = std::move(stsResults.monitor);
622 recoData.stsHits = stsResults.hits;
623 recoData.stsClusters = std::move(stsResults.clusters);
624 QueueStsRecoMetrics(stsHitfinderMonitor);
625 }
626
628 if (Opts().Has(Step::LocalReco) && Opts().Has(fles::Subsystem::TOF)) {
629 xpu::scoped_timer timerTOF("TOF Reco", &procMon.timeTOF);
630 xpu::t_add_bytes(digis.fTof.size() * sizeof(CbmTofDigi));
631 auto [caldigis, calmonitor] = (*fTofCalibrator)(digis.fTof);
632 auto nUnknownRPC = calmonitor.fDigiCalibUnknownRPC;
633 if (nUnknownRPC > 0) {
634 L_(error) << "TOF Digis with unknown RPCs: " << nUnknownRPC;
635 }
636 auto [hits, hitmonitor, digiindices] = (*fTofHitFinder)(caldigis);
637 if (fTofHitFinderQa != nullptr) {
638 fTofHitFinderQa->RegisterHits(&hits);
639 fTofHitFinderQa->Exec();
640 }
641 recoData.tofHits = std::move(hits);
642 QueueTofCalibMetrics(calmonitor);
643 QueueTofRecoMetrics(hitmonitor);
644 }
645
647 if (fTrdHitfind) {
648 xpu::scoped_timer timerTRD("TRD Reco", &procMon.timeTRD);
649 xpu::t_add_bytes(digis.fTrd.size() * sizeof(CbmTrdDigi));
650 // FIXME: additional copy of digis, figure out how to pass 1d + 2d digis at once to hitfinder
651 const auto& digis1d = digis.fTrd;
652 const auto& digis2d = digis.fTrd2d;
653 PODVector<CbmTrdDigi> allDigis{};
654 allDigis.reserve(digis1d.size() + digis2d.size());
655 std::copy(digis1d.begin(), digis1d.end(), std::back_inserter(allDigis));
656 std::copy(digis2d.begin(), digis2d.end(), std::back_inserter(allDigis));
657 auto trdResults = (*fTrdHitfind)(allDigis);
658 recoData.trdHits = std::move(std::get<0>(trdResults));
659 QueueTrdRecoMetrics(std::get<1>(trdResults));
660 }
661
662 L_(info) << "TS contains Hits: STS=" << recoData.stsHits.NElements() << " TOF=" << recoData.tofHits.NElements()
663 << " TRD=" << recoData.trdHits.NElements();
664
665
666 // --- Tracking
667 TrackingChain::Output_t trackingOutput{};
668 if (Opts().Has(Step::Tracking)) {
669 xpu::scoped_timer timerCA("CA", &procMon.timeCA);
670 xpu::t_add_bytes(recoData.stsHits.NElements() * sizeof(sts::Hit));
671 xpu::t_add_bytes(recoData.tofHits.NElements() * sizeof(tof::Hit));
672 xpu::t_add_bytes(recoData.trdHits.NElements() * sizeof(trd::Hit));
674 .stsHits = recoData.stsHits,
675 .tofHits = recoData.tofHits,
676 .trdHits = recoData.trdHits,
677 };
678 trackingOutput = fTracking->Run(input);
679 recoData.tracks = std::move(trackingOutput.tracks);
680 // FIXME: SZh: the hit-matching objects has to be soreted alongside with tracks
681 std::sort(recoData.tracks.begin(), recoData.tracks.end(),
682 [](const cbm::algo::ca::Track& track1, const cbm::algo::ca::Track& track2) {
683 return track1.fParPV.Time() < track2.fParPV.Time();
684 });
685 QueueTrackingMetrics(trackingOutput.monitorData);
686 }
687
688 // --- Event building
689 std::vector<DigiEvent> events;
690 if (Opts().Has(Step::DigiTrigger)) {
691 auto [ev, mon] = fEventBuild->Run(digis, recoData);
692 events = std::move(ev);
693 evbuildMonitor = mon;
694 QueueEvbuildMetrics(evbuildMonitor);
695 }
696
697 // --- Reconstruct and select digi events
700 fEvSelectingMonitor.IncrementCounter(evselect::ECounter::EventsTotal, events.size());
701 for (auto& event : events) {
703 event.fSelectionTriggers = ReconstructEvent(event);
705 }
706 auto v0FinderMonitor = fV0Finder->GetMonitor();
708 v0FinderMonitor.GetCounterValue(kfp::ECounter::KfpLambdaCandidates));
709 }
710
711 // --- Filter data for output
712 if (Opts().HasOutput(RecoData::DigiTimeslice)) {
713 results.bmonDigis = std::move(digis.fBmon);
714 results.stsDigis = std::move(digis.fSts);
715 results.muchDigis = std::move(digis.fMuch);
716 results.mvdDigis = std::move(digis.fMvd);
717 results.trd2dDigis = std::move(digis.fTrd2d);
718 results.trdDigis = std::move(digis.fTrd);
719 results.tofDigis = std::move(digis.fTof);
720 results.richDigis = std::move(digis.fRich);
721 results.fsdDigis = std::move(digis.fFsd);
722 }
723 if (Opts().HasOutput(RecoData::Track)) {
724 results.tracks = std::move(recoData.tracks);
725 results.trackStsHitIndices = std::move(trackingOutput.stsHitIndices);
726 results.trackTofHitIndices = std::move(trackingOutput.tofHitIndices);
727 results.trackTrdHitIndices = std::move(trackingOutput.trdHitIndices);
728 }
729 if (Opts().HasOutput(RecoData::DigiEvent)) results.events = std::move(events);
730 if (Opts().HasOutput(RecoData::Cluster)) results.stsClusters = std::move(recoData.stsClusters);
731 if (Opts().HasOutput(RecoData::Hit)) {
732 results.stsHits = std::move(recoData.stsHits);
733 results.tofHits = std::move(recoData.tofHits);
734 results.trdHits = std::move(recoData.trdHits);
735 }
736
737 // QA
738 if (fSender != nullptr) {
739 // Send all the histograms, collected through the timeslice
740 fQaManager->SetTimesliceId(ts.index());
741 fQaManager->SetTimesliceTimeInRun((ts.start_time() - fRunStartTimeNs) * 1e-9);
742 fQaManager->SendHistograms();
743 }
744 }
745 PrintTimings(procMon.time);
746 if (prevTsId) {
747 procMon.tsDelta = ts.index() - *prevTsId;
748 }
749 prevTsId = ts.index();
750 QueueProcessingMetrics(procMon);
751
752 // QA
753 if (fSender != nullptr) {
754 // Moved out of main emission as otherwise the times are not yet updated
755 (*fGeneralQa)(ts, (*fGeneralQaData));
756 fGeneralQaData->Reset();
757
758 // Send all the histograms, collected after the timeslice
759 // (timeslice index and start in tun time are identical to block 30-50 lines above)
760 fQaManager->SendHistograms();
761 }
762
763 return results;
764}
765
766// ---------------------------------------------------------------------------------------------------------------------
767//
769{
770 if (fStsHitFinder) {
771 fStsHitFinder->Finalize();
772 }
773 if (fTracking) {
774 L_(info) << "Track finding in a timeslice:";
775 fTracking->Finalize();
776 }
777 if (fTrackingEvent) {
778 L_(info) << "Track finding in digi events:";
779 fTrackingEvent->Finalize();
780 }
782 fV0Finder->Finalize();
783 L_(info) << fEvSelectingMonitor.ToString();
784 }
785
786
787 if (Opts().Profiling() >= ProfilingSummary) {
788 L_(info) << MakeReportSubtimers("Run Summary", fTimesliceTimesAcc) << "\n"
790
791 if (Opts().TimingsFile() != "") {
792 std::ofstream file(Opts().TimingsFile().string());
794 }
795 }
796
797 if (fSender == nullptr && Opts().DumpBatchQaHistograms()) {
798 fQaManager->WriteHistograms(Opts().BatchQaOutput().string(), Opts().CompressArchive());
799 }
800}
801
802// ---------------------------------------------------------------------------------------------------------------------
803//
804void Reco::PrintTimings(xpu::timings& timings)
805{
806 if (Opts().CollectKernelTimes()) {
807 fTimesliceTimesAcc.merge(timings);
808 }
809
810 if (Opts().Profiling() >= ProfilingPerTS) {
811 L_(info) << MakeReportSubtimers("TS timings", timings) << "\n" << MakeReportSummary("Total", timings);
812 }
813 else {
814 L_(info) << "TS Processing time (Wall): " << timings.wall() << " ms";
815 }
816}
817
818// ---------------------------------------------------------------------------------------------------------------------
819//
821{
822 CbmEventTriggers triggers(0);
823 RecoResults recoEvent;
824 //* BMON hit reconstruction
825 {
827 auto [calDigis, calMonitor] = (*fBmonCalibrator)(digiEvent.fBmon);
828 auto [hits, hitMonitor, digiIndices] = (*fBmonHitFinder)(calDigis);
830 if (fBmonHitFinderQa != nullptr) {
831 fBmonHitFinderQa->RegisterDigis(&calDigis);
832 fBmonHitFinderQa->RegisterHits(&hits);
833 fBmonHitFinderQa->RegisterDigiIndices(&digiIndices);
834 fBmonHitFinderQa->Exec();
835 }
836 recoEvent.bmonHits = std::move(hits);
837 }
838
839 //* STS hit reconstruction
840 {
842 auto stsResults = (*fStsHitFinder)(digiEvent.fSts);
844 if (stsResults.hits.NElements() < 4) { // TODO: Provide a config for cuts (testing mode for now)
846 return triggers;
847 }
848 recoEvent.stsHits = stsResults.hits;
849 }
850
851 //* TOF hit reconstruction
852 {
854 auto [caldigis, calmonitor] = (*fTofCalibrator)(digiEvent.fTof);
855 auto [hits, hitmonitor, digiindices] = (*fTofHitFinder)(caldigis);
857 if (hits.NElements() < 2) { // TODO: Provide a config for cuts (testing mode for now)
859 return triggers;
860 }
861 recoEvent.tofHits = std::move(hits);
862 }
863
864 //* TRD hit reconstruction
865 {
866 // FIXME: additional copy of digis, figure out how to pass 1d + 2d digis at once to hitfinder
868 const auto& digis1d = digiEvent.fTrd;
869 const auto& digis2d = digiEvent.fTrd2d;
870 PODVector<CbmTrdDigi> allDigis{};
871 allDigis.reserve(digis1d.size() + digis2d.size());
872 std::copy(digis1d.begin(), digis1d.end(), std::back_inserter(allDigis));
873 std::copy(digis2d.begin(), digis2d.end(), std::back_inserter(allDigis));
874 auto trdResults = (*fTrdHitfind)(allDigis);
876 recoEvent.trdHits = std::move(std::get<0>(trdResults));
877 }
878
879 //* Tracking
880 {
882 TrackingChain::Input_t input{.stsHits = recoEvent.stsHits,
883 .tofHits = recoEvent.tofHits,
884 .trdHits = recoEvent.trdHits};
885 TrackingChain::Output_t output = fTrackingEvent->Run(input);
886 recoEvent.tracks = std::move(output.tracks);
887 recoEvent.trackStsHitIndices = std::move(output.stsHitIndices);
888 recoEvent.trackTofHitIndices = std::move(output.tofHitIndices);
889 recoEvent.trackTrdHitIndices = std::move(output.trdHitIndices);
891 if (recoEvent.tracks.size() < 2) { // Reject all events with less then two tracks
893 return triggers;
894 }
895 }
896
897 //* V0-selector
899 triggers = fV0Finder->ProcessEvent(recoEvent);
901 L_(info) << "!!! Found event with potential lambda candidates";
903 }
905 return triggers;
906}
907
908
909// ---------------------------------------------------------------------------------------------------------------------
910//
911template<class Unpacker>
912auto Reco::RunUnpacker(const std::unique_ptr<Unpacker>& unpacker, const fles::Timeslice& ts) -> UnpackResult_t<Unpacker>
913{
914 if (!unpacker) {
915 return {};
916 }
917 auto [digis, monitor, aux] = (*unpacker)(ts);
919 return std::make_tuple(digis, aux);
920}
921
922// ---------------------------------------------------------------------------------------------------------------------
923//
924template<class MSMonitor>
926{
927
928 L_(debug) << Capitalize(util::ToString(monitor.system)) << " errors: " << monitor.print();
929
930 if (!HasMonitor()) {
931 return;
932 }
933
934 std::string_view det = util::ToString(monitor.system);
935
936 auto MkKey = [&](std::string_view key) { return fmt::format("{}{}", key, Capitalize(det)); };
937
938 GetMonitor().QueueMetric("cbmreco", {{"hostname", fles::system::current_hostname()}, {"child", Opts().ChildId()}},
939 {
940 {MkKey("unpackBytesIn"), monitor.sizeBytesIn},
941 {MkKey("unpackBytesOut"), monitor.sizeBytesOut},
942 {MkKey("unpackExpansionFactor"), monitor.ExpansionFactor()},
943 {MkKey("unpackNumMs"), monitor.numMs},
944 {MkKey("unpackNumErrInvalidSysVer"), monitor.errInvalidSysVer},
945 {MkKey("unpackNumErrInvalidEqId"), monitor.errInvalidEqId},
946 });
947}
948
949// ---------------------------------------------------------------------------------------------------------------------
950//
952{
953 if (!HasMonitor()) return;
954
955 GetMonitor().QueueMetric("cbmreco", {{"hostname", fles::system::current_hostname()}, {"child", Opts().ChildId()}},
956 {
957 {"stsRecoNumClusters", (unsigned long) monitor.nClusterTotal},
958 {"stsRecoNumHits", (unsigned long) monitor.nHitsTotal},
959 {"stsRecoNumClusterBucketOverflow", monitor.nClusterBucketOverflow},
960 {"stsRecoNumHitBucketOverflow", monitor.nHitBucketOverflow},
961 });
962}
963
964// ---------------------------------------------------------------------------------------------------------------------
965//
967{
968 if (!HasMonitor()) return;
969
970 GetMonitor().QueueMetric("cbmreco", {{"hostname", fles::system::current_hostname()}, {"child", Opts().ChildId()}},
971 {
972 {"tofRecoNumDigisIn", mon.fNumDigis},
973 {"tofRecoNumHits", mon.fNumHits},
974 });
975}
976
977// ---------------------------------------------------------------------------------------------------------------------
978//
980{
981 if (!HasMonitor()) {
982 return;
983 }
984
985 GetMonitor().QueueMetric("cbmreco", {{"hostname", fles::system::current_hostname()}, {"child", Opts().ChildId()}},
986 {
987 {"trdRecoNumDigisIn", mon.numDigis},
988 {"trdRecoNumHits", mon.numHits},
989 });
990}
991
992// ---------------------------------------------------------------------------------------------------------------------
993//
995{
996 if (!HasMonitor()) return;
997
998 GetMonitor().QueueMetric("cbmreco", {{"hostname", fles::system::current_hostname()}, {"child", Opts().ChildId()}},
999 {
1000 {"tofCalibTimeTotal", mon.fTime.wall()},
1001 {"tofCalibThroughput", FilterNan(mon.fTime.throughput())},
1002 {"tofCalibNumDigisIn", mon.fNumDigis},
1003 {"tofCalibUnknownRPC", mon.fDigiCalibUnknownRPC},
1004 });
1005}
1006
1007
1008// ---------------------------------------------------------------------------------------------------------------------
1009//
1011{
1012 if (fGeneralQaData) {
1013 fGeneralQaData->digimultrig_time_ms = mon.digiMultTrigger.time.wall();
1014 fGeneralQaData->hitmultrig_time_ms = mon.hitMultTrigger.time.wall();
1015 fGeneralQaData->v0trig_time_ms = mon.v0Trigger.time.wall();
1016 fGeneralQaData->evtbuild_time_ms = mon.evbuild.time.wall();
1017 }
1018
1019 if (!HasMonitor()) return;
1020
1021 const MetricTagSet tags = {{"hostname", fles::system::current_hostname()}, {"child", Opts().ChildId()}};
1022
1023 size_t nDigisTotal = 0;
1024 size_t nDigisInEventsTotal = 0;
1025
1026 auto queueDetMetrics = [&](std::string_view det, auto& detMon) {
1027 size_t nDigis = detMon.nDigis;
1028 size_t nDigisInEvents = detMon.nDigisInEvents;
1029 double selectionRatio = nDigis > 0 ? double(nDigisInEvents) / nDigis : 0;
1030
1031 nDigisTotal += nDigis;
1032 nDigisInEventsTotal += nDigisInEvents;
1033
1034 GetMonitor().QueueMetric("cbmreco", tags,
1035 {{fmt::format("{}NumDigisTotal", det), nDigis},
1036 {fmt::format("{}NumDigisInEvents", det), nDigisInEvents},
1037 {fmt::format("{}EvSelectionRatio", det), selectionRatio}});
1038 };
1039
1040 queueDetMetrics("mvd", mon.evbuild.mvd);
1041 queueDetMetrics("sts", mon.evbuild.sts);
1042 queueDetMetrics("much", mon.evbuild.much);
1043 queueDetMetrics("mvd", mon.evbuild.mvd);
1044 queueDetMetrics("tof", mon.evbuild.tof);
1045 queueDetMetrics("bmon", mon.evbuild.bmon);
1046 queueDetMetrics("trd", mon.evbuild.trd);
1047 queueDetMetrics("trd2d", mon.evbuild.trd2d);
1048 queueDetMetrics("rich", mon.evbuild.rich);
1049
1050 double totalSelectionRatio = nDigisTotal > 0 ? double(nDigisInEventsTotal) / nDigisTotal : 0;
1051 GetMonitor().QueueMetric("cbmreco", tags,
1052 {{"digiTriggerTimeTotal", mon.digiMultTrigger.time.wall()},
1053 {"digiTriggerThroughput", FilterNan(mon.digiMultTrigger.time.throughput())},
1054 {"hitTriggerTimeTotal", mon.hitMultTrigger.time.wall()},
1055 {"hitTriggerThroughput", FilterNan(mon.hitMultTrigger.time.throughput())},
1056 {"v0TriggerNumTrackPairs", mon.v0Trigger.numTrackPairs},
1057 {"v0TriggerNumTrackPairsCoinc", mon.v0Trigger.numTrackPairsAfterTimeCut},
1058 {"v0TriggerErrTracksUnsorted", mon.v0Trigger.errTracksUnsorted},
1059 {"v0TriggerTimeTotal", mon.v0Trigger.time.wall()},
1060 {"v0TriggerThroughput", FilterNan(mon.v0Trigger.time.throughput())},
1061 {"eventbuildTimeTotal", mon.evbuild.time.wall()},
1062 {"eventbuildThroughput", FilterNan(mon.evbuild.time.throughput())},
1063 {"numTrigger", mon.evbuild.numTriggers},
1064 {"numEvents", mon.evbuild.numEvents},
1065 {"totalEvSelectionRatio", totalSelectionRatio}});
1066}
1067
1068// ---------------------------------------------------------------------------------------------------------------------
1069//
1071{
1072 if (!HasMonitor()) {
1073 return;
1074 }
1075
1076 GetMonitor().QueueMetric("cbmreco", {{"hostname", fles::system::current_hostname()}, {"child", Opts().ChildId()}},
1077 {{"caTrackFinderTime", monitor.GetTimer(ca::ETimer::FindTracks).GetTotalMs()},
1078 {"caTrackFitterTime", monitor.GetTimer(ca::ETimer::FitTracks).GetTotalMs()},
1079 {"caNofRecoTracks", monitor.GetCounterValue(ca::ECounter::RecoTrack)},
1080 {"caNofRecoHitsTotal", monitor.GetCounterValue(ca::ECounter::RecoHit)},
1081 {"caNofRecoHitsUsed", monitor.GetCounterValue(ca::ECounter::RecoHitUsed)},
1082 {"caNofWindows", monitor.GetCounterValue(ca::ECounter::SubTS)}});
1083}
1084
1085// ---------------------------------------------------------------------------------------------------------------------
1086//
1088{
1089 if (fGeneralQaData) {
1090 fGeneralQaData->total_time_ms = mon.time.wall();
1091 fGeneralQaData->unpack_time_ms = mon.timeUnpack.wall();
1092 fGeneralQaData->sts_reco_time_ms = mon.timeSTS.wall();
1093 fGeneralQaData->tof_reco_time_ms = mon.timeTOF.wall();
1094 fGeneralQaData->trd_reco_time_ms = mon.timeTRD.wall();
1095 fGeneralQaData->ca_time_ms = mon.timeCA.wall();
1096 }
1097
1098 if (!HasMonitor()) {
1099 return;
1100 }
1101
1102 MetricFieldSet fields = {
1103 {"processingTimeTotal", mon.time.wall()}, {"processingThroughput", FilterNan(mon.time.throughput())},
1104 {"caRecoTimeTotal", mon.timeCA.wall()}, {"caRecoThroughput", FilterNan(mon.timeCA.throughput())},
1105 {"trdRecoTimeTotal", mon.timeTRD.wall()}, {"trdRecoThroughput", FilterNan(mon.timeTRD.throughput())},
1106 {"tofRecoTimeTotal", mon.timeTOF.wall()}, {"tofRecoThroughput", FilterNan(mon.timeTOF.throughput())},
1107 {"stsRecoTimeTotal", mon.timeSTS.wall()}, {"stsRecoThroughput", FilterNan(mon.timeSTS.throughput())},
1108 {"unpackTimeTotal", mon.timeUnpack.wall()}, {"unpackThroughput", FilterNan(mon.timeUnpack.throughput())}};
1109
1110 if (mon.tsDelta) {
1111 fields.emplace_back("tsDelta", *mon.tsDelta);
1112 }
1113
1114 GetMonitor().QueueMetric("cbmreco", {{"hostname", fles::system::current_hostname()}, {"child", Opts().ChildId()}},
1115 std::move(fields));
1116}
1117
1118// ---------------------------------------------------------------------------------------------------------------------
1119//
1121{
1122 if (!HasMonitor()) {
1123 return;
1124 }
1125
1126 MetricFieldSet fields = {{"processingTimeIdle", FilterNan(mon.timeIdle)},
1127 {"processingTimeWriteArchive", mon.timeWriteArchive.wall()},
1128 {"processingThroughputWriteArchive", FilterNan(mon.timeWriteArchive.throughput())},
1129 {"processingBytesWritten", FilterNan(mon.bytesWritten)}};
1130
1131 GetMonitor().QueueMetric("cbmreco", {{"hostname", fles::system::current_hostname()}, {"child", Opts().ChildId()}},
1132 std::move(fields));
1133}
#define L_(level)
Collection of auxiliary data from unpackers (header)
A BMON hitfinder QA.
source file for the ca::Track class
static vector< vector< QAHit > > hits
A chain for V0 finding.
Configuration structure for V0 selector in mCBM.
This file contains the definition of the ParFiles class.
QA manager for the online data reconstruction.
A structure to keep parameter files for reconstruction.
A collection of reconstruction setup unit interfaces for different CBM subsystems.
QA module for STS raw digis (source)
A TOF hitfinder QA.
A chain class to execute CA tracking algorithm in online reconstruction (header)
Calibrator for the BMON digis (implementation)
A BMON hit class.
Class to store different triggers for a given event.
bool Test(ETrigger key) const
Tests a particular single trigger.
Data class for a single-channel message in the STS.
Definition CbmStsDigi.h:40
Data class for expanded digital TOF information.
Definition CbmTofDigi.h:47
A vector that is partitioned into multiple subvectors.
const std::vector< RecoData > & OutputTypes() const
const std::string & MonitorUri() const
fs::path ParamsDir() const
bool ReconstructDigiEvents() const
uint64_t RunStart() const
bool CompressArchive() const
bool DumpBatchQaHistograms() const
uint64_t RunId() const
fs::path OutputFile() const
bool HasOutput(RecoData recoData) const
bool CollectAuxData() const
bool Has(fles::Subsystem detector) const
const std::string & ChildId() const
std::unique_ptr< tof::Hitfind > fTofHitFinder
Definition Reco.h:194
std::unique_ptr< tof::HitfindQa > fTofHitFinderQa
Definition Reco.h:195
bool fbReconstructDigiEvents
Definition Reco.h:159
ChainContext fContext
Definition Reco.h:160
std::optional< u64 > prevTsId
Definition Reco.h:165
std::unique_ptr< TrackingChain > fTrackingEvent
Tracking in event.
Definition Reco.h:210
void Init(const Options &)
Definition Reco.cxx:229
std::unique_ptr< bmon::HitfindQa > fBmonHitFinderQa
Definition Reco.h:175
void Validate(const Options &opts) const
Validation of program options.
Definition Reco.cxx:66
std::unique_ptr< trd::Hitfind > fTrdHitfind
Definition Reco.h:200
void QueueTofRecoMetrics(const tof::HitfindMonitorData &)
Definition Reco.cxx:966
std::unique_ptr< mvd::Unpack > fMvdUnpack
Definition Reco.h:181
std::shared_ptr< HistogramSender > fSender
Definition Reco.h:162
std::unique_ptr< bmon::Unpack > fBmonUnpack
Definition Reco.h:172
std::unique_ptr< sts::Unpack > fStsUnpack
Definition Reco.h:187
std::unique_ptr< rich::Unpack > fRichUnpack
Definition Reco.h:184
std::unique_ptr< V0FinderChain > fV0Finder
V0-finding chain (in event or a bunch of events)
Definition Reco.h:213
void QueueTrdRecoMetrics(const trd::HitfindMonitorData &)
Definition Reco.cxx:979
std::unique_ptr< much::Unpack > fMuchUnpack
Definition Reco.h:178
CbmEventTriggers ReconstructEvent(const DigiEvent &event)
Definition Reco.cxx:820
bool fInitialized
Definition Reco.h:158
auto RunUnpacker(const std::unique_ptr< Unpacker > &, const fles::Timeslice &) -> UnpackResult_t< Unpacker >
Definition Reco.cxx:912
uint64_t fRunStartTimeNs
Definition Reco.h:163
void Finalize()
Definition Reco.cxx:768
xpu::timings fTimesliceTimesAcc
Definition Reco.h:161
evselect::Monitor fEvSelectingMonitor
Monitor for event selecting.
Definition Reco.h:216
std::unique_ptr< sts::DigiQa > fStsDigiQa
Raw STS-digis QA.
Definition Reco.h:188
std::unique_ptr< tof::Unpack > fTofUnpack
Definition Reco.h:192
void QueueProcessingMetrics(const ProcessingMonitor &)
Definition Reco.cxx:1087
std::unique_ptr< qa::GeneralQaData > fGeneralQaData
Object aggregating the data points used in the GeneralQa.
Definition Reco.h:169
std::unique_ptr< qa::Manager > fQaManager
Definition Reco.h:219
static double FilterNan(double x)
Definition Reco.h:221
std::unique_ptr< bmon::Calibrate > fBmonCalibrator
Definition Reco.h:173
void QueueStsRecoMetrics(const sts::HitfinderMon &)
Definition Reco.cxx:951
std::unique_ptr< bmon::Hitfind > fBmonHitFinder
Definition Reco.h:174
std::unique_ptr< tof::Calibrate > fTofCalibrator
Definition Reco.h:193
void QueueTofCalibMetrics(const tof::CalibrateMonitorData &)
Definition Reco.cxx:994
std::unique_ptr< trd2d::Unpack > fTrd2dUnpack
Definition Reco.h:199
std::unique_ptr< qa::RecoGeneralQa > fGeneralQa
QA of online processing itself.
Definition Reco.h:168
std::unique_ptr< sts::HitfinderChain > fStsHitFinder
Definition Reco.h:189
std::unique_ptr< TrackingChain > fTracking
Tracking in timeslice.
Definition Reco.h:209
std::unique_ptr< trd::Unpack > fTrdUnpack
Definition Reco.h:198
std::unique_ptr< evbuild::EventbuildChain > fEventBuild
Definition Reco.h:206
std::unique_ptr< fsd::Unpack > fFsdUnpack
Definition Reco.h:203
RecoResults Run(const fles::Timeslice &)
Definition Reco.cxx:552
void PrintTimings(xpu::timings &)
Definition Reco.cxx:804
void QueueUnpackerMetricsDet(const UnpackMonitor< MSMonitor > &)
Definition Reco.cxx:925
void QueueTrackingMetrics(const ca::TrackingMonitorData &)
Definition Reco.cxx:1070
void QueueEvbuildMetrics(const evbuild::EventbuildChainMonitorData &)
Definition Reco.cxx:1010
void QueueProcessingExtraMetrics(const ProcessingExtraMonitor &)
Definition Reco.cxx:1120
const RecoParams & Params() const
Definition SubChain.h:21
Monitor & GetMonitor() const
Definition SubChain.h:25
bool HasMonitor() const
Definition SubChain.h:23
void SetContext(const ChainContext *ctx)
Definition SubChain.h:18
const Options & Opts() const
Definition SubChain.h:20
const Timer & GetTimer(ETimerKey key) const
Gets timer.
int GetCounterValue(ECounterKey key) const
Gets counter value.
double GetTotalMs() const
Gets total time [ms].
Definition CaTimer.h:80
Class representing an output track in the CA tracking algorithm.
Definition CaTrack.h:28
Configuration of digi event building.
Provides the hardware-to-software address mapping for the CBM-RICH.
Provides the hardware-to-software address mapping for the CBM-STS.
A light-weight TRD hit class for online reconstruction, based on CbmTrdHit. .
constexpr bool WITH_ZSTD
Definition BuildInfo.h:62
@ RecoHit
number of reconstructed hits
@ RecoTrack
number of reconstructed tracks
@ SubTS
number of sub time-slices
@ RecoHitUsed
number of used reconstructed hits
MonitorData< ECounter, ETimer > TrackingMonitorData
@ EventsNeStsHits
Events with not enough STS hits.
@ LambdaCandidates
Number of lambda-candidates, returned by KFParticleFinder.
@ EventsTotal
Total number of events processed.
@ EventsSelected
Number of selected events.
@ EventsNeTofHits
Events with enough STS hits, but not enough TOF hits.
@ Timeslices
number of processed timeslices
@ EventsNeTracks
Events with enough hits, but not enough tracks.
@ KfpLambdaCandidates
Number of lambda-candidates.
int GetMaxThreads()
Definition OpenMP.h:46
size_t SizeBytes(const fles::Timeslice &ts)
Definition TsUtils.h:10
std::tuple< algo_traits::Output_t< Unpacker >, algo_traits::Aux_t< Unpacker > > UnpackResult_t
Definition Reco.h:106
std::string MakeReportSubtimers(std::string_view title, const xpu::timings &t, size_t align)
Print timings from subtimers.
std::string MakeReportYaml(const xpu::timings &t)
Print timings in YAML format.
std::string MakeReportSummary(std::string_view title, const xpu::timings &t, size_t align)
Only print the top-level times (Elapsed time, total kernel time, memcpy and memset times)....
std::string_view ToString(T t)
Definition CbmEnumDict.h:64
std::vector< T, PODAllocator< T > > PODVector
PODVector is a std::vector that doesn't initialize its elements.
Definition PODVector.h:17
std::string Capitalize(std::string_view str)
Capitalize the first letter of a string. The rest of the string is made lowercase.
Definition StlUtils.cxx:9
Collection of auxiliary digi objects from different module unpackers.
Definition AuxDigiData.h:29
UnpackAux< bmon::UnpackAuxData > fBmon
Definition AuxDigiData.h:30
UnpackAux< trd2d::UnpackAuxData > fTrd2d
Definition AuxDigiData.h:36
UnpackAux< rich::UnpackAuxData > fRich
Definition AuxDigiData.h:32
UnpackAux< sts::UnpackAuxData > fSts
Definition AuxDigiData.h:33
UnpackAux< much::UnpackAuxData > fMuch
Definition AuxDigiData.h:31
UnpackAux< fsd::UnpackAuxData > fFsd
Definition AuxDigiData.h:38
UnpackAux< tof::UnpackAuxData > fTof
Definition AuxDigiData.h:34
UnpackAux< trd::UnpackAuxData > fTrd
Definition AuxDigiData.h:35
UnpackAux< mvd::UnpackAuxData > fMvd
Definition AuxDigiData.h:37
Collection of digis from all detector systems.
Definition DigiData.h:33
PODVector< CbmRichDigi > fRich
Unpacked RICH digis.
Definition DigiData.h:41
PODVector< CbmTrdDigi > fTrd
Unpacked TRD digis.
Definition DigiData.h:39
PODVector< CbmStsDigi > fSts
Unpacked STS digis.
Definition DigiData.h:34
PODVector< CbmTrdDigi > fTrd2d
Unpacked TRD2D digis.
Definition DigiData.h:40
PODVector< CbmFsdDigi > fFsd
Unpacked FSD digis.
Definition DigiData.h:43
PODVector< CbmTofDigi > fTof
Unpacked TOF digis.
Definition DigiData.h:37
PODVector< CbmMvdRawDigi > fMvd
Unpacked MVD digis.
Definition DigiData.h:36
PODVector< CbmMuchDigi > fMuch
Unpacked MUCH digis.
Definition DigiData.h:35
PODVector< CbmBmonDigi > fBmon
Unpacked Bmon digis.
Definition DigiData.h:38
Event data with event number and trigger time.
Definition DigiData.h:82
Indicates an unrecoverable error. Should tear down the process.
Definition Exceptions.h:34
Class to hold the paths to the parameter files for the different detectors.
Definition ParFiles.h:21
std::optional< RecoParFiles > eventReco
event reconstruction parameters
Definition ParFiles.h:24
std::optional< RecoParFiles > timesliceReco
timeslice reconstruction parameters
Definition ParFiles.h:23
std::optional< ReadoutParFiles > readout
readout parameters
Definition ParFiles.h:22
std::optional< std::string > recoSetupPath
Path to reco-setup.
Definition ParFiles.h:25
Monitor for additional processing steps.
Definition Reco.h:132
xpu::timings timeUnpack
Definition Reco.h:120
std::optional< i64 > tsDelta
Definition Reco.h:125
struct cbm::algo::RecoParams::STS::Memory memory
ca::Vector< std::vector< HitId_t > > trackTofHitIndices
Definition RecoResults.h:54
PartitionedVector< trd::Hit > trdHits
Definition RecoResults.h:49
PODVector< CbmMuchDigi > muchDigis
Definition RecoResults.h:35
PartitionedVector< sts::Cluster > stsClusters
Definition RecoResults.h:45
ca::Vector< ca::Track > tracks
Definition RecoResults.h:52
PartitionedVector< tof::Hit > tofHits
Definition RecoResults.h:48
ca::Vector< std::vector< HitId_t > > trackTrdHitIndices
Definition RecoResults.h:55
std::vector< DigiEvent > events
Definition RecoResults.h:43
PODVector< CbmTrdDigi > trd2dDigis
Definition RecoResults.h:37
PartitionedVector< bmon::Hit > bmonHits
Definition RecoResults.h:50
PODVector< CbmFsdDigi > fsdDigis
Definition RecoResults.h:41
PODVector< CbmMvdRawDigi > mvdDigis
Definition RecoResults.h:36
PartitionedSpan< sts::Hit > stsHits
Definition RecoResults.h:47
PODVector< CbmTofDigi > tofDigis
Definition RecoResults.h:39
ca::Vector< std::vector< HitId_t > > trackStsHitIndices
Definition RecoResults.h:53
PODVector< CbmRichDigi > richDigis
Definition RecoResults.h:40
PODVector< CbmStsDigi > stsDigis
Definition RecoResults.h:34
PODVector< CbmTrdDigi > trdDigis
Definition RecoResults.h:38
PODVector< CbmBmonDigi > bmonDigis
Definition RecoResults.h:33
Input to the TrackingChain.
Output from the TrackingChain.
ca::Vector< ca::Track > tracks
Reconstructed tracks.
ca::Vector< std::vector< std::pair< uint32_t, uint32_t > > > trdHitIndices
TRD hit indices.
ca::Vector< std::vector< std::pair< uint32_t, uint32_t > > > tofHitIndices
TOF hit indices.
ca::Vector< std::vector< std::pair< uint32_t, uint32_t > > > stsHitIndices
STS hit indices.
std::string print() const
Readout setup / Hardware cabling for BMon Used to create the hardware mapping for the BMon unpacker.
size_t numTriggers
Number of input triggers.
EventBuilderDetectorMonitorData much
Monitoring data for MUCH.
EventBuilderDetectorMonitorData rich
Monitoring data for RICH.
size_t numEvents
Number of built and selected events.
EventBuilderDetectorMonitorData sts
Monitoring data for STS.
EventBuilderDetectorMonitorData tof
Monitoring data for TOF.
EventBuilderDetectorMonitorData mvd
Monitoring data for MVD.
EventBuilderDetectorMonitorData bmon
Monitoring data for Bmon.
EventBuilderDetectorMonitorData trd2d
Monitoring data for TRD2D.
xpu::timings time
Time for event building.
EventBuilderDetectorMonitorData trd
Monitoring data for TRD.
TimeClusterTriggerMonitorData hitMultTrigger
TimeClusterTriggerMonitorData digiMultTrigger
xpu::timings time
Time for trigger building.
xpu::timings time
Time for trigger building.
Definition V0Trigger.h:30
Readout setup / Hardware cabling for MUCH Used to create the hardware mapping for the MUCH unpacker.
Readout setup / Hardware cabling for MVD Used to create the hardware mapping for the MVD unpacker.
RecoParams::STS::Memory memory
static LandauTable FromFile(fs::path path)
Readout setup / Hardware cabling for STS Used to create the hardware mapping for the STS unpacker.
Monitoring data for calibration.
Monitoring data for hitfinding.
Definition tof/Hitfind.h:30
Readout setup / Hardware cabling for TOF Used to create the hardware mapping for the TOF unpacker.
Monitoring data for hitfinding.
Definition trd/Hitfind.h:36