Skip to content

Commit a8b31f7

Browse files
committed
ITSMFT: ITS3: reuse clusterizer
Signed-off-by: Felix Schlepper <felix.schlepper@cern.ch>
1 parent 5f89a2e commit a8b31f7

12 files changed

Lines changed: 566 additions & 1302 deletions

File tree

Detectors/ITSMFT/common/reconstruction/CMakeLists.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ o2_target_root_dictionary(
4949
include/ITSMFTReconstruction/DigitPixelReader.h
5050
include/ITSMFTReconstruction/RawPixelReader.h
5151
include/ITSMFTReconstruction/PixelData.h
52-
include/ITSMFTReconstruction/Clusterer.h
5352
include/ITSMFTReconstruction/ClustererParam.h
5453
include/ITSMFTReconstruction/BuildTopologyDictionary.h
5554
include/ITSMFTReconstruction/LookUp.h
@@ -67,4 +66,3 @@ if (OpenMP_CXX_FOUND)
6766
target_compile_definitions(${targetName} PRIVATE WITH_OPENMP)
6867
target_link_libraries(${targetName} PRIVATE OpenMP::OpenMP_CXX)
6968
endif()
70-

Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/Clusterer.h

Lines changed: 540 additions & 36 deletions
Large diffs are not rendered by default.

Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/LookUp.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,14 @@ class LookUp
3737
LookUp(std::string fileName);
3838
static int groupFinder(int nRow, int nCol);
3939
int findGroupID(int nRow, int nCol, const unsigned char patt[ClusterPattern::MaxPatternBytes]) const;
40+
int findGroupID(int nRow, int nCol, uint16_t, const unsigned char patt[ClusterPattern::MaxPatternBytes]) const { return findGroupID(nRow, nCol, patt); }
4041
int getTopologiesOverThreshold() const { return mTopologiesOverThreshold; }
4142
void loadDictionary(std::string fileName);
4243
void setDictionary(const TopologyDictionary* dict);
4344
bool isGroup(int id) const { return mDictionary.isGroup(id); }
45+
bool isGroup(int id, uint16_t) const { return isGroup(id); }
4446
int size() const { return mDictionary.getSize(); }
47+
int size(uint16_t) const { return size(); }
4548
auto getPattern(int id) const { return mDictionary.getPattern(id); }
4649
auto getDictionaty() const { return mDictionary; }
4750

Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx

Lines changed: 2 additions & 494 deletions
Large diffs are not rendered by default.

Detectors/ITSMFT/common/reconstruction/src/ITSMFTReconstructionLinkDef.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
#pragma link off all classes;
1616
#pragma link off all functions;
1717

18-
#pragma link C++ class o2::itsmft::Clusterer + ;
1918
#pragma link C++ class o2::itsmft::PixelReader + ;
2019
#pragma link C++ class o2::itsmft::DigitPixelReader + ;
2120
#pragma link C++ class o2::itsmft::RawPixelReader < o2::itsmft::ChipMappingITS> + ;

Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/STFDecoderSpec.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "Framework/Task.h"
2525
#include "DataFormatsITSMFT/DPLAlpideParam.h"
2626
#include "DataFormatsITSMFT/ROFRecord.h"
27+
#include "ITSMFTReconstruction/Clusterer.h"
2728
#include "ITSMFTReconstruction/ChipMappingITS.h"
2829
#include "ITSMFTReconstruction/ChipMappingMFT.h"
2930
#include "ITSMFTReconstruction/RawPixelDecoder.h"
@@ -38,7 +39,6 @@ class GRPGeomRequest;
3839
}
3940
namespace itsmft
4041
{
41-
class Clusterer;
4242

4343
struct STFDecoderInp {
4444
bool doClusters = true;

Detectors/Upgrades/ITS3/reconstruction/CMakeLists.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,7 @@ o2_add_library(ITS3Reconstruction
3333

3434
o2_target_root_dictionary(
3535
ITS3Reconstruction
36-
HEADERS include/ITS3Reconstruction/Clusterer.h
37-
include/ITS3Reconstruction/TopologyDictionary.h
36+
HEADERS include/ITS3Reconstruction/TopologyDictionary.h
3837
include/ITS3Reconstruction/BuildTopologyDictionary.h
3938
include/ITS3Reconstruction/LookUp.h
4039
include/ITS3Reconstruction/IOUtils.h
Lines changed: 10 additions & 303 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
1+
// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
22
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
33
// All rights not expressly granted are reserved.
44
//
@@ -9,312 +9,19 @@
99
// granted to it by virtue of its status as an Intergovernmental Organization
1010
// or submit itself to any jurisdiction.
1111

12-
/// \file Clusterer.h
13-
/// \brief Definition of the ITS cluster finder
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>
12+
#ifndef ALICEO2_ITS3_CLUSTERER_H
13+
#define ALICEO2_ITS3_CLUSTERER_H
2814

2915
#include "ITSMFTBase/SegmentationAlpide.h"
30-
#include "DataFormatsITSMFT/CompCluster.h"
31-
#include "DataFormatsITSMFT/ROFRecord.h"
32-
#include "ITSMFTReconstruction/PixelReader.h"
33-
#include "ITSMFTReconstruction/PixelData.h"
16+
#include "ITSMFTReconstruction/Clusterer.h"
17+
#include "ITS3Base/SegmentationMosaix.h"
3418
#include "ITS3Reconstruction/LookUp.h"
35-
#include "SimulationDataFormat/MCCompLabel.h"
36-
#include "CommonConstants/LHCConstants.h"
37-
38-
#ifdef _PERFORM_TIMING_
39-
#include <TStopwatch.h>
40-
#endif
41-
42-
class TTree;
43-
44-
namespace o2
45-
{
46-
class MCCompLabel;
47-
namespace dataformats
48-
{
49-
template <typename T>
50-
class ConstMCTruthContainerView;
51-
template <typename T>
52-
class MCTruthContainer;
53-
} // namespace dataformats
54-
55-
namespace its3
56-
{
5719

58-
using CompClusCont = std::vector<itsmft::CompClusterExt>;
59-
using PatternCont = std::vector<unsigned char>;
60-
using ROFRecCont = std::vector<itsmft::ROFRecord>;
61-
62-
// template <class CompClusCont, class PatternCont, class ROFRecCont> // container types (PMR or std::vectors)
63-
64-
class Clusterer
20+
namespace o2::its3
6521
{
66-
using PixelReader = o2::itsmft::PixelReader;
67-
using PixelData = o2::itsmft::PixelData;
68-
using ChipPixelData = o2::itsmft::ChipPixelData;
69-
using CompCluster = o2::itsmft::CompCluster;
70-
using CompClusterExt = o2::itsmft::CompClusterExt;
71-
using Label = o2::MCCompLabel;
72-
using MCTruth = o2::dataformats::MCTruthContainer<o2::MCCompLabel>;
73-
using ConstMCTruth = o2::dataformats::ConstMCTruthContainerView<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-
[[nodiscard]] auto rowSpan() const { return rowMax - rowMin + 1; }
88-
[[nodiscard]] 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-
112-
//=========================================================
113-
/// methods and transient data used within a thread
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-
123-
struct ClustererThread {
124-
Clusterer* parent = nullptr; // parent clusterer
125-
int id = -1;
126-
// buffers for entries in preClusterIndices in 2 columns, to avoid boundary checks, we reserve
127-
// extra elements in the beginning and the end
128-
int* column1 = nullptr;
129-
int* column2 = nullptr;
130-
int* curr = nullptr; // pointer on the 1st row of currently processed columnsX
131-
int* prev = nullptr; // pointer on the 1st row of previously processed columnsX
132-
int size = itsmft::SegmentationAlpide::NRows + 2;
133-
// pixels[].first is the index of the next pixel of the same precluster in the pixels
134-
// pixels[].second is the index of the referred pixel in the ChipPixelData (element of mChips)
135-
std::vector<std::pair<int, uint32_t>> pixels;
136-
std::vector<int> preClusterHeads; // index of precluster head in the pixels
137-
std::vector<int> preClusterIndices;
138-
uint16_t currCol = 0xffff; ///< Column being processed
139-
bool noLeftCol = true; ///< flag that there is no column on the left to check
140-
std::array<Label, MaxLabels> labelsBuff; //! temporary buffer for building cluster labels
141-
std::vector<PixelData> pixArrBuff; //! temporary buffer for pattern calc.
142-
//
143-
/// temporary storage for the thread output
144-
CompClusCont compClusters;
145-
PatternCont patterns;
146-
MCTruth labels;
147-
std::vector<ThreadStat> stats; // statistics for each thread results, used at merging
148-
///
149-
///< reset column buffer, for the performance reasons we use memset
150-
void resetColumn(int* buff) const { std::memset(buff, -1, sizeof(int) * (size - 2)); }
151-
152-
///< swap current and previous column buffers
153-
void swapColumnBuffers() { std::swap(prev, curr); }
154-
155-
///< add cluster at row (entry ip in the ChipPixeData) to the precluster with given index
156-
void expandPreCluster(uint32_t ip, uint16_t row, int preClusIndex)
157-
{
158-
auto& firstIndex = preClusterHeads[preClusterIndices[preClusIndex]];
159-
pixels.emplace_back(firstIndex, ip);
160-
firstIndex = pixels.size() - 1;
161-
curr[row] = preClusIndex;
162-
}
163-
164-
///< add new precluster at given row of current column for the fired pixel with index ip in the ChipPixelData
165-
void addNewPrecluster(uint32_t ip, uint16_t row)
166-
{
167-
preClusterHeads.push_back(pixels.size());
168-
// new head does not point yet (-1) on other pixels, store just the entry of the pixel in the ChipPixelData
169-
pixels.emplace_back(-1, ip);
170-
int lastIndex = preClusterIndices.size();
171-
preClusterIndices.push_back(lastIndex);
172-
curr[row] = lastIndex; // store index of the new precluster in the current column buffer
173-
}
174-
175-
void fetchMCLabels(int digID, const ConstMCTruth* labelsDig, int& nfilled);
176-
void initChip(const ChipPixelData* curChipData, uint32_t first);
177-
void updateChip(const ChipPixelData* curChipData, uint32_t ip);
178-
void finishChip(ChipPixelData* curChipData, CompClusCont* compClus, PatternCont* patterns,
179-
const ConstMCTruth* labelsDig, MCTruth* labelsClus);
180-
void finishChipSingleHitFast(uint32_t hit, ChipPixelData* curChipData, CompClusCont* compClusPtr,
181-
PatternCont* patternsPtr, const ConstMCTruth* labelsDigPtr, MCTruth* labelsClusPTr);
182-
void process(uint16_t chip, uint16_t nChips, CompClusCont* compClusPtr, PatternCont* patternsPtr,
183-
const ConstMCTruth* labelsDigPtr, MCTruth* labelsClPtr, const itsmft::ROFRecord& rofPtr);
184-
185-
~ClustererThread()
186-
{
187-
delete[] column1;
188-
delete[] column2;
189-
}
22+
// Maximum number of rows is determined by Alpide
23+
using Clusterer = o2::itsmft::ClustererT<o2::its3::LookUp, o2::itsmft::SegmentationAlpide::NRows>;
24+
} // namespace o2::its3
25+
extern template class o2::itsmft::ClustererT<o2::its3::LookUp, o2::itsmft::SegmentationAlpide::NRows>;
19026

191-
ClustererThread(Clusterer* par = nullptr, int _id = -1) : parent(par), id(_id), curr(column2 + 1), prev(column1 + 1) {}
192-
ClustererThread(const ClustererThread&) = delete;
193-
ClustererThread(ClustererThread&&) = delete;
194-
ClustererThread& operator=(const ClustererThread&) = delete;
195-
ClustererThread& operator=(ClustererThread&&) = delete;
196-
};
197-
//=========================================================
198-
199-
Clusterer();
200-
Clusterer(Clusterer&&) = delete;
201-
Clusterer& operator=(Clusterer&&) = delete;
202-
~Clusterer() = default;
203-
Clusterer(const Clusterer&) = delete;
204-
Clusterer& operator=(const Clusterer&) = delete;
205-
206-
void process(int nThreads, PixelReader& r, CompClusCont* compClus, PatternCont* patterns, ROFRecCont* vecROFRec, MCTruth* labelsCl = nullptr);
207-
208-
template <typename VCLUS, typename VPAT>
209-
static void streamCluster(const std::vector<PixelData>& pixbuf, const std::array<Label, MaxLabels>* lblBuff, const BBox& bbox, const its3::LookUp& pattIdConverter,
210-
VCLUS* compClusPtr, VPAT* patternsPtr, MCTruth* labelsClusPtr, int nlab, bool isIB, bool isHuge = false);
211-
212-
bool isContinuousReadOut() const { return mContinuousReadout; }
213-
void setContinuousReadOut(bool v) { mContinuousReadout = v; }
214-
215-
int getMaxBCSeparationToMask() const { return mMaxBCSeparationToMask; }
216-
void setMaxBCSeparationToMask(int n) { mMaxBCSeparationToMask = n; }
217-
218-
int getMaxRowColDiffToMask() const { return mMaxRowColDiffToMask; }
219-
void setMaxRowColDiffToMask(int v) { mMaxRowColDiffToMask = v; }
220-
221-
int getMaxROFDepthToSquash() const { return mSquashingDepth; }
222-
void setMaxROFDepthToSquash(int v) { mSquashingDepth = v; }
223-
224-
int getMaxBCSeparationToSquash() const { return mMaxBCSeparationToSquash; }
225-
void setMaxBCSeparationToSquash(int n) { mMaxBCSeparationToSquash = n; }
226-
227-
void print() const;
228-
void clear();
229-
230-
///< load the dictionary of cluster topologies
231-
void setDictionary(const its3::TopologyDictionary* dict)
232-
{
233-
LOGP(info, "Setting TopologyDictionary with IB size={} & OB size={}", dict->getSize(true), dict->getSize(false));
234-
mPattIdConverter.setDictionary(dict);
235-
// dict->print();
236-
}
237-
238-
TStopwatch& getTimer() { return mTimer; } // cannot be const
239-
TStopwatch& getTimerMerge() { return mTimerMerge; } // cannot be const
240-
241-
void setNChips(int n)
242-
{
243-
mChips.resize(n);
244-
mChipsOld.resize(n);
245-
}
246-
247-
private:
248-
void flushClusters(CompClusCont* compClus, MCTruth* labels);
249-
250-
// clusterization options
251-
bool mContinuousReadout = true; ///< flag continuous readout
252-
253-
///< mask continuosly fired pixels in frames separated by less than this amount of BCs (fired from hit in prev. ROF)
254-
int mMaxBCSeparationToMask = static_cast<int>(6000. / o2::constants::lhc::LHCBunchSpacingNS + 10);
255-
int mMaxRowColDiffToMask = 0; ///< provide their difference in col/row is <= than this
256-
int mNHugeClus = 0; ///< number of encountered huge clusters
257-
258-
///< Squashing options
259-
int mSquashingDepth = 0; ///< squashing is applied to next N rofs
260-
int mMaxBCSeparationToSquash = 6000. / o2::constants::lhc::LHCBunchSpacingNS + 10;
261-
262-
std::vector<std::unique_ptr<ClustererThread>> mThreads; // buffers for threads
263-
std::vector<ChipPixelData> mChips; // currently processed ROF's chips data
264-
std::vector<ChipPixelData> mChipsOld; // previously processed ROF's chips data (for masking)
265-
std::vector<ChipPixelData*> mFiredChipsPtr; // pointers on the fired chips data in the decoder cache
266-
267-
its3::LookUp mPattIdConverter; //! Convert the cluster topology to the corresponding entry in the dictionary.
268-
//
269-
#ifdef _PERFORM_TIMING_
270-
TStopwatch mTimer;
271-
TStopwatch mTimerMerge;
27227
#endif
273-
};
274-
275-
template <typename VCLUS, typename VPAT>
276-
void Clusterer::streamCluster(const std::vector<PixelData>& pixbuf, const std::array<Label, MaxLabels>* lblBuff, const Clusterer::BBox& bbox, const its3::LookUp& pattIdConverter,
277-
VCLUS* compClusPtr, VPAT* patternsPtr, MCTruth* labelsClusPtr, int nlab, bool isIB, bool isHuge)
278-
{
279-
if (labelsClusPtr && lblBuff) { // MC labels were requested
280-
auto cnt = compClusPtr->size();
281-
for (int i = nlab; i--;) {
282-
labelsClusPtr->addElement(cnt, (*lblBuff)[i]);
283-
}
284-
}
285-
auto colSpanW = bbox.colSpan();
286-
auto rowSpanW = bbox.rowSpan();
287-
// add to compact clusters, which must be always filled
288-
std::array<unsigned char, itsmft::ClusterPattern::MaxPatternBytes> patt{};
289-
for (const auto& pix : pixbuf) {
290-
uint32_t ir = pix.getRowDirect() - bbox.rowMin, ic = pix.getCol() - bbox.colMin;
291-
int nbits = ir * colSpanW + ic;
292-
patt[nbits >> 3] |= (0x1 << (7 - (nbits % 8)));
293-
}
294-
uint16_t pattID = (isHuge || pattIdConverter.size(isIB) == 0) ? CompCluster::InvalidPatternID : pattIdConverter.findGroupID(rowSpanW, colSpanW, isIB, patt.data());
295-
uint16_t row = bbox.rowMin, col = bbox.colMin;
296-
LOGP(debug, "PattID: findGroupID({},{},{})={}", row, col, patt[0], pattID);
297-
if (pattID == CompCluster::InvalidPatternID || pattIdConverter.isGroup(pattID, isIB)) {
298-
if (pattID != CompCluster::InvalidPatternID) {
299-
// For groupped topologies, the reference pixel is the COG pixel
300-
float xCOG = 0., zCOG = 0.;
301-
itsmft::ClusterPattern::getCOG(rowSpanW, colSpanW, patt.data(), xCOG, zCOG);
302-
row += round(xCOG);
303-
col += round(zCOG);
304-
}
305-
if (patternsPtr) {
306-
patternsPtr->emplace_back((unsigned char)rowSpanW);
307-
patternsPtr->emplace_back((unsigned char)colSpanW);
308-
int nBytes = rowSpanW * colSpanW / 8;
309-
if (((rowSpanW * colSpanW) % 8) != 0) {
310-
nBytes++;
311-
}
312-
patternsPtr->insert(patternsPtr->end(), std::begin(patt), std::begin(patt) + nBytes);
313-
}
314-
}
315-
compClusPtr->emplace_back(row, col, pattID, bbox.chipID);
316-
}
317-
318-
} // namespace its3
319-
} // namespace o2
320-
#endif /* ALICEO2_ITS_CLUSTERER_H */

0 commit comments

Comments
 (0)