@@ -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" };
@@ -308,9 +316,129 @@ struct HfCorrelatorDplusHadrons {
308316 registry.add (" hEtaMcGen" , " D+,Hadron particles - MC Gen" , {HistType::kTH1F , {axisEta}});
309317 registry.add (" hPhiMcGen" , " D+,Hadron particles - MC Gen" , {HistType::kTH1F , {axisPhi}});
310318 registry.add (" hMultFT0AMcGen" , " D+,Hadron multiplicity FT0A - MC Gen" , {HistType::kTH1F , {axisMultiplicity}});
319+ registry.add (" hFakeCollision" , " Fake collision counter" , {HistType::kTH1F , {{1 , -0.5 , 0.5 , " n fake coll" }}});
311320 corrBinning = {{binsZVtx, binsMultiplicity}, true };
312321 }
313322
323+ template <typename ParticleContainer, typename AssocContainer>
324+ void runMcGenDplusHadronAnalysis (const ParticleContainer& particlesToLoop, const AssocContainer& groupedMcParticles, int poolBin, int & counterDplusHadron)
325+ {
326+ for (const auto & particle : particlesToLoop) {
327+
328+ if (std::abs (particle.pdgCode ()) != Pdg::kDPlus ) {
329+ continue ;
330+ }
331+
332+ if (std::abs (particle.flagMcMatchGen ()) != hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) {
333+ continue ;
334+ }
335+
336+ double yD = RecoDecay::y (particle.pVector (), MassDPlus);
337+
338+ if (std::abs (yD) > yCandGenMax ||
339+ particle.pt () < ptCandMin ||
340+ particle.pt () > ptCandMax) {
341+ continue ;
342+ }
343+
344+ std::vector<int > listDaughters{};
345+ std::array<int , NDaughters> const arrDaughDplusPDG = {+kPiPlus , -kKPlus , kPiPlus };
346+ std::array<int , NDaughters> prongsId{};
347+
348+ RecoDecay::getDaughters (particle, &listDaughters, arrDaughDplusPDG, 2 );
349+
350+ if (listDaughters.size () != NDaughters) {
351+ continue ;
352+ }
353+
354+ bool isDaughtersOk = true ;
355+ int counterDaughters = 0 ;
356+
357+ for (const auto & dauIdx : listDaughters) {
358+ auto daughI = particlesToLoop.rawIteratorAt (dauIdx - particlesToLoop.offset ());
359+
360+ if (std::abs (daughI.eta ()) >= EtaDaughtersMax) {
361+ isDaughtersOk = false ;
362+ break ;
363+ }
364+
365+ prongsId[counterDaughters++] = daughI.globalIndex ();
366+ }
367+
368+ if (!isDaughtersOk) { // Skip this D+ candidate if any daughter fails eta cut
369+ continue ;
370+ }
371+ counterDplusHadron++;
372+
373+ registry.fill (HIST (" hDplusBin" ), poolBin);
374+ registry.fill (HIST (" hPtCandMCGen" ), particle.pt ());
375+ registry.fill (HIST (" hEtaMcGen" ), particle.eta ());
376+ registry.fill (HIST (" hPhiMcGen" ), RecoDecay::constrainAngle (particle.phi (), -PIHalf));
377+ registry.fill (HIST (" hYMCGen" ), yD);
378+
379+ // Prompt / Non-prompt separation
380+ bool isDplusPrompt = particle.originMcGen () == RecoDecay::OriginType::Prompt;
381+ bool isDplusNonPrompt = particle.originMcGen () == RecoDecay::OriginType::NonPrompt;
382+
383+ if (isDplusPrompt) {
384+ registry.fill (HIST (" hPtCandMcGenPrompt" ), particle.pt ());
385+ } else if (isDplusNonPrompt) {
386+ registry.fill (HIST (" hPtCandMcGenNonPrompt" ), particle.pt ());
387+ }
388+
389+ // Count triggers
390+ registry.fill (HIST (" hcountDplustriggersMCGen" ), 0 , particle.pt ());
391+
392+ for (const auto & particleAssoc : groupedMcParticles) {
393+
394+ if (std::abs (particleAssoc.eta ()) > etaTrackMax ||
395+ particleAssoc.pt () < ptTrackMin ||
396+ particleAssoc.pt () > ptTrackMax) {
397+ continue ;
398+ }
399+
400+ // Remove daughters if requested
401+ if (removeDaughters) {
402+ if (particleAssoc.globalIndex () == prongsId[0 ] ||
403+ particleAssoc.globalIndex () == prongsId[1 ] ||
404+ particleAssoc.globalIndex () == prongsId[2 ]) {
405+ continue ;
406+ }
407+ }
408+
409+ // Particle species selection
410+ if ((std::abs (particleAssoc.pdgCode ()) != kElectron ) &&
411+ (std::abs (particleAssoc.pdgCode ()) != kMuonMinus ) &&
412+ (std::abs (particleAssoc.pdgCode ()) != kPiPlus ) &&
413+ (std::abs (particleAssoc.pdgCode ()) != kKPlus ) &&
414+ (std::abs (particleAssoc.pdgCode ()) != kProton )) {
415+ continue ;
416+ }
417+
418+ if (!particleAssoc.isPhysicalPrimary ()) {
419+ continue ;
420+ }
421+
422+ int trackOrigin = RecoDecay::getCharmHadronOrigin (groupedMcParticles,
423+ particleAssoc,
424+ true );
425+
426+ registry.fill (HIST (" hPtParticleAssocMcGen" ), particleAssoc.pt ());
427+ entryDplusHadronPair (
428+ getDeltaPhi (particleAssoc.phi (), particle.phi ()),
429+ particleAssoc.eta () - particle.eta (),
430+ particle.pt (),
431+ particleAssoc.pt (),
432+ poolBin);
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,
@@ -536,101 +664,65 @@ struct HfCorrelatorDplusHadrons {
536664 PROCESS_SWITCH (HfCorrelatorDplusHadrons, processMcRec, " Process MC Reco mode" , true );
537665
538666 // / Dplus-Hadron correlation pair builder - for MC gen-level analysis (no filter/selection, only true signal)
539- void processMcGen (SelCollisionsWithDplusMc::iterator const & mcCollision,
667+ void processMcGen (CollisionsMc const & mcCollisions,
668+ soa::Join<aod::Collisions, aod::FT0Mults, aod::EvSels, aod::McCollisionLabels> const & collisions,
540669 CandDplusMcGen const & mcParticles)
541670 {
542- int counterDplusHadron = 0 ;
543- registry.fill (HIST (" hMCEvtCount" ), 0 );
544-
545671 BinningTypeMcGen const corrBinningMcGen{{binsZVtx, binsMultiplicityMc}, true };
546- int poolBin = corrBinningMcGen.getBin (std::make_tuple (mcCollision.posZ (), mcCollision.multMCFT0A ()));
547- registry.fill (HIST (" hMultFT0AMcGen" ), mcCollision.multMCFT0A ());
548672
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) {
560- continue ;
561- }
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) {
569- continue ;
570- }
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++;
673+ for (const auto & mcCollision : mcCollisions) {
585674
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);
675+ int counterDplusHadron = 0 ;
676+ registry.fill (HIST (" hMCEvtCount" ), 0 );
591677
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- }
678+ int poolBin = corrBinningMcGen.getBin (std::make_tuple (mcCollision.posZ (), mcCollision.multMCFT0A ()));
679+ registry.fill (HIST (" hMultFT0AMcGen" ), mcCollision.multMCFT0A ());
600680
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) {
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 ) {
606687 continue ;
607688 }
608- if (removeDaughters) {
609- if (particleAssoc.globalIndex () == prongsId[0 ] || particleAssoc.globalIndex () == prongsId[1 ] || particleAssoc.globalIndex () == prongsId[2 ]) {
610- continue ;
611- }
612- }
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 )) {
689+
690+ if (groupedCollisions.size () > 1 && removeCollWSplitVtx) {
614691 continue ;
615692 }
616- if (!particleAssoc.isPhysicalPrimary ()) {
617- continue ;
693+
694+ for (const auto & collision : groupedCollisions) {
695+
696+ if (useSel8 && !collision.sel8 ()) {
697+ continue ;
698+ }
699+
700+ if (std::abs (collision.posZ ()) > zVtxMax) {
701+ continue ;
702+ }
703+
704+ if (selNoSameBunchPileUpColl &&
705+ !(collision.selection_bit (o2::aod::evsel::kNoSameBunchPileup ))) {
706+ continue ;
707+ }
708+
709+ if (!collision.has_mcCollision ()) {
710+ registry.fill (HIST (" hFakeCollision" ), 0 .);
711+ continue ;
712+ }
713+
714+ // MC particles with reconstructed-collision selection
715+ runMcGenDplusHadronAnalysis (groupedMcParticles, groupedMcParticles, poolBin, counterDplusHadron);
618716 }
619717
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
631- registry.fill (HIST (" hcountDplusHadronPerEvent" ), counterDplusHadron);
632- registry.fill (HIST (" hZvtx" ), mcCollision.posZ ());
633- // registry.fill(HIST("hMultiplicity"), getTracksSize(mcCollision));
718+ } else {
719+ // MC particles without reconstructed-collision selection (preliminary approval approach)
720+ runMcGenDplusHadronAnalysis (groupedMcParticles, groupedMcParticles, poolBin, counterDplusHadron);
721+ }
722+
723+ registry.fill (HIST (" hcountDplusHadronPerEvent" ), counterDplusHadron);
724+ registry.fill (HIST (" hZvtx" ), mcCollision.posZ ());
725+ }
634726 }
635727 PROCESS_SWITCH (HfCorrelatorDplusHadrons, processMcGen, " Process MC Gen mode" , false );
636728
0 commit comments