Project
Loading...
Searching...
No Matches
ROFTimeClusterFinder.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
13
14#include <iostream>
15#include <fmt/format.h>
16#include "Framework/Logger.h"
17
18namespace o2
19{
20namespace mch
21{
22
23using namespace std;
24
25//_________________________________________________________________________________________________
26
27ROFTimeClusterFinder::ROFTimeClusterFinder(gsl::span<const o2::mch::ROFRecord> rofs,
28 gsl::span<const o2::mch::Digit> digits,
29 uint32_t timeClusterSize, uint32_t nBins, bool improvePeakSearch, bool debug)
30 : mTimeClusterSize(timeClusterSize),
31 mNbinsInOneWindow(nBins),
32 mBinWidth(timeClusterSize / nBins),
33 mNbinsInOneTF(0),
34 mIsGoodDigit(createDigitFilter(20, true, true)),
35 mImprovePeakSearch(improvePeakSearch),
36 mTimeBins{},
37 mLastSavedTimeBin(-1),
38 mInputROFs(rofs),
39 mDigits(digits),
40 mOutputROFs{},
41 mDebug(debug)
42{
43}
44
45//_________________________________________________________________________________________________
46
47void ROFTimeClusterFinder::initTimeBins()
48{
49 static constexpr uint32_t maxNTimeBins = 1e7;
50
51 mTimeBins.clear();
52 mNbinsInOneTF = 0;
53
54 if (mInputROFs.empty()) {
55 return;
56 }
57
58 // initialize the time bins vector
59 o2::InteractionRecord mFirstIR = mInputROFs.front().getBCData();
60 auto tfSize = mInputROFs.back().getBCData().differenceInBC(mFirstIR);
61 mNbinsInOneTF = tfSize / mBinWidth + 1;
62 if (mNbinsInOneTF > maxNTimeBins) {
63 LOGP(alarm, "Number of time bins exceeding the limit");
64 mNbinsInOneTF = maxNTimeBins;
65 }
66 mTimeBins.resize(mNbinsInOneTF);
67
68 // store the number of digits in each bin
69 int64_t previousROFbc = -1;
70 for (size_t iRof = 0; iRof < mInputROFs.size(); iRof++) {
71 const auto& rof = mInputROFs[iRof];
72 const auto& ir = rof.getBCData();
73 auto rofBc = ir.differenceInBC(mFirstIR);
74 auto binIdx = rofBc / mBinWidth;
75
76 // sanity checks: ROFs must be ordered in time and not be empty
77 if (rofBc <= previousROFbc || rofBc > tfSize) {
78 LOGP(alarm, "Wrong ROF ordering");
79 break;
80 }
81 previousROFbc = rofBc;
82 if (rof.getNEntries() < 1) {
83 LOGP(alarm, "Empty ROF");
84 break;
85 }
86
87 // stop here if the number of bins exceeds the limit
88 if (binIdx >= mNbinsInOneTF) {
89 break;
90 }
91
92 auto& timeBin = mTimeBins[binIdx];
93
94 if (timeBin.mFirstIdx < 0) {
95 timeBin.mFirstIdx = iRof;
96 }
97 timeBin.mLastIdx = iRof;
98
99 int nDigitsPS = 0;
100 if (mImprovePeakSearch) {
101 auto rofDigits = mDigits.subspan(rof.getFirstIdx(), rof.getNEntries());
102 for (auto& digit : rofDigits) {
103 if (mIsGoodDigit(digit)) {
104 nDigitsPS += 1;
105 }
106 }
107 } else {
108 nDigitsPS = rof.getNEntries();
109 }
110 timeBin.mNDigitsPS += nDigitsPS;
111 }
112
113 if (mDebug) {
114 std::cout << "Peak search histogram:" << std::endl;
115 for (int32_t i = 0; i < mNbinsInOneTF; i++) {
116 if (mTimeBins[i].mFirstIdx >= 0) {
117 auto nDigits = mInputROFs[mTimeBins[i].mLastIdx].getLastIdx() - mInputROFs[mTimeBins[i].mFirstIdx].getFirstIdx() + 1;
118 std::cout << fmt::format("bin {}: {}/{}", i, mTimeBins[i].mNDigitsPS, nDigits) << std::endl;
119 }
120 }
121 }
122}
123
124//_________________________________________________________________________________________________
125
126int32_t ROFTimeClusterFinder::getNextPeak()
127{
128 int32_t sPadding = mNbinsInOneWindow / 2;
129
130 if (mDebug) {
131 std::cout << "Searching peak from " << mLastSavedTimeBin + 1 << std::endl;
132 }
133
134 // loop over the bins and search for local maxima
135 // a local maxima is defined as a bin tht is higher than all the surrounding 4 bins (2 below and 2 above)
136 for (int32_t i = mLastSavedTimeBin + sPadding + 1; i < mNbinsInOneTF; i++) {
137 auto& peak = mTimeBins[i];
138 if (peak.empty()) {
139 continue;
140 }
141
142 bool found{true};
143 // the peak must be strictly higher than previous bins
144 for (int j = i - sPadding; j < i; j++) {
145 if (j >= 0 && peak <= mTimeBins[j]) {
146 found = false;
147 break;
148 }
149 }
150 // the peak must be higher than or equal to next bins
151 for (int j = i + 1; j <= i + sPadding; j++) {
152 if (j < mNbinsInOneTF && peak < mTimeBins[j]) {
153 found = false;
154 break;
155 }
156 }
157
158 if (!found) {
159 continue;
160 }
161
162 if (mDebug) {
163 auto nDigits = mInputROFs[peak.mLastIdx].getLastIdx() - mInputROFs[peak.mFirstIdx].getFirstIdx() + 1;
164 std::cout << fmt::format("new peak found at bin {}, entries = {}/{}", i, peak.mNDigitsPS, nDigits) << std::endl;
165 }
166
167 return i;
168 }
169 return -1;
170}
171
172//_________________________________________________________________________________________________
173
174void ROFTimeClusterFinder::storeROF(int32_t firstBin, int32_t lastBin)
175{
176 if (mDebug) {
177 std::cout << fmt::format("Storing ROF from bin range [{},{}]", firstBin, lastBin) << std::endl;
178 }
179
180 if (firstBin < 0) {
181 firstBin = 0;
182 }
183 if (lastBin >= mNbinsInOneTF) {
184 lastBin = mNbinsInOneTF - 1;
185 }
186
187 int32_t rofFirstIdx{-1};
188 int32_t rofLastIdx{-1};
189 for (int32_t j = firstBin; j <= lastBin; j++) {
190 auto& timeBin = mTimeBins[j];
191 if (timeBin.mFirstIdx < 0) {
192 continue;
193 }
194
195 if (rofFirstIdx < 0) {
196 rofFirstIdx = timeBin.mFirstIdx;
197 };
198 rofLastIdx = timeBin.mLastIdx;
199
200 if (mDebug) {
201 auto size = timeBin.mLastIdx - timeBin.mFirstIdx + 1;
202 auto nDigits = mInputROFs[timeBin.mLastIdx].getLastIdx() - mInputROFs[timeBin.mFirstIdx].getFirstIdx() + 1;
203 std::cout << fmt::format(" bin {}: firstIdx={} size={} ndigits={}/{}", j, timeBin.mFirstIdx, size, timeBin.mNDigitsPS, nDigits) << std::endl;
204 }
205 }
206
207 // a new time ROF is stored only if there are some digit ROFs in the interval
208 if (rofFirstIdx >= 0) {
209 // get the indexes of the first and last ROFs in this time cluster, and the corresponding interaction records
210 auto& firstRofInCluster = mInputROFs[rofFirstIdx];
211 auto& irFirst = firstRofInCluster.getBCData();
212 auto& lastRofInCluster = mInputROFs[rofLastIdx];
213 auto& irLast = lastRofInCluster.getBCData();
214
215 // get the index of the first digit and the number of digits in this time cluster
216 auto firstDigitIdx = firstRofInCluster.getFirstIdx();
217 auto nDigits = lastRofInCluster.getLastIdx() - firstDigitIdx + 1;
218
219 // compute the width in BC units of the time-cluster ROF
220 auto bcDiff = irLast.differenceInBC(irFirst);
221 auto bcWidth = bcDiff + lastRofInCluster.getBCWidth();
222
223 // create a ROF that includes all the digits in this time cluster
224 mOutputROFs.emplace_back(irFirst, firstDigitIdx, nDigits, bcWidth);
225
226 if (mDebug) {
227 std::cout << fmt::format("new ROF stored: firstDigitIdx={} size={} bcWidth={}", firstDigitIdx, nDigits, bcWidth) << std::endl;
228 }
229 }
230
231 mLastSavedTimeBin = lastBin;
232}
233
234//_________________________________________________________________________________________________
235
237{
238 if (mDebug) {
239 std::cout << "\n\n==================\n[ROFTimeClusterFinder] processing new TF\n"
240 << std::endl;
241 }
242
243 initTimeBins();
244 mOutputROFs.clear();
245
246 mLastSavedTimeBin = -1;
247 int32_t peak{-1};
248 while ((peak = getNextPeak()) >= 0) {
249 int32_t peakStart = peak - mNbinsInOneWindow / 2;
250 int32_t peakEnd = peakStart + mNbinsInOneWindow - 1;
251
252 // peak found, we add the corresponding rof(s)
253 // first we fill the gap between the last peak and the current one, if needed
254 if (mDebug) {
255 std::cout << fmt::format("peakStart={} mLastSavedTimeBin={}", peakStart, mLastSavedTimeBin) << std::endl;
256 }
257 while ((peakStart - mLastSavedTimeBin) > 1) {
258 int32_t firstBin = mLastSavedTimeBin + 1;
259 int32_t lastBin = firstBin + mNbinsInOneWindow - 1;
260 if (lastBin >= peakStart) {
261 lastBin = peakStart - 1;
262 }
263
264 storeROF(firstBin, lastBin);
265 }
266 storeROF(peakStart, peakEnd);
267 }
268}
269
270//_________________________________________________________________________________________________
271
273{
274 static constexpr size_t sizeOfROFRecord = sizeof(o2::mch::ROFRecord);
275
276 if (mDebug) {
278 }
279
280 bufSize = mOutputROFs.size() * sizeOfROFRecord;
281 o2::mch::ROFRecord* buf = reinterpret_cast<o2::mch::ROFRecord*>(malloc(bufSize));
282 if (!buf) {
283 bufSize = 0;
284 return nullptr;
285 }
286
288 for (size_t i = 0; i < mOutputROFs.size(); i++) {
289 auto& rof = mOutputROFs[i];
290 memcpy(p, &(rof), sizeOfROFRecord);
291 p += 1;
292 }
293
294 return reinterpret_cast<char*>(buf);
295}
296
297//_________________________________________________________________________________________________
298
300{
301 for (size_t i = 0; i < mInputROFs.size(); i++) {
302 auto& rof = mInputROFs[i];
303 const auto ir = rof.getBCData();
304 std::cout << fmt::format(" ROF {} RANGE {}-{} SIZE {} IR {}-{},{}\n", i, rof.getFirstIdx(), rof.getLastIdx(),
305 rof.getNEntries(), ir.orbit, ir.bc, ir.toLong());
306 }
307}
308
309//_________________________________________________________________________________________________
310
312{
313 for (size_t i = 0; i < mOutputROFs.size(); i++) {
314 auto& rof = mOutputROFs[i];
315 std::cout << fmt::format(" ROF {} RANGE {}-{} SIZE {} IR {}-{},{}\n", i, rof.getFirstIdx(), rof.getLastIdx(),
316 rof.getNEntries(), rof.getBCData().orbit, rof.getBCData().bc, rof.getBCData().toLong());
317 }
318}
319
320} // namespace mch
321} // namespace o2
int32_t i
Class to group the fired pads according to their time stamp.
uint32_t j
Definition RawData.h:0
std::ostringstream debug
char * saveROFRsToBuffer(size_t &bufSize)
stores the output ROFs into a flat memory buffer
ROFTimeClusterFinder(gsl::span< const o2::mch::ROFRecord > rofs, gsl::span< const o2::mch::Digit > digits, uint32_t timeClusterSize, uint32_t nBins, bool improvePeakSearch, bool debug)
void process()
process the digit ROFs and create the time clusters
GLsizeiptr size
Definition glcorearb.h:659
GLuint GLsizei bufSize
Definition glcorearb.h:790
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition glcorearb.h:2514
DigitFilter createDigitFilter(uint32_t minADC, bool rejectBackground, bool selectSignal, const StatusMap &statusMap={}, uint32_t statusMask=0)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
Defining DataPointCompositeObject explicitly as copiable.
uint32_t orbit
LHC orbit.
uint16_t bc
bunch crossing ID of interaction
int64_t differenceInBC(const InteractionRecord &other) const
o2::InteractionRecord ir(0, 0)
std::vector< Digit > digits
const auto irLast
const auto & irFirst