Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ o2_add_library(DataFormatsIOTOF
SOURCES src/Digit.cxx
# SOURCES src/MCLabel.cxx
SOURCES src/Cluster.cxx
PUBLIC_LINK_LIBRARIES O2::DataFormatsITSMFT)
PUBLIC_LINK_LIBRARIES O2::DataFormatsITSMFT
O2::IOTOFBase
O2::FrameworkLogger)

o2_target_root_dictionary(DataFormatsIOTOF
HEADERS include/DataFormatsIOTOF/Digit.h
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,172 @@
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

/// \file Cluster.h
/// \brief Definition of the IOTOF cluster
#ifndef ALICEO2_DATAFORMATSIOTOF_CLUSTER_H
#define ALICEO2_DATAFORMATSIOTOF_CLUSTER_H

#include <Rtypes.h>
#include <cstdint>
#include <string>
#include <iosfwd>
#include <Rtypes.h>

#include "Framework/Logger.h"

namespace o2
{
namespace iotof
{

/// Compact encoding for ALICE3 IOTOF cluster parameters inside a single 64-bit word.
struct ClusterInfo {
// Bit widths (Total: 52 bits out of 64)
static constexpr int NBitsRow = 9;
static constexpr int NBitsCol = 8;
static constexpr int NBitsRowSpan = 4;
static constexpr int NBitsColSpan = 4;
static constexpr int NBitsPattern = 16;
static constexpr int NBitsTopology = 11;

// Bit offsets (ordered logically from LSB to MSB)
static constexpr int ShiftRow = 0;
static constexpr int ShiftCol = ShiftRow + NBitsRow; // 9
static constexpr int ShiftRowSpan = ShiftCol + NBitsCol; // 17
static constexpr int ShiftColSpan = ShiftRowSpan + NBitsRowSpan; // 21
static constexpr int ShiftPattern = ShiftColSpan + NBitsColSpan; // 25
static constexpr int ShiftTopology = ShiftPattern + NBitsPattern; // 41

// Bit masks
static constexpr uint64_t MaskRow = (1ULL << NBitsRow) - 1;
static constexpr uint64_t MaskCol = (1ULL << NBitsCol) - 1;
static constexpr uint64_t MaskRowSpan = (1ULL << NBitsRowSpan) - 1;
static constexpr uint64_t MaskColSpan = (1ULL << NBitsColSpan) - 1;
static constexpr uint64_t MaskPattern = (1ULL << NBitsPattern) - 1;
static constexpr uint64_t MaskTopology = (1ULL << NBitsTopology) - 1;

uint64_t data{0};

// Constructors
constexpr ClusterInfo() = default;
constexpr ClusterInfo(uint64_t d) : data(d) {}

// Static packer
static constexpr uint64_t pack(uint32_t row, uint32_t col, uint32_t rowSpan,

Check failure on line 62 in Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/include/DataFormatsIOTOF/Cluster.h

View workflow job for this annotation

GitHub Actions / PR formatting / whitespace

Trailing spaces

Remove the trailing spaces at the end of the line.
uint32_t colSpan, uint32_t pattern, uint32_t topology) {
return ((static_cast<uint64_t>(row) & MaskRow) << ShiftRow) |
((static_cast<uint64_t>(col) & MaskCol) << ShiftCol) |
((static_cast<uint64_t>(rowSpan) & MaskRowSpan) << ShiftRowSpan) |
((static_cast<uint64_t>(colSpan) & MaskColSpan) << ShiftColSpan) |
((static_cast<uint64_t>(pattern) & MaskPattern) << ShiftPattern) |
((static_cast<uint64_t>(topology) & MaskTopology) << ShiftTopology);
}

namespace o2::iotof
// Getters
constexpr uint32_t getRow() const { return (data >> ShiftRow) & MaskRow; }
constexpr uint32_t getCol() const { return (data >> ShiftCol) & MaskCol; }
constexpr uint32_t getRowSpan() const { return (data >> ShiftRowSpan) & MaskRowSpan; }
constexpr uint32_t getColSpan() const { return (data >> ShiftColSpan) & MaskColSpan; }
constexpr uint32_t getPattern() const { return (data >> ShiftPattern) & MaskPattern; }
constexpr uint32_t getTopology() const { return (data >> ShiftTopology) & MaskTopology; }

// Setters
constexpr void setRow(uint32_t r) {
data = (data & ~(MaskRow << ShiftRow)) | ((static_cast<uint64_t>(r) & MaskRow) << ShiftRow);
}
constexpr void setCol(uint32_t c) {
data = (data & ~(MaskCol << ShiftCol)) | ((static_cast<uint64_t>(c) & MaskCol) << ShiftCol);
}
constexpr void setRowSpan(uint32_t rs) {
data = (data & ~(MaskRowSpan << ShiftRowSpan)) | ((static_cast<uint64_t>(rs) & MaskRowSpan) << ShiftRowSpan);
}
constexpr void setColSpan(uint32_t cs) {
data = (data & ~(MaskColSpan << ShiftColSpan)) | ((static_cast<uint64_t>(cs) & MaskColSpan) << ShiftColSpan);
}
constexpr void setPattern(uint32_t p) {
data = (data & ~(MaskPattern << ShiftPattern)) | ((static_cast<uint64_t>(p) & MaskPattern) << ShiftPattern);
}
constexpr void setTopology(uint32_t t) {
data = (data & ~(MaskTopology << ShiftTopology)) | ((static_cast<uint64_t>(t) & MaskTopology) << ShiftTopology);
}

ClassDefNV(ClusterInfo, 1);
};

class Cluster
{
public:
static constexpr uint16_t InvalidPatternID = static_cast<uint16_t>(ClusterInfo::MaskPattern);

Cluster() = default;
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)
: mChipID(chipID), mTime(time)
{
mClusterInfo.data = ClusterInfo::pack(row, col, rowSpan, colSpan, patt, topo);
}

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)
{
mClusterInfo.data = ClusterInfo::pack(row, col, rowSpan, colSpan, patt, topo);
mChipID = chipID;
mTime = time;
}

struct Cluster {
uint16_t chipID = 0;
uint16_t row = 0;
uint16_t col = 0;
uint16_t size = 1;
double time = 0.0;
// Unpack Getters
uint32_t getRow() const { return mClusterInfo.getRow(); }
uint32_t getCol() const { return mClusterInfo.getCol(); }
uint32_t getRowSpan() const { return mClusterInfo.getRowSpan(); }
uint32_t getColSpan() const { return mClusterInfo.getColSpan(); }
uint32_t getPattern() const { return mClusterInfo.getPattern(); }
uint32_t getTopology() const { return mClusterInfo.getTopology(); }
int getSize() const {
// Count the number of set bits in the pattern to determine the size of the cluster
uint32_t pattern = getPattern();
int size = 0;
while (pattern) {
size += pattern & 1;
pattern >>= 1;
}
return size;
}

// BaseCluster / Interface Compatibility Getters
uint32_t getChipID() const { return mChipID; }
uint32_t getSensorID() const { return mChipID; }
time_t getTime() const { return mTime; }
uint64_t getPackedData() const { return mClusterInfo.data; }

// Setters
void setRow(UShort_t r) { mClusterInfo.setRow(r); }
void setCol(UShort_t c) { mClusterInfo.setCol(c); }
void setRowSpan(UShort_t rs) { mClusterInfo.setRowSpan(rs); }
void setColSpan(UShort_t cs) { mClusterInfo.setColSpan(cs); }
void setPatternID(UShort_t p) { mClusterInfo.setPattern(p); }
void setTopology(UShort_t t) { mClusterInfo.setTopology(t); }
void setChipID(UShort_t c) { mChipID = c; }
void setTime(time_t t) { mTime = t; }

// Operators & Debugging
bool operator==(const Cluster& cl) const
{
return mClusterInfo.data == cl.mClusterInfo.data && mChipID == cl.mChipID && mTime == cl.mTime;
}

void print() const;
std::string asString() const;

ClassDefNV(Cluster, 1);
private:
ClusterInfo mClusterInfo{}; ///< 64-bit packed structure containing geometry/topology
UShort_t mChipID{0}; ///< Chip / Sensor ID
float mTime{0.0f}; ///< Hit timing information

void sanityCheck();

ClassDefNV(Cluster, 2);
};

} // namespace o2::iotof
} // namespace iotof
} // namespace o2

std::ostream& operator<<(std::ostream& stream, const o2::iotof::Cluster& cl);

#endif
#endif /* ALICEO2_DATAFORMATSIOTOF_CLUSTER_H */
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,65 @@
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

/// \file Cluster.cxx
/// \brief Implementation of the IOTOF cluster

#include "DataFormatsIOTOF/Cluster.h"
#include <sstream>
#include "Framework/Logger.h"
#include <cassert>
#include <iostream>
#include <format>

// Root ClassImp macros for serialization metadata
ClassImp(o2::iotof::ClusterInfo);
ClassImp(o2::iotof::Cluster);

namespace o2::iotof
namespace o2
{
namespace iotof
{

std::string Cluster::asString() const
{
std::ostringstream stream;
stream << "chip=" << chipID << " row=" << row << " col=" << col << " size=" << size;
return stream.str();
LOG(debug) << "[Cluster::asString] Converting Cluster to string";
return std::format(
"chip: {:5d} | row: {:3d} col: {:3d} | span: {:2d}x{:2d} | pattern: {:5d} topology: {:4d}",
getChipID(),
getRow(),
getCol(),
getRowSpan(),
getColSpan(),
getPattern(),
getTopology()
);
}

//______________________________________________________________________________
void Cluster::print() const
{
std::cout << *this << "\n";
}

//______________________________________________________________________________
void Cluster::sanityCheck()
{
LOG(debug) << "[Cluster::sanityCheck] Performing sanity check on Cluster fields";

// Ensure extracted values fit within allowed bit masks
assert(getRow() <= ClusterInfo::MaskRow);
assert(getCol() <= ClusterInfo::MaskCol);
assert(getRowSpan() <= ClusterInfo::MaskRowSpan);
assert(getColSpan() <= ClusterInfo::MaskColSpan);
assert(getPattern() <= ClusterInfo::MaskPattern);
assert(getTopology() <= ClusterInfo::MaskTopology);
}

} // namespace o2::iotof
} // namespace iotof
} // namespace o2

