From 5ff4381a5571ab569e716a76ad3917e22e00d6fe Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Mon, 9 Nov 2026 01:07:29 +0100 Subject: [PATCH] Resolve TPC digitizer calibration objects once per sector This moves the calibration lookups of the TPC DigitContainer out of the flush loop. - fillOutputContainer fetched the ion-tail and common-mode pad parameters, the dead channel map and the FEE config from the CDBInterface on every flush, the FEE config even once per time bin. - getDeadChannelMap() rebuilds the dead channel map from the pad flags on every call. - updateCalibrations() now fetches them once per sector from Digitizer::init(), with a fallback on the first flush for callers that do not call init(). - SAMPAProcessing picks up its pointers after this update, because a FEE parameter file reload replaces the objects it points to. https://its.cern.ch/jira/browse/O2-7309 Co-Authored-By: Claude Opus 5.5 --- .../include/TPCSimulation/DigitContainer.h | 9 +++ .../include/TPCSimulation/DigitTime.h | 2 +- .../TPC/simulation/src/DigitContainer.cxx | 75 +++++++++++-------- Detectors/TPC/simulation/src/Digitizer.cxx | 2 + 4 files changed, 54 insertions(+), 34 deletions(-) diff --git a/Detectors/TPC/simulation/include/TPCSimulation/DigitContainer.h b/Detectors/TPC/simulation/include/TPCSimulation/DigitContainer.h index 2a4e9e5b923ce..5f2070c0bf4f3 100644 --- a/Detectors/TPC/simulation/include/TPCSimulation/DigitContainer.h +++ b/Detectors/TPC/simulation/include/TPCSimulation/DigitContainer.h @@ -21,6 +21,7 @@ #include "TPCBase/CRU.h" #include "DataFormatsTPC/Defs.h" #include "TPCSimulation/DigitTime.h" +#include "TPCBase/CalDet.h" #include "CommonUtils/DebugStreamer.h" #include "TPCBase/ParameterDetector.h" #include "TPCBase/ParameterElectronics.h" @@ -78,6 +79,10 @@ class DigitContainer /// Get the size of the container for one event size_t size() const { return mTimeBins.size(); } + /// Fetch the calibration objects used by fillOutputContainer from the CDBInterface + /// Must be called after the CDBInterface is configured; fillOutputContainer calls it lazily otherwise + void updateCalibrations(); + private: TimeBin mFirstTimeBin = 0; ///< First time bin to consider TimeBin mEffectiveTimeBin = 0; ///< Effective time bin of that digit @@ -86,6 +91,10 @@ class DigitContainer std::deque mTimeBins; ///< Time bin Container for the ADC value std::unique_ptr mPrevDigArr; ///< Keep track of ToT and ion tail cumul from last time bin o2::utils::DebugStreamer mStreamer; ///< Debug streamer + const CalPad* mPadParams[3] = {nullptr, nullptr, nullptr}; //!< Ion tail fraction, ion tail slope and common mode k-values per pad + const CalDet* mDeadMap = nullptr; //!< Dead channel map + bool mCMCEnabled = false; //!< Common mode correction enabled in the FEE config (DigiMode Auto) + bool mCalibrationsUpdated = false; //!< Whether updateCalibrations was called void reportSettings(); }; diff --git a/Detectors/TPC/simulation/include/TPCSimulation/DigitTime.h b/Detectors/TPC/simulation/include/TPCSimulation/DigitTime.h index 361b1fb8f6572..9f951afc2442e 100644 --- a/Detectors/TPC/simulation/include/TPCSimulation/DigitTime.h +++ b/Detectors/TPC/simulation/include/TPCSimulation/DigitTime.h @@ -79,7 +79,7 @@ class DigitTime void fillOutputContainer(std::vector& output, dataformats::MCTruthContainer& mcTruth, std::vector& commonModeOutput, const Sector& sector, TimeBin timeBin, PrevDigitInfoArray* prevTime = nullptr, Streamer* debugStream = nullptr, - const CalPad* itParams[2] = nullptr, const CalDet* deadMap = nullptr); + const CalPad* padParams[3] = nullptr, const CalDet* deadMap = nullptr); private: std::array mCommonMode; ///< Common mode container - 4 GEM ROCs per sector diff --git a/Detectors/TPC/simulation/src/DigitContainer.cxx b/Detectors/TPC/simulation/src/DigitContainer.cxx index dfff4b91d6451..4c8ca8c2002db 100644 --- a/Detectors/TPC/simulation/src/DigitContainer.cxx +++ b/Detectors/TPC/simulation/src/DigitContainer.cxx @@ -43,21 +43,9 @@ void DigitContainer::fillOutputContainer(std::vector& output, // Without this we might get crashes in the clusterization step. static const int maxTimeBinForTimeFrame = o2::conf::DigiParams::Instance().maxOrbitsToDigitize != -1 ? ((o2::conf::DigiParams::Instance().maxOrbitsToDigitize * 3564 + 2 * 8 - 2) / 8) : -1; - auto& cdb = CDBInterface::instance(); - - // ion tail per pad parameters - const CalPad* padParams[3] = {nullptr, nullptr, nullptr}; - - if (eleParam.doIonTailPerPad) { - const auto& itSettings = IonTailSettings::Instance(); - if (itSettings.padITCorrFile.size()) { - cdb.setFEEParamsFromFile(itSettings.padITCorrFile); - } - padParams[0] = &cdb.getITFraction(); - padParams[1] = &cdb.getITExpLambda(); - } - if (eleParam.doCommonModePerPad) { - padParams[2] = &cdb.getCMkValues(); + if (!mCalibrationsUpdated) { + LOG(debug) << "TPC DigitContainer: calibrations not set up before the first flush, fetching them now"; + updateCalibrations(); } const bool needsPrevDigArray = eleParam.doIonTail || eleParam.doIonTailPerPad || eleParam.doSaturationTail; @@ -68,17 +56,11 @@ void DigitContainer::fillOutputContainer(std::vector& output, mPrevDigArr = std::make_unique(); } - // dead channel map - const CalDet* deadMap = {nullptr}; - if (eleParam.applyDeadMap) { - deadMap = &cdb.getDeadChannelMap(); - } - static bool reportedSettings = false; if (!reportedSettings) { reportSettings(); - if (deadMap) { - LOGP(info, "Using dead map with {} masked pads", deadMap->getSum()); + if (mDeadMap) { + LOGP(info, "Using dead map with {} masked pads", mDeadMap->getSum()); } reportedSettings = true; } @@ -109,35 +91,34 @@ void DigitContainer::fillOutputContainer(std::vector& output, if (time) { switch (digitizationMode) { case DigitzationMode::FullMode: { - time->fillOutputContainer(output, mcTruth, commonModeOutput, sector, timeBin, mPrevDigArr.get(), debugStream, padParams, deadMap); + time->fillOutputContainer(output, mcTruth, commonModeOutput, sector, timeBin, mPrevDigArr.get(), debugStream, mPadParams, mDeadMap); break; } case DigitzationMode::ZeroSuppression: { - time->fillOutputContainer(output, mcTruth, commonModeOutput, sector, timeBin, mPrevDigArr.get(), debugStream, padParams, deadMap); + time->fillOutputContainer(output, mcTruth, commonModeOutput, sector, timeBin, mPrevDigArr.get(), debugStream, mPadParams, mDeadMap); break; } case DigitzationMode::ZeroSuppressionCMCorr: { - time->fillOutputContainer(output, mcTruth, commonModeOutput, sector, timeBin, mPrevDigArr.get(), debugStream, padParams, deadMap); + time->fillOutputContainer(output, mcTruth, commonModeOutput, sector, timeBin, mPrevDigArr.get(), debugStream, mPadParams, mDeadMap); break; } case DigitzationMode::SubtractPedestal: { - time->fillOutputContainer(output, mcTruth, commonModeOutput, sector, timeBin, mPrevDigArr.get(), debugStream, padParams, deadMap); + time->fillOutputContainer(output, mcTruth, commonModeOutput, sector, timeBin, mPrevDigArr.get(), debugStream, mPadParams, mDeadMap); break; } case DigitzationMode::NoSaturation: { - time->fillOutputContainer(output, mcTruth, commonModeOutput, sector, timeBin, mPrevDigArr.get(), debugStream, padParams, deadMap); + time->fillOutputContainer(output, mcTruth, commonModeOutput, sector, timeBin, mPrevDigArr.get(), debugStream, mPadParams, mDeadMap); break; } case DigitzationMode::PropagateADC: { - time->fillOutputContainer(output, mcTruth, commonModeOutput, sector, timeBin, mPrevDigArr.get(), debugStream, padParams, deadMap); + time->fillOutputContainer(output, mcTruth, commonModeOutput, sector, timeBin, mPrevDigArr.get(), debugStream, mPadParams, mDeadMap); break; } case DigitzationMode::Auto: { - const auto& feeConfig = cdb.getFEEConfig(); - if (feeConfig.isCMCEnabled()) { - time->fillOutputContainer(output, mcTruth, commonModeOutput, sector, timeBin, mPrevDigArr.get(), debugStream, padParams, deadMap); + if (mCMCEnabled) { + time->fillOutputContainer(output, mcTruth, commonModeOutput, sector, timeBin, mPrevDigArr.get(), debugStream, mPadParams, mDeadMap); } else { - time->fillOutputContainer(output, mcTruth, commonModeOutput, sector, timeBin, mPrevDigArr.get(), debugStream, padParams, deadMap); + time->fillOutputContainer(output, mcTruth, commonModeOutput, sector, timeBin, mPrevDigArr.get(), debugStream, mPadParams, mDeadMap); } break; } @@ -158,6 +139,34 @@ void DigitContainer::fillOutputContainer(std::vector& output, } } +void DigitContainer::updateCalibrations() +{ + const auto& eleParam = ParameterElectronics::Instance(); + auto& cdb = CDBInterface::instance(); + + // ion tail per pad parameters + mPadParams[0] = mPadParams[1] = mPadParams[2] = nullptr; + if (eleParam.doIonTailPerPad) { + const auto& itSettings = IonTailSettings::Instance(); + if (itSettings.padITCorrFile.size()) { + cdb.setFEEParamsFromFile(itSettings.padITCorrFile); + } + mPadParams[0] = &cdb.getITFraction(); + mPadParams[1] = &cdb.getITExpLambda(); + } + if (eleParam.doCommonModePerPad) { + mPadParams[2] = &cdb.getCMkValues(); + } + + // dead channel map + mDeadMap = eleParam.applyDeadMap ? &cdb.getDeadChannelMap() : nullptr; + + // common mode correction in the FEE, needed to resolve DigiMode Auto + mCMCEnabled = (eleParam.DigiMode == DigitzationMode::Auto) && cdb.getFEEConfig().isCMCEnabled(); + + mCalibrationsUpdated = true; +} + void DigitContainer::reportSettings() { auto& cdb = CDBInterface::instance(); diff --git a/Detectors/TPC/simulation/src/Digitizer.cxx b/Detectors/TPC/simulation/src/Digitizer.cxx index 49abc0a0b99af..82d5c9f065b0e 100644 --- a/Detectors/TPC/simulation/src/Digitizer.cxx +++ b/Detectors/TPC/simulation/src/Digitizer.cxx @@ -46,6 +46,8 @@ void Digitizer::init() auto& electronTransport = ElectronTransport::instance(); electronTransport.updateParameters(mVDrift); auto& sampaProcessing = SAMPAProcessing::instance(); + // the calibration update may reload FEE parameters from file, so SAMPAProcessing picks up its pointers afterwards + mDigitContainer.updateCalibrations(); sampaProcessing.updateParameters(mVDrift); }