Skip to content

Commit b122c5f

Browse files
IOTOF: add in-pixel efficiency (#15786)
* add pixel efficiency map to iotof digitization * add path to the available file in a comment * change binning of the histograms * clang-format * revert size of the histograms
1 parent 22aefee commit b122c5f

3 files changed

Lines changed: 78 additions & 12 deletions

File tree

‎Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ struct DPLDigitizerParam : public o2::conf::ConfigurableParamHelper<DPLDigitizer
3030
float timeResolution = 0.020f; ///< time resolution sigma in ns (20 ps default)
3131
float tdcBin = 0.010f; ///< TDC time bin (10 ps default)
3232
float efficiency = 0.98f; ///< detection efficiency
33+
std::string efficiencyFilePath{}; ///< optional efficiency map file path.
34+
///< The efficiency map is currently available at /alice/cern.ch/user/g/glucia/ALICE3/IOTOF/pixelEfficiency/PixelEfficiencyMap_TH2.root. FIXME to be removed once switch to CCDBFetcher
3335
int chargeThreshold = 100; ///< charge threshold in Nelectrons
3436
int minChargeToAccount = 7; ///< minimum charge contribution to account
3537
int nSimSteps = 1; ///< number of steps in response simulation

‎Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Digitizer.h‎

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@
2323
#include <deque>
2424
#include <memory>
2525

26-
#include "Rtypes.h" // for Digitizer::Class
27-
#include "TObject.h" // for TObject
26+
#include <TH2D.h>
27+
#include <Rtypes.h> // for Digitizer::Class
28+
#include <TObject.h> // for TObject
2829

2930
#include "ITSMFTSimulation/Hit.h"
3031
#include "DataFormatsIOTOF/Digit.h"
@@ -90,8 +91,13 @@ class Digitizer : public TObject
9091
/// Convert energy loss to charge
9192
int energyToCharge(float energyLoss) const;
9293

94+
/// Load the efficiency map from a file
95+
void loadEfficiencyMap(const std::string& filePath);
96+
9397
/// Check if the hit passes efficiency cut
94-
bool isEfficient() const;
98+
/// \param x Detector local coordinate x in cm with respect to the center of the sensitive volume.
99+
/// \param z Detector local coordinate z in cm with respect to the center of the sensitive volume.
100+
bool isEfficient(const float x, const float z) const;
95101

96102
std::vector<o2::iotof::McLabelRef>* getExtraLabelBuffer(uint32_t roFrame)
97103
{
@@ -108,8 +114,10 @@ class Digitizer : public TObject
108114
}
109115

110116
static constexpr float sec2ns = 1e9f; ///< seconds to nanoseconds conversion
117+
static constexpr float cm2um = 1e4f; ///< centimeters to micrometers conversion
111118

112119
const o2::iotof::GeometryTGeo* mGeometry = nullptr; ///< IOTOF geometry
120+
TH2D* mEfficiencyMap = nullptr; ///< Efficiency map for the detector
113121

114122
std::vector<o2::iotof::Chip> mChips; //! Chips in the detector, indexed by chip ID
115123
std::deque<std::unique_ptr<std::vector<o2::iotof::McLabelRef>>> mExtraLabelBuffer; //! buffer for multiple mc labels to the same pixel

‎Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx‎

Lines changed: 65 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@
2020
#include "IOTOFSimulation/DPLDigitizerParam.h"
2121
#include "DetectorsRaw/HBFUtils.h"
2222

23+
#include <TCollection.h>
24+
#include <TFile.h>
25+
#include <TKey.h>
2326
#include <TRandom.h>
27+
2428
#include <vector>
2529
#include <iostream>
2630
#include <numeric>
@@ -51,6 +55,9 @@ void Digitizer::init()
5155
}
5256

5357
const auto& digitizerParams = o2::iotof::DPLDigitizerParam::Instance();
58+
if (!digitizerParams.efficiencyFilePath.empty()) {
59+
loadEfficiencyMap(digitizerParams.efficiencyFilePath);
60+
}
5461

5562
LOG(info) << "Initializing IOTOF digitizer";
5663
LOG(info) << " Time resolution: " << digitizerParams.timeResolution * 1e3 << " ps";
@@ -95,12 +102,6 @@ void Digitizer::processHit(const o2::itsmft::Hit& hit, int evID, int srcID)
95102
{
96103
// Process a single hit and create a digit if it passes all cuts
97104

98-
// Apply efficiency cut
99-
if (!isEfficient()) {
100-
LOG(debug) << "Hit rejected by efficiency cut";
101-
return;
102-
}
103-
104105
// Get detector element ID
105106
const int chipID = hit.GetDetectorID();
106107
auto& chip = mChips[chipID];
@@ -109,6 +110,26 @@ void Digitizer::processHit(const o2::itsmft::Hit& hit, int evID, int srcID)
109110
return;
110111
}
111112

