Skip to content

Commit d44ccff

Browse files
change to unique function to load map. Add check to ensure that the minimum time resolution is not zero for rescaling
1 parent fe47e4f commit d44ccff

3 files changed

Lines changed: 95 additions & 32 deletions

File tree

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,16 @@ 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
33+
34+
// Optional map paths. Prefix with "ccdb://" to fetch from CCDB, otherwise the path is opened with TFile::Open
35+
// (local file, alien://, root://, ...). An empty path disables the map.
36+
std::string efficiencyMapPath{}; ///< optional efficiency map path.
37+
///< e.g. ccdb://Users/g/glucia/tmp/ALICE3/IOTOF/pixelEfficiency
38+
///< or alien:///alice/cern.ch/user/g/glucia/ALICE3/IOTOF/pixelEfficiency/PixelEfficiencyMap_TH2.root
39+
std::string resolutionMapPath{}; ///< optional resolution map path.
40+
///< e.g. alien:///alice/cern.ch/user/g/glucia/ALICE3/IOTOF/pixelEfficiency/PixelResolutionMap_TH2.root
41+
std::string timeOfArrivalMapPath{}; ///< optional time of arrival map path.
42+
3543
int chargeThreshold = 100; ///< charge threshold in Nelectrons
3644
int minChargeToAccount = 7; ///< minimum charge contribution to account
3745
int nSimSteps = 10; ///< number of steps in response simulation

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,14 @@ class Digitizer : public TObject
8686
void stepping(const o2::itsmft::Hit& hit, float**& respMatrix, float**& avgHitLocalX, float**& avgHitLocalZ, int& rowStart, int& colStart, int& rowSpan, int& colSpan);
8787

8888
/// Apply time smearing to simulate detector resolution
89-
double smearTime(double time) const;
89+
double smearTime(double time, const float x, const float z) const;
9090

9191
/// Convert energy loss to charge
9292
int energyToCharge(float energyLoss) const;
9393

94-
/// Load the efficiency map from a file
95-
void loadEfficiencyMap(const std::string& filePath);
94+
/// Load a map from CCDB (path prefixed with "ccdb://") or from a ROOT file (any other path)
95+
/// \param mapName Name of the histogram inside the ROOT file (ignored for CCDB)
96+
void loadMap(TH2D*& map, const std::string& path, const char* mapName);
9697

9798
/// Check if the hit passes efficiency cut
9899
/// \param x Detector local coordinate x in cm with respect to the center of the sensitive volume.
@@ -118,6 +119,8 @@ class Digitizer : public TObject
118119

119120
const o2::iotof::GeometryTGeo* mGeometry = nullptr; ///< IOTOF geometry
120121
TH2D* mEfficiencyMap = nullptr; ///< Efficiency map for the detector
122+
TH2D* mResolutionMap = nullptr; ///< Resolution map for the detector
123+
TH2D* mTimeOfArrivalMap = nullptr; ///< Time of arrival map for the detector
121124

122125
std::vector<o2::iotof::Chip> mChips; //! Chips in the detector, indexed by chip ID
123126
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: 79 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@
1919
#include "IOTOFSimulation/Digitizer.h"
2020
#include "IOTOFSimulation/DPLDigitizerParam.h"
2121
#include "DetectorsRaw/HBFUtils.h"
22+
#include "CCDB/BasicCCDBManager.h"
2223

2324
#include <TCollection.h>
2425
#include <TFile.h>
2526
#include <TKey.h>
2627
#include <TRandom.h>
2728

2829
#include <set>
30+
#include <string_view>
2931
#include <vector>
3032
#include <iostream>
3133
#include <numeric>
@@ -66,15 +68,28 @@ void Digitizer::init()
6668
}
6769
}
6870

69-
if (!digitizerParams.efficiencyFilePath.empty()) {
70-
loadEfficiencyMap(digitizerParams.efficiencyFilePath);
71-
}
71+
const auto& digitizerParams = o2::iotof::DPLDigitizerParam::Instance();
7272

