Skip to content

Commit 150d8b9

Browse files
committed
AddFinalStage
1 parent 1cb25ed commit 150d8b9

1 file changed

Lines changed: 150 additions & 3 deletions

File tree

PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx

Lines changed: 150 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2909,6 +2909,14 @@ struct HStrangeCorrelation {
29092909
// AnyTrack any truth PairLossTriggerAnyCollision
29102910
// AnyTrackK0 truth any PairLossV0AnyCollision
29112911
// AnyTrackBoth any any both stages at once
2912+
// Final final final fully selected, both in one collision
2913+
// "final" means the object has a reconstructed counterpart that survives
2914+
// every selection the reconstructed correlation applies, and for the pair
2915+
// both counterparts must live in the same reconstructed collision. Final/
2916+
// is therefore the direct truth-coordinate counterpart of the ordinary
2917+
// reconstructed correlation: Rec/Final isolates what is left once pair
2918+
// loss is divided out -- duplicate reconstructed objects, fakes and bin
2919+
// migration.
29122920
// Every folder has the same three objects -- sameEvent/K0Short, hTrigger,
29132921
// hK0Short -- and each of them is filled at the level its own folder
29142922
// prescribes, so a folder can be normalised without looking at any other.
@@ -2928,6 +2936,9 @@ struct HStrangeCorrelation {
29282936
histos.add("ClosureTest/PairLossK0/AnyTrackK0/hK0Short", "truth K0s with a V0-candidate match in any associated collision;#it{p}_{T}^{truth} (GeV/#it{c});#eta^{truth};#varphi^{truth}", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisPhi});
29292937
histos.add("ClosureTest/PairLossK0/AnyTrackBoth/hTrigger", "truth triggers with a reconstructed-track match in any associated collision;#it{p}_{T}^{truth} (GeV/#it{c});#eta^{truth};#varphi^{truth}", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisPhi});
29302938
histos.add("ClosureTest/PairLossK0/AnyTrackBoth/hK0Short", "truth K0s with a V0-candidate match in any associated collision;#it{p}_{T}^{truth} (GeV/#it{c});#eta^{truth};#varphi^{truth}", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisPhi});
2939+
histos.add("ClosureTest/PairLossK0/Final/sameEvent/K0Short", "truth h-K0 pairs whose trigger and K0 both have a fully selected reconstructed counterpart in the same reconstructed collision", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim});
2940+
histos.add("ClosureTest/PairLossK0/Final/hTrigger", "truth triggers with a fully selected reconstructed counterpart;#it{p}_{T}^{truth} (GeV/#it{c});#eta^{truth};#varphi^{truth}", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisPhi});
2941+
histos.add("ClosureTest/PairLossK0/Final/hK0Short", "truth K0s with a fully selected reconstructed counterpart;#it{p}_{T}^{truth} (GeV/#it{c});#eta^{truth};#varphi^{truth}", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisPhi});
29312942
}
29322943
for (int i = 0; i < AssocParticleTypes; i++) {
29332944
if (TESTBIT(doCorrelation, i)) {
@@ -5104,7 +5115,9 @@ struct HStrangeCorrelation {
51045115
aod::McParticles const& mcParticles,
51055116
aod::V0MCCores const& v0MCCores,
51065117
V0DatasWithoutTrackX const& v0Candidates,
5107-
TracksCompleteMC const& tracks)
5118+
TracksCompleteMC const& tracks,
5119+
aod::TriggerTracks const& triggerTracks,
5120+
aod::AssocV0s const& associatedV0s)
51085121
{
51095122

51105123
// Reproduce the first processPairLossK0MC stages without changing the
@@ -5119,6 +5132,11 @@ struct HStrangeCorrelation {
51195132
// candidate pointing back to it, in any associated collision
51205133
// (stage PairLossV0AnyCollision)
51215134
// AnyTrackBoth both requirements at the same time
5135+
// Final the strictest stage: both the trigger and the K0 must have a
5136+
// *fully selected* reconstructed counterpart -- the very
5137+
// TriggerTracks and AssocV0s entries, passing the very final
5138+
// selections, that the reconstructed correlation is built from --
5139+
// and both in one and the same reconstructed collision
51225140
auto fillPairLossK0TruthAndAnyTrack = [&]() {
51235141
if (!pairLossK0Configurations.doClosureTestStages) {
51245142
return;
@@ -5161,6 +5179,125 @@ struct HStrangeCorrelation {
51615179
}
51625180
}
51635181

5182+
// Final-stage bookkeeping. A truth object counts here only if it has at least
5183+
// one fully selected reconstructed counterpart, where "fully selected" means
5184+
// the exact same conditions the reconstructed correlation imposes in
5185+
// fillCorrelationsV0(): the object is in the TriggerTracks / AssocV0s table
5186+
// to begin with, and it then passes isValidTrigger() resp. the whole V0
5187+
// selection chain including the dE/dx compatibility bit and the peak mass
5188+
// window. The selections are read from the filter tables instead of being
5189+
// recomputed from raw tracks so that this stage cannot drift away from the
5190+
// reconstructed analysis it exists to be compared against.
5191+
//
5192+
// The sets are built per reconstructed collision and a pair is required to be
5193+
// final within one and the same collision: the reconstructed same-event
5194+
// correlation only ever pairs a trigger with a V0 sitting in the same vertex,
5195+
// so a pair split across two reconstructed vertices of one MC collision must
5196+
// not count as final here either.
5197+
//
5198+
// N.B.: the reconstructed autocorrelation rejection (trigger track identical
5199+
// to a V0 daughter track) is deliberately not replicated. It is a no-op as
5200+
// soon as the trigger is required to be a physical primary, because
5201+
// mcTrue(IndexK0) forces the daughters to be genuine -- hence secondary --
5202+
// K0 decay products.
5203+
std::vector<std::pair<std::unordered_set<int64_t>, std::unordered_set<int64_t>>> pairLossFinalPerCollision;
5204+
for (auto const& collision : recCollisions) {
5205+
std::unordered_set<int64_t> finalTriggerMcIds;
5206+
std::unordered_set<int64_t> finalK0McIds;
5207+
5208+
const auto finalTriggerSlice = triggerTracks.sliceBy(collisionSliceTracks, collision.globalIndex());
5209+
for (auto const& triggerEntry : finalTriggerSlice) {
5210+
auto track = triggerEntry.track_as<TracksCompleteMC>();
5211+
if (!track.has_mcParticle()) {
5212+
continue;
5213+
}
5214+
if (!isValidTrigger(track, triggerEntry.isLeading())) {
5215+
continue;
5216+
}
5217+
if (trackSelection.checkForITSTPCMissmatchMC && bitcheck(triggerEntry.mcMask(), 13)) {
5218+
continue;
5219+
}
5220+
if (masterConfigurations.doTriggPhysicalPrimary && !triggerEntry.mcPhysicalPrimary()) {
5221+
continue;
5222+
}
5223+
finalTriggerMcIds.insert(track.mcParticleId());
5224+
}
5225+
5226+
const auto finalV0Slice = associatedV0s.sliceBy(collisionSliceV0s, collision.globalIndex());
5227+
for (auto const& assocEntry : finalV0Slice) {
5228+
auto v0 = assocEntry.v0Core_as<V0DatasWithoutTrackX>();
5229+
const auto v0MC = v0MCCores.iteratorAt(v0.globalIndex());
5230+
if (v0MC.particleIdMC() < 0 || v0MC.pdgCode() != PDG_t::kK0Short || !assocEntry.mcTrue(IndexK0)) {
5231+
continue;
5232+
}
5233+
auto positiveTrack = v0.posTrack_as<TracksCompleteMC>();
5234+
auto negativeTrack = v0.negTrack_as<TracksCompleteMC>();
5235+
bool passesFinalSelection = true;
5236+
if (masterConfigurations.doPPAnalysis) {
5237+
passesFinalSelection = v0.v0radius() >= v0Selection.v0RadiusMin && v0.v0radius() <= v0Selection.v0RadiusMax &&
5238+
std::abs(v0.dcapostopv()) >= v0Selection.dcapostopv && std::abs(v0.dcanegtopv()) >= v0Selection.dcanegtopv &&
5239+
v0.v0cosPA() >= v0Selection.v0cospa && v0.dcaV0daughters() <= v0Selection.dcaV0dau;
5240+
} else {
5241+
const float dcaCut = v0Selection.dcaDaugToPVForK0s == 0.0f ? v0Selection.dcaMesonToPV : v0Selection.dcaDaugToPVForK0s;
5242+
const bool passesLifetime = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) *
5243+
o2::constants::physics::MassK0Short <
5244+
v0Selection.lifetimecutK0S;
5245+
const bool passesDaughterDcaAndArmenteros = std::abs(v0.dcapostopv()) > dcaCut && std::abs(v0.dcanegtopv()) > dcaCut &&
5246+
v0.qtarm() * v0Selection.armPodCut > std::abs(v0.alpha());
5247+
passesFinalSelection = v0SelectedPbPb(v0) && passesLifetime && passesDaughterDcaAndArmenteros;
5248+
}
5249+
passesFinalSelection = passesFinalSelection && positiveTrack.tpcNClsCrossedRows() >= trackSelection.minTPCNCrossedRowsAssociated &&
5250+
negativeTrack.tpcNClsCrossedRows() >= trackSelection.minTPCNCrossedRowsAssociated;
5251+
if (trackSelection.checksRequireTPCChi2) {
5252+
passesFinalSelection = passesFinalSelection && positiveTrack.tpcChi2NCl() >= trackSelection.minTPCChi2PerClusterAssociated &&
5253+
negativeTrack.tpcChi2NCl() >= trackSelection.minTPCChi2PerClusterAssociated;
5254+
}
5255+
if (trackSelection.requireClusterInITS) {
5256+
passesFinalSelection = passesFinalSelection && positiveTrack.itsNCls() >= trackSelection.minITSClustersForDaughterTracks &&
5257+
negativeTrack.itsNCls() >= trackSelection.minITSClustersForDaughterTracks;
5258+
}
5259+
passesFinalSelection = passesFinalSelection && assocEntry.compatible(IndexK0, trackSelection.dEdxCompatibility) &&
5260+
(!doAssocPhysicalPrimary || assocEntry.mcPhysicalPrimary()) &&
5261+
assocEntry.invMassNSigma(IndexK0) > -massWindowConfigurations.maxPeakNSigma &&
5262+
assocEntry.invMassNSigma(IndexK0) < massWindowConfigurations.maxPeakNSigma &&
5263+
v0.pt() >= axisRanges[2][0] && v0.pt() <= axisRanges[2][1];
5264+
if (!passesFinalSelection) {
5265+
continue;
5266+
}
5267+
finalK0McIds.insert(v0MC.particleIdMC());
5268+
}
5269+
5270+
pairLossFinalPerCollision.emplace_back(std::move(finalTriggerMcIds), std::move(finalK0McIds));
5271+
}
5272+
5273+
// Object-level membership, used only for the single-particle spectra: at
5274+
// least one collision in which the object is fully selected. The pair
5275+
// histogram uses pairLossHasFinalPair() instead, which is stricter.
5276+
auto pairLossHasFinalTrigger = [&](int64_t mcId) {
5277+
for (auto const& perCollision : pairLossFinalPerCollision) {
5278+
if (perCollision.first.count(mcId) > 0) {
5279+
return true;
5280+
}
5281+
}
5282+
return false;
5283+
};
5284+
auto pairLossHasFinalK0 = [&](int64_t mcId) {
5285+
for (auto const& perCollision : pairLossFinalPerCollision) {
5286+
if (perCollision.second.count(mcId) > 0) {
5287+
return true;
5288+
}
5289+
}
5290+
return false;
5291+
};
5292+
auto pairLossHasFinalPair = [&](int64_t triggerMcId, int64_t k0McId) {
5293+
for (auto const& perCollision : pairLossFinalPerCollision) {
5294+
if (perCollision.first.count(triggerMcId) > 0 && perCollision.second.count(k0McId) > 0) {
5295+
return true;
5296+
}
5297+
}
5298+
return false;
5299+
};
5300+
51645301
for (auto const& collision : recCollisions) {
51655302
if (static_cast<int64_t>(collision.globalIndex()) != pairLossBestCollisionId) {
51665303
continue;
@@ -5234,15 +5371,19 @@ struct HStrangeCorrelation {
52345371

52355372
// One entry per object per folder, at the level that folder prescribes:
52365373
// the trigger is at truth level in Truth/ and AnyTrackK0/, at any level in
5237-
// AnyTrack/ and AnyTrackBoth/; the K0 is at truth level in Truth/ and
5238-
// AnyTrack/, at any level in AnyTrackK0/ and AnyTrackBoth/.
5374+
// AnyTrack/ and AnyTrackBoth/, at fully-selected level in Final/; the K0 is
5375+
// at truth level in Truth/ and AnyTrack/, at any level in AnyTrackK0/ and
5376+
// AnyTrackBoth/, at fully-selected level in Final/.
52395377
for (auto const& truthTrigger : pairLossTruthTriggers) {
52405378
histos.fill(HIST("ClosureTest/PairLossK0/Truth/hTrigger"), truthTrigger.pt, truthTrigger.eta, truthTrigger.phi);
52415379
histos.fill(HIST("ClosureTest/PairLossK0/AnyTrackK0/hTrigger"), truthTrigger.pt, truthTrigger.eta, truthTrigger.phi);
52425380
if (pairLossAnyTrackMcParticleIds.find(truthTrigger.globalIndex) != pairLossAnyTrackMcParticleIds.end()) {
52435381
histos.fill(HIST("ClosureTest/PairLossK0/AnyTrack/hTrigger"), truthTrigger.pt, truthTrigger.eta, truthTrigger.phi);
52445382
histos.fill(HIST("ClosureTest/PairLossK0/AnyTrackBoth/hTrigger"), truthTrigger.pt, truthTrigger.eta, truthTrigger.phi);
52455383
}
5384+
if (pairLossHasFinalTrigger(truthTrigger.globalIndex)) {
5385+
histos.fill(HIST("ClosureTest/PairLossK0/Final/hTrigger"), truthTrigger.pt, truthTrigger.eta, truthTrigger.phi);
5386+
}
52465387
}
52475388
for (auto const& truthK0 : pairLossTruthK0s) {
52485389
histos.fill(HIST("ClosureTest/PairLossK0/Truth/hK0Short"), truthK0.pt, truthK0.eta, truthK0.phi);
@@ -5251,6 +5392,9 @@ struct HStrangeCorrelation {
52515392
histos.fill(HIST("ClosureTest/PairLossK0/AnyTrackK0/hK0Short"), truthK0.pt, truthK0.eta, truthK0.phi);
52525393
histos.fill(HIST("ClosureTest/PairLossK0/AnyTrackBoth/hK0Short"), truthK0.pt, truthK0.eta, truthK0.phi);
52535394
}
5395+
if (pairLossHasFinalK0(truthK0.globalIndex)) {
5396+
histos.fill(HIST("ClosureTest/PairLossK0/Final/hK0Short"), truthK0.pt, truthK0.eta, truthK0.phi);
5397+
}
52545398
}
52555399

52565400
for (auto const& truthTrigger : pairLossTruthTriggers) {
@@ -5281,6 +5425,9 @@ struct HStrangeCorrelation {
52815425
if (triggerHasAnyTrack && k0HasAnyV0) {
52825426
histos.fill(HIST("ClosureTest/PairLossK0/AnyTrackBoth/sameEvent/K0Short"), truthDeltaPhi, truthDeltaEta, truthK0.pt, truthTrigger.pt, pairLossBestCollisionVtxZ, pairLossBestCollisionMultiplicity);
52835427
}
5428+
if (pairLossHasFinalPair(truthTrigger.globalIndex, truthK0.globalIndex)) {
5429+
histos.fill(HIST("ClosureTest/PairLossK0/Final/sameEvent/K0Short"), truthDeltaPhi, truthDeltaEta, truthK0.pt, truthTrigger.pt, pairLossBestCollisionVtxZ, pairLossBestCollisionMultiplicity);
5430+
}
52845431
}
52855432
}
52865433
return;

0 commit comments

Comments
 (0)