From 4692893701f75ec9f4b5554e5c70bdbd10859e60 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Tue, 25 Aug 2026 13:56:54 +0200 Subject: [PATCH] Apply the ZNC cross-section ratio after the pile-up correction This fixes the order in which CTPRateFetcher::fetch divides the ZNC rate by 28 and inverts the Poisson. - The 28 is a ratio of cross sections, so it relates mean numbers of interactions per crossing and has to be applied to mu, after the inversion. - fetch applied it to the counting rate first, inverting the saturation of a rate that had not saturated. - The PbPb hadronic interaction rate it returns is therefore 2.7 % low at mu_ZNC = 0.055 and 5.4 % low at mu_ZNC = 0.116, measured on runs 544490, 559856 and 568721. - getLumi in the same file already applies the factor after the correction. - Every source other than ZNC hadronic gets a ratio of one and is unchanged. Found while working on https://its.cern.ch/jira/browse/O2-7143 Co-Authored-By: Claude Opus 5 --- .../Detectors/CTP/src/CTPRateFetcher.cxx | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/DataFormats/Detectors/CTP/src/CTPRateFetcher.cxx b/DataFormats/Detectors/CTP/src/CTPRateFetcher.cxx index 939203d168604..2ab9deeffa89e 100644 --- a/DataFormats/Detectors/CTP/src/CTPRateFetcher.cxx +++ b/DataFormats/Detectors/CTP/src/CTPRateFetcher.cxx @@ -17,13 +17,32 @@ #include "CommonConstants/LHCConstants.h" using namespace o2::ctp; + +namespace +{ +// The ZDC counts hadronic collisions together with electromagnetic dissociation, whose cross +// section is much the larger of the two: sigma_ZNC / sigma_hadronic is about 28. Being a ratio of +// cross sections it relates mean numbers of interactions per crossing, so it has to be applied to +// mu and not to a counting rate that has already saturated. getLumi() below applies it in that +// order; fetch() has to do the same. +double zncHadronicRatio(const std::string& sourceName) +{ + const bool isZNChadronic = sourceName.find("ZNC") != std::string::npos && + sourceName.find("hadronic") != std::string::npos; + return isZNChadronic ? 28. : 1.; +} +} // namespace + double CTPRateFetcher::fetch(o2::ccdb::BasicCCDBManager* ccdb, uint64_t timeStamp, int runNumber, std::string sourceName) { auto triggerRate = fetchNoPuCorr(ccdb, timeStamp, runNumber, sourceName); - if (triggerRate >= 0) { - return pileUpCorrection(triggerRate); + if (triggerRate < 0) { + return -1; } - return -1; + // fetchNoPuCorr has already divided by the cross-section ratio, so put it back before inverting + // the Poisson and divide again afterwards + const double ratio = zncHadronicRatio(sourceName); + return pileUpCorrection(triggerRate * ratio) / ratio; } double CTPRateFetcher::fetchNoPuCorr(o2::ccdb::BasicCCDBManager* ccdb, uint64_t timeStamp, int runNumber, std::string sourceName) {