diff --git a/algo/CMakeLists.txt b/algo/CMakeLists.txt index ee9040be2fb508c78b0fece2e4c865d0a098a47f..1811fe30e8ef76e31df9cb666b847bc9d1c2545e 100644 --- a/algo/CMakeLists.txt +++ b/algo/CMakeLists.txt @@ -89,6 +89,7 @@ set(SRCS detectors/much/ReadoutConfig.cxx detectors/much/Unpack.cxx detectors/tof/HitFinder.cxx + detectors/tof/Calibrate.cxx detectors/tof/Clusterizer.cxx detectors/tof/ReadoutConfig.cxx detectors/tof/Unpack.cxx diff --git a/algo/detectors/tof/Calibrate.cxx b/algo/detectors/tof/Calibrate.cxx new file mode 100644 index 0000000000000000000000000000000000000000..be30ee715b515676a64f56c9eb788f1dc0ac1766 --- /dev/null +++ b/algo/detectors/tof/Calibrate.cxx @@ -0,0 +1,106 @@ +/* Copyright (C) 2023 Facility for Antiproton and Ion Research in Europe, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Dominik Smith [committer] */ + +#include "Calibrate.h" + +#include <chrono> + +#include "log.hpp" + +using namespace std; +using fles::Subsystem; + +namespace cbm::algo::tof +{ + // ----- Execution ------------------------------------------------------- + Calibrate::resultType Calibrate::operator()(gsl::span<CbmTofDigi> digiIn) + { + xpu::push_timer("TofCalibrate"); + xpu::t_add_bytes(digiIn.size_bytes()); + + // --- Output data + resultType result = {}; + + auto& calDigiOut = result.first; + auto& monitor = result.second; + + // channel deadtime map + std::map<int32_t, double> mChannelDeadTime; + + for (size_t iDigi = 0; iDigi < digiIn.size(); iDigi++) { + + CbmTofDigi pDigi = digiIn[iDigi]; + const double SmType = pDigi.GetType(); + const double Sm = pDigi.GetSm(); + const double Rpc = pDigi.GetRpc(); + const double Chan = pDigi.GetChannel(); + const double Side = pDigi.GetSide(); + const int NbRpc = fTofConfig.NbRpc[SmType]; + + auto& rpcs = fTofConfig.rpcs; + if (SmType >= rpcs.size() || Sm * NbRpc + Rpc >= rpcs.at(SmType).size()) { + monitor.fDigiCalibUnknownRPC++; + continue; + } + + HitfindSetup::Rpc& rpcPar = fTofConfig.rpcs.at(SmType).at(Sm * NbRpc + Rpc); + HitfindSetup::Channel& chanPar = rpcPar.chanPar[Chan]; + + if (rpcPar.swapChannelSides && 5 != SmType && 8 != SmType) { + pDigi.SetAddress(Sm, Rpc, Chan, (0 == Side) ? 1 : 0, SmType); + } + + // Check dead time + const int32_t iAddr = pDigi.GetAddress(); + auto it = mChannelDeadTime.find(iAddr); + if (it != mChannelDeadTime.end() && pDigi.GetTime() <= it->second) { + it->second = pDigi.GetTime() + rpcPar.channelDeadtime; + continue; + } + mChannelDeadTime[iAddr] = pDigi.GetTime() + rpcPar.channelDeadtime; + + // Create calibrated digi + CbmTofDigi pCalDigi(pDigi); + + // calibrate Digi Time + pCalDigi.SetTime(pCalDigi.GetTime() - chanPar.vCPTOff[Side]); + + // subtract Offset + double dTot = pCalDigi.GetTot() - chanPar.vCPTotOff[Side]; + if (dTot < 0.001) dTot = 0.001; + // calibrate Digi ToT + pCalDigi.SetTot(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 = (int32_t)((pCalDigi.GetTot() - rpcPar.TOTMin) / dTotBinSize); + + if (0 > iWx) { iWx = 0; } + if (iWx >= rpcPar.numClWalkBinX) { iWx = rpcPar.numClWalkBinX - 1; } + + const double dDTot = (pCalDigi.GetTot() - 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 + calDigiOut.push_back(pCalDigi); + } + + /// Sort the buffers of hits due to the time offsets applied + std::sort(calDigiOut.begin(), calDigiOut.end(), + [](const CbmTofDigi& a, const CbmTofDigi& b) -> bool { return a.GetTime() < b.GetTime(); }); + + monitor.fTime = xpu::pop_timer(); + + return result; + } + +} // namespace cbm::algo::tof diff --git a/algo/detectors/tof/Calibrate.h b/algo/detectors/tof/Calibrate.h new file mode 100644 index 0000000000000000000000000000000000000000..9d8a60b0dd6b333236937cfabb22bdb084baf037 --- /dev/null +++ b/algo/detectors/tof/Calibrate.h @@ -0,0 +1,76 @@ +/* Copyright (C) 2023 Facility for Antiproton and Ion Research in Europe, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Dominik Smith [committer] */ + +#ifndef TOFCALIBRATE_H +#define TOFCALIBRATE_H 1 + +#include "CbmTofDigi.h" + +#include "tof/Clusterizer.h" +#include "tof/HitfindSetup.h" + +#include <gsl/span> +#include <optional> +#include <sstream> +#include <vector> + +#include <xpu/host.h> + +#include "PartitionedVector.h" + +namespace cbm::algo::tof +{ + + /** @struct CalibrateMonitorData + ** @author Dominik Smith <d.smith@gsi.de> + ** @since 16 Oct 2023 + ** @brief Monitoring data for calibration + **/ + struct CalibrateMonitorData { + xpu::timings fTime; + size_t fDigiCalibUnknownRPC = 0; + + std::string print() const + { + std::stringstream ss; + ss << "Calibrate stats: num unknown RPC " << fDigiCalibUnknownRPC << ", time " << fTime.wall() << std::endl; + return ss.str(); + } + }; + + /** @class Calibrate + ** @brief Algo class for calibration + ** @author Dominik Smith <d.smith@gsi.de> + ** @since 16.10.2023 + ** + **/ + class Calibrate { + + public: + typedef std::pair<std::vector<CbmTofDigi>, CalibrateMonitorData> resultType; + + /** @brief Algorithm execution + ** @param digis to calibrate + ** @return pair: digi timeslice, monitoring data + ** + ** @note Modifies input digis for time calibration + **/ + resultType operator()(gsl::span<CbmTofDigi> digiIn); + + /** @brief Default constructor **/ + Calibrate() {}; + + /** @brief Destructor **/ + ~Calibrate() {}; + + /** @brief Parameters for TOF hitfinders **/ + tof::HitfindSetup fTofConfig {}; + + private: // members + /** @brief Applies calibration to input digis **/ + std::vector<CbmTofDigi> CalibRawDigis(gsl::span<CbmTofDigi> digiVec, CalibrateMonitorData& monitor); + }; +} // namespace cbm::algo::tof + +#endif /* TOFCALIBRATE_H */ diff --git a/algo/detectors/tof/Hitfind.cxx b/algo/detectors/tof/Hitfind.cxx index 2d74178106d92f6036e5b3f5d80dec4e61fc02e1..d789c8367d79416dfc949daec56b968e1075cc96 100644 --- a/algo/detectors/tof/Hitfind.cxx +++ b/algo/detectors/tof/Hitfind.cxx @@ -24,10 +24,12 @@ namespace cbm::algo::tof auto& clusterTs = std::get<0>(result); auto& monitor = std::get<1>(result); - auto& calDigi = std::get<2>(result); + //auto& calDigi = std::get<2>(result); // Do calibration globally (optional, should not be used together with RPC-wise calibration) - calDigi = CalibRawDigis(digiIn, monitor); + //calDigi = CalibRawDigis(digiIn, monitor); + + auto& calDigi = digiIn; // Loop over the digis array and store the Digis in separate vectors for // each RPC modules diff --git a/reco/tasks/CbmTaskTofClusterizer.cxx b/reco/tasks/CbmTaskTofClusterizer.cxx index c9020271df490cd0cf639d5feb636662aef66bef..d3dba4ee11cdffc999ca2b5e9707de0146e9b05c 100644 --- a/reco/tasks/CbmTaskTofClusterizer.cxx +++ b/reco/tasks/CbmTaskTofClusterizer.cxx @@ -313,6 +313,7 @@ bool CbmTaskTofClusterizer::InitAlgos() cbm::algo::fs::path paramsPath = "TofHitfinderPar.yaml"; YAML::Node yaml = YAML::LoadFile(paramsPath.string()); fAlgo.fTofConfig = cbm::algo::config::Read<cbm::algo::tof::HitfindSetup>(yaml); + fCalibrate.fTofConfig = cbm::algo::config::Read<cbm::algo::tof::HitfindSetup>(yaml); fAlgo.Init(); return true; } @@ -347,13 +348,17 @@ bool CbmTaskTofClusterizer::BuildClusters() } } + // Calibrated digis (calibration done in algo) + // Can be left out if calibrated digis not stored separately! + *fTofCalDigiVec = fCalibrate(fTofDigiVec).first; + //call cluster finder - auto clusterOut = fAlgo(fTofDigiVec); + auto clusterOut = fAlgo(*fTofCalDigiVec); auto clusters = std::get<0>(clusterOut); // Calibrated digis (calibration done in algo) // Can be left out if calibrated digis not stored separately! - *fTofCalDigiVec = std::get<2>(clusterOut); + //*fTofCalDigiVec = std::get<2>(clusterOut); //Store hits and match for (auto const& cluster : clusters.Data()) { diff --git a/reco/tasks/CbmTaskTofClusterizer.h b/reco/tasks/CbmTaskTofClusterizer.h index 04a26e1ca3ed14ffc317948630174cd8e21a4803..b4996cc2c33e7b74a971282c4b65778c968a45ec 100644 --- a/reco/tasks/CbmTaskTofClusterizer.h +++ b/reco/tasks/CbmTaskTofClusterizer.h @@ -14,6 +14,7 @@ class CbmTsEventHeader; #include "CbmMatch.h" #include "CbmTofDigi.h" +#include "tof/Calibrate.h" #include "tof/Clusterizer.h" #include "tof/Hitfind.h" @@ -97,7 +98,6 @@ private: std::vector<CbmTofDigi>* fT0DigiVec = nullptr; //! T0 Digis - /** ** @brief Copy constructor. **/ @@ -130,6 +130,9 @@ private: // Hit finder algo cbm::algo::tof::Hitfind fAlgo; + // Calibrator algo + cbm::algo::tof::Calibrate fCalibrate; + const CbmTsEventHeader* fTsHeader; // Input variables