@@ -250,6 +250,136 @@ class TOFResoParamsV2 : public o2::tof::Parameters<13>
250250 TGraph* gNegEtaTimeCorr = nullptr ; // / Time shift correction for negative tracks
251251};
252252
253+ // / \brief Next implementation class to store TOF response parameters for exp. times
254+ class TOFResoParamsV3 : public o2 ::tof::Parameters<13 >
255+ {
256+ 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" },
260+ " TOFResoParamsV3" )
261+ {
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 });
265+ } // Default constructor with default parameters
266+
267+ ~TOFResoParamsV3 () = default ;
268+
269+ // Momentum shift for charge calibration
270+ void setMomentumChargeShiftParameters (std::unordered_map<std::string, float > const & pars)
271+ {
272+ if (pars.count (" Shift.etaN" ) == 0 ) { // If the map does not contain the number of eta bins, we assume that no correction has to be applied
273+ mEtaN = 0 ;
274+ return ;
275+ }
276+ mEtaN = static_cast <int >(pars.at (" Shift.etaN" ));
277+ if (mEtaN <= 0 ) {
278+ LOG (fatal) << " TOFResoParamsV3 shift: etaN must be positive" ;
279+ }
280+ mEtaStart = pars.at (" Shift.etaStart" );
281+ mEtaStop = pars.at (" Shift.etaStop" );
282+ if (mEtaStart >= mEtaStop ) {
283+ LOG (fatal) << " TOFResoParamsV3 shift: etaStart must be smaller than etaStop" ;
284+ }
285+ mInvEtaWidth = 1 .f / ((mEtaStop - mEtaStart ) / mEtaN );
286+ mContent .clear ();
287+ mContent .resize (mEtaN );
288+ for (int i = 0 ; i < mEtaN ; ++i) {
289+ mContent [i] = pars.at (Form (" Shift.etaC%i" , i));
290+ }
291+ }
292+
293+ float getMomentumChargeShift (float eta) const
294+ {
295+ if (mEtaN == 0 ) { // No correction
296+ // LOG(info) << "TOFResoParamsV3 shift: no correction mEtaN is " << mEtaN;
297+ return 0 .f ;
298+ }
299+ const int & etaIndex = (eta <= mEtaStart ) ? 0 : (eta >= mEtaStop ? (mEtaN - 1 ) : (eta - mEtaStart ) * mInvEtaWidth );
300+ // LOG(info) << "TOFResoParamsV3 shift: correction for eta " << eta << " is for index " << etaIndex << " = " << shift;
301+ return mContent .at (etaIndex);
302+ }
303+
304+ void printMomentumChargeShiftParameters () const
305+ {
306+ LOG (info) << " TOF momentum shift parameters" ;
307+ LOG (info) << " etaN: " << mEtaN ;
308+ LOG (info) << " etaStart: " << mEtaStart ;
309+ LOG (info) << " etaStop: " << mEtaStop ;
310+ LOG (info) << " content size " << mContent .size ();
311+ for (int i = 0 ; i < mEtaN ; ++i) {
312+ LOG (info) << " etaC" << i << " : " << mContent [i];
313+ }
314+ }
315+
316+ // Time shift for post calibration
317+ void setTimeShiftParameters (std::unordered_map<std::string, float > const & pars, bool positive)
318+ {
319+ std::string baseOpt = positive ? " TimeShift.Pos." : " TimeShift.Neg." ;
320+
321+ if (pars.count (baseOpt + " GetN" ) == 0 ) { // If the map does not contain the number of eta bins, we assume that no correction has to be applied
322+ return ;
323+ }
324+ const int nPoints = static_cast <int >(pars.at (baseOpt + " GetN" ));
325+ if (nPoints <= 0 ) {
326+ LOG (fatal) << " TOFResoParamsV3 shift: time must be positive" ;
327+ }
328+ TGraph graph;
329+ for (int i = 0 ; i < nPoints; ++i) {
330+ graph.AddPoint (pars.at (Form (" TimeShift.eta%i" , i)), pars.at (Form (" TimeShift.cor%i" , i)));
331+ }
332+ setTimeShiftParameters (&graph, positive);
333+ }
334+ void setTimeShiftParameters (std::string const & filename, std::string const & objname, bool positive)
335+ {
336+ TFile f (filename.c_str (), " READ" );
337+ if (f.IsOpen ()) {
338+ if (positive) {
339+ f.GetObject (objname.c_str (), gPosEtaTimeCorr );
340+ } else {
341+ f.GetObject (objname.c_str (), gNegEtaTimeCorr );
342+ }
343+ f.Close ();
344+ }
345+ LOG (info) << " Set the Time Shift parameters from file " << filename << " and object " << objname << " for " << (positive ? " positive" : " negative" );
346+ }
347+ void setTimeShiftParameters (TGraph* g, bool positive)
348+ {
349+ if (positive) {
350+ gPosEtaTimeCorr = g;
351+ } else {
352+ gNegEtaTimeCorr = g;
353+ }
354+ LOG (info) << " Set the Time Shift parameters from object " << g->GetName () << " " << g->GetTitle () << " for " << (positive ? " positive" : " negative" );
355+ }
356+ float getTimeShift (float eta, int16_t sign) const
357+ {
358+ if (sign > 0 ) {
359+ if (!gPosEtaTimeCorr ) {
360+ return 0 .f ;
361+ }
362+ return gPosEtaTimeCorr ->Eval (eta);
363+ }
364+ if (!gNegEtaTimeCorr ) {
365+ return 0 .f ;
366+ }
367+ return gNegEtaTimeCorr ->Eval (eta);
368+ }
369+
370+ private:
371+ // Charge calibration
372+ int mEtaN = 0 ; // Number of eta bins, 0 means no correction
373+ float mEtaStart = 0 .f;
374+ float mEtaStop = 0 .f;
375+ float mInvEtaWidth = 9999 .f;
376+ std::vector<float > mContent ;
377+
378+ // Time shift for post calibration
379+ TGraph* gPosEtaTimeCorr = nullptr ; // / Time shift correction for positive tracks
380+ TGraph* gNegEtaTimeCorr = nullptr ; // / Time shift correction for negative tracks
381+ };
382+
253383// / \brief Class to handle the the TOF detector response for the expected time
254384template <typename TrackType, o2::track::PID ::ID id>
255385class ExpTimes
@@ -291,6 +421,21 @@ class ExpTimes
291421 return ComputeExpectedTime (track.tofExpMom () / (1 .f + track.sign () * parameters.getShift (track.eta ())), track.length ()) + parameters.getTimeShift (track.eta (), track.sign ());
292422 }
293423
424+ // / Gets the expected signal of the track of interest under the PID assumption corrected for shifts in expected momentum
425+ // / \param parameters Parameters to correct for the momentum shift
426+ // / \param track Track of interest
427+ static float GetCorrectedExpectedSignal (const TOFResoParamsV3& parameters, const TrackType& track)
428+ {
429+ if (!track.hasTOF ()) {
430+ return defaultReturnValue;
431+ }
432+ if (track.trackType () == o2::aod::track::Run2Track) {
433+ return ComputeExpectedTime (track.tofExpMom () * kCSPEDDInv / (1 .f + track.sign () * parameters.getMomentumChargeShift (track.eta ())), track.length ());
434+ }
435+ LOG (debug) << " TOF exp. mom. " << track.tofExpMom () << " shifted = " << track.tofExpMom () / (1 .f + track.sign () * parameters.getMomentumChargeShift (track.eta ()));
436+ return ComputeExpectedTime (track.tofExpMom () / (1 .f + track.sign () * parameters.getMomentumChargeShift (track.eta ())), track.length ()) + parameters.getTimeShift (track.eta (), track.sign ());
437+ }
438+
294439 // / Gets the expected resolution of the t-texp-t0
295440 // / Given a TOF signal and collision time resolutions
296441 // / \param parameters Detector response parameters
0 commit comments