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"
2223#include " PWGHF/DataModel/CandidateReconstructionTables.h"
2324#include " PWGHF/DataModel/CandidateSelectionTables.h"
2425#include " PWGHF/Utils/utilsEvSelHf.h"
26+ #include " PWGUD/Core/UPCHelpers.h"
2527
2628#include " Common/CCDB/ctpRateFetcher.h"
2729#include " Common/Core/RecoDecay.h"
@@ -56,6 +58,13 @@ using namespace o2::framework;
5658using namespace o2 ::framework::expressions;
5759using namespace o2 ::hf_centrality;
5860using namespace o2 ::hf_occupancy;
61+ using namespace o2 ::hf_evsel;
62+
63+ enum class GapType {
64+ GapA = 0 ,
65+ GapC = 1 ,
66+ DoubleGap = 2 ,
67+ };
5968
6069// / D0 analysis task
6170namespace
@@ -87,8 +96,12 @@ struct HfTaskD0 {
8796 // ML inference
8897 Configurable<bool > applyMl{" applyMl" , false , " Flag to apply ML selections" };
8998 Configurable<std::string> ccdbUrl{" ccdbUrl" , " http://alice-ccdb.cern.ch" , " url of the ccdb repository" };
99+ Configurable<std::string> ccdbPathGrp{" ccdbPathGrp" , " GLO/GRP/GRP" , " Path of the grp file (Run 2)" };
100+ Configurable<std::string> ccdbPathGrpMag{" ccdbPathGrpMag" , " GLO/Config/GRPMagField" , " CCDB path of the GRPMagField object (Run 3)" };
90101 Configurable<std::string> irSource{" irSource" , " ZNC hadronic" , " Estimator of the interaction rate (Recommended: pp --> T0VTX, Pb-Pb --> ZNC hadronic)" };
91102
103+ HfEventSelection hfEvSel; // event selection and monitoring
104+
92105 HfHelper hfHelper;
93106 ctpRateFetcher mRateFetcher ;
94107
@@ -110,6 +123,8 @@ struct HfTaskD0 {
110123 using CollisionsWithMcLabels = soa::Join<aod::Collisions, aod::McCollisionLabels, aod::EvSels>;
111124 using CollisionsWithMcLabelsCent = soa::Join<aod::Collisions, aod::McCollisionLabels, aod::EvSels, aod::CentFT0Ms, aod::CentFT0Cs>;
112125 using TracksSelQuality = soa::Join<aod::TracksExtra, aod::TracksWMc>;
126+
127+ Preslice<aod::HfCand2Prong> candD0PerCollision = aod::hf_cand::collisionId;
113128 PresliceUnsorted<CollisionsWithMcLabels> colPerMcCollision = aod::mccollisionlabel::mcCollisionId;
114129 PresliceUnsorted<CollisionsWithMcLabelsCent> colPerMcCollisionCent = aod::mccollisionlabel::mcCollisionId;
115130
@@ -218,9 +233,11 @@ struct HfTaskD0 {
218233 {" 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 .}}}},
219234 {" 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 .}}}}}};
220235
236+ HistogramRegistry qaRegistry{" QAHistos" , {}, OutputObjHandlingPolicy::AnalysisObject};
237+
221238 void init (InitContext&)
222239 {
223- std::array<bool , 12 > doprocess{doprocessDataWithDCAFitterN, doprocessDataWithDCAFitterNCent, doprocessDataWithKFParticle, doprocessMcWithDCAFitterN, doprocessMcWithDCAFitterNCent, doprocessMcWithKFParticle, doprocessDataWithDCAFitterNMl, doprocessDataWithDCAFitterNMlCent, doprocessDataWithKFParticleMl, doprocessMcWithDCAFitterNMl, doprocessMcWithDCAFitterNMlCent, doprocessMcWithKFParticleMl};
240+ std::array<bool , 13 > doprocess{doprocessDataWithDCAFitterN, doprocessDataWithDCAFitterNCent, doprocessDataWithKFParticle, doprocessMcWithDCAFitterN, doprocessMcWithDCAFitterNCent, doprocessMcWithKFParticle, doprocessDataWithDCAFitterNMl, doprocessDataWithDCAFitterNMlCent, doprocessDataWithKFParticleMl, doprocessMcWithDCAFitterNMl, doprocessMcWithDCAFitterNMlCent, doprocessMcWithKFParticleMl, doprocessDataWithDCAFitterNMlWithUpc };
224241 if ((std::accumulate (doprocess.begin (), doprocess.end (), 0 )) == 0 ) {
225242 LOGP (fatal, " At least one process function should be enabled at a time." );
226243 }
@@ -332,6 +349,15 @@ struct HfTaskD0 {
332349 registry.get <THnSparse>(HIST (" hMassVsPtVsPtBVsYVsOriginVsD0Type" ))->Sumw2 ();
333350 }
334351
352+ 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 }}});
353+ 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 }}});
354+ qaRegistry.add (" Data/hUpcGapAfterSelection" , " UPC gap type after selection;Gap side;Counts" , {HistType::kTH1F , {{3 , -0.5 , 2.5 }}});
355+ qaRegistry.get <TH1>(HIST (" Data/hUpcGapAfterSelection" ))->GetXaxis ()->SetBinLabel (static_cast <int >(GapType::GapA) + 1 , " A" );
356+ qaRegistry.get <TH1>(HIST (" Data/hUpcGapAfterSelection" ))->GetXaxis ()->SetBinLabel (static_cast <int >(GapType::GapC) + 1 , " C" );
357+ qaRegistry.get <TH1>(HIST (" Data/hUpcGapAfterSelection" ))->GetXaxis ()->SetBinLabel (static_cast <int >(GapType::DoubleGap) + 1 , " Double" );
358+
359+ hfEvSel.addHistograms (qaRegistry);
360+
335361 ccdb->setURL (ccdbUrl);
336362 ccdb->setCaching (true );
337363 ccdb->setLocalObjectValidityChecking ();
@@ -516,6 +542,99 @@ struct HfTaskD0 {
516542 }
517543 }
518544 }
545+
546+ GapType determineGapType (float FT0A, float FT0C, float ZNA, float ZNC)
547+ {
548+ constexpr float FT0AThreshold = 100.0 ;
549+ constexpr float FT0CThreshold = 50.0 ;
550+ constexpr float ZDCThreshold = 1.0 ;
551+ if (FT0A < FT0AThreshold && FT0C > FT0CThreshold && ZNA < ZDCThreshold && ZNC > ZDCThreshold) {
552+ return GapType::GapA;
553+ }
554+ if (FT0A > FT0AThreshold && FT0C < FT0CThreshold && ZNA > ZDCThreshold && ZNC < ZDCThreshold) {
555+ return GapType::GapC;
556+ }
557+ return GapType::DoubleGap;
558+ }
559+
560+ template <bool fillMl, typename CollType, typename CandType, typename BCsType>
561+ void runAnalysisPerCollisionDataWithUpc (CollType const & collisions,
562+ CandType const & candidates,
563+ BCsType const & bcs,
564+ aod::FT0s const & ft0s,
565+ aod::FV0As const & fv0as,
566+ aod::FDDs const & fdds)
567+ {
568+ for (const auto & collision : collisions) {
569+ uint32_t rejectionMask{0 };
570+ float centrality{-1 .f };
571+ rejectionMask = hfEvSel.getHfCollisionRejectionMaskWithUpc <true , CentralityEstimator::None, BCsType>(collision, centrality, ccdb, qaRegistry, bcs);
572+ if (rejectionMask != 0 ) {
573+ continue ;
574+ }
575+ auto bc = collision.template bc_as <BCsType>();
576+ upchelpers::FITInfo fitInfo{};
577+ udhelpers::getFITinfo (fitInfo, bc, bcs, ft0s, fv0as, fdds);
578+
579+ GapType gap = GapType::DoubleGap;
580+ if (bc.has_zdc ()) {
581+ auto zdc = bc.zdc ();
582+ qaRegistry.fill (HIST (" Data/fitInfo/ampFT0A_vs_ampFT0C" ), fitInfo.ampFT0A , fitInfo.ampFT0C );
583+ qaRegistry.fill (HIST (" Data/zdc/energyZNA_vs_energyZNC" ), zdc.energyCommonZNA (), zdc.energyCommonZNC ());
584+ gap = determineGapType (fitInfo.ampFT0A , fitInfo.ampFT0C , zdc.energyCommonZNA (), zdc.energyCommonZNC ());
585+ qaRegistry.fill (HIST (" Data/hUpcGapAfterSelection" ), static_cast <int >(gap));
586+ }
587+ if (gap == GapType::GapA || gap == GapType::GapC) {
588+ const auto thisCollId = collision.globalIndex ();
589+ const auto & groupedD0Candidates = candidates.sliceBy (candD0PerCollision, thisCollId);
590+
591+ for (const auto & candidate : groupedD0Candidates) {
592+ if (!(candidate.hfflag () & 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) {
593+ continue ;
594+ }
595+ if (yCandRecoMax >= 0 . && std::abs (hfHelper.yD0 (candidate)) > yCandRecoMax) {
596+ continue ;
597+ }
598+
599+ float massD0 = hfHelper.invMassD0ToPiK (candidate);
600+ float massD0bar = hfHelper.invMassD0barToKPi (candidate);
601+ auto ptCandidate = candidate.pt ();
602+
603+ if (candidate.isSelD0 () >= selectionFlagD0) {
604+ registry.fill (HIST (" hMass" ), massD0, ptCandidate);
605+ registry.fill (HIST (" hMassFinerBinning" ), massD0, ptCandidate);
606+ registry.fill (HIST (" hMassVsPhi" ), massD0, ptCandidate, candidate.phi ());
607+ }
608+ if (candidate.isSelD0bar () >= selectionFlagD0bar) {
609+ registry.fill (HIST (" hMass" ), massD0bar, ptCandidate);
610+ registry.fill (HIST (" hMassFinerBinning" ), massD0bar, ptCandidate);
611+ registry.fill (HIST (" hMassVsPhi" ), massD0bar, ptCandidate, candidate.phi ());
612+ }
613+
614+ if constexpr (fillMl) {
615+ if (candidate.isSelD0 () >= selectionFlagD0) {
616+ registry.fill (HIST (" hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type" ), candidate.mlProbD0 ()[0 ], candidate.mlProbD0 ()[1 ], candidate.mlProbD0 ()[2 ], massD0, ptCandidate, hfHelper.yD0 (candidate), SigD0);
617+ registry.fill (HIST (" hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type" ), candidate.mlProbD0 ()[0 ], candidate.mlProbD0 ()[1 ], candidate.mlProbD0 ()[2 ], massD0, ptCandidate, hfHelper.yD0 (candidate), candidate.isSelD0bar () ? ReflectedD0 : PureSigD0);
618+ }
619+ if (candidate.isSelD0bar () >= selectionFlagD0bar) {
620+ registry.fill (HIST (" hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type" ), candidate.mlProbD0 ()[0 ], candidate.mlProbD0 ()[1 ], candidate.mlProbD0 ()[2 ], massD0bar, ptCandidate, hfHelper.yD0 (candidate), SigD0bar);
621+ registry.fill (HIST (" hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type" ), candidate.mlProbD0 ()[0 ], candidate.mlProbD0 ()[1 ], candidate.mlProbD0 ()[2 ], massD0bar, ptCandidate, hfHelper.yD0 (candidate), candidate.isSelD0 () ? ReflectedD0bar : PureSigD0bar);
622+ }
623+ } else {
624+ if (candidate.isSelD0 () >= selectionFlagD0) {
625+ registry.fill (HIST (" hMassVsPtVsPtBVsYVsOriginVsD0Type" ), massD0, ptCandidate, hfHelper.yD0 (candidate), SigD0);
626+ registry.fill (HIST (" hMassVsPtVsPtBVsYVsOriginVsD0Type" ), massD0, ptCandidate, hfHelper.yD0 (candidate), candidate.isSelD0bar () ? ReflectedD0 : PureSigD0);
627+ }
628+ if (candidate.isSelD0bar () >= selectionFlagD0bar) {
629+ registry.fill (HIST (" hMassVsPtVsPtBVsYVsOriginVsD0Type" ), massD0bar, ptCandidate, hfHelper.yD0 (candidate), SigD0bar);
630+ registry.fill (HIST (" hMassVsPtVsPtBVsYVsOriginVsD0Type" ), massD0bar, ptCandidate, hfHelper.yD0 (candidate), candidate.isSelD0 () ? ReflectedD0bar : PureSigD0bar);
631+ }
632+ }
633+ }
634+ }
635+ }
636+ }
637+
519638 void processDataWithDCAFitterN (D0Candidates const &, Collisions const & collisions, aod::TracksWExtra const & tracks, aod::BcFullInfos const & bcs)
520639 {
521640 processData<aod::hf_cand::VertexerType::DCAFitter, false >(selectedD0Candidates, collisions, tracks, bcs);
@@ -977,6 +1096,19 @@ struct HfTaskD0 {
9771096 }
9781097 PROCESS_SWITCH (HfTaskD0, processMcWithKFParticleMl, " Process MC with KFParticle and ML selections" , false );
9791098 // TODO: add the processMcWithKFParticleMlCent
1099+
1100+ void processDataWithDCAFitterNMlWithUpc (soa::Join<aod::Collisions, aod::EvSels> const & collisions,
1101+ aod::BcFullInfos const & bcs,
1102+ D0CandidatesMl const &,
1103+ aod::TracksWExtra const & tracks,
1104+ aod::FT0s const & ft0s,
1105+ aod::FV0As const & fv0as,
1106+ aod::FDDs const & fdds,
1107+ aod::Zdcs const & /* zdcs*/ )
1108+ {
1109+ runAnalysisPerCollisionDataWithUpc<true >(collisions, selectedD0CandidatesMl, bcs, ft0s, fv0as, fdds);
1110+ }
1111+ PROCESS_SWITCH (HfTaskD0, processDataWithDCAFitterNMlWithUpc, " Process real data with DCAFitterN and ML with UPC" , false );
9801112};
9811113
9821114WorkflowSpec defineDataProcessing (ConfigContext const & cfgc)
0 commit comments