From 80bbb34027d4123d5eafb5c33ab5c3997f4ba1c8 Mon Sep 17 00:00:00 2001 From: Tucker Hwang Date: Sat, 12 Sep 2026 23:55:00 -0700 Subject: [PATCH 1/3] Update track efficiency task --- PWGJE/Tasks/trackEfficiency.cxx | 122 +++++++++++++++++--------------- 1 file changed, 66 insertions(+), 56 deletions(-) diff --git a/PWGJE/Tasks/trackEfficiency.cxx b/PWGJE/Tasks/trackEfficiency.cxx index 0eed47da158..b7f98eadbf8 100644 --- a/PWGJE/Tasks/trackEfficiency.cxx +++ b/PWGJE/Tasks/trackEfficiency.cxx @@ -56,6 +56,7 @@ struct TrackEfficiency { Configurable trackSelections{"trackSelections", "globalTracks", "set track selections; other option: uniformTracks"}; Configurable skipMBGapEvents{"skipMBGapEvents", false, "flag to choose to reject min. bias gap events"}; Configurable applyRCTSelections{"applyRCTSelections", true, "decide to apply RCT selections"}; + Configurable rctSelection{"rctSelection", "CBT", "RCT selection to apply if applyRCTSelections is set to true"}; // Tracking efficiency process function configurables: Configurable checkPrimaryPart{"checkPrimaryPart", true, "0: doesn't check mcparticle.isPhysicalPrimary() - 1: checks particle.isPhysicalPrimary()"}; @@ -68,7 +69,14 @@ struct TrackEfficiency { Configurable centralityMax{"centralityMax", 999, ""}; Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; Configurable trackDcaZmax{"trackDcaZmax", 99, "additional cut on dcaZ to PV for tracks; uniformTracks in particular don't cut on this at all"}; - Configurable nBinsLowPt{"nBinsLowPt", 200, "number of pt bins for low pt (below 10GeV) efficiency histograms"}; + Configurable ptHighEffMax{"ptHighEffMax", 100., "maximum pT in efficiency histograms for high pT (lower limit set by upper limit for low pT)"}; + Configurable ptHighEffNBins{"ptHighEffNBins", 18, "number of pt bins in efficiency histograms for high pT"}; + ConfigurableAxis lowPtEffBinning{"lowPtEffBinning", { + 200, + 0., + 10., + }, + "binning of low pT axis in efficiency histograms"}; // Track QA process function configurables: Configurable trackQAEtaMin{"trackQAEtaMin", -0.9, "minimum eta acceptance for tracks in the processTracks QA"}; @@ -78,11 +86,10 @@ struct TrackEfficiency { Configurable trackOccupancyInTimeRangeMax{"trackOccupancyInTimeRangeMax", 999999, "maximum occupancy of tracks in neighbouring collisions in a given time range; only applied for reconstructed tracks, not mc particles"}; Configurable trackOccupancyInTimeRangeMin{"trackOccupancyInTimeRangeMin", -999999, "minimum occupancy of tracks in neighbouring collisions in a given time range; only applied for reconstructed tracks, not mc particles"}; - Configurable> centralityBinning{"centralityBinning", {0., 10., 50., 70., 100}, "binning of centrality histograms"}; - Configurable intRateNBins{"intRateNBins", 50, "number of bins for interaction rate axis"}; - Configurable intRateMax{"intRateMax", 50000.0, "maximum value of interaction rate axis"}; - Configurable phiEffNBins{"phiEffNBins", 200, "number of bins for phi axis in efficiency plots"}; - Configurable etaEffNBins{"etaEffNBins", 200, "number of bins for eta axis in efficiency plots"}; + ConfigurableAxis centBinning{"centBinning", {VARIABLE_WIDTH, 0., 10., 50., 70., 100}, "binning of centrality histograms"}; + ConfigurableAxis intRateBinning{"intRateBinning", {50, 0., 50000.0}, "binning for interaction rate axis"}; + ConfigurableAxis phiEffBinning{"phiEffBinning", {200, -1., 7.}, "binning for phi axis in efficiency histograms"}; + ConfigurableAxis etaEffBinning{"etaEffBinning", {200, -1., 1.}, "binning for eta axis in efficiency histograms"}; Configurable ptHatMin{"ptHatMin", -999, "min pT hat of collisions"}; Configurable ptHatMax{"ptHatMax", 999, "max pT hat of collisions"}; @@ -247,18 +254,18 @@ struct TrackEfficiency { LOGP(info, "Using standard track selection: %s", trackSelections.value); } - AxisSpec ptAxisEff = {nBinsLowPt, 0., 10., "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec ptAxisHighEff = {18, 10., 100., "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec etaAxisEff = {etaEffNBins, -1.0, 1.0, "#eta"}; - AxisSpec phiAxisEff = {phiEffNBins, -1.0, 7., "#phi"}; - AxisSpec centAxis = {centralityBinning, "centrality (%)"}; - AxisSpec intRateAxis = {intRateNBins, 0., intRateMax, "int. rate (kHz)"}; + AxisSpec ptAxisEff = {lowPtEffBinning, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec ptAxisHighEff = {ptHighEffNBins, ptAxisEff.binEdges[-1], ptHighEffMax, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec etaAxisEff{etaEffBinning, "#eta"}; + AxisSpec phiAxisEff{phiEffBinning, "#phi"}; + AxisSpec centAxis = {centBinning, "centrality (%)"}; + AxisSpec intRateAxis = {intRateBinning, "int. rate (kHz)"}; AxisSpec occupancyAxis = {140, -0.5, 13999.5, "occupancy"}; AxisSpec nTracksAxis = {16001, -1., 16000, "n tracks"}; AxisSpec dcaxyAxis = {1000, -1.0, 1.0, "dca_{xy}"}; AxisSpec dcazAxis = {4000, -4.0, 4.0, "dca_{z}"}; - if (doprocessEFficiencyPurity || doprocessEFficiencyPurityWeighted || doprocessQcCheck) { + if (doprocessEfficiencyPurity || doprocessEfficiencyPurityWeighted || doprocessQcCheck) { registry.add("hMcCollCutsCounts", "McColl cuts count checks", {HistType::kTH1F, {{10, 0., 10.}}}); registry.get(HIST("hMcCollCutsCounts"))->GetXaxis()->SetBinLabel(1, "allMcColl"); @@ -283,11 +290,11 @@ struct TrackEfficiency { registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(2, "trackSel"); registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(3, "hasMcParticle"); - if (doprocessEFficiencyPurity || doprocessQcCheck) { + if (doprocessEfficiencyPurity || doprocessQcCheck) { registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(4, "mcPartIsPrimary"); registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(5, "etaAcc"); // not actually applied here but it will give an idea of what will be done in the post processing } - if (doprocessEFficiencyPurityWeighted) { + if (doprocessEfficiencyPurityWeighted) { registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(4, "ptHatMaxFraction"); registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(5, "mcPartIsPrimary"); registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(6, "etaAcc"); // not actually applied here but it will give an idea of what will be done in the post processing @@ -457,7 +464,7 @@ struct TrackEfficiency { Filter particleCuts = (aod::jmcparticle::pt >= trackQAPtMin && aod::jmcparticle::pt < trackQAPtMax && aod::jmcparticle::eta > trackQAEtaMin && aod::jmcparticle::eta < trackQAEtaMax); Filter eventCuts = (nabs(aod::jcollision::posZ) < vertexZCut); - void processEFficiencyPurity(aod::JetMcCollisions::iterator const& mcCollision, + void processEfficiencyPurity(aod::JetMcCollisions::iterator const& mcCollision, soa::SmallGroups const& collisions, // smallgroups gives only the collisions associated to the current mccollision, thanks to the mccollisionlabel pre-integrated in jetcollisionsmcd soa::Join const& jetTracks, soa::Join const&, @@ -489,8 +496,8 @@ struct TrackEfficiency { bool hasSel8Coll = false; bool centralityCheck = false; bool occupancyCheck = false; - if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) - if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have their first associated collision not reconstructed + if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) + if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents, applyRCTSelections, rctSelection)) { // Skipping MC events that have their first associated collision not reconstructed hasSel8Coll = true; } if (!checkOccupancy || ((trackOccupancyInTimeRangeMin < collisions.begin().trackOccupancyInTimeRange()) && (collisions.begin().trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMax))) { // check occupancy only in GP Pb-Pb MC @@ -502,7 +509,7 @@ struct TrackEfficiency { } } else if (acceptSplitCollisions == SplitOkCheckAnyAssocColl) { // check that at least one of the reconstructed collisions passes the checks for (auto const& collision : collisions) { - if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split + if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections, rctSelection)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split hasSel8Coll = true; } if (!checkOccupancy || ((trackOccupancyInTimeRangeMin < collision.trackOccupancyInTimeRange()) && (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMax))) { // check occupancy only in GP Pb-Pb MC @@ -574,7 +581,7 @@ struct TrackEfficiency { return; } - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections) || !(std::abs(collision.posZ()) < vertexZCut)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections, rctSelection) || !(std::abs(collision.posZ()) < vertexZCut)) { continue; } @@ -589,7 +596,6 @@ struct TrackEfficiency { if (!track.has_mcParticle()) { registry.fill(HIST("h3_track_pt_track_eta_track_phi_nonassociatedtrack"), track.pt(), track.eta(), track.phi()); - registry.fill(HIST("h3_track_pt_high_track_eta_track_phi_nonassociatedtrack"), track.pt(), track.eta(), track.phi()); continue; } @@ -604,6 +610,7 @@ struct TrackEfficiency { registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_associatedtrack_nonprimary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi()); if (std::find(seenMcParticlesVector.begin(), seenMcParticlesVector.end(), jMcParticleFromTrack.globalIndex()) != seenMcParticlesVector.end()) { + // particle matches to two tracks so it appears again in this loop over tracks, these histograms keep track of the extra entries from this duplication registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_split_nonprimary"), track.pt(), track.eta(), track.phi()); registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_split_nonprimary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi()); @@ -627,6 +634,9 @@ struct TrackEfficiency { registry.fill(HIST("h2_particle_pt_high_track_pt_high_residual_associatedtrack_primary"), jMcParticleFromTrack.pt(), (jMcParticleFromTrack.pt() - track.pt()) / jMcParticleFromTrack.pt()); if (std::find(seenMcParticlesVector.begin(), seenMcParticlesVector.end(), jMcParticleFromTrack.globalIndex()) != seenMcParticlesVector.end()) { + // particle matches to two tracks so it appears again in this loop over tracks, these histograms keep track of the extra entries from this duplication + // doesn't overlap with the previous std::find call since we looked at non-physical primaries before and now we are only looking at physical primaries + // to get a histogram corrected for the duplication (e.g. for efficiency/resolution studies), you should subtract these histograms below from the corresponding histograms above registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_split_primary"), track.pt(), track.eta(), track.phi()); registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_split_primary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi()); @@ -642,9 +652,9 @@ struct TrackEfficiency { } } } - PROCESS_SWITCH(TrackEfficiency, processEFficiencyPurity, "Histograms for efficiency and purity quantities", true); + PROCESS_SWITCH(TrackEfficiency, processEfficiencyPurity, "Histograms for efficiency and purity quantities", true); - void processEFficiencyPurityWeighted(aod::JetMcCollisions::iterator const& mcCollision, + void processEfficiencyPurityWeighted(aod::JetMcCollisions::iterator const& mcCollision, soa::SmallGroups const& collisions, // smallgroups gives only the collisions associated to the current mccollision, thanks to the mccollisionlabel pre-integrated in jetcollisionsmcd soa::Join const& jetTracks, soa::Join const&, @@ -675,8 +685,8 @@ struct TrackEfficiency { float centrality = -1; bool hasSel8Coll = false; bool centralityCheck = false; - if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) - if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have their first associated collision not reconstructed + if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) + if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents, applyRCTSelections, rctSelection)) { // Skipping MC events that have their first associated collision not reconstructed hasSel8Coll = true; } centrality = checkCentFT0M ? collisions.begin().centFT0M() : collisions.begin().centFT0C(); @@ -685,7 +695,7 @@ struct TrackEfficiency { } } else if (acceptSplitCollisions == SplitOkCheckAnyAssocColl) { // check that at least one of the reconstructed collisions passes the checks for (auto const& collision : collisions) { - if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split + if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections, rctSelection)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split hasSel8Coll = true; } centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -751,7 +761,7 @@ struct TrackEfficiency { return; } - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections) || !(std::abs(collision.posZ()) < vertexZCut)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections, rctSelection) || !(std::abs(collision.posZ()) < vertexZCut)) { continue; } @@ -831,13 +841,13 @@ struct TrackEfficiency { } } } - PROCESS_SWITCH(TrackEfficiency, processEFficiencyPurityWeighted, "Histograms for efficiency and purity quantities for weighted simulations", false); + PROCESS_SWITCH(TrackEfficiency, processEfficiencyPurityWeighted, "Histograms for efficiency and purity quantities for weighted simulations", false); void processTracksFromData(soa::Filtered::iterator const& collision, soa::Filtered> const& jetTracks, soa::Join const&) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections, rctSelection)) { return; } float centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -860,7 +870,7 @@ struct TrackEfficiency { if (!collision.has_mcCollision()) { // the collision is fake and has no associated mc coll; skip as .mccollision() cannot be called return; } - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections, rctSelection)) { return; } float centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -889,7 +899,7 @@ struct TrackEfficiency { return; } float eventWeight = collision.mcCollision().weight(); - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections, rctSelection)) { return; } float centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -933,8 +943,8 @@ struct TrackEfficiency { float centrality = -1; bool hasSel8Coll = false; bool centralityCheck = false; - if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) - if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have their first associated collision not reconstructed + if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) + if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents, applyRCTSelections, rctSelection)) { // Skipping MC events that have their first associated collision not reconstructed hasSel8Coll = true; } centrality = checkCentFT0M ? collisions.begin().centFT0M() : collisions.begin().centFT0C(); @@ -943,7 +953,7 @@ struct TrackEfficiency { } } else if (acceptSplitCollisions == SplitOkCheckAnyAssocColl) { // check that at least one of the reconstructed collisions passes the checks for (auto const& collision : collisions) { - if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split + if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections, rctSelection)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split hasSel8Coll = true; } centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -996,8 +1006,8 @@ struct TrackEfficiency { float centrality = -1; bool hasSel8Coll = false; bool centralityCheck = false; - if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) - if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have their first associated collision not reconstructed + if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) + if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents, applyRCTSelections, rctSelection)) { // Skipping MC events that have their first associated collision not reconstructed hasSel8Coll = true; } centrality = checkCentFT0M ? collisions.begin().centFT0M() : collisions.begin().centFT0C(); @@ -1006,7 +1016,7 @@ struct TrackEfficiency { } } else if (acceptSplitCollisions == SplitOkCheckAnyAssocColl) { // check that at least one of the reconstructed collisions passes the checks for (auto const& collision : collisions) { - if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split + if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections, rctSelection)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split hasSel8Coll = true; } centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -1037,7 +1047,7 @@ struct TrackEfficiency { registry.fill(HIST("h_collisions"), 0.5); registry.fill(HIST("h2_centrality_collisions"), centrality, 0.5); - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections, rctSelection)) { return; } registry.fill(HIST("h_collisions"), 1.5); @@ -1066,7 +1076,7 @@ struct TrackEfficiency { } registry.fill(HIST("h_collisions"), 0.5); registry.fill(HIST("h2_centrality_collisions"), centrality, 0.5); - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections, rctSelection)) { return; } registry.fill(HIST("h_collisions"), 1.5); @@ -1103,7 +1113,7 @@ struct TrackEfficiency { float eventWeight = collision.mcCollision().weight(); registry.fill(HIST("h_collisions"), 0.5); registry.fill(HIST("h_collisions_weighted"), 0.5, eventWeight); - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections, rctSelection)) { return; } registry.fill(HIST("h_collisions"), 1.5); @@ -1140,9 +1150,9 @@ struct TrackEfficiency { float centrality = -1; bool hasSel8Coll = false; bool centralityCheck = false; - if (collisions.size() > 1) { // remove and move the if block below under if (collisions.size() < 1) { when mccoll.centFt0C has been fixed - if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) - if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have their first associated collision not reconstructed + if (collisions.size() > 1) { // remove and move the if block below under if (collisions.size() < 1) { when mccoll.centFt0C has been fixed + if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) + if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents, applyRCTSelections, rctSelection)) { // Skipping MC events that have their first associated collision not reconstructed hasSel8Coll = true; } centrality = checkCentFT0M ? collisions.begin().centFT0M() : collisions.begin().centFT0C(); @@ -1151,7 +1161,7 @@ struct TrackEfficiency { } } else if (acceptSplitCollisions == SplitOkCheckAnyAssocColl) { // check that at least one of the reconstructed collisions passes the checks for (auto const& collision : collisions) { - if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split + if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections, rctSelection)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split hasSel8Coll = true; } centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -1213,9 +1223,9 @@ struct TrackEfficiency { float centrality = -1; bool hasSel8Coll = false; bool centralityCheck = false; - if (collisions.size() > 1) { // remove and move the if block below under if (collisions.size() < 1) { when mccoll.centFt0C has been fixed - if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) - if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have their first associated collision not reconstructed + if (collisions.size() > 1) { // remove and move the if block below under if (collisions.size() < 1) { when mccoll.centFt0C has been fixed + if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) + if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents, applyRCTSelections, rctSelection)) { // Skipping MC events that have their first associated collision not reconstructed hasSel8Coll = true; } centrality = checkCentFT0M ? collisions.begin().centFT0M() : collisions.begin().centFT0C(); @@ -1224,7 +1234,7 @@ struct TrackEfficiency { } } else if (acceptSplitCollisions == SplitOkCheckAnyAssocColl) { // check that at least one of the reconstructed collisions passes the checks for (auto const& collision : collisions) { - if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split + if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections, rctSelection)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split hasSel8Coll = true; } centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -1276,7 +1286,7 @@ struct TrackEfficiency { void processTrackSelectionHistograms(soa::Filtered::iterator const& collision, soa::Join const& jetTracks, soa::Join const&) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections, rctSelection)) { return; } float centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -1330,7 +1340,7 @@ struct TrackEfficiency { registry.fill(HIST("h2_occupancy_ntracksall_presel"), occupancy, nTracksAll); registry.fill(HIST("h2_occupancy_ntrackssel_presel"), occupancy, nTracksAllAcceptanceAndSelected); registry.fill(HIST("h2_occupancy_ntracksselptetacuts_presel"), occupancy, nTracksInAcceptanceAndSelected); - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections, rctSelection)) { return; } registry.fill(HIST("h2_occupancy_ntracksall_postsel"), occupancy, nTracksAll); @@ -1341,7 +1351,7 @@ struct TrackEfficiency { void processItsTpcMatchingData(soa::Filtered::iterator const& collision, soa::Join const& jetTracks, soa::Join const&) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections, rctSelection)) { return; } float centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -1404,7 +1414,7 @@ struct TrackEfficiency { void processItsTpcMatchingMC(soa::Filtered::iterator const& collision, soa::Join const& jetTracks, soa::Join const&, aod::McParticles const&) { // could be added in future: pions+kaons vs protons distinction; easy in MC but what is the procedure for data? - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections, rctSelection)) { return; } float centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -1534,8 +1544,8 @@ struct TrackEfficiency { bool hasSel8Coll = false; bool centralityCheck = false; bool occupancyCheck = false; - if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) - if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have their first associated collision not reconstructed + if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) + if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents, applyRCTSelections, rctSelection)) { // Skipping MC events that have their first associated collision not reconstructed hasSel8Coll = true; } if (!checkOccupancy || ((trackOccupancyInTimeRangeMin < collisions.begin().trackOccupancyInTimeRange()) && (collisions.begin().trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMax))) { // check occupancy only in GP Pb-Pb MC @@ -1547,7 +1557,7 @@ struct TrackEfficiency { } } else if (acceptSplitCollisions == SplitOkCheckAnyAssocColl) { // check that at least one of the reconstructed collisions passes the checks for (auto const& collision : collisions) { - if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split + if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections, rctSelection)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split hasSel8Coll = true; } if (!checkOccupancy || ((trackOccupancyInTimeRangeMin < collision.trackOccupancyInTimeRange()) && (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMax))) { // check occupancy only in GP Pb-Pb MC @@ -1619,7 +1629,7 @@ struct TrackEfficiency { return; } - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections) || !(std::abs(collision.posZ()) < vertexZCut)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections, rctSelection) || !(std::abs(collision.posZ()) < vertexZCut)) { continue; } From 562131871a5255492c8ab1422aa9c7467edf2587 Mon Sep 17 00:00:00 2001 From: Tucker Hwang Date: Sun, 13 Sep 2026 11:23:03 -0700 Subject: [PATCH 2/3] Fix O2 linter issues --- PWGJE/Tasks/trackEfficiency.cxx | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/PWGJE/Tasks/trackEfficiency.cxx b/PWGJE/Tasks/trackEfficiency.cxx index b7f98eadbf8..b2cad506d16 100644 --- a/PWGJE/Tasks/trackEfficiency.cxx +++ b/PWGJE/Tasks/trackEfficiency.cxx @@ -131,7 +131,7 @@ struct TrackEfficiency { } } else { const auto& aodTrack = jetTrack.template track_as>(); - if (effSystMinNCrossedRowsTPCUseAlternateCut && (aodTrack.tpcNClsCrossedRows() < 120 - 5. / aodTrack.pt())) { + if (effSystMinNCrossedRowsTPCUseAlternateCut && (aodTrack.tpcNClsCrossedRows() < 120 - 5. / aodTrack.pt())) { // o2-linter: disable=magic-number (TPC nCrossedRows calculation) return false; } if (customTrackSelection.IsSelected(aodTrack)) { @@ -1634,11 +1634,11 @@ struct TrackEfficiency { } auto collTracks = jetTracks.sliceBy(tracksPerJCollision, collision.globalIndex()); - int ntrack_nonassociatedtrack = 0; - int ntrack_associatedtrack_nonprimary = 0; - int ntrack_associatedtrack_primary = 0; - int ntrack_associatedtrack_split_nonprimary = 0; - int ntrack_associatedtrack_split_primary = 0; + int nTrackNonassociatedTrack = 0; + int nTrackAssociatedTrackNonprimary = 0; + int nTrackAssociatedTrackPrimary = 0; + int nTrackAssociatedTrackSplitNonprimary = 0; + int nTrackAssociatedTrackSplitPrimary = 0; for (auto const& track : collTracks) { registry.fill(HIST("hTrackCutsCounts"), 0.5); @@ -1648,7 +1648,7 @@ struct TrackEfficiency { registry.fill(HIST("hTrackCutsCounts"), 1.5); if (!track.has_mcParticle()) { - ntrack_nonassociatedtrack += 1; + nTrackNonassociatedTrack += 1; registry.fill(HIST("h3_track_pt_track_eta_track_phi_nonassociatedtrack"), track.pt(), track.eta(), track.phi()); @@ -1659,7 +1659,7 @@ struct TrackEfficiency { auto jMcParticleFromTrack = track.mcParticle_as(); if (!jMcParticleFromTrack.isPhysicalPrimary()) { - ntrack_associatedtrack_nonprimary += 1; + nTrackAssociatedTrackNonprimary += 1; registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_nonprimary"), track.pt(), track.eta(), track.phi()); registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_nonprimary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi()); @@ -1668,7 +1668,7 @@ struct TrackEfficiency { registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_associatedtrack_nonprimary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi()); if (std::find(seenMcParticlesVector.begin(), seenMcParticlesVector.end(), jMcParticleFromTrack.globalIndex()) != seenMcParticlesVector.end()) { - ntrack_associatedtrack_split_nonprimary += 1; + nTrackAssociatedTrackSplitNonprimary += 1; registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_split_nonprimary"), track.pt(), track.eta(), track.phi()); registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_split_nonprimary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi()); @@ -1684,7 +1684,7 @@ struct TrackEfficiency { registry.fill(HIST("hTrackCutsCounts"), 3.5); - ntrack_associatedtrack_primary += 1; + nTrackAssociatedTrackPrimary += 1; registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_primary"), track.pt(), track.eta(), track.phi()); registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_primary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi()); registry.fill(HIST("h2_particle_pt_track_pt_residual_associatedtrack_primary"), jMcParticleFromTrack.pt(), (jMcParticleFromTrack.pt() - track.pt()) / jMcParticleFromTrack.pt()); @@ -1694,7 +1694,7 @@ struct TrackEfficiency { registry.fill(HIST("h2_particle_pt_high_track_pt_high_residual_associatedtrack_primary"), jMcParticleFromTrack.pt(), (jMcParticleFromTrack.pt() - track.pt()) / jMcParticleFromTrack.pt()); if (std::find(seenMcParticlesVector.begin(), seenMcParticlesVector.end(), jMcParticleFromTrack.globalIndex()) != seenMcParticlesVector.end()) { - ntrack_associatedtrack_split_primary += 1; + nTrackAssociatedTrackSplitPrimary += 1; registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_split_primary"), track.pt(), track.eta(), track.phi()); registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_split_primary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi()); @@ -1708,11 +1708,11 @@ struct TrackEfficiency { registry.fill(HIST("hTrackCutsCounts"), 4.5); } } - registry.fill(HIST("h_ntrack_nonassociatedtrack"), ntrack_nonassociatedtrack); - registry.fill(HIST("h_ntrack_associatedtrack_nonprimary"), ntrack_associatedtrack_nonprimary); - registry.fill(HIST("h_ntrack_associatedtrack_split_nonprimary"), ntrack_associatedtrack_split_nonprimary); - registry.fill(HIST("h_ntrack_associatedtrack_primary"), ntrack_associatedtrack_primary); - registry.fill(HIST("h_ntrack_associatedtrack_split_primary"), ntrack_associatedtrack_split_primary); + registry.fill(HIST("h_ntrack_nonassociatedtrack"), nTrackNonassociatedTrack); + registry.fill(HIST("h_ntrack_associatedtrack_nonprimary"), nTrackAssociatedTrackNonprimary); + registry.fill(HIST("h_ntrack_associatedtrack_split_nonprimary"), nTrackAssociatedTrackSplitNonprimary); + registry.fill(HIST("h_ntrack_associatedtrack_primary"), nTrackAssociatedTrackPrimary); + registry.fill(HIST("h_ntrack_associatedtrack_split_primary"), nTrackAssociatedTrackSplitPrimary); } } PROCESS_SWITCH(TrackEfficiency, processQcCheck, "Histograms for QC checks", false); From a84c643df866e6154cfadc14422e4f97912bc45a Mon Sep 17 00:00:00 2001 From: Tucker Hwang Date: Sat, 19 Sep 2026 10:24:22 -0700 Subject: [PATCH 3/3] Fix binning --- PWGJE/Tasks/trackEfficiency.cxx | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/PWGJE/Tasks/trackEfficiency.cxx b/PWGJE/Tasks/trackEfficiency.cxx index b2cad506d16..779f6df4805 100644 --- a/PWGJE/Tasks/trackEfficiency.cxx +++ b/PWGJE/Tasks/trackEfficiency.cxx @@ -69,14 +69,9 @@ struct TrackEfficiency { Configurable centralityMax{"centralityMax", 999, ""}; Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; Configurable trackDcaZmax{"trackDcaZmax", 99, "additional cut on dcaZ to PV for tracks; uniformTracks in particular don't cut on this at all"}; - Configurable ptHighEffMax{"ptHighEffMax", 100., "maximum pT in efficiency histograms for high pT (lower limit set by upper limit for low pT)"}; + Configurable ptHighEffMax{"ptHighEffMax", 100., "maximum pT in efficiency histograms for high pT (minimum is set by upper limit of ptLowEffBinning parameter)"}; Configurable ptHighEffNBins{"ptHighEffNBins", 18, "number of pt bins in efficiency histograms for high pT"}; - ConfigurableAxis lowPtEffBinning{"lowPtEffBinning", { - 200, - 0., - 10., - }, - "binning of low pT axis in efficiency histograms"}; + ConfigurableAxis ptLowEffBinning{"ptLowEffBinning", {200, 0., 10.}, "binning of low pT axis in efficiency histograms"}; // Track QA process function configurables: Configurable trackQAEtaMin{"trackQAEtaMin", -0.9, "minimum eta acceptance for tracks in the processTracks QA"}; @@ -86,7 +81,7 @@ struct TrackEfficiency { Configurable trackOccupancyInTimeRangeMax{"trackOccupancyInTimeRangeMax", 999999, "maximum occupancy of tracks in neighbouring collisions in a given time range; only applied for reconstructed tracks, not mc particles"}; Configurable trackOccupancyInTimeRangeMin{"trackOccupancyInTimeRangeMin", -999999, "minimum occupancy of tracks in neighbouring collisions in a given time range; only applied for reconstructed tracks, not mc particles"}; - ConfigurableAxis centBinning{"centBinning", {VARIABLE_WIDTH, 0., 10., 50., 70., 100}, "binning of centrality histograms"}; + ConfigurableAxis centralityBinning{"centralityBinning", {VARIABLE_WIDTH, 0., 10., 50., 70., 100}, "binning of centrality histograms"}; ConfigurableAxis intRateBinning{"intRateBinning", {50, 0., 50000.0}, "binning for interaction rate axis"}; ConfigurableAxis phiEffBinning{"phiEffBinning", {200, -1., 7.}, "binning for phi axis in efficiency histograms"}; ConfigurableAxis etaEffBinning{"etaEffBinning", {200, -1., 1.}, "binning for eta axis in efficiency histograms"}; @@ -254,11 +249,11 @@ struct TrackEfficiency { LOGP(info, "Using standard track selection: %s", trackSelections.value); } - AxisSpec ptAxisEff = {lowPtEffBinning, "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec ptAxisHighEff = {ptHighEffNBins, ptAxisEff.binEdges[-1], ptHighEffMax, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec ptAxisEff = {ptLowEffBinning, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec ptAxisHighEff = {ptHighEffNBins, ptAxisEff.binEdges.back(), ptHighEffMax, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec etaAxisEff{etaEffBinning, "#eta"}; AxisSpec phiAxisEff{phiEffBinning, "#phi"}; - AxisSpec centAxis = {centBinning, "centrality (%)"}; + AxisSpec centAxis = {centralityBinning, "centrality (%)"}; AxisSpec intRateAxis = {intRateBinning, "int. rate (kHz)"}; AxisSpec occupancyAxis = {140, -0.5, 13999.5, "occupancy"}; AxisSpec nTracksAxis = {16001, -1., 16000, "n tracks"}; @@ -610,7 +605,8 @@ struct TrackEfficiency { registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_associatedtrack_nonprimary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi()); if (std::find(seenMcParticlesVector.begin(), seenMcParticlesVector.end(), jMcParticleFromTrack.globalIndex()) != seenMcParticlesVector.end()) { - // particle matches to two tracks so it appears again in this loop over tracks, these histograms keep track of the extra entries from this duplication + // occasionally, one particle can match to two reconstructed tracks + // since this particle will appear again in this loop over tracks, these histograms keep track of the extra entries from this duplication registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_split_nonprimary"), track.pt(), track.eta(), track.phi()); registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_split_nonprimary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi()); @@ -634,9 +630,8 @@ struct TrackEfficiency { registry.fill(HIST("h2_particle_pt_high_track_pt_high_residual_associatedtrack_primary"), jMcParticleFromTrack.pt(), (jMcParticleFromTrack.pt() - track.pt()) / jMcParticleFromTrack.pt()); if (std::find(seenMcParticlesVector.begin(), seenMcParticlesVector.end(), jMcParticleFromTrack.globalIndex()) != seenMcParticlesVector.end()) { - // particle matches to two tracks so it appears again in this loop over tracks, these histograms keep track of the extra entries from this duplication - // doesn't overlap with the previous std::find call since we looked at non-physical primaries before and now we are only looking at physical primaries - // to get a histogram corrected for the duplication (e.g. for efficiency/resolution studies), you should subtract these histograms below from the corresponding histograms above + // same as above, but doesn't overlap with the previous std::find call since we looked at non-physical primaries before and now we are only looking at physical primaries + // to get a histogram corrected for the duplication (e.g. for efficiency/resolution studies), you should subtract these histograms below from the corresponding histograms right before this if block registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_split_primary"), track.pt(), track.eta(), track.phi()); registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_split_primary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi());