Skip to content

Commit 45438cf

Browse files
authored
Diagnose trigger tracks selection losses in hStrangeCorrelation.cxx (#17368)
1 parent 1249ae9 commit 45438cf

1 file changed

Lines changed: 80 additions & 0 deletions

File tree

PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,19 @@ struct HStrangeCorrelation {
313313
ConfigurableAxis axisDaughterDeltaEta{"axisDaughterDeltaEta", {100, -0.2f, 0.2f}, "trigger-daughter delta eta"};
314314
ConfigurableAxis axisDaughterDeltaPhi{"axisDaughterDeltaPhi", {120, -0.3f, 0.3f}, "trigger-daughter delta phi"};
315315
ConfigurableAxis axisDecayRadius{"axisDecayRadius", {100, 0.0f, 200.0f}, "generated K0 decay radius (cm)"};
316+
// The following mirror the isValidTrigger() cuts applied by hStrangeCorrelationFilter.cxx
317+
// when building the TriggerTracks table. They must be kept in sync by hand with whatever
318+
// values are configured for that (separate) filter task, since this diagnostic cannot read
319+
// them directly: it only sees the already-filtered TriggerTracks table, not why a given
320+
// best-collision track failed to enter it.
321+
Configurable<float> triggerTracksEtaMin{"triggerTracksEtaMin", -0.8f, "must match triggerEtaMin in hStrangeCorrelationFilter.cxx"};
322+
Configurable<float> triggerTracksEtaMax{"triggerTracksEtaMax", 0.8f, "must match triggerEtaMax in hStrangeCorrelationFilter.cxx"};
323+
Configurable<float> triggerTracksPtMin{"triggerTracksPtMin", 3.0f, "must match triggerPtCutMin in hStrangeCorrelationFilter.cxx"};
324+
Configurable<float> triggerTracksPtMax{"triggerTracksPtMax", 20.0f, "must match triggerPtCutMax in hStrangeCorrelationFilter.cxx"};
325+
Configurable<int> triggerTracksMinCrossedRows{"triggerTracksMinCrossedRows", 70, "must match minTPCNCrossedRows in hStrangeCorrelationFilter.cxx"};
326+
Configurable<bool> triggerTracksRequireITS{"triggerTracksRequireITS", true, "must match triggerRequireITS in hStrangeCorrelationFilter.cxx"};
327+
Configurable<int> triggerTracksMaxSharedClusters{"triggerTracksMaxSharedClusters", 200, "must match triggerMaxTPCSharedClusters in hStrangeCorrelationFilter.cxx"};
328+
Configurable<bool> triggerTracksRequireLayer0{"triggerTracksRequireLayer0", false, "must match triggerRequireL0 in hStrangeCorrelationFilter.cxx"};
316329
} pairLossK0Configurations;
317330

318331
struct ValidCollision {
@@ -490,6 +503,29 @@ struct HStrangeCorrelation {
490503
bool hasLayer0 = false;
491504
};
492505

506+
// First-failing-condition breakdown for the stage3->4 gate ("Trigger track, best collision"
507+
// -> "Trigger in TriggerTracks"). Order mirrors the early-return order of isValidTrigger()
508+
// in hStrangeCorrelationFilter.cxx exactly, so "first reason to fail" means the same thing here.
509+
enum PairLossTriggerTracksFailureReason : int {
510+
PairLossTriggerTracksPassed = 0,
511+
PairLossTriggerTracksFailEta,
512+
PairLossTriggerTracksFailPt,
513+
PairLossTriggerTracksFailCrossedRows,
514+
PairLossTriggerTracksFailITS,
515+
PairLossTriggerTracksFailSharedClusters,
516+
PairLossTriggerTracksFailLayer0,
517+
PairLossTriggerTracksNReasons
518+
};
519+
520+
static constexpr std::array<std::string_view, PairLossTriggerTracksNReasons> PairLossTriggerTracksFailureNames = {
521+
"Passed all cuts (in TriggerTracks)",
522+
"Failed eta window",
523+
"Failed pT window",
524+
"Failed min TPC crossed rows",
525+
"Failed hasITS requirement",
526+
"Failed max TPC shared clusters",
527+
"Failed ITS layer-0 requirement"};
528+
493529
struct PairLossV0Info {
494530
int64_t globalIndex = -1;
495531
int64_t positiveTrackId = -1;
@@ -566,6 +602,33 @@ struct HStrangeCorrelation {
566602
.hasLayer0 = static_cast<bool>(TESTBIT(track.itsClusterMap(), 0))};
567603
}
568604

605+
// Replicates isValidTrigger() from hStrangeCorrelationFilter.cxx condition-by-condition
606+
// (same early-return order) so that, for a trigger already known to exist in the best
607+
// collision (stage 3), we can tell which single cut is responsible for it not making it
608+
// into the TriggerTracks table (stage 4), instead of only knowing that it failed overall.
609+
int classifyTriggerTracksFailure(PairLossTrackInfo const& info)
610+
{
611+
if (info.eta > pairLossK0Configurations.triggerTracksEtaMax || info.eta < pairLossK0Configurations.triggerTracksEtaMin) {
612+
return PairLossTriggerTracksFailEta;
613+
}
614+
if (info.pt > pairLossK0Configurations.triggerTracksPtMax || info.pt < pairLossK0Configurations.triggerTracksPtMin) {
615+
return PairLossTriggerTracksFailPt;
616+
}
617+
if (info.tpcCrossedRows < pairLossK0Configurations.triggerTracksMinCrossedRows) {
618+
return PairLossTriggerTracksFailCrossedRows;
619+
}
620+
if (info.itsClusters <= 0 && pairLossK0Configurations.triggerTracksRequireITS) {
621+
return PairLossTriggerTracksFailITS;
622+
}
623+
if (info.tpcSharedClusters > pairLossK0Configurations.triggerTracksMaxSharedClusters) {
624+
return PairLossTriggerTracksFailSharedClusters;
625+
}
626+
if (!info.hasLayer0 && pairLossK0Configurations.triggerTracksRequireLayer0) {
627+
return PairLossTriggerTracksFailLayer0;
628+
}
629+
return PairLossTriggerTracksPassed;
630+
}
631+
569632
PairLossDeltaPhiStarInfo calculateMinimumDeltaPhiStar(PairLossTruthTrackInfo const& trigger, PairLossTruthTrackInfo const& daughter, double magneticField, float decayRadiusCm)
570633
{
571634
PairLossDeltaPhiStarInfo result;
@@ -2168,6 +2231,7 @@ struct HStrangeCorrelation {
21682231
const double pairLossRadiusStep = std::max(static_cast<double>(pairLossK0Configurations.radiusStep), 0.001);
21692232
const int pairLossRadiusBins = std::max(1, static_cast<int>(std::ceil((pairLossRadiusMaximum - pairLossRadiusMinimum) / pairLossRadiusStep)));
21702233
const AxisSpec axisPairLossRadiusAtMinimum{pairLossRadiusBins, pairLossRadiusMinimum, pairLossRadiusMaximum, "#it{r}_{min} (m)"};
2234+
const AxisSpec axisPairLossTriggerTracksFailureReason{PairLossTriggerTracksNReasons, -0.5, static_cast<double>(PairLossTriggerTracksNReasons) - 0.5, "TriggerTracks first-failing condition"};
21712235

21722236
histos.add("PairLossK0/Event/hCounter", "K0 pair-loss event counter", kTH1F, {axisPairLossEventStage});
21732237
histos.add("PairLossK0/Event/hNRecoCollisions", "reconstructed collisions per MC collision", kTH1F, {axisPairLossNRecoCollisions});
@@ -2176,6 +2240,7 @@ struct HStrangeCorrelation {
21762240
histos.add("PairLossK0/Stage/hPhysics", "stages in h-K0 physics variables", kTHnF, {axisPairLossStage, axisPairLossTruthDeltaPhi, axisPairLossTruthDeltaEta, axisPairLossTruthK0Pt, axisPairLossTruthTriggerPt, axisPairLossFieldSign});
21772241
histos.add("PairLossK0/Stage/hPhysicsFindable", "stages in h-K0 physics variables for findable K0", kTHnF, {axisPairLossStage, axisPairLossTruthDeltaPhi, axisPairLossTruthDeltaEta, axisPairLossTruthK0Pt, axisPairLossTruthTriggerPt, axisPairLossFieldSign});
21782242
histos.add("PairLossK0/Stage/hClose", "stages in trigger-daughter close-pair variables", kTHnF, {axisPairLossStage, axisPairLossMinDeltaPhiStar, axisPairLossDaughterDeltaEta, axisPairLossTruthK0Pt, axisPairLossTruthTriggerPt, axisPairLossFieldSign, axisPairLossChargeProduct});
2243+
histos.add("PairLossK0/Stage/hTriggerTracksFailureReason", "first-failing TriggerTracks condition for best-collision triggers, in h-K0 physics variables", kTHnF, {axisPairLossTriggerTracksFailureReason, axisPairLossTruthDeltaPhi, axisPairLossTruthDeltaEta, axisPairLossTruthK0Pt, axisPairLossTruthTriggerPt});
21792244

21802245
histos.add("PairLossK0/State/hFinalObjectStatePhysics", "00/01/10/11 final trigger-K0 object state", kTHnF, {axisPairLossFinalObjectState, axisPairLossTruthDeltaPhi, axisPairLossTruthDeltaEta, axisPairLossTruthK0Pt, axisPairLossTruthTriggerPt, axisPairLossFieldSign});
21812246
histos.add("PairLossK0/State/hFinalObjectStateClose", "00/01/10/11 final trigger-K0 object state in close-pair variables", kTHnF, {axisPairLossFinalObjectState, axisPairLossMinDeltaPhiStar, axisPairLossDaughterDeltaEta, axisPairLossTruthK0Pt, axisPairLossTruthTriggerPt, axisPairLossFieldSign, axisPairLossChargeProduct});
@@ -2229,6 +2294,11 @@ struct HStrangeCorrelation {
22292294
stageCounts->GetYaxis()->SetTitle("Truth-pair entries");
22302295
stageCountsFindable->GetYaxis()->SetTitle("Findable truth-pair entries");
22312296

2297+
auto triggerTracksFailureHistogram = histos.get<THn>(HIST("PairLossK0/Stage/hTriggerTracksFailureReason"));
2298+
for (int i = 0; i < PairLossTriggerTracksNReasons; ++i) {
2299+
triggerTracksFailureHistogram->GetAxis(0)->SetBinLabel(i + 1, PairLossTriggerTracksFailureNames[i].data());
2300+
}
2301+
22322302
const std::array<std::string_view, 4> objectStateLabels = {"00 neither", "01 K0 only", "10 trigger only", "11 both"};
22332303
for (auto const& histogram : {histos.get<THn>(HIST("PairLossK0/State/hFinalObjectStatePhysics")), histos.get<THn>(HIST("PairLossK0/State/hFinalObjectStateClose"))}) {
22342304
for (size_t i = 0; i < objectStateLabels.size(); ++i) {
@@ -4103,6 +4173,16 @@ struct HStrangeCorrelation {
41034173
}
41044174
}
41054175

4176+
// Only meaningful conditional on the trigger already existing in the best collision
4177+
// (stage 3): this asks *why* that already-found, already-correctly-labelled track
4178+
// does or does not make it into the TriggerTracks table (stage 4).
4179+
if (triggerBestCollision) {
4180+
if (auto const* bestCollisionTrigger = bestTrack(tracksBestCollision, truthTrigger.globalIndex)) {
4181+
const int failureReason = classifyTriggerTracksFailure(*bestCollisionTrigger);
4182+
histos.fill(HIST("PairLossK0/Stage/hTriggerTracksFailureReason"), failureReason, truthDeltaPhi, truthDeltaEta, truthK0.pt, truthTrigger.pt);
4183+
}
4184+
}
4185+
41064186
const int finalObjectState = (triggerFinal ? 2 : 0) + (v0Final ? 1 : 0);
41074187
const int trackLevelState = (triggerBestCollision ? 2 : 0) + (bothDaughtersBestCollision ? 1 : 0);
41084188
const int daughterTrackState = (positiveDaughterBestCollision ? 2 : 0) + (negativeDaughterBestCollision ? 1 : 0);

0 commit comments

Comments
 (0)