From fa4e6de0aa509d7d7167d9d47e7c18877ab9d913 Mon Sep 17 00:00:00 2001 From: maciacco Date: Thu, 1 Oct 2026 16:19:33 +0200 Subject: [PATCH 1/8] make timing response independent for different pixels (dt from stepping neglected) --- .../Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx index 559a36c3c3467..3af0466460f8b 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx @@ -19,6 +19,7 @@ #include "IOTOFSimulation/Digitizer.h" #include "IOTOFSimulation/DPLDigitizerParam.h" #include "DetectorsRaw/HBFUtils.h" +#include "CommonConstants/PhysicsConstants.h" #include #include @@ -135,7 +136,7 @@ void Digitizer::processHit(const o2::itsmft::Hit& hit, int evID, int srcID) double hitTime = hit.GetTime() * sec2ns; // convert to ns double eventTimeInBC = mEventTime.getTimeOffsetWrtBC(); // event time wrt bc double hitTimeWrtBC = hitTime + eventTimeInBC; // hit time wrt bc - double smearedTime = smearTime(hitTimeWrtBC); + // double smearedTime = smearTime(hitTimeWrtBC); // Create the digit with time information o2::MCCompLabel label(hit.GetTrackID(), evID, srcID, false); @@ -168,6 +169,8 @@ void Digitizer::processHit(const o2::itsmft::Hit& hit, int evID, int srcID) const int nElectronsSampled = gRandom->Poisson(electronsPerStep * nEleResp); // Noise can be added here if needed + double smearedTime = smearTime(hitTimeWrtBC); + registerDigits(chip, roFrameAbs, smearedTime, nROF, static_cast(rowIS), static_cast(colIS), nElectronsSampled, label); } @@ -195,7 +198,6 @@ void Digitizer::stepping(const o2::itsmft::Hit& hit, float**& respMatrix, float* const auto& digitizerParams = o2::iotof::DPLDigitizerParam::Instance(); auto stepVector = (xyzPositionEnd - xyzPositionStart) / digitizerParams.nSimSteps; xyzPositionStart = xyzPositionStart + stepVector * 0.5f; // center the start position in the middle of the step - xyzPositionEnd = xyzPositionEnd - stepVector * 0.5f; // center the end position in the middle of the step rowStart = -1; colStart = -1; From 00c04c6ef6a4f3c6d0dd10e92db138fbf8de01e7 Mon Sep 17 00:00:00 2001 From: maciacco Date: Thu, 1 Oct 2026 16:23:03 +0200 Subject: [PATCH 2/8] remove useless include and commented line --- Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx | 2 -- 1 file changed, 2 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx index 3af0466460f8b..c56e97435db06 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx @@ -19,7 +19,6 @@ #include "IOTOFSimulation/Digitizer.h" #include "IOTOFSimulation/DPLDigitizerParam.h" #include "DetectorsRaw/HBFUtils.h" -#include "CommonConstants/PhysicsConstants.h" #include #include @@ -136,7 +135,6 @@ void Digitizer::processHit(const o2::itsmft::Hit& hit, int evID, int srcID) double hitTime = hit.GetTime() * sec2ns; // convert to ns double eventTimeInBC = mEventTime.getTimeOffsetWrtBC(); // event time wrt bc double hitTimeWrtBC = hitTime + eventTimeInBC; // hit time wrt bc - // double smearedTime = smearTime(hitTimeWrtBC); // Create the digit with time information o2::MCCompLabel label(hit.GetTrackID(), evID, srcID, false); From 5790a464dedb1488452d7de18fa8fe461782167b Mon Sep 17 00:00:00 2001 From: maciacco Date: Tue, 6 Oct 2026 19:05:50 +0200 Subject: [PATCH 3/8] first attempt to include column-group read-out in the digitizer --- .../include/DataFormatsIOTOF/Digit.h | 19 +++++++++-- .../simulation/include/IOTOFSimulation/Chip.h | 13 ++++--- .../IOTOFSimulation/DPLDigitizerParam.h | 3 ++ .../ALICE3/IOTOF/simulation/src/Chip.cxx | 2 +- .../ALICE3/IOTOF/simulation/src/Digitizer.cxx | 34 +++++++++++++++++-- 5 files changed, 61 insertions(+), 10 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/include/DataFormatsIOTOF/Digit.h b/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/include/DataFormatsIOTOF/Digit.h index f1e31b57c6f54..a410a77b44706 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/include/DataFormatsIOTOF/Digit.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/include/DataFormatsIOTOF/Digit.h @@ -25,6 +25,18 @@ namespace o2::iotof { +struct DigitKey { + ULong64_t high; + UInt_t low; + + bool operator<(const DigitKey& other) const { + if (high != other.high) { + return high < other.high; + } + return low < other.low; + } +}; + class Digit : public o2::itsmft::Digit { public: @@ -40,11 +52,14 @@ class Digit : public o2::itsmft::Digit ULong64_t getBc() const { return mBc; } Int_t getTdc() const { return mTdc; } - static ULong64_t getOrderingKey(ULong64_t bc, UShort_t row, UShort_t col) + static DigitKey getOrderingKey(ULong64_t bc, UInt_t tdc, uint16_t row, uint16_t col) { + DigitKey key; uint32_t orbit = bc / o2::constants::lhc::LHCMaxBunches; uint16_t bunch = bc % o2::constants::lhc::LHCMaxBunches; - return (static_cast(orbit) << 32) | (static_cast(bunch) << 16) | (static_cast(row) << 8) | static_cast(col); + key.high = (static_cast(orbit) << 32) | (static_cast(bunch) << 16) | (static_cast(tdc) & 0xFFFF); + key.low = (static_cast(row) << 16) | (static_cast(col) & 0xFFFF); + return key; } private: diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Chip.h b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Chip.h index 8e2f2915a2ec5..d848cf0ecad76 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Chip.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Chip.h @@ -60,7 +60,7 @@ class Chip /// @param option unused void clear() { mDigits.clear(); } - std::map& getDigits() { return mDigits; } + std::map& getDigits() { return mDigits; } bool isEmpty() const { return mDigits.empty(); } void setChipIndex(Int_t index) { mChipIndex = index; } @@ -74,19 +74,24 @@ class Chip Int_t getNumberOfDigits() const { return mDigits.size(); } /// reset points container - o2::iotof::LabeledDigit* findDigit(ULong64_t key); + o2::iotof::LabeledDigit* findDigit(DigitKey key); + + /// Resize the vector of tdc states + void resizeTDCStates(int const size) { mTDCStates.resize(size); } + std::vector>& getTDCStates() { return mTDCStates; } void addDigit(UShort_t row, UShort_t col, Int_t charge, double time, ULong64_t bc, Int_t tdc, o2::MCCompLabel label); protected: Int_t mChipIndex = -1; ///< Chip ID bool mDisabled = false; ///< Flag to indicate if the chip is disabled (e.g. due to dead channels) - std::map mDigits; ///< Map of fired digits, possibly in multiple frames + std::map mDigits; ///< Map of fired digits, possibly in multiple frames + std::vector> mTDCStates; ///< Vector of the last times the TDC pairs went busy ClassDefNV(Chip, 1); }; -inline o2::iotof::LabeledDigit* Chip::findDigit(ULong64_t key) +inline o2::iotof::LabeledDigit* Chip::findDigit(DigitKey key) { // finds the digit corresponding to global key auto digitentry = mDigits.find(key); diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h index 7f96b8e509d0c..eb9ba291385f3 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h @@ -38,6 +38,9 @@ struct DPLDigitizerParam : public o2::conf::ConfigurableParamHelpergetSize(); mChips.resize(numberOfChips); + + const auto& specsConfig = ChipSpecificsParam::Instance(); + const auto& digitizerParams = o2::iotof::DPLDigitizerParam::Instance(); + const double nReadOutCols = specsConfig.NCols / digitizerParams.nColsPerGroup + 1; for (int i = numberOfChips; i--;) { mChips[i].setChipIndex(i); /// Noise map to be implemented @@ -53,9 +57,15 @@ void Digitizer::init() /// mChips[i].disable(mDeadChanMap->isFullChipMasked(i)); /// mChips[i].setDeadChanMap(mDeadChanMap); /// } + + // initialize the vector of TDC states + mChips[i].resizeTDCStates(nReadOutCols); + for (auto& tdcStates : mChips[i].getTDCStates()) { + tdcStates[0] = -999.f; + tdcStates[1] = -999.f; + } } - const auto& digitizerParams = o2::iotof::DPLDigitizerParam::Instance(); if (!digitizerParams.efficiencyFilePath.empty()) { loadEfficiencyMap(digitizerParams.efficiencyFilePath); } @@ -66,6 +76,7 @@ void Digitizer::init() LOG(info) << " Detection efficiency: " << digitizerParams.efficiency * 100 << " %"; LOG(info) << " Continuous mode: " << (mContinuous ? "ON" : "OFF"); sSegmentation = o2::iotof::Segmentation::Instance(); + } //_______________________________________________________________________ @@ -404,12 +415,26 @@ void Digitizer::fillOutputContainer() } auto& chipDigits = chip.getDigits(); + auto& tdcStates = chip.getTDCStates(); + for (const auto& [key, digit] : chipDigits) { if (digit.getCharge() < digitizerParams.chargeThreshold) { continue; // skip digits below threshold } + const int colInGroup = digit.getColumn() / digitizerParams.nColsPerGroup; + const double digitTime = digit.getTime(); + if (digitTime - tdcStates[colInGroup][0] < digitizerParams.tdcBusyTime && digitTime - tdcStates[colInGroup][1] < digitizerParams.tdcBusyTime) { + continue; // both tdc pairs are busy + } + else if (digitTime - tdcStates[colInGroup][0] > digitizerParams.tdcBusyTime) { + tdcStates[colInGroup][0] = digitTime; + } + else if (digitTime - tdcStates[colInGroup][1] > digitizerParams.tdcBusyTime) { + tdcStates[colInGroup][1] = digitTime; + } + int digitID = mDigits->size(); mDigits->emplace_back(digit.getChipIndex(), digit.getRow(), digit.getColumn(), digit.getCharge(), digit.getTime(), digit.getBc(), digit.getTdc()); if (mMCLabels) { @@ -438,7 +463,7 @@ void Digitizer::fillOutputContainer() void Digitizer::registerDigits(Chip& chip, uint32_t roFrame, double time, int nROF, uint16_t row, uint16_t col, int nElectrons, o2::MCCompLabel& label) { - (void)nROF; + // (void)nROF; const auto& digitizerParams = o2::iotof::DPLDigitizerParam::Instance(); @@ -448,8 +473,11 @@ void Digitizer::registerDigits(Chip& chip, uint32_t roFrame, double time, int nR double absoluteTime = tdc * digitizerParams.tdcBin * 1.e-9 + nbc * o2::constants::lhc::LHCBunchSpacingNS; - auto key = o2::iotof::Digit::getOrderingKey(nbc, row, col); + auto key = o2::iotof::Digit::getOrderingKey(nbc, tdc, row, col); o2::iotof::LabeledDigit* existingDigit = chip.findDigit(key); + + chip.addDigit(row, col, nElectrons, absoluteTime, nbc, tdc, label); + if (!existingDigit) { // No existing digit, create a new one chip.addDigit(row, col, nElectrons, absoluteTime, nbc, tdc, label); From 538b04f58b637bd475302c2351459b8c52851777 Mon Sep 17 00:00:00 2001 From: maciacco Date: Wed, 7 Oct 2026 14:21:30 +0200 Subject: [PATCH 4/8] imporve implementation using a tdc-status array --- Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx index 7c2b413f50dd2..1947a5e729aa9 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx @@ -426,6 +426,7 @@ void Digitizer::fillOutputContainer() const int colInGroup = digit.getColumn() / digitizerParams.nColsPerGroup; const double digitTime = digit.getTime(); if (digitTime - tdcStates[colInGroup][0] < digitizerParams.tdcBusyTime && digitTime - tdcStates[colInGroup][1] < digitizerParams.tdcBusyTime) { + // TODO: improve labels treatment if multiple hits cross the same pixel during continue; // both tdc pairs are busy } else if (digitTime - tdcStates[colInGroup][0] > digitizerParams.tdcBusyTime) { @@ -471,7 +472,7 @@ void Digitizer::registerDigits(Chip& chip, uint32_t roFrame, double time, int nR int tdc = int((time - nbc * o2::constants::lhc::LHCBunchSpacingNS) / digitizerParams.tdcBin); nbc += mEventTime.toLong(); - double absoluteTime = tdc * digitizerParams.tdcBin * 1.e-9 + nbc * o2::constants::lhc::LHCBunchSpacingNS; + double absoluteTime = tdc * digitizerParams.tdcBin + nbc * o2::constants::lhc::LHCBunchSpacingNS; auto key = o2::iotof::Digit::getOrderingKey(nbc, tdc, row, col); o2::iotof::LabeledDigit* existingDigit = chip.findDigit(key); From 50552f6b7023b9aecb4a3badb1b289009358144c Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Wed, 7 Oct 2026 12:30:15 +0000 Subject: [PATCH 5/8] Please consider the following formatting changes --- .../DataFormatsIOTOF/include/DataFormatsIOTOF/Digit.h | 3 ++- .../ALICE3/IOTOF/simulation/include/IOTOFSimulation/Chip.h | 2 +- .../simulation/include/IOTOFSimulation/DPLDigitizerParam.h | 4 ++-- .../Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx | 7 ++----- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/include/DataFormatsIOTOF/Digit.h b/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/include/DataFormatsIOTOF/Digit.h index a410a77b44706..d7af3c1872606 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/include/DataFormatsIOTOF/Digit.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/include/DataFormatsIOTOF/Digit.h @@ -29,7 +29,8 @@ struct DigitKey { ULong64_t high; UInt_t low; - bool operator<(const DigitKey& other) const { + bool operator<(const DigitKey& other) const + { if (high != other.high) { return high < other.high; } diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Chip.h b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Chip.h index d848cf0ecad76..1849907d6e071 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Chip.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Chip.h @@ -85,7 +85,7 @@ class Chip protected: Int_t mChipIndex = -1; ///< Chip ID bool mDisabled = false; ///< Flag to indicate if the chip is disabled (e.g. due to dead channels) - std::map mDigits; ///< Map of fired digits, possibly in multiple frames + std::map mDigits; ///< Map of fired digits, possibly in multiple frames std::vector> mTDCStates; ///< Vector of the last times the TDC pairs went busy ClassDefNV(Chip, 1); diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h index eb9ba291385f3..ed1d4b35b1626 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h @@ -38,8 +38,8 @@ struct DPLDigitizerParam : public o2::conf::ConfigurableParamHelper digitizerParams.tdcBusyTime) { + } else if (digitTime - tdcStates[colInGroup][0] > digitizerParams.tdcBusyTime) { tdcStates[colInGroup][0] = digitTime; - } - else if (digitTime - tdcStates[colInGroup][1] > digitizerParams.tdcBusyTime) { + } else if (digitTime - tdcStates[colInGroup][1] > digitizerParams.tdcBusyTime) { tdcStates[colInGroup][1] = digitTime; } From 0245a791a6b0d4937742bb8ce49e025e2149aeac Mon Sep 17 00:00:00 2001 From: maciacco Date: Wed, 7 Oct 2026 14:50:57 +0200 Subject: [PATCH 6/8] fix type --- Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx index 8569604151048..e4bcde1255b89 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx @@ -44,7 +44,7 @@ void Digitizer::init() const auto& specsConfig = ChipSpecificsParam::Instance(); const auto& digitizerParams = o2::iotof::DPLDigitizerParam::Instance(); - const double nReadOutCols = specsConfig.NCols / digitizerParams.nColsPerGroup + 1; + const int nReadOutCols = specsConfig.NCols / digitizerParams.nColsPerGroup + 1; for (int i = numberOfChips; i--;) { mChips[i].setChipIndex(i); /// Noise map to be implemented From d99b87c7d3a86da26716ad224aed1720a96c8f8e Mon Sep 17 00:00:00 2001 From: maciacco Date: Wed, 7 Oct 2026 16:01:54 +0200 Subject: [PATCH 7/8] fix busy window --- .../simulation/include/IOTOFSimulation/DPLDigitizerParam.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h index ed1d4b35b1626..820f776cb1dfd 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h @@ -39,7 +39,7 @@ struct DPLDigitizerParam : public o2::conf::ConfigurableParamHelper Date: Wed, 7 Oct 2026 14:04:24 +0000 Subject: [PATCH 8/8] Please consider the following formatting changes --- .../simulation/include/IOTOFSimulation/DPLDigitizerParam.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h index 820f776cb1dfd..3d2ed2c995c30 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h @@ -38,8 +38,8 @@ struct DPLDigitizerParam : public o2::conf::ConfigurableParamHelper