diff --git a/algo/ca/TrackingChain.cxx b/algo/ca/TrackingChain.cxx index d3ee72ab758c4e28ad48eae2805d8cbfdc7054e0..5ce7a4e51d717bc4ec01905717ad2644b32e54a8 100644 --- a/algo/ca/TrackingChain.cxx +++ b/algo/ca/TrackingChain.cxx @@ -40,7 +40,8 @@ using cbm::algo::ca::constants::clrs::GNb; // grin bald text // --------------------------------------------------------------------------------------------------------------------- // -TrackingChain::TrackingChain(ECbmRecoMode recoMode, const std::unique_ptr<cbm::algo::qa::Manager>& qaManager, std::string_view name) +TrackingChain::TrackingChain(ECbmRecoMode recoMode, const std::unique_ptr<cbm::algo::qa::Manager>& qaManager, + std::string_view name) : fQa(Qa(qaManager, name)) , fRecoMode(recoMode) { diff --git a/algo/ca/TrackingChain.h b/algo/ca/TrackingChain.h index 5d30319fb05404b00584baf1a6be9be787e0518c..39ba48e26fca9cea0cfa295408eb14345a856918 100644 --- a/algo/ca/TrackingChain.h +++ b/algo/ca/TrackingChain.h @@ -44,7 +44,8 @@ namespace cbm::algo /// \param recoMode Reconstruction mode /// \param pManager a QA-manager /// \param name A name of the task (histograms directory) - TrackingChain(ECbmRecoMode recoMode, const std::unique_ptr<cbm::algo::qa::Manager>& qaManager = nullptr, std::string_view name = ""); + TrackingChain(ECbmRecoMode recoMode, const std::unique_ptr<cbm::algo::qa::Manager>& qaManager = nullptr, + std::string_view name = ""); /// \struct Input_t /// \brief Input to the TrackingChain diff --git a/algo/ca/core/utils/CaMonitor.h b/algo/ca/core/utils/CaMonitor.h index 389b196fef4b51be0b5c8b054c0967cb6216fe7b..6d26469cfa6ceec81d71a9742786360776629f24 100644 --- a/algo/ca/core/utils/CaMonitor.h +++ b/algo/ca/core/utils/CaMonitor.h @@ -171,12 +171,13 @@ namespace cbm::algo::ca using std::setfill; using std::setw; std::stringstream msg; - constexpr size_t widthKey = 30; constexpr size_t width = 24; + auto Cmp = [](const std::string& l, const std::string& r) { return l.size() < r.size(); }; msg << "\n===== Monitor: " << fsName << "\n"; if constexpr (!std::is_same_v<ETimerKey, EDummy>) { + size_t widthKeyTimer{std::max_element(faTimerNames.begin(), faTimerNames.end(), Cmp)->size() + 1}; msg << "\n----- Timers:\n"; - msg << setw(widthKey) << left << "Key" << ' '; + msg << setw(widthKeyTimer) << left << "Key" << ' '; msg << setw(width) << left << "N Calls" << ' '; msg << setw(width) << left << "Average [s]" << ' '; msg << setw(width) << left << "Min [s]" << ' '; @@ -185,7 +186,7 @@ namespace cbm::algo::ca msg << right; for (int iKey = 0; iKey < fMonitorData.GetNofTimers(); ++iKey) { const Timer& timer = fMonitorData.GetTimer(static_cast<ETimerKey>(iKey)); - msg << setw(widthKey) << faTimerNames[iKey] << ' '; + msg << setw(widthKeyTimer) << faTimerNames[iKey] << ' '; msg << setw(width) << timer.GetNofCalls() << ' '; msg << setw(width) << timer.GetAverage() << ' '; msg << setw(width) << timer.GetMin() << ' '; @@ -195,7 +196,8 @@ namespace cbm::algo::ca } msg << "\n----- Counters:\n"; - msg << setw(widthKey) << left << "Key" << ' '; + size_t widthKeyCounter{std::max_element(faCounterNames.begin(), faCounterNames.end(), Cmp)->size() + 1}; + msg << setw(widthKeyCounter) << left << "Key" << ' '; msg << setw(width) << left << "Total" << ' '; for (auto key : fvCounterRatioKeys) { msg << setw(width) << left << std::string("per ") + faCounterNames[key] << ' '; @@ -203,7 +205,7 @@ namespace cbm::algo::ca msg << '\n'; for (int iKey = 0; iKey < fMonitorData.GetNofCounters(); ++iKey) { auto counterValue = fMonitorData.GetCounterValue(static_cast<ECounterKey>(iKey)); - msg << setw(widthKey) << left << faCounterNames[iKey] << ' '; + msg << setw(widthKeyCounter) << left << faCounterNames[iKey] << ' '; msg << setw(width) << right << counterValue << ' '; for (auto keyDen : fvCounterRatioKeys) { auto ratio = static_cast<double>(counterValue) / fMonitorData.GetCounterValue(keyDen); diff --git a/algo/global/Reco.cxx b/algo/global/Reco.cxx index 7f7de2d060028950de00968556602c9838aa245b..e9d10bdd359ceb8fa25a6a3df9de825c5f75abfe 100644 --- a/algo/global/Reco.cxx +++ b/algo/global/Reco.cxx @@ -491,6 +491,7 @@ void Reco::Finalize() fTrackingEvent->Finalize(); } if (fbReconstructDigiEvents) { + fV0Finder->Finalize(); L_(info) << fEvSelectingMonitor.ToString(); } diff --git a/algo/kfp/KfpV0Finder.cxx b/algo/kfp/KfpV0Finder.cxx index 52a8f0d03113e0f9d70951a518b2f60cf728e073..5677dc5f6dcafa86a2b7d5ee513a50e05d0985fd 100644 --- a/algo/kfp/KfpV0Finder.cxx +++ b/algo/kfp/KfpV0Finder.cxx @@ -20,5 +20,8 @@ void V0Finder::Init() {} CbmEventTriggers V0Finder::Process(const RecoResults&) { CbmEventTriggers res; + fEventMonitor.Reset(); + fEventMonitor.StartTimer(ETimer::Event); + fEventMonitor.StopTimer(ETimer::Event); return res; } diff --git a/algo/kfp/KfpV0Finder.h b/algo/kfp/KfpV0Finder.h index 5240085b8924627f006c9cc3be35594b6d2e1480..e34e543d26b6d31dcfc0b528bd191d5e28aef32e 100644 --- a/algo/kfp/KfpV0Finder.h +++ b/algo/kfp/KfpV0Finder.h @@ -12,6 +12,7 @@ #include "CbmEventTriggers.h" #include "KFParticleTopoReconstructor.h" #include "global/RecoResults.h" +#include "kfp/KfpV0FinderMonitor.h" #include <memory> @@ -50,10 +51,13 @@ namespace cbm::algo::kfp /// \brief Constant access to the KfParticleFinder of the run topology reconstructor const KFParticleFinder* GetKFParticleFinder() const { return fpTopoReconstructor->GetKFParticleFinder(); } + /// \brief Gets monitor data + const V0FinderMonitorData_t& GetEventMonitor() const { return fEventMonitor; } + /// \brief Initializes the instance (called in the beginning of the run) void Init(); - /// \brief Processes a reconstructed data sample, returns a collection of fired triggers + /// \brief Processes a reconstructed data sample, returns a collection of fired triggers CbmEventTriggers Process(const RecoResults& recoEvent); /// \brief Sets minimal pion DCA to primary vertex @@ -120,6 +124,8 @@ namespace cbm::algo::kfp /// \brief An instance of the topology reconstructor std::unique_ptr<KFParticleTopoReconstructor> fpTopoReconstructor{std::make_unique<KFParticleTopoReconstructor>()}; + V0FinderMonitorData_t fEventMonitor; ///< Monitor data instance (per event) + //* Different run-time cuts and flags (TODO: define in a config) double fTzeroOffset{0.}; ///< Offset for T0 double fMinPionDca{1.5}; ///< Minimum DCA to PV for pions diff --git a/algo/kfp/KfpV0FinderChain.cxx b/algo/kfp/KfpV0FinderChain.cxx index 1fb1a7a9d9a0a32606bbd3759e9006bd88c97a21..621f4d0d88b2b11216b31c2d8df07455678766cc 100644 --- a/algo/kfp/KfpV0FinderChain.cxx +++ b/algo/kfp/KfpV0FinderChain.cxx @@ -20,7 +20,7 @@ using cbm::algo::V0FinderChain; // --------------------------------------------------------------------------------------------------------------------- // -void V0FinderChain::Finalize() {} +void V0FinderChain::Finalize() { L_(info) << fMonitorRun.ToString(); } // --------------------------------------------------------------------------------------------------------------------- // @@ -74,26 +74,26 @@ try { // TODO: In future, there are will be a several instances of the V0Finder, each for a particular thread { //* Set particle PID properties - fV0Finder.SetMinPionDca(pion.minDca); - fV0Finder.SetMinProtonDca(proton.minDca); - fV0Finder.SetPionVelocityRange(pion.minVelocity, pion.maxVelocity); - fV0Finder.SetProtonVelocityRange(proton.minVelocity, proton.maxVelocity); + fFinder.SetMinPionDca(pion.minDca); + fFinder.SetMinProtonDca(proton.minDca); + fFinder.SetPionVelocityRange(pion.minVelocity, pion.maxVelocity); + fFinder.SetProtonVelocityRange(proton.minVelocity, proton.maxVelocity); //* Set KFParticleFinder properties auto& kfpCuts{config.cuts.kfp}; - fV0Finder.SetLdLCut2D(kfpCuts.minDecayLDL); - fV0Finder.SetLCut(kfpCuts.minDecayLength); - fV0Finder.SetChi2Cut2D(kfpCuts.maxChi2NdfGeo); - fV0Finder.SetChiPrimaryCut2D(kfpCuts.maxChi2NdfPrim); + fFinder.SetLdLCut2D(kfpCuts.minDecayLDL); + fFinder.SetLCut(kfpCuts.minDecayLength); + fFinder.SetChi2Cut2D(kfpCuts.maxChi2NdfGeo); + fFinder.SetChiPrimaryCut2D(kfpCuts.maxChi2NdfPrim); //* Set other properties - fV0Finder.SetTzeroOffset(config.tZeroOffset); - fV0Finder.SetQpAssignedUncertainty(config.qpAssignedUncertainty); - fV0Finder.AddDecayToReconstructionList(config.reconstructPdg); - fV0Finder.SetPrimaryAssignedPdg(config.primaryAssignedPdg); + fFinder.SetTzeroOffset(config.tZeroOffset); + fFinder.SetQpAssignedUncertainty(config.qpAssignedUncertainty); + fFinder.AddDecayToReconstructionList(config.reconstructPdg); + fFinder.SetPrimaryAssignedPdg(config.primaryAssignedPdg); //* Init the V0 finder - fV0Finder.Init(); + fFinder.Init(); } L_(info) << "kfp::V0FinderChain: initializing the V0-finder chain ... done"; } @@ -104,4 +104,11 @@ catch (const std::exception& err) { // --------------------------------------------------------------------------------------------------------------------- // -CbmEventTriggers V0FinderChain::ProcessEvent(const RecoResults& recoEvent) { return fV0Finder.Process(recoEvent); } +V0FinderChain::EventOutput V0FinderChain::ProcessEvent(const RecoResults& recoEvent) +{ + EventOutput res; + res.triggers = fFinder.Process(recoEvent); + res.monitor = fFinder.GetEventMonitor(); + fMonitorRun.AddMonitorData(res.monitor); + return res; +} diff --git a/algo/kfp/KfpV0FinderChain.h b/algo/kfp/KfpV0FinderChain.h index e3582f93167d8c369a738dd9409a3d55c73013a3..2be7ddf5d72923f61923893ddb005f5cfcd4fe88 100644 --- a/algo/kfp/KfpV0FinderChain.h +++ b/algo/kfp/KfpV0FinderChain.h @@ -13,6 +13,7 @@ #include "base/SubChain.h" #include "global/RecoResults.h" #include "kfp/KfpV0Finder.h" +#include "kfp/KfpV0FinderMonitor.h" namespace cbm::algo { @@ -20,6 +21,13 @@ namespace cbm::algo /// \brief A chain for the V0 finder class V0FinderChain : public SubChain { public: + /// \struct EventOutput + /// \brief Output from the event + struct EventOutput { + CbmEventTriggers triggers; ///< Set of triggers + kfp::V0FinderMonitorData_t monitor; ///< Monitor + }; + /// \brief Default constructor V0FinderChain() = default; @@ -44,10 +52,12 @@ namespace cbm::algo /// \brief Initializes the instance (called in the beginning of the run) void Init(); - /// \brief Processes an event, returns a collection of fired triggers - CbmEventTriggers ProcessEvent(const RecoResults& recoEvent); + /// \brief Processes an event, returns a collection of fired triggers + EventOutput ProcessEvent(const RecoResults& recoEvent); + private: - kfp::V0Finder fV0Finder; ///< Instance of the V0-finding algorithm + kfp::V0Finder fFinder; ///< Instance of the V0-finding algorithm + kfp::V0FinderMonitor fMonitorRun; ///< Monitor per run }; } // namespace cbm::algo diff --git a/algo/kfp/KfpV0FinderMonitor.h b/algo/kfp/KfpV0FinderMonitor.h new file mode 100644 index 0000000000000000000000000000000000000000..1f63bb246affbab2117b347722ef120a23cf33bc --- /dev/null +++ b/algo/kfp/KfpV0FinderMonitor.h @@ -0,0 +1,86 @@ +/* Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file KfpV0FinderMonitor.h +/// \date 03.02.2025 +/// \brief A monitor for the V0Finder +/// \author Sergei Zharko <s.zharko@gsi.de> + +#pragma once + +#include "CaMonitor.h" + +namespace cbm::algo::kfp +{ + /// \enum ECounter + /// \brief Counter keys for the V0FinderMonitor + enum class ECounter + { + TracksTotal, ///< Total number of tracks + TracksSelected, ///< Tracks, which satisfy topology PID applicability + TracksInfiniteParam, ///< Tracks, which have infinite parameters + TracksWoTofHits, ///< Tracks, which have no TOF hits + TracksWNegativeTofHitTime, ///< Tracks, the last TOF hit of which has a negative time (it's time is less then the t0) + TracksWoStsHits, ///< Tracks, which have no STS hits + TracksWoPid, ///< Tracks, which has undefined PID + TracksWoMomentum, ///< Tracks, which has no momentum + TracksWUnphysicalBeta, ///< Tracks with beta > 1 + Pions, ///< Number of pion-candidates + Protons, ///< Number of proton-candidates + EventsTotal, ///< Total number of events + EventsWoTzero, ///< Number of events with undefined t-zero + EventsLambdaCand, ///< Events with at least one pion and one proton candidate + KfpEventsLambdaCand, ///< Events with lambda-candidates in KF-particle + KfpLambdaCandidates, ///< Number of lambda-candidates + END + }; + + /// \enum ETimer + /// \brief Timer keys for the V0FinderMonitor + enum class ETimer + { + Event, ///< Timer to process a single event + END + }; + + /// \brief Specification of ca::MonitorData for the V0Finder + using V0FinderMonitorData_t = ca::MonitorData<ECounter, ETimer>; + + /// \class Monitor + /// \brief A monitor for the V0Finder + class V0FinderMonitor : public ca::Monitor<ECounter, ETimer> { + public: + /// \brief Default constructor + V0FinderMonitor() : ca::Monitor<ECounter, ETimer>("V0 finder monitor") + { + SetCounterName(ECounter::TracksTotal, "all tracks"); + SetCounterName(ECounter::TracksSelected, "pre-selected tracks"); + SetCounterName(ECounter::TracksInfiniteParam, "tracks satisfying PID selection"); + SetCounterName(ECounter::TracksWoTofHits, "tracks w/o TOF hits"); + SetCounterName(ECounter::TracksWNegativeTofHitTime, "tracks w/ negative TOF time"); + SetCounterName(ECounter::TracksWoStsHits, "tracks w/o STS hits"); + SetCounterName(ECounter::TracksWoPid, "tracks w/o PID"); + SetCounterName(ECounter::TracksWoMomentum, "tracks w/o momentum"); + SetCounterName(ECounter::TracksWUnphysicalBeta, "tracks w/ beta > 1"); + SetCounterName(ECounter::Pions, "pion candidates"); + SetCounterName(ECounter::Protons, "proton candidates"); + SetCounterName(ECounter::EventsTotal, "all events"); + SetCounterName(ECounter::EventsWoTzero, "events w/o t0"); + SetCounterName(ECounter::EventsLambdaCand, "events passed to KFP"); + SetCounterName(ECounter::KfpEventsLambdaCand, "events w/ lambda candidates"); + SetCounterName(ECounter::KfpLambdaCandidates, "lambda candidates"); + + SetTimerName(ETimer::Event, "event processing"); + } + + private: + friend class boost::serialization::access; + template<typename Archive> + void serialize(Archive& ar, const unsigned int /*version*/) + { + ar& boost::serialization::base_object<ca::Monitor<ECounter, ETimer>>(*this); + } + }; + +} // namespace cbm::algo::kfp