From 44cd1ea3eab4adf81bd89d3e62a1e496deeba4b6 Mon Sep 17 00:00:00 2001 From: GiorgioAlbertoLucia Date: Thu, 9 Jul 2026 10:04:44 +0200 Subject: [PATCH 1/4] adding stepping in digitization --- .../ALICE3/IOTOF/simulation/src/Digitizer.cxx | 131 ++++++++++++++++-- 1 file changed, 118 insertions(+), 13 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx index f5694412c5f5e..da59718abb217 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx @@ -17,6 +17,7 @@ /// #include "IOTOFSimulation/Digitizer.h" +#include "IOTOFSimulation/DPLDigitizerParam.h" #include "DetectorsRaw/HBFUtils.h" #include @@ -30,7 +31,6 @@ namespace o2::iotof { o2::iotof::Segmentation* Digitizer::sSegmentation = nullptr; - //_______________________________________________________________________ void Digitizer::init() { @@ -117,6 +117,7 @@ void Digitizer::processHit(const o2::itsmft::Hit& hit, int evID, int srcID) return; } + // Get hit time and apply smearing // Hit time is in seconds, convert to ns and add event time double hitTime = hit.GetTime() * sec2ns; // convert to ns @@ -125,28 +126,132 @@ void Digitizer::processHit(const o2::itsmft::Hit& hit, int evID, int srcID) double smearedTime = smearTime(absoluteTime); // apply detector resolution if (chipID < 0 || chipID >= mGeometry->getSize() || mGeometry->getSize() < 1) { + + // For now, use simple row/col mapping from detector ID + // TODO: Implement proper segmentation when geometry is finalized + uint16_t chipIndex = static_cast(chipID); + + if (chipID > mGeometry->getSize() || mGeometry->getSize() < 1) { LOG(debug) << "Invalid detector ID: " << chipID << ", geometry size: " << mGeometry->getSize(); return; // invalid detector ID } - const auto& matrix = mGeometry->getMatrixL2G(hit.GetDetectorID()); + // stepping is called here + + // Create the digit with time information + o2::MCCompLabel label(hit.GetTrackID(), evID, srcID, false); + const int roFrameAbs = 0; // For now, we can set this to 0 or calculate based on time if needed + const int nROF = 1; // For now, we can assume the signal is contained in one ROF, this can be extended to multiple ROFs based on the time + for (int irow = rowSpan; irow--;) { + uint16_t rowIS = irow + rowStart; + for (int icol = colSpan; icol--;) { + uint16_t colIS = icol + colStart; + float nEleResp = respMatrix[irow][icol]; + if (!nEleResp) { + continue; + } + int nElectronsSampled = gRandom->Poisson(electronsPerStep * nEleResp); + // Noise can be added here if needed + + registerDigits(chip, roFrameAbs, smearedTime, nROF, static_cast(row), static_cast(col), nElectronsSampled, label); + } + } + + for (int irow = 0; irow < rowSpan; ++irow) { + delete[] respMatrix[irow]; + } + delete[] respMatrix; + + + + +} + +void Digitizer::stepping(const o2::itsmft::Hit& hit, float**& respMatrix) +{ + const auto& matrix = mGeometry->getMatrixL2G(hit.GetDetectorID()); + math_utils::Vector3D xyzPositionStart(matrix ^ (hit.GetPosStart())); // start position in sensor frame - // math_utils::Vector3D xyzPositionEnd(matrix ^ (hit.GetPos())); // end position in sensor frame + math_utils::Vector3D xyzPositionEnd(matrix ^ (hit.GetPos())); // end position in sensor frame + + const auto& digitizerParams = DPLDigitizerParam::Instance(); + const 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 + + int rowStart = -1, colStart = -1, rowEnd = -1, colEnd = -1, nSkip = 0; + while (!sSegmentation->localToDetector(xyzPositionStart.X(), xyzPositionStart.Z(), rowStart, colStart, mGeometry->getIOTOFLayer(chipID))) { + if (++nSkip > digitizerParams.nSimSteps) { // additional check to add: should we exclude something? + LOG(debug) << "Hit position out of bounds for detector ID " << chipID; + return; // hit is outside the active area + } + xyzPositionStart += stepVector; + } + + while (!sSegmentation->localToDetector(xyzPositionEnd.X(), xyzPositionEnd.Z(), rowEnd, colEnd, mGeometry->getIOTOFLayer(chipID))) { + if (++nSkip > digitizerParams.nSimSteps) { // additional check to add: should we exclude something? + LOG(debug) << "Hit position out of bounds for detector ID " << chipID; + return; // hit is outside the active area + } + xyzPositionEnd += stepVector; + } + + if (rowStart > rowEnd) { + std::swap(rowStart, rowEnd); + } + if (colStart > colEnd) { + std::swap(colStart, colEnd); + } + + // Expand the range to take into account the effects of charge sharing + rowStart -= digitizerParams.responseMatrixSize / 2; + rowEnd += digitizerParams.responseMatrixSize / 2; + rowStart = std::max(rowStart, 0); + colStart = std::max(colStart, 0); - int row = 0; // Will be determined from start hit position - int col = 0; // Will be determined from start hit position + rowEnd = std::min(rowEnd, mGeometry->getNumberOfRows(chipID) - 1); + colEnd = std::min(colEnd, mGeometry->getNumberOfColumns(chipID) - 1); + int rowSpan = rowEnd - rowStart + 1; + int colSpan = colEnd - colStart + 1; - if (!sSegmentation->localToDetector(xyzPositionStart.X(), xyzPositionStart.Z(), row, col, mGeometry->getIOTOFLayer(chipID))) { - LOG(debug) << "Hit position out of bounds for detector ID " << chipID; - return; // hit is outside the active area + respMatrix = new float*[rowSpan]; + for (int i = 0; i < rowSpan; ++i) { + respMatrix[i] = new float[colSpan](); } - // Create the digit with time information - o2::MCCompLabel label(hit.GetTrackID(), evID, srcID, false); - const int roFrameAbs = 0; // For now, we can set this to 0 or calculate based on time if needed - const int nROF = 1; // For now, we can assume the signal is contained in one ROF, this can be extended to multiple ROFs based on the time + int rowPrev = -1, colPrev = -1, row, col; + if (!respMatrix || rowSpan <= 0 || colSpan <= 0) continue; + if (nSkip) { + nSteps -= nSkip; + } + + auto& currentPosLocal = xyzPositionStart; + for (int iStep = nSteps; iStep--;) { + segmentation->localToDetector(currentPosLocal.X(), currentPosLocal.Z(), row, col, subdetectorID); + if (row != rowPrev || col != colPrev) { + rowPrev = row; + colPrev = col; + } + + currentPosLocal += stepVector; // Move to the next step position + + for (int irow = digitizerParams.responseMatrixSize; irow--;) { + int rowDest = row + irow - (digitizerParams.responseMatrixSize / 2) - rowStart; // destination row in the respMatrix + if (rowDest < 0 || rowDest >= rowSpan) { + continue; + } + for (int icol = digitizerParams.responseMatrixSize; icol--;) { + int colDest = col + icol - (digitizerParams.responseMatrixSize / 2) - colStart; // destination column in the respMatrix + if (colDest < 0 || colDest >= colSpan) { + continue; + } + respMatrix[rowDest][colDest] += 1.; + } + } + } - registerDigits(chip, roFrameAbs, smearedTime, nROF, static_cast(row), static_cast(col), charge, label); + + } //_______________________________________________________________________ From c58b43ab64f1f7fca905f5c7ac2d19bddfe95c7b Mon Sep 17 00:00:00 2001 From: GiorgioAlbertoLucia Date: Thu, 9 Jul 2026 15:42:44 +0200 Subject: [PATCH 2/4] added segmentation to the digitization --- .../base/include/IOTOFBase/GeometryTGeo.h | 8 +- .../IOTOFSimulation/DPLDigitizerParam.h | 1 + .../include/IOTOFSimulation/Digitizer.h | 2 + .../ALICE3/IOTOF/simulation/src/Digitizer.cxx | 105 +++++++++--------- 4 files changed, 60 insertions(+), 56 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/GeometryTGeo.h b/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/GeometryTGeo.h index d466cc2987f23..616c6409f4577 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/GeometryTGeo.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/GeometryTGeo.h @@ -39,7 +39,7 @@ class GeometryTGeo : public o2::detectors::DetMatrixCache static const char* getIOTOFVolPattern() { return sIOTOFVolumeName.c_str(); } // Inner TOF - const int getITOFNumberOfChips() { return mNumberOfChipsIOTOF[0]; } + const int getITOFNumberOfChips() const { return mNumberOfChipsIOTOF[0]; } static const char* getITOFLayerPattern() { return sITOFLayerName.c_str(); } static const char* getITOFStavePattern() { return sITOFStaveName.c_str(); } static const char* getITOFModulePattern() { return sITOFModuleName.c_str(); } @@ -47,7 +47,7 @@ class GeometryTGeo : public o2::detectors::DetMatrixCache static const char* getITOFSensorPattern() { return sITOFSensorName.c_str(); } // Outer TOF - const int getOTOFNumberOfChips() { return mNumberOfChipsIOTOF[1]; } + const int getOTOFNumberOfChips() const { return mNumberOfChipsIOTOF[1]; } static const char* getOTOFLayerPattern() { return sOTOFLayerName.c_str(); } static const char* getOTOFStavePattern() { return sOTOFStaveName.c_str(); } static const char* getOTOFModulePattern() { return sOTOFModuleName.c_str(); } @@ -55,13 +55,13 @@ class GeometryTGeo : public o2::detectors::DetMatrixCache static const char* getOTOFSensorPattern() { return sOTOFSensorName.c_str(); } // Forward TOF - const int getFTOFNumberOfChips() { return mNumberOfChipsFTOF; } + const int getFTOFNumberOfChips() const { return mNumberOfChipsFTOF; } static const char* getFTOFLayerPattern() { return sFTOFLayerName.c_str(); } static const char* getFTOFChipPattern() { return sFTOFChipName.c_str(); } static const char* getFTOFSensorPattern() { return sFTOFSensorName.c_str(); } // Backward TOF - const int getBTOFNumberOfChips() { return mNumberOfChipsBTOF; } + const int getBTOFNumberOfChips() const { return mNumberOfChipsBTOF; } static const char* getBTOFLayerPattern() { return sBTOFLayerName.c_str(); } static const char* getBTOFChipPattern() { return sBTOFChipName.c_str(); } static const char* getBTOFSensorPattern() { return sBTOFSensorName.c_str(); } diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h index 66014e1c7f06e..64289550a625e 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h @@ -31,6 +31,7 @@ struct DPLDigitizerParam : public o2::conf::ConfigurableParamHelper(charge / digitizerParams.nSimSteps); // Apply charge threshold if (charge < mChargeThreshold) { @@ -117,7 +119,6 @@ void Digitizer::processHit(const o2::itsmft::Hit& hit, int evID, int srcID) return; } - // Get hit time and apply smearing // Hit time is in seconds, convert to ns and add event time double hitTime = hit.GetTime() * sec2ns; // convert to ns @@ -125,35 +126,37 @@ void Digitizer::processHit(const o2::itsmft::Hit& hit, int evID, int srcID) double absoluteTime = hitTime + eventTimeNS; // absolute time double smearedTime = smearTime(absoluteTime); // apply detector resolution - if (chipID < 0 || chipID >= mGeometry->getSize() || mGeometry->getSize() < 1) { - // For now, use simple row/col mapping from detector ID // TODO: Implement proper segmentation when geometry is finalized uint16_t chipIndex = static_cast(chipID); - - if (chipID > mGeometry->getSize() || mGeometry->getSize() < 1) { + + if (chipID < 0 || chipID >= mGeometry->getSize() || mGeometry->getSize() < 1) { LOG(debug) << "Invalid detector ID: " << chipID << ", geometry size: " << mGeometry->getSize(); return; // invalid detector ID } // stepping is called here - + float** respMatrix = nullptr; + int rowStart = 0, colStart = 0, rowSpan = 0, colSpan = 0; + stepping(hit, respMatrix, rowStart, colStart, rowSpan, colSpan); + // Create the digit with time information o2::MCCompLabel label(hit.GetTrackID(), evID, srcID, false); - const int roFrameAbs = 0; // For now, we can set this to 0 or calculate based on time if needed - const int nROF = 1; // For now, we can assume the signal is contained in one ROF, this can be extended to multiple ROFs based on the time + const int roFrameAbs = 0; // For now, we can set this to 0 or calculate based on time if needed + const int nROF = 1; // For now, we can assume the signal is contained in one ROF, this can be extended to multiple ROFs based on the time for (int irow = rowSpan; irow--;) { uint16_t rowIS = irow + rowStart; for (int icol = colSpan; icol--;) { uint16_t colIS = icol + colStart; float nEleResp = respMatrix[irow][icol]; if (!nEleResp) { - continue; + continue; } int nElectronsSampled = gRandom->Poisson(electronsPerStep * nEleResp); // Noise can be added here if needed - - registerDigits(chip, roFrameAbs, smearedTime, nROF, static_cast(row), static_cast(col), nElectronsSampled, label); + + registerDigits(chip, roFrameAbs, smearedTime, nROF, + static_cast(rowIS), static_cast(colIS), nElectronsSampled, label); } } @@ -161,41 +164,41 @@ void Digitizer::processHit(const o2::itsmft::Hit& hit, int evID, int srcID) delete[] respMatrix[irow]; } delete[] respMatrix; - - - - } -void Digitizer::stepping(const o2::itsmft::Hit& hit, float**& respMatrix) +void Digitizer::stepping(const o2::itsmft::Hit& hit, float**& respMatrix, int& rowStart, int& colStart, int& rowSpan, int& colSpan) { const auto& matrix = mGeometry->getMatrixL2G(hit.GetDetectorID()); - - math_utils::Vector3D xyzPositionStart(matrix ^ (hit.GetPosStart())); // start position in sensor frame - math_utils::Vector3D xyzPositionEnd(matrix ^ (hit.GetPos())); // end position in sensor frame - - const auto& digitizerParams = DPLDigitizerParam::Instance(); + const int chipID = hit.GetDetectorID(); + const int subdetectorID = mGeometry->getIOTOFLayer(); + + auto xyzPositionStart(matrix ^ (hit.GetPosStart())); // start position in sensor frame + auto xyzPositionEnd(matrix ^ (hit.GetPos())); // end position in sensor frame + + const auto& digitizerParams = o2::iotof::DPLDigitizerParam::Instance(); const 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 - - int rowStart = -1, colStart = -1, rowEnd = -1, colEnd = -1, nSkip = 0; + 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; + int rowEnd = -1, colEnd = -1, nSkip = 0, nSteps = digitizerParams.nSimSteps; while (!sSegmentation->localToDetector(xyzPositionStart.X(), xyzPositionStart.Z(), rowStart, colStart, mGeometry->getIOTOFLayer(chipID))) { - if (++nSkip > digitizerParams.nSimSteps) { // additional check to add: should we exclude something? + if (++nSkip > digitizerParams.nSimSteps) { // additional check to add: should we exclude something? LOG(debug) << "Hit position out of bounds for detector ID " << chipID; return; // hit is outside the active area } xyzPositionStart += stepVector; } - + while (!sSegmentation->localToDetector(xyzPositionEnd.X(), xyzPositionEnd.Z(), rowEnd, colEnd, mGeometry->getIOTOFLayer(chipID))) { - if (++nSkip > digitizerParams.nSimSteps) { // additional check to add: should we exclude something? + if (++nSkip > digitizerParams.nSimSteps) { // additional check to add: should we exclude something? LOG(debug) << "Hit position out of bounds for detector ID " << chipID; return; // hit is outside the active area } xyzPositionEnd += stepVector; } - + if (rowStart > rowEnd) { std::swap(rowStart, rowEnd); } @@ -209,49 +212,48 @@ void Digitizer::stepping(const o2::itsmft::Hit& hit, float**& respMatrix) rowStart = std::max(rowStart, 0); colStart = std::max(colStart, 0); - rowEnd = std::min(rowEnd, mGeometry->getNumberOfRows(chipID) - 1); - colEnd = std::min(colEnd, mGeometry->getNumberOfColumns(chipID) - 1); - int rowSpan = rowEnd - rowStart + 1; - int colSpan = colEnd - colStart + 1; + rowEnd = std::min(rowEnd, (subdetectorID == 0 ? sSegmentation->mITofSpecsConfig.NRows : sSegmentation->mOTofSpecsConfig.NRows) - 1); + colEnd = std::min(colEnd, (subdetectorID == 0 ? sSegmentation->mITofSpecsConfig.NCols : sSegmentation->mOTofSpecsConfig.NCols) - 1); + rowSpan = rowEnd - rowStart + 1; + colSpan = colEnd - colStart + 1; respMatrix = new float*[rowSpan]; for (int i = 0; i < rowSpan; ++i) { respMatrix[i] = new float[colSpan](); } - int rowPrev = -1, colPrev = -1, row, col; - if (!respMatrix || rowSpan <= 0 || colSpan <= 0) continue; + int rowPrev = -1, colPrev = -1, row = 0, col = 0; + if (!respMatrix || rowSpan <= 0 || colSpan <= 0) { + return; + } if (nSkip) { nSteps -= nSkip; } auto& currentPosLocal = xyzPositionStart; for (int iStep = nSteps; iStep--;) { - segmentation->localToDetector(currentPosLocal.X(), currentPosLocal.Z(), row, col, subdetectorID); + sSegmentation->localToDetector(currentPosLocal.X(), currentPosLocal.Z(), row, col, subdetectorID); if (row != rowPrev || col != colPrev) { - rowPrev = row; - colPrev = col; + rowPrev = row; + colPrev = col; } - + currentPosLocal += stepVector; // Move to the next step position for (int irow = digitizerParams.responseMatrixSize; irow--;) { int rowDest = row + irow - (digitizerParams.responseMatrixSize / 2) - rowStart; // destination row in the respMatrix if (rowDest < 0 || rowDest >= rowSpan) { - continue; + continue; } for (int icol = digitizerParams.responseMatrixSize; icol--;) { - int colDest = col + icol - (digitizerParams.responseMatrixSize / 2) - colStart; // destination column in the respMatrix - if (colDest < 0 || colDest >= colSpan) { + int colDest = col + icol - (digitizerParams.responseMatrixSize / 2) - colStart; // destination column in the respMatrix + if (colDest < 0 || colDest >= colSpan) { continue; - } - respMatrix[rowDest][colDest] += 1.; + } + respMatrix[rowDest][colDest] += 1.; } } } - - - } //_______________________________________________________________________ @@ -305,10 +307,9 @@ void Digitizer::fillOutputContainer() auto& chipDigits = chip.getDigits(); for (const auto& [key, digit] : chipDigits) { - /// Charge threshold not implemented yet - /// if (digit.getCharge() < mChargeThreshold) { - /// continue; // skip digits below threshold - /// } + if (digit.getCharge() < mChargeThreshold) { + continue; // skip digits below threshold + } int digitID = mDigits->size(); mDigits->emplace_back(digit.getChipIndex(), digit.getRow(), digit.getColumn(), digit.getCharge(), digit.getTime()); From 13fd76eeb82cda23e25cd30ff61f618d53cf52fd Mon Sep 17 00:00:00 2001 From: GiorgioAlbertoLucia Date: Fri, 10 Jul 2026 16:13:32 +0200 Subject: [PATCH 3/4] added non-segmented version, with configurable choice --- .../IOTOFSimulation/DPLDigitizerParam.h | 1 + .../include/IOTOFSimulation/Digitizer.h | 1 + .../ALICE3/IOTOF/simulation/src/Digitizer.cxx | 75 ++++++++++++------- 3 files changed, 50 insertions(+), 27 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h index 64289550a625e..679ace26da68c 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h @@ -32,6 +32,7 @@ struct DPLDigitizerParam : public o2::conf::ConfigurableParamHelper(chipID); - if (chipID < 0 || chipID >= mGeometry->getSize() || mGeometry->getSize() < 1) { LOG(debug) << "Invalid detector ID: " << chipID << ", geometry size: " << mGeometry->getSize(); return; // invalid detector ID } - - // stepping is called here - float** respMatrix = nullptr; - int rowStart = 0, colStart = 0, rowSpan = 0, colSpan = 0; - stepping(hit, respMatrix, rowStart, colStart, rowSpan, colSpan); - + // Create the digit with time information o2::MCCompLabel label(hit.GetTrackID(), evID, srcID, false); const int roFrameAbs = 0; // For now, we can set this to 0 or calculate based on time if needed const int nROF = 1; // For now, we can assume the signal is contained in one ROF, this can be extended to multiple ROFs based on the time - for (int irow = rowSpan; irow--;) { - uint16_t rowIS = irow + rowStart; - for (int icol = colSpan; icol--;) { - uint16_t colIS = icol + colStart; - float nEleResp = respMatrix[irow][icol]; - if (!nEleResp) { - continue; + + + if (digitizerParams.performStepping) { + float** respMatrix = nullptr; + int rowStart = 0, colStart = 0, rowSpan = 0, colSpan = 0; + stepping(hit, respMatrix, rowStart, colStart, rowSpan, colSpan); + + for (int irow = rowSpan; irow--;) { + uint16_t rowIS = irow + rowStart; + for (int icol = colSpan; icol--;) { + uint16_t colIS = icol + colStart; + float nEleResp = respMatrix[irow][icol]; + if (!nEleResp) { + continue; + } + const int nElectronsSampled = gRandom->Poisson(electronsPerStep * nEleResp); + // Noise can be added here if needed + + registerDigits(chip, roFrameAbs, smearedTime, nROF, + static_cast(rowIS), static_cast(colIS), nElectronsSampled, label); } - int nElectronsSampled = gRandom->Poisson(electronsPerStep * nEleResp); - // Noise can be added here if needed - - registerDigits(chip, roFrameAbs, smearedTime, nROF, - static_cast(rowIS), static_cast(colIS), nElectronsSampled, label); } - } - for (int irow = 0; irow < rowSpan; ++irow) { - delete[] respMatrix[irow]; + for (int irow = 0; irow < rowSpan; ++irow) { + delete[] respMatrix[irow]; + } + delete[] respMatrix; + } else { + int row = 0, col = 0; + responseInTheMiddle(hit, row, col); + const int nElectronsSampled = gRandom->Poisson(charge); + registerDigits(chip, roFrameAbs, smearedTime, nROF, static_cast(row), static_cast(col), nElectronsSampled, label); } - delete[] respMatrix; } void Digitizer::stepping(const o2::itsmft::Hit& hit, float**& respMatrix, int& rowStart, int& colStart, int& rowSpan, int& colSpan) { const auto& matrix = mGeometry->getMatrixL2G(hit.GetDetectorID()); const int chipID = hit.GetDetectorID(); - const int subdetectorID = mGeometry->getIOTOFLayer(); + const int subdetectorID = mGeometry->getIOTOFLayer(chipID); auto xyzPositionStart(matrix ^ (hit.GetPosStart())); // start position in sensor frame auto xyzPositionEnd(matrix ^ (hit.GetPos())); // end position in sensor frame @@ -256,6 +260,23 @@ void Digitizer::stepping(const o2::itsmft::Hit& hit, float**& respMatrix, int& r } } +void Digitizer::responseInTheMiddle(const o2::itsmft::Hit& hit, int& row, int& col) +{ + const auto& matrix = mGeometry->getMatrixL2G(hit.GetDetectorID()); + const int chipID = hit.GetDetectorID(); + + math_utils::Vector3D xyzPositionStart(matrix ^ (hit.GetPosStart())); // start position in sensor frame + math_utils::Vector3D xyzPositionEnd(matrix ^ (hit.GetPos())); // end position in sensor frame + + // Calculate the middle position of the hit + math_utils::Vector3D xyzPositionMiddle = (xyzPositionStart + xyzPositionEnd) * 0.5f; + + if (!sSegmentation->localToDetector(xyzPositionMiddle.X(), xyzPositionMiddle.Z(), row, col, mGeometry->getIOTOFLayer(chipID))) { + LOG(debug) << "Hit position out of bounds for detector ID " << chipID; + return; // hit is outside the active area + } +} + //_______________________________________________________________________ double Digitizer::smearTime(double time) const { From 99fc21299512b7a78a97232e4fda5f0ce3ba19ab Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Fri, 10 Jul 2026 14:17:09 +0000 Subject: [PATCH 4/4] Please consider the following formatting changes --- .../ALICE3/IOTOF/simulation/src/Digitizer.cxx | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx index ea81940ddf9e8..17e2eddbe5576 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx @@ -130,18 +130,17 @@ void Digitizer::processHit(const o2::itsmft::Hit& hit, int evID, int srcID) LOG(debug) << "Invalid detector ID: " << chipID << ", geometry size: " << mGeometry->getSize(); return; // invalid detector ID } - + // Create the digit with time information o2::MCCompLabel label(hit.GetTrackID(), evID, srcID, false); const int roFrameAbs = 0; // For now, we can set this to 0 or calculate based on time if needed const int nROF = 1; // For now, we can assume the signal is contained in one ROF, this can be extended to multiple ROFs based on the time - - + if (digitizerParams.performStepping) { float** respMatrix = nullptr; int rowStart = 0, colStart = 0, rowSpan = 0, colSpan = 0; stepping(hit, respMatrix, rowStart, colStart, rowSpan, colSpan); - + for (int irow = rowSpan; irow--;) { uint16_t rowIS = irow + rowStart; for (int icol = colSpan; icol--;) { @@ -152,7 +151,7 @@ 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 - + registerDigits(chip, roFrameAbs, smearedTime, nROF, static_cast(rowIS), static_cast(colIS), nElectronsSampled, label); } @@ -266,7 +265,7 @@ void Digitizer::responseInTheMiddle(const o2::itsmft::Hit& hit, int& row, int& c const int chipID = hit.GetDetectorID(); math_utils::Vector3D xyzPositionStart(matrix ^ (hit.GetPosStart())); // start position in sensor frame - math_utils::Vector3D xyzPositionEnd(matrix ^ (hit.GetPos())); // end position in sensor frame + math_utils::Vector3D xyzPositionEnd(matrix ^ (hit.GetPos())); // end position in sensor frame // Calculate the middle position of the hit math_utils::Vector3D xyzPositionMiddle = (xyzPositionStart + xyzPositionEnd) * 0.5f;