diff --git a/Detectors/TPC/calibration/include/TPCCalibration/PressureTemperatureHelper.h b/Detectors/TPC/calibration/include/TPCCalibration/PressureTemperatureHelper.h index 8317fc6bc68d8..402b85fec6b70 100644 --- a/Detectors/TPC/calibration/include/TPCCalibration/PressureTemperatureHelper.h +++ b/Detectors/TPC/calibration/include/TPCCalibration/PressureTemperatureHelper.h @@ -28,6 +28,11 @@ class InputSpec; class OutputSpec; } // namespace o2::framework +namespace o2::ccdb +{ +class BasicCCDBManager; +} // namespace o2::ccdb + namespace o2::tpc { @@ -42,6 +47,11 @@ class PressureTemperatureHelper /// trigger checking for CCDB objects void extractCCDBInputs(o2::framework::ProcessingContext& pc) const; + /// fetch pressure/temperature directly via a BasicCCDBManager (e.g. from O2Physics analysis tasks, outside of a + /// DPL device) and refit them. The (comparably expensive) refit is skipped if the CCDB objects did not change + /// since the last call. + void extractCCDBInputs(o2::ccdb::BasicCCDBManager& ccdb, long timestampMS); + // add required inputs static void requestCCDBInputs(std::vector& inputs); @@ -98,7 +108,10 @@ class PressureTemperatureHelper std::pair, std::vector> mTemperatureC; ///< temperature values C-side int mFitIntervalMS{5 * 60 * 1000}; ///< fit interval for the temperature - ClassDefNV(PressureTemperatureHelper, 1); + const void* mLastPressureObj{}; //! last pressure object accounted for via BasicCCDBManager, for dedup only, not streamed + const void* mLastTemperatureObj{}; //! last temperature object accounted for via BasicCCDBManager, for dedup only, not streamed + + ClassDefNV(PressureTemperatureHelper, 2); }; } // namespace o2::tpc #endif diff --git a/Detectors/TPC/calibration/include/TPCCalibration/VDriftHelper.h b/Detectors/TPC/calibration/include/TPCCalibration/VDriftHelper.h index d600df201f985..5522f5aa42743 100644 --- a/Detectors/TPC/calibration/include/TPCCalibration/VDriftHelper.h +++ b/Detectors/TPC/calibration/include/TPCCalibration/VDriftHelper.h @@ -30,6 +30,11 @@ class ConcreteDataMatcher; class InputSpec; } // namespace o2::framework +namespace o2::ccdb +{ +class BasicCCDBManager; +} // namespace o2::ccdb + namespace o2::tpc { class LtrCalibData; @@ -63,9 +68,16 @@ class VDriftHelper void extractCCDBInputs(o2::framework::ProcessingContext& pc, bool laser = true, bool itstpcTgl = true); static void requestCCDBInputs(std::vector& inputs, bool laser = true, bool itstpcTgl = true); + /// Fetch calibration objects via a BasicCCDBManager and update the VDrift accordingly (for use outside a DPL + /// device, e.g. O2Physics). Objects are only re-accounted if they actually changed since the last call. + void extractCCDBInputs(o2::ccdb::BasicCCDBManager& ccdb, long timestampMS, bool laser = false, bool itstpcTgl = true); + protected: static void addInput(std::vector& inputs, o2::framework::InputSpec&& isp); bool extractTPForVDrift(VDriftCorrFact& vdrift, int64_t tsStepMS = 100 * 1000); + + /// Combine the previously accounted laser/ITS-TPC-Tgl inputs, applying T/P scaling if possible, into mVD. + void updateVDrift(long currentTimeMS); VDriftCorrFact mVDLaser{}; VDriftCorrFact mVDTPCITSTgl{}; VDriftCorrFact mVD{}; diff --git a/Detectors/TPC/calibration/src/PressureTemperatureHelper.cxx b/Detectors/TPC/calibration/src/PressureTemperatureHelper.cxx index 4f22ef8e35a03..daab429f0b8f2 100644 --- a/Detectors/TPC/calibration/src/PressureTemperatureHelper.cxx +++ b/Detectors/TPC/calibration/src/PressureTemperatureHelper.cxx @@ -20,6 +20,8 @@ #include "Framework/InputRecord.h" #include "Framework/CCDBParamSpec.h" #include "Framework/DataAllocator.h" +#include "Framework/ConcreteDataMatcher.h" +#include "CCDB/BasicCCDBManager.h" using namespace o2::tpc; using namespace o2::framework; @@ -30,6 +32,26 @@ void PressureTemperatureHelper::extractCCDBInputs(ProcessingContext& pc) const pc.inputs().get("temperature"); } +void PressureTemperatureHelper::extractCCDBInputs(o2::ccdb::BasicCCDBManager& ccdb, long timestampMS) +{ + // getForTimeStamp() is cheap to call every time; compare the returned pointer, not ccdb's own TTL-based cache + // validity, since ccdb only swaps in a new pointer once the content actually changes. + const auto pressurePath = CDBTypeMap.at(CDBType::CalPressure); + if (auto* pressure = ccdb.getForTimeStamp(pressurePath, timestampMS)) { + if (pressure != mLastPressureObj) { + accountCCDBInputs(ConcreteDataMatcher(o2::header::gDataOriginTPC, "PRESSURECCDB", 0), const_cast(pressure)); + mLastPressureObj = pressure; + } + } + const auto temperaturePath = CDBTypeMap.at(CDBType::CalTemperature); + if (auto* temperature = ccdb.getForTimeStamp(temperaturePath, timestampMS)) { + if (temperature != mLastTemperatureObj) { + accountCCDBInputs(ConcreteDataMatcher(o2::header::gDataOriginTPC, "TEMPERATURECCDB", 0), const_cast(temperature)); + mLastTemperatureObj = temperature; + } + } +} + bool PressureTemperatureHelper::accountCCDBInputs(const ConcreteDataMatcher& matcher, void* obj) { if (matcher == ConcreteDataMatcher(o2::header::gDataOriginTPC, "PRESSURECCDB", 0)) { diff --git a/Detectors/TPC/calibration/src/VDriftHelper.cxx b/Detectors/TPC/calibration/src/VDriftHelper.cxx index a7fce18c4b54b..11c29aca3c50f 100644 --- a/Detectors/TPC/calibration/src/VDriftHelper.cxx +++ b/Detectors/TPC/calibration/src/VDriftHelper.cxx @@ -21,6 +21,8 @@ #include "Framework/InputRecord.h" #include "Framework/ConcreteDataMatcher.h" #include "Framework/TimingInfo.h" +#include "CCDB/BasicCCDBManager.h" +#include using namespace o2::tpc; using namespace o2::framework; @@ -147,13 +149,47 @@ void VDriftHelper::extractCCDBInputs(ProcessingContext& pc, bool laser, bool its pc.inputs().get("vdriftTgl"); } mPTHelper.extractCCDBInputs(pc); + updateVDrift(pc.services().get().creation); +} +//________________________________________________________ +void VDriftHelper::extractCCDBInputs(o2::ccdb::BasicCCDBManager& ccdb, long timestampMS, bool laser, bool itstpcTgl) +{ + if (mForceParamDrift && mForceParamOffset) { // fixed from the command line + return; + } + if (laser && !mForceParamDrift) { + if (auto* calib = ccdb.getForTimeStamp(CDBTypeMap.at(CDBType::CalLaserTracks), timestampMS)) { + if (calib->creationTime != mVDLaser.creationTime) { // account only if this is a genuinely new object + accountLaserCalibration(calib); + } + } + } + if (itstpcTgl) { + if (auto* calib = ccdb.getForTimeStamp(CDBTypeMap.at(CDBType::CalVDriftTgl), timestampMS)) { + if (calib->creationTime != mVDTPCITSTgl.creationTime) { // account only if this is a genuinely new object + accountDriftCorrectionITSTPCTgl(calib); + } + } + } + mPTHelper.extractCCDBInputs(ccdb, timestampMS); + updateVDrift(timestampMS); + // unlike the ProcessingContext overload above, callers here have no isUpdated()/acknowledgeUpdate() cycle of + // their own, so consume the update ourselves -- otherwise mUpdated (set once, e.g. in the constructor, and never + // cleared) would keep re-triggering the full block above, and its logging, on every call, even with an unchanged + // CCDB object. + acknowledgeUpdate(); +} + +//________________________________________________________ +void VDriftHelper::updateVDrift(long currentTimeMS) +{ if (mUpdated || mIsTPScalingPossible) { // there was a change // prefer among laser and tgl VDrift the one with the latest update time auto saveVD = mVD; // apply TP scaling of mVD if possible - if (float tp = mPTHelper.getTP(pc.services().get().creation); tp > 0) { + if (float tp = mPTHelper.getTP(currentTimeMS); tp > 0) { // try to extract refTP if needed auto& vd = (mVDTPCITSTgl.creationTime < mVDLaser.creationTime) ? mVDLaser : mVDTPCITSTgl; if (mForceTPScaling) { @@ -167,7 +203,11 @@ void VDriftHelper::extractCCDBInputs(ProcessingContext& pc, bool laser, bool its mUpdated = true; vd.normalizeTP(tp); // keep refVDrift constant, fold the T/P scaling into the correction factor if (vd.creationTime == saveVD.creationTime) { - LOGP(info, "VDriftHelper: Scaling VDrift from {} to {} with T/P from {} to {}", saveVD.getVDrift(), vd.getVDrift(), saveVD.refTP, vd.refTP); + // log only on a meaningful change + constexpr float RelChangeToLog = 1e-3f; // 0.1% + if (std::abs(vd.getVDrift() - saveVD.getVDrift()) > RelChangeToLog * std::abs(saveVD.getVDrift())) { + LOGP(info, "VDriftHelper: Scaling VDrift from {} to {} with T/P from {} to {}", saveVD.getVDrift(), vd.getVDrift(), saveVD.refTP, vd.refTP); + } } else { LOGP(info, "VDriftHelper: Init new VDrift of {} with T/P {}", vd.getVDrift(), vd.refTP); } @@ -200,7 +240,9 @@ void VDriftHelper::extractCCDBInputs(ProcessingContext& pc, bool laser, bool its } rep += fmt::format(" but {} imposed from command line", impos); } - LOGP(info, "{}", rep); + if (mVD.creationTime != saveVD.creationTime) { // only log which source was (re-)selected when that choice actually changed + LOGP(info, "{}", rep); + } } }