Project
Loading...
Searching...
No Matches
ROFFinder.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 <chrono>
15#include <memory>
16#include <stdexcept>
17#include <vector>
18#include <map>
19#include <algorithm>
20#include <numeric>
21#include <fmt/format.h>
22
23#include <fairmq/Tools.h>
24#include <fairlogger/Logger.h>
25
28
29//#define ROFDEBUG 1
30
31namespace o2
32{
33namespace mch
34{
35namespace raw
36{
37
38using namespace std;
39
40static constexpr int sBcInOneADCclock = 4;
41
42//_________________________________________________________________________________________________
43ROFFinder::ROFFinder(const DataDecoder::RawDigitVector& digits, uint32_t firstTForbit) : mInputDigits(digits), mFirstTForbit(firstTForbit)
44{
45}
46
47//_________________________________________________________________________________________________
48ROFFinder::~ROFFinder() = default;
49
50//_________________________________________________________________________________________________
51void ROFFinder::process(bool dummyROFs)
52{
53 if (dummyROFs) {
54 if (!mInputDigits.empty()) {
55 mOrderedDigits.resize(mInputDigits.size());
56 // fill the ordered vector with indexes in ascending order (no time sorting)
57 std::iota(mOrderedDigits.begin(), mOrderedDigits.end(), 0);
58 mOutputROFs.emplace_back(digitTime2IR(mInputDigits[0]), 0, mInputDigits.size());
59 }
60 return;
61 }
62
63 // helper function to check if a given digit index is within the limits of the input vector
64 auto checkDigitId = [&](RawDigitId id) -> bool {
65 bool ok = id < mInputDigits.size();
66 if (!ok) {
67 LOG(error) << "Invalid digit ID " << id << " (digits vector size is " << mInputDigits.size() << ")\n";
68 }
69 return ok;
70 };
71
72 // helper function to retrieve the digit at a given index
73 auto getDigit = [&](RawDigitId id) -> const RawDigit& {
74 return mInputDigits[id];
75 };
76
77 // helper function to initialize the parameters of the next ROF
78 auto startNewROF = [&](const RawDigit& digit, int id) {
79 mFirstIdx = id;
80 mEntries = 1;
81 mIR = digitTime2IR(digit);
82 };
83
84 // fill the time-ordered digit vector
85 sortDigits();
86
87 // loop on time-ordered digits, grouping together in one ROF all those whose time stamp
88 // differs by less than 4 bunch crossings (1 ADC clock cycle)
89 for (size_t id = 0; id < mOrderedDigits.size(); id++) {
90
91 // index of the current digit in the input vector
92 RawDigitId inputId = mOrderedDigits[id];
93
94 // mak sure the index is valid
95 if (!checkDigitId(inputId)) {
96 break;
97 }
98 // get a reference to the current digit, which marks the beginning of a new ROF
99 auto& rofSeed = getDigit(inputId);
100 startNewROF(rofSeed, id);
101
102#ifdef ROFDEBUG
103 std::cout << fmt::format("starting new ROF from {} -> {}\n", id, inputId);
104#endif
105
106 for (size_t id2 = id + 1; id2 < mOrderedDigits.size(); id2++) {
107
108 // index of the current digit in the input vector
109 RawDigitId inputId2 = mOrderedDigits[id2];
110
111 if (!checkDigitId(inputId2)) {
112 break;
113 }
114 auto& digit = getDigit(inputId2);
115
116#ifdef ROFDEBUG
117 std::cout << fmt::format(" checking digit {} -> {}\n", id2, inputId2);
118#endif
119
120 auto tdiff = digit.getTime() - rofSeed.getTime();
121 if (std::abs(tdiff) < sBcInOneADCclock) {
122 mEntries += 1;
123#ifdef ROFDEBUG
124 std::cout << fmt::format(" digit {} -> {} added to current ROF\n", id2, inputId2);
125#endif
126 } else {
127 // terminate and store the current ROF and stop the inner loop
128 storeROF();
129 break;
130 }
131 }
132
133 // increment the outer loop index by the number of digits added to the ROF in the inner loop
134 id += mEntries - 1;
135 }
136
137 // terminate and store the last ROF
138 storeROF();
139}
140
141//_________________________________________________________________________________________________
142void ROFFinder::sortDigits()
143{
144 mOrderedDigits.reserve(mInputDigits.size());
145 for (size_t i = 0; i < mInputDigits.size(); i++) {
146 auto& digit = mInputDigits[i];
147 if (!digit.timeValid()) {
148#ifdef ROFDEBUG
149 LOG(error) << "Digit with invalid time, DS " << digit.info.solar << "," << digit.info.ds << "," << digit.info.chip
150 << " pad " << digit.getDetID() << "," << digit.getPadID() << " "
151 << digit.getOrbit() << " (" << mFirstTForbit << ") time "
152 << digit.getTime() << " SAMPA time " << digit.getBXTime();
153#endif
154 continue;
155 }
156
157 auto orbit = digit.getOrbit();
158 if (orbit < mFirstTForbit) {
159 continue;
160 }
161
162#ifdef ROFDEBUG
163 std::cout << "Inserting digit: "
164 << "pad " << digit.getDetID() << "," << digit.getPadID() << " "
165 << digit.getOrbit() << " " << digit.getTime() << " " << digit.getBXTime() << std::endl;
166#endif
167
168 mOrderedDigits.emplace_back(i);
169 }
170
171 auto rawDigitIdComp = [&](const RawDigitId& id1, const RawDigitId& id2) -> bool {
172 const RawDigit& d1 = mInputDigits[id1];
173 const RawDigit& d2 = mInputDigits[id2];
174 return (d1 < d2);
175 };
176 std::sort(mOrderedDigits.begin(), mOrderedDigits.end(), rawDigitIdComp);
177}
178
179//_________________________________________________________________________________________________
181{
183 auto time = digit.getTime();
184 auto firstOrbit = mFirstTForbit;
185
186 // make sure the interaction record is not initialized with negative BC values
187 while (time < 0) {
188 time += BCINORBIT;
189 firstOrbit -= 1;
190 }
191
192 uint32_t orbit = time / BCINORBIT + firstOrbit;
193 int32_t bc = time % BCINORBIT;
195}
196
197//_________________________________________________________________________________________________
198void ROFFinder::storeROF()
199{
200 if (mEntries > 0) {
201 mOutputROFs.emplace_back(mIR, mFirstIdx, mEntries, sBcInOneADCclock);
202 }
203}
204
205//_________________________________________________________________________________________________
207{
208 static constexpr size_t sizeOfDigit = sizeof(o2::mch::Digit);
209
210#ifdef ROFDEBUG
212#endif
213
214 bufSize = mOrderedDigits.size() * sizeOfDigit;
215 o2::mch::Digit* buf = reinterpret_cast<o2::mch::Digit*>(malloc(bufSize));
216 if (!buf) {
217 bufSize = 0;
218 return nullptr;
219 }
220
221 o2::mch::Digit* p = buf;
222 for (auto& id : mOrderedDigits) {
223 const auto& d = mInputDigits[id];
224 memcpy(p, &(d.digit), sizeOfDigit);
225 p += 1;
226 }
227
228 return reinterpret_cast<char*>(buf);
229}
230
231//_________________________________________________________________________________________________
233{
234 static constexpr size_t sizeOfROFRecord = sizeof(o2::mch::ROFRecord);
235
236#ifdef ROFDEBUG
238#endif
239
240 bufSize = mOutputROFs.size() * sizeOfROFRecord;
241 o2::mch::ROFRecord* buf = reinterpret_cast<o2::mch::ROFRecord*>(malloc(bufSize));
242 if (!buf) {
243 bufSize = 0;
244 return nullptr;
245 }
246
248 for (size_t i = 0; i < mOutputROFs.size(); i++) {
249 auto& rof = mOutputROFs[i];
250 memcpy(p, &(rof), sizeOfROFRecord);
251 p += 1;
252 }
253
254 return reinterpret_cast<char*>(buf);
255}
256
257//_________________________________________________________________________________________________
259{
260 // number of bunch crossings in one orbit
261 static const int32_t BCINORBIT = o2::constants::lhc::LHCMaxBunches;
262
263 bool result = true;
264 for (size_t i = 1; i < mOutputROFs.size(); i++) {
265 const auto& rof = mOutputROFs[i];
266 const auto& rofPrev = mOutputROFs[i - 1];
267 int64_t delta = rof.getBCData().differenceInBC(rofPrev.getBCData());
268 if (rof.getBCData() < rofPrev.getBCData()) {
269 LOG(error) << "Non-monotonic ROFs encountered:";
270 LOG(error) << fmt::format("ROF1 {}-{} {},{} ", rofPrev.getFirstIdx(), rofPrev.getLastIdx(),
271 rofPrev.getBCData().orbit, rofPrev.getBCData().bc)
272 << fmt::format("ROF2 {}-{} {},{}", rof.getFirstIdx(), rof.getLastIdx(),
273 rof.getBCData().orbit, rof.getBCData().bc);
274 result = false;
275 }
276 if ((delta % 4) != 0) {
277 LOG(error) << "Mis-aligned ROFs encountered:";
278 LOG(error) << fmt::format("ROF1 {}-{} {},{} ", rofPrev.getFirstIdx(), rofPrev.getLastIdx(),
279 rofPrev.getBCData().orbit, rofPrev.getBCData().bc)
280 << fmt::format("ROF2 {}-{} {},{}", rof.getFirstIdx(), rof.getLastIdx(),
281 rof.getBCData().orbit, rof.getBCData().bc);
282 result = false;
283 }
284 }
285 return result;
286}
287
288//_________________________________________________________________________________________________
290{
291 for (size_t i = 0; i < mOutputROFs.size(); i++) {
292 auto& rof = mOutputROFs[i];
293 for (int j = rof.getFirstIdx() + 1; j <= rof.getLastIdx(); j++) {
294 auto id = mOrderedDigits[j];
295 auto idPrev = mOrderedDigits[j - 1];
296 const auto& digit = mInputDigits[id];
297 const auto& digitPrev = mInputDigits[idPrev];
298 if (digit.getTime() != digitPrev.getTime()) {
299 LOG(error) << "Mis-aligned digits encountered:";
300 LOG(error) << fmt::format("TIME1 {} ", digitPrev.getTime()) << fmt::format("TIME2 {}", digit.getTime());
301 return false;
302 }
303 }
304 }
305 return true;
306}
307
308//_________________________________________________________________________________________________
309std::optional<DataDecoder::RawDigit> ROFFinder::getOrderedDigit(int i)
310{
311 if (i < 0 || i >= mOrderedDigits.size()) {
312 return std::nullopt;
313 }
314
315 auto id = mOrderedDigits[i];
316 if (id >= mInputDigits.size()) {
317 return std::nullopt;
318 }
319
320 return mInputDigits[id];
321}
322
323//_________________________________________________________________________________________________
325{
326 std::cout << "OUTPUT DIGITS:\n";
327 for (size_t i = 0; i < mOrderedDigits.size(); i++) {
328 const auto id = mOrderedDigits[i];
329 const auto& digit = mInputDigits[id];
330 const auto& d = digit.digit;
331 const auto& t = digit.info;
332
333 if (d.getPadID() < 0) {
334 continue;
335 }
337 bool bending = segment.isBendingPad(d.getPadID());
338 float X = segment.padPositionX(d.getPadID());
339 float Y = segment.padPositionY(d.getPadID());
340 uint32_t orbit = t.orbit;
341 uint32_t bunchCrossing = t.bunchCrossing;
342 uint32_t sampaTime = t.sampaTime;
343 auto tfTime = digit.getTime();
344
345 int iROF = -1;
346 for (size_t j = 0; j < mOutputROFs.size(); j++) {
347 const auto& rof = mOutputROFs[j];
348 if (rof.getFirstIdx() <= i && rof.getLastIdx() >= i) {
349 iROF = j;
350 }
351 }
352 std::cout << fmt::format(" DIGIT [{} -> {}] ROF {} DE {:4d} PAD {:5d} ADC {:6d} TIME {} ({} {} {:4d} {})",
353 i, id, iROF, d.getDetID(), d.getPadID(), d.getADC(), tfTime, orbit, bunchCrossing, sampaTime, t.getBXTime());
354 std::cout << fmt::format("\tC {} PAD_XY {:+2.2f} , {:+2.2f}\n", (bending ? (int)0 : (int)1), X, Y);
355 }
356}
357
358//_________________________________________________________________________________________________
360{
361 std::cout << "OUTPUT ROFs:\n";
362 for (size_t i = 0; i < mOutputROFs.size(); i++) {
363 auto& rof = mOutputROFs[i];
364 std::cout << fmt::format(" ROF {} {}-{} {},{}\n", i, rof.getFirstIdx(), rof.getLastIdx(),
365 rof.getBCData().orbit, rof.getBCData().bc);
366 }
367}
368
369} // namespace raw
370} // namespace mch
371} // namespace o2
uint64_t orbit
Definition RawEventData.h:6
uint64_t bc
Definition RawEventData.h:5
int16_t time
Definition RawEventData.h:4
int32_t i
Header to collect LHC related constants.
Class to group the fired pads according to their time stamp.
uint32_t j
Definition RawData.h:0
MCH digit implementation.
Definition Digit.h:31
A Segmentation lets you find pads of a detection element and then inspect those pads.
std::vector< RawDigit > RawDigitVector
ROFFinder(const DataDecoder::RawDigitVector &digits, uint32_t firstTForbit)
Definition ROFFinder.cxx:43
std::optional< DataDecoder::RawDigit > getOrderedDigit(int i)
char * saveROFRsToBuffer(size_t &bufSize)
char * saveDigitsToBuffer(size_t &bufSize)
void process(bool dummyROFs=false)
Definition ROFFinder.cxx:51
o2::InteractionRecord digitTime2IR(const RawDigit &digit)
GLuint segment
Definition glcorearb.h:4945
GLuint64EXT * result
Definition glcorearb.h:5662
GLuint GLsizei bufSize
Definition glcorearb.h:790
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition glcorearb.h:2514
GLuint id
Definition glcorearb.h:650
constexpr int LHCMaxBunches
O2MCHMAPPINGIMPL3_EXPORT const Segmentation & segmentation(int detElemId)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
Defining DataPointCompositeObject explicitly as copiable.
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< Digit > digits