diff --git a/algo/CMakeLists.txt b/algo/CMakeLists.txt index 82f767e3bf236841a09e069d45d99814b5d0f8cf..5eff2e5606eb1168612012299dcf42894acace4f 100644 --- a/algo/CMakeLists.txt +++ b/algo/CMakeLists.txt @@ -159,6 +159,9 @@ set(SRCS qa/QaManager.cxx qa/hitfind/BmonHitfindQa.cxx qa/hitfind/BmonHitfindQaParameters.cxx + qa/trigger/V0TriggerQa.cxx + qa/hitfind/TofHitfindQa.cxx + qa/hitfind/TofHitfindQaParameters.cxx qa/unpack/StsDigiQa.cxx ca/TrackingSetup.cxx ca/TrackingChain.cxx @@ -200,6 +203,7 @@ target_include_directories(Algo ${CMAKE_CURRENT_SOURCE_DIR}/qa ${CMAKE_CURRENT_SOURCE_DIR}/qa/unpack ${CMAKE_CURRENT_SOURCE_DIR}/qa/hitfind + ${CMAKE_CURRENT_SOURCE_DIR}/qa/trigger ${CMAKE_CURRENT_SOURCE_DIR}/kf ${CMAKE_CURRENT_SOURCE_DIR}/kf/core ${CMAKE_CURRENT_SOURCE_DIR}/kf/core/utils @@ -275,6 +279,8 @@ if (NOT CBM_ONLINE_STANDALONE) ${CMAKE_CURRENT_SOURCE_DIR}/detectors ${CMAKE_CURRENT_SOURCE_DIR}/qa ${CMAKE_CURRENT_SOURCE_DIR}/qa/unpack + ${CMAKE_CURRENT_SOURCE_DIR}/qa/hitfind + ${CMAKE_CURRENT_SOURCE_DIR}/qa/trigger ${CMAKE_CURRENT_SOURCE_DIR}/kf ${CMAKE_CURRENT_SOURCE_DIR}/kf/core ${CMAKE_CURRENT_SOURCE_DIR}/kf/core/utils diff --git a/algo/base/Definitions.h b/algo/base/Definitions.h index b1ff4c9ccc8e804a33a67fe0ab40d81d74dd616e..c9cac7a917126b96499a3c8ede8824f1ee9bb5ca 100644 --- a/algo/base/Definitions.h +++ b/algo/base/Definitions.h @@ -79,6 +79,7 @@ namespace cbm::algo RecoFsd, Tracking, V0Finder, + V0Trigger, }; } // namespace cbm::algo @@ -150,7 +151,8 @@ CBM_ENUM_DICT(cbm::algo::QaStep, {"RecoTof", cbm::algo::QaStep::RecoTof}, {"RecoFsd", cbm::algo::QaStep::RecoFsd}, {"Tracking", cbm::algo::QaStep::Tracking}, - {"V0Finder", cbm::algo::QaStep::V0Finder} + {"V0Finder", cbm::algo::QaStep::V0Finder}, + {"V0Trigger", cbm::algo::QaStep::V0Trigger} ); #endif diff --git a/algo/ca/qa/CaQa.cxx b/algo/ca/qa/CaQa.cxx index 8d081862c78d399aca6ec01d0dda38e432517185..b921d16813e9bae3f93e871810e3ea04c4272400 100644 --- a/algo/ca/qa/CaQa.cxx +++ b/algo/ca/qa/CaQa.cxx @@ -216,6 +216,11 @@ void Qa::Init() auto sTitl = "First vs. last station index;ID^{last}_{station};ID^{first}_{station}"; fphTrkFstLstSta = MakeObj<H2D>(sName, sTitl, nBins, xMin, xMax, nBins, xMin, xMax); } + { + auto sName = format("{}_track_origin", GetTaskName()); + auto sTitl = "Track origin;x [cm];y [cm]"; + fphTrkOriginXY = MakeObj<H2D>(sName, sTitl, kOriginB, kOriginL, kOriginU, kOriginB, kOriginL, kOriginU); + } fphTrkNofHits = MakeObj<H1D>("n_hits", "Number of hits;N_{hit}", nBins, xMin, xMax); } @@ -231,7 +236,7 @@ void Qa::Init() auto titl = format("{} hit occupancy in different stations in XY plane", setNm); auto canv = CanvasConfig(name, titl); for (int iSt = 0; iSt < nSt; ++iSt) { - auto pad = PadConfig(); + auto pad = PadConfig(false, false, false, false, true); pad.RegisterHistogram(fvphHitOccupXY[iSt][hitSet], "colz"); canv.AddPadConfig(pad); } @@ -294,6 +299,11 @@ void Qa::Init() pad.RegisterHistogram(fphTrkFstLstSta, "colz"); canv.AddPadConfig(pad); } + { + auto pad = PadConfig(true, true, false, false, false); + pad.RegisterHistogram(fphTrkOriginXY, "colz"); + canv.AddPadConfig(pad); + } AddCanvasConfig(canv); } } @@ -371,6 +381,7 @@ void Qa::Exec() // Other distributions fphTrkFstLstSta->Fill(fpInputData->GetHit(iLstHit).Station(), fpInputData->GetHit(iFstHit).Station()); fphTrkNofHits->Fill(nHits); + fphTrkOriginXY->Fill(track.fParPV.X(), track.fParPV.Y()); trkFirstHit += nHits; } } diff --git a/algo/ca/qa/CaQa.h b/algo/ca/qa/CaQa.h index 1c42b60562f19c5adf5274c045971fe9bda330bf..ae3658a64971a9d98609d61b5ae28e3d61ab185d 100644 --- a/algo/ca/qa/CaQa.h +++ b/algo/ca/qa/CaQa.h @@ -117,6 +117,9 @@ namespace cbm::algo::ca static constexpr int knTrkParPoints = 2; ///< Number of track points to build par distributions static constexpr int knStaMax = 16; ///< Max number of stations (histogram binning) static constexpr bool kDebug = false; ///< Additional histograms + static constexpr int kOriginB = 100; ///< Track X(Y) at origin: n bins + static constexpr double kOriginL = -10.; ///< Track X(Y) at origin: lower bound [cm] + static constexpr double kOriginU = +10.; ///< Track X(Y) at origin: upper bound [cm] double fMinHitTime = std::numeric_limits<double>::max(); double fMaxHitTime = std::numeric_limits<double>::lowest(); @@ -145,6 +148,7 @@ namespace cbm::algo::ca std::array<qa::H1D*, knTrkParPoints> fvphTrkChi2Ndf = {{0}}; ///< hist: chi2/NDF at first/last hit std::array<qa::H2D*, knTrkParPoints> fvphTrkPhiTheta = {{0}}; ///< hist: theta vs. phi at first/last hit + qa::H2D* fphTrkOriginXY = nullptr; ///< hist: origin of tracks in x-y plane [cm] qa::H2D* fphTrkFstLstSta = nullptr; ///< hist: fst vs lst station index qa::H1D* fphTrkNofHits = nullptr; ///< hist: number of hits in track }; diff --git a/algo/detectors/tof/ReadoutConfig.cxx b/algo/detectors/tof/ReadoutConfig.cxx index 33238820100e333a7709b3d3d131b0b1beea308c..36310a9d4b3ea667023d853026ae6f64652d76f7 100644 --- a/algo/detectors/tof/ReadoutConfig.cxx +++ b/algo/detectors/tof/ReadoutConfig.cxx @@ -417,7 +417,7 @@ namespace cbm::algo::tof fviRpcChUId[uCh] = CbmTofAddress::GetUniqueAddress(iModuleId, 7 - iRpc, 0, 0, iModuleType); uCh++; } - uCh += (24 + 2 * 32); + uCh += (24 + 4 * 32); L_(debug) << " Map end ceramics box at GBTX - uCh = " << uCh; } @@ -557,7 +557,7 @@ namespace cbm::algo::tof int iSideMap = -1; int iStrMap = -1; int iRpcMap = -1; - const int ConOff[8] = {0, 2, 4, 6, 7, 1, 3, 5}; // Get4 after Gbtx + const int ConOff[8] = {0, 2, 4, 6, 7, 1, 3, 5}; //Get4 after Gbtx for (int32_t iFeet = 0; iFeet < 5; iFeet++) { for (int32_t iStr = 0; iStr < 32; iStr++) { switch (iFeet) { @@ -592,6 +592,49 @@ namespace cbm::algo::tof } } } + else if (crob.rpcSide == 5) { + int iSideMap = -1; + int iStrMap = -1; + int iRpcMap = -1; + const int ConOff[8] = {0, 2, 4, 6, 7, 1, 3, 5}; // Get4 after Gbtx + for (int32_t iFeet = 0; iFeet < 5; iFeet++) { + for (int32_t iStr = 0; iStr < 32; iStr++) { + switch (iFeet) { + case 0: iSideMap = -1; break; + case 1: + iRpcMap = 0; + iStrMap = 3 - iStr % 4 + 4 * ConOff[iStr / 4]; + iStrMap = 31 - iStrMap; + iSideMap = 1; + break; + case 2: + iRpcMap = 0; + iStrMap = 3 - iStr % 4 + 4 * ConOff[iStr / 4]; + iStrMap = 31 - iStrMap; + iSideMap = 0; + break; + case 3: + iRpcMap = 1; + iStrMap = 3 - iStr % 4 + 4 * ConOff[iStr / 4]; + iStrMap = 31 - iStrMap; + iSideMap = 0; + break; + case 4: + iRpcMap = 1; + iStrMap = 3 - iStr % 4 + 4 * ConOff[iStr / 4]; + iStrMap = 31 - iStrMap; + iSideMap = 1; + break; + } + if (iSideMap > -1) + fviRpcChUId[uCh] = + CbmTofAddress::GetUniqueAddress(crob.moduleId, iRpcMap, iStrMap, iSideMap, crob.rpcType); + else + fviRpcChUId[uCh] = 0; + uCh++; + } + } + } } } @@ -645,7 +688,11 @@ namespace cbm::algo::tof case 4: // HD cosmic 2019, Buc2018, v18o iRpcMap = 1 - iRpcMap; break; - case 5: // HD cosmic 2020, Buc2018, v20a + case 5: // Buc2025, mCBM + iRpcMap = 1 - iRpcMap; + iSideMap = 1 - iSideMap; + break; + case 55: // HD cosmic 2020, Buc2018, v20a iStrMap = 31 - iStr; break; case 6: //BUC special diff --git a/algo/detectors/tof/ReadoutConfig.h b/algo/detectors/tof/ReadoutConfig.h index 07c91d72927aa86428f56030964c58effeebbef5..6b9ac632faef7de47e026881348a91e3ef750fd0 100644 --- a/algo/detectors/tof/ReadoutConfig.h +++ b/algo/detectors/tof/ReadoutConfig.h @@ -69,7 +69,8 @@ namespace cbm::algo::tof i32 NCrobsPerComponent() const { return nCrobPerComponent; } bool CheckBmonComp(uint32_t uCompId) const { return ((uCompId & 0xFFF0) == 0xABF0); } - bool CheckInnerComp(uint32_t uCompId) const { return ((uCompId & 0xFFF0) == 0xBBC0); } + //bool CheckInnerComp(uint32_t uCompId) const { return ((uCompId & 0xFFF0) == 0xBBC0); } + bool CheckInnerComp(uint32_t uCompId) const { return ((uCompId & 0xFF00) == 0xBB00); } }; diff --git a/algo/evbuild/EventbuildChain.h b/algo/evbuild/EventbuildChain.h index ed6be01c66f7bb36b25d3f1582b9084272171971..32ae1e649c1228b17c49bc59226e2e66f7033f75 100644 --- a/algo/evbuild/EventbuildChain.h +++ b/algo/evbuild/EventbuildChain.h @@ -64,6 +64,11 @@ namespace cbm::algo::evbuild /** @brief Registers tracking setup **/ void RegisterTrackingSetup(std::shared_ptr<TrackingSetup> pSetup) { fSelector.RegisterTrackingSetup(pSetup); } + /** @brief Sets V0 trigger QA + ** @param pQa Qa module + **/ + void SetV0TriggerQa(std::shared_ptr<V0TriggerQa> pQa) { fV0Trigger.SetQa(pQa); } + private: // members Config fConfig; ///< Global configuration ECbmModuleId fTriggerDet = ECbmModuleId::kNotExist; ///< Trigger detector diff --git a/algo/evselector/DigiEventSelector.cxx b/algo/evselector/DigiEventSelector.cxx index bae8b3e2cf4be404206848facf74f594f0ea2c14..4411689bfb468fa88af8bbb41233b3152c9eb5bc 100644 --- a/algo/evselector/DigiEventSelector.cxx +++ b/algo/evselector/DigiEventSelector.cxx @@ -44,6 +44,30 @@ namespace cbm::algo::evbuild } } + // --- Test masked channels (if any) + for (auto& entry : fConfig.fMaskedChannels) { + size_t nDigisAccepted = 0; + auto det = entry.first; + auto itMinNumDigis = fConfig.fMinNumDigis.find(det); + if (itMinNumDigis != fConfig.fMinNumDigis.end() && itMinNumDigis->second > 0) { + switch (det) { + case ECbmModuleId::kBmon: + for (const auto& digi : event.fBmon) { + if (entry.second.find(digi.GetAddress()) == entry.second.end()) { + ++nDigisAccepted; + } + } + break; + default: + // This was met in the first block of the function + break; + } + if (nDigisAccepted < itMinNumDigis->second) { + return false; + } + } + } + return true; } // -------------------------------------------------------------------------- diff --git a/algo/evselector/DigiEventSelectorConfig.cxx b/algo/evselector/DigiEventSelectorConfig.cxx index 647f7c0dfbb3acca86c180639167d2134eed1560..43399c74f0c7af2d827bedb8d8deffdf313ff17f 100644 --- a/algo/evselector/DigiEventSelectorConfig.cxx +++ b/algo/evselector/DigiEventSelectorConfig.cxx @@ -1,11 +1,12 @@ -/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt +/* Copyright (C) 2022-2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt SPDX-License-Identifier: GPL-3.0-only - Authors: Shreya Roy. Pierre-Alain Loizeau, Volker Friese [committer], Dominik Smith */ + Authors: Shreya Roy. Pierre-Alain Loizeau, Volker Friese [committer], Dominik Smith, Sergei Zharko */ #include "DigiEventSelectorConfig.h" #include "AlgoFairloggerCompat.h" +#include <iomanip> namespace cbm::algo::evbuild { @@ -34,6 +35,19 @@ namespace cbm::algo::evbuild L_(warning) << "DigiEventSelectorConfig: Ignoring minimum 0 for layers in " << ::ToString(det); } } + if (auto maskedChannels = config["maskedChannels"]) { + for (YAML::const_iterator it = maskedChannels.begin(); it != maskedChannels.end(); ++it) { + auto det = ToCbmModuleIdCaseInsensitive(it->first.as<std::string>()); + auto value = it->second.as<std::vector<uint32_t>>(); + if (value.size() > 0) { + fMaskedChannels[det] = std::unordered_set<uint32_t>(value.begin(), value.end()); + L_(info) << "Masking following " << ToString(det) << " channels from event selecting: "; + for (auto address : fMaskedChannels[det]) { + L_(info) << " - 0x" << std::hex << std::setw(8) << std::setfill('0') << address << std::dec; + } + } + } + } } // -------------------------------------------------------------------------- @@ -50,6 +64,7 @@ namespace cbm::algo::evbuild auto det = ToString(entry.first); result["minLayers"][det] = entry.second; } + // FIXME: implement masked channels storage return result; } // -------------------------------------------------------------------------- diff --git a/algo/evselector/DigiEventSelectorConfig.h b/algo/evselector/DigiEventSelectorConfig.h index 43276c739ddc21ceaf1bbd4767ad9ef0baf1e136..fa97bdcc13ac1475324f341217e1bc8a7300fcb7 100644 --- a/algo/evselector/DigiEventSelectorConfig.h +++ b/algo/evselector/DigiEventSelectorConfig.h @@ -1,6 +1,6 @@ -/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt +/* Copyright (C) 2022-2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt SPDX-License-Identifier: GPL-3.0-only - Authors: Shreya Roy. Pierre-Alain Loizeau, Volker Friese [committer], Dominik Smith */ + Authors: Shreya Roy. Pierre-Alain Loizeau, Volker Friese [committer], Dominik Smith, Sergei Zharko */ #ifndef CBM_ALGO_EVBUILD_DIGIEVENTSELECTORCONFIG_H #define CBM_ALGO_EVBUILD_DIGIEVENTSELECTORCONFIG_H 1 @@ -9,6 +9,7 @@ #include <cstdint> #include <map> +#include <unordered_set> #include <yaml-cpp/yaml.h> @@ -45,10 +46,12 @@ namespace cbm::algo::evbuild /** @brief Save to YAML **/ YAML::Node ToYaml() const; - private: std::map<ECbmModuleId, size_t> fMinNumDigis; ///< Key: detector, value: minimal number of digis std::map<ECbmModuleId, size_t> fMinNumLayers; ///< Key: detector, value: Minimal number of layers + + /** @brief A map of masked digi addresses, which should not participate in the event building **/ + std::map<ECbmModuleId, std::unordered_set<uint32_t>> fMaskedChannels; }; diff --git a/algo/global/Reco.cxx b/algo/global/Reco.cxx index 0f192df1b6c68934269a1eea7e5561b73dd6aa5d..79784707ea990ca10e78cc88ec1b83c2512481e5 100644 --- a/algo/global/Reco.cxx +++ b/algo/global/Reco.cxx @@ -26,6 +26,7 @@ #include "much/Unpack.h" #include "qa/QaManager.h" #include "qa/hitfind/BmonHitfindQa.h" +#include "qa/hitfind/TofHitfindQa.h" #include "rich/Unpack.h" #include "sts/ChannelMaskSet.h" #include "sts/HitfinderChain.h" @@ -192,6 +193,12 @@ void Reco::Init(const Options& opts) evbuild::Config config(YAML::LoadFile(configFile.string())); fEventBuild = std::make_unique<evbuild::EventbuildChain>(config, (Opts().Has(QaStep::EventBuilding) ? fSender : nullptr)); + if (fQaManager != nullptr && Opts().Has(QaStep::V0Trigger)) { + // FIXME: Replace with a common function SetTriggerQa(fQaManager) + auto pTriggerQa = std::make_shared<evbuild::V0TriggerQa>(fQaManager); + pTriggerQa->Init(); + fEventBuild->SetV0TriggerQa(pTriggerQa); + } fEventBuild->RegisterTrackingSetup(pTrackingSetup); } @@ -215,6 +222,12 @@ void Reco::Init(const Options& opts) auto hitfindSetup = yaml::ReadFromFile<tof::HitfindSetup>(opts.ParamsDir() / parFiles.tof.hitfinder); fTofHitFinder = std::make_unique<tof::Hitfind>(hitfindSetup); + + if (fQaManager != nullptr && Opts().Has(QaStep::RecoTof)) { + fTofHitFinderQa = std::make_unique<tof::HitfindQa>(fQaManager, "TofHitfind"); + fTofHitFinderQa->InitParameters(hitfindSetup); + fTofHitFinderQa->Init(); + } } if (Opts().Has(fles::Subsystem::TRD) && Opts().Has(Step::LocalReco)) { @@ -365,6 +378,10 @@ RecoResults Reco::Run(const fles::Timeslice& ts) L_(error) << "TOF Digis with unknown RPCs: " << nUnknownRPC; } auto [hits, hitmonitor, digiindices] = (*fTofHitFinder)(caldigis); + if (fTofHitFinderQa != nullptr) { + fTofHitFinderQa->RegisterHits(&hits); + fTofHitFinderQa->Exec(); + } recoData.tofHits = std::move(hits); QueueTofCalibMetrics(calmonitor); QueueTofRecoMetrics(hitmonitor); diff --git a/algo/global/Reco.h b/algo/global/Reco.h index 35cb5c34626c8dc84ba994478e83a305522cfd98..e5a8412151d8e05a4cd1b5ee68d71d8ee6f47ebc 100644 --- a/algo/global/Reco.h +++ b/algo/global/Reco.h @@ -60,6 +60,7 @@ namespace cbm::algo class Calibrate; struct CalibrateMonitorData; class Hitfind; + class HitfindQa; struct HitfindMonitorData; } @@ -175,6 +176,7 @@ namespace cbm::algo std::unique_ptr<tof::Unpack> fTofUnpack; std::unique_ptr<tof::Calibrate> fTofCalibrator; std::unique_ptr<tof::Hitfind> fTofHitFinder; + std::unique_ptr<tof::HitfindQa> fTofHitFinderQa; // TRD std::unique_ptr<trd::Unpack> fTrdUnpack; diff --git a/algo/kfp/KfpV0Finder.cxx b/algo/kfp/KfpV0Finder.cxx index c95965bc847347caccc52b1bcf23a0eaeda8fd92..820078945d3ffd25eb18256e3077899c35d47432 100644 --- a/algo/kfp/KfpV0Finder.cxx +++ b/algo/kfp/KfpV0Finder.cxx @@ -80,7 +80,7 @@ void V0Finder::AssignPid(ParticleInfo& particleInfo) // primary //particleInfo.fPdg = fPrimaryAssignedPdg; particleInfo.fPdg = kUndefPdg; - fEventMonitor.IncrementCounter(ECounter::TracksWoPid); + fEventMonitor.IncrementCounter(ECounter::PrimaryDca); } } diff --git a/algo/kfp/KfpV0FinderMonitor.h b/algo/kfp/KfpV0FinderMonitor.h index d60d5b135478e2e6d379a26b69e8755d9b2bd96b..3f3b68ef6af1b548eb85cbb8c771caac3a93f51e 100644 --- a/algo/kfp/KfpV0FinderMonitor.h +++ b/algo/kfp/KfpV0FinderMonitor.h @@ -28,6 +28,7 @@ namespace cbm::algo::kfp TracksWUnphysicalBeta, ///< Tracks with beta > 1 PionsDca, ///< Number of raw pion-candidates ProtonsDca, ///< Number of raw proton-candidates + PrimaryDca, ///< Number of raw proton-candidates Pions, ///< Number of pion-candidates Protons, ///< Number of proton-candidates EventsTotal, ///< Total number of events @@ -76,6 +77,7 @@ namespace cbm::algo::kfp SetCounterName(ECounter::TracksWUnphysicalBeta, "tracks w/ beta > 1"); SetCounterName(ECounter::PionsDca, "raw pion candidates"); SetCounterName(ECounter::ProtonsDca, "raw proton candidates"); + SetCounterName(ECounter::PrimaryDca, "number of primary particles"); SetCounterName(ECounter::Pions, "pion candidates"); SetCounterName(ECounter::Protons, "proton candidates"); SetCounterName(ECounter::EventsTotal, "all events"); diff --git a/algo/kfp/KfpV0FinderQa.cxx b/algo/kfp/KfpV0FinderQa.cxx index ffc903e2a2dcc2c12efa06b4bda11db6db29ffb9..703f067f93cf0b2a81c440817a55d9feac6fe7ea 100644 --- a/algo/kfp/KfpV0FinderQa.cxx +++ b/algo/kfp/KfpV0FinderQa.cxx @@ -57,7 +57,8 @@ void V0FinderQa::Exec(const RecoResults& recoEvent, const V0Finder& v0Finder) const auto& particleInfo{v0Finder.GetParticleInfo()[iTrk]}; const auto& trkParFst{(v0Finder.GetTrackAssignedParams()[iTrk]).first}; bool bPdgDefined = (particleInfo.fPdg != V0Finder::kUndefPdg); - fvphDcaAll->Fill(bPdgDefined ? particleInfo.fDca : -999); + // All particles with defined DCA (primaries + secondary pions and protons) + fvphDcaAll->Fill(std::isnan(particleInfo.fDca) ? -999 : particleInfo.fDca); fvphBetaAll->Fill(particleInfo.fBeta); if (bPdgDefined) { if (particleInfo.fPdg == -211) { @@ -75,15 +76,15 @@ void V0FinderQa::Exec(const RecoResults& recoEvent, const V0Finder& v0Finder) for (uint32_t iTrk = 0; iTrk < tracks.size(); ++iTrk) { const auto& particleInfo{v0Finder.GetParticleInfo()[iTrk]}; bool bPdgDefined = (particleInfo.fPdg != V0Finder::kUndefPdg); - fvphDcaAll->Fill(bPdgDefined ? particleInfo.fDca : -999); - fvphBetaAll->Fill(-999); + fvphDcaAll->Fill(std::isnan(particleInfo.fDca) ? -999 : particleInfo.fDca); + fvphBetaAll->Fill(-9999); if (bPdgDefined) { if (particleInfo.fPdg == -211) { - fvphBetaPion->Fill(-999); - fvphMomPion->Fill(-999); + fvphBetaPion->Fill(-9999); + fvphMomPion->Fill(-9999); } else if (particleInfo.fPdg == 2212) { - fvphBetaProton->Fill(-999); + fvphBetaProton->Fill(-9999); } } } diff --git a/algo/qa/Histogram.h b/algo/qa/Histogram.h index 1b70f3b0588b3eaba2b3617ecc8333957e3d8a39..44040934a422adb09a9b536714610548f30afabc 100644 --- a/algo/qa/Histogram.h +++ b/algo/qa/Histogram.h @@ -55,7 +55,8 @@ namespace cbm::algo::qa enum class EHistFlag : uint8_t { StoreVsTsId = 0b00000001, ///< Store the histogram vs timeslice index - OmitIntegrated = 0b00000010 ///< Omits storing integrated histogram + OmitIntegrated = 0b00000010, ///< Omits storing integrated histogram + SetMinimum = 0b00000100 ///< Sets minimum to the histogram }; /// \class HistogramMetadata diff --git a/algo/qa/QaTaskHeader.h b/algo/qa/QaTaskHeader.h index ceb03e5ad457c9b6ceecb1145c7a5f4c15f262b9..e910a6a103d62dbcee2e17722b9ac4d0a9f924b7 100644 --- a/algo/qa/QaTaskHeader.h +++ b/algo/qa/QaTaskHeader.h @@ -51,7 +51,7 @@ namespace cbm::algo::qa /// /// The task can be inactive, if a nullptr qa::Manager was passed to the constructor. If it is the case, /// the fpData instance is not defined, and no actions on the task should be performed - bool IsActive() const { return static_cast<bool>(fpData != nullptr); } + bool IsActive() const { return fpData.get(); } /// \brief Gets name of the task const std::string& GetTaskName() { return fsName; } diff --git a/algo/qa/hitfind/TofHitfindQa.cxx b/algo/qa/hitfind/TofHitfindQa.cxx new file mode 100644 index 0000000000000000000000000000000000000000..c037dc676457bd599e552e7c3e972ca523c9b4e8 --- /dev/null +++ b/algo/qa/hitfind/TofHitfindQa.cxx @@ -0,0 +1,110 @@ +/* Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file TofHitfindQa.cxx +/// \brief A TOF hitfinder QA (implementation) +/// \since 04.03.2025 +/// \author Sergei Zharko <s.zharko@gsi.de> + +#include "qa/hitfind/TofHitfindQa.h" + +#include "CbmTofAddress.h" +#include "qa/Histogram.h" +#include "tof/Hit.h" + +#include <fmt/format.h> + +using cbm::algo::tof::HitfindQa; + +// --------------------------------------------------------------------------------------------------------------------- +// +void HitfindQa::Init() +try { + using fmt::format; + using qa::CanvasConfig; + using qa::PadConfig; + if (!IsActive()) { + return; + } + + size_t nRpcs = fParameters.rpcs.size(); + if (nRpcs < 1) { + throw std::runtime_error("parameters were not initialized. Please, provide the configuration using the function " + "HitfindQa::InitParameters(hitSetup)"); + } + + // Histogram initialization + fvphRpcHitOccupX.resize(nRpcs, nullptr); + fvphRpcHitOccupY.resize(nRpcs, nullptr); + fvphRpcHitOccupCh.resize(nRpcs, nullptr); + + auto cOccupX = CanvasConfig(format("{}/tof_rpc_occup_x", GetTaskName()), "RPC hit occupancy vs. X", 1, 1); + auto cOccupY = CanvasConfig(format("{}/tof_rpc_occup_y", GetTaskName()), "RPC hit occupancy vs. Y", 1, 1); + auto cOccupCh = CanvasConfig(format("{}/tof_rpc_occup_ch", GetTaskName()), "RPC hit occupancy vs. channel", 1, 1); + for (size_t iRpc = 0; iRpc < nRpcs; ++iRpc) { + const auto& rpcPar = fParameters.rpcs[iRpc]; + int nCh = rpcPar.chAddresses.size(); + auto sDN = format("{:#010x}", rpcPar.address); // diamond suffix + auto sDT = CbmTofAddress::ToString(rpcPar.address); + + // Histograms initialisation + fvphRpcHitOccupX[iRpc] = MakeObj<qa::H1D>(format("tof_hit_occup_x_{}", sDN), format("RPC {};x [cm];counts", sDT), + kHitOccupB, kHitOccupL, kHitOccupU); + fvphRpcHitOccupY[iRpc] = MakeObj<qa::H1D>(format("tof_hit_occup_y_{}", sDN), format("RPC {};y [cm];counts", sDT), + kHitOccupB, kHitOccupL, kHitOccupU); + fvphRpcHitOccupCh[iRpc] = MakeObj<qa::H1D>(format("tof_hit_occup_chan_{}", sDN), + format("RPC {};channel;counts", sDT), nCh, -0.5, nCh - 0.5); + + { + auto pad = PadConfig(fvphRpcHitOccupX[iRpc], "hist"); + pad.SetLog(false, true, false); + cOccupX.AddPadConfig(pad); + } + { + auto pad = PadConfig(fvphRpcHitOccupY[iRpc], "hist"); + pad.SetLog(false, true, false); + cOccupY.AddPadConfig(pad); + } + { + auto pad = PadConfig(fvphRpcHitOccupCh[iRpc], "hist"); + pad.SetLog(false, true, false); + cOccupCh.AddPadConfig(pad); + } + } + + AddCanvasConfig(cOccupX); + AddCanvasConfig(cOccupY); + AddCanvasConfig(cOccupCh); +} +catch (const std::exception& err) { + L_(fatal) << "tof::HitfindQa: initialization failed. Reason: " << err.what(); + throw std::runtime_error("tof::HitfindQa initialization failure"); +} + +// --------------------------------------------------------------------------------------------------------------------- +// +void HitfindQa::Exec() +{ + if (!IsActive()) { + return; + } + + // Fill hit distributions + const auto& hits = fpHits->Data(); + for (size_t iH = 0; iH < hits.size(); ++iH) { + const auto& hit = hits[iH]; + int32_t hitAddress = hit.address; + int32_t iCh = CbmTofAddress::GetChannelId(hitAddress); + uint32_t rpcAddress = CbmTofAddress::GetModFullId(hitAddress); + auto itAddress = fParameters.lookupMap.find(rpcAddress); + if (itAddress == fParameters.lookupMap.end()) { + L_(error) << "tof::HitfindQa: unknown RPC address " << CbmTofAddress::ToString(rpcAddress); + continue; + } + uint32_t iRpc = itAddress->second; + fvphRpcHitOccupX[iRpc]->Fill(hit.X()); + fvphRpcHitOccupY[iRpc]->Fill(hit.Y()); + fvphRpcHitOccupCh[iRpc]->Fill(iCh); + } +} diff --git a/algo/qa/hitfind/TofHitfindQa.h b/algo/qa/hitfind/TofHitfindQa.h new file mode 100644 index 0000000000000000000000000000000000000000..3c630b0b2a72a1943e94df84c95c9b33041e4d16 --- /dev/null +++ b/algo/qa/hitfind/TofHitfindQa.h @@ -0,0 +1,91 @@ +/* Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file TofHitfindQa.h +/// \brief A TOF hitfinder QA +/// \since 04.03.2025 +/// \author Sergei Zharko <s.zharko@gsi.de> + + +#pragma once + +#include "PODVector.h" +#include "PartitionedVector.h" +#include "qa/QaTaskHeader.h" +#include "qa/hitfind/TofHitfindQaParameters.h" + +namespace cbm::algo +{ + namespace qa + { + class H1D; + class H2D; + } // namespace qa + + namespace tof + { + class Hit; + } +} // namespace cbm::algo + +namespace cbm::algo::tof +{ + /// \class HitfindQa + /// \brief A QA module for the BMON hit-finder + class HitfindQa : public qa::TaskHeader { + public: + /// \brief Constructor + /// \param pManager Pointer to the QA manager + /// \param name Name of the QA (directory) + HitfindQa(const std::unique_ptr<qa::Manager>& pManager, std::string_view name) : qa::TaskHeader(pManager, name) {} + + /// \brief Constructor from the configuration object + HitfindQa() = default; + + /// \brief Copy constructor + HitfindQa(const HitfindQa&) = delete; + + /// \brief Move constructor + HitfindQa(HitfindQa&&) = delete; + + /// \brief Destructor + ~HitfindQa() = default; + + /// \brief Copy assignment operator + HitfindQa& operator=(const HitfindQa&) = delete; + + /// \brief Move assignment operator + HitfindQa& operator=(HitfindQa&&) = delete; + + /// \brief Executes the task, fills the histograms + void Exec(); + + /// \brief Initialized the task + void Init(); + + /// \brief Initialisation of the parameters + void InitParameters(const HitfindSetup& hitSetup) { fParameters = std::move(HitfindQaParameters(hitSetup)); } + + /// \brief Registers a sample of hits + /// \param pHits A pointer to a vector of hits + void RegisterHits(const PartitionedVector<tof::Hit>* pHits) { fpHits = pHits; } + + private: + //* Constants + static constexpr int kHitOccupB{200}; ///< Hit occupancy: n bins + static constexpr double kHitOccupL{-100.}; ///< Hit occupancy: lower bound [cm] + static constexpr double kHitOccupU{+100.}; ///< Hit occupancy: upper bound [cm] + + //* Parameters + HitfindQaParameters fParameters; ///< Parameters of the hit finder QA + + //* Data samples + const PartitionedVector<tof::Hit>* fpHits{nullptr}; ///< Pointer to TOF hit sample + + //* Histograms + std::vector<qa::H1D*> fvphRpcHitOccupX; ///< Hit occupancy in RPC vs. x + std::vector<qa::H1D*> fvphRpcHitOccupY; ///< Hit occupancy in RPC vs. y + std::vector<qa::H1D*> fvphRpcHitOccupCh; ///< Hit occupancy in RPC vs. channel + }; +} // namespace cbm::algo::tof diff --git a/algo/qa/hitfind/TofHitfindQaParameters.cxx b/algo/qa/hitfind/TofHitfindQaParameters.cxx new file mode 100644 index 0000000000000000000000000000000000000000..3cb2f35b8cef672094e082cf4de445612f65f44b --- /dev/null +++ b/algo/qa/hitfind/TofHitfindQaParameters.cxx @@ -0,0 +1,40 @@ +/* Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file BmonHitfindQaParameters.cxx +/// \brief A BMON hitfinder QA parameter configuration (implementation) +/// \since 10.02.2025 +/// \author Sergei Zharko <s.zharko@gsi.de> + +#include "qa/hitfind/TofHitfindQaParameters.h" + +#include "AlgoFairloggerCompat.h" +#include "CbmTofAddress.h" + +using cbm::algo::tof::HitfindQaParameters; +using cbm::algo::tof::HitfindSetup; + +// --------------------------------------------------------------------------------------------------------------------- +// +HitfindQaParameters::HitfindQaParameters(const HitfindSetup& hitSetup) +{ + rpcs.clear(); + lookupMap.clear(); + uint32_t iUniqueRpcId = 0; + for (const auto& smType : hitSetup.rpcs) { + for (const auto& rpc : smType) { + uint32_t address = static_cast<uint32_t>(CbmTofAddress::GetModFullId(rpc.chanPar[0].address)); + lookupMap[address] = iUniqueRpcId; + auto& rpcPar = rpcs.emplace_back(); + rpcPar.address = address; + rpcPar.chAddresses.resize(rpc.chanPar.size()); + L_(debug) << "RPC: " << CbmTofAddress::ToString(address); + for (int iCh = 0; iCh < rpcPar.chAddresses.size(); ++iCh) { + rpcPar.chAddresses[iCh] = rpc.chanPar[iCh].address; + L_(debug) << "----> ch: " << CbmTofAddress::ToString(rpcPar.chAddresses[iCh]); + } + iUniqueRpcId++; + } + } +} diff --git a/algo/qa/hitfind/TofHitfindQaParameters.h b/algo/qa/hitfind/TofHitfindQaParameters.h new file mode 100644 index 0000000000000000000000000000000000000000..f64fe1e9f324749c98f268eb3eb6a838278f70fc --- /dev/null +++ b/algo/qa/hitfind/TofHitfindQaParameters.h @@ -0,0 +1,39 @@ +/* Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file TofHitfindQaParameters.h +/// \brief A TOF hitfinder QA parameter configuration +/// \since 03.03.2025 +/// \author Sergei Zharko <s.zharko@gsi.de> + +#pragma once + +#include "tof/HitfindSetup.h" + +#include <unordered_map> +#include <vector> + +namespace cbm::algo::tof +{ + /// \struct HitfindQaParameters + /// \brief A structure to handle TOF QA parameters + struct HitfindQaParameters { + + /// \struct Rpc + struct Rpc { + std::vector<uint32_t> chAddresses; ///< Address of channel vs channel ID + uint32_t address; ///< Address of RPC + }; + + std::unordered_map<uint32_t, uint32_t> lookupMap; ///< A lookup map for RPC addresses + std::vector<Rpc> rpcs; ///< A map for different RPC properties + + /// \brief Default constructor + HitfindQaParameters() = default; + + /// \brief Constructor + /// \param hitSetup Hitfinder parameters + HitfindQaParameters(const HitfindSetup& hitSetup); + }; +} // namespace cbm::algo::tof diff --git a/algo/qa/trigger/V0TriggerQa.cxx b/algo/qa/trigger/V0TriggerQa.cxx new file mode 100644 index 0000000000000000000000000000000000000000..234cf13b19a8603b6f443164c1c12cb4102eb6ac --- /dev/null +++ b/algo/qa/trigger/V0TriggerQa.cxx @@ -0,0 +1,34 @@ +/* Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file V0TriggerQa.cxx +/// \brief A V0-trigger QA (implementation) +/// \since 06.03.2025 +/// \author Sergei Zharko <s.zharko@gsi.de> + +#include "qa/trigger/V0TriggerQa.h" + +#include "qa/Histogram.h" + +using cbm::algo::evbuild::V0TriggerQa; + +// --------------------------------------------------------------------------------------------------------------------- +// +void V0TriggerQa::Init() +{ + // Histograms + fphPairDeltaT = MakeObj<qa::H1D>("v0trigger_pair_delta_t", "Time difference of track pair;#Delta t [ns];Counts", + kPairDeltaTB, kPairDeltaTL, kPairDeltaTU); + fphPairZVertex = MakeObj<qa::H1D>("v0trigger_pair_z_vertex", "z-verex of track pair;z [cm];Counts", kPairZVertexB, + kPairZVertexL, kPairZVertexU); + fphPairDca = MakeObj<qa::H1D>("v0trigger_pair_dca", "Track pair distance of closest approach;DCA [cm];Counts", + kPairDcaB, kPairDcaL, kPairDcaU); + + // Canvas + auto canv = qa::CanvasConfig(GetTaskName(), "V0 Trigger summary", 3, 1); + canv.AddPadConfig(qa::PadConfig(fphPairDeltaT, "hist")); + canv.AddPadConfig(qa::PadConfig(fphPairZVertex, "hist")); + canv.AddPadConfig(qa::PadConfig(fphPairDca, "hist")); + AddCanvasConfig(canv); +} diff --git a/algo/qa/trigger/V0TriggerQa.h b/algo/qa/trigger/V0TriggerQa.h new file mode 100644 index 0000000000000000000000000000000000000000..fff885f86fea36430e70ac8a51446c3577833035 --- /dev/null +++ b/algo/qa/trigger/V0TriggerQa.h @@ -0,0 +1,68 @@ +/* Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file V0TriggerQa.h +/// \brief A V0-trigger QA +/// \since 06.03.2025 +/// \author Sergei Zharko <s.zharko@gsi.de> + +#pragma once + +#include "qa/QaTaskHeader.h" + +namespace cbm::algo::qa +{ + class H1D; +} // namespace cbm::algo::qa + + +namespace cbm::algo::evbuild +{ + /// \class V0TriggerQa + /// \brief A QA module for the V0-trigger + class V0TriggerQa : public qa::TaskHeader { + public: + friend class V0Trigger; // for access to histograms + + /// \brief Constructor + /// \param pManager Pointer to the QA manager + /// \param name Name of the QA (directory) + V0TriggerQa(const std::unique_ptr<qa::Manager>& pManager) : qa::TaskHeader(pManager, "V0Trigger") {} + + /// \brief Copy constructor + V0TriggerQa(const V0TriggerQa&) = delete; + + /// \brief Move constructor + V0TriggerQa(V0TriggerQa&&) = delete; + + /// \brief Destructor + ~V0TriggerQa() = default; + + /// \brief Copy assignment operator + V0TriggerQa& operator=(const V0TriggerQa&) = delete; + + /// \brief Move assignment operator + V0TriggerQa& operator=(V0TriggerQa&&) = delete; + + /// \brief Initializes the task + void Init(); + + private: + //* Constants + static constexpr int kPairDeltaTB{100}; ///< Track pair time difference: n bins + static constexpr double kPairDeltaTL{-50.}; ///< Track pair time difference: lower bound [ns] + static constexpr double kPairDeltaTU{+50.}; ///< Track pair time difference: upper bound [ns] + static constexpr int kPairZVertexB{120}; ///< Track pair z vertex: n bins + static constexpr double kPairZVertexL{-60.}; ///< Track pair z vertex: lower bound [cm] + static constexpr double kPairZVertexU{+60.}; ///< Track pair z vertex: upper bound [cm] + static constexpr int kPairDcaB{300}; ///< Track pair DCA: n bins + static constexpr double kPairDcaL{-0.5}; ///< Track pair DCA: lower bound [cm] + static constexpr double kPairDcaU{+5.5}; ///< Track pair DCA: upper bound [cm] + + //* Histograms + qa::H1D* fphPairDeltaT{nullptr}; ///< Track pair delta T + qa::H1D* fphPairZVertex{nullptr}; ///< Track pair z-vertex + qa::H1D* fphPairDca{nullptr}; ///< Track pair distance at closest approach + }; +} // namespace cbm::algo::evbuild diff --git a/algo/trigger/V0Trigger.cxx b/algo/trigger/V0Trigger.cxx index bf9264801a9a444d56dac990a8998f3cc3da511a..e3ff8ef9f50a58fda75b569cc974952e0bc61001 100644 --- a/algo/trigger/V0Trigger.cxx +++ b/algo/trigger/V0Trigger.cxx @@ -32,6 +32,11 @@ namespace cbm::algo::evbuild // Check track time difference float time1 = trackIter1->fParPV.GetTime(); float time2 = trackIter2->fParPV.GetTime(); + + if (fpQa->IsActive()) { + fpQa->fphPairDeltaT->Fill(time2 - time1); + } + if (time2 < time1) { result.second.errTracksUnsorted++; continue; @@ -42,6 +47,11 @@ namespace cbm::algo::evbuild // Check PCA cuts auto [zVertex, dist] = CalcPCA(trackIter1->fParPV, trackIter2->fParPV); + if (fpQa->IsActive()) { + fpQa->fphPairZVertex->Fill(zVertex); + fpQa->fphPairDca->Fill(dist); + } + if (dist < config.PairDist_max()) { result.second.numTrackPairsAfterDistCut++; if (zVertex >= config.PairZ_min() && zVertex <= config.PairZ_max()) { diff --git a/algo/trigger/V0Trigger.h b/algo/trigger/V0Trigger.h index 6bed8ce5d210aaed169931991c6b79eded3603c6..3736b64f23754f992e76199f1a957d210d213be4 100644 --- a/algo/trigger/V0Trigger.h +++ b/algo/trigger/V0Trigger.h @@ -7,6 +7,7 @@ #include "CaTrack.h" #include "CaVector.h" #include "V0TriggerConfig.h" +#include "qa/trigger/V0TriggerQa.h" #include <utility> #include <vector> @@ -50,6 +51,7 @@ namespace cbm::algo::evbuild /** @brief Constructor **/ V0Trigger() = default; + /** @brief Execution ** @param tracks Input track vector ** @param config Trigger configuration @@ -57,6 +59,13 @@ namespace cbm::algo::evbuild **/ Result operator()(const TrackVector& tracks, const V0TriggerConfig& config) const; + + /** @brief Sets QA module + ** @param pQa Pointer to the QA module + **/ + void SetQa(std::shared_ptr<V0TriggerQa> pQa) { fpQa = pQa; } + + /** @brief Info to string **/ std::string ToString() const; @@ -84,6 +93,8 @@ namespace cbm::algo::evbuild ** @return decision **/ bool IsPrimary(const TrackParam& track, const V0TriggerConfig& config) const; + + std::shared_ptr<V0TriggerQa> fpQa{std::make_shared<V0TriggerQa>(nullptr)}; //! QA module }; } // namespace cbm::algo::evbuild diff --git a/core/detectors/tof/CbmMcbm2018TofPar.cxx b/core/detectors/tof/CbmMcbm2018TofPar.cxx index d2441aecf6afb55abd8de4f9b918cdf827e830b2..ad8f36aff7be8fbd45e94e8f6cea7b34de2f918b 100644 --- a/core/detectors/tof/CbmMcbm2018TofPar.cxx +++ b/core/detectors/tof/CbmMcbm2018TofPar.cxx @@ -268,13 +268,15 @@ void CbmMcbm2018TofPar::BuildChannelsUidMap() uint32_t uGdpb = uCh0 / (fiNrOfFeesPerGdpb * fiNrOfGet4PerFee * fiNrOfChannelsPerGet4); LOG(info) << "Map at ch " << uCh << ", Gdpb " << uGdpb << ", Id " << std::hex << fiGdpbIdArray[uGdpb] << std::dec; switch (fiRpcType[uGbtx]) { + case 3: // intended fall-through case 2: // intended fall-through + case 1: // intended fall-through case 0: { // CBM modules BuildChannelsUidMapCbm(uCh, uGbtx); break; } - case 1: { + case 11: { // STAR eTOF modules BuildChannelsUidMapStar(uCh, uGbtx); break; @@ -418,7 +420,7 @@ void CbmMcbm2018TofPar::BuildChannelsUidMapStar(UInt_t& uCh, UInt_t uGbtx) // ------------------------------------------------------------------------- void CbmMcbm2018TofPar::BuildChannelsUidMapBmon(UInt_t& uCh, UInt_t uGbtx) { - LOG(info) << " Map diamond at GBTX - uCh = " << uCh; + LOG(info) << " Map diamond at GBTX " << uGbtx << " - uCh = " << uCh; for (UInt_t uFee = 0; uFee < kuNbFeePerGbtx; ++uFee) { for (UInt_t uFeeCh = 0; uFeeCh < kuNbChannelsPerFee; ++uFeeCh) { /// Mapping for the 2019 beamtime @@ -432,6 +434,7 @@ void CbmMcbm2018TofPar::BuildChannelsUidMapBmon(UInt_t& uCh, UInt_t uGbtx) /// => 1 Bmon channel per GET4 /// => 1-2 eLinks per GET4 => GET4 ID = GET4 * 2 (+ 1) UInt_t uChannelBmon = uFeeCh / 8 + 4 * fiRpcSide[uGbtx]; + fiRpcType[uGbtx] = 5; //for compatibility with TOF convention fviRpcChUId[uCh] = CbmTofAddress::GetUniqueAddress(fiModuleId[uGbtx], 0, uChannelBmon, 0, fiRpcType[uGbtx]); LOG(info) << Form("Bmon channel: %u from GBTx %2u Fee %2u " "Channel %2u, indx %d address %08x", @@ -506,7 +509,8 @@ void CbmMcbm2018TofPar::BuildChannelsUidMapCera(UInt_t& uCh, UInt_t /*uGbtx*/) fviRpcChUId[uCh] = CbmTofAddress::GetUniqueAddress(iModuleId, 7 - iRpc, 0, 0, iModuleType); uCh++; } - uCh += (24 + 2 * 32); + uCh += (24 + 4 * 32); //for 2024 FSD + //uCh += (24 + 2 * 32); LOG(info) << " Map end ceramics box at GBTX - uCh = " << uCh; } // ------------------------------------------------------------------------- @@ -684,10 +688,52 @@ void CbmMcbm2018TofPar::BuildChannelsUidMapStar2A(UInt_t& uCh, UInt_t uGbtx) } } } + else if (fiRpcSide[uGbtx] == 5) { + int iSideMap = -1; + int iStrMap = -1; + int iRpcMap = -1; + const int ConOff[8] = {0, 2, 4, 6, 7, 1, 3, 5}; //Get4 after Gbtx + for (Int_t iFeet = 0; iFeet < 5; iFeet++) { + for (Int_t iStr = 0; iStr < 32; iStr++) { + switch (iFeet) { + case 0: iSideMap = -1; break; + case 1: + iRpcMap = 0; + iStrMap = 3 - iStr % 4 + 4 * ConOff[iStr / 4]; + iStrMap = 31 - iStrMap; + iSideMap = 1; + break; + case 2: + iRpcMap = 0; + iStrMap = 3 - iStr % 4 + 4 * ConOff[iStr / 4]; + iStrMap = 31 - iStrMap; + iSideMap = 0; + break; + case 3: + iRpcMap = 1; + iStrMap = 3 - iStr % 4 + 4 * ConOff[iStr / 4]; + iStrMap = 31 - iStrMap; + iSideMap = 0; + break; + case 4: + iRpcMap = 1; + iStrMap = 3 - iStr % 4 + 4 * ConOff[iStr / 4]; + iStrMap = 31 - iStrMap; + iSideMap = 1; + break; + } + if (iSideMap > -1) + fviRpcChUId[uCh] = + CbmTofAddress::GetUniqueAddress(fiModuleId[uGbtx], iRpcMap, iStrMap, iSideMap, fiRpcType[uGbtx]); + else + fviRpcChUId[uCh] = 0; + uCh++; + } + } + } } } -// ------------------------------------------------------------------------- void CbmMcbm2018TofPar::BuildChannelsUidMapBuc(UInt_t& uCh, UInt_t uGbtx) { LOG(info) << " Map Buc box " << fiModuleId[uGbtx] << " at GBTX " << uGbtx << " - uCh = " << uCh; @@ -745,7 +791,12 @@ void CbmMcbm2018TofPar::BuildChannelsUidMapBuc(UInt_t& uCh, UInt_t uGbtx) case 4: // HD cosmic 2019, Buc2018, v18o iRpcMap = 1 - iRpcMap; break; - case 5: // HD cosmic 2020, Buc2018, v20a + case 5: // Buc2025, mCBM + iRpcMap = 1 - iRpcMap; + //iStrMap = 31 - iStr; + iSideMap = 1 - iSideMap; + break; + case 55: // HD cosmic 2020, Buc2018, v20a iStrMap = 31 - iStr; break; case 6: //BUC special diff --git a/core/detectors/tof/CbmMcbm2018TofPar.h b/core/detectors/tof/CbmMcbm2018TofPar.h index 6ede9c726ac88bf55d704c1c6d302d1491fb61b8..fa38cb39ec793e5a493d823b2651556e5fb2e855 100644 --- a/core/detectors/tof/CbmMcbm2018TofPar.h +++ b/core/detectors/tof/CbmMcbm2018TofPar.h @@ -85,7 +85,8 @@ class CbmMcbm2018TofPar : public FairParGenericSet { inline Double_t GetTsDeadtimePeriod() { return fdTsDeadtimePeriod; } inline bool CheckBmonComp(uint32_t uCompId) { return ((uCompId & 0xFFF0) == 0xABF0); } - inline bool CheckInnerComp(uint32_t uCompId) { return ((uCompId & 0xFFF0) == 0xBBC0); } + //inline bool CheckInnerComp(uint32_t uCompId) { return ((uCompId & 0xFFF0) == 0xBBC0); } + inline bool CheckInnerComp(uint32_t uCompId) { return ((uCompId & 0xFF00) == 0xBB00); } private: void BuildChannelsUidMap(); @@ -121,6 +122,7 @@ class CbmMcbm2018TofPar : public FairParGenericSet { const UInt_t kuPaditoget4[kuNbChannelsPerFee] = { 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12, 19, 18, 17, 16, 23, 22, 21, 20, 27, 26, 25, 24, 31, 30, 29, 28}; //! Map from PADI channel to GET4 channel + const UInt_t kuElinkToGet4[kuNbGet4PerGbtx] = {27, 2, 7, 3, 31, 26, 30, 1, 33, 37, 32, 13, 9, 14, 10, 15, 17, 21, 16, 35, 34, 38, 25, 24, 0, 6, 20, 23, 18, 22, 28, 4, 29, 5, 19, 36, 39, 8, 12, 11}; diff --git a/external/InstallParameter.cmake b/external/InstallParameter.cmake index e2c98a2f89de41e69ef18f30969ee696f5c1e9f3..7d97a642abd711e516874c0e1bc1d7bdf17ebe1d 100644 --- a/external/InstallParameter.cmake +++ b/external/InstallParameter.cmake @@ -1,4 +1,4 @@ -set(PARAMETER_VERSION 99acefb7a5d6667893b319a44a20b265cfb6fbac) # 2025/02/15 +set(PARAMETER_VERSION 837c4d8a6ad72455bf5843d85360580f19700644) # 2025/03/07 set(PARAMETER_SRC_URL "https://git.cbm.gsi.de/CbmSoft/cbmroot_parameter.git") download_project_if_needed(PROJECT Parameter_source