2424#include < utility>
2525#include < vector>
2626#include < algorithm>
27+ #include < numbers>
28+ #include < fmt/core.h>
2729
2830#include " CCDB/BasicCCDBManager.h"
2931#include " CCDB/CcdbApi.h"
@@ -77,7 +79,7 @@ struct TrackTuner : o2::framework::ConfigurableGroup {
7779 o2::framework::Configurable<bool > cfgUsePvRefitCorrections{" usePvRefitCorrections" , false , " Flag to establish whether to use corrections obtained with or w/o PV refit" };
7880 o2::framework::Configurable<float > cfgQOverPtMC{" qOverPtMC" , -1 ., " Scaling factor on q/pt of MC" };
7981 o2::framework::Configurable<float > cfgQOverPtData{" qOverPtData" , -1 ., " Scaling factor on q/pt of data" };
80-
82+ o2::framework::Configurable< int > cfgNPhiBins{ " nPhiBins " , 0 , " Number of phi bins " };
8183 // /////////////////////////////
8284 // / parameters to be configured
8385 bool debugInfo = false ;
@@ -97,30 +99,31 @@ struct TrackTuner : o2::framework::ConfigurableGroup {
9799 // /////////////////////////////
98100 bool isConfigFromString = false ;
99101 bool isConfigFromConfigurables = false ;
102+ int nPhiBins = 1 ;
100103
101104 o2::ccdb::CcdbApi ccdbApi;
102105 std::map<std::string, std::string> metadata;
103106
104- std::unique_ptr<TGraphErrors> grDcaXYResVsPtPionMC;
105- std::unique_ptr<TGraphErrors> grDcaXYResVsPtPionData;
107+ std::vector<std:: unique_ptr<TGraphErrors> > grDcaXYResVsPtPionMC;
108+ std::vector<std:: unique_ptr<TGraphErrors> > grDcaXYResVsPtPionData;
106109
107- std::unique_ptr<TGraphErrors> grDcaZResVsPtPionMC;
108- std::unique_ptr<TGraphErrors> grDcaZResVsPtPionData;
110+ std::vector<std:: unique_ptr<TGraphErrors> > grDcaZResVsPtPionMC;
111+ std::vector<std:: unique_ptr<TGraphErrors> > grDcaZResVsPtPionData;
109112
110- std::unique_ptr<TGraphErrors> grDcaXYMeanVsPtPionMC;
111- std::unique_ptr<TGraphErrors> grDcaXYMeanVsPtPionData;
113+ std::vector<std:: unique_ptr<TGraphErrors> > grDcaXYMeanVsPtPionMC;
114+ std::vector<std:: unique_ptr<TGraphErrors> > grDcaXYMeanVsPtPionData;
112115
113- std::unique_ptr<TGraphErrors> grDcaZMeanVsPtPionMC;
114- std::unique_ptr<TGraphErrors> grDcaZMeanVsPtPionData;
116+ std::vector<std:: unique_ptr<TGraphErrors> > grDcaZMeanVsPtPionMC;
117+ std::vector<std:: unique_ptr<TGraphErrors> > grDcaZMeanVsPtPionData;
115118
116119 std::unique_ptr<TGraphErrors> grOneOverPtPionMC; // MC
117120 std::unique_ptr<TGraphErrors> grOneOverPtPionData; // Data
118121
119- std::unique_ptr<TGraphErrors> grDcaXYPullVsPtPionMC;
120- std::unique_ptr<TGraphErrors> grDcaXYPullVsPtPionData;
122+ std::vector<std:: unique_ptr<TGraphErrors> > grDcaXYPullVsPtPionMC;
123+ std::vector<std:: unique_ptr<TGraphErrors> > grDcaXYPullVsPtPionData;
121124
122- std::unique_ptr<TGraphErrors> grDcaZPullVsPtPionMC;
123- std::unique_ptr<TGraphErrors> grDcaZPullVsPtPionData;
125+ std::vector<std:: unique_ptr<TGraphErrors> > grDcaZPullVsPtPionMC;
126+ std::vector<std:: unique_ptr<TGraphErrors> > grDcaZPullVsPtPionData;
124127
125128 // / @brief Function doing a few sanity-checks on the configurations
126129 void checkConfig ()
@@ -191,6 +194,7 @@ struct TrackTuner : o2::framework::ConfigurableGroup {
191194 UsePvRefitCorrections,
192195 QOverPtMC,
193196 QOverPtData,
197+ NPhiBins,
194198 NPars };
195199 std::map<uint8_t , std::string> mapParNames = {
196200 std::make_pair (DebugInfo, " debugInfo" ),
@@ -206,7 +210,8 @@ struct TrackTuner : o2::framework::ConfigurableGroup {
206210 std::make_pair (NameFileQoverPt, " nameFileQoverPt" ),
207211 std::make_pair (UsePvRefitCorrections, " usePvRefitCorrections" ),
208212 std::make_pair (QOverPtMC, " qOverPtMC" ),
209- std::make_pair (QOverPtData, " qOverPtData" )};
213+ std::make_pair (QOverPtData, " qOverPtData" ),
214+ std::make_pair (NPhiBins, " nPhiBins" )};
210215 // /////////////////////////////////////////////////////////////////////////////////
211216 LOG (info) << " [TrackTuner]" ;
212217 LOG (info) << " [TrackTuner] >>> Parameters before the custom settings" ;
@@ -224,6 +229,7 @@ struct TrackTuner : o2::framework::ConfigurableGroup {
224229 LOG (info) << " [TrackTuner] usePvRefitCorrections = " << usePvRefitCorrections;
225230 LOG (info) << " [TrackTuner] qOverPtMC = " << qOverPtMC;
226231 LOG (info) << " [TrackTuner] qOverPtData = " << qOverPtData;
232+ LOG (info) << " [TrackTuner] nPhiBins = " << nPhiBins;
227233
228234 // ##############################################################################################
229235 // ######## split the original string, separating substrings delimited by "|" symbol ########
@@ -245,7 +251,7 @@ struct TrackTuner : o2::framework::ConfigurableGroup {
245251
246252 // / check if the number of input parameters is correct
247253 if (static_cast <uint8_t >(slices.size ()) != NPars) {
248- LOG (fatal) << " [TrackTuner] " << slices.size () << " parameters provided, while " << NPars << " are expected. Fix it!" ;
254+ LOG (fatal) << " [TrackTuner] " << slices.size () << " parameters provided, while " << static_cast < int >( NPars) << " are expected. Fix it!" ;
249255 }
250256
251257 // ###################################################################################################################
@@ -337,7 +343,12 @@ struct TrackTuner : o2::framework::ConfigurableGroup {
337343 qOverPtData = std::stof (getValueString (QOverPtData));
338344 outputString += " , qOverPtData=" + std::to_string (qOverPtData);
339345 LOG (info) << " [TrackTuner] qOverPtData = " << qOverPtData;
340-
346+ // Configure nPhiBins
347+ nPhiBins = std::stoi (getValueString (NPhiBins));
348+ outputString += " , nPhiBins=" + std::to_string (nPhiBins);
349+ if (nPhiBins < 0 )
350+ LOG (fatal) << " [TrackTuner] negative nPhiBins!" << nPhiBins;
351+ LOG (info) << " [TrackTuner] nPhiBins = " << nPhiBins;
341352 // / declare that the configuration is done via an input string
342353 isConfigFromString = true ;
343354
@@ -417,6 +428,12 @@ struct TrackTuner : o2::framework::ConfigurableGroup {
417428 qOverPtData = cfgQOverPtData;
418429 outputString += " , qOverPtData=" + std::to_string (qOverPtData);
419430 LOG (info) << " [TrackTuner] qOverPtData = " << qOverPtData;
431+ // Configure nPhiBins
432+ nPhiBins = cfgNPhiBins;
433+ outputString += " , nPhiBins=" + std::to_string (nPhiBins);
434+ if (nPhiBins < 0 )
435+ LOG (fatal) << " [TrackTuner] negative nPhiBins!" << nPhiBins;
436+ LOG (info) << " [TrackTuner] nPhiBins = " << nPhiBins;
420437
421438 // / declare that the configuration is done via the Configurables
422439 isConfigFromConfigurables = true ;
@@ -476,38 +493,72 @@ struct TrackTuner : o2::framework::ConfigurableGroup {
476493 LOG (fatal) << " TDirectory " << td << " not found in input file" << inputFile->GetName () << " . Fix it!" ;
477494 }
478495
479- std::string grDcaXYResNameMC = " resCurrentDcaXY" ;
480- std::string grDcaXYMeanNameMC = " meanCurrentDcaXY" ;
481- std::string grDcaXYPullNameMC = " pullsCurrentDcaXY" ;
482- std::string grDcaXYResNameData = " resUpgrDcaXY" ;
483- std::string grDcaXYMeanNameData = " meanUpgrDcaXY" ;
484- std::string grDcaXYPullNameData = " pullsUpgrDcaXY" ;
485-
486- grDcaXYResVsPtPionMC.reset (dynamic_cast <TGraphErrors*>(td->Get (grDcaXYResNameMC.c_str ())));
487- grDcaXYResVsPtPionData.reset (dynamic_cast <TGraphErrors*>(td->Get (grDcaXYResNameData.c_str ())));
488- grDcaXYMeanVsPtPionMC.reset (dynamic_cast <TGraphErrors*>(td->Get (grDcaXYMeanNameMC.c_str ())));
489- grDcaXYMeanVsPtPionData.reset (dynamic_cast <TGraphErrors*>(td->Get (grDcaXYMeanNameData.c_str ())));
490- grDcaXYPullVsPtPionMC.reset (dynamic_cast <TGraphErrors*>(td->Get (grDcaXYPullNameMC.c_str ())));
491- grDcaXYPullVsPtPionData.reset (dynamic_cast <TGraphErrors*>(td->Get (grDcaXYPullNameData.c_str ())));
492- if (!grDcaXYResVsPtPionMC.get () || !grDcaXYResVsPtPionData.get () || !grDcaXYMeanVsPtPionMC.get () || !grDcaXYMeanVsPtPionData.get () || !grDcaXYPullVsPtPionMC.get () || !grDcaXYPullVsPtPionData.get ()) {
493- LOG (fatal) << " Something wrong with the names of the correction graphs for dcaXY. Fix it!" ;
496+ int inputNphiBins = nPhiBins;
497+ if (inputNphiBins == 0 )
498+ nPhiBins = 1 ; // old phi_independent settings
499+
500+ // reserve memory and initialize vector for needed number of graphs
501+ grDcaXYResVsPtPionMC.resize (nPhiBins);
502+ grDcaXYResVsPtPionData.resize (nPhiBins);
503+
504+ grDcaZResVsPtPionMC.resize (nPhiBins);
505+ grDcaZResVsPtPionData.resize (nPhiBins);
506+
507+ grDcaXYMeanVsPtPionMC.resize (nPhiBins);
508+ grDcaXYMeanVsPtPionData.resize (nPhiBins);
509+
510+ grDcaZMeanVsPtPionMC.resize (nPhiBins);
511+ grDcaZMeanVsPtPionData.resize (nPhiBins);
512+
513+ grDcaXYPullVsPtPionMC.resize (nPhiBins);
514+ grDcaXYPullVsPtPionData.resize (nPhiBins);
515+
516+ grDcaZPullVsPtPionMC.resize (nPhiBins);
517+ grDcaZPullVsPtPionData.resize (nPhiBins);
518+
519+ // / Lambda expression to get the TGraphErrors from file
520+ auto loadGraph = [&](int phiBin, const std::string& strBaseName) -> TGraphErrors* {
521+ std::string strGraphName = inputNphiBins != 0 ? fmt::format (" {}_{}" , strBaseName, phiBin) : strBaseName;
522+ TObject* obj = td->Get (strGraphName.c_str ());
523+ if (!obj) {
524+ LOG (fatal) << " [TrackTuner] TGraphErrors not found in the Input Root file: " << strGraphName;
525+ td->ls ();
526+ return nullptr ;
527+ }
528+ return dynamic_cast <TGraphErrors*>(obj);
529+ };
530+
531+ if (inputNphiBins != 0 ) {
532+ LOG (info) << " [TrackTuner] Loading phi-dependent XY TGraphErrors" ;
494533 }
534+ for (int iPhiBin = 0 ; iPhiBin < nPhiBins; ++iPhiBin) {
495535
496- std::string grDcaZResNameMC = " resCurrentDcaZ" ;
497- std::string grDcaZMeanNameMC = " meanCurrentDcaZ" ;
498- std::string grDcaZPullNameMC = " pullsCurrentDcaZ" ;
499- std::string grDcaZResNameData = " resUpgrDcaZ" ;
500- std::string grDcaZMeanNameData = " meanUpgrDcaZ" ;
501- std::string grDcaZPullNameData = " pullsUpgrDcaZ" ;
502-
503- grDcaZResVsPtPionMC.reset (dynamic_cast <TGraphErrors*>(td->Get (grDcaZResNameMC.c_str ())));
504- grDcaZResVsPtPionData.reset (dynamic_cast <TGraphErrors*>(td->Get (grDcaZResNameData.c_str ())));
505- grDcaZMeanVsPtPionMC.reset (dynamic_cast <TGraphErrors*>(td->Get (grDcaZMeanNameMC.c_str ())));
506- grDcaZMeanVsPtPionData.reset (dynamic_cast <TGraphErrors*>(td->Get (grDcaZMeanNameData.c_str ())));
507- grDcaZPullVsPtPionMC.reset (dynamic_cast <TGraphErrors*>(td->Get (grDcaZPullNameMC.c_str ())));
508- grDcaZPullVsPtPionData.reset (dynamic_cast <TGraphErrors*>(td->Get (grDcaZPullNameData.c_str ())));
509- if (!grDcaZResVsPtPionMC.get () || !grDcaZResVsPtPionData.get () || !grDcaZMeanVsPtPionMC.get () || !grDcaZMeanVsPtPionData.get () || !grDcaZPullVsPtPionMC.get () || !grDcaZPullVsPtPionData.get ()) {
510- LOG (fatal) << " Something wrong with the names of the correction graphs for dcaZ. Fix it!" ;
536+ grDcaXYResVsPtPionMC[iPhiBin].reset (loadGraph (iPhiBin, " resCurrentDcaXY" ));
537+ grDcaXYResVsPtPionData[iPhiBin].reset (loadGraph (iPhiBin, " resUpgrDcaXY" ));
538+ grDcaXYMeanVsPtPionMC[iPhiBin].reset (loadGraph (iPhiBin, " meanCurrentDcaXY" ));
539+ grDcaXYMeanVsPtPionData[iPhiBin].reset (loadGraph (iPhiBin, " meanUpgrDcaXY" ));
540+ grDcaXYPullVsPtPionMC[iPhiBin].reset (loadGraph (iPhiBin, " pullsCurrentDcaXY" ));
541+ grDcaXYPullVsPtPionData[iPhiBin].reset (loadGraph (iPhiBin, " pullsUpgrDcaXY" ));
542+
543+ if (!grDcaXYResVsPtPionMC[iPhiBin].get () || !grDcaXYResVsPtPionData[iPhiBin].get () || !grDcaXYMeanVsPtPionMC[iPhiBin].get () || !grDcaXYMeanVsPtPionData[iPhiBin].get () || !grDcaXYPullVsPtPionMC[iPhiBin].get () || !grDcaXYPullVsPtPionData[iPhiBin].get ()) {
544+ LOG (fatal) << " [TrackTuner] Something wrong with the names of the correction graphs for dcaXY. Fix it! Problematic phi bin is" << iPhiBin;
545+ }
546+ }
547+
548+ if (inputNphiBins != 0 ) {
549+ LOG (info) << " [TrackTuner] Loading phi-dependent Z TGraphErrors" ;
550+ }
551+ for (int iPhiBin = 0 ; iPhiBin < nPhiBins; ++iPhiBin) {
552+ grDcaZResVsPtPionMC[iPhiBin].reset (loadGraph (iPhiBin, " resCurrentDcaZ" ));
553+ grDcaZMeanVsPtPionMC[iPhiBin].reset (loadGraph (iPhiBin, " meanCurrentDcaZ" ));
554+ grDcaZPullVsPtPionMC[iPhiBin].reset (loadGraph (iPhiBin, " pullsCurrentDcaZ" ));
555+ grDcaZResVsPtPionData[iPhiBin].reset (loadGraph (iPhiBin, " resUpgrDcaZ" ));
556+ grDcaZMeanVsPtPionData[iPhiBin].reset (loadGraph (iPhiBin, " meanUpgrDcaZ" ));
557+ grDcaZPullVsPtPionData[iPhiBin].reset (loadGraph (iPhiBin, " pullsUpgrDcaZ" ));
558+
559+ if (!grDcaZResVsPtPionMC[iPhiBin].get () || !grDcaZResVsPtPionData[iPhiBin].get () || !grDcaZMeanVsPtPionMC[iPhiBin].get () || !grDcaZMeanVsPtPionData[iPhiBin].get () || !grDcaZPullVsPtPionMC[iPhiBin].get () || !grDcaZPullVsPtPionData[iPhiBin].get ()) {
560+ LOG (fatal) << " [TrackTuner] Something wrong with the names of the correction graphs for dcaZ. Fix it! Problematic phi bin is" << iPhiBin;
561+ }
511562 }
512563
513564 std::string grOneOverPtPionNameMC = " sigmaVsPtMc" ;
@@ -538,11 +589,17 @@ struct TrackTuner : o2::framework::ConfigurableGroup {
538589 double dcaZPullMC = 1.0 ;
539590 double dcaZPullData = 1.0 ;
540591
541- dcaXYResMC = evalGraph (ptMC, grDcaXYResVsPtPionMC.get ());
542- dcaXYResData = evalGraph (ptMC, grDcaXYResVsPtPionData.get ());
592+ // get phibin
593+ double phiMC = mcparticle.phi ();
594+ if (phiMC < 0 .)
595+ phiMC += o2::constants::math::TwoPI; // 2 * std::numbers::pi;//
596+ int phiBin = phiMC / (o2::constants::math::TwoPI + 0.0000001 ) * nPhiBins; // 0.0000001 just a numerical protection
543597
544- dcaZResMC = evalGraph (ptMC, grDcaZResVsPtPionMC.get ());
545- dcaZResData = evalGraph (ptMC, grDcaZResVsPtPionData.get ());
598+ dcaXYResMC = evalGraph (ptMC, grDcaXYResVsPtPionMC[phiBin].get ());
599+ dcaXYResData = evalGraph (ptMC, grDcaXYResVsPtPionData[phiBin].get ());
600+
601+ dcaZResMC = evalGraph (ptMC, grDcaZResVsPtPionMC[phiBin].get ());
602+ dcaZResData = evalGraph (ptMC, grDcaZResVsPtPionData[phiBin].get ());
546603
547604 // For Q/Pt corrections, files on CCDB will be used if both qOverPtMC and qOverPtData are null
548605 if (updateCurvature || updateCurvatureIU) {
@@ -560,14 +617,15 @@ struct TrackTuner : o2::framework::ConfigurableGroup {
560617 } // updateCurvature, updateCurvatureIU block ends here
561618
562619 if (updateTrackDCAs) {
563- dcaXYMeanMC = evalGraph (ptMC, grDcaXYMeanVsPtPionMC.get ());
564- dcaXYMeanData = evalGraph (ptMC, grDcaXYMeanVsPtPionData.get ());
565620
566- dcaXYPullMC = evalGraph (ptMC, grDcaXYPullVsPtPionMC.get ());
567- dcaXYPullData = evalGraph (ptMC, grDcaXYPullVsPtPionData.get ());
621+ dcaXYMeanMC = evalGraph (ptMC, grDcaXYMeanVsPtPionMC[phiBin].get ());
622+ dcaXYMeanData = evalGraph (ptMC, grDcaXYMeanVsPtPionData[phiBin].get ());
623+
624+ dcaXYPullMC = evalGraph (ptMC, grDcaXYPullVsPtPionMC[phiBin].get ());
625+ dcaXYPullData = evalGraph (ptMC, grDcaXYPullVsPtPionData[phiBin].get ());
568626
569- dcaZPullMC = evalGraph (ptMC, grDcaZPullVsPtPionMC.get ());
570- dcaZPullData = evalGraph (ptMC, grDcaZPullVsPtPionData.get ());
627+ dcaZPullMC = evalGraph (ptMC, grDcaZPullVsPtPionMC[phiBin] .get ());
628+ dcaZPullData = evalGraph (ptMC, grDcaZPullVsPtPionData[phiBin] .get ());
571629 }
572630 // Unit conversion, is it required ??
573631 dcaXYResMC *= 1 .e -4 ;
@@ -676,12 +734,17 @@ struct TrackTuner : o2::framework::ConfigurableGroup {
676734 if (updateTrackDCAs) {
677735 // propagate to DCA with respect to the Production point
678736 o2::base::Propagator::Instance ()->propagateToDCABxByBz (vtxMC, trackParCov, 2 .f , matCorr, dcaInfoCov);
737+ if (debugInfo) {
738+ LOG (info) << " phi MC" << mcparticle.phi ();
739+ LOG (info) << " alpha track" << trackParCov.getAlpha ();
740+ }
679741 // double d0zo =param [1];
680742 double trackParDcaZRec = trackParCov.getZ ();
681743 // double d0rpo =param [0];
682744 double trackParDcaXYRec = trackParCov.getY ();
683745 float mcVxRotated = mcparticle.vx () * std::cos (trackParCov.getAlpha ()) + mcparticle.vy () * std::sin (trackParCov.getAlpha ()); // invert
684746 float mcVyRotated = mcparticle.vy () * std::cos (trackParCov.getAlpha ()) - mcparticle.vx () * std::sin (trackParCov.getAlpha ());
747+
685748 if (debugInfo) {
686749 // LOG(info) << "mcVy " << mcparticle.vy() << std::endl;
687750 LOG (info) << " mcVxRotated " << mcVxRotated;
@@ -954,7 +1017,7 @@ struct TrackTuner : o2::framework::ConfigurableGroup {
9541017 {
9551018
9561019 if (!graph) {
957- printf ( " \t evalGraph fails !\n " ) ;
1020+ LOG (fatal) << " \t evalGraph fails !\n " ;
9581021 return 0 .;
9591022 }
9601023 int nPoints = graph->GetN ();
0 commit comments