diff --git a/algo/evbuild/EventBuilder.cxx b/algo/evbuild/EventBuilder.cxx index 30a6e2831f3f8744e512a7131312e63b9887135d..4416fd877dcda4532c522bc1bebf3981f92a8d31 100644 --- a/algo/evbuild/EventBuilder.cxx +++ b/algo/evbuild/EventBuilder.cxx @@ -7,6 +7,8 @@ #include <cassert> #include <iomanip> +#include <xpu/host.h> + using std::is_sorted; using std::vector; @@ -14,25 +16,41 @@ namespace cbm::algo::evbuild { // ----- Algorithm execution -------------------------------------------- - EventBuilder::resultType EventBuilder::operator()(const DigiData& ts, const vector<double> triggers) const + EventBuilder::resultType EventBuilder::operator()(const DigiData& ts, const vector<double> triggers, + std::optional<DigiEventSelector> selector) const { + xpu::push_timer("EventBuilder"); + // --- Output data resultType result = {}; - result.first.resize(triggers.size()); + auto& events = result.first; + events.resize(triggers.size()); - std::transform(triggers.begin(), triggers.end(), result.first.begin(), + std::transform(triggers.begin(), triggers.end(), events.begin(), [&ts, &result, this](const double& trigger) { return BuildEvent(ts, result.second, trigger); }); + // --- Apply event selector + if (selector.has_value()) { + auto notSelected = [&](DigiEvent& ev) { return !((*selector)(ev)); }; + auto removeIt = std::remove_if(events.begin(), events.end(), notSelected); + events.erase(removeIt, events.end()); + } + EventBuilderMonitorData& monitor = result.second; - monitor.fSts.fNum += ts.fSts.size(); - monitor.fRich.fNum += ts.fRich.size(); - monitor.fMuch.fNum += ts.fMuch.size(); - monitor.fTrd.fNum += ts.fTrd.size(); - monitor.fTrd2d.fNum += ts.fTrd2d.size(); - monitor.fTof.fNum += ts.fTof.size(); - monitor.fPsd.fNum += ts.fPsd.size(); - monitor.fFsd.fNum += ts.fFsd.size(); - monitor.fBmon.fNum += ts.fBmon.size(); + monitor.sts.nDigis += ts.fSts.size(); + monitor.rich.nDigis += ts.fRich.size(); + monitor.much.nDigis += ts.fMuch.size(); + monitor.trd.nDigis += ts.fTrd.size(); + monitor.trd2d.nDigis += ts.fTrd2d.size(); + monitor.tof.nDigis += ts.fTof.size(); + monitor.psd.nDigis += ts.fPsd.size(); + monitor.fsd.nDigis += ts.fFsd.size(); + monitor.bmon.nDigis += ts.fBmon.size(); + monitor.nEvents += result.first.size(); + + auto timings = xpu::pop_timer(); + monitor.timeMs = timings.wall(); + return result; } @@ -90,15 +108,15 @@ namespace cbm::algo::evbuild default: break; } } - monitor.fSts.fNumInEvents += event.fSts.size(); - monitor.fRich.fNumInEvents += event.fRich.size(); - monitor.fMuch.fNumInEvents += event.fMuch.size(); - monitor.fTrd.fNumInEvents += event.fTrd.size(); - monitor.fTrd2d.fNumInEvents += event.fTrd2d.size(); - monitor.fTof.fNumInEvents += event.fTof.size(); - monitor.fPsd.fNumInEvents += event.fPsd.size(); - monitor.fFsd.fNumInEvents += event.fFsd.size(); - monitor.fBmon.fNumInEvents += event.fBmon.size(); + monitor.sts.nDigisInEvents += event.fSts.size(); + monitor.rich.nDigisInEvents += event.fRich.size(); + monitor.much.nDigisInEvents += event.fMuch.size(); + monitor.trd.nDigisInEvents += event.fTrd.size(); + monitor.trd2d.nDigisInEvents += event.fTrd2d.size(); + monitor.tof.nDigisInEvents += event.fTof.size(); + monitor.psd.nDigisInEvents += event.fPsd.size(); + monitor.fsd.nDigisInEvents += event.fFsd.size(); + monitor.bmon.nDigisInEvents += event.fBmon.size(); return event; } // -------------------------------------------------------------------------- diff --git a/algo/evbuild/EventBuilder.h b/algo/evbuild/EventBuilder.h index c737b12f53a7bbbca7cc91e988f28ee9adfd1470..89a2ccaeacefff82bbf3e5568d953d336dd61eed 100644 --- a/algo/evbuild/EventBuilder.h +++ b/algo/evbuild/EventBuilder.h @@ -10,10 +10,12 @@ #include <algorithm> #include <gsl/span> #include <map> +#include <optional> #include <string> #include <vector> #include "DigiData.h" +#include "DigiEventSelector.h" #include "EventBuilderConfig.h" namespace cbm::algo::evbuild @@ -25,8 +27,8 @@ namespace cbm::algo::evbuild ** @brief Monitoring data for event building for one detector **/ struct EventBuilderDetectorMonitorData { - size_t fNumInEvents; ///< Number of digis collected into events - size_t fNum; ///< Full number of digis in input source + size_t nDigisInEvents = 0; ///< Number of digis collected into events + size_t nDigis = 0; ///< Full number of digis in input source }; @@ -36,15 +38,17 @@ namespace cbm::algo::evbuild ** @brief Monitoring data for event building **/ struct EventBuilderMonitorData { - EventBuilderDetectorMonitorData fSts; ///< Monitoring data for STS - EventBuilderDetectorMonitorData fMuch; ///< Monitoring data for MUCH - EventBuilderDetectorMonitorData fTof; ///< Monitoring data for TOF - EventBuilderDetectorMonitorData fBmon; ///< Monitoring data for T0 - EventBuilderDetectorMonitorData fTrd; ///< Monitoring data for TRD - EventBuilderDetectorMonitorData fTrd2d; ///< Monitoring data for TRD2D - EventBuilderDetectorMonitorData fRich; ///< Monitoring data for RICH - EventBuilderDetectorMonitorData fPsd; ///< Monitoring data for PSD - EventBuilderDetectorMonitorData fFsd; ///< Monitoring data for FSD + EventBuilderDetectorMonitorData sts; ///< Monitoring data for STS + EventBuilderDetectorMonitorData much; ///< Monitoring data for MUCH + EventBuilderDetectorMonitorData tof; ///< Monitoring data for TOF + EventBuilderDetectorMonitorData bmon; ///< Monitoring data for T0 + EventBuilderDetectorMonitorData trd; ///< Monitoring data for TRD + EventBuilderDetectorMonitorData trd2d; ///< Monitoring data for TRD2D + EventBuilderDetectorMonitorData rich; ///< Monitoring data for RICH + EventBuilderDetectorMonitorData psd; ///< Monitoring data for PSD + EventBuilderDetectorMonitorData fsd; ///< Monitoring data for FSD + size_t nEvents = 0; ///< Number of events found in TS + double timeMs = 0.; ///< Time for event building in ms }; @@ -79,9 +83,11 @@ namespace cbm::algo::evbuild /** @brief Execution ** @param ts Digi source (timeslice) ** @param triggers List of trigger times + ** @param selector Optional event selector ** @return Vector of constructed events and monitoring data **/ - resultType operator()(const DigiData& ts, const std::vector<double> triggers) const; + resultType operator()(const DigiData& ts, const std::vector<double> triggers, + std::optional<DigiEventSelector> selector) const; /** @brief Info to string **/ diff --git a/algo/evbuild/EventbuildChain.cxx b/algo/evbuild/EventbuildChain.cxx index c044dcc56f7b10d8d926270e8e3a809b2666f1ad..5b9df9737bc05086e9efc8d4d5a8e4bbaa52d78b 100644 --- a/algo/evbuild/EventbuildChain.cxx +++ b/algo/evbuild/EventbuildChain.cxx @@ -30,22 +30,17 @@ EventbuildChain::EventbuildChain(const Config& config) // ----- Run event building on a timeslice -------------------------------- -std::vector<DigiEvent> EventbuildChain::Run(const DigiData& timeslice) +EventbuildChain::ResultType EventbuildChain::Run(const DigiData& timeslice) { // --- Extract the digi time stamps of the trigger detector std::vector<double> digiTimes = GetDigiTimes(timeslice, fTriggerDet); // --- Call the trigger algorithm - std::vector<double> triggers = fTrigger(digiTimes).first; + auto [triggers, triggerMon] = fTrigger(digiTimes); // --- Perform event building - std::vector<DigiEvent> events = fBuilder(timeslice, triggers).first; - - // --- Apply event selector - auto notSelected = [&](DigiEvent& ev) { return !(fSelector(ev)); }; - auto removeIt = std::remove_if(events.begin(), events.end(), notSelected); - events.erase(removeIt, events.end()); + auto [events, evbuildMon] = fBuilder(timeslice, triggers, fSelector); // --- Run event QA DigiEventQaData qaData = fQa(events); @@ -53,7 +48,12 @@ std::vector<DigiEvent> EventbuildChain::Run(const DigiData& timeslice) // --- Some log L_(info) << "Triggers: " << triggers.size() << ", events " << events.size(); - return events; + ResultType result; + result.first = std::move(events); + result.second.trigger = triggerMon; + result.second.evbuild = evbuildMon; + + return result; } // ---------------------------------------------------------------------------- diff --git a/algo/evbuild/EventbuildChain.h b/algo/evbuild/EventbuildChain.h index 728e55541e48b7a8bbd8abf0889f1a9311e57812..9b81a556ed243674b2115a7b6e2b0cb7110314dd 100644 --- a/algo/evbuild/EventbuildChain.h +++ b/algo/evbuild/EventbuildChain.h @@ -25,6 +25,11 @@ namespace cbm::algo::evbuild class Config; + struct EventbuildChainMonitorData { + EventBuilderMonitorData evbuild; + TimeClusterTriggerMonitorData trigger; + }; + /** @class EventbuildChain ** @brief Steering class for event building from digi timeslices ** @author Volker Friese <v.friese@gsi.de> @@ -38,11 +43,13 @@ namespace cbm::algo::evbuild class EventbuildChain : public SubChain { public: + using ResultType = std::pair<std::vector<DigiEvent>, EventbuildChainMonitorData>; + /** @brief Constructor **/ EventbuildChain(const Config& config); /** @brief Execution **/ - std::vector<DigiEvent> Run(const DigiData&); + ResultType Run(const DigiData&); /** @brief Status info to logger **/ void Status() const; diff --git a/algo/global/Reco.cxx b/algo/global/Reco.cxx index 17da31ad9443a2448293bdbff0767f3e1c0447ee..97cacad54a581b8cacb1ba64c0bbbae80c8a8025 100644 --- a/algo/global/Reco.cxx +++ b/algo/global/Reco.cxx @@ -113,7 +113,12 @@ RecoResults Reco::Run(const fles::Timeslice& ts) // --- Digi event building std::vector<DigiEvent> events; - if (Opts().HasStep(Step::DigiTrigger)) events = fEventBuild->Run(unpackResult.first); + evbuild::EventbuildChainMonitorData evbuildMonitor; + if (Opts().HasStep(Step::DigiTrigger)) { + auto [ev, mon] = fEventBuild->Run(unpackResult.first); + events = std::move(ev); + evbuildMonitor = mon; + } sts::HitfinderMonitor stsHitfinderMonitor; if (Opts().HasStep(Step::LocalReco) && Opts().HasDetector(fles::Subsystem::STS)) @@ -123,6 +128,7 @@ RecoResults Reco::Run(const fles::Timeslice& ts) QueueUnpackerMetrics(ts, unpackMonitor, unpackResult.first); QueueStsRecoMetrics(stsHitfinderMonitor); + QueueEvbuildMetrics(evbuildMonitor); PrintTimings(ts_times); @@ -232,3 +238,43 @@ void Reco::QueueStsRecoMetrics(const sts::HitfinderMonitor& monitor) {"stsRecoNumHitBucketOverflow", monitor.fNumHitBucketOverflow}, }); } + +void Reco::QueueEvbuildMetrics(const evbuild::EventbuildChainMonitorData& mon) +{ + if (!HasMonitor()) return; + + const MetricTagSet tags = {{"hostname", fles::system::current_hostname()}, {"child", Opts().ChildId()}}; + + size_t nDigisTotal = 0; + size_t nDigisInEventsTotal = 0; + + auto queueDetMetrics = [&](std::string_view det, auto& detMon) { + size_t nDigis = detMon.nDigis; + size_t nDigisInEvents = detMon.nDigisInEvents; + double selectionRatio = nDigis > 0 ? double(nDigisInEvents) / nDigis : 0; + + nDigisTotal += nDigis; + nDigisInEventsTotal += nDigisInEvents; + + GetMonitor().QueueMetric("cbmreco", tags, + {{fmt::format("{}NumDigisTotal", det), nDigis}, + {fmt::format("{}NumDigisInEvents", det), nDigisInEvents}, + {fmt::format("{}EvSelectionRatio", det), selectionRatio}}); + }; + + queueDetMetrics("sts", mon.evbuild.sts); + queueDetMetrics("much", mon.evbuild.much); + queueDetMetrics("tof", mon.evbuild.tof); + queueDetMetrics("bmon", mon.evbuild.bmon); + queueDetMetrics("trd", mon.evbuild.trd); + queueDetMetrics("trd2d", mon.evbuild.trd2d); + queueDetMetrics("rich", mon.evbuild.rich); + + double totalSelectionRatio = nDigisTotal > 0 ? double(nDigisInEventsTotal) / nDigisTotal : 0; + GetMonitor().QueueMetric("cbmreco", tags, + {{"digiTriggerTimeTotal", mon.trigger.timeMs}, + {"eventbuildTimeTotal", mon.evbuild.timeMs}, + {"numTrigger", mon.trigger.nTriggers}, + {"numEvents", mon.evbuild.nEvents}, + {"totalEvSelectionRatio", totalSelectionRatio}}); +} diff --git a/algo/global/Reco.h b/algo/global/Reco.h index b12fcb51d5f3fd41ce2e71b2d1976ee952863ece..17e1e09d77af000f82622a7012ccfb7456ad6d12 100644 --- a/algo/global/Reco.h +++ b/algo/global/Reco.h @@ -60,6 +60,7 @@ namespace cbm::algo void QueueUnpackerMetrics(const fles::Timeslice&, const UnpackMonitorData&, const DigiData&); void QueueStsRecoMetrics(const sts::HitfinderMonitor&); + void QueueEvbuildMetrics(const evbuild::EventbuildChainMonitorData&); }; } // namespace cbm::algo diff --git a/algo/test/_GTestEventBuilder.cxx b/algo/test/_GTestEventBuilder.cxx index 9e30ce8f91843c26cd2d0b1a6f21f2882e584406..e435950775dbd12428671c12f5d2def0859f3679 100644 --- a/algo/test/_GTestEventBuilder.cxx +++ b/algo/test/_GTestEventBuilder.cxx @@ -52,7 +52,7 @@ TEST(_GTestEventBuilder, CheckEventBuilderAlgorithmSimple) triggerIn.push_back(i * triggerSpacing); } - cbm::algo::evbuild::EventBuilder::resultType result = evbuild(tsIn, triggerIn); + cbm::algo::evbuild::EventBuilder::resultType result = evbuild(tsIn, triggerIn, std::nullopt); std::vector<DigiEvent>& eventsOut = result.first; cbm::algo::evbuild::EventBuilderMonitorData& monitor = result.second; @@ -70,21 +70,21 @@ TEST(_GTestEventBuilder, CheckEventBuilderAlgorithmSimple) EXPECT_EQ(eventsOut[i].fTime, triggerIn[i]); } - EXPECT_EQ(monitor.fMuch.fNumInEvents, 9 * nTrigger); - EXPECT_EQ(monitor.fSts.fNumInEvents, 9 * nTrigger); - EXPECT_EQ(monitor.fTof.fNumInEvents, 9 * nTrigger); - EXPECT_EQ(monitor.fTrd.fNumInEvents, 9 * nTrigger); - EXPECT_EQ(monitor.fRich.fNumInEvents, 9 * nTrigger); - EXPECT_EQ(monitor.fPsd.fNumInEvents, 9 * nTrigger); - EXPECT_EQ(monitor.fFsd.fNumInEvents, 9 * nTrigger); - EXPECT_EQ(monitor.fBmon.fNumInEvents, 9 * nTrigger); + EXPECT_EQ(monitor.much.nDigisInEvents, 9 * nTrigger); + EXPECT_EQ(monitor.sts.nDigisInEvents, 9 * nTrigger); + EXPECT_EQ(monitor.tof.nDigisInEvents, 9 * nTrigger); + EXPECT_EQ(monitor.trd.nDigisInEvents, 9 * nTrigger); + EXPECT_EQ(monitor.rich.nDigisInEvents, 9 * nTrigger); + EXPECT_EQ(monitor.psd.nDigisInEvents, 9 * nTrigger); + EXPECT_EQ(monitor.fsd.nDigisInEvents, 9 * nTrigger); + EXPECT_EQ(monitor.bmon.nDigisInEvents, 9 * nTrigger); - EXPECT_EQ(monitor.fMuch.fNum, nInput); - EXPECT_EQ(monitor.fSts.fNum, nInput); - EXPECT_EQ(monitor.fTof.fNum, nInput); - EXPECT_EQ(monitor.fTrd.fNum, nInput); - EXPECT_EQ(monitor.fRich.fNum, nInput); - EXPECT_EQ(monitor.fPsd.fNum, nInput); - EXPECT_EQ(monitor.fFsd.fNum, nInput); - EXPECT_EQ(monitor.fBmon.fNum, nInput); + EXPECT_EQ(monitor.much.nDigis, nInput); + EXPECT_EQ(monitor.sts.nDigis, nInput); + EXPECT_EQ(monitor.tof.nDigis, nInput); + EXPECT_EQ(monitor.trd.nDigis, nInput); + EXPECT_EQ(monitor.rich.nDigis, nInput); + EXPECT_EQ(monitor.psd.nDigis, nInput); + EXPECT_EQ(monitor.fsd.nDigis, nInput); + EXPECT_EQ(monitor.bmon.nDigis, nInput); } diff --git a/algo/test/_GTestTimeClusterTrigger.cxx b/algo/test/_GTestTimeClusterTrigger.cxx index f2932774ab997b0fc2ca17eadc41357c1da95ae2..5cced089c530b7c57d5666fbe24a51a5c9d5492a 100644 --- a/algo/test/_GTestTimeClusterTrigger.cxx +++ b/algo/test/_GTestTimeClusterTrigger.cxx @@ -37,6 +37,6 @@ TEST(_GTestTimeClusterTrigger, CheckTriggerAlgorithmSimple) EXPECT_EQ(dataOut[i], 495. + i * 1000.); } - EXPECT_EQ(dataIn.size(), monitor.fNum); - EXPECT_EQ(nMinNumber * dataOut.size(), monitor.fNumInTrigger); + EXPECT_EQ(dataIn.size(), monitor.num); + EXPECT_EQ(nMinNumber * dataOut.size(), monitor.numInTrigger); } diff --git a/algo/trigger/TimeClusterTrigger.cxx b/algo/trigger/TimeClusterTrigger.cxx index 6cf6a87b8dc77f318c11640cd452a4be4d77971d..504ee44d71f711f52f5b660841e6f97a3c35aed3 100644 --- a/algo/trigger/TimeClusterTrigger.cxx +++ b/algo/trigger/TimeClusterTrigger.cxx @@ -10,6 +10,8 @@ #include <sstream> #include <vector> +#include <xpu/host.h> + using std::string; using std::stringstream; using std::vector; @@ -22,6 +24,8 @@ namespace cbm::algo::evbuild if (!std::is_sorted(dataVec.begin(), dataVec.end())) throw std::runtime_error("TimeClusterTrigger: unsorted input"); + xpu::push_timer("TimeClusterTrigger"); + // --- Parameters double winSize = fConfig.Window(); int32_t minNumData = fConfig.Threshold(); @@ -46,7 +50,7 @@ namespace cbm::algo::evbuild triggerVec.push_back(0.5 * (*current + *winStart)); // Increment monitoring counter with number of digis used - monitor.fNumInTrigger += std::distance(winStart, current) + 1; + monitor.numInTrigger += std::distance(winStart, current) + 1; // Start new window after dead time winStart = current + 1; @@ -60,7 +64,11 @@ namespace cbm::algo::evbuild current++; } // Store number of input data for monitoring - monitor.fNum += dataVec.size(); + monitor.num += dataVec.size(); + monitor.nTriggers = triggerVec.size(); + + auto timings = xpu::pop_timer(); + monitor.timeMs = timings.wall(); return result; } diff --git a/algo/trigger/TimeClusterTrigger.h b/algo/trigger/TimeClusterTrigger.h index ce8eec7098a8f2bf9726c7d2a0f7dd96df1821d4..814efe4a1213d892da0220687ed789072bf941c4 100644 --- a/algo/trigger/TimeClusterTrigger.h +++ b/algo/trigger/TimeClusterTrigger.h @@ -20,8 +20,10 @@ namespace cbm::algo::evbuild ** @brief Monitoring data for time cluster trigger algorithm **/ struct TimeClusterTriggerMonitorData { - size_t fNumInTrigger = 0; ///< Time stamps used for trigger building - size_t fNum = 0; ///< Total time stamps in input + size_t numInTrigger = 0; ///< Time stamps used for trigger building + size_t num = 0; ///< Total time stamps in input + size_t nTriggers = 0; ///< Number of triggers + double timeMs = 0.; ///< Time for trigger building in ms }; /** @class TimeClusterTrigger diff --git a/reco/tasks/CbmTaskBuildEvents.cxx b/reco/tasks/CbmTaskBuildEvents.cxx index b7fb3cc8c614ba4ee6bf45ee00a8734d6ae29159..2cd696a9ef3c04f856d3e7ec6bf9485f0d512124 100644 --- a/reco/tasks/CbmTaskBuildEvents.cxx +++ b/reco/tasks/CbmTaskBuildEvents.cxx @@ -121,8 +121,8 @@ void CbmTaskBuildEvents::Exec(Option_t*) // --- If the input is already CbmDigiTimeslice (from unpacking), use that directly if (fTimeslice) { timerStep.Start(); - *fEvents = - cbm::algo::DigiEvent::ToCbmDigiEvents((*fAlgo)(cbm::algo::DigiData(fTimeslice->fData), *fTriggers).first); + *fEvents = cbm::algo::DigiEvent::ToCbmDigiEvents( + (*fAlgo)(cbm::algo::DigiData(fTimeslice->fData), *fTriggers, std::nullopt).first); timerStep.Stop(); fTimeBuildEvt += timerStep.RealTime(); for (const auto& entry : fConfig->fWindows) @@ -138,7 +138,8 @@ void CbmTaskBuildEvents::Exec(Option_t*) timerStep.Stop(); fTimeFillTs += timerStep.RealTime(); timerStep.Start(); - *fEvents = cbm::algo::DigiEvent::ToCbmDigiEvents((*fAlgo)(cbm::algo::DigiData(ts.fData), *fTriggers).first); + *fEvents = + cbm::algo::DigiEvent::ToCbmDigiEvents((*fAlgo)(cbm::algo::DigiData(ts.fData), *fTriggers, std::nullopt).first); timerStep.Stop(); fTimeBuildEvt += timerStep.RealTime(); }