diff --git a/PhysicsAnalysis/AnalysisCommon/CPAnalysisExamples/CPAnalysisExamples/MyToolProvider.h b/PhysicsAnalysis/AnalysisCommon/CPAnalysisExamples/CPAnalysisExamples/MyToolProvider.h
index 4527763d1b60bda4e84cc8920561df6d1d171c52..ca6ca3082942727ebd75f91a8265f15778a85d56 100644
--- a/PhysicsAnalysis/AnalysisCommon/CPAnalysisExamples/CPAnalysisExamples/MyToolProvider.h
+++ b/PhysicsAnalysis/AnalysisCommon/CPAnalysisExamples/CPAnalysisExamples/MyToolProvider.h
@@ -1,7 +1,5 @@
-// Dear emacs, this is -*- c++ -*-
-
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 
@@ -22,7 +20,7 @@
 #include "JetResolution/JERTool.h"                 
 #include "JetResolution/JERSmearingTool.h"                   
 #include "JetUncertainties/JetUncertaintiesTool.h"  
-#include "MuonMomentumCorrections/MuonCalibrationAndSmearingTool.h"          
+#include "MuonAnalysisInterfaces/MuonCalibrationAndSmearingTool.h"          
 #include "MuonEfficiencyCorrections/MuonEfficiencyScaleFactors.h"           
 #include "MuonSelectorTools/MuonSelectionTool.h"
 #include "ElectronPhotonFourMomentumCorrection/EgammaCalibrationAndSmearingTool.h"       
diff --git a/PhysicsAnalysis/AnalysisCommon/CPAnalysisExamples/CPAnalysisExamples/ToolExamplesAlg.h b/PhysicsAnalysis/AnalysisCommon/CPAnalysisExamples/CPAnalysisExamples/ToolExamplesAlg.h
index 796504582c6c07a5802047d0c19d43db50957f36..899f6fd21418365a701295ad57b43ff5022b3cd1 100644
--- a/PhysicsAnalysis/AnalysisCommon/CPAnalysisExamples/CPAnalysisExamples/ToolExamplesAlg.h
+++ b/PhysicsAnalysis/AnalysisCommon/CPAnalysisExamples/CPAnalysisExamples/ToolExamplesAlg.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef CPANALYSISEXAMPLES_TOOLEXAMPLESALG_H
@@ -25,8 +25,8 @@
 #include "ElectronEfficiencyCorrection/IAsgElectronEfficiencyCorrectionTool.h"
 
 ///Muons
-#include "MuonMomentumCorrections/IMuonCalibrationAndSmearingTool.h"
-#include "MuonSelectorTools/IMuonSelectionTool.h"
+#include "MuonAnalysisInterfaces/IMuonCalibrationAndSmearingTool.h"
+#include "MuonAnalysisInterfaces/IMuonSelectionTool.h"
 
 #include "MuonAnalysisInterfaces/IMuonEfficiencyScaleFactors.h"
 
diff --git a/PhysicsAnalysis/HiggsPhys/Run2/HZZ/Tools/ZMassConstraint/Root/ConstraintFit.cxx b/PhysicsAnalysis/HiggsPhys/Run2/HZZ/Tools/ZMassConstraint/Root/ConstraintFit.cxx
index 629273d5b79f06442edf492e8627d03b9a00bdda..906e8d86d1c01040fd3e4bcd61eb44f1338f32c9 100644
--- a/PhysicsAnalysis/HiggsPhys/Run2/HZZ/Tools/ZMassConstraint/Root/ConstraintFit.cxx
+++ b/PhysicsAnalysis/HiggsPhys/Run2/HZZ/Tools/ZMassConstraint/Root/ConstraintFit.cxx
@@ -1,23 +1,14 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
-///////////////////////////////////////////////////////////
-// A C++ implementation of Mass constraint fitting
-// 23/09/2006
-// K. Nikolopoulos
-// --- * --- * --- * --- * ---* --- * --- * --- * ---
-//
-//
-//
-//
 #include "xAODEgamma/PhotonxAODHelpers.h"
 #include "xAODTracking/TrackParticle.h"
 #include "ZMassConstraint/ConstraintFit.h"
 #include "ZMassConstraint/ConstraintFitInput.h"
 #include "ZMassConstraint/ConstraintFitOutput.h"
 #include "EgammaAnalysisInterfaces/IEgammaCalibrationAndSmearingTool.h"
-#include "MuonMomentumCorrections/MuonCalibrationAndSmearingTool.h"
+#include "MuonAnalysisInterfaces/IMuonCalibrationAndSmearingTool.h"
 
 namespace ZMassConstraint 
 {
diff --git a/PhysicsAnalysis/JetTagging/JetTagTools/src/JetVertexCharge.cxx b/PhysicsAnalysis/JetTagging/JetTagTools/src/JetVertexCharge.cxx
index 70a3911b36a4984e4e874eea62efe538c85a9423..3fac453b1c3ae33d9785c8f80979584d4c2e9e1e 100644
--- a/PhysicsAnalysis/JetTagging/JetTagTools/src/JetVertexCharge.cxx
+++ b/PhysicsAnalysis/JetTagging/JetTagTools/src/JetVertexCharge.cxx
@@ -26,7 +26,7 @@
 #include "xAODMuon/MuonContainer.h"
 
 #include "MuonAnalysisInterfaces/IMuonSelectionTool.h" 
-#include "MuonMomentumCorrections/IMuonCalibrationAndSmearingTool.h"
+#include "MuonAnalysisInterfaces/IMuonCalibrationAndSmearingTool.h"
 #include "TMVA/Reader.h"
 #include "TList.h"
 #include "TObjString.h"
diff --git a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/CMakeLists.txt b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/CMakeLists.txt
index 4c51e9ae37d5d7c3bdf66dec408a08257dcff902..61e557115ca9671a370a814ac7806e975c0ea388 100644
--- a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/CMakeLists.txt
+++ b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/CMakeLists.txt
@@ -1,4 +1,3 @@
-# $Id: CMakeLists.txt 777720 2016-10-11 16:57:24Z krasznaa $
 ################################################################################
 # Package: MuonMomentumCorrections
 ################################################################################
@@ -20,24 +19,24 @@ atlas_depends_on_subdirs(
    Control/AthToolSupport/AsgTools
    Event/xAOD/xAODMuon
    PhysicsAnalysis/AnalysisCommon/PATInterfaces
+   PhysicsAnalysis/Interfaces/MuonAnalysisInterfaces
+   PhysicsAnalysis/Interfaces/AsgAnalysisInterfaces
    PRIVATE
    Event/xAOD/xAODBase
    Event/xAOD/xAODCore
    Event/xAOD/xAODEventInfo
-   PhysicsAnalysis/MuonID/MuonSelectorTools
    Tools/PathResolver
    ${extra_deps} )
 
 # External dependencies:
-find_package( Boost )
 find_package( ROOT COMPONENTS Core Tree RIO Physics )
 
 # Libraries in the package:
 atlas_add_library( MuonMomentumCorrectionsLib
    MuonMomentumCorrections/*.h Root/*.cxx
    PUBLIC_HEADERS MuonMomentumCorrections
-   INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS}
-   LINK_LIBRARIES ${Boost_LIBRARIES} ${ROOT_LIBRARIES} AsgTools xAODMuon
+   INCLUDE_DIRS  ${ROOT_INCLUDE_DIRS}
+   LINK_LIBRARIES  ${ROOT_LIBRARIES} AsgTools xAODMuon MuonAnalysisInterfacesLib AsgAnalysisInterfaces
    PATInterfaces
    PRIVATE_LINK_LIBRARIES xAODEventInfo PathResolver )
 
@@ -45,7 +44,7 @@ if( NOT XAOD_STANDALONE )
    atlas_add_component( MuonMomentumCorrections
       src/*.h src/*.cxx src/components/*.cxx
       INCLUDE_DIRS ${ROOT_INCLUDE_DIRS}
-      LINK_LIBRARIES ${ROOT_LIBRARIES} AthenaBaseComps xAODMuon xAODCore
+      LINK_LIBRARIES ${ROOT_LIBRARIES} AthenaBaseComps xAODMuon xAODCore MuonAnalysisInterfacesLib AsgAnalysisInterfaces
       xAODBase GaudiKernel MuonSelectorToolsLib MuonMomentumCorrectionsLib )
 endif()
 
@@ -56,11 +55,11 @@ atlas_add_dictionary( MuonMomentumCorrectionsDict
 
 # Executable(s) in the package:
 atlas_add_executable( MCAST_Tester
-  util/MCAST_Tester.cxx
-  INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}
-  LINK_LIBRARIES ${ROOT_LIBRARIES} ${Boost_LIBRARIES} xAODRootAccess
-  xAODEventInfo xAODMuon xAODCore PATInterfaces xAODCore AsgTools
-  MuonSelectorToolsLib MuonMomentumCorrectionsLib )
+   util/MCAST_Tester.cxx
+   INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}
+   LINK_LIBRARIES ${ROOT_LIBRARIES} ${Boost_LIBRARIES} xAODRootAccess
+   xAODEventInfo xAODMuon xAODCore PATInterfaces xAODCore AsgTools AsgAnalysisInterfaces
+   MuonSelectorToolsLib MuonMomentumCorrectionsLib  MuonAnalysisInterfacesLib)
 
 # Install files from the package:
 atlas_install_joboptions( share/*.py )
diff --git a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/MuonMomentumCorrections/IMuonCalibrationAndSmearingTool.h b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/MuonMomentumCorrections/IMuonCalibrationAndSmearingTool.h
deleted file mode 100644
index fe40a1cd392d253f32793ba036ae96187fa107be..0000000000000000000000000000000000000000
--- a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/MuonMomentumCorrections/IMuonCalibrationAndSmearingTool.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
-*/
-
-#ifndef MCAST_IMUONCALIBRATIONANDSMEARINGTOOL_H
-#define MCAST_IMUONCALIBRATIONANDSMEARINGTOOL_H
-
-// Framework include(s):
-#include "AsgTools/IAsgTool.h"
-
-// EDM include(s):
-#include "xAODMuon/Muon.h"
-
-// Local include(s):
-#include "PATInterfaces/CorrectionCode.h"
-#include "PATInterfaces/ISystematicsTool.h"
-#include "PATInterfaces/SystematicCode.h"     
-#include "PATInterfaces/SystematicRegistry.h"
-#include "PATInterfaces/SystematicSet.h"
-#include "PATInterfaces/SystematicVariation.h"
-
-namespace CP {
-
-class IMuonCalibrationAndSmearingTool : public virtual asg::IAsgTool, virtual public CP::ISystematicsTool {
-
-  //::: Declare the interface that the class provides
-  ASG_TOOL_INTERFACE( CP::IMuonCalibrationAndSmearingTool )
-
-public:
-  class IVars
-  {
-  public:
-    virtual ~IVars() = default;
-  };
-
-
-  //::: Apply the correction on a modifyable object
-  virtual CorrectionCode applyCorrection( xAOD::Muon& mu ) const = 0;
-  virtual CorrectionCode applyCorrection( xAOD::Muon& mu,
-                                          std::unique_ptr<IVars>& vars) const = 0;
-  //::: Create a corrected copy from a constant muon
-  virtual CorrectionCode correctedCopy( const xAOD::Muon& input, xAOD::Muon*& output ) const = 0;
-  //::: Is the tool affected by a specific systematic?
-  virtual bool isAffectedBySystematic( const SystematicVariation& systematic ) const = 0;
-  //::: Which systematics have an effect on the tool's behaviour?
-  virtual SystematicSet affectingSystematics() const = 0;
-  //::: Systematics to be used for physics analysis
-  virtual SystematicSet recommendedSystematics() const = 0;
-  //::: Use specific systematic
-  virtual SystematicCode applySystematicVariation ( const SystematicSet& systConfig ) = 0;
-  //::: expectedResolution
-  virtual double expectedResolution( const IVars& vars, const std::string& DetType, const xAOD::Muon& mu, const bool mc ) const=0;
-  //::: expectedResolution
-  virtual double expectedResolution( const IVars& vars, const int DetType, const xAOD::Muon& mu, const bool mc) const=0;
-
-  virtual void setUseStatCombination(bool flag) = 0;
-}; // class IMuonCalibrationAndSmearingTool
-
-} // namespace CP
-
-#endif // MCAST_IMUONCALIBRATIONANDSMEARINGTOOL_H
diff --git a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/MuonMomentumCorrections/MuonCalibrationAndSmearingTool.h b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/MuonMomentumCorrections/MuonCalibrationAndSmearingTool.h
index 7935b60c88a1111497400517a096361745ddc093..8a1d8f6e93fc13a0ebc1960eb4f3a5457a7d1467 100644
--- a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/MuonMomentumCorrections/MuonCalibrationAndSmearingTool.h
+++ b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/MuonMomentumCorrections/MuonCalibrationAndSmearingTool.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef MCAST_MUONCALIBRATIONANDMEARINGTOOL_H
@@ -8,38 +8,36 @@
 // Framework include(s):
 #include "AsgTools/AsgTool.h"
 #include "StoreGate/ReadHandleKey.h"
-
-//EDM include(s)
 #include "xAODEventInfo/EventInfo.h"
+#include "MuonAnalysisInterfaces/IMuonCalibrationAndSmearingTool.h"
 
 // ROOT include(s)
 #include "TRandom3.h"
 #include "TH3F.h"
 #include "TProfile2D.h"
 #include "TFile.h"
+#include "TMatrix.h"
+#include "TVectorD.h"
 
 // C++ include(s)
-#include <boost/unordered_map.hpp>
+#include <unordered_map>
 #include <fstream>
 #include <string>
 #include <vector>
 #include <map>
 
-// Local include(s):
-#include "MuonMomentumCorrections/IMuonCalibrationAndSmearingTool.h"
-
 #define EPSILON 1.0E-6
 #define DEFAULT_INIT_VAL -999
 #define MCAST_MAX_PT 100000000
-#define MZPDG 91.1876 
+#define MZPDG 91.1876
 
 namespace CP {
 
 namespace MCAST {
 
-  namespace DataType { enum { Data10 = 1, Data11 = 2, Data12 = 3, Data15 = 4, Data16=5}; }
+  namespace DataType { enum { Data10 = 1, Data11 = 2, Data12 = 3, Data15 = 4, Data16=5, Data17=6, Data18=7}; }
   namespace AlgoType { enum { Muid = 1, Staco = 2, Muons = 3 }; }
-  namespace Release { enum { Rel16_6 = 1, Rel17 = 2, Rel17_2 = 3, Rel17_2_Repro = 4, Rel17_2_Sum13 = 5, PreRec = 6, PreRec_2015_06_22  = 7, PreRec_2015_08_06  = 8, Rec_2015_11_15 = 9, Rec_2016_01_13 = 10, Rec_2016_01_19 = 11, PreRec_2016_05_23 = 12 , Recs2016_08_07=13 , Recs2016_15_07}; }
+  namespace Release { enum { Rel16_6 = 1, Rel17 = 2, Rel17_2 = 3, Rel17_2_Repro = 4, Rel17_2_Sum13 = 5, PreRec = 6, PreRec_2015_06_22  = 7, PreRec_2015_08_06  = 8, Rec_2015_11_15 = 9, Rec_2016_01_13 = 10, Rec_2016_01_19 = 11, PreRec_2016_05_23 = 12 , Recs2016_08_07=13 , Recs2016_15_07=14, Recs2017_08_02=15}; }
   namespace SmearingType { enum { Pt = 1, QoverPt = 2 }; }
   namespace DetectorType { enum { MS = 1, ID = 2, CB = 3 }; }
   namespace SystVariation { enum { Default = 0, Down = -1, Up = 1 }; }
@@ -50,190 +48,205 @@ namespace MCAST {
 
 class MuonCalibrationAndSmearingTool : public virtual IMuonCalibrationAndSmearingTool, public virtual ISystematicsTool, public asg::AsgTool {
 
-  //::: Create a proper constructor for Athena
+  // Create a proper constructor for Athena
   ASG_TOOL_CLASS2( MuonCalibrationAndSmearingTool, CP::IMuonCalibrationAndSmearingTool, CP::ISystematicsTool )
 
-
-public:
-
-  //::: Constructor
-  MuonCalibrationAndSmearingTool( const std::string& name );
-  
-  //::: Copy constructor
-  MuonCalibrationAndSmearingTool( const MuonCalibrationAndSmearingTool& tool );
-
-  //::: Destructor
-  virtual ~MuonCalibrationAndSmearingTool();
-
-  virtual StatusCode initialize() override;
-
-  //::: Apply the correction on a modifyable object
-  virtual CorrectionCode applyCorrection( xAOD::Muon& mu ) const override;
-  virtual CorrectionCode applyCorrection( xAOD::Muon& mu,
-                                          std::unique_ptr<IVars>& vars) const override;
-  //::: Create a corrected copy from a constant muon
-  virtual CorrectionCode correctedCopy( const xAOD::Muon& input, xAOD::Muon*& output ) const override;
-
-  //::: Is the tool affected by a specific systematic?
-  virtual bool isAffectedBySystematic( const SystematicVariation& systematic ) const override;
-  //::: Which systematics have an effect on the tool's behaviour?
-  virtual SystematicSet affectingSystematics() const override;
-  //::: Systematics to be used for physics analysis
-  virtual SystematicSet recommendedSystematics() const override;
-  //::: Use specific systematic
-  virtual SystematicCode applySystematicVariation ( const SystematicSet& systConfig ) override;
-  virtual double expectedResolution( const IVars& vars, const std::string& DetType, const xAOD::Muon& mu, const bool mc = false ) const override; //!< Expected resolution in data (or unsmeard MC if second argument is true)
-  virtual double expectedResolution( const IVars& vars, const int DetType, const xAOD::Muon& mu, const bool mc = false ) const override; //!< Expected resolution in data (or unsmeard MC if second argument is true)
-
-
-  double ExpectedResolution( const IVars& ivars,
-                             const std::string& DetType, const xAOD::Muon& mu, const bool mc = false ) const; //!< Expected resolution in data (or unsmeard MC if second argument is true)
-  double ExpectedResolution( const IVars& ivars,
-                             const int DetType, const xAOD::Muon& mu, const bool mc = false ) const; //!< Expected resolution in data (or unsmeard MC if second argument is true)
-
- 
-  virtual void setUseStatCombination(bool flag) override;
-  
-
-private:
-  struct Vars : public IVars
-  {
-    double m_ptms = 0;
-    double m_ptid = 0;
-    double m_ptcb = 0;
-    double m_weightID = 0;
-    double m_weightMS = 0;
-    double m_charge = 0;
-    double m_eta = 0;
-    double m_smearDeltaMS = 0;
-    double m_smearDeltaID = 0;
-    double m_smearDeltaCB = 0;
-    int m_detRegion = -1;
-    double m_g0 = 0;
-    double m_g1 = 0;
-    double m_g2 = 0;
-    double m_g3 = 0;
-    double m_g4 = 0;
-  };
-
-  CorrectionCode applyStatCombination( const ElementLink< xAOD::TrackParticleContainer >& inDetTrackParticle, 
-                                       const ElementLink< xAOD::TrackParticleContainer >& extrTrackParticle ,
-                                       int charge,
-                                       AmgVector(5)& parsCB,
-                                       AmgSymMatrix(5)& covCB,
-                                       double& chi2) const;
-  CorrectionCode applyStatCombination( xAOD::Muon& mu ) const;
-
-  CorrectionCode applySagittaBiasCorrectionAuto(Vars& vars,
-                                                const int DetType,const xAOD::Muon& mu,bool isMC=false,const unsigned int SytCase=0) const;
- 
-   CorrectionCode CorrectForCharge(double p2,double& pt,int q=0, bool isMC=false) const;
-  CorrectionCode applyiSagittaBiasCorrection(Vars& vars,
-                                             const unsigned int SgCorrType, const xAOD::Muon& mu,unsigned int iter=0,bool stop=false,bool isMC=false) const;
- 
-
-  //::: Regions helpers 
-  StatusCode   Regions( std::string inRegionFile, int doMacroRegionsFlag = 0 );
-  void         PrintRegions() const;
-  unsigned int GetNRegions() const;
-  int          GetRegion( const double eta, const double phi ) const;
-  float        GetRegionInnerEta( const int r_i ) const; //Return Eta closer to the origin
-  std::string  GetRegionName( const int r_i ) const;
-  std::string  GetRegionName( const double eta, const double phi ) const;
-  double GetSmearing( const Vars& vars, int, const xAOD::Muon& ) const;
-  double GetSystVariation( const Vars& vars, int DetType, double var ) const;
-  int GetScaleRegion( const xAOD::Muon& ) const;
-  void CalcCBWeights( Vars& vars, const xAOD::Muon& ) const;
-  double CalculatePt( const Vars& vars,
-                      const int DetType, const double inSmearID, const double inSmearMS, const double scaleVar ) const;
-  StatusCode FillValues();
-  void Clean();
-  double ScaleApply( const int detRegion,
-                     const double pt, double S = 1.0, const double S_EnLoss = 0. ) const;
-  //double ScaleApply( const double pt, const double S1, const double S2, double S = 1.0, const double S_EnLoss = 0. ) const;
-  void CleanScales();
-  void CollectMacroRegionsSL();//Small and large regions are collected together
-  void CollectMacroRegionsSL_UpDn();//Small,Large,Up,Down regions are collected together
-  void CollectMacroRegionsSL_SplitBAR();//Large,Small sectors split plus Feet(12+14) and 11+15 sector split in Barrel
-  void CollectSectors();
-
-  StatusCode SetData( const std::string& );
-  StatusCode SetAlgorithm( const std::string& );
-  StatusCode SetRelease( const std::string& );
-  StatusCode SetType( const std::string& );
-  
-  unsigned int setSagittaHistogramsSingle(TProfile2D *pCB=NULL,unsigned int track=0);
-  double  sagitta(TProfile2D* corrM, TLorentzVector &lv) const;
-  
-  void ConvertToSagittaBias(TH2F *h,float mean=1) const;
-  TProfile2D* GetHist(const std::string &fname="", const std::string &hname="inclusive",double GlobalScale=MZPDG) const;
-
-  //private:
-  //::: fake assignment operator missing actual implementation
-  MuonCalibrationAndSmearingTool& operator=(const MuonCalibrationAndSmearingTool& )= delete;
-
-  struct ParameterSet { 
-    double SmearTypeID; 
-    double SmearTypeMS; 
-    double Scale; 
-    double SagittaRho;
-    double SagittaBias;
-  };
-  std::string m_year, m_algo, m_type, m_release;
-  std::string m_FilesPath;
-  bool m_toroidOff;
-  int m_Tsmear;
-  //int m_Tdet;
-  int m_Tdata;
-  int m_Trel;
-  int m_Talgo;
-  double m_useNsigmaForICombine;
-  std::vector<double> m_scale_ID, m_enLoss_MS, m_scale_MS, m_scale_CB;
-  //sys variations (stat error added in quadrature), one if it's simmetrized, 2 if Up != Dw.
-  std::vector<double> m_scaleSyst_ID, m_enLossSyst_MS, m_scaleSyst_MS, m_scaleSyst_CB;
-  std::vector<double> m_scaleSystUp_ID, m_enLossSystUp_MS, m_scaleSystUp_MS;
-  std::vector<double> m_scaleSystDw_ID, m_enLossSystDw_MS, m_scaleSystDw_MS;
-
-  std::vector<double> m_scaleBins;
-  std::vector<double> m_p1_ID, m_p2_ID, m_p2_ID_TAN, m_p0_MS, m_p1_MS, m_p2_MS;
-  std::vector<double> m_E_p1_ID, m_E_p2_ID, m_E_p2_ID_TAN, m_E_p0_MS, m_E_p1_MS, m_E_p2_MS;
-  // syst. errors on resolution parameters corrections:
-  //one if it's simmetrized, then Stat and Sys err are separate in cfg file.
-  std::vector<double> m_S_p1_ID, m_S_p2_ID, m_S_p2_ID_TAN, m_S_p0_MS, m_S_p1_MS, m_S_p2_MS;
-  //Two if Up != Dw, Stat and Sys err added in quadrature in cfg file.
-  std::vector<double> m_SUp_p1_ID, m_SUp_p2_ID, m_SUp_p2_ID_TAN, m_SUp_p0_MS, m_SUp_p1_MS, m_SUp_p2_MS;
-  std::vector<double> m_SDw_p1_ID, m_SDw_p2_ID, m_SDw_p2_ID_TAN, m_SDw_p0_MS, m_SDw_p1_MS, m_SDw_p2_MS;
-  std::vector<double> m_MC_p1_ID, m_MC_p2_ID, m_MC_p2_ID_TAN, m_MC_p0_MS, m_MC_p1_MS, m_MC_p2_MS;
-
-  std::vector<std::string> m_names;
-  bool m_loadNames;
-  int m_nb_regions;
-  std::vector<float> m_eta_min, m_eta_max, m_phi_min, m_phi_max;
-  
-  bool m_doMacroRegions;
-  std::map< int, int > m_MacroRegionIdxMap;
-  std::vector< std::string > m_MacroRegionName;
-  std::vector< double > m_MacroRegionInnerEta;
-
-  SG::ReadHandleKey<xAOD::EventInfo> m_eventInfo{this,"EventInfo","EventInfo","EventInfo"}; 
-  
-  boost::unordered_map< SystematicSet, ParameterSet > m_Parameters;
-  ParameterSet *m_currentParameters;
-  
-  double m_StatCombPtThreshold;
-  bool m_useStatComb;
-  
-  std::vector <TProfile2D*> *m_sagittasCB;
-  std::vector <TProfile2D*> *m_sagittasID;
-  std::vector <TProfile2D*> *m_sagittasME;
-
-  bool m_doSagittaCorrection;
-  std::vector <double> m_GlobalZScales;
-  std::vector <unsigned int > m_SagittaIterations;
-  
-
-}; //::: class MuonCalibrationAndSmearingTool
-
-} //::: namespace CP
+  public:
+    // Interface methods that must be defined
+    // Interface - Apply the correction on a modifyable object
+    virtual CorrectionCode applyCorrection( xAOD::Muon& mu ) const override;
+    // Interface - Create a corrected copy from a constant muon
+    virtual CorrectionCode correctedCopy( const xAOD::Muon& input, xAOD::Muon*& output ) const override;
+    // Interface - Is the tool affected by a specific systematic?
+    virtual bool isAffectedBySystematic( const SystematicVariation& systematic ) const override;
+    // Interface - Which systematics have an effect on the tool's behaviour?
+    virtual SystematicSet affectingSystematics() const override;
+    // Interface - Systematics to be used for physics analysis
+    virtual SystematicSet recommendedSystematics() const override;
+    // Interface - Use specific systematic
+    virtual SystematicCode applySystematicVariation ( const SystematicSet& systConfig ) override;
+    // Interface - get the expected resolution of the muon
+    virtual double expectedResolution( const std::string& DetType, const xAOD::Muon& mu, const bool mc ) const override;
+    // Interface - get the expected resolution of the muon
+    virtual double expectedResolution( const int& DetType, const xAOD::Muon& mu, const bool mc ) const override;
+
+  public:
+    // InfoHelper is intended to be used to ease the passing of information between internal
+    // methods within this class.  This is created in anticipation of usage in AthenaMT
+    struct InfoHelper{
+      double ptms = 0;
+      double ptid = 0;
+      double ptcb = 0;
+      double eta = 0;
+      double phi = 0;
+      double g0;
+      double g1;
+      double g2;
+      double g3;
+      double g4;
+      int    charge = 1;
+      int    detRegion = 0;
+      std::vector < float >  cbParsA;
+      std::vector < float >  cbCovMat;
+      double weightMS = 0;
+      double weightID = 0;
+      double smearDeltaMS = 0;
+      double smearDeltaID = 0;
+      double smearDeltaCB = 0;
+    };
+
+  public:
+
+    // Constructor
+    MuonCalibrationAndSmearingTool( const std::string& name );
+
+    // Copy constructor
+    MuonCalibrationAndSmearingTool( const MuonCalibrationAndSmearingTool& tool );
+
+    // Destructor
+    virtual ~MuonCalibrationAndSmearingTool();
+
+    virtual StatusCode initialize() override;
+
+    double ExpectedResolution( const std::string& DetType, const xAOD::Muon& mu, const bool mc ) const;
+    double ExpectedResolution( const int DetType, const xAOD::Muon& mu, const bool mc ) const;
+
+    // Expert method to apply the MC correction on a modifyable trackParticle for ID- or MS-only corrections
+    virtual CorrectionCode applyCorrectionTrkOnly( xAOD::TrackParticle& inTrk, const int DetType ) const override;
+
+    virtual CorrectionCode applyStatCombination( const ElementLink< xAOD::TrackParticleContainer >& inDetTrackParticle,
+                                                 const ElementLink< xAOD::TrackParticleContainer >& extrTrackParticle ,
+                                                 int charge,
+                                                 AmgVector(5)& parsCB,
+                                                 AmgSymMatrix(5)& covCB,
+                                                 double& chi2) const;
+    virtual CorrectionCode applyStatCombination( xAOD::Muon& mu, InfoHelper& muonInfo ) const;
+    virtual CorrectionCode applySagittaBiasCorrectionAuto(const int DetType, xAOD::Muon& mu, bool isMC, const unsigned int SytCase, InfoHelper& muonInfo) const;
+    virtual CorrectionCode CorrectForCharge(double p2, double& pt, int q, bool isMC, double p2Kin=0) const;
+    virtual CorrectionCode applySagittaBiasCorrection(const unsigned int SgCorrType, xAOD::Muon& mu, unsigned int iter, bool stop, bool isMC, InfoHelper& muonInfo) const;
+
+
+  protected:
+    // Regions helpers
+    StatusCode   Regions( std::string inRegionFile, int doMacroRegionsFlag = 0 );
+    void         PrintRegions() const;
+    unsigned int GetNRegions() const;
+    int          GetRegion( const double eta, const double phi ) const;
+    float        GetRegionInnerEta( const int r_i ) const; //Return Eta closer to the origin
+    std::string  GetRegionName( const int r_i ) const;
+    std::string  GetRegionName( const double eta, const double phi ) const;
+    double GetSmearing( int DetType, InfoHelper& muonInfo ) const;
+    double GetSystVariation( int DetType, double var, InfoHelper& muonInfo ) const;
+    StatusCode SetInfoHelperCorConsts(InfoHelper& inMuonInfo) const;
+    void CalcCBWeights( xAOD::Muon&, InfoHelper& muonInfo ) const;
+    double CalculatePt( const int DetType, const double inSmearID, const double inSmearMS, const double scaleVar, InfoHelper& muonInfo ) const;
+    StatusCode FillValues();
+    void Clean();
+    double ScaleApply( const double pt, double S, const double S_EnLoss, InfoHelper& muonInfo ) const;
+    void CleanScales();
+    void CollectMacroRegionsSL();//Small and large regions are collected together
+    void CollectMacroRegionsSL_UpDn();//Small,Large,Up,Down regions are collected together
+    void CollectMacroRegionsSL_SplitBAR();//Large,Small sectors split plus Feet(12+14) and 11+15 sector split in Barrel
+    void CollectSectors();
+
+    StatusCode SetData( std::string );
+    StatusCode SetAlgorithm( std::string );
+    StatusCode SetRelease( std::string );
+    StatusCode SetType( std::string );
+
+    virtual unsigned int setSagittaHistogramsSingle(TProfile2D *pCB=NULL,unsigned int track=0);
+    virtual double  sagitta(TProfile2D* corrM, TLorentzVector &lv) const;
+
+    virtual void ConvertToSagittaBias(TH2F *h,float mean=1);
+    virtual TProfile2D* GetHist(const std::string &fname="", const std::string &hname="inclusive",double GlobalScale=MZPDG);
+    virtual bool isBadMuon( const xAOD::Muon& mu, InfoHelper& muonInfo ) const;
+    //private:
+    // fake assignment operator missing actual implementation
+    MuonCalibrationAndSmearingTool& operator=(const MuonCalibrationAndSmearingTool& );
+
+    struct ParameterSet {
+      double SmearTypeID;
+      double SmearTypeMS;
+      double Scale;
+      double SagittaRho;
+      double SagittaBias;
+    };
+
+    SG::ReadHandleKey<xAOD::EventInfo> m_eventInfo{this, "EventInfoContName", "EventInfo", "event info key"};
+
+    bool  m_useExternalSeed;
+    int   m_externalSeed;
+
+    std::string m_year, m_algo, m_type, m_release;
+    std::string m_FilesPath;
+    bool m_toroidOff;
+    int m_Tsmear;
+    int m_Tdata;
+    int m_Trel;
+    int m_Talgo;
+    double m_useNsigmaForICombine;
+    std::vector<double> m_scale_ID, m_enLoss_MS, m_scale_MS, m_scale_CB;
+
+    //sys variations (stat error added in quadrature), one if it's simmetrized, 2 if Up != Dw.
+    std::vector<double> m_scaleSyst_ID, m_enLossSyst_MS, m_scaleSyst_MS, m_scaleSyst_CB;
+    std::vector<double> m_scaleSystUp_ID, m_enLossSystUp_MS, m_scaleSystUp_MS;
+    std::vector<double> m_scaleSystDw_ID, m_enLossSystDw_MS, m_scaleSystDw_MS;
+
+    std::vector<double> m_scaleBins;
+    std::vector<double> m_p1_ID, m_p2_ID, m_p2_ID_TAN, m_p0_MS, m_p1_MS, m_p2_MS;
+    std::vector<double> m_E_p1_ID, m_E_p2_ID, m_E_p2_ID_TAN, m_E_p0_MS, m_E_p1_MS, m_E_p2_MS;
+    // syst. errors on resolution parameters corrections:
+    //one if it's simmetrized, then Stat and Sys err are separate in cfg file.
+    std::vector<double> m_S_p1_ID, m_S_p2_ID, m_S_p2_ID_TAN, m_S_p0_MS, m_S_p1_MS, m_S_p2_MS;
+    //Two if Up != Dw, Stat and Sys err added in quadrature in cfg file.
+    std::vector<double> m_SUp_p1_ID, m_SUp_p2_ID, m_SUp_p2_ID_TAN, m_SUp_p0_MS, m_SUp_p1_MS, m_SUp_p2_MS;
+    std::vector<double> m_SDw_p1_ID, m_SDw_p2_ID, m_SDw_p2_ID_TAN, m_SDw_p0_MS, m_SDw_p1_MS, m_SDw_p2_MS;
+    std::vector<double> m_MC_p1_ID, m_MC_p2_ID, m_MC_p2_ID_TAN, m_MC_p0_MS, m_MC_p1_MS, m_MC_p2_MS;
+
+    std::vector<std::string> m_names;
+    bool m_loadNames;
+    int m_nb_regions;
+    std::vector<float> m_eta_min, m_eta_max, m_phi_min, m_phi_max;
+
+    bool m_doMacroRegions;
+    std::map< int, int > m_MacroRegionIdxMap;
+    std::vector< std::string > m_MacroRegionName;
+    std::vector< double > m_MacroRegionInnerEta;
+
+    std::unordered_map< SystematicSet, ParameterSet > m_Parameters;
+    ParameterSet *m_currentParameters;
+
+    double m_StatCombPtThreshold;
+    bool m_useStatComb;
+
+    unsigned int m_sgItersID;
+    unsigned int m_sgItersCB;
+    unsigned int m_sgItersME;
+    bool m_sgIetrsManual;
+    double m_fixedRho;
+    bool m_useFixedRho;
+
+    std::vector <TProfile2D*> *m_sagittasCB;
+    std::vector <TProfile2D*> *m_sagittasID;
+    std::vector <TProfile2D*> *m_sagittasME;
+
+    bool m_SagittaCorrPhaseSpace;
+    bool m_doSagittaCorrection;
+    bool m_doSagittaMCDistortion;
+    bool m_doNotUseAMGMATRIXDECOR;
+
+    TProfile2D *m_sagittaPhaseSpaceCB;
+    TProfile2D *m_sagittaPhaseSpaceID;
+    TProfile2D *m_sagittaPhaseSpaceME;
+
+    std::string m_SagittaRelease;
+    std::vector <unsigned int > m_SagittaIterations;
+    std::vector <double> m_GlobalZScales;
+
+
+
+  }; // class MuonCalibrationAndSmearingTool
+
+} // namespace CP
 
 #endif
diff --git a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/MuonMomentumCorrections/MuonCalibrationPeriodTool.h b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/MuonMomentumCorrections/MuonCalibrationPeriodTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..668675db73d23b6de5fb53fd4cc67a07a21f2608
--- /dev/null
+++ b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/MuonMomentumCorrections/MuonCalibrationPeriodTool.h
@@ -0,0 +1,114 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef MCAST_MuonCalibrationPeriodTool_H
+#define MCAST_MuonCalibrationPeriodTool_H
+
+// Framework include(s):
+#include <AsgTools/AsgMetadataTool.h>
+#include <AsgTools/AnaToolHandle.h>
+#include "StoreGate/ReadHandleKey.h"
+#include "MuonAnalysisInterfaces/IMuonCalibrationAndSmearingTool.h"
+
+// EDM include(s):
+#include "xAODEventInfo/EventInfo.h"
+
+namespace CP {
+
+
+class MuonCalibrationPeriodTool : public virtual IMuonCalibrationAndSmearingTool, public virtual ISystematicsTool, public asg::AsgMetadataTool {
+  
+  // Create a proper constructor for Athena
+  ASG_TOOL_CLASS2( MuonCalibrationPeriodTool, CP::IMuonCalibrationAndSmearingTool, CP::ISystematicsTool )
+  
+  public:
+     // There are two recommended options by MCP to setup the tool (https://twiki.cern.ch/twiki/bin/viewauth/AtlasProtected/MCPAnalysisConsolidationMC16)
+     //  1) Correct data for the sagitta bias -- if no statistical limits
+     //  2) Add extra systematic for MC and keep data untouched
+     //  The calibration mode can be set via the property 'calibrationMode'
+     enum CalibMode{
+        correctData =0,
+        additionalMCsys = 1, // <--- default
+        expert =2
+     };
+     /// Apply the correction on a modifyable object
+    virtual CorrectionCode applyCorrection( xAOD::Muon& mu ) const override;
+    /// Create a corrected copy from a constant muon
+    virtual CorrectionCode correctedCopy( const xAOD::Muon& input, xAOD::Muon*& output ) const override;
+    /// Get the expected pT resolution
+    virtual double expectedResolution( const std::string& DetType, const xAOD::Muon& mu, const bool mc ) const override;
+    /// Get the expected pT resolution - int argument is more efficient
+    virtual double expectedResolution( const int& DetType, const xAOD::Muon& mu, const bool mc ) const override;
+    /// Expert method to apply the MC correction on a modifyable trackParticle for ID- or MS-only corrections
+    virtual CorrectionCode applyCorrectionTrkOnly( xAOD::TrackParticle& inTrk, const int DetType) const override;
+    
+    
+    // Interface - Is the tool affected by a specific systematic?
+    virtual bool isAffectedBySystematic( const SystematicVariation& systematic ) const override;
+    // Interface - Which systematics have an effect on the tool's behaviour?
+    virtual SystematicSet affectingSystematics() const override;
+    // Interface - Systematics to be used for physics analysis
+    virtual SystematicSet recommendedSystematics() const override;
+    // Interface - Use specific systematic
+    virtual SystematicCode applySystematicVariation ( const SystematicSet& systConfig ) override;
+    
+    // Constructor
+    MuonCalibrationPeriodTool( const std::string& name );
+
+    // Destructor
+    virtual ~MuonCalibrationPeriodTool();
+
+    // Initializing the subtools
+    virtual StatusCode initialize() override;
+    
+    private:
+        
+        unsigned int getPeriod() const;
+        const CP::IMuonCalibrationAndSmearingTool* getTool() const;
+        
+        // Have three tool instances for each Monte Carlo campaign
+        asg::AnaToolHandle<CP::IMuonCalibrationAndSmearingTool> m_calibTool_1516;
+        asg::AnaToolHandle<CP::IMuonCalibrationAndSmearingTool> m_calibTool_17;
+        asg::AnaToolHandle<CP::IMuonCalibrationAndSmearingTool> m_calibTool_18;
+        
+        SG::ReadHandleKey<xAOD::EventInfo> m_eventInfo{this, "EventInfoContName", "EventInfo", "event info key"};
+        
+        // Sagitta and calibration releases which are parsed to
+        // the three instances of the tool
+        std::string m_sagittaRelease1516;
+        std::string m_sagittaRelease17;
+        std::string m_sagittaRelease18;
+        std::string m_release;
+        
+        int m_calib_mode;
+        
+        bool m_StatComb1516;
+        bool m_SagittaCorr1516;
+        bool m_SagittaMCDistortion1516;
+        bool m_SagittaCorrPhaseSpace1516;
+        
+        bool m_StatComb17;
+        bool m_SagittaCorr17;
+        bool m_SagittaMCDistortion17;
+        bool m_SagittaCorrPhaseSpace17;
+        
+        bool m_StatComb18;
+        bool m_SagittaCorr18;
+        bool m_SagittaMCDistortion18;
+        bool m_SagittaCorrPhaseSpace18;
+        
+        
+        
+        // Monte Carlo runNumbers correspond to different production campaigns
+        std::vector<unsigned int> m_MCperiods1516;
+        std::vector<unsigned int> m_MCperiods17;
+        std::vector<unsigned int> m_MCperiods18;
+        // Optionally one can use the random run number to assign the right tool in MC
+        bool m_useRndRun;
+ 
+  }; 
+
+} // namespace CP
+
+#endif
diff --git a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/MuonMomentumCorrections/MuonMomentumCorrectionsDict.h b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/MuonMomentumCorrections/MuonMomentumCorrectionsDict.h
index 6fefb4d650d4eccf82a568c1fa86ee2b318c1a21..661e0ab0d25a318da84a9bb6307255424c7f5152 100644
--- a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/MuonMomentumCorrections/MuonMomentumCorrectionsDict.h
+++ b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/MuonMomentumCorrections/MuonMomentumCorrectionsDict.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef MUONMOMENTUMCORRECTIONS_MUONMOMENTUMCORRECTIONSDICT_H
@@ -9,7 +9,8 @@
 #define EIGEN_DONT_VECTORIZE
 #endif // __GCCXML__
 
-#include "MuonMomentumCorrections/IMuonCalibrationAndSmearingTool.h"
+#include "MuonAnalysisInterfaces/IMuonCalibrationAndSmearingTool.h"
 #include "MuonMomentumCorrections/MuonCalibrationAndSmearingTool.h"
+#include "MuonMomentumCorrections/MuonCalibrationPeriodTool.h"
 
 #endif // not MUONMOMENTUMCORRECTIONS_MUONMOMENTUMCORRECTIONSDICT_H
diff --git a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/MuonMomentumCorrections/selection.xml b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/MuonMomentumCorrections/selection.xml
index a5f089e75d968455793eb67102beae5a66c88337..d5e7c45d239484b3970b4b61f1997d06d3a3341a 100644
--- a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/MuonMomentumCorrections/selection.xml
+++ b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/MuonMomentumCorrections/selection.xml
@@ -1,8 +1,8 @@
 <lcgdict>
 
   <!-- Tools in this package -->
-  <class name="CP::IMuonCalibrationAndSmearingTool" />
   <class name="CP::MuonCalibrationAndSmearingTool" />
+  <class name="CP::MuonCalibrationPeriodTool" />
 
   <!-- Suppress the unwanted classes found by ROOT 6. -->
   <!-- Hopefully we can remove these extra lines at one point... -->
diff --git a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/Root/MuonCalibrationAndSmearingTool.cxx b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/Root/MuonCalibrationAndSmearingTool.cxx
index 2f94d246a168a921260e314f340b82b1a6862e53..dfbae377248ef07c0ceedb48c4da35a651250866 100644
--- a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/Root/MuonCalibrationAndSmearingTool.cxx
+++ b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/Root/MuonCalibrationAndSmearingTool.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 // Framework include(s):
@@ -11,2378 +11,2753 @@
 
 namespace CP {
 
-MuonCalibrationAndSmearingTool::MuonCalibrationAndSmearingTool( const std::string& name ) :
-  asg::AsgTool( name ),
-  m_Tsmear( 0 ),
-  //m_Tdet( 0 ),
-  m_Tdata( 0 ), m_Trel( 0 ), m_Talgo( 0 ), 
-
-  m_useNsigmaForICombine( 0. ),
-
-  m_loadNames( false ), m_nb_regions( 0. ), m_doMacroRegions( false ), m_StatCombPtThreshold(300.00),  m_useStatComb(false), m_doSagittaCorrection(false){
-
-  declareProperty( "Year", m_year = "Data16" );
-  declareProperty( "Algo", m_algo = "muons" );
-  declareProperty( "SmearingType", m_type = "q_pT" );
-  //  declareProperty( "Release", m_release = "Recs2016_08_07" );
-  declareProperty( "Release", m_release = "Recs2016_15_07" );
-  declareProperty( "ToroidOff", m_toroidOff = false );
-  declareProperty( "FilesPath", m_FilesPath = "" );
-
-  m_currentParameters = NULL; 
-  
-  m_SagittaIterations.push_back(0);
-  m_SagittaIterations.push_back(0);
-  m_SagittaIterations.push_back(0);
-  m_sagittasCB=new std::vector <TProfile2D*>();
-  m_sagittasID=new  std::vector <TProfile2D*>();
-  m_sagittasME=new std::vector <TProfile2D*>();
-  
-
-}
-
-MuonCalibrationAndSmearingTool::MuonCalibrationAndSmearingTool( const MuonCalibrationAndSmearingTool& tool ) : 
-  asg::AsgTool( tool.name() + "Copy" ),
-
-  m_Tsmear( tool.m_Tsmear ),
-  //m_Tdet( tool.m_Tdet ),
-  m_Tdata( tool.m_Tdata ),
-  m_Trel( tool.m_Trel ),
-  m_Talgo( tool.m_Talgo ),
-
-  m_useNsigmaForICombine( tool.m_useNsigmaForICombine ),
-
-  m_scale_ID( tool.m_scale_ID ),
-  m_enLoss_MS( tool.m_enLoss_MS ),
-  m_scale_MS( tool.m_scale_MS ),
-  m_scale_CB( tool.m_scale_CB ),
-
-  m_scaleSyst_ID( tool.m_scaleSyst_ID ),
-  m_enLossSyst_MS( tool.m_enLossSyst_MS ),
-  m_scaleSyst_MS( tool.m_scaleSyst_MS ),
-  m_scaleSyst_CB( tool.m_scaleSyst_CB ),
-
-  m_scaleSystUp_ID( tool.m_scaleSystUp_ID ),
-  m_enLossSystUp_MS( tool.m_enLossSystUp_MS ),
-  m_scaleSystUp_MS( tool.m_scaleSystUp_MS ),
-
-  m_scaleSystDw_ID( tool.m_scaleSystDw_ID ),
-  m_enLossSystDw_MS( tool.m_enLossSystDw_MS ),
-  m_scaleSystDw_MS( tool.m_scaleSystDw_MS ),
-
-  m_p1_ID( tool.m_p1_ID ),
-  m_p2_ID( tool.m_p2_ID ),
-  m_p2_ID_TAN( tool.m_p2_ID_TAN ),
-  m_p0_MS( tool.m_p0_MS ),
-  m_p1_MS( tool.m_p1_MS ),
-  m_p2_MS( tool.m_p2_MS ),
-
-  m_E_p1_ID( tool.m_E_p1_ID ),
-  m_E_p2_ID( tool.m_E_p2_ID ),
-  m_E_p2_ID_TAN( tool.m_E_p2_ID_TAN ),
-  m_E_p0_MS( tool.m_E_p0_MS ),
-  m_E_p1_MS( tool.m_E_p1_MS ),
-  m_E_p2_MS( tool.m_E_p2_MS ),
-  m_S_p1_ID( tool.m_S_p1_ID ),
-  m_S_p2_ID( tool.m_S_p2_ID ),
-  m_S_p2_ID_TAN( tool.m_S_p2_ID_TAN ),
-  m_S_p0_MS( tool.m_S_p0_MS ),
-  m_S_p1_MS( tool.m_S_p1_MS ),
-  m_S_p2_MS( tool.m_S_p2_MS ),
-
-  m_SUp_p1_ID( tool.m_SUp_p1_ID ),
-  m_SUp_p2_ID( tool.m_SUp_p2_ID ),
-  m_SUp_p2_ID_TAN( tool.m_SUp_p2_ID_TAN ),
-  m_SUp_p0_MS( tool.m_SUp_p0_MS ),
-  m_SUp_p1_MS( tool.m_SUp_p1_MS ),
-  m_SUp_p2_MS( tool.m_SUp_p2_MS ),
-  m_SDw_p1_ID( tool.m_SDw_p1_ID ),
-  m_SDw_p2_ID( tool.m_SDw_p2_ID ),
-  m_SDw_p2_ID_TAN( tool.m_SDw_p2_ID_TAN ),
-  m_SDw_p0_MS( tool.m_SDw_p0_MS ),
-  m_SDw_p1_MS( tool.m_SDw_p1_MS ),
-  m_SDw_p2_MS( tool.m_SDw_p2_MS ),
-
-  m_MC_p1_ID( tool.m_MC_p1_ID ),
-  m_MC_p2_ID( tool.m_MC_p2_ID ),
-  m_MC_p2_ID_TAN( tool.m_MC_p2_ID_TAN ),
-  m_MC_p0_MS( tool.m_MC_p0_MS ),
-  m_MC_p1_MS( tool.m_MC_p1_MS ),
-  m_MC_p2_MS( tool.m_MC_p2_MS ),
-
-  m_names( tool.m_names ),
-  m_loadNames( tool.m_loadNames ),
-  m_nb_regions( tool.m_nb_regions ),
-  m_eta_min( tool.m_eta_min ),
-  m_eta_max( tool.m_eta_max ),
-  m_phi_min( tool.m_phi_min ),
-  m_phi_max( tool.m_phi_max ),
-
-  m_doMacroRegions( tool.m_doMacroRegions ),
-  m_MacroRegionIdxMap( tool.m_MacroRegionIdxMap ),
-  m_MacroRegionName( tool.m_MacroRegionName ),
-  m_MacroRegionInnerEta( tool.m_MacroRegionInnerEta ),
-  m_Parameters( tool.m_Parameters ),
-  m_currentParameters( NULL),
-  m_StatCombPtThreshold(tool.m_StatCombPtThreshold),
-  m_useStatComb(tool.m_useStatComb),
-  m_doSagittaCorrection(tool.m_doSagittaCorrection),
-  m_GlobalZScales(tool.m_GlobalZScales),
-  m_SagittaIterations(tool.m_SagittaIterations){
-  
-  declareProperty( "Year", m_year = "Data16" );
-  declareProperty( "Algo", m_algo = "muons" );
-  declareProperty( "SmearingType", m_type = "q_pT" );
-  declareProperty( "Release", m_release = "Recs2016_15_07" );
-  //declareProperty( "Release", m_release = "Recs2016_08_07" );
-  //declareProperty( "Release", m_release = "PreRecs2016_05_23" );
-  declareProperty( "ToroidOff", m_toroidOff = false );
-  declareProperty( "FilesPath", m_FilesPath = "" );
-  
-}
+  MuonCalibrationAndSmearingTool::MuonCalibrationAndSmearingTool( const std::string& name ) :
+    asg::AsgTool( name ),
+    m_externalSeed(0),
+    m_Tsmear( 0 ),
+    m_Tdata( 0 ),
+    m_Trel( 0 ),
+    m_Talgo( 0 ),
+    m_useNsigmaForICombine( 0. ),
+    m_loadNames( false ),
+    m_nb_regions( 0. ),
+    m_doMacroRegions( false ),
+    m_StatCombPtThreshold(300.00),
+    m_useStatComb(false),
+    m_SagittaCorrPhaseSpace(false),
+    m_doSagittaCorrection(false),
+    m_doSagittaMCDistortion(false),
+    m_SagittaRelease("sagittaBiasDataAll_03_02_19"){
+
+    declareProperty("Year", m_year = "Data16" );
+    declareProperty("Algo", m_algo = "muons" );
+    declareProperty("SmearingType", m_type = "q_pT" );
+    declareProperty("Release", m_release = "Recs2019_05_30" );
+    declareProperty("ToroidOff", m_toroidOff = false );
+    declareProperty("FilesPath", m_FilesPath = "" );
+    declareProperty("StatComb", m_useStatComb = false);
+    declareProperty("MinCombPt", m_StatCombPtThreshold=300.0);
+    declareProperty("SagittaCorr", m_doSagittaCorrection = false);
+    declareProperty("SagittaRelease", m_SagittaRelease = "sagittaBiasDataAll_03_02_19");
+    declareProperty("doSagittaMCDistortion",m_doSagittaMCDistortion=true);
+    declareProperty("SagittaCorrPhaseSpace",m_SagittaCorrPhaseSpace=false);
+    declareProperty("sgItersCB",m_sgItersCB=4);
+    declareProperty("sgItersID",m_sgItersID=4);
+    declareProperty("sgItersME",m_sgItersME=4);
+    declareProperty("sgIetrsManual",m_sgIetrsManual=false);
+    declareProperty("fixedRho",m_fixedRho=1.0);
+    declareProperty("useFixedRho",m_useFixedRho=false);
+    declareProperty("noEigenDecor" ,m_doNotUseAMGMATRIXDECOR=false);
+    declareProperty("useExternalSeed" ,m_useExternalSeed=false);
+    declareProperty("externalSeed" ,m_externalSeed=0);
+
+    m_currentParameters = nullptr;
+    m_SagittaIterations.push_back(0);
+    m_SagittaIterations.push_back(0);
+    m_SagittaIterations.push_back(0);
+    m_sagittasCB=new std::vector <TProfile2D*>();
+    m_sagittasID=new std::vector <TProfile2D*>();
+    m_sagittasME=new std::vector <TProfile2D*>();
+    m_sagittaPhaseSpaceCB=nullptr;
+    m_sagittaPhaseSpaceID=nullptr;
+    m_sagittaPhaseSpaceME=nullptr;
+  }
+
+  MuonCalibrationAndSmearingTool::MuonCalibrationAndSmearingTool( const MuonCalibrationAndSmearingTool& tool ) :
+    asg::AsgTool( tool.name() + "Copy" ),
+
+    m_useExternalSeed( tool.m_useExternalSeed ),
+    m_externalSeed( tool.m_externalSeed ),
+
+    m_Tsmear( tool.m_Tsmear ),
+    m_Tdata( tool.m_Tdata ),
+    m_Trel( tool.m_Trel ),
+    m_Talgo( tool.m_Talgo ),
+    m_useNsigmaForICombine( tool.m_useNsigmaForICombine ),
+
+    m_scale_ID( tool.m_scale_ID ),
+    m_enLoss_MS( tool.m_enLoss_MS ),
+    m_scale_MS( tool.m_scale_MS ),
+    m_scale_CB( tool.m_scale_CB ),
+
+    m_scaleSyst_ID( tool.m_scaleSyst_ID ),
+    m_enLossSyst_MS( tool.m_enLossSyst_MS ),
+    m_scaleSyst_MS( tool.m_scaleSyst_MS ),
+    m_scaleSyst_CB( tool.m_scaleSyst_CB ),
+
+    m_scaleSystUp_ID( tool.m_scaleSystUp_ID ),
+    m_enLossSystUp_MS( tool.m_enLossSystUp_MS ),
+    m_scaleSystUp_MS( tool.m_scaleSystUp_MS ),
+
+    m_scaleSystDw_ID( tool.m_scaleSystDw_ID ),
+    m_enLossSystDw_MS( tool.m_enLossSystDw_MS ),
+    m_scaleSystDw_MS( tool.m_scaleSystDw_MS ),
+
+    m_p1_ID( tool.m_p1_ID ),
+    m_p2_ID( tool.m_p2_ID ),
+    m_p2_ID_TAN( tool.m_p2_ID_TAN ),
+    m_p0_MS( tool.m_p0_MS ),
+    m_p1_MS( tool.m_p1_MS ),
+    m_p2_MS( tool.m_p2_MS ),
+
+    m_E_p1_ID( tool.m_E_p1_ID ),
+    m_E_p2_ID( tool.m_E_p2_ID ),
+    m_E_p2_ID_TAN( tool.m_E_p2_ID_TAN ),
+    m_E_p0_MS( tool.m_E_p0_MS ),
+    m_E_p1_MS( tool.m_E_p1_MS ),
+    m_E_p2_MS( tool.m_E_p2_MS ),
+    m_S_p1_ID( tool.m_S_p1_ID ),
+    m_S_p2_ID( tool.m_S_p2_ID ),
+    m_S_p2_ID_TAN( tool.m_S_p2_ID_TAN ),
+    m_S_p0_MS( tool.m_S_p0_MS ),
+    m_S_p1_MS( tool.m_S_p1_MS ),
+    m_S_p2_MS( tool.m_S_p2_MS ),
+
+    m_SUp_p1_ID( tool.m_SUp_p1_ID ),
+    m_SUp_p2_ID( tool.m_SUp_p2_ID ),
+    m_SUp_p2_ID_TAN( tool.m_SUp_p2_ID_TAN ),
+    m_SUp_p0_MS( tool.m_SUp_p0_MS ),
+    m_SUp_p1_MS( tool.m_SUp_p1_MS ),
+    m_SUp_p2_MS( tool.m_SUp_p2_MS ),
+    m_SDw_p1_ID( tool.m_SDw_p1_ID ),
+    m_SDw_p2_ID( tool.m_SDw_p2_ID ),
+    m_SDw_p2_ID_TAN( tool.m_SDw_p2_ID_TAN ),
+    m_SDw_p0_MS( tool.m_SDw_p0_MS ),
+    m_SDw_p1_MS( tool.m_SDw_p1_MS ),
+    m_SDw_p2_MS( tool.m_SDw_p2_MS ),
+
+    m_MC_p1_ID( tool.m_MC_p1_ID ),
+    m_MC_p2_ID( tool.m_MC_p2_ID ),
+    m_MC_p2_ID_TAN( tool.m_MC_p2_ID_TAN ),
+    m_MC_p0_MS( tool.m_MC_p0_MS ),
+    m_MC_p1_MS( tool.m_MC_p1_MS ),
+    m_MC_p2_MS( tool.m_MC_p2_MS ),
+
+    m_names( tool.m_names ),
+    m_loadNames( tool.m_loadNames ),
+    m_nb_regions( tool.m_nb_regions ),
+    m_eta_min( tool.m_eta_min ),
+    m_eta_max( tool.m_eta_max ),
+    m_phi_min( tool.m_phi_min ),
+    m_phi_max( tool.m_phi_max ),
+
+    m_doMacroRegions( tool.m_doMacroRegions ),
+    m_MacroRegionIdxMap( tool.m_MacroRegionIdxMap ),
+    m_MacroRegionName( tool.m_MacroRegionName ),
+    m_MacroRegionInnerEta( tool.m_MacroRegionInnerEta ),
+    m_Parameters( tool.m_Parameters ),
+    m_currentParameters( nullptr),
+    m_StatCombPtThreshold(tool.m_StatCombPtThreshold),
+    m_useStatComb(tool.m_useStatComb),
+    m_SagittaCorrPhaseSpace(tool.m_SagittaCorrPhaseSpace),
+    m_doSagittaCorrection(tool.m_doSagittaCorrection),
+    m_doNotUseAMGMATRIXDECOR(tool.m_doNotUseAMGMATRIXDECOR),
+    m_SagittaIterations(tool.m_SagittaIterations),
+    m_GlobalZScales(tool.m_GlobalZScales){
+    declareProperty( "Year", m_year = "Data16" );
+    declareProperty( "Algo", m_algo = "muons" );
+    declareProperty( "SmearingType", m_type = "q_pT" );
+    declareProperty( "Release", m_release = "Recs2019_05_30" );
+    declareProperty( "ToroidOff", m_toroidOff = false );
+    declareProperty( "FilesPath", m_FilesPath = "" );
 
+  }
 
-  MuonCalibrationAndSmearingTool::~MuonCalibrationAndSmearingTool(){
-    if(m_sagittasCB!=NULL){
-      for( auto t : *m_sagittasCB) delete t;
-      delete m_sagittasCB;
-    }
-    
-    if(m_sagittasID!=NULL){
-      for( auto t : *m_sagittasID) delete t;
-      delete m_sagittasID;
-    }
-    
-    if(m_sagittasME!=NULL){
-      for( auto t : *m_sagittasME) delete t;
-      delete m_sagittasME;
-    }
-    
 
+  MuonCalibrationAndSmearingTool::~MuonCalibrationAndSmearingTool(){
+    if(m_sagittasCB!=nullptr) delete m_sagittasCB;
+    if(m_sagittasID!=nullptr) delete m_sagittasID;
+    if(m_sagittasME!=nullptr) delete m_sagittasME;
+    if(m_sagittaPhaseSpaceCB!=nullptr) delete m_sagittaPhaseSpaceCB;
+    if(m_sagittaPhaseSpaceID!=nullptr) delete m_sagittaPhaseSpaceID;
+    if(m_sagittaPhaseSpaceME!=nullptr) delete m_sagittaPhaseSpaceME;
   }
 
 
-StatusCode MuonCalibrationAndSmearingTool::initialize() {
-
-  //::: Greet the user:
-  ATH_MSG_INFO( "Initialising..." );
+  StatusCode MuonCalibrationAndSmearingTool::initialize(){
 
-  if( SetData( m_year ) == StatusCode::FAILURE ) return StatusCode::FAILURE;
-  if( SetAlgorithm( m_algo ) == StatusCode::FAILURE ) return StatusCode::FAILURE;
-  if( SetRelease( m_release ) == StatusCode::FAILURE ) return StatusCode::FAILURE;
-  if( SetType( m_type ) == StatusCode::FAILURE ) return StatusCode::FAILURE;
+    // Greet the user:
+    ATH_MSG_INFO( "Initialising..." );
 
-  ATH_MSG_DEBUG( "Checking Initialization - Year: " << m_year );
-  ATH_MSG_DEBUG( "Checking Initialization - Algo: " << m_algo );
-  ATH_MSG_DEBUG( "Checking Initialization - Type: " << m_type );
-  ATH_MSG_DEBUG( "Checking Initialization - Release: " << m_release );
-  
-  std::string regionsPath;
-  int regionMode = 0; // simple Eta Bins
-  //::: Check if FilesPath defined: if so override other configurations (advanced user setting, for debugging within MCP)
-  if ( m_FilesPath == "" ) {
-    if ( m_Trel <= MCAST::Release::Rel17 ) {
-      regionsPath = PathResolverFindCalibFile( "MuonMomentumCorrections/Regions.dat" );
+    if( SetData( m_year ) == StatusCode::FAILURE ) { 
+         ATH_MSG_ERROR( "Error in initialization of year: " << m_year );
+        return StatusCode::FAILURE;
     }
-    else if ( m_Trel == MCAST::Release::Rel17_2_Repro ) {
-      regionsPath = PathResolverFindCalibFile( "MuonMomentumCorrections/RegionsRepro.dat" );
+    if( SetAlgorithm( m_algo ) == StatusCode::FAILURE ) {
+        ATH_MSG_ERROR( "Error in initialization of algo: " << m_algo );
+        return StatusCode::FAILURE;
     }
-    else if ( m_Trel == MCAST::Release::Rel17_2_Sum13 ) {
-      regionsPath = PathResolverFindCalibFile( "MuonMomentumCorrections/RegionsPhi18.dat" );
-      regionMode = 2;//MS: 48Bins L/S split plus 11_15 and Feet in the BARREL. ID has values from 16 eta bins
-      m_useNsigmaForICombine = 0;
+    if( SetRelease( m_release ) == StatusCode::FAILURE ) {
+        ATH_MSG_ERROR( "Error in initialization of release: " << m_release );
+        return StatusCode::FAILURE;
     }
-    else if ( m_Trel >= MCAST::Release::PreRec ) {
-      regionsPath = PathResolverFindCalibFile( "MuonMomentumCorrections/RegionsPhi18.dat" );
-      regionMode = 1; 
-      m_useNsigmaForICombine = 0;
+    if( SetType( m_type ) == StatusCode::FAILURE ) {
+        ATH_MSG_ERROR( "Error in initialization of type: " << m_type );
+        return StatusCode::FAILURE;
     }
 
-    //    else if ( m_Trel >= MCAST::Release::Recs2016_08_07 ) {
-    //regionsPath = PathResolverFindCalibFile( "MuonMomentumCorrections/RegionsPhi18.dat" );
-    //regionMode = 1;
-    //m_useNsigmaForICombine = 0;
-    //}
+    ATH_MSG_DEBUG( "Checking Initialization - Year: " << m_year );
+    ATH_MSG_DEBUG( "Checking Initialization - Algo: " << m_algo );
+    ATH_MSG_DEBUG( "Checking Initialization - Type: " << m_type );
+    ATH_MSG_DEBUG( "Checking Initialization - Release: " << m_release );
 
+    std::string regionsPath;
+    int regionMode = 0; // simple Eta Bins
+    // Check if FilesPath defined: if so override other configurations (advanced user setting, for debugging within MCP)
+    if ( m_FilesPath == "" ) {
+      if ( m_Trel <= MCAST::Release::Rel17 ) {
+        regionsPath = PathResolverFindCalibFile( "MuonMomentumCorrections/Regions.dat" );
+      }
+      else if ( m_Trel == MCAST::Release::Rel17_2_Repro ) {
+        regionsPath = PathResolverFindCalibFile( "MuonMomentumCorrections/RegionsRepro.dat" );
+      }
+      else if ( m_Trel == MCAST::Release::Rel17_2_Sum13 ) {
+        regionsPath = PathResolverFindCalibFile( "MuonMomentumCorrections/RegionsPhi18.dat" );
+        regionMode = 2;//MS: 48Bins L/S split plus 11_15 and Feet in the BARREL. ID has values from 16 eta bins
+        m_useNsigmaForICombine = 0;
+      }
+      else if ( m_Trel >= MCAST::Release::PreRec ) {
+        regionsPath = PathResolverFindCalibFile( "MuonMomentumCorrections/RegionsPhi18.dat" );
+        regionMode = 1;
+        m_useNsigmaForICombine = 0;
+      }
+      else {
+        ATH_MSG_ERROR( "Unknown release" );
+        return StatusCode::FAILURE;
+      }
+    }
     else {
-      ATH_MSG_ERROR( "Unknown release" );
+      regionsPath = m_FilesPath + "RegionsPhi18.dat";
+      regionMode = 1;
+      m_useNsigmaForICombine = 0;
+    }
+    ATH_MSG_DEBUG( "Checking Initialization - Regions file: " << regionsPath );
+
+    if( Regions( regionsPath, regionMode ) == StatusCode::FAILURE ) {
+        ATH_MSG_ERROR( "Unkown regions or regionMode");
+        return StatusCode::FAILURE;
+    }
+
+    if( FillValues() == StatusCode::FAILURE ) {
+        ATH_MSG_ERROR( "Unkown region values");
+        return StatusCode::FAILURE;
+    }
+    if( !applySystematicVariation( SystematicSet() ) ) {
+      ATH_MSG_ERROR( "Unable to run with no systematic" );
       return StatusCode::FAILURE;
     }
-  }
-  else {
-    regionsPath = m_FilesPath + "RegionsPhi18.dat";
-    regionMode = 1; 
-    m_useNsigmaForICombine = 0;
-  }
-  ATH_MSG_DEBUG( "Checking Initialization - Regions file: " << regionsPath );
+    SystematicRegistry& registry = SystematicRegistry::getInstance();
+    if( registry.registerSystematics( *this ) != SystematicCode::Ok ) { 
+        ATH_MSG_ERROR( "Unkown systematic list");
+        return StatusCode::FAILURE;
+    }
 
-  if( Regions( regionsPath, regionMode ) == StatusCode::FAILURE ) return StatusCode::FAILURE;
-  
-  if( FillValues() == StatusCode::FAILURE ) return StatusCode::FAILURE;
 
-  if( !applySystematicVariation( SystematicSet() ) ) {
-    ATH_MSG_ERROR( "Unable to run with no systematic" );
-    return StatusCode::FAILURE;
-  }
-  SystematicRegistry& registry = SystematicRegistry::getInstance();
-  if( registry.registerSystematics( *this ) != SystematicCode::Ok ) return StatusCode::FAILURE;
-
-  if(m_Tdata == MCAST::DataType::Data16){
-    m_StatCombPtThreshold=200.00; 
-    m_GlobalZScales.clear();
-    m_GlobalZScales.push_back(90.2893);  m_GlobalZScales.push_back(90.4996);    m_GlobalZScales.push_back(90.1407); 
-    m_doSagittaCorrection=true;
-    m_SagittaIterations.clear();
-    m_SagittaIterations.push_back(10); m_SagittaIterations.push_back(10); m_SagittaIterations.push_back(10);
-    std::vector<std::string> trackNames; trackNames.push_back("CB"); trackNames.push_back("ID");  trackNames.push_back("ME"); 
-    
-    for( unsigned int i=0; i<m_SagittaIterations.size(); i++){
-      ATH_MSG_VERBOSE("Case "<<i<<" track Name "<<trackNames.at(i)<<" and iterations "<<m_SagittaIterations.at(i));
-      for( unsigned int j=0; j< m_SagittaIterations.at(i) ;  j++){
-        ATH_MSG_VERBOSE("Track "<<i<<" file "<< PathResolverFindCalibFile(Form("MuonMomentumCorrections/sagittaBiasDataAll/outqDeltamPlots_iter%d/",j) + trackNames.at(i) + "_data.root"));
-        std::unique_ptr<TProfile2D> hist(GetHist( PathResolverFindCalibFile(Form("MuonMomentumCorrections/sagittaBiasDataAll/outqDeltamPlots_iter%d/",j) + trackNames.at(i) + "_data.root"),"inclusive",m_GlobalZScales.at(i)));
+    if(m_Tdata == MCAST::DataType::Data15 ||  m_Tdata == MCAST::DataType::Data16 || m_Tdata == MCAST::DataType::Data17 ||  m_Tdata == MCAST::DataType::Data18){
+      m_StatCombPtThreshold=300.0;// Setting stat combination threshold for full Run 2 data, in case it's used
+    }
+
+    if(m_useStatComb){
+      ATH_MSG_INFO("Using statistical combination abovbe "<<m_StatCombPtThreshold<<" GeV");
+    }
+
+    if(m_doSagittaCorrection){
+      ATH_MSG_INFO("Will be correcting the sagitta for data ");
+    }
+
+    if(m_Tdata >= MCAST::DataType::Data15    && ( m_doSagittaCorrection || m_doSagittaMCDistortion) ){
+      m_GlobalZScales.clear();
+      m_GlobalZScales.push_back(90.2893);  m_GlobalZScales.push_back(90.4996);    m_GlobalZScales.push_back(90.1407);
+
+      m_SagittaIterations.clear();
+
+      // First batch of corrections
+      if(m_SagittaRelease.compare("sagittaBiasDataAll")==0){
+        m_SagittaIterations.push_back(10); m_SagittaIterations.push_back(10); m_SagittaIterations.push_back(10);
+      }
+      // Second batch of corrections reduced uncertainty
+      else if (m_SagittaRelease.compare("sagittaBiasDataAll_06_02_17")==0){
+        m_SagittaIterations.push_back(11); m_SagittaIterations.push_back(11); m_SagittaIterations.push_back(11);
+      }
+
+      // R21 batch of corrections reduced uncertainty
+      else if (m_SagittaRelease.compare("sagittaBiasDataAll_02_08_17")==0){
+        m_SagittaIterations.push_back(11); m_SagittaIterations.push_back(11); m_SagittaIterations.push_back(11);
+      }
+
+      // R21 first batch of corrections reduced uncertainty
+      else if (m_SagittaRelease.compare("sagittaBiasDataAll_25_07_17")==0){
+        m_SagittaIterations.push_back(11); m_SagittaIterations.push_back(11); m_SagittaIterations.push_back(11);
+      }
+
+      // R21 first batch of corrections reduced uncertainty for data 17 with phases-pace correction 
+      else if (m_SagittaRelease.compare("sagittaBiasDataAll_30_07_18")==0){
+        m_SagittaIterations.push_back(11); m_SagittaIterations.push_back(11); m_SagittaIterations.push_back(11);
+      }
+      // R21 first batch of corrections reduced uncertainty for data 17 with phases-pace correction integrated in phi
+      else if (m_SagittaRelease.compare("sagittaBiasDataAll_IntegratedPhi_30_07_18")==0){
+        m_SagittaIterations.push_back(11); m_SagittaIterations.push_back(11); m_SagittaIterations.push_back(11);
+      }
+      // R21 corrections: full run 2 with uniform treatment of 2015+2016, 2017, 2018 data. 
+      // it includes MC phase-space correction, 30x30 bins for good stat, iterations set 4, for minimal RMS
+      else if (m_SagittaRelease.find("sagittaBiasDataAll_03_02_19") != std::string::npos){
+        m_SagittaIterations.push_back(4); m_SagittaIterations.push_back(4); m_SagittaIterations.push_back(4);
+      }
+
+      else {
+        ATH_MSG_WARNING("Unknown SagittaBiasRelease: Number of sagitta iterations set to 0");
+        m_SagittaIterations.push_back(0); m_SagittaIterations.push_back(0); m_SagittaIterations.push_back(0);
+      }
+
+      if(m_sgIetrsManual){
+        ATH_MSG_INFO("Number of sagitta iterations set to manual CB "<<m_sgItersCB<<" ID "<<m_sgItersID<<" "<<m_sgItersME);
+        m_SagittaIterations.clear();
+        m_SagittaIterations.push_back(m_sgItersCB);
+        m_SagittaIterations.push_back(m_sgItersID);
+        m_SagittaIterations.push_back(m_sgItersME);
+      }
+
 
-        setSagittaHistogramsSingle(hist.get() , i);
+      std::vector<std::string> trackNames; trackNames.push_back("CB"); trackNames.push_back("ID");  trackNames.push_back("ME");
+
+
+      for( unsigned int i=0; i<m_SagittaIterations.size(); i++){
+        ATH_MSG_VERBOSE("Case "<<i<<" track Name "<<trackNames.at(i)<<" and iterations "<<m_SagittaIterations.at(i));
+        for( unsigned int j=0; j< m_SagittaIterations.at(i) ;  j++){
+          ATH_MSG_VERBOSE("Track "<<i<<" file "<< PathResolverFindCalibFile(Form("MuonMomentumCorrections/%s/outqDeltamPlots_iter%d/",m_SagittaRelease.c_str(),j) + trackNames.at(i) + "_data.root"));
+          std::unique_ptr<TProfile2D> hist(GetHist( PathResolverFindCalibFile(Form("MuonMomentumCorrections/%s/outqDeltamPlots_iter%d/",m_SagittaRelease.c_str(),j) + trackNames.at(i) + "_data.root"),"inclusive",m_GlobalZScales.at(i)));
+          MuonCalibrationAndSmearingTool::setSagittaHistogramsSingle(hist.get(), i);
+        }
+      }
+
+      if(m_SagittaCorrPhaseSpace){
+        // Load the mc sagitta bias maps 
+        m_sagittaPhaseSpaceCB=GetHist( PathResolverFindCalibFile(Form("MuonMomentumCorrections/%s/outqDeltamPlots_iter%d/",m_SagittaRelease.c_str(),0) + trackNames.at(0) + "_mc_NoCorr.root"),"inclusive",m_GlobalZScales.at(0));
+        m_sagittaPhaseSpaceID=GetHist( PathResolverFindCalibFile(Form("MuonMomentumCorrections/%s/outqDeltamPlots_iter%d/",m_SagittaRelease.c_str(),0) + trackNames.at(1) + "_mc_NoCorr.root"),"inclusive",m_GlobalZScales.at(1));
+        m_sagittaPhaseSpaceME=GetHist( PathResolverFindCalibFile(Form("MuonMomentumCorrections/%s/outqDeltamPlots_iter%d/",m_SagittaRelease.c_str(),0) + trackNames.at(2) + "_mc_NoCorr.root"),"inclusive",m_GlobalZScales.at(2));
+      }
+      else{
+        m_sagittaPhaseSpaceCB=nullptr;
+        m_sagittaPhaseSpaceID=nullptr;
+        m_sagittaPhaseSpaceME=nullptr;
       }
+
+      // Set configuration in case only systematic uncertainty is used. 
+      if(m_doSagittaCorrection==false && m_doSagittaMCDistortion==true){
+        ATH_MSG_INFO("Not correcting data, only using systematic uncertainty");
+        m_useFixedRho=true;
+        m_fixedRho=0.0;
+        ATH_MSG_INFO("Using only statistical combination of sagitta bias ID and sagitta bias MS with rho "<<m_fixedRho);
+      } 
     }
+    ATH_CHECK(m_eventInfo.initialize());
+    // Return gracefully:
+    return StatusCode::SUCCESS;
   }
 
-  ATH_CHECK(m_eventInfo.initialize());
-  //::: Return gracefully:
-  return StatusCode::SUCCESS;
-}
-  
-  
-  
-  void MuonCalibrationAndSmearingTool::ConvertToSagittaBias(TH2F *h,float mean) const {
-    if(h==NULL)return ; 
+
+
+  void MuonCalibrationAndSmearingTool::ConvertToSagittaBias(TH2F *h,float mean){
+    if(h==nullptr)return ;
     ATH_MSG_VERBOSE("Will normalise w.r.t the scale of "<<mean);
     h->Scale(4/mean*1e3);
     h->GetZaxis()->SetTitle("#delta#it{s} [TeV^{-1}]");
     h->GetZaxis()->SetRangeUser(-1,+1);
   }
-  
-  TProfile2D* MuonCalibrationAndSmearingTool::GetHist(const std::string &fname, const std::string &hname, double GlobalScale) const {
-    if( fname.size() == 0 || hname.size()==0 ) return NULL;
-    
+
+  TProfile2D* MuonCalibrationAndSmearingTool::GetHist(const std::string &fname, const std::string &hname, double GlobalScale){
+    if( fname.size() == 0 || hname.size()==0 ) return nullptr;
+
     ATH_MSG_INFO("Opening correction file : " <<fname);
     TFile *fmc=TFile::Open(fname.c_str());
 
-    if(fmc==NULL) { 
+    if(fmc==nullptr) {
       ATH_MSG_ERROR("File not found");
-      return NULL;
+      return nullptr;
     }
 
-    TH3 *h3= static_cast<TH3*>(fmc->Get(hname.c_str()));
-    
-    if( h3==NULL ){ 
+    TH3 *h3=static_cast<TH3*>(fmc->Get(hname.c_str()));
+
+    if( h3==nullptr ){
       ATH_MSG_ERROR("NULL sagitta map");
-      return NULL; 
+      return nullptr;
     }
 
     h3->SetDirectory(0);
-    TProfile2D *hinclusive= h3->Project3DProfile("yx");
+    TProfile2D *hinclusive=h3->Project3DProfile("yx");
     hinclusive->SetDirectory(0);
     hinclusive->GetXaxis()->SetTitle(h3->GetXaxis()->GetTitle());
     hinclusive->GetYaxis()->SetTitle(h3->GetYaxis()->GetTitle());
     hinclusive->GetZaxis()->SetTitle(h3->GetZaxis()->GetTitle());
-    
+
     ConvertToSagittaBias((TH2F*)hinclusive,GlobalScale);
-    
+
     delete h3;
     fmc->Close();
     delete fmc;
     return hinclusive;
-}
+  }
 
 
-  // This may cause a leak 
+  // This may cause a leak
   unsigned int MuonCalibrationAndSmearingTool::setSagittaHistogramsSingle(TProfile2D *pCB,unsigned int track){
     if( track == 0 ) {
-      m_sagittasCB->push_back((TProfile2D*)pCB->Clone(Form("pCB_%d",(int)m_sagittasCB->size())));
-      return m_sagittasCB->size(); 
-  }
+      pCB->SetName((Form("pCB_%d",(int)m_sagittasCB->size())));
+      m_sagittasCB->push_back(pCB);
+      return m_sagittasCB->size();
+    }
     else if( track == 1 ) {
-      m_sagittasID->push_back((TProfile2D*)pCB->Clone(Form("pID_%d",(int)m_sagittasID->size())));
-      return m_sagittasID->size(); 
-  }
+      pCB->SetName(Form("pID_%d",(int)m_sagittasID->size()));
+      m_sagittasID->push_back(pCB);
+      return m_sagittasID->size();
+    }
     else if( track == 2 ) {
-      m_sagittasME->push_back((TProfile2D*)pCB->Clone(Form("pME_%d",(int)m_sagittasME->size())));
+      pCB->SetName(Form("pME_%d",(int)m_sagittasME->size()));
+      m_sagittasME->push_back(pCB);
       return  m_sagittasME->size();
     }
-    else 
+    else
       return 0;
   }
-  
+
   double  MuonCalibrationAndSmearingTool::sagitta(TProfile2D* corrM, TLorentzVector &lv) const {
-    if( corrM == NULL) return 0; ; 
+    if( corrM == nullptr) return 0; ;
     int binEta=corrM->GetXaxis()->FindBin(lv.Eta());
     int binPhi=corrM->GetYaxis()->FindBin(lv.Phi());
     if(std::abs(lv.Eta()) >2.5) {
       ATH_MSG_DEBUG("Muon eta > 2.5 sagitta bias = 0");
-      return 0.0; 
+      return 0.0;
     }
     double p2=corrM->GetBinContent(binEta,binPhi);
 
-    if(m_currentParameters->SagittaBias == MCAST::SystVariation::Up)
-      p2=0.5*p2;
-    else if (m_currentParameters->SagittaBias == MCAST::SystVariation::Down)
-      p2=-0.5*p2; 
-
-    return p2; 
+    if(m_currentParameters->SagittaBias != MCAST::SystVariation::Default){
+      if(m_currentParameters->SagittaBias == MCAST::SystVariation::Up){
+        p2=0.5*p2;
+      }
+      else if (m_currentParameters->SagittaBias == MCAST::SystVariation::Down){
+        p2=-0.5*p2;
+      }
+    }
+    return p2;
   }
-  
-  CorrectionCode MuonCalibrationAndSmearingTool::CorrectForCharge(double p2,double& pt,int q, bool isMC) const{
-    
-    if(  q==0 ) { 
+
+  CorrectionCode MuonCalibrationAndSmearingTool::CorrectForCharge(double p2, double& pt, int q, bool isMC,double p2Kin) const {
+
+    if( q==0 ) {
       ATH_MSG_DEBUG("Muon charge is 0");
       return CorrectionCode::OutOfValidityRange;
     }
     double corrPt=pt;
-    if(isMC) 
-      corrPt=corrPt/(1 -q*p2*1e-3*corrPt); 
-    else 
-      corrPt= corrPt/(1+q*p2*1e-3*corrPt);
+    if(isMC)
+      corrPt = corrPt/(1 - q*p2*1e-3*corrPt);
+    else{
+      p2=p2-p2Kin;
+      corrPt = corrPt/(1 + q*p2*1e-3*corrPt);
+    }
     pt=corrPt;
     return CorrectionCode::Ok;
   }
-  
-  CorrectionCode
-  MuonCalibrationAndSmearingTool::applyiSagittaBiasCorrection(Vars& vars,
-                                                              const unsigned int SgCorrType, const xAOD::Muon& mu,unsigned int iter,bool stop,bool isMC) const
-  {
+
+  CorrectionCode MuonCalibrationAndSmearingTool::applySagittaBiasCorrection(const unsigned int SgCorrType, xAOD::Muon& mu, unsigned int iter, bool stop, bool isMC, InfoHelper& muonInfo) const {
+
+    if(m_doSagittaMCDistortion && isMC && iter == 0) stop=true;
+
     if(iter == 0){
       ATH_MSG_DEBUG("Sagitta correction method "<< SgCorrType <<" iter "<<iter);
       if( ( mu.primaryTrackParticleLink() ).isValid() ) {
         const ElementLink< xAOD::TrackParticleContainer >& cb_track = mu.primaryTrackParticleLink();
-        vars.m_ptcb = ( !cb_track ) ? 0. : ( *cb_track )->pt() / 1000.;
+        muonInfo.ptcb = ( !cb_track ) ? 0. : ( *cb_track )->pt() / 1000.;
       }
-      else vars.m_ptcb = 0.;
-      
+      else muonInfo.ptcb = 0.;
+      if( m_useStatComb && muonInfo.ptcb > m_StatCombPtThreshold && isBadMuon(mu, muonInfo)) {
+        if(m_doNotUseAMGMATRIXDECOR){
+          muonInfo.ptcb = sin(muonInfo.cbParsA[3])/std::fabs(muonInfo.cbParsA[4])/ 1000;
+        }
+        else {
+          if(!mu.isAvailable < AmgVector(5) >( "StatCombCBPars" )) return CorrectionCode::Error;
+          AmgVector(5) parsCB = mu.auxdata < AmgVector(5) >( "StatCombCBPars" );
+          muonInfo.ptcb = sin(parsCB[3])/std::fabs(parsCB[4])/ 1000;
+        }}
+
       if( ( mu.inDetTrackParticleLink() ).isValid() ) {
         const ElementLink< xAOD::TrackParticleContainer >& id_track = mu.inDetTrackParticleLink();
-        vars.m_ptid = ( !id_track ) ? 0. : ( *id_track )->pt() / 1000.;
+        muonInfo.ptid = ( !id_track ) ? 0. : ( *id_track )->pt() / 1000.;
       }
-      else vars.m_ptid = 0.;
-      
+      else muonInfo.ptid = 0.;
+
       if( ( mu.extrapolatedMuonSpectrometerTrackParticleLink() ).isValid() ) {
         const ElementLink< xAOD::TrackParticleContainer >& ms_track = mu.extrapolatedMuonSpectrometerTrackParticleLink();
-        vars.m_ptms = ( !ms_track ) ? 0. : ( *ms_track )->pt() / 1000.;
+        muonInfo.ptms = ( !ms_track ) ? 0. : ( *ms_track )->pt() / 1000.;
       }
-      else  
-        vars.m_ptms = 0.;
+      else
+        muonInfo.ptms = 0.;
     }
 
-    if(vars.m_ptid==0 && vars.m_ptms ==0){
+    if(muonInfo.ptid==0 && muonInfo.ptms ==0){
       ATH_MSG_DEBUG("ME and ID momenta == 0");
       return CorrectionCode::OutOfValidityRange;
     }
+
+    muonInfo.eta = mu.eta();
+    muonInfo.phi = mu.phi();
+
+
+    ATH_MSG_VERBOSE("iter "<<iter<< " Muon info pt "<<muonInfo.ptcb<<" id "<<muonInfo.ptid<<" ms "<<muonInfo.ptms<<" eta "<<muonInfo.eta<<" phi "<<muonInfo.phi<<" charge "<< muonInfo.charge);
+
+
+    TLorentzVector lvCB; lvCB.SetPtEtaPhiM(muonInfo.ptcb,muonInfo.eta,muonInfo.phi,mu.m()/1e3);
+    TLorentzVector lvID; lvID.SetPtEtaPhiM(muonInfo.ptid,muonInfo.eta,muonInfo.phi,mu.m()/1e3);
+    TLorentzVector lvME; lvME.SetPtEtaPhiM(muonInfo.ptms,muonInfo.eta,muonInfo.phi,mu.m()/1e3);
+
+    int q=muonInfo.charge;
+
+    double p2PhaseSpaceCB=0.0;
+    double p2PhaseSpaceID=0.0;
+    double p2PhaseSpaceME=0.0;
     
-    double eta = mu.eta();
-    double phi = mu.phi();
-    
-    
-    ATH_MSG_VERBOSE("iter "<<iter<< " Muon info pt "<<vars.m_ptcb<<" id "<<vars.m_ptid<<" ms "<<vars.m_ptms<<" eta "<<eta<<" phi "<<phi);
-    
+    if(m_SagittaCorrPhaseSpace && m_sagittaPhaseSpaceCB!=nullptr)
+      p2PhaseSpaceCB=m_SagittaCorrPhaseSpace ? sagitta(m_sagittaPhaseSpaceCB,lvCB):0.0;
+    if(m_SagittaCorrPhaseSpace && m_sagittaPhaseSpaceID!=nullptr)
+      p2PhaseSpaceID=m_SagittaCorrPhaseSpace ? sagitta(m_sagittaPhaseSpaceID,lvID):0.0;
+    if(m_SagittaCorrPhaseSpace && m_sagittaPhaseSpaceME!=nullptr)
+      p2PhaseSpaceME=m_SagittaCorrPhaseSpace ? sagitta(m_sagittaPhaseSpaceME,lvME):0.0;
+
 
-    TLorentzVector lvCB; lvCB.SetPtEtaPhiM(vars.m_ptcb,eta,phi,mu.m()/1e3);
-    TLorentzVector lvID; lvID.SetPtEtaPhiM(vars.m_ptid,eta,phi,mu.m()/1e3);
-    TLorentzVector lvME; lvME.SetPtEtaPhiM(vars.m_ptms,eta,phi,mu.m()/1e3);
-        
-    int q=vars.m_charge;
 
     if( q==0 ){
       ATH_MSG_DEBUG("Charge == 0");
       return CorrectionCode::OutOfValidityRange;
-    } 
-    
+    }
+
     if(SgCorrType==MCAST::SagittaCorType::CB) {
-      if(vars.m_ptcb == 0 ) return CorrectionCode::Ok;
+      if(muonInfo.ptcb == 0 ) return CorrectionCode::Ok;
       if( iter >=  m_sagittasCB->size())  return CorrectionCode::Ok;
-      CorrectForCharge( sagitta(m_sagittasCB->at(iter),lvCB)*0.5, vars.m_ptcb, q, isMC);
+      CorrectionCode corr = CorrectForCharge( sagitta(m_sagittasCB->at(iter),lvCB)*0.5, muonInfo.ptcb, q, isMC,p2PhaseSpaceCB);
       iter++;
-      if(!stop)  return applyiSagittaBiasCorrection(vars,MCAST::SagittaCorType::CB,mu,iter,stop,isMC);
+      if(corr != CorrectionCode::Ok) return corr;
+      if(!stop)  return applySagittaBiasCorrection(MCAST::SagittaCorType::CB, mu, iter, stop, isMC, muonInfo);
     }
-    
+
     else if(SgCorrType == MCAST::SagittaCorType::ID){
-      if(vars.m_ptid == 0 ) return CorrectionCode::Ok;
+      if(muonInfo.ptid == 0 ) return CorrectionCode::Ok;
       if( iter >= m_sagittasID->size())  return CorrectionCode::Ok;
-      CorrectForCharge(  sagitta(m_sagittasID->at(iter),lvID)*0.5 , vars.m_ptid, q, isMC);
+      CorrectionCode corr = CorrectForCharge(  sagitta(m_sagittasID->at(iter),lvID)*0.5 , muonInfo.ptid, q, isMC,p2PhaseSpaceID);
       iter++;
-      if(!stop)return applyiSagittaBiasCorrection(vars,MCAST::SagittaCorType::ID,mu,iter,stop,isMC);
+      if(corr != CorrectionCode::Ok) return corr;
+      if(!stop)return applySagittaBiasCorrection(MCAST::SagittaCorType::ID, mu, iter, stop, isMC, muonInfo);
     }
-    
+
     else if(SgCorrType == MCAST::SagittaCorType::ME){
-      if(vars.m_ptms == 0 ) return CorrectionCode::Ok;
+      if(muonInfo.ptms == 0 ) return CorrectionCode::Ok;
       if( iter >=  m_sagittasME->size() )  return CorrectionCode::Ok;
-      CorrectForCharge(sagitta(m_sagittasME->at(iter),lvME) *0.5 , vars.m_ptms, q, isMC);
+      CorrectionCode corr = CorrectForCharge(sagitta(m_sagittasME->at(iter),lvME) *0.5 , muonInfo.ptms, q, isMC,p2PhaseSpaceME);
       iter++;
-      if(!stop) return applyiSagittaBiasCorrection(vars,MCAST::SagittaCorType::ME,mu,iter,stop,isMC);
+      if(corr != CorrectionCode::Ok) return corr;
+      if(!stop) return applySagittaBiasCorrection(MCAST::SagittaCorType::ME, mu, iter, stop, isMC, muonInfo);
     }
-    
+
     else if( SgCorrType == MCAST::SagittaCorType::WEIGHTS){
-    
+      const xAOD::TrackParticle* CB_track  = mu.trackParticle( xAOD::Muon::CombinedTrackParticle );
       const xAOD::TrackParticle* ID_track  = mu.trackParticle( xAOD::Muon::InnerDetectorTrackParticle );
-      const xAOD::TrackParticle* ME_track =  mu.trackParticle( xAOD::Muon::ExtrapolatedMuonSpectrometerTrackParticle );
-   
+      const xAOD::TrackParticle* ME_track  =  mu.trackParticle( xAOD::Muon::ExtrapolatedMuonSpectrometerTrackParticle );
+
       double CBqOverPE = 1e10;
-      if( ID_track != NULL && ME_track != NULL ) 
-        CBqOverPE=pow(sqrt( ID_track->definingParametersCovMatrix()( 4, 4 ) + ME_track->definingParametersCovMatrix()( 4, 4 ))/1e3,2);
-      
+      if( ID_track != nullptr && ME_track != nullptr )
+        CBqOverPE=std::pow(std::sqrt( ID_track->definingParametersCovMatrix()( 4, 4 ) + ME_track->definingParametersCovMatrix()( 4, 4 ))/1e3,2);
+
       double IDqOverPE =  1e10;
-      if(ID_track!=NULL)
-        IDqOverPE=pow( ID_track->definingParametersCovMatrix()( 4, 4 )/1e3,2);
-      
+      if(ID_track!=nullptr)
+        IDqOverPE=std::pow( ID_track->definingParametersCovMatrix()( 4, 4 )/1e3,2);
+
       double MEqOverPE = 1e10;
-      if(ME_track!=NULL)
-        MEqOverPE = pow( ME_track->definingParametersCovMatrix()( 4, 4 )/1e3,2);
-          
+      if(ME_track!=nullptr)
+        MEqOverPE = std::pow( ME_track->definingParametersCovMatrix()( 4, 4 )/1e3,2);
 
-      CalcCBWeights( vars, mu );
-      
-      //double m_f = ((1/vars.m_ptcb  - 1/vars.m_ptms) / ( 1/vars.m_ptid - 1/vars.m_ptms)) ; 
-      //double m_f2 = (( (1/vars.m_ptcb)  - (1/vars.m_ptms)*1/MEqOverPE ) / ( (1/vars.m_ptid)*1/IDqOverPE - (1/vars.m_ptms)*1/MEqOverPE));
-      double ptTilde = (1/IDqOverPE*vars.m_ptid + 1/MEqOverPE*vars.m_ptms)/(1/IDqOverPE+1/MEqOverPE);
-      //double deltaTilde  =(vars.m_ptcb-ptTilde)/vasr.vars.m_ptcb;
-      
-      double pTilde = ((1/IDqOverPE)*(1/vars.m_ptid) + (1/MEqOverPE)*(1/vars.m_ptms))/(1/IDqOverPE+1/MEqOverPE);
-      double deltaPTilde  =(1/vars.m_ptcb-pTilde)/(1/vars.m_ptcb);
-    
-      double deltaID=fabs((1/vars.m_ptid-1/vars.m_ptcb)/(1/vars.m_ptcb));
-      double deltaMS=fabs((1/vars.m_ptms-1/vars.m_ptcb)/(1/vars.m_ptcb));
-      if(deltaID == 0 ) deltaID=1e-6; 
-      if(deltaMS == 0 ) deltaMS=1e-6; 
-    
-      bool dump=false; 
+
+      CalcCBWeights( mu, muonInfo );
+
+
+      double ptTilde = (1/IDqOverPE*muonInfo.ptid + 1/MEqOverPE*muonInfo.ptms)/(1/IDqOverPE+1/MEqOverPE);
+      double pTilde = ((1/IDqOverPE)*(1/muonInfo.ptid) + (1/MEqOverPE)*(1/muonInfo.ptms))/(1/IDqOverPE+1/MEqOverPE);
+      double deltaPTilde  =(1/muonInfo.ptcb-pTilde)/(1/muonInfo.ptcb);
+
+      double deltaID=std::fabs((1/muonInfo.ptid-1/muonInfo.ptcb)/(1/muonInfo.ptcb));
+      double deltaMS=std::fabs((1/muonInfo.ptms-1/muonInfo.ptcb)/(1/muonInfo.ptcb));
+      if(deltaID == 0 ) deltaID=1e-6;
+      if(deltaMS == 0 ) deltaMS=1e-6;
+
+      bool dump=true;
 
       if(iter==0){
-       
-        ATH_MSG_DEBUG("eta "<<eta<<" phi  "<<phi);
-        ATH_MSG_DEBUG(" ptCB: "<<vars.m_ptcb<<" --> "<<ptTilde<<" diff "<< (vars.m_ptcb-ptTilde)*100/vars.m_ptcb<<" %");
-        ATH_MSG_DEBUG(" 1/pT: "<<1/vars.m_ptcb<<" --> "<<pTilde<<" diff "<< deltaPTilde *100 <<" %"<< "1/pttilde "<< 1/ptTilde);
-        ATH_MSG_DEBUG(" deltaID "<<(vars.m_ptid-vars.m_ptcb)*100/vars.m_ptcb<<" % delta MS "<<(vars.m_ptms-vars.m_ptcb)*100/vars.m_ptcb<<" % ");
-        ATH_MSG_DEBUG(" sigma(q/p) CB "<<CBqOverPE*100<<" "<<IDqOverPE*100<<" ME "<<MEqOverPE*100);
-    }
-      
-      //double rho= (1/vars.m_ptid - 1/vars.m_ptms) /  (1/vars.m_ptid + 1/vars.m_ptms) ;
 
-      if( iter ==  m_sagittasCB->size() ) { 
+        ATH_MSG_DEBUG("eta "<<muonInfo.eta<<" phi  "<<muonInfo.phi);
+        ATH_MSG_DEBUG(" ptCB: "<<muonInfo.ptcb<<" --> "<<ptTilde<<" diff "<< (muonInfo.ptcb-ptTilde)*100/muonInfo.ptcb<<" %");
+        ATH_MSG_DEBUG(" 1/pT: "<<1/muonInfo.ptcb<<" --> "<<pTilde<<" diff "<< deltaPTilde *100 <<" %"<< "1/pttilde "<< 1/ptTilde);
+        ATH_MSG_DEBUG(" deltaID "<<(muonInfo.ptid-muonInfo.ptcb)*100/muonInfo.ptcb<<" % delta MS "<<(muonInfo.ptms-muonInfo.ptcb)*100/muonInfo.ptcb<<" % ");
+        ATH_MSG_DEBUG(" sigma(q/p) CB "<<CBqOverPE*100<<" ID "<<IDqOverPE*100<<" ME "<<MEqOverPE*100);
+      }
+
+
+      if( iter ==  m_sagittasCB->size() ) {
         if(dump)
-          ATH_MSG_DEBUG("--> " << vars.m_ptcb);
+          ATH_MSG_DEBUG("--> " << muonInfo.ptcb);
         return CorrectionCode::Ok;
-      }    
-    
-      
-    float sagittaID=iter >= m_sagittasID->size() ? 0 : sagitta(m_sagittasID->at(iter),lvID);
-    float sagittaME=iter >= m_sagittasME->size() ? 0 : sagitta(m_sagittasME->at(iter),lvME);
-    //float sagittaCB=iter >= m_sagittasCB->size() ? 0 : sagitta(m_sagittasCB->at(iter),lvCB);
-    
-    double tmpPtID = lvID.Pt();   //vars.m_ptid;
-    double tmpPtMS = lvME.Pt();   //vars.m_ptms;
-    //double tmpPtCB = lvCB.Pt();   //vars.m_ptcb;
-    
-    double tmpDeltaID=0; 
-    double tmpDeltaMS=0;
-    
-    CorrectionCode idOK=applyiSagittaBiasCorrection(vars,MCAST::SagittaCorType::ID,mu,iter,true,isMC);
-    TLorentzVector lvIDCorr; lvIDCorr.SetPtEtaPhiM(vars.m_ptid,eta,phi,mu.m()/1e3);
+      }
 
-    if(idOK == CorrectionCode::Ok && tmpPtID!=0 ) tmpDeltaID = ( -tmpPtID +lvIDCorr.Pt() )/ tmpPtID  ;
-    else tmpDeltaID=0; 
-    ATH_MSG_VERBOSE( "Shift ID "<<tmpDeltaID );
-    
-    
-    CorrectionCode meOK=applyiSagittaBiasCorrection(vars,MCAST::SagittaCorType::ME,mu,iter,true,isMC);
-    TLorentzVector lvMECorr;  lvMECorr.SetPtEtaPhiM(vars.m_ptms,eta,phi,mu.m()/1e3);
-    if(meOK == CorrectionCode::Ok && tmpPtMS!=0 ) tmpDeltaMS = ( -tmpPtMS + lvMECorr.Pt()/1e3 ) /tmpPtMS  ;
-    else tmpDeltaMS=0;  
-    ATH_MSG_VERBOSE( "Shift MS "<<tmpDeltaMS ); 
-    
-    //float pTCB=lvCB.Pt();
-    //double CBsagitta = vars.m_weightID * sagittaID + vars.m_weightMS *  sagittaME;
-    //double CBsagitta2 = (1/pTCB + m_f*( sagittaID - sagittaME) + sagittaME);
-    
-    double CBsagitta3 = (1/(IDqOverPE*deltaID) * sagittaID  
-                         + 1/(MEqOverPE*deltaMS) * sagittaME)/(1/(IDqOverPE*deltaID)+1/(MEqOverPE*deltaMS));
-    
-    
-    CorrectForCharge(CBsagitta3, vars.m_ptcb,q,isMC);
-    
-    /*
-      if(dump){
-      std::cout<<"-";
-      for( unsigned int i=0; i<iter; i++)
-        std::cout<<"-";
-        std::cout<<"> "<<vars.m_ptcb<<" --> "<<pTCB<<" "<<pTCB/vars.m_ptcb  <<"(CB) "<< (lvIDCorr.Pt())/vars.m_ptid <<" (ID) "<< (lvMECorr.Pt())/vars.m_ptms <<" (ME) w: "<<vars.m_weightID<<" (ID) "<<vars.m_weightMS<<"(MS) Delta CB "<<sagittaCB<<" "
-        <<" SG1 "<< CBsagitta<< " SG2 "<< CBsagitta2<<" SG4 "<<CBsagitta3<< " ID "<< sagittaID<< " ME "<<sagittaME
-        <<" f " <<m_f << " f3 "<<m_f2<<" rho "<<rho<<" q "<< q <<" iter "<< iter <<std::endl;
-        }
-    */
+      double tmpPtID = lvID.Pt();   //muonInfo.ptid;
+      double tmpPtMS = lvME.Pt();   //muonInfo.ptms;
+
+      double tmpDeltaID=0;
+      double tmpDeltaMS=0;
+
+      CorrectionCode idOK=applySagittaBiasCorrection(MCAST::SagittaCorType::ID, mu,0,false, isMC, muonInfo);
+      TLorentzVector lvIDCorr; lvIDCorr.SetPtEtaPhiM(muonInfo.ptid,muonInfo.eta,muonInfo.phi,mu.m()/1e3);
+
+      if(idOK == CorrectionCode::Ok && tmpPtID!=0 ) tmpDeltaID = ( -tmpPtID +lvIDCorr.Pt() )/ tmpPtID  ;
+      else tmpDeltaID=0;
+      ATH_MSG_VERBOSE( "Shift ID "<<tmpDeltaID );
+      // Now modify the ID covariance matrix
+      AmgVector(5) parsID = ID_track->definingParameters();
+      parsID[4]=1.0 / (lvIDCorr.P()*1e3); 
+
+
+      CorrectionCode meOK=applySagittaBiasCorrection(MCAST::SagittaCorType::ME, mu,0, false, isMC, muonInfo);
+      TLorentzVector lvMECorr;  lvMECorr.SetPtEtaPhiM(muonInfo.ptms,muonInfo.eta,muonInfo.phi,mu.m()/1e3);
+      if(meOK == CorrectionCode::Ok && tmpPtMS!=0 ) tmpDeltaMS = ( -tmpPtMS + lvMECorr.Pt()/1e3 ) /tmpPtMS  ;
+      else tmpDeltaMS=0;
+      ATH_MSG_VERBOSE( "Shift MS "<<tmpDeltaMS );
+      // Now modify the ME covariance matrix 
+      AmgVector(5) parsMS = ME_track->definingParameters();
+      parsMS[4]=1.0 / (lvMECorr.P()*1e3);
+
+      double simpleCombPt  = (1/(IDqOverPE*deltaID) * lvIDCorr.Pt() + 
+			      1/(MEqOverPE*deltaMS) * lvMECorr.Pt())/(1/(IDqOverPE*deltaID)+1/(MEqOverPE*deltaMS)); 
+
+      // Calculate the stat combination before sagitta bias: 
+     
+      double chi2Nom=-999;
+      AmgVector(5) parsCBNom=CB_track->definingParameters();
+      AmgSymMatrix(5) covCBNom=CB_track->definingParametersCovMatrix();
+      int charge = mu.charge();
+      const ElementLink< xAOD::TrackParticleContainer >& ms_track = mu.extrapolatedMuonSpectrometerTrackParticleLink();
+      const ElementLink< xAOD::TrackParticleContainer >& id_track=mu.inDetTrackParticleLink();
+      CorrectionCode NominalCorrCode=applyStatCombination(id_track,
+                                                          ms_track,
+                                                          charge,
+                                                          parsCBNom,
+                                                          covCBNom,
+                                                          chi2Nom);
+      if(NominalCorrCode!=CorrectionCode::Ok) return NominalCorrCode;
+          
       
-    
-    iter++;
-    return applyiSagittaBiasCorrection(vars,MCAST::SagittaCorType::WEIGHTS,mu,iter,stop,isMC);
+      // Perform the statistical combination 
+      AmgSymMatrix(5) covID = ID_track->definingParametersCovMatrix();
+      AmgSymMatrix(5) covMS = ME_track->definingParametersCovMatrix();
+      
+      const AmgSymMatrix(5)  weightID = covID.inverse();
+      if  ( weightID.determinant() == 0 ){
+        ATH_MSG_WARNING( " ID weight matrix computation failed     " ) ;
+        return CorrectionCode::Error;
+      }
+      
+      const AmgSymMatrix(5)  weightMS = covMS.inverse();
+      if  ( weightMS.determinant() == 0 ){
+        ATH_MSG_WARNING( "weightMS computation failed      " ) ;
+        return CorrectionCode::Error;
+      }
+      
+      AmgSymMatrix(5) weightCB = weightID + weightMS ;
+      AmgSymMatrix(5) covCB = weightCB.inverse();
+      if (covCB.determinant() == 0){
+        ATH_MSG_WARNING( " Inversion of weightCB failed " ) ;
+        return CorrectionCode::Error;
+      }
+
+      AmgSymMatrix(5) covSum = covID + covMS ;
+      AmgSymMatrix(5) invCovSum = covSum.inverse();
+      if (invCovSum.determinant() == 0){
+        ATH_MSG_WARNING( " Inversion of covSum failed " ) ;
+        return CorrectionCode::Error;
+      }
+      double  diffPhi = parsMS[2] - parsID[2] ;
+      if(diffPhi>M_PI)       parsMS[2] -= 2.*M_PI;
+      else if(diffPhi<-M_PI) parsMS[2] += 2.*M_PI;
+
+      AmgVector(5) parsCB = covCB * ( weightID * parsID + weightMS * parsMS ) ;
+      parsCB[4] *= muonInfo.charge;
+
+      if(parsCB[2]>M_PI)       parsCB[2] -= 2.*M_PI;
+      else if(parsCB[2]<-M_PI) parsCB[2] += 2.*M_PI;
+      double statCombPtNom = std::sin(parsCBNom[3])/std::fabs(parsCBNom[4])/ 1000;
+      double statCombPt    = std::sin(parsCB[3])/std::fabs(parsCB[4])/ 1000;
+      muonInfo.ptcb =  muonInfo.ptcb * (1  +  (statCombPt-statCombPtNom)/statCombPtNom ) ;
+      ATH_MSG_VERBOSE(" Poor man's combination "<<simpleCombPt<<" Stat comb "<<statCombPt<<" Stat comb nom "<<" statCombPtNom "<<statCombPtNom ); 
+
     }
-    
+
     return CorrectionCode::Ok;
+  }
+
+
+  CorrectionCode MuonCalibrationAndSmearingTool::applySagittaBiasCorrectionAuto(const int DetType, xAOD::Muon& mu, bool isMC, const unsigned int SytCase, InfoHelper& muonInfo) const {
+    //isSystematics ==false
+
+    //:: If RHO is fixed and one does not apply a correction, return the nominal muon; 
+    if( (SytCase == MCAST::SagittaSysType::RHO) && !m_doSagittaCorrection && m_doSagittaMCDistortion){
+      ATH_MSG_VERBOSE("Final pt "<<muonInfo.ptcb);
+      return CorrectionCode::Ok;
     }
-    
-    
-    CorrectionCode
-    MuonCalibrationAndSmearingTool::applySagittaBiasCorrectionAuto(Vars& vars,
-                                                                   const int DetType, const xAOD::Muon& mu, bool isMC,const unsigned int SytCase) const//isSystematics ==false
-    {
-      unsigned int itersCB=0;
 
+    unsigned int itersCB=0;
     if(SytCase == MCAST::SagittaSysType::BIAS && m_SagittaIterations.at(0) > 1)
       itersCB= m_SagittaIterations.at(0) - 1;
-    
+
     unsigned int itersID=0;
-    
+
     if(SytCase == MCAST::SagittaSysType::BIAS && m_SagittaIterations.at(1) > 1)
       itersID= m_SagittaIterations.at(1) - 1;
-    
+
     unsigned int itersME=0;
     if(SytCase == MCAST::SagittaSysType::BIAS && m_SagittaIterations.at(2) > 1)
       itersME= m_SagittaIterations.at(2) - 1;
 
-    // FIXME: arguments look wrong in these calls???
-    // Correct the ID momentum;
-    if(DetType == MCAST::DetectorType::ID)
-      return applyiSagittaBiasCorrection(vars,MCAST::SagittaCorType::ID,mu,isMC,itersID);
-    
-    // Correct the ME momentum; 
-    else if(DetType == MCAST::DetectorType::MS)
-      return applyiSagittaBiasCorrection(vars,MCAST::SagittaCorType::ME,mu,isMC,itersME);
-    
-    // Correct the CB momentum; 
-    else if(DetType == MCAST::DetectorType::CB){
-      
-      if( vars.m_ptcb == 0) {
+    // In case one distrots the MC iterations are set to 1. Systamtics willl be calculated based on the full effect.
+    if(m_doSagittaMCDistortion && isMC){
+      itersCB =0; itersID =0;  itersME=0;
+    }
+
+
+    if(DetType == MCAST::DetectorType::ID){  // Correct the ID momentum
+      return applySagittaBiasCorrection(MCAST::SagittaCorType::ID, mu, isMC, itersID, false, muonInfo);
+    }
+
+    else if(DetType == MCAST::DetectorType::MS){  // Correct the ME momentum
+      return applySagittaBiasCorrection(MCAST::SagittaCorType::ME, mu, isMC, itersME, false, muonInfo);
+    }
+    else if(DetType == MCAST::DetectorType::CB){  // Correct the CB momentum;
+      if( muonInfo.ptcb == 0) {
         ATH_MSG_VERBOSE("Combined pt = 0 correcting separtly ID and ME");
-        if(vars.m_ptid !=0)
-          if(applySagittaBiasCorrectionAuto(vars,MCAST::DetectorType::ID,mu,isMC,SytCase)!=CP::CorrectionCode::Ok) 
-            return CP::CorrectionCode::Error;
-        if( vars.m_ptms !=0 )
-          if(applySagittaBiasCorrectionAuto(vars,MCAST::DetectorType::MS,mu,isMC,SytCase)!=CP::CorrectionCode::Ok) 
-            return CP::CorrectionCode::Error;
-        return CP::CorrectionCode::Ok;
+        if(muonInfo.ptid !=0 && muonInfo.ptms !=0){
+          if( applySagittaBiasCorrectionAuto(MCAST::DetectorType::ID, mu, isMC, SytCase, muonInfo) != CorrectionCode::Ok &&
+              applySagittaBiasCorrectionAuto(MCAST::DetectorType::MS, mu, isMC, SytCase, muonInfo) != CorrectionCode::Ok ) return CorrectionCode::Error;
+        }
+        else if(muonInfo.ptid !=0 ){
+          if (applySagittaBiasCorrectionAuto(MCAST::DetectorType::ID, mu, isMC, SytCase, muonInfo) != CorrectionCode::Ok) return CorrectionCode::Error;
+        }
+        else if(muonInfo.ptms !=0 ){
+          if (applySagittaBiasCorrectionAuto(MCAST::DetectorType::MS, mu, isMC, SytCase, muonInfo) != CorrectionCode::Ok) return CorrectionCode::Error;
+        }
+        else {
+          return CP::CorrectionCode::Ok;
+        }
       }
-      
+
       double central= 45.2;
       double width=15.5;
-      
-      bool isSystematic = SytCase == MCAST::SagittaSysType::RHO;
-      
-      if(isSystematic) {
-        double sigmaID = ExpectedResolution( vars, MCAST::DetectorType::ID, mu, true ) * vars.m_ptcb;
-        double sigmaMS = ExpectedResolution( vars, MCAST::DetectorType::MS, mu, true ) * vars.m_ptcb;
-        double denominator = (  vars.m_ptcb  ) * sqrt( sigmaID*sigmaID + sigmaMS*sigmaMS );
-        double res= denominator ? sqrt( 2. ) * sigmaID * sigmaMS / denominator : 0.;
-      
+      double sigmas=1.0;
+      double rho= m_useFixedRho ? m_fixedRho:0.0; 
+
+      bool isSystematic = (SytCase == MCAST::SagittaSysType::RHO) && !m_doSagittaCorrection && m_doSagittaMCDistortion; 
+
+      if(isSystematic ) {
+        double sigmaID = ExpectedResolution( MCAST::DetectorType::ID, mu, true ) * muonInfo.ptcb;
+        double sigmaMS = ExpectedResolution( MCAST::DetectorType::MS, mu, true ) * muonInfo.ptcb;
+        double denominator = (  muonInfo.ptcb  ) * std::sqrt( sigmaID*sigmaID + sigmaMS*sigmaMS );
+        double res= denominator ? std::sqrt( 2. ) * sigmaID * sigmaMS / denominator : 0.;
+
         if(m_currentParameters->SagittaRho==MCAST::SystVariation::Up){
-          central=central + std::fabs(0.5 * res  * central); 
+          central=central + std::fabs(0.5 * res  * central);
         }
         else if(m_currentParameters->SagittaRho==MCAST::SystVariation::Down){
-          central=central - std::fabs(0.5 * res  * central); 
+          central=central - std::fabs(0.5 * res  * central);
         }
       }
       
-      double sigmas=(fabs(vars.m_ptcb - central)/width); 
-      double rho= 1/sigmas;
-      if(sigmas <  1 ) rho=1;
-
-      //::: For standalone muons and Silicon associated fowrad do not use the combined 
-      if( vars.m_ptid ==0 || vars.m_ptms ==0){ 
+      if(!m_useFixedRho){
+        sigmas=(std::fabs(muonInfo.ptcb - central)/width);
+        rho= 1/sigmas;
+        if(sigmas <  1 ) rho=1;
+      }
+      
+      // For standalone muons and Silicon associated fowrad do not use the combined
+      if( muonInfo.ptid ==0 || muonInfo.ptms ==0){
         ATH_MSG_VERBOSE("Applying sagitta correction for Standalone");
-        
         rho=0;
-        if(vars.m_ptid == 0  && vars.m_ptms != 0 )  {
-          if(applyiSagittaBiasCorrection(vars, MCAST::SagittaCorType::ME,mu,isMC,itersME)!=CorrectionCode::Ok){
+        if(muonInfo.ptid == 0  && muonInfo.ptms != 0 )  {
+          if(applySagittaBiasCorrection(MCAST::SagittaCorType::ME, mu, isMC, itersME, false, muonInfo)!=CorrectionCode::Ok){
             return CP::CorrectionCode::Error;
-            vars.m_ptcb=vars.m_ptms;
-          }}
-        
-        else if(vars.m_ptid != 0  && vars.m_ptms == 0 )  {
-          if(applyiSagittaBiasCorrection(vars,MCAST::SagittaCorType::ID,mu,isMC,itersID)!=CorrectionCode::Ok){
+          }
+        }
+        else if(muonInfo.ptid != 0  && muonInfo.ptms == 0 )  {
+          if(applySagittaBiasCorrection(MCAST::SagittaCorType::ID, mu, isMC, itersID, false, muonInfo)!=CorrectionCode::Ok){
             return CP::CorrectionCode::Error;
-            vars.m_ptcb=vars.m_ptid;
-          }}
-
+          }
+        }
         else {
           ATH_MSG_DEBUG("All momenta are 0");
           return    CP::CorrectionCode::OutOfValidityRange;
         }
-        
-        ATH_MSG_VERBOSE("Final pt "<<vars.m_ptcb);
+
+        ATH_MSG_VERBOSE("Final pt "<<muonInfo.ptcb);
         return CP::CorrectionCode::Ok;
       }
-      
-      double ptCB=vars.m_ptcb;
-      double ptWeight=vars.m_ptcb;
-      
+
+      double origPt=muonInfo.ptcb;
+      double ptCB=muonInfo.ptcb;
+      double ptWeight=muonInfo.ptcb;
+
       ATH_MSG_VERBOSE("Applying CB sagitta correction");
-      
-      if(applyiSagittaBiasCorrection(vars,MCAST::SagittaCorType::CB,mu,isMC,itersCB)!=CP::CorrectionCode::Ok){
+
+      if(applySagittaBiasCorrection(MCAST::SagittaCorType::CB, mu, isMC, itersCB, false, muonInfo)!=CP::CorrectionCode::Ok){
         return CP::CorrectionCode::Error;
       }
-      
+
       else {
-        ptCB = vars.m_ptcb;
+        ptCB = muonInfo.ptcb;
+        muonInfo.ptcb=origPt;
       }
 
       ATH_MSG_VERBOSE("Applying Weighted sagitta correction");
 
-      if(applyiSagittaBiasCorrection(vars,MCAST::SagittaCorType::WEIGHTS,mu,isMC,itersCB)!=CP::CorrectionCode::Ok){
+      if(applySagittaBiasCorrection(MCAST::SagittaCorType::WEIGHTS, mu, isMC, itersCB, false, muonInfo)!=CP::CorrectionCode::Ok){
         return CP::CorrectionCode::Error;
-      } 
+      }
       else {
-        ptWeight =  vars.m_ptcb; 
+        ptWeight =  muonInfo.ptcb;
+        muonInfo.ptcb=origPt;
+      }
+
+      if(m_useFixedRho){
+        ATH_MSG_VERBOSE("Using fixed rho value "<<m_fixedRho);
+        rho=m_fixedRho;
       }
       
-      vars.m_ptcb = rho*ptCB + (1-rho)*ptWeight; 
-      ATH_MSG_VERBOSE("Final pt "<<vars.m_ptcb<<" "<<rho<<" * "<<ptCB<<" 1- rho "<<1-rho<<"  *  "<<ptWeight<<" sigmas "<<sigmas);
+      muonInfo.ptcb = rho*ptCB + (1-rho)*ptWeight;
+      
+      ATH_MSG_VERBOSE("Final pt "<<muonInfo.ptcb<<" "<<rho<<" * "<<ptCB<<" 1- rho "<<1-rho<<"  *  "<<ptWeight<<" sigmas "<<sigmas);
       return CorrectionCode::Ok;
     }
-
-    else  
+    else{
       return CorrectionCode::Ok;
+    }
   }
 
 
-CorrectionCode MuonCalibrationAndSmearingTool::applyCorrection( xAOD::Muon& mu ) const {
-  std::unique_ptr<IVars> vars;
-  return applyCorrection (mu, vars);
-}
-
-CorrectionCode MuonCalibrationAndSmearingTool::applyCorrection( xAOD::Muon& mu,
-                                                                std::unique_ptr<IVars>& ivars) const {
-
-  ATH_MSG_VERBOSE( "Muon Type = " << mu.muonType() << " ( 0: Combined, 1: StandAlone, 2: SegmentTagged, 3: CaloTagged )" );
-  ATH_MSG_VERBOSE( "Muon Author = " << mu.author() );
-
-  auto vars_up = std::make_unique<Vars>();
-  Vars& vars = *vars_up;
-  ivars = std::move (vars_up);
-  
-
-  //::: Set pt ID:
-  
-  ATH_MSG_VERBOSE( "Retrieving ElementLink to ID TrackParticle..." );
-  ATH_MSG_VERBOSE( "Setting Pt  [ID]: if no track available, set to 0..." );
-  ATH_MSG_VERBOSE( "mu.isAvailable< ElementLink< xAOD::TrackParticleContainer > >( \"inDetTrackParticleLink\" ) = " << mu.isAvailable< ElementLink< xAOD::TrackParticleContainer > >( "inDetTrackParticleLink" ) );
-  ATH_MSG_VERBOSE( "( mu.inDetTrackParticleLink() == NULL ) = " << ( mu.inDetTrackParticleLink() == NULL ) );
-  ATH_MSG_VERBOSE( "mu.inDetTrackParticleLink() = " << mu.inDetTrackParticleLink() );
-  ATH_MSG_VERBOSE( "( mu.inDetTrackParticleLink() ).isValid() = " << ( mu.inDetTrackParticleLink() ).isValid() );
-  
-  if( ( mu.inDetTrackParticleLink() ).isValid() ) {
-    //if( mu.isAvailable<ElementLink<xAOD::TrackParticleContainer> > ("inDetTrackParticleLink")){
-    const ElementLink< xAOD::TrackParticleContainer >& id_track = mu.inDetTrackParticleLink();
-    vars.m_ptid = ( !id_track ) ? 0. : ( *id_track )->pt() / 1000.;
-  }
-  else vars.m_ptid = 0.;
-
-  //::: Set pt MS:
-  
-  ATH_MSG_VERBOSE( "Retrieving ElementLink to MS TrackParticle..." );
-  ATH_MSG_VERBOSE( "Setting Pt  [MS]: if no track available, set to 0..." );
-  ATH_MSG_VERBOSE( "mu.isAvailable< ElementLink< xAOD::TrackParticleContainer > >( \"extrapolatedMuonSpectrometerTrackParticleLink\" ) = " << mu.isAvailable< ElementLink< xAOD::TrackParticleContainer > >( "extrapolatedMuonSpectrometerTrackParticleLink" ) );
-  ATH_MSG_VERBOSE( "( mu.extrapolatedMuonSpectrometerTrackParticleLink() == NULL ) = " << ( mu.extrapolatedMuonSpectrometerTrackParticleLink() == NULL ) );
-  ATH_MSG_VERBOSE( "mu.extrapolatedMuonSpectrometerTrackParticleLink() = " << mu.extrapolatedMuonSpectrometerTrackParticleLink() );
-  ATH_MSG_VERBOSE( "( mu.extrapolatedMuonSpectrometerTrackParticleLink() ).isValid() = " << ( mu.extrapolatedMuonSpectrometerTrackParticleLink() ).isValid() );
-  if( ( mu.extrapolatedMuonSpectrometerTrackParticleLink() ).isValid() ) {
-    // if( mu.isAvailable< ElementLink< xAOD::TrackParticleContainer > >( "extrapolatedMuonSpectrometerTrackParticleLink" ) ) {
-    const ElementLink< xAOD::TrackParticleContainer >& ms_track = mu.extrapolatedMuonSpectrometerTrackParticleLink();
-    vars.m_ptms = ( !ms_track ) ? 0. : ( *ms_track )->pt() / 1000.;
-  }
- else  
-    //ATH_MSG_VERBOSE("No link to extrapolatedMuonSpectrometerTrackParticleLink setting pt to 0");
-    vars.m_ptms = 0.;
-  
-  //::: Set pt CB:
-  
-  ATH_MSG_VERBOSE( "Retrieving ElementLink to CB TrackParticle..." );
-  ATH_MSG_VERBOSE( "Setting Pt  [CB]: if no track available, set to 0..." );
-  ATH_MSG_VERBOSE( "mu.isAvailable< ElementLink< xAOD::TrackParticleContainer > >( \"primaryTrackParticleLink\" ) = " << mu.isAvailable< ElementLink< xAOD::TrackParticleContainer > >( "primaryTrackParticleLink" ) );
-  ATH_MSG_VERBOSE( "( mu.primaryTrackParticleLink() == NULL ) = " << ( mu.primaryTrackParticleLink() == NULL ) );
-  ATH_MSG_VERBOSE( "mu.primaryTrackParticleLink() = " << mu.primaryTrackParticleLink() );
-  ATH_MSG_VERBOSE( "( mu.primaryTrackParticleLink() ).isValid() = " << ( mu.primaryTrackParticleLink() ).isValid() );
-  
-  if( ( mu.primaryTrackParticleLink() ).isValid() ) {
-    //if( mu.isAvailable< ElementLink < xAOD::TrackParticleContainer > > ( "primaryTrackParticleLink" ) ) {
-    const ElementLink< xAOD::TrackParticleContainer >& cb_track = mu.primaryTrackParticleLink();
-    vars.m_ptcb = ( !cb_track ) ? 0. : ( *cb_track )->pt() / 1000.;
-  }
-  else vars.m_ptcb = 0.;
+  CorrectionCode MuonCalibrationAndSmearingTool::applyCorrection( xAOD::Muon& mu ) const {
 
-  //::: Set the charge 
-  
-  if( mu.muonType() == xAOD::Muon::SiliconAssociatedForwardMuon ) {
-    if( mu.isAvailable<ElementLink<xAOD::TrackParticleContainer > > ("combinedTrackParticleLink")){
-      if(mu.combinedTrackParticleLink().isValid()){
-          const ElementLink< xAOD::TrackParticleContainer >& cb_track = mu.combinedTrackParticleLink();
-          vars.m_charge = ( *cb_track )->charge();
-      }}}
-   
-  else 
-    vars.m_charge = mu.charge();
-  
-  //::: Set remaining muon information:
-  //::: Check if muon has been already corrected! If so, take original pt...
-  //ATH_MSG_VERBOSE( "Setting Pt  [CB]..." );
-  //if( mu.isAvailable< float >( "OriginalMuonPt" ) && mu.auxdata< float >( "OriginalMuonPt" ) > 0 ) {
-  //  vars.m_ptcb = mu.auxdata< float >( "OriginalMuonPt" ) / 1000.;
-  //  ATH_MSG_DEBUG( "Found \"OriginalMuonPt\" decoration, with value: " << vars.m_ptcb * 1000. );
-  //}
-  //else {
-  //  vars.m_ptcb = mu.pt() / 1000.;
-  //  mu.auxdata< float >( "OriginalMuonPt" ) = mu.pt();
-  //  ATH_MSG_DEBUG( "Setting \"OriginalMuonPt\" decoration to value: " << mu.auxdata< float >( "OriginalMuonPt" ) );
-  //}
-  ATH_MSG_VERBOSE( "Setting Eta [CB]..." );
-  vars.m_eta = mu.eta();
-  ATH_MSG_VERBOSE( "Setting Phi [CB]..." );
-  double phi = mu.phi();
-
-
-  //::: Set the statistical combination for muons above given pT threshotld. 
-  if( m_useStatComb && vars.m_ptcb > m_StatCombPtThreshold) {
-    CorrectionCode cbCode=applyStatCombination(mu); 
-    if( cbCode!=CorrectionCode::Ok) return cbCode;
-    if(!mu.isAvailable < AmgVector(5) >( "StatCombCBPars" )) return CorrectionCode::Error;
-    AmgVector(5) parsCB = mu.auxdata < AmgVector(5) >( "StatCombCBPars" );
-    vars.m_ptcb = sin(parsCB[3])/fabs(parsCB[4]);    
-  }
+    ATH_MSG_VERBOSE( "Muon Type = " << mu.muonType() << " ( 0: Combined, 1: StandAlone, 2: SegmentTagged, 3: CaloTagged )" );
+    ATH_MSG_VERBOSE( "Muon Author = " << mu.author() );
 
-  //::: Retrieve the event information:
-  SG::ReadHandle<xAOD::EventInfo> evtInfo(m_eventInfo);
-  ATH_MSG_VERBOSE( "Checking Simulation flag: " << evtInfo->eventType( xAOD::EventInfo::IS_SIMULATION ) );
+    // Make InfoHelper for passing muon info between functions
+    InfoHelper muonInfo;
 
-  if( !evtInfo->eventType( xAOD::EventInfo::IS_SIMULATION ) ) {
+    // Set pt ID:
 
-    //::: Statistical combiantion specifics
-    if(m_useStatComb){
-      mu.setP4( vars.m_ptcb * 1000 , vars.m_eta, phi );
+    ATH_MSG_VERBOSE( "Retrieving ElementLink to ID TrackParticle..." );
+    ATH_MSG_VERBOSE( "Setting Pt  [ID]: if no track available, set to 0..." );
+    ATH_MSG_VERBOSE( "mu.isAvailable< ElementLink< xAOD::TrackParticleContainer > >( \"inDetTrackParticleLink\" ) = " << mu.isAvailable< ElementLink< xAOD::TrackParticleContainer > >( "inDetTrackParticleLink" ) );
+    ATH_MSG_VERBOSE( "( mu.inDetTrackParticleLink() == nullptr ) = " << ( mu.inDetTrackParticleLink() == nullptr ) );
+    ATH_MSG_VERBOSE( "mu.inDetTrackParticleLink() = " << mu.inDetTrackParticleLink() );
+    ATH_MSG_VERBOSE( "( mu.inDetTrackParticleLink() ).isValid() = " << ( mu.inDetTrackParticleLink() ).isValid() );
+
+    if( ( mu.inDetTrackParticleLink() ).isValid() ) {
+            const ElementLink< xAOD::TrackParticleContainer >& id_track = mu.inDetTrackParticleLink();
+      muonInfo.ptid = ( !id_track ) ? 0. : ( *id_track )->pt() / 1000.;
+    } else {
+      ATH_MSG_VERBOSE("The ID track link is not valid - setting pT(ID)=0");
+      muonInfo.ptid = 0.;
     }
-    
-    //::: Sagitta Correction  specifics
-    if(m_doSagittaCorrection){
-      CorrectionCode sgCode=applySagittaBiasCorrectionAuto(vars,MCAST::DetectorType::CB,mu,false,MCAST::SagittaSysType::NOMINAL);
-      if(sgCode!=CorrectionCode::Ok) return sgCode;
-      mu.setP4( vars.m_ptcb * 1000 , vars.m_eta, phi );
+
+    // Set pt MS:
+
+    ATH_MSG_VERBOSE( "Retrieving ElementLink to MS TrackParticle..." );
+    ATH_MSG_VERBOSE( "Setting Pt  [MS]: if no track available, set to 0..." );
+    ATH_MSG_VERBOSE( "mu.isAvailable< ElementLink< xAOD::TrackParticleContainer > >( \"extrapolatedMuonSpectrometerTrackParticleLink\" ) = " << mu.isAvailable< ElementLink< xAOD::TrackParticleContainer > >( "extrapolatedMuonSpectrometerTrackParticleLink" ) );
+    ATH_MSG_VERBOSE( "( mu.extrapolatedMuonSpectrometerTrackParticleLink() == nullptr ) = " << ( mu.extrapolatedMuonSpectrometerTrackParticleLink() == nullptr ) );
+    ATH_MSG_VERBOSE( "mu.extrapolatedMuonSpectrometerTrackParticleLink() = " << mu.extrapolatedMuonSpectrometerTrackParticleLink() );
+    ATH_MSG_VERBOSE( "( mu.extrapolatedMuonSpectrometerTrackParticleLink() ).isValid() = " << ( mu.extrapolatedMuonSpectrometerTrackParticleLink() ).isValid() );
+    if( ( mu.extrapolatedMuonSpectrometerTrackParticleLink() ).isValid() ) {
+          const ElementLink< xAOD::TrackParticleContainer >& ms_track = mu.extrapolatedMuonSpectrometerTrackParticleLink();
+      muonInfo.ptms = ( !ms_track ) ? 0. : ( *ms_track )->pt() / 1000.;
     }
-    
-    mu.auxdata< float >( "InnerDetectorPt" ) = vars.m_ptid * 1000.;
-    //::: Toroid-off specifics
-    if( m_toroidOff ) {
-      mu.auxdata< float >( "MuonSpectrometerPt" ) = 0.;
-      mu.setP4( vars.m_ptid * 1000., vars.m_eta, phi );
+    else{
+      ATH_MSG_VERBOSE("No link to extrapolatedMuonSpectrometerTrackParticleLink setting pT(MS)=0");
+      muonInfo.ptms = 0.;
     }
-    else {
-      mu.auxdata< float >( "MuonSpectrometerPt" ) = vars.m_ptms * 1000.;
+
+    // Set pt CB:
+
+    ATH_MSG_VERBOSE( "Retrieving ElementLink to CB TrackParticle..." );
+    ATH_MSG_VERBOSE( "Setting Pt  [CB]: if no track available, set to 0..." );
+    ATH_MSG_VERBOSE( "mu.isAvailable< ElementLink< xAOD::TrackParticleContainer > >( \"primaryTrackParticleLink\" ) = " << mu.isAvailable< ElementLink< xAOD::TrackParticleContainer > >( "primaryTrackParticleLink" ) );
+    ATH_MSG_VERBOSE( "( mu.primaryTrackParticleLink() == nullptr ) = " << ( mu.primaryTrackParticleLink() == nullptr ) );
+    ATH_MSG_VERBOSE( "mu.primaryTrackParticleLink() = " << mu.primaryTrackParticleLink() );
+    ATH_MSG_VERBOSE( "( mu.primaryTrackParticleLink() ).isValid() = " << ( mu.primaryTrackParticleLink() ).isValid() );
+
+    if( ( mu.primaryTrackParticleLink() ).isValid() ) {
+      const ElementLink< xAOD::TrackParticleContainer >& cb_track = mu.primaryTrackParticleLink();
+      muonInfo.ptcb = ( !cb_track ) ? 0. : ( *cb_track )->pt() / 1000.;
     }
-   
-    //::: SAF specifics
+    else{
+      ATH_MSG_VERBOSE("The ID+MS combined track link is not valid - setting pT(ID)=0");
+      muonInfo.ptcb = 0.;
+    }
+
+    // Set the charge
+
     if( mu.muonType() == xAOD::Muon::SiliconAssociatedForwardMuon ) {
-      ATH_MSG_VERBOSE( "Retrieving ElementLink to CB TrackParticle..." );
-      ATH_MSG_VERBOSE( "Setting Pt  [CB]: if no track available, set to 0..." );
-      //ATH_MSG_VERBOSE( "mu.isAvailable< ElementLink< xAOD::TrackParticleContainer > >( \"combinedTrackParticleLink\" ) = " << mu.isAvailable< ElementLink< xAOD::TrackParticleContainer > >( "combinedTrackParticleLink" ) );
-      //ATH_MSG_VERBOSE( "( mu.combinedTrackParticleLink() == NULL ) = " << ( mu.combinedTrackParticleLink() == NULL ) );
-      //ATH_MSG_VERBOSE( "mu.combinedTrackParticleLink() = " << mu.combinedTrackParticleLink() );
-      //ATH_MSG_VERBOSE( "( mu.combinedTrackParticleLink() ).isValid() = " << ( mu.combinedTrackParticleLink() ).isValid() );
-      float temp_cb_pt = 0.;
-      //if( mu.isAvailable<ElementLink<xAOD::TrackParticleContainer> > ("inDetTrackParticleLink")){
       if( mu.isAvailable<ElementLink<xAOD::TrackParticleContainer > > ("combinedTrackParticleLink")){
         if(mu.combinedTrackParticleLink().isValid()){
           const ElementLink< xAOD::TrackParticleContainer >& cb_track = mu.combinedTrackParticleLink();
-          temp_cb_pt = ( !cb_track ) ? 0. : ( *cb_track )->pt();
-        }}
-      mu.setP4( temp_cb_pt, vars.m_eta, phi );
+          muonInfo.charge = ( *cb_track )->charge();
+        }
+      }
+    }
+    else{
+      muonInfo.charge = mu.charge();
     }
-    
-    return CorrectionCode::Ok;
-  }
-  
-  
-  ATH_MSG_DEBUG( "Checking Input Muon Info -  Pt_ID: " << vars.m_ptid * 1000. );
-  ATH_MSG_DEBUG( "Checking Input Muon Info -  Pt_MS: " << vars.m_ptms * 1000. );
-  ATH_MSG_DEBUG( "Checking Input Muon Info -  Pt_CB: " << vars.m_ptcb * 1000. );
-  ATH_MSG_VERBOSE( "Checking Input Muon Info -    Eta: " << vars.m_eta );
-  ATH_MSG_VERBOSE( "Checking Input Muon Info -    Phi: " << phi );
-  ATH_MSG_VERBOSE( "Checking Input Muon Info - Sector: " << mu.auxdata< unsigned char >( "primarySector" ) );
-  ATH_MSG_VERBOSE( "Checking Input Muon Info - Charge: " << ( ( vars.m_charge > 0 ) ? "+" : "-" ) );
-  ATH_MSG_VERBOSE( "Checking Input Muon Info -  Pt_CB - Pt_ID: " << ( vars.m_ptcb - vars.m_ptid ) * 1000. );
-
-  //::: Getting detector region
-  if( int( phi ) == DEFAULT_INIT_VAL && m_Trel == MCAST::Release::Rel17_2_Sum13 ) ATH_MSG_ERROR( "You need phi of the muon for after Rel17.2Sum13!" );
- 
-  if( int( phi ) == DEFAULT_INIT_VAL && m_Trel < MCAST::Release::Rel17_2_Sum13 ) {
-    //Lower release have just Eta bins, so usually the user doesn't input
-    //Phi and 0 is a good default for these regions
-    vars.m_detRegion = GetRegion( vars.m_eta, 0 );
-  }
-  else {
-    vars.m_detRegion = GetRegion( vars.m_eta, phi );
-  }
-  if( vars.m_detRegion == -1 ) {
-    ATH_MSG_DEBUG( "Can't find correct detector region! Set smearing to 0." );
-    mu.auxdata< float >( "InnerDetectorPt" ) = vars.m_ptid * 1000.;
-    mu.auxdata< float >( "MuonSpectrometerPt" ) = vars.m_ptms * 1000.;
-    return CorrectionCode::OutOfValidityRange;
-  }
-  
-  //::: Get Event Number:
-  const unsigned long long eventNumber = evtInfo->eventNumber();
-  //::: Construct a seed for the random number generator:
-  const UInt_t seed = 1 + std::abs( mu.phi() ) * 1E6 + std::abs( mu.eta() ) * 1E3 + eventNumber;
-  TRandom3 random3( seed );
-
-//m_scaleRegion = GetScaleRegion( mu );
-  vars.m_g0 = random3.Gaus( 0, 1 );
-  vars.m_g1 = random3.Gaus( 0, 1 );
-  vars.m_g2 = random3.Gaus( 0, 1 );
-  vars.m_g3 = random3.Gaus( 0, 1 );
-  vars.m_g4 = random3.Gaus( 0, 1 );
-  ATH_MSG_VERBOSE( "Checking Random Values - g_0: " << vars.m_g0 );
-  ATH_MSG_VERBOSE( "Checking Random Values - g_1: " << vars.m_g1 );
-  ATH_MSG_VERBOSE( "Checking Random Values - g_2: " << vars.m_g2 );
-  ATH_MSG_VERBOSE( "Checking Random Values - g_3: " << vars.m_g3 );
-  ATH_MSG_VERBOSE( "Checking Random Values - g_4: " << vars.m_g4 );
-
-  //::: Getting smearing values 
-  //::: MS
-  if( m_currentParameters->SmearTypeMS == MCAST::SystVariation::Default ) {
-    vars.m_smearDeltaMS = GetSmearing( vars, MCAST::DetectorType::MS, mu );
-  }
-  else if( m_currentParameters->SmearTypeMS == MCAST::SystVariation::Up ) {
-    vars.m_smearDeltaMS = GetSystVariation( vars, MCAST::DetectorType::MS, 1. );
-  }
-  else if( m_currentParameters->SmearTypeMS == MCAST::SystVariation::Down ) {
-    vars.m_smearDeltaMS = GetSystVariation( vars, MCAST::DetectorType::MS, -1. );
-  }
-  else {
-    ATH_MSG_ERROR( "Invalid value for m_currentParameters->SmearTypeMS" );
-  }
-  //::: ID
-  if( m_currentParameters->SmearTypeID == MCAST::SystVariation::Default ) {
-    vars.m_smearDeltaID = GetSmearing( vars, MCAST::DetectorType::ID, mu );
-  }
-  else if( m_currentParameters->SmearTypeID == MCAST::SystVariation::Up ) {
-    vars.m_smearDeltaID = GetSystVariation( vars, MCAST::DetectorType::ID, 1. );
-  }
-  else if( m_currentParameters->SmearTypeID == MCAST::SystVariation::Down ) {
-    vars.m_smearDeltaID = GetSystVariation( vars, MCAST::DetectorType::ID, -1. );
-  }
-  else {
-    ATH_MSG_ERROR( "Invalid value for m_currentParameters->SmearTypeID" );
-  }
-  
-  CalcCBWeights( vars, mu );
-  ATH_MSG_VERBOSE( "Checking Smearing - smearDeltaID: " << vars.m_smearDeltaID );
-  ATH_MSG_VERBOSE( "Checking Smearing - smearDeltaMS: " << vars.m_smearDeltaMS );
-  ATH_MSG_VERBOSE( "Checking Weights - weightID: " << vars.m_weightID << " - fabs( weightID - 1 ): " << fabs( vars.m_weightID - 1 ) );
-  ATH_MSG_VERBOSE( "Checking Weights - weightMS: " << vars.m_weightMS << " - fabs( weightMS - 1 ): " << fabs( vars.m_weightMS - 1 ) );
-  vars.m_smearDeltaCB = vars.m_smearDeltaID * vars.m_weightID + vars.m_smearDeltaMS * vars.m_weightMS;
-
-  //::: Calibrate the pt of the muon:
-  double res_idPt = 1000. * CalculatePt( vars, MCAST::DetectorType::ID, vars.m_smearDeltaID, vars.m_smearDeltaMS, m_currentParameters->Scale );
-  double res_msPt = 1000. * CalculatePt( vars, MCAST::DetectorType::MS, vars.m_smearDeltaID, vars.m_smearDeltaMS, m_currentParameters->Scale );
-  double res_cbPt = 1000. * CalculatePt( vars, MCAST::DetectorType::CB, vars.m_smearDeltaID, vars.m_smearDeltaMS, m_currentParameters->Scale );
-
-  if( m_doSagittaCorrection &&  (m_currentParameters->SagittaRho != MCAST::SystVariation::Default ||  
-                                 m_currentParameters->SagittaBias != MCAST::SystVariation::Default) ){
-    
-    vars.m_ptid = res_idPt/1000.; 
-    vars.m_ptms = res_msPt/1000.; 
-    vars.m_ptcb = res_cbPt/1000.; 
-
-    CorrectionCode sgCode=CorrectionCode::Ok;
-    if(m_currentParameters->SagittaRho != MCAST::SystVariation::Default){
-      if(m_currentParameters->SagittaRho == MCAST::SystVariation::Up || m_currentParameters->SagittaRho == MCAST::SystVariation::Down){
-        sgCode=applySagittaBiasCorrectionAuto(vars,MCAST::DetectorType::CB,mu,true,MCAST::SagittaSysType::RHO);
-      }}
-    
-    else if(m_currentParameters->SagittaBias != MCAST::SystVariation::Default){
-      if(m_currentParameters->SagittaBias == MCAST::SystVariation::Up || m_currentParameters->SagittaBias == MCAST::SystVariation::Down){
-        sgCode=applySagittaBiasCorrectionAuto(vars,MCAST::DetectorType::CB,mu,true,MCAST::SagittaSysType::BIAS);
-      }}
-    
-    if(sgCode!=CorrectionCode::Ok) return sgCode;
-    
-    res_idPt=vars.m_ptid *1000.;
-    res_msPt=vars.m_ptms *1000.;
-    res_cbPt=vars.m_ptcb *1000.;
-  }
 
+   
+    ATH_MSG_VERBOSE( "Setting Eta [CB]..." );
+    muonInfo.eta = mu.eta();
+    ATH_MSG_VERBOSE( "Setting Phi [CB]..." );
+    muonInfo.phi = mu.phi();
 
-  //::: Override combined momentum for special cases
-  if( fabs( vars.m_weightID - 1 ) < EPSILON ) res_cbPt = res_idPt; 
-  if( fabs( vars.m_weightMS - 1 ) < EPSILON ) res_cbPt = res_msPt; 
-  //::: Using ToroidOff flag
-  mu.auxdata< float >( "InnerDetectorPt" ) = res_idPt;
-  if( m_toroidOff ) {
-    mu.auxdata< float >( "MuonSpectrometerPt" ) = 0.;
-    mu.setP4( res_idPt, vars.m_eta, phi );
-  }
-  else {
-    mu.auxdata< float >( "MuonSpectrometerPt" ) = res_msPt;
-    mu.setP4( res_cbPt, vars.m_eta, phi );
-  }
-  ATH_MSG_DEBUG( "Checking Output Muon Info - Pt_ID: " << res_idPt );
-  ATH_MSG_DEBUG( "Checking Output Muon Info - Pt_MS: " << res_msPt );
-  ATH_MSG_DEBUG( "Checking Output Muon Info - Pt_CB: " << res_cbPt );
-  ATH_MSG_VERBOSE( "Checking Output Muon Info - Pt_CB - Pt_ID: " << res_cbPt - res_idPt );
 
-  //::: Return gracefully:
-  return CorrectionCode::Ok;
 
-}
+    // Getting detector region
+    if( int( muonInfo.phi ) == DEFAULT_INIT_VAL && m_Trel == MCAST::Release::Rel17_2_Sum13 )
+      ATH_MSG_ERROR( "You need phi of the muon for after Rel17.2Sum13!" );
 
-CorrectionCode MuonCalibrationAndSmearingTool::correctedCopy( const xAOD::Muon& input, xAOD::Muon*& output ) const {
+    if( int( muonInfo.phi ) == DEFAULT_INIT_VAL && m_Trel < MCAST::Release::Rel17_2_Sum13 ) {
+      //Lower release have just Eta bins, so usually the user doesn't input
+      //Phi and 0 is a good default for these regions
+      muonInfo.detRegion = GetRegion( muonInfo.eta, 0 );
+    }
+    else {
+      muonInfo.detRegion = GetRegion( muonInfo.eta, muonInfo.phi );
+    }
 
-  //::: A sanity check:
-  if( output ) ATH_MSG_WARNING( "Non-null pointer received. " "There's a possible memory leak!" );
+    // Clear the vector of cov matrices
+    muonInfo.cbParsA.clear();
+    muonInfo.cbCovMat.clear();
 
-  //::: Create a new object:
-  ATH_MSG_VERBOSE( "Going to create new xAOD::Muon..." );
-  output = new xAOD::Muon();
-  ATH_MSG_VERBOSE( "Calling makePrivateStore..." );
-  output->makePrivateStore( input );
+    // Set the statistical combination for muons above given pT threshotld.
+    if( m_useStatComb && muonInfo.ptcb > m_StatCombPtThreshold && isBadMuon(mu, muonInfo)) {
+      CorrectionCode cbCode=applyStatCombination(mu, muonInfo);
+      if( cbCode==CorrectionCode::Ok){
+        if(m_doNotUseAMGMATRIXDECOR){
+          muonInfo.ptcb = std::sin(muonInfo.cbParsA[3])/std::fabs(muonInfo.cbParsA[4])/ 1000;
+        }
+        else {
+          if(!mu.isAvailable < AmgVector(5) >( "StatCombCBPars" )) return CorrectionCode::Error;
+          AmgVector(5) parsCB = mu.auxdata < AmgVector(5) >( "StatCombCBPars" );
+          muonInfo.ptcb = std::sin(parsCB[3])/std::fabs(parsCB[4])/ 1000;
+        }
+      }
+    }
 
-  //::: Use the other function to modify this object:
-  ATH_MSG_VERBOSE( "Calling applyCorrection..." );
-  return applyCorrection( *output );
-}
+    // Retrieve the event information:
+    SG::ReadHandle<xAOD::EventInfo> evtInfo(m_eventInfo);
+    ATH_MSG_VERBOSE( "Checking Simulation flag: " << evtInfo->eventType( xAOD::EventInfo::IS_SIMULATION ) );
 
-bool MuonCalibrationAndSmearingTool::isAffectedBySystematic( const SystematicVariation& systematic ) const {
+    if( !evtInfo->eventType( xAOD::EventInfo::IS_SIMULATION ) ) {
 
-  SystematicSet sys = affectingSystematics();
-  return sys.find( systematic ) != sys.end();
+      // Statistical combiantion specifics
+      if(m_useStatComb){
+        mu.setP4( muonInfo.ptcb * 1000 , muonInfo.eta, muonInfo.phi );
+      }
 
-}
+      // Sagitta Correction  specifics
+      if(m_doSagittaCorrection){
+        CorrectionCode sgCode = applySagittaBiasCorrectionAuto(MCAST::DetectorType::CB, mu, false, MCAST::SagittaSysType::NOMINAL, muonInfo);
+        if(sgCode!=CorrectionCode::Ok) return sgCode;
+        mu.setP4( muonInfo.ptcb * 1000 , muonInfo.eta, muonInfo.phi );
+      }
 
-SystematicSet MuonCalibrationAndSmearingTool::affectingSystematics() const {
+      mu.auxdata< float >( "InnerDetectorPt" ) = muonInfo.ptid * 1000.;
 
-  SystematicSet result;
+      // Toroid-off specifics
+      if( m_toroidOff ) {
+        mu.auxdata< float >( "MuonSpectrometerPt" ) = 0.;
+        mu.setP4( muonInfo.ptid * 1000., muonInfo.eta, muonInfo.phi );
+      }
+      else {
+        mu.auxdata< float >( "MuonSpectrometerPt" ) = muonInfo.ptms * 1000.;
+      }
 
-  //::: ID systematics
-  result.insert( SystematicVariation( "MUON_ID", 1 ) );
-  result.insert( SystematicVariation( "MUON_ID", -1 ) );
+      // SAF specifics
+      if( mu.muonType() == xAOD::Muon::SiliconAssociatedForwardMuon ) {
+        ATH_MSG_VERBOSE( "Retrieving ElementLink to CB TrackParticle..." );
+        ATH_MSG_VERBOSE( "Setting Pt  [CB]: if no track available, set to 0..." );
+        float temp_cb_pt = 0.;
+        if( mu.isAvailable<ElementLink<xAOD::TrackParticleContainer > > ("combinedTrackParticleLink")){
+          if(mu.combinedTrackParticleLink().isValid()){
+            const ElementLink< xAOD::TrackParticleContainer >& cb_track = mu.combinedTrackParticleLink();
+            temp_cb_pt = ( !cb_track ) ? 0. : ( *cb_track )->pt();
+          }
+        }
+        mu.setP4( temp_cb_pt, muonInfo.eta, muonInfo.phi );
+      }
 
-  //::: MS systematics
-  result.insert( SystematicVariation( "MUON_MS", 1 ) );
-  result.insert( SystematicVariation( "MUON_MS", -1 ) );
+      return CorrectionCode::Ok;
+    }
 
-  //::: Scale systematics
-  result.insert( SystematicVariation( "MUON_SCALE", 1 ) );
-  result.insert( SystematicVariation( "MUON_SCALE", -1 ) );
+    //Now get the specific regions and the MC smearing/scale calib
+    if( SetInfoHelperCorConsts(muonInfo) == StatusCode::FAILURE ) {
+      ATH_MSG_DEBUG( "Can't configure Correction constants! Set smearing to 0." );
+      mu.auxdata< float >( "InnerDetectorPt" ) = muonInfo.ptid * 1000.;
+      mu.auxdata< float >( "MuonSpectrometerPt" ) = muonInfo.ptms * 1000.;
+      return CorrectionCode::OutOfValidityRange;
+    }
 
-  //::: Sagitta correction rho
-  result.insert( SystematicVariation( "MUON_SAGITTA_RHO", 1 ) );
-  result.insert( SystematicVariation( "MUON_SAGITTA_RHO", -1 ) );
+    CalcCBWeights( mu, muonInfo );
+    ATH_MSG_VERBOSE( "Checking Weights - weightID: " << muonInfo.weightID << " - fabs( weightID - 1 ): " << std::fabs( muonInfo.weightID - 1 ) );
+    ATH_MSG_VERBOSE( "Checking Weights - weightMS: " << muonInfo.weightMS << " - fabs( weightMS - 1 ): " << std::fabs( muonInfo.weightMS - 1 ) );
+    muonInfo.smearDeltaCB = muonInfo.smearDeltaID * muonInfo.weightID + muonInfo.smearDeltaMS * muonInfo.weightMS;
 
-  //::: Sagitta correction resid bias 
-  result.insert( SystematicVariation( "MUON_SAGITTA_RESBIAS", 1 ) );
-  result.insert( SystematicVariation( "MUON_SAGITTA_RESBIAS", -1 ) );
-  
-  return result;
+    // Calibrate the pt of the muon:
+    double res_idPt = 1000. * CalculatePt( MCAST::DetectorType::ID, muonInfo.smearDeltaID, muonInfo.smearDeltaMS, m_currentParameters->Scale, muonInfo );
+    double res_msPt = 1000. * CalculatePt( MCAST::DetectorType::MS, muonInfo.smearDeltaID, muonInfo.smearDeltaMS, m_currentParameters->Scale, muonInfo );
+    double res_cbPt = 1000. * CalculatePt( MCAST::DetectorType::CB, muonInfo.smearDeltaID, muonInfo.smearDeltaMS, m_currentParameters->Scale, muonInfo );
 
-}
+    if( ( m_doSagittaCorrection ||  m_doSagittaMCDistortion ) &&  (m_currentParameters->SagittaRho != MCAST::SystVariation::Default ||
+                                                                   m_currentParameters->SagittaBias != MCAST::SystVariation::Default) ){
+      ATH_MSG_VERBOSE( "Systematic uncertainties for sagitta bias "<< muonInfo.ptcb << res_idPt);
 
-SystematicSet MuonCalibrationAndSmearingTool::recommendedSystematics() const {
+      muonInfo.ptid = res_idPt/1000.;
+      muonInfo.ptms = res_msPt/1000.;
+      muonInfo.ptcb = res_cbPt/1000.;
 
-  return affectingSystematics();
 
-}
+      CorrectionCode sgCode=CorrectionCode::Ok;
+      if(m_currentParameters->SagittaRho != MCAST::SystVariation::Default){
+        if(m_currentParameters->SagittaRho == MCAST::SystVariation::Up || m_currentParameters->SagittaRho == MCAST::SystVariation::Down){
+          sgCode=applySagittaBiasCorrectionAuto(MCAST::DetectorType::CB, mu, true, MCAST::SagittaSysType::RHO, muonInfo);
+        }
+      }
 
-SystematicCode MuonCalibrationAndSmearingTool::applySystematicVariation( const SystematicSet& systConfig ) {
+      else if(m_currentParameters->SagittaBias != MCAST::SystVariation::Default){
+        if(m_currentParameters->SagittaBias == MCAST::SystVariation::Up || m_currentParameters->SagittaBias == MCAST::SystVariation::Down){
+          sgCode=applySagittaBiasCorrectionAuto(MCAST::DetectorType::CB, mu, true, MCAST::SagittaSysType::BIAS, muonInfo);
+        }
+      }
 
-  //::: First check if we already know this systematic configuration
-  boost::unordered_map< SystematicSet, ParameterSet >::iterator parIter = m_Parameters.find( systConfig );
-  if( parIter != m_Parameters.end() ) {
-    m_currentParameters = &parIter->second;
-    return SystematicCode::Ok;
-  }
+      if(sgCode!=CorrectionCode::Ok)
+        return sgCode;
 
-  //::: Then check if it is actually supported
-  static CP::SystematicSet affSysts = affectingSystematics();
-  SystematicSet checkSysConf;
-  if( !SystematicSet::filterForAffectingSystematics( systConfig, affSysts, checkSysConf ) ) {
-    ATH_MSG_ERROR( "Passing unsupported systematic to the tool!" );
-    return SystematicCode::Unsupported;
-  }
+      res_idPt=muonInfo.ptid *1000.;
+      res_msPt=muonInfo.ptms *1000.;
+      res_cbPt=muonInfo.ptcb *1000.;
+    }
 
-  ParameterSet param;
-  param.SmearTypeID = MCAST::SystVariation::Default; 
-  param.SmearTypeMS = MCAST::SystVariation::Default;
-  param.Scale = MCAST::SystVariation::Default;
-  param.SagittaRho=MCAST::SystVariation::Default;
-  param.SagittaBias=MCAST::SystVariation::Default;
+    // Override combined momentum for special cases
+    if( std::fabs( muonInfo.weightID - 1 ) < EPSILON ) res_cbPt = res_idPt;
+    if( std::fabs( muonInfo.weightMS - 1 ) < EPSILON ) res_cbPt = res_msPt;
+    // Using ToroidOff flag
+    mu.auxdata< float >( "InnerDetectorPt" ) = res_idPt;
+    if( m_toroidOff ) {
+      mu.auxdata< float >( "MuonSpectrometerPt" ) = 0.;
+      mu.setP4( res_idPt, muonInfo.eta, muonInfo.phi );
+    }
+    else {
+      mu.auxdata< float >( "MuonSpectrometerPt" ) = res_msPt;
+      double cbPT=0;
 
-  //::: ID systematics
-  SystematicVariation syst = systConfig.getSystematicByBaseName( "MUON_ID" );
+      if( ( mu.primaryTrackParticleLink() ).isValid() ) {
+        const ElementLink< xAOD::TrackParticleContainer >& cb_track = mu.primaryTrackParticleLink();
+        cbPT=(*cb_track)->pt()/1000;
+      }
+      ATH_MSG_VERBOSE("CB pt "<<cbPT<<" stat comb "<<muonInfo.ptcb<<" corrected pt "<<res_cbPt/1000);
+      mu.setP4( res_cbPt, muonInfo.eta, muonInfo.phi );
+    }
+    ATH_MSG_DEBUG( "Checking Output Muon Info - Pt_ID: " << res_idPt );
+    ATH_MSG_DEBUG( "Checking Output Muon Info - Pt_MS: " << res_msPt );
+    ATH_MSG_DEBUG( "Checking Output Muon Info - Pt_CB: " << res_cbPt );
+    ATH_MSG_VERBOSE( "Checking Output Muon Info - Pt_CB - Pt_ID: " << res_cbPt - res_idPt );
 
-  if( syst == SystematicVariation( "MUON_ID", 1 ) ) {
-    param.SmearTypeMS = MCAST::SystVariation::Default;
-    param.SmearTypeID = MCAST::SystVariation::Up;
-    param.Scale = MCAST::SystVariation::Default;
-    param.SagittaRho=MCAST::SystVariation::Default;
-    param.SagittaBias=MCAST::SystVariation::Default;
-  }
-  else if( syst == SystematicVariation( "MUON_ID", -1 ) ) {
-    //param.SmearTypeMS = vars.m_smearDeltaMS;
-    //param.SmearTypeID = GetSystVariation( vars, MCAST::DetectorType::ID, -1. );
-    param.SmearTypeMS = MCAST::SystVariation::Default;
-    param.SmearTypeID = MCAST::SystVariation::Down;
-    param.Scale = MCAST::SystVariation::Default;
-    param.SagittaRho=MCAST::SystVariation::Default;
-    param.SagittaBias=MCAST::SystVariation::Default;
+    // Return gracefully:
+    return CorrectionCode::Ok;
   }
-  else if( !syst.empty() ) return SystematicCode::Unsupported;
 
-  //::: MS systematics
-  syst = systConfig.getSystematicByBaseName( "MUON_MS" );
 
-  if( syst == SystematicVariation( "MUON_MS", 1 ) ) {
-    //param.SmearTypeMS = GetSystVariation( vars, MCAST::DetectorType::MS, 1. );
-    //param.SmearTypeID = vars.m_smearDeltaID;
-    param.SmearTypeMS = MCAST::SystVariation::Up;
-    param.SmearTypeID = MCAST::SystVariation::Default;
-    param.Scale = MCAST::SystVariation::Default;
-    param.SagittaRho=MCAST::SystVariation::Default;
-    param.SagittaBias=MCAST::SystVariation::Default;
-  }
-  else if( syst == SystematicVariation( "MUON_MS", -1 ) ) {
-    //param.SmearTypeID = vars.m_smearDeltaID;
-    //param.SmearTypeMS = GetSystVariation( vars, MCAST::DetectorType::MS, -1. );
-    param.SmearTypeMS = MCAST::SystVariation::Down;
-    param.SmearTypeID = MCAST::SystVariation::Default;
-    param.Scale = MCAST::SystVariation::Default;
-    param.SagittaRho=MCAST::SystVariation::Default;
-    param.SagittaBias=MCAST::SystVariation::Default;
-  }
-  else if( !syst.empty() ) return SystematicCode::Unsupported;
+  CorrectionCode MuonCalibrationAndSmearingTool::applyCorrectionTrkOnly( xAOD::TrackParticle& inTrk, const int DetType) const {
+    // Make InfoHelper for passing muon info between functions
+    InfoHelper muonInfo;
 
-  //::: Scale systematics
-  syst = systConfig.getSystematicByBaseName( "MUON_SCALE" );
+    if( DetType == MCAST::DetectorType::ID ) {//ID-trk only correction
+      muonInfo.ptid = inTrk.pt() / 1000.;
+      muonInfo.ptms = 0.;
+      muonInfo.ptcb = muonInfo.ptid;
+      muonInfo.weightID = 1.;
+      muonInfo.weightMS = 0.;
+    } else if ( DetType == MCAST::DetectorType::MS){ //MS-trk only correction
+      muonInfo.ptid = 0.;
+      muonInfo.ptms = inTrk.pt() / 1000.;
+      muonInfo.ptcb = muonInfo.ptms;
+      muonInfo.weightID = 0.;
+      muonInfo.weightMS = 1.;
+    } else {
+      ATH_MSG_ERROR( "Track Type not recongnized!");
+      return CorrectionCode::Error;
+    }
+    muonInfo.charge = inTrk.charge();
+    muonInfo.eta = inTrk.eta();
+    muonInfo.phi = inTrk.phi();
 
-  if( syst == SystematicVariation( "MUON_SCALE", 1 ) ) {
-    param.SmearTypeMS = MCAST::SystVariation::Default;
-    param.SmearTypeID = MCAST::SystVariation::Default;
-    param.Scale = MCAST::SystVariation::Down;
-    param.SagittaRho=MCAST::SystVariation::Default;
-    param.SagittaBias=MCAST::SystVariation::Default;
-  }
-  else if( syst == SystematicVariation( "MUON_SCALE", -1 ) ) {
-    param.SmearTypeMS = MCAST::SystVariation::Default;
-    param.SmearTypeID = MCAST::SystVariation::Default;
-    param.Scale = MCAST::SystVariation::Up;
-    param.SagittaRho=MCAST::SystVariation::Default;
-    param.SagittaBias=MCAST::SystVariation::Default;
-  }
-  else if( !syst.empty() ) return SystematicCode::Unsupported;
+    //::: Retrieve the event information:
+    SG::ReadHandle<xAOD::EventInfo> evtInfo(m_eventInfo);
+    ATH_MSG_VERBOSE( "Checking Simulation flag: " << evtInfo->eventType( xAOD::EventInfo::IS_SIMULATION ) );
 
- 
-  //::: Sagitta Rho systematics
-  syst = systConfig.getSystematicByBaseName( "MUON_SAGITTA_RHO" );
+    if( evtInfo->eventType( xAOD::EventInfo::IS_SIMULATION ) ) {
+      //Now get the specific regions and the MC smearing/scale calib
+      if( SetInfoHelperCorConsts(muonInfo) == StatusCode::FAILURE ){
+        ATH_MSG_ERROR( "Can't configure Correction constants! Set smearing to 0." );
+        return CorrectionCode::OutOfValidityRange;
+      }
 
-  if( syst == SystematicVariation( "MUON_SAGITTA_RHO", 1 ) ) {
-    param.SmearTypeMS = MCAST::SystVariation::Default;
-    param.SmearTypeID = MCAST::SystVariation::Default;
-    param.Scale = MCAST::SystVariation::Default;
-    param.SagittaRho=MCAST::SystVariation::Down;
-    param.SagittaBias=MCAST::SystVariation::Default;
-  }
-  else if( syst == SystematicVariation( "MUON_SAGITTA_RHO", -1 ) ) {
-    param.SmearTypeMS = MCAST::SystVariation::Default;
-    param.SmearTypeID = MCAST::SystVariation::Default;
-    param.Scale = MCAST::SystVariation::Default;
-    param.SagittaRho=MCAST::SystVariation::Up;
-    param.SagittaBias=MCAST::SystVariation::Default;
-  }
-  else if( !syst.empty() ) return SystematicCode::Unsupported;  
+      ATH_MSG_VERBOSE( "Checking Weights - weightID: " << muonInfo.weightID <<" - weightMS: " << muonInfo.weightMS);
 
-  
-  //::: Sagitta Residual Bias systematics
-  syst = systConfig.getSystematicByBaseName( "MUON_SAGITTA_RESBIAS" );
-  
-  if( syst == SystematicVariation( "MUON_SAGITTA_RESBIAS", 1 ) ) {
-    param.SmearTypeMS = MCAST::SystVariation::Default;
-    param.SmearTypeID = MCAST::SystVariation::Default;
-    param.Scale = MCAST::SystVariation::Default;
-    param.SagittaRho=MCAST::SystVariation::Default;
-    param.SagittaBias=MCAST::SystVariation::Down;
-  }
-  else if( syst == SystematicVariation( "MUON_SAGITTA_RESBIAS", -1 ) ) {
-    param.SmearTypeMS = MCAST::SystVariation::Default;
-    param.SmearTypeID = MCAST::SystVariation::Default;
-    param.Scale = MCAST::SystVariation::Default;
-    param.SagittaRho=MCAST::SystVariation::Default;
-    param.SagittaBias=MCAST::SystVariation::Up;
-  }
-  else if( !syst.empty() ) return SystematicCode::Unsupported;  
-  
-  
-  //:::
-  ATH_MSG_DEBUG( "Systematic variation's parameters, SmearTypeID: " << param.SmearTypeID ); 
-  ATH_MSG_DEBUG( "Systematic variation's parameters, SmearTypeMS: " << param.SmearTypeMS ); 
-  ATH_MSG_DEBUG( "Systematic variation's parameters, Scale: " << param.Scale ); 
-  //::: store this calibration for future use, and make it current
-  m_currentParameters = &m_Parameters.insert( std::make_pair( systConfig, param ) ).first->second;
-  return SystematicCode::Ok;
-
-}
-
-StatusCode MuonCalibrationAndSmearingTool::SetData( const std::string& data ) {
-
-  if( data == "Data10" ) {
-    m_Tdata = MCAST::DataType::Data10;
-  }
-  else if( data == "Data11" ) {
-    m_Tdata = MCAST::DataType::Data11;
-  }
-  else if( data == "Data12" ) {
-    m_Tdata = MCAST::DataType::Data12;
-  }
-  else if( data == "Data15" ) {
-    m_Tdata = MCAST::DataType::Data15;
-  }
-  else if( data == "Data16" ) {
-    m_Tdata = MCAST::DataType::Data16;
-  }
+      //::: Calibrate the pt of the muon:
+      double res_pt = 1000. * muonInfo.ptcb; //at this level ptcb is a dummy copy of ptID or ptMS
+      if(DetType == MCAST::DetectorType::ID) {
+        res_pt = 1000. * CalculatePt( MCAST::DetectorType::ID, muonInfo.smearDeltaID, muonInfo.smearDeltaMS, m_currentParameters->Scale, muonInfo);
+      } else if ( DetType == MCAST::DetectorType::MS){
+        res_pt = 1000. * CalculatePt( MCAST::DetectorType::MS, muonInfo.smearDeltaID, muonInfo.smearDeltaMS, m_currentParameters->Scale, muonInfo);
+      } else {
+        return CorrectionCode::Error;
+      }
+
+      inTrk.setDefiningParameters(inTrk.d0(), inTrk.z0(), inTrk.phi0(), inTrk.theta(), inTrk.charge()/(res_pt*cosh(inTrk.eta())));
 
-  else {
-    ATH_MSG_ERROR( "Unrecognized value for SetData" );
-    return StatusCode::FAILURE;
+    } //+++++++ DO HERE THE SAGITTA BIAS CASE!
+
+    return CorrectionCode::Ok;
   }
-  return StatusCode::SUCCESS;
 
-}
+  StatusCode MuonCalibrationAndSmearingTool::SetInfoHelperCorConsts(InfoHelper& inMuonInfo) const{
 
-StatusCode MuonCalibrationAndSmearingTool::SetAlgorithm( const std::string& algo ) {
+    ATH_MSG_DEBUG( "Checking Input Muon Info -  Pt_ID: " << inMuonInfo.ptid * 1000. );
+    ATH_MSG_DEBUG( "Checking Input Muon Info -  Pt_MS: " << inMuonInfo.ptms * 1000. );
+    ATH_MSG_DEBUG( "Checking Input Muon Info -  Pt_CB: " << inMuonInfo.ptcb * 1000. );
+    ATH_MSG_VERBOSE( "Checking Input Muon Info -    Eta: " << inMuonInfo.eta );
+    ATH_MSG_VERBOSE( "Checking Input Muon Info -    Phi: " << inMuonInfo.phi );
+    ATH_MSG_VERBOSE( "Checking Input Muon Info - Charge: " << ( ( inMuonInfo.charge > 0 ) ? "+" : "-" ) );
+    ATH_MSG_VERBOSE( "Checking Input Muon Info -  Pt_CB - Pt_ID: " << ( inMuonInfo.ptcb - inMuonInfo.ptid ) * 1000. );
 
-  if( algo == "muid" ) {
-    m_Talgo = MCAST::AlgoType::Muid;
-  }
-  else if( algo == "staco" ) {
-    m_Talgo = MCAST::AlgoType::Staco;
-  }
-  else if( algo == "muons" ) {
-    m_Talgo = MCAST::AlgoType::Muons;
-  }
-  else {
-    ATH_MSG_ERROR( "Unrecognized value for SetAlgorithm" );
-    return StatusCode::FAILURE;
-  }
-  return StatusCode::SUCCESS;
+    // Random number generation for smearing
+    TRandom3   loc_random3;
 
-}
+    // if you don't want to use the external seed it will be set based on the eventNumber and the muon(eta,phi)
+    if( !m_useExternalSeed ) {
+      // Get Event Number, Retrieve the event information:
+      SG::ReadHandle<xAOD::EventInfo> evtInfo(m_eventInfo);
+      const unsigned long long eventNumber = evtInfo->eventNumber();
+      // Construct a seed for the random number generator:
+      const UInt_t seed = 1 + std::abs( inMuonInfo.phi) * 1E6 + std::abs( inMuonInfo.eta ) * 1E3 + eventNumber;
+      loc_random3.SetSeed( seed );
+    }
+    else{
+      const UInt_t seed = m_externalSeed;
+      loc_random3.SetSeed( seed );
+    }
 
-StatusCode MuonCalibrationAndSmearingTool::SetType( const std::string& type ) {
+    inMuonInfo.smearDeltaMS = 0.;
+    inMuonInfo.smearDeltaID = 0.;
+    inMuonInfo.smearDeltaCB = 0.;
+    inMuonInfo.detRegion = -1;
 
-  if( type == "pT" ) {
-    m_Tsmear = MCAST::SmearingType::Pt;
-    ATH_MSG_DEBUG( "Using " << type << " Smearing " );
-  }
-  else if( type == "q_pT" ) {
-    m_Tsmear = MCAST::SmearingType::QoverPt;
-    ATH_MSG_DEBUG( "Using " << type << " Smearing " );
-  }
-  else {
-    ATH_MSG_ERROR( "Unrecognized value for SetType" );
-    return StatusCode::FAILURE;
-  }
-  return StatusCode::SUCCESS;
+    // Getting detector region
+    if( int( inMuonInfo.phi ) == DEFAULT_INIT_VAL && m_Trel == MCAST::Release::Rel17_2_Sum13 )
+      ATH_MSG_ERROR( "You need phi of the muon for after Rel17.2Sum13!" );
+    if( int( inMuonInfo.phi ) == DEFAULT_INIT_VAL && m_Trel < MCAST::Release::Rel17_2_Sum13 ) {
+      //Lower release have just Eta bins, so usually the user doesn't input
+      //Phi and 0 is a good default for these regions
+      inMuonInfo.detRegion = GetRegion( inMuonInfo.eta, 0 );
+    }
+    else {
+      inMuonInfo.detRegion = GetRegion( inMuonInfo.eta, inMuonInfo.phi );
+    }
+
+    if( inMuonInfo.detRegion == -1 ) {
+      ATH_MSG_DEBUG( "Can't find correct detector region! Set smearing to 0." );
+      return StatusCode::SUCCESS;
+    }
 
-}
+    // Getting random numbers for smearing
+    inMuonInfo.g0 = loc_random3.Gaus( 0, 1 );
+    inMuonInfo.g1 = loc_random3.Gaus( 0, 1 );
+    inMuonInfo.g2 = loc_random3.Gaus( 0, 1 );
+    inMuonInfo.g3 = loc_random3.Gaus( 0, 1 );
+    inMuonInfo.g4 = loc_random3.Gaus( 0, 1 );
+    ATH_MSG_VERBOSE( "Checking Random Values - g_0: " << inMuonInfo.g0 );
+    ATH_MSG_VERBOSE( "Checking Random Values - g_1: " << inMuonInfo.g1 );
+    ATH_MSG_VERBOSE( "Checking Random Values - g_2: " << inMuonInfo.g2 );
+    ATH_MSG_VERBOSE( "Checking Random Values - g_3: " << inMuonInfo.g3 );
+    ATH_MSG_VERBOSE( "Checking Random Values - g_4: " << inMuonInfo.g4 );
 
-StatusCode MuonCalibrationAndSmearingTool::SetRelease( const std::string& rel ) {
+    // Getting smearing values
+    // MS
+    if( m_currentParameters->SmearTypeMS == MCAST::SystVariation::Default ) {
+      inMuonInfo.smearDeltaMS = GetSmearing( MCAST::DetectorType::MS, inMuonInfo );
+    }
+    else if( m_currentParameters->SmearTypeMS == MCAST::SystVariation::Up ) {
+      inMuonInfo.smearDeltaMS = GetSystVariation( MCAST::DetectorType::MS, 1., inMuonInfo );
+    }
+    else if( m_currentParameters->SmearTypeMS == MCAST::SystVariation::Down ) {
+      inMuonInfo.smearDeltaMS = GetSystVariation( MCAST::DetectorType::MS, -1., inMuonInfo );
+    }
+    else {
+      ATH_MSG_ERROR( "Invalid value for m_currentParameters->SmearTypeMS" );
+    }
+    // ID
+    if( m_currentParameters->SmearTypeID == MCAST::SystVariation::Default ) {
+      inMuonInfo.smearDeltaID = GetSmearing( MCAST::DetectorType::ID, inMuonInfo );
+    }
+    else if( m_currentParameters->SmearTypeID == MCAST::SystVariation::Up ) {
+      inMuonInfo.smearDeltaID = GetSystVariation( MCAST::DetectorType::ID, 1., inMuonInfo );
+    }
+    else if( m_currentParameters->SmearTypeID == MCAST::SystVariation::Down ) {
+      inMuonInfo.smearDeltaID = GetSystVariation( MCAST::DetectorType::ID, -1., inMuonInfo );
+    }
+    else {
+      ATH_MSG_ERROR( "Invalid value for m_currentParameters->SmearTypeID" );
+    }
 
-  if( rel == "Rel16.6" ) {
-    m_Trel = MCAST::Release::Rel16_6;
-  }
-  else if( rel == "Rel17" ) {
-    m_Trel = MCAST::Release::Rel17;
-  }
-  else if( rel == "Rel17.2" ) {
-    m_Trel = MCAST::Release::Rel17_2;
+    ATH_MSG_VERBOSE( "Checking Smearing - smearDeltaID: " << inMuonInfo.smearDeltaID );
+    ATH_MSG_VERBOSE( "Checking Smearing - smearDeltaMS: " << inMuonInfo.smearDeltaMS );
+    return StatusCode::SUCCESS;
   }
-  else if( rel == "Rel17.2Repro" ) {
-    m_Trel = MCAST::Release::Rel17_2_Repro;
-  }
-  else if( rel == "Rel17.2Sum13" ) {
-    m_Trel = MCAST::Release::Rel17_2_Sum13;
-  }
-  else if( rel == "PreRecs" ) {
-    m_Trel = MCAST::Release::PreRec;
-  }
-  else if( rel == "PreRecs2015_06_22" ) {
-    m_Trel = MCAST::Release::PreRec_2015_06_22;
-  }
-  else if( rel == "PreRecs2015_08_06" ) {
-    m_Trel = MCAST::Release::PreRec_2015_08_06;
-  }
-  else if( rel == "Recs2015_11_15" ) {
-    m_Trel = MCAST::Release::Rec_2015_11_15;
-  }
-  else if( rel == "Recs2016_01_13" ) {
-    m_Trel = MCAST::Release::Rec_2016_01_13;
-  }
-  else if( rel == "Recs2016_01_19" ) {
-    m_Trel = MCAST::Release::Rec_2016_01_19;
-  }
-  else if( rel == "PreRecs2016_05_23" ) {
-    m_Trel = MCAST::Release::PreRec_2016_05_23;
+
+
+  CorrectionCode MuonCalibrationAndSmearingTool::correctedCopy( const xAOD::Muon& input, xAOD::Muon*& output ) const {
+
+    // A sanity check:
+    if( output ) ATH_MSG_WARNING( "Non-null pointer received. " "There's a possible memory leak!" );
+
+    // Create a new object:
+    ATH_MSG_VERBOSE( "Going to create new xAOD::Muon..." );
+    output = new xAOD::Muon();
+    ATH_MSG_VERBOSE( "Calling makePrivateStore..." );
+    output->makePrivateStore( input );
+
+    // Use the other function to modify this object:
+    ATH_MSG_VERBOSE( "Calling applyCorrection..." );
+
+    CP::CorrectionCode retCode = applyCorrection( *output );
+
+    return retCode;
+
   }
-  else if (rel == "Recs2016_08_07") {
-    m_Trel = MCAST::Release::Recs2016_08_07;
+
+  bool MuonCalibrationAndSmearingTool::isAffectedBySystematic( const SystematicVariation& systematic ) const {
+    SystematicSet sys = affectingSystematics();
+    return sys.find( systematic ) != sys.end();
   }
-  else if (rel == "Recs2016_15_07") {
-    m_Trel = MCAST::Release::Recs2016_08_07;
+
+  SystematicSet MuonCalibrationAndSmearingTool::affectingSystematics() const {
+
+    SystematicSet result;
+
+    // ID systematics
+    result.insert( SystematicVariation( "MUON_ID", 1 ) );
+    result.insert( SystematicVariation( "MUON_ID", -1 ) );
+
+    // MS systematics
+    result.insert( SystematicVariation( "MUON_MS", 1 ) );
+    result.insert( SystematicVariation( "MUON_MS", -1 ) );
+
+    // Scale systematics
+    result.insert( SystematicVariation( "MUON_SCALE", 1 ) );
+    result.insert( SystematicVariation( "MUON_SCALE", -1 ) );
+
+    // Sagitta correction rho
+    result.insert( SystematicVariation( "MUON_SAGITTA_RHO", 1 ) );
+    result.insert( SystematicVariation( "MUON_SAGITTA_RHO", -1 ) );
+
+    // Sagitta correction resid bias
+    result.insert( SystematicVariation( "MUON_SAGITTA_RESBIAS", 1 ) );
+    result.insert( SystematicVariation( "MUON_SAGITTA_RESBIAS", -1 ) );
+
+    return result;
+
   }
-  
-  else {
-    m_Trel = MCAST::Release::Recs2016_08_07;
-    //ATH_MSG_ERROR( "Unrecognized value for SetRelease" );
-    //return StatusCode::FAILURE;
+
+  SystematicSet MuonCalibrationAndSmearingTool::recommendedSystematics() const {
+    return affectingSystematics();
   }
-  return StatusCode::SUCCESS;
 
-}
+  SystematicCode MuonCalibrationAndSmearingTool::applySystematicVariation( const SystematicSet& systConfig ) {
 
-//double MuonCalibrationAndSmearingTool::ScaleApply( const double pt, const double S1, const double S2, double S, const double S_enLoss ) const {
-double MuonCalibrationAndSmearingTool::ScaleApply( const int detRegion,
-                                                   const double pt, double S, const double S_enLoss ) const {
+    // First check if we already know this systematic configuration
+    std::unordered_map< SystematicSet, ParameterSet >::iterator parIter = m_Parameters.find( systConfig );
+    if( parIter != m_Parameters.end() ) {
+      m_currentParameters = &parIter->second;
+      return SystematicCode::Ok;
+    }
 
+    // Then check if it is actually supported
+    static CP::SystematicSet affSysts = affectingSystematics();
+    SystematicSet checkSysConf;
+    if( !SystematicSet::filterForAffectingSystematics( systConfig, affSysts, checkSysConf ) ) {
+      ATH_MSG_ERROR( "Passing unsupported systematic to the tool!" );
+      return SystematicCode::Unsupported;
+    }
 
-  //::: Sanity checks:
-  if( detRegion < 0 || detRegion >= m_nb_regions ) return pt;
+    ParameterSet param;
+    param.SmearTypeID = MCAST::SystVariation::Default;
+    param.SmearTypeMS = MCAST::SystVariation::Default;
+    param.Scale = MCAST::SystVariation::Default;
+    param.SagittaRho=MCAST::SystVariation::Default;
+    param.SagittaBias=MCAST::SystVariation::Default;
 
-  //::: default momentum scale (derived form template fits)
-  return pt * S + S_enLoss;
-  //bool apply_to_data = false;
-  //return apply_to_data ? pt / S : ( pt * S + S_enLoss );
+    // ID systematics
+    SystematicVariation syst = systConfig.getSystematicByBaseName( "MUON_ID" );
+
+    if( syst == SystematicVariation( "MUON_ID", 1 ) ) {
+      param.SmearTypeMS = MCAST::SystVariation::Default;
+      param.SmearTypeID = MCAST::SystVariation::Up;
+      param.Scale = MCAST::SystVariation::Default;
+      param.SagittaRho=MCAST::SystVariation::Default;
+      param.SagittaBias=MCAST::SystVariation::Default;
+    }
+    else if( syst == SystematicVariation( "MUON_ID", -1 ) ) {
+      param.SmearTypeMS = MCAST::SystVariation::Default;
+      param.SmearTypeID = MCAST::SystVariation::Down;
+      param.Scale = MCAST::SystVariation::Default;
+      param.SagittaRho=MCAST::SystVariation::Default;
+      param.SagittaBias=MCAST::SystVariation::Default;
+    }
+    else if( !syst.empty() ) return SystematicCode::Unsupported;
+
+    // MS systematics
+    syst = systConfig.getSystematicByBaseName( "MUON_MS" );
+
+    if( syst == SystematicVariation( "MUON_MS", 1 ) ) {
+      param.SmearTypeMS = MCAST::SystVariation::Up;
+      param.SmearTypeID = MCAST::SystVariation::Default;
+      param.Scale = MCAST::SystVariation::Default;
+      param.SagittaRho=MCAST::SystVariation::Default;
+      param.SagittaBias=MCAST::SystVariation::Default;
+    }
+    else if( syst == SystematicVariation( "MUON_MS", -1 ) ) {
+      param.SmearTypeMS = MCAST::SystVariation::Down;
+      param.SmearTypeID = MCAST::SystVariation::Default;
+      param.Scale = MCAST::SystVariation::Default;
+      param.SagittaRho=MCAST::SystVariation::Default;
+      param.SagittaBias=MCAST::SystVariation::Default;
+    }
+    else if( !syst.empty() ) return SystematicCode::Unsupported;
+
+    // Scale systematics
+    syst = systConfig.getSystematicByBaseName( "MUON_SCALE" );
+
+    if( syst == SystematicVariation( "MUON_SCALE", 1 ) ) {
+      param.SmearTypeMS = MCAST::SystVariation::Default;
+      param.SmearTypeID = MCAST::SystVariation::Default;
+      param.Scale = MCAST::SystVariation::Down;
+      param.SagittaRho=MCAST::SystVariation::Default;
+      param.SagittaBias=MCAST::SystVariation::Default;
+    }
+    else if( syst == SystematicVariation( "MUON_SCALE", -1 ) ) {
+      param.SmearTypeMS = MCAST::SystVariation::Default;
+      param.SmearTypeID = MCAST::SystVariation::Default;
+      param.Scale = MCAST::SystVariation::Up;
+      param.SagittaRho=MCAST::SystVariation::Default;
+      param.SagittaBias=MCAST::SystVariation::Default;
+    }
+    else if( !syst.empty() ) return SystematicCode::Unsupported;
+
+
+    // Sagitta Rho systematics
+    syst = systConfig.getSystematicByBaseName( "MUON_SAGITTA_RHO" );
+
+    if( syst == SystematicVariation( "MUON_SAGITTA_RHO", 1 ) ) {
+      param.SmearTypeMS = MCAST::SystVariation::Default;
+      param.SmearTypeID = MCAST::SystVariation::Default;
+      param.Scale = MCAST::SystVariation::Default;
+      param.SagittaRho=MCAST::SystVariation::Down;
+      param.SagittaBias=MCAST::SystVariation::Default;
+    }
+    else if( syst == SystematicVariation( "MUON_SAGITTA_RHO", -1 ) ) {
+      param.SmearTypeMS = MCAST::SystVariation::Default;
+      param.SmearTypeID = MCAST::SystVariation::Default;
+      param.Scale = MCAST::SystVariation::Default;
+      param.SagittaRho=MCAST::SystVariation::Up;
+      param.SagittaBias=MCAST::SystVariation::Default;
+    }
+    else if( !syst.empty() ) return SystematicCode::Unsupported;
+
+
+    // Sagitta Residual Bias systematics
+    syst = systConfig.getSystematicByBaseName( "MUON_SAGITTA_RESBIAS" );
+
+    if( syst == SystematicVariation( "MUON_SAGITTA_RESBIAS", 1 ) ) {
+      param.SmearTypeMS = MCAST::SystVariation::Default;
+      param.SmearTypeID = MCAST::SystVariation::Default;
+      param.Scale = MCAST::SystVariation::Default;
+      param.SagittaRho=MCAST::SystVariation::Default;
+      param.SagittaBias=MCAST::SystVariation::Down;
+    }
+    else if( syst == SystematicVariation( "MUON_SAGITTA_RESBIAS", -1 ) ) {
+      param.SmearTypeMS = MCAST::SystVariation::Default;
+      param.SmearTypeID = MCAST::SystVariation::Default;
+      param.Scale = MCAST::SystVariation::Default;
+      param.SagittaRho=MCAST::SystVariation::Default;
+      param.SagittaBias=MCAST::SystVariation::Up;
+    }
+    else if( !syst.empty() ) return SystematicCode::Unsupported;
+
+
+    //
+    ATH_MSG_DEBUG( "Systematic variation's parameters, SmearTypeID: " << param.SmearTypeID );
+    ATH_MSG_DEBUG( "Systematic variation's parameters, SmearTypeMS: " << param.SmearTypeMS );
+    ATH_MSG_DEBUG( "Systematic variation's parameters, Scale: " << param.Scale );
+    // store this calibration for future use, and make it current
+    m_currentParameters = &m_Parameters.insert( std::make_pair( systConfig, param ) ).first->second;
+    return SystematicCode::Ok;
 
-}
+  }
 
+  StatusCode MuonCalibrationAndSmearingTool::SetData( std::string data ) {
 
-double MuonCalibrationAndSmearingTool::CalculatePt( const Vars& vars,
-                                                    const int DetType, const double inSmearID, const double inSmearMS, const double scaleVar) const
-{
-  double scaleID = 0., enLossCorrMS = 0., scaleMS = 0., scaleCB = 0.;//initialize all to 0
-  //::: These are alternative scale corrections (KPKM,KC,K,C) they are != 0. if Tscale != SCALE_DEFAULT.
-  //double s1_ID = 0., s2_ID = 0., s1_MS = 0., s2_MS = 0., s1_CB = 0., s2_CB = 0.;//Description of these is in ApplyScale
+    if( data == "Data10" ) {
+      m_Tdata = MCAST::DataType::Data10;
+    }
+    else if( data == "Data11" ) {
+      m_Tdata = MCAST::DataType::Data11;
+    }
+    else if( data == "Data12" ) {
+      m_Tdata = MCAST::DataType::Data12;
+    }
+    else if( data == "Data15" ) {
+      m_Tdata = MCAST::DataType::Data15;
+    }
+    else if( data == "Data16" ) {
+      m_Tdata = MCAST::DataType::Data16;
+    }
+    else if( data == "Data17" ) {
+      m_Tdata = MCAST::DataType::Data17;
+    }
+    else if( data == "Data18" ) {
+      m_Tdata = MCAST::DataType::Data18;
+    }
+    else {
+      ATH_MSG_ERROR( "Unrecognized value for SetData" );
+      return StatusCode::FAILURE;
+    }
+
+    return StatusCode::SUCCESS;
 
-  if( fabs( scaleVar ) != 1. && scaleVar != 0. ) ATH_MSG_ERROR( "Unpredicted scale variation of Delta "<<scaleVar<<" sigmas!" );
+  }
+
+  StatusCode MuonCalibrationAndSmearingTool::SetAlgorithm( std::string algo ) {
 
-  if( m_scale_ID[vars.m_detRegion] != -1 ) {
-    if( m_Trel >= MCAST::Release::Rel17_2_Sum13 ) {
-      scaleID = scaleVar > 0. ? m_scaleSystUp_ID[vars.m_detRegion] : m_scaleSystDw_ID[vars.m_detRegion];
+    if( algo == "muid" ) {
+      m_Talgo = MCAST::AlgoType::Muid;
+    }
+    else if( algo == "staco" ) {
+      m_Talgo = MCAST::AlgoType::Staco;
+    }
+    else if( algo == "muons" ) {
+      m_Talgo = MCAST::AlgoType::Muons;
     }
     else {
-      scaleID = m_scaleSyst_ID[vars.m_detRegion];
+      ATH_MSG_ERROR( "Unrecognized value for SetAlgorithm" );
+      return StatusCode::FAILURE;
     }
-    scaleID = m_scale_ID[vars.m_detRegion] + scaleVar*scaleID;
-  }
-  else {
-    scaleID = ( m_Trel >= MCAST::Release::Rel17_2_Sum13 ) ? 0. : 1.;
+    return StatusCode::SUCCESS;
+
   }
-  if( m_scale_MS[vars.m_detRegion] != -1 ) {
-    if( m_Trel >= MCAST::Release::Rel17_2_Sum13 ) {
-      scaleMS = scaleVar > 0. ? m_scaleSystUp_MS[vars.m_detRegion] : m_scaleSystDw_MS[vars.m_detRegion];
-      enLossCorrMS = scaleVar > 0. ? m_enLossSystUp_MS[vars.m_detRegion] : m_enLossSystDw_MS[vars.m_detRegion];
+
+  StatusCode MuonCalibrationAndSmearingTool::SetType( std::string type ) {
+
+    if( type == "pT" ) {
+      m_Tsmear = MCAST::SmearingType::Pt;
+      ATH_MSG_DEBUG( "Using " << type << " Smearing " );
+    }
+    else if( type == "q_pT" ) {
+      m_Tsmear = MCAST::SmearingType::QoverPt;
+      ATH_MSG_DEBUG( "Using " << type << " Smearing " );
     }
     else {
-      scaleMS = m_scaleSyst_MS[vars.m_detRegion];
+      ATH_MSG_ERROR( "Unrecognized value for SetType" );
+      return StatusCode::FAILURE;
     }
-    scaleMS =  m_scale_MS[vars.m_detRegion] + scaleVar*scaleMS;
-    if( true ) enLossCorrMS = m_enLoss_MS[vars.m_detRegion] + scaleVar*enLossCorrMS;
-  }
-  else {
-    scaleMS = ( m_Trel >= MCAST::Release::Rel17_2_Sum13 ) ? 0. : 1.;
-  }
-  if( m_Trel >= MCAST::Release::Rel17_2_Sum13 ) { //NB: MCAST::Release::Rel17_2_Sum13 has scale parametrized around 0, not 1!!
-    scaleID += 1.;
-    scaleMS += 1.;
-  }
-  if( m_scale_CB[vars.m_detRegion] != -1 ) {
-    scaleCB = m_scale_CB[vars.m_detRegion] + scaleVar * m_scaleSyst_CB[vars.m_detRegion];
-  }
-  else {
-    if( vars.m_ptms ) scaleCB = ( scaleID * vars.m_weightID + ( scaleMS + enLossCorrMS / vars.m_ptms ) * vars.m_weightMS );
-    else         scaleCB = scaleID; // was scaleID * vars.m_weightID
-  }
-  
-  double tmpDelta = 1.;
-  double outPtID = vars.m_ptid, outPtMS = vars.m_ptms, outPtCB = vars.m_ptcb;
-  if( DetType == MCAST::DetectorType::ID ) {
-    ATH_MSG_VERBOSE( "Checking s1_ID = " << scaleID );
-    ATH_MSG_VERBOSE( "Double-Checking outPtID = " << outPtID << " at first..." );
-    if( outPtID == 0. ) return outPtID;
-    //Load the ID scale and smearing that you will use
-    ATH_MSG_VERBOSE( "Double-Checking int( inSmearID ) = " << int( inSmearID ) );
-    ATH_MSG_VERBOSE( "Double-Checking DEFAULT_INIT_VAL = " << DEFAULT_INIT_VAL );
-    tmpDelta = ( int( inSmearID ) == DEFAULT_INIT_VAL ) ? 1. + vars.m_smearDeltaID : 1. + inSmearID;
-    ATH_MSG_VERBOSE( "Double-Checking inSmearID = " << inSmearID );
-    ATH_MSG_VERBOSE( "Double-Checking vars.m_smearDeltaID = " << vars.m_smearDeltaID );
-    ATH_MSG_VERBOSE( "Double-Checking tmpDelta = " << tmpDelta );
-    if( m_Trel < MCAST::Release::Rel17_2_Sum13 ) {
-      if( m_Tsmear == MCAST::SmearingType::Pt )  outPtID = outPtID * tmpDelta;
-      if( m_Tsmear == MCAST::SmearingType::QoverPt ) outPtID = ( tmpDelta == 0 ) ? MCAST_MAX_PT : outPtID / tmpDelta;
-    }
-    //outPtID = ScaleApply( vars.m_detRegion, fabs( outPtID ), s1_ID, s2_ID, scaleID );
-    outPtID = ScaleApply( vars.m_detRegion, fabs( outPtID ), scaleID );
-    if( m_Trel >= MCAST::Release::Rel17_2_Sum13 ) {
-      if( m_Tsmear == MCAST::SmearingType::Pt )  outPtID = outPtID * tmpDelta;
-      if( m_Tsmear == MCAST::SmearingType::QoverPt ) outPtID = ( tmpDelta == 0 ) ? MCAST_MAX_PT : outPtID / tmpDelta;
-    }
-    return outPtID;
-  }
-  if( DetType == MCAST::DetectorType::MS ) {
-    ATH_MSG_VERBOSE( "Checking s0_MS = " << enLossCorrMS );
-    ATH_MSG_VERBOSE( "Checking s1_MS = " << scaleMS );
-    ATH_MSG_VERBOSE( "Double-Checking outPtMS = " << outPtMS << " at first..." );
-    if( outPtMS == 0. ) return outPtMS;
-    //Load the MS scale and smearing that you will use
-    ATH_MSG_VERBOSE( "Double-Checking int( inSmearMS ) = " << int( inSmearMS ) );
-    ATH_MSG_VERBOSE( "Double-Checking DEFAULT_INIT_VAL = " << DEFAULT_INIT_VAL );
-    tmpDelta = ( int( inSmearMS ) == DEFAULT_INIT_VAL ) ? 1. + vars.m_smearDeltaMS : 1. + inSmearMS;
-    ATH_MSG_VERBOSE( "Double-Checking inSmearMS = " << inSmearMS );
-    ATH_MSG_VERBOSE( "Double-Checking m_smearDeltaMS = " << vars.m_smearDeltaMS );
-    ATH_MSG_VERBOSE( "Double-Checking tmpDelta = " << tmpDelta );
-    //In these releases the smearing was applied to the pt before the scale
-    if( m_Trel < MCAST::Release::Rel17_2_Sum13 ) {
-      if( m_Tsmear == MCAST::SmearingType::Pt )  outPtMS = outPtMS * tmpDelta;
-      if( m_Tsmear == MCAST::SmearingType::QoverPt ) outPtMS = ( tmpDelta == 0 ) ? MCAST_MAX_PT : outPtMS / tmpDelta;
-    }
-    ATH_MSG_VERBOSE( "Double-Checking outPtMS = " << outPtMS << " at second..." );
-    //outPtMS = ScaleApply( vars.m_detRegion, fabs( outPtMS ), s1_MS, s2_MS, scaleMS, enLossCorrMS );
-    outPtMS = ScaleApply( vars.m_detRegion, fabs( outPtMS ), scaleMS, enLossCorrMS );
-    ATH_MSG_VERBOSE( "Double-Checking outPtMS = " << outPtMS << " at third..." );
-    if( m_Trel >= MCAST::Release::Rel17_2_Sum13 ) {
-      if( m_Tsmear == MCAST::SmearingType::Pt )  outPtMS = outPtMS * tmpDelta;
-      if( m_Tsmear == MCAST::SmearingType::QoverPt ) outPtMS = ( tmpDelta == 0 ) ? MCAST_MAX_PT : outPtMS / tmpDelta;
-    }
-    ATH_MSG_VERBOSE( "Double-Checking outPtMS = " << outPtMS << " at fourth..." );
-    return outPtMS;
+    return StatusCode::SUCCESS;
+
   }
-  if( DetType == MCAST::DetectorType::CB ) {
-    if( int( inSmearID ) != DEFAULT_INIT_VAL && int( inSmearMS ) != DEFAULT_INIT_VAL ) {
-      tmpDelta = 1. + inSmearID * vars.m_weightID + inSmearMS * vars.m_weightMS;
+
+  StatusCode MuonCalibrationAndSmearingTool::SetRelease( std::string rel ) {
+
+    if( rel == "Rel16.6" ) {
+      m_Trel = MCAST::Release::Rel16_6;
     }
-    else if( int( inSmearID ) == DEFAULT_INIT_VAL && int( inSmearMS ) == DEFAULT_INIT_VAL ) {
-      tmpDelta = 1. + vars.m_smearDeltaCB;
+    else if( rel == "Rel17" ) {
+      m_Trel = MCAST::Release::Rel17;
     }
-    else {
+    else if( rel == "Rel17.2" ) {
+      m_Trel = MCAST::Release::Rel17_2;
+    }
+    else if( rel == "Rel17.2Repro" ) {
+      m_Trel = MCAST::Release::Rel17_2_Repro;
+    }
+    else if( rel == "Rel17.2Sum13" ) {
+      m_Trel = MCAST::Release::Rel17_2_Sum13;
+    }
+    else if( rel == "PreRecs" ) {
+      m_Trel = MCAST::Release::PreRec;
+    }
+    else if( rel == "PreRecs2015_06_22" ) {
+      m_Trel = MCAST::Release::PreRec_2015_06_22;
+    }
+    else if( rel == "PreRecs2015_08_06" ) {
+      m_Trel = MCAST::Release::PreRec_2015_08_06;
+    }
+    else if( rel == "Recs2015_11_15" ) {
+      m_Trel = MCAST::Release::Rec_2015_11_15;
+    }
+    else if( rel == "Recs2016_01_13" ) {
+      m_Trel = MCAST::Release::Rec_2016_01_13;
     }
-    //In these releases the smearing was applied to the pt before the scale
-    if( m_Trel < MCAST::Release::Rel17_2_Sum13 ) {
-      if( m_Tsmear == MCAST::SmearingType::Pt )  outPtCB = outPtCB * tmpDelta;
-      if( m_Tsmear == MCAST::SmearingType::QoverPt ) outPtCB = ( tmpDelta == 0 ) ? MCAST_MAX_PT : outPtCB / tmpDelta;
+    else if( rel == "Recs2016_01_19" ) {
+      m_Trel = MCAST::Release::Rec_2016_01_19;
     }
-    //outPtCB = ScaleApply( vars.m_detRegion, fabs( outPtCB ), s1_CB, s2_CB, scaleCB );
-    outPtCB = ScaleApply( vars.m_detRegion, fabs( outPtCB ), scaleCB );
-    if( m_Trel >= MCAST::Release::Rel17_2_Sum13 ) {
-      if( m_Tsmear == MCAST::SmearingType::Pt )  outPtCB = outPtCB * tmpDelta;
-      if( m_Tsmear == MCAST::SmearingType::QoverPt ) outPtCB = ( tmpDelta == 0 ) ? MCAST_MAX_PT : outPtCB / tmpDelta;
+    else if( rel == "PreRecs2016_05_23" ) {
+      m_Trel = MCAST::Release::PreRec_2016_05_23;
     }
-    return outPtCB;
+    else if (rel == "Recs2016_08_07") {
+      m_Trel = MCAST::Release::Recs2016_08_07;
+    }
+    else if (rel == "Recs2016_15_07") {
+      m_Trel = MCAST::Release::Recs2016_08_07;
+    }
+    else if (rel == "Recs2017_08_02") {
+      m_Trel = MCAST::Release::Recs2017_08_02;
+    }
+    else {
+      m_Trel = MCAST::Release::Recs2017_08_02;
+      ATH_MSG_DEBUG( "Unrecognized value for SetRelease, using Recs2017_08_02" );
+    }
+    return StatusCode::SUCCESS;
+
   }
-  return 0.;
 
-}
+  double MuonCalibrationAndSmearingTool::ScaleApply( const double pt, double S, const double S_enLoss, InfoHelper& muonInfo ) const {
+
+    // Sanity checks:
+    if( muonInfo.detRegion < 0 || muonInfo.detRegion >= m_nb_regions ) return pt;
+
+    // default momentum scale (derived form template fits)
+    return pt * S + S_enLoss;
+
+  }
+
+
+  double MuonCalibrationAndSmearingTool::CalculatePt( const int DetType, const double inSmearID, const double inSmearMS, const double scaleVar, InfoHelper& muonInfo ) const {
 
-StatusCode MuonCalibrationAndSmearingTool::FillValues() {
+    double scaleID = 0., enLossCorrMS = 0., scaleMS = 0., scaleCB = 0.;//initialize all to 0
+    // These are alternative scale corrections (KPKM,KC,K,C) they are != 0. if Tscale != SCALE_DEFAULT.
 
-  Clean();
-  double tmpval;
-  std::string tmpname;
-  std::ifstream InValues;
+    if( std::fabs( scaleVar ) != 1. && scaleVar != 0. ) ATH_MSG_ERROR( "Unpredicted scale variation of Delta "<<scaleVar<<" sigmas!" );
 
-  //::: Retrieving scale corrections!
-  std::string scale_val;
-  //::: Check if FilesPath defined: if so override other configurations (advanced user setting, for debugging within MCP)
-  if ( m_FilesPath == "" ) {
-    if( m_Trel >= MCAST::Release::PreRec ) {
-      scale_val = PathResolverFindCalibFile( "MuonMomentumCorrections/Scale_" + m_algo + "_" + m_year + "_" + m_release + ".dat" );
+    if( m_scale_ID[muonInfo.detRegion] != -1 ) {
+      if( m_Trel >= MCAST::Release::Rel17_2_Sum13 ) {
+        scaleID = scaleVar > 0. ? m_scaleSystUp_ID[muonInfo.detRegion] : m_scaleSystDw_ID[muonInfo.detRegion];
+      }
+      else {
+        scaleID = m_scaleSyst_ID[muonInfo.detRegion];
+      }
+      scaleID = m_scale_ID[muonInfo.detRegion] + scaleVar*scaleID;
     }
-    else if( m_year == "Data11" && m_Trel >= MCAST::Release::Rel17_2_Sum13 ) {
-      scale_val = PathResolverFindCalibFile( "MuonMomentumCorrections/Data11_Scale_values_" + m_algo + "_" + m_release + ".dat" );
+    else {
+      scaleID = ( m_Trel >= MCAST::Release::Rel17_2_Sum13 ) ? 0. : 1.;
+    }
+    if( m_scale_MS[muonInfo.detRegion] != -1 ) {
+      if( m_Trel >= MCAST::Release::Rel17_2_Sum13 ) {
+        scaleMS = scaleVar > 0. ? m_scaleSystUp_MS[muonInfo.detRegion] : m_scaleSystDw_MS[muonInfo.detRegion];
+        enLossCorrMS = scaleVar > 0. ? m_enLossSystUp_MS[muonInfo.detRegion] : m_enLossSystDw_MS[muonInfo.detRegion];
+      }
+      else {
+        scaleMS = m_scaleSyst_MS[muonInfo.detRegion];
+      }
+      scaleMS =  m_scale_MS[muonInfo.detRegion] + scaleVar*scaleMS;
+      if( true ) enLossCorrMS = m_enLoss_MS[muonInfo.detRegion] + scaleVar*enLossCorrMS;
     }
     else {
-      scale_val = PathResolverFindCalibFile( "MuonMomentumCorrections/Scale_values_" + m_algo + "_" + m_release + ".dat" );
+      scaleMS = ( m_Trel >= MCAST::Release::Rel17_2_Sum13 ) ? 0. : 1.;
     }
-  }
-  else {
-    scale_val = m_FilesPath + "Scale_" + m_algo + "_" + m_year + "_" + m_release + ".dat";
-  }
-  //if ( m_Trel >= MCAST::Release::PreRec ) scale_val = "Scales_Test.dat";
-  ATH_MSG_DEBUG( "Checking Files - Scales: " << scale_val );
-
-  InValues.open( scale_val.c_str() );
-  int i = 0;
-  if( !InValues.good() ) {
-    ATH_MSG_ERROR( "File " << scale_val <<" not found!!" );
-    return StatusCode::FAILURE;
-  }
-  else {
-    while( InValues.good() && i < m_nb_regions ) {
-      tmpval = 0;
-      if( i == 0 ) {
-        getline( InValues, tmpname );
+    if( m_Trel >= MCAST::Release::Rel17_2_Sum13 ) { //NB: MCAST::Release::Rel17_2_Sum13 has scale parametrized around 0, not 1!!
+      scaleID += 1.;
+      scaleMS += 1.;
+    }
+    if( m_scale_CB[muonInfo.detRegion] != -1 ) {
+      scaleCB = m_scale_CB[muonInfo.detRegion] + scaleVar * m_scaleSyst_CB[muonInfo.detRegion];
+    }
+    else {
+      if( muonInfo.ptms ) scaleCB = ( scaleID * muonInfo.weightID + ( scaleMS + enLossCorrMS / muonInfo.ptms ) * muonInfo.weightMS );
+      else         scaleCB = scaleID; // was scaleID * muonInfo.weightID
+    }
+
+    double tmpDelta = 1.;
+    double outPtID = muonInfo.ptid, outPtMS = muonInfo.ptms, outPtCB = muonInfo.ptcb;
+    if( DetType == MCAST::DetectorType::ID ) {
+      ATH_MSG_VERBOSE( "Checking s1_ID = " << scaleID );
+      ATH_MSG_VERBOSE( "Double-Checking outPtID = " << outPtID << " at first..." );
+      if( outPtID == 0. ) return outPtID;
+      //Load the ID scale and smearing that you will use
+      ATH_MSG_VERBOSE( "Double-Checking int( inSmearID ) = " << int( inSmearID ) );
+      ATH_MSG_VERBOSE( "Double-Checking DEFAULT_INIT_VAL = " << DEFAULT_INIT_VAL );
+      tmpDelta = ( int( inSmearID ) == DEFAULT_INIT_VAL ) ? 1. + muonInfo.smearDeltaID : 1. + inSmearID;
+      ATH_MSG_VERBOSE( "Double-Checking inSmearID = " << inSmearID );
+      ATH_MSG_VERBOSE( "Double-Checking muonInfo.smearDeltaID = " << muonInfo.smearDeltaID );
+      ATH_MSG_VERBOSE( "Double-Checking tmpDelta = " << tmpDelta );
+      if( m_Trel < MCAST::Release::Rel17_2_Sum13 ) {
+        if( m_Tsmear == MCAST::SmearingType::Pt )  outPtID = outPtID * tmpDelta;
+        if( m_Tsmear == MCAST::SmearingType::QoverPt ) outPtID = ( tmpDelta == 0 ) ? MCAST_MAX_PT : outPtID / tmpDelta;
       }
+      outPtID = ScaleApply( std::fabs(outPtID), scaleID, 0., muonInfo );
       if( m_Trel >= MCAST::Release::Rel17_2_Sum13 ) {
-        //These have a different order and Up/Dw split sys
-        InValues>>tmpval;
-        m_scale_ID.push_back( tmpval );
-        InValues>>tmpval;
-        m_enLoss_MS.push_back( tmpval );
-        InValues>>tmpval;
-        m_scale_MS.push_back( tmpval );
-        InValues>>tmpval;
-        m_scaleSystUp_ID.push_back( tmpval );
-        InValues>>tmpval;
-        m_enLossSystUp_MS.push_back( tmpval );
-        InValues>>tmpval;
-        m_scaleSystUp_MS.push_back( tmpval );
-        InValues>>tmpval;
-        m_scaleSystDw_ID.push_back( tmpval );
-        InValues>>tmpval;
-        m_enLossSystDw_MS.push_back( tmpval );
-        InValues>>tmpval;
-        m_scaleSystDw_MS.push_back( tmpval );
+        if( m_Tsmear == MCAST::SmearingType::Pt )  outPtID = outPtID * tmpDelta;
+        if( m_Tsmear == MCAST::SmearingType::QoverPt ) outPtID = ( tmpDelta == 0 ) ? MCAST_MAX_PT : outPtID / tmpDelta;
+      }
+      return outPtID;
+    }
+    if( DetType == MCAST::DetectorType::MS ) {
+      ATH_MSG_VERBOSE( "Checking s0_MS = " << enLossCorrMS );
+      ATH_MSG_VERBOSE( "Checking s1_MS = " << scaleMS );
+      ATH_MSG_VERBOSE( "Double-Checking outPtMS = " << outPtMS << " at first..." );
+      if( outPtMS == 0. ) return outPtMS;
+      //Load the MS scale and smearing that you will use
+      ATH_MSG_VERBOSE( "Double-Checking int( inSmearMS ) = " << int( inSmearMS ) );
+      ATH_MSG_VERBOSE( "Double-Checking DEFAULT_INIT_VAL = " << DEFAULT_INIT_VAL );
+      tmpDelta = ( int( inSmearMS ) == DEFAULT_INIT_VAL ) ? 1. + muonInfo.smearDeltaMS : 1. + inSmearMS;
+      ATH_MSG_VERBOSE( "Double-Checking inSmearMS = " << inSmearMS );
+      ATH_MSG_VERBOSE( "Double-Checking muonInfo.smearDeltaMS = " << muonInfo.smearDeltaMS );
+      ATH_MSG_VERBOSE( "Double-Checking tmpDelta = " << tmpDelta );
+      //In these releases the smearing was applied to the pt before the scale
+      if( m_Trel < MCAST::Release::Rel17_2_Sum13 ) {
+        if( m_Tsmear == MCAST::SmearingType::Pt )  outPtMS = outPtMS * tmpDelta;
+        if( m_Tsmear == MCAST::SmearingType::QoverPt ) outPtMS = ( tmpDelta == 0 ) ? MCAST_MAX_PT : outPtMS / tmpDelta;
+      }
+      ATH_MSG_VERBOSE( "Double-Checking outPtMS = " << outPtMS << " at second..." );
+      outPtMS = ScaleApply( std::fabs( outPtMS ), scaleMS, enLossCorrMS, muonInfo );
+      ATH_MSG_VERBOSE( "Double-Checking outPtMS = " << outPtMS << " at third..." );
+      if( m_Trel >= MCAST::Release::Rel17_2_Sum13 ) {
+        if( m_Tsmear == MCAST::SmearingType::Pt )  outPtMS = outPtMS * tmpDelta;
+        if( m_Tsmear == MCAST::SmearingType::QoverPt ) outPtMS = ( tmpDelta == 0 ) ? MCAST_MAX_PT : outPtMS / tmpDelta;
+      }
+      ATH_MSG_VERBOSE( "Double-Checking outPtMS = " << outPtMS << " at fourth..." );
+      return outPtMS;
+    }
+    if( DetType == MCAST::DetectorType::CB ) {
+      if( int( inSmearID ) != DEFAULT_INIT_VAL && int( inSmearMS ) != DEFAULT_INIT_VAL ) {
+        tmpDelta = 1. + inSmearID * muonInfo.weightID + inSmearMS * muonInfo.weightMS;
+      }
+      else if( int( inSmearID ) == DEFAULT_INIT_VAL && int( inSmearMS ) == DEFAULT_INIT_VAL ) {
+        tmpDelta = 1. + muonInfo.smearDeltaCB;
       }
       else {
-        m_enLoss_MS.push_back( 0. );
-        m_enLossSyst_MS.push_back( 0. );
-        InValues>>tmpval;
-        m_scale_ID.push_back( tmpval );
-        InValues>>tmpval;
-        m_scaleSyst_ID.push_back( tmpval );
-        InValues>>tmpval;
-        m_scale_MS.push_back( tmpval );
-        InValues>>tmpval;
-        m_scaleSyst_MS.push_back( tmpval );
       }
-      //CB is always on the cfg file although rarely used
-      InValues>>tmpval;
-      m_scale_CB.push_back( tmpval );
-      InValues>>tmpval;
-      m_scaleSyst_CB.push_back( tmpval );
-      i++;
+      //In these releases the smearing was applied to the pt before the scale
+      if( m_Trel < MCAST::Release::Rel17_2_Sum13 ) {
+        if( m_Tsmear == MCAST::SmearingType::Pt )  outPtCB = outPtCB * tmpDelta;
+        if( m_Tsmear == MCAST::SmearingType::QoverPt ) outPtCB = ( tmpDelta == 0 ) ? MCAST_MAX_PT : outPtCB / tmpDelta;
+      }
+
+      outPtCB = ScaleApply( std::fabs(outPtCB), scaleCB, 0., muonInfo );
+      if( m_Trel >= MCAST::Release::Rel17_2_Sum13 ) {
+        if( m_Tsmear == MCAST::SmearingType::Pt )  outPtCB = outPtCB * tmpDelta;
+        if( m_Tsmear == MCAST::SmearingType::QoverPt ) outPtCB = ( tmpDelta == 0 ) ? MCAST_MAX_PT : outPtCB / tmpDelta;
+      }
+
+      return outPtCB;
     }
+    return 0.;
+
   }
-  InValues.close();
-  InValues.clear();
- 
-  //::: Retrieving data values
-  std::string data_val;
-  //::: Check if FilesPath defined: if so override other configurations (advanced user setting, for debugging within MCP)
-  if ( m_FilesPath == "" ) {
-    if( m_Trel >= MCAST::Release::PreRec ) {
-      data_val = PathResolverFindCalibFile( "MuonMomentumCorrections/Smearing_" + m_algo + "_" + m_year + "_" + m_release + ".dat" );
+
+  StatusCode MuonCalibrationAndSmearingTool::FillValues() {
+    ATH_MSG_VERBOSE( "Initializing lookup tables [FillValues()] : "<<m_algo<<"   "<<m_year<<"   "<<m_release );
+    Clean();
+    double tmpval;
+    std::string tmpname;
+    std::ifstream InValues;
+
+    // Retrieving scale corrections!
+    std::string scale_val;
+    // Check if FilesPath defined: if so override other configurations (advanced user setting, for debugging within MCP)
+    if ( m_FilesPath == "" ) {
+      if( m_Trel >= MCAST::Release::PreRec ) {
+        scale_val = PathResolverFindCalibFile( "MuonMomentumCorrections/Scale_" + m_algo + "_" + m_year + "_" + m_release + ".dat" );
+      }
+      else if( m_year == "Data11" && m_Trel >= MCAST::Release::Rel17_2_Sum13 ) {
+        scale_val = PathResolverFindCalibFile( "MuonMomentumCorrections/Data11_Scale_values_" + m_algo + "_" + m_release + ".dat" );
+      }
+      else {
+        scale_val = PathResolverFindCalibFile( "MuonMomentumCorrections/Scale_values_" + m_algo + "_" + m_release + ".dat" );
+      }
     }
     else {
-      data_val = PathResolverFindCalibFile( "MuonMomentumCorrections/" + m_year + "_values_" + m_algo + "_" + m_release + ".dat" ); 
+      scale_val = m_FilesPath + "Scale_" + m_algo + "_" + m_year + "_" + m_release + ".dat";
     }
-  }
-  else {
-    data_val = m_FilesPath + "Smearing_" + m_algo + "_" + m_year + "_" + m_release + ".dat";
-  }
-  //if ( m_Trel >= MCAST::Release::Test ) data_val = "Smearings_Test.dat";
-  ATH_MSG_DEBUG( "Checking Files - Data: " << data_val );
-
-  InValues.open( data_val.c_str() );
-  i = 0;
-  if( !InValues.good() ) {
-    ATH_MSG_ERROR( "File " << data_val << " not found!!" );
-    return StatusCode::FAILURE;
-  }
-  else {
-    while( InValues.good() && i < m_nb_regions ) {
-      tmpval = 0;
-      if( i == 0 ) {
-        getline( InValues,tmpname );
-      }
-      InValues>>tmpval;
-      m_p1_ID.push_back( tmpval );
-      InValues>>tmpval;
-      m_p2_ID.push_back( tmpval );
-      InValues>>tmpval;
-      m_p2_ID_TAN.push_back( tmpval );
-      InValues>>tmpval;
-      if( m_Trel >= MCAST::Release::Rel17_2_Sum13 ) {
-        m_p0_MS.push_back( tmpval );
+    ATH_MSG_DEBUG( "Checking Files - Scales: " << scale_val );
+
+    InValues.open( scale_val.c_str() );
+    int i = 0;
+    if( !InValues.good() ) {
+      ATH_MSG_ERROR( "File " << scale_val <<" not found!!" );
+      return StatusCode::FAILURE;
+    }
+    else {
+      while( InValues.good() && i < m_nb_regions ) {
+        tmpval = 0;
+        if( i == 0 ) {
+          getline( InValues, tmpname );
+        }
+        if( m_Trel >= MCAST::Release::Rel17_2_Sum13 ) {
+          //These have a different order and Up/Dw split sys
+          InValues>>tmpval;
+          m_scale_ID.push_back( tmpval );
+          InValues>>tmpval;
+          m_enLoss_MS.push_back( tmpval );
+          InValues>>tmpval;
+          m_scale_MS.push_back( tmpval );
+          InValues>>tmpval;
+          m_scaleSystUp_ID.push_back( tmpval );
+          InValues>>tmpval;
+          m_enLossSystUp_MS.push_back( tmpval );
+          InValues>>tmpval;
+          m_scaleSystUp_MS.push_back( tmpval );
+          InValues>>tmpval;
+          m_scaleSystDw_ID.push_back( tmpval );
+          InValues>>tmpval;
+          m_enLossSystDw_MS.push_back( tmpval );
+          InValues>>tmpval;
+          m_scaleSystDw_MS.push_back( tmpval );
+        }
+        else {
+          m_enLoss_MS.push_back( 0. );
+          m_enLossSyst_MS.push_back( 0. );
+          InValues>>tmpval;
+          m_scale_ID.push_back( tmpval );
+          InValues>>tmpval;
+          m_scaleSyst_ID.push_back( tmpval );
+          InValues>>tmpval;
+          m_scale_MS.push_back( tmpval );
+          InValues>>tmpval;
+          m_scaleSyst_MS.push_back( tmpval );
+        }
+        //CB is always on the cfg file although rarely used
         InValues>>tmpval;
+        m_scale_CB.push_back( tmpval );
+        InValues>>tmpval;
+        m_scaleSyst_CB.push_back( tmpval );
+        i++;
+      }
+    }
+    InValues.close();
+    InValues.clear();
+
+    // Retrieving data values
+    std::string data_val;
+    // Check if FilesPath defined: if so override other configurations (advanced user setting, for debugging within MCP)
+    if ( m_FilesPath == "" ) {
+      if( m_Trel >= MCAST::Release::PreRec ) {
+        data_val = PathResolverFindCalibFile( "MuonMomentumCorrections/Smearing_" + m_algo + "_" + m_year + "_" + m_release + ".dat" );
       }
       else {
-        m_p0_MS.push_back( 0 );
+        data_val = PathResolverFindCalibFile( "MuonMomentumCorrections/" + m_year + "_values_" + m_algo + "_" + m_release + ".dat" );
       }
-      m_p1_MS.push_back( tmpval );
-      InValues>>tmpval;
-      m_p2_MS.push_back( tmpval );
-      //Syst and stat uncertianties: they are split and symmetrized before Rel17.2Sum13, after
-      // that, the stat is added in ^2 and they are split in Up/Dw
-      if( m_Trel >= MCAST::Release::Rel17_2_Sum13 ) {
-        InValues>>tmpval;
-        m_SUp_p1_ID.push_back( tmpval );
-        InValues>>tmpval;
-        m_SUp_p2_ID.push_back( tmpval );
-        InValues>>tmpval;
-        m_SUp_p2_ID_TAN.push_back( tmpval );
-        InValues>>tmpval;
-        m_SUp_p0_MS.push_back( tmpval );
-        InValues>>tmpval;
-        m_SUp_p1_MS.push_back( tmpval );
-        InValues>>tmpval;
-        m_SUp_p2_MS.push_back( tmpval );
-        InValues>>tmpval;
-        m_SDw_p1_ID.push_back( tmpval );
+    }
+    else {
+      data_val = m_FilesPath + "Smearing_" + m_algo + "_" + m_year + "_" + m_release + ".dat";
+    }
+    ATH_MSG_DEBUG( "Checking Files - Data: " << data_val );
+
+    InValues.open( data_val.c_str() );
+    i = 0;
+    if( !InValues.good() ) {
+      ATH_MSG_ERROR( "File " << data_val << " not found!!" );
+      return StatusCode::FAILURE;
+    }
+    else {
+      while( InValues.good() && i < m_nb_regions ) {
+        tmpval = 0;
+        if( i == 0 ) {
+          getline( InValues,tmpname );
+        }
         InValues>>tmpval;
-        m_SDw_p2_ID.push_back( tmpval );
+        m_p1_ID.push_back( tmpval );
         InValues>>tmpval;
-        m_SDw_p2_ID_TAN.push_back( tmpval );
+        m_p2_ID.push_back( tmpval );
         InValues>>tmpval;
-        m_SDw_p0_MS.push_back( tmpval );
+        m_p2_ID_TAN.push_back( tmpval );
         InValues>>tmpval;
-        m_SDw_p1_MS.push_back( tmpval );
+        if( m_Trel >= MCAST::Release::Rel17_2_Sum13 ) {
+          m_p0_MS.push_back( tmpval );
+          InValues>>tmpval;
+        }
+        else {
+          m_p0_MS.push_back( 0 );
+        }
+        m_p1_MS.push_back( tmpval );
         InValues>>tmpval;
-        m_SDw_p2_MS.push_back( tmpval );
+        m_p2_MS.push_back( tmpval );
+        //Syst and stat uncertianties: they are split and symmetrized before Rel17.2Sum13, after
+        // that, the stat is added in ^2 and they are split in Up/Dw
+        if( m_Trel >= MCAST::Release::Rel17_2_Sum13 ) {
+          InValues>>tmpval;
+          m_SUp_p1_ID.push_back( tmpval );
+          InValues>>tmpval;
+          m_SUp_p2_ID.push_back( tmpval );
+          InValues>>tmpval;
+          m_SUp_p2_ID_TAN.push_back( tmpval );
+          InValues>>tmpval;
+          m_SUp_p0_MS.push_back( tmpval );
+          InValues>>tmpval;
+          m_SUp_p1_MS.push_back( tmpval );
+          InValues>>tmpval;
+          m_SUp_p2_MS.push_back( tmpval );
+          InValues>>tmpval;
+          m_SDw_p1_ID.push_back( tmpval );
+          InValues>>tmpval;
+          m_SDw_p2_ID.push_back( tmpval );
+          InValues>>tmpval;
+          m_SDw_p2_ID_TAN.push_back( tmpval );
+          InValues>>tmpval;
+          m_SDw_p0_MS.push_back( tmpval );
+          InValues>>tmpval;
+          m_SDw_p1_MS.push_back( tmpval );
+          InValues>>tmpval;
+          m_SDw_p2_MS.push_back( tmpval );
+        }
+        else {
+          m_E_p0_MS.push_back( 0 );
+          m_S_p0_MS.push_back( 0 );
+          //Stat
+          InValues>>tmpval;
+          m_E_p1_ID.push_back( tmpval );
+          InValues>>tmpval;
+          m_E_p2_ID.push_back( tmpval );
+          InValues>>tmpval;
+          m_E_p2_ID_TAN.push_back( tmpval );
+          InValues>>tmpval;
+          m_E_p1_MS.push_back( tmpval );
+          InValues>>tmpval;
+          m_E_p2_MS.push_back( tmpval );
+          /*systematic*/
+          InValues>>tmpval;
+          m_S_p1_ID.push_back( tmpval );
+          InValues>>tmpval;
+          m_S_p2_ID.push_back( tmpval );
+          InValues>>tmpval;
+          m_S_p2_ID_TAN.push_back( tmpval );
+          InValues>>tmpval;
+          m_S_p1_MS.push_back( tmpval );
+          InValues>>tmpval;
+          m_S_p2_MS.push_back( tmpval );
+        }
+      }
+    }
+    InValues.close();
+    InValues.clear();
+
+    // Retrieving MC values
+    std::string mc_val;
+    // Check if FilesPath defined: if so override other configurations (advanced user setting, for debugging within MCP)
+    if ( m_FilesPath == "" ) {
+      if ( m_Trel >= MCAST::Release::PreRec ) {
+        mc_val = PathResolverFindCalibFile( "MuonMomentumCorrections/MC_values_" + m_algo + "_" + m_year + "_" + m_release + ".dat" );
+      }
+      else if ( m_Trel >= MCAST::Release::PreRec ) {
+        mc_val = PathResolverFindCalibFile( "MuonMomentumCorrections/MC_values_" + m_algo + "_Rel17.2Sum13.dat" );
       }
       else {
-        m_E_p0_MS.push_back( 0 );
-        m_S_p0_MS.push_back( 0 );
-        //Stat
-        InValues>>tmpval;
-        m_E_p1_ID.push_back( tmpval );
-        InValues>>tmpval;
-        m_E_p2_ID.push_back( tmpval );
-        InValues>>tmpval;
-        m_E_p2_ID_TAN.push_back( tmpval );
-        InValues>>tmpval;
-        m_E_p1_MS.push_back( tmpval );
+        mc_val = PathResolverFindCalibFile( "MuonMomentumCorrections/MC_values_" + m_algo + "_" + m_release + ".dat" );
+      }
+    }
+    else {
+      mc_val = m_FilesPath + "MC_values_" + m_algo + "_Rel17.2Sum13.dat";
+    }
+    ATH_MSG_DEBUG( "Checking Files - MC: " << mc_val );
+
+    InValues.open( mc_val.c_str() );
+    i = 0;
+    if( !InValues.good() ) {
+      ATH_MSG_ERROR( "File " << mc_val << " not found!!" );
+      return StatusCode::FAILURE;
+    }
+    else {
+      while( InValues.good() && i<m_nb_regions ) {
+        tmpval = 0;
+        if( i == 0 ) {
+          getline( InValues,tmpname );
+        }
         InValues>>tmpval;
-        m_E_p2_MS.push_back( tmpval );
-        /*systematic*/
+        m_MC_p1_ID.push_back( tmpval );
         InValues>>tmpval;
-        m_S_p1_ID.push_back( tmpval );
+        m_MC_p2_ID.push_back( tmpval );
         InValues>>tmpval;
-        m_S_p2_ID.push_back( tmpval );
+        m_MC_p2_ID_TAN.push_back( tmpval );
         InValues>>tmpval;
-        m_S_p2_ID_TAN.push_back( tmpval );
+        m_MC_p0_MS.push_back( tmpval );
         InValues>>tmpval;
-        m_S_p1_MS.push_back( tmpval );
+        m_MC_p1_MS.push_back( tmpval );
         InValues>>tmpval;
-        m_S_p2_MS.push_back( tmpval );
+        m_MC_p2_MS.push_back( tmpval );
       }
     }
-  }
-  InValues.close();
-  InValues.clear();
+    InValues.close();
+    InValues.clear();
 
-  //::: Retrieving MC values
-  std::string mc_val;
-  //::: Check if FilesPath defined: if so override other configurations (advanced user setting, for debugging within MCP)
-  if ( m_FilesPath == "" ) {
-    if ( m_Trel >= MCAST::Release::PreRec ) {
-      mc_val = PathResolverFindCalibFile( "MuonMomentumCorrections/MC_values_" + m_algo + "_" + m_year + "_" + m_release + ".dat" );
-    }
-    else if ( m_Trel >= MCAST::Release::PreRec ) {
-      mc_val = PathResolverFindCalibFile( "MuonMomentumCorrections/MC_values_" + m_algo + "_Rel17.2Sum13.dat" );
-    }
-    else {
-      mc_val = PathResolverFindCalibFile( "MuonMomentumCorrections/MC_values_" + m_algo + "_" + m_release + ".dat" );
-    }
-  }
-  else {
-    mc_val = m_FilesPath + "MC_values_" + m_algo + "_Rel17.2Sum13.dat";
-  }
-  ATH_MSG_DEBUG( "Checking Files - MC: " << mc_val );
-  
-  InValues.open( mc_val.c_str() );
-  i = 0;
-  if( !InValues.good() ) {
-    ATH_MSG_ERROR( "File " << mc_val << " not found!!" );
-    return StatusCode::FAILURE;
-  }
-  else {
-    while( InValues.good() && i<m_nb_regions ) {
-      tmpval = 0;
-      if( i == 0 ) {
-        getline( InValues,tmpname );
-      }
-      InValues>>tmpval;
-      m_MC_p1_ID.push_back( tmpval );
-      InValues>>tmpval;
-      m_MC_p2_ID.push_back( tmpval );
-      InValues>>tmpval;
-      m_MC_p2_ID_TAN.push_back( tmpval );
-      InValues>>tmpval;
-      m_MC_p0_MS.push_back( tmpval );
-      InValues>>tmpval;
-      m_MC_p1_MS.push_back( tmpval );
-      InValues>>tmpval;
-      m_MC_p2_MS.push_back( tmpval );
-    }
-  }
-  InValues.close();
-  InValues.clear();
-  
-  return StatusCode::SUCCESS;
+    return StatusCode::SUCCESS;
 
-}
-
-int MuonCalibrationAndSmearingTool::GetScaleRegion( const xAOD::Muon& mu ) const {
-
-  if( m_scaleBins.empty() ) {
-    return -1;
-  }
-  double min = m_scaleBins[0];
-  double max = m_scaleBins[m_scaleBins.size()-1];
-  if( mu.eta()<min ) {
-    return 0;
-  }
-  if( mu.eta()>=max ) {
-    return m_scaleBins.size() - 1;
   }
 
-  std::vector<double>::const_iterator lb = lower_bound( m_scaleBins.begin(),m_scaleBins.end(),mu.eta()+1e-9 ); // [first,last)
-  return( std::min( static_cast<int>( distance( m_scaleBins.begin(),lb ) ) , static_cast<int>( m_scaleBins.size()-1 ) ) );
-
-}
+  double MuonCalibrationAndSmearingTool::GetSmearing( int DetType, InfoHelper& muonInfo ) const {
 
-double MuonCalibrationAndSmearingTool::GetSmearing( const Vars& vars,
-                                                    int DetType, const xAOD::Muon& mu ) const
-{
-
-  bool useTan2 = true;
-  if ( m_Trel >= MCAST::Release::PreRec && m_Trel < MCAST::Release::Rec_2015_11_15 ) useTan2 = false; 
-  if ( vars.m_detRegion < 0 || vars.m_detRegion >= m_nb_regions ) return 0; //++++++ HOW TO IMPROVE THIS CHECK?!
-  double smear = 0.;
-  if ( DetType == MCAST::DetectorType::MS ) {
-    if( vars.m_ptms == 0 ) {
-      return 0.;
-    }
-    else {
-      smear = m_p0_MS[vars.m_detRegion]*vars.m_g0/vars.m_ptms + m_p1_MS[vars.m_detRegion]*vars.m_g1 + m_p2_MS[vars.m_detRegion]*vars.m_g2*vars.m_ptms;
-      return smear;
-    }
-  }
-  else if( DetType == MCAST::DetectorType::ID ) {
-    if( m_Trel >= MCAST::Release::Rec_2015_11_15 ) {
-      float additional_weight = 1.;
-      ATH_MSG_VERBOSE( "mu.eta() = " << mu.eta() << ",  abs( mu.eta() ) = " << std::abs( mu.eta() ) << ",  fabs( mu.eta() ) = " << fabs( mu.eta() ) );  
-      ATH_MSG_VERBOSE( "Case 0: useTan2 && abs( mu.eta() ) > 2 = " << useTan2 << " && " << ( std::abs( mu.eta() ) > 2 ) );  
-      if ( useTan2 && fabs( mu.eta() ) > 2 ) {
-        ATH_MSG_VERBOSE( "Case 1: Using p1ID = " << m_p1_ID[vars.m_detRegion] << " and p2ID = " << m_p2_ID[vars.m_detRegion] );
-        additional_weight = sinh( mu.eta() ) * sinh( mu.eta() );
-      } 
-      else ATH_MSG_VERBOSE( "Case 2: Using p1ID = " << m_p1_ID[vars.m_detRegion] << " and p2ID = " << m_p2_ID[vars.m_detRegion] );
-      smear = m_p1_ID[vars.m_detRegion]*vars.m_g3 + m_p2_ID[vars.m_detRegion]*vars.m_g4*vars.m_ptid*additional_weight;
-      return smear;
+    bool useTan2 = true;
+    if ( m_Trel >= MCAST::Release::PreRec && m_Trel < MCAST::Release::Rec_2015_11_15 ) useTan2 = false;
+    if ( muonInfo.detRegion < 0 || muonInfo.detRegion >= m_nb_regions ) return 0; //++++++ HOW TO IMPROVE THIS CHECK?!
+    double smear = 0.;
+    if ( DetType == MCAST::DetectorType::MS ) {
+      if( muonInfo.ptms == 0 ) {
+        return 0.;
+      }
+      else {
+        smear = m_p0_MS[muonInfo.detRegion]*muonInfo.g0/muonInfo.ptms + m_p1_MS[muonInfo.detRegion]*muonInfo.g1 + m_p2_MS[muonInfo.detRegion]*muonInfo.g2*muonInfo.ptms;
+        return smear;
+      }
     }
-    else {
-      if ( useTan2 && m_p2_ID_TAN[vars.m_detRegion] != 0. ) {
-        ATH_MSG_VERBOSE( "Case 3: Using p1ID = " << m_p1_ID[vars.m_detRegion] << " and p2ID = " << m_p2_ID[vars.m_detRegion] );
-        smear = m_p1_ID[vars.m_detRegion]*vars.m_g3 + m_p2_ID_TAN[vars.m_detRegion]*vars.m_g4*vars.m_ptid*sinh( mu.eta() )*sinh( mu.eta() );
+    else if( DetType == MCAST::DetectorType::ID ) {
+      if( m_Trel >= MCAST::Release::Rec_2015_11_15 ) {
+        float additional_weight = 1.;
+        ATH_MSG_VERBOSE( "muonInfo.eta = " << muonInfo.eta << ",  abs( muonInfo.eta ) = " << std::abs( muonInfo.eta ) << ",  fabs( muonInfo.eta ) = " << std::fabs( muonInfo.eta ) );
+        ATH_MSG_VERBOSE( "Case 0: useTan2 && abs( muonInfo.eta ) > 2 = " << useTan2 << " && " << ( std::abs( muonInfo.eta ) > 2 ) );
+        if ( useTan2 && std::fabs( muonInfo.eta ) > 2 ) {
+          ATH_MSG_VERBOSE( "Case 1: Using p1ID = " << m_p1_ID[muonInfo.detRegion] << " and p2ID = " << m_p2_ID[muonInfo.detRegion] );
+          additional_weight = std::sinh( muonInfo.eta ) * std::sinh( muonInfo.eta );
+        }
+        else ATH_MSG_VERBOSE( "Case 2: Using p1ID = " << m_p1_ID[muonInfo.detRegion] << " and p2ID = " << m_p2_ID[muonInfo.detRegion] );
+        smear = m_p1_ID[muonInfo.detRegion]*muonInfo.g3 + m_p2_ID[muonInfo.detRegion]*muonInfo.g4*muonInfo.ptid*additional_weight;
         return smear;
       }
       else {
-        ATH_MSG_VERBOSE( "Case 4: Using p1ID = " << m_p1_ID[vars.m_detRegion] << " and p2ID = " << m_p2_ID[vars.m_detRegion] );
-        smear = m_p1_ID[vars.m_detRegion]*vars.m_g3 + m_p2_ID[vars.m_detRegion]*vars.m_g4*vars.m_ptid;
-        return smear;
+        if ( useTan2 && m_p2_ID_TAN[muonInfo.detRegion] != 0. ) {
+          ATH_MSG_VERBOSE( "Case 3: Using p1ID = " << m_p1_ID[muonInfo.detRegion] << " and p2ID = " << m_p2_ID[muonInfo.detRegion] );
+          smear = m_p1_ID[muonInfo.detRegion]*muonInfo.g3 + m_p2_ID_TAN[muonInfo.detRegion]*muonInfo.g4*muonInfo.ptid*std::sinh( muonInfo.eta )*sinh( muonInfo.eta );
+          return smear;
+        }
+        else {
+          ATH_MSG_VERBOSE( "Case 4: Using p1ID = " << m_p1_ID[muonInfo.detRegion] << " and p2ID = " << m_p2_ID[muonInfo.detRegion] );
+          smear = m_p1_ID[muonInfo.detRegion]*muonInfo.g3 + m_p2_ID[muonInfo.detRegion]*muonInfo.g4*muonInfo.ptid;
+          return smear;
+        }
       }
     }
+    else {
+      ATH_MSG_ERROR( " DetType not defined "<<DetType );
+    }
+    return 0.;
+
   }
-  else {
-    ATH_MSG_ERROR( " DetType not defined "<<DetType );
-  }
-  return 0.;
-
-}
-
-void MuonCalibrationAndSmearingTool::CalcCBWeights( Vars& vars,
-                                                    const xAOD::Muon& mu ) const
-{
-  //Calculate the weights of ID and MS used for CB. Two ways are implemented:
-  // - weight by ^2 of exp reso
-  // - from equation pT_CB = R(pT_ID) + (1-R)(pT_MS)
-  //(weights should be correctly normalized)
-  vars.m_weightID = 0.5;
-  vars.m_weightMS = 0.5;
-  if ( vars.m_detRegion < 0 || vars.m_detRegion >= m_nb_regions ) return;
-  if ( vars.m_ptcb == 0 ) {
-    ATH_MSG_WARNING( "Combined Pt = 0" );
-    return;
-  }
-  const bool doNotAddSmearing = true;
-  double SigmaMS = ExpectedResolution( vars, MCAST::DetectorType::MS, mu, doNotAddSmearing );
-  double SigmaID = ExpectedResolution( vars, MCAST::DetectorType::ID, mu, doNotAddSmearing );
-  double Nsigma = m_useNsigmaForICombine;
-  if( fabs( vars.m_ptcb - vars.m_ptms ) > Nsigma * SigmaMS * vars.m_ptcb || fabs( vars.m_ptcb - vars.m_ptid ) > Nsigma * SigmaID * vars.m_ptcb ) {
-    double R=1, Rplus;
-    if( fabs( vars.m_ptcb-vars.m_ptms ) == fabs( vars.m_ptcb - vars.m_ptid ) ) {
+
+  void MuonCalibrationAndSmearingTool::CalcCBWeights( xAOD::Muon& mu, InfoHelper& muonInfo ) const {
+
+    //Calculate the weights of ID and MS used for CB. Two ways are implemented:
+    // - weight by ^2 of exp reso
+    // - from equation pT_CB = R(pT_ID) + (1-R)(pT_MS)
+    //(weights should be correctly normalized)
+    muonInfo.weightID = 0.5;
+    muonInfo.weightMS = 0.5;
+    if ( muonInfo.detRegion < 0 || muonInfo.detRegion >= m_nb_regions ) return;
+    if ( muonInfo.ptcb == 0 ) {
+      ATH_MSG_DEBUG( "Combined Pt = 0" );
       return;
     }
-    if( fabs( vars.m_ptcb-vars.m_ptms ) != 0 && fabs( vars.m_ptcb-vars.m_ptms ) > fabs( vars.m_ptcb-vars.m_ptid ) ) {
-      R = ( vars.m_ptid - vars.m_ptcb )/( vars.m_ptcb - vars.m_ptms ); /* R~wMS/wID */
-      Rplus = 1 + R;
-      if ( Rplus != 0 && R > 0 ) {
-        vars.m_weightID = 1/Rplus;
-        vars.m_weightMS = R/Rplus;
-        return;
+    const bool doNotAddSmearing = true;
+    double SigmaMS = ExpectedResolution( MCAST::DetectorType::MS, mu, doNotAddSmearing );
+    double SigmaID = ExpectedResolution( MCAST::DetectorType::ID, mu, doNotAddSmearing );
+    double Nsigma = m_useNsigmaForICombine;
+    if( std::fabs( muonInfo.ptcb - muonInfo.ptms ) > Nsigma * SigmaMS * muonInfo.ptcb || std::fabs( muonInfo.ptcb - muonInfo.ptid ) > Nsigma * SigmaID * muonInfo.ptcb ) {
+      double R=1, Rplus;
+      if( std::fabs( muonInfo.ptcb-muonInfo.ptms ) == std::fabs( muonInfo.ptcb - muonInfo.ptid ) ) return; //This case returns weightID = weightMS = 0.5
+      if( std::fabs( muonInfo.ptcb-muonInfo.ptms ) != 0 && std::fabs( muonInfo.ptcb-muonInfo.ptms ) > std::fabs( muonInfo.ptcb-muonInfo.ptid ) ) {
+        R = ( muonInfo.ptid - muonInfo.ptcb )/( muonInfo.ptcb - muonInfo.ptms ); /* R~wMS/wID */
+        Rplus = 1 + R;
+        if ( Rplus != 0 && R > 0 ) {
+          muonInfo.weightID = 1/Rplus;
+          muonInfo.weightMS = R/Rplus;
+          return;
+        }
       }
-    }
-    if ( fabs( vars.m_ptcb-vars.m_ptid ) != 0 && fabs( vars.m_ptcb-vars.m_ptms ) < fabs( vars.m_ptcb-vars.m_ptid ) ) {
-      R = ( vars.m_ptms - vars.m_ptcb )/( vars.m_ptcb - vars.m_ptid ); /* R~wID/wMS */
-      Rplus = 1 + R;
-      if ( Rplus != 0 && R > 0 ) {
-        vars.m_weightID = R/Rplus;
-        vars.m_weightMS = 1/Rplus;
-        return;
+      if ( std::fabs( muonInfo.ptcb-muonInfo.ptid ) != 0 && std::fabs( muonInfo.ptcb-muonInfo.ptms ) < std::fabs( muonInfo.ptcb-muonInfo.ptid ) ) {
+        R = ( muonInfo.ptms - muonInfo.ptcb )/( muonInfo.ptcb - muonInfo.ptid ); /* R~wID/wMS */
+        Rplus = 1 + R;
+        if ( Rplus != 0 && R > 0 ) {
+          muonInfo.weightID = R/Rplus;
+          muonInfo.weightMS = 1/Rplus;
+          return;
+        }
       }
     }
-  }
 
-  double wMS = vars.m_ptms/vars.m_ptcb/pow(SigmaMS,2);
-  double wID = vars.m_ptid/vars.m_ptcb/pow(SigmaID,2);
-  vars.m_weightID = wID/(wMS + wID);
-  vars.m_weightMS = wMS/(wMS + wID);
-  return;
-}
+    
+    double wMS = muonInfo.ptms/muonInfo.ptcb/std::pow(SigmaMS,2);
+    double wID = muonInfo.ptid/muonInfo.ptcb/std::pow(SigmaID,2);
+    muonInfo.weightID =  wID/(wMS + wID);
+    muonInfo.weightMS =  wMS/(wMS + wID);
+    return;
 
-void MuonCalibrationAndSmearingTool::CleanScales() {
+  }
 
-  m_scaleBins.clear();
+  void MuonCalibrationAndSmearingTool::CleanScales() {
 
-}
-  
-  double MuonCalibrationAndSmearingTool::expectedResolution( const IVars& ivars,
-                                                             const std::string& DetType, const xAOD::Muon& mu, const bool mc  ) const {
-    return ExpectedResolution(ivars,DetType,mu,mc);
-  }
-  double MuonCalibrationAndSmearingTool::expectedResolution( const IVars& ivars,
-                                                             const int DetType, const xAOD::Muon& mu, const bool mc  ) const {
-    return ExpectedResolution(ivars,DetType,mu,mc);
-  }
-  
-  double MuonCalibrationAndSmearingTool::ExpectedResolution( const IVars& ivars,
-                                                             const std::string &DetType, const xAOD::Muon& mu, const bool mc ) const {
+    m_scaleBins.clear();
 
-  if( DetType == "MS" ) {
-    return ExpectedResolution( ivars, MCAST::DetectorType::MS, mu, mc );
-  }
-  else if( DetType == "ID" ) {
-    return ExpectedResolution( ivars, MCAST::DetectorType::ID, mu, mc );
-  }
-  else if( DetType == "CB" ) {
-    return ExpectedResolution( ivars, MCAST::DetectorType::CB, mu, mc );
-  }
-  else {
-    ATH_MSG_ERROR( "wrong DetType in input " << DetType );
-    return 0.;
   }
 
-}
-
-double MuonCalibrationAndSmearingTool::ExpectedResolution( const IVars& ivars,
-                                                           const int DetType, const xAOD::Muon& mu, const bool mc ) const
-{
-  const Vars& vars = static_cast<const Vars&> (ivars);
-
-  bool useTan2 = true;
-  /** do the average with the EXPECTED resolutions **/
-  if ( vars.m_detRegion<0 || vars.m_detRegion>=m_nb_regions ) return 0;
-  double expRes = 0.;
-  if ( DetType == MCAST::DetectorType::MS ) {
-    if (vars.m_ptms == 0) return 1e12;
-    double p0 = mc ? m_MC_p0_MS[vars.m_detRegion] : ( m_MC_p0_MS[vars.m_detRegion] + m_p0_MS[vars.m_detRegion] );
-    double p1 = mc ? m_MC_p1_MS[vars.m_detRegion] : ( m_MC_p1_MS[vars.m_detRegion] + m_p1_MS[vars.m_detRegion] );
-    double p2 = mc ? m_MC_p2_MS[vars.m_detRegion] : ( m_MC_p2_MS[vars.m_detRegion] + m_p2_MS[vars.m_detRegion] );
-    expRes =  sqrt( pow( p0/vars.m_ptms, 2 ) + pow( p1, 2 ) + pow( p2*vars.m_ptms ,2 ) );
-    return expRes; //+++++No SYS!!!
+  double MuonCalibrationAndSmearingTool::expectedResolution( const std::string& DetType, const xAOD::Muon& mu, const bool mc ) const {
+    // Expected resolution in data (or unsmeared MC if second argument is true)
+    return ExpectedResolution(DetType, mu, mc);
   }
-  else if ( DetType == MCAST::DetectorType::ID ) {
-    if ( vars.m_ptid == 0 ) ATH_MSG_DEBUG( "ptid == 0" );
-    double p1 = mc ? m_MC_p1_ID[vars.m_detRegion] : ( m_MC_p1_ID[vars.m_detRegion] + m_p1_ID[vars.m_detRegion] );
-    double p2 = mc ? m_MC_p2_ID[vars.m_detRegion] : ( m_MC_p2_ID[vars.m_detRegion] + m_p2_ID[vars.m_detRegion] );
-    if ( m_MC_p2_ID_TAN[vars.m_detRegion] != 0 && useTan2 ) {
-      p2 = mc ? m_MC_p2_ID_TAN[vars.m_detRegion] : ( m_MC_p2_ID_TAN[vars.m_detRegion] + m_p2_ID_TAN[vars.m_detRegion] );
-      p2 = p2*sinh( mu.eta() )*sinh( mu.eta() );
-    }
-    expRes = sqrt( pow( p1, 2 ) + pow( p2*vars.m_ptid ,2 ) );
-    return expRes; //+++++No SYS!!!
-  }
-  else if ( DetType == MCAST::DetectorType::CB ) {
-    // Due to complicated maths, the expected combined resolution
-    // is given by this equation (note: all sigmas are fractional uncertainties):
-    // sigma_CB = sqrt(2) * sigma_ID * sigma_MS * pTMS * pTID / {pTCB * sqrt({sigma_ID*pTID}^2 + {sigma_MS*pTMS}^2)}
-    // Do a little recursive calling to make things easier to read
-    // Turn these into *absolute* uncertainties to make life easier
-    double sigmaID = ExpectedResolution( vars, MCAST::DetectorType::ID, mu, mc ) * vars.m_ptid;
-    double sigmaMS = ExpectedResolution( vars, MCAST::DetectorType::MS, mu, mc ) * vars.m_ptms;
-    double denominator = ( vars.m_ptcb ) * sqrt( sigmaID*sigmaID + sigmaMS*sigmaMS );
-    return denominator ? sqrt( 2. ) * sigmaID * sigmaMS / denominator : 0.;
-  }
-  else {
-    ATH_MSG_ERROR( "wrong DetType in input "<<DetType );
-    return 0.;
+
+  double MuonCalibrationAndSmearingTool::expectedResolution( const int& DetType, const xAOD::Muon& mu, const bool mc ) const {
+    // Expected resolution in data (or unsmeared MC if second argument is true)
+    return ExpectedResolution(DetType, mu, mc);
   }
 
-}
-
-void MuonCalibrationAndSmearingTool::Clean() {
-
-  m_scale_ID.clear();
-  m_enLoss_MS.clear();
-  m_scale_MS.clear();
-  m_scale_CB.clear();
-  m_scaleSyst_ID.clear();
-  m_enLossSyst_MS.clear();
-  m_scaleSyst_MS.clear();
-  m_scaleSyst_CB.clear();
-  m_scaleSystUp_ID.clear();
-  m_enLossSystUp_MS.clear();
-  m_scaleSystUp_MS.clear();
-  m_scaleSystDw_ID.clear();
-  m_enLossSystDw_MS.clear();
-  m_scaleSystDw_MS.clear();
-  CleanScales();
-  m_p1_ID.clear();
-  m_p2_ID.clear();
-  m_p2_ID_TAN.clear();
-  m_p0_MS.clear();
-  m_p1_MS.clear();
-  m_p2_MS.clear();
-  m_E_p1_ID.clear();
-  m_E_p2_ID.clear();
-  m_E_p2_ID_TAN.clear();
-  m_E_p0_MS.clear();
-  m_E_p1_MS.clear();
-  m_E_p2_MS.clear();
-  m_S_p1_ID.clear();
-  m_S_p2_ID.clear();
-  m_S_p2_ID_TAN.clear();
-  m_S_p0_MS.clear();
-  m_S_p1_MS.clear();
-  m_S_p2_MS.clear();
-  m_SUp_p1_ID.clear();
-  m_SUp_p2_ID.clear();
-  m_SUp_p2_ID_TAN.clear();
-  m_SUp_p0_MS.clear();
-  m_SUp_p1_MS.clear();
-  m_SUp_p2_MS.clear();
-  m_SDw_p1_ID.clear();
-  m_SDw_p2_ID.clear();
-  m_SDw_p2_ID_TAN.clear();
-  m_SDw_p0_MS.clear();
-  m_SDw_p1_MS.clear();
-  m_SDw_p2_MS.clear();
-  m_MC_p1_ID.clear();
-  m_MC_p2_ID.clear();
-  m_MC_p2_ID_TAN.clear();
-  m_MC_p0_MS.clear();
-  m_MC_p1_MS.clear();
-  m_MC_p2_MS.clear();
-
-}
-
-void MuonCalibrationAndSmearingTool::PrintRegions() const {
-
-  if( m_doMacroRegions ) {
-    for( std::map<int, int>::const_iterator it = m_MacroRegionIdxMap.begin(); it!=m_MacroRegionIdxMap.end(); ++it ) {
-      int bReg = it->first, mReg = it->second;
-      ATH_MSG_INFO( "Base region n "<<bReg );
-      ATH_MSG_INFO( "phi_min="<<m_phi_min[bReg]<<", phi_max="<<m_phi_max[bReg] );
-      ATH_MSG_INFO( "eta_min="<<m_eta_min[bReg]<<", eta_max="<<m_eta_max[bReg] );
-      ATH_MSG_INFO( "included in Macro region N "<<mReg<<" with innerEta="<<m_MacroRegionInnerEta[mReg] );
+  double MuonCalibrationAndSmearingTool::ExpectedResolution( const std::string &DetType, const xAOD::Muon& mu, const bool mc ) const {
+    // Expected resolution in data (or unsmeared MC if second argument is true)
+    if( DetType == "MS" ) {
+      return ExpectedResolution( MCAST::DetectorType::MS, mu, mc );
     }
-  }
-  else {
-    for( int bReg=0; bReg<m_nb_regions; ++bReg ) {
-      ATH_MSG_INFO( "Base region n "<<bReg<<": phi_min="<<m_phi_min[bReg]<<", phi_max="<<m_phi_max[bReg] );
-      ATH_MSG_INFO( "eta_min="<<m_eta_min[bReg]<<", eta_max="<<m_eta_max[bReg] );
+    else if( DetType == "ID" ) {
+      return ExpectedResolution( MCAST::DetectorType::ID, mu, mc );
+    }
+    else if( DetType == "CB" ) {
+      return ExpectedResolution( MCAST::DetectorType::CB, mu, mc );
+    }
+    else {
+      ATH_MSG_ERROR( "The DetType that you entered is not allows - DetType = " << DetType );
+      return 0.;
     }
   }
 
-}
+  double MuonCalibrationAndSmearingTool::ExpectedResolution( const int DetType,const xAOD::Muon& mu, const bool mc ) const {
 
-unsigned int MuonCalibrationAndSmearingTool::GetNRegions() const {
+    // get the pt measurements from the xAOD::Muon object
 
-  if( m_doMacroRegions ) return m_MacroRegionName.size();
-  else return m_nb_regions;
+    double loc_ptid = 0;
+    double loc_ptms = 0;
+    double loc_ptcb = 0;
 
-}
+    // Set pt ID:
 
-StatusCode MuonCalibrationAndSmearingTool::Regions( std::string inRegionFile, int doMacroRegionsFlag ) {
+    ATH_MSG_VERBOSE( "Retrieving ElementLink to ID TrackParticle..." );
+    ATH_MSG_VERBOSE( "Setting Pt  [ID]: if no track available, set to 0..." );
+    ATH_MSG_VERBOSE( "mu.isAvailable< ElementLink< xAOD::TrackParticleContainer > >( \"inDetTrackParticleLink\" ) = " << mu.isAvailable< ElementLink< xAOD::TrackParticleContainer > >( "inDetTrackParticleLink" ) );
+    ATH_MSG_VERBOSE( "( mu.inDetTrackParticleLink() == nullptr ) = " << ( mu.inDetTrackParticleLink() == nullptr ) );
+    ATH_MSG_VERBOSE( "mu.inDetTrackParticleLink() = " << mu.inDetTrackParticleLink() );
+    ATH_MSG_VERBOSE( "( mu.inDetTrackParticleLink() ).isValid() = " << ( mu.inDetTrackParticleLink() ).isValid() );
 
-  m_eta_min.clear();
-  m_eta_max.clear();
-  m_phi_min.clear();
-  m_phi_max.clear();
-  m_loadNames = false;
-  m_doMacroRegions = false;
-  std::string tmpname;
-  double tmpval;
-  int i = 0;
-  std::ifstream inFile( inRegionFile.c_str() );
-  if( !inFile.good() ) {
-    ATH_MSG_ERROR( "File not good" );
-    return StatusCode::FAILURE;
-  }
-  else {
-    while( !inFile.eof() ) {
-      tmpval=0;
-      tmpname="";
-      if( i==0 ) {
-        getline( inFile,tmpname );
-        //Check if I am loading the name of the regions in the file
-        if( tmpname.find( "name" ) != std::string::npos && !m_loadNames ) m_loadNames = true;
-      }
-      else {
-        inFile>>tmpval;
-        if( inFile.eof() ) break; //this will break immediatly as soon as the new line is empty
-        m_eta_min.push_back( tmpval );
-        inFile>>tmpval;
-        m_eta_max.push_back( tmpval );
-        inFile>>tmpval;
-        m_phi_min.push_back( tmpval );
-        inFile>>tmpval;
-        m_phi_max.push_back( tmpval );
-        if( m_loadNames ) { //Fill the name vector only if you have them!
-          inFile>>tmpname;
-          m_names.push_back( tmpname );
-        }
-      }
-      ++i;
+    if( ( mu.inDetTrackParticleLink() ).isValid() ) {
+        const ElementLink< xAOD::TrackParticleContainer >& id_track = mu.inDetTrackParticleLink();
+        loc_ptid = ( !id_track ) ? 0. : ( *id_track )->pt() / 1000.;
     }
-  }
-  inFile.close();
-  m_nb_regions = ( int ) m_eta_min.size();
-  if( doMacroRegionsFlag ) { //In case I want macroRegions, I need to define the criteria here
-    m_doMacroRegions = true;
-    switch( doMacroRegionsFlag ) {
-    case 1:
-      //Collects all the Large and Small sectors if they belong to the same eta bin
-      CollectMacroRegionsSL();
-      break;
-    case 2:
-      //Large,Small sectors split plus Feet(12+14) and 11+15 sector split in Barrel
-      CollectMacroRegionsSL_SplitBAR();
-      break;
-    case 3:
-      //Collects all the Large and Small, Up and Down sectors if they belong to the same eta bin
-      CollectMacroRegionsSL_UpDn();
-      break;
-    case 4:
-      //Collects all the Large and Small, Up and Down sectors if they belong to the same eta bin
-      CollectSectors();
-      break;
-    default:
-      ATH_MSG_ERROR( "doMacroRegionFlag=" << doMacroRegionsFlag << " not defined!" );
-      return StatusCode::FAILURE;
+    else{
+      ATH_MSG_VERBOSE("The ID track link is not valid - setting pT(ID)=0");
+      loc_ptid = 0.;
+    }
+
+    // Set pt MS:
+
+    ATH_MSG_VERBOSE( "Retrieving ElementLink to MS TrackParticle..." );
+    ATH_MSG_VERBOSE( "Setting Pt  [MS]: if no track available, set to 0..." );
+    ATH_MSG_VERBOSE( "mu.isAvailable< ElementLink< xAOD::TrackParticleContainer > >( \"extrapolatedMuonSpectrometerTrackParticleLink\" ) = " << mu.isAvailable< ElementLink< xAOD::TrackParticleContainer > >( "extrapolatedMuonSpectrometerTrackParticleLink" ) );
+    ATH_MSG_VERBOSE( "( mu.extrapolatedMuonSpectrometerTrackParticleLink() == nullptr ) = " << ( mu.extrapolatedMuonSpectrometerTrackParticleLink() == nullptr ) );
+    ATH_MSG_VERBOSE( "mu.extrapolatedMuonSpectrometerTrackParticleLink() = " << mu.extrapolatedMuonSpectrometerTrackParticleLink() );
+    ATH_MSG_VERBOSE( "( mu.extrapolatedMuonSpectrometerTrackParticleLink() ).isValid() = " << ( mu.extrapolatedMuonSpectrometerTrackParticleLink() ).isValid() );
+    if( ( mu.extrapolatedMuonSpectrometerTrackParticleLink() ).isValid() ) {
+        const ElementLink< xAOD::TrackParticleContainer >& ms_track = mu.extrapolatedMuonSpectrometerTrackParticleLink();
+        loc_ptms = ( !ms_track ) ? 0. : ( *ms_track )->pt() / 1000.;
+    }
+    else{
+      ATH_MSG_VERBOSE("No link to extrapolatedMuonSpectrometerTrackParticleLink setting pT(MS)=0");
+      loc_ptms = 0.;
     }
-  }
-  return StatusCode::SUCCESS;
 
-}
+    // Set pt CB:
 
-int MuonCalibrationAndSmearingTool::GetRegion( const double eta, const double phi ) const {
+    ATH_MSG_VERBOSE( "Retrieving ElementLink to CB TrackParticle..." );
+    ATH_MSG_VERBOSE( "Setting Pt  [CB]: if no track available, set to 0..." );
+    ATH_MSG_VERBOSE( "mu.isAvailable< ElementLink< xAOD::TrackParticleContainer > >( \"primaryTrackParticleLink\" ) = " << mu.isAvailable< ElementLink< xAOD::TrackParticleContainer > >( "primaryTrackParticleLink" ) );
+    ATH_MSG_VERBOSE( "( mu.primaryTrackParticleLink() == nullptr ) = " << ( mu.primaryTrackParticleLink() == nullptr ) );
+    ATH_MSG_VERBOSE( "mu.primaryTrackParticleLink() = " << mu.primaryTrackParticleLink() );
+    ATH_MSG_VERBOSE( "( mu.primaryTrackParticleLink() ).isValid() = " << ( mu.primaryTrackParticleLink() ).isValid() );
 
-  ATH_MSG_VERBOSE( "eta,phi = " << eta << "," << phi );
-  int ret_k =-1;
-  for( int k=0; k < m_nb_regions; ++k ) {
-    if( eta>=m_eta_min[k] && eta<m_eta_max[k] ) {
-      if( m_phi_min[k] <= m_phi_max[k] ) { //Standard case
-        if( phi>=m_phi_min[k] && phi<m_phi_max[k] ) {
-          ret_k = k;
-          break;
-        }
-      }
-      else {  //Circular closure of Phi, min and max are excanged in the .dat file
-        if( phi>=m_phi_min[k] || phi<m_phi_max[k] ) {
-          ret_k = k;
-          break;
-        }
-      }
+    if( ( mu.primaryTrackParticleLink() ).isValid() ) {
+        const ElementLink< xAOD::TrackParticleContainer >& cb_track = mu.primaryTrackParticleLink();
+        loc_ptcb = ( !cb_track ) ? 0. : ( *cb_track )->pt() / 1000.;
+    }
+    else{
+      ATH_MSG_VERBOSE("The ID+MS combined track link is not valid - setting pT(ID)=0");
+      loc_ptcb = 0.;
     }
-  }
-  if( ret_k == -1 ) {
-    ATH_MSG_DEBUG( "Region corresponding to Eta=" << eta << ", Phi=" << phi << " NOT FOUND!" );
-    return -1;
-  }
-  if( m_doMacroRegions ) {
-    ATH_MSG_VERBOSE( "INDEX = " << m_MacroRegionIdxMap.find( ret_k )->second );
-    return m_MacroRegionIdxMap.find( ret_k )->second;
-  }
-  return ret_k;
 
-}
+    // obtain detRegion given the muon (eta,phi)
+    int loc_detRegion = 0;
+    double loc_eta = mu.eta();
+    double loc_phi = mu.phi();
 
-float MuonCalibrationAndSmearingTool::GetRegionInnerEta( const int r_i ) const { //Return Eta closer to the origin
+    // Getting detector region
+    if( int( loc_phi ) == DEFAULT_INIT_VAL && m_Trel == MCAST::Release::Rel17_2_Sum13 ) ATH_MSG_ERROR( "You need phi of the muon for after Rel17.2Sum13!" );
 
-  if( m_doMacroRegions ) {
-    if( r_i>=0 && r_i < ( int )m_MacroRegionName.size() ) return m_MacroRegionInnerEta[r_i];
-  }
-  else {
-    if( r_i >= 0 && r_i < m_nb_regions ) {
-      if( m_eta_min[r_i] >= 0. ) return m_eta_min[r_i];
-      else return m_eta_max[r_i];
+    if( int( loc_phi ) == DEFAULT_INIT_VAL && m_Trel < MCAST::Release::Rel17_2_Sum13 ) {
+      //Lower release have just Eta bins, so usually the user doesn't input
+      //Phi and 0 is a good default for these regions
+      loc_detRegion = GetRegion( loc_eta, 0 );
+    }
+    else {
+      loc_detRegion = GetRegion( loc_eta, loc_phi );
+    }
+
+    ATH_MSG_VERBOSE( "Getting Expected Resolution: " );
+    ATH_MSG_VERBOSE( " detRegion = "<<loc_detRegion);
+    ATH_MSG_VERBOSE( " ptid      = "<<loc_ptid);
+    ATH_MSG_VERBOSE( " ptms      = "<<loc_ptms);
+    ATH_MSG_VERBOSE( " ptcb      = "<<loc_ptcb);
+    ATH_MSG_VERBOSE( " m_nb_regions = "<<m_nb_regions);
+    ATH_MSG_VERBOSE( " mc = "<<mc);
+
+    // Expected resolution in data (or unsmeared MC if second argument is true)
+    bool useTan2 = true;
+    /** do the average with the EXPECTED resolutions **/
+    if ( loc_detRegion<0 || loc_detRegion>=m_nb_regions ) return 0;
+    double expRes = 0.;
+    if ( DetType == MCAST::DetectorType::MS ) {
+      ATH_MSG_VERBOSE("MS resolution");
+      if (loc_ptms == 0) return 1e12;
+      double p0 = mc ? m_MC_p0_MS[loc_detRegion] : ( std::sqrt(m_MC_p0_MS[loc_detRegion]*m_MC_p0_MS[loc_detRegion] + m_p0_MS[loc_detRegion]*m_p0_MS[loc_detRegion]));
+      double p1 = mc ? m_MC_p1_MS[loc_detRegion] : ( std::sqrt(m_MC_p1_MS[loc_detRegion]*m_MC_p1_MS[loc_detRegion] + m_p1_MS[loc_detRegion]*m_p1_MS[loc_detRegion]));
+      double p2 = mc ? m_MC_p2_MS[loc_detRegion] : ( std::sqrt(m_MC_p2_MS[loc_detRegion]*m_MC_p2_MS[loc_detRegion] + m_p2_MS[loc_detRegion]*m_p2_MS[loc_detRegion]));
+    ATH_MSG_VERBOSE("p0,p1,p2 = "<<p0<<"  "<<p1<<"  "<<p2);
+      expRes =  std::sqrt( std::pow( p0/loc_ptms, 2 ) + std::pow( p1, 2 ) + std::pow( p2*loc_ptms ,2 ) );
+      ATH_MSG_VERBOSE("expRes = "<<expRes);
+      return expRes; //+++++No SYS!!!
+    }
+    else if ( DetType == MCAST::DetectorType::ID ) {
+      ATH_MSG_VERBOSE("ID resolution");
+      if ( loc_ptid == 0 ) ATH_MSG_DEBUG( "ptid == 0" );
+      double p1 = mc ? m_MC_p1_ID[loc_detRegion] : ( std::sqrt(m_MC_p1_ID[loc_detRegion]*m_MC_p1_ID[loc_detRegion] + m_p1_ID[loc_detRegion]*m_p1_ID[loc_detRegion]));
+      double p2 = mc ? m_MC_p2_ID[loc_detRegion] : ( std::sqrt(m_MC_p2_ID[loc_detRegion]*m_MC_p2_ID[loc_detRegion] + m_p2_ID[loc_detRegion]*m_p2_ID[loc_detRegion]));
+      if ( m_MC_p2_ID_TAN[loc_detRegion] != 0 && useTan2 ) {
+        p2 = mc ? m_MC_p2_ID_TAN[loc_detRegion] : ( std::sqrt(m_MC_p2_ID_TAN[loc_detRegion]*m_MC_p2_ID_TAN[loc_detRegion] + m_p2_ID_TAN[loc_detRegion]*m_p2_ID_TAN[loc_detRegion]));
+        p2 = p2*std::sinh( mu.eta() )*std::sinh( mu.eta() );
+      }
+      ATH_MSG_VERBOSE("p1,p2 = "<<p1<<"  "<<p2);
+      expRes = std::sqrt( std::pow( p1, 2 ) + std::pow( p2*loc_ptid ,2 ) );
+      ATH_MSG_VERBOSE("expRes = "<<expRes);
+      return expRes; //+++++No SYS!!!
+    }
+    else if ( DetType == MCAST::DetectorType::CB ) {
+      ATH_MSG_VERBOSE("CB resolution");
+      // Due to complicated maths, the expected combined resolution
+      // is given by this equation (note: all sigmas are fractional uncertainties):
+      // sigma_CB = sqrt(2) * sigma_ID * sigma_MS * pTMS * pTID / {pTCB * sqrt({sigma_ID*pTID}^2 + {sigma_MS*pTMS}^2)}
+      // Do a little recursive calling to make things easier to read
+      // Turn these into *absolute* uncertainties to make life easier
+      double sigmaID = ExpectedResolution( MCAST::DetectorType::ID, mu, mc ) * loc_ptid;
+      double sigmaMS = ExpectedResolution( MCAST::DetectorType::MS, mu, mc ) * loc_ptms;
+      ATH_MSG_VERBOSE("sigmaID,sigmaMS = "<<sigmaID<<"  "<<sigmaMS);
+      double denominator = ( loc_ptcb ) * std::sqrt( sigmaID*sigmaID + sigmaMS*sigmaMS );
+      return denominator ?  sigmaID * sigmaMS / denominator : 0.;
+    }
+    else {
+      ATH_MSG_ERROR( "wrong DetType in input "<<DetType );
+      return 0.;
     }
-  }
-  //ATH_MSG_WARNING( "Region Inner Eta corresponding to Region index=" << r_i << " NOT FOUND!" );
-  return -999.;
 
-}
+  }
 
-std::string MuonCalibrationAndSmearingTool::GetRegionName( const int r_i ) const {
+  void MuonCalibrationAndSmearingTool::Clean() {
+
+    m_scale_ID.clear();
+    m_enLoss_MS.clear();
+    m_scale_MS.clear();
+    m_scale_CB.clear();
+    m_scaleSyst_ID.clear();
+    m_enLossSyst_MS.clear();
+    m_scaleSyst_MS.clear();
+    m_scaleSyst_CB.clear();
+    m_scaleSystUp_ID.clear();
+    m_enLossSystUp_MS.clear();
+    m_scaleSystUp_MS.clear();
+    m_scaleSystDw_ID.clear();
+    m_enLossSystDw_MS.clear();
+    m_scaleSystDw_MS.clear();
+    CleanScales();
+    m_p1_ID.clear();
+    m_p2_ID.clear();
+    m_p2_ID_TAN.clear();
+    m_p0_MS.clear();
+    m_p1_MS.clear();
+    m_p2_MS.clear();
+    m_E_p1_ID.clear();
+    m_E_p2_ID.clear();
+    m_E_p2_ID_TAN.clear();
+    m_E_p0_MS.clear();
+    m_E_p1_MS.clear();
+    m_E_p2_MS.clear();
+    m_S_p1_ID.clear();
+    m_S_p2_ID.clear();
+    m_S_p2_ID_TAN.clear();
+    m_S_p0_MS.clear();
+    m_S_p1_MS.clear();
+    m_S_p2_MS.clear();
+    m_SUp_p1_ID.clear();
+    m_SUp_p2_ID.clear();
+    m_SUp_p2_ID_TAN.clear();
+    m_SUp_p0_MS.clear();
+    m_SUp_p1_MS.clear();
+    m_SUp_p2_MS.clear();
+    m_SDw_p1_ID.clear();
+    m_SDw_p2_ID.clear();
+    m_SDw_p2_ID_TAN.clear();
+    m_SDw_p0_MS.clear();
+    m_SDw_p1_MS.clear();
+    m_SDw_p2_MS.clear();
+    m_MC_p1_ID.clear();
+    m_MC_p2_ID.clear();
+    m_MC_p2_ID_TAN.clear();
+    m_MC_p0_MS.clear();
+    m_MC_p1_MS.clear();
+    m_MC_p2_MS.clear();
+
+  }
+
+  void MuonCalibrationAndSmearingTool::PrintRegions() const {
 
-  if( m_loadNames ) {
     if( m_doMacroRegions ) {
-      if( r_i>=0 && r_i < ( int )m_MacroRegionName.size() ) return m_MacroRegionName[r_i];
+      for( std::map<int, int>::const_iterator it = m_MacroRegionIdxMap.begin(); it!=m_MacroRegionIdxMap.end(); ++it ) {
+        int bReg = it->first, mReg = it->second;
+        ATH_MSG_INFO( "Base region n "<<bReg );
+        ATH_MSG_INFO( "phi_min="<<m_phi_min[bReg]<<", phi_max="<<m_phi_max[bReg] );
+        ATH_MSG_INFO( "eta_min="<<m_eta_min[bReg]<<", eta_max="<<m_eta_max[bReg] );
+        ATH_MSG_INFO( "included in Macro region N "<<mReg<<" with innerEta="<<m_MacroRegionInnerEta[mReg] );
+      }
     }
     else {
-      if( r_i>=0 && r_i < m_nb_regions ) return m_names[r_i];
+      for( int bReg=0; bReg<m_nb_regions; ++bReg ) {
+        ATH_MSG_INFO( "Base region n "<<bReg<<": phi_min="<<m_phi_min[bReg]<<", phi_max="<<m_phi_max[bReg] );
+        ATH_MSG_INFO( "eta_min="<<m_eta_min[bReg]<<", eta_max="<<m_eta_max[bReg] );
+      }
     }
-    ATH_MSG_WARNING( "Region Name corresponding to Region index=" << r_i << " NOT FOUND!" );
+
   }
-  ATH_MSG_WARNING( "Region Names are not set!" );
-  return "NAN";
-
-}
-
-std::string MuonCalibrationAndSmearingTool::GetRegionName( const double eta, const double phi ) const {
-
-  if( m_loadNames ) return GetRegionName( GetRegion( eta, phi ) );
-  ATH_MSG_WARNING( "Region Names are not set!" );
-  return "NAN";
-
-}
-
-//Collects all the Large and Small sectors if they belong to the same eta bin
-void MuonCalibrationAndSmearingTool::CollectMacroRegionsSL() {
-
-  double etaMin = -999., etaMax = -999.;
-  int macroRegionIdx = 0;
-  for( int k=0; k < m_nb_regions; ++k ) {
-    if( etaMin != m_eta_min[k] || etaMax !=m_eta_max[k] ) {
-      //Build a new macroRegion
-      etaMin = m_eta_min[k];
-      etaMax = m_eta_max[k];
-      //One of the following is true
-      std::string macroRegName = m_names[k].substr( 0, m_names[k].find( "EL" ) );
-      macroRegName = macroRegName.substr( 0, m_names[k].find( "BL" ) );
-      macroRegName = macroRegName.substr( 0, m_names[k].find( "ES" ) );
-      macroRegName = macroRegName.substr( 0, m_names[k].find( "BS" ) );
-      m_MacroRegionName.push_back( macroRegName+"Large" );
-      m_MacroRegionName.push_back( macroRegName+"Small" );
-      //insert twice the innerEta, for Large and for Small sectors
-      for( int i=0; i<2; ++i ) {
-        if( etaMin >= 0. ) m_MacroRegionInnerEta.push_back( etaMin );
-        else         m_MacroRegionInnerEta.push_back( etaMax );
-      }
-      macroRegionIdx+=2;
-    }
-    if( m_names[k].find( "EL" ) != std::string::npos || m_names[k].find( "BL" ) != std::string::npos )
-      m_MacroRegionIdxMap[k] = macroRegionIdx-2;//Large sectors
-    if( m_names[k].find( "ES" ) != std::string::npos || m_names[k].find( "BS" ) != std::string::npos )
-      m_MacroRegionIdxMap[k] = macroRegionIdx-1;//Small sectors
+
+  unsigned int MuonCalibrationAndSmearingTool::GetNRegions() const {
+    if( m_doMacroRegions )
+      return m_MacroRegionName.size();
+    else
+      return m_nb_regions;
   }
-  return;
-
-}
-
-//Collects all the Large and Small sectors if they belong to the same eta bin
-void MuonCalibrationAndSmearingTool::CollectSectors() {
-
-  double etaMin = -999., etaMax = -999.;
-  int macroRegionIdx = 0;
-  for( int k=0; k < m_nb_regions; ++k ) {
-    if( etaMin != m_eta_min[k] || etaMax !=m_eta_max[k] ) {
-      //Build a new macroRegion
-      etaMin = m_eta_min[k];
-      etaMax = m_eta_max[k];
-      //One of the following is true
-      std::string macroRegName = m_names[k].substr( 0, m_names[k].find( "EL" ) );
-      macroRegName = macroRegName.substr( 0, m_names[k].find( "BL" ) );
-      macroRegName = macroRegName.substr( 0, m_names[k].find( "ES" ) );
-      macroRegName = macroRegName.substr( 0, m_names[k].find( "BS" ) );
-      m_MacroRegionName.push_back( macroRegName+"LargeDn" );
-      m_MacroRegionName.push_back( macroRegName+"SmallDn" );
-      m_MacroRegionName.push_back( macroRegName+"LargeUp" );
-      m_MacroRegionName.push_back( macroRegName+"SmallUp" );
-      //insert 4 time the innerEta, for Large and Small sectors times Up and Dn
-      for( int i=0; i<4; ++i ) {
-        if( etaMin >= 0. ) m_MacroRegionInnerEta.push_back( etaMin );
-        else         m_MacroRegionInnerEta.push_back( etaMax );
-      }
-      macroRegionIdx+=4;
-    }
-    if( m_names[k].find( "EL" ) != std::string::npos || m_names[k].find( "BL" ) != std::string::npos ) { //Large sectors
-      if( m_names[k].find( "11" ) != std::string::npos || m_names[k].find( "13" ) != std::string::npos ||
-          m_names[k].find( "15" ) != std::string::npos ) {
-        m_MacroRegionIdxMap[k] = macroRegionIdx-4;//Down Large sectors (within 10 to 16)
-      }
-      else {
-        m_MacroRegionIdxMap[k] = macroRegionIdx-2; //Up, large sectors
-      }
+
+  StatusCode MuonCalibrationAndSmearingTool::Regions( std::string inRegionFile, int doMacroRegionsFlag ) {
+
+    m_eta_min.clear();
+    m_eta_max.clear();
+    m_phi_min.clear();
+    m_phi_max.clear();
+    m_loadNames = false;
+    m_doMacroRegions = false;
+    std::string tmpname;
+    double tmpval;
+    int i = 0;
+    std::ifstream inFile( inRegionFile.c_str() );
+    if( !inFile.good() ) {
+      ATH_MSG_ERROR( "File not good" );
+      return StatusCode::FAILURE;
     }
-    if( m_names[k].find( "ES" ) != std::string::npos || m_names[k].find( "BS" ) != std::string::npos ) { //Small sectors
-      if( m_names[k].find( "10" ) != std::string::npos || m_names[k].find( "12" ) != std::string::npos ||
-          m_names[k].find( "14" ) != std::string::npos || m_names[k].find( "16" ) != std::string::npos ) {
-        m_MacroRegionIdxMap[k] = macroRegionIdx-3; //Down Small sectors (from 10 to 16). Should I remove 10 and 16? ++++++
+    else {
+      while( !inFile.eof() ) {
+        tmpval=0;
+        tmpname="";
+        if( i==0 ) {
+          getline( inFile,tmpname );
+          //Check if I am loading the name of the regions in the file
+          if( tmpname.find( "name" ) != std::string::npos && !m_loadNames ) m_loadNames = true;
+        }
+        else {
+          inFile>>tmpval;
+          if( inFile.eof() ) break; //this will break immediatly as soon as the new line is empty
+          m_eta_min.push_back( tmpval );
+          inFile>>tmpval;
+          m_eta_max.push_back( tmpval );
+          inFile>>tmpval;
+          m_phi_min.push_back( tmpval );
+          inFile>>tmpval;
+          m_phi_max.push_back( tmpval );
+          if( m_loadNames ) { //Fill the name vector only if you have them!
+            inFile>>tmpname;
+            m_names.push_back( tmpname );
+          }
+        }
+        ++i;
       }
-      else {
-        m_MacroRegionIdxMap[k] = macroRegionIdx-1; ; //Up, Small sectors
+    }
+    inFile.close();
+    m_nb_regions = ( int ) m_eta_min.size();
+    if( doMacroRegionsFlag ) { //In case I want macroRegions, I need to define the criteria here
+      m_doMacroRegions = true;
+      switch( doMacroRegionsFlag ) {
+      case 1:
+        //Collects all the Large and Small sectors if they belong to the same eta bin
+        CollectMacroRegionsSL();
+        break;
+      case 2:
+        //Large,Small sectors split plus Feet(12+14) and 11+15 sector split in Barrel
+        CollectMacroRegionsSL_SplitBAR();
+        break;
+      case 3:
+        //Collects all the Large and Small, Up and Down sectors if they belong to the same eta bin
+        CollectMacroRegionsSL_UpDn();
+        break;
+      case 4:
+        //Collects all the Large and Small, Up and Down sectors if they belong to the same eta bin
+        CollectSectors();
+        break;
+      default:
+        ATH_MSG_ERROR( "doMacroRegionFlag=" << doMacroRegionsFlag << " not defined!" );
+        return StatusCode::FAILURE;
       }
     }
+    return StatusCode::SUCCESS;
+
   }
-  return;
-
-}
-
-void MuonCalibrationAndSmearingTool::CollectMacroRegionsSL_UpDn() {
-
-  double etaMin = -999., etaMax = -999.;
-  int macroRegionIdx = 0;
-  for( int k=0; k < m_nb_regions; ++k ) {
-    if( etaMin != m_eta_min[k] || etaMax !=m_eta_max[k] ) {
-      //Build a new macroRegion
-      etaMin = m_eta_min[k];
-      etaMax = m_eta_max[k];
-      //One of the following is true
-      std::string macroRegName = m_names[k].substr( 0, m_names[k].find( "EL" ) );
-      macroRegName = macroRegName.substr( 0, m_names[k].find( "BL" ) );
-      macroRegName = macroRegName.substr( 0, m_names[k].find( "ES" ) );
-      macroRegName = macroRegName.substr( 0, m_names[k].find( "BS" ) );
-      m_MacroRegionName.push_back( macroRegName+"LargeDn" );
-      m_MacroRegionName.push_back( macroRegName+"SmallDn" );
-      m_MacroRegionName.push_back( macroRegName+"LargeUp" );
-      m_MacroRegionName.push_back( macroRegName+"SmallUp" );
-      //insert 4 time the innerEta, for Large and Small sectors times Up and Dn
-      for( int i=0; i<4; ++i ) {
-        if( etaMin >= 0. ) m_MacroRegionInnerEta.push_back( etaMin );
-        else         m_MacroRegionInnerEta.push_back( etaMax );
-      }
-      macroRegionIdx+=4;
-    }
-    if( m_names[k].find( "EL" ) != std::string::npos || m_names[k].find( "BL" ) != std::string::npos ) { //Large sectors
-      if( m_names[k].find( "11" ) != std::string::npos || m_names[k].find( "13" ) != std::string::npos ||
-          m_names[k].find( "15" ) != std::string::npos ) {
-        m_MacroRegionIdxMap[k] = macroRegionIdx-4;//Down Large sectors (within 10 to 16)
+
+  int MuonCalibrationAndSmearingTool::GetRegion( const double eta, const double phi ) const {
+
+    ATH_MSG_VERBOSE( "eta,phi = " << eta << "," << phi );
+    int ret_k =-1;
+    for( int k=0; k < m_nb_regions; ++k ) {
+      if( eta>=m_eta_min[k] && eta<m_eta_max[k] ) {
+        if( m_phi_min[k] <= m_phi_max[k] ) { //Standard case
+          if( phi>=m_phi_min[k] && phi<m_phi_max[k] ) {
+            ret_k = k;
+            break;
+          }
+        }
+        else {  //Circular closure of Phi, min and max are excanged in the .dat file
+          if( phi>=m_phi_min[k] || phi<m_phi_max[k] ) {
+            ret_k = k;
+            break;
+          }
+        }
       }
-      else {
-        m_MacroRegionIdxMap[k] = macroRegionIdx-2; //Up, large sectors
+    }
+    if( ret_k == -1 ) {
+      ATH_MSG_DEBUG( "Region corresponding to Eta=" << eta << ", Phi=" << phi << " NOT FOUND!" );
+      return -1;
+    }
+    if( m_doMacroRegions ) {
+      ATH_MSG_VERBOSE( "INDEX = " << m_MacroRegionIdxMap.find( ret_k )->second );
+      return m_MacroRegionIdxMap.find( ret_k )->second;
+    }
+    return ret_k;
+
+  }
+
+  float MuonCalibrationAndSmearingTool::GetRegionInnerEta( const int r_i ) const { //Return Eta closer to the origin
+
+    if( m_doMacroRegions ) {
+      if( r_i>=0 && r_i < ( int )m_MacroRegionName.size() ) return m_MacroRegionInnerEta[r_i];
+    }
+    else {
+      if( r_i >= 0 && r_i < m_nb_regions ) {
+        if( m_eta_min[r_i] >= 0. ) return m_eta_min[r_i];
+        else return m_eta_max[r_i];
       }
     }
-    if( m_names[k].find( "ES" ) != std::string::npos || m_names[k].find( "BS" ) != std::string::npos ) { //Small sectors
-      if( m_names[k].find( "10" ) != std::string::npos || m_names[k].find( "12" ) != std::string::npos ||
-          m_names[k].find( "14" ) != std::string::npos || m_names[k].find( "16" ) != std::string::npos ) {
-        m_MacroRegionIdxMap[k] = macroRegionIdx-3; //Down Small sectors (from 10 to 16). Should I remove 10 and 16? ++++++
+    return -999.;
+
+  }
+
+  std::string MuonCalibrationAndSmearingTool::GetRegionName( const int r_i ) const {
+
+    if( m_loadNames ) {
+      if( m_doMacroRegions ) {
+        if( r_i>=0 && r_i < ( int )m_MacroRegionName.size() ) return m_MacroRegionName[r_i];
       }
       else {
-        m_MacroRegionIdxMap[k] = macroRegionIdx-1; ; //Up, Small sectors
+        if( r_i>=0 && r_i < m_nb_regions ) return m_names[r_i];
       }
+      ATH_MSG_WARNING( "Region Name corresponding to Region index=" << r_i << " NOT FOUND!" );
     }
+    ATH_MSG_WARNING( "Region Names are not set!" );
+    return "NAN";
+
+  }
+
+  std::string MuonCalibrationAndSmearingTool::GetRegionName( const double eta, const double phi ) const {
+
+    if( m_loadNames ) return GetRegionName( GetRegion( eta, phi ) );
+    ATH_MSG_WARNING( "Region Names are not set!" );
+    return "NAN";
+
   }
-  return;
-
-}
-
-//Collects all the Large and Small sectors if they belong to the same eta bin and splits
-// the barrel 12,14 smalls and 11+15 larges that may need different calibrations
-void MuonCalibrationAndSmearingTool::CollectMacroRegionsSL_SplitBAR() {
-
-  double etaMin = -999., etaMax = -999.;
-  int macroRegionIdx = 0;
-  for( int k=0; k < m_nb_regions; ++k ) {
-    if( etaMin != m_eta_min[k] || etaMax !=m_eta_max[k] ) { //Build a new macroRegion
-      etaMin = m_eta_min[k];
-      etaMax = m_eta_max[k];
-      std::string macroRegName ="";
-      if( m_names[k].find( "EL" )!= std::string::npos || m_names[k].find( "ES" ) != std::string::npos ) {
-        //We are in the End-Cap sectors so we split only Large and Small sectors
-        macroRegName = m_names[k].substr( 0, m_names[k].find( "EL" ) );
+
+  //Collects all the Large and Small sectors if they belong to the same eta bin
+  void MuonCalibrationAndSmearingTool::CollectMacroRegionsSL() {
+
+    double etaMin = -999., etaMax = -999.;
+    int macroRegionIdx = 0;
+    for( int k=0; k < m_nb_regions; ++k ) {
+      if( etaMin != m_eta_min[k] || etaMax !=m_eta_max[k] ) {
+        //Build a new macroRegion
+        etaMin = m_eta_min[k];
+        etaMax = m_eta_max[k];
+        //One of the following is true
+        std::string macroRegName = m_names[k].substr( 0, m_names[k].find( "EL" ) );
+        macroRegName = macroRegName.substr( 0, m_names[k].find( "BL" ) );
         macroRegName = macroRegName.substr( 0, m_names[k].find( "ES" ) );
-        //insert 4 time the innerEta, for Large and Small sectors
+        macroRegName = macroRegName.substr( 0, m_names[k].find( "BS" ) );
         m_MacroRegionName.push_back( macroRegName+"Large" );
         m_MacroRegionName.push_back( macroRegName+"Small" );
+        //insert twice the innerEta, for Large and for Small sectors
         for( int i=0; i<2; ++i ) {
           if( etaMin >= 0. ) m_MacroRegionInnerEta.push_back( etaMin );
-          else               m_MacroRegionInnerEta.push_back( etaMax );
+          else         m_MacroRegionInnerEta.push_back( etaMax );
         }
         macroRegionIdx+=2;
       }
-      else {  //We are in the Barrels sectors so we split Large, Small, 12+14, 11+15 sectors
-        macroRegName = m_names[k].substr( 0, m_names[k].find( "BL" ) );
+      if( m_names[k].find( "EL" ) != std::string::npos || m_names[k].find( "BL" ) != std::string::npos )
+        m_MacroRegionIdxMap[k] = macroRegionIdx-2;//Large sectors
+      if( m_names[k].find( "ES" ) != std::string::npos || m_names[k].find( "BS" ) != std::string::npos )
+        m_MacroRegionIdxMap[k] = macroRegionIdx-1;//Small sectors
+    }
+    return;
+
+  }
+
+  //Collects all the Large and Small sectors if they belong to the same eta bin
+  void MuonCalibrationAndSmearingTool::CollectSectors() {
+
+    double etaMin = -999., etaMax = -999.;
+    int macroRegionIdx = 0;
+    for( int k=0; k < m_nb_regions; ++k ) {
+      if( etaMin != m_eta_min[k] || etaMax !=m_eta_max[k] ) {
+        //Build a new macroRegion
+        etaMin = m_eta_min[k];
+        etaMax = m_eta_max[k];
+        //One of the following is true
+        std::string macroRegName = m_names[k].substr( 0, m_names[k].find( "EL" ) );
+        macroRegName = macroRegName.substr( 0, m_names[k].find( "BL" ) );
+        macroRegName = macroRegName.substr( 0, m_names[k].find( "ES" ) );
         macroRegName = macroRegName.substr( 0, m_names[k].find( "BS" ) );
+        m_MacroRegionName.push_back( macroRegName+"LargeDn" );
+        m_MacroRegionName.push_back( macroRegName+"SmallDn" );
+        m_MacroRegionName.push_back( macroRegName+"LargeUp" );
+        m_MacroRegionName.push_back( macroRegName+"SmallUp" );
         //insert 4 time the innerEta, for Large and Small sectors times Up and Dn
-        m_MacroRegionName.push_back( macroRegName+"Large" );
-        m_MacroRegionName.push_back( macroRegName+"Small" );
-        m_MacroRegionName.push_back( macroRegName+"Large11_15" );
-        m_MacroRegionName.push_back( macroRegName+"SmallFeet" );
         for( int i=0; i<4; ++i ) {
           if( etaMin >= 0. ) m_MacroRegionInnerEta.push_back( etaMin );
-          else               m_MacroRegionInnerEta.push_back( etaMax );
+          else         m_MacroRegionInnerEta.push_back( etaMax );
         }
         macroRegionIdx+=4;
       }
-    }
-    if( m_names[k].find( "EL" ) != std::string::npos ) { //End-Cap Large sectors
-      m_MacroRegionIdxMap[k] = macroRegionIdx-2;
-    }
-    else if( m_names[k].find( "ES" ) != std::string::npos ) { //End-Cap Small sectors
-      m_MacroRegionIdxMap[k] = macroRegionIdx-1; //
-    }
-    else if ( m_names[k].find( "BL" ) != std::string::npos ) { //Barrel Large sectors
-      if( m_names[k].find( "11" ) != std::string::npos || m_names[k].find( "15" ) != std::string::npos ) {
-        m_MacroRegionIdxMap[k] = macroRegionIdx-2;//Barrel Large sectors with different alignment (11,15)
+      if( m_names[k].find( "EL" ) != std::string::npos || m_names[k].find( "BL" ) != std::string::npos ) { //Large sectors
+        if( m_names[k].find( "11" ) != std::string::npos || m_names[k].find( "13" ) != std::string::npos ||
+            m_names[k].find( "15" ) != std::string::npos ) {
+          m_MacroRegionIdxMap[k] = macroRegionIdx-4;//Down Large sectors (within 10 to 16)
+        }
+        else {
+          m_MacroRegionIdxMap[k] = macroRegionIdx-2; //Up, large sectors
+        }
       }
-      else {
-        m_MacroRegionIdxMap[k] = macroRegionIdx-4; //Standard Barrel Large sectors
+      if( m_names[k].find( "ES" ) != std::string::npos || m_names[k].find( "BS" ) != std::string::npos ) { //Small sectors
+        if( m_names[k].find( "10" ) != std::string::npos || m_names[k].find( "12" ) != std::string::npos ||
+            m_names[k].find( "14" ) != std::string::npos || m_names[k].find( "16" ) != std::string::npos ) {
+          m_MacroRegionIdxMap[k] = macroRegionIdx-3; //Down Small sectors (from 10 to 16). Should I remove 10 and 16? ++++++
+        }
+        else {
+          m_MacroRegionIdxMap[k] = macroRegionIdx-1; ; //Up, Small sectors
+        }
       }
     }
-    else if( m_names[k].find( "BS" ) != std::string::npos ) { //Barrel Small sectors
-      if( m_names[k].find( "12" ) != std::string::npos || m_names[k].find( "14" ) != std::string::npos ) {
-        m_MacroRegionIdxMap[k] = macroRegionIdx-1; //Feet Small sectors (12+14, Down).
+    return;
+
+  }
+
+  void MuonCalibrationAndSmearingTool::CollectMacroRegionsSL_UpDn() {
+
+    double etaMin = -999., etaMax = -999.;
+    int macroRegionIdx = 0;
+    for( int k=0; k < m_nb_regions; ++k ) {
+      if( etaMin != m_eta_min[k] || etaMax !=m_eta_max[k] ) {
+        //Build a new macroRegion
+        etaMin = m_eta_min[k];
+        etaMax = m_eta_max[k];
+        //One of the following is true
+        std::string macroRegName = m_names[k].substr( 0, m_names[k].find( "EL" ) );
+        macroRegName = macroRegName.substr( 0, m_names[k].find( "BL" ) );
+        macroRegName = macroRegName.substr( 0, m_names[k].find( "ES" ) );
+        macroRegName = macroRegName.substr( 0, m_names[k].find( "BS" ) );
+        m_MacroRegionName.push_back( macroRegName+"LargeDn" );
+        m_MacroRegionName.push_back( macroRegName+"SmallDn" );
+        m_MacroRegionName.push_back( macroRegName+"LargeUp" );
+        m_MacroRegionName.push_back( macroRegName+"SmallUp" );
+        //insert 4 time the innerEta, for Large and Small sectors times Up and Dn
+        for( int i=0; i<4; ++i ) {
+          if( etaMin >= 0. ) m_MacroRegionInnerEta.push_back( etaMin );
+          else         m_MacroRegionInnerEta.push_back( etaMax );
+        }
+        macroRegionIdx+=4;
       }
-      else {
-        m_MacroRegionIdxMap[k] = macroRegionIdx-3; //All standard Barrel Small sectors
+      if( m_names[k].find( "EL" ) != std::string::npos || m_names[k].find( "BL" ) != std::string::npos ) { //Large sectors
+        if( m_names[k].find( "11" ) != std::string::npos || m_names[k].find( "13" ) != std::string::npos ||
+            m_names[k].find( "15" ) != std::string::npos ) {
+          m_MacroRegionIdxMap[k] = macroRegionIdx-4;//Down Large sectors (within 10 to 16)
+        }
+        else {
+          m_MacroRegionIdxMap[k] = macroRegionIdx-2; //Up, large sectors
+        }
+      }
+      if( m_names[k].find( "ES" ) != std::string::npos || m_names[k].find( "BS" ) != std::string::npos ) { //Small sectors
+        if( m_names[k].find( "10" ) != std::string::npos || m_names[k].find( "12" ) != std::string::npos ||
+            m_names[k].find( "14" ) != std::string::npos || m_names[k].find( "16" ) != std::string::npos ) {
+          m_MacroRegionIdxMap[k] = macroRegionIdx-3; //Down Small sectors (from 10 to 16). Should I remove 10 and 16? ++++++
+        }
+        else {
+          m_MacroRegionIdxMap[k] = macroRegionIdx-1; ; //Up, Small sectors
+        }
       }
     }
+    return;
+
   }
-  return;
 
-}
+  //Collects all the Large and Small sectors if they belong to the same eta bin and splits
+  // the barrel 12,14 smalls and 11+15 larges that may need different calibrations
+  void MuonCalibrationAndSmearingTool::CollectMacroRegionsSL_SplitBAR() {
+
+    double etaMin = -999., etaMax = -999.;
+    int macroRegionIdx = 0;
+    for( int k=0; k < m_nb_regions; ++k ) {
+      if( etaMin != m_eta_min[k] || etaMax !=m_eta_max[k] ) { //Build a new macroRegion
+        etaMin = m_eta_min[k];
+        etaMax = m_eta_max[k];
+        std::string macroRegName ="";
+        if( m_names[k].find( "EL" )!= std::string::npos || m_names[k].find( "ES" ) != std::string::npos ) {
+          //We are in the End-Cap sectors so we split only Large and Small sectors
+          macroRegName = m_names[k].substr( 0, m_names[k].find( "EL" ) );
+          macroRegName = macroRegName.substr( 0, m_names[k].find( "ES" ) );
+          //insert 4 time the innerEta, for Large and Small sectors
+          m_MacroRegionName.push_back( macroRegName+"Large" );
+          m_MacroRegionName.push_back( macroRegName+"Small" );
+          for( int i=0; i<2; ++i ) {
+            if( etaMin >= 0. ) m_MacroRegionInnerEta.push_back( etaMin );
+            else               m_MacroRegionInnerEta.push_back( etaMax );
+          }
+          macroRegionIdx+=2;
+        }
+        else {  //We are in the Barrels sectors so we split Large, Small, 12+14, 11+15 sectors
+          macroRegName = m_names[k].substr( 0, m_names[k].find( "BL" ) );
+          macroRegName = macroRegName.substr( 0, m_names[k].find( "BS" ) );
+          //insert 4 time the innerEta, for Large and Small sectors times Up and Dn
+          m_MacroRegionName.push_back( macroRegName+"Large" );
+          m_MacroRegionName.push_back( macroRegName+"Small" );
+          m_MacroRegionName.push_back( macroRegName+"Large11_15" );
+          m_MacroRegionName.push_back( macroRegName+"SmallFeet" );
+          for( int i=0; i<4; ++i ) {
+            if( etaMin >= 0. ) m_MacroRegionInnerEta.push_back( etaMin );
+            else               m_MacroRegionInnerEta.push_back( etaMax );
+          }
+          macroRegionIdx+=4;
+        }
+      }
+      if( m_names[k].find( "EL" ) != std::string::npos ) { //End-Cap Large sectors
+        m_MacroRegionIdxMap[k] = macroRegionIdx-2;
+      }
+      else if( m_names[k].find( "ES" ) != std::string::npos ) { //End-Cap Small sectors
+        m_MacroRegionIdxMap[k] = macroRegionIdx-1; //
+      }
+      else if ( m_names[k].find( "BL" ) != std::string::npos ) { //Barrel Large sectors
+        if( m_names[k].find( "11" ) != std::string::npos || m_names[k].find( "15" ) != std::string::npos ) {
+          m_MacroRegionIdxMap[k] = macroRegionIdx-2;//Barrel Large sectors with different alignment (11,15)
+        }
+        else {
+          m_MacroRegionIdxMap[k] = macroRegionIdx-4; //Standard Barrel Large sectors
+        }
+      }
+      else if( m_names[k].find( "BS" ) != std::string::npos ) { //Barrel Small sectors
+        if( m_names[k].find( "12" ) != std::string::npos || m_names[k].find( "14" ) != std::string::npos ) {
+          m_MacroRegionIdxMap[k] = macroRegionIdx-1; //Feet Small sectors (12+14, Down).
+        }
+        else {
+          m_MacroRegionIdxMap[k] = macroRegionIdx-3; //All standard Barrel Small sectors
+        }
+      }
+    }
+    return;
 
-double MuonCalibrationAndSmearingTool::GetSystVariation( const Vars& vars,
-                                                         int DetType, double var ) const
-{
-  if( var != 1. && var != -1 ) {
-    ATH_MSG_WARNING( "Systematic variation is not +/- 1 sigma, returning 0." );
-    return 0;
   }
-  if( vars.m_detRegion < 0 || vars.m_detRegion >= m_nb_regions ) return 0;
 
-  double p0_MS_var = 0., p1_MS_var = 0., p2_MS_var = 0., p1_ID_var = 0., p2_ID_var = 0., p2_ID_TAN_var = 0.;   
-  double newSmear = 0.;
-  if( DetType == MCAST::DetectorType::MS ) {
-    if( vars.m_ptms == 0 ) {  
+  double MuonCalibrationAndSmearingTool::GetSystVariation( int DetType, double var, InfoHelper& muonInfo ) const {
+
+    if( var != 1. && var != -1 ) {
+      ATH_MSG_WARNING( "Systematic variation is not +/- 1 sigma, returning 0." );
       return 0;
-    } else {
+    }
+    if( muonInfo.detRegion < 0 || muonInfo.detRegion >= m_nb_regions ) return 0;
+
+    double p0_MS_var = 0., p1_MS_var = 0., p2_MS_var = 0., p1_ID_var = 0., p2_ID_var = 0., p2_ID_TAN_var = 0.;
+    double newSmear = 0.;
+    if( DetType == MCAST::DetectorType::MS ) {
+      if( muonInfo.ptms == 0 ) {
+        return 0;
+      } else {
+        if( m_Trel < MCAST::Release::Rel17_2_Sum13 ) {
+          p0_MS_var = std::pow( m_E_p0_MS[ muonInfo.detRegion ] * m_E_p0_MS[ muonInfo.detRegion ] + m_S_p0_MS[ muonInfo.detRegion ] * m_S_p0_MS[ muonInfo.detRegion ], 0.5 );
+          p1_MS_var = std::pow( m_E_p1_MS[ muonInfo.detRegion] * m_E_p1_MS[ muonInfo.detRegion ] + m_S_p1_MS[ muonInfo.detRegion ] * m_S_p1_MS[ muonInfo.detRegion ], 0.5 );
+          p2_MS_var = std::pow( m_E_p2_MS[ muonInfo.detRegion] * m_E_p2_MS[ muonInfo.detRegion ] + m_S_p2_MS[ muonInfo.detRegion ] * m_S_p2_MS[ muonInfo.detRegion ], 0.5 );
+        } else {//Syst are not more symmetric in the latest release, the stat/sys add in quadrature is already done
+          p0_MS_var = var > 0. ? m_SUp_p0_MS[ muonInfo.detRegion ] : m_SDw_p0_MS[ muonInfo.detRegion ];
+          p1_MS_var = var > 0. ? m_SUp_p1_MS[ muonInfo.detRegion ] : m_SDw_p1_MS[ muonInfo.detRegion ];
+          p2_MS_var = var > 0. ? m_SUp_p2_MS[ muonInfo.detRegion ] : m_SDw_p2_MS[ muonInfo.detRegion ];
+        }
+
+        p0_MS_var = m_p0_MS[ muonInfo.detRegion ] + var * p0_MS_var;
+        p1_MS_var = m_p1_MS[ muonInfo.detRegion ] + var * p1_MS_var;
+        p2_MS_var = m_p2_MS[ muonInfo.detRegion ] + var * p2_MS_var;
+
+        if( p0_MS_var < 0. ) p0_MS_var = 0.; //Truncation of unphysical variations
+        if( p1_MS_var < 0. ) p1_MS_var = 0.;
+        if( p2_MS_var < 0. ) p2_MS_var = 0.;
+        newSmear = ( p0_MS_var * muonInfo.g0 / muonInfo.ptms + p1_MS_var * muonInfo.g1 + p2_MS_var * muonInfo.g2 * muonInfo.ptms );
+        return newSmear;
+      }
+    } else if( DetType == MCAST::DetectorType::ID ) {
       if( m_Trel < MCAST::Release::Rel17_2_Sum13 ) {
-        p0_MS_var = pow( m_E_p0_MS[ vars.m_detRegion ] * m_E_p0_MS[ vars.m_detRegion ] + m_S_p0_MS[ vars.m_detRegion ] * m_S_p0_MS[ vars.m_detRegion ], 0.5 );
-        p1_MS_var = pow( m_E_p1_MS[ vars.m_detRegion] * m_E_p1_MS[ vars.m_detRegion ] + m_S_p1_MS[ vars.m_detRegion ] * m_S_p1_MS[ vars.m_detRegion ], 0.5 );
-        p2_MS_var = pow( m_E_p2_MS[ vars.m_detRegion] * m_E_p2_MS[ vars.m_detRegion ] + m_S_p2_MS[ vars.m_detRegion ] * m_S_p2_MS[ vars.m_detRegion ], 0.5 );
+        p1_ID_var     = std::pow( m_E_p1_ID[ muonInfo.detRegion ] * m_E_p1_ID[ muonInfo.detRegion ] + m_S_p1_ID[ muonInfo.detRegion ] * m_S_p1_ID[ muonInfo.detRegion ], 0.5 );
+        p2_ID_var     = std::pow( m_E_p2_ID[ muonInfo.detRegion ] * m_E_p2_ID[ muonInfo.detRegion ] + m_S_p2_ID[ muonInfo.detRegion ] * m_S_p2_ID[ muonInfo.detRegion ], 0.5 );
+        p2_ID_TAN_var = std::pow( m_E_p2_ID_TAN[ muonInfo.detRegion ] * m_E_p2_ID_TAN[ muonInfo.detRegion ] + m_S_p2_ID_TAN[ muonInfo.detRegion ] * m_S_p2_ID_TAN[ muonInfo.detRegion ], 0.5 );
       } else {//Syst are not more symmetric in the latest release, the stat/sys add in quadrature is already done
-        p0_MS_var = var > 0. ? m_SUp_p0_MS[ vars.m_detRegion ] : m_SDw_p0_MS[ vars.m_detRegion ];
-        p1_MS_var = var > 0. ? m_SUp_p1_MS[ vars.m_detRegion ] : m_SDw_p1_MS[ vars.m_detRegion ];
-        p2_MS_var = var > 0. ? m_SUp_p2_MS[ vars.m_detRegion ] : m_SDw_p2_MS[ vars.m_detRegion ];
+        p1_ID_var     = var > 0. ? m_SUp_p1_ID[ muonInfo.detRegion ] : m_SDw_p1_ID[ muonInfo.detRegion ];
+        p2_ID_var     = var > 0. ? m_SUp_p2_ID[ muonInfo.detRegion ] : m_SDw_p2_ID[ muonInfo.detRegion ];
+        p2_ID_TAN_var = var > 0. ? m_SUp_p2_ID_TAN[ muonInfo.detRegion ] : m_SDw_p2_ID_TAN[ muonInfo.detRegion ];
+      }
+      p1_ID_var     = m_p1_ID[ muonInfo.detRegion ] + var * p1_ID_var;
+      p2_ID_var     = m_p2_ID[ muonInfo.detRegion ] + var * p2_ID_var;
+      p2_ID_TAN_var = m_p2_ID_TAN[ muonInfo.detRegion ] + var * p2_ID_TAN_var;
+
+      if( p1_ID_var < 0. ) p1_ID_var = 0.; //Truncation of unphysical variations
+      if( p2_ID_var < 0. ) p2_ID_var = 0.;
+      if( p2_ID_TAN_var < 0. ) p2_ID_TAN_var = 0.;
+
+      bool useTan2 = true;
+      if( useTan2 && m_p2_ID_TAN[ muonInfo.detRegion ] != 0 ) {
+        newSmear = ( p1_ID_var * muonInfo.g3 + p2_ID_TAN_var * muonInfo.g4 * muonInfo.ptid * sinh( muonInfo.eta ) * sinh( muonInfo.eta ) );
+      } else {
+        newSmear = ( p1_ID_var * muonInfo.g3 + p2_ID_var * muonInfo.g4 * muonInfo.ptid );
       }
-
-      p0_MS_var = m_p0_MS[ vars.m_detRegion ] + var * p0_MS_var;
-      p1_MS_var = m_p1_MS[ vars.m_detRegion ] + var * p1_MS_var;
-      p2_MS_var = m_p2_MS[ vars.m_detRegion ] + var * p2_MS_var;
-
-      if( p0_MS_var < 0. ) p0_MS_var = 0.; //Truncation of unphysical variations
-      if( p1_MS_var < 0. ) p1_MS_var = 0.;
-      if( p2_MS_var < 0. ) p2_MS_var = 0.;
-      newSmear = ( p0_MS_var * vars.m_g0 / vars.m_ptms + p1_MS_var * vars.m_g1 + p2_MS_var * vars.m_g2 * vars.m_ptms );
       return newSmear;
     }
-  } else if( DetType == MCAST::DetectorType::ID ) {
-    if( m_Trel < MCAST::Release::Rel17_2_Sum13 ) {
-      p1_ID_var     = pow( m_E_p1_ID[ vars.m_detRegion ] * m_E_p1_ID[ vars.m_detRegion ] + m_S_p1_ID[ vars.m_detRegion ] * m_S_p1_ID[ vars.m_detRegion ], 0.5 );
-      p2_ID_var     = pow( m_E_p2_ID[ vars.m_detRegion ] * m_E_p2_ID[ vars.m_detRegion ] + m_S_p2_ID[ vars.m_detRegion ] * m_S_p2_ID[ vars.m_detRegion ], 0.5 );
-      p2_ID_TAN_var = pow( m_E_p2_ID_TAN[ vars.m_detRegion ] * m_E_p2_ID_TAN[ vars.m_detRegion ] + m_S_p2_ID_TAN[ vars.m_detRegion ] * m_S_p2_ID_TAN[ vars.m_detRegion ], 0.5 );
-    } else {//Syst are not more symmetric in the latest release, the stat/sys add in quadrature is already done
-      p1_ID_var     = var > 0. ? m_SUp_p1_ID[ vars.m_detRegion ] : m_SDw_p1_ID[ vars.m_detRegion ];
-      p2_ID_var     = var > 0. ? m_SUp_p2_ID[ vars.m_detRegion ] : m_SDw_p2_ID[ vars.m_detRegion ];
-      p2_ID_TAN_var = var > 0. ? m_SUp_p2_ID_TAN[ vars.m_detRegion ] : m_SDw_p2_ID_TAN[ vars.m_detRegion ];
-    }
-    p1_ID_var     = m_p1_ID[ vars.m_detRegion ] + var * p1_ID_var;
-    p2_ID_var     = m_p2_ID[ vars.m_detRegion ] + var * p2_ID_var;
-    p2_ID_TAN_var = m_p2_ID_TAN[ vars.m_detRegion ] + var * p2_ID_TAN_var;
-
-    if( p1_ID_var < 0. ) p1_ID_var = 0.; //Truncation of unphysical variations
-    if( p2_ID_var < 0. ) p2_ID_var = 0.;
-    if( p2_ID_TAN_var < 0. ) p2_ID_TAN_var = 0.;
-
-    bool useTan2 = true;
-    if( useTan2 && m_p2_ID_TAN[ vars.m_detRegion ] != 0 ) {         
-      newSmear = ( p1_ID_var * vars.m_g3 + p2_ID_TAN_var * vars.m_g4 * vars.m_ptid * sinh( vars.m_eta ) * sinh( vars.m_eta ) );
-    } else {
-      newSmear = ( p1_ID_var * vars.m_g3 + p2_ID_var * vars.m_g4 * vars.m_ptid );
-    }
-    return newSmear;
+    return 0;
   }
-  return 0;
-}
 
 
-  CorrectionCode MuonCalibrationAndSmearingTool::applyStatCombination( xAOD::Muon& mu ) const {
-    
-    //::: Set pt ID:
-    ATH_MSG_VERBOSE( "Retrieving ElementLink to ID TrackParticle..." );
+  CorrectionCode MuonCalibrationAndSmearingTool::applyStatCombination( xAOD::Muon& mu, InfoHelper& muonInfo ) const {
+
+    // Set pt ID:
+    ATH_MSG_VERBOSE( "Stat comb: Retrieving ElementLink to ID TrackParticle..." );
     ATH_MSG_VERBOSE( "mu.isAvailable< ElementLink< xAOD::TrackParticleContainer > >( \"inDetTrackParticleLink\" ) = " << mu.isAvailable< ElementLink< xAOD::TrackParticleContainer > >( "inDetTrackParticleLink" ) );
-    ATH_MSG_VERBOSE( "( mu.inDetTrackParticleLink() == NULL ) = " << ( mu.inDetTrackParticleLink() == NULL ) );
+    ATH_MSG_VERBOSE( "( mu.inDetTrackParticleLink() == nullptr ) = " << ( mu.inDetTrackParticleLink() == nullptr ) );
     ATH_MSG_VERBOSE( "mu.inDetTrackParticleLink() = " << mu.inDetTrackParticleLink() );
     ATH_MSG_VERBOSE( "( mu.inDetTrackParticleLink() ).isValid() = " << ( mu.inDetTrackParticleLink() ).isValid() );
-    
-   
-    if( !( mu.inDetTrackParticleLink() ).isValid() ) 
+
+
+    if( !( mu.inDetTrackParticleLink() ).isValid() )
       return CorrectionCode::Error;
-    
+
     const ElementLink< xAOD::TrackParticleContainer >& id_track=mu.inDetTrackParticleLink();
 
-    //::: Set pt MS:
-    
-    ATH_MSG_VERBOSE( "Retrieving ElementLink to MS TrackParticle..." );
+    // Set pt MS:
+
+    ATH_MSG_VERBOSE( "Stat comb: Retrieving ElementLink to MS TrackParticle..." );
     ATH_MSG_VERBOSE( "mu.isAvailable< ElementLink< xAOD::TrackParticleContainer > >( \"extrapolatedMuonSpectrometerTrackParticleLink\" ) = " << mu.isAvailable< ElementLink< xAOD::TrackParticleContainer > >( "extrapolatedMuonSpectrometerTrackParticleLink" ) );
-    ATH_MSG_VERBOSE( "( mu.extrapolatedMuonSpectrometerTrackParticleLink() == NULL ) = " << ( mu.extrapolatedMuonSpectrometerTrackParticleLink() == NULL ) );
+    ATH_MSG_VERBOSE( "( mu.extrapolatedMuonSpectrometerTrackParticleLink() == nullptr ) = " << ( mu.extrapolatedMuonSpectrometerTrackParticleLink() == nullptr ) );
     ATH_MSG_VERBOSE( "mu.extrapolatedMuonSpectrometerTrackParticleLink() = " << mu.extrapolatedMuonSpectrometerTrackParticleLink() );
     ATH_MSG_VERBOSE( "( mu.extrapolatedMuonSpectrometerTrackParticleLink() ).isValid() = " << ( mu.extrapolatedMuonSpectrometerTrackParticleLink() ).isValid() );
-    
-  if( !( mu.extrapolatedMuonSpectrometerTrackParticleLink() ).isValid() ) 
-    return CorrectionCode::Error;
-  
-  const ElementLink< xAOD::TrackParticleContainer >& ms_track = mu.extrapolatedMuonSpectrometerTrackParticleLink();
-
-  //::: Set the charge 
-  int charge = mu.charge();
-
-  AmgVector(5) parsCB;
-  AmgSymMatrix(5) covCB;
-  double chi2;
-  
-  if(applyStatCombination(id_track,ms_track,charge,parsCB,covCB,chi2)!=CorrectionCode::Ok) 
-    return CorrectionCode::Error;
-  
-  mu.auxdata< AmgVector(5) >( "StatCombCBPars" ) = parsCB;
-  mu.auxdata< AmgSymMatrix(5) >( "StatCombCBCovariance" ) = covCB;
-  mu.auxdata< double > ("StatCombChi2") = chi2; 
-  
-  return CorrectionCode::Ok;
-  }  
-
-  CorrectionCode MuonCalibrationAndSmearingTool::applyStatCombination( const ElementLink< xAOD::TrackParticleContainer >& inDetTrackParticle, 
+
+    if( !( mu.extrapolatedMuonSpectrometerTrackParticleLink() ).isValid() )
+      return CorrectionCode::Error;
+
+    const ElementLink< xAOD::TrackParticleContainer >& ms_track = mu.extrapolatedMuonSpectrometerTrackParticleLink();
+
+    // Set the charge
+    int charge = mu.charge();
+
+    // SAF specifics
+    if( mu.muonType() == xAOD::Muon::SiliconAssociatedForwardMuon ) {
+      if( mu.isAvailable<ElementLink<xAOD::TrackParticleContainer > > ("combinedTrackParticleLink")){
+        if(mu.combinedTrackParticleLink().isValid()){
+          if(mu.combinedTrackParticleLink().isValid()){
+            const ElementLink< xAOD::TrackParticleContainer >& cb_track = mu.combinedTrackParticleLink();
+            muonInfo.charge = ( *cb_track )->charge();
+          }
+        }
+      }}
+
+    const xAOD::TrackParticle*       cbtrack = mu.trackParticle( xAOD::Muon::CombinedTrackParticle );
+    AmgVector(5) parsCB=cbtrack->definingParameters();
+    AmgSymMatrix(5) covCB=cbtrack->definingParametersCovMatrix();
+    double chi2=-999;
+
+
+    if(applyStatCombination(id_track,ms_track,charge,parsCB,covCB,chi2)!=CorrectionCode::Ok)
+      return CorrectionCode::Error;
+
+    muonInfo.cbParsA.clear();
+    muonInfo.cbCovMat.clear();
+
+    for(unsigned int i=0 ; i < 5; i++)
+      muonInfo.cbParsA.push_back(parsCB[i]);
+
+    for(unsigned int i=0 ; i < 5; i++)
+      for(unsigned int j=0 ; j < 5; j++)
+        muonInfo.cbCovMat.push_back(covCB(i,j));
+
+    if(m_doNotUseAMGMATRIXDECOR){
+      mu.auxdata< std::vector <float> > ( "StatCombCBParsVector" ) =  muonInfo.cbParsA;
+      mu.auxdata< std::vector <float > > ( "StatCombCBCovarianceVector" ) = muonInfo.cbCovMat;
+    }
+    if(!m_doNotUseAMGMATRIXDECOR){
+      mu.auxdata< AmgVector(5) >( "StatCombCBPars" ) = parsCB;
+      mu.auxdata< AmgSymMatrix(5) >( "StatCombCBCovariance" ) = covCB;
+    }
+    mu.auxdata< double > ("StatCombChi2") = chi2;
+
+    return CorrectionCode::Ok;
+  }
+
+  CorrectionCode MuonCalibrationAndSmearingTool::applyStatCombination( const ElementLink< xAOD::TrackParticleContainer >& inDetTrackParticle,
                                                                        const ElementLink< xAOD::TrackParticleContainer >& extrTrackParticle,
                                                                        int charge,
                                                                        AmgVector(5)& parsCB,
                                                                        AmgSymMatrix(5)& covCB,
-                                                                       double& chi2) const
-  {
-    
+                                                                       double& chi2) const {
+
     chi2   = 1e20;
     AmgVector(5) parsID = (*inDetTrackParticle)->definingParameters();
-    parsID[4] = fabs(parsID[4]);
+    parsID[4] = std::fabs(parsID[4]);
 
     AmgVector(5) parsMS = (*extrTrackParticle)->definingParameters();
-    //int chargeMS = parsMS[4]/fabs(parsMS[4]);
-    parsMS[4] = fabs(parsMS[4]);
-    
+    parsMS[4] = std::fabs(parsMS[4]);
+
     AmgSymMatrix(5) covID = (*inDetTrackParticle)->definingParametersCovMatrix();
-    
+
     const AmgSymMatrix(5)  weightID = covID.inverse();
     if  ( weightID.determinant() == 0 ){
       ATH_MSG_WARNING( " ID weight matrix computation failed     " ) ;
@@ -2391,62 +2766,68 @@ double MuonCalibrationAndSmearingTool::GetSystVariation( const Vars& vars,
 
     AmgSymMatrix(5) covMS = (*extrTrackParticle)->definingParametersCovMatrix();
 
-    // Error inflation to account for ID-MS misaligment
-    double dSigma[5] = { 1.0, 2.0/sin(parsMS[3]), 0.001, 0.001, 0.0};
-    double factor[5];
-    for ( int i = 0; i<5 ; i++ ) {
-      factor[i] = sqrt((covMS(i,i)+dSigma[i]*dSigma[i])/covMS(i,i));
-    }
-    for ( int i = 0 ; i<5 ; i++ ) {
-      for ( int j = 0 ; j<5 ; j++ ) {
-        if ( i==j ) {
-          covMS(i,j) = covMS(i,j)*factor[i]*factor[j];
-	}
-      }
-    }
-
     const AmgSymMatrix(5)  weightMS = covMS.inverse();
     if  ( weightMS.determinant() == 0 ){
       ATH_MSG_WARNING( "weightMS computation failed      " ) ;
       return CorrectionCode::Error;
-        }
-    
+    }
+
     AmgSymMatrix(5) weightCB = weightID + weightMS ;
     covCB = weightCB.inverse();
     if (covCB.determinant() == 0){
       ATH_MSG_WARNING( " Inversion of weightCB failed " ) ;
       return CorrectionCode::Error;
-        }
- 
-    //std::cout<<"CB covariance: "<<std::endl<<covCB<<std::endl;
-    
+    }
+
+
     AmgSymMatrix(5) covSum = covID + covMS ;
     AmgSymMatrix(5) invCovSum = covSum.inverse();
- 
-  if (invCovSum.determinant() == 0){
-	    ATH_MSG_WARNING( " Inversion of covSum failed " ) ;
-        return CorrectionCode::Error;
-	  } 
- 
- double  diffPhi = parsMS[2] - parsID[2] ;
- if(diffPhi>M_PI)       parsMS[2] -= 2.*M_PI;
- else if(diffPhi<-M_PI) parsMS[2] += 2.*M_PI;
- 
- AmgVector(5) diffPars = parsID - parsMS;
- chi2 = diffPars.transpose() * invCovSum * diffPars;
- chi2 = chi2/5. ;
- 
- parsCB = covCB * ( weightID * parsID + weightMS * parsMS ) ;
- parsCB[4] *= charge;
-
- if(parsCB[2]>M_PI)       parsCB[2] -= 2.*M_PI;
- else if(parsCB[2]<-M_PI) parsCB[2] += 2.*M_PI;
- return CorrectionCode::Ok;
+
+    if (invCovSum.determinant() == 0){
+      ATH_MSG_WARNING( " Inversion of covSum failed " ) ;
+      return CorrectionCode::Error;
+    }
+
+    double  diffPhi = parsMS[2] - parsID[2] ;
+    if(diffPhi>M_PI)       parsMS[2] -= 2.*M_PI;
+    else if(diffPhi<-M_PI) parsMS[2] += 2.*M_PI;
+
+    AmgVector(5) diffPars = parsID - parsMS;
+    chi2 = diffPars.transpose() * invCovSum * diffPars;
+    chi2 = chi2/5. ;
+
+    parsCB = covCB * ( weightID * parsID + weightMS * parsMS ) ;
+    parsCB[4] *= charge;
+
+    if(parsCB[2]>M_PI)       parsCB[2] -= 2.*M_PI;
+    else if(parsCB[2]<-M_PI) parsCB[2] += 2.*M_PI;
+    return CorrectionCode::Ok;
   }
-  
-  void MuonCalibrationAndSmearingTool::setUseStatCombination(bool flag){
-    m_useStatComb=flag;
+
+  bool MuonCalibrationAndSmearingTool::isBadMuon( const xAOD::Muon& mu, InfoHelper& muonInfo ) const {
+
+    if( mu.muonType() != xAOD::Muon::Combined ) return false;
+    // ::
+    const xAOD::TrackParticle*       idtrack = mu.trackParticle( xAOD::Muon::InnerDetectorTrackParticle );
+    const xAOD::TrackParticle*       metrack = mu.trackParticle( xAOD::Muon::ExtrapolatedMuonSpectrometerTrackParticle );
+    const xAOD::TrackParticle*       cbtrack = mu.trackParticle( xAOD::Muon::CombinedTrackParticle );
+
+    // ::
+    bool IsBadMuon = false;
+    if( idtrack && metrack && cbtrack ) {
+      ATH_MSG_VERBOSE("ME ERROR "<<std::sqrt( metrack->definingParametersCovMatrix()(4,4) )<<" ID ERROR"<<std::sqrt( idtrack->definingParametersCovMatrix()(4,4) )<<" CB error "<<sqrt( cbtrack->definingParametersCovMatrix()(4,4) ));
+      // ::
+      double qOverP_ME = metrack->qOverP();
+      double qOverPerr_ME = std::sqrt( metrack->definingParametersCovMatrix()(4,4) );
+      // ::
+      // recipe for high-pt selection
+      ATH_MSG_VERBOSE("fabs("<<qOverPerr_ME<<"/"<<qOverP_ME<<") < sqrt( pow(8/"<<muonInfo.ptms<<",2) + pow(0.07,2) + pow(0.0005*"<<muonInfo.ptms<<",2))");
+
+      IsBadMuon = std::fabs(qOverPerr_ME / qOverP_ME)<std::sqrt( std::pow(8/muonInfo.ptms,2) + std::pow(0.07,2) + std::pow(0.0005*muonInfo.ptms,2));
+    }
+    ATH_MSG_VERBOSE( std::string(IsBadMuon ? " IS BAD MUON ": " IS GOOD MUON"));
+    return IsBadMuon;
   }
 
-  
+
 } // namespace CP
diff --git a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/Root/MuonCalibrationPeriodTool.cxx b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/Root/MuonCalibrationPeriodTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..586f93bde50b656b280e77b3949eee716bdcbc62
--- /dev/null
+++ b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/Root/MuonCalibrationPeriodTool.cxx
@@ -0,0 +1,305 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+// Local include(s):
+#include <MuonMomentumCorrections/MuonCalibrationPeriodTool.h>
+
+namespace CP {
+
+   unsigned int MuonCalibrationPeriodTool::getPeriod() const {
+        static SG::AuxElement::ConstAccessor<unsigned int> acc_rnd("RandomRunNumber");
+        // I've copied the run number ranges from SUSYTools
+        // https://gitlab.cern.ch/atlas/athena/blob/21.2/PhysicsAnalysis/SUSYPhys/SUSYTools/Root/SUSYObjDef_xAOD.cxx#L2438
+        static const unsigned int last_run_16  = 320000;
+        static const unsigned int last_run_17  = 350000;
+        // Not the appropiate value but okay we can fix it afterwards
+        static const unsigned int last_run_18  = 500000;
+
+        SG::ReadHandle<xAOD::EventInfo> evtInfo(m_eventInfo);
+        bool isData = !evtInfo->eventType(xAOD::EventInfo::IS_SIMULATION);
+        unsigned int run = evtInfo->runNumber();
+        // retrieve the random run number
+        if (!isData && m_useRndRun){
+             if (acc_rnd.isAvailable(*evtInfo)) run = acc_rnd(*evtInfo);
+             else {
+                 ATH_MSG_ERROR("No random runnumber could be found allthough the tool is configured to assign the years based on it. Please make sure to apply the prwTool before-hand or consider to set the property 'useRandomRunNumber' to false.");
+                 return -1;
+             }
+        }
+        // Check the Monte carlo
+        if (!isData &&  (!m_useRndRun || !acc_rnd.isAvailable(*evtInfo)) ){
+            if (std::find(m_MCperiods1516.begin(), m_MCperiods1516.end(),run) != m_MCperiods1516.end()) {
+                ATH_MSG_DEBUG("The current run "<<run<<" corresponds to data mc16a / data15-16");                
+                return 1516;
+            } else if (std::find(m_MCperiods17.begin(), m_MCperiods17.end(),run) != m_MCperiods17.end()) {
+                ATH_MSG_DEBUG("The current run "<<run<<" corresponds to data mc16d / data17");                
+                return 17;
+            } else if (std::find(m_MCperiods18.begin(), m_MCperiods18.end(),run) != m_MCperiods18.end()){ 
+                ATH_MSG_DEBUG("The current run "<<run<<" corresponds to data mc16e / data18");                
+                return 18;
+            }
+        } 
+        // Check data itself or the random run number is used
+        else if (isData || m_useRndRun) {
+            if (run < last_run_16) {
+                ATH_MSG_DEBUG("The current run "<<run<<" is taken in data 15-16");
+                return 1516;
+            } else if (run < last_run_17) {
+                 ATH_MSG_DEBUG("The current run "<<run<<" is taken in data 17");
+                return 17;
+            } else if (run < last_run_18) {
+                ATH_MSG_DEBUG("The current run "<<run<<" is taken in data 18");
+                return 18;
+            }
+        }
+        ATH_MSG_FATAL("Could not assign run-number "<<run<<" to a specific year of data-taking");
+        return -1;
+    }
+   const CP::IMuonCalibrationAndSmearingTool* MuonCalibrationPeriodTool::getTool() const {
+        unsigned int period = getPeriod();
+        if (period ==  1516) return m_calibTool_1516.get();
+        else if (period ==  17) return m_calibTool_17.get();
+        else if (period ==  18) return m_calibTool_18.get();
+        ATH_MSG_WARNING("getTool() - no tool found for period "<<period<<", return nullptr");
+        return nullptr;
+    }
+    StatusCode MuonCalibrationPeriodTool::initialize() {
+        if(m_MCperiods1516.empty()) {
+            ATH_MSG_FATAL("No period numbers have been provided for mc16a");
+            return StatusCode::FAILURE;
+        } else if (m_MCperiods17.empty()){
+            ATH_MSG_FATAL("No period numbers have been provided for mc16d");
+            return StatusCode::FAILURE;
+        } else if (m_MCperiods18.empty()){
+            ATH_MSG_FATAL("No period numbers have been provided for mc16e");
+            return StatusCode::FAILURE;
+        }
+        if (m_useRndRun) ATH_MSG_INFO("The assignment of the calibration tools will be based on the random run number. Please make sure to call the pileup-tool before applying this tool");
+        bool statComb1516(false), sagittaCorr1516(false),sagittaMCDistortion1516(false), sagittaCorrPhaseSpace1516(false);
+        bool statComb17(false), sagittaCorr17(false), sagittaMCDistortion17(false), sagittaCorrPhaseSpace17(false);
+        bool statComb18(false), sagittaCorr18(false), sagittaMCDistortion18(false), sagittaCorrPhaseSpace18(false);
+        
+        if (m_calib_mode == MuonCalibrationPeriodTool::correctData){
+            ATH_MSG_INFO("Data will be corrected for sagitta bias which (recommended setup 1)");
+            statComb1516 = false;
+            sagittaCorr1516 = true;
+            sagittaMCDistortion1516 = false;
+            sagittaCorrPhaseSpace1516 = true;
+            
+            statComb17 = false;
+            sagittaCorr17 = true;
+            sagittaMCDistortion17 = false;
+            sagittaCorrPhaseSpace17 = true;
+            
+            statComb18 = false;
+            sagittaCorr18 = true;
+            sagittaMCDistortion18 = false;
+            sagittaCorrPhaseSpace18 = true;
+            
+        }  else if (m_calib_mode == MuonCalibrationPeriodTool::additionalMCsys){
+            ATH_MSG_INFO("Data will be untouched. Instead an additional systematic will be added (recommended setup 2)");
+            statComb1516 = false;
+            sagittaCorr1516 = false;
+            sagittaMCDistortion1516 = true;
+            sagittaCorrPhaseSpace1516 = false;
+            
+            statComb17 = false;
+            sagittaCorr17 = false;
+            sagittaMCDistortion17 = true;
+            sagittaCorrPhaseSpace17 = false;
+            
+            statComb18 = false;
+            sagittaCorr18 = false;
+            sagittaMCDistortion18 = true;
+            sagittaCorrPhaseSpace18 = false; 
+        } else if (m_calib_mode == MuonCalibrationPeriodTool::expert){
+          ATH_MSG_INFO("You've choosen the expert mode and overwrite each property for yourself.");
+            statComb1516 = m_StatComb1516;
+            sagittaCorr1516 = m_SagittaCorr1516;
+            sagittaMCDistortion1516 = m_SagittaMCDistortion1516;
+            sagittaCorrPhaseSpace1516 = m_SagittaCorrPhaseSpace1516;
+            
+            statComb17 = m_StatComb17;
+            sagittaCorr17 = m_SagittaCorr17;
+            sagittaMCDistortion17 = m_SagittaMCDistortion17;
+            sagittaCorrPhaseSpace17 = m_SagittaCorrPhaseSpace17;
+            
+            statComb18 = m_StatComb18;
+            sagittaCorr18 = m_SagittaCorr18;
+            sagittaMCDistortion18 = m_SagittaMCDistortion18;
+            sagittaCorrPhaseSpace18 = m_SagittaCorrPhaseSpace18;
+        
+        } else{
+            ATH_MSG_FATAL("Invalid  calibration mode: "<<m_calib_mode<<" Allowed modes are correctData("<<MuonCalibrationPeriodTool::correctData
+                            <<") additionalMCsys ("<<MuonCalibrationPeriodTool::additionalMCsys<<") or expert ("<<MuonCalibrationPeriodTool::expert<<")");
+            return StatusCode::FAILURE;
+        }
+        
+        if (!m_calibTool_1516.isUserConfigured()){
+            ATH_MSG_INFO("Setup the MuonMomentum calibration tool for 2015-2016 & mc16a");
+            m_calibTool_1516.setTypeAndName("CP::MuonCalibrationAndSmearingTool/"+name()+"_1516");
+            ATH_CHECK(m_calibTool_1516.setProperty("Year", "Data16"));
+            ATH_CHECK(m_calibTool_1516.setProperty("Release", m_release));
+            ATH_CHECK(m_calibTool_1516.setProperty("SagittaRelease", m_sagittaRelease1516));
+            ATH_CHECK(m_calibTool_1516.setProperty("StatComb", statComb1516));
+            ATH_CHECK(m_calibTool_1516.setProperty("SagittaCorr", sagittaCorr1516));
+            ATH_CHECK(m_calibTool_1516.setProperty("doSagittaMCDistortion", sagittaMCDistortion1516));
+            ATH_CHECK(m_calibTool_1516.setProperty("SagittaCorrPhaseSpace", sagittaCorrPhaseSpace1516));
+        }
+        if (!m_calibTool_17.isUserConfigured()){
+            ATH_MSG_INFO("Setup the MuonMomentum calibration tool for 2017 & mc16c/d");
+            m_calibTool_17.setTypeAndName("CP::MuonCalibrationAndSmearingTool/"+name()+"_17");
+            ATH_CHECK(m_calibTool_17.setProperty("Year", "Data17"));
+            ATH_CHECK(m_calibTool_17.setProperty("Release", m_release));
+            ATH_CHECK(m_calibTool_17.setProperty("SagittaRelease", m_sagittaRelease17));
+            ATH_CHECK(m_calibTool_17.setProperty("StatComb", statComb17));
+            ATH_CHECK(m_calibTool_17.setProperty("SagittaCorr", sagittaCorr17));
+            ATH_CHECK(m_calibTool_17.setProperty("doSagittaMCDistortion", sagittaMCDistortion17));
+            ATH_CHECK(m_calibTool_17.setProperty("SagittaCorrPhaseSpace", sagittaCorrPhaseSpace17));
+        }
+        if (!m_calibTool_18.isUserConfigured()){
+            ATH_MSG_INFO("Setup the MuonMomentum calibration tool for 2018 & mc16e");
+            m_calibTool_18.setTypeAndName("CP::MuonCalibrationAndSmearingTool/"+name()+"_18");
+            ATH_CHECK(m_calibTool_18.setProperty("Year", "Data18"));
+            ATH_CHECK(m_calibTool_18.setProperty("Release", m_release));
+            ATH_CHECK(m_calibTool_18.setProperty("SagittaRelease", m_sagittaRelease18));
+            ATH_CHECK(m_calibTool_18.setProperty("StatComb", statComb18));
+            ATH_CHECK(m_calibTool_18.setProperty("SagittaCorr", sagittaCorr18));
+            ATH_CHECK(m_calibTool_18.setProperty("doSagittaMCDistortion", sagittaMCDistortion18));
+            ATH_CHECK(m_calibTool_18.setProperty("SagittaCorrPhaseSpace", sagittaCorrPhaseSpace18));
+        }
+        
+        ATH_CHECK(m_calibTool_1516.retrieve());
+        ATH_CHECK(m_calibTool_17.retrieve());
+        ATH_CHECK(m_calibTool_18.retrieve());
+        return StatusCode::SUCCESS;
+    }
+    
+  MuonCalibrationPeriodTool::MuonCalibrationPeriodTool( const std::string& name ) :
+        asg::AsgMetadataTool( name ),
+        m_calibTool_1516(),
+        m_calibTool_17(),
+        m_calibTool_18(),
+        m_sagittaRelease1516("sagittaBiasDataAll_03_02_19_Data16"),
+        m_sagittaRelease17("sagittaBiasDataAll_03_02_19_Data17"),
+        m_sagittaRelease18("sagittaBiasDataAll_03_02_19_Data18"),
+        m_release("Recs2019_05_30"),
+        m_calib_mode(CalibMode::additionalMCsys),
+        m_StatComb1516(false),
+        m_SagittaCorr1516(true),
+        m_SagittaMCDistortion1516(false),
+        m_SagittaCorrPhaseSpace1516(true),
+        
+        m_StatComb17(false),
+        m_SagittaCorr17(true),
+        m_SagittaMCDistortion17(false),
+        m_SagittaCorrPhaseSpace17(true),        
+        
+        m_StatComb18(false),
+        m_SagittaCorr18(false),
+        m_SagittaMCDistortion18(true),
+        m_SagittaCorrPhaseSpace18(true),
+        
+        m_MCperiods1516(),
+        m_MCperiods17(),
+        m_MCperiods18(),
+        m_useRndRun(true) {
+
+        m_calibTool_1516.declarePropertyFor(this, "CalibrationTool1516", "Parse the configured instance of the calibration tool for 15&16 data or mc16a");
+        m_calibTool_17.declarePropertyFor(this, "CalibrationTool17", "Parse the configured instance of the calibration tool for 17 data or mc16d");
+        m_calibTool_18.declarePropertyFor(this, "CalibrationTool18", "Parse the configured instance of the calibration tool for 18 data or mc16e");
+        declareProperty("calibrationMode", m_calib_mode);
+        
+        // Properties to configure the subtools -- expert only
+        declareProperty("SagittaRelease1516", m_sagittaRelease1516);
+        declareProperty("SagittaRelease17", m_sagittaRelease17);
+        declareProperty("SagittaRelease18", m_sagittaRelease18);
+        declareProperty("Release", m_release);
+        
+        declareProperty("StatComb1516", m_StatComb1516);
+        declareProperty("SagittaCorr1516", m_SagittaCorr1516);
+        declareProperty("doSagittaMCDistortion1516", m_SagittaMCDistortion1516);
+        declareProperty("SagittaCorrPhaseSpace1516", m_SagittaCorrPhaseSpace1516);
+        
+        declareProperty("StatComb17", m_StatComb17);
+        declareProperty("SagittaCorr17", m_SagittaCorr17);
+        declareProperty("doSagittaMCDistortion17", m_SagittaMCDistortion17);
+        declareProperty("SagittaCorrPhaseSpace17", m_SagittaCorrPhaseSpace17);
+        
+        declareProperty("StatComb18", m_StatComb18);
+        declareProperty("SagittaCorr18", m_SagittaCorr18);
+        declareProperty("doSagittaMCDistortion18", m_SagittaMCDistortion18);
+        declareProperty("SagittaCorrPhaseSpace18", m_SagittaCorrPhaseSpace18);
+        
+        declareProperty("MCperiods1516", m_MCperiods1516 = {284500});
+        declareProperty("MCperiods17", m_MCperiods17 = {300000, 304000, 305000});
+        declareProperty("MCperiods18", m_MCperiods18 = {310000});
+        
+        declareProperty("useRandomRunNumber", m_useRndRun);
+        // run 304000/305000 correspond to 13/7 TeV low-mu data in 2017
+    }
+    MuonCalibrationPeriodTool::~MuonCalibrationPeriodTool(){}
+
+    CorrectionCode MuonCalibrationPeriodTool::applyCorrection( xAOD::Muon& mu ) const {
+        const CP::IMuonCalibrationAndSmearingTool* tool = getTool();
+        if (tool == nullptr){
+            ATH_MSG_FATAL("No valid tool has been found to apply the correction of muon with pt: "<<mu.pt()/1.e3<<"  eta: "<<mu.eta()<<" phi: "<<mu.phi());
+            return CorrectionCode::Error;
+        }
+        return tool->applyCorrection(mu);
+    }
+    CorrectionCode MuonCalibrationPeriodTool::correctedCopy( const xAOD::Muon& input, xAOD::Muon*& output ) const {
+        const CP::IMuonCalibrationAndSmearingTool* tool = getTool();
+        if (tool == nullptr){
+            ATH_MSG_FATAL("No valid tool has been found to create the corrected copy of muon with pt: "<<input.pt()/1.e3<<"  eta: "<<input.eta()<<" phi: "<<input.phi());
+            return CorrectionCode::Error;
+        }
+        return tool->correctedCopy(input, output);
+    
+    }
+    CorrectionCode MuonCalibrationPeriodTool::applyCorrectionTrkOnly( xAOD::TrackParticle& inTrk, const int DetType) const {
+        const CP::IMuonCalibrationAndSmearingTool* tool = getTool();
+        if (tool == nullptr){
+            ATH_MSG_FATAL("No valid tool has been found to apply the correction of the track with pt: "<<inTrk.pt()/1.e3<<"  eta: "<<inTrk.eta()<<" phi: "<<inTrk.phi());
+            return CorrectionCode::Error;
+        }
+        return tool->applyCorrectionTrkOnly(inTrk, DetType);        
+    }    
+    double MuonCalibrationPeriodTool::expectedResolution( const std::string& DetType, const xAOD::Muon& mu, const bool mc ) const {
+        const CP::IMuonCalibrationAndSmearingTool* tool = getTool();
+        if (tool == nullptr){
+            ATH_MSG_FATAL("No valid tool has been found to predict the resolution of muon with pt: "<<mu.pt()/1.e3<<"  eta: "<<mu.eta()<<" phi: "<<mu.phi());
+            throw std::runtime_error(Form("No valid tool has been found to predict the resolution of muon with pt: %.3f eta: %.2f phi: %.2f",mu.pt()/1.e3,mu.eta(), mu.phi()));
+            return std::nan("float");
+        }
+        return tool->expectedResolution(DetType,mu,mc);
+    }
+    double MuonCalibrationPeriodTool::expectedResolution( const int& DetType, const xAOD::Muon& mu, const bool mc ) const {
+        const CP::IMuonCalibrationAndSmearingTool* tool = getTool();
+        if (tool == nullptr){
+            ATH_MSG_FATAL("No valid tool has been found to predict the resolution of muon with pt: "<<mu.pt()/1.e3<<"  eta: "<<mu.eta()<<" phi: "<<mu.phi());
+            throw std::runtime_error(Form("No valid tool has been found to predict the resolution of muon with pt: %.3f eta: %.2f phi: %.2f",mu.pt()/1.e3,mu.eta(), mu.phi()));
+            return std::nan("float");
+        }
+        return tool->expectedResolution(DetType,mu,mc);
+    }
+    // Systematics do not change throughout the year. So let's take the ones given by 1516 tool
+    bool MuonCalibrationPeriodTool::isAffectedBySystematic( const SystematicVariation& systematic ) const {
+        return m_calibTool_1516->isAffectedBySystematic(systematic);
+    }
+    SystematicSet MuonCalibrationPeriodTool::affectingSystematics() const {
+        return m_calibTool_1516->affectingSystematics();
+    }
+    SystematicSet MuonCalibrationPeriodTool::recommendedSystematics() const {
+        return m_calibTool_1516->recommendedSystematics();
+    }
+    // We need to parse the variations to all three instances because we do not know whether the file changes in the backgronud
+    // during the variation loop
+    SystematicCode MuonCalibrationPeriodTool::applySystematicVariation ( const SystematicSet& systConfig ) {
+        if (m_calibTool_1516->applySystematicVariation(systConfig) == SystematicCode::Unsupported) {}
+        if (m_calibTool_17->applySystematicVariation(systConfig) == SystematicCode::Unsupported) {}
+        return m_calibTool_18->applySystematicVariation(systConfig);
+    }
+
+} // namespace CP
diff --git a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/src/CalibratedMuonsProvider.cxx b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/src/CalibratedMuonsProvider.cxx
index 18e0279b811e1fd5a61a85abd02413dc54ef884d..e2507dd82d41c0dee825948163173ed654f10464 100644
--- a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/src/CalibratedMuonsProvider.cxx
+++ b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/src/CalibratedMuonsProvider.cxx
@@ -1,41 +1,48 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
-
 #include "xAODMuon/MuonContainer.h"
 
 // Local include(s):
 #include "CalibratedMuonsProvider.h"
 #include "xAODCore/ShallowCopy.h"
 #include "xAODBase/IParticleHelpers.h"
+#include "xAODEventInfo/EventInfo.h"
 
 namespace CP {
-
-static const SG::AuxElement::Accessor<ElementLink<xAOD::IParticleContainer> > origLinkAcc("originalObjectLink");
-
-CalibratedMuonsProvider::CalibratedMuonsProvider( const std::string& name, ISvcLocator* svcLoc )
-      : AthAlgorithm( name, svcLoc ),
-         m_tool( "CP::MuonCalibrationAndSmearingTool/MuonCalibrationAndSmearingTool")
-{
+static SG::AuxElement::ConstAccessor<unsigned int> acc_rnd("RandomRunNumber");
+ 
+CalibratedMuonsProvider::CalibratedMuonsProvider( const std::string& name, ISvcLocator* svcLoc ):
+       AthAlgorithm( name, svcLoc ),
+         m_tool( "CP::MuonCalibrationPeriodTool/MuonCalibrationAndSmearingTool"),
+         m_prwTool(""),
+         m_useRndNumber(false) {
       declareProperty( "Input", m_inputKey = "Muons" );
       declareProperty( "Output", m_outputKey = "CalibratedMuons"); 
       declareProperty( "Tool", m_tool );
+      declareProperty( "prwTool", m_prwTool );
+      
 
 
 }
 
 StatusCode CalibratedMuonsProvider::initialize() {
       ATH_CHECK( m_tool.retrieve() );
+      if (!m_prwTool.empty()){
+         m_useRndNumber = true;
+         ATH_MSG_DEBUG("prwTool is given assume that the selection of the periods is based on the random run number");
+         ATH_CHECK(m_prwTool.retrieve());
+      }
       return StatusCode::SUCCESS;
 }
 
 StatusCode CalibratedMuonsProvider::execute() {
-
+       
       xAOD::MuonContainer* nonconst_muons = 0;
       const xAOD::MuonContainer* muons = 0;
       std::pair< xAOD::MuonContainer*, xAOD::ShallowAuxContainer* > out;
-
+    
       if(m_inputKey==m_outputKey) { //attempt to modify in-situ, but must retrieve as non-const
          CHECK( evtStore()->retrieve( nonconst_muons, m_inputKey ) );
               muons = nonconst_muons;
@@ -43,28 +50,31 @@ StatusCode CalibratedMuonsProvider::execute() {
       } else {
          CHECK( evtStore()->retrieve( muons, m_inputKey ) );
          out = xAOD::shallowCopyContainer( *muons );
+         //record to storegate 
+         CHECK( evtStore()->record( out.first, m_outputKey ) );
+         CHECK( evtStore()->record( out.second, m_outputKey+"Aux.") );
          //add original object link to met recalculations work
          if(!setOriginalObjectLink( *muons, *out.first )) { 
             ATH_MSG_ERROR("Failed to add original object links to shallow copy of " << m_inputKey);
             return StatusCode::FAILURE;
          }  
       }
-      
+      if (m_useRndNumber) {
+            const xAOD::EventInfo* evInfo = nullptr;
+            ATH_CHECK(evtStore()->retrieve(evInfo, "EventInfo"));
+            if (!evInfo->eventType(xAOD::EventInfo::IS_SIMULATION)) {
+                m_useRndNumber = false;
+                ATH_MSG_DEBUG("On data no random run number is needed.");
+            } else if (!acc_rnd.isAvailable(*evInfo)){
+                 ATH_MSG_DEBUG("Apply the prw tool");
+                 ATH_CHECK(m_prwTool->apply(*evInfo));
+            }
+      }      
       for(auto iParticle : *(out.first)) {
-//          if(m_inputKey!=m_outputKey && !muons->isAvailable< ElementLink<xAOD::IParticleContainer> >("originalObjectLink")) {
-// 	   const ElementLink<xAOD::IParticleContainer> link( *muons , iParticle->index() );
-//             origLinkAcc(*iParticle) = link;
-//             //iParticle->auxdecor< ElementLink<xAOD::IParticleContainer>  >("originalObjectLink") = link;
-//          }
-         
-         if(msg().level()==MSG::VERBOSE) std::cout << name() << " Old pt=" << iParticle->pt();
+         ATH_MSG_DEBUG(" Old pt=" << iParticle->pt());
          if(m_tool->applyCorrection(*iParticle).code()==CorrectionCode::Error) return StatusCode::FAILURE;
-         if(msg().level()==MSG::VERBOSE) std::cout << " New pt=" << iParticle->pt() << std::endl;
-      }
-
-      //record to storegate 
-      CHECK( evtStore()->record( out.first, m_outputKey ) );
-      CHECK( evtStore()->record( out.second, m_outputKey+"Aux.") );
+         ATH_MSG_DEBUG(" New pt=" << iParticle->pt());
+     }
 
 
       // Return gracefully:
diff --git a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/src/CalibratedMuonsProvider.h b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/src/CalibratedMuonsProvider.h
index 1c52a6c0f9b516655bca65cddadecd2afe0cd881..b88531668eb866914512c532d399e19e7f8ba8f1 100644
--- a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/src/CalibratedMuonsProvider.h
+++ b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/src/CalibratedMuonsProvider.h
@@ -1,7 +1,5 @@
-// Dear emacs, this is -*- c++ -*-
-
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef CALIBRATEDMUONSPROVIDER
@@ -12,8 +10,8 @@
 #include "AthenaBaseComps/AthAlgorithm.h"
 #include "GaudiKernel/ToolHandle.h"
 
-#include "MuonMomentumCorrections/IMuonCalibrationAndSmearingTool.h"
-
+#include "MuonAnalysisInterfaces/IMuonCalibrationAndSmearingTool.h"
+#include <AsgAnalysisInterfaces/IPileupReweightingTool.h>
 
 namespace CP {
 
@@ -35,7 +33,9 @@ namespace CP {
       std::string m_inputKey,m_outputKey;
 
       /// Scale factor tool
-      ToolHandle< IMuonCalibrationAndSmearingTool > m_tool;
+      ToolHandle <IMuonCalibrationAndSmearingTool > m_tool;
+      ToolHandle <IPileupReweightingTool> m_prwTool;
+      bool m_useRndNumber;
 
    }; // class 
 
diff --git a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/src/CalibratedTracksProvider.cxx b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/src/CalibratedTracksProvider.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..577ce7461c332ad74536273a805caa885bf7ff6d
--- /dev/null
+++ b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/src/CalibratedTracksProvider.cxx
@@ -0,0 +1,83 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "xAODTracking/TrackParticleContainer.h"
+
+// Local include(s):
+#include "CalibratedTracksProvider.h"
+#include "xAODCore/ShallowCopy.h"
+#include "xAODBase/IParticleHelpers.h"
+#include "xAODEventInfo/EventInfo.h"
+
+namespace CP {
+
+static SG::AuxElement::ConstAccessor<unsigned int> acc_rnd("RandomRunNumber");
+CalibratedTracksProvider::CalibratedTracksProvider( const std::string& name, ISvcLocator* svcLoc ): 
+         AthAlgorithm( name, svcLoc ),
+         m_tool( "CP::MuonCalibrationPeriodTool/MuonCalibrationAndSmearingTool"),
+         m_prwTool(""),         
+         m_detType(2), // MS = 1, ID = 2
+         m_useRndNumber(false) {
+      declareProperty( "Input", m_inputKey = "InDetTrackParticles" ); // or ExtrapolatedMuonTrackParticles
+      declareProperty( "Output", m_outputKey = "CalibratedInDetTrackParticles");
+      declareProperty( "Tool", m_tool );
+      declareProperty( "prwTool", m_prwTool );      
+      declareProperty( "DetType", m_detType );
+
+}
+
+StatusCode CalibratedTracksProvider::initialize() {
+      ATH_CHECK( m_tool.retrieve());
+       if (!m_prwTool.empty()){
+         m_useRndNumber = true;
+         ATH_MSG_DEBUG("prwTool is given assume that the selection of the periods is based on the random run number");
+         ATH_CHECK(m_prwTool.retrieve());
+      }
+      return StatusCode::SUCCESS;
+}
+
+StatusCode CalibratedTracksProvider::execute() {
+
+      xAOD::TrackParticleContainer* nonconst_tracks = 0;
+      const xAOD::TrackParticleContainer* tracks = 0;
+      std::pair< xAOD::TrackParticleContainer*, xAOD::ShallowAuxContainer* > out;
+
+      if(m_inputKey==m_outputKey) { //attempt to modify in-situ, but must retrieve as non-const
+         CHECK( evtStore()->retrieve( nonconst_tracks, m_inputKey ) );
+              tracks = nonconst_tracks;
+               out.first = nonconst_tracks;
+      } else {
+         CHECK( evtStore()->retrieve( tracks, m_inputKey ) );
+         out = xAOD::shallowCopyContainer( *tracks );
+         //record to storegate 
+         CHECK( evtStore()->record( out.first, m_outputKey ) );
+         CHECK( evtStore()->record( out.second, m_outputKey+"Aux.") );
+         //add original object link to met recalculations work
+         if(!setOriginalObjectLink( *tracks, *out.first )) { 
+            ATH_MSG_ERROR("Failed to add original object links to shallow copy of " << m_inputKey);
+            return StatusCode::FAILURE;
+         }  
+      }
+      if (m_useRndNumber) {
+            const xAOD::EventInfo* evInfo = nullptr;
+            ATH_CHECK(evtStore()->retrieve(evInfo, "EventInfo"));
+            if (!evInfo->eventType(xAOD::EventInfo::IS_SIMULATION)) {
+                m_useRndNumber = false;
+                ATH_MSG_DEBUG("On data no random run number is needed.");
+            } else if (!acc_rnd.isAvailable(*evInfo)){
+                 ATH_MSG_DEBUG("Apply the prw tool");
+                 ATH_CHECK(m_prwTool->apply(*evInfo));
+            }
+      }
+      for(auto iParticle : *(out.first)) {
+        ATH_MSG_VERBOSE("Old pt=" << iParticle->pt());
+        if(m_tool->applyCorrectionTrkOnly(*iParticle, m_detType).code()==CorrectionCode::Error) return StatusCode::FAILURE;
+        ATH_MSG_VERBOSE("New pt=" << iParticle->pt());
+      }
+
+      // Return gracefully:
+      return StatusCode::SUCCESS;
+   }
+
+} // namespace CP
diff --git a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/src/CalibratedTracksProvider.h b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/src/CalibratedTracksProvider.h
new file mode 100644
index 0000000000000000000000000000000000000000..ecd7531913175348f79b4ca6ecb85d7a725a0634
--- /dev/null
+++ b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/src/CalibratedTracksProvider.h
@@ -0,0 +1,46 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef CALIBRATEDTRACKSPROVIDER
+#define CALIBRATEDTRACKSPROVIDER
+
+// Gaudi/Athena include(s):
+#include "AthenaBaseComps/AthAlgorithm.h"
+#include "GaudiKernel/ToolHandle.h"
+
+#include "MuonAnalysisInterfaces/IMuonCalibrationAndSmearingTool.h"
+#include <AsgAnalysisInterfaces/IPileupReweightingTool.h>
+
+namespace CP {
+
+   /// decorates a track collection with efficiency and scale factor
+
+   class CalibratedTracksProvider : public AthAlgorithm {
+
+   public:
+      /// Regular Algorithm constructor
+       CalibratedTracksProvider( const std::string& name, ISvcLocator* svcLoc );
+
+      /// Function initialising the algorithm
+      virtual StatusCode initialize();
+      /// Function executing the algorithm
+      virtual StatusCode execute();
+
+   private:
+      /// track container
+      std::string m_inputKey,m_outputKey;
+
+      ///Calibration tool handle
+      ToolHandle<IMuonCalibrationAndSmearingTool > m_tool;
+      ToolHandle<IPileupReweightingTool> m_prwTool;
+
+      /// detector type of track (MS or ID)
+      int m_detType;
+      bool m_useRndNumber;
+
+   }; // class 
+
+} // namespace CP
+
+#endif //
diff --git a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/src/TestMCASTTool.h b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/src/TestMCASTTool.h
index 6d5c03d16d53fd67321e59ff9cd5936355b56e5b..e59d97167a128f5cf82db882d0093d42d25aa492 100644
--- a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/src/TestMCASTTool.h
+++ b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/src/TestMCASTTool.h
@@ -10,7 +10,7 @@
 #include "GaudiKernel/ToolHandle.h"
 
 // Local include(s):
-#include "MuonMomentumCorrections/IMuonCalibrationAndSmearingTool.h"
+#include "MuonAnalysisInterfaces/IMuonCalibrationAndSmearingTool.h"
 #include "MuonAnalysisInterfaces/IMuonSelectionTool.h"
 
 // Root include(s)
diff --git a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/src/components/MuonCalibrationAndSmearing_entries.cxx b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/src/components/MuonCalibrationAndSmearing_entries.cxx
index 6516d336096460bc5116420e2cc2441868c7323a..9422b52bc54b0e6d0d54a5d579bc01f7e102961b 100644
--- a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/src/components/MuonCalibrationAndSmearing_entries.cxx
+++ b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/src/components/MuonCalibrationAndSmearing_entries.cxx
@@ -1,9 +1,17 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
 #include "MuonMomentumCorrections/MuonCalibrationAndSmearingTool.h"
+#include "MuonMomentumCorrections/MuonCalibrationPeriodTool.h"
 
 #include "../TestMCASTTool.h"
 #include "../CalibratedMuonsProvider.h"
+#include "../CalibratedTracksProvider.h"
 
 DECLARE_COMPONENT( CP::MuonCalibrationAndSmearingTool )
+DECLARE_COMPONENT( CP::MuonCalibrationPeriodTool )
 DECLARE_COMPONENT( CP::TestMCASTTool )
 DECLARE_COMPONENT( CP::CalibratedMuonsProvider )
+DECLARE_COMPONENT( CP::CalibratedTracksProvider )
 
diff --git a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/util/MCAST_Tester.cxx b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/util/MCAST_Tester.cxx
index 354fd61d4acda30d99389c0ed889c1dbc420aae5..abfa28de33d76a1ab29b5ada6af40402e0e35b5f 100644
--- a/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/util/MCAST_Tester.cxx
+++ b/PhysicsAnalysis/MuonID/MuonIDAnalysis/MuonMomentumCorrections/util/MCAST_Tester.cxx
@@ -1,17 +1,20 @@
 /*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 // System include(s):
 #include <memory>
 #include <cstdlib>
+#include <string>
 #include <unordered_map>
 
+
 // ROOT include(s):
 #include <TFile.h>
 #include <TError.h>
 #include <TString.h>
 #include <TTree.h>
+#include <TChain.h>
 
 // Infrastructure include(s):
 #include "xAODRootAccess/Init.h"
@@ -28,60 +31,91 @@
 #include "xAODCore/tools/IOStats.h"
 #include "xAODCore/tools/ReadStats.h"
 #include "AsgTools/Check.h"
+#include "AsgTools/AnaToolHandle.h"
 
 #include "PATInterfaces/SystematicCode.h"
 
 // Local include(s):
+
+// calibration
+#include "MuonAnalysisInterfaces/IMuonCalibrationAndSmearingTool.h"
 #include "MuonMomentumCorrections/MuonCalibrationAndSmearingTool.h"
+
+// selection
+#include "MuonAnalysisInterfaces/IMuonSelectionTool.h"
 #include "MuonSelectorTools/MuonSelectionTool.h"
-#include <string>
+
+
 
 using namespace std;
 
 int main( int argc, char* argv[] ) {
 
-  bool do_it_the_right_way = false;
-  //::: The application's name:
+  bool useCorrectedCopy = false;
+
+  // The application's name:
   const char* APP_NAME = argv[ 0 ];
 
-  //::: Check if we received a file name:
+  // Check if we received a file name:
   if( argc < 2 ) {
+    Error( APP_NAME, "==============================================" );
     Error( APP_NAME, "No file name received!" );
-    Error( APP_NAME, "  Usage: %s [xAOD file name]", APP_NAME );
+    Error( APP_NAME, "Usage: $> %s [xAOD file name]", APP_NAME );
+    Error( APP_NAME, " $> %s [xAOD file name]", APP_NAME );
+    Error( APP_NAME, " $> %s [xAOD file name] -n X  |  X = number of events you want to run on", APP_NAME );
+    Error( APP_NAME, " $> %s [xAOD file name] -event X  |  X = specific number of the event to run on - for debugging", APP_NAME );
+    Error( APP_NAME, "==============================================" );
     return 1;
   }
 
+  ////////////////////////////////////////////////////
+  //:::  parse the options
+  ////////////////////////////////////////////////////
   string options;
-  for( int i=0; i<argc; i++)   { options+=(argv[i]);  }
-  
+  for( int i=0; i<argc; i++){
+    options+=(argv[i]);
+  }
+
   int Ievent=-1;
   if(options.find("-event")!=string::npos){
-  for( int ipos=0; ipos<argc ; ipos++ ) {
-    if (string(argv[ipos]).compare("-event")==0)
-      {       Ievent=atoi(argv[ipos+1]); break; }
-  }}
+    for( int ipos=0; ipos<argc ; ipos++ ) {
+      if(string(argv[ipos]).compare("-event")==0){
+        Ievent = atoi(argv[ipos+1]);
+        Info( APP_NAME, "Argument (-event) : Running only on event # %i", Ievent );
+        break;
+      }
+    }
+  }
 
   int nEvents=-1;
   if(options.find("-n")!=string::npos){
-  for( int ipos=0; ipos<argc ; ipos++ ) {
-    if (string(argv[ipos]).compare("-n")==0)
-      {       nEvents=atoi(argv[ipos+1]); break; }
-  }}
+    for( int ipos=0; ipos<argc ; ipos++ ) {
+      if(string(argv[ipos]).compare("-n")==0){
+        nEvents = atoi(argv[ipos+1]);
+        Info( APP_NAME, "Argument (-n) : Running on NEvents = %i", nEvents );
+        break;
+      }
+    }
+  }
 
-  
-  //std::cout<<"Checking for event "<<Ievent<<std::endl;  
-  //::: Initialise the application:
-  //ATH_CHECK( xAOD::Init( APP_NAME ) );
+
+  ////////////////////////////////////////////////////
+  //:::  initialize the application and get the event
+  ////////////////////////////////////////////////////
   xAOD::Init( APP_NAME );
+  xAOD::TReturnCode::enableFailure();
 
   //::: Open the input file:
   const TString fileName = argv[ 1 ];
   Info( APP_NAME, "Opening file: %s", fileName.Data() );
   TFile* ifile( TFile::Open( fileName, "READ" ) );
-  if( !ifile ) Error( APP_NAME, "Cannot find file %s", fileName.Data() );
+  if( !ifile ) Error( APP_NAME, "Cannot find file %s",fileName.Data() );
+
+  TChain *chain = new TChain ("CollectionTree","CollectionTree");
+  chain->Add(fileName);
 
   //::: Create a TEvent object:
-  xAOD::TEvent event( ifile, xAOD::TEvent::kAthenaAccess );
+  xAOD::TEvent event( (TTree*)chain, xAOD::TEvent::kAthenaAccess );
   Info( APP_NAME, "Number of events in the file: %i", static_cast< int >( event.getEntries() ) );
 
   //::: Create a transient object store. Needed for the tools.
@@ -89,62 +123,79 @@ int main( int argc, char* argv[] ) {
 
   //::: Decide how many events to run over:
   Long64_t entries = event.getEntries();
-
-  //if( argc > 2 ) {
-  // const Long64_t e = atoll( argv[ 2 ] );
-  //if( e < entries ) {
-  //  entries = e;
-  //}
-  //}
-
-  //::: Create the tool(s) to test:
-
-  //::: Muon Calibration and Smearing
-  CP::MuonCalibrationAndSmearingTool corrTool( "MuonCorrectionTool" );
-  //corrTool.msg().setLevel( MSG::VERBOSE);
-  corrTool.msg().setLevel( MSG::WARNING);
-  //ATH_CHECK( corrTool.initialize() );
-  //corrTool.setProperty( "Release", "PreRecs" );
-  //corrTool.setProperty( "Year", "Data15" );
-  corrTool.setProperty( "Year", "Data16" );
-  corrTool.setProperty("Release","Recs2016_08_07");
-  if(corrTool.initialize()!=StatusCode::SUCCESS) return 1;
-
-  //::: Muon Selection
-
-  CP::MuonSelectionTool selTool( "MuonSelectionTool" );
-  //selTool.setProperty( "MaxEta", 2.5 );
-  //ATH_CHECK( selTool.initialize() );
-  selTool.initialize();
-
+ 
+  ////////////////////////////////////////////////////
+  //::: MuonCalibrationAndSmearingTool
+  // setup the tool handle as per the
+  // recommendation by ASG - https://twiki.cern.ch/twiki/bin/view/AtlasProtected/AthAnalysisBase#How_to_use_AnaToolHandle
+  ////////////////////////////////////////////////////
+  //::: create the tool handle
+  asg::AnaToolHandle<CP::IMuonCalibrationAndSmearingTool> corrTool; //!
+  corrTool.setTypeAndName("CP::MuonCalibrationAndSmearingTool/MuonCorrectionTool");
+    //::: set the properties
+  corrTool.setProperty("Year",                  "Data17" );
+  corrTool.setProperty("Release",               "Recs2018_05_20" );     
+  corrTool.setProperty("StatComb",              false);
+  corrTool.setProperty("SagittaCorr",           false);
+  corrTool.setProperty("SagittaRelease",        "sagittaBiasDataAll_30_07_18");
+  corrTool.setProperty("doSagittaMCDistortion", true);
+  corrTool.setProperty("SagittaCorrPhaseSpace", true);
+  corrTool.setProperty("fixedRho",              0.0);
+  corrTool.setProperty("useFixedRho",           true);
+  corrTool.setProperty("noEigenDecor" ,         false);
+  
+  //::: retrieve the tool
+  corrTool.retrieve();
+
+  ////////////////////////////////////////////////////
+  //::: MuonSelectionTool
+  // setup the tool handle as per the
+  // recommendation by ASG - https://twiki.cern.ch/twiki/bin/view/AtlasProtected/AthAnalysisBase#How_to_use_AnaToolHandle
+  ////////////////////////////////////////////////////
+  //::: create the tool handle
+  asg::AnaToolHandle<CP::IMuonSelectionTool> selTool; //!
+  selTool.setTypeAndName("CP::MuonSelectionTool/MuonSelectionTool");
+
+  //::: retrieve the tool
+  selTool.retrieve();
+
+  ////////////////////////////////////////////////////
   //::: Systematics initialization
+  ////////////////////////////////////////////////////
   std::vector< CP::SystematicSet > sysList;
-  //sysList.push_back( CP::SystematicSet() );
-  
+  sysList.push_back( CP::SystematicSet() );
+
   const CP::SystematicRegistry& registry = CP::SystematicRegistry::getInstance();
   const CP::SystematicSet& recommendedSystematics = registry.recommendedSystematics();
   for( CP::SystematicSet::const_iterator sysItr = recommendedSystematics.begin(); sysItr != recommendedSystematics.end(); ++sysItr ) {
     sysList.push_back( CP::SystematicSet() );
     sysList.back().insert( *sysItr );
   }
-  
+
   std::vector< CP::SystematicSet >::const_iterator sysListItr;
 
   std::cout<<"Systematics are "<<std::endl;
   for( sysListItr = sysList.begin(); sysListItr != sysList.end(); ++sysListItr )
     std::cout<<sysListItr->name()<<std::endl;
 
-  //::: Output initialization
+  // branches to be stored
   Float_t InitPtCB( 0. ), InitPtID( 0. ), InitPtMS( 0. );
   Float_t CorrPtCB( 0. ), CorrPtID( 0. ), CorrPtMS( 0. );
   Float_t Eta( 0. ), Phi( 0. ), Charge( 0. );
   Float_t ExpResoCB( 0. ), ExpResoID( 0. ), ExpResoMS( 0. );
+
+  // output file
   TFile* outputFile = TFile::Open( "output.root", "recreate" );
+
+  // it contains a single TTree per systematic variation
   std::unordered_map< CP::SystematicSet, TTree* > sysTreeMap;
   for( sysListItr = sysList.begin(); sysListItr != sysList.end(); ++sysListItr ) {
-    std::string treeName = "test_tree_" + sysListItr->name();
+
+    // create new tree for the systematic in question
+    std::string treeName = "test_tree_" + (sysListItr->name().size()==0 ? "NOMINAL":sysListItr->name());
     TTree* sysTree = new TTree( treeName.c_str(), "test tree for MCAST" );
 
+    // add branches
     sysTree->Branch( "InitPtCB", &InitPtCB, "InitPtCB/F" );
     sysTree->Branch( "InitPtID", &InitPtID, "InitPtID/F" );
     sysTree->Branch( "InitPtMS", &InitPtMS, "InitPtMS/F" );
@@ -161,64 +212,46 @@ int main( int argc, char* argv[] ) {
     sysTreeMap[ *sysListItr ] = sysTree;
   }
 
-  //::: Loop over the events:
+  ////////////////////////////////////////////////////
+  //::: Loop over the events
+  ////////////////////////////////////////////////////
   for( Long64_t entry = 0; entry < entries; ++entry ) {
 
-    if( nEvents!=-1 && entry > nEvents ) break; 
-    //::: Tell the object which entry to look at:
+    if( nEvents!=-1 && entry > nEvents ) break;
+    // Tell the object which entry to look at:
     event.getEntry( entry );
 
-    //::: Print some event information for fun:
+    // Print some event information
     const xAOD::EventInfo* evtInfo = 0;
-    //ATH_CHECK( event.retrieve( evtInfo, "EventInfo" ) );
     event.retrieve( evtInfo, "EventInfo" );
     if(Ievent!=-1 && static_cast <int> (evtInfo->eventNumber())!=Ievent) {
-      //std::cout<<"Event "<<evtInfo->eventNumber()<<" Ievent "<<Ievent<<std::endl;
-      continue;  
+      continue;
     }
 
-
-    //Info( APP_NAME, "===>>>  start processing event #%i, run #%i %i events processed so far  <<<===", static_cast< int >( evtInfo->eventNumber() ), static_cast< int >( evtInfo->runNumber() ), static_cast< int >( entry ) );
-    
     //::: Get the Muons from the event:
     const xAOD::MuonContainer* muons = 0;
-    //ATH_CHECK( event.retrieve( muons, "Muons" ) );
     event.retrieve( muons, "Muons" );
-    //Info( APP_NAME, "Number of muons: %i", static_cast< int >( muons->size() ) );
 
     // create a shallow copy of the muons container
     std::pair< xAOD::MuonContainer*, xAOD::ShallowAuxContainer* > muons_shallowCopy = xAOD::shallowCopyContainer( *muons );
 
-    // iterate over our shallow copy
-    //xAOD::MuonContainer::iterator muonSC_itr = ( muons_shallowCopy.first)->begin();
-    //xAOD::MuonContainer::iterator muonSC_end = ( muons_shallowCopy.first)->end();
-
     xAOD::MuonContainer* muonsCorr = muons_shallowCopy.first;
 
     //::: Loop over systematics
     for( sysListItr = sysList.begin(); sysListItr != sysList.end(); ++sysListItr ) {
-      
+
       Info( APP_NAME, "Looking at %s systematic", ( sysListItr->name() ).c_str() );
 
-      //::: Check if systematic is applicable
-      if( corrTool.applySystematicVariation( *sysListItr ) != CP::SystematicCode::Ok ) { 
+      //::: Check if systematic is applicable to the correction tool
+      if( corrTool->applySystematicVariation( *sysListItr ) != CP::SystematicCode::Ok ) {
         Error( APP_NAME, "Cannot configure muon calibration tool for systematic" );
       }
 
-      //for( int i=-0; i<1e3 ; i++) { 
       //::: Loop over muon container
       for( auto muon: *muonsCorr ) {
 
-        //::: Select "good" muons:
-        // if( ! selTool.passedIDCuts( **mu_itr ) ) {
-        //   Info( APP_NAME, "This muon doesn't pass the ID hits quality cuts");
-        //   continue;
-        // }
-        //::: Should be using correctedCopy here, thesting behaviour of applyCorrection though
+        //::: Should be using correctedCopy here, testing behaviour of applyCorrection though
         InitPtCB = muon->pt();
-        //InitPtID = muon->isAvailable< float >( "InnerDetectorPt" ) ? muon->auxdata< float >( "InnerDetectorPt" ) : -999;
-        //InitPtMS = muon->isAvailable< float >( "MuonSpectrometerPt" ) ? muon->auxdata< float >( "MuonSpectrometerPt" ) : -999;
-
         InitPtID = -999;
         if(muon->inDetTrackParticleLink().isValid()){
           const ElementLink< xAOD::TrackParticleContainer >& id_track = muon->inDetTrackParticleLink();
@@ -229,19 +262,20 @@ int main( int argc, char* argv[] ) {
           const ElementLink< xAOD::TrackParticleContainer >& ms_track = muon->extrapolatedMuonSpectrometerTrackParticleLink();
           InitPtMS = (!ms_track) ? 0:(*ms_track)->pt();
         }
-        
+
         Eta = muon->eta();
         Phi = muon->phi();
         Charge = muon->charge();
-        //::: Print some info about the selected muon:
-        //Info( APP_NAME, "Selected muon: eta = %g, phi = %g, pt = %g", muon->eta(), muon->phi(), muon->pt()/1e3 );
-        
+
         float ptCB = 0 ;
         if(muon->primaryTrackParticleLink().isValid()){
           const ElementLink< xAOD::TrackParticleContainer >& cb_track = muon->primaryTrackParticleLink();
           ptCB = (!cb_track) ? 0:(*cb_track)->pt();
         }
-        float ptID = 0; 
+        else {
+          Info( APP_NAME, "Missing primary track particle link for --> CB %g, author: %d, type: %d",ptCB,muon->author(),muon->muonType());
+        }
+        float ptID = 0;
         if(muon->inDetTrackParticleLink().isValid()){
           const ElementLink< xAOD::TrackParticleContainer >& id_track = muon->inDetTrackParticleLink();
           ptID = (!id_track) ?  0:(*id_track)->pt();
@@ -251,50 +285,44 @@ int main( int argc, char* argv[] ) {
           const ElementLink< xAOD::TrackParticleContainer >& ms_track = muon->extrapolatedMuonSpectrometerTrackParticleLink();
           ptME = (!ms_track) ? 0:(*ms_track)->pt();
         }
+
         Info( APP_NAME, "--> CB %g, ID %g, ME %g, author: %d, type: %d",ptCB,ptID,ptME,muon->author(),muon->muonType());
-        
-        //:::
-        if( do_it_the_right_way ) {
+
+        // either use the correctedCopy call or correct the muon object itself
+        if( useCorrectedCopy ) {
           //::: Create a calibrated muon:
           xAOD::Muon* mu = 0;
-          if( !corrTool.correctedCopy( *muon, mu ) ) {
+          if( !corrTool->correctedCopy( *muon, mu ) ) {
             Error( APP_NAME, "Cannot really apply calibration nor smearing" );
             continue;
           }
           CorrPtCB = mu->pt();
           CorrPtID = mu->auxdata< float >( "InnerDetectorPt" );
           CorrPtMS = mu->auxdata< float >( "MuonSpectrometerPt" );
-
-          //Info( APP_NAME, "Calibrated muon: eta = %g, phi = %g, pt(CB) = %g, pt(ID) = %g, pt(MS) = %g", mu->eta(), mu->phi(), mu->pt(), mu->auxdata< float >( "InnerDetectorPt" ), mu->auxdata< float >( "MuonSpectrometerPt" ) );
-          
+          Info( APP_NAME, "Calibrated muon: eta = %g, phi = %g, pt(CB) = %g, pt(ID) = %g, pt(MS) = %g", mu->eta(), mu->phi(), mu->pt(), mu->auxdata< float >( "InnerDetectorPt" ), mu->auxdata< float >( "MuonSpectrometerPt" ) );
           sysTreeMap[ *sysListItr ]->Fill();
           //::: Delete the calibrated muon:
           delete mu;
         }
         else {
-          //if( muon->type() == 0 ) continue;
-          std::unique_ptr<CP::MuonCalibrationAndSmearingTool::IVars> ivars;
-          if( !corrTool.applyCorrection( *muon, ivars ) ) {
+          if( !corrTool->applyCorrection( *muon ) ) {
             Error( APP_NAME, "Cannot really apply calibration nor smearing" );
             continue;
           }
           CorrPtCB = muon->pt();
           CorrPtID = muon->auxdata< float >( "InnerDetectorPt" );
           CorrPtMS = muon->auxdata< float >( "MuonSpectrometerPt" );
-          ExpResoCB = corrTool.ExpectedResolution( *ivars, "CB", *muon );
-          ExpResoID = corrTool.ExpectedResolution( *ivars, "ID", *muon );
-          ExpResoMS = corrTool.ExpectedResolution( *ivars, "MS", *muon );
-
-          Info( APP_NAME, "Calibrated muon: eta = %g, phi = %g, pt(CB) = %g, pt(ID) = %g, pt(MS) = %g", muon->eta(), muon->phi(), muon->pt()/1e3, muon->auxdata< float >( "InnerDetectorPt" )/1e3, muon->auxdata< float >( "MuonSpectrometerPt" )/1e3 );
+          ExpResoCB = corrTool->expectedResolution( "CB", *muon, true );
+          ExpResoID = corrTool->expectedResolution( "ID", *muon, true );
+          ExpResoMS = corrTool->expectedResolution( "MS", *muon, true );
+          Info( APP_NAME, "Calibrated muon: eta = %g, phi = %g, pt(CB) = %g, pt(ID) = %g, pt(MS) = %g", muon->eta(), muon->phi(), muon->pt()/1e3,CorrPtID,CorrPtMS);
+          Info( APP_NAME, " expReso : ExpResoCB = %g , ExpResoID = %g , ExpResoMS = %g", ExpResoCB, ExpResoID, ExpResoMS);
           sysTreeMap[ *sysListItr ]->Fill();
         }
-        //break; 
       }
-      //}
     }
-    
+
     //::: Close with a message:
-    if(entry %  1000 ==0 ) 
       Info( APP_NAME, "===>>>  done processing event #%i, run #%i %i events processed so far  <<<===", static_cast< int >( evtInfo->eventNumber() ), static_cast< int >( evtInfo->runNumber() ), static_cast< int >( entry + 1 ) );
   }
 
@@ -302,11 +330,14 @@ int main( int argc, char* argv[] ) {
     sysTreeMap[ *sysListItr ]->Write();
   }
 
+  delete chain;
+
   //::: Close output file
   outputFile->Close();
 
   xAOD::IOStats::instance().stats().printSmartSlimmingBranchList();
 
+
   //::: Return gracefully:
   return 0;
 
diff --git a/PhysicsAnalysis/MuonID/MuonPerformanceAnalysis/MuonResonanceTools/MuonResonanceTools/IMuonResonanceSelectionTool.h b/PhysicsAnalysis/MuonID/MuonPerformanceAnalysis/MuonResonanceTools/MuonResonanceTools/IMuonResonanceSelectionTool.h
index 2274803c62bd348532afe6d567f722c30600828c..5b94cc689249235742388466ed815738dcd9555b 100644
--- a/PhysicsAnalysis/MuonID/MuonPerformanceAnalysis/MuonResonanceTools/MuonResonanceTools/IMuonResonanceSelectionTool.h
+++ b/PhysicsAnalysis/MuonID/MuonPerformanceAnalysis/MuonResonanceTools/MuonResonanceTools/IMuonResonanceSelectionTool.h
@@ -13,7 +13,7 @@
 #include "EventPrimitives/EventPrimitivesHelpers.h"
 #include "MuonAnalysisInterfaces/IMuonSelectionTool.h"
 #include "MuonAnalysisInterfaces/IMuonEfficiencyScaleFactors.h"
-#include "MuonMomentumCorrections/IMuonCalibrationAndSmearingTool.h"
+#include "MuonAnalysisInterfaces/IMuonCalibrationAndSmearingTool.h"
 #include "TrigMuonMatching/ITrigMuonMatching.h"
 #include "TrigDecisionTool/TrigDecisionTool.h"
 #include "PATInterfaces/SystematicVariation.h"
diff --git a/PhysicsAnalysis/MuonID/MuonTagTools/MuonTagTools/MuonTagTool.h b/PhysicsAnalysis/MuonID/MuonTagTools/MuonTagTools/MuonTagTool.h
index 2d5e293b099cc992a6aad25c777df008560d24de..0c97709ca80a3229e3067de550a64380e21a9809 100644
--- a/PhysicsAnalysis/MuonID/MuonTagTools/MuonTagTools/MuonTagTool.h
+++ b/PhysicsAnalysis/MuonID/MuonTagTools/MuonTagTools/MuonTagTool.h
@@ -18,7 +18,7 @@ Purpose : build the Muon Tag objects - MuonTagCollection.h.
 #include "GaudiKernel/ToolHandle.h"
 #include <inttypes.h>
 #include "xAODMuon/MuonContainer.h"
-#include "MuonMomentumCorrections/IMuonCalibrationAndSmearingTool.h"
+#include "MuonAnalysisInterfaces/IMuonCalibrationAndSmearingTool.h"
 #include "MuonAnalysisInterfaces/IMuonSelectionTool.h"
 #include "IsolationSelection/IIsolationSelectionTool.h"
 #include "xAODEventInfo/EventInfo.h"
diff --git a/PhysicsAnalysis/SUSYPhys/SUSYTools/Root/Muons.cxx b/PhysicsAnalysis/SUSYPhys/SUSYTools/Root/Muons.cxx
index 0447efd2f201aa7d30ce9e9f68f90ec4ed90fad8..6da339e9d6f89a478ad301cf4a69f7680b911447 100644
--- a/PhysicsAnalysis/SUSYPhys/SUSYTools/Root/Muons.cxx
+++ b/PhysicsAnalysis/SUSYPhys/SUSYTools/Root/Muons.cxx
@@ -15,7 +15,7 @@
 
 #include "AsgAnalysisInterfaces/IPileupReweightingTool.h"
 
-#include "MuonMomentumCorrections/IMuonCalibrationAndSmearingTool.h"
+#include "MuonAnalysisInterfaces/IMuonCalibrationAndSmearingTool.h"
 #include "MuonAnalysisInterfaces/IMuonEfficiencyScaleFactors.h"
 #include "MuonAnalysisInterfaces/IMuonSelectionTool.h"
 #include "MuonAnalysisInterfaces/IMuonTriggerScaleFactors.h"
diff --git a/PhysicsAnalysis/SUSYPhys/SUSYTools/Root/SUSYObjDef_xAOD.cxx b/PhysicsAnalysis/SUSYPhys/SUSYTools/Root/SUSYObjDef_xAOD.cxx
index af233c0211df2e33291ddf7fcc97cfce6694c8e2..388e531a2877913c6b9acd4ca30258f25b609216 100644
--- a/PhysicsAnalysis/SUSYPhys/SUSYTools/Root/SUSYObjDef_xAOD.cxx
+++ b/PhysicsAnalysis/SUSYPhys/SUSYTools/Root/SUSYObjDef_xAOD.cxx
@@ -37,7 +37,7 @@
 #include "ElectronPhotonSelectorTools/IEGammaAmbiguityTool.h"
 
 #include "MuonAnalysisInterfaces/IMuonSelectionTool.h"
-#include "MuonMomentumCorrections/IMuonCalibrationAndSmearingTool.h"
+#include "MuonAnalysisInterfaces/IMuonCalibrationAndSmearingTool.h"
 #include "MuonAnalysisInterfaces/IMuonEfficiencyScaleFactors.h"
 #include "MuonAnalysisInterfaces/IMuonTriggerScaleFactors.h"
 
diff --git a/PhysicsAnalysis/TopPhys/xAOD/TopCPTools/TopCPTools/TopMuonCPTools.h b/PhysicsAnalysis/TopPhys/xAOD/TopCPTools/TopCPTools/TopMuonCPTools.h
index bf62cf5e8d63e1e53c5be178540d0d4e1e4f0027..3ed0e73dfa51e29c70d9b51df79b9fe3bfeb6b59 100644
--- a/PhysicsAnalysis/TopPhys/xAOD/TopCPTools/TopCPTools/TopMuonCPTools.h
+++ b/PhysicsAnalysis/TopPhys/xAOD/TopCPTools/TopCPTools/TopMuonCPTools.h
@@ -16,7 +16,7 @@
 #include "AsgTools/AnaToolHandle.h"
 
 // Muon include(s):
-#include "MuonMomentumCorrections/IMuonCalibrationAndSmearingTool.h"
+#include "MuonAnalysisInterfaces/IMuonCalibrationAndSmearingTool.h"
 #include "MuonAnalysisInterfaces/IMuonSelectionTool.h"
 #include "MuonAnalysisInterfaces/IMuonTriggerScaleFactors.h"
 #include "MuonAnalysisInterfaces/IMuonEfficiencyScaleFactors.h"
diff --git a/PhysicsAnalysis/TopPhys/xAOD/TopSystematicObjectMaker/TopSystematicObjectMaker/MuonObjectCollectionMaker.h b/PhysicsAnalysis/TopPhys/xAOD/TopSystematicObjectMaker/TopSystematicObjectMaker/MuonObjectCollectionMaker.h
index c3ad4217749624bee4555b687e01e92f3997aba7..090e939feddc62bbe1947c5f1f5f9abfb0623937 100644
--- a/PhysicsAnalysis/TopPhys/xAOD/TopSystematicObjectMaker/TopSystematicObjectMaker/MuonObjectCollectionMaker.h
+++ b/PhysicsAnalysis/TopPhys/xAOD/TopSystematicObjectMaker/TopSystematicObjectMaker/MuonObjectCollectionMaker.h
@@ -31,7 +31,7 @@
 #include "PATInterfaces/SystematicSet.h"
 
 // CP Tool include(s):
-#include "MuonMomentumCorrections/IMuonCalibrationAndSmearingTool.h"
+#include "MuonAnalysisInterfaces/IMuonCalibrationAndSmearingTool.h"
 #include "IsolationSelection/IIsolationSelectionTool.h"
 // the following is needed to make sure all muons for which d0sig is calculated are at least Loose
 #include "MuonAnalysisInterfaces/IMuonSelectionTool.h"