@@ -186,6 +186,11 @@ struct HfCorrelatorDplusHadrons {
186186
187187 Configurable<int > selectionFlagDplus{" selectionFlagDplus" , 7 , " Selection Flag for Dplus" }; // 7 corresponds to topo+PID cuts
188188 Configurable<int > numberEventsMixed{" numberEventsMixed" , 5 , " Number of events mixed in ME process" };
189+ Configurable<bool > removeUnreconstructedGenCollisions{" removeUnreconstructedGenCollisions" ,true ," Remove generator-level collisions that were not reconstructed" };
190+ Configurable<bool > removeCollWSplitVtx{" removeCollWSplitVtx" , true , " Flag for rejecting the splitted collisions" };
191+ Configurable<bool > useSel8{" useSel8" , true , " Flag for applying sel8 for collision selection" };
192+ Configurable<bool > selNoSameBunchPileUpColl{" selNoSameBunchPileUpColl" , true , " Flag for rejecting the collisions associated with the same bunch crossing" };
193+ Configurable<float > zVtxMax{" zVtxMax" , 10 ., " max. position-z of the reconstructed collision" };
189194 Configurable<bool > applyEfficiency{" applyEfficiency" , true , " Flag for applying D-meson efficiency weights" };
190195 Configurable<bool > removeDaughters{" removeDaughters" , true , " Flag for removing D-meson daughters from correlations" };
191196 Configurable<float > yCandMax{" yCandMax" , 0.8 , " max. cand. rapidity" };
@@ -210,6 +215,7 @@ struct HfCorrelatorDplusHadrons {
210215 // Event Mixing for the Data Mode
211216 using SelCollisionsWithDplus = soa::Filtered<soa::Join<aod::Collisions, aod::Mults, aod::EvSels, aod::DmesonSelection>>;
212217 using SelCollisionsWithDplusMc = soa::Filtered<soa::Join<aod::McCollisions, aod::DmesonSelection, aod::MultsExtraMC>>; // collisionFilter applied
218+ using CollisionsMc = soa::Join<aod::McCollisions, aod::MultsExtraMC>;
213219 using CandidatesDplusData = soa::Filtered<soa::Join<aod::HfCand3Prong, aod::HfSelDplusToPiKPi, aod::HfMlDplusToPiKPi>>;
214220 // Event Mixing for the MCRec Mode
215221 using CandidatesDplusMcRec = soa::Filtered<soa::Join<aod::HfCand3Prong, aod::HfSelDplusToPiKPi, aod::HfMlDplusToPiKPi, aod::HfCand3ProngMcRec>>;
@@ -226,6 +232,8 @@ struct HfCorrelatorDplusHadrons {
226232 Filter dplusFilter = ((o2::aod::hf_track_index::hfflag & static_cast <uint8_t >(1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi)) != static_cast <uint8_t >(0 )) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus;
227233 Filter trackFilter = (nabs(aod::track::eta) < etaTrackMax) && (nabs(aod::track::pt) > ptTrackMin) && (nabs(aod::track::dcaXY) < dcaXYTrackMax) && (nabs(aod::track::dcaZ) < dcaZTrackMax);
228234 Preslice<aod::McParticles> presliceMc{aod::mcparticle::mcCollisionId};
235+ Preslice<CandDplusMcGen> candMcGenPerMcCollision = o2::aod::mcparticle::mcCollisionId;
236+ PresliceUnsorted<soa::Join<aod::Collisions, aod::FT0Mults, aod::EvSels, aod::McCollisionLabels>> recoCollisionsPerMcCollision = o2::aod::mccollisionlabel::mcCollisionId;
229237 // Filter particlesFilter = nabs(aod::mcparticle::pdgCode) == 411 || ((aod::mcparticle::flags & (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary) == (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary);
230238 ConfigurableAxis binsMultiplicity{" binsMultiplicity" , {VARIABLE_WIDTH, 0 .0f , 2000 .0f , 6000 .0f , 100000 .0f }, " Mixing bins - multiplicity" };
231239 ConfigurableAxis binsZVtx{" binsZVtx" , {VARIABLE_WIDTH, -10 .0f , -2 .5f , 2 .5f , 10 .0f }, " Mixing bins - z-vertex" };
@@ -311,6 +319,126 @@ struct HfCorrelatorDplusHadrons {
311319 corrBinning = {{binsZVtx, binsMultiplicity}, true };
312320 }
313321
322+ template <typename ParticleContainer, typename AssocContainer>
323+ void runMcGenDplusHadronAnalysis (const ParticleContainer& particlesToLoop, const AssocContainer& groupedMcParticles, int poolBin, int & counterDplusHadron)
324+ {
325+ for (const auto & particle : particlesToLoop) {
326+
327+ if (std::abs (particle.pdgCode ()) != Pdg::kDPlus ) {
328+ continue ;
329+ }
330+
331+ if (std::abs (particle.flagMcMatchGen ()) != hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) {
332+ continue ;
333+ }
334+
335+ double yD = RecoDecay::y (particle.pVector (), MassDPlus);
336+
337+ if (std::abs (yD) > yCandGenMax ||
338+ particle.pt () < ptCandMin ||
339+ particle.pt () > ptCandMax) {
340+ continue ;
341+ }
342+
343+ std::vector<int > listDaughters{};
344+ std::array<int , NDaughters> const arrDaughDplusPDG = {+kPiPlus , -kKPlus , kPiPlus };
345+ std::array<int , NDaughters> prongsId{};
346+
347+ RecoDecay::getDaughters (particle, &listDaughters, arrDaughDplusPDG, 2 );
348+
349+ if (listDaughters.size () != NDaughters) {
350+ continue ;
351+ }
352+
353+ bool isDaughtersOk = true ;
354+ int counterDaughters = 0 ;
355+
356+ for (const auto & dauIdx : listDaughters) {
357+ auto daughI = particlesToLoop.rawIteratorAt (dauIdx - particlesToLoop.offset ());
358+
359+ if (std::abs (daughI.eta ()) >= EtaDaughtersMax) {
360+ isDaughtersOk = false ;
361+ break ;
362+ }
363+
364+ prongsId[counterDaughters++] = daughI.globalIndex ();
365+ }
366+
367+ if (!isDaughtersOk) { // Skip this D+ candidate if any daughter fails eta cut
368+ continue ;
369+ }
370+ counterDplusHadron++;
371+
372+ registry.fill (HIST (" hDplusBin" ), poolBin);
373+ registry.fill (HIST (" hPtCandMCGen" ), particle.pt ());
374+ registry.fill (HIST (" hEtaMcGen" ), particle.eta ());
375+ registry.fill (HIST (" hPhiMcGen" ), RecoDecay::constrainAngle (particle.phi (), -PIHalf));
376+ registry.fill (HIST (" hYMCGen" ), yD);
377+
378+ // Prompt / Non-prompt separation
379+ bool isDplusPrompt = particle.originMcGen () == RecoDecay::OriginType::Prompt;
380+ bool isDplusNonPrompt = particle.originMcGen () == RecoDecay::OriginType::NonPrompt;
381+
382+ if (isDplusPrompt) {
383+ registry.fill (HIST (" hPtCandMcGenPrompt" ), particle.pt ());
384+ } else if (isDplusNonPrompt) {
385+ registry.fill (HIST (" hPtCandMcGenNonPrompt" ), particle.pt ());
386+ }
387+
388+ // Count triggers
389+ registry.fill (HIST (" hcountDplustriggersMCGen" ), 0 , particle.pt ());
390+
391+ for (const auto & particleAssoc : groupedMcParticles) {
392+
393+ if (std::abs (particleAssoc.eta ()) > etaTrackMax ||
394+ particleAssoc.pt () < ptTrackMin ||
395+ particleAssoc.pt () > ptTrackMax) {
396+ continue ;
397+ }
398+
399+ // Remove daughters if requested
400+ if (removeDaughters) {
401+ if (particleAssoc.globalIndex () == prongsId[0 ] ||
402+ particleAssoc.globalIndex () == prongsId[1 ] ||
403+ particleAssoc.globalIndex () == prongsId[2 ]) {
404+ continue ;
405+ }
406+ }
407+
408+ // Particle species selection
409+ if ((std::abs (particleAssoc.pdgCode ()) != kElectron ) &&
410+ (std::abs (particleAssoc.pdgCode ()) != kMuonMinus ) &&
411+ (std::abs (particleAssoc.pdgCode ()) != kPiPlus ) &&
412+ (std::abs (particleAssoc.pdgCode ()) != kKPlus ) &&
413+ (std::abs (particleAssoc.pdgCode ()) != kProton )) {
414+ continue ;
415+ }
416+
417+ if (!particleAssoc.isPhysicalPrimary ()) {
418+ continue ;
419+ }
420+
421+ int trackOrigin = RecoDecay::getCharmHadronOrigin (groupedMcParticles,
422+ particleAssoc,
423+ true );
424+
425+ registry.fill (HIST (" hPtParticleAssocMcGen" ), particleAssoc.pt ());
426+ entryDplusHadronPair (
427+ getDeltaPhi (particleAssoc.phi (), particle.phi ()),
428+ particleAssoc.eta () - particle.eta (),
429+ particle.pt (),
430+ particleAssoc.pt (),
431+ poolBin
432+ );
433+
434+ entryDplusHadronRecoInfo (MassDPlus, true );
435+ entryDplusHadronGenInfo (isDplusPrompt,
436+ particleAssoc.isPhysicalPrimary (),
437+ trackOrigin);
438+ }
439+ }
440+ }
441+
314442 // / Dplus-hadron correlation pair builder - for real data and data-like analysis (i.e. reco-level w/o matching request via MC truth)
315443 void processData (SelCollisionsWithDplus::iterator const & collision,
316444 TracksData const & tracks,
@@ -535,103 +663,68 @@ struct HfCorrelatorDplusHadrons {
535663 }
536664 PROCESS_SWITCH (HfCorrelatorDplusHadrons, processMcRec, " Process MC Reco mode" , true );
537665
538- // / Dplus-Hadron correlation pair builder - for MC gen-level analysis (no filter/selection, only true signal)
539- void processMcGen (SelCollisionsWithDplusMc::iterator const & mcCollision,
540- CandDplusMcGen const & mcParticles)
541- {
666+ // / Dplus-Hadron correlation pair builder - for MC gen-level analysis (no filter/selection, only true signal)
667+ void processMcGen (CollisionsMc const & mcCollisions,
668+ soa::Join<aod::Collisions, aod::FT0Mults, aod::EvSels, aod::McCollisionLabels> const & collisions,
669+ CandDplusMcGen const & mcParticles)
670+ {
671+ BinningTypeMcGen const corrBinningMcGen{{binsZVtx, binsMultiplicityMc}, true };
672+
673+ for (const auto & mcCollision : mcCollisions) {
674+
542675 int counterDplusHadron = 0 ;
543676 registry.fill (HIST (" hMCEvtCount" ), 0 );
544677
545- BinningTypeMcGen const corrBinningMcGen{{binsZVtx, binsMultiplicityMc}, true };
546678 int poolBin = corrBinningMcGen.getBin (std::make_tuple (mcCollision.posZ (), mcCollision.multMCFT0A ()));
547679 registry.fill (HIST (" hMultFT0AMcGen" ), mcCollision.multMCFT0A ());
548680
549- // MC gen level
550- for (const auto & particle1 : mcParticles) {
551- // check if the particle is Dplus (for general plot filling and selection, so both cases are fine) - NOTE: decay channel is not probed!
552- if (std::abs (particle1.pdgCode ()) != Pdg::kDPlus ) {
553- continue ;
554- }
555- if (std::abs (particle1.flagMcMatchGen ()) != hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) {
556- continue ;
557- }
558- double const yD = RecoDecay::y (particle1.pVector (), MassDPlus);
559- if (std::abs (yD) >= yCandMax || particle1.pt () <= ptCandMin) {
681+ const auto groupedMcParticles = mcParticles.sliceBy (candMcGenPerMcCollision, mcCollision.globalIndex ());
682+ const auto groupedCollisions = collisions.sliceBy (recoCollisionsPerMcCollision, mcCollision.globalIndex ());
683+
684+ if (removeUnreconstructedGenCollisions) {
685+
686+ if (groupedCollisions.size () < 1 ) {
560687 continue ;
561688 }
562- std::vector<int > listDaughters{};
563- std::array<int , NDaughters> const arrDaughDplusPDG = {+kPiPlus , -kKPlus , kPiPlus };
564- std::array<int , NDaughters> prongsId{};
565- listDaughters.clear ();
566- RecoDecay::getDaughters (particle1, &listDaughters, arrDaughDplusPDG, 2 );
567- int counterDaughters = 0 ;
568- if (listDaughters.size () != NDaughters) {
689+
690+ if (groupedCollisions.size () > 1 && removeCollWSplitVtx) {
569691 continue ;
570692 }
571- bool isDaughtersOk = true ;
572- for (const auto & dauIdx : listDaughters) {
573- auto daughI = mcParticles.rawIteratorAt (dauIdx - mcParticles.offset ());
574- if (std::abs (daughI.eta ()) >= EtaDaughtersMax) {
575- isDaughtersOk = false ;
576- break ;
577- }
578- counterDaughters += 1 ;
579- prongsId[counterDaughters - 1 ] = daughI.globalIndex ();
580- }
581- if (!isDaughtersOk) {
582- continue ; // Skip this D+ candidate if any daughter fails eta cut
583- }
584- counterDplusHadron++;
585-
586- registry.fill (HIST (" hDplusBin" ), poolBin);
587- registry.fill (HIST (" hPtCandMCGen" ), particle1.pt ());
588- registry.fill (HIST (" hEtaMcGen" ), particle1.eta ());
589- registry.fill (HIST (" hPhiMcGen" ), RecoDecay::constrainAngle (particle1.phi (), -PIHalf));
590- registry.fill (HIST (" hYMCGen" ), yD);
591693
592- // prompt and non-prompt division
593- bool isDplusPrompt = particle1.originMcGen () == RecoDecay::OriginType::Prompt;
594- bool isDplusNonPrompt = particle1.originMcGen () == RecoDecay::OriginType::NonPrompt;
595- if (isDplusPrompt) {
596- registry.fill (HIST (" hPtCandMcGenPrompt" ), particle1.pt ());
597- } else if (isDplusNonPrompt) {
598- registry.fill (HIST (" hPtCandMcGenNonPrompt" ), particle1.pt ());
599- }
694+ for (const auto & collision : groupedCollisions) {
600695
601- // Dplus Hadron correlation dedicated section
602- // if it's a Dplus particle, search for Hadron and evaluate correlations
603- registry.fill (HIST (" hcountDplustriggersMCGen" ), 0 , particle1.pt ()); // to count trigger Dplus for normalisation)
604- for (const auto & particleAssoc : mcParticles) {
605- if (std::abs (particleAssoc.eta ()) > etaTrackMax || particleAssoc.pt () < ptTrackMin || particleAssoc.pt () > ptTrackMax) {
696+ if (useSel8 && !collision.sel8 ()) {
606697 continue ;
607698 }
608- if (removeDaughters) {
609- if (particleAssoc.globalIndex () == prongsId[0 ] || particleAssoc.globalIndex () == prongsId[1 ] || particleAssoc.globalIndex () == prongsId[2 ]) {
610- continue ;
611- }
699+
700+ if (std::abs (collision.posZ ()) > zVtxMax) {
701+ continue ;
612702 }
613- if ((std::abs (particleAssoc.pdgCode ()) != kElectron ) && (std::abs (particleAssoc.pdgCode ()) != kMuonMinus ) && (std::abs (particleAssoc.pdgCode ()) != kPiPlus ) && (std::abs (particleAssoc.pdgCode ()) != kKPlus ) && (std::abs (particleAssoc.pdgCode ()) != kProton )) {
703+
704+ if (selNoSameBunchPileUpColl &&
705+ !(collision.selection_bit (o2::aod::evsel::kNoSameBunchPileup ))) {
614706 continue ;
615707 }
616- if (!particleAssoc.isPhysicalPrimary ()) {
708+
709+ if (!collision.has_mcCollision ()) {
710+ registry.fill (HIST (" hFakeCollision" ), 0 .);
617711 continue ;
618712 }
619713
620- int trackOrigin = RecoDecay::getCharmHadronOrigin (mcParticles, particleAssoc, true );
621- registry.fill (HIST (" hPtParticleAssocMcGen" ), particleAssoc.pt ());
622- entryDplusHadronPair (getDeltaPhi (particleAssoc.phi (), particle1.phi ()),
623- particleAssoc.eta () - particle1.eta (),
624- particle1.pt (),
625- particleAssoc.pt (),
626- poolBin);
627- entryDplusHadronRecoInfo (MassDPlus, true );
628- entryDplusHadronGenInfo (isDplusPrompt, particleAssoc.isPhysicalPrimary (), trackOrigin);
629- } // end associated loop
630- } // end trigger
714+ // MC particles with reconstructed-collision selection
715+ runMcGenDplusHadronAnalysis (groupedMcParticles, groupedMcParticles, poolBin, counterDplusHadron);
716+ }
717+
718+ }
719+ else {
720+ // MC particles without reconstructed-collision selection (preliminay approval approach)
721+ runMcGenDplusHadronAnalysis (groupedMcParticles, groupedMcParticles, poolBin, counterDplusHadron);
722+ }
723+
631724 registry.fill (HIST (" hcountDplusHadronPerEvent" ), counterDplusHadron);
632725 registry.fill (HIST (" hZvtx" ), mcCollision.posZ ());
633- // registry.fill(HIST("hMultiplicity"), getTracksSize(mcCollision));
634726 }
727+ }
635728 PROCESS_SWITCH (HfCorrelatorDplusHadrons, processMcGen, " Process MC Gen mode" , false );
636729
637730 void processDataMixedEvent (SelCollisionsWithDplus const & collisions,
0 commit comments