diff --git a/PWGLF/Tasks/Resonances/xi1530Analysisqa.cxx b/PWGLF/Tasks/Resonances/xi1530Analysisqa.cxx index 3ed15c1328d..c7b1ab13ed5 100644 --- a/PWGLF/Tasks/Resonances/xi1530Analysisqa.cxx +++ b/PWGLF/Tasks/Resonances/xi1530Analysisqa.cxx @@ -31,6 +31,7 @@ #include #include #include +#include #include #include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) @@ -49,6 +50,7 @@ #include #include #include +#include #include using namespace o2; @@ -81,6 +83,12 @@ struct Xi1530Analysisqa { using ResoMicroTracks = aod::ResoMicroTracks_001; using ResoMCCols = soa::Join; + // This native generator status is a production-specific injection tag. + static constexpr auto IsInjectedParent = [](auto const& mcparent) { + constexpr int InjectedGeneratorStatus = -11; + return o2::mcgenstatus::getGenStatusCode(mcparent.statusCode()) == InjectedGeneratorStatus; + }; + // Own just the event rows: zero-copy slices would retain entire DF buffers. struct MixingCollision { float x, y, z, centrality, multiplicity; @@ -142,8 +150,8 @@ struct Xi1530Analysisqa { struct : ConfigurableGroup { // Primary track selections - Configurable cMinPtcut{"cMinPtcut", 0.15, "Track minium pt cut"}; - Configurable cMaxetacut{"cMaxetacut", 0.8, "Track maximum eta cut"}; + Configurable cMinPtcut{"cMinPtcut", 0.00, "Track minium pt cut"}; + Configurable cMaxetacut{"cMaxetacut", 999., "Track maximum eta cut"}; Configurable cfgPrimaryTrack{"cfgPrimaryTrack", true, "Primary track selection"}; Configurable cfgPVContributor{"cfgPVContributor", true, "PV contributor track selection"}; @@ -152,6 +160,11 @@ struct Xi1530Analysisqa { Configurable cfgTPCRows{"cfgTPCRows", 80, "Minimum Number of TPC Crossed Rows "}; + // Micro001 quality cuts use strict lower bounds; -1 preserves the previous selection. + // Full ResoTracks has no ITS cluster map and retains cfgTPCcluster/cfgTPCRows. + Configurable cfgITSNCls{"cfgITSNCls", -1, "Require ITS NCls > cut; -1 disables the cut"}; + Configurable cfgITSNClsInnerBarrel{"cfgITSNClsInnerBarrel", -1, "Require inner-barrel ITS NCls > cut; -1 disables the cut"}; + Configurable cfgRapidityMinCut{"cfgRapidityMinCut", -0.5, "Rapidity cut for tracks"}; Configurable cfgRapidityMaxCut{"cfgRapidityMaxCut", 0.5, "Rapidity cut for tracks"}; @@ -315,6 +328,8 @@ struct Xi1530Analysisqa { Configurable cfgMaxRot{"cfgMaxRot", 7.0 * constants::math::PI / 6.0, "Maximum of rotation"}; Configurable cfgRotPion{"cfgRotPion", true, "Rotate pion"}; Configurable cfgNrotBkg{"cfgNrotBkg", 4, "Number of rotated copies (background) per each original candidate"}; + + Configurable cMCInjection{"cMCInjection", true, "Select generated MC parents with native status -11 (production-specific injection tag)"}; } additionalConfig; //*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*// @@ -589,7 +604,13 @@ struct Xi1530Analysisqa { if (std::abs(track.dcaXY()) >= dcaXYCut || std::abs(track.dcaZ()) >= dcaZCut) { return false; } - if constexpr (!IsResoMicrotrack) { + if constexpr (IsResoMicrotrack) { + if (track.itsNCls() <= primarytrackConfig.cfgITSNCls || + track.itsNClsInnerBarrel() <= primarytrackConfig.cfgITSNClsInnerBarrel || + track.tpcNClsCrossedRows() <= primarytrackConfig.cfgTPCRows) { + return false; + } + } else { if (track.tpcNClsFound() <= primarytrackConfig.cfgTPCcluster) { return false; } @@ -808,9 +829,25 @@ struct Xi1530Analysisqa { return properLifetime; } + // Build once per selected collision, not once per reconstructed pair. + std::unordered_set getInjectedMotherIds(aod::ResoMCParents_001 const& parents) + { + std::unordered_set motherIds; + if (!additionalConfig.cMCInjection) { + return motherIds; + } + for (auto const& parent : parents) { + if (std::abs(parent.pdgCode()) == kXiStar && IsInjectedParent(parent)) { + motherIds.insert(parent.originalMcParticleId()); + } + } + return motherIds; + } + template void fillHistograms(const CollisionType& collision, const centType& inCent, const TracksType& dTracks1, const TracksTypeCasc& dTracks2, - const MixingCollision* cascadeCollision = nullptr) // Order: ResoColl, ResoTrack, ResoCascTrack + const MixingCollision* cascadeCollision = nullptr, + const std::unordered_set& injectedMotherIds = {}) // Order: ResoColl, ResoTrack, ResoCascTrack { auto cent = inCent; @@ -1194,6 +1231,9 @@ struct Xi1530Analysisqa { if (xiCand.motherId() < 0 || pionCand.motherId() != xiCand.motherId()) { continue; } + if (additionalConfig.cMCInjection && !injectedMotherIds.contains(xiCand.motherId())) { + continue; + } auto lResonancePtMC = xiCand.motherPt(); if (additionalConfig.cUseTruthRapidity) { const bool passesTruthRapidity = xiCand.motherRap() > primarytrackConfig.cfgRapidityMinCut && xiCand.motherRap() < primarytrackConfig.cfgRapidityMaxCut; @@ -1352,7 +1392,8 @@ struct Xi1530Analysisqa { // Calculate numerator for the Acceptance x Efficiency void processMC(ResoMCCols::iterator const& resoCollision, soa::Join const& cascTracks, - soa::Join const& resoTracks) + soa::Join const& resoTracks, + aod::ResoMCParents_001 const& resoParents) { auto inCent = resoCollision.cent(); const auto multiplicity = resoCollision.multiplicity(); @@ -1365,12 +1406,14 @@ struct Xi1530Analysisqa { if (histoConfig.multQA) { histos.fill(HIST("multQA/h2MultCent"), inCent, multiplicity); } - fillHistograms(resoCollision, inCent, resoTracks, cascTracks); + const auto injectedMotherIds = getInjectedMotherIds(resoParents); + fillHistograms(resoCollision, inCent, resoTracks, cascTracks, nullptr, injectedMotherIds); } void processMCMicro(ResoMCCols::iterator const& resoCollision, soa::Join const& cascTracks, - soa::Join const& resoTracks) + soa::Join const& resoTracks, + aod::ResoMCParents_001 const& reParent) { if ((additionalConfig.cRecoINELgt0 && !resoCollision.isRecINELgt0()) || (additionalConfig.cMCINELgt0 && !resoCollision.isINELgt0()) || @@ -1380,7 +1423,8 @@ struct Xi1530Analysisqa { if (histoConfig.multQA) { histos.fill(HIST("multQA/h2MultCent"), resoCollision.cent(), resoCollision.multiplicity()); } - fillHistograms(resoCollision, resoCollision.cent(), resoTracks, cascTracks); + const auto injectedMotherIds = getInjectedMotherIds(reParent); + fillHistograms(resoCollision, resoCollision.cent(), resoTracks, cascTracks, nullptr, injectedMotherIds); } // Calculate denominator for the Acceptance x Efficiency, actually it is not Trueth info... @@ -1402,6 +1446,9 @@ struct Xi1530Analysisqa { if (std::abs(part.pdgCode()) != kXiStar) { continue; } + if (additionalConfig.cMCInjection && !IsInjectedParent(part)) { + continue; + } if ((part.y() <= primarytrackConfig.cfgRapidityMinCut) || (part.y() >= primarytrackConfig.cfgRapidityMaxCut)) { continue; }