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{
182 constexpr int BCINORBIT = o2::constants::lhc::LHCMaxBunches;
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;
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;
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
o2::raw::RawFileWriter * raw
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error First event to Number of events to Number of iterations to Number of iterations to Number of initial iterations excluded from const char Directory with events to Events directory is and not inside events d
configStandalone Reconstruction rec_tpc multiplier for the combined cluster track error during track following area in cm for the search of for z only used if decrease removal by when above this local occupancy rowx Shift of TPC revert cluster flag edge bit distance to edge exceeds this ZOffset for secondary multiple of radius max P of electron K BB bands crossing max P of electron p BB bands crossing max P of electron d BB bands crossing max P of electron t BB bands crossing min accepted dEdxMaxTPC of the track Additive extra cluster error for Y2 if edge flag set Additive extra cluster error for Y2 if single set Additive extra cluster error for Y2 if or single set Additive extra cluster error for Z2 if or single set Extra errors to add to track when crossing depending on addErrorsCECrossing Inner portion of y range in sector that is not used in searching for extrapolated track candidates factor2YS for track merging factor2K for track merging Margin in cm of Y position when rejecting edge clusters based on uncorrected track Y Max fraction of shared clusters for tracklet Except pad from cluster finding if total number of charges in a fragment is above this Except pad from cluster finding if number of consecutive charges in a fragment is above this Threshold where a timebin is considered disabling the noisy pad check for that pad Treat signal above this minimum as saturated Smoothing factor for the exponential Highly Ionising Particle tail filter Number of timebins to use for the averaging Add additional custom track errors when crossing relative as fraction of Do N fit passes in final fit of< 0:reject at max -n hits") AddOptionRTC(rejectIFCLowRadiusCluster, uint8_t, 1, "", 0, "Reject clusters that get the IFC mask error during refit") AddOptionRTC(dEdxTruncLow, uint8_t, 2, "", 0, "Low truncation threshold, fraction of 128") AddOptionRTC(dEdxTruncHigh, uint8_t, 77, "", 0, "High truncation threshold, fraction of 128") AddOptionRTC(extrapolationTracking, int8_t, 1, "", 0, "Enable Extrapolation Tracking(prolong tracks to adjacent sectors to find short segments)") AddOptionRTC(disableRefitAttachment, uint8_t, 0, "", 0, "Bitmask to disable certain attachment steps during refit(1:attachment, 2:propagation, 4:loop following, 8:mirroring)") AddOptionRTC(rejectionStrategy, uint8_t, o2::gpu::GPUSettings::RejectionStrategyA, "", 0, "Enable rejection of TPC clusters for compression(0=no, 1=strategy A, 2=strategy B)") AddOptionRTC(mergeLoopersAfterburner, uint8_t, 1, "", 0, "Run afterburner for additional looper merging") AddOptionRTC(compressionTypeMask, uint8_t, o2::gpu::GPUSettings::CompressionFull, "", 0, "TPC Compression mode bits(1=truncate charge/width LSB, 2=differences, 4=track-model)") AddOptionRTC(compressionSortOrder, uint8_t, o2::gpu::GPUSettings::SortTime, "", 0, "Sort order of TPC compression(0=time, 1=pad, 2=Z-time-pad, 3=Z-pad-time, 4=no sorting(use incoming order))") AddOptionRTC(sigBitsCharge, uint8_t, 4, "", 0, "Number of significant bits for TPC cluster charge in compression mode 1") AddOptionRTC(sigBitsWidth, uint8_t, 3, "", 0, "Number of significant bits for TPC cluster width in compression mode 1") AddOptionRTC(dropLoopers, uint8_t, 0, "", 0, "Drop looping tracks starting from second loop") AddOptionRTC(mergerInterpolateErrors, uint8_t, 1, "", 0, "Use interpolation instead of extrapolation for chi2 based cluster rejection") AddOptionRTC(mergerInterpolateRejectAlsoOnCurrentPosition, uint8_t, 1, "", 0, "When using mergerInterpolateErrors, reject based on chi2 twice computed with interpolated and current track position starting from NDF > mergerNonInterpolateRejectMinNDF Merge tracks accross the central electrode Enable PID response Add sub threshold clusters in TPC dEdx computation OR mask of TPC flags that will reject the cluster in alternative dEdx Reject edge clusters based on uncorrected track Y during track fit Increase decrease removal by when on this number of pads from the edge h configStandalone Reconstruction rec_trd Max chi2 for TRD tracklets to be matched to a track Chi2 cut for strict matching mode Number of sigmas for ITS TPC track time error estimate Addition to search road around track prolongation along Y in cm Optimal tracklet rphi resolution in maximum chi2 per attached tracklet for TRD tracks take into account the full likelihood of the slope including exponential tails Tracks with less attached tracklets are discarded after the tracking Post trigger Pile up integration time in BCs fits all iterations but the last one in projections Use material lookup table for TPC refit Apply workarounds to avoid cyclic merge should not be needed tpc dyn configStandalone Processing proc_rtc Replace constant variables static by constexpr expressions Compile RTC in deterministic with NO_FAST_MATH flags and GPUCA_DETERMINISTIC_MODE define Use RTC to optimize GPU code h configStandalone Processing proc_rtctech Use a file lock to serialize access to the cache folder int32_t
char error[CURL_ERROR_SIZE]
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)
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
O2MCHMAPPINGIMPL3_EXPORT const Segmentation & segmentation(int detElemId)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
void * malloc(size_t n)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< Digit > digits