1414// /
1515// / \author Gian Michele Innocenti <gian.michele.innocenti@cern.ch>, CERN
1616// / \author Vít Kučera <vit.kucera@cern.ch>, CERN
17+ // / \author Minjung Kim <minjung.kim@cern.ch>, CERN
1718
1819#include " PWGHF/Core/CentralityEstimation.h"
1920#include " PWGHF/Core/DecayChannels.h"
2425#include " PWGHF/DataModel/CandidateSelectionTables.h"
2526#include " PWGHF/DataModel/TrackIndexSkimmingTables.h"
2627#include " PWGHF/Utils/utilsEvSelHf.h"
28+ #include " PWGUD/Core/UPCHelpers.h"
2729
2830#include " Common/CCDB/ctpRateFetcher.h"
2931#include " Common/Core/RecoDecay.h"
@@ -58,6 +60,13 @@ using namespace o2::framework;
5860using namespace o2 ::framework::expressions;
5961using namespace o2 ::hf_centrality;
6062using namespace o2 ::hf_occupancy;
63+ using namespace o2 ::hf_evsel;
64+
65+ enum class GapType {
66+ GapA = 0 ,
67+ GapC = 1 ,
68+ DoubleGap = 2 ,
69+ };
6170
6271// / D0 analysis task
6372namespace
@@ -89,8 +98,12 @@ struct HfTaskD0 {
8998 // ML inference
9099 Configurable<bool > applyMl{" applyMl" , false , " Flag to apply ML selections" };
91100 Configurable<std::string> ccdbUrl{" ccdbUrl" , " http://alice-ccdb.cern.ch" , " url of the ccdb repository" };
101+ Configurable<std::string> ccdbPathGrp{" ccdbPathGrp" , " GLO/GRP/GRP" , " Path of the grp file (Run 2)" };
102+ Configurable<std::string> ccdbPathGrpMag{" ccdbPathGrpMag" , " GLO/Config/GRPMagField" , " CCDB path of the GRPMagField object (Run 3)" };
92103 Configurable<std::string> irSource{" irSource" , " ZNC hadronic" , " Estimator of the interaction rate (Recommended: pp --> T0VTX, Pb-Pb --> ZNC hadronic)" };
93104
105+ HfEventSelection hfEvSel; // event selection and monitoring
106+
94107 ctpRateFetcher mRateFetcher ;
95108
96109 SliceCache cache;
@@ -111,6 +124,8 @@ struct HfTaskD0 {
111124 using CollisionsWithMcLabels = soa::Join<aod::Collisions, aod::McCollisionLabels, aod::EvSels>;
112125 using CollisionsWithMcLabelsCent = soa::Join<aod::Collisions, aod::McCollisionLabels, aod::EvSels, aod::CentFT0Ms, aod::CentFT0Cs>;
113126 using TracksSelQuality = soa::Join<aod::TracksExtra, aod::TracksWMc>;
127+
128+ Preslice<aod::HfCand2Prong> candD0PerCollision = aod::hf_cand::collisionId;
114129 PresliceUnsorted<CollisionsWithMcLabels> colPerMcCollision = aod::mccollisionlabel::mcCollisionId;
115130 PresliceUnsorted<CollisionsWithMcLabelsCent> colPerMcCollisionCent = aod::mccollisionlabel::mcCollisionId;
116131
@@ -219,9 +234,11 @@ struct HfTaskD0 {
219234 {" hMassReflBkgD0bar" , " 2-prong candidates (matched);#it{m}_{inv} (GeV/#it{c}^{2}); #it{p}_{T}; #it{y}" , {HistType::kTH3F , {{120 , 1.5848 , 2.1848 }, {150 , 0 ., 30 .}, {20 , -5 ., 5 .}}}},
220235 {" hMassSigBkgD0bar" , " 2-prong candidates (not checked);#it{m}_{inv} (GeV/#it{c}^{2}); #it{p}_{T}; #it{y}" , {HistType::kTH3F , {{120 , 1.5848 , 2.1848 }, {150 , 0 ., 30 .}, {20 , -5 ., 5 .}}}}}};
221236
237+ HistogramRegistry qaRegistry{" QAHistos" , {}, OutputObjHandlingPolicy::AnalysisObject};
238+
222239 void init (InitContext&)
223240 {
224- std::array<bool , 12 > doprocess{doprocessDataWithDCAFitterN, doprocessDataWithDCAFitterNCent, doprocessDataWithKFParticle, doprocessMcWithDCAFitterN, doprocessMcWithDCAFitterNCent, doprocessMcWithKFParticle, doprocessDataWithDCAFitterNMl, doprocessDataWithDCAFitterNMlCent, doprocessDataWithKFParticleMl, doprocessMcWithDCAFitterNMl, doprocessMcWithDCAFitterNMlCent, doprocessMcWithKFParticleMl};
241+ std::array<bool , 13 > doprocess{doprocessDataWithDCAFitterN, doprocessDataWithDCAFitterNCent, doprocessDataWithKFParticle, doprocessMcWithDCAFitterN, doprocessMcWithDCAFitterNCent, doprocessMcWithKFParticle, doprocessDataWithDCAFitterNMl, doprocessDataWithDCAFitterNMlCent, doprocessDataWithKFParticleMl, doprocessMcWithDCAFitterNMl, doprocessMcWithDCAFitterNMlCent, doprocessMcWithKFParticleMl, doprocessDataWithDCAFitterNMlWithUpc };
225242 if ((std::accumulate (doprocess.begin (), doprocess.end (), 0 )) == 0 ) {
226243 LOGP (fatal, " At least one process function should be enabled at a time." );
227244 }
@@ -333,6 +350,15 @@ struct HfTaskD0 {
333350 registry.get <THnSparse>(HIST (" hMassVsPtVsPtBVsYVsOriginVsD0Type" ))->Sumw2 ();
334351 }
335352
353+ qaRegistry.add (" Data/fitInfo/ampFT0A_vs_ampFT0C" , " FT0-A vs FT0-C amplitude;FT0-A amplitude (a.u.);FT0-C amplitude (a.u.)" , {HistType::kTH2F , {{2500 , 0 ., 250 }, {2500 , 0 ., 250 }}});
354+ qaRegistry.add (" Data/zdc/energyZNA_vs_energyZNC" , " ZNA vs ZNC common energy;E_{ZNA}^{common} (a.u.);E_{ZNC}^{common} (a.u.)" , {HistType::kTH2F , {{200 , 0 ., 20 }, {200 , 0 ., 20 }}});
355+ qaRegistry.add (" Data/hUpcGapAfterSelection" , " UPC gap type after selection;Gap side;Counts" , {HistType::kTH1F , {{3 , -0.5 , 2.5 }}});
356+ qaRegistry.get <TH1>(HIST (" Data/hUpcGapAfterSelection" ))->GetXaxis ()->SetBinLabel (static_cast <int >(GapType::GapA) + 1 , " A" );
357+ qaRegistry.get <TH1>(HIST (" Data/hUpcGapAfterSelection" ))->GetXaxis ()->SetBinLabel (static_cast <int >(GapType::GapC) + 1 , " C" );
358+ qaRegistry.get <TH1>(HIST (" Data/hUpcGapAfterSelection" ))->GetXaxis ()->SetBinLabel (static_cast <int >(GapType::DoubleGap) + 1 , " Double" );
359+
360+ hfEvSel.addHistograms (qaRegistry);
361+
336362 ccdb->setURL (ccdbUrl);
337363 ccdb->setCaching (true );
338364 ccdb->setLocalObjectValidityChecking ();
@@ -517,6 +543,99 @@ struct HfTaskD0 {
517543 }
518544 }
519545 }
546+
547+ GapType determineGapType (float FT0A, float FT0C, float ZNA, float ZNC)
548+ {
549+ constexpr float FT0AThreshold = 100.0 ;
550+ constexpr float FT0CThreshold = 50.0 ;
551+ constexpr float ZDCThreshold = 1.0 ;
552+ if (FT0A < FT0AThreshold && FT0C > FT0CThreshold && ZNA < ZDCThreshold && ZNC > ZDCThreshold) {
553+ return GapType::GapA;
554+ }
555+ if (FT0A > FT0AThreshold && FT0C < FT0CThreshold && ZNA > ZDCThreshold && ZNC < ZDCThreshold) {
556+ return GapType::GapC;
557+ }
558+ return GapType::DoubleGap;
559+ }
560+
561+ template <bool fillMl, typename CollType, typename CandType, typename BCsType>
562+ void runAnalysisPerCollisionDataWithUpc (CollType const & collisions,
563+ CandType const & candidates,
564+ BCsType const & bcs,
565+ aod::FT0s const & ft0s,
566+ aod::FV0As const & fv0as,
567+ aod::FDDs const & fdds)
568+ {
569+ for (const auto & collision : collisions) {
570+ uint32_t rejectionMask{0 };
571+ float centrality{-1 .f };
572+ rejectionMask = hfEvSel.getHfCollisionRejectionMaskWithUpc <true , CentralityEstimator::None, BCsType>(collision, centrality, ccdb, qaRegistry, bcs);
573+ if (rejectionMask != 0 ) {
574+ continue ;
575+ }
576+ auto bc = collision.template bc_as <BCsType>();
577+ upchelpers::FITInfo fitInfo{};
578+ udhelpers::getFITinfo (fitInfo, bc, bcs, ft0s, fv0as, fdds);
579+
580+ GapType gap = GapType::DoubleGap;
581+ if (bc.has_zdc ()) {
582+ auto zdc = bc.zdc ();
583+ qaRegistry.fill (HIST (" Data/fitInfo/ampFT0A_vs_ampFT0C" ), fitInfo.ampFT0A , fitInfo.ampFT0C );
584+ qaRegistry.fill (HIST (" Data/zdc/energyZNA_vs_energyZNC" ), zdc.energyCommonZNA (), zdc.energyCommonZNC ());
585+ gap = determineGapType (fitInfo.ampFT0A , fitInfo.ampFT0C , zdc.energyCommonZNA (), zdc.energyCommonZNC ());
586+ qaRegistry.fill (HIST (" Data/hUpcGapAfterSelection" ), static_cast <int >(gap));
587+ }
588+ if (gap == GapType::GapA || gap == GapType::GapC) {
589+ const auto thisCollId = collision.globalIndex ();
590+ const auto & groupedD0Candidates = candidates.sliceBy (candD0PerCollision, thisCollId);
591+
592+ for (const auto & candidate : groupedD0Candidates) {
593+ if (!(candidate.hfflag () & 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) {
594+ continue ;
595+ }
596+ if (yCandRecoMax >= 0 . && std::abs (HfHelper::yD0 (candidate)) > yCandRecoMax) {
597+ continue ;
598+ }
599+
600+ float massD0 = HfHelper::invMassD0ToPiK (candidate);
601+ float massD0bar = HfHelper::invMassD0barToKPi (candidate);
602+ auto ptCandidate = candidate.pt ();
603+
604+ if (candidate.isSelD0 () >= selectionFlagD0) {
605+ registry.fill (HIST (" hMass" ), massD0, ptCandidate);
606+ registry.fill (HIST (" hMassFinerBinning" ), massD0, ptCandidate);
607+ registry.fill (HIST (" hMassVsPhi" ), massD0, ptCandidate, candidate.phi ());
608+ }
609+ if (candidate.isSelD0bar () >= selectionFlagD0bar) {
610+ registry.fill (HIST (" hMass" ), massD0bar, ptCandidate);
611+ registry.fill (HIST (" hMassFinerBinning" ), massD0bar, ptCandidate);
612+ registry.fill (HIST (" hMassVsPhi" ), massD0bar, ptCandidate, candidate.phi ());
613+ }
614+
615+ if constexpr (fillMl) {
616+ if (candidate.isSelD0 () >= selectionFlagD0) {
617+ registry.fill (HIST (" hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type" ), candidate.mlProbD0 ()[0 ], candidate.mlProbD0 ()[1 ], candidate.mlProbD0 ()[2 ], massD0, ptCandidate, HfHelper::yD0 (candidate), SigD0);
618+ registry.fill (HIST (" hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type" ), candidate.mlProbD0 ()[0 ], candidate.mlProbD0 ()[1 ], candidate.mlProbD0 ()[2 ], massD0, ptCandidate, HfHelper::yD0 (candidate), candidate.isSelD0bar () ? ReflectedD0 : PureSigD0);
619+ }
620+ if (candidate.isSelD0bar () >= selectionFlagD0bar) {
621+ registry.fill (HIST (" hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type" ), candidate.mlProbD0 ()[0 ], candidate.mlProbD0 ()[1 ], candidate.mlProbD0 ()[2 ], massD0bar, ptCandidate, HfHelper::yD0 (candidate), SigD0bar);
622+ registry.fill (HIST (" hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type" ), candidate.mlProbD0 ()[0 ], candidate.mlProbD0 ()[1 ], candidate.mlProbD0 ()[2 ], massD0bar, ptCandidate, HfHelper::yD0 (candidate), candidate.isSelD0 () ? ReflectedD0bar : PureSigD0bar);
623+ }
624+ } else {
625+ if (candidate.isSelD0 () >= selectionFlagD0) {
626+ registry.fill (HIST (" hMassVsPtVsPtBVsYVsOriginVsD0Type" ), massD0, ptCandidate, HfHelper::yD0 (candidate), SigD0);
627+ registry.fill (HIST (" hMassVsPtVsPtBVsYVsOriginVsD0Type" ), massD0, ptCandidate, HfHelper::yD0 (candidate), candidate.isSelD0bar () ? ReflectedD0 : PureSigD0);
628+ }
629+ if (candidate.isSelD0bar () >= selectionFlagD0bar) {
630+ registry.fill (HIST (" hMassVsPtVsPtBVsYVsOriginVsD0Type" ), massD0bar, ptCandidate, HfHelper::yD0 (candidate), SigD0bar);
631+ registry.fill (HIST (" hMassVsPtVsPtBVsYVsOriginVsD0Type" ), massD0bar, ptCandidate, HfHelper::yD0 (candidate), candidate.isSelD0 () ? ReflectedD0bar : PureSigD0bar);
632+ }
633+ }
634+ }
635+ }
636+ }
637+ }
638+
520639 void processDataWithDCAFitterN (D0Candidates const &, Collisions const & collisions, aod::TracksWExtra const & tracks, aod::BcFullInfos const & bcs)
521640 {
522641 processData<aod::hf_cand::VertexerType::DCAFitter, false >(selectedD0Candidates, collisions, tracks, bcs);
@@ -978,6 +1097,19 @@ struct HfTaskD0 {
9781097 }
9791098 PROCESS_SWITCH (HfTaskD0, processMcWithKFParticleMl, " Process MC with KFParticle and ML selections" , false );
9801099 // TODO: add the processMcWithKFParticleMlCent
1100+
1101+ void processDataWithDCAFitterNMlWithUpc (soa::Join<aod::Collisions, aod::EvSels> const & collisions,
1102+ aod::BcFullInfos const & bcs,
1103+ D0CandidatesMl const &,
1104+ aod::TracksWExtra const & tracks,
1105+ aod::FT0s const & ft0s,
1106+ aod::FV0As const & fv0as,
1107+ aod::FDDs const & fdds,
1108+ aod::Zdcs const & /* zdcs*/ )
1109+ {
1110+ runAnalysisPerCollisionDataWithUpc<true >(collisions, selectedD0CandidatesMl, bcs, ft0s, fv0as, fdds);
1111+ }
1112+ PROCESS_SWITCH (HfTaskD0, processDataWithDCAFitterNMlWithUpc, " Process real data with DCAFitterN and ML with UPC" , false );
9811113};
9821114
9831115WorkflowSpec defineDataProcessing (ConfigContext const & cfgc)
0 commit comments