Skip to content

Commit d40e63f

Browse files
author
Marcello Di Costanzo
committed
Implement cluster finder with spatial and timing constraints
1 parent de03530 commit d40e63f

23 files changed

Lines changed: 1005 additions & 136 deletions

File tree

Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ o2_add_library(DataFormatsIOTOF
1313
SOURCES src/Digit.cxx
1414
# SOURCES src/MCLabel.cxx
1515
SOURCES src/Cluster.cxx
16-
PUBLIC_LINK_LIBRARIES O2::DataFormatsITSMFT)
16+
PUBLIC_LINK_LIBRARIES O2::DataFormatsITSMFT
17+
O2::IOTOFBase
18+
O2::FrameworkLogger)
1719

1820
o2_target_root_dictionary(DataFormatsIOTOF
1921
HEADERS include/DataFormatsIOTOF/Digit.h
Lines changed: 158 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
1+
// Copyright 2019-2020 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,28 +9,172 @@
99
// granted to it by virtue of its status as an Intergovernmental Organization
1010
// or submit itself to any jurisdiction.
1111

12-
#ifndef ALICEO2_DATAFORMATSIOTOF_CLUSTER_H
13-
#define ALICEO2_DATAFORMATSIOTOF_CLUSTER_H
12+
/// \file Cluster.h
13+
/// \brief Definition of the IOTOF cluster
14+
#ifndef ALICEO2_IOTOF_CLUSTER_H
15+
#define ALICEO2_IOTOF_CLUSTER_H
1416

15-
#include <Rtypes.h>
1617
#include <cstdint>
1718
#include <string>
19+
#include <iosfwd>
20+
#include <Rtypes.h>
21+
22+
#include "Framework/Logger.h"
23+
24+
namespace o2
25+
{
26+
namespace iotof
27+
{
28+
29+
/// Compact encoding for ALICE3 IOTOF cluster parameters inside a single 64-bit word.
30+
struct ClusterInfo {
31+
// Bit widths (Total: 52 bits out of 64)
32+
static constexpr int NBitsRow = 9;
33+
static constexpr int NBitsCol = 8;
34+
static constexpr int NBitsRowSpan = 4;
35+
static constexpr int NBitsColSpan = 4;
36+
static constexpr int NBitsPattern = 16;
37+
static constexpr int NBitsTopology = 11;
38+
39+
// Bit offsets (ordered logically from LSB to MSB)
40+
static constexpr int ShiftRow = 0;
41+
static constexpr int ShiftCol = ShiftRow + NBitsRow; // 9
42+
static constexpr int ShiftRowSpan = ShiftCol + NBitsCol; // 17
43+
static constexpr int ShiftColSpan = ShiftRowSpan + NBitsRowSpan; // 21
44+
static constexpr int ShiftPattern = ShiftColSpan + NBitsColSpan; // 25
45+
static constexpr int ShiftTopology = ShiftPattern + NBitsPattern; // 41
46+
47+
// Bit masks
48+
static constexpr uint64_t MaskRow = (1ULL << NBitsRow) - 1;
49+
static constexpr uint64_t MaskCol = (1ULL << NBitsCol) - 1;
50+
static constexpr uint64_t MaskRowSpan = (1ULL << NBitsRowSpan) - 1;
51+
static constexpr uint64_t MaskColSpan = (1ULL << NBitsColSpan) - 1;
52+
static constexpr uint64_t MaskPattern = (1ULL << NBitsPattern) - 1;
53+
static constexpr uint64_t MaskTopology = (1ULL << NBitsTopology) - 1;
54+
55+
uint64_t data{0};
56+
57+
// Constructors
58+
constexpr ClusterInfo() = default;
59+
constexpr ClusterInfo(uint64_t d) : data(d) {}
60+
61+
// Static packer
62+
static constexpr uint64_t pack(uint32_t row, uint32_t col, uint32_t rowSpan,
63+
uint32_t colSpan, uint32_t pattern, uint32_t topology) {
64+
return ((static_cast<uint64_t>(row) & MaskRow) << ShiftRow) |
65+
((static_cast<uint64_t>(col) & MaskCol) << ShiftCol) |
66+
((static_cast<uint64_t>(rowSpan) & MaskRowSpan) << ShiftRowSpan) |
67+
((static_cast<uint64_t>(colSpan) & MaskColSpan) << ShiftColSpan) |
68+
((static_cast<uint64_t>(pattern) & MaskPattern) << ShiftPattern) |
69+
((static_cast<uint64_t>(topology) & MaskTopology) << ShiftTopology);
70+
}
1871

19-
namespace o2::iotof
72+
// Getters
73+
constexpr uint32_t getRow() const { return (data >> ShiftRow) & MaskRow; }
74+
constexpr uint32_t getCol() const { return (data >> ShiftCol) & MaskCol; }
75+
constexpr uint32_t getRowSpan() const { return (data >> ShiftRowSpan) & MaskRowSpan; }
76+
constexpr uint32_t getColSpan() const { return (data >> ShiftColSpan) & MaskColSpan; }
77+
constexpr uint32_t getPattern() const { return (data >> ShiftPattern) & MaskPattern; }
78+
constexpr uint32_t getTopology() const { return (data >> ShiftTopology) & MaskTopology; }
79+
80+
// Setters
81+
constexpr void setRow(uint32_t r) {
82+
data = (data & ~(MaskRow << ShiftRow)) | ((static_cast<uint64_t>(r) & MaskRow) << ShiftRow);
83+
}
84+
constexpr void setCol(uint32_t c) {
85+
data = (data & ~(MaskCol << ShiftCol)) | ((static_cast<uint64_t>(c) & MaskCol) << ShiftCol);
86+
}
87+
constexpr void setRowSpan(uint32_t rs) {
88+
data = (data & ~(MaskRowSpan << ShiftRowSpan)) | ((static_cast<uint64_t>(rs) & MaskRowSpan) << ShiftRowSpan);
89+
}
90+
constexpr void setColSpan(uint32_t cs) {
91+
data = (data & ~(MaskColSpan << ShiftColSpan)) | ((static_cast<uint64_t>(cs) & MaskColSpan) << ShiftColSpan);
92+
}
93+
constexpr void setPattern(uint32_t p) {
94+
data = (data & ~(MaskPattern << ShiftPattern)) | ((static_cast<uint64_t>(p) & MaskPattern) << ShiftPattern);
95+
}
96+
constexpr void setTopology(uint32_t t) {
97+
data = (data & ~(MaskTopology << ShiftTopology)) | ((static_cast<uint64_t>(t) & MaskTopology) << ShiftTopology);
98+
}
99+
100+
ClassDefNV(ClusterInfo, 1);
101+
};
102+
103+
class Cluster
20104
{
105+
public:
106+
static constexpr uint16_t InvalidPatternID = static_cast<uint16_t>(ClusterInfo::MaskPattern);
107+
108+
Cluster() = default;
109+
Cluster(UShort_t row, UShort_t col, UShort_t rowSpan, UShort_t colSpan, UShort_t patt, UShort_t topo, UShort_t chipID = 0, time_t time = 0.0f)
110+
: mChipID(chipID), mTime(time)
111+
{
112+
mClusterInfo.data = ClusterInfo::pack(row, col, rowSpan, colSpan, patt, topo);
113+
}
114+
115+
void set(UShort_t row, UShort_t col, UShort_t rowSpan, UShort_t colSpan, UShort_t patt, UShort_t topo, UShort_t chipID, time_t time)
116+
{
117+
mClusterInfo.data = ClusterInfo::pack(row, col, rowSpan, colSpan, patt, topo);
118+
mChipID = chipID;
119+
mTime = time;
120+
}
21121

22-
struct Cluster {
23-
uint16_t chipID = 0;
24-
uint16_t row = 0;
25-
uint16_t col = 0;
26-
uint16_t size = 1;
27-
double time = 0.0;
122+
// Unpack Getters
123+
uint32_t getRow() const { return mClusterInfo.getRow(); }
124+
uint32_t getCol() const { return mClusterInfo.getCol(); }
125+
uint32_t getRowSpan() const { return mClusterInfo.getRowSpan(); }
126+
uint32_t getColSpan() const { return mClusterInfo.getColSpan(); }
127+
uint32_t getPattern() const { return mClusterInfo.getPattern(); }
128+
uint32_t getTopology() const { return mClusterInfo.getTopology(); }
129+
int getSize() const {
130+
// Count the number of set bits in the pattern to determine the size of the cluster
131+
uint32_t pattern = getPattern();
132+
int size = 0;
133+
while (pattern) {
134+
size += pattern & 1;
135+
pattern >>= 1;
136+
}
137+
return size;
138+
}
28139

140+
// BaseCluster / Interface Compatibility Getters
141+
uint32_t getChipID() const { return mChipID; }
142+
uint32_t getSensorID() const { return mChipID; }
143+
time_t getTime() const { return mTime; }
144+
uint64_t getPackedData() const { return mClusterInfo.data; }
145+
146+
// Setters
147+
void setRow(UShort_t r) { mClusterInfo.setRow(r); }
148+
void setCol(UShort_t c) { mClusterInfo.setCol(c); }
149+
void setRowSpan(UShort_t rs) { mClusterInfo.setRowSpan(rs); }
150+
void setColSpan(UShort_t cs) { mClusterInfo.setColSpan(cs); }
151+
void setPatternID(UShort_t p) { mClusterInfo.setPattern(p); }
152+
void setTopology(UShort_t t) { mClusterInfo.setTopology(t); }
153+
void setChipID(UShort_t c) { mChipID = c; }
154+
void setTime(time_t t) { mTime = t; }
155+
156+
// Operators & Debugging
157+
bool operator==(const Cluster& cl) const
158+
{
159+
return mClusterInfo.data == cl.mClusterInfo.data && mChipID == cl.mChipID && mTime == cl.mTime;
160+
}
161+
162+
void print() const;
29163
std::string asString() const;
30164

31-
ClassDefNV(Cluster, 1);
165+
private:
166+
ClusterInfo mClusterInfo{}; ///< 64-bit packed structure containing geometry/topology
167+
UShort_t mChipID{0}; ///< Chip / Sensor ID
168+
float mTime{0.0f}; ///< Hit timing information
169+
170+
void sanityCheck();
171+
172+
ClassDefNV(Cluster, 2);
32173
};
33174

34-
} // namespace o2::iotof
175+
} // namespace iotof
176+
} // namespace o2
177+
178+
std::ostream& operator<<(std::ostream& stream, const o2::iotof::Cluster& cl);
35179

36-
#endif
180+
#endif /* ALICEO2_IOTOF_CLUSTER_H */
Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
1+
// Copyright 2019-2020 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,19 +9,65 @@
99
// granted to it by virtue of its status as an Intergovernmental Organization
1010
// or submit itself to any jurisdiction.
1111

12+
/// \file Cluster.cxx
13+
/// \brief Implementation of the IOTOF cluster
14+
1215
#include "DataFormatsIOTOF/Cluster.h"
13-
#include <sstream>
16+
#include "Framework/Logger.h"
17+
#include <cassert>
18+
#include <iostream>
19+
#include <format>
1420

21+
// Root ClassImp macros for serialization metadata
22+
ClassImp(o2::iotof::ClusterInfo);
1523
ClassImp(o2::iotof::Cluster);
1624

17-
namespace o2::iotof
25+
namespace o2
26+
{
27+
namespace iotof
1828
{
1929

2030
std::string Cluster::asString() const
2131
{
22-
std::ostringstream stream;
23-
stream << "chip=" << chipID << " row=" << row << " col=" << col << " size=" << size;
24-
return stream.str();
32+
LOG(debug) << "[Cluster::asString] Converting Cluster to string";
33+
return std::format(
34+
"chip: {:5d} | row: {:3d} col: {:3d} | span: {:2d}x{:2d} | pattern: {:5d} topology: {:4d}",
35+
getChipID(),
36+
getRow(),
37+
getCol(),
38+
getRowSpan(),
39+
getColSpan(),
40+
getPattern(),
41+
getTopology()
42+
);
43+
}
44+
45+
//______________________________________________________________________________
46+
void Cluster::print() const
47+
{
48+
std::cout << *this << "\n";
2549
}
2650

27-
} // namespace o2::iotof
51+
//______________________________________________________________________________
52+
void Cluster::sanityCheck()
53+
{
54+
LOG(debug) << "[Cluster::sanityCheck] Performing sanity check on Cluster fields";
55+
56+
// Ensure extracted values fit within allowed bit masks
57+
assert(getRow() <= ClusterInfo::MaskRow);
58+
assert(getCol() <= ClusterInfo::MaskCol);
59+
assert(getRowSpan() <= ClusterInfo::MaskRowSpan);
60+
assert(getColSpan() <= ClusterInfo::MaskColSpan);
61+
assert(getPattern() <= ClusterInfo::MaskPattern);
62+
assert(getTopology() <= ClusterInfo::MaskTopology);
63+
}
64+
65+
} // namespace iotof
66+
} // namespace o2
67+
68+
// Stream operator implementation
69+
std::ostream& operator<<(std::ostream& stream, const o2::iotof::Cluster& cl)
70+
{
71+
stream << cl.asString();
72+
return stream;
73+
}

Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/src/DataFormatsIOTOFLinkDef.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#pragma link C++ class o2::iotof::Digit + ;
1919
#pragma link C++ class std::vector < o2::iotof::Digit> + ;
2020

21+
#pragma link C++ class o2::iotof::ClusterInfo + ;
2122
#pragma link C++ class o2::iotof::Cluster + ;
2223
#pragma link C++ class std::vector < o2::iotof::Cluster> + ;
2324

Detectors/Upgrades/ALICE3/IOTOF/base/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@
1111

1212
o2_add_library(IOTOFBase
1313
SOURCES src/GeometryTGeo.cxx
14+
src/Segmentation.cxx
1415
src/IOTOFBaseParam.cxx
1516
PUBLIC_LINK_LIBRARIES O2::DetectorsBase
1617
O2::MathUtils)
1718

1819
o2_target_root_dictionary(IOTOFBase
1920
HEADERS include/IOTOFBase/GeometryTGeo.h
21+
include/IOTOFBase/Segmentation.h
2022
include/IOTOFBase/IOTOFBaseParam.h)

0 commit comments

Comments
 (0)