1616
1717#define _PERFORM_TIMING_
1818
19+ // uncomment this to not allow diagonal clusters, e.g. like |* |
20+ // | *|
21+ #define _ALLOW_DIAGONAL_ALPIDE_CLUSTERS_
22+
1923#include < utility>
2024#include < vector>
2125#include < cstring>
2226#include < memory>
2327#include < gsl/span>
2428#include " ITSMFTBase/SegmentationAlpide.h"
25- #include " DataFormatsITS3 /CompCluster.h"
29+ #include " DataFormatsITSMFT /CompCluster.h"
2630#include " DataFormatsITSMFT/ROFRecord.h"
2731#include " ITSMFTReconstruction/PixelReader.h"
2832#include " ITSMFTReconstruction/PixelData.h"
@@ -51,23 +55,60 @@ class MCTruthContainer;
5155namespace its3
5256{
5357
54- using CompClusCont = std::vector<CompClusterExt>;
58+ using CompClusCont = std::vector<itsmft:: CompClusterExt>;
5559using PatternCont = std::vector<unsigned char >;
5660using ROFRecCont = std::vector<itsmft::ROFRecord>;
5761
58- // template <class CompClusCont, class PatternCont, class ROFRecCont> // container types (PMR or std::vectors)
62+ // template <class CompClusCont, class PatternCont, class ROFRecCont> // container types (PMR or std::vectors)
5963
6064class Clusterer
6165{
6266 using PixelReader = o2::itsmft::PixelReader;
6367 using PixelData = o2::itsmft::PixelData;
6468 using ChipPixelData = o2::itsmft::ChipPixelData;
69+ using CompCluster = o2::itsmft::CompCluster;
70+ using CompClusterExt = o2::itsmft::CompClusterExt;
6571 using Label = o2::MCCompLabel;
6672 using MCTruth = o2::dataformats::MCTruthContainer<o2::MCCompLabel>;
6773 using ConstMCTruth = o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>;
6874
6975 public:
7076 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 ; }
89+ bool isAcceptableSize () const { return colMax - colMin < o2::itsmft::ClusterPattern::MaxColSpan && rowMax - rowMin < o2::itsmft::ClusterPattern::MaxRowSpan; }
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+
71112 // =========================================================
72113 // / methods and transient data used within a thread
73114 struct ThreadStat {
@@ -81,7 +122,7 @@ class Clusterer
81122 };
82123
83124 struct ClustererThread {
84-
125+ int id = - 1 ;
85126 Clusterer* parent = nullptr ; // parent clusterer
86127 // buffers for entries in preClusterIndices in 2 columns, to avoid boundary checks, we reserve
87128 // extra elements in the beginning and the end
@@ -132,13 +173,8 @@ class Clusterer
132173 curr[row] = lastIndex; // store index of the new precluster in the current column buffer
133174 }
134175
135- void streamCluster (const std::vector<PixelData>& pixbuf, uint16_t rowMin, uint16_t rowSpanW, uint16_t colMin, uint16_t colSpanW,
136- uint16_t chipID,
137- CompClusCont* compClusPtr, PatternCont* patternsPtr,
138- MCTruth* labelsClusPtr, int nlab, bool isHuge = false );
139-
140176 void fetchMCLabels (int digID, const ConstMCTruth* labelsDig, int & nfilled);
141- void initChip (const ChipPixelData* curChipData, uint32_t first, int chipID );
177+ void initChip (const ChipPixelData* curChipData, uint32_t first);
142178 void updateChip (const ChipPixelData* curChipData, uint32_t ip);
143179 void finishChip (ChipPixelData* curChipData, CompClusCont* compClus, PatternCont* patterns,
144180 const ConstMCTruth* labelsDig, MCTruth* labelsClus);
@@ -147,7 +183,6 @@ class Clusterer
147183 void process (uint16_t chip, uint16_t nChips, CompClusCont* compClusPtr, PatternCont* patternsPtr,
148184 const ConstMCTruth* labelsDigPtr, MCTruth* labelsClPtr, const itsmft::ROFRecord& rofPtr);
149185
150- ClustererThread (Clusterer* par = nullptr ) : parent(par) {}
151186 ~ClustererThread ()
152187 {
153188 if (column1) {
@@ -157,6 +192,11 @@ class Clusterer
157192 delete[] column2;
158193 }
159194 }
195+ ClustererThread (Clusterer* par = nullptr , int _id = -1 ) : parent(par), id(_id), curr(column2 + 1 ), prev(column1 + 1 )
196+ {
197+ // std::fill(std::begin(column1), std::end(column1), -1);
198+ // std::fill(std::begin(column2), std::end(column2), -1);
199+ }
160200 };
161201 // =========================================================
162202
@@ -168,6 +208,10 @@ class Clusterer
168208
169209 void process (int nThreads, PixelReader& r, CompClusCont* compClus, PatternCont* patterns, ROFRecCont* vecROFRec, MCTruth* labelsCl = nullptr );
170210
211+ template <typename VCLUS , typename VPAT >
212+ static void streamCluster (const std::vector<PixelData>& pixbuf, const std::array<Label, MaxLabels>* lblBuff, const BBox& bbox, const itsmft::LookUp& pattIdConverter,
213+ VCLUS * compClusPtr, VPAT * patternsPtr, MCTruth* labelsClusPtr, int nlab, bool isHuge = false );
214+
171215 bool isContinuousReadOut () const { return mContinuousReadout ; }
172216 void setContinuousReadOut (bool v) { mContinuousReadout = v; }
173217
@@ -177,6 +221,12 @@ class Clusterer
177221 int getMaxRowColDiffToMask () const { return mMaxRowColDiffToMask ; }
178222 void setMaxRowColDiffToMask (int v) { mMaxRowColDiffToMask = v; }
179223
224+ int getMaxROFDepthToSquash () const { return mSquashingDepth ; }
225+ void setMaxROFDepthToSquash (int v) { mSquashingDepth = v; }
226+
227+ int getMaxBCSeparationToSquash () const { return mMaxBCSeparationToSquash ; }
228+ void setMaxBCSeparationToSquash (int n) { mMaxBCSeparationToSquash = n; }
229+
180230 void print () const ;
181231 void clear ();
182232
@@ -188,28 +238,12 @@ class Clusterer
188238
189239 // /< load the dictionary of cluster topologies
190240 void loadDictionary (const std::string& fileName) { mPattIdConverter .loadDictionary (fileName); }
241+ void setDictionary (const itsmft::TopologyDictionary* dict) { mPattIdConverter .setDictionary (dict); }
191242
192243 TStopwatch& getTimer () { return mTimer ; } // cannot be const
193244 TStopwatch& getTimerMerge () { return mTimerMerge ; } // cannot be const
194245
195246 private:
196- // /< recalculate min max row and column of the cluster accounting for the position of pix
197- static void adjustBoundingBox (uint16_t row, uint16_t col, uint16_t & rMin, uint16_t & rMax, uint16_t & cMin, uint16_t & cMax)
198- {
199- if (row < rMin) {
200- rMin = row;
201- }
202- if (row > rMax) {
203- rMax = row;
204- }
205- if (col < cMin) {
206- cMin = col;
207- }
208- if (col > cMax) {
209- cMax = col;
210- }
211- }
212-
213247 void flushClusters (CompClusCont* compClus, MCTruth* labels);
214248
215249 // clusterization options
@@ -218,6 +252,11 @@ class Clusterer
218252 // /< mask continuosly fired pixels in frames separated by less than this amount of BCs (fired from hit in prev. ROF)
219253 int mMaxBCSeparationToMask = 6000 . / o2::constants::lhc::LHCBunchSpacingNS + 10 ;
220254 int mMaxRowColDiffToMask = 0 ; // /< provide their difference in col/row is <= than this
255+ int mNHugeClus = 0 ; // /< number of encountered huge clusters
256+
257+ // /< Squashing options
258+ int mSquashingDepth = 0 ; // /< squashing is applied to next N rofs
259+ int mMaxBCSeparationToSquash = 6000 . / o2::constants::lhc::LHCBunchSpacingNS + 10 ;
221260
222261 std::vector<std::unique_ptr<ClustererThread>> mThreads ; // buffers for threads
223262 std::vector<ChipPixelData> mChips ; // currently processed ROF's chips data
@@ -230,6 +269,48 @@ class Clusterer
230269 TStopwatch mTimerMerge ;
231270};
232271
272+ template <typename VCLUS , typename VPAT >
273+ void Clusterer::streamCluster (const std::vector<PixelData>& pixbuf, const std::array<Label, MaxLabels>* lblBuff, const Clusterer::BBox& bbox, const itsmft::LookUp& pattIdConverter,
274+ VCLUS * compClusPtr, VPAT * patternsPtr, MCTruth* labelsClusPtr, int nlab, bool isHuge)
275+ {
276+ if (labelsClusPtr && lblBuff) { // MC labels were requested
277+ auto cnt = compClusPtr->size ();
278+ for (int i = nlab; i--;) {
279+ labelsClusPtr->addElement (cnt, (*lblBuff)[i]);
280+ }
281+ }
282+ auto colSpanW = bbox.colSpan ();
283+ auto rowSpanW = bbox.rowSpan ();
284+ // add to compact clusters, which must be always filled
285+ std::array<unsigned char , itsmft::ClusterPattern::MaxPatternBytes> patt{};
286+ for (const auto & pix : pixbuf) {
287+ uint32_t ir = pix.getRowDirect () - bbox.rowMin , ic = pix.getCol () - bbox.colMin ;
288+ int nbits = ir * colSpanW + ic;
289+ patt[nbits >> 3 ] |= (0x1 << (7 - (nbits % 8 )));
290+ }
291+ uint16_t pattID = (isHuge || pattIdConverter.size () == 0 ) ? CompCluster::InvalidPatternID : pattIdConverter.findGroupID (rowSpanW, colSpanW, patt.data ());
292+ uint16_t row = bbox.rowMin , col = bbox.colMin ;
293+ if (pattID == CompCluster::InvalidPatternID || pattIdConverter.isGroup (pattID)) {
294+ if (pattID != CompCluster::InvalidPatternID) {
295+ // For groupped topologies, the reference pixel is the COG pixel
296+ float xCOG = 0 ., zCOG = 0 .;
297+ itsmft::ClusterPattern::getCOG (rowSpanW, colSpanW, patt.data (), xCOG, zCOG);
298+ row += round (xCOG);
299+ col += round (zCOG);
300+ }
301+ if (patternsPtr) {
302+ patternsPtr->emplace_back ((unsigned char )rowSpanW);
303+ patternsPtr->emplace_back ((unsigned char )colSpanW);
304+ int nBytes = rowSpanW * colSpanW / 8 ;
305+ if (((rowSpanW * colSpanW) % 8 ) != 0 ) {
306+ nBytes++;
307+ }
308+ patternsPtr->insert (patternsPtr->end (), std::begin (patt), std::begin (patt) + nBytes);
309+ }
310+ }
311+ compClusPtr->emplace_back (row, col, pattID, bbox.chipID );
312+ }
313+
233314} // namespace its3
234315} // namespace o2
235316#endif /* ALICEO2_ITS_CLUSTERER_H */
0 commit comments