// Stream operator implementation
std::ostream& operator<<(std::ostream& stream, const o2::iotof::Cluster& cl)
{
stream << cl.asString();
return stream;
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#pragma link C++ class o2::iotof::Digit + ;
#pragma link C++ class std::vector < o2::iotof::Digit> + ;

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

Expand Down
2 changes: 2 additions & 0 deletions Detectors/Upgrades/ALICE3/IOTOF/base/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@

o2_add_library(IOTOFBase
SOURCES src/GeometryTGeo.cxx
src/Segmentation.cxx
src/IOTOFBaseParam.cxx
PUBLIC_LINK_LIBRARIES O2::DetectorsBase
O2::MathUtils)

o2_target_root_dictionary(IOTOFBase
HEADERS include/IOTOFBase/GeometryTGeo.h
include/IOTOFBase/Segmentation.h
include/IOTOFBase/IOTOFBaseParam.h)
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ class Segmentation
/// the center of the sensitive volulme.
/// \param int iRow Detector x cell coordinate. Has the range 0 <= iRow < mNumberOfRows
/// \param int iCol Detector z cell coordinate. Has the range 0 <= iCol < mNumberOfColumns
bool localToDetector(float x, float z, int& iRow, int& iCol, const int subDetectorID);
bool localToDetector(float x, float z, int& iRow, int& iCol, const int subDetectorID) const;
/// same but w/o check for row/column range
void localToDetectorUnchecked(float xRow, float zCol, int& iRow, int& iCol, const int subDetectorID);
void localToDetectorUnchecked(float xRow, float zCol, int& iRow, int& iCol, const int subDetectorID) const;

/// Transformation from Detector cell coordiantes to Geant detector centered
/// local coordinates (cm)
Expand All @@ -67,7 +67,7 @@ class Segmentation

// w/o check for row/col range
template <typename T = float, typename L = float>
void detectorToLocalUnchecked(L row, L col, T& xRow, T& zCol, const int subDetectorID)
void detectorToLocalUnchecked(L row, L col, T& xRow, T& zCol, const int subDetectorID) const
{
if (subDetectorID != 0 && subDetectorID != 1) {
row = col = -1;
Expand All @@ -78,7 +78,7 @@ class Segmentation
zCol = col * specsConfig.PitchCol + getFirstColCoordinate(subDetectorID);
}
template <typename T = float, typename L = float>
void detectorToLocalUnchecked(L row, L col, math_utils::Point3D<T>& loc, const int subDetectorID)
void detectorToLocalUnchecked(L row, L col, math_utils::Point3D<T>& loc, const int subDetectorID) const
{
if (subDetectorID != 0 && subDetectorID != 1) {
row = col = -1;
Expand All @@ -88,7 +88,7 @@ class Segmentation
loc.SetCoordinates(getFirstRowCoordinate(subDetectorID) - row * specsConfig.PitchRow, T(0.), col * specsConfig.PitchCol + getFirstColCoordinate(subDetectorID));
}
template <typename T = float, typename L = float>
void detectorToLocalUnchecked(L row, L col, std::array<T, 3>& loc, const int subDetectorID)
void detectorToLocalUnchecked(L row, L col, std::array<T, 3>& loc, const int subDetectorID) const
{
if (subDetectorID != 0 && subDetectorID != 1) {
row = col = -1;
Expand All @@ -103,7 +103,7 @@ class Segmentation
// same but with check for row/col range

template <typename T = float, typename L = float>
bool detectorToLocal(L row, L col, T& xRow, T& zCol, const int subDetectorID)
bool detectorToLocal(L row, L col, T& xRow, T& zCol, const int subDetectorID) const
{
if (subDetectorID != 0 && subDetectorID != 1) {
row = col = -1;
Expand All @@ -118,7 +118,7 @@ class Segmentation
}

template <typename T = float, typename L = float>
bool detectorToLocal(L row, L col, math_utils::Point3D<T>& loc, const int subDetectorID)
bool detectorToLocal(L row, L col, math_utils::Point3D<T>& loc, const int subDetectorID) const
{
if (subDetectorID != 0 && subDetectorID != 1) {
row = col = -1;
Expand All @@ -132,7 +132,7 @@ class Segmentation
return true;
}
template <typename T = float, typename L = float>
bool detectorToLocal(L row, L col, std::array<T, 3>& loc, const int subDetectorID)
bool detectorToLocal(L row, L col, std::array<T, 3>& loc, const int subDetectorID) const
{
if (subDetectorID != 0 && subDetectorID != 1) {
row = col = -1;
Expand All @@ -146,12 +146,12 @@ class Segmentation
return true;
}

float getFirstRowCoordinate(const int subDetectorID)
float getFirstRowCoordinate(const int subDetectorID) const
{
const auto& specsConfig = ChipSpecificsParam::Instance();
return 0.5 * ((specsConfig.ActiveMatrixSizeRows() - specsConfig.PassiveEdgeTop + specsConfig.PassiveEdgeReadOut) - specsConfig.PitchRow);
}
float getFirstColCoordinate(const int subDetectorID)
float getFirstColCoordinate(const int subDetectorID) const
{
const auto& specsConfig = ChipSpecificsParam::Instance();
return 0.5 * (specsConfig.PitchCol - specsConfig.ActiveMatrixSizeCols());
Expand All @@ -161,7 +161,7 @@ class Segmentation
};

//_________________________________________________________________________________________________
inline void Segmentation::localToDetectorUnchecked(float xRow, float zCol, int& iRow, int& iCol, const int subDetectorID)
inline void Segmentation::localToDetectorUnchecked(float xRow, float zCol, int& iRow, int& iCol, const int subDetectorID) const
{
// convert to row/col w/o over/underflow check
if (subDetectorID != 0 && subDetectorID != 1) {
Expand All @@ -187,7 +187,7 @@ inline void Segmentation::localToDetectorUnchecked(float xRow, float zCol, int&
}

//_________________________________________________________________________________________________
inline bool Segmentation::localToDetector(float xRow, float zCol, int& iRow, int& iCol, const int subDetectorID)
inline bool Segmentation::localToDetector(float xRow, float zCol, int& iRow, int& iCol, const int subDetectorID) const
{
// convert to row/col
if (subDetectorID != 0 && subDetectorID != 1) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#pragma link off all functions;

#pragma link C++ class o2::iotof::GeometryTGeo + ;
#pragma link C++ class o2::iotof::Segmentation + ;
#pragma link C++ class o2::iotof::IOTOFBaseParam + ;
#pragma link C++ class o2::conf::ConfigurableParamHelper < o2::iotof::IOTOFBaseParam> + ;

Expand Down
Loading
Loading