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"