2929#include " PWGHF/Core/CentralityEstimation.h"
3030#include " PWGHF/DataModel/CandidateReconstructionTables.h"
3131#include " PWGHF/DataModel/CandidateSelectionTables.h"
32+ #include " PWGHF/Utils/utilsEvSelHf.h"
3233
3334using namespace o2 ;
3435using namespace o2 ::analysis;
3536using namespace o2 ::framework;
3637using namespace o2 ::framework::expressions;
38+ using namespace o2 ::hf_centrality;
39+ using namespace o2 ::hf_occupancy;
3740
3841// / Λc± → p± K∓ π± analysis task
3942struct HfTaskLc {
@@ -43,21 +46,11 @@ struct HfTaskLc {
4346 Configurable<std::vector<double >> binsPt{" binsPt" , std::vector<double >{hf_cuts_lc_to_p_k_pi::vecBinsPt}, " pT bin limits" };
4447 // ThnSparse for ML outputScores and Vars
4548 Configurable<bool > fillTHn{" fillTHn" , false , " fill THn" };
46- ConfigurableAxis thnConfigAxisPt{" thnConfigAxisPt" , {72 , 0 , 36 }, " " };
47- ConfigurableAxis thnConfigAxisMass{" thnConfigAxisMass" , {300 , 1.98 , 2.58 }, " " };
48- ConfigurableAxis thnConfigAxisPtProng{" thnConfigAxisPtProng" , {100 , 0 , 20 }, " " };
49- ConfigurableAxis thnConfigAxisCentrality{" thnConfigAxisCentrality" , {100 , 0 , 100 }, " " };
50- ConfigurableAxis thnConfigAxisChi2PCA{" thnConfigAxisChi2PCA" , {100 , 0 , 20 }, " " };
51- ConfigurableAxis thnConfigAxisDecLength{" thnConfigAxisDecLength" , {10 , 0 , 0.05 }, " " };
52- ConfigurableAxis thnConfigAxisCPA{" thnConfigAxisCPA" , {20 , 0.8 , 1 }, " " };
53- ConfigurableAxis thnConfigAxisBdtScoreBkg{" thnConfigAxisBdtScoreBkg" , {1000 , 0 ., 1 .}, " " };
54- ConfigurableAxis thnConfigAxisBdtScoreSignal{" thnConfigAxisBdtScoreSignal" , {100 , 0 ., 1 .}, " " };
55- ConfigurableAxis thnConfigAxisCanType{" thnConfigAxisCanType" , {5 , 0 ., 5 .}, " " };
56- ConfigurableAxis thnAxisRapidity{" thnAxisRapidity" , {20 , -1 , 1 }, " Cand. rapidity bins" };
57- ConfigurableAxis thnConfigAxisGenPtB{" thnConfigAxisGenPtB" , {1000 , 0 , 100 }, " Gen Pt B" };
58- ConfigurableAxis thnConfigAxisNumPvContr{" thnConfigAxisNumPvContr" , {200 , -0.5 , 199.5 }, " Number of PV contributors" };
49+ Configurable<bool > storeOccupancy{" storeOccupancy" , true , " Flag to store occupancy information" };
50+ Configurable<int > occEstimator{" occEstimator" , 2 , " Occupancy estimation (None: 0, ITS: 1, FT0C: 2)" };
5951
6052 HfHelper hfHelper;
53+ SliceCache cache;
6154
6255 using Collisions = soa::Join<aod::Collisions, aod::EvSels>;
6356 using CollisionsMc = soa::Join<aod::Collisions, aod::McCollisionLabels, aod::EvSels>;
@@ -73,9 +66,23 @@ struct HfTaskLc {
7366 using LcCandidatesMlMc = soa::Filtered<soa::Join<aod::HfCand3Prong, aod::HfSelLc, aod::HfMlLcToPKPi, aod::HfCand3ProngMcRec>>;
7467 using McParticles3ProngMatched = soa::Join<aod::McParticles, aod::HfCand3ProngMcGen>;
7568 Filter filterSelectCandidates = aod::hf_sel_candidate_lc::isSelLcToPKPi >= selectionFlagLc || aod::hf_sel_candidate_lc::isSelLcToPiKP >= selectionFlagLc;
76- PresliceUnsorted<aod::McCollisionLabels> colPerMcCollision = aod::mcparticle::mcCollisionId;
7769 Preslice<aod::HfCand3Prong> candLcPerCollision = aod::hf_cand::collisionId;
78- SliceCache cache;
70+ PresliceUnsorted<aod::McCollisionLabels> colPerMcCollision = aod::mcparticle::mcCollisionId;
71+
72+ ConfigurableAxis thnConfigAxisPt{" thnConfigAxisPt" , {72 , 0 , 36 }, " " };
73+ ConfigurableAxis thnConfigAxisMass{" thnConfigAxisMass" , {300 , 1.98 , 2.58 }, " " };
74+ ConfigurableAxis thnConfigAxisPtProng{" thnConfigAxisPtProng" , {100 , 0 , 20 }, " " };
75+ ConfigurableAxis thnConfigAxisCentrality{" thnConfigAxisCentrality" , {100 , 0 , 100 }, " " };
76+ ConfigurableAxis thnConfigAxisChi2PCA{" thnConfigAxisChi2PCA" , {100 , 0 , 20 }, " " };
77+ ConfigurableAxis thnConfigAxisDecLength{" thnConfigAxisDecLength" , {10 , 0 , 0.05 }, " " };
78+ ConfigurableAxis thnConfigAxisCPA{" thnConfigAxisCPA" , {20 , 0.8 , 1 }, " " };
79+ ConfigurableAxis thnConfigAxisBdtScoreBkg{" thnConfigAxisBdtScoreBkg" , {1000 , 0 ., 1 .}, " " };
80+ ConfigurableAxis thnConfigAxisBdtScoreSignal{" thnConfigAxisBdtScoreSignal" , {100 , 0 ., 1 .}, " " };
81+ ConfigurableAxis thnConfigAxisCanType{" thnConfigAxisCanType" , {5 , 0 ., 5 .}, " " };
82+ ConfigurableAxis thnAxisRapidity{" thnAxisRapidity" , {20 , -1 , 1 }, " Cand. rapidity bins" };
83+ ConfigurableAxis thnConfigAxisGenPtB{" thnConfigAxisGenPtB" , {1000 , 0 , 100 }, " Gen Pt B" };
84+ ConfigurableAxis thnConfigAxisNumPvContr{" thnConfigAxisNumPvContr" , {200 , -0.5 , 199.5 }, " Number of PV contributors" };
85+ ConfigurableAxis thnConfigAxisOccupancy{" thnConfigAxisOccupancy" , {14 , 0 , 14000 }, " axis for centrality" };
7986
8087 HistogramRegistry registry{
8188 " registry" ,
@@ -292,22 +299,44 @@ struct HfTaskLc {
292299 const AxisSpec thnAxisY{thnAxisRapidity, " rapidity" };
293300 const AxisSpec thnAxisPtB{thnConfigAxisGenPtB, " #it{p}_{T}^{B} (GeV/#it{c})" };
294301 const AxisSpec thnAxisTracklets{thnConfigAxisNumPvContr, " Number of PV contributors" };
302+ const AxisSpec thnAxisOccupancy{thnConfigAxisOccupancy, " Occupancy" };
295303
296- if (doprocessDataWithMl || doprocessDataWithMlWithFT0C || doprocessDataWithMlWithFT0M) {
304+ bool isDataWithMl = doprocessDataWithMl || doprocessDataWithMlWithFT0C || doprocessDataWithMlWithFT0M;
305+ bool isMcWithMl = doprocessMcWithMl || doprocessMcWithMlWithFT0C || doprocessMcWithMlWithFT0M;
306+ bool isDataStd = doprocessDataStd || doprocessDataStdWithFT0C || doprocessDataStdWithFT0M;
307+ bool isMcStd = doprocessMcStd || doprocessMcStdWithFT0C || doprocessMcStdWithFT0M;
297308
298- registry. add ( " hnLcVarsWithBdt " , " THn for Lambdac candidates with BDT scores for data with ML " , HistType:: kTHnSparseF , {thnAxisMass, thnAxisPt, thnAxisCentrality, thnAxisBdtScoreLcBkg, thnAxisBdtScoreLcPrompt, thnAxisBdtScoreLcNonPrompt, thnAxisTracklets}) ;
309+ std::vector<AxisSpec> axesStd, axesWithBdt, axesGen ;
299310
300- } else if (doprocessMcWithMl || doprocessMcWithMlWithFT0C || doprocessMcWithMlWithFT0M) {
301-
302- registry.add (" hnLcVarsWithBdt" , " THn for Lambdac candidates with BDT scores for mc with ML" , HistType::kTHnSparseF , {thnAxisMass, thnAxisPt, thnAxisCentrality, thnAxisBdtScoreLcBkg, thnAxisBdtScoreLcPrompt, thnAxisBdtScoreLcNonPrompt, thnAxisTracklets, thnAxisPtB, thnAxisCanType});
303- registry.add (" hnLcVarsGen" , " THn for Generated Lambdac" , HistType::kTHnSparseF , {thnAxisPt, thnAxisY, thnAxisTracklets, thnAxisPtB, thnAxisCanType});
311+ if (isDataStd || isMcStd) {
312+ axesStd = {thnAxisMass, thnAxisPt, thnAxisCentrality, thnAxisPtProng0, thnAxisPtProng1, thnAxisPtProng2, thnAxisChi2PCA, thnAxisDecLength, thnAxisCPA, thnAxisTracklets, thnAxisPtB, thnAxisCanType};
313+ }
314+ if (isMcStd || isMcWithMl) {
315+ axesGen = {thnAxisPt, thnAxisCentrality, thnAxisY, thnAxisTracklets, thnAxisPtB, thnAxisCanType};
316+ }
317+ if (isDataWithMl || isMcWithMl) {
318+ axesWithBdt = {thnAxisMass, thnAxisPt, thnAxisCentrality, thnAxisBdtScoreLcBkg, thnAxisBdtScoreLcPrompt, thnAxisBdtScoreLcNonPrompt, thnAxisTracklets, thnAxisPtB, thnAxisCanType};
319+ }
304320
305- } else if (doprocessDataStd || doprocessDataStdWithFT0C || doprocessDataStdWithFT0M) {
306- registry.add (" hnLcVars" , " THn for Reconstructed Lambdac candidates for data without ML" , HistType::kTHnSparseF , {thnAxisMass, thnAxisPt, thnAxisCentrality, thnAxisPtProng0, thnAxisPtProng1, thnAxisPtProng2, thnAxisChi2PCA, thnAxisDecLength, thnAxisCPA, thnAxisTracklets});
321+ if (storeOccupancy) {
322+ if (!axesWithBdt.empty ())
323+ axesWithBdt.push_back (thnAxisOccupancy);
324+ if (!axesStd.empty ())
325+ axesStd.push_back (thnAxisOccupancy);
326+ if (!axesGen.empty ())
327+ axesGen.push_back (thnAxisOccupancy);
328+ }
307329
330+ if (isDataWithMl) {
331+ registry.add (" hnLcVarsWithBdt" , " THn for Lambdac candidates with BDT scores for data with ML" , HistType::kTHnSparseF , axesWithBdt);
332+ } else if (isMcWithMl) {
333+ registry.add (" hnLcVarsWithBdt" , " THn for Lambdac candidates with BDT scores for mc with ML" , HistType::kTHnSparseF , axesWithBdt);
334+ registry.add (" hnLcVarsGen" , " THn for Generated Lambdac" , HistType::kTHnSparseF , axesGen);
335+ } else if (isDataStd) {
336+ registry.add (" hnLcVars" , " THn for Reconstructed Lambdac candidates for data without ML" , HistType::kTHnSparseF , axesStd);
308337 } else {
309- registry.add (" hnLcVars" , " THn for Reconstructed Lambdac candidates for mc without ML" , HistType::kTHnSparseF , {thnAxisMass, thnAxisPt, thnAxisCentrality, thnAxisPtProng0, thnAxisPtProng1, thnAxisPtProng2, thnAxisChi2PCA, thnAxisDecLength, thnAxisCPA, thnAxisTracklets, thnAxisPtB, thnAxisCanType} );
310- registry.add (" hnLcVarsGen" , " THn for Generated Lambdac" , HistType::kTHnSparseF , {thnAxisPt, thnAxisY, thnAxisTracklets, thnAxisPtB, thnAxisCanType} );
338+ registry.add (" hnLcVars" , " THn for Reconstructed Lambdac candidates for mc without ML" , HistType::kTHnSparseF , axesStd );
339+ registry.add (" hnLcVarsGen" , " THn for Generated Lambdac" , HistType::kTHnSparseF , axesGen );
311340 }
312341 }
313342 }
@@ -484,6 +513,10 @@ struct HfTaskLc {
484513 }
485514 if (fillTHn) {
486515 float cent = evaluateCentralityColl (collision);
516+ float occ{-1 .};
517+ if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) {
518+ occ = o2::hf_occupancy::getOccupancyColl (collision, occEstimator);
519+ }
487520 double massLc (-1 );
488521 double outputBkg (-1 ), outputPrompt (-1 ), outputFD (-1 );
489522 if ((candidate.isSelLcToPKPi () >= selectionFlagLc) && pdgCodeProng0 == kProton ) {
@@ -496,9 +529,21 @@ struct HfTaskLc {
496529 outputFD = candidate.mlProbLcToPKPi ()[2 ]; // / non-prompt score
497530 }
498531 // / Fill the ML outputScores and variables of candidate
499- registry.get <THnSparse>(HIST (" hnLcVarsWithBdt" ))->Fill (massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, ptRecB, originType);
532+ if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) {
533+ registry.get <THnSparse>(HIST (" hnLcVarsWithBdt" ))->Fill (massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, ptRecB, originType, occ);
534+ } else {
535+ registry.get <THnSparse>(HIST (" hnLcVarsWithBdt" ))->Fill (massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, ptRecB, originType);
536+ }
537+
500538 } else {
501- registry.get <THnSparse>(HIST (" hnLcVars" ))->Fill (massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, numPvContributors, ptRecB, originType);
539+
540+ if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) {
541+ registry.get <THnSparse>(HIST (" hnLcVars" ))->Fill (massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, numPvContributors, ptRecB, originType, occ);
542+
543+ } else {
544+
545+ registry.get <THnSparse>(HIST (" hnLcVars" ))->Fill (massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, numPvContributors, ptRecB, originType);
546+ }
502547 }
503548 }
504549 if ((candidate.isSelLcToPiKP () >= selectionFlagLc) && pdgCodeProng0 == kPiPlus ) {
@@ -511,9 +556,18 @@ struct HfTaskLc {
511556 outputFD = candidate.mlProbLcToPiKP ()[2 ]; // / non-prompt score
512557 }
513558 // / Fill the ML outputScores and variables of candidate (todo: add multiplicity)
514- registry.get <THnSparse>(HIST (" hnLcVarsWithBdt" ))->Fill (massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, ptRecB, originType);
559+ if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) {
560+ registry.get <THnSparse>(HIST (" hnLcVarsWithBdt" ))->Fill (massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, ptRecB, originType, occ);
561+
562+ } else {
563+ registry.get <THnSparse>(HIST (" hnLcVarsWithBdt" ))->Fill (massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, ptRecB, originType);
564+ }
515565 } else {
516- registry.get <THnSparse>(HIST (" hnLcVars" ))->Fill (massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, numPvContributors, ptRecB, originType);
566+ if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) {
567+ registry.get <THnSparse>(HIST (" hnLcVars" ))->Fill (massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, numPvContributors, ptRecB, originType, occ);
568+ } else {
569+ registry.get <THnSparse>(HIST (" hnLcVars" ))->Fill (massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, numPvContributors, ptRecB, originType);
570+ }
517571 }
518572 }
519573 }
@@ -541,6 +595,11 @@ struct HfTaskLc {
541595 for (const auto & recCol : recoCollsPerMcColl) {
542596 numPvContributors = recCol.numContrib () > numPvContributors ? recCol.numContrib () : numPvContributors;
543597 }
598+ float cent = o2::hf_centrality::getCentralityGenColl (recoCollsPerMcColl);
599+ float occ{-1 .};
600+ if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) {
601+ occ = o2::hf_occupancy::getOccupancyGenColl (recoCollsPerMcColl, occEstimator);
602+ }
544603
545604 registry.fill (HIST (" MC/generated/signal/hPtGen" ), ptGen);
546605 registry.fill (HIST (" MC/generated/signal/hEtaGen" ), particle.eta ());
@@ -552,7 +611,12 @@ struct HfTaskLc {
552611
553612 if (particle.originMcGen () == RecoDecay::OriginType::Prompt) {
554613 if (fillTHn) {
555- registry.get <THnSparse>(HIST (" hnLcVarsGen" ))->Fill (ptGen, yGen, numPvContributors, ptGenB, originType);
614+ if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) {
615+ registry.get <THnSparse>(HIST (" hnLcVarsGen" ))->Fill (ptGen, cent, yGen, numPvContributors, ptGenB, originType, occ);
616+
617+ } else {
618+ registry.get <THnSparse>(HIST (" hnLcVarsGen" ))->Fill (ptGen, cent, yGen, numPvContributors, ptGenB, originType);
619+ }
556620 }
557621 registry.fill (HIST (" MC/generated/prompt/hPtGenPrompt" ), ptGen);
558622 registry.fill (HIST (" MC/generated/prompt/hEtaGenPrompt" ), particle.eta ());
@@ -565,7 +629,12 @@ struct HfTaskLc {
565629 if (particle.originMcGen () == RecoDecay::OriginType::NonPrompt) {
566630 ptGenB = mcParticles.rawIteratorAt (particle.idxBhadMotherPart ()).pt ();
567631 if (fillTHn) {
568- registry.get <THnSparse>(HIST (" hnLcVarsGen" ))->Fill (ptGen, yGen, numPvContributors, ptGenB, originType);
632+ if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) {
633+ registry.get <THnSparse>(HIST (" hnLcVarsGen" ))->Fill (ptGen, cent, yGen, numPvContributors, ptGenB, originType, occ);
634+
635+ } else {
636+ registry.get <THnSparse>(HIST (" hnLcVarsGen" ))->Fill (ptGen, cent, yGen, numPvContributors, ptGenB, originType);
637+ }
569638 }
570639 registry.fill (HIST (" MC/generated/nonprompt/hPtGenNonPrompt" ), ptGen);
571640 registry.fill (HIST (" MC/generated/nonprompt/hEtaGenNonPrompt" ), particle.eta ());
@@ -650,6 +719,10 @@ struct HfTaskLc {
650719
651720 if (fillTHn) {
652721 float cent = evaluateCentralityColl (collision);
722+ float occ{-1 .};
723+ if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) {
724+ occ = o2::hf_occupancy::getOccupancyColl (collision, occEstimator);
725+ }
653726 double massLc (-1 );
654727 double outputBkg (-1 ), outputPrompt (-1 ), outputFD (-1 );
655728 if (candidate.isSelLcToPKPi () >= selectionFlagLc) {
@@ -662,9 +735,20 @@ struct HfTaskLc {
662735 outputFD = candidate.mlProbLcToPKPi ()[2 ]; // / non-prompt score
663736 }
664737 // / Fill the ML outputScores and variables of candidate
665- registry.get <THnSparse>(HIST (" hnLcVarsWithBdt" ))->Fill (massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors);
738+ if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) {
739+ registry.get <THnSparse>(HIST (" hnLcVarsWithBdt" ))->Fill (massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, occ);
740+
741+ } else {
742+ registry.get <THnSparse>(HIST (" hnLcVarsWithBdt" ))->Fill (massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors);
743+ }
666744 } else {
667- registry.get <THnSparse>(HIST (" hnLcVars" ))->Fill (massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, numPvContributors);
745+ if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) {
746+
747+ registry.get <THnSparse>(HIST (" hnLcVars" ))->Fill (massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, numPvContributors, occ);
748+ } else {
749+
750+ registry.get <THnSparse>(HIST (" hnLcVars" ))->Fill (massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, numPvContributors);
751+ }
668752 }
669753 }
670754 if (candidate.isSelLcToPiKP () >= selectionFlagLc) {
@@ -677,15 +761,22 @@ struct HfTaskLc {
677761 outputFD = candidate.mlProbLcToPiKP ()[2 ]; // / non-prompt score
678762 }
679763 // / Fill the ML outputScores and variables of candidate
680- registry.get <THnSparse>(HIST (" hnLcVarsWithBdt" ))->Fill (massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors);
764+ if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) {
765+ registry.get <THnSparse>(HIST (" hnLcVarsWithBdt" ))->Fill (massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, occ);
766+ } else {
767+ registry.get <THnSparse>(HIST (" hnLcVarsWithBdt" ))->Fill (massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors);
768+ }
681769 } else {
682- registry.get <THnSparse>(HIST (" hnLcVars" ))->Fill (massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, numPvContributors);
770+ if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) {
771+ registry.get <THnSparse>(HIST (" hnLcVars" ))->Fill (massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, numPvContributors, occ);
772+ } else {
773+ registry.get <THnSparse>(HIST (" hnLcVars" ))->Fill (massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, numPvContributors);
774+ }
683775 }
684776 }
685777 }
686778 }
687779 }
688-
689780 // / Run the analysis on real data
690781 // / \tparam fillMl switch to fill ML histograms
691782 template <bool fillMl, typename CollType, typename CandType>
0 commit comments