Skip to content

Commit 489d19f

Browse files
TPC VDrift: make VDriftHelper usable outside DPL (e.g. O2Physics)
Split VDriftHelper::extractCCDBInputs into the CCDB-fetching part and a framework-independent updateVDrift() and add BasicCCDBManager-based overloads to VDriftHelper/PressureTemperatureHelper so O2Physics can call these directly instead of reimplementing the T/P-scaling logic (see AliceO2Group/O2Physics#17656). Calling these every event is cheap: laser/TGL/pressure/temperature are only re-accounted when the underlying CCDB object actually changed and logging is throttled to avoid stdout spam in trains.
1 parent de03530 commit 489d19f

4 files changed

Lines changed: 93 additions & 4 deletions

File tree

Detectors/TPC/calibration/include/TPCCalibration/PressureTemperatureHelper.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ class InputSpec;
2828
class OutputSpec;
2929
} // namespace o2::framework
3030

31+
namespace o2::ccdb
32+
{
33+
class BasicCCDBManager;
34+
} // namespace o2::ccdb
35+
3136
namespace o2::tpc
3237
{
3338

@@ -42,6 +47,11 @@ class PressureTemperatureHelper
4247
/// trigger checking for CCDB objects
4348
void extractCCDBInputs(o2::framework::ProcessingContext& pc) const;
4449

50+
/// fetch pressure/temperature directly via a BasicCCDBManager (e.g. from O2Physics analysis tasks, outside of a
51+
/// DPL device) and refit them. The (comparably expensive) refit is skipped if the CCDB objects did not change
52+
/// since the last call.
53+
void extractCCDBInputs(o2::ccdb::BasicCCDBManager& ccdb, long timestampMS);
54+
4555
// add required inputs
4656
static void requestCCDBInputs(std::vector<o2::framework::InputSpec>& inputs);
4757

@@ -98,7 +108,10 @@ class PressureTemperatureHelper
98108
std::pair<std::vector<float>, std::vector<ULong64_t>> mTemperatureC; ///< temperature values C-side
99109
int mFitIntervalMS{5 * 60 * 1000}; ///< fit interval for the temperature
100110

101-
ClassDefNV(PressureTemperatureHelper, 1);
111+
const void* mLastPressureObj{}; //! last pressure object accounted for via BasicCCDBManager, for dedup only, not streamed
112+
const void* mLastTemperatureObj{}; //! last temperature object accounted for via BasicCCDBManager, for dedup only, not streamed
113+
114+
ClassDefNV(PressureTemperatureHelper, 2);
102115
};
103116
} // namespace o2::tpc
104117
#endif

Detectors/TPC/calibration/include/TPCCalibration/VDriftHelper.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ class ConcreteDataMatcher;
3030
class InputSpec;
3131
} // namespace o2::framework
3232

33+
namespace o2::ccdb
34+
{
35+
class BasicCCDBManager;
36+
} // namespace o2::ccdb
37+
3338
namespace o2::tpc
3439
{
3540
class LtrCalibData;
@@ -63,9 +68,16 @@ class VDriftHelper
6368
void extractCCDBInputs(o2::framework::ProcessingContext& pc, bool laser = true, bool itstpcTgl = true);
6469
static void requestCCDBInputs(std::vector<o2::framework::InputSpec>& inputs, bool laser = true, bool itstpcTgl = true);
6570

71+
/// Fetch calibration objects via a BasicCCDBManager and update the VDrift accordingly (for use outside a DPL
72+
/// device, e.g. O2Physics). Objects are only re-accounted if they actually changed since the last call.
73+
void extractCCDBInputs(o2::ccdb::BasicCCDBManager& ccdb, long timestampMS, bool laser = false, bool itstpcTgl = true);
74+
6675
protected:
6776
static void addInput(std::vector<o2::framework::InputSpec>& inputs, o2::framework::InputSpec&& isp);
6877
bool extractTPForVDrift(VDriftCorrFact& vdrift, int64_t tsStepMS = 100 * 1000);
78+
79+
/// Combine the previously accounted laser/ITS-TPC-Tgl inputs, applying T/P scaling if possible, into mVD.
80+
void updateVDrift(long currentTimeMS);
6981
VDriftCorrFact mVDLaser{};
7082
VDriftCorrFact mVDTPCITSTgl{};
7183
VDriftCorrFact mVD{};

Detectors/TPC/calibration/src/PressureTemperatureHelper.cxx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#include "Framework/InputRecord.h"
2121
#include "Framework/CCDBParamSpec.h"
2222
#include "Framework/DataAllocator.h"
23+
#include "Framework/ConcreteDataMatcher.h"
24+
#include "CCDB/BasicCCDBManager.h"
2325

2426
using namespace o2::tpc;
2527
using namespace o2::framework;
@@ -30,6 +32,26 @@ void PressureTemperatureHelper::extractCCDBInputs(ProcessingContext& pc) const
3032
pc.inputs().get<dcs::Temperature*>("temperature");
3133
}
3234

