1414
1515#include " TRKReconstruction/ClustererACTS.h"
1616#include " TRKBase/GeometryTGeo.h"
17+ #include " DataFormatsITSMFT/ClusterPattern.h"
1718#include < Acts/Clusterization/Clusterization.hpp>
1819
1920#include < algorithm>
21+ #include < array>
2022#include < numeric>
2123
2224using namespace o2 ::trk;
@@ -176,29 +178,6 @@ void ClustererACTS::process(gsl::span<const Digit> digits,
176178 continue ;
177179 }
178180
179- // template <typename CellCollection, typename ClusterCollection,
180- // std::size_t GridDim = 2,
181- // typename Connect = DefaultConnect<typename CellCollection::value_type, GridDim>>
182- // requires(GridDim == 1 || GridDim == 2)
183- // void createClusters(Acts::Ccl::ClusteringData& data,
184- // CellCollection& cells,
185- // ClusterCollection& clusters,
186- // Connect&& connect = Connect());
187- using Cell = Cell2D;
188- using CellCollection = std::vector<Cell>;
189- using Cluster = Cluster2D;
190- using ClusterCollection = std::vector<Cluster>;
191- CellCollection cells;
192- Acts::Ccl::ClusteringData data;
193- ClusterCollection collection;
194-
195- Acts::Ccl::createClusters<CellCollection, ClusterCollection, 2 >(data,
196- cells,
197- collection,
198- Acts::Ccl::DefaultConnect<Cell, 2 >(false ));
199-
200- LOG (debug) << " Clustering with ACTS, found " << collection.size () << " clusters in ROF " << iROF;
201-
202181 // Sort digit indices within this ROF by (chipID, col, row) so we can process
203182 // chip by chip, column by column -- the same ordering the ALPIDE scanner expects.
204183 mSortIdx .resize (nEntries);
@@ -215,6 +194,17 @@ void ClustererACTS::process(gsl::span<const Digit> digits,
215194 return da.getRow () < db.getRow ();
216195 });
217196
197+ // Type aliases for ACTS clustering
198+ using Cell = Cell2D;
199+ using CellCollection = std::vector<Cell>;
200+ using Cluster = Cluster2D;
201+ using ClusterCollection = std::vector<Cluster>;
202+ static constexpr int GridDim = 2 ; // /< Dimensionality of the clustering grid (2D for pixel detectors)
203+
204+ CellCollection cells; // Input collection of cells (pixels) to be clustered
205+ Acts::Ccl::ClusteringData data; // Internal data structure used by ACTS clustering algorithm
206+ ClusterCollection clsCollection; // Output collection of clusters found by the algorithm
207+
218208 // Process one chip at a time
219209 int sliceStart = 0 ;
220210 while (sliceStart < nEntries) {
@@ -225,9 +215,139 @@ void ClustererACTS::process(gsl::span<const Digit> digits,
225215 }
226216 const int chipN = sliceStart - chipFirst;
227217
228- mThread ->processChip (digits, chipFirst, chipN, &clusters, &patterns, digitLabels, clusterLabels, geom);
229- }
218+ // Fill cells from digits for this chip
219+ cells.clear ();
220+ data.clear ();
221+ clsCollection.clear ();
222+ cells.reserve (chipN);
223+ for (int i = chipFirst; i < chipFirst + chipN; ++i) {
224+ const auto & digit = digits[mSortIdx [i]];
225+ cells.emplace_back (digit.getRow (), digit.getColumn ());
226+ }
227+
228+ LOG (debug) << " Clustering with ACTS on chip " << chipID << " " << cells.size () << " digits" ;
229+ Acts::Ccl::createClusters<CellCollection, ClusterCollection, GridDim>(data,
230+ cells,
231+ clsCollection,
232+ Acts::Ccl::DefaultConnect<Cell, GridDim>(false ));
233+
234+ LOG (debug) << " found " << clsCollection.size () << " clusters" ;
235+
236+ // Convert ACTS clusters to O2 clusters
237+ for (const auto & actsCluster : clsCollection) {
238+ if (actsCluster.cells .empty ()) {
239+ continue ;
240+ }
241+
242+ // Calculate bounding box
243+ uint16_t rowMin = static_cast <uint16_t >(actsCluster.cells [0 ].row );
244+ uint16_t rowMax = rowMin;
245+ uint16_t colMin = static_cast <uint16_t >(actsCluster.cells [0 ].col );
246+ uint16_t colMax = colMin;
247+
248+ for (const auto & cell : actsCluster.cells ) {
249+ rowMin = std::min (rowMin, static_cast <uint16_t >(cell.row ));
250+ rowMax = std::max (rowMax, static_cast <uint16_t >(cell.row ));
251+ colMin = std::min (colMin, static_cast <uint16_t >(cell.col ));
252+ colMax = std::max (colMax, static_cast <uint16_t >(cell.col ));
253+ }
254+
255+ const uint16_t rowSpan = rowMax - rowMin + 1 ;
256+ const uint16_t colSpan = colMax - colMin + 1 ;
257+
258+ // Check if cluster needs splitting (too large for pattern encoding)
259+ const bool isHuge = rowSpan > o2::itsmft::ClusterPattern::MaxRowSpan ||
260+ colSpan > o2::itsmft::ClusterPattern::MaxColSpan;
261+
262+ if (isHuge) {
263+ // Split huge cluster into MaxRowSpan x MaxColSpan tiles
264+ LOG (warning) << " Splitting huge TRK cluster: chipID " << chipID
265+ << " , rows " << rowMin << " :" << rowMax
266+ << " cols " << colMin << " :" << colMax;
267+
268+ for (uint16_t tileColMin = colMin; tileColMin <= colMax;
269+ tileColMin = static_cast <uint16_t >(tileColMin + o2::itsmft::ClusterPattern::MaxColSpan)) {
270+ uint16_t tileColMax = std::min (colMax, static_cast <uint16_t >(tileColMin + o2::itsmft::ClusterPattern::MaxColSpan - 1 ));
271+
272+ for (uint16_t tileRowMin = rowMin; tileRowMin <= rowMax;
273+ tileRowMin = static_cast <uint16_t >(tileRowMin + o2::itsmft::ClusterPattern::MaxRowSpan)) {
274+ uint16_t tileRowMax = std::min (rowMax, static_cast <uint16_t >(tileRowMin + o2::itsmft::ClusterPattern::MaxRowSpan - 1 ));
275+
276+ // Collect cells in this tile
277+ std::vector<std::pair<uint16_t , uint16_t >> tileCells;
278+ for (const auto & cell : actsCluster.cells ) {
279+ uint16_t r = static_cast <uint16_t >(cell.row );
280+ uint16_t c = static_cast <uint16_t >(cell.col );
281+ if (r >= tileRowMin && r <= tileRowMax && c >= tileColMin && c <= tileColMax) {
282+ tileCells.emplace_back (r, c);
283+ }
284+ }
285+
286+ if (tileCells.empty ()) {
287+ continue ;
288+ }
289+
290+ uint16_t tileRowSpan = tileRowMax - tileRowMin + 1 ;
291+ uint16_t tileColSpan = tileColMax - tileColMin + 1 ;
292+
293+ // Encode pattern for this tile
294+ std::array<unsigned char , o2::itsmft::ClusterPattern::MaxPatternBytes> patt{};
295+ for (const auto & [r, c] : tileCells) {
296+ uint32_t ir = r - tileRowMin;
297+ uint32_t ic = c - tileColMin;
298+ int nbit = ir * tileColSpan + ic;
299+ patt[nbit >> 3 ] |= (0x1 << (7 - (nbit % 8 )));
300+ }
301+ patterns.emplace_back (static_cast <unsigned char >(tileRowSpan));
302+ patterns.emplace_back (static_cast <unsigned char >(tileColSpan));
303+ const int nBytes = (tileRowSpan * tileColSpan + 7 ) / 8 ;
304+ patterns.insert (patterns.end (), patt.begin (), patt.begin () + nBytes);
305+
306+ // Create O2 cluster for this tile
307+ o2::trk::Cluster cluster;
308+ cluster.chipID = chipID;
309+ cluster.row = tileRowMin;
310+ cluster.col = tileColMin;
311+ cluster.size = static_cast <uint16_t >(tileCells.size ());
312+ if (geom) {
313+ cluster.subDetID = static_cast <int16_t >(geom->getSubDetID (chipID));
314+ cluster.layer = static_cast <int16_t >(geom->getLayer (chipID));
315+ cluster.disk = static_cast <int16_t >(geom->getDisk (chipID));
316+ }
317+ clusters.emplace_back (cluster);
318+ }
319+ }
320+ } else {
321+ // Normal cluster - encode directly
322+ std::array<unsigned char , o2::itsmft::ClusterPattern::MaxPatternBytes> patt{};
323+ for (const auto & cell : actsCluster.cells ) {
324+ uint32_t ir = static_cast <uint32_t >(cell.row - rowMin);
325+ uint32_t ic = static_cast <uint32_t >(cell.col - colMin);
326+ int nbit = ir * colSpan + ic;
327+ patt[nbit >> 3 ] |= (0x1 << (7 - (nbit % 8 )));
328+ }
329+ patterns.emplace_back (static_cast <unsigned char >(rowSpan));
330+ patterns.emplace_back (static_cast <unsigned char >(colSpan));
331+ const int nBytes = (rowSpan * colSpan + 7 ) / 8 ;
332+ patterns.insert (patterns.end (), patt.begin (), patt.begin () + nBytes);
333+
334+ // Create O2 cluster
335+ o2::trk::Cluster cluster;
336+ cluster.chipID = chipID;
337+ cluster.row = rowMin;
338+ cluster.col = colMin;
339+ cluster.size = static_cast <uint16_t >(actsCluster.cells .size ());
340+ if (geom) {
341+ cluster.subDetID = static_cast <int16_t >(geom->getSubDetID (chipID));
342+ cluster.layer = static_cast <int16_t >(geom->getLayer (chipID));
343+ cluster.disk = static_cast <int16_t >(geom->getDisk (chipID));
344+ }
345+ clusters.emplace_back (cluster);
346+ }
347+ }
230348
349+ LOG (debug) << " clusterization of chip " << chipID << " completed!" ;
350+ }
231351 clusterROFs.emplace_back (inROF.getBCData (), inROF.getROFrame (),
232352 outFirst, static_cast <int >(clusters.size ()) - outFirst);
233353 }
0 commit comments