2626#include " PWGHF/DataModel/CandidateSelectionTables.h"
2727#include " PWGHF/Utils/utilsAnalysis.h"
2828#include " PWGHF/Utils/utilsEvSelHf.h"
29+ #include " PWGHF/Utils/utilsUpcHf.h"
2930#include " PWGUD/Core/UPCHelpers.h"
3031
3132#include " Common/Core/RecoDecay.h"
@@ -62,12 +63,7 @@ using namespace o2::framework::expressions;
6263using namespace o2 ::hf_centrality;
6364using namespace o2 ::hf_occupancy;
6465using namespace o2 ::hf_evsel;
65-
66- enum class GapType {
67- GapA = 0 ,
68- GapC = 1 ,
69- DoubleGap = 2 ,
70- };
66+ using namespace o2 ::analysis::hf_upc;
7167
7268// / D± analysis task
7369struct HfTaskDplus {
@@ -128,6 +124,7 @@ struct HfTaskDplus {
128124 ConfigurableAxis thnConfigAxisMlScore0{" thnConfigAxisMlScore0" , {100 , 0 ., 1 .}, " axis for ML output score 0" };
129125 ConfigurableAxis thnConfigAxisMlScore1{" thnConfigAxisMlScore1" , {100 , 0 ., 1 .}, " axis for ML output score 1" };
130126 ConfigurableAxis thnConfigAxisMlScore2{" thnConfigAxisMlScore2" , {100 , 0 ., 1 .}, " axis for ML output score 2" };
127+ ConfigurableAxis thnConfigAxisGapType{" thnConfigAxisGapType" , {3 , -0.5 , 2.5 }, " axis for UPC gap type (0=GapA, 1=GapC, 2=DoubleGap)" };
131128
132129 HistogramRegistry registry{
133130 " registry" ,
@@ -161,6 +158,7 @@ struct HfTaskDplus {
161158 AxisSpec const thnAxisCent{thnConfigAxisCent, " Centrality" };
162159 AxisSpec const thnAxisOccupancy{thnConfigAxisOccupancy, " Occupancy" };
163160 AxisSpec const thnAxisPvContributors{thnConfigAxisPvContributors, " PV contributors" };
161+ AxisSpec const thnAxisGapType{thnConfigAxisGapType, " Gap type" };
164162
165163 registry.add (" hMass" , " 3-prong candidates;inv. mass (#pi K #pi) (GeV/#it{c}^{2});entries" , {HistType::kTH2F , {{350 , 1.7 , 2.05 }, {vbins, " #it{p}_{T} (GeV/#it{c})" }}});
166164 registry.add (" hEta" , " 3-prong candidates;candidate #it{#eta};entries" , {HistType::kTH2F , {{100 , -2 ., 2 .}, {vbins, " #it{p}_{T} (GeV/#it{c})" }}});
@@ -200,10 +198,10 @@ struct HfTaskDplus {
200198 registry.add (" hPtVsYGenPrompt" , " MC particles (matched, prompt);#it{p}_{T}^{gen.}; #it{y}" , {HistType::kTH2F , {{vbins, " #it{p}_{T} (GeV/#it{c})" }, {100 , -5 ., 5 .}}});
201199 registry.add (" hPtVsYGenNonPrompt" , " MC particles (matched, non-prompt);#it{p}_{T}^{gen.}; #it{y}" , {HistType::kTH2F , {{vbins, " #it{p}_{T} (GeV/#it{c})" }, {100 , -5 ., 5 .}}});
202200
203- if (doprocessDataWithMl || doprocessData) {
201+ if (doprocessDataWithMl || doprocessData || doprocessDataWithMlWithUpc ) {
204202 std::vector<AxisSpec> axes = {thnAxisMass, thnAxisPt};
205203
206- if (doprocessDataWithMl) {
204+ if (doprocessDataWithMl || doprocessDataWithMlWithUpc ) {
207205 axes.push_back (thnAxisMlScore0);
208206 axes.push_back (thnAxisMlScore1);
209207 axes.push_back (thnAxisMlScore2);
@@ -214,6 +212,9 @@ struct HfTaskDplus {
214212 if (storeOccupancy) {
215213 axes.push_back (thnAxisOccupancy);
216214 }
215+ if (doprocessDataWithMlWithUpc) {
216+ axes.push_back (thnAxisGapType);
217+ }
217218
218219 registry.add (" hSparseMass" , " THn for Dplus" , HistType::kTHnSparseF , axes);
219220 }
@@ -313,13 +314,15 @@ struct HfTaskDplus {
313314 // / \param centrality collision centrality
314315 // / \param occupancy collision occupancy
315316 // / \param numPvContributors contributors to the PV
317+ // / \param gapType UPC gap type (-1 for non-UPC)
316318 template <bool IsMc, bool IsMatched, typename T1>
317319 void fillSparseML (const T1& candidate,
318320 float ptbhad,
319321 int flagBHad,
320322 float centrality,
321323 float occupancy,
322- float numPvContributors)
324+ float numPvContributors,
325+ int gapType = -1 )
323326 {
324327 std::vector<float > outputMl = {-999 ., -999 ., -999 .};
325328 for (unsigned int iclass = 0 ; iclass < classMl->size (); iclass++) {
@@ -384,16 +387,30 @@ struct HfTaskDplus {
384387 }
385388 }
386389 } else { // Data
387- if (storeCentrality && storeOccupancy) {
388- registry.fill (HIST (" hSparseMass" ), hfHelper.invMassDplusToPiKPi (candidate), candidate.pt (), outputMl[0 ], outputMl[1 ], outputMl[2 ], centrality, occupancy);
389- } else if (storeCentrality && !storeOccupancy) {
390- registry.fill (HIST (" hSparseMass" ), hfHelper.invMassDplusToPiKPi (candidate), candidate.pt (), outputMl[0 ], outputMl[1 ], outputMl[2 ], centrality);
391- } else if (!storeCentrality && storeOccupancy) {
392- registry.fill (HIST (" hSparseMass" ), hfHelper.invMassDplusToPiKPi (candidate), candidate.pt (), outputMl[0 ], outputMl[1 ], outputMl[2 ], occupancy);
393- } else if (!storeCentrality && !storeOccupancy && storePvContributors) {
394- registry.fill (HIST (" hSparseMass" ), hfHelper.invMassDplusToPiKPi (candidate), candidate.pt (), outputMl[0 ], outputMl[1 ], outputMl[2 ], numPvContributors);
390+ if (gapType >= 0 ) {
391+ // UPC mode: always include gap type
392+ if (storeCentrality && storeOccupancy) {
393+ registry.fill (HIST (" hSparseMass" ), hfHelper.invMassDplusToPiKPi (candidate), candidate.pt (), outputMl[0 ], outputMl[1 ], outputMl[2 ], centrality, occupancy, static_cast <float >(gapType));
394+ } else if (storeCentrality && !storeOccupancy) {
395+ registry.fill (HIST (" hSparseMass" ), hfHelper.invMassDplusToPiKPi (candidate), candidate.pt (), outputMl[0 ], outputMl[1 ], outputMl[2 ], centrality, static_cast <float >(gapType));
396+ } else if (!storeCentrality && storeOccupancy) {
397+ registry.fill (HIST (" hSparseMass" ), hfHelper.invMassDplusToPiKPi (candidate), candidate.pt (), outputMl[0 ], outputMl[1 ], outputMl[2 ], occupancy, static_cast <float >(gapType));
398+ } else {
399+ registry.fill (HIST (" hSparseMass" ), hfHelper.invMassDplusToPiKPi (candidate), candidate.pt (), outputMl[0 ], outputMl[1 ], outputMl[2 ], static_cast <float >(gapType));
400+ }
395401 } else {
396- registry.fill (HIST (" hSparseMass" ), hfHelper.invMassDplusToPiKPi (candidate), candidate.pt (), outputMl[0 ], outputMl[1 ], outputMl[2 ]);
402+ // Non-UPC mode: original behavior
403+ if (storeCentrality && storeOccupancy) {
404+ registry.fill (HIST (" hSparseMass" ), hfHelper.invMassDplusToPiKPi (candidate), candidate.pt (), outputMl[0 ], outputMl[1 ], outputMl[2 ], centrality, occupancy);
405+ } else if (storeCentrality && !storeOccupancy) {
406+ registry.fill (HIST (" hSparseMass" ), hfHelper.invMassDplusToPiKPi (candidate), candidate.pt (), outputMl[0 ], outputMl[1 ], outputMl[2 ], centrality);
407+ } else if (!storeCentrality && storeOccupancy) {
408+ registry.fill (HIST (" hSparseMass" ), hfHelper.invMassDplusToPiKPi (candidate), candidate.pt (), outputMl[0 ], outputMl[1 ], outputMl[2 ], occupancy);
409+ } else if (!storeCentrality && !storeOccupancy && storePvContributors) {
410+ registry.fill (HIST (" hSparseMass" ), hfHelper.invMassDplusToPiKPi (candidate), candidate.pt (), outputMl[0 ], outputMl[1 ], outputMl[2 ], numPvContributors);
411+ } else {
412+ registry.fill (HIST (" hSparseMass" ), hfHelper.invMassDplusToPiKPi (candidate), candidate.pt (), outputMl[0 ], outputMl[1 ], outputMl[2 ]);
413+ }
397414 }
398415 }
399416 }
@@ -680,20 +697,6 @@ struct HfTaskDplus {
680697 }
681698 }
682699
683- GapType determineGapType (float FT0A, float FT0C, float ZNA, float ZNC)
684- {
685- constexpr float FT0AThreshold = 100.0 ;
686- constexpr float FT0CThreshold = 50.0 ;
687- constexpr float ZDCThreshold = 1.0 ;
688- if (FT0A < FT0AThreshold && FT0C > FT0CThreshold && ZNA < ZDCThreshold && ZNC > ZDCThreshold) {
689- return GapType::GapA;
690- }
691- if (FT0A > FT0AThreshold && FT0C < FT0CThreshold && ZNA > ZDCThreshold && ZNC < ZDCThreshold) {
692- return GapType::GapC;
693- }
694- return GapType::DoubleGap;
695- }
696-
697700 template <bool fillMl, typename CollType, typename CandType, typename BCsType>
698701 void runAnalysisPerCollisionDataWithUpc (CollType const & collisions,
699702 CandType const & candidates,
@@ -719,10 +722,10 @@ struct HfTaskDplus {
719722 auto zdc = bc.zdc ();
720723 qaRegistry.fill (HIST (" Data/fitInfo/ampFT0A_vs_ampFT0C" ), fitInfo.ampFT0A , fitInfo.ampFT0C );
721724 qaRegistry.fill (HIST (" Data/zdc/energyZNA_vs_energyZNC" ), zdc.energyCommonZNA (), zdc.energyCommonZNC ());
722- gap = determineGapType (fitInfo.ampFT0A , fitInfo.ampFT0C , zdc.energyCommonZNA (), zdc.energyCommonZNC ());
723- qaRegistry.fill (HIST (" Data/hUpcGapAfterSelection" ), static_cast < int > (gap));
725+ gap = hf_upc:: determineGapType (fitInfo.ampFT0A , fitInfo.ampFT0C , zdc.energyCommonZNA (), zdc.energyCommonZNC ());
726+ qaRegistry.fill (HIST (" Data/hUpcGapAfterSelection" ), hf_upc::gapTypeToInt (gap));
724727 }
725- if (gap == GapType::GapA || gap == GapType::GapC ) {
728+ if (hf_upc::isSingleSidedGap ( gap) ) {
726729 // Use the candidates from this collision
727730 const auto thisCollId = collision.globalIndex ();
728731 const auto & groupedDplusCandidates = candidates.sliceBy (candDplusPerCollision, thisCollId);
@@ -731,14 +734,15 @@ struct HfTaskDplus {
731734 float numPvContr{-1 .f };
732735 float ptBhad{-1 .f };
733736 int const flagBHad{-1 };
737+ int const gapTypeInt = hf_upc::gapTypeToInt (gap);
734738
735739 for (const auto & candidate : groupedDplusCandidates) {
736740 if ((yCandRecoMax >= 0 . && std::abs (hfHelper.yDplus (candidate)) > yCandRecoMax)) {
737741 continue ;
738742 }
739743 fillHisto (candidate);
740744 if constexpr (fillMl) {
741- fillSparseML<false , false >(candidate, ptBhad, flagBHad, cent, occ, numPvContr);
745+ fillSparseML<false , false >(candidate, ptBhad, flagBHad, cent, occ, numPvContr, gapTypeInt );
742746 }
743747 }
744748 }
0 commit comments