1616// / \author Fabio Catalano <fabio.catalano@cern.ch>, Politecnico and INFN Torino
1717// / \author Vít Kučera <vit.kucera@cern.ch>, CERN
1818// / \author Luca Aglietta <luca.aglietta@cern.ch>, University and INFN Torino
19+ // / \author Minjung Kim <minjung.kim@cern.ch>, Inha University
1920
2021#include " PWGHF/Core/CentralityEstimation.h"
2122#include " PWGHF/Core/DecayChannels.h"
2627#include " PWGHF/DataModel/TrackIndexSkimmingTables.h"
2728#include " PWGHF/Utils/utilsAnalysis.h"
2829#include " PWGHF/Utils/utilsEvSelHf.h"
30+ #include " PWGUD/Core/UPCHelpers.h"
2931
3032#include " Common/Core/RecoDecay.h"
3133#include " Common/DataModel/Centrality.h"
3234#include " Common/DataModel/EventSelection.h"
3335
36+ #include < CCDB/BasicCCDBManager.h>
3437#include < CommonConstants/PhysicsConstants.h>
3538#include < Framework/ASoA.h>
3639#include < Framework/AnalysisDataModel.h>
5053#include < cstdint>
5154#include < cstdlib>
5255#include < numeric>
56+ #include < string>
5357#include < vector>
5458
5559using namespace o2 ;
@@ -58,6 +62,13 @@ using namespace o2::framework;
5862using namespace o2 ::framework::expressions;
5963using namespace o2 ::hf_centrality;
6064using namespace o2 ::hf_occupancy;
65+ using namespace o2 ::hf_evsel;
66+
67+ enum class GapType {
68+ GapA = 0 ,
69+ GapC = 1 ,
70+ DoubleGap = 2 ,
71+ };
6172
6273// / D± analysis task
6374struct HfTaskDplus {
@@ -73,6 +84,13 @@ struct HfTaskDplus {
7384 Configurable<bool > storeOccupancy{" storeOccupancy" , false , " Flag to store occupancy information" };
7485 Configurable<bool > storePvContributors{" storePvContributors" , false , " Flag to store number of PV contributors information" };
7586 Configurable<bool > fillMcBkgHistos{" fillMcBkgHistos" , false , " Flag to fill and store histograms for MC background" };
87+ Configurable<std::string> ccdbUrl{" ccdbUrl" , " http://alice-ccdb.cern.ch" , " url of the ccdb repository" };
88+ Configurable<std::string> ccdbPathGrp{" ccdbPathGrp" , " GLO/GRP/GRP" , " Path of the grp file (Run 2)" };
89+ Configurable<std::string> ccdbPathGrpMag{" ccdbPathGrpMag" , " GLO/Config/GRPMagField" , " CCDB path of the GRPMagField object (Run 3)" };
90+
91+ HfEventSelection hfEvSel; // event selection and monitoring
92+
93+ Service<o2::ccdb::BasicCCDBManager> ccdb;
7694
7795 using CandDplusData = soa::Filtered<soa::Join<aod::HfCand3Prong, aod::HfSelDplusToPiKPi>>;
7896 using CandDplusDataWithMl = soa::Filtered<soa::Join<aod::HfCand3Prong, aod::HfSelDplusToPiKPi, aod::HfMlDplusToPiKPi>>;
@@ -85,6 +103,7 @@ struct HfTaskDplus {
85103
86104 Filter filterDplusFlag = (o2::aod::hf_track_index::hfflag & static_cast <uint8_t >(BIT(aod::hf_cand_3prong::DecayType::DplusToPiKPi))) != static_cast <uint8_t >(0 );
87105
106+ Preslice<aod::HfCand3Prong> candDplusPerCollision = aod::hf_cand::collisionId;
88107 Preslice<aod::McParticles> mcParticlesPerMcCollision = aod::mcparticle::mcCollisionId;
89108 PresliceUnsorted<aod::McCollisionLabels> recoColPerMcCollision = aod::mccollisionlabel::mcCollisionId;
90109
@@ -122,9 +141,11 @@ struct HfTaskDplus {
122141 {" hEtaRecBg" , " 3-prong candidates (unmatched);#it{#eta};entries" , {HistType::kTH1F , {{100 , -2 ., 2 .}}}},
123142 {" hEtaGen" , " MC particles (matched);#it{#eta};entries" , {HistType::kTH1F , {{100 , -2 ., 2 .}}}}}};
124143
144+ HistogramRegistry qaRegistry{" QAHistos" , {}, OutputObjHandlingPolicy::AnalysisObject};
145+
125146 void init (InitContext&)
126147 {
127- std::array<bool , 4 > doprocess{doprocessData, doprocessDataWithMl, doprocessMc, doprocessMcWithMl};
148+ std::array<bool , 5 > doprocess{doprocessData, doprocessDataWithMl, doprocessMc, doprocessMcWithMl, doprocessDataWithMlWithUpc };
128149 if ((std::accumulate (doprocess.begin (), doprocess.end (), 0 )) != 1 ) {
129150 LOGP (fatal, " Only one process function should be enabled! Please check your configuration!" );
130151 }
@@ -239,6 +260,19 @@ struct HfTaskDplus {
239260 registry.add (" hSparseMassGenPrompt" , " THn for gen Prompt Dplus" , HistType::kTHnSparseF , axesGenPrompt);
240261 registry.add (" hSparseMassGenFD" , " THn for gen FD Dplus" , HistType::kTHnSparseF , axesGenFD);
241262 }
263+
264+ 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 }}});
265+ 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 }}});
266+ qaRegistry.add (" Data/hUpcGapAfterSelection" , " UPC gap type after selection;Gap side;Counts" , {HistType::kTH1F , {{3 , -0.5 , 2.5 }}});
267+ qaRegistry.get <TH1>(HIST (" Data/hUpcGapAfterSelection" ))->GetXaxis ()->SetBinLabel (static_cast <int >(GapType::GapA) + 1 , " A" );
268+ qaRegistry.get <TH1>(HIST (" Data/hUpcGapAfterSelection" ))->GetXaxis ()->SetBinLabel (static_cast <int >(GapType::GapC) + 1 , " C" );
269+ qaRegistry.get <TH1>(HIST (" Data/hUpcGapAfterSelection" ))->GetXaxis ()->SetBinLabel (static_cast <int >(GapType::DoubleGap) + 1 , " Double" );
270+
271+ hfEvSel.addHistograms (qaRegistry); // collision monitoring
272+
273+ ccdb->setURL (ccdbUrl);
274+ ccdb->setCaching (true );
275+ ccdb->setLocalObjectValidityChecking ();
242276 }
243277
244278 // Fill histograms of quantities for the reconstructed Dplus candidates
@@ -646,6 +680,71 @@ struct HfTaskDplus {
646680 }
647681 }
648682
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+
697+ template <bool fillMl, typename CollType, typename CandType, typename BCsType>
698+ void runAnalysisPerCollisionDataWithUpc (CollType const & collisions,
699+ CandType const & candidates,
700+ BCsType const & bcs,
701+ aod::FT0s const & ft0s,
702+ aod::FV0As const & fv0as,
703+ aod::FDDs const & fdds)
704+ {
705+ for (const auto & collision : collisions) {
706+ uint32_t rejectionMask{0 }; // 32 bits, in case new ev. selections will be added
707+ float centrality{-1 .f };
708+ rejectionMask = hfEvSel.getHfCollisionRejectionMaskWithUpc <true , CentralityEstimator::None, BCsType>(collision, centrality, ccdb, qaRegistry, bcs);
709+ if (rejectionMask != 0 ) {
710+ // / at least one event selection not satisfied --> reject the candidate
711+ continue ;
712+ }
713+ auto bc = collision.template bc_as <BCsType>();
714+ upchelpers::FITInfo fitInfo{};
715+ udhelpers::getFITinfo (fitInfo, bc, bcs, ft0s, fv0as, fdds);
716+
717+ GapType gap = GapType::DoubleGap;
718+ if (bc.has_zdc ()) {
719+ auto zdc = bc.zdc ();
720+ qaRegistry.fill (HIST (" Data/fitInfo/ampFT0A_vs_ampFT0C" ), fitInfo.ampFT0A , fitInfo.ampFT0C );
721+ 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));
724+ }
725+ if (gap == GapType::GapA || gap == GapType::GapC) {
726+ // Use the candidates from this collision
727+ const auto thisCollId = collision.globalIndex ();
728+ const auto & groupedDplusCandidates = candidates.sliceBy (candDplusPerCollision, thisCollId);
729+ float cent{-1 .f };
730+ float occ{-1 .f };
731+ float numPvContr{-1 .f };
732+ float ptBhad{-1 .f };
733+ int const flagBHad{-1 };
734+
735+ for (const auto & candidate : groupedDplusCandidates) {
736+ if ((yCandRecoMax >= 0 . && std::abs (HfHelper::yDplus (candidate)) > yCandRecoMax)) {
737+ continue ;
738+ }
739+ fillHisto (candidate);
740+ if constexpr (fillMl) {
741+ fillSparseML<false , false >(candidate, ptBhad, flagBHad, cent, occ, numPvContr);
742+ }
743+ }
744+ }
745+ }
746+ }
747+
649748 // process functions
650749 void processData (CandDplusData const & candidates, CollisionsCent const & collisions)
651750 {
@@ -678,6 +777,19 @@ struct HfTaskDplus {
678777 runAnalysisMcGen<true >(mcGenCollisions, mcRecoCollisions, mcGenParticles);
679778 }
680779 PROCESS_SWITCH (HfTaskDplus, processMcWithMl, " Process MC with ML" , false );
780+
781+ void processDataWithMlWithUpc (soa::Join<aod::Collisions, aod::EvSels> const & collisions,
782+ aod::BcFullInfos const & bcs,
783+ CandDplusDataWithMl const & selectedDplusCandidatesMl,
784+ aod::Tracks const &,
785+ aod::FT0s const & ft0s,
786+ aod::FV0As const & fv0as,
787+ aod::FDDs const & fdds,
788+ aod::Zdcs const & /* zdcs*/ )
789+ {
790+ runAnalysisPerCollisionDataWithUpc<true >(collisions, selectedDplusCandidatesMl, bcs, ft0s, fv0as, fdds);
791+ }
792+ PROCESS_SWITCH (HfTaskDplus, processDataWithMlWithUpc, " Process real data with the ML method with UPC" , false );
681793};
682794
683795WorkflowSpec defineDataProcessing (ConfigContext const & cfgc)
0 commit comments