113+
// middle position of the hit in the sensor frame
114+
const auto& matrix = mGeometry->getMatrixL2G(chipID);
115+
auto xyzPositionStart = matrix ^ hit.GetPosStart();
116+
auto xyzPositionEnd = matrix ^ hit.GetPos();
117+
const auto xMid = 0.5f * (xyzPositionStart.X() + xyzPositionEnd.X());
118+
const auto zMid = 0.5f * (xyzPositionStart.Z() + xyzPositionEnd.Z());
119+
// move this to the local pixel coordinates for the efficiency map
120+
int row, col;
121+
float xPixelCenter, zPixelCenter;
122+
if (!sSegmentation->localToDetector(xMid, zMid, row, col, mGeometry->getIOTOFLayer(chipID))) {
123+
LOG(debug) << "Hit rejected because position (" << xMid << ", " << zMid << ") is outside the active area of chip " << chipID;
124+
return; // hit is outside the active area
125+
}
126+
sSegmentation->detectorToLocalUnchecked(row, col, xPixelCenter, zPixelCenter, mGeometry->getIOTOFLayer(chipID));
127+
128+
if (!isEfficient(xMid - xPixelCenter, zMid - zPixelCenter)) {
129+
LOG(debug) << "Hit rejected by efficiency cut";
130+
return;
131+
}
132+
112133
// Convert energy loss to charge (number of electrons)
113134
float energyLoss = hit.GetEnergyLoss(); // in GeV
114135
int charge = energyToCharge(energyLoss);
@@ -126,7 +147,7 @@ void Digitizer::processHit(const o2::itsmft::Hit& hit, int evID, int srcID)
126147
double hitTime = hit.GetTime() * sec2ns; // convert to ns
127148
double eventTimeInBC = mEventTime.getTimeOffsetWrtBC(); // event time wrt bc
128149
double hitTimeWrtBC = hitTime + eventTimeInBC; // hit time wrt bc
129-
double smearedTime = smearTime(hitTimeWrtBC); // apply detector resolution
150+
double smearedTime = smearTime(hitTimeWrtBC);
130151

131152
if (chipID < 0 || chipID >= mGeometry->getSize() || mGeometry->getSize() < 1) {
132153
LOG(debug) << "Invalid detector ID: " << chipID << ", geometry size: " << mGeometry->getSize();
@@ -166,8 +187,8 @@ void Digitizer::processHit(const o2::itsmft::Hit& hit, int evID, int srcID)
166187

167188
void Digitizer::stepping(const o2::itsmft::Hit& hit, float**& respMatrix, int& rowStart, int& colStart, int& rowSpan, int& colSpan)
168189
{
169-
const auto& matrix = mGeometry->getMatrixL2G(hit.GetDetectorID());
170190
const int chipID = hit.GetDetectorID();
191+
const auto& matrix = mGeometry->getMatrixL2G(chipID);
171192
const int subdetectorID = mGeometry->getIOTOFLayer(chipID);
172193

173194
auto xyzPositionStart(matrix ^ (hit.GetPosStart())); // start position in sensor frame
@@ -277,10 +298,45 @@ int Digitizer::energyToCharge(float energyLoss) const
277298
}
278299

279300
//_______________________________________________________________________
280-
bool Digitizer::isEfficient() const
301+
void Digitizer::loadEfficiencyMap(const std::string& filePath)
302+
{
303+
// Load the efficiency map from a file
304+
TFile* file = TFile::Open(filePath.c_str());
305+
if (!file || !file->IsOpen()) {
306+
LOG(error) << "Failed to open efficiency map file: " << filePath;
307+
return;
308+
}
309+
310+
auto* rawMap = dynamic_cast<TH2D*>(file->Get("hEfficiencyMap"));
311+
if (!rawMap) {
312+
LOG(error) << "Failed to retrieve efficiency map from file: " << filePath;
313+
LOG(error) << "Available keys in the file:";
314+
TIter next(file->GetListOfKeys());
315+
TKey* key;
316+
while ((key = dynamic_cast<TKey*>(next()))) {
317+
LOG(error) << " " << key->GetName() << " (" << key->GetClassName() << ")";
318+
}
319+
file->Close();
320+
return;
321+
}
322+
mEfficiencyMap = dynamic_cast<TH2D*>(rawMap->Clone("mEfficiencyMap"));
323+
mEfficiencyMap->SetDirectory(nullptr); // Detach from file to avoid deletion when file is closed
324+
325+
file->Close();
326+
}
327+
328+
//_______________________________________________________________________
329+
bool Digitizer::isEfficient(const float x, const float z) const
281330
{
282331
// Apply efficiency cut using random number
283332
const auto& digitizerParams = o2::iotof::DPLDigitizerParam::Instance();
333+
if (mEfficiencyMap) {
334+
// int bin = mEfficiencyMap->FindBin(x * o2::iotof::Digitizer::cm2um, z * o2::iotof::Digitizer::cm2um);
335+
int bin = mEfficiencyMap->FindBin(x * o2::iotof::Digitizer::cm2um, z * o2::iotof::Digitizer::cm2um);
336+
float efficiency = mEfficiencyMap->GetBinContent(bin);
337+
LOG(debug) << "Efficiency map check: x=" << x * o2::iotof::Digitizer::cm2um << ", z=" << z * o2::iotof::Digitizer::cm2um << ", bin=" << bin << ", efficiency=" << efficiency;
338+
return gRandom->Uniform() < efficiency;
339+
}
284340
return gRandom->Uniform() < digitizerParams.efficiency;
285341
}
286342

0 commit comments

Comments
 (0)