diff --git a/reco/L1/CMakeLists.txt b/reco/L1/CMakeLists.txt index 1564b7318a78a618cf330a75c7c03a624d3c0c94..080760aca90f84bb3e73d0f7a4182dd42cc32d9c 100644 --- a/reco/L1/CMakeLists.txt +++ b/reco/L1/CMakeLists.txt @@ -111,6 +111,7 @@ set(HEADERS L1Algo/L1EArray.h L1Algo/L1Undef.h L1Algo/utils/CaUvConverter.h + L1Algo/utils/CaMonitor.h catools/CaToolsWindowFinder.h catools/CaToolsLinkKey.h catools/CaToolsHitRecord.h @@ -214,6 +215,7 @@ install(FILES CbmL1Counters.h utils/CbmCaIdealHitProducer.h utils/CbmCaIdealHitProducerDet.h L1Algo/utils/CaUvConverter.h + L1Algo/utils/CaMonitor.h qa/CbmCaInputQaBase.h DESTINATION include ) diff --git a/reco/L1/CbmCaMCModule.cxx b/reco/L1/CbmCaMCModule.cxx index d70f501990a5b4a24dc3345d5a9119f2e859f12d..2e65dc8449572bf6c7000a457bab524be1c43dea 100644 --- a/reco/L1/CbmCaMCModule.cxx +++ b/reco/L1/CbmCaMCModule.cxx @@ -92,6 +92,19 @@ try { // Check initialization this->CheckInit(); + // Init monitor + fMonitor.SetKeyName(EMonitorKey::kMcTrack, "N MC tracks"); + fMonitor.SetKeyName(EMonitorKey::kMcTrackReconstructable, "N MC tracks rec-able"); + fMonitor.SetKeyName(EMonitorKey::kMcPoint, "N MC points"); + fMonitor.SetKeyName(EMonitorKey::kRecoNevents, "N reco events"); + fMonitor.SetKeyName(EMonitorKey::kMissedMatchesMvd, "N missed MVD matches"); + fMonitor.SetKeyName(EMonitorKey::kMissedMatchesSts, "N missed STS matches"); + fMonitor.SetKeyName(EMonitorKey::kMissedMatchesMuch, "N missed MuCh matches"); + fMonitor.SetKeyName(EMonitorKey::kMissedMatchesTrd, "N missed TRD matches"); + fMonitor.SetKeyName(EMonitorKey::kMissedMatchesTof, "N missed TOF matches"); + fMonitor.SetRatioKeys({EMonitorKey::kRecoNevents}); + + LOG(info) << "CA MC Module: initializing CA tracking Monte-Carlo module... \033[1;32mDone!\033[0m"; return true; } @@ -125,12 +138,16 @@ void MCModule::InitEvent(CbmEvent* /*pEvent*/) fpMCData->Clear(); this->ReadMCTracks(); this->ReadMCPoints(); + fMonitor.Increment(EMonitorKey::kMcTrack, fpMCData->GetNofPoints()); + fMonitor.Increment(EMonitorKey::kMcPoint, fpMCData->GetNofTracks()); // Prepare tracks: set point indexes and redefine indexes from external to internal containers for (auto& aTrk : fpMCData->GetTrackContainer()) { aTrk.SortPointIndexes( [&](const int& iPl, const int& iPr) { return fpMCData->GetPoint(iPl).GetZ() < fpMCData->GetPoint(iPr).GetZ(); }); } + + fMonitor.Increment(EMonitorKey::kRecoNevents); } // --------------------------------------------------------------------------------------------------------------------- @@ -182,7 +199,7 @@ void MCModule::InitTrackInfo() // --------------------------------------------------------------------------------------------------------------------- // -void MCModule::Finish() {} +void MCModule::Finish() { LOG(info) << '\n' << fMonitor.ToString(); } // ********************************** @@ -200,6 +217,9 @@ void MCModule::MatchRecoAndMC() this->MatchPointsAndHits<L1DetectorID::kTof>(); this->MatchRecoAndMCTracks(); this->InitTrackInfo(); + for (const auto& trkMC : fpMCData->GetTrackContainer()) { + if (trkMC.IsReconstructable()) { fMonitor.Increment(EMonitorKey::kMcTrackReconstructable); } + } } // --------------------------------------------------------------------------------------------------------------------- diff --git a/reco/L1/CbmCaMCModule.h b/reco/L1/CbmCaMCModule.h index af9ea9ef2cc51c8f1c3ac806d58394f92b61e42b..e51f7ed6ef2eb6a03c41862a34da793ff50f9f78 100644 --- a/reco/L1/CbmCaMCModule.h +++ b/reco/L1/CbmCaMCModule.h @@ -34,6 +34,7 @@ #include <string_view> #include <type_traits> +#include "CaMonitor.h" #include "CaToolsMCData.h" #include "CaToolsMCPoint.h" #include "L1Constants.h" @@ -100,7 +101,7 @@ namespace cbm::ca /// This method finds a match for a given hit or matches for hits clusters (in case of STS), finds the best /// link in the match and returns the corresponding global ID of the MC points. template<L1DetectorID DetId> - int MatchHitWithMc(int iHitExt) const; + int MatchHitWithMc(int iHitExt); /// @brief Match reconstructed and MC data /// @@ -202,6 +203,23 @@ namespace cbm::ca template<L1DetectorID DetID> std::optional<::ca::tools::MCPoint> FillMCPoint(int iExtId, int iEvent, int iFile); + /// @enum EMonitorKey + /// @brief Monitor keys + enum class EMonitorKey + { + kMcTrack, ///< Number of MC tracks + kMcTrackReconstructable, ///< Number of reconstructable MC tracks + kMcPoint, ///< Number of MC points + kRecoNevents, ///< Number of events + kMissedMatchesMvd, ///< Number of missed matches in MVD + kMissedMatchesSts, ///< Number of missed matches in STS + kMissedMatchesMuch, ///< Number of missed matches in MuCh + kMissedMatchesTrd, ///< Number of missed matches in TRD + kMissedMatchesTof, ///< Number of missed TOF matches + kEND + }; + ::ca::Monitor<EMonitorKey> fMonitor {"CA MC Module"}; ///< Monitor + // ------ Flags CbmCaDetIdArr_t<bool> fvbUseDet = {{false}}; ///< Flag: is detector subsystem used bool fbLegacyEventMode = false; ///< if tracking uses events instead of time-slices (back compatibility) @@ -245,11 +263,27 @@ namespace cbm::ca // --------------------------------------------------------------------------------------------------------------------- // template<L1DetectorID DetID> -int cbm::ca::MCModule::MatchHitWithMc(int iHitExt) const +int cbm::ca::MCModule::MatchHitWithMc(int iHitExt) { int iPoint = -1; const auto* pHitMatch = dynamic_cast<CbmMatch*>(fvpBrHitMatches[DetID]->At(iHitExt)); - assert(pHitMatch); + if (!pHitMatch) { + LOG(warn) << "Hit match with index " << iHitExt << " is missing for " << kDetName[DetID]; + if constexpr (L1DetectorID::kMvd == DetID) { fMonitor.Increment(EMonitorKey::kMissedMatchesMvd); } + else if constexpr (L1DetectorID::kSts == DetID) { + fMonitor.Increment(EMonitorKey::kMissedMatchesSts); + } + else if constexpr (L1DetectorID::kMuch == DetID) { + fMonitor.Increment(EMonitorKey::kMissedMatchesMuch); + } + else if constexpr (L1DetectorID::kTrd == DetID) { + fMonitor.Increment(EMonitorKey::kMissedMatchesTrd); + } + else if constexpr (L1DetectorID::kTof == DetID) { + fMonitor.Increment(EMonitorKey::kMissedMatchesTof); + } + return iPoint; + } if constexpr (L1DetectorID::kTof == DetID) { for (int iLink = 0; iLink < pHitMatch->GetNofLinks(); ++iLink) { diff --git a/reco/L1/CbmL1.cxx b/reco/L1/CbmL1.cxx index 56dac242b2851b495cc46631e819c4c59af55a89..bf0a7c1cdd5f357226fbb5d2b540c6cc263a6fae 100644 --- a/reco/L1/CbmL1.cxx +++ b/reco/L1/CbmL1.cxx @@ -659,9 +659,12 @@ InitStatus CbmL1::Init() DumpMaterialToFile("L1material.root"); - // Initialize counters - fEventNo = 0; - fNofRecoTracks = 0; + // Initialize monitor + fMonitor.SetKeyName(EMonitorKey::kEvent, "N events"); + fMonitor.SetKeyName(EMonitorKey::kRecoTrack, "N reco tracks"); + fMonitor.SetKeyName(EMonitorKey::kRecoHit, "N hits"); + fMonitor.SetRatioKeys({EMonitorKey::kEvent, EMonitorKey::kRecoTrack}); + fMonitor.Reset(); return kSUCCESS; } @@ -788,9 +791,10 @@ void CbmL1::Reconstruct(CbmEvent* event) t.Hits.push_back(cbmHitID); } fvRecoTracks.push_back(t); + fMonitor.Increment(EMonitorKey::kRecoHit, it->NHits); } - fNofRecoTracks += static_cast<int>(fpAlgo->fRecoTracks.size()); + fMonitor.Increment(EMonitorKey::kRecoTrack, fvRecoTracks.size()); LOG(debug) << "CA Track Finder: " << fpAlgo->fCaRecoTime << " s/sub-ts"; @@ -829,6 +833,7 @@ void CbmL1::Reconstruct(CbmEvent* event) } ++fEventNo; + fMonitor.Increment(EMonitorKey::kEvent); } // ----- Finish CbmStsFitPerformanceTask task ----------------------------- @@ -836,9 +841,9 @@ void CbmL1::Finish() { // monitor the material - LOG(info) << "\033[31;1m ****************************\033[0m"; - LOG(info) << "\033[31;1m ** CA Tracking monitore **\033[0m"; - LOG(info) << "\033[31;1m ****************************\033[0m"; + LOG(info) << "\033[31;1m ***************************\033[0m"; + LOG(info) << "\033[31;1m ** CA Tracking monitor **\033[0m"; + LOG(info) << "\033[31;1m ***************************\033[0m"; LOG(info) << "\033[31;1m ----- Material budget -------------------------------------- \033[0m"; @@ -848,11 +853,7 @@ void CbmL1::Finish() LOG(info) << "\033[31;1m -------------------------------------------------------------\033[0m"; // monitor of the reconstructed tracks - LOG(info) << "\033[31;1m ----- Counters ----------------------------------------------\033[0m"; - LOG(info) << "\tNumber of analyzed events: " << fEventNo; - LOG(info) << "\tNumber of reconstructed tracks: " << fNofRecoTracks; - LOG(info) << "\tNumber of reconstructed tracks per event/TS: " << static_cast<double>(fNofRecoTracks) / fEventNo; - LOG(info) << "\033[31;1m -------------------------------------------------------------\033[0m"; + LOG(info) << '\n' << fMonitor.ToString(); TDirectory* curr = gDirectory; TFile* currentFile = gFile; diff --git a/reco/L1/CbmL1.h b/reco/L1/CbmL1.h index 0eb834827ca58a32e9e5cd28f9fc17954c4118f1..82358e36ef9de87618b9c55a7bd6374b1ed54818 100644 --- a/reco/L1/CbmL1.h +++ b/reco/L1/CbmL1.h @@ -53,6 +53,7 @@ #include <unordered_map> #include <utility> +#include "CaMonitor.h" #include "L1Algo/L1Algo.h" #include "L1Algo/L1Vector.h" #include "L1EventEfficiencies.h" @@ -257,6 +258,17 @@ public: void SetMcbmMode() { fTrackingMode = L1Algo::TrackingMode::kMcbm; } void SetGlobalMode() { fTrackingMode = L1Algo::TrackingMode::kGlobal; } + // Tracking monitor (prototype) + enum class EMonitorKey + { + kEvent, + kRecoTrack, + kRecoHit, + kEND + }; + + ca::Monitor<EMonitorKey> fMonitor = {"CA Tracking"}; ///< Tracking monitor + // void SetTrackingLevel( Int_t iLevel ){ fTrackingLevel = iLevel; } // void MomentumCutOff( Double_t cut ){ fMomentumCutOff = cut; } diff --git a/reco/L1/L1Algo/utils/CaMonitor.h b/reco/L1/L1Algo/utils/CaMonitor.h new file mode 100644 index 0000000000000000000000000000000000000000..70f908db614b018899956acd061a41c20a60d645 --- /dev/null +++ b/reco/L1/L1Algo/utils/CaMonitor.h @@ -0,0 +1,114 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// @file CaMonitor.h +/// @brief CA Tracking monitor class +/// @since 25.08.2023 +/// @author S.Zharko <s.zharko@gsi.de> + +#ifndef CaMonitor_h +#define CaMonitor_h 1 + +#include <iomanip> +#include <sstream> +#include <string> + +#include "L1EArray.h" + +namespace ca +{ + /// @class Monitor + /// @brief Monitor class for CA tracking + /// @tparam EMonitorKey A enum class, containing keys for monitorables + /// + template<class EMonitorKey> + class Monitor { + public: + /// @brief Alias to array, indexed by Monitorable enumeration + template<typename T> + using MonitorableArr_t = L1EArray<EMonitorKey, T>; + + /// @brief Constructor + /// @param name Name of monitor + Monitor(const std::string& name) : fsName(name) {} + + /// @brief Gets key name + /// @param key Monitorable key + const std::string& GetKeyName(EMonitorKey key) const { return faKeyNames[key]; } + + /// @brief Gets counter value + /// @param key + int GetValue(EMonitorKey key) const { return faKeyCounters[key]; } + + /// @brief Increments key counter by 1 + /// @param key Monitorable key + void Increment(EMonitorKey key) { ++faKeyCounters[key]; }; + + /// @brief Increments key counter by a number + /// @param key Monitorable key + /// @param num Number to add + void Increment(EMonitorKey key, int num) { faKeyCounters[key] += num; } + + /// @brief Resets the counters + void Reset() { faKeyCounters.fill(0); } + + /// @brief Sets keys of monitorables, which are used as denominators for ratios + /// @param vKeys Vector of keys + void SetRatioKeys(const std::vector<EMonitorKey>& vKeys) { fvRatioKeys = vKeys; } + + /// @brief Sets name of key + /// @param name Name of monitoralble + void SetKeyName(EMonitorKey key, const char* name) { faKeyNames[key] = name; } + + /// @brief Prints counters summary to string + std::string ToString() const; + + private: + std::vector<EMonitorKey> fvRatioKeys {}; ///< List of keys, which are used as denominators in ratios + std::string fsName; ///< Name of the monitor + MonitorableArr_t<std::string> faKeyNames {}; ///< Names of keys + MonitorableArr_t<int> faKeyCounters {}; ///< Counters of keys + }; +} // namespace ca + +// ***************************************** +// ** Template function implementations ** +// ***************************************** + + +// --------------------------------------------------------------------------------------------------------------------- +// +template<class EMonitorKey> +std::string ca::Monitor<EMonitorKey>::ToString() const +{ + using std::left; + using std::right; + using std::setfill; + using std::setw; + std::stringstream msg; + constexpr size_t width = 24; + size_t fillWidth = (width + 2) * (1 + fvRatioKeys.size()); + msg << "----- Monitor: " << fsName << ' ' << setw(fillWidth - fsName.size() - 16) << setfill('-') << '-' << '\n'; + msg << setfill(' '); + msg << setw(width) << left << "Key" << ' '; + msg << setw(width) << left << "Total" << ' '; + for (auto key : fvRatioKeys) { + msg << setw(width) << left << std::string("per ") + faKeyNames[key] << ' '; + } + msg << '\n'; + for (int iKey = 0; iKey < static_cast<int>(EMonitorKey::kEND); ++iKey) { + msg << setw(width) << left << faKeyNames[iKey] << ' '; + msg << setw(width) << right << faKeyCounters[iKey] << ' '; + for (auto keyDen : fvRatioKeys) { + auto ratio = static_cast<double>(faKeyCounters[iKey]) / faKeyCounters[keyDen]; + msg << setw(width) << right << ratio << ' '; + } + msg << '\n'; + } + msg << setw(fillWidth) << setfill('-') << '-' << '\n'; + msg << setfill(' '); + return msg.str(); +} + +#endif // CaToolsMonitor_h diff --git a/reco/L1/qa/CbmCaOutputQa.cxx b/reco/L1/qa/CbmCaOutputQa.cxx index d1d3b944fe1764d83383ed941090dcc1059b592b..121e8359885ebf416757747846f7774a5b438003 100644 --- a/reco/L1/qa/CbmCaOutputQa.cxx +++ b/reco/L1/qa/CbmCaOutputQa.cxx @@ -475,6 +475,14 @@ InitStatus OutputQa::InitDataBranches() if (!fpMCModule->InitRun()) { return kFATAL; } } + // Initialize monitor + fMonitor.SetKeyName(EMonitorKey::kEvent, "N events"); + fMonitor.SetKeyName(EMonitorKey::kTrack, "N reco tracks"); + fMonitor.SetKeyName(EMonitorKey::kHit, "N hits"); + fMonitor.SetKeyName(EMonitorKey::kMcTrack, "N MC tracks"); + fMonitor.SetKeyName(EMonitorKey::kMcPoint, "N MC points"); + fMonitor.SetRatioKeys({EMonitorKey::kEvent, EMonitorKey::kTrack}); + return kSUCCESS; } @@ -554,41 +562,44 @@ InitStatus OutputQa::InitHistograms() bool OutputQa::Check() { // Create summary table - int nRows = std::count_if(fvbTrackTypeOn.begin(), fvbTrackTypeOn.end(), [](const auto& f) { return f == true; }); - CbmQaTable* aTable = MakeQaObject<CbmQaTable>("summary_table", "Tracking summary table", nRows + 1, 9); - int iRow = 0; - std::vector<std::string> colNames = {"Efficiency", "Killed", "Length", "Fakes", "Clones", - "Reco/Evt", "MC/Evt", "Nst(hit)", "Nst(point)"}; - aTable->SetNamesOfCols(colNames); - aTable->SetColWidth(14); - double nEvents = static_cast<double>(GetEventNumber()); - LOG(info) << "Number of events: " << GetEventNumber(); - for (int iTrType = 0; iTrType < static_cast<int>(fvpTrackHistograms.size()); ++iTrType) { - if (!fvbTrackTypeOn[iTrType] || !fvpTrackHistograms[iTrType]->IsMCUsed()) { continue; } - aTable->SetRowName(iRow, fvpTrackHistograms[iTrType]->GetTitle()); - aTable->SetCell(iRow, 0, fvpTrackHistograms[iTrType]->GetIntegratedEff()); - aTable->SetCell(iRow, 1, fvpTrackHistograms[iTrType]->GetKilledRate()); - aTable->SetCell(iRow, 2, fvpTrackHistograms[iTrType]->GetAverageRecoLength()); - aTable->SetCell(iRow, 3, fvpTrackHistograms[iTrType]->GetAverageFakeLength()); - aTable->SetCell(iRow, 4, fvpTrackHistograms[iTrType]->GetClonesRate()); - aTable->SetCell(iRow, 5, fvpTrackHistograms[iTrType]->GetNofRecoTracksMatched() / nEvents); - aTable->SetCell(iRow, 6, fvpTrackHistograms[iTrType]->GetNofMCTracks() / nEvents); - aTable->SetCell(iRow, 7, fvpTrackHistograms[iTrType]->GetAverageNofStationsWithHit()); - aTable->SetCell(iRow, 8, fvpTrackHistograms[iTrType]->GetAverageNofStationsWithPoint()); - ++iRow; - } - double nGhosts = 0.; - if (fvpTrackHistograms[ETrackType::kGhost] && fvpTrackHistograms[ETrackType::kAll]) { - nGhosts = fvpTrackHistograms[ETrackType::kGhost]->fph_reco_p->GetEntries(); - aTable->SetRowName(iRow, "N ghosts"); - aTable->SetCell(iRow, 0, nGhosts); - aTable->SetRowName(iRow + 1, "Ghost rate"); - aTable->SetCell(iRow + 1, 0, nGhosts / fvpTrackHistograms[ETrackType::kAll]->GetNofMCTracks()); + if (IsMCUsed()) { + fpMCModule->Finish(); + + int nRows = std::count_if(fvbTrackTypeOn.begin(), fvbTrackTypeOn.end(), [](const auto& f) { return f == true; }); + CbmQaTable* aTable = MakeQaObject<CbmQaTable>("summary_table", "Tracking summary table", nRows + 1, 9); + int iRow = 0; + std::vector<std::string> colNames = {"Efficiency", "Killed", "Length", "Fakes", "Clones", + "Reco/Evt", "MC/Evt", "Nst(hit)", "Nst(point)"}; + aTable->SetNamesOfCols(colNames); + aTable->SetColWidth(14); + double nEvents = static_cast<double>(GetEventNumber()); + LOG(info) << "Number of events: " << GetEventNumber(); + for (int iTrType = 0; iTrType < static_cast<int>(fvpTrackHistograms.size()); ++iTrType) { + if (!fvbTrackTypeOn[iTrType] || !fvpTrackHistograms[iTrType]->IsMCUsed()) { continue; } + aTable->SetRowName(iRow, fvpTrackHistograms[iTrType]->GetTitle()); + aTable->SetCell(iRow, 0, fvpTrackHistograms[iTrType]->GetIntegratedEff()); + aTable->SetCell(iRow, 1, fvpTrackHistograms[iTrType]->GetKilledRate()); + aTable->SetCell(iRow, 2, fvpTrackHistograms[iTrType]->GetAverageRecoLength()); + aTable->SetCell(iRow, 3, fvpTrackHistograms[iTrType]->GetAverageFakeLength()); + aTable->SetCell(iRow, 4, fvpTrackHistograms[iTrType]->GetClonesRate()); + aTable->SetCell(iRow, 5, fvpTrackHistograms[iTrType]->GetNofRecoTracksMatched() / nEvents); + aTable->SetCell(iRow, 6, fvpTrackHistograms[iTrType]->GetNofMCTracks() / nEvents); + aTable->SetCell(iRow, 7, fvpTrackHistograms[iTrType]->GetAverageNofStationsWithHit()); + aTable->SetCell(iRow, 8, fvpTrackHistograms[iTrType]->GetAverageNofStationsWithPoint()); + ++iRow; + } + double nGhosts = 0.; + if (fvpTrackHistograms[ETrackType::kGhost] && fvpTrackHistograms[ETrackType::kAll]) { + nGhosts = fvpTrackHistograms[ETrackType::kGhost]->fph_reco_p->GetEntries(); + aTable->SetRowName(iRow, "N ghosts"); + aTable->SetCell(iRow, 0, nGhosts); + aTable->SetRowName(iRow + 1, "Ghost rate"); + aTable->SetCell(iRow + 1, 0, nGhosts / fvpTrackHistograms[ETrackType::kAll]->GetNofMCTracks()); + } + LOG(info) << '\n' << aTable->ToString(3); } - LOG(info) << '\n' << aTable->ToString(3); - return true; } diff --git a/reco/L1/qa/CbmCaOutputQa.h b/reco/L1/qa/CbmCaOutputQa.h index 582429ba85292fa894838b200ea0f6efc900897e..cabc82c0b8d852103c180e729664856671c22e79 100644 --- a/reco/L1/qa/CbmCaOutputQa.h +++ b/reco/L1/qa/CbmCaOutputQa.h @@ -21,6 +21,7 @@ #include <array> #include <memory> +#include "CaMonitor.h" #include "CaToolsDebugger.h" #include "L1Parameters.h" @@ -245,6 +246,19 @@ namespace cbm::ca L1Vector<CbmL1Track> fvRecoTracks {"CbmCaOutputQa::fvRecoTracks"}; ::ca::tools::MCData fMCData; ///< Input MC data (points and tracks) + /// @enum EMonitorKey + /// @brief QA monitor counters + enum class EMonitorKey + { + kEvent, + kTrack, + kHit, + kMcTrack, + kMcPoint, + kEND + }; + + ::ca::Monitor<EMonitorKey> fMonitor {"Output tracking QA"}; // ************************* // ** List of histograms **