1717// / \author Vít Kučera <vit.kucera@cern.ch>, CERN
1818// / \author Annalena Kalteyer <annalena.sophie.kalteyer@cern.ch>, GSI Darmstadt
1919// / \author Biao Zhang <biao.zhang@cern.ch>, Heidelberg University
20+ // / \author Ran Tu <ran.tu@cern.ch>, Fudan University
2021
2122#include " PWGHF/Core/CentralityEstimation.h"
2223#include " PWGHF/Core/DecayChannels.h"
3031#include " Common/DataModel/Centrality.h"
3132#include " Common/DataModel/EventSelection.h"
3233
34+ #include < CCDB/BasicCCDBManager.h>
3335#include < CommonConstants/PhysicsConstants.h>
3436#include < Framework/ASoA.h>
3537#include < Framework/AnalysisDataModel.h>
4749#include < array>
4850#include < cmath>
4951#include < numeric>
52+ #include < string>
5053#include < vector> // std::vector
5154
5255using namespace o2 ;
@@ -55,6 +58,13 @@ using namespace o2::framework;
5558using namespace o2 ::framework::expressions;
5659using namespace o2 ::hf_centrality;
5760using 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+ };
5868
5969// / Λc± → p± K∓ π± analysis task
6070struct HfTaskLc {
@@ -77,9 +87,15 @@ struct HfTaskLc {
7787 MlClassNonPrompt,
7888 NumberOfMlClasses
7989 };
90+ Configurable<std::string> ccdbUrl{" ccdbUrl" , " http://alice-ccdb.cern.ch" , " url of the ccdb repository" };
91+ Configurable<std::string> ccdbPathGrp{" ccdbPathGrp" , " GLO/GRP/GRP" , " Path of the grp file (Run 2)" };
92+ Configurable<std::string> ccdbPathGrpMag{" ccdbPathGrpMag" , " GLO/Config/GRPMagField" , " CCDB path of the GRPMagField object (Run 3)" };
93+
94+ HfEventSelection hfEvSel; // event selection and monitoring
8095
8196 HfHelper hfHelper;
8297 SliceCache cache;
98+ Service<o2::ccdb::BasicCCDBManager> ccdb;
8399
84100 using Collisions = soa::Join<aod::Collisions, aod::EvSels>;
85101 using CollisionsMc = soa::Join<aod::Collisions, aod::McCollisionLabels, aod::EvSels>;
@@ -205,13 +221,14 @@ struct HfTaskLc {
205221 {" MC/generated/prompt/hPhiGenPrompt" , " MC particles (matched, prompt);#it{#Phi};entries" , {HistType::kTH1F , {{100 , 0 ., 6.3 }}}},
206222 {" MC/generated/nonprompt/hPhiGenNonPrompt" , " MC particles (matched, non-prompt);#it{#Phi};entries" , {HistType::kTH1F , {{100 , 0 ., 6.3 }}}}}};
207223
224+ HistogramRegistry qaRegistry{" QAHistos" , {}, OutputObjHandlingPolicy::AnalysisObject};
225+
208226 void init (InitContext&)
209227 {
210- std::array<bool , 12 > doprocess{doprocessDataStd, doprocessDataStdWithFT0C, doprocessDataStdWithFT0M, doprocessDataWithMl, doprocessDataWithMlWithFT0C, doprocessDataWithMlWithFT0M, doprocessMcStd, doprocessMcStdWithFT0C, doprocessMcStdWithFT0M, doprocessMcWithMl, doprocessMcWithMlWithFT0C, doprocessMcWithMlWithFT0M};
228+ std::array<bool , 13 > doprocess{doprocessDataStd, doprocessDataStdWithFT0C, doprocessDataStdWithFT0M, doprocessDataWithMl, doprocessDataWithMlWithFT0C, doprocessDataWithMlWithFT0M, doprocessMcStd, doprocessMcStdWithFT0C, doprocessMcStdWithFT0M, doprocessMcWithMl, doprocessMcWithMlWithFT0C, doprocessMcWithMlWithFT0M, doprocessDataWithMlWithUpc };
211229 if ((std::accumulate (doprocess.begin (), doprocess.end (), 0 )) != 1 ) {
212230 LOGP (fatal, " no or more than one process function enabled! Please check your configuration!" );
213231 }
214-
215232 auto vbins = (std::vector<double >)binsPt;
216233 // / mass candidate
217234 registry.add (" Data/hMassVsPtVsNPvContributors" , " 3-prong candidates;inv. mass (p K #pi) (GeV/#it{c}^{2}); p_{T}; Number of PV contributors" , {HistType::kTH3F , {{600 , 1.98 , 2.58 }, {vbins, " #it{p}_{T} (GeV/#it{c})" }, {5000 , 0 ., 10000 .}}});
@@ -312,6 +329,12 @@ struct HfTaskLc {
312329 registry.add (" MC/reconstructed/prompt/hDecLenErrSigPrompt" , " 3-prong candidates (matched, prompt);decay length error (cm);entries" , {HistType::kTH2F , {{100 , 0 ., 1 .}, {vbins, " #it{p}_{T} (GeV/#it{c})" }}});
313330 registry.add (" MC/reconstructed/nonprompt/hDecLenErrSigNonPrompt" , " 3-prong candidates (matched, non-prompt);decay length error (cm);entries" , {HistType::kTH2F , {{100 , 0 ., 1 .}, {vbins, " #it{p}_{T} (GeV/#it{c})" }}});
314331
332+ 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 }}});
333+ 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 }}});
334+ qaRegistry.add (" Data/hUpcGapAfterSelection" , " UPC gap type after selection;Gap side;Counts" , {HistType::kTH1F , {{3 , -0.5 , 2.5 }}});
335+ qaRegistry.get <TH1>(HIST (" Data/hUpcGapAfterSelection" ))->GetXaxis ()->SetBinLabel (static_cast <int >(GapType::GapA) + 1 , " A" );
336+ qaRegistry.get <TH1>(HIST (" Data/hUpcGapAfterSelection" ))->GetXaxis ()->SetBinLabel (static_cast <int >(GapType::GapC) + 1 , " C" );
337+ qaRegistry.get <TH1>(HIST (" Data/hUpcGapAfterSelection" ))->GetXaxis ()->SetBinLabel (static_cast <int >(GapType::DoubleGap) + 1 , " Double" );
315338 if (fillTHn) {
316339 const AxisSpec thnAxisMass{thnConfigAxisMass, " inv. mass (p K #pi) (GeV/#it{c}^{2})" };
317340 const AxisSpec thnAxisPt{thnConfigAxisPt, " #it{p}_{T}(#Lambda_{c}^{+}) (GeV/#it{c})" };
@@ -332,7 +355,7 @@ struct HfTaskLc {
332355 const AxisSpec thnAxisOccupancy{thnConfigAxisOccupancy, " Occupancy" };
333356 const AxisSpec thnAxisProperLifetime{thnConfigAxisProperLifetime, " T_{proper} (ps)" };
334357
335- bool const isDataWithMl = doprocessDataWithMl || doprocessDataWithMlWithFT0C || doprocessDataWithMlWithFT0M;
358+ bool const isDataWithMl = doprocessDataWithMl || doprocessDataWithMlWithFT0C || doprocessDataWithMlWithFT0M || doprocessDataWithMlWithUpc ;
336359 bool const isMcWithMl = doprocessMcWithMl || doprocessMcWithMlWithFT0C || doprocessMcWithMlWithFT0M;
337360 bool const isDataStd = doprocessDataStd || doprocessDataStdWithFT0C || doprocessDataStdWithFT0M;
338361 bool const isMcStd = doprocessMcStd || doprocessMcStdWithFT0C || doprocessMcStdWithFT0M;
@@ -382,6 +405,12 @@ struct HfTaskLc {
382405 registry.add (" hnLcVarsGen" , " THn for Generated Lambdac" , HistType::kTHnSparseF , axesGen);
383406 }
384407 }
408+
409+ hfEvSel.addHistograms (qaRegistry); // collision monitoring
410+
411+ ccdb->setURL (ccdbUrl);
412+ ccdb->setCaching (true );
413+ ccdb->setLocalObjectValidityChecking ();
385414 }
386415
387416 // / Evaluate centrality/multiplicity percentile (centrality estimator is automatically selected based on the used table)
@@ -859,6 +888,60 @@ struct HfTaskLc {
859888 }
860889 }
861890
891+ template <bool fillMl, typename CollType, typename CandType, typename BCsType>
892+ void runAnalysisPerCollisionDataWithUpc (CollType const & collisions,
893+ CandType const & candidates,
894+ BCsType const & bcs,
895+ aod::FT0s const & ft0s,
896+ aod::FV0As const & fv0as,
897+ aod::FDDs const & fdds
898+
899+ )
900+ {
901+
902+ for (const auto & collision : collisions) {
903+
904+ uint32_t rejectionMask{0 }; // 32 bits, in case new ev. selections will be added
905+ float centrality{-1 .f };
906+ rejectionMask = hfEvSel.getHfCollisionRejectionMaskWithUpc <true , CentralityEstimator::None, BCsType>(collision, centrality, ccdb, qaRegistry, bcs);
907+ if (rejectionMask != 0 ) {
908+ // / at least one event selection not satisfied --> reject the candidate
909+ continue ;
910+ }
911+ auto bc = collision.template bc_as <BCsType>();
912+ upchelpers::FITInfo fitInfo{};
913+ udhelpers::getFITinfo (fitInfo, bc, bcs, ft0s, fv0as, fdds);
914+
915+ GapType gap = GapType::DoubleGap;
916+ if (bc.has_zdc ()) {
917+ auto zdc = bc.zdc ();
918+ qaRegistry.fill (HIST (" Data/fitInfo/ampFT0A_vs_ampFT0C" ), fitInfo.ampFT0A , fitInfo.ampFT0C );
919+ qaRegistry.fill (HIST (" Data/zdc/energyZNA_vs_energyZNC" ), zdc.energyCommonZNA (), zdc.energyCommonZNC ());
920+ gap = determineGapType (fitInfo.ampFT0A , fitInfo.ampFT0C , zdc.energyCommonZNA (), zdc.energyCommonZNC ());
921+ qaRegistry.fill (HIST (" Data/hUpcGapAfterSelection" ), static_cast <int >(gap));
922+ }
923+ if (gap == GapType::GapA || gap == GapType::GapC) {
924+ fillHistosData<fillMl>(collision, candidates);
925+ } else {
926+ continue ;
927+ }
928+ }
929+ }
930+
931+ GapType determineGapType (float FT0A, float FT0C, float ZNA, float ZNC)
932+ {
933+ constexpr float FT0AThreshold = 100.0 ;
934+ constexpr float FT0CThreshold = 50.0 ;
935+ constexpr float ZDCThreshold = 1.0 ;
936+ if (FT0A < FT0AThreshold && FT0C > FT0CThreshold && ZNA < ZDCThreshold && ZNC > ZDCThreshold) {
937+ return GapType::GapA;
938+ }
939+ if (FT0A > FT0AThreshold && FT0C < FT0CThreshold && ZNA > ZDCThreshold && ZNC < ZDCThreshold) {
940+ return GapType::GapC;
941+ }
942+ return GapType::DoubleGap;
943+ }
944+
862945 // / Run the analysis on MC data
863946 // / \tparam fillMl switch to fill ML histograms
864947 template <bool FillMl, typename CollType, typename CandType, typename CandLcMcGen>
@@ -922,6 +1005,19 @@ struct HfTaskLc {
9221005 }
9231006 PROCESS_SWITCH (HfTaskLc, processDataWithMlWithFT0M, " Process real data with the ML method and with FT0M centrality" , false );
9241007
1008+ void processDataWithMlWithUpc (soa::Join<aod::Collisions, aod::EvSels> const & collisions,
1009+ aod::BcFullInfos const & bcs,
1010+ LcCandidatesMl const & selectedLcCandidatesMl,
1011+ aod::Tracks const &,
1012+ aod::FT0s const & ft0s,
1013+ aod::FV0As const & fv0as,
1014+ aod::FDDs const & fdds,
1015+ aod::Zdcs const & /* zdcs*/ )
1016+ {
1017+ runAnalysisPerCollisionDataWithUpc<true >(collisions, selectedLcCandidatesMl, bcs, ft0s, fv0as, fdds);
1018+ }
1019+ PROCESS_SWITCH (HfTaskLc, processDataWithMlWithUpc, " Process real data with the ML method with UPC" , false );
1020+
9251021 void processMcStd (CollisionsMc const & collisions,
9261022 LcCandidatesMc const & selectedLcCandidatesMc,
9271023 McParticles3ProngMatched const & mcParticles,
0 commit comments