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>
@@ -55,6 +57,13 @@ using namespace o2::framework;
5557using namespace o2 ::framework::expressions;
5658using namespace o2 ::hf_centrality;
5759using namespace o2 ::hf_occupancy;
60+ using namespace o2 ::hf_evsel;
61+
62+ enum class GapType {
63+ GapA = 0 ,
64+ GapC = 1 ,
65+ DoubleGap = 2 ,
66+ };
5867
5968// / Λc± → p± K∓ π± analysis task
6069struct HfTaskLc {
@@ -64,7 +73,7 @@ struct HfTaskLc {
6473 Configurable<std::vector<double >> binsPt{" binsPt" , std::vector<double >{hf_cuts_lc_to_p_k_pi::vecBinsPt}, " pT bin limits" };
6574 // ThnSparse for ML outputScores and Vars
6675 Configurable<bool > fillTHn{" fillTHn" , false , " fill THn" };
67- Configurable<bool > storeOccupancy{" storeOccupancy" , true , " Flag to store occupancy information" };
76+ Configurable<bool > storeOccupancy{" storeOccupancy" , false , " Flag to store occupancy information" };
6877 Configurable<int > occEstimator{" occEstimator" , 2 , " Occupancy estimation (None: 0, ITS: 1, FT0C: 2)" };
6978 Configurable<bool > storeProperLifetime{" storeProperLifetime" , false , " Flag to store proper lifetime" };
7079
@@ -77,6 +86,12 @@ struct HfTaskLc {
7786 MlClassNonPrompt,
7887 NumberOfMlClasses
7988 };
89+ Configurable<std::string> ccdbUrl{" ccdbUrl" , " http://alice-ccdb.cern.ch" , " url of the ccdb repository" };
90+ Configurable<std::string> ccdbPathGrp{" ccdbPathGrp" , " GLO/GRP/GRP" , " Path of the grp file (Run 2)" };
91+ Configurable<std::string> ccdbPathGrpMag{" ccdbPathGrpMag" , " GLO/Config/GRPMagField" , " CCDB path of the GRPMagField object (Run 3)" };
92+
93+ HfEventSelection hfEvSel; // event selection and monitoring
94+ Service<o2::ccdb::BasicCCDBManager> ccdb;
8095
8196 HfHelper hfHelper;
8297 SliceCache cache;
@@ -205,13 +220,14 @@ struct HfTaskLc {
205220 {" MC/generated/prompt/hPhiGenPrompt" , " MC particles (matched, prompt);#it{#Phi};entries" , {HistType::kTH1F , {{100 , 0 ., 6.3 }}}},
206221 {" MC/generated/nonprompt/hPhiGenNonPrompt" , " MC particles (matched, non-prompt);#it{#Phi};entries" , {HistType::kTH1F , {{100 , 0 ., 6.3 }}}}}};
207222
223+ HistogramRegistry qaRegistry{" QAHistos" , {}, OutputObjHandlingPolicy::AnalysisObject};
224+
208225 void init (InitContext&)
209226 {
210- std::array<bool , 12 > doprocess{doprocessDataStd, doprocessDataStdWithFT0C, doprocessDataStdWithFT0M, doprocessDataWithMl, doprocessDataWithMlWithFT0C, doprocessDataWithMlWithFT0M, doprocessMcStd, doprocessMcStdWithFT0C, doprocessMcStdWithFT0M, doprocessMcWithMl, doprocessMcWithMlWithFT0C, doprocessMcWithMlWithFT0M};
227+ std::array<bool , 13 > doprocess{doprocessDataStd, doprocessDataStdWithFT0C, doprocessDataStdWithFT0M, doprocessDataWithMl, doprocessDataWithMlWithFT0C, doprocessDataWithMlWithFT0M, doprocessMcStd, doprocessMcStdWithFT0C, doprocessMcStdWithFT0M, doprocessMcWithMl, doprocessMcWithMlWithFT0C, doprocessMcWithMlWithFT0M, doprocessDataWithMlWithUpc };
211228 if ((std::accumulate (doprocess.begin (), doprocess.end (), 0 )) != 1 ) {
212229 LOGP (fatal, " no or more than one process function enabled! Please check your configuration!" );
213230 }
214-
215231 auto vbins = (std::vector<double >)binsPt;
216232 // / mass candidate
217233 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 +328,12 @@ struct HfTaskLc {
312328 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})" }}});
313329 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})" }}});
314330
331+ 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 }}});
332+ 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 }}});
333+ qaRegistry.add (" Data/hUpcGapAfterSelection" , " UPC gap type after selection;Gap side;Counts" , {HistType::kTH1F , {{3 , -0.5 , 2.5 }}});
334+ qaRegistry.get <TH1>(HIST (" Data/hUpcGapAfterSelection" ))->GetXaxis ()->SetBinLabel (static_cast <int >(GapType::GapA) + 1 , " A" );
335+ qaRegistry.get <TH1>(HIST (" Data/hUpcGapAfterSelection" ))->GetXaxis ()->SetBinLabel (static_cast <int >(GapType::GapC) + 1 , " C" );
336+ qaRegistry.get <TH1>(HIST (" Data/hUpcGapAfterSelection" ))->GetXaxis ()->SetBinLabel (static_cast <int >(GapType::DoubleGap) + 1 , " Double" );
315337 if (fillTHn) {
316338 const AxisSpec thnAxisMass{thnConfigAxisMass, " inv. mass (p K #pi) (GeV/#it{c}^{2})" };
317339 const AxisSpec thnAxisPt{thnConfigAxisPt, " #it{p}_{T}(#Lambda_{c}^{+}) (GeV/#it{c})" };
@@ -332,7 +354,7 @@ struct HfTaskLc {
332354 const AxisSpec thnAxisOccupancy{thnConfigAxisOccupancy, " Occupancy" };
333355 const AxisSpec thnAxisProperLifetime{thnConfigAxisProperLifetime, " T_{proper} (ps)" };
334356
335- bool const isDataWithMl = doprocessDataWithMl || doprocessDataWithMlWithFT0C || doprocessDataWithMlWithFT0M;
357+ bool const isDataWithMl = doprocessDataWithMl || doprocessDataWithMlWithFT0C || doprocessDataWithMlWithFT0M || doprocessDataWithMlWithUpc ;
336358 bool const isMcWithMl = doprocessMcWithMl || doprocessMcWithMlWithFT0C || doprocessMcWithMlWithFT0M;
337359 bool const isDataStd = doprocessDataStd || doprocessDataStdWithFT0C || doprocessDataStdWithFT0M;
338360 bool const isMcStd = doprocessMcStd || doprocessMcStdWithFT0C || doprocessMcStdWithFT0M;
@@ -382,6 +404,12 @@ struct HfTaskLc {
382404 registry.add (" hnLcVarsGen" , " THn for Generated Lambdac" , HistType::kTHnSparseF , axesGen);
383405 }
384406 }
407+
408+ hfEvSel.addHistograms (qaRegistry); // collision monitoring
409+
410+ ccdb->setURL (ccdbUrl);
411+ ccdb->setCaching (true );
412+ ccdb->setLocalObjectValidityChecking ();
385413 }
386414
387415 // / Evaluate centrality/multiplicity percentile (centrality estimator is automatically selected based on the used table)
@@ -859,6 +887,60 @@ struct HfTaskLc {
859887 }
860888 }
861889
890+ template <bool fillMl, typename CollType, typename CandType, typename BCsType>
891+ void runAnalysisPerCollisionDataWithUpc (CollType const & collisions,
892+ CandType const & candidates,
893+ BCsType const & bcs,
894+ aod::FT0s const & ft0s,
895+ aod::FV0As const & fv0as,
896+ aod::FDDs const & fdds
897+
898+ )
899+ {
900+
901+ for (const auto & collision : collisions) {
902+
903+ uint32_t rejectionMask{0 }; // 32 bits, in case new ev. selections will be added
904+ float centrality{-1 .f };
905+ rejectionMask = hfEvSel.getHfCollisionRejectionMaskWithUpc <true , CentralityEstimator::None, BCsType>(collision, centrality, ccdb, qaRegistry, bcs);
906+ if (rejectionMask != 0 ) {
907+ // / at least one event selection not satisfied --> reject the candidate
908+ continue ;
909+ }
910+ auto bc = collision.template bc_as <BCsType>();
911+ upchelpers::FITInfo fitInfo{};
912+ udhelpers::getFITinfo (fitInfo, bc, bcs, ft0s, fv0as, fdds);
913+
914+ GapType gap = GapType::DoubleGap;
915+ if (bc.has_zdc ()) {
916+ auto zdc = bc.zdc ();
917+ qaRegistry.fill (HIST (" Data/fitInfo/ampFT0A_vs_ampFT0C" ), fitInfo.ampFT0A , fitInfo.ampFT0C );
918+ qaRegistry.fill (HIST (" Data/zdc/energyZNA_vs_energyZNC" ), zdc.energyCommonZNA (), zdc.energyCommonZNC ());
919+ gap = determineGapType (fitInfo.ampFT0A , fitInfo.ampFT0C , zdc.energyCommonZNA (), zdc.energyCommonZNC ());
920+ qaRegistry.fill (HIST (" Data/hUpcGapAfterSelection" ), static_cast <int >(gap));
921+ }
922+ if (gap == GapType::GapA || gap == GapType::GapC) {
923+ fillHistosData<fillMl>(collision, candidates);
924+ } else {
925+ continue ;
926+ }
927+ }
928+ }
929+
930+ GapType determineGapType (float FT0A, float FT0C, float ZNA, float ZNC)
931+ {
932+ constexpr float FT0AThreshold = 100.0 ;
933+ constexpr float FT0CThreshold = 50.0 ;
934+ constexpr float ZDCThreshold = 1.0 ;
935+ if (FT0A < FT0AThreshold && FT0C > FT0CThreshold && ZNA < ZDCThreshold && ZNC > ZDCThreshold) {
936+ return GapType::GapA;
937+ }
938+ if (FT0A > FT0AThreshold && FT0C < FT0CThreshold && ZNA > ZDCThreshold && ZNC < ZDCThreshold) {
939+ return GapType::GapC;
940+ }
941+ return GapType::DoubleGap;
942+ }
943+
862944 // / Run the analysis on MC data
863945 // / \tparam fillMl switch to fill ML histograms
864946 template <bool FillMl, typename CollType, typename CandType, typename CandLcMcGen>
@@ -880,7 +962,7 @@ struct HfTaskLc {
880962 {
881963 runAnalysisPerCollisionData<false >(collisions, selectedLcCandidates);
882964 }
883- PROCESS_SWITCH (HfTaskLc, processDataStd, " Process Data with the standard method" , true );
965+ PROCESS_SWITCH (HfTaskLc, processDataStd, " Process Data with the standard method" , false );
884966
885967 void processDataWithMl (Collisions const & collisions,
886968 LcCandidatesMl const & selectedLcCandidatesMl,
@@ -922,6 +1004,19 @@ struct HfTaskLc {
9221004 }
9231005 PROCESS_SWITCH (HfTaskLc, processDataWithMlWithFT0M, " Process real data with the ML method and with FT0M centrality" , false );
9241006
1007+ void processDataWithMlWithUpc (soa::Join<aod::Collisions, aod::EvSels> const & collisions,
1008+ aod::BcFullInfos const & bcs,
1009+ LcCandidatesMl const & selectedLcCandidatesMl,
1010+ aod::Tracks const &,
1011+ aod::FT0s const & ft0s,
1012+ aod::FV0As const & fv0as,
1013+ aod::FDDs const & fdds,
1014+ aod::Zdcs const & /* zdcs*/ )
1015+ {
1016+ runAnalysisPerCollisionDataWithUpc<true >(collisions, selectedLcCandidatesMl, bcs, ft0s, fv0as, fdds);
1017+ }
1018+ PROCESS_SWITCH (HfTaskLc, processDataWithMlWithUpc, " Process real data with the ML method with UPC" , true );
1019+
9251020 void processMcStd (CollisionsMc const & collisions,
9261021 LcCandidatesMc const & selectedLcCandidatesMc,
9271022 McParticles3ProngMatched const & mcParticles,
0 commit comments