35+
void PressureTemperatureHelper::extractCCDBInputs(o2::ccdb::BasicCCDBManager& ccdb, long timestampMS)
36+
{
37+
// getForTimeStamp() is cheap to call every time; compare the returned pointer, not ccdb's own TTL-based cache
38+
// validity, since ccdb only swaps in a new pointer once the content actually changes.
39+
const auto pressurePath = CDBTypeMap.at(CDBType::CalPressure);
40+
if (auto* pressure = ccdb.getForTimeStamp<dcs::Pressure>(pressurePath, timestampMS)) {
41+
if (pressure != mLastPressureObj) {
42+
accountCCDBInputs(ConcreteDataMatcher(o2::header::gDataOriginTPC, "PRESSURECCDB", 0), const_cast<dcs::Pressure*>(pressure));
43+
mLastPressureObj = pressure;
44+
}
45+
}
46+
const auto temperaturePath = CDBTypeMap.at(CDBType::CalTemperature);
47+
if (auto* temperature = ccdb.getForTimeStamp<dcs::Temperature>(temperaturePath, timestampMS)) {
48+
if (temperature != mLastTemperatureObj) {
49+
accountCCDBInputs(ConcreteDataMatcher(o2::header::gDataOriginTPC, "TEMPERATURECCDB", 0), const_cast<dcs::Temperature*>(temperature));
50+
mLastTemperatureObj = temperature;
51+
}
52+
}
53+
}
54+
3355
bool PressureTemperatureHelper::accountCCDBInputs(const ConcreteDataMatcher& matcher, void* obj)
3456
{
3557
if (matcher == ConcreteDataMatcher(o2::header::gDataOriginTPC, "PRESSURECCDB", 0)) {

Detectors/TPC/calibration/src/VDriftHelper.cxx

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#include "Framework/InputRecord.h"
2222
#include "Framework/ConcreteDataMatcher.h"
2323
#include "Framework/TimingInfo.h"
24+
#include "CCDB/BasicCCDBManager.h"
25+
#include <cmath>
2426

2527
using namespace o2::tpc;
2628
using namespace o2::framework;
@@ -147,13 +149,47 @@ void VDriftHelper::extractCCDBInputs(ProcessingContext& pc, bool laser, bool its
147149
pc.inputs().get<o2::tpc::VDriftCorrFact*>("vdriftTgl");
148150
}
149151
mPTHelper.extractCCDBInputs(pc);
152+
updateVDrift(pc.services().get<o2::framework::TimingInfo>().creation);
153+
}
150154

155+
//________________________________________________________
156+
void VDriftHelper::extractCCDBInputs(o2::ccdb::BasicCCDBManager& ccdb, long timestampMS, bool laser, bool itstpcTgl)
157+
{
158+
if (mForceParamDrift && mForceParamOffset) { // fixed from the command line
159+
return;
160+
}
161+
if (laser && !mForceParamDrift) {
162+
if (auto* calib = ccdb.getForTimeStamp<o2::tpc::LtrCalibData>(CDBTypeMap.at(CDBType::CalLaserTracks), timestampMS)) {
163+
if (calib->creationTime != mVDLaser.creationTime) { // account only if this is a genuinely new object
164+
accountLaserCalibration(calib);
165+
}
166+
}
167+
}
168+
if (itstpcTgl) {
169+
if (auto* calib = ccdb.getForTimeStamp<o2::tpc::VDriftCorrFact>(CDBTypeMap.at(CDBType::CalVDriftTgl), timestampMS)) {
170+
if (calib->creationTime != mVDTPCITSTgl.creationTime) { // account only if this is a genuinely new object
171+
accountDriftCorrectionITSTPCTgl(calib);
172+
}
173+
}
174+
}
175+
mPTHelper.extractCCDBInputs(ccdb, timestampMS);
176+
updateVDrift(timestampMS);
177+
// unlike the ProcessingContext overload above, callers here have no isUpdated()/acknowledgeUpdate() cycle of
178+
// their own, so consume the update ourselves -- otherwise mUpdated (set once, e.g. in the constructor, and never
179+
// cleared) would keep re-triggering the full block above, and its logging, on every call, even with an unchanged
180+
// CCDB object.
181+
acknowledgeUpdate();
182+
}
183+
184+
//________________________________________________________
185+
void VDriftHelper::updateVDrift(long currentTimeMS)
186+
{
151187
if (mUpdated || mIsTPScalingPossible) { // there was a change
152188
// prefer among laser and tgl VDrift the one with the latest update time
153189
auto saveVD = mVD;
154190

155191
// apply TP scaling of mVD if possible
156-
if (float tp = mPTHelper.getTP(pc.services().get<o2::framework::TimingInfo>().creation); tp > 0) {
192+
if (float tp = mPTHelper.getTP(currentTimeMS); tp > 0) {
157193
// try to extract refTP if needed
158194
auto& vd = (mVDTPCITSTgl.creationTime < mVDLaser.creationTime) ? mVDLaser : mVDTPCITSTgl;
159195
if (mForceTPScaling) {
@@ -167,7 +203,11 @@ void VDriftHelper::extractCCDBInputs(ProcessingContext& pc, bool laser, bool its
167203
mUpdated = true;
168204
vd.normalizeTP(tp); // keep refVDrift constant, fold the T/P scaling into the correction factor
169205
if (vd.creationTime == saveVD.creationTime) {
170-
LOGP(info, "VDriftHelper: Scaling VDrift from {} to {} with T/P from {} to {}", saveVD.getVDrift(), vd.getVDrift(), saveVD.refTP, vd.refTP);
206+
// log only on a meaningful change
207+
constexpr float RelChangeToLog = 1e-3f; // 0.1%
208+
if (std::abs(vd.getVDrift() - saveVD.getVDrift()) > RelChangeToLog * std::abs(saveVD.getVDrift())) {
209+
LOGP(info, "VDriftHelper: Scaling VDrift from {} to {} with T/P from {} to {}", saveVD.getVDrift(), vd.getVDrift(), saveVD.refTP, vd.refTP);
210+
}
171211
} else {
172212
LOGP(info, "VDriftHelper: Init new VDrift of {} with T/P {}", vd.getVDrift(), vd.refTP);
173213
}
@@ -200,7 +240,9 @@ void VDriftHelper::extractCCDBInputs(ProcessingContext& pc, bool laser, bool its
200240
}
201241
rep += fmt::format(" but {} imposed from command line", impos);
202242
}
203-
LOGP(info, "{}", rep);
243+
if (mVD.creationTime != saveVD.creationTime) { // only log which source was (re-)selected when that choice actually changed
244+
LOGP(info, "{}", rep);
245+
}
204246
}
205247
}
206248

0 commit comments

Comments
 (0)