Project
Loading...
Searching...
No Matches
Clusterer.h
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#ifndef ALICEO2_ITS_CLUSTERER_H
15#define ALICEO2_ITS_CLUSTERER_H
16
17#define _PERFORM_TIMING_
18
19// uncomment this to not allow diagonal clusters, e.g. like |* |
20// | *|
21#define _ALLOW_DIAGONAL_ALPIDE_CLUSTERS_
22
23#include <utility>
24#include <vector>
25#include <cstring>
26#include <memory>
27#include <gsl/span>
36#include "Rtypes.h"
37
38#ifdef _PERFORM_TIMING_
39#include <TStopwatch.h>
40#endif
41
42class TTree;
43
44namespace o2
45{
46class MCCompLabel;
47namespace dataformats
48{
49template <typename T>
50class ConstMCTruthContainerView;
51template <typename T>
53} // namespace dataformats
54
55namespace itsmft
56{
57
58using CompClusCont = std::vector<CompClusterExt>;
59using PatternCont = std::vector<unsigned char>;
60using ROFRecCont = std::vector<ROFRecord>;
61
62// template <class CompClusCont, class PatternCont, class ROFRecCont> // container types (PMR or std::vectors)
63
65{
71 using Label = o2::MCCompLabel;
74
75 public:
76 static constexpr int MaxLabels = 10;
77 static constexpr int MaxHugeClusWarn = 5; // max number of warnings for HugeCluster
78
79 struct BBox {
80 uint16_t chipID = 0xffff;
81 uint16_t rowMin = 0xffff;
82 uint16_t colMin = 0xffff;
83 uint16_t rowMax = 0;
84 uint16_t colMax = 0;
85 BBox(uint16_t c) : chipID(c) {}
86 bool isInside(uint16_t row, uint16_t col) const { return row >= rowMin && row <= rowMax && col >= colMin && col <= colMax; }
87 auto rowSpan() const { return rowMax - rowMin + 1; }
88 auto colSpan() const { return colMax - colMin + 1; }
90 void clear()
91 {
92 rowMin = colMin = 0xffff;
93 rowMax = colMax = 0;
94 }
95 void adjust(uint16_t row, uint16_t col)
96 {
97 if (row < rowMin) {
98 rowMin = row;
99 }
100 if (row > rowMax) {
101 rowMax = row;
102 }
103 if (col < colMin) {
104 colMin = col;
105 }
106 if (col > colMax) {
107 colMax = col;
108 }
109 }
110 };
111
112 //=========================================================
114 struct ThreadStat {
115 uint16_t firstChip = 0;
116 uint16_t nChips = 0;
117 uint32_t firstClus = 0;
118 uint32_t firstPatt = 0;
119 uint32_t nClus = 0;
120 uint32_t nPatt = 0;
121 };
122
124 struct PreCluster {
125 int head = 0; // index of precluster head in the pixels
126 int index = 0;
127 };
128 int id = -1;
129 Clusterer* parent = nullptr; // parent clusterer
130 // buffers for entries in preClusterIndices in 2 columns, to avoid boundary checks, we reserve
131 // extra elements in the beginning and the end
134 int* curr = nullptr; // pointer on the 1st row of currently processed columnsX
135 int* prev = nullptr; // pointer on the 1st row of previously processed columnsX
136 // pixels[].first is the index of the next pixel of the same precluster in the pixels
137 // pixels[].second is the index of the referred pixel in the ChipPixelData (element of mChips)
138 std::vector<std::pair<int, uint32_t>> pixels;
139 uint16_t currCol = 0xffff;
140 bool noLeftCol = true;
141 std::array<Label, MaxLabels> labelsBuff;
142 std::vector<PixelData> pixArrBuff;
143 std::vector<PreCluster> preClusters;
144 //
149 std::vector<ThreadStat> stats; // statistics for each thread results, used at merging
152 void resetColumn(int* buff) { std::memset(buff, -1, sizeof(int) * SegmentationAlpide::NRows); }
153
155 void swapColumnBuffers() { std::swap(prev, curr); }
156
158 void expandPreCluster(uint32_t ip, uint16_t row, int preClusIndex)
159 {
160 auto& firstIndex = preClusters[preClusters[preClusIndex].index].head;
161 pixels.emplace_back(firstIndex, ip);
162 firstIndex = pixels.size() - 1;
163 curr[row] = preClusIndex;
164 }
165
167 void addNewPrecluster(uint32_t ip, uint16_t row)
168 {
169 int lastIndex = preClusters.size();
170 preClusters.emplace_back(pixels.size(), lastIndex);
171 // new head does not point yet (-1) on other pixels, store just the entry of the pixel in the ChipPixelData
172 pixels.emplace_back(-1, ip);
173 curr[row] = lastIndex; // store index of the new precluster in the current column buffer
174 }
175
176 void fetchMCLabels(int digID, const ConstMCTruth* labelsDig, int& nfilled);
177 void initChip(const ChipPixelData* curChipData, uint32_t first);
178 void updateChip(const ChipPixelData* curChipData, uint32_t ip);
179 void finishChip(ChipPixelData* curChipData, CompClusCont* compClus, PatternCont* patterns,
180 const ConstMCTruth* labelsDig, MCTruth* labelsClus);
181 void finishChipSingleHitFast(uint32_t hit, ChipPixelData* curChipData, CompClusCont* compClusPtr,
182 PatternCont* patternsPtr, const ConstMCTruth* labelsDigPtr, MCTruth* labelsClusPTr);
183 void process(uint16_t chip, uint16_t nChips, CompClusCont* compClusPtr, PatternCont* patternsPtr,
184 const ConstMCTruth* labelsDigPtr, MCTruth* labelsClPtr, const ROFRecord& rofPtr);
185
186 ClustererThread(Clusterer* par = nullptr, int _id = -1) : parent(par), id(_id), curr(column2 + 1), prev(column1 + 1)
187 {
188 std::fill(std::begin(column1), std::end(column1), -1);
189 std::fill(std::begin(column2), std::end(column2), -1);
190 }
191 };
192 //=========================================================
193
194 Clusterer();
195 ~Clusterer() = default;
196
197 Clusterer(const Clusterer&) = delete;
198 Clusterer& operator=(const Clusterer&) = delete;
199
200 void process(int nThreads, PixelReader& r, CompClusCont* compClus, PatternCont* patterns, ROFRecCont* vecROFRec, MCTruth* labelsCl = nullptr);
201
202 template <typename VCLUS, typename VPAT>
203 static void streamCluster(const std::vector<PixelData>& pixbuf, const std::array<Label, MaxLabels>* lblBuff, const BBox& bbox, const LookUp& pattIdConverter,
204 VCLUS* compClusPtr, VPAT* patternsPtr, MCTruth* labelsClusPtr, int nlab, bool isHuge = false);
205
206 bool isContinuousReadOut() const { return mContinuousReadout; }
207 void setContinuousReadOut(bool v) { mContinuousReadout = v; }
208
209 bool isDropHugeClusters() const { return mDropHugeClusters; }
210 void setDropHugeClusters(bool v) { mDropHugeClusters = v; }
211
212 int getMaxBCSeparationToMask() const { return mMaxBCSeparationToMask; }
213 void setMaxBCSeparationToMask(int n) { mMaxBCSeparationToMask = n; }
214
215 int getMaxRowColDiffToMask() const { return mMaxRowColDiffToMask; }
216 void setMaxRowColDiffToMask(int v) { mMaxRowColDiffToMask = v; }
217
218 int getMaxROFDepthToSquash(int layer = -1) const { return (layer < 0) ? mSquashingDepth : mSquashingLayerDepth[layer]; }
219 void setMaxROFDepthToSquash(int v) { mSquashingDepth = v; }
220 void addMaxROFDepthToSquash(int v) { mSquashingLayerDepth.push_back(v); }
221
222 int getMaxBCSeparationToSquash(int layer = -1) const { return (layer < 0) ? mMaxBCSeparationToSquash : mMaxBCSeparationToSquashLayer[layer]; }
223 void setMaxBCSeparationToSquash(int n) { mMaxBCSeparationToSquash = n; }
224 void addMaxBCSeparationToSquash(int n) { mMaxBCSeparationToSquashLayer.push_back(n); }
225
226 void print(bool showTiming = true) const;
227 void clear();
228 void reset();
229
230 void setNChips(int n)
231 {
232 mChips.resize(n);
233 mChipsOld.resize(n);
234 }
235
237 void loadDictionary(const std::string& fileName) { mPattIdConverter.loadDictionary(fileName); }
238 void setDictionary(const TopologyDictionary* dict) { mPattIdConverter.setDictionary(dict); }
239 const TopologyDictionary& getDictionary() const { return mPattIdConverter.getDictionary(); }
240 auto& getPattIdConverter() const { return mPattIdConverter; }
241
242 TStopwatch& getTimer() { return mTimer; } // cannot be const
243 TStopwatch& getTimerMerge() { return mTimerMerge; } // cannot be const
244
245 private:
246 void flushClusters(CompClusCont* compClus, MCTruth* labels);
247
248 // clusterization options
249 bool mContinuousReadout = true;
250 bool mDropHugeClusters = false;
251
253 int mMaxBCSeparationToMask = 6000. / o2::constants::lhc::LHCBunchSpacingNS + 10;
254 int mMaxRowColDiffToMask = 0;
255 int mNHugeClus = 0;
256
258 int mSquashingDepth = 0;
259 int mMaxBCSeparationToSquash = 6000. / o2::constants::lhc::LHCBunchSpacingNS + 10;
260 std::vector<int> mSquashingLayerDepth;
261 std::vector<int> mMaxBCSeparationToSquashLayer;
262
263 std::vector<std::unique_ptr<ClustererThread>> mThreads; // buffers for threads
264 std::vector<ChipPixelData> mChips; // currently processed ROF's chips data
265 std::vector<ChipPixelData> mChipsOld; // previously processed ROF's chips data (for masking)
266 std::vector<ChipPixelData*> mFiredChipsPtr; // pointers on the fired chips data in the decoder cache
267
268 LookUp mPattIdConverter;
269
270 TStopwatch mTimer;
271 TStopwatch mTimerMerge;
272};
273
274template <typename VCLUS, typename VPAT>
275void Clusterer::streamCluster(const std::vector<PixelData>& pixbuf, const std::array<Label, MaxLabels>* lblBuff, const Clusterer::BBox& bbox, const LookUp& pattIdConverter,
276 VCLUS* compClusPtr, VPAT* patternsPtr, MCTruth* labelsClusPtr, int nlab, bool isHuge)
277{
278 if (labelsClusPtr && lblBuff) { // MC labels were requested
279 auto cnt = compClusPtr->size();
280 for (int i = nlab; i--;) {
281 labelsClusPtr->addElement(cnt, (*lblBuff)[i]);
282 }
283 }
284 auto colSpanW = bbox.colSpan();
285 auto rowSpanW = bbox.rowSpan();
286 // add to compact clusters, which must be always filled
287 std::array<unsigned char, ClusterPattern::MaxPatternBytes> patt{};
288 for (const auto& pix : pixbuf) {
289 uint32_t ir = pix.getRowDirect() - bbox.rowMin, ic = pix.getCol() - bbox.colMin;
290 int nbits = ir * colSpanW + ic;
291 patt[nbits >> 3] |= (0x1 << (7 - (nbits % 8)));
292 }
293 uint16_t pattID = (isHuge || pattIdConverter.size() == 0) ? CompCluster::InvalidPatternID : pattIdConverter.findGroupID(rowSpanW, colSpanW, patt.data());
294 uint16_t row = bbox.rowMin, col = bbox.colMin;
295 if (pattID == CompCluster::InvalidPatternID || pattIdConverter.isGroup(pattID)) {
296 if (pattID != CompCluster::InvalidPatternID) {
297 // For grouped topologies, the reference pixel is the COG pixel
298 float xCOG = 0., zCOG = 0.;
299 ClusterPattern::getCOG(rowSpanW, colSpanW, patt.data(), xCOG, zCOG);
300 row += round(xCOG);
301 col += round(zCOG);
302 }
303 if (patternsPtr) {
304 patternsPtr->emplace_back((unsigned char)rowSpanW);
305 patternsPtr->emplace_back((unsigned char)colSpanW);
306 int nBytes = rowSpanW * colSpanW / 8;
307 if (((rowSpanW * colSpanW) % 8) != 0) {
308 nBytes++;
309 }
310 patternsPtr->insert(patternsPtr->end(), std::begin(patt), std::begin(patt) + nBytes);
311 }
312 }
313 compClusPtr->emplace_back(row, col, pattID, bbox.chipID);
314}
315
316} // namespace itsmft
317} // namespace o2
318#endif /* ALICEO2_ITS_CLUSTERER_H */
Definition of the ITSMFT compact cluster.
void print() const
int32_t i
Definition of the ITSMFT ROFrame (trigger) record.
Definition of the LookUp class.
std::vector< o2::MCCompLabel > labels
Header to collect LHC related constants.
Transient data classes for single pixel and set of pixels from current chip.
Abstract class for Alpide data reader class.
uint32_t c
Definition RawData.h:2
Definition of the SegmentationAlpide class.
void addElement(uint32_t dataindex, TruthElement const &element, bool noElement=false)
static int getCOG(int rowSpan, int colSpan, const unsigned char patt[MaxPatternBytes], float &xCOG, float &zCOG)
Static: Compute pattern's COG position. Returns the number of fired pixels.
static constexpr uint8_t MaxRowSpan
static constexpr uint8_t MaxColSpan
int getMaxBCSeparationToMask() const
Definition Clusterer.h:212
void setMaxRowColDiffToMask(int v)
Definition Clusterer.h:216
void setMaxBCSeparationToMask(int n)
Definition Clusterer.h:213
TStopwatch & getTimerMerge()
Definition Clusterer.h:243
Clusterer & operator=(const Clusterer &)=delete
int getMaxROFDepthToSquash(int layer=-1) const
Definition Clusterer.h:218
bool isDropHugeClusters() const
Definition Clusterer.h:209
void setDictionary(const TopologyDictionary *dict)
Definition Clusterer.h:238
void process(int nThreads, PixelReader &r, CompClusCont *compClus, PatternCont *patterns, ROFRecCont *vecROFRec, MCTruth *labelsCl=nullptr)
Definition Clusterer.cxx:27
static constexpr int MaxLabels
Definition Clusterer.h:76
void setContinuousReadOut(bool v)
Definition Clusterer.h:207
int getMaxRowColDiffToMask() const
Definition Clusterer.h:215
auto & getPattIdConverter() const
Definition Clusterer.h:240
void setMaxBCSeparationToSquash(int n)
Definition Clusterer.h:223
void addMaxBCSeparationToSquash(int n)
Definition Clusterer.h:224
void setMaxROFDepthToSquash(int v)
Definition Clusterer.h:219
bool isContinuousReadOut() const
Definition Clusterer.h:206
int getMaxBCSeparationToSquash(int layer=-1) const
Definition Clusterer.h:222
void addMaxROFDepthToSquash(int v)
Definition Clusterer.h:220
void setDropHugeClusters(bool v)
Definition Clusterer.h:210
static constexpr int MaxHugeClusWarn
Definition Clusterer.h:77
static void streamCluster(const std::vector< PixelData > &pixbuf, const std::array< Label, MaxLabels > *lblBuff, const BBox &bbox, const LookUp &pattIdConverter, VCLUS *compClusPtr, VPAT *patternsPtr, MCTruth *labelsClusPtr, int nlab, bool isHuge=false)
Definition Clusterer.h:275
Clusterer(const Clusterer &)=delete
const TopologyDictionary & getDictionary() const
Definition Clusterer.h:239
TStopwatch & getTimer()
Definition Clusterer.h:242
void loadDictionary(const std::string &fileName)
Definition Clusterer.h:237
void setNChips(int n)
load the dictionary of cluster topologies
Definition Clusterer.h:230
static constexpr unsigned short InvalidPatternID
Definition CompCluster.h:46
int size() const
Definition LookUp.h:44
void setDictionary(const TopologyDictionary *dict)
Definition LookUp.cxx:42
auto & getDictionary() const
Definition LookUp.h:46
void loadDictionary(std::string fileName)
Definition LookUp.cxx:36
< single pixel datum, with possibility to set a flag of pixel being masked out
Definition PixelData.h:33
PixelReader class for the ITSMFT.
Definition PixelReader.h:34
GLdouble n
Definition glcorearb.h:1982
const GLdouble * v
Definition glcorearb.h:832
GLuint index
Definition glcorearb.h:781
GLint first
Definition glcorearb.h:399
GLint GLint GLsizei GLint GLenum GLenum const void * pixels
Definition glcorearb.h:275
GLenum GLuint GLint GLint layer
Definition glcorearb.h:1310
GLboolean r
Definition glcorearb.h:1233
GLuint id
Definition glcorearb.h:650
std::vector< unsigned char > PatternCont
Definition Clusterer.h:59
const int float col
std::vector< ROFRecord > ROFRecCont
Definition Clusterer.h:60
std::vector< CompClusterExt > CompClusCont
Definition Clusterer.h:58
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
void adjust(uint16_t row, uint16_t col)
Definition Clusterer.h:95
bool isInside(uint16_t row, uint16_t col) const
Definition Clusterer.h:86
bool isAcceptableSize() const
Definition Clusterer.h:89
int column2[SegmentationAlpide::NRows+2]
Definition Clusterer.h:133
int column1[SegmentationAlpide::NRows+2]
Definition Clusterer.h:132
std::vector< PixelData > pixArrBuff
temporary buffer for building cluster labels
Definition Clusterer.h:142
std::vector< PreCluster > preClusters
temporary buffer for pattern calc.
Definition Clusterer.h:143
void addNewPrecluster(uint32_t ip, uint16_t row)
Definition Clusterer.h:167
void initChip(const ChipPixelData *curChipData, uint32_t first)
void finishChip(ChipPixelData *curChipData, CompClusCont *compClus, PatternCont *patterns, const ConstMCTruth *labelsDig, MCTruth *labelsClus)
uint16_t currCol
Column being processed.
Definition Clusterer.h:139
std::vector< std::pair< int, uint32_t > > pixels
Definition Clusterer.h:138
bool noLeftCol
flag that there is no column on the left to check
Definition Clusterer.h:140
void expandPreCluster(uint32_t ip, uint16_t row, int preClusIndex)
add new precluster at given row of current column for the fired pixel with index ip in the ChipPixelD...
Definition Clusterer.h:158
void fetchMCLabels(int digID, const ConstMCTruth *labelsDig, int &nfilled)
ClustererThread(Clusterer *par=nullptr, int _id=-1)
Definition Clusterer.h:186
void process(uint16_t chip, uint16_t nChips, CompClusCont *compClusPtr, PatternCont *patternsPtr, const ConstMCTruth *labelsDigPtr, MCTruth *labelsClPtr, const ROFRecord &rofPtr)
void swapColumnBuffers()
add cluster at row (entry ip in the ChipPixeData) to the precluster with given index
Definition Clusterer.h:155
void finishChipSingleHitFast(uint32_t hit, ChipPixelData *curChipData, CompClusCont *compClusPtr, PatternCont *patternsPtr, const ConstMCTruth *labelsDigPtr, MCTruth *labelsClusPTr)
std::array< Label, MaxLabels > labelsBuff
Definition Clusterer.h:141
std::vector< ThreadStat > stats
Definition Clusterer.h:149
CompClusCont compClusters
preclusters info
Definition Clusterer.h:146
void resetColumn(int *buff)
reset column buffer, for the performance reasons we use memset
Definition Clusterer.h:152
void updateChip(const ChipPixelData *curChipData, uint32_t ip)
methods and transient data used within a thread
Definition Clusterer.h:114
o2::InteractionRecord ir(0, 0)
std::vector< int > row
LookUp pattIdConverter