Project
Loading...
Searching...
No Matches
VDriftHelper.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
18#include "Framework/Logger.h"
25#include <cmath>
26
27using namespace o2::tpc;
28using namespace o2::framework;
29
30//________________________________________________________
32{
33 const auto& gaspar = o2::tpc::ParameterGas::Instance();
34 const auto& detpar = o2::tpc::ParameterDetector::Instance();
35 const auto& elpar = o2::tpc::ParameterElectronics::Instance();
36 mVD.corrFact = 1.0;
37 mVD.refVDrift = gaspar.DriftV;
38 mVD.refTimeOffset = detpar.DriftTimeOffset * elpar.ZbinWidth; // convert time bins to \mus
39 // was it imposed from the command line?
40 mVD.creationTime = 1; // just to be above 0
41 if (o2::conf::ConfigurableParam::getProvenance("TPCGasParam.DriftV") == o2::conf::ConfigurableParam::EParamProvenance::kRT) { // we stick to this value
42 mVD.creationTime = std::numeric_limits<long>::max();
43 mForceParamDrift = true;
44 LOGP(info, "TPC VDrift was set from command line to {}, will neglect update from CCDB", mVD.refVDrift);
45 }
46 if (o2::conf::ConfigurableParam::getProvenance("TPCDetParam.DriftTimeOffset") == o2::conf::ConfigurableParam::EParamProvenance::kRT) { // we stick to this value
47 mVD.creationTime = std::numeric_limits<long>::max();
48 mForceParamOffset = true;
49 LOGP(info, "TPC drift time offset was set from command line to {} mus ({} TB), will neglect update from CCDB",
50 mVD.refTimeOffset, detpar.DriftTimeOffset);
51 }
52
53 // check if temperature and pressure is set from the command line
55 mForceTPScaling = true;
56 LOGP(info, "VDriftHelper: Temperature and pressure were set from command line to {} C and {} mbar, will neglect updates from CCDB", gaspar.Temperature, gaspar.Pressure);
57 if (gaspar.Temperature <= 0 || gaspar.Pressure <= 0) {
58 LOGP(info, "VDriftHelper: Disabling VDrift scaling with T / P");
59 }
60 }
61
62 mUpdated = true;
64}
65
66//________________________________________________________
67void VDriftHelper::accountLaserCalibration(const LtrCalibData* calib, long fallBackTimeStamp)
68{
69 if (!calib || mForceParamDrift) { // laser may set only DriftParam (the offset is 0)
70 return;
71 }
72 if (!calib->isValid()) {
73 LOGP(warn, "Ignoring invalid laser calibration (corrections: A-side={}, C-side={}, NTracks: A-side={} C-side={})", calib->dvCorrectionA, calib->dvCorrectionC, calib->nTracksA, calib->nTracksC);
74 return;
75 }
76 // old entries of laser calib have no update time assigned
77 long updateTS = calib->creationTime > 0 ? calib->creationTime : fallBackTimeStamp;
78 LOG(info) << "accountLaserCalibration " << calib->refVDrift << " / " << calib->getDriftVCorrection() << " t " << updateTS << " vs " << mVDLaser.creationTime;
79 // old entries of laser calib have no reference assigned
80 float ref = calib->refVDrift > 0. ? calib->refVDrift : o2::tpc::ParameterGas::Instance().DriftV;
81 float corr = calib->getDriftVCorrection();
82 if (corr > 0.) { // laser correction is inverse multiplicative
83 static bool firstCall = true;
84 auto prevRef = mVDLaser.refVDrift;
86 mVDLaser.corrFact = 1. / corr;
89 mVDLaser.refTP = calib->tp;
90 mUpdated = true;
92 if (mMayRenormSrc & (0x1U << Source::Laser)) { // this was 1st setting?
93 if (corr != 1.f) { // this may happen if old-style (non-normalized) standalone or non-normalized run-time laset calibration is used
94 LOGP(warn, "VDriftHelper: renorming initial TPC refVDrift={}/correction={} to {}/1.0, source: {}", mVDLaser.refVDrift, mVDLaser.corrFact, mVDLaser.getVDrift(), getSourceName(mSource));
95 mVDLaser.normalize(); // renorm reference to have correction = 1.
96 }
97 mMayRenormSrc &= ~(0x1U << Source::Laser); // unset MayRenorm
98 } else if (ref != prevRef) { // we want to keep the same reference over the run, this may happen if run-time laser calibration is supplied
99 LOGP(warn, "VDriftHelper: renorming updated TPC refVDrift={}/correction={} previous refVDrift {}, source: {}", mVDLaser.refVDrift, mVDLaser.corrFact, prevRef, getSourceName(mSource));
100 mVDLaser.normalize(prevRef);
101 }
102 }
103}
104
105//________________________________________________________
107{
108 if (!calib || (mForceParamDrift && mForceParamOffset)) {
109 return;
110 }
111 LOG(info) << "accountDriftCorrectionITSTPCTgl " << calib->corrFact << " t " << calib->creationTime << " vs " << mVDTPCITSTgl.creationTime;
112 auto prevRefVDrift = mVDTPCITSTgl.refVDrift;
113 auto prevRefTOffs = mVDTPCITSTgl.refTimeOffset;
114 mVDTPCITSTgl = *calib;
115 mUpdated = true;
117 if (mMayRenormSrc & (0x1U << Source::ITSTPCTgl)) { // this was 1st setting?
118 if (!mForceParamDrift && mVDTPCITSTgl.corrFact != 1.f) { // this may happen if calibration from prevous run is used
119 LOGP(warn, "VDriftHelper: renorming initial TPC refVDrift={}/correction={} to {}/1.0, source: {}", mVDTPCITSTgl.refVDrift, mVDTPCITSTgl.corrFact, mVDTPCITSTgl.getVDrift(), getSourceName(mSource));
120 mVDTPCITSTgl.normalize(); // renorm reference to have correction = 1.
121 }
123 LOGP(warn, "VDriftHelper: renorming initial TPC refTimeOffset={}/correction={} to {}/0.0, source: {}", mVDTPCITSTgl.refTimeOffset, mVDTPCITSTgl.timeOffsetCorr, mVDTPCITSTgl.getTimeOffset(), getSourceName());
125 }
126 mMayRenormSrc &= ~(0x1U << Source::ITSTPCTgl); // unset MayRenorm
127 } else {
128 if (!mForceParamDrift && mVDTPCITSTgl.refVDrift != prevRefVDrift) { // we want to keep the same reference over the run, this should not happen!
129 LOGP(warn, "VDriftHelper: renorming updated TPC refVDrift={}/correction={} previous refVDrift {}, source: {}", mVDTPCITSTgl.refVDrift, mVDTPCITSTgl.corrFact, prevRefVDrift, getSourceName());
130 mVDTPCITSTgl.normalize(prevRefVDrift);
131 }
132 if (!mForceParamOffset && mVDTPCITSTgl.refTimeOffset != prevRefTOffs) { // we want to keep the same reference over the run, this should not happen!
133 LOGP(warn, "VDriftHelper: renorming updated TPC refTimeOffset={}/correction={} previous refTimeOffset {}, source: {}", mVDTPCITSTgl.refTimeOffset, mVDTPCITSTgl.timeOffsetCorr, prevRefTOffs, getSourceName());
134 mVDTPCITSTgl.normalizeOffset(prevRefTOffs);
135 }
136 }
137}
138
139//________________________________________________________
141{
142 if (mForceParamDrift && mForceParamOffset) { // fixed from the command line
143 return;
144 }
145 if (laser && !mForceParamDrift) {
146 pc.inputs().get<o2::tpc::LtrCalibData*>("laserCalib");
147 }
148 if (itstpcTgl) {
149 pc.inputs().get<o2::tpc::VDriftCorrFact*>("vdriftTgl");
150 }
153}
154
155//________________________________________________________
156void 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
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
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.
182}
183
184//________________________________________________________
185void VDriftHelper::updateVDrift(long currentTimeMS)
186{
187 if (mUpdated || mIsTPScalingPossible) { // there was a change
188 // prefer among laser and tgl VDrift the one with the latest update time
189 auto saveVD = mVD;
190
191 // apply TP scaling of mVD if possible
192 if (float tp = mPTHelper.getTP(currentTimeMS); tp > 0) {
193 // try to extract refTP if needed
195 if (mForceTPScaling) {
196 const auto& gaspar = o2::tpc::ParameterGas::Instance();
197 tp = (gaspar.Temperature > 0 && gaspar.Pressure > 0) ? ((gaspar.Temperature + 273.15) / gaspar.Pressure) : -1;
198 mIsTPScalingPossible = (tp > 0) && (vd.refTP > 0 || extractTPForVDrift(vd));
199 } else {
200 mIsTPScalingPossible = (vd.refTP > 0) || extractTPForVDrift(vd);
201 }
203 mUpdated = true;
204 vd.normalizeTP(tp); // keep refVDrift constant, fold the T/P scaling into the correction factor
205 if (vd.creationTime == saveVD.creationTime) {
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 }
211 } else {
212 LOGP(info, "VDriftHelper: Init new VDrift of {} with T/P {}", vd.getVDrift(), vd.refTP);
213 }
214 }
215 }
216
219
220 if (mForceParamDrift) {
221 mVD.refVDrift = saveVD.refVDrift;
222 mVD.corrFact = saveVD.corrFact;
223 mVD.corrFactErr = 0.f;
224 }
225 if (mForceParamOffset) {
226 mVD.refTimeOffset = saveVD.refTimeOffset;
227 mVD.timeOffsetCorr = 0.f;
228 }
230 auto loseCTime = loserVD.creationTime;
231 loserVD = mVD; // override alternative VD to avoid normalization problems later
232 loserVD.creationTime = loseCTime;
233 std::string rep = fmt::format("Prefer TPC Drift from {} with time {} to {} with time {}",
237 std::string impos = mForceParamDrift ? "VDrift" : "";
238 if (mForceParamOffset) {
239 impos += mForceParamDrift ? " and DriftTimeOffset" : "DriftTimeOffset";
240 }
241 rep += fmt::format(" but {} imposed from command line", impos);
242 }
243 if (mVD.creationTime != saveVD.creationTime) { // only log which source was (re-)selected when that choice actually changed
244 LOGP(info, "{}", rep);
245 }
246 }
247}
248
249//________________________________________________________
250void VDriftHelper::requestCCDBInputs(std::vector<InputSpec>& inputs, bool laser, bool itstpcTgl)
251{
252 if (laser) {
253 addInput(inputs, {"laserCalib", "TPC", "CalibLaserTracks", 0, Lifetime::Condition, ccdbParamSpec(CDBTypeMap.at(CDBType::CalLaserTracks))});
254 }
255 if (itstpcTgl) {
256 // VDrift calibration may change during the run (in opposite to Laser calibration, at least at the moment), so ask per-TF query
257 addInput(inputs, {"vdriftTgl", "TPC", "VDriftTgl", 0, Lifetime::Condition, ccdbParamSpec(CDBTypeMap.at(CDBType::CalVDriftTgl), {}, 1)});
258 }
259 // adding pressure and temperature inputs
261}
262
263//________________________________________________________
264void VDriftHelper::addInput(std::vector<InputSpec>& inputs, InputSpec&& isp)
265{
266 if (std::find(inputs.begin(), inputs.end(), isp) == inputs.end()) {
267 inputs.emplace_back(isp);
268 }
269}
270
271//________________________________________________________
273{
274 if (matcher == ConcreteDataMatcher("TPC", "VDriftTgl", 0)) {
276 return true;
277 }
278 if (matcher == ConcreteDataMatcher("TPC", "CalibLaserTracks", 0)) {
279 accountLaserCalibration(static_cast<LtrCalibData*>(obj));
280 return true;
281 }
282 return mPTHelper.accountCCDBInputs(matcher, obj);
283}
284
286{
287 const int64_t tsStart = vdrift.firstTime;
288 const int64_t tsEnd = vdrift.lastTime;
289
290 if (tsStart == tsEnd) {
291 static bool warned = false;
292 if (!warned) {
293 warned = true;
294 LOGP(warn, "VDriftHelper: Cannot extract T/P for VDrift with identical start/end time {}!", tsStart);
295 }
296 return false;
297 }
298
299 // make sanity check of the time range
300 const auto [minValidTime, maxValidTime] = mPTHelper.getMinMaxTime();
301 const int64_t minTimeAccepted = static_cast<int64_t>(minValidTime) - 20 * o2::ccdb::CcdbObjectInfo::MINUTE;
302 const int64_t maxTimeAccepted = static_cast<int64_t>(maxValidTime) + 20 * o2::ccdb::CcdbObjectInfo::MINUTE;
303
304 // check if the stored time stamp range is valid i.e. check if the range is in the vicinity of the current time
305 if ((minTimeAccepted > tsEnd) || (tsStart > maxTimeAccepted)) {
306 // check if creation time can be used
307 LOGP(warn, "VDriftHelper: Time range of VDrift object {} - {} is not valid for time range of T/P object {} - {}! Do not extract ref. T/P for VDrift!", tsStart, tsEnd, minValidTime, maxValidTime);
308 return false;
309 }
310
311 double meanTP = 0;
312 int countTP = 0;
313
314 for (int64_t ts = tsStart; ts < tsEnd; ts += tsStepMS) {
315 meanTP += mPTHelper.getTP(ts);
316 ++countTP;
317 }
318
319 if (countTP == 0) {
320 LOGP(error, "VDriftHelper: Could not get T/P for time range {} -> {}", tsStart, tsEnd);
321 return false;
322 }
323
324 meanTP /= countTP;
325
326 LOGP(info, "VDriftHelper: Setting mean T/P for VDrift to {} for time range {} -> {}", meanTP, tsStart, tsEnd);
327 vdrift.refTP = meanTP;
328 return true;
329}
Simple interface to the CDB manager.
uint64_t laser
calibration data from laser track calibration
Definition of the parameter class for the detector.
Definition of the parameter class for the detector electronics.
Definition of the parameter class for the detector gas.
Helper class to extract VDrift from different sources.
T * getForTimeStamp(std::string const &path, long timestamp, std::map< std::string, std::string > *headers=nullptr)
retrieve an object of type T from CCDB as stored under path and timestamp. Optional to get the header...
static constexpr long MINUTE
static EParamProvenance getProvenance(const std::string &key)
decltype(auto) get(R binding, int part=0) const
InputRecord & inputs()
The inputs associated with this processing context.
ServiceRegistryRef services()
The services registry associated with this processing context.
static void requestCCDBInputs(std::vector< o2::framework::InputSpec > &inputs)
void extractCCDBInputs(o2::framework::ProcessingContext &pc) const
trigger checking for CCDB objects
std::pair< ULong64_t, ULong64_t > getMinMaxTime() const
get minimum and maximum time stamps of the pressure and temperature data
bool accountCCDBInputs(const o2::framework::ConcreteDataMatcher &matcher, void *obj)
check for new CCDB objects
static void requestCCDBInputs(std::vector< o2::framework::InputSpec > &inputs, bool laser=true, bool itstpcTgl=true)
bool extractTPForVDrift(VDriftCorrFact &vdrift, int64_t tsStepMS=100 *1000)
void updateVDrift(long currentTimeMS)
Combine the previously accounted laser/ITS-TPC-Tgl inputs, applying T/P scaling if possible,...
VDriftCorrFact mVDLaser
void extractCCDBInputs(o2::framework::ProcessingContext &pc, bool laser=true, bool itstpcTgl=true)
static void addInput(std::vector< o2::framework::InputSpec > &inputs, o2::framework::InputSpec &&isp)
std::string_view getSourceName() const
bool accountCCDBInputs(const o2::framework::ConcreteDataMatcher &matcher, void *obj)
static constexpr std::array< std::string_view, NSources > SourceNames
VDriftCorrFact mVD
void accountDriftCorrectionITSTPCTgl(const VDriftCorrFact *calib)
VDriftCorrFact mVDTPCITSTgl
PressureTemperatureHelper mPTHelper
void accountLaserCalibration(const LtrCalibData *calib, long fallBackTimeStamp=2)
GLint ref
Definition glcorearb.h:291
Defining ITS Vertex explicitly as messageable.
Definition Cartesian.h:288
std::vector< ConfigParamSpec > ccdbParamSpec(std::string const &path, int runDependent, std::vector< CCDBMetadata > metadata={}, int qrate=0)
Global TPC definitions and constants.
Definition SimTraits.h:172
const std::unordered_map< CDBType, const std::string > CDBTypeMap
Storage name in CCDB for each calibration and parameter type.
Definition CDBTypes.h:98
@ CalVDriftTgl
ITS-TPC difTgl vdrift calibration.
@ CalLaserTracks
Laser track calibration data.
float getDriftVCorrection() const
float dvCorrectionA
drift velocity correction factor A-Side (inverse multiplicative)
float tp
temperature over pressure ratio
float dvCorrectionC
drift velocity correction factor C-Side (inverse multiplicative)
uint16_t nTracksC
number of tracks used for C-Side fit
long creationTime
time of creation
uint16_t nTracksA
number of tracks used for A-Side fit
float refTimeOffset
additive time offset reference (\mus)
float refVDrift
reference vdrift for which factor was extracted
float DriftV
Drift velocity [cm/us].
long creationTime
time of creation
void normalizeOffset(float newRefTimeOffset=-999.)
float corrFactErr
stat error of correction factor
void normalize(float newVRef=0.f)
float refTimeOffset
additive time offset reference (\mus)
long lastTime
last time stamp of processed TFs
float refVDrift
reference vdrift for which factor was extracted
float getTimeOffset() const
float timeOffsetCorr
additive time offset correction (\mus)
float corrFact
drift velocity correction factor (multiplicative)
float refTP
reference temperature / pressure for which refVDrift was extracted
long firstTime
first time stamp of processed TFs
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"