CbmRoot
Loading...
Searching...
No Matches
bmon/Calibrate.cxx
Go to the documentation of this file.
1/* Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Sergei Zharko [committer] */
4
9
10#include "Calibrate.h"
11
13#include "CbmTofAddress.h"
14#include "util/TimingsFormat.h"
15
16#include <bitset>
17#include <chrono>
18
21using fles::Subsystem;
22
23// ---------------------------------------------------------------------------------------------------------------------
24//
25Calibrate::Calibrate(CalibrateSetup setup) : fSetup(setup), fSelectionBitsOffset(0)
26{
27 // Initialize offset arrays for channel deadtime check
28 int nDiamondsInSetup = fSetup.diamonds.size();
29 if (nDiamondsInSetup == 0) {
30 throw std::runtime_error("No diamonds found in the BMON calibration config");
31 }
32 if (!(fSetup.selectionMask) != (nDiamondsInSetup == 1)) {
33 throw std::runtime_error("Wrong diamond selection mask: for a single diamond it must be zero, and for multiple"
34 " diamonds it must be non-zero");
35 }
36 if (nDiamondsInSetup > 1) {
37 // Define the selection bit offset
38 while (!((fSetup.selectionMask >> fSelectionBitsOffset) % 2)) {
40 }
41
42 // Sort the diamonds in the setup by their SM or Side or other distinguishing index
43 std::sort(fSetup.diamonds.begin(), fSetup.diamonds.end(), [&](const auto& lhs, const auto& rhs) {
44 return GetDiamondIndex(lhs.refAddress) < GetDiamondIndex(rhs.refAddress);
45 });
46 }
47
48 // Remove the channel information from the reference address
49 for (auto& diamond : fSetup.diamonds) {
50 diamond.refAddress &= ~CbmTofAddress::GetChannelIdBitmask();
51 }
52
53 // Calculate the channel offsets, needed for the dead time
54 fChannelOffset = std::vector<size_t>(nDiamondsInSetup + 1, 0); // the last element -- total number of channels
55 for (int32_t iD = 0; iD < nDiamondsInSetup; ++iD) {
56 fChannelOffset[iD + 1] = fChannelOffset[iD] + fSetup.diamonds[iD].chanPar.size();
57 }
58 fChannelDeadTime = std::vector<double>(fChannelOffset.back(), std::numeric_limits<double>::quiet_NaN());
59
60 // **** DEBUG: END
61}
62
63// ---------------------------------------------------------------------------------------------------------------------
64//
65Calibrate::resultType Calibrate::operator()(gsl::span<const CbmBmonDigi> digiIn)
66{
67 xpu::push_timer("BmonCalibrate");
68 xpu::t_add_bytes(digiIn.size_bytes());
69
70 // --- Output data
71 resultType result = {};
72
73 auto& calDigiOut = std::get<0>(result);
74 auto& monitor = std::get<1>(result);
75 calDigiOut.reserve(digiIn.size());
76
77 // Reset the channel dead time
78 std::fill(fChannelDeadTime.begin(), fChannelDeadTime.end(), std::numeric_limits<double>::quiet_NaN());
79
80 const auto& diamonds = fSetup.diamonds;
81 for (const auto& digi : digiIn) {
82 uint32_t address = static_cast<uint32_t>(digi.GetAddress());
83 int32_t iChannel = CbmTofAddress::GetChannelId(address);
84 size_t iDiamond = GetDiamondIndex(address);
85 if (iDiamond >= diamonds.size()
86 || (address & ~CbmTofAddress::GetChannelIdBitmask()) != diamonds[iDiamond].refAddress) {
87 monitor.fDigiCalibUnknownRPC++;
88 L_(error) << "Unknown BMON digi address: " << CbmTofAddress::ToString(address) << ", iDiamond = " << iDiamond;
89 continue;
90 }
91
92 const auto& diamondPar = diamonds[iDiamond];
93 const auto& channelPar = diamondPar.chanPar[iChannel];
94
95 // Check dead time
96 const size_t iChannelGlb = fChannelOffset[iDiamond] + iChannel;
97 const double deadTime = fChannelDeadTime[iChannelGlb];
98
99 if (!std::isnan(deadTime) && digi.GetTime() <= deadTime) {
100 fChannelDeadTime[iChannelGlb] = digi.GetTime() + diamondPar.channelDeadtime;
101 monitor.fDigiDeadTimeCount++;
102 continue;
103 }
104 fChannelDeadTime[iChannelGlb] = digi.GetTime() + diamondPar.channelDeadtime;
105
106 // Create calibrated digi
107 CbmBmonDigi& pCalDigi = calDigiOut.emplace_back(digi);
108 pCalDigi.SetAddress(address);
109
110 // calibrate Digi Time
111 pCalDigi.SetTime(pCalDigi.GetTime() - channelPar.vCPTOff);
112
113 // subtract Offset
114 const double dTot = std::max(pCalDigi.GetCharge() - channelPar.vCPTotOff, 0.001);
115
116 // calibrate Digi charge (corresponds to TOF ToT)
117 pCalDigi.SetCharge(dTot * channelPar.vCPTotGain);
118
119 // walk correction
120 const std::vector<double>& walk = channelPar.vCPWalk;
121 const double dTotBinSize = (diamondPar.TOTMax - diamondPar.TOTMin) / diamondPar.numClWalkBinX;
122 int32_t iWx = std::max((int32_t)((pCalDigi.GetCharge() - diamondPar.TOTMin) / dTotBinSize), 0);
123 iWx = std::min(iWx, diamondPar.numClWalkBinX - 1);
124
125 const double dDTot = (pCalDigi.GetCharge() - diamondPar.TOTMin) / dTotBinSize - (double) iWx - 0.5;
126 double dWT = walk[iWx];
127
128 // linear interpolation to next bin
129 if (dDTot > 0) {
130 if (iWx < diamondPar.numClWalkBinX - 1) {
131 dWT += dDTot * (walk[iWx + 1] - walk[iWx]);
132 }
133 }
134 else {
135 if (0 < iWx) {
136 dWT -= dDTot * (walk[iWx - 1] - walk[iWx]);
137 }
138 }
139 pCalDigi.SetTime(pCalDigi.GetTime() - dWT); // calibrate Digi Time
140 }
141
143 // (insert-sort faster than std::sort due to pre-sorting)
144 for (std::size_t i = 1; i < calDigiOut.size(); ++i) {
145 CbmTofDigi digi = calDigiOut[i];
146 std::size_t j = i;
147 while (j > 0 && calDigiOut[j - 1].GetTime() > digi.GetTime()) {
148 calDigiOut[j] = calDigiOut[j - 1];
149 --j;
150 }
151 calDigiOut[j] = digi;
152 }
153
154 // Kept for possible unsorted input
155 // std::sort(calDigiOut.begin(), calDigiOut.end(),
156 // [](const CbmTofDigi& a, const CbmTofDigi& b) -> bool { return a.GetTime() < b.GetTime(); });
157
158 monitor.fTime = xpu::pop_timer();
159 monitor.fNumDigis = digiIn.size();
160 return result;
161}
#define L_(level)
Calibrator for the BMON digis (implementation)
Data class for a signal in the t-zero detector.
Definition CbmBmonDigi.h:31
double GetTime() const
Time.
Definition CbmBmonDigi.h:87
double GetCharge() const
Charge.
Definition CbmBmonDigi.h:98
void SetCharge(float charge)
Set the measured charge.
void SetAddress(int32_t addr)
Set the address.
void SetTime(double time)
Set the measurement time.
static std::string ToString(int32_t address)
static int32_t GetChannelId(uint32_t address)
static int32_t GetChannelIdBitmask()
Data class for expanded digital TOF information.
Definition CbmTofDigi.h:47
double GetTime() const
Inherited from CbmDigi.
Definition CbmTofDigi.h:132
Algorithm to calibrate BMon digis.
CalibrateSetup fSetup
Parameters of calibrator.
Calibrate(CalibrateSetup params)
Constructor.
std::vector< double > fChannelDeadTime
Dead time, stored for a channel.
resultType operator()(gsl::span< const CbmBmonDigi > digiIn)
Calibrates a portion of digis.
std::tuple< std::vector< CbmBmonDigi >, CalibrateMonitorData > resultType
size_t GetDiamondIndex(uint32_t address) const
Returns an index of the diamond by the address.
uint32_t fSelectionBitsOffset
Number of bits to ther right from the first bit in the selection mask.
std::vector< size_t > fChannelOffset
Channel offset: offset for the channel index of each diamond.
BMON calibration per channel.