Skip to content

Commit d7ff7f5

Browse files
authored
[Common] [TOF] introduce generic resolution parametrization (#8616)
1 parent b1a5490 commit d7ff7f5

File tree

2 files changed

+155
-43
lines changed

2 files changed

+155
-43
lines changed

Common/Core/PID/PIDTOF.h

Lines changed: 64 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,19 @@
2828
#include "TMath.h"
2929
#include "TGraph.h"
3030
#include "TFile.h"
31+
#include "TF2.h"
3132

3233
// O2 includes
3334
#include "DataFormatsTOF/ParameterContainers.h"
3435
#include "Framework/Logger.h"
3536
#include "ReconstructionDataFormats/PID.h"
3637
#include "Framework/DataTypes.h"
38+
#include "CommonConstants/PhysicsConstants.h"
3739

3840
namespace o2::pid::tof
3941
{
4042

41-
// Utility values
43+
// Utility values (to remove!)
4244
static constexpr float kCSPEED = TMath::C() * 1.0e2f * 1.0e-12f; /// Speed of light in TOF units (cm/ps)
4345
static constexpr float kCSPEDDInv = 1.f / kCSPEED; /// Inverse of the Speed of light in TOF units (ps/cm)
4446
static constexpr float defaultReturnValue = -999.f; /// Default return value in case TOF measurement is not available
@@ -55,7 +57,7 @@ class Beta
5557
/// \param length Length in cm of the track
5658
/// \param tofSignal TOF signal in ps for the track
5759
/// \param collisionTime collision time in ps for the event of the track
58-
static float GetBeta(const float length, const float tofSignal, const float collisionTime) { return length / (tofSignal - collisionTime) * kCSPEDDInv; }
60+
static float GetBeta(const float length, const float tofSignal, const float collisionTime) { return length / (tofSignal - collisionTime) * o2::constants::physics::invLightSpeedCm2PS; }
5961

6062
/// Gets the beta for the track of interest
6163
/// \param track Track of interest
@@ -139,6 +141,11 @@ class TOFResoParamsV2 : public o2::tof::Parameters<13>
139141

140142
~TOFResoParamsV2() = default;
141143

144+
template <o2::track::PID::ID pid>
145+
float getResolution(const float, const float) const
146+
{
147+
return -1.f;
148+
}
142149
// Momentum shift for charge calibration
143150
void setMomentumChargeShiftParameters(std::unordered_map<std::string, float> const& pars)
144151
{
@@ -254,14 +261,12 @@ class TOFResoParamsV2 : public o2::tof::Parameters<13>
254261
class TOFResoParamsV3 : public o2::tof::Parameters<13>
255262
{
256263
public:
257-
TOFResoParamsV3() : Parameters(std::array<std::string, 13>{"TrkRes.Pi.P0", "TrkRes.Pi.P1", "TrkRes.Pi.P2", "TrkRes.Pi.P3", "time_resolution",
258-
"TrkRes.Ka.P0", "TrkRes.Ka.P1", "TrkRes.Ka.P2", "TrkRes.Ka.P3",
259-
"TrkRes.Pr.P0", "TrkRes.Pr.P1", "TrkRes.Pr.P2", "TrkRes.Pr.P3"},
264+
TOFResoParamsV3() : Parameters(std::array<std::string, 13>{"time_resolution", "time_resolution", "time_resolution", "time_resolution", "time_resolution",
265+
"time_resolution", "time_resolution", "time_resolution", "time_resolution",
266+
"time_resolution", "time_resolution", "time_resolution", "time_resolution"},
260267
"TOFResoParamsV3")
261268
{
262-
setParameters(std::array<float, 13>{0.008, 0.008, 0.002, 40.0, 60.0,
263-
0.008, 0.008, 0.002, 40.0,
264-
0.008, 0.008, 0.002, 40.0});
269+
setParameters(std::array<float, 13>{60.0});
265270
} // Default constructor with default parameters
266271

267272
~TOFResoParamsV3() = default;
@@ -313,7 +318,7 @@ class TOFResoParamsV3 : public o2::tof::Parameters<13>
313318
}
314319
}
315320

316-
// Time shift for post calibration
321+
// Time shift for post calibration to realign as a function of eta
317322
void setTimeShiftParameters(std::unordered_map<std::string, float> const& pars, bool positive)
318323
{
319324
std::string baseOpt = positive ? "TimeShift.Pos." : "TimeShift.Neg.";
@@ -367,13 +372,55 @@ class TOFResoParamsV3 : public o2::tof::Parameters<13>
367372
return gNegEtaTimeCorr->Eval(eta);
368373
}
369374

375+
void setResolutionParametrization(std::unordered_map<std::string, float> const& pars)
376+
{
377+
static constexpr std::array<const char*, 9> particleNames = {"El", "Mu", "Pi", "Ka", "Pr", "De", "Tr", "He", "Al"};
378+
for (int i = 0; i < 9; ++i) {
379+
const std::string baseOpt = Form("tofResTrack.%s_", particleNames[i]);
380+
// Check if a key begins with a string
381+
for (const auto& [key, value] : pars) {
382+
if (key.find(baseOpt) == 0) {
383+
// Remove from the key the baseOpt
384+
const std::string fun = key.substr(baseOpt.size());
385+
mResolution[i] = new TF2(baseOpt.c_str(), fun.c_str(), 0., 20, -1, 1.);
386+
LOG(info) << "Set the resolution function for " << particleNames[i] << " with formula " << mResolution[i]->GetFormula()->GetExpFormula();
387+
break;
388+
}
389+
}
390+
}
391+
// Print a summary
392+
for (int i = 0; i < 9; ++i) {
393+
if (!mResolution[i]) {
394+
LOG(info) << "Resolution function for " << particleNames[i] << " not provided, using default " << mDefaultResoParams[i];
395+
mResolution[i] = new TF2(Form("tofResTrack.%s_Default", particleNames[i]), mDefaultResoParams[i], 0., 20, -1, 1.);
396+
}
397+
LOG(info) << "Resolution function for " << particleNames[i] << " is " << mResolution[i]->GetName() << " with formula " << mResolution[i]->GetFormula()->GetExpFormula();
398+
}
399+
}
400+
401+
template <o2::track::PID::ID pid>
402+
float getResolution(const float p, const float eta) const
403+
{
404+
return mResolution[pid]->Eval(p, eta);
405+
}
406+
370407
private:
371408
// Charge calibration
372409
int mEtaN = 0; // Number of eta bins, 0 means no correction
373410
float mEtaStart = 0.f;
374411
float mEtaStop = 0.f;
375412
float mInvEtaWidth = 9999.f;
376413
std::vector<float> mContent;
414+
std::array<TF2*, 9> mResolution{nullptr};
415+
static constexpr std::array<const char*, 9> mDefaultResoParams{"14.3*TMath::Power((TMath::Max(x-0.319,0.1))*(1-0.4235*y*y),-0.8467)",
416+
"14.3*TMath::Power((TMath::Max(x-0.319,0.1))*(1-0.4235*y*y),-0.8467)",
417+
"14.3*TMath::Power((TMath::Max(x-0.319,0.1))*(1-0.4235*y*y),-0.8467)",
418+
"42.66*TMath::Power((TMath::Max(x-0.417,0.1))*(1-0.4235*y*y),-0.7145)",
419+
"99.46*TMath::Power((TMath::Max(x-0.447,0.1))*(1-0.4235*y*y),-0.8094)",
420+
"216*TMath::Power((TMath::Max(x-0.647,0.1))*(1-0.4235*y*y),-0.76)",
421+
"315*TMath::Power((TMath::Max(x-0.811,0.1))*(1-0.4235*y*y),-0.783)",
422+
"157*TMath::Power((TMath::Max(x-0.556,0.1))*(1-0.4235*y*y),-0.783)",
423+
"216*TMath::Power((TMath::Max(x-0.647,0.1))*(1-0.4235*y*y),-0.76)"};
377424

378425
// Time shift for post calibration
379426
TGraph* gPosEtaTimeCorr = nullptr; /// Time shift correction for positive tracks
@@ -391,7 +438,7 @@ class ExpTimes
391438
static constexpr float mMassZSqared = mMassZ * mMassZ; /// (M/z)^2
392439

393440
/// Computes the expected time of a track, given it TOF expected momentum
394-
static float ComputeExpectedTime(const float tofExpMom, const float length) { return length * sqrt((mMassZSqared) + (tofExpMom * tofExpMom)) / (kCSPEED * tofExpMom); }
441+
static float ComputeExpectedTime(const float tofExpMom, const float length) { return length * sqrt((mMassZSqared) + (tofExpMom * tofExpMom)) / (o2::constants::physics::LightSpeedCm2PS * tofExpMom); }
395442

396443
/// Gets the expected signal of the track of interest under the PID assumption
397444
/// \param track Track of interest
@@ -401,7 +448,7 @@ class ExpTimes
401448
return defaultReturnValue;
402449
}
403450
if (track.trackType() == o2::aod::track::Run2Track) {
404-
return ComputeExpectedTime(track.tofExpMom() * kCSPEDDInv, track.length());
451+
return ComputeExpectedTime(track.tofExpMom() * o2::constants::physics::invLightSpeedCm2PS, track.length());
405452
}
406453
return ComputeExpectedTime(track.tofExpMom(), track.length());
407454
}
@@ -416,7 +463,7 @@ class ExpTimes
416463
return defaultReturnValue;
417464
}
418465
if (track.trackType() == o2::aod::track::Run2Track) {
419-
return ComputeExpectedTime(track.tofExpMom() * kCSPEDDInv / (1.f + track.sign() * parameters.getMomentumChargeShift(track.eta())), track.length());
466+
return ComputeExpectedTime(track.tofExpMom() * o2::constants::physics::invLightSpeedCm2PS / (1.f + track.sign() * parameters.getMomentumChargeShift(track.eta())), track.length());
420467
}
421468
LOG(debug) << "TOF exp. mom. " << track.tofExpMom() << " shifted = " << track.tofExpMom() / (1.f + track.sign() * parameters.getMomentumChargeShift(track.eta()));
422469
return ComputeExpectedTime(track.tofExpMom() / (1.f + track.sign() * parameters.getMomentumChargeShift(track.eta())), track.length()) + parameters.getTimeShift(track.eta(), track.sign());
@@ -432,9 +479,14 @@ class ExpTimes
432479
static float GetExpectedSigma(const ParamType& parameters, const TrackType& track, const float tofSignal, const float collisionTimeRes)
433480
{
434481
const float& mom = track.p();
482+
const float& eta = track.eta();
435483
if (mom <= 0) {
436484
return -999.f;
437485
}
486+
const float reso = parameters.template getResolution<id>(mom, eta);
487+
if (reso > 0) {
488+
return std::sqrt(reso * reso + parameters[4] * parameters[4] + collisionTimeRes * collisionTimeRes);
489+
}
438490
if constexpr (id <= o2::track::PID::Pion) {
439491
LOG(debug) << "Using parameters for the pion hypothesis and ID " << id;
440492
const float dpp = parameters[0] + parameters[1] * mom + parameters[2] * mMassZ / mom; // mean relative pt resolution;

0 commit comments

Comments
 (0)