Project
Loading...
Searching...
No Matches
WindowFiller.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 "TCanvas.h"
15#include "TFile.h"
16#include "TH1F.h"
17#include "TH2F.h"
18#include "TLeaf.h"
19#include "TMath.h"
20#include "TProfile2D.h"
21#include "TRandom.h"
22#include <algorithm>
23#include <cassert>
24#include <fairlogger/Logger.h>
26
27using namespace o2::tof;
28
30
31// How data acquisition works in real data
32/*
33 |<----------- 1 orbit ------------->|
34 ------|-----------|-----------|-----------|------
35 ^ ^ ^ ^ when triggers happen
36 |<--- latency ---|
37 |<- matching1->|
38 |<- matching2->|
39 |<- matching3->|
40 |<>| = overlap between two consecutive matching
41
42Norbit = number of orbits elapsed
43Nbunch = bunch in the current orbit (0:3563)
44Ntdc = number of tdc counts within the matching window --> for 1/3 orbit (0:3649535)
45
46raw time = trigger time (Norbit and Nbunch) - latency window + TDC(Ntdc)
47 */
48
49// What we implemented here (so far)
50/*
51 |<----------- 1 orbit ------------->|
52 ------|-----------|-----------|-----------|------
53 |<- matching1->|
54 |<- matching2->|
55 |<- matching3->|
56 |<>| = overlap between two consecutive matching windows
57
58- NO OVERLAP between two consecutive windows at the moment (to be implemented)
59- NO LATENCY WINDOW (we manage it during raw encoding/decoding) then digits already corrected
60
61NBC = Number of bunch since timeframe beginning = Norbit*3564 + Nbunch
62Ntdc = here within the current BC -> (0:1023)
63
64digit time = NBC*1024 + Ntdc
65 */
66
68{
69
70 // method to initialize the parameters neede to digitize and the array of strip objects containing
71 // the digits belonging to a strip
72
73 for (Int_t i = 0; i < Geo::NSTRIPS; i++) {
74 for (Int_t j = 0; j < MAXWINDOWS; j++) {
75 mStrips[j].emplace_back(i);
76 if (j < MAXWINDOWS - 1) {
77 mStripsNext[j] = &(mStrips[j + 1]);
78 }
79 }
80 }
81}
82//______________________________________________________________________
84{
87
88 for (Int_t i = 0; i < MAXWINDOWS; i++) {
89 for (Int_t j = 0; j < Geo::NSTRIPS; j++) {
90 mStrips[i][j].clear();
91 }
92 }
93 mFutureDigits.clear();
94
95 mStripsCurrent = &(mStrips[0]);
96 mStripsNext[0] = &(mStrips[1]);
97
98 mDigitsPerTimeFrame.clear();
99 mReadoutWindowData.clear();
101
103
104 mFirstIR.bc = 0;
105 mFirstIR.orbit = 0;
106}
107
108//______________________________________________________________________
109void WindowFiller::fillDigitsInStrip(std::vector<Strip>* strips, int channel, int tdc, int tot, uint64_t nbc, UInt_t istrip, uint32_t triggerorbit, uint16_t triggerbunch)
110{
111 if (channel > -1) { // check channel validity
112 (*strips)[istrip].addDigit(channel, tdc, tot, nbc, 0, triggerorbit, triggerbunch);
113 }
114}
115//______________________________________________________________________
116void WindowFiller::addCrateHeaderData(unsigned long orbit, int crate, int32_t bc, uint32_t eventCounter)
117{
118 if (orbit < mFirstIR.orbit) {
119 return;
120 }
122
123 orbit *= Geo::NWINDOW_IN_ORBIT; // move from orbit to N readout window
124 orbit += (bc + 100) / Geo::BC_IN_WINDOW; // select readout window in the orbit according to the BC (100 shift to avoid border effects)
125
126 if (mCrateHeaderData.size() < orbit + 1) {
127 mCrateHeaderData.resize(orbit + 1);
128 }
129
130 mCrateHeaderData[orbit].bc[crate] = bc;
131 mCrateHeaderData[orbit].eventCounter[crate] = eventCounter;
132}
133//______________________________________________________________________
135{
136 if (mContinuous) {
137 digits.clear();
138 }
139
140 // filling the digit container doing a loop on all strips
141 for (auto& strip : *mStripsCurrent) {
142 strip.fillOutputContainer(digits);
143 }
144
145 if (mContinuous) {
146 int first = mDigitsPerTimeFrame.size();
147 int ne = digits.size();
148 ReadoutWindowData info(first, ne);
149 int orbit_shift = mReadoutWindowData.size() / Geo::NWINDOW_IN_ORBIT;
150
152
153 int bc_shift = -1;
154 int eventcounter = -1;
155 int ncratesSeen = 0;
156 if (mReadoutWindowData.size() >= mCrateHeaderData.size()) {
157 bc_shift = (mReadoutWindowData.size() % Geo::NWINDOW_IN_ORBIT) * Geo::BC_IN_WINDOW; // insert default value
158 eventcounter = mReadoutWindowData.size() % 4096;
159 for (int icrate = 0; icrate < Geo::kNCrate; icrate++) {
160 info.setEmptyCrate(icrate);
161 }
162 } else {
163 unsigned long irow = mReadoutWindowData.size();
164 for (int icrate = 0; icrate < Geo::kNCrate; icrate++) {
165 if (mCrateHeaderData[irow].bc[icrate] == -1) { // crate not read
166 info.setEmptyCrate(icrate);
167 continue;
168 } else {
169 mDigitHeader.crateSeen(icrate);
170 }
171 ncratesSeen++;
172
173 if (bc_shift == -1 || mCrateHeaderData[irow].bc[icrate] < bc_shift) {
174 bc_shift = mCrateHeaderData[irow].bc[icrate];
175 }
176 if (eventcounter == -1 || mCrateHeaderData[irow].eventCounter[icrate] < eventcounter) {
177 eventcounter = mCrateHeaderData[irow].eventCounter[icrate];
178 }
179 }
180
181 mDigitHeader.numCratesSeen(ncratesSeen);
182
183 if (bc_shift == -1) {
184 bc_shift = (mReadoutWindowData.size() % Geo::NWINDOW_IN_ORBIT) * Geo::BC_IN_WINDOW; // insert default value
185 }
186 if (eventcounter == -1) {
187 eventcounter = mReadoutWindowData.size() % 4096; // insert default value
188 }
189 }
190
191 info.setBCData(mFirstIR.orbit + orbit_shift, mFirstIR.bc + bc_shift);
192 info.setEventCounter(eventcounter);
193 int firstPattern = mPatterns.size();
194 int npatterns = 0;
195
196 // check if patterns are in the current row
197 unsigned int initrow = mFirstIR.orbit * Geo::NWINDOW_IN_ORBIT;
198 for (std::vector<PatternData>::reverse_iterator it = mCratePatterns.rbegin(); it != mCratePatterns.rend(); ++it) {
199 unsigned int irow = it->row;
200 // printf("pattern row=%ld (%u - %u) current=%ld\n",irow - initrow,irow,initrow,mReadoutWindowCurrent);
201
202 if (irow - initrow > mReadoutWindowCurrent) {
203 break;
204 }
205
206 if (irow - initrow < mReadoutWindowCurrent) { // this should not happen
207 LOG(error) << "One pattern skipped because appears to occur early of the current row " << it->row << " < " << mReadoutWindowCurrent << " ?!";
208 } else {
209 uint32_t cpatt = it->pattern;
210 auto dpatt = reinterpret_cast<compressed::Diagnostic_t*>(&cpatt);
211 uint8_t slot = dpatt->slotID;
212 uint32_t cbit = 1;
213
214 mPatterns.push_back(slot + 28); // add slot
215 info.addedDiagnostic(it->icrate);
216 npatterns++;
217
218 for (int ibit = 0; ibit < 28; ibit++) {
219 if (dpatt->faultBits & cbit) {
220 mPatterns.push_back(ibit); // add bit error
221 info.addedDiagnostic(it->icrate);
222 npatterns++;
223 }
224 cbit <<= 1;
225 }
226 // uint8_t w1 = cpatt & 0xff;
227 // uint8_t w2 = (cpatt >> 8) & 0xff;
228 // uint8_t w3 = (cpatt >> 16) & 0xff;
229 // uint8_t w4 = (cpatt >> 24) & 0xff;
231 // mPatterns.push_back(w1);
232 // info.addedDiagnostic(it->icrate);
233 // npatterns++;
234 // mPatterns.push_back(w2);
235 // info.addedDiagnostic(it->icrate);
236 // npatterns++;
237 // mPatterns.push_back(w3);
238 // info.addedDiagnostic(it->icrate);
239 // npatterns++;
240 // mPatterns.push_back(w4);
241 // info.addedDiagnostic(it->icrate);
242 // npatterns++;
243 }
244 mCratePatterns.pop_back();
245 }
246
247 info.setFirstEntryDia(firstPattern);
248 info.setNEntriesDia(npatterns);
249 if (digits.size() || npatterns) {
250 mDigitsPerTimeFrame.insert(mDigitsPerTimeFrame.end(), digits.begin(), digits.end());
251 mReadoutWindowDataFiltered.push_back(info);
252 }
253 mReadoutWindowData.push_back(info);
254 }
255
256 // switch to next mStrip after flushing current readout window data
260 }
262 int k = mIcurrentReadoutWindow + 1;
263 for (Int_t i = 0; i < MAXWINDOWS - 1; i++) {
264 if (k >= MAXWINDOWS) {
265 k = 0;
266 }
267 mStripsNext[i] = &(mStrips[k]);
268 k++;
269 }
270
272}
273//______________________________________________________________________
275{ // flush all residual buffered data
276 // TO be implemented
277
278 // sort patterns (diagnostic words) in time
279 std::sort(mCratePatterns.begin(), mCratePatterns.end(),
280 [](PatternData a, PatternData b) { if(a.row == b.row) { return a.icrate > b.icrate; } else { return a.row > b.row; } });
281
282 for (Int_t i = 0; i < MAXWINDOWS; i++) {
283 int n = 0;
284 for (int j = 0; j < mStrips[i].size(); j++) {
285 n += ((mStrips[i])[j]).getNumberOfDigits();
286 }
287 }
288
289 checkIfReuseFutureDigitsRO();
290
291 if (!mContinuous) {
292 fillOutputContainer(digits);
293 } else {
294 for (Int_t i = 0; i < MAXWINDOWS; i++) {
295 fillOutputContainer(digits); // fill all windows which are before (not yet stored) of the new current one
296 checkIfReuseFutureDigitsRO();
297 }
298
299 int round = 0;
300 while (mFutureDigits.size()) {
301 round++;
302 fillOutputContainer(digits); // fill all windows which are before (not yet stored) of the new current one
303 checkIfReuseFutureDigitsRO();
304 }
305
307
308 for (Int_t i = 0; i < MAXWINDOWS; i++) {
309 if (mReadoutWindowData.size() < nwindowperTF) {
310 fillOutputContainer(digits); // fill last readout windows
311 }
312 }
313
314 // check that all orbits are complete in terms of number of readout windows
315 while ((mReadoutWindowData.size() % nwindowperTF)) {
316 fillOutputContainer(digits); // fill windows without digits to complete all orbits in the last TF
317 }
318 }
319}
320//______________________________________________________________________
322{
323 if (!mFutureDigits.size()) {
324 return;
325 }
326
327 // check if digits stored very far in future match the new readout windows currently available
328 if (mFutureToBeSorted) {
329 // sort digit in descending BC order: kept last as first
330 std::sort(mFutureDigits.begin(), mFutureDigits.end(),
331 [](o2::tof::Digit a, o2::tof::Digit b) { return a.getBC() > b.getBC(); });
332 mFutureToBeSorted = false;
333 }
334
335 int idigit = mFutureDigits.size() - 1;
336
337 int bclimit = 999999; // if bc is larger than this value stop the search in the next loop since bc are ordered in descending order
338
339 for (std::vector<Digit>::reverse_iterator digit = mFutureDigits.rbegin(); digit != mFutureDigits.rend(); ++digit) {
340
341 if (digit->getBC() > bclimit) {
342 break;
343 }
344
345 double timestamp = digit->getBC() * Geo::BC_TIME + digit->getTDC() * Geo::TDCBIN * 1E-3; // in ns
346 int isnext = Int_t(timestamp * Geo::READOUTWINDOW_INV) - (mReadoutWindowCurrent + 1); // to be replaced with uncalibrated time
347
348 if (isnext < 0) { // we jump too ahead in future, digit will be not stored
349 LOG(debug) << "Digit lost because we jump too ahead in future. Current RO window=" << isnext << "\n";
350
351 // remove digit from array in the future
352 int labelremoved = digit->getLabel();
353 mFutureDigits.erase(mFutureDigits.begin() + idigit);
354
355 idigit--;
356
357 continue;
358 }
359
360 if (isnext < MAXWINDOWS - 1) { // move from digit buffer array to the proper window
361 std::vector<Strip>* strips = mStripsCurrent;
362
363 if (isnext) {
364 strips = mStripsNext[isnext - 1];
365 }
366
367 fillDigitsInStrip(strips, digit->getChannel(), digit->getTDC(), digit->getTOT(), digit->getBC(), digit->getChannel() / Geo::NPADS);
368
369 // int labelremoved = digit->getLabel();
370 mFutureDigits.erase(mFutureDigits.begin() + idigit);
371
372 } else {
373 bclimit = digit->getBC();
374 }
375 idigit--; // go back to the next position in the reverse iterator
376 } // close future digit loop
377}
378//______________________________________________________________________
379void WindowFiller::checkIfReuseFutureDigitsRO() // the same but using readout info information from raw
380{
381 if (!mFutureDigits.size()) {
382 return;
383 }
384
385 // check if digits stored very far in future match the new readout windows currently available
386 if (mFutureToBeSorted) {
387 // sort digit in descending BC order: kept last as first
388 std::sort(mFutureDigits.begin(), mFutureDigits.end(),
390 if (a.getTriggerOrbit() != b.getTriggerOrbit()) {
391 return a.getTriggerOrbit() > b.getTriggerOrbit();
392 }
393 if (a.getTriggerBunch() != b.getTriggerBunch()) {
394 return a.getTriggerBunch() > b.getTriggerBunch();
395 }
396 return a.getBC() > b.getBC();
397 });
398 mFutureToBeSorted = false;
399 }
400
401 int idigit = mFutureDigits.size() - 1;
402
403 int rolimit = 999999; // if bc is larger than this value stop the search in the next loop since bc are ordered in descending order
404
405 for (std::vector<Digit>::reverse_iterator digit = mFutureDigits.rbegin(); digit != mFutureDigits.rend(); ++digit) {
406
407 int row = (digit->getTriggerOrbit() - mFirstIR.orbit) * Geo::BC_IN_ORBIT + (digit->getTriggerBunch() - mFirstIR.bc) + 100; // N bunch id of the trigger from timeframe start + 100 bunches
408
410
411 if (row > rolimit) {
412 break;
413 }
414
415 int isnext = row - mReadoutWindowCurrent;
416
417 if (isnext < 0) { // we jump too ahead in future, digit will be not stored
418 LOG(debug) << "Digit lost because we jump too ahead in future. Current RO window=" << isnext << "\n";
419
420 // remove digit from array in the future
421 int labelremoved = digit->getLabel();
422 mFutureDigits.erase(mFutureDigits.begin() + idigit);
423
424 idigit--;
425
426 continue;
427 }
428
429 if (isnext < MAXWINDOWS - 1) { // move from digit buffer array to the proper window
430 std::vector<Strip>* strips = mStripsCurrent;
431
432 if (isnext) {
433 strips = mStripsNext[isnext - 1];
434 }
435
436 if (mMaskNoiseRate < 0 || mChannelCounts[digit->getChannel()] < mMaskNoiseRate) {
437 fillDigitsInStrip(strips, digit->getChannel(), digit->getTDC(), digit->getTOT(), digit->getBC(), digit->getChannel() / Geo::NPADS);
438 }
439
440 // int labelremoved = digit->getLabel();
441 mFutureDigits.erase(mFutureDigits.begin() + idigit);
442 } else {
443 rolimit = row;
444 }
445 idigit--; // go back to the next position in the reverse iterator
446 } // close future digit loop
447}
448
450{
451 bool isTOFempty = true;
453 // fill diagnostic frequency
454 for (int j = 0; j < mReadoutWindowData.size(); j++) {
456 int fd = mReadoutWindowData[j].firstDia();
457 for (int ic = 0; ic < 72; ic++) {
458 if (ic) {
459 fd += mReadoutWindowData[j].getDiagnosticInCrate(ic - 1);
460 }
461 int dia = mReadoutWindowData[j].getDiagnosticInCrate(ic);
462 int slot = 0;
463 if (mReadoutWindowData[j].isEmptyCrate(ic)) {
465 } else {
466 isTOFempty = false;
467 if (dia) {
468 int lastdia = fd + dia;
469
470 ULong64_t key;
471 for (int dd = fd; dd < lastdia; dd++) {
472 if (mPatterns[dd] >= 28) {
473 slot = mPatterns[dd] - 28;
475 continue;
476 }
477
478 key += (1 << mPatterns[dd]);
479
480 if (dd + 1 == lastdia || mPatterns[dd + 1] >= 28) {
482 }
483 }
484 }
485 }
486 }
487 }
488
489 if (isTOFempty) {
491 }
492
493 // fill also noise diagnostic if the counts within the TF is larger than a threashold (default >=11, -> 1 kHZ)
494 int masknoise = mMaskNoiseRate;
495 if (masknoise < 0) {
496 masknoise = -masknoise;
497 }
498
499 for (int i = 0; i < Geo::NCHANNELS; i++) {
500 if (mChannelCounts[i] >= masknoise) {
501 int additionalMask = 0;
502
503 if (mChannelCounts[i] >= masknoise * 10) {
504 additionalMask += (1 << 19); // > 10 kHZ (if masknoise = 1 kHz)
505 if (mChannelCounts[i] >= masknoise * 100) {
506 additionalMask += (1 << 20); // > 100 kHZ (if masknoise = 1 kHz)
507 }
508 }
509
510 //Fill noisy in diagnostic
511 mDiagnosticFrequency.fillNoisy(i + additionalMask, mReadoutWindowData.size());
512 }
513 }
514}
uint64_t orbit
Definition RawEventData.h:6
uint64_t bc
Definition RawEventData.h:5
int32_t i
uint32_t j
Definition RawData.h:0
std::ostringstream debug
ClassImp(WindowFiller)
StringRef key
uint32_t fillEmptyCrate(int crate, uint32_t frequency=1)
Definition Diagnostic.h:43
uint32_t fillEmptyTOF(uint32_t frequency=1)
Definition Diagnostic.h:44
static ULong64_t getTRMKey(int crate, int trm)
uint32_t fillROW()
Definition Diagnostic.h:42
uint32_t fill(ULong64_t pattern)
uint32_t fillNoisy(int channel, int frequency=1)
Definition Diagnostic.h:41
TOF digit implementation.
Definition Digit.h:31
static constexpr Int_t NPADS
Definition Geo.h:110
static constexpr double BC_IN_WINDOW_INV
Definition Geo.h:166
static constexpr Double_t READOUTWINDOW_INV
Definition Geo.h:167
static constexpr Double_t BC_TIME
Definition Geo.h:101
@ kNCrate
Definition Geo.h:95
static constexpr int NCHANNELS
Definition Geo.h:124
static constexpr Float_t TDCBIN
TDC bin width [ps].
Definition Geo.h:150
static constexpr int BC_IN_WINDOW
Definition Geo.h:165
static constexpr int BC_IN_ORBIT
Definition Geo.h:105
static constexpr int NWINDOW_IN_ORBIT
Definition Geo.h:163
static constexpr Int_t NSTRIPS
Definition Geo.h:121
static uint32_t getNOrbitInTF()
Definition Utils.h:72
void addCrateHeaderData(unsigned long orbit, int crate, int32_t bc, uint32_t eventCounter)
void fillDigitsInStrip(std::vector< Strip > *strips, int channel, int tdc, int tot, uint64_t nbc, UInt_t istrip, uint32_t triggerorbit=0, uint16_t triggerbunch=0)
std::vector< CrateHeaderData > mCrateHeaderData
std::vector< Strip > mStrips[MAXWINDOWS]
static const int MAXWINDOWS
std::vector< PatternData > mCratePatterns
std::vector< Strip > * mStripsCurrent
int mChannelCounts[o2::tof::Geo::NCHANNELS]
std::vector< Strip > * mStripsNext[MAXWINDOWS - 1]
void flushOutputContainer(std::vector< Digit > &digits)
std::vector< ReadoutWindowData > mReadoutWindowDataFiltered
std::vector< uint8_t > mPatterns
Diagnostic mDiagnosticFrequency
std::vector< Digit > mDigitsPerTimeFrame
std::vector< Digit > mFutureDigits
std::vector< ReadoutWindowData > mReadoutWindowData
void fillOutputContainer(std::vector< Digit > &digits)
InteractionRecord mFirstIR
GLdouble n
Definition glcorearb.h:1982
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
uint32_t orbit
LHC orbit.
uint16_t bc
bunch crossing ID of interaction
void numCratesSeen(int ncrates)
Definition Digit.h:215
void crateSeen(int crate)
Definition Digit.h:214
void setEventCounter(int ev)
Definition Digit.h:190
void setEmptyCrate(int crate)
Definition Digit.h:139
void setBCData(int orbit, int bc)
Definition Digit.h:152
void setFirstEntryDia(int first)
Definition Digit.h:187
void addedDiagnostic(int crate)
Definition Digit.h:141
void setNEntriesDia(int ne)
Definition Digit.h:188
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< Digit > digits
std::vector< int > row