From a4734cb8d3c05a926cd2702ecde44162cd2fed5c Mon Sep 17 00:00:00 2001 From: "s.zharko@gsi.de" <s.zharko@gsi.de> Date: Wed, 5 Feb 2025 20:03:41 +0100 Subject: [PATCH] online: BMON digi calibrator --- algo/CMakeLists.txt | 1 + algo/detectors/bmon/Calibrate.cxx | 166 +++++++++++++++++++++++++++ algo/detectors/bmon/Calibrate.h | 50 ++++++++ algo/detectors/bmon/CalibrateSetup.h | 67 +++++++++++ algo/detectors/bmon/UnpackMS.cxx | 1 + algo/global/ParFiles.cxx | 12 +- algo/global/ParFiles.h | 2 + algo/global/Reco.cxx | 71 ++++++++++++ algo/global/Reco.h | 2 + core/data/bmon/CbmBmonDigi.h | 27 ++--- core/data/tof/CbmTofAddress.cxx | 18 +++ core/data/tof/CbmTofAddress.h | 13 ++- core/data/tof/CbmTofDigi.h | 29 ++--- external/InstallParameter.cmake | 2 + 14 files changed, 431 insertions(+), 30 deletions(-) create mode 100644 algo/detectors/bmon/Calibrate.cxx create mode 100644 algo/detectors/bmon/Calibrate.h create mode 100644 algo/detectors/bmon/CalibrateSetup.h diff --git a/algo/CMakeLists.txt b/algo/CMakeLists.txt index 09ee075af5..58ac4397e4 100644 --- a/algo/CMakeLists.txt +++ b/algo/CMakeLists.txt @@ -95,6 +95,7 @@ set(SRCS evselector/DigiEventSelector.cxx evselector/DigiEventSelectorConfig.cxx unpack/CommonUnpacker.cxx + detectors/bmon/Calibrate.cxx detectors/sts/ChannelMaskSet.cxx detectors/sts/ReadoutConfig.cxx detectors/sts/HitfinderChain.cxx diff --git a/algo/detectors/bmon/Calibrate.cxx b/algo/detectors/bmon/Calibrate.cxx new file mode 100644 index 0000000000..70d99daeb4 --- /dev/null +++ b/algo/detectors/bmon/Calibrate.cxx @@ -0,0 +1,166 @@ +/* Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file Calibrate.h +/// \brief Calibrator for the BMON digis (implementation) +/// \since 04.02.2025 +/// \author Sergei Zharko <s.zharko@gsi.de> + +#include "Calibrate.h" + +#include "AlgoFairloggerCompat.h" +#include "CbmTofAddress.h" +#include "util/TimingsFormat.h" + +#include <chrono> + +using cbm::algo::bmon::Calibrate; +using cbm::algo::bmon::CalibrateSetup; +using fles::Subsystem; + +// --------------------------------------------------------------------------------------------------------------------- +// +Calibrate::Calibrate(CalibrateSetup setup) : fSetup(setup), fSmOffset(1, 0), fRpcOffset(1, 0) +{ + // Initialize offset arrays for channel deadtime check + int32_t NbSm = fSetup.NbSm; + int32_t NbRpc = fSetup.NbRpc; + for (int32_t Sm = 0; Sm < NbSm; Sm++) { + fSmOffset.push_back(fSmOffset.back() + NbRpc); + for (int32_t Rpc = 0; Rpc < NbRpc; Rpc++) { + int32_t NbChan = fSetup.rpcs[Sm * NbRpc + Rpc].chanPar.size(); + fRpcOffset.push_back(fRpcOffset.back() + 2 * NbChan); //Factor 2 for channel sides + } + } + + // **** DEBUG: BEGIN + for (size_t iO = 0; iO < fSmOffset.size(); ++iO) { + L_(info) << "SM offset: " << iO << ", " << fSmOffset[iO]; + } + for (size_t iO = 0; iO < fRpcOffset.size(); ++iO) { + L_(info) << "RPC offset: " << iO << ", " << fRpcOffset[iO]; + } + // **** DEBUG: END + + fChannelDeadTime = std::vector<double>(fRpcOffset.back(), std::numeric_limits<double>::quiet_NaN()); +} + +// --------------------------------------------------------------------------------------------------------------------- +// +Calibrate::resultType Calibrate::operator()(gsl::span<const CbmBmonDigi> digiIn) +{ + xpu::push_timer("TofCalibrate"); + xpu::t_add_bytes(digiIn.size_bytes()); + + // --- Output data + resultType result = {}; + + auto& calDigiOut = result.first; + auto& monitor = result.second; + calDigiOut.reserve(digiIn.size()); + + std::fill(fChannelDeadTime.begin(), fChannelDeadTime.end(), std::numeric_limits<double>::quiet_NaN()); + + for (const auto& digi : digiIn) { + uint32_t address = static_cast<uint32_t>(digi.GetAddress()); + const int32_t SmType{CbmTofAddress::GetSmType(address)}; + const int32_t Sm{CbmTofAddress::GetSmId(address)}; + const int32_t Rpc{CbmTofAddress::GetRpcId(address)}; + const int NbRpc{fSetup.NbRpc}; + + int32_t Chan{CbmTofAddress::GetChannelId(address)}; + int32_t Side{CbmTofAddress::GetChannelSide(address)}; + + // NOTE: Follow the hack in the CbmTofEventClusterizer::Exec() for the BMON digis and change the address + // of calibrated digis. In general it is incorrect and needs further investigation. + uint32_t calAddress = address; + if (Side == 1) { + Side = 0; + Chan += 6; + calAddress = CbmTofAddress::GetUniqueAddress(Sm, Rpc, Chan, Side, SmType); + } + + auto& rpcs = fSetup.rpcs; + if (SmType != fSetup.SmType || Sm * NbRpc + Rpc >= static_cast<int>(rpcs.size())) { + monitor.fDigiCalibUnknownRPC++; + L_(error) << "Unknown BMON digi address: " << CbmTofAddress::ToString(calAddress); + continue; + } + + CalibrateSetup::Rpc& rpcPar = fSetup.rpcs[Sm * NbRpc + Rpc]; + CalibrateSetup::Channel& chanPar = rpcPar.chanPar[Chan]; + + // Check dead time + // FIXME: BMON digis (must) have only one side -> Fix the offsets, when mcbm2024_05 will be fixed + const size_t chanIdx = fRpcOffset[fSmOffset[Sm] + Rpc] + Chan + Side * rpcPar.chanPar.size(); + const double deadTime = fChannelDeadTime[chanIdx]; + + if (!std::isnan(deadTime) && digi.GetTime() <= deadTime) { + fChannelDeadTime[chanIdx] = digi.GetTime() + rpcPar.channelDeadtime; + monitor.fDigiDeadTimeCount++; + continue; + } + fChannelDeadTime[chanIdx] = digi.GetTime() + rpcPar.channelDeadtime; + + // Create calibrated digi + CbmBmonDigi& pCalDigi = calDigiOut.emplace_back(digi); + pCalDigi.SetAddress(calAddress); + + // Check if channel sides need to be swapped + if (rpcPar.swapChannelSides) { + pCalDigi.SetAddress(CbmTofAddress::GetUniqueAddress(Sm, Rpc, Chan, (0 == Side) ? 1 : 0, SmType)); + } + + // calibrate Digi Time + pCalDigi.SetTime(pCalDigi.GetTime() - chanPar.vCPTOff[Side]); + + // subtract Offset + const double dTot = std::max(pCalDigi.GetCharge() - chanPar.vCPTotOff[Side], 0.001); + + // calibrate Digi charge (corresponds to TOF ToT) + pCalDigi.SetCharge(dTot * chanPar.vCPTotGain[Side]); + + // walk correction + std::vector<double>& walk = chanPar.vCPWalk[Side]; + const double dTotBinSize = (rpcPar.TOTMax - rpcPar.TOTMin) / rpcPar.numClWalkBinX; + int32_t iWx = std::max((int32_t)((pCalDigi.GetCharge() - rpcPar.TOTMin) / dTotBinSize), 0); + iWx = std::min(iWx, rpcPar.numClWalkBinX - 1); + + const double dDTot = (pCalDigi.GetCharge() - rpcPar.TOTMin) / dTotBinSize - (double) iWx - 0.5; + double dWT = walk[iWx]; + + // linear interpolation to next bin + if (dDTot > 0) { + if (iWx < rpcPar.numClWalkBinX - 1) { + dWT += dDTot * (walk[iWx + 1] - walk[iWx]); + } + } + else { + if (0 < iWx) { + dWT -= dDTot * (walk[iWx - 1] - walk[iWx]); + } + } + pCalDigi.SetTime(pCalDigi.GetTime() - dWT); // calibrate Digi Time + } + + /// Sort the buffers of hits due to the time offsets applied + // (insert-sort faster than std::sort due to pre-sorting) + for (std::size_t i = 1; i < calDigiOut.size(); ++i) { + CbmTofDigi digi = calDigiOut[i]; + std::size_t j = i; + while (j > 0 && calDigiOut[j - 1].GetTime() > digi.GetTime()) { + calDigiOut[j] = calDigiOut[j - 1]; + --j; + } + calDigiOut[j] = digi; + } + + // Kept for possible unsorted input + // std::sort(calDigiOut.begin(), calDigiOut.end(), + // [](const CbmTofDigi& a, const CbmTofDigi& b) -> bool { return a.GetTime() < b.GetTime(); }); + + monitor.fTime = xpu::pop_timer(); + monitor.fNumDigis = digiIn.size(); + return result; +} diff --git a/algo/detectors/bmon/Calibrate.h b/algo/detectors/bmon/Calibrate.h new file mode 100644 index 0000000000..291a6882b4 --- /dev/null +++ b/algo/detectors/bmon/Calibrate.h @@ -0,0 +1,50 @@ +/* Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file Calibrate.h +/// \brief Calibratior for the BMON digis +/// \since 04.02.2025 +/// \author Sergei Zharko <s.zharko@gsi.de> + +#pragma once + +#include "CbmBmonDigi.h" +#include "PartitionedVector.h" +#include "bmon/CalibrateSetup.h" +#include "tof/Calibrate.h" // for the monitor data +#include "tof/Clusterizer.h" + +#include <gsl/span> +#include <optional> +#include <sstream> +#include <vector> + +#include <xpu/host.h> + +namespace cbm::algo::bmon +{ + // NOTE: reusing TOF monitor + using CalibrateMonitorData = tof::CalibrateMonitorData; + + /// \class Calibrate + /// \brief Algorithm to calibrate BMon digis + class Calibrate { + public: + using resultType = std::pair<std::vector<CbmBmonDigi>, CalibrateMonitorData>; + + /// \brief Constructor + /// \param params Calibration parameters + explicit Calibrate(CalibrateSetup params); + + /// \brief Calibrates a portion of digis + /// \param digiIn A portion of digis to calibrate + resultType operator()(gsl::span<const CbmBmonDigi> digiIn); + + private: + CalibrateSetup fSetup; ///< Parameters of calibrator + std::vector<double> fChannelDeadTime; ///< Storage for dead time check + std::vector<size_t> fSmOffset; ///< Super module offset + std::vector<size_t> fRpcOffset; ///< RPC offset + }; +} // namespace cbm::algo::bmon diff --git a/algo/detectors/bmon/CalibrateSetup.h b/algo/detectors/bmon/CalibrateSetup.h new file mode 100644 index 0000000000..0d9dedd93c --- /dev/null +++ b/algo/detectors/bmon/CalibrateSetup.h @@ -0,0 +1,67 @@ +/* Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file CalibrateSetup.h +/// \brief Configuration of the calibrator for the BMON digis +/// \since 04.02.2025 +/// \author Sergei Zharko <s.zharko@gsi.de> + +#pragma once + +#include "Definitions.h" +#include "yaml/Property.h" + +#include <array> +#include <map> +#include <string> +#include <vector> + +namespace cbm::algo::bmon +{ + /// \struct CalibrateSetup + /// \brief BMON calibration per channel + struct CalibrateSetup { + + struct Channel { + std::vector<double> vCPTOff; + std::vector<double> vCPTotGain; + std::vector<double> vCPTotOff; + std::vector<std::vector<double>> vCPWalk; + + CBM_YAML_PROPERTIES(yaml::Property(&Channel::vCPTOff, "vCPTOff", "CPT offset"), + yaml::Property(&Channel::vCPTotGain, "vCPTotGain", "CP time over threshold gain"), + yaml::Property(&Channel::vCPTotOff, "vCPTotOff", "CP time over threshold offset"), + yaml::Property(&Channel::vCPWalk, "vCPWalk", "CP walk correction", YAML::Block, YAML::Flow)); + }; + + struct Rpc { + int32_t numClWalkBinX; + double TOTMax; + double TOTMin; + bool swapChannelSides; + double channelDeadtime; + std::vector<Channel> chanPar; + + CBM_YAML_PROPERTIES(yaml::Property(&Rpc::numClWalkBinX, "numClWalkBinX", "number of walk correction bins"), + yaml::Property(&Rpc::TOTMax, "TOTMax", "maximum time over threshold"), + yaml::Property(&Rpc::TOTMin, "TOTMin", "minimum time over threshold"), + yaml::Property(&Rpc::swapChannelSides, "swapChannelSides", "flag for swapping channel sides"), + yaml::Property(&Rpc::channelDeadtime, "channelDeadtime", "channel dead time"), + yaml::Property(&Rpc::chanPar, "chanPar", "channel parameters")); + }; + + /* Members */ + int32_t SmType; + int32_t NbSm; + int32_t NbRpc; + std::vector<Rpc> rpcs; + + CBM_YAML_PROPERTIES( + yaml::Property(&CalibrateSetup::SmType, "SmType", "Super module type"), + yaml::Property(&CalibrateSetup::NbSm, "NbSm", "Number of SMs"), + yaml::Property(&CalibrateSetup::NbRpc, "NbRpc", "Number of RPCs"), + yaml::Property(&CalibrateSetup::rpcs, "rpcs", "Parameters of RPCs")); + }; + +} // namespace cbm::algo::bmon diff --git a/algo/detectors/bmon/UnpackMS.cxx b/algo/detectors/bmon/UnpackMS.cxx index b4fbf123e1..22d56e90d1 100644 --- a/algo/detectors/bmon/UnpackMS.cxx +++ b/algo/detectors/bmon/UnpackMS.cxx @@ -5,6 +5,7 @@ #include "UnpackMS.h" #include "AlgoFairloggerCompat.h" +#include "CbmTofAddress.h" #include <cassert> #include <cmath> diff --git a/algo/global/ParFiles.cxx b/algo/global/ParFiles.cxx index 8eb07742a6..eabec37b4b 100644 --- a/algo/global/ParFiles.cxx +++ b/algo/global/ParFiles.cxx @@ -25,7 +25,9 @@ ParFiles::ParFiles(uint32_t runId) switch (setup) { case Setup::mCBM2022: - bmon.readout = "BmonReadout_mcbm2022.yaml"; + bmon.readout = "BmonReadout_mcbm2022.yaml"; + bmon.calibrate = "BmonCalibratePar_mcbm2022.yaml"; + bmon.hitfinder = "BmonHitfinderPar_mcbm2022.yaml"; sts.readout = "StsReadout_mcbm2022.yaml"; sts.chanMask = "StsChannelMaskSet_mcbm2022.yaml"; @@ -46,7 +48,9 @@ ParFiles::ParFiles(uint32_t runId) break; case Setup::mCBM2024_03: - bmon.readout = "BmonReadout_mcbm2024.yaml"; + bmon.readout = "BmonReadout_mcbm2024.yaml"; + bmon.calibrate = "BmonCalibratePar_mcbm2024.yaml"; + bmon.hitfinder = "BmonHitfinderPar_mcbm2024.yaml"; sts.readout = "StsReadout_mcbm2024.yaml"; sts.chanMask = "StsChannelMaskSet_mcbm2024.yaml"; @@ -67,7 +71,9 @@ ParFiles::ParFiles(uint32_t runId) break; case Setup::mCBM2024_05: - bmon.readout = "BmonReadout_mcbm2024.yaml"; + bmon.readout = "BmonReadout_mcbm2024.yaml"; + bmon.calibrate = "mcbm2024_05/BmonCalibratePar.yaml"; + bmon.hitfinder = "mcbm2024_05/BmonHitfinderPar.yaml"; sts.readout = "StsReadout_mcbm2024.yaml"; sts.chanMask = "StsChannelMaskSet_mcbm2024.yaml"; diff --git a/algo/global/ParFiles.h b/algo/global/ParFiles.h index 9c966ac637..691e27b39b 100644 --- a/algo/global/ParFiles.h +++ b/algo/global/ParFiles.h @@ -26,6 +26,8 @@ namespace cbm::algo struct { fs::path readout; + fs::path calibrate; + fs::path hitfinder; } bmon; struct { diff --git a/algo/global/Reco.cxx b/algo/global/Reco.cxx index e9a0a7a9a0..9bdc35bb6b 100644 --- a/algo/global/Reco.cxx +++ b/algo/global/Reco.cxx @@ -14,6 +14,7 @@ #include "RecoGeneralQa.h" #include "StsDigiQa.h" #include "TrackingSetup.h" +#include "bmon/Calibrate.h" #include "bmon/ReadoutConfig.h" #include "bmon/Unpack.h" #include "ca/TrackingChain.h" @@ -41,6 +42,10 @@ #include <xpu/host.h> +// DEBUG: BEGIN +#include <set> +// DEBUG: END + using namespace cbm::algo; using fles::Subsystem; @@ -204,6 +209,14 @@ void Reco::Init(const Options& opts) fStsHitFinder->SetParameters(hitFinderPars); } + // BMON Hitfinder + if (Opts().Has(fles::Subsystem::BMON) && Opts().Has(Step::LocalReco)) { + auto calibSetup = yaml::ReadFromFile<bmon::CalibrateSetup>(opts.ParamsDir() / parFiles.bmon.calibrate); + fBmonCalibrator = std::make_unique<bmon::Calibrate>(calibSetup); + + //auto hitfindSetup = yaml::ReadFromFile<bmon::HitfindSetup>(opts.ParamsDir() / parFiles.bmon.hitfinder); + //fBmonHitFinder = std::make_unique<bmon::Hitfind>(hitfindSetup); + } // TOF Hitfinder if (Opts().Has(fles::Subsystem::TOF) && Opts().Has(Step::LocalReco)) { @@ -372,6 +385,64 @@ RecoResults Reco::Run(const fles::Timeslice& ts) QueueEvbuildMetrics(evbuildMonitor); } + // ***** DEBUG: BEGIN + if constexpr (1) { + std::set<uint32_t> bmonFoundAddressesUnp; // found addresses among unpacked bmon digis + std::set<uint32_t> bmonFoundAddressesCal; // found addresses among clalibrated bmon digis + + int nEvents = 20; //events.size(); + for (int iE = 0; iE < nEvents; ++iE) { + //L_(info) << "-------------- event #" << iE; + const auto& event = events[iE]; + for (const auto& digi : event.fBmon) { + bmonFoundAddressesUnp.insert(digi.GetAddress()); + } + + // Calibrate TOF digis: + auto [tofDigis, tofCalMonitor] = (*fTofCalibrator)(event.fTof); + auto [bmonDigis, bmonCalMonitor] = (*fBmonCalibrator)(event.fBmon); + + for (const auto& digi : bmonDigis) { + bmonFoundAddressesCal.insert(digi.GetAddress()); + } + + double bmonMinT = 1e+20; + double bmonMaxT = -1e+20; + for (const auto& digi : bmonDigis) { + //L_(info) << "BMON: " << digi.GetTime(); + bmonMinT = std::min(bmonMinT, digi.GetTime()); + bmonMaxT = std::max(bmonMaxT, digi.GetTime()); + } + double tofMinT = 1e+20; + double tofMaxT = -1e+20; + for (const auto& digi : tofDigis) { + //L_(info) << "TOF: " << digi.GetTime(); + tofMinT = std::min(tofMinT, digi.GetTime()); + tofMaxT = std::max(tofMaxT, digi.GetTime()); + } + double stsMinT = 1e+20; + double stsMaxT = -1e+20; + const auto& stsDigis = event.fSts; + for (const auto& digi : stsDigis) { + //L_(info) << "STS: " << digi.GetTime(); + stsMinT = std::min(stsMinT, digi.GetTime()); + stsMaxT = std::max(stsMaxT, digi.GetTime()); + } + L_(info) << "BMON time: " << bmonMinT << ", " << bmonMaxT << ", " << (bmonMaxT - bmonMinT); + L_(info) << "TOF time: " << tofMinT << ", " << tofMaxT << ", " << (tofMaxT - tofMinT); + L_(info) << "STS time: " << stsMinT << ", " << stsMaxT << ", " << (stsMaxT - stsMinT); + } + L_(info) << "!!!! Found addresses in BMON after unpacking: "; + for (auto address : bmonFoundAddressesUnp) { + L_(info) << " - " << CbmTofAddress::ToString(address); + } + L_(info) << "!!!! Found addresses in BMON after calibration: "; + for (auto address : bmonFoundAddressesCal) { + L_(info) << " - " << CbmTofAddress::ToString(address); + } + } + // ***** DEBUG: END + // --- Filter data for output if (Opts().HasOutput(RecoData::DigiTimeslice)) { results.bmonDigis = std::move(digis.fBmon); diff --git a/algo/global/Reco.h b/algo/global/Reco.h index 8e26d35271..982a95cfa4 100644 --- a/algo/global/Reco.h +++ b/algo/global/Reco.h @@ -27,6 +27,7 @@ namespace cbm::algo namespace bmon { class Unpack; + class Calibrate; } namespace much @@ -146,6 +147,7 @@ namespace cbm::algo // BMON std::unique_ptr<bmon::Unpack> fBmonUnpack; + std::unique_ptr<bmon::Calibrate> fBmonCalibrator; // MUCH std::unique_ptr<much::Unpack> fMuchUnpack; diff --git a/core/data/bmon/CbmBmonDigi.h b/core/data/bmon/CbmBmonDigi.h index 200e72d0ce..7f0584e2fc 100644 --- a/core/data/bmon/CbmBmonDigi.h +++ b/core/data/bmon/CbmBmonDigi.h @@ -111,19 +111,20 @@ public: private: - int32_t fAddress = ToIntegralType<ECbmModuleId>(ECbmModuleId::kBmon); ///< Unique CBM address - double fTime = -1.; ///< Time of signal in BMON [ns] - float fCharge = -1.; ///< Charge - - friend class boost::serialization::access; - - template<class Archive> - void serialize(Archive& ar, const unsigned int /*version*/) - { - ar& fAddress; - ar& fTime; - ar& fCharge; - } + // FIXME: SZh 5.2.2025: change address type int32_t -> uint32_t + int32_t fAddress = ToIntegralType<ECbmModuleId>(ECbmModuleId::kBmon); ///< Unique CBM address + double fTime = -1.; ///< Time of signal in BMON [ns] + float fCharge = -1.; ///< Charge + + friend class boost::serialization::access; + + template<class Archive> + void serialize(Archive& ar, const unsigned int /*version*/) + { + ar& fAddress; + ar& fTime; + ar& fCharge; + } #ifndef NO_ROOT ClassDefNV(CbmBmonDigi, 1); diff --git a/core/data/tof/CbmTofAddress.cxx b/core/data/tof/CbmTofAddress.cxx index 0ed83293f2..068504c399 100644 --- a/core/data/tof/CbmTofAddress.cxx +++ b/core/data/tof/CbmTofAddress.cxx @@ -11,6 +11,9 @@ #include "CbmTofAddress.h" +#include <iomanip> +#include <sstream> + // It seems C++ standard force the initialization to be in cxx/cpp file (outside of class definition) // When not trivial constant values => To check if it should apply also to simple values maybe? /** Offset in bits for Super Module Id in the address field **/ @@ -40,3 +43,18 @@ const int32_t CbmTofAddress::fgkiStripFullIdMask = (((1 << fgkSystemBits) - 1)) + (((1 << fgkSmIdBits) - 1) << fgkSmIdOffset) + (((1 << fgkSmTypeBits) - 1) << fgkSmTypeOffset) + (((1 << fgkRpcIdBits) - 1) << fgkRpcIdOffset) + (((1 << fgkChannelIdBits) - 1) << fgkChannelIdOffset); + +std::string CbmTofAddress::ToString(int32_t address) +{ + using std::setfill; + using std::setw; + std::stringstream msg; + msg << std::hex << "0x" << setw(8) << setfill('0') << address << std::dec << setfill(' '); + msg << ": SmType=" << setw(3) << CbmTofAddress::GetSmType(address); + msg << ", Sm=" << setw(2) << CbmTofAddress::GetSmId(address); + msg << ", Rpc=" << setw(2) << CbmTofAddress::GetRpcId(address); + msg << ", Ch=" << setw(2) << CbmTofAddress::GetChannelId(address); + msg << ", Side=" << setw(1) << CbmTofAddress::GetChannelSide(address); + msg << ", RpcType=" << setw(2) << CbmTofAddress::GetRpcType(address); + return msg.str(); +} diff --git a/core/data/tof/CbmTofAddress.h b/core/data/tof/CbmTofAddress.h index f8954d532e..3abf9b1703 100644 --- a/core/data/tof/CbmTofAddress.h +++ b/core/data/tof/CbmTofAddress.h @@ -44,6 +44,7 @@ #include "CbmTofDetectorId_v12b.h" // for CbmTofDetectorId_v12b #include <cstdint> +#include <string> class CbmTofAddress : public CbmAddress { public: @@ -91,6 +92,11 @@ public: ** @return systemId **/ static int32_t GetRpcId(uint32_t address) { return ((address >> fgkRpcIdOffset) & ((1 << fgkRpcIdBits) - 1)); }; + /** Get the Rpc Type from the address + ** @param address Unique address + ** @return systemId + **/ + static int32_t GetRpcType(uint32_t address) { return ((address >> fgkRpcTypeOffset) & ((1 << fgkRpcTypeBits) - 1)); }; /** Get the Channel Id from the address ** @param address Unique address ** @return systemId @@ -169,8 +175,13 @@ public: return GetUniqueAddress(detId.GetSModule(detIdInput), detId.GetCounter(detIdInput), detId.GetCell(detIdInput), 0, detId.GetSMType(detIdInput)); }; + /** String representation of the address + ** @param address Unique address + ** @return String representation of the address + **/ + static std::string ToString(int32_t address); -private: + private: /** ** To adapt the address sub-fields repartition in size, ** you just need to change number of bits of the two sub-fields changing length. diff --git a/core/data/tof/CbmTofDigi.h b/core/data/tof/CbmTofDigi.h index 942c6edb18..7448ad1a72 100644 --- a/core/data/tof/CbmTofDigi.h +++ b/core/data/tof/CbmTofDigi.h @@ -109,6 +109,7 @@ public: /** ** @brief Inherited from CbmDigi. **/ + // FIXME: SZh 5.2.2025: change address type int32_t -> uint32_t int32_t GetAddress() const { return fuAddress; }; @@ -160,6 +161,8 @@ public: double GetSide() const { return CbmTofAddress::GetChannelSide(GetAddress()); }; /** Modifiers **/ + + // FIXME: SZh 5.2.2025: change address type int32_t -> uint32_t void SetAddress(int32_t address) { fuAddress = address; }; void SetAddress(uint32_t Sm, uint32_t Rpc, uint32_t Channel, uint32_t Side = 0, uint32_t SmType = 0); void SetTime(double time) { fdTime = time; }; @@ -169,19 +172,19 @@ public: private: - double fdTime; ///< Absolute time [ps] - double fdTot; ///< Tot [ps] - uint32_t fuAddress; ///< Unique channel address - - friend class boost::serialization::access; - - template<class Archive> - void serialize(Archive& ar, const unsigned int /*version*/) - { - ar& fuAddress; - ar& fdTime; - ar& fdTot; - } + double fdTime; ///< Absolute time [ns] + double fdTot; ///< Tot [ns?] + uint32_t fuAddress; ///< Unique channel address + + friend class boost::serialization::access; + + template<class Archive> + void serialize(Archive& ar, const unsigned int /*version*/) + { + ar& fuAddress; + ar& fdTime; + ar& fdTot; + } #ifndef NO_ROOT ClassDefNV(CbmTofDigi, 3); diff --git a/external/InstallParameter.cmake b/external/InstallParameter.cmake index 74e6f43126..b368899baf 100644 --- a/external/InstallParameter.cmake +++ b/external/InstallParameter.cmake @@ -1,5 +1,7 @@ set(PARAMETER_VERSION ab9972f137bc52efd58bf3672e670a2d4fbcb1be) # 2025/02/11 set(PARAMETER_SRC_URL "https://git.cbm.gsi.de/CbmSoft/cbmroot_parameter.git") +#set(PARAMETER_VERSION 96b2189ac86b3d49c32f63da76e68f66544bba55) # 2025/05/02, BMON hitfinder parameters for online +#set(PARAMETER_SRC_URL "https://git.cbm.gsi.de/s.zharko/cbmroot_parameter.git") download_project_if_needed(PROJECT Parameter_source GIT_REPOSITORY ${PARAMETER_SRC_URL} -- GitLab