7373
LOG(info) << "Initializing IOTOF digitizer";
7474
LOG(info) << " Time resolution: " << digitizerParams.timeResolution * 1e3 << " ps";
7575
LOG(info) << " Charge threshold: " << digitizerParams.chargeThreshold << " electrons";
76-
LOG(info) << " Detection efficiency: " << digitizerParams.efficiency * 100 << " %";
7776
LOG(info) << " Continuous mode: " << (mContinuous ? "ON" : "OFF");
77+
78+
loadMap(mEfficiencyMap, digitizerParams.efficiencyMapPath, "hEfficiencyMap");
79+
if (!mEfficiencyMap) {
80+
LOG(info) << "No efficiency map loaded, using uniform efficiency: " << digitizerParams.efficiency * 100 << " %";
81+
}
82+
83+
loadMap(mResolutionMap, digitizerParams.resolutionMapPath, "hResolutionMap");
84+
if (!mResolutionMap) {
85+
LOG(info) << "No resolution map loaded, using uniform time resolution: " << digitizerParams.timeResolution * 1e3 << " ps";
86+
}
87+
88+
loadMap(mTimeOfArrivalMap, digitizerParams.timeOfArrivalMapPath, "hTimeOfArrivalMap");
89+
if (!mTimeOfArrivalMap) {
90+
LOG(info) << "No time of arrival map loaded";
91+
}
92+
7893
sSegmentation = o2::iotof::Segmentation::Instance();
7994
}
8095

@@ -173,12 +188,11 @@ void Digitizer::processHit(const o2::itsmft::Hit& hit, int evID, int srcID)
173188
LOG(debug) << "Hit rejected by efficiency cut at pixel (row,col) = (" << rowIS << ", " << colIS << ")";
174189
continue;
175190
}
191+
double smearedTime = smearTime(hitTimeWrtBC, avgHitLocalX[irow][icol], avgHitLocalZ[irow][icol]);
176192

177193
const int nElectronsSampled = gRandom->Poisson(electronsPerStep * nEleResp);
178194
// Noise can be added here if needed
179195

180-
double smearedTime = smearTime(hitTimeWrtBC);
181-
182196
registerDigits(chip, roFrameAbs, smearedTime, nROF,
183197
static_cast<uint16_t>(rowIS), static_cast<uint16_t>(colIS), nElectronsSampled, label);
184198
}
@@ -326,12 +340,22 @@ void Digitizer::stepping(const o2::itsmft::Hit& hit, float**& respMatrix, float*
326340
}
327341

328342
//_______________________________________________________________________
329-
double Digitizer::smearTime(double time) const
343+
double Digitizer::smearTime(double time, const float x, const float y) const
330344
{
331345
// Apply Gaussian smearing to simulate detector time resolution
332346
const auto& digitizerParams = o2::iotof::DPLDigitizerParam::Instance();
347+
348+
float resolutionScaling = 1.;
349+
if (mResolutionMap) {
350+
const float minimumResolution = mResolutionMap->GetMinimum();
351+
int bin = mResolutionMap->FindBin(x * o2::iotof::Digitizer::cm2um, y * o2::iotof::Digitizer::cm2um);
352+
resolutionScaling = minimumResolution > 0. ? mResolutionMap->GetBinContent(bin) / minimumResolution : 1.;
353+
LOG(debug) << "Time resolution map check: x=" << x * o2::iotof::Digitizer::cm2um << ", y=" << y * o2::iotof::Digitizer::cm2um << ", bin=" << bin << ", resolution=" << minimumResolution;
354+
LOG(debug) << "Time resolution scaling: " << resolutionScaling;
355+
}
356+
333357
if (digitizerParams.timeResolution > 0) {
334-
return time + gRandom->Gaus(0, digitizerParams.timeResolution);
358+
return time + gRandom->Gaus(0, digitizerParams.timeResolution * resolutionScaling);
335359
}
336360
return time;
337361
}
@@ -347,31 +371,59 @@ int Digitizer::energyToCharge(float energyLoss) const
347371
}
348372

