Skip to content

Commit 8a9a9dc

Browse files
authored
[PWGLF] Refactor track selection and update rapidity cuts, commented long LOGF entries (#18172)
1 parent cd20e0a commit 8a9a9dc

2 files changed

Lines changed: 243 additions & 201 deletions

File tree

‎PWGLF/TableProducer/Resonances/hResonanceCorrelationFilter.cxx‎

Lines changed: 88 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -83,20 +83,31 @@ struct HResonanceCorrelationFilter {
8383
Configurable<bool> cfgEvtSel8{"cfgEvtSel8", true, "Evt Sel 8 check for offline selection"};
8484
Configurable<bool> cfgEvtNoSameBunchPileupCut{"cfgEvtNoSameBunchPileupCut", true, "Evt sel: reject collisions associated with the same found-by-T0 bunch crossing"};
8585
Configurable<bool> cfgEvtGoodZvtxFT0vsPVCut{"cfgEvtGoodZvtxFT0vsPVCut", true, "Evt sel: require small difference between z-vertex from PV and from FT0"};
86+
// Centrality source switch for hCentralitySelected: O-O collisions have a
87+
// well-defined FT0C centrality estimator; p-O (asymmetric system) does
88+
// not, so FV0A is used there instead. Only affects which estimator is
89+
// read for that one QA histogram -- doesn't change any selection cut.
90+
Configurable<bool> cfgUseFV0ACentrality{"cfgUseFV0ACentrality", false, "Centrality estimator for hCentralitySelected: false = O-O (FT0C), true = p-O (FV0A)"};
8691
} configEvents;
8792

8893
// Merged from the formerly separate configTracks/generalSelections/
8994
// trackSelections groups -- all three were "cuts applied to a track or
9095
// track pair", just split by who last touched them. No member names
9196
// collided, so every Configurable below keeps its original key; only the
9297
// "<group>." prefix at each call site changed, to configTracks.
98+
// General, species-agnostic track-quality cuts: applied identically to
99+
// every track that reaches trackCut() -- trigger, associated hadron, AND
100+
// Phi/K*0 daughter candidates alike (see trackCut() below, and its call
101+
// sites at isValidTrigger(), isValidAssocTrack<Species>(), and both
102+
// processPhis()/processKstars()). cfgCutEta/cMinPtcut additionally gate
103+
// the framework-level `acceptanceFilter` Filter, applied to every track
104+
// in every process function before any of the above ever sees it.
93105
struct : ConfigurableGroup {
94106
std::string prefix = "configTracks";
95107
// Pre-selection Track cuts
96108
Configurable<float> cMinPtcut{"cMinPtcut", 0.15f, "Minimal pT for tracks"};
97109
Configurable<float> cMinTPCNClsFound{"cMinTPCNClsFound", 120, "minimum TPCNClsFound value for good track"};
98110
Configurable<float> cfgCutEta{"cfgCutEta", 0.8f, "Eta range for tracks"};
99-
Configurable<float> cfgCutRapidity{"cfgCutRapidity", 0.5f, "rapidity range for particles"};
100111
Configurable<int> cfgMinCrossedRows{"cfgMinCrossedRows", 70, "min crossed rows for good track"};
101112
Configurable<float> cfgMaxTPCChi2NCl{"cfgMaxTPCChi2NCl", 4.0f, "max TPC chi2/clusters for good track"};
102113
Configurable<float> cfgMaxITSChi2NCl{"cfgMaxITSChi2NCl", 36.0f, "max ITS chi2/clusters for good track"};
@@ -115,30 +126,49 @@ struct HResonanceCorrelationFilter {
115126
Configurable<bool> cfgHasTOF{"cfgHasTOF", false, "Require TOF"};
116127
Configurable<bool> cTPCNClsFound{"cTPCNClsFound", false, "Switch to turn on/off TPCNClsFound cut"};
117128

118-
// Associated particle selections in phase space (formerly generalSelections)
119-
Configurable<float> assocEtaMin{"assocEtaMin", -0.8, "triggeretamin"};
120-
Configurable<float> assocEtaMax{"assocEtaMax", 0.8, "triggeretamax"};
121-
Configurable<float> assocPtCutMin{"assocPtCutMin", 0.2, "assocptmin"};
122-
Configurable<float> assocPtCutMax{"assocPtCutMax", 10, "assocptmax"};
129+
// Track quality shared by trigger AND assoc selection (isValidTrigger()
130+
// and isValidAssocTrack<Species>() both read this same configurable --
131+
// it is NOT split into trigger-/assoc-only copies below).
132+
Configurable<int> minTPCNCrossedRows{"minTPCNCrossedRows", 70, "Minimum TPC crossed rows"};
123133

124-
// Trigger particle selections in phase space (formerly generalSelections)
134+
// primary particle DCAxy selections (formerly trackSelections)
135+
// formula: |DCAxy| < 0.004f + (0.013f / pt)
136+
Configurable<float> dcaXYconstant{"dcaXYconstant", 0.004, "[0] in |DCAxy| < [0]+[1]/pT"};
137+
Configurable<float> dcaXYpTdep{"dcaXYpTdep", 0.013, "[1] in |DCAxy| < [0]+[1]/pT"};
138+
} configTracks;
139+
140+
// Phi/K*0 resonance-candidate cuts: applied to the RECONSTRUCTED candidate
141+
// (the K+K- or K-pi 4-vector), not to the daughter tracks themselves --
142+
// the daughters go through the shared configTracks/trackCut() cuts above
143+
// like every other track. Currently holds just the one configurable; kept
144+
// as its own group rather than folded into configTracks so it reads as
145+
// "resonance-level", not "track-level".
146+
struct : ConfigurableGroup {
147+
std::string prefix = "configResoDauTracks";
148+
Configurable<float> cfgCutRapidity{"cfgCutRapidity", 0.5f, "rapidity range for the reconstructed Phi/K*0 candidate"};
149+
} configResoDauTracks;
150+
151+
// Trigger-hadron-only phase-space and quality cuts.
152+
struct : ConfigurableGroup {
153+
std::string prefix = "configTriggerTracks";
125154
Configurable<float> triggerEtaMin{"triggerEtaMin", -0.8, "triggeretamin"};
126155
Configurable<float> triggerEtaMax{"triggerEtaMax", 0.8, "triggeretamax"};
127-
Configurable<float> triggerPtCutMin{"triggerPtCutMin", 3, "triggerptmin"};
156+
Configurable<float> triggerPtCutMin{"triggerPtCutMin", 2, "triggerptmin"};
128157
Configurable<float> triggerPtCutMax{"triggerPtCutMax", 20, "triggerptmax"};
129-
130-
// Track quality (formerly trackSelections)
131-
Configurable<int> minTPCNCrossedRows{"minTPCNCrossedRows", 70, "Minimum TPC crossed rows"};
132158
Configurable<bool> triggerRequireITS{"triggerRequireITS", true, "require ITS signal in trigger tracks"};
133-
Configurable<bool> assocRequireITS{"assocRequireITS", true, "require ITS signal in assoc tracks"};
134159
Configurable<int> triggerMaxTPCSharedClusters{"triggerMaxTPCSharedClusters", 200, "maximum number of shared TPC clusters (inclusive)"};
135160
Configurable<bool> triggerRequireL0{"triggerRequireL0", false, "require ITS L0 cluster for trigger"};
161+
} configTriggerTracks;
136162

137-
// primary particle DCAxy selections (formerly trackSelections)
138-
// formula: |DCAxy| < 0.004f + (0.013f / pt)
139-
Configurable<float> dcaXYconstant{"dcaXYconstant", 0.004, "[0] in |DCAxy| < [0]+[1]/pT"};
140-
Configurable<float> dcaXYpTdep{"dcaXYpTdep", 0.013, "[1] in |DCAxy| < [0]+[1]/pT"};
141-
} configTracks;
163+
// Associated-hadron-only phase-space and quality cuts.
164+
struct : ConfigurableGroup {
165+
std::string prefix = "configAssocTracks";
166+
Configurable<float> assocEtaMin{"assocEtaMin", -0.8, "triggeretamin"};
167+
Configurable<float> assocEtaMax{"assocEtaMax", 0.8, "triggeretamax"};
168+
Configurable<float> assocPtCutMin{"assocPtCutMin", 0.2, "assocptmin"};
169+
Configurable<float> assocPtCutMax{"assocPtCutMax", 10, "assocptmax"};
170+
Configurable<bool> assocRequireITS{"assocRequireITS", true, "require ITS signal in assoc tracks"};
171+
} configAssocTracks;
142172

143173
struct : ConfigurableGroup {
144174
std::string prefix = "configPID";
@@ -181,15 +211,6 @@ struct HResonanceCorrelationFilter {
181211
Configurable<float> rejectSigma{"rejectSigma", 1, "n sigma for rejecting pion candidates"};
182212
} configPID;
183213

184-
// Unused in this file today -- nothing here reads from CCDB any more
185-
// (Zorro was the only consumer and has been removed). Kept (grouped,
186-
// rather than removed) since that's outside today's ask.
187-
struct : ConfigurableGroup {
188-
std::string prefix = "ccdbConfigurations";
189-
Configurable<std::string> ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository to use"};
190-
Configurable<std::string> parameterCCDBPath{"parameterCCDBPath", "Users/k/kcui/LHC25b4a/parameter", "Path of the mean and sigma"};
191-
} ccdbConfigurations;
192-
193214
// must include windows for background and peak
194215
//
195216
// This filter-level cut is an acceptance pre-cut only -- it decides what
@@ -238,6 +259,8 @@ struct HResonanceCorrelationFilter {
238259
ConfigurableAxis axisDCAxyQA{"axisDCAxyQA", {200, -0.5f, 0.5f}, "DCA_{xy} (cm)"};
239260
ConfigurableAxis axisDCAzQA{"axisDCAzQA", {200, -0.5f, 0.5f}, "DCA_{z} (cm)"};
240261
ConfigurableAxis axisTPCCrossedRowsQA{"axisTPCCrossedRowsQA", {160, 0, 160}, "TPC crossed rows"};
262+
ConfigurableAxis axisVertexZQA{"axisVertexZQA", {60, -15.0f, 15.0f}, "Vertex Z (cm)"};
263+
ConfigurableAxis axisCentralityQA{"axisCentralityQA", {100, 0.0f, 100.0f}, "Centrality (%)"};
241264
} axesConfigurations;
242265

243266
// QA
@@ -292,6 +315,12 @@ struct HResonanceCorrelationFilter {
292315
void init(InitContext const&)
293316
{
294317
histos.add("CollCutCounts", "No. of event after cuts", kTH1I, {{10, 0, 10}});
318+
// Z-vertex and centrality of selected events (filled in isSelectedEvents()
319+
// once a collision passes every cut, i.e. the same "All Passed Events"
320+
// point as CollCutCounts bin 8). Centrality source for the latter is
321+
// configEvents.cfgUseFV0ACentrality: FT0C for O-O, FV0A for p-O.
322+
histos.add("hVertexZSelected", "Vertex Z of selected events", kTH1F, {axesConfigurations.axisVertexZQA});
323+
histos.add("hCentralitySelected", "Centrality of selected events", kTH1F, {axesConfigurations.axisCentralityQA});
295324
histos.get<TH1>(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(1, "All Events");
296325
histos.get<TH1>(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(2, "|Vz| < cut");
297326
histos.get<TH1>(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(3, "kIsTriggerTVX");
@@ -326,6 +355,8 @@ struct HResonanceCorrelationFilter {
326355
histos.add((dir + "/hPtVsDCAz").c_str(), "p_{T} vs DCA_{z}", kTH2F, {axesConfigurations.axisPtQA, axesConfigurations.axisDCAzQA});
327356
histos.add((dir + "/hPtVsTPCNSigma").c_str(), "p_{T} vs TPC n#sigma", kTH2F, {axesConfigurations.axisPtQA, axesConfigurations.axisNSigmaQA});
328357
histos.add((dir + "/hPtVsTOFNSigma").c_str(), "p_{T} vs TOF n#sigma", kTH2F, {axesConfigurations.axisPtQA, axesConfigurations.axisNSigmaQA});
358+
// TPC vs TOF nSigma correlation, for the usual PID "banana plot" check
359+
histos.add((dir + "/hTPCNSigmaVsTOFNSigma").c_str(), "TPC n#sigma vs TOF n#sigma", kTH2F, {axesConfigurations.axisNSigmaQA, axesConfigurations.axisNSigmaQA});
329360
};
330361
bookDaughterQA("QA/Phi/Kaon");
331362
bookDaughterQA("QA/Kstar/Kaon");
@@ -360,6 +391,9 @@ struct HResonanceCorrelationFilter {
360391
histos.fill(HIST("QA/Phi/Kaon/hPtVsDCAz"), track.pt(), track.dcaZ());
361392
histos.fill(HIST("QA/Phi/Kaon/hPtVsTPCNSigma"), track.pt(), track.tpcNSigmaKa());
362393
histos.fill(HIST("QA/Phi/Kaon/hPtVsTOFNSigma"), track.pt(), track.tofNSigmaKa());
394+
if (track.hasTOF()) {
395+
histos.fill(HIST("QA/Phi/Kaon/hTPCNSigmaVsTOFNSigma"), track.tpcNSigmaKa(), track.tofNSigmaKa());
396+
}
363397
}
364398

365399
template <typename Track>
@@ -376,6 +410,9 @@ struct HResonanceCorrelationFilter {
376410
histos.fill(HIST("QA/Kstar/Kaon/hPtVsDCAz"), track.pt(), track.dcaZ());
377411
histos.fill(HIST("QA/Kstar/Kaon/hPtVsTPCNSigma"), track.pt(), track.tpcNSigmaKa());
378412
histos.fill(HIST("QA/Kstar/Kaon/hPtVsTOFNSigma"), track.pt(), track.tofNSigmaKa());
413+
if (track.hasTOF()) {
414+
histos.fill(HIST("QA/Kstar/Kaon/hTPCNSigmaVsTOFNSigma"), track.tpcNSigmaKa(), track.tofNSigmaKa());
415+
}
379416
}
380417

381418
template <typename Track>
@@ -392,6 +429,9 @@ struct HResonanceCorrelationFilter {
392429
histos.fill(HIST("QA/Kstar/Pion/hPtVsDCAz"), track.pt(), track.dcaZ());
393430
histos.fill(HIST("QA/Kstar/Pion/hPtVsTPCNSigma"), track.pt(), track.tpcNSigmaPi());
394431
histos.fill(HIST("QA/Kstar/Pion/hPtVsTOFNSigma"), track.pt(), track.tofNSigmaPi());
432+
if (track.hasTOF()) {
433+
histos.fill(HIST("QA/Kstar/Pion/hTPCNSigmaVsTOFNSigma"), track.tpcNSigmaPi(), track.tofNSigmaPi());
434+
}
395435
}
396436

397437
// Trigger hadrons carry no PID selection, so only the 5 non-PID variables
@@ -463,6 +503,14 @@ struct HResonanceCorrelationFilter {
463503

464504
if (fillHist) {
465505
histos.fill(HIST("CollCutCounts"), 8);
506+
histos.fill(HIST("hVertexZSelected"), collision.posZ());
507+
// Guarded with if constexpr: isSelectedEvents() is called with several
508+
// different collision join types (some callers pass fillHist=false and
509+
// don't join centrality tables at all), so this only compiles/fills for
510+
// callers whose collision type actually has both estimators joined.
511+
if constexpr (requires { collision.centFT0C(); collision.centFV0A(); }) {
512+
histos.fill(HIST("hCentralitySelected"), configEvents.cfgUseFV0ACentrality ? collision.centFV0A() : collision.centFT0C());
513+
}
466514
}
467515

468516
return true;
@@ -692,23 +740,23 @@ struct HResonanceCorrelationFilter {
692740
if (!trackCut(track)) {
693741
return false;
694742
}
695-
if (track.eta() > configTracks.triggerEtaMax || track.eta() < configTracks.triggerEtaMin) {
743+
if (track.eta() > configTriggerTracks.triggerEtaMax || track.eta() < configTriggerTracks.triggerEtaMin) {
696744
return false;
697745
}
698746
// if (track.sign()= 1 ) {continue;}
699-
if (track.pt() > configTracks.triggerPtCutMax || track.pt() < configTracks.triggerPtCutMin) {
747+
if (track.pt() > configTriggerTracks.triggerPtCutMax || track.pt() < configTriggerTracks.triggerPtCutMin) {
700748
return false;
701749
}
702750
if (track.tpcNClsCrossedRows() < configTracks.minTPCNCrossedRows) {
703751
return false; // crossed rows
704752
}
705-
if (!track.hasITS() && configTracks.triggerRequireITS) {
753+
if (!track.hasITS() && configTriggerTracks.triggerRequireITS) {
706754
return false; // skip, doesn't have ITS signal (skips lots of TPC-only!)
707755
}
708-
if (track.tpcNClsShared() > configTracks.triggerMaxTPCSharedClusters) {
756+
if (track.tpcNClsShared() > configTriggerTracks.triggerMaxTPCSharedClusters) {
709757
return false; // skip, has shared clusters
710758
}
711-
if (!(BIT_CHECK(track.itsClusterMap(), 0)) && configTracks.triggerRequireL0) {
759+
if (!(BIT_CHECK(track.itsClusterMap(), 0)) && configTriggerTracks.triggerRequireL0) {
712760
return false; // skip, doesn't have cluster in ITS L0
713761
}
714762
return true;
@@ -743,16 +791,16 @@ struct HResonanceCorrelationFilter {
743791
if (!trackCut(assoc)) {
744792
return false;
745793
}
746-
if (assoc.eta() > configTracks.assocEtaMax || assoc.eta() < configTracks.assocEtaMin) {
794+
if (assoc.eta() > configAssocTracks.assocEtaMax || assoc.eta() < configAssocTracks.assocEtaMin) {
747795
return false;
748796
}
749-
if (assoc.pt() > configTracks.assocPtCutMax || assoc.pt() < configTracks.assocPtCutMin) {
797+
if (assoc.pt() > configAssocTracks.assocPtCutMax || assoc.pt() < configAssocTracks.assocPtCutMin) {
750798
return false;
751799
}
752800
if (assoc.tpcNClsCrossedRows() < configTracks.minTPCNCrossedRows) {
753801
return false; // crossed rows
754802
}
755-
if (!assoc.hasITS() && configTracks.assocRequireITS) {
803+
if (!assoc.hasITS() && configAssocTracks.assocRequireITS) {
756804
return false; // skip, doesn't have ITS signal (skips lots of TPC-only!)
757805
}
758806

@@ -855,7 +903,7 @@ struct HResonanceCorrelationFilter {
855903
}
856904

857905
// for real data processing
858-
void processTriggers(soa::Join<aod::Collisions, aod::EvSels, aod::CentFT0Ms, aod::CentFT0Cs, aod::PVMults>::iterator const& collision, soa::Filtered<FullTracks> const& tracks)
906+
void processTriggers(soa::Join<aod::Collisions, aod::EvSels, aod::CentFT0Ms, aod::CentFT0Cs, aod::CentFV0As, aod::PVMults>::iterator const& collision, soa::Filtered<FullTracks> const& tracks)
859907
{
860908
triggerCandidates.clear();
861909
if (!isSelectedEvents(collision)) {
@@ -894,7 +942,7 @@ struct HResonanceCorrelationFilter {
894942
}
895943

896944
// for MC processing
897-
void processTriggersMC(soa::Join<aod::Collisions, aod::EvSels, aod::CentFT0Ms, aod::CentFT0Cs, aod::PVMults>::iterator const& collision, soa::Filtered<FullTracksMC> const& tracks, aod::McParticles const&)
945+
void processTriggersMC(soa::Join<aod::Collisions, aod::EvSels, aod::CentFT0Ms, aod::CentFT0Cs, aod::CentFV0As, aod::PVMults>::iterator const& collision, soa::Filtered<FullTracksMC> const& tracks, aod::McParticles const&)
898946
{
899947
triggerCandidates.clear();
900948
if (!isSelectedEvents(collision)) {
@@ -1090,7 +1138,7 @@ struct HResonanceCorrelationFilter {
10901138
float invMass = phi.M();
10911139

10921140
// rapidity cut
1093-
if (std::abs(phi.Rapidity()) > configTracks.cfgCutRapidity) {
1141+
if (std::abs(phi.Rapidity()) > configResoDauTracks.cfgCutRapidity) {
10941142
continue;
10951143
}
10961144

@@ -1181,7 +1229,7 @@ struct HResonanceCorrelationFilter {
11811229
float invMass = phi.M();
11821230

11831231
// rapidity cut
1184-
if (std::abs(phi.Rapidity()) > configTracks.cfgCutRapidity) {
1232+
if (std::abs(phi.Rapidity()) > configResoDauTracks.cfgCutRapidity) {
11851233
continue;
11861234
}
11871235

@@ -1299,7 +1347,7 @@ struct HResonanceCorrelationFilter {
12991347
float invMass = kstar.M();
13001348

13011349
// rapidity cut
1302-
if (std::abs(kstar.Rapidity()) > configTracks.cfgCutRapidity) {
1350+
if (std::abs(kstar.Rapidity()) > configResoDauTracks.cfgCutRapidity) {
13031351
continue;
13041352
}
13051353

@@ -1388,7 +1436,7 @@ struct HResonanceCorrelationFilter {
13881436
float invMass = kstar.M();
13891437

13901438
// rapidity cut
1391-
if (std::abs(kstar.Rapidity()) > configTracks.cfgCutRapidity) {
1439+
if (std::abs(kstar.Rapidity()) > configResoDauTracks.cfgCutRapidity) {
13921440
continue;
13931441
}
13941442

0 commit comments

Comments
 (0)