From 2d8ddad8eba655bc27b6f28dee357b2e2d5f6791 Mon Sep 17 00:00:00 2001
From: Weitao Wang <weitao@cern.ch>
Date: Tue, 18 Mar 2025 18:57:27 +0100
Subject: [PATCH 1/2] new function for highpt unc sagitta correction

---
 .../MuonMomentumCorrections/EnumDef.h         |  2 +-
 .../Root/CalibInitializer.cxx                 |  1 +
 .../Root/MuonCalibIntSagittaTool.cxx          | 45 +++----------------
 3 files changed, 8 insertions(+), 40 deletions(-)

diff --git a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/MuonMomentumCorrections/EnumDef.h b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/MuonMomentumCorrections/EnumDef.h
index 34e70db8ea2b..c095eb877b92 100644
--- a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/MuonMomentumCorrections/EnumDef.h
+++ b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/MuonMomentumCorrections/EnumDef.h
@@ -13,7 +13,7 @@ namespace MCP {
     enum class TrackType{ CB, ID, ME }; 
 
     // This is for SagittaCorrection, there are two different types of error terms
-    enum class SagittaCorrection{ Nominal, Datastat__1up, Residual__1up }; 
+    enum class SagittaCorrection{ Nominal, Datastat__1up, Residual__1up, PtExtra__1up }; 
 
     // This for the calibration constants of the Scale and Resolution Corrections, s0/s1/r0/r1/r2
     enum class ScaleResCorrection{ Nominal, SystErr__1up, SystErr__1down }; 
diff --git a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/Root/CalibInitializer.cxx b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/Root/CalibInitializer.cxx
index 47c0455c484b..79f858875ed1 100644
--- a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/Root/CalibInitializer.cxx
+++ b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/Root/CalibInitializer.cxx
@@ -24,6 +24,7 @@ namespace MCP {
                 calibMap[SagittaCorrection::Nominal]        = std::make_shared<CalibContainer>(path, "p" + trackType + "_0");
                 calibMap[SagittaCorrection::Datastat__1up]  = std::make_shared<CalibContainer>(path, "p" + trackType + "_statError");
                 calibMap[SagittaCorrection::Residual__1up]  = std::make_shared<CalibContainer>(path, "p" + trackType + "_1");
+                calibMap[SagittaCorrection::PtExtra__1up]  = std::make_shared<CalibContainer>(path, "p" + trackType + "_ptExtra");
             }
             else if(correctionType == "mc")
             {
diff --git a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/Root/MuonCalibIntSagittaTool.cxx b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/Root/MuonCalibIntSagittaTool.cxx
index e15dc2e19d5b..2d7637f4c5df 100644
--- a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/Root/MuonCalibIntSagittaTool.cxx
+++ b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/Root/MuonCalibIntSagittaTool.cxx
@@ -245,47 +245,14 @@ namespace CP
                 // Till it reach 450 GeV and then to flatten it. 
                 // The value is chosen in an arbitrary fashion. To be replaced and fixed, once we have a better idea of 
                 double corr = 0;
-                double deltas = 0.00002;
-                if (eta > 2 || (eta > -2 && eta < -1.05)) {
-                    if (pT > 450.0)
-                        corr += std::abs(450.0 - 45) / 100 * deltas;  // Above 450 GeV flat
-                    else
-                        corr += std::abs(pT - 45) / 100 * deltas;
-                }
-                if (eta < -2 || (eta < 2 && eta> 1.5)) {
-                    if (pT > 450.0)
-                        corr += std::abs(450.0 - 45) / 200 * deltas;  // Above 450 GeV flat
-                    else
-                        corr += std::abs(pT - 45) / 200 * deltas;
-                }
-                // additional uncertainties for 2022 data
-                if (m_release.value().find("Recs2023") != std::string::npos) {
-                  if ( (trk.year==MCP::DataYear::Data22) && pT > 100.0) {
-                    if (eta < 0 && eta> -0.5) corr += 2.1*deltas;
-                    else if (eta < -1.05) corr += 1.1*deltas;
-                    else if (eta > 0.5 ) corr += 0.8*deltas;
-                  }
-                } else {
-                  if ( trk.year==MCP::DataYear::Data22 ) {
-                    if (eta > -2 && eta < -1.05) corr = corr*2.5;
-                    if (eta < -2) corr = corr*6;
-                    if (eta > 1.5 && eta < 2) {
-                      if (pT > 450.0)
-                        corr += std::abs(450.0 - 45) / 80 * deltas;  // Above 450 GeV flat
-                      else
-                        corr += std::abs(pT - 45) / 80 * deltas;
-                    }
-                    if (eta > 1.05 && eta < 1.5) {
-                      if (pT > 450.0)
-                        corr += std::abs(450.0 - 45) / 40 * deltas;  // Above 450 GeV flat
-                      else
-                        corr += std::abs(pT - 45) / 40 * deltas;
-                    }
-                  }
-                }
+                //double deltas = 0.00002;
+                double deltas = corrMap->at(MCP::SagittaCorrection::PtExtra__1up)->getCalibConstant(trk);
+                if (pT > 450.0)
+                    corr += std::abs(450.0 - 45) * deltas;  // Above 450 GeV flat
+                else
+                    corr += std::abs(pT - 45) * deltas;
                 ATH_MSG_VERBOSE("Deltas corr: "<<deltas);
 
-
                 corrections.push_back(corr*scale);
                 ATH_MSG_VERBOSE("final corr: "<<corr);
 
-- 
GitLab


From 2551e2bcc1f3d6fda0cc01ee92937d43b79e97c9 Mon Sep 17 00:00:00 2001
From: Weitao Wang <weitao@cern.ch>
Date: Tue, 25 Mar 2025 20:06:20 +0100
Subject: [PATCH 2/2] make it compatible with old recommendation

---
 .../MuonMomentumCorrections/CalibContainer.h  |  1 +
 .../Root/CalibContainer.cxx                   | 30 ++++++-----
 .../Root/MuonCalibIntSagittaTool.cxx          | 54 ++++++++++++++++---
 3 files changed, 66 insertions(+), 19 deletions(-)

diff --git a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/MuonMomentumCorrections/CalibContainer.h b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/MuonMomentumCorrections/CalibContainer.h
index c0e5d21522c6..5a736e5a3be6 100644
--- a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/MuonMomentumCorrections/CalibContainer.h
+++ b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/MuonMomentumCorrections/CalibContainer.h
@@ -23,6 +23,7 @@ namespace MCP {
 
         // To retrieve the calib constant
         double getCalibConstant(const TrackCalibObj& trk) const;
+        bool mapExist() const { return m_calibConstantHist ? true : false; };
 
     protected:
         std::unique_ptr<const TH1> m_calibConstantHist;  
diff --git a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/Root/CalibContainer.cxx b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/Root/CalibContainer.cxx
index 2caef4c3bf32..12bf27f388c9 100644
--- a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/Root/CalibContainer.cxx
+++ b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/Root/CalibContainer.cxx
@@ -31,20 +31,24 @@ namespace MCP {
       
       TH2* hist = nullptr;
       fmc->GetObject(histName.c_str(), hist);
-      if (!hist) 
-        {
-	  throw std::invalid_argument("Cannot find hist ("+histName+") in file " + fileName);
-        }
-      hist->SetDirectory(nullptr);
-      m_calibConstantHist.reset(hist);
-      
-      // Store to check later if the input ranges are within the range of the hist
-      // subtract epsilon so that it doesn't go into the overflow bin at the highest edge
-      m_maxX  = m_calibConstantHist->GetXaxis()->GetXmax() - std::numeric_limits<double>::epsilon();
-      m_minX  = m_calibConstantHist->GetXaxis()->GetXmin() + std::numeric_limits<double>::epsilon();
-      m_maxY  = m_calibConstantHist->GetYaxis()->GetXmax() - std::numeric_limits<double>::epsilon();
-      m_minY  = m_calibConstantHist->GetYaxis()->GetXmin() + std::numeric_limits<double>::epsilon();
+      if (!hist) {
+          if (histName.find("ptExtra") != std::string::npos) {
+            // exceptional condition, to make it compatible with old recommendations
+            m_calibConstantHist.reset(nullptr);
+          } else {
+	    throw std::invalid_argument("Cannot find hist ("+histName+") in file " + fileName);
+          }
+      } else {
+        hist->SetDirectory(nullptr);
+        m_calibConstantHist.reset(hist);
       
+        // Store to check later if the input ranges are within the range of the hist
+        // subtract epsilon so that it doesn't go into the overflow bin at the highest edge
+        m_maxX  = m_calibConstantHist->GetXaxis()->GetXmax() - std::numeric_limits<double>::epsilon();
+        m_minX  = m_calibConstantHist->GetXaxis()->GetXmin() + std::numeric_limits<double>::epsilon();
+        m_maxY  = m_calibConstantHist->GetYaxis()->GetXmax() - std::numeric_limits<double>::epsilon();
+        m_minY  = m_calibConstantHist->GetYaxis()->GetXmin() + std::numeric_limits<double>::epsilon();
+      }  
     }
 
     double CalibContainer::getCalibConstant(const TrackCalibObj& trk) const
diff --git a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/Root/MuonCalibIntSagittaTool.cxx b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/Root/MuonCalibIntSagittaTool.cxx
index 2d7637f4c5df..58be9778d4be 100644
--- a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/Root/MuonCalibIntSagittaTool.cxx
+++ b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/Root/MuonCalibIntSagittaTool.cxx
@@ -245,16 +245,58 @@ namespace CP
                 // Till it reach 450 GeV and then to flatten it. 
                 // The value is chosen in an arbitrary fashion. To be replaced and fixed, once we have a better idea of 
                 double corr = 0;
-                //double deltas = 0.00002;
-                double deltas = corrMap->at(MCP::SagittaCorrection::PtExtra__1up)->getCalibConstant(trk);
-                if (pT > 450.0)
+                double deltas = 0.00002;
+               
+                if (corrMap->at(MCP::SagittaCorrection::PtExtra__1up)->mapExist()) {
+                  deltas = corrMap->at(MCP::SagittaCorrection::PtExtra__1up)->getCalibConstant(trk);
+                  if (pT > 450.0)
                     corr += std::abs(450.0 - 45) * deltas;  // Above 450 GeV flat
-                else
+                  else
                     corr += std::abs(pT - 45) * deltas;
-                ATH_MSG_VERBOSE("Deltas corr: "<<deltas);
+                } else {
+                  // old style uncertainty for Run2 and early Run3 recommendations 
+                  if (eta > 2 || (eta > -2 && eta < -1.05)) {
+                      if (pT > 450.0)
+                          corr += std::abs(450.0 - 45) / 100 * deltas;  // Above 450 GeV flat
+                      else
+                          corr += std::abs(pT - 45) / 100 * deltas;
+                  }
+                  if (eta < -2 || (eta < 2 && eta> 1.5)) {
+                      if (pT > 450.0)
+                          corr += std::abs(450.0 - 45) / 200 * deltas;  // Above 450 GeV flat
+                      else
+                          corr += std::abs(pT - 45) / 200 * deltas;
+                  }
+                  // additional uncertainties for 2022 data
+                  if (m_release.value().find("Recs2023") != std::string::npos) {
+                    if ( (trk.year==MCP::DataYear::Data22) && pT > 100.0) {
+                      if (eta < 0 && eta> -0.5) corr += 2.1*deltas;
+                      else if (eta < -1.05) corr += 1.1*deltas;
+                      else if (eta > 0.5 ) corr += 0.8*deltas;
+                    }
+                  } else {
+                    if ( trk.year==MCP::DataYear::Data22 ) {
+                      if (eta > -2 && eta < -1.05) corr = corr*2.5;
+                      if (eta < -2) corr = corr*6;
+                      if (eta > 1.5 && eta < 2) {
+                        if (pT > 450.0)
+                          corr += std::abs(450.0 - 45) / 80 * deltas;  // Above 450 GeV flat
+                        else
+                          corr += std::abs(pT - 45) / 80 * deltas;
+                      }
+                      if (eta > 1.05 && eta < 1.5) {
+                        if (pT > 450.0)
+                          corr += std::abs(450.0 - 45) / 40 * deltas;  // Above 450 GeV flat
+                        else
+                          corr += std::abs(pT - 45) / 40 * deltas;
+                      }
+                    }
+                  }
+                  // done for old style uncertainty for Run2 and early Run3 recommendations 
+                }
 
                 corrections.push_back(corr*scale);
-                ATH_MSG_VERBOSE("final corr: "<<corr);
+                ATH_MSG_VERBOSE("High pT variation for pT "<<pT<<" deltas "<<deltas<<"  final corr: "<<corr);
 
             }
             else if(m_currentParameters->SagittaDataStat != MCP::SystVariation::Default)
-- 
GitLab