349373
//_______________________________________________________________________
350-
void Digitizer::loadEfficiencyMap(const std::string& filePath)
374+
375+
void Digitizer::loadMap(TH2D*& map, const std::string& path, const char* mapName)
351376
{
352-
// Load the efficiency map from a file
353-
TFile* file = TFile::Open(filePath.c_str());
354-
if (!file || !file->IsOpen()) {
355-
LOG(error) << "Failed to open efficiency map file: " << filePath;
377+
// Load a map either from CCDB (path prefixed with "ccdb://") or from a ROOT file
378+
// (anything TFile::Open understands: local path, alien://, root://, http://, ...)
379+
static constexpr std::string_view ccdbPrefix = "ccdb://";
380+
381+
if (path.empty()) {
356382
return;
357383
}
358384

359-
auto* rawMap = dynamic_cast<TH2D*>(file->Get("hEfficiencyMap"));
360-
if (!rawMap) {
361-
LOG(error) << "Failed to retrieve efficiency map from file: " << filePath;
362-
LOG(error) << "Available keys in the file:";
363-
TIter next(file->GetListOfKeys());
364-
TKey* key;
365-
while ((key = dynamic_cast<TKey*>(next()))) {
366-
LOG(error) << " " << key->GetName() << " (" << key->GetClassName() << ")";
385+
TH2D* rawMap = nullptr;
386+
TFile* file = nullptr;
387+
388+
if (path.rfind(ccdbPrefix, 0) == 0) {
389+
const std::string ccdbPath = path.substr(ccdbPrefix.size());
390+
LOG(info) << "Loading " << mapName << " from CCDB: " << ccdbPath;
391+
rawMap = o2::ccdb::BasicCCDBManager::instance().get<TH2D>(ccdbPath); // owned by the CCDB manager
392+
if (!rawMap) {
393+
LOG(error) << "Failed to retrieve " << mapName << " from CCDB path: " << ccdbPath;
394+
return;
395+
}
396+
} else {
397+
LOG(info) << "Loading " << mapName << " from file: " << path;
398+
file = TFile::Open(path.c_str());
399+
if (!file || !file->IsOpen()) {
400+
LOG(error) << "Failed to open file: " << path;
401+
delete file;
402+
return;
403+
}
404+
rawMap = dynamic_cast<TH2D*>(file->Get(mapName));
405+
if (!rawMap) {
406+
LOG(error) << "Failed to retrieve " << mapName << " from file: " << path;
407+
LOG(error) << "Available keys in the file:";
408+
TIter next(file->GetListOfKeys());
409+
TKey* key;
410+
while ((key = dynamic_cast<TKey*>(next()))) {
411+
LOG(error) << " " << key->GetName() << " (" << key->GetClassName() << ")";
412+
}
413+
file->Close();
414+
delete file;
415+
return;
367416
}
368-
file->Close();
369-
return;
370417
}
371-
mEfficiencyMap = dynamic_cast<TH2D*>(rawMap->Clone("mEfficiencyMap"));
372-
mEfficiencyMap->SetDirectory(nullptr); // Detach from file to avoid deletion when file is closed
373418

374-
file->Close();
419+
map = dynamic_cast<TH2D*>(rawMap->Clone());
420+
map->SetDirectory(nullptr); // Detach from file to avoid deletion when file is closed
421+
LOG(info) << "Loaded " << mapName << " (" << map->GetNbinsX() << " x " << map->GetNbinsY() << " bins)";
422+
423+
if (file) {
424+
file->Close();
425+
delete file;
426+
}
375427
}
376428

377429
//_______________________________________________________________________
@@ -469,7 +521,7 @@ void Digitizer::registerDigits(Chip& chip, uint32_t roFrame, double time, int nR
469521
int tdc = int((time - nbc * o2::constants::lhc::LHCBunchSpacingNS) / digitizerParams.tdcBin);
470522
nbc += mEventTime.toLong();
471523

472-
double absoluteTime = tdc * digitizerParams.tdcBin + nbc * o2::constants::lhc::LHCBunchSpacingNS;
524+
double absoluteTime = tdc * digitizerParams.tdcBin * 1.e-9 + nbc * o2::constants::lhc::LHCBunchSpacingNS;
473525

474526
auto key = o2::iotof::Digit::getOrderingKey(nbc, tdc, row, col);
475527
o2::iotof::LabeledDigit* existingDigit = chip.findDigit(key);

0 commit comments

Comments
 (0)