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
3840namespace o2 ::pid::tof
3941{
4042
41- // Utility values
43+ // Utility values (to remove!)
4244static constexpr float kCSPEED = TMath::C() * 1 .0e2f * 1 .0e-12f ; // / Speed of light in TOF units (cm/ps)
4345static constexpr float kCSPEDDInv = 1 .f / kCSPEED ; // / Inverse of the Speed of light in TOF units (ps/cm)
4446static 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>
254261class 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