Skip to content

Commit dd0b368

Browse files
joonsukbaeclaude
andcommitted
[Common] Fix stale Q/Pt values in TrackTuner graph-based smearing
When qOverPtMC and qOverPtData are configured as negative sentinels (requesting graph-based evaluation), the original code overwrites the member variables on the first track call. All subsequent tracks then skip graph evaluation and reuse stale values from the first track's pT, applying incorrect smearing. Fix: use local variables (currentQOverPtMC, currentQOverPtData) so each track evaluates the graphs at its own pT. The member variable sentinels remain negative, ensuring graph evaluation on every call. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 33057d7 commit dd0b368

1 file changed

Lines changed: 38 additions & 30 deletions

File tree

Common/Tools/TrackTuner.h

Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -735,19 +735,27 @@ struct TrackTuner : o2::framework::ConfigurableGroup {
735735
dcaZResMC = evalGraph(ptMC, grDcaZResVsPtPionMC[phiBin].get());
736736
dcaZResData = evalGraph(ptMC, grDcaZResVsPtPionData[phiBin].get());
737737

738-
// For Q/Pt corrections, files on CCDB will be used if both qOverPtMC and qOverPtData are null
738+
// Use local copies so that graph-based Q/Pt correction is evaluated
739+
// per-track at the correct pT. Writing directly to qOverPtMC/qOverPtData
740+
// would overwrite the negative sentinel on the first call, causing all
741+
// subsequent tracks to skip graph evaluation and reuse stale values.
742+
double currentQOverPtMC = qOverPtMC;
743+
double currentQOverPtData = qOverPtData;
739744
if (updateCurvature || updateCurvatureIU) {
740-
if ((qOverPtMC < 0) || (qOverPtData < 0)) {
741-
if (debugInfo) {
742-
LOG(info) << "### q/pt smearing: qOverPtMC=" << qOverPtMC << ", qOverPtData=" << qOverPtData << ". One of them is negative. Retrieving then values from graphs from input .root file";
743-
}
745+
if ((currentQOverPtMC < 0) || (currentQOverPtData < 0)) {
744746
/// check that input graphs for q/pt smearing are correctly retrieved
745747
if (!grOneOverPtPionData.get() || !grOneOverPtPionMC.get()) {
746748
LOG(fatal) << "### q/pt smearing: input graphs not correctly retrieved. Aborting.";
747749
}
748-
qOverPtMC = std::max(0.0, evalGraph(ptMC, grOneOverPtPionMC.get()));
749-
qOverPtData = std::max(0.0, evalGraph(ptMC, grOneOverPtPionData.get()));
750-
} // qOverPtMC, qOverPtData block ends here
750+
currentQOverPtMC = std::max(0.0, evalGraph(ptMC, grOneOverPtPionMC.get()));
751+
currentQOverPtData = std::max(0.0, evalGraph(ptMC, grOneOverPtPionData.get()));
752+
if (debugInfo) {
753+
LOG(info) << "### q/pt graph-based smearing: pT=" << ptMC
754+
<< " sigma(1/pT)_MC=" << currentQOverPtMC
755+
<< " sigma(1/pT)_Data=" << currentQOverPtData
756+
<< " ratio(Data/MC)=" << (currentQOverPtMC > 0. ? currentQOverPtData / currentQOverPtMC : -1.);
757+
}
758+
} // currentQOverPtMC, currentQOverPtData block ends here
751759
} // updateCurvature, updateCurvatureIU block ends here
752760

753761
if (updateTrackDCAs) {
@@ -816,44 +824,44 @@ struct TrackTuner : o2::framework::ConfigurableGroup {
816824
// double dpt1o =pt1o-pt1mc;
817825
deltaQpt = trackParQPtMCRec - trackParQPtMC;
818826
// double dpt1n =dpt1o *(spt1o >0. ? (spt1n /spt1o ) : 1.);
819-
deltaQptTuned = deltaQpt * (qOverPtMC > 0. ? (qOverPtData / qOverPtMC) : 1.);
827+
deltaQptTuned = deltaQpt * (currentQOverPtMC > 0. ? (currentQOverPtData / currentQOverPtMC) : 1.);
820828
// double pt1n = pt1mc+dpt1n;
821829
trackParQPtTuned = trackParQPtMC + deltaQptTuned;
822830
trackParCov.setQ2Pt(trackParQPtTuned);
823831

824832
// updating track cov matrix elements for 1/Pt at innermost update point
825833
// if(sd0rpo>0. && spt1o>0.)covar[10]*=(sd0rpn/sd0rpo)*(spt1n/spt1o);//ypt
826834
sigma1PtY = trackParCov.getSigma1PtY();
827-
if (dcaXYResMC > 0. && qOverPtMC > 0.) {
828-
sigma1PtY *= ((dcaXYResData / dcaXYResMC) * (qOverPtData / qOverPtMC));
835+
if (dcaXYResMC > 0. && currentQOverPtMC > 0.) {
836+
sigma1PtY *= ((dcaXYResData / dcaXYResMC) * (currentQOverPtData / currentQOverPtMC));
829837
trackParCov.setCov(sigma1PtY, 10);
830838
}
831839

832840
// if(sd0zo>0. && spt1o>0.) covar[11]*=(sd0zn/sd0zo)*(spt1n/spt1o);//zpt
833841
sigma1PtZ = trackParCov.getSigma1PtZ();
834-
if (dcaZResMC > 0. && qOverPtMC > 0.) {
835-
sigma1PtZ *= ((dcaZResData / dcaZResMC) * (qOverPtData / qOverPtMC));
842+
if (dcaZResMC > 0. && currentQOverPtMC > 0.) {
843+
sigma1PtZ *= ((dcaZResData / dcaZResMC) * (currentQOverPtData / currentQOverPtMC));
836844
trackParCov.setCov(sigma1PtZ, 11);
837845
}
838846

839847
// if(spt1o>0.) covar[12]*=(spt1n/spt1o);//sinPhipt
840848
sigma1PtSnp = trackParCov.getSigma1PtSnp();
841-
if (qOverPtMC > 0.) {
842-
sigma1PtSnp *= (qOverPtData / qOverPtMC);
849+
if (currentQOverPtMC > 0.) {
850+
sigma1PtSnp *= (currentQOverPtData / currentQOverPtMC);
843851
trackParCov.setCov(sigma1PtSnp, 12);
844852
}
845853

846854
// if(spt1o>0.) covar[13]*=(spt1n/spt1o);//tanTpt
847855
sigma1PtTgl = trackParCov.getSigma1PtTgl();
848-
if (qOverPtMC > 0.) {
849-
sigma1PtTgl *= (qOverPtData / qOverPtMC);
856+
if (currentQOverPtMC > 0.) {
857+
sigma1PtTgl *= (currentQOverPtData / currentQOverPtMC);
850858
trackParCov.setCov(sigma1PtTgl, 13);
851859
}
852860

853861
// if(spt1o>0.) covar[14]*=(spt1n/spt1o)*(spt1n/spt1o);//ptpt
854862
sigma1Pt2 = trackParCov.getSigma1Pt2();
855-
if (qOverPtMC > 0.) {
856-
sigma1Pt2 *= (qOverPtData / qOverPtMC) * (qOverPtData / qOverPtMC);
863+
if (currentQOverPtMC > 0.) {
864+
sigma1Pt2 *= (currentQOverPtData / currentQOverPtMC) * (currentQOverPtData / currentQOverPtMC);
857865
trackParCov.setCov(sigma1Pt2, 14);
858866
}
859867
} // updateCurvatureIU block ends here
@@ -949,7 +957,7 @@ struct TrackTuner : o2::framework::ConfigurableGroup {
949957
}
950958
deltaQpt = trackParQPtMCRec - trackParQPtMC;
951959
// double dpt1n =dpt1o *(spt1o >0. ? (spt1n /spt1o ) : 1.);
952-
deltaQptTuned = deltaQpt * (qOverPtMC > 0. ? (qOverPtData / qOverPtMC) : 1.);
960+
deltaQptTuned = deltaQpt * (currentQOverPtMC > 0. ? (currentQOverPtData / currentQOverPtMC) : 1.);
953961
// double pt1n = pt1mc+dpt1n;
954962
trackParQPtTuned = trackParQPtMC + deltaQptTuned;
955963
trackParCov.setQ2Pt(trackParQPtTuned);
@@ -1010,36 +1018,36 @@ struct TrackTuner : o2::framework::ConfigurableGroup {
10101018
if ((updateCurvature) && (!updateCurvatureIU)) {
10111019
// if(sd0rpo>0. && spt1o>0.)covar[10]*=(sd0rpn/sd0rpo)*(spt1n/spt1o);//ypt
10121020
sigma1PtY = trackParCov.getSigma1PtY();
1013-
if (dcaXYResMC > 0. && qOverPtMC > 0.) {
1014-
sigma1PtY *= ((dcaXYResData / dcaXYResMC) * (qOverPtData / qOverPtMC));
1021+
if (dcaXYResMC > 0. && currentQOverPtMC > 0.) {
1022+
sigma1PtY *= ((dcaXYResData / dcaXYResMC) * (currentQOverPtData / currentQOverPtMC));
10151023
trackParCov.setCov(sigma1PtY, 10);
10161024
}
10171025

10181026
// if(sd0zo>0. && spt1o>0.) covar[11]*=(sd0zn/sd0zo)*(spt1n/spt1o);//zpt
10191027
sigma1PtZ = trackParCov.getSigma1PtZ();
1020-
if (dcaZResMC > 0. && qOverPtMC > 0.) {
1021-
sigma1PtZ *= ((dcaZResData / dcaZResMC) * (qOverPtData / qOverPtMC));
1028+
if (dcaZResMC > 0. && currentQOverPtMC > 0.) {
1029+
sigma1PtZ *= ((dcaZResData / dcaZResMC) * (currentQOverPtData / currentQOverPtMC));
10221030
trackParCov.setCov(sigma1PtZ, 11);
10231031
}
10241032

10251033
// if(spt1o>0.) covar[12]*=(spt1n/spt1o);//sinPhipt
10261034
sigma1PtSnp = trackParCov.getSigma1PtSnp();
1027-
if (qOverPtMC > 0.) {
1028-
sigma1PtSnp *= (qOverPtData / qOverPtMC);
1035+
if (currentQOverPtMC > 0.) {
1036+
sigma1PtSnp *= (currentQOverPtData / currentQOverPtMC);
10291037
trackParCov.setCov(sigma1PtSnp, 12);
10301038
}
10311039

10321040
// if(spt1o>0.) covar[13]*=(spt1n/spt1o);//tanTpt
10331041
sigma1PtTgl = trackParCov.getSigma1PtTgl();
1034-
if (qOverPtMC > 0.) {
1035-
sigma1PtTgl *= (qOverPtData / qOverPtMC);
1042+
if (currentQOverPtMC > 0.) {
1043+
sigma1PtTgl *= (currentQOverPtData / currentQOverPtMC);
10361044
trackParCov.setCov(sigma1PtTgl, 13);
10371045
}
10381046

10391047
// if(spt1o>0.) covar[14]*=(spt1n/spt1o)*(spt1n/spt1o);//ptpt
10401048
sigma1Pt2 = trackParCov.getSigma1Pt2();
1041-
if (qOverPtMC > 0.) {
1042-
sigma1Pt2 *= (qOverPtData / qOverPtMC) * (qOverPtData / qOverPtMC);
1049+
if (currentQOverPtMC > 0.) {
1050+
sigma1Pt2 *= (currentQOverPtData / currentQOverPtMC) * (currentQOverPtData / currentQOverPtMC);
10431051
trackParCov.setCov(sigma1Pt2, 14);
10441052
}
10451053
} // ---> track cov matrix elements for 1/Pt ends here

0 commit comments

Comments
 (0)