Skip to content

Commit d0c8f2e

Browse files
authored
Implement custom track selection for Run 3
Added custom track selection parameters and validation checks for Run 3 quality. Updated track selection logic to incorporate new custom settings.
1 parent 81202ee commit d0c8f2e

1 file changed

Lines changed: 106 additions & 43 deletions

File tree

‎PWGCF/EbyEFluctuations/Tasks/meanPtFlucId.cxx‎

Lines changed: 106 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
/// \author Tanu Gahlaut <tanu.gahlaut@cern.ch>
1818

1919
#include "Common/CCDB/EventSelectionParams.h"
20+
#include "Common/Core/TrackSelection.h"
2021
#include "Common/DataModel/Centrality.h"
2122
#include "Common/DataModel/EventSelection.h"
2223
#include "Common/DataModel/Multiplicity.h"
@@ -65,24 +66,31 @@ struct MeanPtFlucId {
6566
Configurable<float> cfgCutPtMax{"cfgCutPtMax", 2.0, "maximum pT"};
6667
Configurable<float> cfgCutPtMin{"cfgCutPtMin", 0.2, "minimum pT"};
6768
Configurable<float> cfgCutEta{"cfgCutEta", 0.8, "Eta cut"};
68-
Configurable<float> cfgCutITSChi2NCl{"cfgCutITSChi2NCl", 36.0, "ITS Chi2/NCl cut"};
69-
Configurable<float> cfgCutTPCChi2NCl{"cfgCutTPCChi2NCl", 4.0, "TPC Chi2/NCl cut"};
70-
Configurable<float> cfgCutTPCNCls{"cfgCutTPCNCls", 70.0, "TPC NCls cut"};
7169
Configurable<float> cfgCutDCAxy{"cfgCutDCAxy", 0.1, "DCAxy cut"};
7270
Configurable<float> cfgCutDCAz{"cfgCutDCAz", 0.2, "DCAz cut"};
7371
Configurable<float> cfgDcaPtDepOffset{"cfgDcaPtDepOffset", 0.004, "Offset of the pT-dependent DCA cut (cm)"};
7472
Configurable<float> cfgDcaPtDepScale{"cfgDcaPtDepScale", 0.013, "1/pT coefficient of the pT-dependent DCA cut (cm GeV/c)"};
75-
Configurable<int> cfgCutNCrossedRowsTPC{"cfgCutNCrossedRowsTPC", 70, "Minimum number of crossed TPC rows"};
7673
Configurable<bool> cfgGlobalTrack{"cfgGlobalTrack", true, "Require the standard global-track selection (includes its DCA cuts)"};
7774
Configurable<bool> cfgGlobalTrackWoDCA{"cfgGlobalTrackWoDCA", false, "Require global-track quality without built-in DCA cuts; disable cfgGlobalTrack to use only this selection"};
78-
Configurable<bool> cfgDcaXYPtDep{"cfgDcaXYPtDep", true, "Apply the pT-dependent absolute DCAxy cut; takes precedence over cfgDcaXY"};
79-
Configurable<bool> cfgNTPCCrossedRows{"cfgNTPCCrossedRows", false, "Apply the minimum number of crossed TPC rows"};
80-
Configurable<bool> cfgTPCChi2NCl{"cfgTPCChi2NCl", false, "Chi2 per N_{TPC} Clusters Cut "};
81-
Configurable<bool> cfgITSChi2NCl{"cfgITSChi2NCl", false, "Chi2 per N_{ITS} Clusters Cut "};
8275
Configurable<bool> cfgDcaXY{"cfgDcaXY", false, "DCA XY Cut "};
8376
Configurable<bool> cfgDcaZ{"cfgDcaZ", false, "DCA Z Cut "};
77+
Configurable<bool> cfgDcaXYPtDep{"cfgDcaXYPtDep", true, "Apply the pT-dependent absolute DCAxy cut; takes precedence over cfgDcaXY"};
8478
Configurable<bool> cfgDcaZPtDep{"cfgDcaZPtDep", false, "DCA Z pT dependent Cut "};
8579
} trackCuts;
80+
struct : ConfigurableGroup {
81+
Configurable<bool> cfgUseCustomTrackSelection{"cfgUseCustomTrackSelection", false, "Use custom Run 3 quality instead of global flags; shared acceptance and DCA cuts still apply"};
82+
Configurable<int> cfgCustomMinTPCClusters{"cfgCustomMinTPCClusters", 0, "Custom minimum TPC found clusters (global default: no additional minimum)"};
83+
Configurable<int> cfgCustomMinTPCCrossedRows{"cfgCustomMinTPCCrossedRows", 70, "Custom minimum TPC crossed rows"};
84+
Configurable<float> cfgCustomMinTPCCrossedRowsOverFindable{"cfgCustomMinTPCCrossedRowsOverFindable", 0.8f, "Custom minimum crossed rows / findable TPC clusters"};
85+
Configurable<float> cfgCustomMaxTPCChi2{"cfgCustomMaxTPCChi2", 4.f, "Custom maximum TPC chi2 per cluster"};
86+
Configurable<int> cfgCustomMinITSClusters{"cfgCustomMinITSClusters", 0, "Custom minimum ITS clusters, in addition to the selected hit pattern"};
87+
Configurable<float> cfgCustomMaxITSChi2{"cfgCustomMaxITSChi2", 36.f, "Custom maximum ITS chi2 per cluster"};
88+
Configurable<int> cfgCustomITSMatching{"cfgCustomITSMatching", 1, "Custom ITS hits: 1=any inner 3, 2=any of 7, 3=all 7, 4=first layer, 5=at least 2 inner"};
89+
Configurable<bool> cfgCustomRequireITS{"cfgCustomRequireITS", true, "Require ITS information (Run 3 ITS-refit criterion)"};
90+
Configurable<bool> cfgCustomRequireTPC{"cfgCustomRequireTPC", true, "Require TPC information (Run 3 TPC-refit criterion)"};
91+
} customTrackCuts;
92+
93+
TrackSelection mySelection;
8694
struct : ConfigurableGroup {
8795
Configurable<float> cfgCutPosZ{"cfgCutPosZ", 7.0, "cut for vertex Z"};
8896
Configurable<float> cfgP0U{"cfgP0U", 6.36269, "p_{0} for upper cut for N_{TPC} vs N{sim}"};
@@ -281,8 +289,64 @@ struct MeanPtFlucId {
281289
std::vector<double> matrixWInBin;
282290
std::vector<double> matrixW2InBin;
283291

292+
// Run 3 global quality baseline, with each systematic threshold set explicitly.
293+
TrackSelection myTrackSelection()
294+
{
295+
constexpr int MinITSMatchingMode = 1;
296+
constexpr int MaxITSMatchingMode = 5;
297+
constexpr int NumberOfITSLayers = 7;
298+
const auto& cuts = customTrackCuts;
299+
auto finiteNonnegative = [](float value) { return std::isfinite(value) && value >= 0.f; };
300+
if (cuts.cfgCustomITSMatching.value < MinITSMatchingMode || cuts.cfgCustomITSMatching.value > MaxITSMatchingMode ||
301+
cuts.cfgCustomMinTPCClusters.value < 0 || cuts.cfgCustomMinTPCCrossedRows.value < 0 ||
302+
cuts.cfgCustomMinITSClusters.value < 0 || cuts.cfgCustomMinITSClusters.value > NumberOfITSLayers ||
303+
!finiteNonnegative(cuts.cfgCustomMinTPCCrossedRowsOverFindable.value) ||
304+
!finiteNonnegative(cuts.cfgCustomMaxTPCChi2.value) || !finiteNonnegative(cuts.cfgCustomMaxITSChi2.value)) {
305+
LOGF(fatal, "Invalid custom track-selection settings: check hit counts, ITS matching and nonnegative finite thresholds");
306+
}
307+
if (!std::isfinite(trackCuts.cfgCutPtMin.value) || !std::isfinite(trackCuts.cfgCutPtMax.value) ||
308+
!std::isfinite(trackCuts.cfgCutEta.value) || trackCuts.cfgCutPtMin.value <= 0.f ||
309+
trackCuts.cfgCutPtMin.value >= trackCuts.cfgCutPtMax.value || trackCuts.cfgCutEta.value <= 0.f) {
310+
LOGF(fatal, "Custom selection requires finite 0 < pTmin < pTmax and etaMax > 0");
311+
}
312+
TrackSelection selectedTracks;
313+
selectedTracks.SetTrackType(aod::track::TrackTypeEnum::Track); // Run 3 propagated tracks
314+
// Run 3 ITS layers: no Run 2 SPD requirement.
315+
switch (cuts.cfgCustomITSMatching.value) {
316+
case 1:
317+
selectedTracks.SetRequireHitsInITSLayers(1, {0, 1, 2});
318+
break;
319+
case 2:
320+
selectedTracks.SetRequireHitsInITSLayers(1, {0, 1, 2, 3, 4, 5, 6});
321+
break;
322+
case 3:
323+
selectedTracks.SetRequireHitsInITSLayers(7, {0, 1, 2, 3, 4, 5, 6});
324+
break;
325+
case 4:
326+
selectedTracks.SetRequireHitsInITSLayers(1, {0});
327+
break;
328+
case 5:
329+
selectedTracks.SetRequireHitsInITSLayers(2, {0, 1, 2});
330+
break;
331+
}
332+
selectedTracks.SetRequireITSRefit(cuts.cfgCustomRequireITS.value);
333+
selectedTracks.SetRequireTPCRefit(cuts.cfgCustomRequireTPC.value);
334+
selectedTracks.SetMinNClustersTPC(cuts.cfgCustomMinTPCClusters.value);
335+
selectedTracks.SetMinNCrossedRowsTPC(cuts.cfgCustomMinTPCCrossedRows.value);
336+
selectedTracks.SetMinNCrossedRowsOverFindableClustersTPC(cuts.cfgCustomMinTPCCrossedRowsOverFindable.value);
337+
selectedTracks.SetMaxChi2PerClusterTPC(cuts.cfgCustomMaxTPCChi2.value);
338+
selectedTracks.SetMinNClustersITS(cuts.cfgCustomMinITSClusters.value);
339+
selectedTracks.SetMaxChi2PerClusterITS(cuts.cfgCustomMaxITSChi2.value);
340+
return selectedTracks;
341+
}
342+
284343
void init(InitContext const&)
285344
{
345+
if (customTrackCuts.cfgUseCustomTrackSelection) {
346+
mySelection = myTrackSelection();
347+
LOGF(info, "Custom Run 3 quality replaces global flags; pT, eta and DCA cuts are applied in selTrack");
348+
mySelection.print();
349+
}
286350
if (!std::isfinite(pidConfig.cfgTofShiftPi.value) || !std::isfinite(pidConfig.cfgTofShiftKa.value) || !std::isfinite(pidConfig.cfgTofShiftPr.value)) {
287351
LOGF(fatal, "TOF nSigma shifts must be finite: pion=%g, kaon=%g, proton=%g",
288352
pidConfig.cfgTofShiftPi.value, pidConfig.cfgTofShiftKa.value, pidConfig.cfgTofShiftPr.value);
@@ -753,27 +817,41 @@ struct MeanPtFlucId {
753817
template <typename T>
754818
bool selTrack(T const& track)
755819
{
756-
if (trackCuts.cfgGlobalTrack && !track.isGlobalTrack()) {
757-
return false;
758-
}
759-
760-
if (trackCuts.cfgGlobalTrackWoDCA && !track.isGlobalTrackWoDCA()) {
820+
// Shared analysis acceptance, evaluated once for either selection mode.
821+
if (!std::isfinite(track.pt()) || !std::isfinite(track.eta()) || track.pt() <= 0.f ||
822+
track.pt() < trackCuts.cfgCutPtMin || track.pt() >= trackCuts.cfgCutPtMax ||
823+
std::abs(track.eta()) >= trackCuts.cfgCutEta || track.sign() == 0) {
761824
return false;
762825
}
763826

764-
if (track.pt() < trackCuts.cfgCutPtMin) {
765-
return false;
766-
}
767-
768-
if (track.pt() >= trackCuts.cfgCutPtMax) {
769-
return false;
770-
}
771-
772-
if (track.sign() == 0) {
773-
return false;
827+
if (customTrackCuts.cfgUseCustomTrackSelection) {
828+
// Acceptance is checked above with the analysis's exclusive upper bounds.
829+
// Only quality cuts belong to the custom selector; DCA is applied below.
830+
const bool isRun2 = TrackSelection::IsRun2Track(track);
831+
for (int i = 0; i < static_cast<int>(TrackSelection::TrackCuts::kNCuts); ++i) {
832+
const auto cut = static_cast<TrackSelection::TrackCuts>(i);
833+
if (cut == TrackSelection::TrackCuts::kPtRange || cut == TrackSelection::TrackCuts::kEtaRange ||
834+
cut == TrackSelection::TrackCuts::kDCAxy || cut == TrackSelection::TrackCuts::kDCAz) {
835+
continue;
836+
}
837+
if (!mySelection.IsSelected(track, cut, isRun2)) {
838+
return false;
839+
}
840+
}
841+
} else if (trackCuts.cfgGlobalTrack) {
842+
if (!track.isGlobalTrack()) {
843+
return false;
844+
}
845+
} else if (trackCuts.cfgGlobalTrackWoDCA) {
846+
if (!track.isGlobalTrackWoDCA()) {
847+
return false;
848+
}
774849
}
775850

776-
const float maxDca = trackCuts.cfgDcaPtDepOffset + trackCuts.cfgDcaPtDepScale / track.pt();
851+
// Shared DCA cuts, applied after either custom or standard quality selection.
852+
const float maxDca = (trackCuts.cfgDcaXYPtDep || trackCuts.cfgDcaZPtDep)
853+
? trackCuts.cfgDcaPtDepOffset + trackCuts.cfgDcaPtDepScale / track.pt()
854+
: 0.f;
777855

778856
if (trackCuts.cfgDcaXYPtDep) {
779857
if (std::abs(track.dcaXY()) >= maxDca) {
@@ -795,22 +873,6 @@ struct MeanPtFlucId {
795873
}
796874
}
797875

798-
if (std::abs(track.eta()) >= trackCuts.cfgCutEta) {
799-
return false;
800-
}
801-
802-
if (trackCuts.cfgTPCChi2NCl && track.tpcChi2NCl() > trackCuts.cfgCutTPCChi2NCl) {
803-
return false;
804-
}
805-
806-
if (trackCuts.cfgITSChi2NCl && track.itsChi2NCl() > trackCuts.cfgCutITSChi2NCl) {
807-
return false;
808-
}
809-
810-
if (trackCuts.cfgNTPCCrossedRows && track.tpcNClsCrossedRows() < trackCuts.cfgCutNCrossedRowsTPC) {
811-
return false;
812-
}
813-
814876
return true;
815877
}
816878

@@ -1498,11 +1560,12 @@ struct MeanPtFlucId {
14981560
eta = mcPart.eta();
14991561
phi = mcPart.phi();
15001562

1501-
if (std::abs(eta) < trackCuts.cfgCutEta) {
1502-
nSim++;
1563+
if (!(std::abs(eta) < trackCuts.cfgCutEta)) {
1564+
continue;
15031565
}
1566+
nSim++;
15041567

1505-
if (pt >= trackCuts.cfgCutPtMin && pt < trackCuts.cfgCutPtMax && std::abs(eta) < trackCuts.cfgCutEta) {
1568+
if (pt >= trackCuts.cfgCutPtMin && pt < trackCuts.cfgCutPtMax) {
15061569
chargedTracksGen.push_back({pt});
15071570
hist.fill(HIST("Gen/Charged/h_PtTruth"), pt);
15081571
hist.fill(HIST("Gen/Charged/h_PtTruth_e"), pt);

0 commit comments

Comments
 (0)