From e5d9f26fed9286afeedbc7643c5ffda5f68a0355 Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Wed, 17 Jun 2026 14:59:54 +0200 Subject: [PATCH] [PWGDQ] add computation of chi2-like values from ML score The ML score, which takes values between 0 and 1, is converted to a chi2-like value ranging from zero to infinity with this simple formula: chi2 = 1 / score - 1 The chi2-like definition allows to apply certain chi2-based selection, and particulartly the leading/next-to-leading chi2 gap, also in the case of matching performed with ML models. --- PWGDQ/Tasks/qaMatching.cxx | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/PWGDQ/Tasks/qaMatching.cxx b/PWGDQ/Tasks/qaMatching.cxx index 602222d6e08..a72c3238bd3 100644 --- a/PWGDQ/Tasks/qaMatching.cxx +++ b/PWGDQ/Tasks/qaMatching.cxx @@ -1999,6 +1999,21 @@ struct QaMatching { return attempts; } + template + void getMatchChi2AndScore(TMUON const& muonTrack, float& matchChi2, float& matchScore) + { + matchChi2 = muonTrack.chi2MatchMCHMFT() / MatchingDegreesOfFreedom; + matchScore = muonTrack.matchScoreMCHMFT(); + if (matchScore >= 0 && matchChi2 < 0) { + // match score from ML-based matching, we compute a chi2-like value from the score + float matchScoreInv = (matchScore > 0) ? 1.0 / matchScore : std::numeric_limits::max(); + matchChi2 = matchScoreInv - 1.f; + } else { + // we assume a standard chi2-based matching, and compute the score value from the chi2 + matchScore = chi2ToScore(muonTrack.chi2MatchMCHMFT(), MatchingDegreesOfFreedom, MatchingScoreChi2Max); + } + } + template void fillCollisions(EVT const& collisions, BC const& bcs, @@ -2052,8 +2067,10 @@ struct QaMatching { } else { // global muon tracks (MFT-MCH or MFT-MCH-MID) int64_t muonTrackIndex = muonTrack.globalIndex(); - double matchChi2 = muonTrack.chi2MatchMCHMFT() / MatchingDegreesOfFreedom; - double matchScore = chi2ToScore(muonTrack.chi2MatchMCHMFT(), MatchingDegreesOfFreedom, MatchingScoreChi2Max); + float matchChi2{-1}; + float matchScore{-1}; + getMatchChi2AndScore(muonTrack, matchChi2, matchScore); + auto const& mchTrack = muonTrack.template matchMCHTrack_as(); int64_t mchTrackIndex = mchTrack.globalIndex(); auto const& mftTrack = muonTrack.template matchMFTTrack_as(); @@ -2902,8 +2919,12 @@ struct QaMatching { std::vector inputML = mlResponse.getInputFeatures(muonTrack, mftTrack, mchTrack, mftTrackProp, mchTrackProp, collision); mlResponse.isSelectedMl(inputML, 0, output); float matchScore = output[0]; - float matchChi2Prod = muonTrack.chi2MatchMCHMFT() / MatchingDegreesOfFreedom; - float matchScoreProd = chi2ToScore(muonTrack.chi2MatchMCHMFT(), MatchingDegreesOfFreedom, MatchingScoreChi2Max); + float matchScoreInv = (matchScore > 0) ? 1.0 / matchScore : std::numeric_limits::max(); + float matchChi2 = matchScoreInv - 1.f; + + float matchChi2Prod{-1}; + float matchScoreProd{-1}; + getMatchChi2AndScore(muonTrack, matchChi2Prod, matchScoreProd); // check if a vector of global muon candidates is already available for the current MCH index // if not, initialize a new one and add the current global muon track @@ -2917,7 +2938,7 @@ struct QaMatching { mftTrackProp, mchTrackProp, matchScore, - -1, + matchChi2, -1, matchScoreProd, matchChi2Prod, @@ -2932,7 +2953,7 @@ struct QaMatching { mftTrackProp, mchTrackProp, matchScore, - -1, + matchChi2, -1, matchScoreProd, matchChi2Prod,