Project
Loading...
Searching...
No Matches
DigitPixelReader.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
14
17#include <fairlogger/Logger.h>
18#include <cassert>
19#include <algorithm>
20#include <numeric>
21
22#include <iostream>
23
24using namespace o2::itsmft;
26
27//______________________________________________________________________________
29{
30 // in the self-managed mode we need to delete locally created containers
31 clear();
32}
33
34//_____________________________________
36{
37 // prerare data of the next trigger, return number of digits
38 while (++mIdROF < mROFRecVec.size()) {
39 if (mROFRecVec[mIdROF].getNEntries() > 0) {
40 mIdDig = 0; // jump to the 1st digit of the trigger
41 mInteractionRecord = mROFRecVec[mIdROF].getBCData();
42 if (mSquashOverflowsDepth) {
43 auto nUsed = std::accumulate(mSquashedDigitsMask.begin() + mROFRecVec[mIdROF].getFirstEntry(),
44 mSquashedDigitsMask.begin() + mROFRecVec[mIdROF].getFirstEntry() + mROFRecVec[mIdROF].getNEntries() - 1, 0);
45 return mROFRecVec[mIdROF].getNEntries() - nUsed;
46 } else {
47 return mROFRecVec[mIdROF].getNEntries();
48 }
49 }
50 }
51 return 0;
52}
53
54//______________________________________________________________________________
55ChipPixelData* DigitPixelReader::getNextChipData(std::vector<ChipPixelData>& chipDataVec)
56{
57 // decode data of single chip to corresponding slot of chipDataVec
58 if (mIdROF >= mROFRecVec.size()) {
59 return nullptr; // TF is done
60 }
61 if (mIdROF < 0 || mIdDig >= mROFRecVec[mIdROF].getNEntries()) {
62 if (!mDecodeNextAuto || !decodeNextTrigger()) { // no automatic decoding is asked or we are at the end of the TF
63 return nullptr;
64 }
65 }
66 auto chipID = mDigits[mROFRecVec[mIdROF].getFirstEntry() + mIdDig].getChipIndex();
67 return getNextChipData(chipDataVec[chipID]) ? &chipDataVec[chipID] : nullptr;
68}
69
70//______________________________________________________________________________
72{
73 // decode data of single chip to chipData
74 if (mIdROF >= mROFRecVec.size()) {
75 return false; // TF is done
76 }
77 if (mIdROF < 0 || mIdDig >= mROFRecVec[mIdROF].getNEntries()) {
78 if (!mDecodeNextAuto || !decodeNextTrigger()) { // no automatic decoding is asked or we are at the end of the TF
79 return false;
80 }
81 }
82 chipData.clear();
83 int did = mROFRecVec[mIdROF].getFirstEntry() + mIdDig;
84 chipData.setStartID(did); // for the MC references, not used if squashing
85 const auto* digit = &mDigits[did];
86 chipData.setChipID(digit->getChipIndex());
87 chipData.setROFrame(mROFRecVec[mIdROF].getROFrame());
89 chipData.setTrigger(mTrigger);
90 if (mSquashOverflowsDepth) {
91 if (!mSquashedDigitsMask[did]) {
92 chipData.getData().emplace_back(digit);
93 mSquashedDigitsMask[did] = true;
94 if (mDigitsMCTruth) {
95 chipData.getPixIds().push_back(did); // this we do only with squashing + MC
96 }
97 }
98 } else {
99 chipData.getData().emplace_back(digit);
100 }
101 int lim = mROFRecVec[mIdROF].getFirstEntry() + mROFRecVec[mIdROF].getNEntries();
102 while ((++did < lim) && (digit = &mDigits[did])->getChipIndex() == chipData.getChipID()) {
103 if (mSquashOverflowsDepth) {
104 if (!mSquashedDigitsMask[did]) {
105 chipData.getData().emplace_back(digit);
106 mSquashedDigitsMask[did] = true;
107 if (mDigitsMCTruth) {
108 chipData.getPixIds().push_back(did); // this we do only with squashing + MC
109 }
110 }
111 } else {
112 chipData.getData().emplace_back(digit);
113 }
114 }
115 mIdDig = did - mROFRecVec[mIdROF].getFirstEntry();
116
117 // Merge overflow digits from next N ROFs, being N the depth of the search
118 if (!mIdROF || mIdROFLast != mIdROF) {
119 mIdROFLast = mIdROF;
120 for (uint16_t iROF{1}; iROF <= mSquashOverflowsDepth && (mIdROF + iROF) < mROFRecVec.size(); ++iROF) {
121 mBookmarkNextROFs[iROF - 1] = mROFRecVec[mIdROF + iROF].getFirstEntry(); // reset starting bookmark
122 }
123 }
124
125 // Loop over next ROFs
126 for (uint16_t iROF{1}; iROF <= mSquashOverflowsDepth && (mIdROF + iROF) < mROFRecVec.size(); ++iROF) {
127 int idNextROF{mIdROF + iROF};
128 if (std::abs(mROFRecVec[idNextROF].getBCData().differenceInBC(mROFRecVec[idNextROF - 1].getBCData())) > mMaxBCSeparationToSquash) {
129 break; // ROFs are too distant in BCs
130 }
131
132 int nDigitsNext{0};
133 for (int i{mBookmarkNextROFs[iROF - 1]}; i < mROFRecVec[idNextROF].getFirstEntry() + mROFRecVec[idNextROF].getNEntries(); ++i) {
134 if (mDigits[i].getChipIndex() < chipData.getChipID()) {
135 ++mBookmarkNextROFs[iROF - 1];
136 } else {
137 if (mDigits[i].getChipIndex() == chipData.getChipID()) {
138 ++nDigitsNext;
139 } else {
140 break;
141 }
142 }
143 }
144 if (!nDigitsNext) { // No data related to this chip in next rof, we stop squashing, assuming continue persistence
145 break;
146 }
147 size_t initialSize{chipData.getData().size()};
148 // Compile mask for repeated digits (digits with same row,col)
149 for (size_t iPixel{0}, iDigitNext{0}; iPixel < initialSize; ++iPixel) {
150 const auto& pixel = chipData.getData()[iPixel];
151 for (; iDigitNext < nDigitsNext; ++iDigitNext) {
152 const auto* digitNext = &mDigits[mBookmarkNextROFs[iROF - 1] + iDigitNext];
153 if (digitNext->getRow() == pixel.getRowDirect() && digitNext->getColumn() == pixel.getCol()) {
154 mSquashedDigitsMask[mBookmarkNextROFs[iROF - 1] + iDigitNext] = true;
155 break;
156 }
157 }
158 // seek to iDigitNext which is inferior than itC - mMaxSquashDist
159 const auto mincol = pixel.getCol() > mMaxSquashDist ? pixel.getCol() - mMaxSquashDist : 0;
160 const auto minrow = pixel.getRowDirect() > mMaxSquashDist ? pixel.getRowDirect() - mMaxSquashDist : 0;
161 if (iDigitNext == nDigitsNext) { // in case iDigitNext loop below reached the end
162 iDigitNext--;
163 }
164 while ((mDigits[mBookmarkNextROFs[iROF - 1] + iDigitNext].getColumn() > mincol || mDigits[mBookmarkNextROFs[iROF - 1] + iDigitNext].getRow() > minrow) && iDigitNext > 0) {
165 iDigitNext--;
166 }
167 for (; iDigitNext < nDigitsNext; iDigitNext++) {
168 if (mSquashedDigitsMask[mBookmarkNextROFs[iROF - 1] + iDigitNext]) {
169 continue;
170 }
171 const auto* digitNext = &mDigits[mBookmarkNextROFs[iROF - 1] + iDigitNext];
172 const auto drow = digitNext->getRow() - pixel.getRowDirect();
173 const auto dcol = digitNext->getColumn() - pixel.getCol();
174 if (!dcol && !drow) {
175 mSquashedDigitsMask[mBookmarkNextROFs[iROF - 1] + iDigitNext] = true;
176 break;
177 }
178 }
179 }
180
181 // loop over chip pixels
182 for (int iPixel{0}, iDigitNext{0}; iPixel < initialSize; ++iPixel) {
183 const o2::itsmft::PixelData pixel = chipData.getData()[iPixel]; // we need a copy to avoid the reference to be invalidated
184 // seek to iDigitNext which is inferior than itC - mMaxSquashDist
185 const auto mincol = pixel.getCol() > mMaxSquashDist ? pixel.getCol() - mMaxSquashDist : 0;
186 const auto minrow = pixel.getRowDirect() > mMaxSquashDist ? pixel.getRowDirect() - mMaxSquashDist : 0;
187 if (iDigitNext == nDigitsNext) { // in case iDigitNext loop below reached the end
188 iDigitNext--;
189 }
190 while ((mDigits[mBookmarkNextROFs[iROF - 1] + iDigitNext].getColumn() > mincol || mDigits[mBookmarkNextROFs[iROF - 1] + iDigitNext].getRow() > minrow) && iDigitNext > 0) {
191 iDigitNext--;
192 }
193 for (; iDigitNext < nDigitsNext; iDigitNext++) {
194 if (mSquashedDigitsMask[mBookmarkNextROFs[iROF - 1] + iDigitNext]) {
195 continue;
196 }
197 const auto* digitNext = &mDigits[mBookmarkNextROFs[iROF - 1] + iDigitNext];
198 const auto drow = digitNext->getRow() - pixel.getRowDirect();
199 const auto dcol = digitNext->getColumn() - pixel.getCol();
200 // if (!dcol && !drow) {
201 // same pixel fired in two ROFs, but we did it already
202 // mSquashedDigitsMask[mBookmarkNextROFs[iROF - 1] + iDigitNext] = true;
203 // continue;
204 // }
205 if (dcol > mMaxSquashDist || (dcol == mMaxSquashDist && drow > mMaxSquashDist)) {
206 break; // all greater iDigitNexts will not match to this pixel too
207 }
208 if (dcol < -mMaxSquashDist || (drow > mMaxSquashDist || drow < -mMaxSquashDist)) {
209 continue;
210 } else {
211 mSquashedDigitsMask[mBookmarkNextROFs[iROF - 1] + iDigitNext] = true;
212 chipData.getData().emplace_back(digitNext); // push squashed pixel
213 if (mDigitsMCTruth) {
214 chipData.getPixIds().push_back(mBookmarkNextROFs[iROF - 1] + iDigitNext);
215 }
216 squashNeighbours(iROF, iDigitNext, nDigitsNext, chipData); // recursively squash neighbours
217 }
218 }
219 }
220 mBookmarkNextROFs[iROF - 1] += nDigitsNext;
221 }
222 if (mSquashOverflowsDepth) {
223 if (mDigitsMCTruth) {
224 auto& pixels = chipData.getData();
225 chipData.getPixelsOrder().resize(pixels.size());
226 std::iota(chipData.getPixelsOrder().begin(), chipData.getPixelsOrder().end(), 0);
227 std::sort(chipData.getPixelsOrder().begin(), chipData.getPixelsOrder().end(), [&pixels](int a, int b) -> bool { return pixels[a].getCol() == pixels[b].getCol() ? pixels[a].getRow() < pixels[b].getRow() : pixels[a].getCol() < pixels[b].getCol(); });
228 }
229 std::sort(chipData.getData().begin(), chipData.getData().end(), [](auto& d1, auto& d2) -> bool { return d1.getCol() == d2.getCol() ? d1.getRow() < d2.getRow() : d1.getCol() < d2.getCol(); });
230 }
231
232 return true;
233}
234
235//______________________________________________________________________________
236void DigitPixelReader::squashNeighbours(const uint16_t& iROF, const int& iDigit, const int& maxDigits, ChipPixelData& chipData)
237{ // Recursively find and squash neighbours
238 const auto* digit = &mDigits[mBookmarkNextROFs[iROF - 1] + iDigit]; // current pivot digit, already pushed back and marked
239
240 for (int iOtherDigit{0}; iOtherDigit < maxDigits; ++iOtherDigit) {
241 if (mSquashedDigitsMask[mBookmarkNextROFs[iROF - 1] + iOtherDigit]) {
242 continue;
243 }
244 const auto* otherDigit = &mDigits[mBookmarkNextROFs[iROF - 1] + iOtherDigit];
245 const auto drow = otherDigit->getRow() - digit->getRow();
246 const auto dcol = otherDigit->getColumn() - digit->getColumn();
247 if (dcol > mMaxSquashDist || (dcol == mMaxSquashDist && drow > mMaxSquashDist)) {
248 break; // all greater iOtherDigits will not match to this pixel too
249 }
250 if (dcol < -mMaxSquashDist || (drow > mMaxSquashDist || drow < -mMaxSquashDist)) {
251 continue;
252 } else {
253 mSquashedDigitsMask[mBookmarkNextROFs[iROF - 1] + iOtherDigit] = true;
254 chipData.getData().emplace_back(otherDigit); // push squashed pixel
255 if (mDigitsMCTruth) {
256 chipData.getPixIds().push_back(mBookmarkNextROFs[iROF - 1] + iOtherDigit);
257 }
258 squashNeighbours(iROF, iOtherDigit, maxDigits, chipData); // recursively squash neighbours
259 }
260 }
261}
262
263//______________________________________________________________________________
264void DigitPixelReader::openInput(const std::string inpName, o2::detectors::DetID det)
265{
266 // open input file, load digits, MC labels
267 assert(det.getID() == o2::detectors::DetID::ITS || det.getID() == o2::detectors::DetID::MFT);
268
269 clear();
270 std::string detName = det.getName();
271
272 if (!(mInputTree = o2::utils::RootChain::load("o2sim", inpName))) {
273 LOG(fatal) << "Failed to load Digits tree from " << inpName;
274 }
275 mInputTree->SetBranchAddress((detName + "Digit").c_str(), &mDigitsSelf);
276 if (!mDigitsSelf) {
277 LOG(fatal) << "Failed to find " << (detName + "Digit").c_str() << " branch in the " << mInputTree->GetName()
278 << " from file " << inpName;
279 }
280
281 mInputTree->SetBranchAddress((detName + "DigitROF").c_str(), &mROFRecVecSelf);
282 if (!mROFRecVecSelf) {
283 LOG(fatal) << "Failed to find " << (detName + "DigitROF").c_str() << " branch in the " << mInputTree->GetName()
284 << " from file " << inpName;
285 }
286
287 mInputTree->SetBranchAddress((detName + "DigitMC2ROF").c_str(), &mMC2ROFRecVecSelf);
288 if (!mMC2ROFRecVecSelf) {
289 LOG(fatal) << "Failed to find " << (detName + "DigitMC2ROF").c_str() << " branch in the " << mInputTree->GetName()
290 << " from file " << inpName;
291 }
292
293 mInputTree->SetBranchAddress((detName + "DigitMCTruth").data(), &mDigitsMCTruthSelf);
294 // setDigitsMCTruth(mDigitsMCTruthSelf); // it will be assigned again at the reading, this is just to signal that the MCtruth is there
295}
296
297//______________________________________________________________________________
299{
300 // load next entry from the self-managed input
301 auto nev = mInputTree->GetEntries();
302 auto evID = mInputTree->GetReadEntry();
303 if (evID < -1) {
304 evID = -1;
305 }
306 if (++evID < nev) {
307 init();
308 mInputTree->GetEntry(evID);
309 setDigits(gsl::span(mDigitsSelf->data(), mDigitsSelf->size()));
310 setROFRecords(gsl::span(mROFRecVecSelf->data(), mROFRecVecSelf->size()));
311 setMC2ROFRecords(gsl::span(mMC2ROFRecVecSelf->data(), mMC2ROFRecVecSelf->size()));
312 // setDigitsMCTruth(mDigitsMCTruthSelf);
313 return true;
314 } else {
315 return false;
316 }
317}
318
319//______________________________________________________________________________
321{
322 // clear data structures
323 mInputTree.reset();
324 delete mDigitsSelf;
325 delete mDigitsMCTruthSelf;
326 mDigitsMCTruthSelf = nullptr;
327 mDigitsSelf = nullptr;
328 //
329 mDigits = gsl::span<const o2::itsmft::Digit>();
330 mROFRecVec = gsl::span<const o2::itsmft::ROFRecord>();
331 mMC2ROFRecVec = gsl::span<const o2::itsmft::MC2ROFRecord>();
332}
Definition of the Alpide pixel reader for MC digits processing.
int32_t i
o2::mid::ColumnData & getColumn(std::vector< o2::mid::ColumnData > &patterns, uint8_t icolumn, uint8_t deId)
Static class with identifiers, bitmasks and names for ALICE detectors.
Definition DetID.h:58
static constexpr const char * getName(ID id)
names of defined detectors
Definition DetID.h:145
static constexpr ID ITS
Definition DetID.h:63
static constexpr ID MFT
Definition DetID.h:71
void setInteractionRecord(const o2::InteractionRecord &r)
Definition PixelData.h:114
std::vector< uint32_t > & getPixIds()
Definition PixelData.h:273
void setROFrame(uint32_t r)
Definition PixelData.h:120
void setStartID(uint32_t id)
Definition PixelData.h:121
std::vector< int > & getPixelsOrder()
Definition PixelData.h:274
void setChipID(uint16_t id)
Definition PixelData.h:119
void setTrigger(uint32_t t)
Definition PixelData.h:123
uint16_t getChipID() const
Definition PixelData.h:108
const std::vector< PixelData > & getData() const
Definition PixelData.h:115
void squashNeighbours(const uint16_t &iROF, const int &iDigit, const int &maxDigits, ChipPixelData &chipData)
bool getNextChipData(ChipPixelData &chipData) override
void openInput(const std::string rawInput, o2::detectors::DetID det)
void setDigits(const gsl::span< const o2::itsmft::Digit > a)
void setMC2ROFRecords(const gsl::span< const o2::itsmft::MC2ROFRecord > a)
void setROFRecords(const gsl::span< const o2::itsmft::ROFRecord > a)
Digit class for the ITS.
Definition Digit.h:30
< single pixel datum, with possibility to set a flag of pixel being masked out
Definition PixelData.h:33
uint16_t getRowDirect() const
for faster access when the pixel is guaranteed to not be masked
Definition PixelData.h:45
uint16_t getCol() const
Definition PixelData.h:39
o2::InteractionRecord mInteractionRecord
Definition PixelReader.h:73
static std::unique_ptr< TChain > load(const std::string trName, const std::string inpFile)
Definition RootChain.cxx:21
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLint GLint GLsizei GLint GLenum GLenum const void * pixels
Definition glcorearb.h:275
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"