@@ -84,14 +84,19 @@ enum AnalysisMode {
8484 kDeltaYvsDeltaPhi
8585};
8686
87- enum ParticleOfInterest {
87+ enum AssociatedParticleType {
88+ kK0S = 0 ,
89+ kXi ,
90+ kPion ,
91+ kAssocPartSize
92+ };
93+
94+ /* enum ParticleOfInterest {
8895 Phi = 0,
8996 K0S,
9097 Pion,
91- /* PionTPC,
92- PionTPCTOF*/
9398 ParticleOfInterestSize
94- };
99+ };*/
95100
96101/*
97102#define LIST_OF_PARTICLES_OF_INTEREST \
@@ -121,7 +126,9 @@ static constexpr auto particleOfInterestLabels = std::to_array<std::string_view>
121126});
122127*/
123128
124- struct BoundEfficiencyMap {
129+ using EffMapPtr = std::variant<std::shared_ptr<TH2 >, std::shared_ptr<TH3 >>;
130+
131+ /* struct BoundEfficiencyMap {
125132 using CoordsTuple = std::tuple<float, float, float>;
126133
127134 const TH3* effMap;
@@ -149,6 +156,58 @@ struct BoundEfficiencyMap {
149156 const auto& [x, y, z] = coords;
150157 return effMap->Interpolate(x, y, z);
151158 }
159+ };*/
160+
161+ struct BoundEfficiencyMap {
162+ using CoordsTuple = std::tuple<float , float , float >;
163+
164+ const EffMapPtr& effMap;
165+ CoordsTuple coords;
166+
167+ BoundEfficiencyMap (const EffMapPtr& effMap, float x, float y, float z) : effMap(effMap), coords(x, y, z) {}
168+ BoundEfficiencyMap (const EffMapPtr& effMap, const CoordsTuple& coords) : effMap(effMap), coords(coords) {}
169+
170+ float getBinEfficiency () const
171+ {
172+ return std::visit (
173+ [this ](auto && mapPtr) -> float {
174+ if (!mapPtr)
175+ return 1 .0f ;
176+
177+ const auto & [x, y, z] = coords;
178+
179+ // Extract the actual histogram type (TH2 or TH3) held by the smart pointer
180+ using HistoType = typename std::decay_t <decltype (mapPtr)>::element_type;
181+
182+ // Compile-time branching: generates the exact correct function call
183+ if constexpr (std::is_same_v<HistoType, TH2 >) {
184+ return mapPtr->GetBinContent (mapPtr->FindFixBin (y, z)); // 2D case only
185+ } else {
186+ return mapPtr->GetBinContent (mapPtr->FindFixBin (x, y, z)); // Full 3D case
187+ }
188+ },
189+ effMap);
190+ }
191+
192+ float interpolateEfficiency () const
193+ {
194+ return std::visit (
195+ [this ](auto && mapPtr) -> float {
196+ if (!mapPtr)
197+ return 1 .0f ;
198+
199+ const auto & [x, y, z] = coords;
200+
201+ using HistoType = typename std::decay_t <decltype (mapPtr)>::element_type;
202+
203+ if constexpr (std::is_same_v<HistoType, TH2 >) {
204+ return mapPtr->Interpolate (y, z); // Native 2D interpolation
205+ } else {
206+ return mapPtr->Interpolate (x, y, z); // Native 3D interpolation
207+ }
208+ },
209+ effMap);
210+ }
152211};
153212
154213struct PhiStrangenessCorrelation {
@@ -195,6 +254,12 @@ struct PhiStrangenessCorrelation {
195254 // Configurable on pion pT bins
196255 Configurable<std::vector<double >> binspTPi{" binspTPi" , {0.2 , 0.3 , 0.4 , 0.5 , 0.6 , 0.8 , 1.0 , 1.2 , 1.5 , 2.0 , 3.0 }, " pT bin limits for pions" };
197256
257+ struct : ConfigurableGroup {
258+ Configurable<bool > doK0SCorrelation{" doK0SCorrelation" , true , " Enable Phi-K0S correlation" };
259+ Configurable<bool > doXiCorrelation{" doXiCorrelation" , false , " Enable Phi-Xi correlation" };
260+ Configurable<bool > doPionCorrelation{" doPionCorrelation" , true , " Enable Phi-Pion correlation" };
261+ } activeCorrelationConfigs;
262+
198263 // Configurables for delta y selection
199264 struct : ConfigurableGroup {
200265 Configurable<int > nBinsY{" nBinsY" , 20 , " Number of bins in y axis" };
@@ -250,18 +315,22 @@ struct PhiStrangenessCorrelation {
250315 // Necessary service to retrieve efficiency maps from CCDB
251316 Service<ccdb::BasicCCDBManager> ccdb;
252317
253- std::array<std::shared_ptr<TH3 >, ParticleOfInterestSize> effMaps{};
318+ // std::shared_ptr<TH3> effMapPhi{};
319+ // std::array<std::shared_ptr<TH3>, kAssocPartSize> effMapsAssoc{};
320+
321+ EffMapPtr effMapPhi{};
322+ std::array<EffMapPtr, kAssocPartSize > effMapsAssoc{};
254323
255324 // Binning policy and axes for mixed event
256- ConfigurableAxis axisVertexMixing{" axisVertexMixing" , {20 , -10 , 10 }, " Z vertex axis binning for mixing" };
257- ConfigurableAxis axisCentralityMixing{" axisCentralityMixing" , {20 , 0 , 100 }, " Multiplicity percentil binning for mixing" };
325+ ConfigurableAxis axisVertexMixing{" axisVertexMixing" , {10 , -10 . 0f , 10 . 0f }, " Z vertex axis binning for mixing" };
326+ ConfigurableAxis axisCentralityMixing{" axisCentralityMixing" , {VARIABLE_WIDTH , 0 . 0f , 1 . 0f , 5 . 0f , 10 . 0f , 15 . 0f , 20 . 0f , 30 . 0f , 40 . 0f , 50 . 0f , 70 . 0f , 100 . 0f }, " Multiplicity percentage binning for mixing" };
258327
259328 using BinningTypeVertexCent = ColumnBinningPolicy<aod::collision::PosZ, aod::cent::CentFT0M>;
260329 BinningTypeVertexCent binningOnVertexAndCent{{axisVertexMixing, axisCentralityMixing}, true };
261330
262331 static constexpr std::array<std::string_view, 2 > phiMassRegionLabels{" Signal" , " Sideband" };
263- static constexpr std::array<std::string_view, ParticleOfInterestSize> particleOfInterestLabels{" Phi" , " K0S" , " Pion" /* "PionTPC", "PionTPCTOF"*/ };
264- static constexpr std::array<std::string_view, ParticleOfInterestSize - 1 > assocParticleLabels{" K0S" , " Pi" };
332+ // static constexpr std::array<std::string_view, ParticleOfInterestSize> particleOfInterestLabels{"Phi", "K0S", "Pion" /*"PionTPC", "PionTPCTOF"*/};
333+ static constexpr std::array<std::string_view, kAssocPartSize > assocParticleLabels{" K0S" , " Xi " , " Pi" };
265334
266335 // Light structures to store only the necessary information for the correlation analysis at MCGen level
267336 struct MiniParticle {
@@ -274,6 +343,7 @@ struct PhiStrangenessCorrelation {
274343 float multiplicity;
275344 std::vector<MiniParticle> phiParticles;
276345 std::vector<MiniParticle> k0sParticles;
346+ std::vector<MiniParticle> xiParticles;
277347 std::vector<MiniParticle> pionParticles;
278348 };
279349
@@ -348,21 +418,56 @@ struct PhiStrangenessCorrelation {
348418 ccdb->setLocalObjectValidityChecking ();
349419 ccdb->setFatalWhenNull (false );
350420
351- for (int i = 0 ; i < ParticleOfInterestSize; ++i) {
421+ /* for (int i = 0; i < ParticleOfInterestSize; ++i) {
352422 loadEfficiencyMapFromCCDB(static_cast<ParticleOfInterest>(i));
353- }
423+ }*/
424+ loadEfficiencyMaps ();
354425 }
355426
356427 eventBuffer.resize (binsMult->size () - 1 );
357428 }
358429
359- void loadEfficiencyMapFromCCDB (ParticleOfInterest poi)
430+ void fetchSingleEfficiencyMapFromCCDB (EffMapPtr& effMap, std::string_view particleName)
431+ {
432+ std::string path = fmt::format (" {}{}" , ccdbEfficiencyPath.value , particleName);
433+
434+ if (auto map3D = std::shared_ptr<TH3 >(ccdb->get <TH3D >(path))) {
435+ effMap = map3D;
436+ LOG (info) << " Efficiency map (TH3) for " << particleName << " loaded from CCDB" ;
437+ return ;
438+ }
439+
440+ if (auto map2D = std::shared_ptr<TH2 >(ccdb->get <TH2D >(path))) {
441+ effMap = map2D;
442+ LOG (info) << " Efficiency map (TH2) for " << particleName << " loaded from CCDB" ;
443+ return ;
444+ }
445+
446+ LOG (fatal) << " Could not load efficiency map (neither TH3 nor TH2) for " << particleName << " from CCDB!" ;
447+ }
448+
449+ void loadEfficiencyMaps ()
450+ {
451+ // Always load the Trigger (Phi) map
452+ fetchSingleEfficiencyMapFromCCDB (effMapPhi, " Phi" );
453+
454+ // Map the user configurations for the associated particles
455+ bool doAssocCorrelations[kAssocPartSize ] = {activeCorrelationConfigs.doK0SCorrelation , activeCorrelationConfigs.doXiCorrelation , activeCorrelationConfigs.doPionCorrelation };
456+
457+ // Only load the associated maps that are explicitly enabled
458+ for (size_t i = 0 ; i < kAssocPartSize ; ++i) {
459+ if (doAssocCorrelations[i])
460+ fetchSingleEfficiencyMapFromCCDB (effMapsAssoc[i], assocParticleLabels[i]);
461+ }
462+ }
463+
464+ /* void loadEfficiencyMapFromCCDB(ParticleOfInterest poi)
360465 {
361466 effMaps[poi] = std::shared_ptr<TH3>(ccdb->get<TH3D>(fmt::format("{}{}", ccdbEfficiencyPath.value, particleOfInterestLabels[poi])));
362467 if (!effMaps[poi])
363468 LOG(fatal) << "Could not load efficiency map for " << particleOfInterestLabels[poi] << "!";
364469 LOG(info) << "Efficiency map for " << particleOfInterestLabels[poi] << " loaded from CCDB";
365- }
470+ }*/
366471
367472 // Compute weight based on efficiencies
368473 template <typename ... BoundEffMaps>
@@ -397,10 +502,14 @@ struct PhiStrangenessCorrelation {
397502
398503 const std::array<std::pair<float , float >, 2 > phiMassRegions = {phiConfigs.rangeMPhiSignal , phiConfigs.rangeMPhiSideband };
399504
505+ bool doAssocCorrelations[kAssocPartSize ] = {activeCorrelationConfigs.doK0SCorrelation ,
506+ activeCorrelationConfigs.doXiCorrelation ,
507+ activeCorrelationConfigs.doPionCorrelation };
508+
400509 const bool applyK0sMassCut = (analysisMode == kDeltaYvsDeltaPhi ) && k0sConfigs.selectK0sInSigRegion ;
401510 const auto & [minMassK0s, maxMassK0s] = k0sConfigs.rangeMK0sSignal .value ;
402511 auto isK0sValid = [&](const auto & k0s) {
403- return ! applyK0sMassCut || k0s.inMassRegion (minMassK0s, maxMassK0s);
512+ return (!applyEfficiency || k0s. pt () <= binspTK0S-> back ()) && (! applyK0sMassCut || k0s.inMassRegion (minMassK0s, maxMassK0s) );
404513 };
405514
406515 const bool applyPionNSigmaCut = (analysisMode == kDeltaYvsDeltaPhi ) && pionConfigs.selectPionInSigRegion ;
@@ -409,33 +518,40 @@ struct PhiStrangenessCorrelation {
409518 const float & tofPIDThreshold = pionConfigs.tofPIDThreshold ;
410519
411520 auto isPionValid = [&](const auto & pion) {
412- return ! applyPionNSigmaCut || pion.inNSigmaRegion (pidTPCMax, tofPIDThreshold, pidTOFMax);
521+ return (!applyEfficiency || pion. pt () <= binspTPi-> back ()) && (! applyPionNSigmaCut || pion.inNSigmaRegion (pidTPCMax, tofPIDThreshold, pidTOFMax) );
413522 };
414523
415524 for (const auto & phiCand : phiCandidates) {
416- float weightPhi = computeWeight (BoundEfficiencyMap (effMaps[Phi], multiplicity, phiCand.pt (), phiCand.y ()));
525+ if (applyEfficiency && phiCand.pt () > binspTPhi->back ())
526+ continue ;
527+
528+ float weightPhi = computeWeight (BoundEfficiencyMap (effMapPhi, multiplicity, phiCand.pt (), phiCand.y ()));
417529
418530 histos.fill (HIST (" phi/h3PhiData" ), multiplicity, phiCand.pt (), phiCand.m (), weightPhi);
419531
420532 auto processCorrelations = [&](auto fillK0S, auto fillPion) {
421- // Loop over all reduced K0S candidates
422- for (const auto & k0s : k0sReduced) {
423- if (!isK0sValid (k0s))
424- continue ;
533+ if (doAssocCorrelations[kK0S ]) {
534+ // Loop over all reduced K0S candidates
535+ for (const auto & k0s : k0sReduced) {
536+ if (!isK0sValid (k0s))
537+ continue ;
425538
426- float weightPhiK0S = computeWeight (BoundEfficiencyMap (effMaps[Phi], multiplicity, phiCand.pt (), phiCand.y ()),
427- BoundEfficiencyMap (effMaps[K0S ], multiplicity, k0s.pt (), k0s.y ()));
428- fillK0S (k0s, weightPhiK0S);
539+ float weightPhiK0S = computeWeight (BoundEfficiencyMap (effMapPhi, multiplicity, phiCand.pt (), phiCand.y ()),
540+ BoundEfficiencyMap (effMapsAssoc[kK0S ], multiplicity, k0s.pt (), k0s.y ()));
541+ fillK0S (k0s, weightPhiK0S);
542+ }
429543 }
430544
431- // Loop over all primary pion candidates
432- for (const auto & pionTrack : pionTracks) {
433- if (!isPionValid (pionTrack))
434- continue ;
545+ if (doAssocCorrelations[kPion ]) {
546+ // Loop over all primary pion candidates
547+ for (const auto & pionTrack : pionTracks) {
548+ if (!isPionValid (pionTrack))
549+ continue ;
435550
436- float weightPhiPion = computeWeight (BoundEfficiencyMap (effMaps[Phi], multiplicity, phiCand.pt (), phiCand.y ()),
437- BoundEfficiencyMap (effMaps[Pion], multiplicity, pionTrack.pt (), pionTrack.y ()));
438- fillPion (pionTrack, weightPhiPion);
551+ float weightPhiPion = computeWeight (BoundEfficiencyMap (effMapPhi, multiplicity, phiCand.pt (), phiCand.y ()),
552+ BoundEfficiencyMap (effMapsAssoc[kPion ], multiplicity, pionTrack.pt (), pionTrack.y ()));
553+ fillPion (pionTrack, weightPhiPion);
554+ }
439555 }
440556 };
441557
@@ -533,7 +649,7 @@ struct PhiStrangenessCorrelation {
533649 const auto & [minMassK0s, maxMassK0s] = k0sConfigs.rangeMK0sSignal .value ;
534650
535651 auto isK0sValid = [&](const auto & k0s) {
536- return ! applyK0sMassCut || k0s.inMassRegion (minMassK0s, maxMassK0s);
652+ return (!applyEfficiency || k0s. pt () <= binspTK0S-> back ()) && (! applyK0sMassCut || k0s.inMassRegion (minMassK0s, maxMassK0s) );
537653 };
538654
539655 auto tuplePhiK0S = std::make_tuple (phiCandidates, k0sReduced);
@@ -544,12 +660,14 @@ struct PhiStrangenessCorrelation {
544660 float multiplicity = c1.centFT0M ();
545661
546662 for (const auto & [phiCand, k0s] : o2::soa::combinations (o2::soa::CombinationsFullIndexPolicy (phiCands, k0sRed))) {
663+ if (applyEfficiency && phiCand.pt () > binspTPhi->back ())
664+ continue ;
547665 if (!isK0sValid (k0s))
548666 continue ;
549667
550668 auto processCorrelations = [&](auto fillK0S) {
551- float weightPhiK0S = computeWeight (BoundEfficiencyMap (effMaps[Phi] , multiplicity, phiCand.pt (), phiCand.y ()),
552- BoundEfficiencyMap (effMaps[ K0S ], multiplicity, k0s.pt (), k0s.y ()));
669+ float weightPhiK0S = computeWeight (BoundEfficiencyMap (effMapPhi , multiplicity, phiCand.pt (), phiCand.y ()),
670+ BoundEfficiencyMap (effMapsAssoc[ kK0S ], multiplicity, k0s.pt (), k0s.y ()));
553671 fillK0S (k0s, weightPhiK0S);
554672 };
555673
@@ -626,7 +744,7 @@ struct PhiStrangenessCorrelation {
626744 const float & tofPIDThreshold = pionConfigs.tofPIDThreshold ;
627745
628746 auto isPionValid = [&](const auto & pion) {
629- return ! applyPionNSigmaCut || pion.inNSigmaRegion (pidTPCMax, tofPIDThreshold, pidTOFMax);
747+ return (!applyEfficiency || pion. pt () <= binspTPi-> back ()) && (! applyPionNSigmaCut || pion.inNSigmaRegion (pidTPCMax, tofPIDThreshold, pidTOFMax) );
630748 };
631749
632750 auto tuplePhiPion = std::make_tuple (phiCandidates, pionTracks);
@@ -637,12 +755,14 @@ struct PhiStrangenessCorrelation {
637755 float multiplicity = c1.centFT0M ();
638756
639757 for (const auto & [phiCand, piTrack] : o2::soa::combinations (o2::soa::CombinationsFullIndexPolicy (phiCands, piTracks))) {
758+ if (applyEfficiency && phiCand.pt () > binspTPhi->back ())
759+ continue ;
640760 if (!isPionValid (piTrack))
641761 continue ;
642762
643763 auto processCorrelations = [&](auto fillPion) {
644- float weightPhiPion = computeWeight (BoundEfficiencyMap (effMaps[Phi] , multiplicity, phiCand.pt (), phiCand.y ()),
645- BoundEfficiencyMap (effMaps[Pion ], multiplicity, piTrack.pt (), piTrack.y ()));
764+ float weightPhiPion = computeWeight (BoundEfficiencyMap (effMapPhi , multiplicity, phiCand.pt (), phiCand.y ()),
765+ BoundEfficiencyMap (effMapsAssoc[ kPion ], multiplicity, piTrack.pt (), piTrack.y ()));
646766 fillPion (piTrack, weightPhiPion);
647767 };
648768
@@ -961,6 +1081,7 @@ struct PhiStrangenessCorrelation {
9611081
9621082 std::vector<MiniParticle> phiParticles;
9631083 std::vector<MiniParticle> k0sParticles;
1084+ std::vector<MiniParticle> xiParticles;
9641085 std::vector<MiniParticle> pionParticles;
9651086
9661087 auto inYAcceptance = [&](const auto & mcParticle) {
@@ -997,14 +1118,20 @@ struct PhiStrangenessCorrelation {
9971118 if (multBin < 0 )
9981119 return ;
9991120
1121+ bool doAssocCorrelations[kAssocPartSize ] = {activeCorrelationConfigs.doK0SCorrelation ,
1122+ activeCorrelationConfigs.doXiCorrelation ,
1123+ activeCorrelationConfigs.doPionCorrelation };
1124+
10001125 // Same Event Correlations
1001- std::vector<MiniParticle>* currentAssocParticles[] = {&k0sParticles, &pionParticles};
1126+ std::vector<MiniParticle>* currentAssocParticles[] = {&k0sParticles, &xiParticles, & pionParticles};
10021127
10031128 for (const auto & phiParticle : phiParticles) {
10041129 histos.fill (HIST (" phi/h3PhiMCGen" ), multiplicity, phiParticle.pt , phiParticle.y );
10051130
10061131 static_for<0 , assocParticleLabels.size () - 1 >([&](auto i_idx) {
10071132 constexpr unsigned int i = i_idx.value ;
1133+ if (!doAssocCorrelations[i])
1134+ return ;
10081135
10091136 for (const auto & assocParticle : *(currentAssocParticles[i])) {
10101137 histos.fill (HIST (" phi" ) + HIST (assocParticleLabels[i]) + HIST (" /h5Phi" ) + HIST (assocParticleLabels[i]) + HIST (" ClosureMCGen" ),
@@ -1017,12 +1144,14 @@ struct PhiStrangenessCorrelation {
10171144
10181145 // Mixed Event Correlations
10191146 for (const auto & pastEvent : eventBuffer[multBin]) {
1020- const std::vector<MiniParticle>* pastAssocParticles[] = {&pastEvent.k0sParticles , &pastEvent.pionParticles };
1147+ const std::vector<MiniParticle>* pastAssocParticles[] = {&pastEvent.k0sParticles , &pastEvent.xiParticles , &pastEvent. pionParticles };
10211148
10221149 // Loop over past events in the same multiplicity bin and fill histograms with all combinations of current phi particles and past associated particles
10231150 for (const auto & phiParticle : phiParticles) {
10241151 static_for<0 , assocParticleLabels.size () - 1 >([&](auto i_idx) {
10251152 constexpr unsigned int i = i_idx.value ;
1153+ if (!doAssocCorrelations[i])
1154+ return ;
10261155
10271156 for (const auto & assocParticle : *(pastAssocParticles[i])) {
10281157 histos.fill (HIST (" phi" ) + HIST (assocParticleLabels[i]) + HIST (" /h5Phi" ) + HIST (assocParticleLabels[i]) + HIST (" ClosureMCGenME" ),
@@ -1038,6 +1167,7 @@ struct PhiStrangenessCorrelation {
10381167 currentEvent.multiplicity = multiplicity;
10391168 currentEvent.phiParticles = std::move (phiParticles);
10401169 currentEvent.k0sParticles = std::move (k0sParticles);
1170+ currentEvent.xiParticles = std::move (xiParticles);
10411171 currentEvent.pionParticles = std::move (pionParticles);
10421172
10431173 eventBuffer[multBin].push_front (std::move (currentEvent));
0 commit comments