@@ -238,8 +238,6 @@ struct HfTaskD0 {
238238 {" 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 .}}}},
239239 {" 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 .}}}}}};
240240
241- HistogramRegistry qaRegistry{" QAHistos" , {}, OutputObjHandlingPolicy::AnalysisObject};
242-
243241 void init (InitContext&)
244242 {
245243 std::array<bool , 13 > doprocess{doprocessDataWithDCAFitterN, doprocessDataWithDCAFitterNCent, doprocessDataWithKFParticle, doprocessMcWithDCAFitterN, doprocessMcWithDCAFitterNCent, doprocessMcWithKFParticle, doprocessDataWithDCAFitterNMl, doprocessDataWithDCAFitterNMlCent, doprocessDataWithKFParticleMl, doprocessMcWithDCAFitterNMl, doprocessMcWithDCAFitterNMlCent, doprocessMcWithKFParticleMl, doprocessDataWithDCAFitterNMlWithUpc};
@@ -371,14 +369,14 @@ struct HfTaskD0 {
371369 registry.get <THnSparse>(HIST (" hMassVsPtVsPtBVsYVsOriginVsD0Type" ))->Sumw2 ();
372370 }
373371
374- 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 }}});
375- 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 }}});
376- qaRegistry .add (" Data/hUpcGapAfterSelection" , " UPC gap type after selection;Gap side;Counts" , {HistType::kTH1F , {{3 , -0.5 , 2.5 }}});
377- qaRegistry .get <TH1>(HIST (" Data/hUpcGapAfterSelection" ))->GetXaxis ()->SetBinLabel (static_cast <int >(GapType::GapA) + 1 , " A" );
378- qaRegistry .get <TH1>(HIST (" Data/hUpcGapAfterSelection" ))->GetXaxis ()->SetBinLabel (static_cast <int >(GapType::GapC) + 1 , " C" );
379- qaRegistry .get <TH1>(HIST (" Data/hUpcGapAfterSelection" ))->GetXaxis ()->SetBinLabel (static_cast <int >(GapType::DoubleGap) + 1 , " Double" );
372+ registry .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 }}});
373+ registry .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 }}});
374+ registry .add (" Data/hUpcGapAfterSelection" , " UPC gap type after selection;Gap side;Counts" , {HistType::kTH1F , {{3 , -0.5 , 2.5 }}});
375+ registry .get <TH1>(HIST (" Data/hUpcGapAfterSelection" ))->GetXaxis ()->SetBinLabel (static_cast <int >(GapType::GapA) + 1 , " A" );
376+ registry .get <TH1>(HIST (" Data/hUpcGapAfterSelection" ))->GetXaxis ()->SetBinLabel (static_cast <int >(GapType::GapC) + 1 , " C" );
377+ registry .get <TH1>(HIST (" Data/hUpcGapAfterSelection" ))->GetXaxis ()->SetBinLabel (static_cast <int >(GapType::DoubleGap) + 1 , " Double" );
380378
381- hfEvSel.addHistograms (qaRegistry );
379+ hfEvSel.addHistograms (registry );
382380
383381 ccdb->setURL (ccdbUrl);
384382 ccdb->setCaching (true );
@@ -565,7 +563,7 @@ struct HfTaskD0 {
565563 }
566564 }
567565
568- template <bool fillMl , typename CollType, typename CandType, typename BCsType>
566+ template <bool FillMl , typename CollType, typename CandType, typename BCsType>
569567 void runAnalysisPerCollisionDataWithUpc (CollType const & collisions,
570568 CandType const & candidates,
571569 BCsType const & bcs,
@@ -574,39 +572,45 @@ struct HfTaskD0 {
574572 aod::FDDs const & fdds)
575573 {
576574 for (const auto & collision : collisions) {
577- uint32_t rejectionMask{0 };
578575 float centrality{-1 .f };
579- rejectionMask = hfEvSel.getHfCollisionRejectionMaskWithUpc <true , CentralityEstimator::None, BCsType>(collision, centrality, ccdb, qaRegistry , bcs);
576+ const auto rejectionMask = hfEvSel.getHfCollisionRejectionMaskWithUpc <true , CentralityEstimator::None, BCsType>(collision, centrality, ccdb, registry , bcs);
580577 if (rejectionMask != 0 ) {
581578 continue ;
582579 }
583- auto bc = collision.template bc_as <BCsType>();
580+ const auto & bc = collision.template bc_as <BCsType>();
584581 upchelpers::FITInfo fitInfo{};
585582 udhelpers::getFITinfo (fitInfo, bc, bcs, ft0s, fv0as, fdds);
586583
587584 GapType gap = GapType::DoubleGap;
588585 if (bc.has_zdc ()) {
589- auto zdc = bc.zdc ();
590- qaRegistry .fill (HIST (" Data/fitInfo/ampFT0A_vs_ampFT0C" ), fitInfo.ampFT0A , fitInfo.ampFT0C );
591- qaRegistry .fill (HIST (" Data/zdc/energyZNA_vs_energyZNC" ), zdc.energyCommonZNA (), zdc.energyCommonZNC ());
586+ const auto & zdc = bc.zdc ();
587+ registry .fill (HIST (" Data/fitInfo/ampFT0A_vs_ampFT0C" ), fitInfo.ampFT0A , fitInfo.ampFT0C );
588+ registry .fill (HIST (" Data/zdc/energyZNA_vs_energyZNC" ), zdc.energyCommonZNA (), zdc.energyCommonZNC ());
592589 gap = hf_upc::determineGapType (fitInfo.ampFT0A , fitInfo.ampFT0C , zdc.energyCommonZNA (), zdc.energyCommonZNC (),
593590 upcFT0AThreshold, upcFT0CThreshold, upcZDCThreshold);
594- qaRegistry .fill (HIST (" Data/hUpcGapAfterSelection" ), hf_upc::gapTypeToInt (gap));
591+ registry .fill (HIST (" Data/hUpcGapAfterSelection" ), hf_upc::gapTypeToInt (gap));
595592 }
596593 if (hf_upc::isSingleSidedGap (gap)) {
597594 int const gapTypeInt = hf_upc::gapTypeToInt (gap);
598595 const auto thisCollId = collision.globalIndex ();
599596 const auto & groupedD0Candidates = candidates.sliceBy (candD0PerCollision, thisCollId);
597+
598+ // Calculate occupancy and interaction rate if needed
600599 float occ{-1 .f };
600+ float ir{-1 .f };
601+ if (storeOccupancyAndIR && occEstimator != OccupancyEstimator::None) {
602+ occ = o2::hf_occupancy::getOccupancyColl (collision, occEstimator);
603+ ir = mRateFetcher .fetch (ccdb.service , bc.timestamp (), bc.runNumber (), irSource, true ) * 1 .e -3 ; // kHz
604+ }
601605
602606 for (const auto & candidate : groupedD0Candidates) {
603607 if (yCandRecoMax >= 0 . && std::abs (HfHelper::yD0 (candidate)) > yCandRecoMax) {
604608 continue ;
605609 }
606610
607- float massD0 = HfHelper::invMassD0ToPiK (candidate);
608- float massD0bar = HfHelper::invMassD0barToKPi (candidate);
609- auto ptCandidate = candidate.pt ();
611+ const float massD0 = HfHelper::invMassD0ToPiK (candidate);
612+ const float massD0bar = HfHelper::invMassD0barToKPi (candidate);
613+ const auto ptCandidate = candidate.pt ();
610614
611615 if (candidate.isSelD0 () >= selectionFlagD0) {
612616 registry.fill (HIST (" hMass" ), massD0, ptCandidate);
@@ -619,56 +623,53 @@ struct HfTaskD0 {
619623 registry.fill (HIST (" hMassVsPhi" ), massD0bar, ptCandidate, candidate.phi ());
620624 }
621625
622- // Fill THnSparse with structure matching taskDplus: [mass, pt, mlScores, cent, occ, gapType, FT0A, FT0C]
623- if constexpr (fillMl) {
624- auto fillTHnData = [&](float mass, int d0Type) {
625- std::vector<double > valuesToFill{static_cast <double >(mass), static_cast <double >(ptCandidate),
626- candidate.mlProbD0 ()[0 ], candidate.mlProbD0 ()[1 ], candidate.mlProbD0 ()[2 ],
627- static_cast <double >(HfHelper::yD0 (candidate)), static_cast <double >(d0Type)};
628- if (storeCentrality) {
629- valuesToFill.push_back (centrality);
630- }
631- if (storeOccupancyAndIR) {
632- valuesToFill.push_back (occ);
633- }
634- valuesToFill.push_back (static_cast <double >(gapTypeInt));
635- valuesToFill.push_back (static_cast <double >(fitInfo.ampFT0A ));
636- valuesToFill.push_back (static_cast <double >(fitInfo.ampFT0C ));
637- registry.get <THnSparse>(HIST (" hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type" ))->Fill (valuesToFill.data ());
638- };
639-
640- if (candidate.isSelD0 () >= selectionFlagD0) {
641- fillTHnData (massD0, SigD0);
642- fillTHnData (massD0, candidate.isSelD0bar () ? ReflectedD0 : PureSigD0);
626+ // Fill THnSparse with structure matching histogram axes: [mass, pt, (mlScores if FillMl), rapidity, d0Type, (cent if storeCentrality), (occ, ir if storeOccupancyAndIR), gapType, FT0A, FT0C]
627+ auto fillTHnData = [&](float mass, int d0Type) {
628+ // Pre-calculate vector size to avoid reallocations
629+ constexpr int nAxesBase = 7 ; // mass, pt, rapidity, d0Type, gapType, FT0A, FT0C
630+ constexpr int nAxesMl = FillMl ? 3 : 0 ; // 3 ML scores if FillMl
631+ int const nAxesCent = storeCentrality ? 1 : 0 ; // centrality if storeCentrality
632+ int const nAxesOccIR = storeOccupancyAndIR ? 2 : 0 ; // occupancy and IR if storeOccupancyAndIR
633+ int const nAxesTotal = nAxesBase + nAxesMl + nAxesCent + nAxesOccIR;
634+
635+ std::vector<double > valuesToFill;
636+ valuesToFill.reserve (nAxesTotal);
637+
638+ // Fill values in order matching histogram axes
639+ valuesToFill.push_back (static_cast <double >(mass));
640+ valuesToFill.push_back (static_cast <double >(ptCandidate));
641+ if constexpr (FillMl) {
642+ valuesToFill.push_back (candidate.mlProbD0 ()[0 ]);
643+ valuesToFill.push_back (candidate.mlProbD0 ()[1 ]);
644+ valuesToFill.push_back (candidate.mlProbD0 ()[2 ]);
643645 }
644- if (candidate.isSelD0bar () >= selectionFlagD0bar) {
645- fillTHnData (massD0bar, SigD0bar);
646- fillTHnData (massD0bar, candidate.isSelD0 () ? ReflectedD0bar : PureSigD0bar);
646+ valuesToFill.push_back (static_cast <double >(HfHelper::yD0 (candidate)));
647+ valuesToFill.push_back (static_cast <double >(d0Type));
648+ if (storeCentrality) {
649+ valuesToFill.push_back (centrality);
647650 }
648- } else {
649- auto fillTHnData = [&](float mass, int d0Type) {
650- std::vector<double > valuesToFill{static_cast <double >(mass), static_cast <double >(ptCandidate),
651- static_cast <double >(HfHelper::yD0 (candidate)), static_cast <double >(d0Type)};
652- if (storeCentrality) {
653- valuesToFill.push_back (centrality);
654- }
655- if (storeOccupancyAndIR) {
656- valuesToFill.push_back (occ);
657- }
658- valuesToFill.push_back (static_cast <double >(gapTypeInt));
659- valuesToFill.push_back (static_cast <double >(fitInfo.ampFT0A ));
660- valuesToFill.push_back (static_cast <double >(fitInfo.ampFT0C ));
661- registry.get <THnSparse>(HIST (" hMassVsPtVsPtBVsYVsOriginVsD0Type" ))->Fill (valuesToFill.data ());
662- };
663-
664- if (candidate.isSelD0 () >= selectionFlagD0) {
665- fillTHnData (massD0, SigD0);
666- fillTHnData (massD0, candidate.isSelD0bar () ? ReflectedD0 : PureSigD0);
651+ if (storeOccupancyAndIR) {
652+ valuesToFill.push_back (occ);
653+ valuesToFill.push_back (ir);
667654 }
668- if (candidate.isSelD0bar () >= selectionFlagD0bar) {
669- fillTHnData (massD0bar, SigD0bar);
670- fillTHnData (massD0bar, candidate.isSelD0 () ? ReflectedD0bar : PureSigD0bar);
655+ valuesToFill.push_back (static_cast <double >(gapTypeInt));
656+ valuesToFill.push_back (static_cast <double >(fitInfo.ampFT0A ));
657+ valuesToFill.push_back (static_cast <double >(fitInfo.ampFT0C ));
658+
659+ if constexpr (FillMl) {
660+ registry.get <THnSparse>(HIST (" hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type" ))->Fill (valuesToFill.data ());
661+ } else {
662+ registry.get <THnSparse>(HIST (" hMassVsPtVsPtBVsYVsOriginVsD0Type" ))->Fill (valuesToFill.data ());
671663 }
664+ };
665+
666+ if (candidate.isSelD0 () >= selectionFlagD0) {
667+ fillTHnData (massD0, SigD0);
668+ fillTHnData (massD0, candidate.isSelD0bar () ? ReflectedD0 : PureSigD0);
669+ }
670+ if (candidate.isSelD0bar () >= selectionFlagD0bar) {
671+ fillTHnData (massD0bar, SigD0bar);
672+ fillTHnData (massD0bar, candidate.isSelD0 () ? ReflectedD0bar : PureSigD0bar);
672673 }
673674 }
674675 }
0 commit comments