diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/CMakeLists.txt b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/CMakeLists.txt
index 5505e4ba604a9bc873ae245d4120dd00bf3ac5e4..76dad01ad304c27c4370d7c49466a9e5967350bb 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/CMakeLists.txt
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/CMakeLists.txt
@@ -20,10 +20,10 @@ atlas_add_library( ElectronPhotonFourMomentumCorrectionLib
    INCLUDE_DIRS ${ROOT_INCLUDE_DIRS}
    PRIVATE_INCLUDE_DIRS ${Boost_INCLUDE_DIRS}
    LINK_LIBRARIES ${ROOT_LIBRARIES} AsgTools AsgMessagingLib xAODCaloEvent xAODEgamma
-   xAODEventInfo PATInterfaces EgammaAnalysisInterfacesLib PATCoreAcceptLib
+   xAODEventInfo PATInterfaces EgammaAnalysisInterfacesLib egammaUtils PATCoreAcceptLib
    xAODRootAccess xAODTracking
    PRIVATE_LINK_LIBRARIES ${Boost_LIBRARIES} AthLinks xAODMetaData egammaLayerRecalibTool
-   egammaMVACalibAnalysisLib egammaUtils PathResolver ${extra_libs} )
+   egammaMVACalibAnalysisLib PathResolver ${extra_libs} )
 
 if( NOT XAOD_STANDALONE )
    atlas_add_component( ElectronPhotonFourMomentumCorrection
@@ -65,16 +65,6 @@ if( XAOD_STANDALONE )
       xAODCaloEvent xAODCore PATInterfaces ElectronPhotonFourMomentumCorrectionLib )
 endif()
 
-# Test(s) in the package:
-if( XAOD_STANDALONE )
-   # FIX ME: these tests were temporarily disabled as they were
-   # failing in the nightlies.
-
-   # atlas_add_test( ut_test SCRIPT test/ut_test.py )
-   # atlas_add_test( ut_test_factory SCRIPT test/ut_test_factory.py )
-   # atlas_add_test( ut_test_resolution SCRIPT test/ut_test_resolution.py )
-endif()
-
 # Install files from the package:
 atlas_install_python_modules( python/*.py )
 atlas_install_joboptions( share/*.py )
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/EgammaCalibrationAndSmearingTool.h b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/EgammaCalibrationAndSmearingTool.h
index cf7d530c0b9b83d87866754c376f7dce35164422..c0b26dea71db2e859fa0d4dd7d325bf200710e4d 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/EgammaCalibrationAndSmearingTool.h
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/EgammaCalibrationAndSmearingTool.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
 */
 
 
@@ -57,7 +55,7 @@ namespace xAOD {
   inline float get_eta_calo(const xAOD::CaloCluster& cluster, int author, bool do_throw=false)
 	{
 	  double eta_calo;
-	  if(author== xAOD::EgammaParameters::AuthorFwdElectron){ 
+	  if(author== xAOD::EgammaParameters::AuthorFwdElectron){
             eta_calo = cluster.eta();
           }
 	  else if (cluster.retrieveMoment(xAOD::CaloCluster::ETACALOFRAME,
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/EgammaFactory.h b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/EgammaFactory.h
index 250038eb298b0a79513eec0b8f6c5b84a9c0f186..9ace3e35671c91fd5eacc64c7e4c76ace50de6fc 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/EgammaFactory.h
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/EgammaFactory.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
-// Dear emacs, this is -*-c++-*-
+
 #ifndef EGAMMAFACTORY_H
 #define EGAMMAFACTORY_H
 
@@ -49,7 +49,8 @@ public:
   xAOD::Photon* create_photon(float eta, float phi, float e0, float e1, float e2, float e3, float e, float rconv=0, float zconv=0);
   xAOD::Electron* create_electron(float eta, float phi, float e);
   xAOD::Electron* create_electron(float eta, float phi, float e0, float e1, float e2, float e3, float e);
-  xAOD::EventInfo* create_eventinfo(bool simulation, int runnumber, int eventnumber=1);
+    // TODO: fix mu
+  xAOD::EventInfo* create_eventinfo(bool simulation, int runnumber, int eventnumber=1, int average_interaction_per_crossing=20);
 private:
   xAOD::TStore m_store;  //!
   xAOD::CaloClusterContainer* m_clusters;  //!
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrectionDict.h b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrectionDict.h
index d4157b4d7136f2caeea24593d8cab3a5b4fbf031..7eeee582ca66a96980fb90db23551a6a466653b6 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrectionDict.h
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrectionDict.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
-// Dear emacs, this is -*-c++-*-
+
 //
 // Dictionary generation for this package
 //
@@ -12,6 +12,7 @@
 #define ELECTRONPHOTONFOURMOMENTUMCORRECTION_ELECTRONPHOTONFOURMOMENTUMCORRECTIONDICT_H
 
 
+#include "egammaUtils/eg_resolution.h"
 #include "ElectronPhotonFourMomentumCorrection/egammaEnergyCorrectionTool.h"
 #include "ElectronPhotonFourMomentumCorrection/EgammaCalibrationAndSmearingTool.h"
 #include "ElectronPhotonFourMomentumCorrection/EgammaFactory.h"
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/GainTool.h b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/GainTool.h
index 0ca13feab8aad6328a38a0c7d1e428b37c6709fd..56cee09544dcad2fd54671886b96b5d4ff644e9a 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/GainTool.h
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/GainTool.h
@@ -1,45 +1,45 @@
 /*
-  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 ELECTRONPHOTONFOURMOMENTUMCORRECTION_GAINTOOL_H
-#define ELECTRONPHOTONFOURMOMENTUMCORRECTION_GAINTOOL_H
-
-#include <string>
-#include <memory>
-#include <PATCore/PATCoreEnums.h>
-
-class TFile;
-class TF1;
-
-namespace egGain {
-
-  class GainTool {
-    
-  public:
-    GainTool(const std::string& filenameTO, const std::string& filenameVar);
-    void Init(const std::string& filenameTO, const std::string& filenameVar);
-    virtual ~GainTool();
-
-    double CorrectionGainTool(double eta_input, double energy_input, double energy_layer2_input,
-			      PATCore::ParticleType::Type ptype=PATCore::ParticleType::Electron);
-
-  private:
-    
-    static const int m_NUM_ETA_BINS=28;
-    static const int m_NUM_ENERGY_BINS=3;
-    static const int m_NUM_UNCONV_ENERGY_BINS=4;
-
-    std::unique_ptr <TFile> m_TOFile;
-    std::unique_ptr <TFile> m_varFile;    
-
-    TF1* m_funcTO[m_NUM_ETA_BINS]; 
-    TF1* m_funcG[m_NUM_ENERGY_BINS][m_NUM_ETA_BINS];
-    TF1* m_conv_funcG[m_NUM_ENERGY_BINS][m_NUM_ETA_BINS]; 
-    TF1* m_unconv_funcG[m_NUM_UNCONV_ENERGY_BINS][m_NUM_ETA_BINS]; 
-    
-  };
-  
-  
-} 
-#endif
+#ifndef ELECTRONPHOTONFOURMOMENTUMCORRECTION_GAINTOOL_H
+#define ELECTRONPHOTONFOURMOMENTUMCORRECTION_GAINTOOL_H
+
+#include <string>
+#include <memory>
+#include <PATCore/PATCoreEnums.h>
+
+class TFile;
+class TF1;
+
+namespace egGain {
+
+  class GainTool {
+
+  public:
+    GainTool(const std::string& filenameTO, const std::string& filenameVar);
+    void Init(const std::string& filenameTO, const std::string& filenameVar);
+    virtual ~GainTool();
+
+    double CorrectionGainTool(double eta_input, double energy_input, double energy_layer2_input,
+			      PATCore::ParticleType::Type ptype=PATCore::ParticleType::Electron);
+
+  private:
+
+    static const int m_NUM_ETA_BINS=28;
+    static const int m_NUM_ENERGY_BINS=3;
+    static const int m_NUM_UNCONV_ENERGY_BINS=4;
+
+    std::unique_ptr <TFile> m_TOFile;
+    std::unique_ptr <TFile> m_varFile;
+
+    TF1* m_funcTO[m_NUM_ETA_BINS];
+    TF1* m_funcG[m_NUM_ENERGY_BINS][m_NUM_ETA_BINS];
+    TF1* m_conv_funcG[m_NUM_ENERGY_BINS][m_NUM_ETA_BINS];
+    TF1* m_unconv_funcG[m_NUM_UNCONV_ENERGY_BINS][m_NUM_ETA_BINS];
+
+  };
+
+
+}
+#endif
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/GainUncertainty.h b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/GainUncertainty.h
index 4dd53f2ec5adbe8a587a10a7304b44948efd9629..317f5d8558c11218d98312f69dd6b4284cbdfb64 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/GainUncertainty.h
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/GainUncertainty.h
@@ -1,50 +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
 */
 
-#ifndef ELECTRONPHOTONFOURMOMENTUMCORRECTION_GAINUNCERTAINTYY_H
-#define ELECTRONPHOTONFOURMOMENTUMCORRECTION_GAINUNCERTAINTYY_H
-
-#include <AsgMessaging/AsgMessaging.h>
-#include <PATCore/PATCoreEnums.h>
-#include <memory>
-#include <string>
-
-
-class TFile;
-class TH1F;
-class TH1D;
-
-namespace egGain{
-
-class GainUncertainty : public asg::AsgMessaging {
-public:
-
-    GainUncertainty(std::string filename);
-    void Init(std::string filename);
-    ~GainUncertainty();
-
- // return relative uncertainty on energy from gain uncertainty
- // input etaCalo_input = eta in Calo frame
- //       et_input = Et in MeV
- //       ptype    = particle type
-
-  double getUncertainty(double etaCalo_input, double et_input, PATCore::ParticleType::Type ptype=PATCore::ParticleType::Electron) const;
-
-private:
-
-  static const int m_NUM_ETA_BINS=5;
-
-  std::unique_ptr<TFile> m_gainFile;
-
-  TH1F* m_alpha_specialGainRun;
-  TH1F* m_gain_impact_Zee;
-  TH1D* m_gain_Impact_elec[5];
-  TH1D* m_gain_Impact_conv[5];
-  TH1D* m_gain_Impact_unco[5];
-
-};
-
-}
-
-#endif
+#ifndef ELECTRONPHOTONFOURMOMENTUMCORRECTION_GAINUNCERTAINTYY_H
+#define ELECTRONPHOTONFOURMOMENTUMCORRECTION_GAINUNCERTAINTYY_H
+
+#include <AsgMessaging/AsgMessaging.h>
+#include <PATCore/PATCoreEnums.h>
+#include <memory>
+#include <string>
+
+
+class TFile;
+class TH1;
+
+namespace egGain{
+
+class GainUncertainty : public asg::AsgMessaging {
+public:
+
+    GainUncertainty(const std::string& filename);
+    ~GainUncertainty();
+
+ // return relative uncertainty on energy from gain uncertainty
+ // input etaCalo_input = eta in Calo frame
+ //       et_input = Et in MeV
+ //       ptype    = particle type
+
+  double getUncertainty(double etaCalo_input, double et_input, PATCore::ParticleType::Type ptype=PATCore::ParticleType::Electron) const;
+
+private:
+
+  static const int m_NUM_ETA_BINS=5;
+
+  std::unique_ptr<TFile> m_gainFile;
+
+  TH1* m_alpha_specialGainRun;
+  TH1* m_gain_impact_Zee;
+  TH1* m_gain_Impact_elec[5];
+  TH1* m_gain_Impact_conv[5];
+  TH1* m_gain_Impact_unco[5];
+
+};
+
+}
+
+#endif
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/IEgammaCalibrationAndSmearingTool.h b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/IEgammaCalibrationAndSmearingTool.h
index ed52291f80886184506a7db0e1fda491c10cf3f7..028d88d945fc0ffd7878c940cf5f623df4d9cc78 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/IEgammaCalibrationAndSmearingTool.h
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/IEgammaCalibrationAndSmearingTool.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
 */
 
 
@@ -10,6 +8,5 @@
 
 #include "EgammaAnalysisInterfaces/IEgammaCalibrationAndSmearingTool.h"
 #pragma message "In the process of moving the Interface part under PhysicsAnalysis/Interfaces/EgammaAnalysisInterfaces"
-#pragma GCC warning "TODO: Use the headers from EgammaAnalysisInterfaces"
 
 #endif
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/LArTemperatureCorrectionTool.h b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/LArTemperatureCorrectionTool.h
index adea579b920e4ea3aa22beba42108ac357dc9dbe..1769425b53e67d95ba5c1b6650d7267a7a1eb3d7 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/LArTemperatureCorrectionTool.h
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/LArTemperatureCorrectionTool.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 LARTEMPERATURECORRECTIONTOOL_H
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/e1hg_systematics.h b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/e1hg_systematics.h
index 84c60d8afcb06dcb3c7caafda59fc678d862f38d..913d9992aea323031140d1e8c8068fe1d6119f32 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/e1hg_systematics.h
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/e1hg_systematics.h
@@ -1,43 +1,43 @@
 /*
-  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 E1HG_SYSTEMATICS_H
-#define E1HG_SYSTEMATICS_H
-#include "TH1.h"
-#include "TFile.h"
-#include "TArrayD.h"
-
-/**
-  @class e1hg_Systematics
-  @brief get systematics from MG/HG layer 1 miscalibration assuming MG is correctly re-calibrated with muons
-
-*/
-
-class e1hg_systematics {
-
- public:
-  /** @brief constructor (initialization done there reading root files) */
-  e1hg_systematics();
-  ~e1hg_systematics();
-
-  /** 
-   @brief particle_type = 0 (electrons), 1 (unconv photons), 2 (conv photons) 
-   @brief energy = energy in MeV
-   @brief eta
-   @brief return value  alpha    Ebiased =  E*(1 + alpha)
-  */
-  double getAlpha(int particle_type, double energy, double eta, bool interpolate=false) const;
-
- private:
-
-  // histograms to store parameters
-  TH1D* m_helec[8];
-  TH1D* m_hphot[8];
-  TH1D* m_hphot2[8];
-  TFile* m_file0;
-  const TArrayD* m_etBins;
-
-};
-
-#endif
+#ifndef E1HG_SYSTEMATICS_H
+#define E1HG_SYSTEMATICS_H
+#include "TH1.h"
+#include "TFile.h"
+#include "TArrayD.h"
+
+/**
+  @class e1hg_Systematics
+  @brief get systematics from MG/HG layer 1 miscalibration assuming MG is correctly re-calibrated with muons
+
+*/
+
+class e1hg_systematics {
+
+ public:
+  /** @brief constructor (initialization done there reading root files) */
+  e1hg_systematics();
+  ~e1hg_systematics();
+
+  /**
+   @brief particle_type = 0 (electrons), 1 (unconv photons), 2 (conv photons)
+   @brief energy = energy in MeV
+   @brief eta
+   @brief return value  alpha    Ebiased =  E*(1 + alpha)
+  */
+  double getAlpha(int particle_type, double energy, double eta, bool interpolate=false) const;
+
+ private:
+
+  // histograms to store parameters
+  TH1D* m_helec[8];
+  TH1D* m_hphot[8];
+  TH1D* m_hphot2[8];
+  TFile* m_file0;
+  const TArrayD* m_etBins;
+
+};
+
+#endif
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/egammaEnergyCorrectionTool.h b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/egammaEnergyCorrectionTool.h
index 7abd7c637fccdf897cd6dc98ecf4b2315fcfbe3e..8b8a23fc810cf8306260f6dbb7faee4a8ca9f9df 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/egammaEnergyCorrectionTool.h
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/egammaEnergyCorrectionTool.h
@@ -1,8 +1,7 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
-// Dear emacs, this is -*-c++-*-
 //////////////////////////////////////////////////////////////
 //
 // REWRITE - February 2013, Karsten Koeneke
@@ -30,18 +29,19 @@
 
 // ROOT includes
 #include "TRandom3.h"
-#include "TList.h"
-#include "TFile.h"
-#include "TGraphErrors.h"
-#include "TH1D.h"
-#include "TH2F.h"
 #include "TSystem.h"
-#include "TF1.h"
 
 // Forward declarations
 class eg_resolution;
 class get_MaterialResolutionEffect;
 class e1hg_systematics;
+
+class TH1;
+class TH2;
+class TAxis;
+class TFile;
+class TList;
+
 namespace egGain { class GainTool;            // run1 tool
                    class GainUncertainty;     // run2 tool
                  }
@@ -82,6 +82,8 @@ namespace egEnergyCorr {
       // IBL+PP0 for run 2
       MaterialIBLUp, MaterialIBLDown, MaterialPP0Up, MaterialPP0Down,
 
+      // Atlfast 2 resolution uncertainties
+      af2Up, af2Down,
 
       // to help with loops
       LastResolutionVariation
@@ -144,6 +146,12 @@ namespace egEnergyCorr {
       // ... Layer scale variations : data driven, uncorrelated vs eta
       PSUp, PSDown, S12Up, S12Down,
 
+      //PS correlated contribution
+      PSb12Up, PSb12Down,
+
+      // topo cluster threshold
+      topoClusterThresUp,topoClusterThresDown,
+
       // extra E12 for es2017 run2
       S12ExtraLastEtaBinRun2Up, S12ExtraLastEtaBinRun2Down,
 
@@ -162,6 +170,9 @@ namespace egEnergyCorr {
       // PP0
       MatPP0Up, MatPP0Down,
 
+      // AF2 systematics
+      af2Up, af2Down,
+
       // The following apply to photons only
 
       // ... Leakage
@@ -211,20 +222,33 @@ namespace egEnergyCorr {
     es2017,                 // Moriond 2017
     es2017_summer,          // Summer 2017
     es2017_summer_improved, // Recommendations for Higgs mass paper
+    es2017_summer_final,    // Final 20.7 recommendations
+
+    es2015_5TeV,            // For 2015 low mu 5 TeV runs
+
     es2017_R21_PRE,         // Pre-recommendations for release 21
-    
+
+    es2017_R21_v0,          // Release 21 model with layer calibration corrections from run 2, no global scale correction
+    es2017_R21_v1,          // Release 21 model July 2018 adding forward, AFII, mc16d/reproc data, new mat syst
+    es2017_R21_ofc0_v1,  // Release 21 model calibration extrapolated for OFC(mu=0), coveering 2015,2016,2017 and 2018 data
+    es2018_R21_v0,
+    es2018_R21_v1,     // model with new E1/E2 muon calibration from full run 2 low+high mu data
+
     UNDEFINED
 
   };
 
-  // Geometry dostortions
+  // Geometry distortions
 
   enum Geometry {
     ConfigA=0,     // 5% ID material scaling
     ConfigCD,      // 10% services scaling
     ConfigEL,      // +7.5%X0 in SCT/TRT endcap; 10%X0, radial, in cryostat
     ConfigFMX,     // +7.5%X0 on ID endplate; 5%X0, radial, between PS and Strips
-    ConfigGp       // all together
+    ConfigGp,      // all together
+    ConfigN,       // material between PS and calo in EndCap (only used for release 21)
+    ConfigIBL,     // IBL systematics in run 2 geometry
+    ConfigPP0      // PP0 systematics in run 2 geometry
   };
 
   // Measured material categories
@@ -308,26 +332,24 @@ namespace AtlasRoot {
                       egEnergyCorr::Resolution::resolutionType resType = egEnergyCorr::Resolution::SigmaEff90 ) const;
 
     // new for mc12c model. Return relative uncertainty on the resolution
-    double getResolutionError(double energy, double eta, double etaCalo, PATCore::ParticleType::Type ptype, egEnergyCorr::Resolution::Variation value,
+    double getResolutionError(PATCore::ParticleDataType::DataType dataType,double energy, double eta, double etaCalo, PATCore::ParticleType::Type ptype, egEnergyCorr::Resolution::Variation value,
                               egEnergyCorr::Resolution::resolutionType resType = egEnergyCorr::Resolution::Gaussian) const;
 
 
     std::string variationName(egEnergyCorr::Scale::Variation& var) const;
     std::string variationName(egEnergyCorr::Resolution::Variation& var) const;
 
-    static egEnergyCorr::Scale::Variation ScaleVariationFromString(std::string& var);
-    static egEnergyCorr::Resolution::Variation ResolutionVariationFromString(std::string& var);
 
     // convenient method for decorrelation of statistical error
-    const TAxis& get_ZeeStat_eta_axis() const { return *m_zeeNom->GetXaxis(); }
+    const TAxis& get_ZeeStat_eta_axis() const;
 
   private:
     // TODO: remove mutable
-    mutable egGain::GainTool* m_gain_tool;                    // run 1
-    egGain::GainUncertainty* m_gain_tool_run2;        // based on special run for run2
-    mutable eg_resolution* m_resolution_tool;
-    mutable get_MaterialResolutionEffect* m_getMaterialDelta;
-    mutable e1hg_systematics* m_e1hg_tool;
+    mutable std::unique_ptr<egGain::GainTool> m_gain_tool;                    // run 1
+    std::unique_ptr<egGain::GainUncertainty> m_gain_tool_run2;        // based on special run for run2
+    mutable std::unique_ptr<eg_resolution> m_resolution_tool;
+    mutable std::unique_ptr<get_MaterialResolutionEffect> m_getMaterialDelta;
+    mutable std::unique_ptr<e1hg_systematics> m_e1hg_tool;
 
     double getAlphaValue(long int runnumber, double cl_eta, double cl_etaCalo,
 			 double energy, double energyS2, double eraw,
@@ -356,7 +378,7 @@ namespace AtlasRoot {
     /// MC calibration corrections
 
 
-    double applyAFtoG4(double eta, PATCore::ParticleType::Type ptype) const;
+    double applyAFtoG4(double eta, double ptGeV, PATCore::ParticleType::Type ptype) const;
     double applyFStoG4(double eta) const;
 
     // functions for resolution uncertainty evaluation
@@ -400,6 +422,8 @@ namespace AtlasRoot {
     double getAlphaMaterial( double cl_eta, egEnergyCorr::MaterialCategory imat, PATCore::ParticleType::Type ptype,
 			     egEnergyCorr::Scale::Variation var = egEnergyCorr::Scale::Nominal, double varSF = 1. ) const;
 
+    double getMaterialEffect(egEnergyCorr::Geometry geo,PATCore::ParticleType::Type ptype,double cl_eta,double ET) const;
+
     double getMaterialNonLinearity( double cl_eta, double energy, egEnergyCorr::MaterialCategory imat, PATCore::ParticleType::Type ptype,
 				    egEnergyCorr::Scale::Variation var = egEnergyCorr::Scale::Nominal, double varSF = 1. ) const;
 
@@ -427,15 +451,15 @@ namespace AtlasRoot {
      @brief  Output : resolution_error = uncertainty on energy resolution in MeV from the systematics included according to bit mask
      @brief resolution_type 0=gaussian core, 1= sigma eff 80%, 2 = sigma eff 90%
   */
-    void getResolution_systematics(int particle_type, double energy, double eta, double etaCalo, int syst_mask, double& resolution, double& resolution_error,double& resolution_error_up, double & resolution_error_down, int resol_type=0) const;
+    void getResolution_systematics(int particle_type, double energy, double eta, double etaCalo, int syst_mask, double& resolution, double& resolution_error,double& resolution_error_up, double & resolution_error_down, int resol_type=0, bool fast=false) const;
 
     // approximate pileup noise contribution to the resolution
-    double pileUpTerm(double eta, int particle_type) const;
+    double pileUpTerm(double energy, double eta, int particle_type) const;
 
   private:
 
 
-    TFile* m_rootFile;
+    std::unique_ptr<TFile> m_rootFile;
     std::string m_rootFileName;
 
     mutable TRandom3   m_random3;
@@ -443,120 +467,147 @@ namespace AtlasRoot {
     unsigned int  m_begRunNumber;
     unsigned int  m_endRunNumber;
 
-    TH1D*         m_trkSyst;
-
-    TH1D*         m_aPSNom;
-    TH1D*         m_daPSCor;
-    TH1D*         m_aS12Nom;
-    TH1D*         m_daS12Cor;
-
-    TH1D*         m_zeeNom;
-    TH1D*         m_zeeNom_data2015;
-
-    TH1D*         m_zeeSyst;
-    TH1D*         m_zeePhys;
-    TH1*          m_uA2MeV_2015_first2weeks_correction;
-
-    TH1D*         m_resNom;
-    TH1D*         m_resSyst;
-    TH1D*         m_peakResData;
-    TH1D*         m_peakResMC;
-
-    TH1D*         m_dX_ID_Nom;
-
-    TH1D*         m_dX_IPPS_Nom;
-    TH1D*         m_dX_IPPS_LAr;
-
-    TH1D*         m_dX_IPAcc_Nom;
-    TH1D*         m_dX_IPAcc_G4;
-    TH1D*         m_dX_IPAcc_LAr;
-    TH1D*         m_dX_IPAcc_GL1;
-
-    TH1D*         m_dX_PSAcc_Nom;
-    TH1D*         m_dX_PSAcc_G4;
-    TH1D*         m_dX_PSAcc_LAr;
-
-    TAxis*        m_psElectronEtaBins;
-    TList*        m_psElectronGraphs;
-    TAxis*        m_psUnconvertedEtaBins;
-    TList*        m_psUnconvertedGraphs;
-    TAxis*        m_psConvertedEtaBins;
-    TList*        m_psConvertedGraphs;
-
-    TAxis*        m_E4ElectronEtaBins = nullptr;
-    TList*        m_E4ElectronGraphs = nullptr;
-    TAxis*        m_E4UnconvertedEtaBins = nullptr;
-    TList*        m_E4UnconvertedGraphs = nullptr;
-    TAxis*        m_E4ConvertedEtaBins = nullptr;
-    TList*        m_E4ConvertedGraphs = nullptr;
-
-    TAxis*        m_s12ElectronEtaBins;
-    TList*        m_s12ElectronGraphs;
-    TAxis*        m_s12UnconvertedEtaBins;
-    TList*        m_s12UnconvertedGraphs;
-    TAxis*        m_s12ConvertedEtaBins;
-    TList*        m_s12ConvertedGraphs;
-
-    TH1D*         m_pedestalL0;
-    TH1D*         m_pedestalL1;
-    TH1D*         m_pedestalL2;
-    TH1D*         m_pedestalL3;
-
-    TH1F*         m_pedestals_es2017;
-
-    TH2D*         m_convRadius;
-    TH1D*         m_convFakeRate;
-    TH1D*         m_convRecoEfficiency;
-
-    TH1D*         m_leakageConverted;
-    TH1D*         m_leakageUnconverted;
-
-    TH1D*         m_zeeES2Profile;
-
-    TH2D*         m_pp0_elec;
-    TH2D*         m_pp0_unconv;
-    TH2D*         m_pp0_conv;
-
-    TH1D*         m_wstot_slope_A_data;
-    TH1D*         m_wstot_slope_B_MC;
-    TH1D*         m_wstot_40GeV_data;
-    TH1D*         m_wstot_40GeV_MC;
-    TH1D*         m_wstot_pT_data_p0_electrons;
-    TH1D*         m_wstot_pT_data_p1_electrons;
-    TH1D*         m_wstot_pT_data_p0_unconverted_photons;
-    TH1D*         m_wstot_pT_data_p1_unconverted_photons;
-    TH1D*         m_wstot_pT_data_p0_converted_photons;
-    TH1D*         m_wstot_pT_data_p1_converted_photons;
-    TH1D*         m_wstot_pT_MC_p0_electrons;
-    TH1D*         m_wstot_pT_MC_p1_electrons;
-    TH1D*         m_wstot_pT_MC_p0_unconverted_photons;
-    TH1D*         m_wstot_pT_MC_p1_unconverted_photons;
-    TH1D*         m_wstot_pT_MC_p0_converted_photons;
-    TH1D*         m_wstot_pT_MC_p1_converted_photons;
-    
+   std::unique_ptr<TH1>         m_trkSyst;
+
+    std::unique_ptr<TH1>         m_aPSNom;
+    std::unique_ptr<TH1>         m_daPSCor;
+    std::unique_ptr<TH1>         m_daPSb12;
+    std::unique_ptr<TH1>         m_aS12Nom;
+    std::unique_ptr<TH1>         m_daS12Cor;
+
+    std::unique_ptr<TH1>         m_zeeNom;
+    std::unique_ptr<TH1>         m_zeeNom_data2015;
+    std::unique_ptr<TH1>         m_zeeNom_data2016;
+    std::unique_ptr<TH1>         m_zeeNom_data2017;
+    std::unique_ptr<TH1>         m_zeeNom_data2018;
+    std::unique_ptr<TH1>         m_zeeFwdk;
+    std::unique_ptr<TH1>         m_zeeFwdb;
+
+    std::unique_ptr<TH1>         m_zeeSyst;
+    std::unique_ptr<TH1>         m_zeePhys;
+    std::unique_ptr<TH1>         m_uA2MeV_2015_first2weeks_correction;
+
+    std::unique_ptr<TH1>         m_resNom;
+    std::unique_ptr<TH1>         m_resSyst;
+    std::unique_ptr<TH1>         m_peakResData;
+    std::unique_ptr<TH1>         m_peakResMC;
+
+    std::unique_ptr<TH1>         m_dX_ID_Nom;
+
+    std::unique_ptr<TH1>         m_dX_IPPS_Nom;
+    std::unique_ptr<TH1>         m_dX_IPPS_LAr;
+
+    std::unique_ptr<TH1>         m_dX_IPAcc_Nom;
+    std::unique_ptr<TH1>         m_dX_IPAcc_G4;
+    std::unique_ptr<TH1>         m_dX_IPAcc_LAr;
+    std::unique_ptr<TH1>         m_dX_IPAcc_GL1;
+
+    std::unique_ptr<TH1>         m_dX_PSAcc_Nom;
+    std::unique_ptr<TH1>         m_dX_PSAcc_G4;
+    std::unique_ptr<TH1>         m_dX_PSAcc_LAr;
+
+    std::unique_ptr<TAxis>        m_psElectronEtaBins;
+    std::unique_ptr<TList>        m_psElectronGraphs;
+    std::unique_ptr<TAxis>        m_psUnconvertedEtaBins;
+    std::unique_ptr<TList>        m_psUnconvertedGraphs;
+    std::unique_ptr<TAxis>        m_psConvertedEtaBins;
+    std::unique_ptr<TList>        m_psConvertedGraphs;
+
+    std::unique_ptr<TAxis>        m_E4ElectronEtaBins;
+    std::unique_ptr<TList>        m_E4ElectronGraphs;
+    std::unique_ptr<TAxis>        m_E4UnconvertedEtaBins;
+    std::unique_ptr<TList>        m_E4UnconvertedGraphs;
+    std::unique_ptr<TAxis>        m_E4ConvertedEtaBins;
+    std::unique_ptr<TList>        m_E4ConvertedGraphs;
+
+    std::unique_ptr<TAxis>        m_s12ElectronEtaBins;
+    std::unique_ptr<TList>        m_s12ElectronGraphs;
+    std::unique_ptr<TAxis>        m_s12UnconvertedEtaBins;
+    std::unique_ptr<TList>        m_s12UnconvertedGraphs;
+    std::unique_ptr<TAxis>        m_s12ConvertedEtaBins;
+    std::unique_ptr<TList>        m_s12ConvertedGraphs;
+
+    std::unique_ptr<TH1>         m_pedestalL0;
+    std::unique_ptr<TH1>         m_pedestalL1;
+    std::unique_ptr<TH1>         m_pedestalL2;
+    std::unique_ptr<TH1>         m_pedestalL3;
+
+    std::unique_ptr<TH1>         m_pedestals_es2017;
+
+    std::unique_ptr<TH1>         m_convRadius;
+    std::unique_ptr<TH1>         m_convFakeRate;
+    std::unique_ptr<TH1>         m_convRecoEfficiency;
+
+    std::unique_ptr<TH1>         m_leakageConverted;
+    std::unique_ptr<TH1>         m_leakageUnconverted;
+
+    std::unique_ptr<TH1>         m_zeeES2Profile;
+
+    std::unique_ptr<TH2>         m_pp0_elec;
+    std::unique_ptr<TH2>         m_pp0_unconv;
+    std::unique_ptr<TH2>         m_pp0_conv;
+
+    std::unique_ptr<TH1>         m_wstot_slope_A_data;
+    std::unique_ptr<TH1>         m_wstot_slope_B_MC;
+    std::unique_ptr<TH1>         m_wstot_pT_data_p0_electrons;
+    std::unique_ptr<TH1>         m_wstot_pT_data_p1_electrons;
+    std::unique_ptr<TH1>         m_wstot_pT_data_p0_unconverted_photons;
+    std::unique_ptr<TH1>         m_wstot_pT_data_p1_unconverted_photons;
+    std::unique_ptr<TH1>         m_wstot_pT_data_p0_converted_photons;
+    std::unique_ptr<TH1>         m_wstot_pT_data_p1_converted_photons;
+    std::unique_ptr<TH1>         m_wstot_pT_MC_p0_electrons;
+    std::unique_ptr<TH1>         m_wstot_pT_MC_p1_electrons;
+    std::unique_ptr<TH1>         m_wstot_pT_MC_p0_unconverted_photons;
+    std::unique_ptr<TH1>         m_wstot_pT_MC_p1_unconverted_photons;
+    std::unique_ptr<TH1>         m_wstot_pT_MC_p0_converted_photons;
+    std::unique_ptr<TH1>         m_wstot_pT_MC_p1_converted_photons;
+
     // Geometry distortion vectors (to be ordered as in the the Geometry enum!)
 
-    std::vector<TH1D*> m_matElectronScale;
-    std::vector<TH1D*> m_matUnconvertedScale;
-    std::vector<TH1D*> m_matConvertedScale;
-    std::vector<TH1F*> m_matElectronCstTerm;
-    std::vector<TH1D*> m_matX0Additions;
+    std::vector<std::unique_ptr<TH1>> m_matElectronScale;
+    std::vector<std::unique_ptr<TH1>> m_matUnconvertedScale;
+    std::vector<std::unique_ptr<TH1>> m_matConvertedScale;
+    std::vector<std::unique_ptr<TH1>> m_matElectronCstTerm;
+    std::vector<std::unique_ptr<TH1>> m_matX0Additions;
 
     // Non-linearity graphs
 
-    TAxis*              m_matElectronEtaBins;
-    std::vector<TList*> m_matElectronGraphs;
+    std::unique_ptr<TAxis>              m_matElectronEtaBins;
+    std::vector<std::unique_ptr<TList>> m_matElectronGraphs;
+
+    // 2D histograms for release 21 material systematics sensitivity parameterization
+    std::unique_ptr<TH2> m_electronBias_ConfigA;
+    std::unique_ptr<TH2> m_electronBias_ConfigEpLp;
+    std::unique_ptr<TH2> m_electronBias_ConfigFpMX;
+    std::unique_ptr<TH2> m_electronBias_ConfigN;
+    std::unique_ptr<TH2> m_electronBias_ConfigIBL;
+    std::unique_ptr<TH2> m_electronBias_ConfigPP0;
+    std::unique_ptr<TH2> m_unconvertedBias_ConfigA;
+    std::unique_ptr<TH2> m_unconvertedBias_ConfigEpLp;
+    std::unique_ptr<TH2> m_unconvertedBias_ConfigFpMX;
+    std::unique_ptr<TH2> m_unconvertedBias_ConfigN;
+    std::unique_ptr<TH2> m_unconvertedBias_ConfigIBL;
+    std::unique_ptr<TH2> m_unconvertedBias_ConfigPP0;
+    std::unique_ptr<TH2> m_convertedBias_ConfigA;
+    std::unique_ptr<TH2> m_convertedBias_ConfigEpLp;
+    std::unique_ptr<TH2> m_convertedBias_ConfigFpMX;
+    std::unique_ptr<TH2> m_convertedBias_ConfigN;
+    std::unique_ptr<TH2> m_convertedBias_ConfigIBL;
+    std::unique_ptr<TH2> m_convertedBias_ConfigPP0;
 
     // Fastsim -> Fullsim corrections
 
-    TH1D*         m_G4OverAFII_electron;
-    TH1D*         m_G4OverAFII_converted;
-    TH1D*         m_G4OverAFII_unconverted;
-    TH1D*         m_G4OverFrSh;
-
-    TH2F* m_G4OverAFII_resolution_electron;
-    TH2F* m_G4OverAFII_resolution_unconverted;
-    TH2F* m_G4OverAFII_resolution_converted;
+    std::unique_ptr<TH1>         m_G4OverAFII_electron;
+    std::unique_ptr<TH1>         m_G4OverAFII_converted;
+    std::unique_ptr<TH1>         m_G4OverAFII_unconverted;
+    std::unique_ptr<TH2>         m_G4OverAFII_electron_2D;
+    std::unique_ptr<TH2>         m_G4OverAFII_converted_2D;
+    std::unique_ptr<TH2>         m_G4OverAFII_unconverted_2D;
+    std::unique_ptr<TH1>         m_G4OverFrSh;
+
+    std::unique_ptr<TH2> m_G4OverAFII_resolution_electron;
+    std::unique_ptr<TH2> m_G4OverAFII_resolution_unconverted;
+    std::unique_ptr<TH2> m_G4OverAFII_resolution_converted;
 
     // Main ES model switch
 
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/get_MaterialResolutionEffect.h b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/get_MaterialResolutionEffect.h
index 9991efa21dacab3f044bfe66e0c3b9ca3ad613d2..e29f7602e8b83d14f9075beabef6efee8a22231c 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/get_MaterialResolutionEffect.h
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/get_MaterialResolutionEffect.h
@@ -1,20 +1,16 @@
 /*
-  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 get_MaterialResolutionEffect_H
 #define get_MaterialResolutionEffect_H
-#include <stdlib.h>
-#include <math.h>
 #include <memory>
+#include <cstdlib>
+#include <cmath>
+#include <array>
 
 #include "AsgMessaging/AsgMessaging.h"
 
-#include "TH1.h"
-#include "TH2D.h"
-#include "TFile.h"
-#include "TArrayD.h"
-
 /**
   @class get_MaterialResolutionEffect
   @brief get resolution systematics from material effect (mc12c setup, MVA calibration)
@@ -24,6 +20,12 @@
 
 */
 
+class TH1;
+class TH2;
+class TFile;
+class TArrayD;
+
+
 class get_MaterialResolutionEffect : public asg::AsgMessaging {
 
  public:
@@ -44,12 +46,11 @@ class get_MaterialResolutionEffect : public asg::AsgMessaging {
  private:
 
   // histograms to store resolution parameters
-  TH1D* m_hSystPeak[4][8][3];
-  TH1D* m_hSystResol[4][8][3];
-  TH2D* m_hsyst_IBL_PP0[3];
+  std::array<std::array<std::array<std::unique_ptr<TH1>, 3>, 8>,4> m_hSystPeak;
+  std::array<std::array<std::array<std::unique_ptr<TH1>, 3>, 8>,4> m_hSystResol;
+  std::array<std::unique_ptr<TH2>, 3> m_hsyst_IBL_PP0;
   std::unique_ptr <TFile> m_file0;
-  //const TArrayD* m_etaBins;
-  const TArrayD* m_etBins;
+  const TArrayD* m_etBins; //A xistogram will own this
 
 
 };
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/selection.xml b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/selection.xml
index 9b0f78361db20c000c464b382e9604136fae2f52..a3fa90c9f8e24fae0a1830d93220cf7d9510571d 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/selection.xml
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/selection.xml
@@ -1,6 +1,5 @@
  <lcgdict>
 
-   <class name="CP::IEgammaCalibrationAndSmearingTool" />
    <class name="CP::EgammaCalibrationAndSmearingTool" />
 
    <class name="AtlasRoot::egammaEnergyCorrectionTool" />
@@ -20,4 +19,5 @@
    <class name="EgammaFactory" />
    <class name="LArTemperatureCorrectionTool" />
 
+
 </lcgdict>
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/systematics_S12.def b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/systematics_S12.def
new file mode 100644
index 0000000000000000000000000000000000000000..d95f1cac96383cecf875a9c8992efcd8d7241a21
--- /dev/null
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/ElectronPhotonFourMomentumCorrection/systematics_S12.def
@@ -0,0 +1,19 @@
+SYSMACRO(EG_SCALE_ZEESYST,        1, std::vector<double>(),        egEnergyCorr::Scale::ZeeSystUp,        egEnergyCorr::Scale::ZeeSystDown)
+SYSMACRO(EG_SCALE_LARCALIB,       0, decorrelation_bins_BE,        egEnergyCorr::Scale::LArCalibUp,       egEnergyCorr::Scale::LArCalibDown)
+SYSMACRO(EG_SCALE_LARUNCONVCALIB, 0, decorrelation_bins_BE,        egEnergyCorr::Scale::LArUnconvCalibUp, egEnergyCorr::Scale::LArUnconvCalibDown)
+SYSMACRO(EG_SCALE_LARELECCALIB,   1, std::vector<double>(),        egEnergyCorr::Scale::LArElecCalibUp,   egEnergyCorr::Scale::LArElecCalibDown)
+SYSMACRO(EG_SCALE_LARELECUNCONV,  0, decorrelation_bins_BE,        egEnergyCorr::Scale::LArElecUnconvUp,  egEnergyCorr::Scale::LArElecUnconvDown)
+SYSMACRO(EG_SCALE_G4,             1, std::vector<double>(),        egEnergyCorr::Scale::G4Up,             egEnergyCorr::Scale::G4Down)
+SYSMACRO(EG_SCALE_PS,             0, decorrelation_edges_MODULE,   egEnergyCorr::Scale::PSUp,             egEnergyCorr::Scale::PSDown)
+SYSMACRO(EG_SCALE_S12,            0, decorrelation_edges_S12,      egEnergyCorr::Scale::S12Up,            egEnergyCorr::Scale::S12Down);
+SYSMACRO(EG_SCALE_MATID,          0, decorrelation_edges_MATERIAL, egEnergyCorr::Scale::MatIDUp,          egEnergyCorr::Scale::MatIDDown);
+SYSMACRO(EG_SCALE_MATCRYO,        0, decorrelation_edges_TWELVE,   egEnergyCorr::Scale::MatCryoUp,        egEnergyCorr::Scale::MatCryoDown)
+SYSMACRO(EG_SCALE_MATCALO,        0, decorrelation_edges_TWELVE,   egEnergyCorr::Scale::MatCaloUp,        egEnergyCorr::Scale::MatCaloDown)
+SYSMACRO(EG_SCALE_L1GAIN,         1, std::vector<double>(),        egEnergyCorr::Scale::L1GainUp,         egEnergyCorr::Scale::L1GainDown)
+SYSMACRO(EG_SCALE_L2GAIN,         1, std::vector<double>(),        egEnergyCorr::Scale::L2GainUp,         egEnergyCorr::Scale::L2GainDown)
+SYSMACRO(EG_SCALE_PEDESTAL,       1, std::vector<double>(),        egEnergyCorr::Scale::PedestalUp,       egEnergyCorr::Scale::PedestalDown)
+SYSMACRO(PH_SCALE_LEAKAGEUNCONV,  1, std::vector<double>(),        egEnergyCorr::Scale::LeakageUnconvUp,  egEnergyCorr::Scale::LeakageUnconvDown)
+SYSMACRO(PH_SCALE_LEAKAGECONV,    1, std::vector<double>(),        egEnergyCorr::Scale::LeakageConvUp,    egEnergyCorr::Scale::LeakageConvDown)
+SYSMACRO(PH_SCALE_CONVEFFICIENCY, 1, std::vector<double>(),        egEnergyCorr::Scale::ConvEfficiencyUp, egEnergyCorr::Scale::ConvEfficiencyDown)
+SYSMACRO(PH_SCALE_CONVFAKERATE,   1, std::vector<double>(),        egEnergyCorr::Scale::ConvFakeRateUp,   egEnergyCorr::Scale::ConvFakeRateDown)
+SYSMACRO(PH_SCALE_CONVRADIUS,     1, std::vector<double>(),        egEnergyCorr::Scale::ConvRadiusUp,     egEnergyCorr::Scale::ConvRadiusDown)
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/EgammaCalibrationAndSmearingTool.cxx b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/EgammaCalibrationAndSmearingTool.cxx
index df8f2686cf82eb310fc2ee9730645d27ddcb8f24..0b582b9b794e07ff24c0f5d2c53b9cf6053f2f64 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/EgammaCalibrationAndSmearingTool.cxx
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/EgammaCalibrationAndSmearingTool.cxx
@@ -60,10 +60,16 @@ std::unique_ptr<egGain::GainTool> gainToolFactory(egEnergyCorr::ESModel model)
       return std::make_unique<egGain::GainTool>(gain_filename1, gain_filename2);
     }
     case egEnergyCorr::es2017:
-    case egEnergyCorr::es2017_summer: 
+    case egEnergyCorr::es2017_summer:
     case egEnergyCorr::es2017_summer_improved:
+    case egEnergyCorr::es2017_summer_final:
     case egEnergyCorr::es2017_R21_PRE:
-      return nullptr;  
+    case egEnergyCorr::es2017_R21_v0:
+    case egEnergyCorr::es2017_R21_v1:
+    case egEnergyCorr::es2017_R21_ofc0_v1:
+    case egEnergyCorr::es2018_R21_v0:
+    case egEnergyCorr::es2018_R21_v1:
+      return nullptr;
     default:
       return nullptr;
   }
@@ -97,9 +103,16 @@ std::unique_ptr<egammaMVATool> egammaMVAToolFactory(egEnergyCorr::ESModel model)
         case egEnergyCorr::es2017:
         case egEnergyCorr::es2017_summer:
         case egEnergyCorr::es2017_summer_improved:
+        case egEnergyCorr::es2017_summer_final:
+        case egEnergyCorr::es2015_5TeV:
           folder = "egammaMVACalib/offline/v4.0";
           break;
         case egEnergyCorr::es2017_R21_PRE:
+        case egEnergyCorr::es2017_R21_v0:
+        case egEnergyCorr::es2017_R21_v1:
+        case egEnergyCorr::es2017_R21_ofc0_v1:
+        case egEnergyCorr::es2018_R21_v0:
+        case egEnergyCorr::es2018_R21_v1:
 	  folder = "egammaMVACalib/offline/v7";
           break;
         default: folder = "";
@@ -134,13 +147,26 @@ std::unique_ptr<egammaLayerRecalibTool> egammaLayerRecalibToolFactory(egEnergyCo
     case egEnergyCorr::es2015c_summer:
     case egEnergyCorr::es2016PRE:
     case egEnergyCorr::es2017:
-    case egEnergyCorr::es2017_R21_PRE:  
+    case egEnergyCorr::es2015_5TeV:
+    case egEnergyCorr::es2017_R21_PRE:
       tune = "2012_alt_with_layer2";
       break;
     case egEnergyCorr::es2017_summer:
     case egEnergyCorr::es2017_summer_improved:
       tune = "es2017_20.7_improved";
       break;
+    case egEnergyCorr::es2017_summer_final:
+      tune = "es2017_20.7_final";
+      break;
+    case egEnergyCorr::es2017_R21_v0:
+    case egEnergyCorr::es2017_R21_v1:
+    case egEnergyCorr::es2017_R21_ofc0_v1:
+    case egEnergyCorr::es2018_R21_v0:
+      tune = "es2017_21.0_v0";
+      break;
+    case egEnergyCorr::es2018_R21_v1:
+      tune = "es2018_21.0_v0";
+      break;
     default:
       return nullptr;
   }
@@ -170,9 +196,16 @@ bool use_intermodule_correction(egEnergyCorr::ESModel model)
     case egEnergyCorr::es2015c_summer:
     case egEnergyCorr::es2016PRE:
     case egEnergyCorr::es2017:
-    case egEnergyCorr::es2017_summer:  
+    case egEnergyCorr::es2017_summer:
     case egEnergyCorr::es2017_summer_improved:
+    case egEnergyCorr::es2017_summer_final:
+    case egEnergyCorr::es2015_5TeV:
     case egEnergyCorr::es2017_R21_PRE:
+    case egEnergyCorr::es2017_R21_v0:
+    case egEnergyCorr::es2017_R21_v1:
+    case egEnergyCorr::es2017_R21_ofc0_v1:
+    case egEnergyCorr::es2018_R21_v0:
+    case egEnergyCorr::es2018_R21_v1:
       return true;
     case egEnergyCorr::UNDEFINED:  // TODO: find better logic
       return false;
@@ -209,8 +242,15 @@ bool is_run2(egEnergyCorr::ESModel model)
     case egEnergyCorr::es2016PRE:
     case egEnergyCorr::es2017:
     case egEnergyCorr::es2017_summer:
-    case egEnergyCorr::es2017_summer_improved:    
-    case egEnergyCorr::es2017_R21_PRE:  
+    case egEnergyCorr::es2017_summer_improved:
+    case egEnergyCorr::es2017_summer_final:
+    case egEnergyCorr::es2015_5TeV:
+    case egEnergyCorr::es2017_R21_PRE:
+    case egEnergyCorr::es2017_R21_v0:
+    case egEnergyCorr::es2017_R21_v1:
+    case egEnergyCorr::es2017_R21_ofc0_v1:
+    case egEnergyCorr::es2018_R21_v0:
+    case egEnergyCorr::es2018_R21_v1:
       return true;
     case egEnergyCorr::UNDEFINED:  // TODO: find better logic
       return false;
@@ -289,8 +329,15 @@ StatusCode EgammaCalibrationAndSmearingTool::initialize() {
   else if (m_ESModel == "es2016PRE") { m_TESModel = egEnergyCorr::es2016PRE; }
   else if (m_ESModel == "es2016data_mc15c") { m_TESModel = egEnergyCorr::es2017; }
   else if (m_ESModel == "es2016data_mc15c_summer") { m_TESModel = egEnergyCorr::es2017_summer; }
-  else if (m_ESModel == "es2016data_mc15c_summer_improved") { m_TESModel = egEnergyCorr::es2017_summer_improved; } 
+  else if (m_ESModel == "es2016data_mc15c_summer_improved") { m_TESModel = egEnergyCorr::es2017_summer_improved; }
+  else if (m_ESModel == "es2016data_mc15c_final") { m_TESModel = egEnergyCorr::es2017_summer_final; }
+  else if (m_ESModel == "es2015_5TeV") { m_TESModel = egEnergyCorr::es2015_5TeV; }
   else if (m_ESModel == "es2017_R21_PRE") { m_TESModel = egEnergyCorr::es2017_R21_PRE; }
+  else if (m_ESModel == "es2017_R21_v0") {m_TESModel = egEnergyCorr::es2017_R21_v0;}
+  else if (m_ESModel == "es2017_R21_v1") {m_TESModel = egEnergyCorr::es2017_R21_v1;}
+  else if (m_ESModel == "es2017_R21_ofc0_v1") {m_TESModel = egEnergyCorr::es2017_R21_ofc0_v1;}
+  else if (m_ESModel == "es2018_R21_v0") {m_TESModel = egEnergyCorr::es2018_R21_v0;}
+  else if (m_ESModel == "es2018_R21_v1") {m_TESModel = egEnergyCorr::es2018_R21_v1;}
   else if (m_ESModel.empty()) {
     ATH_MSG_ERROR("you must set ESModel property");
     return StatusCode::FAILURE;
@@ -423,7 +470,8 @@ StatusCode EgammaCalibrationAndSmearingTool::initialize() {
   }
 
   // configure layer recalibration tool
-  //For now: layer recalibration only needed before release 21
+  //For now: layer recalibration not applied to PRE release 21 (using run 1 based calibration applied at reco level)
+  //  for following R21 recommendations, need to apply the run2/run1 layer calibration ratio
   if (m_ESModel == "es2017_R21_PRE"){
     ATH_MSG_INFO("Layer recalibration already applied at cell level");
     m_useLayerCorrection = false;
@@ -439,7 +487,7 @@ StatusCode EgammaCalibrationAndSmearingTool::initialize() {
     }
     if (m_layer_recalibration_tool) { m_layer_recalibration_tool->msg().setLevel(this->msg().level()); }
   }
-  
+
   if (m_use_temp_correction201215 != AUTO) m_rootTool->use_temp_correction201215(m_use_temp_correction201215);
   if (m_use_uA2MeV_2015_first2weeks_correction != AUTO) m_rootTool->use_uA2MeV_2015_first2weeks_correction(m_use_uA2MeV_2015_first2weeks_correction);
   if (not m_use_full_statistical_error and m_decorrelation_model_scale == ScaleDecorrelation::FULL) { m_rootTool->useStatErrorScaling(true); }
@@ -448,7 +496,7 @@ StatusCode EgammaCalibrationAndSmearingTool::initialize() {
     ATH_MSG_ERROR("ep combination not supported yet");
     throw std::runtime_error("ep combination not supported yet");
   }
-  
+
   if (m_useIntermoduleCorrection == AUTO) { m_useIntermoduleCorrection = use_intermodule_correction(m_TESModel); }
   if (m_usePhiUniformCorrection == AUTO) { m_usePhiUniformCorrection = use_phi_uniform_correction(m_TESModel); }
   m_use_mapping_correction = not is_run2(m_TESModel);
@@ -503,18 +551,18 @@ StatusCode EgammaCalibrationAndSmearingTool::initialize() {
  * The typical scenario is :
  * For every IncidentType::BeginInputFile we can check for metadata
  * and try to employ them in determining the simulation Flavor.
- * If we found metadata 
+ * If we found metadata
  * set m_metadata_retrieved= True else set it to False
- * 
+ *
  * EndInputFile should not do something. As in any case we try for
  * each new IncidentType::BeginInputFile to do a retrieval
  *
  * The beginEvent should kick in only if the beginInputFile has
- * failed to find metadata . In which case we try to employ the event info 
- * 
+ * failed to find metadata . In which case we try to employ the event info
+ *
  * Asg/base class has our back in cases where the 1st beginEvent
  * happens before the 1st beginInputFile.
- * 
+ *
  * For this tool the apply correction is also using the EventInfo
  * to figure out data vs MC.
  */
@@ -522,7 +570,7 @@ StatusCode EgammaCalibrationAndSmearingTool::initialize() {
 StatusCode EgammaCalibrationAndSmearingTool::get_simflavour_from_metadata(PATCore::ParticleDataType::DataType& result) const
 {
 // adapted from https://svnweb.cern.ch/trac/atlasoff/browser/PhysicsAnalysis/AnalysisCommon/CPAnalysisExamples/trunk/Root/MetadataToolExample.cxx
-#ifndef XAOD_STANDALONE 
+#ifndef XAOD_STANDALONE
   //Try the Athena/POOL machinery
   std::string dataType("");
   if(AthAnalysisHelper::retrieveMetadata("/TagInfo", "project_name", dataType, inputMetaStore()).isSuccess()){
@@ -536,7 +584,7 @@ StatusCode EgammaCalibrationAndSmearingTool::get_simflavour_from_metadata(PATCor
           std::string simType("");
           ATH_CHECK(AthAnalysisHelper::retrieveMetadata("/Simulation/Parameters", "SimulationFlavour", simType, inputMetaStore()));
           boost::to_upper(simType);
-          result = (simType.find("ATLFASTII")==std::string::npos) ?  PATCore::ParticleDataType::Full : PATCore::ParticleDataType::Fast; 
+          result = (simType.find("ATLFASTII")==std::string::npos) ?  PATCore::ParticleDataType::Full : PATCore::ParticleDataType::Fast;
           return StatusCode::SUCCESS;
       }
   }
@@ -577,13 +625,13 @@ StatusCode EgammaCalibrationAndSmearingTool::beginInputFile()
   const StatusCode status_metadata = get_simflavour_from_metadata(data_flavour_metadata);
   if (status_metadata == StatusCode::SUCCESS) {
     m_metadata_retrieved = true;
-    ATH_MSG_DEBUG("metadata from new file: " << 
-            (data_flavour_metadata == PATCore::ParticleDataType::Data ? "data" : 
+    ATH_MSG_DEBUG("metadata from new file: " <<
+            (data_flavour_metadata == PATCore::ParticleDataType::Data ? "data" :
              (data_flavour_metadata == PATCore::ParticleDataType::Full ? "full simulation" : "fast simulation")));
 
     if (data_flavour_metadata != PATCore::ParticleDataType::Data) {
-        if (m_use_AFII == AUTO) { 
-            m_simulation = data_flavour_metadata; 
+        if (m_use_AFII == AUTO) {
+            m_simulation = data_flavour_metadata;
         }
         else { // user has set a preference
           // check if the preference is consistent and warn
@@ -611,7 +659,7 @@ StatusCode EgammaCalibrationAndSmearingTool::endInputFile() {
 }
 
 StatusCode EgammaCalibrationAndSmearingTool::beginEvent() {
-  
+
     if (m_metadata_retrieved) return StatusCode::SUCCESS;
 
     //determine MC/Data from evtInfo ... this will work for both athena and eventloop
@@ -702,7 +750,7 @@ CP::CorrectionCode EgammaCalibrationAndSmearingTool::correctedCopy(const xAOD::P
 double EgammaCalibrationAndSmearingTool::getEnergy(const xAOD::Photon& input)
 {
   xAOD::Photon* new_particle = nullptr;
-  ANA_CHECK_THROW (correctedCopy(input, new_particle));
+  ANA_CHECK_THROW(correctedCopy(input, new_particle));
   const double e = new_particle->e();
   delete new_particle;
   return e;
@@ -711,7 +759,7 @@ double EgammaCalibrationAndSmearingTool::getEnergy(const xAOD::Photon& input)
 double EgammaCalibrationAndSmearingTool::getEnergy(const xAOD::Electron& input)
 {
   xAOD::Electron* new_particle = nullptr;
-  ANA_CHECK_THROW (correctedCopy(input, new_particle));
+  ANA_CHECK_THROW(correctedCopy(input, new_particle));
   const double e = new_particle->e();
   delete new_particle;
   return e;
@@ -720,7 +768,7 @@ double EgammaCalibrationAndSmearingTool::getEnergy(const xAOD::Electron& input)
 
 CP::CorrectionCode EgammaCalibrationAndSmearingTool::applyCorrection(xAOD::Egamma & input, const xAOD::EventInfo& event_info)
 {
-  /* 
+  /*
    * Here we check for each event the kind of data DATA vs FullSim
    * The m_simulation flavour has already be determined from metadata
    */
@@ -838,7 +886,7 @@ CP::CorrectionCode EgammaCalibrationAndSmearingTool::applyCorrection(xAOD::Egamm
              oldtool_scale_flag_this_event(input, event_info),
              oldtool_resolution_flag_this_event(input, event_info),
              m_TResolutionType,
-	           m_varSF);
+	     m_varSF);
 
   ATH_MSG_DEBUG("energy after scale/systematic correction = " << boost::format("%.2f") % energy);
 
@@ -854,7 +902,7 @@ CP::CorrectionCode EgammaCalibrationAndSmearingTool::applyCorrection(xAOD::Egamm
 
 double EgammaCalibrationAndSmearingTool::getEnergy(xAOD::Egamma* p, const xAOD::EventInfo* event_info)
 {
-  ANA_CHECK_THROW (applyCorrection(*p, *event_info));
+  ANA_CHECK_THROW(applyCorrection(*p, *event_info));
   ATH_MSG_DEBUG("returning " << p->e());
   return p->e();
 }
@@ -910,13 +958,18 @@ void EgammaCalibrationAndSmearingTool::setupSystematics() {
     // TODO: independet implementation of ALL UP looping on all the variations
     m_syst_description[CP::SystematicVariation("EG_SCALE_ALL", +1)] = SysInfo{always, egEnergyCorr::Scale::AllUp};
     m_syst_description[CP::SystematicVariation("EG_SCALE_ALL", -1)] = SysInfo{always, egEnergyCorr::Scale::AllDown};
+    // extra AF2 systematics in addition to the 1NP
+    if ( m_TESModel == egEnergyCorr::es2017_R21_v0  || m_TESModel == egEnergyCorr::es2017_R21_v1 || m_TESModel == egEnergyCorr::es2017_R21_ofc0_v1 || m_TESModel == egEnergyCorr::es2018_R21_v0 || m_TESModel == egEnergyCorr::es2018_R21_v1) {
+       m_syst_description[CP::SystematicVariation("EG_SCALE_AF2",+1)] =  SysInfo{always, egEnergyCorr::Scale::af2Up};
+       m_syst_description[CP::SystematicVariation("EG_SCALE_AF2",-1)] =  SysInfo{always, egEnergyCorr::Scale::af2Down};
+    }
   }
   else if (m_decorrelation_model_scale == ScaleDecorrelation::FULL_ETA_CORRELATED) {
     // all the physical effects separately, considered as fully correlated in eta
 
     // common systematics for all the esmodels
-    #define SYSMACRO(name, fullcorrelated, decorrelation, flagup, flagdown)                \
-      m_syst_description[CP::SystematicVariation(#name, +1)] = SysInfo{always, flagup};    \
+    #define SYSMACRO(name, fullcorrelated, decorrelation, flagup, flagdown) \
+      m_syst_description[CP::SystematicVariation(#name, +1)] = SysInfo{always, flagup}; \
       m_syst_description[CP::SystematicVariation(#name, -1)] = SysInfo{always, flagdown};
     #include "ElectronPhotonFourMomentumCorrection/systematics.def"
     #undef SYSMACRO
@@ -928,8 +981,9 @@ void EgammaCalibrationAndSmearingTool::setupSystematics() {
     // additional systematics for S12 run2
     if (m_TESModel == egEnergyCorr::es2015PRE_res_improved or m_TESModel == egEnergyCorr::es2015PRE or
         m_TESModel == egEnergyCorr::es2015cPRE or m_TESModel == egEnergyCorr::es2015c_summer or
-        m_TESModel == egEnergyCorr::es2016PRE or m_TESModel == egEnergyCorr::es2017 or 
-	m_TESModel == egEnergyCorr::es2017_summer or m_TESModel == egEnergyCorr::es2017_summer_improved or m_TESModel == egEnergyCorr::es2017_R21_PRE) {
+        m_TESModel == egEnergyCorr::es2016PRE or m_TESModel == egEnergyCorr::es2017 or
+	m_TESModel == egEnergyCorr::es2017_summer or m_TESModel == egEnergyCorr::es2017_summer_improved
+	or m_TESModel == egEnergyCorr::es2015_5TeV) {
       m_syst_description[CP::SystematicVariation("EG_SCALE_LARCALIB_EXTRA2015PRE", +1)] = SysInfo{always, egEnergyCorr::Scale::LArCalibExtra2015PreUp};
       m_syst_description[CP::SystematicVariation("EG_SCALE_LARCALIB_EXTRA2015PRE", -1)] = SysInfo{always, egEnergyCorr::Scale::LArCalibExtra2015PreDown};
     }
@@ -943,26 +997,26 @@ void EgammaCalibrationAndSmearingTool::setupSystematics() {
     }
 
     // additional systematic for S12 last eta bin run2
-    if (m_TESModel == egEnergyCorr::es2017 or m_TESModel == egEnergyCorr::es2017_summer or m_TESModel == egEnergyCorr::es2017_summer_improved or m_TESModel == egEnergyCorr::es2017_R21_PRE) {
+    if (m_TESModel == egEnergyCorr::es2017 or m_TESModel == egEnergyCorr::es2017_summer or m_TESModel == egEnergyCorr::es2017_summer_improved or m_TESModel == egEnergyCorr::es2015_5TeV) {
       m_syst_description[CP::SystematicVariation("EG_SCALE_S12EXTRALASTETABINRUN2", +1)] = SysInfo{always, egEnergyCorr::Scale::S12ExtraLastEtaBinRun2Up};
       m_syst_description[CP::SystematicVariation("EG_SCALE_S12EXTRALASTETABINRUN2", -1)] = SysInfo{always, egEnergyCorr::Scale::S12ExtraLastEtaBinRun2Down};
     }
 
     // additional systematic for PP0 region
-    if (m_TESModel == egEnergyCorr::es2017 or m_TESModel == egEnergyCorr::es2017_summer or m_TESModel == egEnergyCorr::es2017_summer_improved or m_TESModel == egEnergyCorr::es2017_R21_PRE) {
+    if (m_TESModel == egEnergyCorr::es2017 or m_TESModel == egEnergyCorr::es2017_summer or m_TESModel == egEnergyCorr::es2017_summer_improved or m_TESModel == egEnergyCorr::es2017_summer_final or m_TESModel == egEnergyCorr::es2015_5TeV or m_TESModel == egEnergyCorr::es2017_R21_v0 or m_TESModel == egEnergyCorr::es2017_R21_v1 or m_TESModel == egEnergyCorr::es2017_R21_ofc0_v1 or m_TESModel == egEnergyCorr::es2018_R21_v0 or  m_TESModel == egEnergyCorr::es2018_R21_v1) {
       m_syst_description[CP::SystematicVariation("EG_SCALE_MATPP0", +1)] = SysInfo{always, egEnergyCorr::Scale::MatPP0Up};
       m_syst_description[CP::SystematicVariation("EG_SCALE_MATPP0", -1)] = SysInfo{always, egEnergyCorr::Scale::MatPP0Down};
     }
 
     // systematic related to wtots1
-    if (m_TESModel == egEnergyCorr::es2017 or m_TESModel == egEnergyCorr::es2017_summer or m_TESModel == egEnergyCorr::es2017_summer_improved or m_TESModel == egEnergyCorr::es2017_R21_PRE) {
+    if (m_TESModel == egEnergyCorr::es2017 or m_TESModel == egEnergyCorr::es2017_summer or m_TESModel == egEnergyCorr::es2017_summer_improved or m_TESModel == egEnergyCorr::es2017_summer_final or m_TESModel == egEnergyCorr::es2015_5TeV or m_TESModel == egEnergyCorr::es2017_R21_v0 or m_TESModel == egEnergyCorr::es2017_R21_v1 or m_TESModel == egEnergyCorr::es2017_R21_ofc0_v1 or m_TESModel == egEnergyCorr::es2018_R21_v0 or  m_TESModel == egEnergyCorr::es2018_R21_v1 ) {
       m_syst_description[CP::SystematicVariation("EG_SCALE_WTOTS1", +1)] = SysInfo{always, egEnergyCorr::Scale::Wtots1Up};
       m_syst_description[CP::SystematicVariation("EG_SCALE_WTOTS1", -1)] = SysInfo{always, egEnergyCorr::Scale::Wtots1Down};
     }
 
     // systematic for the scintillators
     if (m_TESModel == egEnergyCorr::es2015cPRE or m_TESModel == egEnergyCorr::es2015c_summer or m_TESModel == egEnergyCorr::es2016PRE or m_TESModel == egEnergyCorr::es2017
-	or m_TESModel == egEnergyCorr::es2017_summer or m_TESModel == egEnergyCorr::es2017_summer_improved or m_TESModel == egEnergyCorr::es2017_R21_PRE) {
+      or m_TESModel == egEnergyCorr::es2017_summer or m_TESModel == egEnergyCorr::es2017_summer_improved or m_TESModel == egEnergyCorr::es2017_summer_final or m_TESModel == egEnergyCorr::es2015_5TeV or m_TESModel == egEnergyCorr::es2017_R21_v0 or m_TESModel == egEnergyCorr::es2017_R21_v1 or  m_TESModel == egEnergyCorr::es2017_R21_ofc0_v1 or m_TESModel == egEnergyCorr::es2018_R21_v0 or m_TESModel == egEnergyCorr::es2018_R21_v1) {
       // scintillator systematics
       m_syst_description[CP::SystematicVariation("EG_SCALE_E4SCINTILLATOR", +1)] = SysInfo{always, egEnergyCorr::Scale::E4ScintillatorUp};
       m_syst_description[CP::SystematicVariation("EG_SCALE_E4SCINTILLATOR", -1)] = SysInfo{always, egEnergyCorr::Scale::E4ScintillatorDown};
@@ -973,6 +1027,26 @@ void EgammaCalibrationAndSmearingTool::setupSystematics() {
       m_syst_description[CP::SystematicVariation("EG_SCALE_LARTEMPERATURE_EXTRA2016PRE", +1)] = SysInfo{always, egEnergyCorr::Scale::LArTemperature2016PreUp};
       m_syst_description[CP::SystematicVariation("EG_SCALE_LARTEMPERATURE_EXTRA2016PRE", -1)] = SysInfo{always, egEnergyCorr::Scale::LArTemperature2016PreDown};
     }
+
+    //PS correlated barrel uncertainty
+    if (m_TESModel == egEnergyCorr::es2017_summer_final or m_TESModel == egEnergyCorr::es2017_R21_v0 or m_TESModel == egEnergyCorr::es2017_R21_v1 or m_TESModel == egEnergyCorr::es2017_R21_ofc0_v1 or m_TESModel == egEnergyCorr::es2018_R21_v0 or m_TESModel == egEnergyCorr::es2018_R21_v1){
+      m_syst_description[CP::SystematicVariation("EG_SCALE_PS_BARREL_B12", +1)] = SysInfo{always, egEnergyCorr::Scale::PSb12Up};
+      m_syst_description[CP::SystematicVariation("EG_SCALE_PS_BARREL_B12", -1)] = SysInfo{always, egEnergyCorr::Scale::PSb12Down};
+    }
+
+    // topo clustr threshold systematics aded to release 21 recommendations
+    if ( m_TESModel == egEnergyCorr::es2017_R21_v0 or m_TESModel == egEnergyCorr::es2017_R21_v1 or m_TESModel == egEnergyCorr::es2017_R21_ofc0_v1 or m_TESModel == egEnergyCorr::es2018_R21_v0 or m_TESModel == egEnergyCorr::es2018_R21_v1){
+       m_syst_description[CP::SystematicVariation("EG_SCALE_TOPOCLUSTER_THRES",+1)] = SysInfo{always, egEnergyCorr::Scale::topoClusterThresUp};
+       m_syst_description[CP::SystematicVariation("EG_SCALE_TOPOCLUSTER_THRES",-1)] = SysInfo{always, egEnergyCorr::Scale::topoClusterThresDown};
+    }
+
+    // extra AF2 systematics for release 21 recommendations - Moriond 2018 - pending proper AF2 to FullSim correction with release 21
+    if ( m_TESModel == egEnergyCorr::es2017_R21_v0 || m_TESModel == egEnergyCorr::es2017_R21_v1 || m_TESModel == egEnergyCorr::es2017_R21_ofc0_v1 || m_TESModel == egEnergyCorr::es2018_R21_v0  ||  m_TESModel ==  egEnergyCorr::es2018_R21_v1){
+       m_syst_description[CP::SystematicVariation("EG_SCALE_AF2",+1)] =  SysInfo{always, egEnergyCorr::Scale::af2Up};
+       m_syst_description[CP::SystematicVariation("EG_SCALE_AF2",-1)] =  SysInfo{always, egEnergyCorr::Scale::af2Down};
+    }
+
+
   }
   else if (m_decorrelation_model_scale == ScaleDecorrelation::ONENP_PLUS_UNCONR) {
       // qsum of all variations correlated 8/13 TeV + uncorrelated (additional systematics for 2015PRE or 2016)
@@ -984,8 +1058,8 @@ void EgammaCalibrationAndSmearingTool::setupSystematics() {
       #include "ElectronPhotonFourMomentumCorrection/systematics_1NPCOR_PLUS_UNCOR.def"
       #undef SYSMACRO
 
-    // additional systematic for S12 last eta bin run2
-    if (m_TESModel == egEnergyCorr::es2017 or m_TESModel == egEnergyCorr::es2017_summer or m_TESModel == egEnergyCorr::es2017_summer_improved or m_TESModel == egEnergyCorr::es2017_R21_PRE) {
+    // additional systematic for S12 last eta bin run2 - not needed anymore for last 20.7 model since it is part of bin per bin E1/E2 uncertainty in root file
+    if (m_TESModel == egEnergyCorr::es2017 or m_TESModel == egEnergyCorr::es2017_summer or m_TESModel == egEnergyCorr::es2017_summer_improved) {
       m_syst_description[CP::SystematicVariation("EG_SCALE_S12EXTRALASTETABINRUN2", +1)] = SysInfo{always, egEnergyCorr::Scale::S12ExtraLastEtaBinRun2Up};
       m_syst_description[CP::SystematicVariation("EG_SCALE_S12EXTRALASTETABINRUN2", -1)] = SysInfo{always, egEnergyCorr::Scale::S12ExtraLastEtaBinRun2Down};
     }
@@ -998,6 +1072,19 @@ void EgammaCalibrationAndSmearingTool::setupSystematics() {
     const std::vector<double> decorrelation_edges_MODULE = {0., 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.37, 1.52, 1.8};
     const std::vector<double> decorrelation_edges_MATERIAL = {0.0, 1.1, 1.5, 2.1, 2.5};
 
+    std::vector<double> decorrelation_edges_S12;
+    // for es2018_R21_v1 : 4 eta bins for muon E1/E2 uncertainty correlation
+    if (m_TESModel==  egEnergyCorr::es2018_R21_v1) {
+       decorrelation_edges_S12.resize(5);
+       decorrelation_edges_S12={0.,1.35,1.5,2.4,2.5};
+     }
+     // for previous run 2 muon calibration with 20.7, 5 eta bins for E1/E2 uncertainty correlation
+     else {
+       decorrelation_edges_S12.resize(6);
+       decorrelation_edges_S12={0., 0.6, 1.4, 1.5, 2.4, 2.5};
+     }
+
+    if(m_TESModel != egEnergyCorr::es2017_summer_final and m_TESModel != egEnergyCorr::es2017_R21_v0 and m_TESModel != egEnergyCorr::es2017_R21_v1 and m_TESModel != egEnergyCorr::es2017_R21_ofc0_v1 and m_TESModel != egEnergyCorr::es2018_R21_v0 and  m_TESModel != egEnergyCorr::es2018_R21_v1){
     #define SYSMACRO(name, fullcorrelated, decorrelation, flagup, flagdown)                \
     if (bool(fullcorrelated)) {                                                            \
       m_syst_description[CP::SystematicVariation(#name, +1)] = SysInfo{always, flagup};    \
@@ -1013,6 +1100,24 @@ void EgammaCalibrationAndSmearingTool::setupSystematics() {
     }
     #include "ElectronPhotonFourMomentumCorrection/systematics.def"
     #undef SYSMACRO
+    }
+    else{
+    #define SYSMACRO(name, fullcorrelated, decorrelation, flagup, flagdown)                \
+    if (bool(fullcorrelated)) {                                                            \
+      m_syst_description[CP::SystematicVariation(#name, +1)] = SysInfo{always, flagup};    \
+      m_syst_description[CP::SystematicVariation(#name, -1)] = SysInfo{always, flagdown};  \
+    }                                                                                      \
+    else {                                                                                 \
+      int i = 0;                                                                           \
+      for (const auto& p : AbsEtaCaloPredicatesFactory(decorrelation)) {                       \
+        m_syst_description[CP::SystematicVariation(#name "__ETABIN" + std::to_string(i), +1)] = SysInfo{p, flagup};    \
+        m_syst_description[CP::SystematicVariation(#name "__ETABIN" + std::to_string(i), -1)] = SysInfo{p, flagdown};  \
+        i += 1;                                                                            \
+      }                                                                                    \
+    }
+    #include "ElectronPhotonFourMomentumCorrection/systematics_S12.def"
+    #undef SYSMACRO
+    }//else
 
     if (m_use_full_statistical_error) {
       // statistical error, decorrelate in *all* the bins
@@ -1038,7 +1143,8 @@ void EgammaCalibrationAndSmearingTool::setupSystematics() {
     if (m_TESModel == egEnergyCorr::es2015PRE_res_improved or m_TESModel == egEnergyCorr::es2015PRE or
         m_TESModel == egEnergyCorr::es2015cPRE or m_TESModel == egEnergyCorr::es2015c_summer or
         m_TESModel == egEnergyCorr::es2016PRE or m_TESModel == egEnergyCorr::es2017
-	or m_TESModel == egEnergyCorr::es2017_summer or m_TESModel == egEnergyCorr::es2017_summer_improved or m_TESModel == egEnergyCorr::es2017_R21_PRE) {
+	or m_TESModel == egEnergyCorr::es2017_summer or m_TESModel == egEnergyCorr::es2017_summer_improved
+	or m_TESModel == egEnergyCorr::es2015_5TeV) {
       m_syst_description[CP::SystematicVariation("EG_SCALE_LARCALIB_EXTRA2015PRE__ETABIN0", +1)] = SysInfo{AbsEtaCaloPredicateFactory({0, 1.45}), egEnergyCorr::Scale::LArCalibExtra2015PreUp};
       m_syst_description[CP::SystematicVariation("EG_SCALE_LARCALIB_EXTRA2015PRE__ETABIN0", -1)] = SysInfo{AbsEtaCaloPredicateFactory({0, 1.45}), egEnergyCorr::Scale::LArCalibExtra2015PreDown};
       m_syst_description[CP::SystematicVariation("EG_SCALE_LARCALIB_EXTRA2015PRE__ETABIN1", +1)] = SysInfo{AbsEtaCaloPredicateFactory({1.45, 2.47}), egEnergyCorr::Scale::LArCalibExtra2015PreUp};
@@ -1058,13 +1164,13 @@ void EgammaCalibrationAndSmearingTool::setupSystematics() {
     }
 
     // additional systematic for S12 last eta bin run2
-    if (m_TESModel == egEnergyCorr::es2017 or m_TESModel == egEnergyCorr::es2017_summer or m_TESModel == egEnergyCorr::es2017_summer_improved or m_TESModel == egEnergyCorr::es2017_R21_PRE) {
+    if (m_TESModel == egEnergyCorr::es2017 or m_TESModel == egEnergyCorr::es2017_summer or m_TESModel == egEnergyCorr::es2017_summer_improved or m_TESModel == egEnergyCorr::es2015_5TeV) {
       m_syst_description[CP::SystematicVariation("EG_SCALE_S12EXTRALASTETABINRUN2", +1)] = SysInfo{always, egEnergyCorr::Scale::S12ExtraLastEtaBinRun2Up};
       m_syst_description[CP::SystematicVariation("EG_SCALE_S12EXTRALASTETABINRUN2", -1)] = SysInfo{always, egEnergyCorr::Scale::S12ExtraLastEtaBinRun2Down};
     }
 
     // additional systematic for PP0 region
-    if (m_TESModel == egEnergyCorr::es2017 or m_TESModel == egEnergyCorr::es2017_summer or m_TESModel == egEnergyCorr::es2017_summer_improved or m_TESModel == egEnergyCorr::es2017_R21_PRE) {
+    if (m_TESModel == egEnergyCorr::es2017 or m_TESModel == egEnergyCorr::es2017_summer or m_TESModel == egEnergyCorr::es2017_summer_improved or m_TESModel == egEnergyCorr::es2017_summer_final or m_TESModel == egEnergyCorr::es2015_5TeV or m_TESModel == egEnergyCorr::es2017_R21_v0 or m_TESModel == egEnergyCorr::es2017_R21_v1 or  m_TESModel == egEnergyCorr::es2017_R21_ofc0_v1 or m_TESModel == egEnergyCorr::es2018_R21_v0 or m_TESModel == egEnergyCorr::es2018_R21_v1) {
       m_syst_description[CP::SystematicVariation("EG_SCALE_MATPP0__ETABIN0", +1)] = SysInfo{AbsEtaCaloPredicateFactory(0, 1.5), egEnergyCorr::Scale::MatPP0Up};
       m_syst_description[CP::SystematicVariation("EG_SCALE_MATPP0__ETABIN1", +1)] = SysInfo{AbsEtaCaloPredicateFactory(1.5, 2.5), egEnergyCorr::Scale::MatPP0Up};
       m_syst_description[CP::SystematicVariation("EG_SCALE_MATPP0__ETABIN0", -1)] = SysInfo{AbsEtaCaloPredicateFactory(0, 1.5), egEnergyCorr::Scale::MatPP0Down};
@@ -1072,14 +1178,14 @@ void EgammaCalibrationAndSmearingTool::setupSystematics() {
     }
 
     // systematic related to wtots1
-    if (m_TESModel == egEnergyCorr::es2017 or m_TESModel == egEnergyCorr::es2017_summer or m_TESModel == egEnergyCorr::es2017_summer_improved or m_TESModel == egEnergyCorr::es2017_R21_PRE) {
+    if (m_TESModel == egEnergyCorr::es2017 or m_TESModel == egEnergyCorr::es2017_summer or m_TESModel == egEnergyCorr::es2017_summer_improved or m_TESModel == egEnergyCorr::es2017_summer_final or m_TESModel == egEnergyCorr::es2015_5TeV or m_TESModel == egEnergyCorr::es2017_R21_v0 or m_TESModel == egEnergyCorr::es2017_R21_v1 or m_TESModel == egEnergyCorr::es2017_R21_ofc0_v1 or m_TESModel == egEnergyCorr::es2018_R21_v0 or m_TESModel == egEnergyCorr::es2018_R21_v1) {
       m_syst_description[CP::SystematicVariation("EG_SCALE_WTOTS1", +1)] = SysInfo{always, egEnergyCorr::Scale::Wtots1Up};
       m_syst_description[CP::SystematicVariation("EG_SCALE_WTOTS1", -1)] = SysInfo{always, egEnergyCorr::Scale::Wtots1Down};
     }
 
     // systematic for the scintillators
     if (m_TESModel == egEnergyCorr::es2015cPRE or m_TESModel == egEnergyCorr::es2015c_summer or m_TESModel == egEnergyCorr::es2016PRE or m_TESModel == egEnergyCorr::es2017
-	or m_TESModel == egEnergyCorr::es2017_summer or m_TESModel == egEnergyCorr::es2017_summer_improved or m_TESModel == egEnergyCorr::es2017_R21_PRE) {
+    or m_TESModel == egEnergyCorr::es2017_summer or m_TESModel == egEnergyCorr::es2017_summer_improved or m_TESModel == egEnergyCorr::es2017_summer_final or m_TESModel == egEnergyCorr::es2015_5TeV or m_TESModel == egEnergyCorr::es2017_R21_v0 or m_TESModel == egEnergyCorr::es2017_R21_v1 or m_TESModel == egEnergyCorr::es2017_R21_ofc0_v1 or m_TESModel == egEnergyCorr::es2018_R21_v0 or  m_TESModel == egEnergyCorr::es2018_R21_v1) {
       m_syst_description[CP::SystematicVariation("EG_SCALE_E4SCINTILLATOR__ETABIN0", +1)] = SysInfo{AbsEtaCaloPredicateFactory(1.4, 1.46), egEnergyCorr::Scale::E4ScintillatorUp};
       m_syst_description[CP::SystematicVariation("EG_SCALE_E4SCINTILLATOR__ETABIN1", +1)] = SysInfo{AbsEtaCaloPredicateFactory(1.46, 1.52), egEnergyCorr::Scale::E4ScintillatorUp};
       m_syst_description[CP::SystematicVariation("EG_SCALE_E4SCINTILLATOR__ETABIN2", +1)] = SysInfo{AbsEtaCaloPredicateFactory(1.52, 1.6), egEnergyCorr::Scale::E4ScintillatorUp};
@@ -1097,6 +1203,26 @@ void EgammaCalibrationAndSmearingTool::setupSystematics() {
       m_syst_description[CP::SystematicVariation("EG_SCALE_LARTEMPERATURE_EXTRA2016PRE__ETABIN1", -1)] = SysInfo{AbsEtaCaloPredicateFactory(decorrelation_bins_BE[1]), egEnergyCorr::Scale::LArTemperature2016PreDown};
     }
 
+    //PS correlated barrel uncertainty
+    if (m_TESModel == egEnergyCorr::es2017_summer_final or m_TESModel == egEnergyCorr::es2017_R21_v0 or m_TESModel == egEnergyCorr::es2017_R21_v1 or m_TESModel == egEnergyCorr::es2017_R21_ofc0_v1 or m_TESModel == egEnergyCorr::es2018_R21_v0 or m_TESModel == egEnergyCorr::es2018_R21_v1){
+      m_syst_description[CP::SystematicVariation("EG_SCALE_PS_BARREL_B12", +1)] = SysInfo{always, egEnergyCorr::Scale::PSb12Up};
+      m_syst_description[CP::SystematicVariation("EG_SCALE_PS_BARREL_B12", -1)] = SysInfo{always, egEnergyCorr::Scale::PSb12Down};
+    }
+
+    // topo clustr threshold systematics aded to release 21 recommendations
+    if ( m_TESModel == egEnergyCorr::es2017_R21_v0 or m_TESModel == egEnergyCorr::es2017_R21_v1 or m_TESModel == egEnergyCorr::es2017_R21_ofc0_v1 or m_TESModel == egEnergyCorr::es2018_R21_v0 or m_TESModel == egEnergyCorr::es2018_R21_v1){
+       m_syst_description[CP::SystematicVariation("EG_SCALE_TOPOCLUSTER_THRES",+1)] = SysInfo{always, egEnergyCorr::Scale::topoClusterThresUp};
+       m_syst_description[CP::SystematicVariation("EG_SCALE_TOPOCLUSTER_THRES",-1)] = SysInfo{always, egEnergyCorr::Scale::topoClusterThresDown};
+    }
+
+    // extra AF2 systematics for release 21 recommendations - Moriond 2018 - pending proper AF2 to FullSim correction with release 21
+    if ( m_TESModel == egEnergyCorr::es2017_R21_v0  || m_TESModel == egEnergyCorr::es2017_R21_v1 ||  m_TESModel == egEnergyCorr::es2017_R21_ofc0_v1 || m_TESModel == egEnergyCorr::es2018_R21_v0 || m_TESModel ==  egEnergyCorr::es2018_R21_v1){
+       m_syst_description[CP::SystematicVariation("EG_SCALE_AF2",+1)] =  SysInfo{always, egEnergyCorr::Scale::af2Up};
+       m_syst_description[CP::SystematicVariation("EG_SCALE_AF2",-1)] =  SysInfo{always, egEnergyCorr::Scale::af2Down};
+    }
+
+
+
   }
   else {
     ATH_MSG_FATAL("scale decorrelation model invalid");
@@ -1122,11 +1248,15 @@ void EgammaCalibrationAndSmearingTool::setupSystematics() {
     m_syst_description_resolution[CP::SystematicVariation("EG_RESOLUTION_MATERIALCRYO", -1)] = egEnergyCorr::Resolution::MaterialCryoDown;
     m_syst_description_resolution[CP::SystematicVariation("EG_RESOLUTION_PILEUP", +1)] = egEnergyCorr::Resolution::PileUpUp;
     m_syst_description_resolution[CP::SystematicVariation("EG_RESOLUTION_PILEUP", -1)] = egEnergyCorr::Resolution::PileUpDown;
-    if (m_TESModel == egEnergyCorr::es2017 or m_TESModel == egEnergyCorr::es2017_summer or m_TESModel == egEnergyCorr::es2017_summer_improved or m_TESModel == egEnergyCorr::es2017_R21_PRE) {
+    if (m_TESModel == egEnergyCorr::es2017 or m_TESModel == egEnergyCorr::es2017_summer or m_TESModel == egEnergyCorr::es2017_summer_improved or m_TESModel == egEnergyCorr::es2017_summer_final or m_TESModel == egEnergyCorr::es2015_5TeV or m_TESModel == egEnergyCorr::es2017_R21_v0 or m_TESModel == egEnergyCorr::es2017_R21_v1 or m_TESModel == egEnergyCorr::es2017_R21_ofc0_v1 or m_TESModel == egEnergyCorr::es2018_R21_v0 or m_TESModel == egEnergyCorr::es2018_R21_v1) {
       m_syst_description_resolution[CP::SystematicVariation("EG_RESOLUTION_MATERIALIBL", +1)] = egEnergyCorr::Resolution::MaterialIBLUp;
       m_syst_description_resolution[CP::SystematicVariation("EG_RESOLUTION_MATERIALIBL", -1)] = egEnergyCorr::Resolution::MaterialIBLDown;
       m_syst_description_resolution[CP::SystematicVariation("EG_RESOLUTION_MATERIALPP0", +1)] = egEnergyCorr::Resolution::MaterialPP0Up;
       m_syst_description_resolution[CP::SystematicVariation("EG_RESOLUTION_MATERIALPP0", -1)] = egEnergyCorr::Resolution::MaterialPP0Down;
+      if (m_TESModel == egEnergyCorr::es2017_R21_v1 || m_TESModel == egEnergyCorr::es2017_R21_ofc0_v1 || m_TESModel == egEnergyCorr::es2018_R21_v0 ||  m_TESModel == egEnergyCorr::es2018_R21_v1) {
+        m_syst_description_resolution[CP::SystematicVariation("EG_RESOLUTION_AF2", +1)] = egEnergyCorr::Resolution::af2Up;
+        m_syst_description_resolution[CP::SystematicVariation("EG_RESOLUTION_AF2", -1)] = egEnergyCorr::Resolution::af2Down;
+      }
     }
   }
   else {
@@ -1187,25 +1317,25 @@ StatusCode EgammaCalibrationAndSmearingTool::applySystematicVariation(const CP::
 
 double EgammaCalibrationAndSmearingTool::intermodule_correction(double Ecl,  double phi, double eta) const
 {
-    
+
   //Intermodule Widening Correction: E_corr = E / (a' - b' * ((1 / (1 + exp((phi_mod - 2 * pi / 32) * c))) * (1 / (1 + exp((phi_mod - 2 * pi / 32) * (d))))))
   //(phi_min, phi_max) : [a' = a / a, b' = b / a, c, d]
-  
+
   double Ecl_corr = 0.;
   int DivInt = 0;
   double pi = 3.1415926535897932384626433832795 ;
 
-  if ( m_TESModel == egEnergyCorr::es2017_summer_improved ) {
-    
+  if ( m_TESModel == egEnergyCorr::es2017_summer_improved || m_TESModel == egEnergyCorr::es2017_summer_final || m_TESModel == egEnergyCorr::es2017_R21_v0 || m_TESModel == egEnergyCorr::es2017_R21_v1 || m_TESModel == egEnergyCorr::es2017_R21_ofc0_v1 || m_TESModel == egEnergyCorr::es2018_R21_v0 || m_TESModel == egEnergyCorr::es2018_R21_v1) {
+
     double phi_mod = 0;
     if (phi < 0)
       phi_mod = fmod(phi, 2 * pi / 16.) + pi / 8.;
     else
       phi_mod = fmod(phi, 2 * pi / 16.);
-    
+
     //  The correction concerns only the barrel
     if(fabs(eta) <= 1.37){
-      
+
       if(phi< (-7 * pi / 8) && phi> (-1 * pi))
 	Ecl_corr = Ecl / (1-0.1086 * ((1 / (1 + exp((phi_mod- 2*pi/32.) * 175.2759))) * (1 / (1 + exp((phi_mod- 2*pi/32.) * (-189.3612))))));
       if(phi< (-6 * pi / 8) && phi> (-7 * pi / 8))
@@ -1239,34 +1369,34 @@ double EgammaCalibrationAndSmearingTool::intermodule_correction(double Ecl,  dou
       if(phi< (8 * pi / 8) && phi> (7 * pi / 8))
 	Ecl_corr = Ecl / (1-0.1001 * ((1 / (1 + exp((phi_mod- 2*pi/32.) * 199.1735))) * (1 / (1 + exp((phi_mod- 2*pi/32.) * (-176.4056))))));
     }
-    
-    
+
+
     //  No correction for the EC
     else{
       Ecl_corr = Ecl;
     }
-    
+
   }
-  
+
   else {
-    
+
     //  Definitions of module folding into four quarters (top, left, bottom and right)
-    
+
     DivInt =  (int) (phi / ((2 * pi) / 16.));
     double phi_mod = phi - DivInt * (2 * pi / 16.);
-    
-    
+
+
     //  Centring on the intermodule --> phi_mod will now be in [0,0.4]
     if (phi_mod < 0) phi_mod += pi / 8.;
-    
+
     //  The correction concerns only the barrel
     if(fabs(eta) <= 1.4){
-      
+
       //  Top quarter
       if(phi < (3 * pi) / 4. && phi >= pi / 4.){
 	Ecl_corr = Ecl / (1-0.131 * ((1 / (1 + exp((phi_mod-0.2) * 199.08))) * (1 / (1 + exp((phi_mod-0.2) * (-130.36))))));
       }
-      
+
       //  Right quarter
       if(phi < pi / 4. && phi >= -pi / 4.){
 	Ecl_corr = Ecl / (1-0.0879 * ((1 / (1 + exp((phi_mod-0.2) * 221.01))) * (1 / (1 + exp((phi_mod-0.2) * (-149.51))))));
@@ -1280,15 +1410,15 @@ double EgammaCalibrationAndSmearingTool::intermodule_correction(double Ecl,  dou
 	Ecl_corr = Ecl / (1-0.102 * ((1 / (1 + exp((phi_mod-0.2) * 235.37))) * (1 / (1 + exp((phi_mod-0.2) * (-219.04))))));
       }
     }
-    
+
     //  No correction for the EC
     else{
       Ecl_corr = Ecl;
     }
   }
-  
+
   return Ecl_corr;
-  
+
 }
 
 double EgammaCalibrationAndSmearingTool::correction_phi_unif(double eta, double phi) const
@@ -1303,48 +1433,48 @@ double EgammaCalibrationAndSmearingTool::correction_phi_unif(double eta, double
       else if (phi < (13 * PI / 32.) && phi > (12 * PI / 32.)) { Fcorr -= 0.035; }
     }
   }
-  
-  if ( m_TESModel == egEnergyCorr::es2017_summer_improved ) {
+
+  if ( m_TESModel == egEnergyCorr::es2017_summer_improved || m_TESModel == egEnergyCorr::es2017_summer_final || m_TESModel == egEnergyCorr::es2017_R21_v0 || m_TESModel == egEnergyCorr::es2017_R21_v1 or m_TESModel == egEnergyCorr::es2017_R21_ofc0_v1 || m_TESModel == egEnergyCorr::es2018_R21_v0 || m_TESModel == egEnergyCorr::es2018_R21_v1) {
 
     if(eta < 0.2 && eta > 0.) {
       if (phi < (-7 * 2 * PI / 32.) && phi > (-8 * 2 * PI / 32.)) { Fcorr = 1.016314; }
-    } 
-    
+    }
+
     else if (eta < 0.6 && eta > 0.4) {
       if (phi < 0 && phi > (-2 * PI / 32.)) { Fcorr = 1.041591; }
       else if (phi < (-4 * 2 * PI / 32.) && phi > (-5 * 2 * PI / 32.)) { Fcorr = 1.067346; }
     }
-    
+
     else if (eta < 0.8 && eta > 0.6) {
       if (phi < (7 * 2 * PI / 32.) && phi > (6 * 2 * PI / 32.)) { Fcorr = 1.027980; }
     }
-    
+
     else if (eta < 1.4 && eta > 1.2) {
       if (phi < (-9 * 2 * PI / 32.) && phi > (-10 * 2 * PI / 32.)) { Fcorr = 1.020299; }
       else if (phi < (-11 * 2 * PI / 32.) && phi > (-12 * 2 * PI / 32.)) { Fcorr = 1.051426; }
     }
-    
+
     else if (eta < 2.3 && eta > 2.1) {
       if (phi < (-12 * 2 * PI / 32.) && phi > (-13 * 2 * PI / 32.)) { Fcorr = 1.071695; }
     }
-    
+
     else if(eta < 0. && eta > -0.2) {
       if (phi < (-12 * 2 * PI / 32.) && phi > (-13 * 2 * PI / 32.)) { Fcorr = 1.008227; }
       else if (phi < (-8 * 2 * PI / 32.) && phi > (-9 * 2 * PI / 32.)) { Fcorr = 1.013929; }
     }
-    
+
     else if(eta < -0.2 && eta > -0.4) {
       if (phi < (-9 * 2 * PI / 32.) && phi > (-10 * 2 * PI / 32.)) { Fcorr = 1.015749; }
     }
-    
+
     else if(eta < -1.2 && eta > -1.4) {
       if (phi < (-6 * 2 * PI / 32.) && phi > (-7 * 2 * PI / 32.)) { Fcorr = 1.064954; }
     }
-    
+
     else if (eta < -1.6 && eta > -1.8 ) {
       if (phi < (9 * 2 * PI / 32.) && phi > (8 * 2 * PI / 32.)) { Fcorr = 1.027448; }
     }
-    
+
     else if(eta < -2.3 && eta > -2.5) {
       if (phi < (-8 * 2 * PI / 32.) && phi > (-9 * 2 * PI / 32.)) { Fcorr = 1.025882; }
       else if (phi < (5 * 2 * PI / 32.) && phi > (4 * 2 * PI / 32.)) { Fcorr = 1.036616; }
@@ -1352,9 +1482,9 @@ double EgammaCalibrationAndSmearingTool::correction_phi_unif(double eta, double
       else if (phi < (10 * 2 * PI / 32.) && phi > (9 * 2 * PI / 32.)) { Fcorr = 1.026856; }
       else if (phi < (11 * 2 * PI / 32.) && phi > (10 * 2 * PI / 32.)) { Fcorr = 0.994382; }
     }
-    
+
   } // es2017_summer_improved end
-  
+
   else{
     if (eta < 0.6 && eta > 0.4) {
       if (phi < 0 && phi > (-2 * PI / 32.)) { Fcorr = 1.028; }
@@ -1390,7 +1520,7 @@ double EgammaCalibrationAndSmearingTool::correction_phi_unif(double eta, double
       else if (phi < (11 * 2 * PI / 32.) && phi > (10 * 2 * PI / 32.)) { Fcorr = 1.020; }
     }
   }
-  
+
   return Fcorr;
 }
 
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/EgammaFactory.cxx b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/EgammaFactory.cxx
index 35ae16b405346a6e434b967b83eb0899ae42c03d..5d8bc56a147f4c42c242d542b81e916353378a02 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/EgammaFactory.cxx
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/EgammaFactory.cxx
@@ -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
 */
 
 #ifdef XAOD_STANDALONE
@@ -116,13 +116,14 @@ EgammaFactory::~EgammaFactory()
   m_store.clear();
 }
 
-xAOD::EventInfo* EgammaFactory::create_eventinfo(bool simulation, int runnumber, int eventnumber)
+xAOD::EventInfo* EgammaFactory::create_eventinfo(bool simulation, int runnumber, int eventnumber, int average_interaction_per_crossing)
 {
   xAOD::EventInfo* ei= new xAOD::EventInfo();
   ei->makePrivateStore();
   ei->setRunNumber(runnumber);
   ei->setEventNumber(eventnumber);
   ei->setEventTypeBitmask(simulation);
+  ei->setAverageInteractionsPerCrossing(average_interaction_per_crossing);
   return ei;
 }
 
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/GainTool.cxx b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/GainTool.cxx
index 2c55f11797e517dcf9e70774b0f42bb191c460bc..5900ab49c2749ed51f949919be902a05dca22743 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/GainTool.cxx
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/GainTool.cxx
@@ -1,269 +1,268 @@
 /*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
-#include <sstream>
-#include <cmath>
-#include <algorithm>
-#include <TF1.h>
-#include <TFile.h>
-
-#include <ElectronPhotonFourMomentumCorrection/GainTool.h>
-
-using namespace std;
-
-namespace egGain {
-  
-  GainTool::GainTool(const std::string& filenameTO, const std::string& filenameVar){
-    Init( filenameTO, filenameVar);
-  }
-    
-  GainTool::~GainTool() {
-    
-    for (int i=0;i<m_NUM_ETA_BINS;++i){
-      delete m_funcTO[i];
-
-      for (int j=0;j< m_NUM_ENERGY_BINS;++j){
-	delete m_funcG[j][i];
-	delete m_conv_funcG[j][i];	
-      }
-      for (int j=0;j< m_NUM_UNCONV_ENERGY_BINS;++j){
-	delete  m_unconv_funcG[j][i];
-      }
-    }
-    
-  }
-
-  void GainTool::Init(const std::string& filenameTO, const std::string& filenameVar){
-
-    m_TOFile = std::make_unique<TFile>(filenameTO.c_str() );
-    m_varFile = std::make_unique<TFile>(filenameVar.c_str());
-
-    for (int id = 0 ; id < m_NUM_ETA_BINS ; id++){
-      string etabin;
-      stringstream test;
-      test << id;
-      etabin = "finalFD"+test.str();
-      m_funcTO[id] =(TF1*)m_TOFile->Get(etabin.c_str());
-
-      string etabin1_P_elec;
-      string etabin2_P_elec;
-      string etabin3_P_elec;
-
-      string etabin1_M_elec;
-      string etabin2_M_elec;
-      string etabin3_M_elec;
-
-      string etabin1_P_conv;
-      string etabin2_P_conv;
-      string etabin3_P_conv;
-
-      string etabin1_M_conv;
-      string etabin2_M_conv;
-      string etabin3_M_conv;
-
-      string etabin1_P_unconv;
-      string etabin2_P_unconv;
-      string etabin3_P_unconv;
-      string etabin4_P_unconv;
-
-      string etabin1_M_unconv;
-      string etabin2_M_unconv;
-      string etabin3_M_unconv;
-      string etabin4_M_unconv;
-
-      stringstream testP;
-      testP << id-14;
-      stringstream testM;
-      testM << 13-id;
-
-      etabin1_P_elec = "elec_func1_"+testP.str();
-      etabin2_P_elec = "elec_func2_"+testP.str();
-      etabin3_P_elec = "elec_func3_"+testP.str();
-
-      etabin1_M_elec = "elec_func1_"+testM.str();
-      etabin2_M_elec= "elec_func2_"+testM.str();
-      etabin3_M_elec= "elec_func3_"+testM.str();
-
-      etabin1_P_conv = "phot_conv_func1_"+testP.str();
-      etabin2_P_conv = "phot_conv_func2_"+testP.str();
-      etabin3_P_conv = "phot_conv_func3_"+testP.str();
-
-      etabin1_M_conv = "phot_conv_func1_"+testM.str();
-      etabin2_M_conv = "phot_conv_func2_"+testM.str();
-      etabin3_M_conv = "phot_conv_func3_"+testM.str();
-
-      etabin1_P_unconv = "phot_unconv_func1_"+testP.str();
-      etabin2_P_unconv = "phot_unconv_func2_"+testP.str();
-      etabin3_P_unconv = "phot_unconv_func3_"+testP.str();
-      etabin4_P_unconv = "phot_unconv_func4_"+testP.str();
-
-      etabin1_M_unconv ="phot_unconv_func1_"+testM.str();
-      etabin2_M_unconv= "phot_unconv_func2_"+testM.str();
-      etabin3_M_unconv= "phot_unconv_func3_"+testM.str();
-      etabin4_M_unconv= "phot_unconv_func4_"+testM.str();
-
-      if(id<14){
-	m_funcG[0][id]=(TF1*)m_varFile->Get(etabin1_M_elec.c_str());
-	m_funcG[1][id]=(TF1*)m_varFile->Get(etabin2_M_elec.c_str());
-	m_funcG[2][id]=(TF1*)m_varFile->Get(etabin3_M_elec.c_str());
-	
-	m_conv_funcG[0][id]=(TF1*)m_varFile->Get(etabin1_M_conv.c_str());
-	m_conv_funcG[1][id]=(TF1*)m_varFile->Get(etabin2_M_conv.c_str());
-	m_conv_funcG[2][id]=(TF1*)m_varFile->Get(etabin3_M_conv.c_str());
-	
-	m_unconv_funcG[0][id]=(TF1*)m_varFile->Get(etabin1_M_unconv.c_str());
-	m_unconv_funcG[1][id]=(TF1*)m_varFile->Get(etabin2_M_unconv.c_str());
-	m_unconv_funcG[2][id]=(TF1*)m_varFile->Get(etabin3_M_unconv.c_str());
-	m_unconv_funcG[3][id]=(TF1*)m_varFile->Get(etabin4_M_unconv.c_str());	
-      }
-
-      else {
-	m_funcG[0][id]=(TF1*)m_varFile->Get(etabin1_P_elec.c_str());
-	m_funcG[1][id]=(TF1*)m_varFile->Get(etabin2_P_elec.c_str());
-	m_funcG[2][id]=(TF1*)m_varFile->Get(etabin3_P_elec.c_str());
-	
-	m_conv_funcG[0][id]=(TF1*)m_varFile->Get(etabin1_P_conv.c_str());
-	m_conv_funcG[1][id]=(TF1*)m_varFile->Get(etabin2_P_conv.c_str());
-	m_conv_funcG[2][id]=(TF1*)m_varFile->Get(etabin3_P_conv.c_str());
-	
-	m_unconv_funcG[0][id]=(TF1*)m_varFile->Get(etabin1_P_unconv.c_str());
-	m_unconv_funcG[1][id]=(TF1*)m_varFile->Get(etabin2_P_unconv.c_str());
-	m_unconv_funcG[2][id]=(TF1*)m_varFile->Get(etabin3_P_unconv.c_str());
-	m_unconv_funcG[3][id]=(TF1*)m_varFile->Get(etabin4_P_unconv.c_str());
-      }
-    }
-  }
-
-  double GainTool::CorrectionGainTool(double eta_input, double energy_input, double energy_layer2_input, PATCore::ParticleType::Type ptype){
-
-    double eta_low[28] = {-2.4,-2.32,-2.22,-2.12,-2.02,-1.92,-1.82,-1.72,-1.62,-1.37,-1.2,-0.8,-0.6,-0.4,0.,0.4,0.6,0.8,1.2,1.52,1.62,1.72,1.82,1.92,2.02,2.12,2.22,2.32};
-    double eta_high[28] = {-2.32,-2.22,-2.12,-2.02,-1.92,-1.82,-1.72,-1.62,-1.52,-1.2,-0.8,-0.6,-0.4,0,0.4,0.6,0.8,1.2,1.37,1.62,1.72,1.82,1.92,2.02,2.12,2.22,2.32,2.4};
-
-
-    double diffES[28] = {-0.0763457,0.198092,-0.0288093,-0.0808452,0.0271571,-0.0975428,-0.0164521,-0.0737317,0.136447,0.0352632,-0.00197711,0.0244447,-0.0641183,0.0810265,
-			   0.00735352,-0.013568,-0.0169185,-0.0142155,-0.0255637,0.0586014,-0.163098,0.0237162,-0.0690589,-0.0346536,-0.0886648,-0.0914096,0.0738988,-0.0376201};
-
-
-    double corrHG[28] = {-0.484364,0.263687,-0.037742,-0.0553371,-0.0640682,-0.201265,-0.176052,-0.206764,0.0224639,0.00855262,-0.00583258,0.00196343,-0.108951,0.0708467,
-			   -0.00438541,-0.0928867,-0.0487188,-0.0214743,-0.0619355,-0.055117,-0.297427,-0.0795861,-0.173311,-0.0905191,-0.297548,-0.147814,-0.0867268,-0.384337};
-
-    double corrMG[28]={-0.0160707,0.199527,-0.000845413,-0.0611091,0.0877896,0.0479742,0.141414,0.639507,0.72873,0.21984,0.0643192,0.146518,0.0279768,0.140151,0.0682126,
-			 0.167472,0.154887,0.122343,0.212282,0.657224,0.576652,0.135954,0.0798118,0.0167071,-0.0221686,-0.0398211,0.128146,-0.0226478};
-
-    double range_energy[28]={195.,180.,175.,160.,140.,145.,155.,155.,145.,140.,120.,90.,90.,75.,75.,90.,90.,120.,140.,145.,155.,155.,145.,140.,160.,175.,180.,195.};
-    
-    double corrM_G, corrE;
-    corrM_G =1;
-    corrE=0;
-
-    double energy_output;
-
-    TF1* funcG_com[m_NUM_ENERGY_BINS][m_NUM_ETA_BINS]={};
-
-    if (fabs(eta_input) > 2.4)
-      return energy_input*1000.;
-
-    int id_eta = -9999999;
-
-    for(int i = 0 ; i < 28 ; i++){
-      if( (eta_input >= eta_low[i]) && (eta_input <= eta_high[i]) ){
-	id_eta = i;
-	break;
-      }
-    }
-
-    if (id_eta < 0)
-      return energy_input*1000.;
-
-    if (ptype == PATCore::ParticleType::UnconvertedPhoton){
-      double norm_unconv=1.;
-      if (id_eta<17 && id_eta>10) norm_unconv = m_unconv_funcG[0][id_eta]->Eval(range_energy[id_eta]);
-      else if (id_eta<25 && id_eta>2) norm_unconv = m_unconv_funcG[1][id_eta]->Eval(range_energy[id_eta]);
-      else  norm_unconv = m_unconv_funcG[2][id_eta]->Eval(range_energy[id_eta]);
-
-      if (energy_input<92) corrM_G = (m_unconv_funcG[0][id_eta]->Eval(energy_input))/(norm_unconv);
-      else if (energy_input<160 && energy_input>=92) corrM_G = (m_unconv_funcG[1][id_eta]->Eval(energy_input))/(norm_unconv);
-      else if (energy_input<400 && energy_input>=160) corrM_G = (m_unconv_funcG[2][id_eta]->Eval(energy_input))/(norm_unconv);
-      else if (energy_input>=400) corrM_G = (m_unconv_funcG[3][id_eta]->Eval(energy_input))/(norm_unconv);
-    }
-
-    else if (ptype==PATCore::ParticleType::ConvertedPhoton){
-      funcG_com[0][id_eta]= m_conv_funcG[0][id_eta];
-      funcG_com[1][id_eta]= m_conv_funcG[1][id_eta];
-      funcG_com[2][id_eta]= m_conv_funcG[2][id_eta];
-    }
-    else if (ptype==PATCore::ParticleType::Electron){
-      funcG_com[0][id_eta]= m_funcG[0][id_eta];
-      funcG_com[1][id_eta]= m_funcG[1][id_eta];
-      funcG_com[2][id_eta]= m_funcG[2][id_eta];
-    }
-
-
-    if(ptype==PATCore::ParticleType::ConvertedPhoton || ptype==PATCore::ParticleType::Electron){
-      if(id_eta==12 || id_eta == 13 || id_eta == 14 || id_eta==15){
-	if (energy_input<105) corrM_G = (funcG_com[0][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
-	else if (energy_input<400 && energy_input>=105) corrM_G = (funcG_com[1][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
-	else if (energy_input>=400) corrM_G = (funcG_com[2][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
-      }
-
-      else if(id_eta == 11 || id_eta ==16){
-	if (energy_input<130) corrM_G = (funcG_com[0][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
-	else if (energy_input<440 && energy_input>=130) corrM_G = (funcG_com[1][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
-	else if (energy_input>=440) corrM_G = (funcG_com[2][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
-      }
-
-      else if(id_eta == 10 || id_eta ==17){
-	if (energy_input<190) corrM_G = (funcG_com[0][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
-	else if (energy_input<400 && energy_input>=190) corrM_G = (funcG_com[1][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
-	else if (energy_input>=400) corrM_G = (funcG_com[2][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
-      }
-
-      else if(id_eta == 9 || id_eta ==18){
-	if (energy_input<200) corrM_G = (funcG_com[0][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
-	else if (energy_input<480 && energy_input>=200) corrM_G = (funcG_com[1][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
-	else if (energy_input>=480) corrM_G = (funcG_com[2][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
-      }
-
-      else if(id_eta==7 || id_eta == 8 || id_eta ==19 || id_eta==20){
-	if (energy_input<250) corrM_G = (funcG_com[0][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
-	else if (energy_input<450 && energy_input>=250) corrM_G = (funcG_com[1][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
-	else if (energy_input>=450) corrM_G = (funcG_com[2][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
-      }
-
-      else if(id_eta == 6 || id_eta ==21){
-	if (energy_input<180) corrM_G = (funcG_com[0][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
-	else if (energy_input<385 && energy_input>=180) corrM_G = (funcG_com[1][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
-	else if (energy_input>=385) corrM_G = (funcG_com[2][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
-      }
-
-      else if(id_eta == 5 || id_eta ==22){
-	if (energy_input<165) corrM_G = (funcG_com[0][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
-	else if (energy_input<460 && energy_input>=165) corrM_G = (funcG_com[1][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
-	else if (energy_input>=460) corrM_G = (funcG_com[2][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
-      }
-
-      else if(id_eta == 4 || id_eta ==23){
-	if (energy_input<160) corrM_G = (funcG_com[0][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
-	else if (energy_input<450 && energy_input>=160) corrM_G = (funcG_com[1][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
-	else if (energy_input>=450) corrM_G = (funcG_com[2][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
-      }
-
-      else{
-	if (energy_input<200) corrM_G = (funcG_com[0][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
-	else if (energy_input<480 && energy_input>=200) corrM_G = (funcG_com[1][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
-	else if (energy_input>=480) corrM_G = (funcG_com[2][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
-      }
-    }
-    
-    double ets2 = energy_layer2_input/cosh(eta_input);
-    double valTO = (m_funcTO[id_eta])->Eval(ets2);
-    if (valTO < 0) {
-      valTO=0;
-    }
-
-    corrE = -2 * energy_input* (((corrMG[id_eta]/91.2) - (diffES[id_eta]/91.2))*valTO*corrM_G + ((corrHG[id_eta]/91.2) - (diffES[id_eta]/91.2))*(1-valTO));
-    energy_output = (energy_input+corrE)*1000.;
-    return energy_output;
-  }
-}
+#include <sstream>
+#include <cmath>
+#include <algorithm>
+#include <TF1.h>
+#include <TFile.h>
+
+#include <ElectronPhotonFourMomentumCorrection/GainTool.h>
+
+using namespace std;
+
+namespace egGain {
+
+  GainTool::GainTool(const std::string& filenameTO, const std::string& filenameVar){
+    m_TOFile = 0;
+    m_varFile = 0;
+    Init( filenameTO, filenameVar);
+  }
+
+  GainTool::~GainTool() {
+
+    for (int i=0;i<m_NUM_ETA_BINS;++i){
+      delete m_funcTO[i];
+
+      for (int j=0;j< m_NUM_ENERGY_BINS;++j){
+	delete m_funcG[j][i];
+	delete m_conv_funcG[j][i];
+      }
+      for (int j=0;j< m_NUM_UNCONV_ENERGY_BINS;++j){
+	delete  m_unconv_funcG[j][i];
+      }
+    }
+
+  }
+
+  void GainTool::Init(const std::string& filenameTO, const std::string& filenameVar){
+
+    m_TOFile = std::make_unique<TFile>(filenameTO.c_str() );
+    m_varFile = std::make_unique<TFile>(filenameVar.c_str());
+
+    for (int id = 0 ; id < m_NUM_ETA_BINS ; id++){
+      string etabin;
+      stringstream test;
+      test << id;
+      etabin = "finalFD"+test.str();
+      m_funcTO[id] =(TF1*)m_TOFile->Get(etabin.c_str());
+
+      string etabin1_P_elec;
+      string etabin2_P_elec;
+      string etabin3_P_elec;
+
+      string etabin1_M_elec;
+      string etabin2_M_elec;
+      string etabin3_M_elec;
+
+      string etabin1_P_conv;
+      string etabin2_P_conv;
+      string etabin3_P_conv;
+
+      string etabin1_M_conv;
+      string etabin2_M_conv;
+      string etabin3_M_conv;
+
+      string etabin1_P_unconv;
+      string etabin2_P_unconv;
+      string etabin3_P_unconv;
+      string etabin4_P_unconv;
+
+      string etabin1_M_unconv;
+      string etabin2_M_unconv;
+      string etabin3_M_unconv;
+      string etabin4_M_unconv;
+
+      stringstream testP;
+      testP << id-14;
+      stringstream testM;
+      testM << 13-id;
+
+      etabin1_P_elec = "elec_func1_"+testP.str();
+      etabin2_P_elec = "elec_func2_"+testP.str();
+      etabin3_P_elec = "elec_func3_"+testP.str();
+
+      etabin1_M_elec = "elec_func1_"+testM.str();
+      etabin2_M_elec= "elec_func2_"+testM.str();
+      etabin3_M_elec= "elec_func3_"+testM.str();
+
+      etabin1_P_conv = "phot_conv_func1_"+testP.str();
+      etabin2_P_conv = "phot_conv_func2_"+testP.str();
+      etabin3_P_conv = "phot_conv_func3_"+testP.str();
+
+      etabin1_M_conv = "phot_conv_func1_"+testM.str();
+      etabin2_M_conv = "phot_conv_func2_"+testM.str();
+      etabin3_M_conv = "phot_conv_func3_"+testM.str();
+
+      etabin1_P_unconv = "phot_unconv_func1_"+testP.str();
+      etabin2_P_unconv = "phot_unconv_func2_"+testP.str();
+      etabin3_P_unconv = "phot_unconv_func3_"+testP.str();
+      etabin4_P_unconv = "phot_unconv_func4_"+testP.str();
+
+      etabin1_M_unconv ="phot_unconv_func1_"+testM.str();
+      etabin2_M_unconv= "phot_unconv_func2_"+testM.str();
+      etabin3_M_unconv= "phot_unconv_func3_"+testM.str();
+      etabin4_M_unconv= "phot_unconv_func4_"+testM.str();
+
+      if(id<14){
+	m_funcG[0][id]=(TF1*)m_varFile->Get(etabin1_M_elec.c_str());
+	m_funcG[1][id]=(TF1*)m_varFile->Get(etabin2_M_elec.c_str());
+	m_funcG[2][id]=(TF1*)m_varFile->Get(etabin3_M_elec.c_str());
+
+	m_conv_funcG[0][id]=(TF1*)m_varFile->Get(etabin1_M_conv.c_str());
+	m_conv_funcG[1][id]=(TF1*)m_varFile->Get(etabin2_M_conv.c_str());
+	m_conv_funcG[2][id]=(TF1*)m_varFile->Get(etabin3_M_conv.c_str());
+
+	m_unconv_funcG[0][id]=(TF1*)m_varFile->Get(etabin1_M_unconv.c_str());
+	m_unconv_funcG[1][id]=(TF1*)m_varFile->Get(etabin2_M_unconv.c_str());
+	m_unconv_funcG[2][id]=(TF1*)m_varFile->Get(etabin3_M_unconv.c_str());
+	m_unconv_funcG[3][id]=(TF1*)m_varFile->Get(etabin4_M_unconv.c_str());
+      }
+
+      else {
+	m_funcG[0][id]=(TF1*)m_varFile->Get(etabin1_P_elec.c_str());
+	m_funcG[1][id]=(TF1*)m_varFile->Get(etabin2_P_elec.c_str());
+	m_funcG[2][id]=(TF1*)m_varFile->Get(etabin3_P_elec.c_str());
+
+	m_conv_funcG[0][id]=(TF1*)m_varFile->Get(etabin1_P_conv.c_str());
+	m_conv_funcG[1][id]=(TF1*)m_varFile->Get(etabin2_P_conv.c_str());
+	m_conv_funcG[2][id]=(TF1*)m_varFile->Get(etabin3_P_conv.c_str());
+
+	m_unconv_funcG[0][id]=(TF1*)m_varFile->Get(etabin1_P_unconv.c_str());
+	m_unconv_funcG[1][id]=(TF1*)m_varFile->Get(etabin2_P_unconv.c_str());
+	m_unconv_funcG[2][id]=(TF1*)m_varFile->Get(etabin3_P_unconv.c_str());
+	m_unconv_funcG[3][id]=(TF1*)m_varFile->Get(etabin4_P_unconv.c_str());
+      }
+    }
+  }
+
+  double GainTool::CorrectionGainTool(double eta_input, double energy_input, double energy_layer2_input, PATCore::ParticleType::Type ptype){
+
+    double eta_low[28] = {-2.4,-2.32,-2.22,-2.12,-2.02,-1.92,-1.82,-1.72,-1.62,-1.37,-1.2,-0.8,-0.6,-0.4,0.,0.4,0.6,0.8,1.2,1.52,1.62,1.72,1.82,1.92,2.02,2.12,2.22,2.32};
+    double eta_high[28] = {-2.32,-2.22,-2.12,-2.02,-1.92,-1.82,-1.72,-1.62,-1.52,-1.2,-0.8,-0.6,-0.4,0,0.4,0.6,0.8,1.2,1.37,1.62,1.72,1.82,1.92,2.02,2.12,2.22,2.32,2.4};
+
+
+    double diffES[28] = {-0.0763457,0.198092,-0.0288093,-0.0808452,0.0271571,-0.0975428,-0.0164521,-0.0737317,0.136447,0.0352632,-0.00197711,0.0244447,-0.0641183,0.0810265,
+			   0.00735352,-0.013568,-0.0169185,-0.0142155,-0.0255637,0.0586014,-0.163098,0.0237162,-0.0690589,-0.0346536,-0.0886648,-0.0914096,0.0738988,-0.0376201};
+
+
+    double corrHG[28] = {-0.484364,0.263687,-0.037742,-0.0553371,-0.0640682,-0.201265,-0.176052,-0.206764,0.0224639,0.00855262,-0.00583258,0.00196343,-0.108951,0.0708467,
+			   -0.00438541,-0.0928867,-0.0487188,-0.0214743,-0.0619355,-0.055117,-0.297427,-0.0795861,-0.173311,-0.0905191,-0.297548,-0.147814,-0.0867268,-0.384337};
+
+    double corrMG[28]={-0.0160707,0.199527,-0.000845413,-0.0611091,0.0877896,0.0479742,0.141414,0.639507,0.72873,0.21984,0.0643192,0.146518,0.0279768,0.140151,0.0682126,
+			 0.167472,0.154887,0.122343,0.212282,0.657224,0.576652,0.135954,0.0798118,0.0167071,-0.0221686,-0.0398211,0.128146,-0.0226478};
+
+    double range_energy[28]={195.,180.,175.,160.,140.,145.,155.,155.,145.,140.,120.,90.,90.,75.,75.,90.,90.,120.,140.,145.,155.,155.,145.,140.,160.,175.,180.,195.};
+
+    double corrM_G, corrE;
+    corrM_G =1;
+    corrE=0;
+
+    double energy_output;
+
+    TF1* funcG_com[m_NUM_ENERGY_BINS][m_NUM_ETA_BINS]={};
+
+    if (fabs(eta_input) > 2.4)
+      return energy_input*1000.;
+
+    int id_eta = -9999999;
+
+    for(int i = 0 ; i < 28 ; i++){
+      if( (eta_input >= eta_low[i]) && (eta_input <= eta_high[i]) ){
+	id_eta = i;
+	break;
+      }
+    }
+
+    if (ptype == PATCore::ParticleType::UnconvertedPhoton){
+      double norm_unconv=1.;
+      if (id_eta<17 && id_eta>10) norm_unconv = m_unconv_funcG[0][id_eta]->Eval(range_energy[id_eta]);
+      else if (id_eta<25 && id_eta>2) norm_unconv = m_unconv_funcG[1][id_eta]->Eval(range_energy[id_eta]);
+      else norm_unconv = m_unconv_funcG[2][id_eta]->Eval(range_energy[id_eta]);
+
+      if (energy_input<92) corrM_G = (m_unconv_funcG[0][id_eta]->Eval(energy_input))/(norm_unconv);
+      else if (energy_input<160 && energy_input>=92) corrM_G = (m_unconv_funcG[1][id_eta]->Eval(energy_input))/(norm_unconv);
+      else if (energy_input<400 && energy_input>=160) corrM_G = (m_unconv_funcG[2][id_eta]->Eval(energy_input))/(norm_unconv);
+      else if (energy_input>=400) corrM_G = (m_unconv_funcG[3][id_eta]->Eval(energy_input))/(norm_unconv);
+    }
+
+    else if (ptype==PATCore::ParticleType::ConvertedPhoton){
+      funcG_com[0][id_eta]= m_conv_funcG[0][id_eta];
+      funcG_com[1][id_eta]= m_conv_funcG[1][id_eta];
+      funcG_com[2][id_eta]= m_conv_funcG[2][id_eta];
+    }
+    else if (ptype==PATCore::ParticleType::Electron){
+      funcG_com[0][id_eta]= m_funcG[0][id_eta];
+      funcG_com[1][id_eta]= m_funcG[1][id_eta];
+      funcG_com[2][id_eta]= m_funcG[2][id_eta];
+    }
+
+
+    if(ptype==PATCore::ParticleType::ConvertedPhoton || ptype==PATCore::ParticleType::Electron){
+      if(id_eta==12 || id_eta == 13 || id_eta == 14 || id_eta==15){
+	if (energy_input<105) corrM_G = (funcG_com[0][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
+	else if (energy_input<400 && energy_input>=105) corrM_G = (funcG_com[1][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
+	else if (energy_input>=400) corrM_G = (funcG_com[2][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
+      }
+
+      else if(id_eta == 11 || id_eta ==16){
+	if (energy_input<130) corrM_G = (funcG_com[0][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
+	else if (energy_input<440 && energy_input>=130) corrM_G = (funcG_com[1][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
+	else if (energy_input>=440) corrM_G = (funcG_com[2][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
+      }
+
+      else if(id_eta == 10 || id_eta ==17){
+	if (energy_input<190) corrM_G = (funcG_com[0][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
+	else if (energy_input<400 && energy_input>=190) corrM_G = (funcG_com[1][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
+	else if (energy_input>=400) corrM_G = (funcG_com[2][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
+      }
+
+      else if(id_eta == 9 || id_eta ==18){
+	if (energy_input<200) corrM_G = (funcG_com[0][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
+	else if (energy_input<480 && energy_input>=200) corrM_G = (funcG_com[1][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
+	else if (energy_input>=480) corrM_G = (funcG_com[2][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
+      }
+
+      else if(id_eta==7 || id_eta == 8 || id_eta ==19 || id_eta==20){
+	if (energy_input<250) corrM_G = (funcG_com[0][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
+	else if (energy_input<450 && energy_input>=250) corrM_G = (funcG_com[1][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
+	else if (energy_input>=450) corrM_G = (funcG_com[2][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
+      }
+
+      else if(id_eta == 6 || id_eta ==21){
+	if (energy_input<180) corrM_G = (funcG_com[0][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
+	else if (energy_input<385 && energy_input>=180) corrM_G = (funcG_com[1][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
+	else if (energy_input>=385) corrM_G = (funcG_com[2][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
+      }
+
+      else if(id_eta == 5 || id_eta ==22){
+	if (energy_input<165) corrM_G = (funcG_com[0][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
+	else if (energy_input<460 && energy_input>=165) corrM_G = (funcG_com[1][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
+	else if (energy_input>=460) corrM_G = (funcG_com[2][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
+      }
+
+      else if(id_eta == 4 || id_eta ==23){
+	if (energy_input<160) corrM_G = (funcG_com[0][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
+	else if (energy_input<450 && energy_input>=160) corrM_G = (funcG_com[1][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
+	else if (energy_input>=450) corrM_G = (funcG_com[2][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
+      }
+
+      else{
+	if (energy_input<200) corrM_G = (funcG_com[0][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
+	else if (energy_input<480 && energy_input>=200) corrM_G = (funcG_com[1][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
+	else if (energy_input>=480) corrM_G = (funcG_com[2][id_eta]->Eval(energy_input))/(funcG_com[0][id_eta]->Eval(range_energy[id_eta]));
+      }
+    }
+
+    double ets2 = energy_layer2_input/cosh(eta_input);
+    double valTO = (m_funcTO[id_eta])->Eval(ets2);
+    if (valTO < 0) {
+      valTO=0;
+    }
+
+    corrE = -2 * energy_input* (((corrMG[id_eta]/91.2) - (diffES[id_eta]/91.2))*valTO*corrM_G + ((corrHG[id_eta]/91.2) - (diffES[id_eta]/91.2))*(1-valTO));
+    energy_output = (energy_input+corrE)*1000.;
+    return energy_output;
+  }
+}
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/GainUncertainty.cxx b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/GainUncertainty.cxx
index f3ac3656d2bd029d515d545f0f5c0ff4e133d87d..e56bd5d96de85e4c46525bf514bf6754b3145e64 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/GainUncertainty.cxx
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/GainUncertainty.cxx
@@ -1,86 +1,83 @@
 /*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
-#include <ElectronPhotonFourMomentumCorrection/GainUncertainty.h>
-#include "PathResolver/PathResolver.h"
-#include <TH1F.h>
-#include <TH1D.h>
-#include <TFile.h>
-#include <iostream>
-
-
-namespace egGain {
-
-
-//--------------------------------------
-
-  GainUncertainty::GainUncertainty(std::string filename) : asg::AsgMessaging("GainUncertainty") {
-    
-    ATH_MSG_INFO("opening file " << filename);
-    m_gainFile = std::make_unique<TFile>(filename.c_str());
-
-    if (not (m_alpha_specialGainRun = (TH1F*)(m_gainFile->Get("alpha_specialGainRun")))) ATH_MSG_FATAL("cannot open histogram1");
-    if (not (m_gain_impact_Zee = (TH1F*)(m_gainFile->Get("gain_impact_Zee")))) ATH_MSG_FATAL("cannot open histogram2");
-    for (int i=0;i<m_NUM_ETA_BINS;i++) {
-     char name[60];
-     sprintf(name,"gain_Impact_elec_%d",i);
-     if (not (m_gain_Impact_elec[i] = (TH1D*)(m_gainFile->Get(name)))) ATH_MSG_FATAL("cannot open histogram3");
-     sprintf(name,"gain_Impact_conv_%d",i);
-     if (not (m_gain_Impact_conv[i] = (TH1D*)(m_gainFile->Get(name)))) ATH_MSG_FATAL("cannot open histogram4");
-     sprintf(name,"gain_Impact_unco_%d",i);
-     if (not (m_gain_Impact_unco[i]= (TH1D*)(m_gainFile->Get(name)))) ATH_MSG_FATAL("cannot open histogram5");
-    }
-    
-  }
-
-//----------------------------------------------
-
-  GainUncertainty::~GainUncertainty() {
-      delete m_alpha_specialGainRun;
-      delete m_gain_impact_Zee;
-      for (int i=0;i<m_NUM_ETA_BINS;i++) {
-        delete m_gain_Impact_elec[i];
-        delete m_gain_Impact_conv[i];
-        delete m_gain_Impact_unco[i];
-      }
-  }
-
-//----------------------------------------------
-
-    // returns relative uncertainty on energy
-
-  double GainUncertainty::getUncertainty(double etaCalo_input, double et_input,  PATCore::ParticleType::Type ptype) const {
-       double aeta=std::fabs(etaCalo_input);
-       int ibin=-1;
-       if (aeta<0.8) ibin=0;
-       else if (aeta<1.37) ibin=1;
-       else if (aeta<1.52) ibin=2;
-       else if (aeta<1.80) ibin=3;
-       else if (aeta<2.50) ibin=4;
-       if (ibin<0) return 0.;
-       
-       //Protection needed as the histograms stops at 1 TeV
-       if(et_input>999999.) et_input = 999999.;
-       
-//       std::cout << " --- in  GainUncertainty::getUncertainty " << etaCalo_input << " " << et_input << " " << ptype << " ibin " << ibin << std::endl;
-
-       double impact=0.;
-       if (ptype==PATCore::ParticleType::Electron) impact = m_gain_Impact_elec[ibin]->GetBinContent(m_gain_Impact_elec[ibin]->FindFixBin(0.001*et_input));
-       if (ptype==PATCore::ParticleType::ConvertedPhoton) impact = m_gain_Impact_conv[ibin]->GetBinContent(m_gain_Impact_conv[ibin]->FindFixBin(0.001*et_input));
-       if (ptype==PATCore::ParticleType::UnconvertedPhoton) impact = m_gain_Impact_unco[ibin]->GetBinContent(m_gain_Impact_unco[ibin]->FindFixBin(0.001*et_input));
-
-//       std::cout << " impact " << impact << std::endl;
-       double_t sigmaE = m_alpha_specialGainRun->GetBinContent(m_alpha_specialGainRun->FindFixBin(aeta))
-                        /m_gain_impact_Zee->GetBinContent(m_gain_impact_Zee->FindFixBin(aeta))
-                        *impact ;
-
-//       std::cout << " m_alpha_specialGainRun, m_gain_impact_Zee, impact , sigmaE " << m_alpha_specialGainRun->GetBinContent(m_alpha_specialGainRun->FindBin(aeta))
-//  << " " << m_gain_impact_Zee->GetBinContent(m_gain_impact_Zee->FindBin(aeta)) << " " << impact << " " << sigmaE << std::endl;
-
-       return sigmaE;
-
-  }
-
-
-}
+#include <ElectronPhotonFourMomentumCorrection/GainUncertainty.h>
+#include <TH1.h>
+#include <TFile.h>
+
+
+namespace egGain {
+
+
+//--------------------------------------
+
+  GainUncertainty::GainUncertainty(const std::string& filename) : asg::AsgMessaging("GainUncertainty") {
+
+    ATH_MSG_INFO("opening file " << filename);
+    m_gainFile.reset( TFile::Open( filename.c_str(), "READ" ) );
+
+    if (not (m_alpha_specialGainRun = (TH1*)(m_gainFile->Get("alpha_specialGainRun")))) ATH_MSG_FATAL("cannot open histogram1");
+    if (not (m_gain_impact_Zee = (TH1*)(m_gainFile->Get("gain_impact_Zee")))) ATH_MSG_FATAL("cannot open histogram2");
+    for (int i=0;i<m_NUM_ETA_BINS;i++) {
+     char name[60];
+     sprintf(name,"gain_Impact_elec_%d",i);
+     if (not (m_gain_Impact_elec[i] = (TH1*)(m_gainFile->Get(name)))) ATH_MSG_FATAL("cannot open histogram3");
+     sprintf(name,"gain_Impact_conv_%d",i);
+     if (not (m_gain_Impact_conv[i] = (TH1*)(m_gainFile->Get(name)))) ATH_MSG_FATAL("cannot open histogram4");
+     sprintf(name,"gain_Impact_unco_%d",i);
+     if (not (m_gain_Impact_unco[i]= (TH1*)(m_gainFile->Get(name)))) ATH_MSG_FATAL("cannot open histogram5");
+    }
+
+  }
+
+//----------------------------------------------
+
+  GainUncertainty::~GainUncertainty() {
+      delete m_alpha_specialGainRun;
+      delete m_gain_impact_Zee;
+      for (int i=0;i<m_NUM_ETA_BINS;i++) {
+        delete m_gain_Impact_elec[i];
+        delete m_gain_Impact_conv[i];
+        delete m_gain_Impact_unco[i];
+      }
+  }
+
+//----------------------------------------------
+
+    // returns relative uncertainty on energy
+
+  double GainUncertainty::getUncertainty(double etaCalo_input, double et_input,  PATCore::ParticleType::Type ptype) const {
+       double aeta=std::fabs(etaCalo_input);
+       int ibin=-1;
+       if (aeta<0.8) ibin=0;
+       else if (aeta<1.37) ibin=1;
+       else if (aeta<1.52) ibin=2;
+       else if (aeta<1.80) ibin=3;
+       else if (aeta<2.50) ibin=4;
+       if (ibin<0) return 0.;
+
+       //Protection needed as the histograms stops at 1 TeV
+       if(et_input>999999.) et_input = 999999.;
+
+//       std::cout << " --- in  GainUncertainty::getUncertainty " << etaCalo_input << " " << et_input << " " << ptype << " ibin " << ibin << std::endl;
+
+       double impact=0.;
+       if (ptype==PATCore::ParticleType::Electron) impact = m_gain_Impact_elec[ibin]->GetBinContent(m_gain_Impact_elec[ibin]->FindFixBin(0.001*et_input));
+       if (ptype==PATCore::ParticleType::ConvertedPhoton) impact = m_gain_Impact_conv[ibin]->GetBinContent(m_gain_Impact_conv[ibin]->FindFixBin(0.001*et_input));
+       if (ptype==PATCore::ParticleType::UnconvertedPhoton) impact = m_gain_Impact_unco[ibin]->GetBinContent(m_gain_Impact_unco[ibin]->FindFixBin(0.001*et_input));
+
+//       std::cout << " impact " << impact << std::endl;
+       double_t sigmaE = m_alpha_specialGainRun->GetBinContent(m_alpha_specialGainRun->FindFixBin(aeta))
+                        /m_gain_impact_Zee->GetBinContent(m_gain_impact_Zee->FindFixBin(aeta))
+                        *impact ;
+
+//       std::cout << " m_alpha_specialGainRun, m_gain_impact_Zee, impact , sigmaE " << m_alpha_specialGainRun->GetBinContent(m_alpha_specialGainRun->FindBin(aeta))
+//  << " " << m_gain_impact_Zee->GetBinContent(m_gain_impact_Zee->FindBin(aeta)) << " " << impact << " " << sigmaE << std::endl;
+
+       return sigmaE;
+
+  }
+
+
+}
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/LArTemperatureCorrectionTool.cxx b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/LArTemperatureCorrectionTool.cxx
index ac57cfa596c753e8f0bce6cbb9d97d0baf77f9d8..d05fa9ebc20b05fad5010c61910b0fb83725e53b 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/LArTemperatureCorrectionTool.cxx
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/LArTemperatureCorrectionTool.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
 */
 
 #include <TParameter.h>
@@ -20,9 +20,7 @@ LArTemperatureCorrectionTool::LArTemperatureCorrectionTool(const std::string& fi
   if (!m_file or m_file->IsZombie()) { ATH_MSG_ERROR("cannot open file"); }
 
   m_tree = dynamic_cast<TTree*>(m_file->Get("temperature"));
-  if ( m_tree == nullptr ) { 
-    throw std::runtime_error( "cannot find tree" );
-  }
+  if (!m_tree) { ATH_MSG_FATAL("cannot find tree"); }
 
   Int_t t_run = 0;
   m_tree->SetBranchAddress("run", &t_run);
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/e1hg_systematics.cxx b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/e1hg_systematics.cxx
index 6864be8740e34ae5c1d0782c885272e524609428..98a580c5295a2a511d4597671c152dd34006db16 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/e1hg_systematics.cxx
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/e1hg_systematics.cxx
@@ -1,105 +1,105 @@
 /*
-  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 "ElectronPhotonFourMomentumCorrection/e1hg_systematics.h"
-#include "PathResolver/PathResolver.h"
-#include <stdlib.h>
-#include <math.h>
-
-#include "TAxis.h"
-#include "Riostream.h"
-
-#ifndef ROOTCORE
-#include "PathResolver/PathResolver.h"
-#endif
-
-e1hg_systematics::e1hg_systematics()
-{
-
-  m_file0 = TFile::Open( PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v8/e1hg_systematics_histos.root").c_str() );
-
-
-  for (Int_t ieta=0;ieta<8;ieta++) {
-     char name[60];
-     sprintf(name,"elec_%d",ieta);
-     m_helec[ieta] = (TH1D*) m_file0->Get(name);
-     sprintf(name,"unconv_%d",ieta);
-     m_hphot[ieta] = (TH1D*) m_file0->Get(name);
-     sprintf(name,"conv_%d",ieta);
-     m_hphot2[ieta] = (TH1D*) m_file0->Get(name);
-
-  }
-
-  TAxis* aa=m_helec[0]->GetXaxis();
-  m_etBins = aa->GetXbins();
-
-}
-
-//=========================================================================
-e1hg_systematics::~e1hg_systematics()
-{
-  m_file0->Close();
-}
-
-//============================================================================
-// inputs are particle_type (0=elec, 1=reco unconv photon, 2=reco conv photon)
-//            energy in MeV
-//            eta
-//
-// returned value is alpha = DeltaE / E
-//
-double e1hg_systematics::getAlpha(int particle_type, double energy, double eta, bool interpolate) const
-{
-
-   //cout << " in getDelta " << endl;
-   if (particle_type<0 || particle_type>2) return 0.;
-
-   float aeta=fabs(eta);
-   int ieta=0;
-   if (aeta<0.4) ieta=0;
-   else if (aeta<0.8) ieta=1;
-   else if (aeta<1.1) ieta=2;
-   else if (aeta<1.37) ieta=3;
-   else if (aeta<1.52) ieta=4;
-   else if (aeta<1.80) ieta=5;
-   else if (aeta<2.10) ieta=6;
-   else                ieta=7;
-
-
-   double energyGeV = energy*0.001;
-   double et = energyGeV/cosh(eta);
-
-   int ibinEt=m_etBins->GetSize()-2;
-   for (int i=1;i<m_etBins->GetSize();i++) {
-      if (et<m_etBins->GetAt(i)) {
-         ibinEt=i-1;
-         break;
-      }
-   }
-
-//   cout << " energy, et , ibinEt " << energyGeV << " " << et << " " << ibinEt << endl;
-
-   Double_t scale=0.;
-   //HACK: some ES model dependency needs to be introduced
-   /*Default up to es2017_summer
-     if (aeta<1.80) scale=0.;
-     else if (aeta<2.3) scale = 0.050*(aeta-1.8)/0.4 /0.05;
-     else scale=0.025/0.05;
-   */
-
-   if (aeta<1.80) scale=0.;
-   else if (aeta<2.3) scale = (0.050*(aeta-1.8)/0.4+0.025)/0.05;
-   else scale = 0.05/0.05;
-   
-   if( !interpolate ) {
-     if (particle_type==0) return scale*m_helec[ieta]->GetBinContent(ibinEt+1);
-     else if (particle_type==1) return scale*m_hphot[ieta]->GetBinContent(ibinEt+1);
-     else  return scale*m_hphot2[ieta]->GetBinContent(ibinEt+1); //This is 2, since if particle_type is not 0,1,2 we have returned 0 above
-   } else {
-     if (particle_type==0) return scale*m_helec[ieta]->Interpolate(et);
-     else if (particle_type==1) return scale*m_hphot[ieta]->Interpolate(et);
-     else  return scale*m_hphot2[ieta]->Interpolate(et); //This is 2, since if particle_type is not 0,1,2 we have returned 0
-   }
-
-}
+#include "ElectronPhotonFourMomentumCorrection/e1hg_systematics.h"
+#include "PathResolver/PathResolver.h"
+#include <stdlib.h>
+#include <math.h>
+
+#include "TAxis.h"
+#include "Riostream.h"
+
+#ifndef ROOTCORE
+#include "PathResolver/PathResolver.h"
+#endif
+
+e1hg_systematics::e1hg_systematics()
+{
+
+  m_file0 = TFile::Open( PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v8/e1hg_systematics_histos.root").c_str() );
+
+
+  for (Int_t ieta=0;ieta<8;ieta++) {
+     char name[60];
+     sprintf(name,"elec_%d",ieta);
+     m_helec[ieta] = (TH1D*) m_file0->Get(name);
+     sprintf(name,"unconv_%d",ieta);
+     m_hphot[ieta] = (TH1D*) m_file0->Get(name);
+     sprintf(name,"conv_%d",ieta);
+     m_hphot2[ieta] = (TH1D*) m_file0->Get(name);
+
+  }
+
+  TAxis* aa=m_helec[0]->GetXaxis();
+  m_etBins = aa->GetXbins();
+
+}
+
+//=========================================================================
+e1hg_systematics::~e1hg_systematics()
+{
+  m_file0->Close();
+}
+
+//============================================================================
+// inputs are particle_type (0=elec, 1=reco unconv photon, 2=reco conv photon)
+//            energy in MeV
+//            eta
+//
+// returned value is alpha = DeltaE / E
+//
+double e1hg_systematics::getAlpha(int particle_type, double energy, double eta, bool interpolate) const
+{
+
+   //cout << " in getDelta " << endl;
+   if (particle_type<0 || particle_type>2) return 0.;
+
+   float aeta=fabs(eta);
+   int ieta=0;
+   if (aeta<0.4) ieta=0;
+   else if (aeta<0.8) ieta=1;
+   else if (aeta<1.1) ieta=2;
+   else if (aeta<1.37) ieta=3;
+   else if (aeta<1.52) ieta=4;
+   else if (aeta<1.80) ieta=5;
+   else if (aeta<2.10) ieta=6;
+   else                ieta=7;
+
+
+   double energyGeV = energy*0.001;
+   double et = energyGeV/cosh(eta);
+
+   int ibinEt=m_etBins->GetSize()-2;
+   for (int i=1;i<m_etBins->GetSize();i++) {
+      if (et<m_etBins->GetAt(i)) {
+         ibinEt=i-1;
+         break;
+      }
+   }
+
+//   cout << " energy, et , ibinEt " << energyGeV << " " << et << " " << ibinEt << endl;
+
+   Double_t scale=0.;
+   //HACK: some ES model dependency needs to be introduced
+   /*Default up to es2017_summer
+     if (aeta<1.80) scale=0.;
+     else if (aeta<2.3) scale = 0.050*(aeta-1.8)/0.4 /0.05;
+     else scale=0.025/0.05;
+   */
+
+   if (aeta<1.80) scale=0.;
+   else if (aeta<2.3) scale = (0.050*(aeta-1.8)/0.4+0.025)/0.05;
+   else scale = 0.05/0.05;
+
+   if( !interpolate ) {
+     if (particle_type==0) return scale*m_helec[ieta]->GetBinContent(ibinEt+1);
+     else if (particle_type==1) return scale*m_hphot[ieta]->GetBinContent(ibinEt+1);
+     else  return scale*m_hphot2[ieta]->GetBinContent(ibinEt+1); //This is 2, since if particle_type is not 0,1,2 we have returned 0 above
+   } else {
+     if (particle_type==0) return scale*m_helec[ieta]->Interpolate(et);
+     else if (particle_type==1) return scale*m_hphot[ieta]->Interpolate(et);
+     else  return scale*m_hphot2[ieta]->Interpolate(et); //This is 2, since if particle_type is not 0,1,2 we have returned 0
+   }
+
+}
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/egammaEnergyCorrectionTool.cxx b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/egammaEnergyCorrectionTool.cxx
index 3253f9da912d08032c8746328042e13b5baf95db..46534de4455d8852b59c63cd00b4c64afb1fc0c6 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/egammaEnergyCorrectionTool.cxx
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/egammaEnergyCorrectionTool.cxx
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
-// Dear emacs, this is -*-c++-*-
+
 ///
 /// Implementation of energy scale uncertainties, for 2010 data and beyond
 ///
@@ -14,12 +14,20 @@
 
 #include <boost/format.hpp>
 
+#include "TH1.h"
+#include "TH2.h"
+#include "TF1.h"
+#include "TFile.h"
+#include "TList.h"
+#include "TGraphErrors.h"
+
+#include "egammaUtils/eg_resolution.h"
 #include "ElectronPhotonFourMomentumCorrection/egammaEnergyCorrectionTool.h"
 #include "ElectronPhotonFourMomentumCorrection/GainTool.h"
 #include "ElectronPhotonFourMomentumCorrection/get_MaterialResolutionEffect.h"
 #include "ElectronPhotonFourMomentumCorrection/e1hg_systematics.h"
 #include "ElectronPhotonFourMomentumCorrection/GainUncertainty.h"
-#include "egammaUtils/eg_resolution.h"
+
 
 #include "PathResolver/PathResolver.h"
 
@@ -65,120 +73,31 @@ namespace AtlasRoot {
   egammaEnergyCorrectionTool::egammaEnergyCorrectionTool()
     :
     asg::AsgMessaging("egammaEnergyCorrectionTool"),
-    m_rootFile (nullptr),
-    m_rootFileName (PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v13/egammaEnergyCorrectionData.root")),
+    m_rootFileName(PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v24/egammaEnergyCorrectionData.root")),
     m_esmodel(egEnergyCorr::UNDEFINED)
   {
+
+
+
     if (m_rootFileName.empty()) {
       ATH_MSG_FATAL("cannot find configuration file");
       throw std::runtime_error("cannot find file");
     }
-    
+
     m_begRunNumber = 0;
     m_endRunNumber = 0;
 
-    // corrections and systematics
-
-    m_aPSNom = nullptr;
-    m_daPSCor = nullptr;
-    m_aS12Nom = nullptr;
-    m_daS12Cor = nullptr;
-    m_zeeNom = nullptr;
-    m_zeeSyst = nullptr;
-    m_zeePhys = nullptr;
-    m_uA2MeV_2015_first2weeks_correction = nullptr;
-
-    m_zeeNom_data2015 = nullptr;  
-    m_wstot_slope_A_data = nullptr;
-    m_wstot_slope_B_MC = nullptr;
-    m_wstot_40GeV_data = nullptr;
-    m_wstot_40GeV_MC = nullptr;
-    m_wstot_pT_data_p0_electrons = nullptr; 
-    m_wstot_pT_data_p1_electrons = nullptr; 
-    m_wstot_pT_data_p0_unconverted_photons = nullptr;
-    m_wstot_pT_data_p1_unconverted_photons = nullptr;
-    m_wstot_pT_data_p0_converted_photons = nullptr;
-    m_wstot_pT_data_p1_converted_photons = nullptr;
-    m_wstot_pT_MC_p0_electrons = nullptr;
-    m_wstot_pT_MC_p1_electrons = nullptr;
-    m_wstot_pT_MC_p0_unconverted_photons = nullptr;
-    m_wstot_pT_MC_p1_unconverted_photons = nullptr;
-    m_wstot_pT_MC_p0_converted_photons = nullptr;
-    m_wstot_pT_MC_p1_converted_photons = nullptr;
-
-    m_resNom = nullptr;
-    m_resSyst = nullptr;
-
-    m_trkSyst = nullptr;
-
-    m_peakResData = nullptr;
-    m_peakResMC = nullptr;
-
-    m_dX_ID_Nom = nullptr;
-
-    m_dX_IPPS_Nom = nullptr;
-    m_dX_IPPS_LAr = nullptr;
-
-    m_dX_IPAcc_Nom = nullptr;
-    m_dX_IPAcc_LAr = nullptr;
-    m_dX_IPAcc_G4 = nullptr;
-    m_dX_IPAcc_GL1 = nullptr;
-
-    m_dX_PSAcc_Nom = nullptr;
-    m_dX_PSAcc_LAr = nullptr;
-    m_dX_PSAcc_G4 = nullptr;
-
-    m_psElectronEtaBins = nullptr;
-    m_psElectronGraphs = nullptr;
-    m_psUnconvertedEtaBins = nullptr;
-    m_psUnconvertedGraphs = nullptr;
-    m_psConvertedEtaBins = nullptr;
-    m_psConvertedGraphs = nullptr;
-
-    m_s12ElectronEtaBins = nullptr;
-    m_s12ElectronGraphs = nullptr;
-    m_s12UnconvertedEtaBins = nullptr;
-    m_s12UnconvertedGraphs = nullptr;
-    m_s12ConvertedEtaBins = nullptr;
-    m_s12ConvertedGraphs = nullptr;
-
-    m_pedestalL0 = nullptr;
-    m_pedestalL1 = nullptr;
-    m_pedestalL2 = nullptr;
-    m_pedestalL3 = nullptr;
-
-    m_pedestals_es2017 = nullptr;
-
-    m_convRadius = nullptr;
-    m_convFakeRate = nullptr;
-    m_convRecoEfficiency = nullptr;
-
-    m_leakageConverted = nullptr;
-    m_leakageUnconverted = nullptr;
-
-    m_zeeES2Profile = nullptr;
-
-    m_matElectronEtaBins = nullptr;
-
-    m_G4OverAFII_electron = nullptr;
-    m_G4OverAFII_unconverted = nullptr;
-    m_G4OverAFII_converted = nullptr;
-    m_G4OverAFII_resolution_electron = nullptr;
-    m_G4OverAFII_resolution_unconverted = nullptr;
-    m_G4OverAFII_resolution_converted = nullptr;
-
-    m_pp0_elec = m_pp0_conv = m_pp0_unconv = nullptr;
-
-    m_G4OverFrSh = nullptr;
+
+    /*
+     * All histogram vectors start empty
+     */
 
     m_use_new_resolution_model = false;
 
     // tools
 
-    m_gain_tool = nullptr;
-    m_gain_tool_run2 = nullptr;
     m_resolution_tool = nullptr;
-    m_getMaterialDelta = nullptr;
+    //m_getMaterialDelta = nullptr;
     m_e1hg_tool = nullptr;
 
     // switches
@@ -204,52 +123,6 @@ namespace AtlasRoot {
 
     // Clean up
 
-    if ( m_rootFile )                   delete m_rootFile;
-
-    if ( m_gain_tool )                  delete m_gain_tool;
-    if ( m_gain_tool_run2 )             delete m_gain_tool_run2;
-    if ( m_e1hg_tool )                  delete m_e1hg_tool;
-    if ( m_resolution_tool )            delete m_resolution_tool;
-    if ( m_getMaterialDelta)            delete m_getMaterialDelta;
-
-    if ( m_aPSNom )                     delete m_aPSNom;
-    if ( m_daPSCor )                    delete m_daPSCor;
-    if ( m_aS12Nom )                    delete m_aS12Nom;
-    if ( m_daS12Cor )                   delete m_daS12Cor;
-    if ( m_zeeNom )                     delete m_zeeNom;
-    if ( m_zeeSyst )                    delete m_zeeSyst;
-    if (m_uA2MeV_2015_first2weeks_correction) delete m_uA2MeV_2015_first2weeks_correction;
-    if ( m_zeePhys )                    delete m_zeePhys;
-    if ( m_resNom )                     delete m_resNom;
-    if ( m_resSyst )                    delete m_resSyst;
-    if ( m_peakResData )                delete m_peakResData;
-    if ( m_peakResMC )                  delete m_peakResMC;
-    if ( m_dX_ID_Nom )                  delete m_dX_ID_Nom;
-    if ( m_dX_IPPS_Nom )                delete m_dX_IPPS_Nom;
-    if ( m_dX_IPPS_LAr )                delete m_dX_IPPS_LAr;
-    if ( m_dX_IPAcc_Nom )               delete m_dX_IPAcc_Nom;
-    if ( m_dX_IPAcc_LAr )               delete m_dX_IPAcc_LAr;
-    if ( m_dX_IPAcc_G4 )                delete m_dX_IPAcc_G4;
-    if ( m_dX_IPAcc_GL1 )               delete m_dX_IPAcc_GL1;
-    if ( m_dX_PSAcc_Nom )               delete m_dX_PSAcc_Nom;
-    if ( m_dX_PSAcc_LAr )               delete m_dX_PSAcc_LAr;
-    if ( m_dX_PSAcc_G4 )                delete m_dX_PSAcc_G4;
-    if ( m_G4OverAFII_electron )        delete m_G4OverAFII_electron;
-    if ( m_G4OverAFII_converted )       delete m_G4OverAFII_converted;
-    if ( m_G4OverAFII_unconverted )     delete m_G4OverAFII_unconverted;
-    if ( m_G4OverAFII_resolution_electron )        delete m_G4OverAFII_resolution_electron;
-    if ( m_G4OverAFII_resolution_converted )       delete m_G4OverAFII_resolution_converted;
-    if ( m_G4OverAFII_resolution_unconverted )     delete m_G4OverAFII_resolution_unconverted;
-    if ( m_G4OverFrSh )                 delete m_G4OverFrSh;
-    if ( m_matElectronEtaBins )         delete m_matElectronEtaBins;
-    delete m_pp0_elec;
-    delete m_pp0_conv;
-    delete m_pp0_unconv;
-    delete m_pedestalL0;
-    delete m_pedestalL1;
-    delete m_pedestalL2;
-    delete m_pedestalL3;
-    delete m_pedestals_es2017;
   }
 
 
@@ -266,20 +139,20 @@ namespace AtlasRoot {
 
     ATH_MSG_DEBUG("initialize internal tool");
 
-    // Load the ROOT file
-    const char* fname(gSystem->ExpandPathName( m_rootFileName.c_str() ));
-    m_rootFile = TFile::Open( fname, "READ" );
+    // Load the ROOT filea
+
+    const std::unique_ptr<char[]> fname(gSystem->ExpandPathName(m_rootFileName.c_str()));
+    m_rootFile.reset(TFile::Open( fname.get(), "READ" ));
 
     if ( !m_rootFile ) {
       ATH_MSG_ERROR("no root file found");
-      delete fname;
       return 0;
     }
 
     // instantiate the resolution parametriaton
 
-    if (!m_getMaterialDelta)
-      m_getMaterialDelta = new get_MaterialResolutionEffect();
+    //`:if (!m_getMaterialDelta)
+    m_getMaterialDelta.reset( new get_MaterialResolutionEffect());
 
 
     // Energy corrections and systematic uncertainties
@@ -290,16 +163,17 @@ namespace AtlasRoot {
 
     if ( m_esmodel==egEnergyCorr::es2010 ) {
       m_use_new_resolution_model = false;
-      m_aPSNom      = (TH1D*) m_rootFile->Get("Scales/es2010/alphaPS_errTot");           m_aPSNom->SetDirectory(0);
-      m_aS12Nom     = (TH1D*) m_rootFile->Get("Scales/es2010/alphaS12_errTot");          m_aS12Nom->SetDirectory(0);
+      m_aPSNom.reset( dynamic_cast< TH1* >( m_rootFile->Get( "Scales/es2010/alphaPS_errTot" ) ) );
+      m_aPSNom->SetDirectory(nullptr);
+      m_aS12Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2010/alphaS12_errTot")));          m_aS12Nom->SetDirectory(nullptr);
 
-      m_zeeNom      = (TH1D*) m_rootFile->Get("Scales/es2010/alphaZee_errStat");         m_zeeNom->SetDirectory(0);
-      m_zeeSyst     = (TH1D*) m_rootFile->Get("Scales/es2010/alphaZee_errSyst");         m_zeeSyst->SetDirectory(0);
+      m_zeeNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2010/alphaZee_errStat")));         m_zeeNom->SetDirectory(nullptr);
+      m_zeeSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2010/alphaZee_errSyst")));         m_zeeSyst->SetDirectory(nullptr);
 
-      m_resNom      = (TH1D*) m_rootFile->Get("Resolution/es2010/ctZee_errStat");        m_resNom->SetDirectory(0);
-      m_resSyst     = (TH1D*) m_rootFile->Get("Resolution/es2010/ctZee_errSyst");        m_resSyst->SetDirectory(0);
-      m_peakResData = (TH1D*) m_rootFile->Get("Resolution/es2010/resZee_Data");          m_peakResData->SetDirectory(0);
-      m_peakResMC   = (TH1D*) m_rootFile->Get("Resolution/es2010/resZee_MC");            m_peakResMC->SetDirectory(0);
+      m_resNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2010/ctZee_errStat")));        m_resNom->SetDirectory(nullptr);
+      m_resSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2010/ctZee_errSyst")));        m_resSyst->SetDirectory(nullptr);
+      m_peakResData.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2010/resZee_Data")));          m_peakResData->SetDirectory(nullptr);
+      m_peakResMC.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2010/resZee_MC")));            m_peakResMC->SetDirectory(nullptr);
 
       m_begRunNumber = 152166;
       m_endRunNumber = 170482;
@@ -310,16 +184,16 @@ namespace AtlasRoot {
 
     } else if ( m_esmodel==egEnergyCorr::es2011c ) {
       m_use_new_resolution_model = false;
-      m_aPSNom      = (TH1D*) m_rootFile->Get("Scales/es2011c/alphaPS_errTot");          m_aPSNom->SetDirectory(0);
-      m_aS12Nom     = (TH1D*) m_rootFile->Get("Scales/es2011c/alphaS12_errTot");         m_aS12Nom->SetDirectory(0);
+      m_aPSNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2011c/alphaPS_errTot")));          m_aPSNom->SetDirectory(nullptr);
+      m_aS12Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2011c/alphaS12_errTot")));         m_aS12Nom->SetDirectory(nullptr);
 
-      m_zeeNom      = (TH1D*) m_rootFile->Get("Scales/es2011c/alphaZee_errStat");        m_zeeNom->SetDirectory(0);
-      m_zeeSyst     = (TH1D*) m_rootFile->Get("Scales/es2011c/alphaZee_errSyst");        m_zeeSyst->SetDirectory(0);
+      m_zeeNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2011c/alphaZee_errStat")));        m_zeeNom->SetDirectory(nullptr);
+      m_zeeSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2011c/alphaZee_errSyst")));        m_zeeSyst->SetDirectory(nullptr);
 
-      m_resNom      = (TH1D*) m_rootFile->Get("Resolution/es2011c/ctZee_errStat");       m_resNom->SetDirectory(0);
-      m_resSyst     = (TH1D*) m_rootFile->Get("Resolution/es2011c/ctZee_errSyst");       m_resSyst->SetDirectory(0);
-      m_peakResData = (TH1D*) m_rootFile->Get("Resolution/es2011c/resZee_Data");         m_peakResData->SetDirectory(0);
-      m_peakResMC   = (TH1D*) m_rootFile->Get("Resolution/es2011c/resZee_MC");           m_peakResMC->SetDirectory(0);
+      m_resNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2011c/ctZee_errStat")));       m_resNom->SetDirectory(nullptr);
+      m_resSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2011c/ctZee_errSyst")));       m_resSyst->SetDirectory(nullptr);
+      m_peakResData.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2011c/resZee_Data")));         m_peakResData->SetDirectory(nullptr);
+      m_peakResMC.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2011c/resZee_MC")));           m_peakResMC->SetDirectory(nullptr);
 
       m_begRunNumber = 177531;
       m_endRunNumber = 194382;
@@ -331,61 +205,61 @@ namespace AtlasRoot {
 
     } else if ( m_esmodel==egEnergyCorr::es2011d || m_esmodel==egEnergyCorr::es2011dMedium || m_esmodel==egEnergyCorr::es2011dTight ) {
       m_use_new_resolution_model = true;
-      m_resolution_tool = new eg_resolution("run1");
-      m_aPSNom       = (TH1D*) m_rootFile->Get("Scales/es2011d/alphaPS_uncor");                 m_aPSNom->SetDirectory(0);
-      m_daPSCor      = (TH1D*) m_rootFile->Get("Scales/es2011d/dalphaPS_cor");                  m_daPSCor->SetDirectory(0);
-      m_aS12Nom      = (TH1D*) m_rootFile->Get("Scales/es2011d/alphaS12_uncor");                m_aS12Nom->SetDirectory(0);
-      m_daS12Cor     = (TH1D*) m_rootFile->Get("Scales/es2011d/dalphaS12_cor");                 m_daS12Cor->SetDirectory(0);
+      m_resolution_tool.reset(new eg_resolution("run1"));
+      m_aPSNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2011d/alphaPS_uncor")));                 m_aPSNom->SetDirectory(nullptr);
+      m_daPSCor.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2011d/dalphaPS_cor")));                  m_daPSCor->SetDirectory(nullptr);
+      m_aS12Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2011d/alphaS12_uncor")));                m_aS12Nom->SetDirectory(nullptr);
+      m_daS12Cor.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2011d/dalphaS12_cor")));                 m_daS12Cor->SetDirectory(nullptr);
 
-      m_trkSyst      = (TH1D*) m_rootFile->Get("Scales/es2011d/momentum_errSyst");              m_trkSyst->SetDirectory(0);
+      m_trkSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2011d/momentum_errSyst")));              m_trkSyst->SetDirectory(nullptr);
 
       if( m_esmodel==egEnergyCorr::es2011d ) {
 
-        m_zeeNom       = (TH1D*) m_rootFile->Get("Scales/es2011d/alphaZee_errStat");              m_zeeNom->SetDirectory(0);
-        m_zeeSyst      = (TH1D*) m_rootFile->Get("Scales/es2011d/alphaZee_errSyst");              m_zeeSyst->SetDirectory(0);
-        m_resNom       = (TH1D*) m_rootFile->Get("Resolution/es2011d/ctZee_errStat");             m_resNom->SetDirectory(0);
-        m_resSyst      = (TH1D*) m_rootFile->Get("Resolution/es2011d/ctZee_errSyst");             m_resSyst->SetDirectory(0);
+        m_zeeNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2011d/alphaZee_errStat")));              m_zeeNom->SetDirectory(nullptr);
+        m_zeeSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2011d/alphaZee_errSyst")));              m_zeeSyst->SetDirectory(nullptr);
+        m_resNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2011d/ctZee_errStat")));             m_resNom->SetDirectory(nullptr);
+        m_resSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2011d/ctZee_errSyst")));             m_resSyst->SetDirectory(nullptr);
 
       } else if( m_esmodel==egEnergyCorr::es2011dMedium ) {
 
-        m_zeeNom       = (TH1D*) m_rootFile->Get("Scales/es2011dMedium/alphaZee_errStat");        m_zeeNom->SetDirectory(0);
-        m_zeeSyst      = (TH1D*) m_rootFile->Get("Scales/es2011dMedium/alphaZee_errSyst");        m_zeeSyst->SetDirectory(0);
-        m_zeePhys      = (TH1D*) m_rootFile->Get("Scales/es2011dMedium/alphaZee_errPhys");        m_zeePhys->SetDirectory(0);
-        m_resNom       = (TH1D*) m_rootFile->Get("Resolution/es2011dMedium/ctZee_errStat");       m_resNom->SetDirectory(0);
-        m_resSyst      = (TH1D*) m_rootFile->Get("Resolution/es2011dMedium/ctZee_errSyst");       m_resSyst->SetDirectory(0);
+        m_zeeNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2011dMedium/alphaZee_errStat")));        m_zeeNom->SetDirectory(nullptr);
+        m_zeeSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2011dMedium/alphaZee_errSyst")));        m_zeeSyst->SetDirectory(nullptr);
+        m_zeePhys.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2011dMedium/alphaZee_errPhys")));        m_zeePhys->SetDirectory(nullptr);
+        m_resNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2011dMedium/ctZee_errStat")));       m_resNom->SetDirectory(nullptr);
+        m_resSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2011dMedium/ctZee_errSyst")));       m_resSyst->SetDirectory(nullptr);
 
       } else if( m_esmodel==egEnergyCorr::es2011dTight ) {
 
-        m_zeeNom       = (TH1D*) m_rootFile->Get("Scales/es2011dTight/alphaZee_errStat");         m_zeeNom->SetDirectory(0);
-        m_zeeSyst      = (TH1D*) m_rootFile->Get("Scales/es2011dTight/alphaZee_errSyst");         m_zeeSyst->SetDirectory(0);
-        m_zeePhys      = (TH1D*) m_rootFile->Get("Scales/es2011dTight/alphaZee_errPhys");         m_zeePhys->SetDirectory(0);
-        m_resNom       = (TH1D*) m_rootFile->Get("Resolution/es2011dTight/ctZee_errStat");        m_resNom->SetDirectory(0);
-        m_resSyst      = (TH1D*) m_rootFile->Get("Resolution/es2011dTight/ctZee_errSyst");        m_resSyst->SetDirectory(0);
+        m_zeeNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2011dTight/alphaZee_errStat")));         m_zeeNom->SetDirectory(nullptr);
+        m_zeeSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2011dTight/alphaZee_errSyst")));         m_zeeSyst->SetDirectory(nullptr);
+        m_zeePhys.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2011dTight/alphaZee_errPhys")));         m_zeePhys->SetDirectory(nullptr);
+        m_resNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2011dTight/ctZee_errStat")));        m_resNom->SetDirectory(nullptr);
+        m_resSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2011dTight/ctZee_errSyst")));        m_resSyst->SetDirectory(nullptr);
 
       }
 
-      m_pedestalL0   = (TH1D*) m_rootFile->Get("Pedestals/es2011d/pedestals_l0");               m_pedestalL0->SetDirectory(0);
-      m_pedestalL1   = (TH1D*) m_rootFile->Get("Pedestals/es2011d/pedestals_l1");               m_pedestalL1->SetDirectory(0);
-      m_pedestalL2   = (TH1D*) m_rootFile->Get("Pedestals/es2011d/pedestals_l2");               m_pedestalL2->SetDirectory(0);
-      m_pedestalL3   = (TH1D*) m_rootFile->Get("Pedestals/es2011d/pedestals_l3");               m_pedestalL3->SetDirectory(0);
+      m_pedestalL0.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2011d/pedestals_l0")));               m_pedestalL0->SetDirectory(nullptr);
+      m_pedestalL1.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2011d/pedestals_l1")));               m_pedestalL1->SetDirectory(nullptr);
+      m_pedestalL2.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2011d/pedestals_l2")));               m_pedestalL2->SetDirectory(nullptr);
+      m_pedestalL3.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2011d/pedestals_l3")));               m_pedestalL3->SetDirectory(nullptr);
 
-      m_dX_ID_Nom    = (TH1D*) m_rootFile->Get("Material/DX0_ConfigA");                         m_dX_ID_Nom->SetDirectory(0);
+      m_dX_ID_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/DX0_ConfigA")));                         m_dX_ID_Nom->SetDirectory(nullptr);
 
-      m_dX_IPPS_Nom  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errUncor");   m_dX_IPPS_Nom->SetDirectory(0);
-      m_dX_IPPS_LAr  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errLAr");     m_dX_IPPS_LAr->SetDirectory(0);
+      m_dX_IPPS_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errUncor")));   m_dX_IPPS_Nom->SetDirectory(nullptr);
+      m_dX_IPPS_LAr.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errLAr")));     m_dX_IPPS_LAr->SetDirectory(nullptr);
 
-      m_dX_IPAcc_Nom = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errUncor");  m_dX_IPAcc_Nom->SetDirectory(0);
-      m_dX_IPAcc_LAr = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errLAr");    m_dX_IPAcc_LAr->SetDirectory(0);
-      m_dX_IPAcc_G4  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errG4");     m_dX_IPAcc_G4->SetDirectory(0);
-      m_dX_IPAcc_GL1  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errGL1");    m_dX_IPAcc_GL1->SetDirectory(0);
+      m_dX_IPAcc_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errUncor")));  m_dX_IPAcc_Nom->SetDirectory(nullptr);
+      m_dX_IPAcc_LAr.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errLAr")));    m_dX_IPAcc_LAr->SetDirectory(nullptr);
+      m_dX_IPAcc_G4.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errG4")));     m_dX_IPAcc_G4->SetDirectory(nullptr);
+      m_dX_IPAcc_GL1.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errGL1")));    m_dX_IPAcc_GL1->SetDirectory(nullptr);
 
-      m_dX_PSAcc_Nom = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errUncor");  m_dX_PSAcc_Nom->SetDirectory(0);
-      m_dX_PSAcc_LAr = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errLAr");    m_dX_PSAcc_LAr->SetDirectory(0);
-      m_dX_PSAcc_G4  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errG4");     m_dX_PSAcc_G4->SetDirectory(0);
+      m_dX_PSAcc_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errUncor")));  m_dX_PSAcc_Nom->SetDirectory(nullptr);
+      m_dX_PSAcc_LAr.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errLAr")));    m_dX_PSAcc_LAr->SetDirectory(nullptr);
+      m_dX_PSAcc_G4.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errG4")));     m_dX_PSAcc_G4->SetDirectory(nullptr);
 
-      m_convRadius            = (TH2D*) m_rootFile->Get("Conversions/es2011d/convRadiusMigrations");  m_convRadius->SetDirectory(0);
-      m_convFakeRate          = (TH1D*) m_rootFile->Get("Conversions/es2011d/convFakeRate");          m_convFakeRate->SetDirectory(0);
-      m_convRecoEfficiency    = (TH1D*) m_rootFile->Get("Conversions/es2011d/convRecoEfficiency");    m_convRecoEfficiency->SetDirectory(0);
+      m_convRadius.reset( dynamic_cast< TH1* >( m_rootFile->Get("Conversions/es2011d/convRadiusMigrations")));  m_convRadius->SetDirectory(nullptr);
+      m_convFakeRate.reset( dynamic_cast< TH1* >( m_rootFile->Get("Conversions/es2011d/convFakeRate")));          m_convFakeRate->SetDirectory(nullptr);
+      m_convRecoEfficiency.reset( dynamic_cast< TH1* >( m_rootFile->Get("Conversions/es2011d/convRecoEfficiency")));    m_convRecoEfficiency->SetDirectory(nullptr);
 
       m_begRunNumber = 177531;
       m_endRunNumber = 194382;
@@ -393,25 +267,26 @@ namespace AtlasRoot {
 
       const std::string gain_filename1 = PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v8/FunctionsTO.root");
       const std::string gain_filename2 = PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v8/FunctionsG_all.root");
-      m_gain_tool = new egGain::GainTool(gain_filename1, gain_filename2);
+      m_gain_tool.reset(new egGain::GainTool(gain_filename1, gain_filename2));
+
 
-      m_e1hg_tool = new e1hg_systematics();
+      m_e1hg_tool.reset(new e1hg_systematics());
 
       // mc12a : crude MSc fix in G4; old geometry
       // All systematics as in 2010.
 
     } else if ( m_esmodel==egEnergyCorr::es2012a ) {
       m_use_new_resolution_model = false;
-      m_aPSNom      = (TH1D*) m_rootFile->Get("Scales/es2012a/alphaPS_errTot");          m_aPSNom->SetDirectory(0);
-      m_aS12Nom     = (TH1D*) m_rootFile->Get("Scales/es2012a/alphaS12_errTot");         m_aS12Nom->SetDirectory(0);
+      m_aPSNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012a/alphaPS_errTot")));          m_aPSNom->SetDirectory(nullptr);
+      m_aS12Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012a/alphaS12_errTot")));         m_aS12Nom->SetDirectory(nullptr);
 
-      m_zeeNom      = (TH1D*) m_rootFile->Get("Scales/es2012a/alphaZee_errStat");        m_zeeNom->SetDirectory(0);
-      m_zeeSyst     = (TH1D*) m_rootFile->Get("Scales/es2012a/alphaZee_errSyst");        m_zeeSyst->SetDirectory(0);
+      m_zeeNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012a/alphaZee_errStat")));        m_zeeNom->SetDirectory(nullptr);
+      m_zeeSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012a/alphaZee_errSyst")));        m_zeeSyst->SetDirectory(nullptr);
 
-      m_resNom      = (TH1D*) m_rootFile->Get("Resolution/es2012a/ctZee_errStat");       m_resNom->SetDirectory(0);
-      m_resSyst     = (TH1D*) m_rootFile->Get("Resolution/es2012a/ctZee_errSyst");       m_resSyst->SetDirectory(0);
-      m_peakResData = (TH1D*) m_rootFile->Get("Resolution/es2012a/resZee_Data");         m_peakResData->SetDirectory(0);
-      m_peakResMC   = (TH1D*) m_rootFile->Get("Resolution/es2012a/resZee_MC");           m_peakResMC->SetDirectory(0);
+      m_resNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2012a/ctZee_errStat")));       m_resNom->SetDirectory(nullptr);
+      m_resSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2012a/ctZee_errSyst")));       m_resSyst->SetDirectory(nullptr);
+      m_peakResData.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2012a/resZee_Data")));         m_peakResData->SetDirectory(nullptr);
+      m_peakResMC.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2012a/resZee_MC")));           m_peakResMC->SetDirectory(nullptr);
 
       m_begRunNumber = 195847;
       m_endRunNumber = 219365;
@@ -421,93 +296,93 @@ namespace AtlasRoot {
 
     } else if (m_esmodel == egEnergyCorr::es2012c) {
       m_use_new_resolution_model = true;
-      m_resolution_tool = new eg_resolution("run1");
+      m_resolution_tool.reset(new eg_resolution("run1"));
 
-      m_aPSNom       = (TH1D*) m_rootFile->Get("Scales/es2012c/alphaPS_uncor");                 m_aPSNom->SetDirectory(0);
-      m_daPSCor      = (TH1D*) m_rootFile->Get("Scales/es2012c/dalphaPS_cor");                  m_daPSCor->SetDirectory(0);
-      m_aS12Nom      = (TH1D*) m_rootFile->Get("Scales/es2012c/alphaS12_uncor");                m_aS12Nom->SetDirectory(0);
-      m_daS12Cor     = (TH1D*) m_rootFile->Get("Scales/es2012c/dalphaS12_cor");                 m_daS12Cor->SetDirectory(0);
+      m_aPSNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/alphaPS_uncor")));                 m_aPSNom->SetDirectory(nullptr);
+      m_daPSCor.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/dalphaPS_cor")));                  m_daPSCor->SetDirectory(nullptr);
+      m_aS12Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/alphaS12_uncor")));                m_aS12Nom->SetDirectory(nullptr);
+      m_daS12Cor.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/dalphaS12_cor")));                 m_daS12Cor->SetDirectory(nullptr);
 
-      m_trkSyst      = (TH1D*) m_rootFile->Get("Scales/es2012c/momentum_errSyst");              m_trkSyst->SetDirectory(0);
+      m_trkSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/momentum_errSyst")));              m_trkSyst->SetDirectory(nullptr);
 
-      m_zeeNom       = (TH1D*) m_rootFile->Get("Scales/es2012c/alphaZee_errStat");              m_zeeNom->SetDirectory(0);
-      m_zeeSyst      = (TH1D*) m_rootFile->Get("Scales/es2012c/alphaZee_errSyst");              m_zeeSyst->SetDirectory(0);
+      m_zeeNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/alphaZee_errStat")));              m_zeeNom->SetDirectory(nullptr);
+      m_zeeSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/alphaZee_errSyst")));              m_zeeSyst->SetDirectory(nullptr);
 
-      m_resNom       = (TH1D*) m_rootFile->Get("Resolution/es2012c/ctZee_errStat");             m_resNom->SetDirectory(0);
-      m_resSyst      = (TH1D*) m_rootFile->Get("Resolution/es2012c/ctZee_errSyst");             m_resSyst->SetDirectory(0);
+      m_resNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2012c/ctZee_errStat")));             m_resNom->SetDirectory(nullptr);
+      m_resSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2012c/ctZee_errSyst")));             m_resSyst->SetDirectory(nullptr);
 
-      m_pedestalL0   = (TH1D*) m_rootFile->Get("Pedestals/es2012c/pedestals_l0");               m_pedestalL0->SetDirectory(0);
-      m_pedestalL1   = (TH1D*) m_rootFile->Get("Pedestals/es2012c/pedestals_l1");               m_pedestalL1->SetDirectory(0);
-      m_pedestalL2   = (TH1D*) m_rootFile->Get("Pedestals/es2012c/pedestals_l2");               m_pedestalL2->SetDirectory(0);
-      m_pedestalL3   = (TH1D*) m_rootFile->Get("Pedestals/es2012c/pedestals_l3");               m_pedestalL3->SetDirectory(0);
+      m_pedestalL0.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2012c/pedestals_l0")));               m_pedestalL0->SetDirectory(nullptr);
+      m_pedestalL1.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2012c/pedestals_l1")));               m_pedestalL1->SetDirectory(nullptr);
+      m_pedestalL2.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2012c/pedestals_l2")));               m_pedestalL2->SetDirectory(nullptr);
+      m_pedestalL3.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2012c/pedestals_l3")));               m_pedestalL3->SetDirectory(nullptr);
 
-      m_dX_ID_Nom    = (TH1D*) m_rootFile->Get("Material/DX0_ConfigA");                         m_dX_ID_Nom->SetDirectory(0);
+      m_dX_ID_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/DX0_ConfigA")));                         m_dX_ID_Nom->SetDirectory(nullptr);
 
-      m_dX_IPPS_Nom  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errUncor");   m_dX_IPPS_Nom->SetDirectory(0);
-      m_dX_IPPS_LAr  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errLAr");     m_dX_IPPS_LAr->SetDirectory(0);
+      m_dX_IPPS_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errUncor")));   m_dX_IPPS_Nom->SetDirectory(nullptr);
+      m_dX_IPPS_LAr.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errLAr")));     m_dX_IPPS_LAr->SetDirectory(nullptr);
 
-      m_dX_IPAcc_Nom = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errUncor");  m_dX_IPAcc_Nom->SetDirectory(0);
-      m_dX_IPAcc_LAr = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errLAr");    m_dX_IPAcc_LAr->SetDirectory(0);
-      m_dX_IPAcc_G4  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errG4");     m_dX_IPAcc_G4->SetDirectory(0);
-      m_dX_IPAcc_GL1  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errGL1");    m_dX_IPAcc_GL1->SetDirectory(0);
+      m_dX_IPAcc_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errUncor")));  m_dX_IPAcc_Nom->SetDirectory(nullptr);
+      m_dX_IPAcc_LAr.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errLAr")));    m_dX_IPAcc_LAr->SetDirectory(nullptr);
+      m_dX_IPAcc_G4.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errG4")));     m_dX_IPAcc_G4->SetDirectory(nullptr);
+      m_dX_IPAcc_GL1.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errGL1")));    m_dX_IPAcc_GL1->SetDirectory(nullptr);
 
-      m_dX_PSAcc_Nom = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errUncor");  m_dX_PSAcc_Nom->SetDirectory(0);
-      m_dX_PSAcc_LAr = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errLAr");    m_dX_PSAcc_LAr->SetDirectory(0);
-      m_dX_PSAcc_G4  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errG4");     m_dX_PSAcc_G4->SetDirectory(0);
+      m_dX_PSAcc_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errUncor")));  m_dX_PSAcc_Nom->SetDirectory(nullptr);
+      m_dX_PSAcc_LAr.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errLAr")));    m_dX_PSAcc_LAr->SetDirectory(nullptr);
+      m_dX_PSAcc_G4.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errG4")));     m_dX_PSAcc_G4->SetDirectory(nullptr);
 
-      m_convRadius            = (TH2D*) m_rootFile->Get("Conversions/es2012c/convRadiusMigrations");  m_convRadius->SetDirectory(0);
-      m_convFakeRate          = (TH1D*) m_rootFile->Get("Conversions/es2012c/convFakeRate");          m_convFakeRate->SetDirectory(0);
-      m_convRecoEfficiency    = (TH1D*) m_rootFile->Get("Conversions/es2012c/convRecoEfficiency");    m_convRecoEfficiency->SetDirectory(0);
+      m_convRadius.reset( dynamic_cast< TH1* >( m_rootFile->Get("Conversions/es2012c/convRadiusMigrations")));  m_convRadius->SetDirectory(nullptr);
+      m_convFakeRate.reset( dynamic_cast< TH1* >( m_rootFile->Get("Conversions/es2012c/convFakeRate")));          m_convFakeRate->SetDirectory(nullptr);
+      m_convRecoEfficiency.reset( dynamic_cast< TH1* >( m_rootFile->Get("Conversions/es2012c/convRecoEfficiency")));    m_convRecoEfficiency->SetDirectory(nullptr);
 
       m_begRunNumber = 195847;
       m_endRunNumber = 219365;
 
       const std::string gain_filename1 = PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v8/FunctionsTO.root");
       const std::string gain_filename2 = PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v8/FunctionsG_all.root");
-      m_gain_tool = new egGain::GainTool(gain_filename1, gain_filename2);
+      m_gain_tool.reset(new egGain::GainTool(gain_filename1, gain_filename2));
 
-      m_e1hg_tool = new e1hg_systematics();
+      m_e1hg_tool.reset(new e1hg_systematics());
     }
     else if (m_esmodel == egEnergyCorr::es2012XX) {
       m_use_etaCalo_scales = true;
       m_use_new_resolution_model = true;
-      m_resolution_tool = new eg_resolution("run1");
+      m_resolution_tool.reset(new eg_resolution("run1"));
 
-      m_aPSNom       = (TH1D*) m_rootFile->Get("Scales/es2012c/alphaPS_uncor");                 m_aPSNom->SetDirectory(0);
-      m_daPSCor      = (TH1D*) m_rootFile->Get("Scales/es2012c/dalphaPS_cor");                  m_daPSCor->SetDirectory(0);
-      m_aS12Nom      = (TH1D*) m_rootFile->Get("Scales/es2012c/alphaS12_uncor");                m_aS12Nom->SetDirectory(0);
-      m_daS12Cor     = (TH1D*) m_rootFile->Get("Scales/es2012c/dalphaS12_cor");                 m_daS12Cor->SetDirectory(0);
+      m_aPSNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/alphaPS_uncor")));                 m_aPSNom->SetDirectory(nullptr);
+      m_daPSCor.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/dalphaPS_cor")));                  m_daPSCor->SetDirectory(nullptr);
+      m_aS12Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/alphaS12_uncor")));                m_aS12Nom->SetDirectory(nullptr);
+      m_daS12Cor.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/dalphaS12_cor")));                 m_daS12Cor->SetDirectory(nullptr);
 
-      m_trkSyst      = (TH1D*) m_rootFile->Get("Scales/es2012c/momentum_errSyst");              m_trkSyst->SetDirectory(0);
+      m_trkSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/momentum_errSyst")));              m_trkSyst->SetDirectory(nullptr);
 
-      m_zeeNom       = (TH1D*) m_rootFile->Get("Scales/es2015PRE/alphaZee_errStat");        m_zeeNom->SetDirectory(0);
-      m_zeeSyst      = (TH1D*) m_rootFile->Get("Scales/es2012c/alphaZee_errSyst");              m_zeeSyst->SetDirectory(0);
+      m_zeeNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2015PRE/alphaZee_errStat")));        m_zeeNom->SetDirectory(nullptr);
+      m_zeeSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/alphaZee_errSyst")));              m_zeeSyst->SetDirectory(nullptr);
 
-      m_resNom       = (TH1D*) m_rootFile->Get("Resolution/es2015PRE/ctZee_errStat");       m_resNom->SetDirectory(0);
-      m_resSyst      = (TH1D*) m_rootFile->Get("Resolution/es2012c/ctZee_errSyst");             m_resSyst->SetDirectory(0);
+      m_resNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2015PRE/ctZee_errStat")));       m_resNom->SetDirectory(nullptr);
+      m_resSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2012c/ctZee_errSyst")));             m_resSyst->SetDirectory(nullptr);
 
-      m_pedestalL0   = (TH1D*) m_rootFile->Get("Pedestals/es2012c/pedestals_l0");               m_pedestalL0->SetDirectory(0);
-      m_pedestalL1   = (TH1D*) m_rootFile->Get("Pedestals/es2012c/pedestals_l1");               m_pedestalL1->SetDirectory(0);
-      m_pedestalL2   = (TH1D*) m_rootFile->Get("Pedestals/es2012c/pedestals_l2");               m_pedestalL2->SetDirectory(0);
-      m_pedestalL3   = (TH1D*) m_rootFile->Get("Pedestals/es2012c/pedestals_l3");               m_pedestalL3->SetDirectory(0);
+      m_pedestalL0.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2012c/pedestals_l0")));               m_pedestalL0->SetDirectory(nullptr);
+      m_pedestalL1.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2012c/pedestals_l1")));               m_pedestalL1->SetDirectory(nullptr);
+      m_pedestalL2.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2012c/pedestals_l2")));               m_pedestalL2->SetDirectory(nullptr);
+      m_pedestalL3.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2012c/pedestals_l3")));               m_pedestalL3->SetDirectory(nullptr);
 
-      m_dX_ID_Nom    = (TH1D*) m_rootFile->Get("Material/DX0_ConfigA");                         m_dX_ID_Nom->SetDirectory(0);
+      m_dX_ID_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/DX0_ConfigA")));                         m_dX_ID_Nom->SetDirectory(nullptr);
 
-      m_dX_IPPS_Nom  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errUncor");   m_dX_IPPS_Nom->SetDirectory(0);
-      m_dX_IPPS_LAr  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errLAr");     m_dX_IPPS_LAr->SetDirectory(0);
+      m_dX_IPPS_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errUncor")));   m_dX_IPPS_Nom->SetDirectory(nullptr);
+      m_dX_IPPS_LAr.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errLAr")));     m_dX_IPPS_LAr->SetDirectory(nullptr);
 
-      m_dX_IPAcc_Nom = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errUncor");  m_dX_IPAcc_Nom->SetDirectory(0);
-      m_dX_IPAcc_LAr = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errLAr");    m_dX_IPAcc_LAr->SetDirectory(0);
-      m_dX_IPAcc_G4  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errG4");     m_dX_IPAcc_G4->SetDirectory(0);
-      m_dX_IPAcc_GL1  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errGL1");    m_dX_IPAcc_GL1->SetDirectory(0);
+      m_dX_IPAcc_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errUncor")));  m_dX_IPAcc_Nom->SetDirectory(nullptr);
+      m_dX_IPAcc_LAr.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errLAr")));    m_dX_IPAcc_LAr->SetDirectory(nullptr);
+      m_dX_IPAcc_G4.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errG4")));     m_dX_IPAcc_G4->SetDirectory(nullptr);
+      m_dX_IPAcc_GL1.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errGL1")));    m_dX_IPAcc_GL1->SetDirectory(nullptr);
 
-      m_dX_PSAcc_Nom = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errUncor");  m_dX_PSAcc_Nom->SetDirectory(0);
-      m_dX_PSAcc_LAr = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errLAr");    m_dX_PSAcc_LAr->SetDirectory(0);
-      m_dX_PSAcc_G4  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errG4");     m_dX_PSAcc_G4->SetDirectory(0);
+      m_dX_PSAcc_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errUncor")));  m_dX_PSAcc_Nom->SetDirectory(nullptr);
+      m_dX_PSAcc_LAr.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errLAr")));    m_dX_PSAcc_LAr->SetDirectory(nullptr);
+      m_dX_PSAcc_G4.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errG4")));     m_dX_PSAcc_G4->SetDirectory(nullptr);
 
-      m_convRadius            = (TH2D*) m_rootFile->Get("Conversions/es2012c/convRadiusMigrations");  m_convRadius->SetDirectory(0);
-      m_convFakeRate          = (TH1D*) m_rootFile->Get("Conversions/es2012c/convFakeRate");          m_convFakeRate->SetDirectory(0);
-      m_convRecoEfficiency    = (TH1D*) m_rootFile->Get("Conversions/es2012c/convRecoEfficiency");    m_convRecoEfficiency->SetDirectory(0);
+      m_convRadius.reset( dynamic_cast< TH1* >( m_rootFile->Get("Conversions/es2012c/convRadiusMigrations")));  m_convRadius->SetDirectory(nullptr);
+      m_convFakeRate.reset( dynamic_cast< TH1* >( m_rootFile->Get("Conversions/es2012c/convFakeRate")));          m_convFakeRate->SetDirectory(nullptr);
+      m_convRecoEfficiency.reset( dynamic_cast< TH1* >( m_rootFile->Get("Conversions/es2012c/convRecoEfficiency")));    m_convRecoEfficiency->SetDirectory(nullptr);
 
       m_begRunNumber = 195847;
       m_endRunNumber = 219365;
@@ -515,200 +390,200 @@ namespace AtlasRoot {
 
       const std::string gain_filename1 = PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v8/FunctionsTO.root");
       const std::string gain_filename2 = PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v8/FunctionsG_all.root");
-      m_gain_tool = new egGain::GainTool(gain_filename1, gain_filename2);
+      m_gain_tool.reset(new egGain::GainTool(gain_filename1, gain_filename2));
 
-      m_e1hg_tool = new e1hg_systematics();
+      m_e1hg_tool.reset(new e1hg_systematics());
     }
     else if (m_esmodel == egEnergyCorr::es2015PRE or m_esmodel == egEnergyCorr::es2015cPRE) {
       m_use_etaCalo_scales = true;
       m_use_new_resolution_model = true;
-      m_resolution_tool = new eg_resolution("run2_pre");
+      m_resolution_tool.reset( new eg_resolution("run2_pre")) ;
 
-      m_aPSNom       = (TH1D*) m_rootFile->Get("Scales/es2012c/alphaPS_uncor");                 m_aPSNom->SetDirectory(0);
-      m_daPSCor      = (TH1D*) m_rootFile->Get("Scales/es2012c/dalphaPS_cor");                  m_daPSCor->SetDirectory(0);
-      m_aS12Nom      = (TH1D*) m_rootFile->Get("Scales/es2012c/alphaS12_uncor");                m_aS12Nom->SetDirectory(0);
-      m_daS12Cor     = (TH1D*) m_rootFile->Get("Scales/es2012c/dalphaS12_cor");                 m_daS12Cor->SetDirectory(0);
+      m_aPSNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/alphaPS_uncor")));                 m_aPSNom->SetDirectory(nullptr);
+      m_daPSCor.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/dalphaPS_cor")));                  m_daPSCor->SetDirectory(nullptr);
+      m_aS12Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/alphaS12_uncor")));                m_aS12Nom->SetDirectory(nullptr);
+      m_daS12Cor.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/dalphaS12_cor")));                 m_daS12Cor->SetDirectory(nullptr);
 
-      m_trkSyst      = (TH1D*) m_rootFile->Get("Scales/es2012c/momentum_errSyst");              m_trkSyst->SetDirectory(0);
+      m_trkSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/momentum_errSyst")));              m_trkSyst->SetDirectory(nullptr);
 
-      m_zeeNom       = (TH1D*) m_rootFile->Get("Scales/es2015PRE/alphaZee_errStat");        m_zeeNom->SetDirectory(0);
-      m_zeeSyst      = (TH1D*) m_rootFile->Get("Scales/es2015PRE/alphaZee_errSyst");              m_zeeSyst->SetDirectory(0);
-      m_uA2MeV_2015_first2weeks_correction = (TH1*) m_rootFile->Get("Scales/es2015PRE/histo_uA2MeV_week12"); m_uA2MeV_2015_first2weeks_correction->SetDirectory(0);
+      m_zeeNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2015PRE/alphaZee_errStat")));        m_zeeNom->SetDirectory(nullptr);
+      m_zeeSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2015PRE/alphaZee_errSyst")));              m_zeeSyst->SetDirectory(nullptr);
+      m_uA2MeV_2015_first2weeks_correction.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2015PRE/histo_uA2MeV_week12"))); m_uA2MeV_2015_first2weeks_correction->SetDirectory(nullptr);
 
-      m_resNom       = (TH1D*) m_rootFile->Get("Resolution/es2015PRE/ctZee_errStat");       m_resNom->SetDirectory(0);
-      m_resSyst      = (TH1D*) m_rootFile->Get("Resolution/es2015PRE/ctZee_errSyst");             m_resSyst->SetDirectory(0);
+      m_resNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2015PRE/ctZee_errStat")));       m_resNom->SetDirectory(nullptr);
+      m_resSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2015PRE/ctZee_errSyst")));             m_resSyst->SetDirectory(nullptr);
 
-      m_pedestalL0   = (TH1D*) m_rootFile->Get("Pedestals/es2012c/pedestals_l0");               m_pedestalL0->SetDirectory(0);
-      m_pedestalL1   = (TH1D*) m_rootFile->Get("Pedestals/es2012c/pedestals_l1");               m_pedestalL1->SetDirectory(0);
-      m_pedestalL2   = (TH1D*) m_rootFile->Get("Pedestals/es2012c/pedestals_l2");               m_pedestalL2->SetDirectory(0);
-      m_pedestalL3   = (TH1D*) m_rootFile->Get("Pedestals/es2012c/pedestals_l3");               m_pedestalL3->SetDirectory(0);
+      m_pedestalL0.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2012c/pedestals_l0")));               m_pedestalL0->SetDirectory(nullptr);
+      m_pedestalL1.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2012c/pedestals_l1")));               m_pedestalL1->SetDirectory(nullptr);
+      m_pedestalL2.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2012c/pedestals_l2")));               m_pedestalL2->SetDirectory(nullptr);
+      m_pedestalL3.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2012c/pedestals_l3")));               m_pedestalL3->SetDirectory(nullptr);
 
-      m_dX_ID_Nom    = (TH1D*) m_rootFile->Get("Material/DX0_ConfigA");                         m_dX_ID_Nom->SetDirectory(0);
+      m_dX_ID_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/DX0_ConfigA")));                         m_dX_ID_Nom->SetDirectory(nullptr);
 
-      m_dX_IPPS_Nom  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errUncor");   m_dX_IPPS_Nom->SetDirectory(0);
-      m_dX_IPPS_LAr  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errLAr");     m_dX_IPPS_LAr->SetDirectory(0);
+      m_dX_IPPS_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errUncor")));   m_dX_IPPS_Nom->SetDirectory(nullptr);
+      m_dX_IPPS_LAr.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errLAr")));     m_dX_IPPS_LAr->SetDirectory(nullptr);
 
-      m_dX_IPAcc_Nom = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errUncor");  m_dX_IPAcc_Nom->SetDirectory(0);
-      m_dX_IPAcc_LAr = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errLAr");    m_dX_IPAcc_LAr->SetDirectory(0);
-      m_dX_IPAcc_G4  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errG4");     m_dX_IPAcc_G4->SetDirectory(0);
-      m_dX_IPAcc_GL1  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errGL1");    m_dX_IPAcc_GL1->SetDirectory(0);
+      m_dX_IPAcc_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errUncor")));  m_dX_IPAcc_Nom->SetDirectory(nullptr);
+      m_dX_IPAcc_LAr.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errLAr")));    m_dX_IPAcc_LAr->SetDirectory(nullptr);
+      m_dX_IPAcc_G4.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errG4")));     m_dX_IPAcc_G4->SetDirectory(nullptr);
+      m_dX_IPAcc_GL1.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errGL1")));    m_dX_IPAcc_GL1->SetDirectory(nullptr);
 
-      m_dX_PSAcc_Nom = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errUncor");  m_dX_PSAcc_Nom->SetDirectory(0);
-      m_dX_PSAcc_LAr = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errLAr");    m_dX_PSAcc_LAr->SetDirectory(0);
-      m_dX_PSAcc_G4  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errG4");     m_dX_PSAcc_G4->SetDirectory(0);
+      m_dX_PSAcc_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errUncor")));  m_dX_PSAcc_Nom->SetDirectory(nullptr);
+      m_dX_PSAcc_LAr.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errLAr")));    m_dX_PSAcc_LAr->SetDirectory(nullptr);
+      m_dX_PSAcc_G4.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errG4")));     m_dX_PSAcc_G4->SetDirectory(nullptr);
 
-      m_convRadius            = (TH2D*) m_rootFile->Get("Conversions/es2012c/convRadiusMigrations");  m_convRadius->SetDirectory(0);
-      m_convFakeRate          = (TH1D*) m_rootFile->Get("Conversions/es2012c/convFakeRate");          m_convFakeRate->SetDirectory(0);
-      m_convRecoEfficiency    = (TH1D*) m_rootFile->Get("Conversions/es2012c/convRecoEfficiency");    m_convRecoEfficiency->SetDirectory(0);
+      m_convRadius.reset( dynamic_cast< TH1* >( m_rootFile->Get("Conversions/es2012c/convRadiusMigrations")));  m_convRadius->SetDirectory(nullptr);
+      m_convFakeRate.reset( dynamic_cast< TH1* >( m_rootFile->Get("Conversions/es2012c/convFakeRate")));          m_convFakeRate->SetDirectory(nullptr);
+      m_convRecoEfficiency.reset( dynamic_cast< TH1* >( m_rootFile->Get("Conversions/es2012c/convRecoEfficiency")));    m_convRecoEfficiency->SetDirectory(nullptr);
 
       m_begRunNumber = 195847;
       m_endRunNumber = 219365;
 
-      m_G4OverAFII_resolution_electron = (TH2F*)m_rootFile->Get("FastSim/es2015/el_full_fast_resolution");
-      m_G4OverAFII_resolution_unconverted = (TH2F*)m_rootFile->Get("FastSim/es2015/ph_unconv_full_fast_resolution");
-      m_G4OverAFII_resolution_converted = (TH2F*)m_rootFile->Get("FastSim/es2015/ph_conv_full_fast_resolution");
+      m_G4OverAFII_resolution_electron.reset( dynamic_cast< TH2* >( m_rootFile->Get("FastSim/es2015/el_full_fast_resolution")));
+      m_G4OverAFII_resolution_unconverted.reset( dynamic_cast< TH2* >( m_rootFile->Get("FastSim/es2015/ph_unconv_full_fast_resolution")));
+      m_G4OverAFII_resolution_converted.reset( dynamic_cast< TH2* >( m_rootFile->Get("FastSim/es2015/ph_conv_full_fast_resolution")));
 
       assert(m_G4OverAFII_resolution_electron);
       assert(m_G4OverAFII_resolution_unconverted);
       assert(m_G4OverAFII_resolution_converted);
 
-      m_G4OverAFII_resolution_electron->SetDirectory(0);
-      m_G4OverAFII_resolution_unconverted->SetDirectory(0);
-      m_G4OverAFII_resolution_converted->SetDirectory(0);
+      m_G4OverAFII_resolution_electron->SetDirectory(nullptr);
+      m_G4OverAFII_resolution_unconverted->SetDirectory(nullptr);
+      m_G4OverAFII_resolution_converted->SetDirectory(nullptr);
 
       const std::string gain_filename1 = PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v8/FunctionsTO.root");
       const std::string gain_filename2 = PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v8/FunctionsG_all.root");
-      m_gain_tool = new egGain::GainTool(gain_filename1, gain_filename2);
+      m_gain_tool.reset(new egGain::GainTool(gain_filename1, gain_filename2));
 
-      m_e1hg_tool = new e1hg_systematics();
+      m_e1hg_tool.reset(new e1hg_systematics());
     }
 
     else if (m_esmodel == egEnergyCorr::es2015PRE_res_improved or m_esmodel == egEnergyCorr::es2015cPRE_res_improved) {
       m_use_etaCalo_scales = true;
       m_use_new_resolution_model = true;
-      m_resolution_tool = new eg_resolution("run2_pre");
+      m_resolution_tool.reset(new eg_resolution("run2_pre"));
 
-      m_aPSNom       = (TH1D*) m_rootFile->Get("Scales/es2012c/alphaPS_uncor");                 m_aPSNom->SetDirectory(0);
-      m_daPSCor      = (TH1D*) m_rootFile->Get("Scales/es2012c/dalphaPS_cor");                  m_daPSCor->SetDirectory(0);
-      m_aS12Nom      = (TH1D*) m_rootFile->Get("Scales/es2012c/alphaS12_uncor");                m_aS12Nom->SetDirectory(0);
-      m_daS12Cor     = (TH1D*) m_rootFile->Get("Scales/es2012c/dalphaS12_cor");                 m_daS12Cor->SetDirectory(0);
+      m_aPSNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/alphaPS_uncor")));                 m_aPSNom->SetDirectory(nullptr);
+      m_daPSCor.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/dalphaPS_cor")));                  m_daPSCor->SetDirectory(nullptr);
+      m_aS12Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/alphaS12_uncor")));                m_aS12Nom->SetDirectory(nullptr);
+      m_daS12Cor.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/dalphaS12_cor")));                 m_daS12Cor->SetDirectory(nullptr);
 
-      m_trkSyst      = (TH1D*) m_rootFile->Get("Scales/es2012c/momentum_errSyst");              m_trkSyst->SetDirectory(0);
+      m_trkSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/momentum_errSyst")));              m_trkSyst->SetDirectory(nullptr);
 
-      m_zeeNom       = (TH1D*) m_rootFile->Get("Scales/es2015PRE/alphaZee_errStat");        m_zeeNom->SetDirectory(0);
-      m_zeeSyst      = (TH1D*) m_rootFile->Get("Scales/es2015PRE/alphaZee_errSyst");              m_zeeSyst->SetDirectory(0);
-      m_uA2MeV_2015_first2weeks_correction = (TH1*) m_rootFile->Get("Scales/es2015PRE/histo_uA2MeV_week12"); m_uA2MeV_2015_first2weeks_correction->SetDirectory(0);
+      m_zeeNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2015PRE/alphaZee_errStat")));        m_zeeNom->SetDirectory(nullptr);
+      m_zeeSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2015PRE/alphaZee_errSyst")));              m_zeeSyst->SetDirectory(nullptr);
+      m_uA2MeV_2015_first2weeks_correction.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2015PRE/histo_uA2MeV_week12"))); m_uA2MeV_2015_first2weeks_correction->SetDirectory(nullptr);
 
-      m_resNom       = (TH1D*) m_rootFile->Get("Resolution/es2015PRE/ctZee_errStat");       m_resNom->SetDirectory(0);
-      m_resSyst      = (TH1D*) m_rootFile->Get("Resolution/es2015PRE_res_improved/ctZee_errSyst");             m_resSyst->SetDirectory(0);
+      m_resNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2015PRE/ctZee_errStat")));       m_resNom->SetDirectory(nullptr);
+      m_resSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2015PRE_res_improved/ctZee_errSyst")));             m_resSyst->SetDirectory(nullptr);
 
-      m_pedestalL0   = (TH1D*) m_rootFile->Get("Pedestals/es2012c/pedestals_l0");               m_pedestalL0->SetDirectory(0);
-      m_pedestalL1   = (TH1D*) m_rootFile->Get("Pedestals/es2012c/pedestals_l1");               m_pedestalL1->SetDirectory(0);
-      m_pedestalL2   = (TH1D*) m_rootFile->Get("Pedestals/es2012c/pedestals_l2");               m_pedestalL2->SetDirectory(0);
-      m_pedestalL3   = (TH1D*) m_rootFile->Get("Pedestals/es2012c/pedestals_l3");               m_pedestalL3->SetDirectory(0);
+      m_pedestalL0.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2012c/pedestals_l0")));               m_pedestalL0->SetDirectory(nullptr);
+      m_pedestalL1.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2012c/pedestals_l1")));               m_pedestalL1->SetDirectory(nullptr);
+      m_pedestalL2.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2012c/pedestals_l2")));               m_pedestalL2->SetDirectory(nullptr);
+      m_pedestalL3.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2012c/pedestals_l3")));               m_pedestalL3->SetDirectory(nullptr);
 
-      m_dX_ID_Nom    = (TH1D*) m_rootFile->Get("Material/DX0_ConfigA");                         m_dX_ID_Nom->SetDirectory(0);
+      m_dX_ID_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/DX0_ConfigA")));                         m_dX_ID_Nom->SetDirectory(nullptr);
 
-      m_dX_IPPS_Nom  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errUncor");   m_dX_IPPS_Nom->SetDirectory(0);
-      m_dX_IPPS_LAr  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errLAr");     m_dX_IPPS_LAr->SetDirectory(0);
+      m_dX_IPPS_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errUncor")));   m_dX_IPPS_Nom->SetDirectory(nullptr);
+      m_dX_IPPS_LAr.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errLAr")));     m_dX_IPPS_LAr->SetDirectory(nullptr);
 
-      m_dX_IPAcc_Nom = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errUncor");  m_dX_IPAcc_Nom->SetDirectory(0);
-      m_dX_IPAcc_LAr = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errLAr");    m_dX_IPAcc_LAr->SetDirectory(0);
-      m_dX_IPAcc_G4  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errG4");     m_dX_IPAcc_G4->SetDirectory(0);
-      m_dX_IPAcc_GL1  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errGL1");    m_dX_IPAcc_GL1->SetDirectory(0);
+      m_dX_IPAcc_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errUncor")));  m_dX_IPAcc_Nom->SetDirectory(nullptr);
+      m_dX_IPAcc_LAr.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errLAr")));    m_dX_IPAcc_LAr->SetDirectory(nullptr);
+      m_dX_IPAcc_G4.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errG4")));     m_dX_IPAcc_G4->SetDirectory(nullptr);
+      m_dX_IPAcc_GL1.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errGL1")));    m_dX_IPAcc_GL1->SetDirectory(nullptr);
 
-      m_dX_PSAcc_Nom = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errUncor");  m_dX_PSAcc_Nom->SetDirectory(0);
-      m_dX_PSAcc_LAr = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errLAr");    m_dX_PSAcc_LAr->SetDirectory(0);
-      m_dX_PSAcc_G4  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errG4");     m_dX_PSAcc_G4->SetDirectory(0);
+      m_dX_PSAcc_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errUncor")));  m_dX_PSAcc_Nom->SetDirectory(nullptr);
+      m_dX_PSAcc_LAr.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errLAr")));    m_dX_PSAcc_LAr->SetDirectory(nullptr);
+      m_dX_PSAcc_G4.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errG4")));     m_dX_PSAcc_G4->SetDirectory(nullptr);
 
-      m_convRadius            = (TH2D*) m_rootFile->Get("Conversions/es2012c/convRadiusMigrations");  m_convRadius->SetDirectory(0);
-      m_convFakeRate          = (TH1D*) m_rootFile->Get("Conversions/es2012c/convFakeRate");          m_convFakeRate->SetDirectory(0);
-      m_convRecoEfficiency    = (TH1D*) m_rootFile->Get("Conversions/es2012c/convRecoEfficiency");    m_convRecoEfficiency->SetDirectory(0);
+      m_convRadius.reset( dynamic_cast< TH1* >( m_rootFile->Get("Conversions/es2012c/convRadiusMigrations")));  m_convRadius->SetDirectory(nullptr);
+      m_convFakeRate.reset( dynamic_cast< TH1* >( m_rootFile->Get("Conversions/es2012c/convFakeRate")));          m_convFakeRate->SetDirectory(nullptr);
+      m_convRecoEfficiency.reset( dynamic_cast< TH1* >( m_rootFile->Get("Conversions/es2012c/convRecoEfficiency")));    m_convRecoEfficiency->SetDirectory(nullptr);
 
       m_begRunNumber = 195847;
       m_endRunNumber = 219365;
 
-      m_G4OverAFII_resolution_electron = (TH2F*)m_rootFile->Get("FastSim/es2015/el_full_fast_resolution");
-      m_G4OverAFII_resolution_unconverted = (TH2F*)m_rootFile->Get("FastSim/es2015/ph_unconv_full_fast_resolution");
-      m_G4OverAFII_resolution_converted = (TH2F*)m_rootFile->Get("FastSim/es2015/ph_conv_full_fast_resolution");
+      m_G4OverAFII_resolution_electron.reset( dynamic_cast< TH2* >( m_rootFile->Get("FastSim/es2015/el_full_fast_resolution")));
+      m_G4OverAFII_resolution_unconverted.reset( dynamic_cast< TH2* >( m_rootFile->Get("FastSim/es2015/ph_unconv_full_fast_resolution")));
+      m_G4OverAFII_resolution_converted.reset( dynamic_cast< TH2* >( m_rootFile->Get("FastSim/es2015/ph_conv_full_fast_resolution")));
 
       assert(m_G4OverAFII_resolution_electron);
       assert(m_G4OverAFII_resolution_unconverted);
       assert(m_G4OverAFII_resolution_converted);
 
-      m_G4OverAFII_resolution_electron->SetDirectory(0);
-      m_G4OverAFII_resolution_unconverted->SetDirectory(0);
-      m_G4OverAFII_resolution_converted->SetDirectory(0);
+      m_G4OverAFII_resolution_electron->SetDirectory(nullptr);
+      m_G4OverAFII_resolution_unconverted->SetDirectory(nullptr);
+      m_G4OverAFII_resolution_converted->SetDirectory(nullptr);
 
       const std::string gain_filename1 = PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v8/FunctionsTO.root");
       const std::string gain_filename2 = PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v8/FunctionsG_all.root");
-      m_gain_tool = new egGain::GainTool(gain_filename1, gain_filename2);
+      m_gain_tool.reset(new egGain::GainTool(gain_filename1, gain_filename2));
 
-      m_e1hg_tool = new e1hg_systematics();
+      m_e1hg_tool.reset(new e1hg_systematics());
     }
 
     else if (m_esmodel == egEnergyCorr::es2015c_summer) {
       m_use_etaCalo_scales = true;
       m_use_new_resolution_model = true;
-      m_resolution_tool = new eg_resolution("run2_pre");
+      m_resolution_tool.reset(new eg_resolution("run2_pre"));
 
-      m_aPSNom       = (TH1D*) m_rootFile->Get("Scales/es2012c/alphaPS_uncor");                 m_aPSNom->SetDirectory(0);
-      m_daPSCor      = (TH1D*) m_rootFile->Get("Scales/es2012c/dalphaPS_cor");                  m_daPSCor->SetDirectory(0);
-      m_aS12Nom      = (TH1D*) m_rootFile->Get("Scales/es2012c/alphaS12_uncor");                m_aS12Nom->SetDirectory(0);
-      m_daS12Cor     = (TH1D*) m_rootFile->Get("Scales/es2012c/dalphaS12_cor");                 m_daS12Cor->SetDirectory(0);
+      m_aPSNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/alphaPS_uncor")));                 m_aPSNom->SetDirectory(nullptr);
+      m_daPSCor.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/dalphaPS_cor")));                  m_daPSCor->SetDirectory(nullptr);
+      m_aS12Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/alphaS12_uncor")));                m_aS12Nom->SetDirectory(nullptr);
+      m_daS12Cor.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/dalphaS12_cor")));                 m_daS12Cor->SetDirectory(nullptr);
 
-      m_trkSyst      = (TH1D*) m_rootFile->Get("Scales/es2012c/momentum_errSyst");              m_trkSyst->SetDirectory(0);
+      m_trkSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/momentum_errSyst")));              m_trkSyst->SetDirectory(nullptr);
 
-      m_zeeNom       = (TH1D*) m_rootFile->Get("Scales/es2015Summer/alphaZee_errStat");        m_zeeNom->SetDirectory(0);
-      m_zeeSyst      = (TH1D*) m_rootFile->Get("Scales/es2015Summer/alphaZee_errSyst");              m_zeeSyst->SetDirectory(0);
+      m_zeeNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2015Summer/alphaZee_errStat")));        m_zeeNom->SetDirectory(nullptr);
+      m_zeeSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2015Summer/alphaZee_errSyst")));              m_zeeSyst->SetDirectory(nullptr);
       m_uA2MeV_2015_first2weeks_correction = nullptr;
 
-      m_resNom       = (TH1D*) m_rootFile->Get("Resolution/es2015Summer/ctZee_errStat");       m_resNom->SetDirectory(0);
-      m_resSyst      = (TH1D*) m_rootFile->Get("Resolution/es2015Summer/ctZee_errSyst");       m_resSyst->SetDirectory(0);
+      m_resNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2015Summer/ctZee_errStat")));       m_resNom->SetDirectory(nullptr);
+      m_resSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2015Summer/ctZee_errSyst")));       m_resSyst->SetDirectory(nullptr);
 
-      m_pedestalL0   = (TH1D*) m_rootFile->Get("Pedestals/es2012c/pedestals_l0");               m_pedestalL0->SetDirectory(0);
-      m_pedestalL1   = (TH1D*) m_rootFile->Get("Pedestals/es2012c/pedestals_l1");               m_pedestalL1->SetDirectory(0);
-      m_pedestalL2   = (TH1D*) m_rootFile->Get("Pedestals/es2012c/pedestals_l2");               m_pedestalL2->SetDirectory(0);
-      m_pedestalL3   = (TH1D*) m_rootFile->Get("Pedestals/es2012c/pedestals_l3");               m_pedestalL3->SetDirectory(0);
+      m_pedestalL0.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2012c/pedestals_l0")));               m_pedestalL0->SetDirectory(nullptr);
+      m_pedestalL1.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2012c/pedestals_l1")));               m_pedestalL1->SetDirectory(nullptr);
+      m_pedestalL2.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2012c/pedestals_l2")));               m_pedestalL2->SetDirectory(nullptr);
+      m_pedestalL3.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2012c/pedestals_l3")));               m_pedestalL3->SetDirectory(nullptr);
 
-      m_dX_ID_Nom    = (TH1D*) m_rootFile->Get("Material/DX0_ConfigA");                         m_dX_ID_Nom->SetDirectory(0);
+      m_dX_ID_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/DX0_ConfigA")));                         m_dX_ID_Nom->SetDirectory(nullptr);
 
-      m_dX_IPPS_Nom  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errUncor");   m_dX_IPPS_Nom->SetDirectory(0);
-      m_dX_IPPS_LAr  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errLAr");     m_dX_IPPS_LAr->SetDirectory(0);
+      m_dX_IPPS_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errUncor")));   m_dX_IPPS_Nom->SetDirectory(nullptr);
+      m_dX_IPPS_LAr.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errLAr")));     m_dX_IPPS_LAr->SetDirectory(nullptr);
 
-      m_dX_IPAcc_Nom = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errUncor");  m_dX_IPAcc_Nom->SetDirectory(0);
-      m_dX_IPAcc_LAr = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errLAr");    m_dX_IPAcc_LAr->SetDirectory(0);
-      m_dX_IPAcc_G4  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errG4");     m_dX_IPAcc_G4->SetDirectory(0);
-      m_dX_IPAcc_GL1  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errGL1");    m_dX_IPAcc_GL1->SetDirectory(0);
+      m_dX_IPAcc_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errUncor")));  m_dX_IPAcc_Nom->SetDirectory(nullptr);
+      m_dX_IPAcc_LAr.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errLAr")));    m_dX_IPAcc_LAr->SetDirectory(nullptr);
+      m_dX_IPAcc_G4.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errG4")));     m_dX_IPAcc_G4->SetDirectory(nullptr);
+      m_dX_IPAcc_GL1.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errGL1")));    m_dX_IPAcc_GL1->SetDirectory(nullptr);
 
-      m_dX_PSAcc_Nom = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errUncor");  m_dX_PSAcc_Nom->SetDirectory(0);
-      m_dX_PSAcc_LAr = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errLAr");    m_dX_PSAcc_LAr->SetDirectory(0);
-      m_dX_PSAcc_G4  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errG4");     m_dX_PSAcc_G4->SetDirectory(0);
+      m_dX_PSAcc_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errUncor")));  m_dX_PSAcc_Nom->SetDirectory(nullptr);
+      m_dX_PSAcc_LAr.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errLAr")));    m_dX_PSAcc_LAr->SetDirectory(nullptr);
+      m_dX_PSAcc_G4.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errG4")));     m_dX_PSAcc_G4->SetDirectory(nullptr);
 
-      m_convRadius            = (TH2D*) m_rootFile->Get("Conversions/es2012c/convRadiusMigrations");  m_convRadius->SetDirectory(0);
-      m_convFakeRate          = (TH1D*) m_rootFile->Get("Conversions/es2012c/convFakeRate");          m_convFakeRate->SetDirectory(0);
-      m_convRecoEfficiency    = (TH1D*) m_rootFile->Get("Conversions/es2012c/convRecoEfficiency");    m_convRecoEfficiency->SetDirectory(0);
+      m_convRadius.reset( dynamic_cast< TH1* >( m_rootFile->Get("Conversions/es2012c/convRadiusMigrations")));  m_convRadius->SetDirectory(nullptr);
+      m_convFakeRate.reset( dynamic_cast< TH1* >( m_rootFile->Get("Conversions/es2012c/convFakeRate")));          m_convFakeRate->SetDirectory(nullptr);
+      m_convRecoEfficiency.reset( dynamic_cast< TH1* >( m_rootFile->Get("Conversions/es2012c/convRecoEfficiency")));    m_convRecoEfficiency->SetDirectory(nullptr);
 
       m_begRunNumber = 195847;
       m_endRunNumber = 219365;
 
-      m_G4OverAFII_resolution_electron = (TH2F*)m_rootFile->Get("FastSim/es2015/el_full_fast_resolution");
-      m_G4OverAFII_resolution_unconverted = (TH2F*)m_rootFile->Get("FastSim/es2015/ph_unconv_full_fast_resolution");
-      m_G4OverAFII_resolution_converted = (TH2F*)m_rootFile->Get("FastSim/es2015/ph_conv_full_fast_resolution");
+      m_G4OverAFII_resolution_electron.reset( dynamic_cast< TH2* >( m_rootFile->Get("FastSim/es2015/el_full_fast_resolution")));
+      m_G4OverAFII_resolution_unconverted.reset( dynamic_cast< TH2* >( m_rootFile->Get("FastSim/es2015/ph_unconv_full_fast_resolution")));
+      m_G4OverAFII_resolution_converted.reset( dynamic_cast< TH2* >( m_rootFile->Get("FastSim/es2015/ph_conv_full_fast_resolution")));
 
       assert(m_G4OverAFII_resolution_electron);
       assert(m_G4OverAFII_resolution_unconverted);
       assert(m_G4OverAFII_resolution_converted);
 
-      m_G4OverAFII_resolution_electron->SetDirectory(0);
-      m_G4OverAFII_resolution_unconverted->SetDirectory(0);
-      m_G4OverAFII_resolution_converted->SetDirectory(0);
+      m_G4OverAFII_resolution_electron->SetDirectory(nullptr);
+      m_G4OverAFII_resolution_unconverted->SetDirectory(nullptr);
+      m_G4OverAFII_resolution_converted->SetDirectory(nullptr);
 
       const std::string gain_filename1 = PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v8/FunctionsTO.root");
       const std::string gain_filename2 = PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v8/FunctionsG_all.root");
-      m_gain_tool = new egGain::GainTool(gain_filename1, gain_filename2);
+      m_gain_tool.reset(new egGain::GainTool(gain_filename1, gain_filename2));
 
-      m_e1hg_tool = new e1hg_systematics();
+      m_e1hg_tool.reset( new e1hg_systematics());
       m_use_temp_correction201215 = true;  // for eta > 2.5
       m_use_temp_correction201516 = false;
     }
@@ -716,267 +591,390 @@ namespace AtlasRoot {
     else if (m_esmodel == egEnergyCorr::es2016PRE) {
       m_use_etaCalo_scales = true;
       m_use_new_resolution_model = true;
-      m_resolution_tool = new eg_resolution("run2_pre");
+      m_resolution_tool.reset( new eg_resolution("run2_pre"));
 
-      m_aPSNom       = (TH1D*) m_rootFile->Get("Scales/es2012c/alphaPS_uncor");                 m_aPSNom->SetDirectory(0);
-      m_daPSCor      = (TH1D*) m_rootFile->Get("Scales/es2012c/dalphaPS_cor");                  m_daPSCor->SetDirectory(0);
-      m_aS12Nom      = (TH1D*) m_rootFile->Get("Scales/es2012c/alphaS12_uncor");                m_aS12Nom->SetDirectory(0);
-      m_daS12Cor     = (TH1D*) m_rootFile->Get("Scales/es2012c/dalphaS12_cor");                 m_daS12Cor->SetDirectory(0);
+      m_aPSNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/alphaPS_uncor")));                 m_aPSNom->SetDirectory(nullptr);
+      m_daPSCor.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/dalphaPS_cor")));                  m_daPSCor->SetDirectory(nullptr);
+      m_aS12Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/alphaS12_uncor")));                m_aS12Nom->SetDirectory(nullptr);
+      m_daS12Cor.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/dalphaS12_cor")));                 m_daS12Cor->SetDirectory(nullptr);
 
-      m_trkSyst      = (TH1D*) m_rootFile->Get("Scales/es2012c/momentum_errSyst");              m_trkSyst->SetDirectory(0);
+      m_trkSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/momentum_errSyst")));              m_trkSyst->SetDirectory(nullptr);
 
-      m_zeeNom       = (TH1D*) m_rootFile->Get("Scales/es2015Summer/alphaZee_errStat");         m_zeeNom->SetDirectory(0);
-      m_zeeSyst      = (TH1D*) m_rootFile->Get("Scales/es2015Summer/alphaZee_errSyst");         m_zeeSyst->SetDirectory(0);
-      m_uA2MeV_2015_first2weeks_correction = nullptr;
+      m_zeeNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2015Summer/alphaZee_errStat")));         m_zeeNom->SetDirectory(nullptr);
+      m_zeeSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2015Summer/alphaZee_errSyst")));         m_zeeSyst->SetDirectory(nullptr);
 
-      m_resNom       = (TH1D*) m_rootFile->Get("Resolution/es2015Summer/ctZee_errStat");        m_resNom->SetDirectory(0);
-      m_resSyst      = (TH1D*) m_rootFile->Get("Resolution/es2015Summer/ctZee_errSyst");        m_resSyst->SetDirectory(0);
+      m_resNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2015Summer/ctZee_errStat")));        m_resNom->SetDirectory(nullptr);
+      m_resSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2015Summer/ctZee_errSyst")));        m_resSyst->SetDirectory(nullptr);
 
-      m_pedestalL0   = (TH1D*) m_rootFile->Get("Pedestals/es2012c/pedestals_l0");               m_pedestalL0->SetDirectory(0);
-      m_pedestalL1   = (TH1D*) m_rootFile->Get("Pedestals/es2012c/pedestals_l1");               m_pedestalL1->SetDirectory(0);
-      m_pedestalL2   = (TH1D*) m_rootFile->Get("Pedestals/es2012c/pedestals_l2");               m_pedestalL2->SetDirectory(0);
-      m_pedestalL3   = (TH1D*) m_rootFile->Get("Pedestals/es2012c/pedestals_l3");               m_pedestalL3->SetDirectory(0);
+      m_pedestalL0.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2012c/pedestals_l0")));               m_pedestalL0->SetDirectory(nullptr);
+      m_pedestalL1.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2012c/pedestals_l1")));               m_pedestalL1->SetDirectory(nullptr);
+      m_pedestalL2.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2012c/pedestals_l2")));               m_pedestalL2->SetDirectory(nullptr);
+      m_pedestalL3.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2012c/pedestals_l3")));               m_pedestalL3->SetDirectory(nullptr);
 
-      m_dX_ID_Nom    = (TH1D*) m_rootFile->Get("Material/DX0_ConfigA");                         m_dX_ID_Nom->SetDirectory(0);
+      m_dX_ID_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/DX0_ConfigA")));                         m_dX_ID_Nom->SetDirectory(nullptr);
 
-      m_dX_IPPS_Nom  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errUncor");   m_dX_IPPS_Nom->SetDirectory(0);
-      m_dX_IPPS_LAr  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errLAr");     m_dX_IPPS_LAr->SetDirectory(0);
+      m_dX_IPPS_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errUncor")));   m_dX_IPPS_Nom->SetDirectory(nullptr);
+      m_dX_IPPS_LAr.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errLAr")));     m_dX_IPPS_LAr->SetDirectory(nullptr);
 
-      m_dX_IPAcc_Nom = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errUncor");  m_dX_IPAcc_Nom->SetDirectory(0);
-      m_dX_IPAcc_LAr = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errLAr");    m_dX_IPAcc_LAr->SetDirectory(0);
-      m_dX_IPAcc_G4  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errG4");     m_dX_IPAcc_G4->SetDirectory(0);
-      m_dX_IPAcc_GL1  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errGL1");    m_dX_IPAcc_GL1->SetDirectory(0);
+      m_dX_IPAcc_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errUncor")));  m_dX_IPAcc_Nom->SetDirectory(nullptr);
+      m_dX_IPAcc_LAr.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errLAr")));    m_dX_IPAcc_LAr->SetDirectory(nullptr);
+      m_dX_IPAcc_G4.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errG4")));     m_dX_IPAcc_G4->SetDirectory(nullptr);
+      m_dX_IPAcc_GL1.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errGL1")));    m_dX_IPAcc_GL1->SetDirectory(nullptr);
 
-      m_dX_PSAcc_Nom = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errUncor");  m_dX_PSAcc_Nom->SetDirectory(0);
-      m_dX_PSAcc_LAr = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errLAr");    m_dX_PSAcc_LAr->SetDirectory(0);
-      m_dX_PSAcc_G4  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errG4");     m_dX_PSAcc_G4->SetDirectory(0);
+      m_dX_PSAcc_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errUncor")));  m_dX_PSAcc_Nom->SetDirectory(nullptr);
+      m_dX_PSAcc_LAr.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errLAr")));    m_dX_PSAcc_LAr->SetDirectory(nullptr);
+      m_dX_PSAcc_G4.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errG4")));     m_dX_PSAcc_G4->SetDirectory(nullptr);
 
-      m_convRadius            = (TH2D*) m_rootFile->Get("Conversions/es2012c/convRadiusMigrations");  m_convRadius->SetDirectory(0);
-      m_convFakeRate          = (TH1D*) m_rootFile->Get("Conversions/es2012c/convFakeRate");          m_convFakeRate->SetDirectory(0);
-      m_convRecoEfficiency    = (TH1D*) m_rootFile->Get("Conversions/es2012c/convRecoEfficiency");    m_convRecoEfficiency->SetDirectory(0);
+      m_convRadius.reset( dynamic_cast< TH1* >( m_rootFile->Get("Conversions/es2012c/convRadiusMigrations")));  m_convRadius->SetDirectory(nullptr);
+      m_convFakeRate.reset( dynamic_cast< TH1* >( m_rootFile->Get("Conversions/es2012c/convFakeRate")));          m_convFakeRate->SetDirectory(nullptr);
+      m_convRecoEfficiency.reset( dynamic_cast< TH1* >( m_rootFile->Get("Conversions/es2012c/convRecoEfficiency")));    m_convRecoEfficiency->SetDirectory(nullptr);
 
       m_begRunNumber = 195847;
       m_endRunNumber = 219365;
 
-      m_G4OverAFII_resolution_electron = (TH2F*)m_rootFile->Get("FastSim/es2015/el_full_fast_resolution");
-      m_G4OverAFII_resolution_unconverted = (TH2F*)m_rootFile->Get("FastSim/es2015/ph_unconv_full_fast_resolution");
-      m_G4OverAFII_resolution_converted = (TH2F*)m_rootFile->Get("FastSim/es2015/ph_conv_full_fast_resolution");
+      m_G4OverAFII_resolution_electron.reset( dynamic_cast< TH2* >( m_rootFile->Get("FastSim/es2015/el_full_fast_resolution")));
+      m_G4OverAFII_resolution_unconverted.reset( dynamic_cast< TH2* >( m_rootFile->Get("FastSim/es2015/ph_unconv_full_fast_resolution")));
+      m_G4OverAFII_resolution_converted.reset( dynamic_cast< TH2* >( m_rootFile->Get("FastSim/es2015/ph_conv_full_fast_resolution")));
 
       assert(m_G4OverAFII_resolution_electron);
       assert(m_G4OverAFII_resolution_unconverted);
       assert(m_G4OverAFII_resolution_converted);
 
-      m_G4OverAFII_resolution_electron->SetDirectory(0);
-      m_G4OverAFII_resolution_unconverted->SetDirectory(0);
-      m_G4OverAFII_resolution_converted->SetDirectory(0);
+      m_G4OverAFII_resolution_electron->SetDirectory(nullptr);
+      m_G4OverAFII_resolution_unconverted->SetDirectory(nullptr);
+      m_G4OverAFII_resolution_converted->SetDirectory(nullptr);
 
       const std::string gain_filename1 = PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v8/FunctionsTO.root");
       const std::string gain_filename2 = PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v8/FunctionsG_all.root");
-      m_gain_tool = new egGain::GainTool(gain_filename1, gain_filename2);
+      m_gain_tool.reset(new egGain::GainTool(gain_filename1, gain_filename2));
 
-      m_e1hg_tool = new e1hg_systematics();
+      m_e1hg_tool.reset( new e1hg_systematics());
       m_use_temp_correction201215 = true;  // for eta > 2.5
       m_use_temp_correction201516 = true;
     }
 
-    else if (m_esmodel == egEnergyCorr::es2017 or m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_R21_PRE) {//add release 21 here for now
+    else if (m_esmodel == egEnergyCorr::es2017 or m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved
+             or m_esmodel == egEnergyCorr::es2017_summer_final or m_esmodel == egEnergyCorr::es2015_5TeV or m_esmodel == egEnergyCorr::es2017_R21_PRE
+             or m_esmodel == egEnergyCorr::es2017_R21_v0 or m_esmodel == egEnergyCorr::es2017_R21_v1 or  m_esmodel == egEnergyCorr::es2017_R21_ofc0_v1 or m_esmodel == egEnergyCorr::es2018_R21_v0 or  m_esmodel == egEnergyCorr::es2018_R21_v1) {//add release 21 here for now
       m_use_etaCalo_scales = true;
       m_use_new_resolution_model = true;
-      m_resolution_tool = new eg_resolution("run2_pre");
-
-      m_aPSNom       = (TH1D*) m_rootFile->Get("Scales/es2012c/alphaPS_uncor");                 m_aPSNom->SetDirectory(0);
-      m_daPSCor      = (TH1D*) m_rootFile->Get("Scales/es2012c/dalphaPS_cor");                  m_daPSCor->SetDirectory(0);
-      m_aS12Nom      = (TH1D*) m_rootFile->Get("Scales/es2012c/alphaS12_uncor");                m_aS12Nom->SetDirectory(0);
-      m_daS12Cor     = (TH1D*) m_rootFile->Get("Scales/es2012c/dalphaS12_cor");                 m_daS12Cor->SetDirectory(0);
+      if (m_esmodel == egEnergyCorr::es2017_R21_v1 || m_esmodel == egEnergyCorr::es2017_R21_ofc0_v1 || m_esmodel == egEnergyCorr::es2018_R21_v0 || m_esmodel == egEnergyCorr::es2018_R21_v1)
+        m_resolution_tool.reset(new eg_resolution("run2_R21_v1"));
+      else
+        m_resolution_tool.reset(new eg_resolution("run2_pre"));
+
+      if(m_esmodel == egEnergyCorr::es2017_summer_final or m_esmodel == egEnergyCorr::es2017_R21_v0 or m_esmodel == egEnergyCorr::es2017_R21_v1 or m_esmodel == egEnergyCorr::es2017_R21_ofc0_v1 or m_esmodel == egEnergyCorr::es2018_R21_v0 ){
+        m_aPSNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2017_summer_final/alphaPS_uncor")));       m_aPSNom->SetDirectory(nullptr);
+        m_daPSb12.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2017_summer_final/dalphaPS_b12")));        m_daPSb12->SetDirectory(nullptr);
+        m_daPSCor.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/dalphaPS_cor")));                    m_daPSCor->SetDirectory(nullptr);
+        m_aS12Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2017_summer_final/alphaS12_uncor")));      m_aS12Nom->SetDirectory(nullptr);
+        m_daS12Cor.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/dalphaS12_cor")));                   m_daS12Cor->SetDirectory(nullptr);
+      }
+      else if (m_esmodel == egEnergyCorr::es2018_R21_v1){
+        m_aPSNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2017_summer_final/alphaPS_uncor")));       m_aPSNom->SetDirectory(nullptr);
+        m_daPSb12.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2017_summer_final/dalphaPS_b12")));        m_daPSb12->SetDirectory(nullptr);
+        m_daPSCor.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/dalphaPS_cor")));                    m_daPSCor->SetDirectory(nullptr);
+        m_aS12Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2018_R21_v1/alphaS12_uncor")));      m_aS12Nom->SetDirectory(nullptr);
+        m_daS12Cor.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/dalphaS12_cor")));                   m_daS12Cor->SetDirectory(nullptr);
+      }
+      else{
+        m_aPSNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/alphaPS_uncor")));                 m_aPSNom->SetDirectory(nullptr);
+        m_daPSCor.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/dalphaPS_cor")));                  m_daPSCor->SetDirectory(nullptr);
+        m_aS12Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/alphaS12_uncor")));                m_aS12Nom->SetDirectory(nullptr);
+        m_daS12Cor.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/dalphaS12_cor")));                 m_daS12Cor->SetDirectory(nullptr);
+      }
+      m_trkSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2012c/momentum_errSyst")));              m_trkSyst->SetDirectory(nullptr);
 
-      m_trkSyst      = (TH1D*) m_rootFile->Get("Scales/es2012c/momentum_errSyst");              m_trkSyst->SetDirectory(0);
-      
       if(m_esmodel == egEnergyCorr::es2017){
-      m_zeeNom       = (TH1D*) m_rootFile->Get("Scales/es2017/alphaZee_errStat_period_2016");         m_zeeNom->SetDirectory(0);
-      m_zeeNom_data2015 = (TH1D*) m_rootFile->Get("Scales/es2017/alphaZee_errStat_period_2015");      m_zeeNom_data2015->SetDirectory(0);
+        m_zeeNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2017/alphaZee_errStat_period_2016")));         m_zeeNom->SetDirectory(nullptr);
+        m_zeeNom_data2015.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2017/alphaZee_errStat_period_2015")));      m_zeeNom_data2015->SetDirectory(nullptr);
       }
       else if(m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved){
-	m_zeeNom       = (TH1D*) m_rootFile->Get("Scales/es2017_summer/alphaZee_errStat_period_2016");         m_zeeNom->SetDirectory(0); 
-	m_zeeNom_data2015 = (TH1D*) m_rootFile->Get("Scales/es2017_summer/alphaZee_errStat_period_2015");      m_zeeNom_data2015->SetDirectory(0);
+        m_zeeNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2017_summer/alphaZee_errStat_period_2016")));         m_zeeNom->SetDirectory(nullptr);
+        m_zeeNom_data2015.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2017_summer/alphaZee_errStat_period_2015")));      m_zeeNom_data2015->SetDirectory(nullptr);
+      }
+      else if(m_esmodel == egEnergyCorr::es2017_summer_final){
+        m_zeeNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2017_summer_final/alphaZee_errStat_period_2016")));         m_zeeNom->SetDirectory(nullptr);
+        m_zeeNom_data2015.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2017_summer_final/alphaZee_errStat_period_2015")));      m_zeeNom_data2015->SetDirectory(nullptr);
+      }
+      else if(m_esmodel == egEnergyCorr::es2015_5TeV){
+        m_zeeNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2015_5TeV/alphaZee_errStat_period_2015")));         m_zeeNom->SetDirectory(nullptr);
+        //Same histogram added twice for simplicity
+        m_zeeNom_data2015.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2015_5TeV/alphaZee_errStat_period_2015")));      m_zeeNom_data2015->SetDirectory(nullptr);
+      }
+      else if (m_esmodel==egEnergyCorr::es2017_R21_v0) {
+        m_zeeNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2017_R21_v0/alphaZee_errStat_period_2017")));  m_zeeNom->SetDirectory(nullptr);
+        m_zeeNom_data2016.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2017_R21_v0/alphaZee_errStat_period_2016")));  m_zeeNom_data2016->SetDirectory(nullptr);
+        m_zeeNom_data2015.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2017_R21_v0/alphaZee_errStat_period_2015")));  m_zeeNom_data2015->SetDirectory(nullptr);
+      }
+      else if (m_esmodel==egEnergyCorr::es2017_R21_v1) {
+        m_zeeNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2017_R21_v1/alphaZee_errStat_period_2017")));  m_zeeNom->SetDirectory(nullptr);
+        m_zeeNom_data2016.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2017_R21_v1/alphaZee_errStat_period_2016")));  m_zeeNom_data2016->SetDirectory(nullptr);
+        m_zeeNom_data2015.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2017_R21_v1/alphaZee_errStat_period_2015")));  m_zeeNom_data2015->SetDirectory(nullptr);
+        m_zeeFwdk.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2017_R21_v1/alphaFwd_Finalk"))); m_zeeFwdk->SetDirectory(nullptr);
+        m_zeeFwdb.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2017_R21_v1/alphaFwd_Finalb"))); m_zeeFwdb->SetDirectory(nullptr);
+      }
+      else if (m_esmodel==egEnergyCorr::es2017_R21_ofc0_v1) {
+        m_zeeNom.reset(dynamic_cast<TH1*> (m_rootFile->Get("Scales/es2017_R21_ofc0_v1/alphaZee_errStat_period_2017")));  m_zeeNom->SetDirectory(nullptr);
+        m_zeeNom_data2016.reset(dynamic_cast<TH1*> (m_rootFile->Get("Scales/es2017_R21_ofc0_v1/alphaZee_errStat_period_2016")));  m_zeeNom_data2016->SetDirectory(nullptr);
+        m_zeeNom_data2015.reset(dynamic_cast<TH1*> (m_rootFile->Get("Scales/es2017_R21_ofc0_v1/alphaZee_errStat_period_2015")));  m_zeeNom_data2015->SetDirectory(nullptr);
+        m_zeeNom_data2018.reset(dynamic_cast<TH1*> (m_rootFile->Get("Scales/es2017_R21_ofc0_v1/alphaZee_errStat_period_2018")));  m_zeeNom_data2018->SetDirectory(nullptr);
+        m_zeeFwdk.reset(dynamic_cast<TH1*> (m_rootFile->Get("Scales/es2017_R21_v1/alphaFwd_Finalk"))); m_zeeFwdk->SetDirectory(nullptr);
+        m_zeeFwdb.reset(dynamic_cast<TH1*> (m_rootFile->Get("Scales/es2017_R21_v1/alphaFwd_Finalb"))); m_zeeFwdb->SetDirectory(nullptr);
       }
+      else if (m_esmodel == egEnergyCorr::es2018_R21_v0){
+
+        m_zeeNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2018_R21_v0/alphaZee_errStat_period_2018")));  m_zeeNom->SetDirectory(nullptr);
+        m_zeeNom_data2017.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2018_R21_v0/alphaZee_errStat_period_2017")));  m_zeeNom_data2017->SetDirectory(nullptr);
+        m_zeeNom_data2016.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2018_R21_v0/alphaZee_errStat_period_2016")));  m_zeeNom_data2016->SetDirectory(nullptr);
+        m_zeeNom_data2015.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2018_R21_v0/alphaZee_errStat_period_2015")));  m_zeeNom_data2015->SetDirectory(nullptr);
+        m_zeeFwdk.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2018_R21_v0/alphaFwd_Finalk"))); m_zeeFwdk->SetDirectory(nullptr);
+        m_zeeFwdb.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2018_R21_v0/alphaFwd_Finalb"))); m_zeeFwdb->SetDirectory(nullptr);
+      }
+      else if (m_esmodel == egEnergyCorr::es2018_R21_v1) {
+        m_zeeNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2018_R21_v1/alphaZee_errStat_period_2018")));  m_zeeNom->SetDirectory(nullptr);
+        m_zeeNom_data2017.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2018_R21_v1/alphaZee_errStat_period_2017")));  m_zeeNom_data2017->SetDirectory(nullptr);
+        m_zeeNom_data2016.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2018_R21_v1/alphaZee_errStat_period_2016")));  m_zeeNom_data2016->SetDirectory(nullptr);
+        m_zeeNom_data2015.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2018_R21_v1/alphaZee_errStat_period_2015")));  m_zeeNom_data2015->SetDirectory(nullptr);
+        //same as in v0 model
+        m_zeeFwdk.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2018_R21_v0/alphaFwd_Finalk"))); m_zeeFwdk->SetDirectory(nullptr);
+        m_zeeFwdb.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2018_R21_v0/alphaFwd_Finalb"))); m_zeeFwdb->SetDirectory(nullptr);
+       }
+
+
       else{
-	m_zeeNom       = (TH1D*) m_rootFile->Get("Scales/es2017_R21_PRE/alphaZee_errStat_period_2016");         m_zeeNom->SetDirectory(0);  
+        m_zeeNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2017_R21_PRE/alphaZee_errStat_period_2016")));         m_zeeNom->SetDirectory(nullptr);
         //SAME HISTO FOR 2015 FOR NOW
-	m_zeeNom_data2015 = (TH1D*) m_rootFile->Get("Scales/es2017_R21_PRE/alphaZee_errStat_period_2016");      m_zeeNom_data2015->SetDirectory(0);
+        m_zeeNom_data2015.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2017_R21_PRE/alphaZee_errStat_period_2016")));      m_zeeNom_data2015->SetDirectory(nullptr);
       }
       if(m_esmodel == egEnergyCorr::es2017){
-	m_zeeSyst      = (TH1D*) m_rootFile->Get("Scales/es2017/alphaZee_errSyst");         m_zeeSyst->SetDirectory(0);
+        m_zeeSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2017/alphaZee_errSyst")));         m_zeeSyst->SetDirectory(nullptr);
+      }
+      else if(m_esmodel == egEnergyCorr::es2017_summer_final){
+        m_zeeSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2017_summer_final/alphaZee_errSyst")));         m_zeeSyst->SetDirectory(nullptr);
+      }
+      else if(m_esmodel == egEnergyCorr::es2015_5TeV){
+        m_zeeSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2015_5TeV/alphaZee_errSyst")));         m_zeeSyst->SetDirectory(nullptr);
+      }
+      else if (m_esmodel == egEnergyCorr::es2017_R21_v0) {
+        m_zeeSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2017_summer_final/alphaZee_errSyst")));         m_zeeSyst->SetDirectory(nullptr);
+      }
+      else if (m_esmodel == egEnergyCorr::es2017_R21_v1) {
+        m_zeeSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2017_R21_v1/alphaZee_errSyst")));         m_zeeSyst->SetDirectory(nullptr);
+      }
+      else if (m_esmodel == egEnergyCorr::es2017_R21_ofc0_v1) {
+         m_zeeSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2017_R21_ofc0_v1/alphaZee_errSyst")));         m_zeeSyst->SetDirectory(nullptr);
+      }
+      else if (m_esmodel == egEnergyCorr::es2018_R21_v0) {
+        m_zeeSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2018_R21_v0/alphaZee_errSyst")));         m_zeeSyst->SetDirectory(nullptr);
+      }
+      else if (m_esmodel == egEnergyCorr::es2018_R21_v1) {
+        m_zeeSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2018_R21_v1/alphaZee_errSyst")));         m_zeeSyst->SetDirectory(nullptr);
       }
-      //else if(m_esmodel == egEnergyCorr::es2017_summer_improved){
-      //m_zeeSyst      = (TH1D*) m_rootFile->Get("Scales/es2017_summer_improved/alphaZee_errSyst");         m_zeeSyst->SetDirectory(0);
-      //}
       else{
-	m_zeeSyst      = (TH1D*) m_rootFile->Get("Scales/es2017_summer/alphaZee_errSyst");         m_zeeSyst->SetDirectory(0);
+        m_zeeSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2017_summer/alphaZee_errSyst")));         m_zeeSyst->SetDirectory(nullptr);
       }
-      
+
       m_uA2MeV_2015_first2weeks_correction = nullptr;
       if(m_esmodel == egEnergyCorr::es2017){
-	m_resNom       = (TH1D*) m_rootFile->Get("Resolution/es2017/ctZee_errStat");        m_resNom->SetDirectory(0);
-      }
-      else if(m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved){
-	m_resNom       = (TH1D*) m_rootFile->Get("Resolution/es2017_summer/ctZee_errStat");        m_resNom->SetDirectory(0);
-      }
+        m_resNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2017/ctZee_errStat")));        m_resNom->SetDirectory(nullptr);}
+      else if(m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2015_5TeV){
+        m_resNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2017_summer/ctZee_errStat")));        m_resNom->SetDirectory(nullptr);}
+      else if(m_esmodel == egEnergyCorr::es2017_summer_final) {
+        m_resNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2017_summer_final/ctZee_errStat")));        m_resNom->SetDirectory(nullptr);}
+      else if (m_esmodel==egEnergyCorr::es2017_R21_v0) {
+         m_resNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2017_R21_v0/ctZee_errStat")));        m_resNom->SetDirectory(nullptr);}
+      else if (m_esmodel==egEnergyCorr::es2017_R21_v1) {
+        m_resNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2017_R21_v1/ctZee_errStat")));        m_resNom->SetDirectory(nullptr);}
+      else if (m_esmodel==egEnergyCorr::es2017_R21_ofc0_v1) {
+        m_resNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2017_R21_ofc0_v1/ctZee_errStat")));        m_resNom->SetDirectory(nullptr);}
+      else if (m_esmodel==egEnergyCorr::es2018_R21_v0) {
+        m_resNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2018_R21_v0/ctZee_errStat")));        m_resNom->SetDirectory(nullptr);}
+      else if (m_esmodel==egEnergyCorr::es2018_R21_v1) {
+         m_resNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2018_R21_v1/ctZee_errStat")));        m_resNom->SetDirectory(nullptr); }
       else{
-	m_resNom       = (TH1D*) m_rootFile->Get("Resolution/es2017_R21_PRE/ctZee_errStat");        m_resNom->SetDirectory(0); 
+        m_resNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2017_R21_PRE/ctZee_errStat")));        m_resNom->SetDirectory(nullptr);
       }
+
       if(m_esmodel == egEnergyCorr::es2017){
-	m_resSyst      = (TH1D*) m_rootFile->Get("Resolution/es2017/ctZee_errSyst");        m_resSyst->SetDirectory(0);
+        m_resSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2017/ctZee_errSyst")));        m_resSyst->SetDirectory(nullptr);
+      }
+      else if(m_esmodel == egEnergyCorr::es2017_summer_final){
+        m_resSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2017_summer_final/ctZee_errSyst")));        m_resSyst->SetDirectory(nullptr);
+      }
+      else if(m_esmodel == egEnergyCorr::es2015_5TeV){
+        m_resSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2015_5TeV/ctZee_errSyst")));        m_resSyst->SetDirectory(nullptr);
       }
-      else{ 
-	m_resSyst      = (TH1D*) m_rootFile->Get("Resolution/es2017_summer/ctZee_errSyst");        m_resSyst->SetDirectory(0);
+      else if (m_esmodel == egEnergyCorr::es2017_R21_v0) {
+         m_resSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2017_summer_final/ctZee_errSyst")));        m_resSyst->SetDirectory(nullptr);
+      }
+      else if (m_esmodel == egEnergyCorr::es2017_R21_v1) {
+        m_resSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2017_R21_v1/ctZee_errSyst")));        m_resSyst->SetDirectory(nullptr);
+      }
+      else if (m_esmodel == egEnergyCorr::es2017_R21_ofc0_v1) {
+        m_resSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2017_R21_ofc0_v1/ctZee_errSyst")));        m_resSyst->SetDirectory(nullptr);
+      }
+      else if (m_esmodel == egEnergyCorr::es2018_R21_v0) {
+        m_resSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2018_R21_v0/ctZee_errSyst")));        m_resSyst->SetDirectory(nullptr);
+      }
+      else if (m_esmodel == egEnergyCorr::es2018_R21_v1) {
+        m_resSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2018_R21_v1/ctZee_errSyst")));        m_resSyst->SetDirectory(nullptr);
+      }
+      else{
+        m_resSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2017_summer/ctZee_errSyst")));        m_resSyst->SetDirectory(nullptr);
       }
       //else{
-      //m_resSyst      = (TH1D*) m_rootFile->Get("Resolution/es2017_summer_improved/ctZee_errSyst");        m_resSyst->SetDirectory(0);
+      //m_resSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2017_summer_improved/ctZee_errSyst")));        m_resSyst->SetDirectory(nullptr);
       //}
-      
-      m_pedestals_es2017 = get_object<TH1F>(*m_rootFile, "Pedestals/es2017/pedestals");          m_pedestals_es2017->SetDirectory(0);
 
-      m_dX_ID_Nom    = (TH1D*) m_rootFile->Get("Material/DX0_ConfigA");                         m_dX_ID_Nom->SetDirectory(0);
+      m_pedestals_es2017.reset( dynamic_cast< TH1* >(m_rootFile->Get("Pedestals/es2017/pedestals")));          m_pedestals_es2017->SetDirectory(nullptr);
+
+      m_dX_ID_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/DX0_ConfigA")));                         m_dX_ID_Nom->SetDirectory(nullptr);
 
-      m_dX_IPPS_Nom  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errUncor");   m_dX_IPPS_Nom->SetDirectory(0);
-      m_dX_IPPS_LAr  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errLAr");     m_dX_IPPS_LAr->SetDirectory(0);
+      m_dX_IPPS_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errUncor")));   m_dX_IPPS_Nom->SetDirectory(nullptr);
+      m_dX_IPPS_LAr.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errLAr")));     m_dX_IPPS_LAr->SetDirectory(nullptr);
 
-      m_dX_IPAcc_Nom = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errUncor");  m_dX_IPAcc_Nom->SetDirectory(0);
-      m_dX_IPAcc_LAr = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errLAr");    m_dX_IPAcc_LAr->SetDirectory(0);
-      m_dX_IPAcc_G4  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errG4");     m_dX_IPAcc_G4->SetDirectory(0);
-      m_dX_IPAcc_GL1  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errGL1");    m_dX_IPAcc_GL1->SetDirectory(0);
+      m_dX_IPAcc_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errUncor")));  m_dX_IPAcc_Nom->SetDirectory(nullptr);
+      m_dX_IPAcc_LAr.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errLAr")));    m_dX_IPAcc_LAr->SetDirectory(nullptr);
+      m_dX_IPAcc_G4.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errG4")));     m_dX_IPAcc_G4->SetDirectory(nullptr);
+      m_dX_IPAcc_GL1.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errGL1")));    m_dX_IPAcc_GL1->SetDirectory(nullptr);
 
-      m_dX_PSAcc_Nom = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errUncor");  m_dX_PSAcc_Nom->SetDirectory(0);
-      m_dX_PSAcc_LAr = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errLAr");    m_dX_PSAcc_LAr->SetDirectory(0);
-      m_dX_PSAcc_G4  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errG4");     m_dX_PSAcc_G4->SetDirectory(0);
+      m_dX_PSAcc_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errUncor")));  m_dX_PSAcc_Nom->SetDirectory(nullptr);
+      m_dX_PSAcc_LAr.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errLAr")));    m_dX_PSAcc_LAr->SetDirectory(nullptr);
+      m_dX_PSAcc_G4.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errG4")));     m_dX_PSAcc_G4->SetDirectory(nullptr);
 
-      m_convRadius            = (TH2D*) m_rootFile->Get("Conversions/es2012c/convRadiusMigrations");  m_convRadius->SetDirectory(0);
+      m_convRadius.reset( dynamic_cast< TH1* >( m_rootFile->Get("Conversions/es2012c/convRadiusMigrations")));  m_convRadius->SetDirectory(nullptr);
       if(m_esmodel == egEnergyCorr::es2017){
-	m_convFakeRate          = (TH1D*) m_rootFile->Get("Conversions/es2012c/convFakeRate");          m_convFakeRate->SetDirectory(0);
-	m_convRecoEfficiency    = (TH1D*) m_rootFile->Get("Conversions/es2012c/convRecoEfficiency");    m_convRecoEfficiency->SetDirectory(0);
+	m_convFakeRate.reset( dynamic_cast< TH1* >( m_rootFile->Get("Conversions/es2012c/convFakeRate")));          m_convFakeRate->SetDirectory(nullptr);
+	m_convRecoEfficiency.reset( dynamic_cast< TH1* >( m_rootFile->Get("Conversions/es2012c/convRecoEfficiency")));    m_convRecoEfficiency->SetDirectory(nullptr);
       }
       else{
-	m_convFakeRate          = (TH1D*) m_rootFile->Get("Conversions/es2017_summer/convFakeRate");          m_convFakeRate->SetDirectory(0); 
-        m_convRecoEfficiency    = (TH1D*) m_rootFile->Get("Conversions/es2017_summer/convRecoEfficiency");    m_convRecoEfficiency->SetDirectory(0);
+	m_convFakeRate.reset( dynamic_cast< TH1* >( m_rootFile->Get("Conversions/es2017_summer/convFakeRate")));          m_convFakeRate->SetDirectory(nullptr);
+        m_convRecoEfficiency.reset( dynamic_cast< TH1* >( m_rootFile->Get("Conversions/es2017_summer/convRecoEfficiency")));    m_convRecoEfficiency->SetDirectory(nullptr);
       }
-      
+
       // TODO: change path when moving to calibarea
       // TODO: better package this somewhere
 
       const std::string filename_pp0 = PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v8/PP0sys.root");
-      
+
       TFile file_pp0(filename_pp0.c_str());
-      m_pp0_elec = get_object<TH2D>(file_pp0, "elec");
-      m_pp0_conv = get_object<TH2D>(file_pp0, "conv");
-      m_pp0_unconv = get_object<TH2D>(file_pp0, "unco");
+      m_pp0_elec.reset( dynamic_cast< TH2* >( file_pp0.Get("elec")));
+      m_pp0_conv.reset( dynamic_cast< TH2* >( file_pp0.Get("conv")));
+      m_pp0_unconv.reset( dynamic_cast< TH2* >( file_pp0.Get("unco")));
 
-      m_pp0_elec->SetDirectory(0);
-      m_pp0_unconv->SetDirectory(0);
-      m_pp0_conv->SetDirectory(0);
+      m_pp0_elec->SetDirectory(nullptr);
+      m_pp0_unconv->SetDirectory(nullptr);
+      m_pp0_conv->SetDirectory(nullptr);
 
       //similar case for wtots1
       const std::string filename_wstot = PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v8/wstot_related_syst.root");
-      
+
 
       TFile file_wstot(filename_wstot.c_str());
-      m_wstot_slope_A_data = (TH1D*) file_wstot.Get("A_data"); m_wstot_slope_A_data->SetDirectory(0);
-      m_wstot_slope_B_MC = (TH1D*) file_wstot.Get("B_mc"); m_wstot_slope_B_MC->SetDirectory(0);
-      m_wstot_40GeV_data = (TH1D*) file_wstot.Get("wstot40_data"); m_wstot_40GeV_data->SetDirectory(0);
-      m_wstot_40GeV_MC = (TH1D*) file_wstot.Get("wstot40_mc"); m_wstot_40GeV_MC->SetDirectory(0);
-      m_wstot_pT_data_p0_electrons = (TH1D*) file_wstot.Get("wstot_pT_el_data_p0"); m_wstot_pT_data_p0_electrons->SetDirectory(0);
-      m_wstot_pT_data_p1_electrons = (TH1D*) file_wstot.Get("wstot_pT_el_data_p1"); m_wstot_pT_data_p1_electrons->SetDirectory(0);
-      m_wstot_pT_data_p0_unconverted_photons = (TH1D*) file_wstot.Get("wstot_pT_uc_data_p0"); m_wstot_pT_data_p0_unconverted_photons->SetDirectory(0);
-      m_wstot_pT_data_p1_unconverted_photons = (TH1D*) file_wstot.Get("wstot_pT_uc_data_p1"); m_wstot_pT_data_p1_unconverted_photons->SetDirectory(0);
-      m_wstot_pT_data_p0_converted_photons = (TH1D*) file_wstot.Get("wstot_pT_c_data_p0"); m_wstot_pT_data_p0_converted_photons->SetDirectory(0);
-      m_wstot_pT_data_p1_converted_photons = (TH1D*) file_wstot.Get("wstot_pT_c_data_p1"); m_wstot_pT_data_p1_converted_photons->SetDirectory(0);
-      m_wstot_pT_MC_p0_electrons = (TH1D*) file_wstot.Get("wstot_pT_el_mc_p0"); m_wstot_pT_MC_p0_electrons->SetDirectory(0);
-      m_wstot_pT_MC_p1_electrons = (TH1D*) file_wstot.Get("wstot_pT_el_mc_p1"); m_wstot_pT_MC_p1_electrons->SetDirectory(0);
-      m_wstot_pT_MC_p0_unconverted_photons = (TH1D*) file_wstot.Get("wstot_pT_ph_uc_mc_p0"); m_wstot_pT_MC_p0_unconverted_photons->SetDirectory(0);
-      m_wstot_pT_MC_p1_unconverted_photons = (TH1D*) file_wstot.Get("wstot_pT_ph_uc_mc_p1"); m_wstot_pT_MC_p1_unconverted_photons->SetDirectory(0);
-      m_wstot_pT_MC_p0_converted_photons = (TH1D*) file_wstot.Get("wstot_pT_ph_c_mc_p0"); m_wstot_pT_MC_p0_converted_photons->SetDirectory(0);
-      m_wstot_pT_MC_p1_converted_photons = (TH1D*) file_wstot.Get("wstot_pT_ph_c_mc_p1"); m_wstot_pT_MC_p1_converted_photons->SetDirectory(0);
+      m_wstot_slope_A_data.reset(  dynamic_cast< TH1* >( file_wstot.Get("A_data"))); m_wstot_slope_A_data->SetDirectory(nullptr);
+      m_wstot_slope_B_MC.reset(  dynamic_cast< TH1* >( file_wstot.Get("B_mc"))); m_wstot_slope_B_MC->SetDirectory(nullptr);
+      m_wstot_pT_data_p0_electrons.reset(  dynamic_cast< TH1* >( file_wstot.Get("wstot_pT_el_data_p0"))); m_wstot_pT_data_p0_electrons->SetDirectory(nullptr);
+      m_wstot_pT_data_p1_electrons.reset(  dynamic_cast< TH1* >( file_wstot.Get("wstot_pT_el_data_p1"))); m_wstot_pT_data_p1_electrons->SetDirectory(nullptr);
+      m_wstot_pT_data_p0_unconverted_photons.reset(  dynamic_cast< TH1* >( file_wstot.Get("wstot_pT_uc_data_p0"))); m_wstot_pT_data_p0_unconverted_photons->SetDirectory(nullptr);
+      m_wstot_pT_data_p1_unconverted_photons.reset(  dynamic_cast< TH1* >( file_wstot.Get("wstot_pT_uc_data_p1"))); m_wstot_pT_data_p1_unconverted_photons->SetDirectory(nullptr);
+      m_wstot_pT_data_p0_converted_photons.reset(  dynamic_cast< TH1* >( file_wstot.Get("wstot_pT_c_data_p0"))); m_wstot_pT_data_p0_converted_photons->SetDirectory(nullptr);
+      m_wstot_pT_data_p1_converted_photons.reset(  dynamic_cast< TH1* >( file_wstot.Get("wstot_pT_c_data_p1"))); m_wstot_pT_data_p1_converted_photons->SetDirectory(nullptr);
+      m_wstot_pT_MC_p0_electrons.reset(  dynamic_cast< TH1* >( file_wstot.Get("wstot_pT_el_mc_p0"))); m_wstot_pT_MC_p0_electrons->SetDirectory(nullptr);
+      m_wstot_pT_MC_p1_electrons.reset(  dynamic_cast< TH1* >( file_wstot.Get("wstot_pT_el_mc_p1"))); m_wstot_pT_MC_p1_electrons->SetDirectory(nullptr);
+      m_wstot_pT_MC_p0_unconverted_photons.reset(  dynamic_cast< TH1* >( file_wstot.Get("wstot_pT_ph_uc_mc_p0"))); m_wstot_pT_MC_p0_unconverted_photons->SetDirectory(nullptr);
+      m_wstot_pT_MC_p1_unconverted_photons.reset(  dynamic_cast< TH1* >( file_wstot.Get("wstot_pT_ph_uc_mc_p1"))); m_wstot_pT_MC_p1_unconverted_photons->SetDirectory(nullptr);
+      m_wstot_pT_MC_p0_converted_photons.reset(  dynamic_cast< TH1* >( file_wstot.Get("wstot_pT_ph_c_mc_p0"))); m_wstot_pT_MC_p0_converted_photons->SetDirectory(nullptr);
+      m_wstot_pT_MC_p1_converted_photons.reset(  dynamic_cast< TH1* >( file_wstot.Get("wstot_pT_ph_c_mc_p1"))); m_wstot_pT_MC_p1_converted_photons->SetDirectory(nullptr);
 
       m_begRunNumber = 252604;
       m_endRunNumber = 314199;
 
-      m_G4OverAFII_resolution_electron = (TH2F*)m_rootFile->Get("FastSim/es2017/el_full_fast_resolution");
-      m_G4OverAFII_resolution_unconverted = (TH2F*)m_rootFile->Get("FastSim/es2017/ph_unconv_full_fast_resolution");
-      m_G4OverAFII_resolution_converted = (TH2F*)m_rootFile->Get("FastSim/es2017/ph_conv_full_fast_resolution");
-
+      if (m_esmodel == egEnergyCorr::es2017_R21_v1 || m_esmodel == egEnergyCorr::es2017_R21_ofc0_v1 || m_esmodel == egEnergyCorr::es2018_R21_v0 || m_esmodel == egEnergyCorr::es2018_R21_v1) {
+         m_G4OverAFII_resolution_electron.reset( dynamic_cast< TH2* >( m_rootFile->Get("FastSim/es2017_v1/resol_Af2ToG4_elec_rel21")));
+         m_G4OverAFII_resolution_unconverted.reset( dynamic_cast< TH2* >( m_rootFile->Get("FastSim/es2017_v1/resol_Af2ToG4_unco_rel21")));
+         m_G4OverAFII_resolution_converted.reset( dynamic_cast< TH2* >( m_rootFile->Get("FastSim/es2017_v1/resol_Af2ToG4_conv_rel21")));
+      }
+      else {
+        m_G4OverAFII_resolution_electron.reset( dynamic_cast< TH2* >( m_rootFile->Get("FastSim/es2017/el_full_fast_resolution")));
+        m_G4OverAFII_resolution_unconverted.reset( dynamic_cast< TH2* >( m_rootFile->Get("FastSim/es2017/ph_unconv_full_fast_resolution")));
+        m_G4OverAFII_resolution_converted.reset( dynamic_cast< TH2* >( m_rootFile->Get("FastSim/es2017/ph_conv_full_fast_resolution")));
+      }
       assert(m_G4OverAFII_resolution_electron);
       assert(m_G4OverAFII_resolution_unconverted);
       assert(m_G4OverAFII_resolution_converted);
 
-      m_G4OverAFII_resolution_electron->SetDirectory(0);
-      m_G4OverAFII_resolution_unconverted->SetDirectory(0);
-      m_G4OverAFII_resolution_converted->SetDirectory(0);
+      m_G4OverAFII_resolution_electron->SetDirectory(nullptr);
+      m_G4OverAFII_resolution_unconverted->SetDirectory(nullptr);
+      m_G4OverAFII_resolution_converted->SetDirectory(nullptr);
 
       const std::string gain_filename1 = PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v8/FunctionsTO.root");
       const std::string gain_filename2 = PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v8/FunctionsG_all.root");
       m_gain_tool = nullptr;
 
       std::string gain_tool_run_2_filename;
-      if(m_esmodel == egEnergyCorr::es2017 or m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_R21_PRE){
-	gain_tool_run_2_filename = PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v11/gain_uncertainty_specialRun.root"); 
+      if(m_esmodel == egEnergyCorr::es2017 or m_esmodel == egEnergyCorr::es2017_summer
+         or m_esmodel == egEnergyCorr::es2017_R21_PRE or m_esmodel == egEnergyCorr::es2015_5TeV ){
+        gain_tool_run_2_filename = PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v11/gain_uncertainty_specialRun.root");
       }
       else{
-	gain_tool_run_2_filename = PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v12/gain_uncertainty_specialRun.root");
+        gain_tool_run_2_filename = PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v14/gain_uncertainty_specialRun.root");
       }
-      m_gain_tool_run2 = new egGain::GainUncertainty(gain_tool_run_2_filename);
-      
-      m_e1hg_tool = new e1hg_systematics();
+      m_gain_tool_run2.reset( new egGain::GainUncertainty(gain_tool_run_2_filename));
+
+      m_e1hg_tool.reset( new e1hg_systematics());
       m_use_temp_correction201215 = false;
       m_use_temp_correction201516 = false;
     }
 
     else if ( m_esmodel==egEnergyCorr::es2015_day0_3percent ) {
       m_use_new_resolution_model = true;
-      m_resolution_tool = new eg_resolution("run2_pre");
+      m_resolution_tool.reset(new eg_resolution("run2_pre"));
 
-      m_aPSNom       = (TH1D*) m_rootFile->Get("Scales/es2015_day0/alphaPS_uncor");             m_aPSNom->SetDirectory(0);         // old one
-      m_daPSCor      = (TH1D*) m_rootFile->Get("Scales/es2015_day0/dalphaPS_cor");              m_daPSCor->SetDirectory(0);        // old one
-      m_aS12Nom      = (TH1D*) m_rootFile->Get("Scales/es2015_day0/alphaS12_uncor");            m_aS12Nom->SetDirectory(0);        // old one
-      m_daS12Cor     = (TH1D*) m_rootFile->Get("Scales/es2015_day0/dalphaS12_cor");             m_daS12Cor->SetDirectory(0);       // old one
+      m_aPSNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2015_day0/alphaPS_uncor")));             m_aPSNom->SetDirectory(nullptr);         // old one
+      m_daPSCor.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2015_day0/dalphaPS_cor")));              m_daPSCor->SetDirectory(nullptr);        // old one
+      m_aS12Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2015_day0/alphaS12_uncor")));            m_aS12Nom->SetDirectory(nullptr);        // old one
+      m_daS12Cor.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2015_day0/dalphaS12_cor")));             m_daS12Cor->SetDirectory(nullptr);       // old one
 
-      m_trkSyst      = (TH1D*) m_rootFile->Get("Scales/es2015_day0/momentum_errSyst");          m_trkSyst->SetDirectory(0);        // old one
+      m_trkSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2015_day0/momentum_errSyst")));          m_trkSyst->SetDirectory(nullptr);        // old one
 
-      m_zeeNom       = (TH1D*) m_rootFile->Get("Scales/es2015_day0/alphaZee_errStat");          m_zeeNom->SetDirectory(0);         // old one
-      m_zeeSyst      = (TH1D*) m_rootFile->Get("Scales/es2015_day0/alphaZee_errSyst");          m_zeeSyst->SetDirectory(0);        // old one
+      m_zeeNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2015_day0/alphaZee_errStat")));          m_zeeNom->SetDirectory(nullptr);         // old one
+      m_zeeSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Scales/es2015_day0/alphaZee_errSyst")));          m_zeeSyst->SetDirectory(nullptr);        // old one
 
-      m_resNom       = (TH1D*) m_rootFile->Get("Resolution/es2012c/ctZee_errStat");             m_resNom->SetDirectory(0);         // old one
-      m_resSyst      = (TH1D*) m_rootFile->Get("Resolution/es2012c/ctZee_errSyst");             m_resSyst->SetDirectory(0);        // old one
+      m_resNom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2012c/ctZee_errStat")));             m_resNom->SetDirectory(nullptr);         // old one
+      m_resSyst.reset( dynamic_cast< TH1* >( m_rootFile->Get("Resolution/es2012c/ctZee_errSyst")));             m_resSyst->SetDirectory(nullptr);        // old one
 
-      m_pedestalL0   = (TH1D*) m_rootFile->Get("Pedestals/es2012c/pedestals_l0");               m_pedestalL0->SetDirectory(0);     // old one
-      m_pedestalL1   = (TH1D*) m_rootFile->Get("Pedestals/es2012c/pedestals_l1");               m_pedestalL1->SetDirectory(0);     // old one
-      m_pedestalL2   = (TH1D*) m_rootFile->Get("Pedestals/es2012c/pedestals_l2");               m_pedestalL2->SetDirectory(0);     // old one
-      m_pedestalL3   = (TH1D*) m_rootFile->Get("Pedestals/es2012c/pedestals_l3");               m_pedestalL3->SetDirectory(0);     // old one
+      m_pedestalL0.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2012c/pedestals_l0")));               m_pedestalL0->SetDirectory(nullptr);     // old one
+      m_pedestalL1.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2012c/pedestals_l1")));               m_pedestalL1->SetDirectory(nullptr);     // old one
+      m_pedestalL2.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2012c/pedestals_l2")));               m_pedestalL2->SetDirectory(nullptr);     // old one
+      m_pedestalL3.reset( dynamic_cast< TH1* >( m_rootFile->Get("Pedestals/es2012c/pedestals_l3")));               m_pedestalL3->SetDirectory(nullptr);     // old one
 
-      m_dX_ID_Nom    = (TH1D*) m_rootFile->Get("Material/DX0_ConfigA");                         m_dX_ID_Nom->SetDirectory(0);      // old one
+      m_dX_ID_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/DX0_ConfigA")));                         m_dX_ID_Nom->SetDirectory(nullptr);      // old one
 
-      m_dX_IPPS_Nom  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errUncor");   m_dX_IPPS_Nom->SetDirectory(0);    // old one
-      m_dX_IPPS_LAr  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errLAr");     m_dX_IPPS_LAr->SetDirectory(0);    // old one
+      m_dX_IPPS_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errUncor")));   m_dX_IPPS_Nom->SetDirectory(nullptr);    // old one
+      m_dX_IPPS_LAr.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPPS_NewG_errLAr")));     m_dX_IPPS_LAr->SetDirectory(nullptr);    // old one
 
-      m_dX_IPAcc_Nom = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errUncor");  m_dX_IPAcc_Nom->SetDirectory(0);   // old one
-      m_dX_IPAcc_LAr = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errLAr");    m_dX_IPAcc_LAr->SetDirectory(0);   // old one
-      m_dX_IPAcc_G4  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errG4");     m_dX_IPAcc_G4->SetDirectory(0);    // old one
-      m_dX_IPAcc_GL1  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errGL1");    m_dX_IPAcc_GL1->SetDirectory(0);  // old one
+      m_dX_IPAcc_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errUncor")));  m_dX_IPAcc_Nom->SetDirectory(nullptr);   // old one
+      m_dX_IPAcc_LAr.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errLAr")));    m_dX_IPAcc_LAr->SetDirectory(nullptr);   // old one
+      m_dX_IPAcc_G4.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errG4")));     m_dX_IPAcc_G4->SetDirectory(nullptr);    // old one
+      m_dX_IPAcc_GL1.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_IPAcc_NewG_errGL1")));    m_dX_IPAcc_GL1->SetDirectory(nullptr);  // old one
 
-      m_dX_PSAcc_Nom = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errUncor");  m_dX_PSAcc_Nom->SetDirectory(0);   // old one
-      m_dX_PSAcc_LAr = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errLAr");    m_dX_PSAcc_LAr->SetDirectory(0);   // old one
-      m_dX_PSAcc_G4  = (TH1D*) m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errG4");     m_dX_PSAcc_G4->SetDirectory(0);    // old one
+      m_dX_PSAcc_Nom.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errUncor")));  m_dX_PSAcc_Nom->SetDirectory(nullptr);   // old one
+      m_dX_PSAcc_LAr.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errLAr")));    m_dX_PSAcc_LAr->SetDirectory(nullptr);   // old one
+      m_dX_PSAcc_G4.reset( dynamic_cast< TH1* >( m_rootFile->Get("Material/Measured/DXerr_PSAcc_NewG_errG4")));     m_dX_PSAcc_G4->SetDirectory(nullptr);    // old one
 
-      m_convRadius            = (TH2D*) m_rootFile->Get("Conversions/es2012c/convRadiusMigrations");  m_convRadius->SetDirectory(0);          // old one
-      m_convFakeRate          = (TH1D*) m_rootFile->Get("Conversions/es2012c/convFakeRate");          m_convFakeRate->SetDirectory(0);        // old one
-      m_convRecoEfficiency    = (TH1D*) m_rootFile->Get("Conversions/es2012c/convRecoEfficiency");    m_convRecoEfficiency->SetDirectory(0);  // old one
+      m_convRadius.reset( dynamic_cast< TH1* >( m_rootFile->Get("Conversions/es2012c/convRadiusMigrations")));  m_convRadius->SetDirectory(nullptr);          // old one
+      m_convFakeRate.reset( dynamic_cast< TH1* >( m_rootFile->Get("Conversions/es2012c/convFakeRate")));          m_convFakeRate->SetDirectory(nullptr);        // old one
+      m_convRecoEfficiency.reset( dynamic_cast< TH1* >( m_rootFile->Get("Conversions/es2012c/convRecoEfficiency")));    m_convRecoEfficiency->SetDirectory(nullptr);  // old one
 
       m_begRunNumber = 195847;
       m_endRunNumber = 219365;
 
       const std::string gain_filename1 = PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v8/FunctionsTO.root");
       const std::string gain_filename2 = PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v8/FunctionsG_all.root");
-      m_gain_tool = new egGain::GainTool(gain_filename1, gain_filename2);
+      m_gain_tool.reset( new egGain::GainTool(gain_filename1, gain_filename2));
 
-      m_e1hg_tool = new e1hg_systematics();
+      m_e1hg_tool.reset( new e1hg_systematics());
 
 
       // If we are here, fail      :
@@ -992,89 +990,162 @@ namespace AtlasRoot {
 
     if (m_esmodel == egEnergyCorr::es2015cPRE or m_esmodel == egEnergyCorr::es2015cPRE_res_improved or
         m_esmodel == egEnergyCorr::es2015c_summer or m_esmodel == egEnergyCorr::es2016PRE or m_esmodel == egEnergyCorr::es2017
-	or m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_R21_PRE)
+	or m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_summer_final
+        or m_esmodel == egEnergyCorr::es2017_R21_v0 or m_esmodel == egEnergyCorr::es2017_R21_v1  or m_esmodel == egEnergyCorr::es2017_R21_ofc0_v1
+	or m_esmodel == egEnergyCorr::es2017_R21_PRE or m_esmodel == egEnergyCorr::es2015_5TeV or m_esmodel == egEnergyCorr::es2018_R21_v0 or  m_esmodel == egEnergyCorr::es2018_R21_v1)
     {
       // E4 systematics
-      m_E4ElectronEtaBins = get_object<TAxis>(*m_rootFile, "E4Recalibration/v4/electron_eta_axis");
-      m_E4ElectronGraphs = get_object<TList>(*m_rootFile, "E4Recalibration/v4/electron");
+      m_E4ElectronEtaBins.reset( dynamic_cast< TAxis* >( m_rootFile->Get("E4Recalibration/v4/electron_eta_axis")));
+      m_E4ElectronGraphs.reset( dynamic_cast< TList* >( m_rootFile->Get("E4Recalibration/v4/electron")));m_E4ElectronGraphs->SetOwner();
       // for photons use the same as electrons
-      m_E4UnconvertedEtaBins = get_object<TAxis>(*m_rootFile, "E4Recalibration/v4/electron_eta_axis");
-      m_E4UnconvertedGraphs = get_object<TList>(*m_rootFile, "E4Recalibration/v4/electron");
-      m_E4ConvertedEtaBins = get_object<TAxis>(*m_rootFile, "E4Recalibration/v4/electron_eta_axis");
-      m_E4ConvertedGraphs = get_object<TList>(*m_rootFile, "E4Recalibration/v4/electron");
+      m_E4UnconvertedEtaBins.reset( dynamic_cast< TAxis* >( m_rootFile->Get("E4Recalibration/v4/electron_eta_axis")));
+      m_E4UnconvertedGraphs.reset( dynamic_cast< TList* >( m_rootFile->Get("E4Recalibration/v4/electron")));m_E4UnconvertedGraphs->SetOwner();
+      m_E4ConvertedEtaBins.reset( dynamic_cast< TAxis* >( m_rootFile->Get("E4Recalibration/v4/electron_eta_axis")));
+      m_E4ConvertedGraphs.reset( dynamic_cast< TList* >( m_rootFile->Get("E4Recalibration/v4/electron")));m_E4ConvertedGraphs->SetOwner();
     }
 
     // ... PS and S12 recalibration curves
     if (m_esmodel == egEnergyCorr::es2015PRE or m_esmodel == egEnergyCorr::es2015PRE_res_improved or
         m_esmodel == egEnergyCorr::es2015cPRE or m_esmodel == egEnergyCorr::es2015cPRE_res_improved or
         m_esmodel == egEnergyCorr::es2015c_summer or m_esmodel == egEnergyCorr::es2016PRE or m_esmodel == egEnergyCorr::es2017
-	or m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_R21_PRE) {
-
-      m_psElectronEtaBins =          get_object<TAxis>(*m_rootFile, "PSRecalibration/es2015PRE/ElectronAxis");
-      m_psElectronGraphs =           get_object<TList>(*m_rootFile, "PSRecalibration/es2015PRE/ElectronBiasPS");
-      m_psUnconvertedEtaBins =       get_object<TAxis>(*m_rootFile, "PSRecalibration/es2015PRE/UnconvertedAxis");
-      m_psUnconvertedGraphs =        get_object<TList>(*m_rootFile, "PSRecalibration/es2015PRE/UnconvertedBiasPS");
-      m_psConvertedEtaBins =         get_object<TAxis>(*m_rootFile, "PSRecalibration/es2015PRE/ConvertedAxis");
-      m_psConvertedGraphs =          get_object<TList>(*m_rootFile, "PSRecalibration/es2015PRE/ConvertedBiasPS");
-
-      m_s12ElectronEtaBins =         get_object<TAxis>(*m_rootFile, "S1Recalibration/es2015PRE/ElectronAxis");
-      m_s12ElectronGraphs =          get_object<TList>(*m_rootFile, "S1Recalibration/es2015PRE/ElectronBiasS1");
-      m_s12UnconvertedEtaBins =      get_object<TAxis>(*m_rootFile, "S1Recalibration/es2015PRE/UnconvertedAxis");
-      m_s12UnconvertedGraphs =       get_object<TList>(*m_rootFile, "S1Recalibration/es2015PRE/UnconvertedBiasS1");
-      m_s12ConvertedEtaBins =        get_object<TAxis>(*m_rootFile, "S1Recalibration/es2015PRE/ConvertedAxis");
-      m_s12ConvertedGraphs =         get_object<TList>(*m_rootFile, "S1Recalibration/es2015PRE/ConvertedBiasS1");
+	or m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_summer_final
+        or m_esmodel == egEnergyCorr::es2017_R21_v0 or m_esmodel == egEnergyCorr::es2017_R21_v1 or m_esmodel == egEnergyCorr::es2017_R21_ofc0_v1
+	or m_esmodel == egEnergyCorr::es2017_R21_PRE or m_esmodel == egEnergyCorr::es2015_5TeV or m_esmodel == egEnergyCorr::es2018_R21_v0 or m_esmodel == egEnergyCorr::es2018_R21_v1) {
+
+      m_psElectronEtaBins.reset( dynamic_cast< TAxis* >( m_rootFile->Get("PSRecalibration/es2015PRE/ElectronAxis")));
+      m_psElectronGraphs.reset( dynamic_cast< TList* >( m_rootFile->Get("PSRecalibration/es2015PRE/ElectronBiasPS")));m_psElectronGraphs->SetOwner();
+      m_psUnconvertedEtaBins.reset( dynamic_cast< TAxis* >( m_rootFile->Get("PSRecalibration/es2015PRE/UnconvertedAxis")));
+      m_psUnconvertedGraphs.reset( dynamic_cast< TList* >( m_rootFile->Get("PSRecalibration/es2015PRE/UnconvertedBiasPS")));m_psUnconvertedGraphs->SetOwner();
+      m_psConvertedEtaBins.reset( dynamic_cast< TAxis* >( m_rootFile->Get("PSRecalibration/es2015PRE/ConvertedAxis")));
+      m_psConvertedGraphs.reset( dynamic_cast< TList* >( m_rootFile->Get("PSRecalibration/es2015PRE/ConvertedBiasPS")));m_psConvertedGraphs->SetOwner();
+
+      m_s12ElectronEtaBins.reset( dynamic_cast< TAxis* >( m_rootFile->Get("S1Recalibration/es2015PRE/ElectronAxis")));
+      m_s12ElectronGraphs.reset( dynamic_cast< TList* >( m_rootFile->Get("S1Recalibration/es2015PRE/ElectronBiasS1")));m_s12ElectronGraphs->SetOwner();
+      m_s12UnconvertedEtaBins.reset( dynamic_cast< TAxis* >( m_rootFile->Get("S1Recalibration/es2015PRE/UnconvertedAxis")));
+      m_s12UnconvertedGraphs.reset( dynamic_cast< TList* >( m_rootFile->Get("S1Recalibration/es2015PRE/UnconvertedBiasS1")));m_s12UnconvertedGraphs->SetOwner();
+      m_s12ConvertedEtaBins.reset( dynamic_cast< TAxis* >( m_rootFile->Get("S1Recalibration/es2015PRE/ConvertedAxis")));
+      m_s12ConvertedGraphs.reset( dynamic_cast< TList* >( m_rootFile->Get("S1Recalibration/es2015PRE/ConvertedBiasS1")));m_s12ConvertedGraphs->SetOwner();
     }
     else // run1
     {
-      m_psElectronEtaBins =          (TAxis*) m_rootFile->Get("PSRecalibration/ElectronAxis");
-      m_psElectronGraphs =           (TList*) m_rootFile->Get("PSRecalibration/ElectronBiasPS");
-      m_psUnconvertedEtaBins =       (TAxis*) m_rootFile->Get("PSRecalibration/UnconvertedAxis");
-      m_psUnconvertedGraphs =        (TList*) m_rootFile->Get("PSRecalibration/UnconvertedBiasPS");
-      m_psConvertedEtaBins =         (TAxis*) m_rootFile->Get("PSRecalibration/ConvertedAxis");
-      m_psConvertedGraphs =          (TList*) m_rootFile->Get("PSRecalibration/ConvertedBiasPS");
+      m_psElectronEtaBins.reset( dynamic_cast< TAxis* >( m_rootFile->Get("PSRecalibration/ElectronAxis")));
+      m_psElectronGraphs.reset( dynamic_cast< TList* >( m_rootFile->Get("PSRecalibration/ElectronBiasPS")));m_psElectronGraphs->SetOwner();
+      m_psUnconvertedEtaBins.reset( dynamic_cast< TAxis* >( m_rootFile->Get("PSRecalibration/UnconvertedAxis")));
+      m_psUnconvertedGraphs.reset( dynamic_cast< TList* >( m_rootFile->Get("PSRecalibration/UnconvertedBiasPS")));m_psUnconvertedGraphs->SetOwner();
+      m_psConvertedEtaBins.reset( dynamic_cast< TAxis* >( m_rootFile->Get("PSRecalibration/ConvertedAxis")));
+      m_psConvertedGraphs.reset( dynamic_cast< TList* >( m_rootFile->Get("PSRecalibration/ConvertedBiasPS")));m_psConvertedGraphs->SetOwner();
 
-      m_s12ElectronEtaBins =         (TAxis*) m_rootFile->Get("S1Recalibration/ElectronAxis");
-      m_s12ElectronGraphs =          (TList*) m_rootFile->Get("S1Recalibration/ElectronBiasS1");
-      m_s12UnconvertedEtaBins =      (TAxis*) m_rootFile->Get("S1Recalibration/UnconvertedAxis");
-      m_s12UnconvertedGraphs =       (TList*) m_rootFile->Get("S1Recalibration/UnconvertedBiasS1");
-      m_s12ConvertedEtaBins =        (TAxis*) m_rootFile->Get("S1Recalibration/ConvertedAxis");
-      m_s12ConvertedGraphs =         (TList*) m_rootFile->Get("S1Recalibration/ConvertedBiasS1");
+      m_s12ElectronEtaBins.reset( dynamic_cast< TAxis* >( m_rootFile->Get("S1Recalibration/ElectronAxis")));
+      m_s12ElectronGraphs.reset( dynamic_cast< TList* >( m_rootFile->Get("S1Recalibration/ElectronBiasS1")));m_s12ElectronGraphs->SetOwner();
+      m_s12UnconvertedEtaBins.reset( dynamic_cast< TAxis* >( m_rootFile->Get("S1Recalibration/UnconvertedAxis")));
+      m_s12UnconvertedGraphs.reset( dynamic_cast< TList* >( m_rootFile->Get("S1Recalibration/UnconvertedBiasS1")));m_s12UnconvertedGraphs->SetOwner();
+      m_s12ConvertedEtaBins.reset( dynamic_cast< TAxis* >( m_rootFile->Get("S1Recalibration/ConvertedAxis")));
+      m_s12ConvertedGraphs.reset( dynamic_cast< TList* >( m_rootFile->Get("S1Recalibration/ConvertedBiasS1")));m_s12ConvertedGraphs->SetOwner();
     }
 
     // further inputs do not depend on year
 
     // ... material distortions
 
-    m_matUnconvertedScale.push_back( (TH1D*) m_rootFile->Get("Material/unconvertedBiasSubtracted_ConfigA") );
-    m_matUnconvertedScale.push_back( (TH1D*) m_rootFile->Get("Material/unconvertedBiasSubtracted_ConfigCpDp") );
-    m_matUnconvertedScale.push_back( (TH1D*) m_rootFile->Get("Material/unconvertedBiasSubtracted_ConfigEpLp") );
-    m_matUnconvertedScale.push_back( (TH1D*) m_rootFile->Get("Material/unconvertedBiasSubtracted_ConfigFpMX") );
-    m_matUnconvertedScale.push_back( (TH1D*) m_rootFile->Get("Material/unconvertedBiasSubtracted_ConfigGp") );
-
-    m_matConvertedScale.push_back( (TH1D*) m_rootFile->Get("Material/convertedBiasSubtracted_ConfigA") );
-    m_matConvertedScale.push_back( (TH1D*) m_rootFile->Get("Material/convertedBiasSubtracted_ConfigCpDp") );
-    m_matConvertedScale.push_back( (TH1D*) m_rootFile->Get("Material/convertedBiasSubtracted_ConfigEpLp") );
-    m_matConvertedScale.push_back( (TH1D*) m_rootFile->Get("Material/convertedBiasSubtracted_ConfigFpMX") );
-    m_matConvertedScale.push_back( (TH1D*) m_rootFile->Get("Material/convertedBiasSubtracted_ConfigGp") );
-
-    m_matElectronCstTerm.push_back( (TH1F*) m_rootFile->Get("Material/electronCstTerm_ConfigA") );
-    m_matElectronCstTerm.push_back( (TH1F*) m_rootFile->Get("Material/electronCstTerm_ConfigCpDp") );
-    m_matElectronCstTerm.push_back( (TH1F*) m_rootFile->Get("Material/electronCstTerm_ConfigEpLp") );
-    m_matElectronCstTerm.push_back( (TH1F*) m_rootFile->Get("Material/electronCstTerm_ConfigFpMX") );
-    m_matElectronCstTerm.push_back( (TH1F*) m_rootFile->Get("Material/electronCstTerm_ConfigGp") );
-
-    m_matX0Additions.push_back( (TH1D*) m_rootFile->Get("Material/DX0_ConfigA") );
-    m_matX0Additions.push_back( (TH1D*) m_rootFile->Get("Material/DX0_ConfigCpDp") );
-    m_matX0Additions.push_back( (TH1D*) m_rootFile->Get("Material/DX0_ConfigEpLp") );
-    m_matX0Additions.push_back( (TH1D*) m_rootFile->Get("Material/DX0_ConfigFpMX") );
-    m_matX0Additions.push_back( (TH1D*) m_rootFile->Get("Material/DX0_ConfigGp") );
-
-    m_matElectronEtaBins =         (TAxis*) m_rootFile->Get("Material/LinearityEtaBins");
-    m_matElectronGraphs.push_back( (TList*) m_rootFile->Get("Material/Linearity_Cluster_ConfigA") );
-    m_matElectronGraphs.push_back( (TList*) m_rootFile->Get("Material/Linearity_Cluster_ConfigCpDp") );
-    m_matElectronGraphs.push_back( (TList*) m_rootFile->Get("Material/Linearity_Cluster_ConfigEpLp") );
-    m_matElectronGraphs.push_back( (TList*) m_rootFile->Get("Material/Linearity_Cluster_ConfigFpMX") );
-    m_matElectronGraphs.push_back( (TList*) m_rootFile->Get("Material/Linearity_Cluster_ConfigGp") );
+    m_matUnconvertedScale.emplace_back(std::unique_ptr<TH1>( (TH1*) m_rootFile->Get("Material/unconvertedBiasSubtracted_ConfigA") ));
+    m_matUnconvertedScale.back()->SetDirectory(nullptr);
+    m_matUnconvertedScale.emplace_back(std::unique_ptr<TH1>( (TH1*) m_rootFile->Get("Material/unconvertedBiasSubtracted_ConfigCpDp") ));
+    m_matUnconvertedScale.back()->SetDirectory(nullptr);
+    m_matUnconvertedScale.emplace_back(std::unique_ptr<TH1>( (TH1*) m_rootFile->Get("Material/unconvertedBiasSubtracted_ConfigEpLp") ));
+    m_matUnconvertedScale.back()->SetDirectory(nullptr);
+    m_matUnconvertedScale.emplace_back(std::unique_ptr<TH1>( (TH1*) m_rootFile->Get("Material/unconvertedBiasSubtracted_ConfigFpMX") ));
+    m_matUnconvertedScale.back()->SetDirectory(nullptr);
+    m_matUnconvertedScale.emplace_back(std::unique_ptr<TH1>( (TH1*) m_rootFile->Get("Material/unconvertedBiasSubtracted_ConfigGp") ));
+    m_matUnconvertedScale.back()->SetDirectory(nullptr);
+
+    m_matConvertedScale.emplace_back(std::unique_ptr<TH1>(  (TH1*) m_rootFile->Get("Material/convertedBiasSubtracted_ConfigA") ));
+    m_matConvertedScale.back()->SetDirectory(nullptr);
+    m_matConvertedScale.emplace_back(std::unique_ptr<TH1>(  (TH1*) m_rootFile->Get("Material/convertedBiasSubtracted_ConfigCpDp") ));
+    m_matConvertedScale.back()->SetDirectory(nullptr);
+    m_matConvertedScale.emplace_back(std::unique_ptr<TH1>(  (TH1*) m_rootFile->Get("Material/convertedBiasSubtracted_ConfigEpLp") ));
+    m_matConvertedScale.back()->SetDirectory(nullptr);
+    m_matConvertedScale.emplace_back(std::unique_ptr<TH1>(  (TH1*) m_rootFile->Get("Material/convertedBiasSubtracted_ConfigFpMX") ));
+    m_matConvertedScale.back()->SetDirectory(nullptr);
+    m_matConvertedScale.emplace_back(std::unique_ptr<TH1>(  (TH1*) m_rootFile->Get("Material/convertedBiasSubtracted_ConfigGp") ));
+    m_matConvertedScale.back()->SetDirectory(nullptr);
+
+    m_matElectronCstTerm.emplace_back(std::unique_ptr<TH1>(  (TH1*) m_rootFile->Get("Material/electronCstTerm_ConfigA") ));
+    m_matElectronCstTerm.back()->SetDirectory(nullptr);
+    m_matElectronCstTerm.emplace_back(std::unique_ptr<TH1>(  (TH1*) m_rootFile->Get("Material/electronCstTerm_ConfigCpDp") ));
+    m_matElectronCstTerm.back()->SetDirectory(nullptr);
+    m_matElectronCstTerm.emplace_back(std::unique_ptr<TH1>(  (TH1*) m_rootFile->Get("Material/electronCstTerm_ConfigEpLp") ));
+    m_matElectronCstTerm.back()->SetDirectory(nullptr);
+    m_matElectronCstTerm.emplace_back(std::unique_ptr<TH1>(  (TH1*) m_rootFile->Get("Material/electronCstTerm_ConfigFpMX") ));
+    m_matElectronCstTerm.back()->SetDirectory(nullptr);
+    m_matElectronCstTerm.emplace_back(std::unique_ptr<TH1>(  (TH1*) m_rootFile->Get("Material/electronCstTerm_ConfigGp") ));
+    m_matElectronCstTerm.back()->SetDirectory(nullptr);
+
+    if (m_esmodel==egEnergyCorr::es2017_R21_v1 || m_esmodel==egEnergyCorr::es2017_R21_ofc0_v1 || m_esmodel == egEnergyCorr::es2018_R21_v0 || m_esmodel == egEnergyCorr::es2018_R21_v1) {
+     // update dX0 plots for distorted geometry for case A, EL, FMX and N
+      m_matX0Additions.emplace_back(std::unique_ptr<TH1>(  (TH1*) m_rootFile->Get("Material_rel21/DX0_ConfigA") ));
+      m_matX0Additions.back()->SetDirectory(nullptr);
+      m_matX0Additions.emplace_back(std::unique_ptr<TH1>(  (TH1*) m_rootFile->Get("Material/DX0_ConfigCpDp") ));
+      m_matX0Additions.back()->SetDirectory(nullptr);
+      m_matX0Additions.emplace_back(std::unique_ptr<TH1>(  (TH1*) m_rootFile->Get("Material_rel21/DX0_ConfigEpLp") ));
+      m_matX0Additions.back()->SetDirectory(nullptr);
+      m_matX0Additions.emplace_back(std::unique_ptr<TH1>(  (TH1*) m_rootFile->Get("Material_rel21/DX0_ConfigFpMX") ));
+      m_matX0Additions.back()->SetDirectory(nullptr);
+      m_matX0Additions.emplace_back(std::unique_ptr<TH1>(  (TH1*) m_rootFile->Get("Material/DX0_ConfigGp") ));
+      m_matX0Additions.back()->SetDirectory(nullptr);
+      m_matX0Additions.emplace_back(std::unique_ptr<TH1>(  (TH1*) m_rootFile->Get("Material_rel21/DX0_ConfigN") ));
+      m_matX0Additions.back()->SetDirectory(nullptr);
+    }
+    else {
+      m_matX0Additions.emplace_back(std::unique_ptr<TH1>(  (TH1*) m_rootFile->Get("Material/DX0_ConfigA") ));
+      m_matX0Additions.back()->SetDirectory(nullptr);
+      m_matX0Additions.emplace_back(std::unique_ptr<TH1>(  (TH1*) m_rootFile->Get("Material/DX0_ConfigCpDp") ));
+      m_matX0Additions.back()->SetDirectory(nullptr);
+      m_matX0Additions.emplace_back(std::unique_ptr<TH1>(  (TH1*) m_rootFile->Get("Material/DX0_ConfigEpLp") ));
+      m_matX0Additions.back()->SetDirectory(nullptr);
+      m_matX0Additions.emplace_back(std::unique_ptr<TH1>(  (TH1*) m_rootFile->Get("Material/DX0_ConfigFpMX") ));
+      m_matX0Additions.back()->SetDirectory(nullptr);
+      m_matX0Additions.emplace_back(std::unique_ptr<TH1>(  (TH1*) m_rootFile->Get("Material/DX0_ConfigGp") ));
+      m_matX0Additions.back()->SetDirectory(nullptr);
+    }
+
+
+    m_matElectronEtaBins.reset( dynamic_cast<TAxis*>(m_rootFile->Get("Material/LinearityEtaBins")));
+    m_matElectronGraphs.emplace_back( std::unique_ptr<TList>( (TList*) m_rootFile->Get("Material/Linearity_Cluster_ConfigA")) );
+    m_matElectronGraphs.emplace_back( std::unique_ptr<TList>( (TList*) m_rootFile->Get("Material/Linearity_Cluster_ConfigCpDp")) );
+    m_matElectronGraphs.emplace_back( std::unique_ptr<TList>( (TList*) m_rootFile->Get("Material/Linearity_Cluster_ConfigEpLp")) );
+    m_matElectronGraphs.emplace_back( std::unique_ptr<TList>( (TList*) m_rootFile->Get("Material/Linearity_Cluster_ConfigFpMX")) );
+    m_matElectronGraphs.emplace_back( std::unique_ptr<TList>( (TList*) m_rootFile->Get("Material/Linearity_Cluster_ConfigGp")) );
+
+
+    for (auto &mat: m_matElectronGraphs) {
+      mat->SetOwner();
+    }
+
+
+    // ... new material distortions from release 21 parameterizations
+
+    if (m_esmodel==egEnergyCorr::es2017_R21_v1 || m_esmodel==egEnergyCorr::es2017_R21_ofc0_v1 || m_esmodel == egEnergyCorr::es2018_R21_v0 || m_esmodel == egEnergyCorr::es2018_R21_v1) {
+      m_electronBias_ConfigA.reset( dynamic_cast< TH2* >( m_rootFile->Get("Material_rel21/electronBias_ConfigA")));            m_electronBias_ConfigA->SetDirectory(nullptr);
+      m_electronBias_ConfigEpLp.reset( dynamic_cast< TH2* >( m_rootFile->Get("Material_rel21/electronBias_ConfigEpLp")));      m_electronBias_ConfigEpLp->SetDirectory(nullptr);
+      m_electronBias_ConfigFpMX.reset( dynamic_cast< TH2* >( m_rootFile->Get("Material_rel21/electronBias_ConfigFpMX")));      m_electronBias_ConfigFpMX->SetDirectory(nullptr);
+      m_electronBias_ConfigN.reset( dynamic_cast< TH2* >( m_rootFile->Get("Material_rel21/electronBias_ConfigN")));            m_electronBias_ConfigN->SetDirectory(nullptr);
+      m_electronBias_ConfigIBL.reset( dynamic_cast< TH2* >( m_rootFile->Get("Material_rel21/electronBias_ConfigIBL")));        m_electronBias_ConfigIBL->SetDirectory(nullptr);
+      m_electronBias_ConfigPP0.reset( dynamic_cast< TH2* >( m_rootFile->Get("Material_rel21/electronBias_ConfigPP0")));        m_electronBias_ConfigPP0->SetDirectory(nullptr);
+      m_unconvertedBias_ConfigA.reset( dynamic_cast< TH2* >( m_rootFile->Get("Material_rel21/unconvertedBias_ConfigA")));      m_unconvertedBias_ConfigA->SetDirectory(nullptr);
+      m_unconvertedBias_ConfigEpLp.reset( dynamic_cast< TH2* >( m_rootFile->Get("Material_rel21/unconvertedBias_ConfigEpLp"))); m_unconvertedBias_ConfigEpLp->SetDirectory(nullptr);
+      m_unconvertedBias_ConfigFpMX.reset( dynamic_cast< TH2* >( m_rootFile->Get("Material_rel21/unconvertedBias_ConfigFpMX")));m_unconvertedBias_ConfigFpMX->SetDirectory(nullptr);
+      m_unconvertedBias_ConfigN.reset( dynamic_cast< TH2* >( m_rootFile->Get("Material_rel21/unconvertedBias_ConfigN")));      m_unconvertedBias_ConfigN->SetDirectory(nullptr);
+      m_unconvertedBias_ConfigIBL.reset( dynamic_cast< TH2* >( m_rootFile->Get("Material_rel21/unconvertedBias_ConfigIBL")));  m_unconvertedBias_ConfigIBL->SetDirectory(nullptr);
+      m_unconvertedBias_ConfigPP0.reset( dynamic_cast< TH2* >( m_rootFile->Get("Material_rel21/unconvertedBias_ConfigPP0")));  m_unconvertedBias_ConfigPP0->SetDirectory(nullptr);
+      m_convertedBias_ConfigA.reset( dynamic_cast< TH2* >( m_rootFile->Get("Material_rel21/convertedBias_ConfigA")));          m_convertedBias_ConfigA->SetDirectory(nullptr);
+      m_convertedBias_ConfigEpLp.reset( dynamic_cast< TH2* >( m_rootFile->Get("Material_rel21/convertedBias_ConfigEpLp")));    m_convertedBias_ConfigEpLp->SetDirectory(nullptr);
+      m_convertedBias_ConfigFpMX.reset( dynamic_cast< TH2* >( m_rootFile->Get("Material_rel21/convertedBias_ConfigFpMX")));    m_convertedBias_ConfigFpMX->SetDirectory(nullptr);
+      m_convertedBias_ConfigN.reset( dynamic_cast< TH2* >( m_rootFile->Get("Material_rel21/convertedBias_ConfigN")));          m_convertedBias_ConfigN->SetDirectory(nullptr);
+      m_convertedBias_ConfigIBL.reset( dynamic_cast< TH2* >( m_rootFile->Get("Material_rel21/convertedBias_ConfigIBL")));      m_convertedBias_ConfigIBL->SetDirectory(nullptr);
+      m_convertedBias_ConfigPP0.reset( dynamic_cast< TH2* >( m_rootFile->Get("Material_rel21/convertedBias_ConfigPP0")));      m_convertedBias_ConfigPP0->SetDirectory(nullptr);
+    }
+
+
 
     // ... Fastsim to Fullsim corrections
 
@@ -1082,34 +1153,46 @@ namespace AtlasRoot {
         m_esmodel == egEnergyCorr::es2015cPRE or m_esmodel == egEnergyCorr::es2015cPRE_res_improved or
         m_esmodel == egEnergyCorr::es2015c_summer or m_esmodel == egEnergyCorr::es2016PRE) {
 
-      m_G4OverAFII_electron = (TH1D*) m_rootFile->Get("FastSim/es2015/el_scale_full_fast_peak_gaussian"); m_G4OverAFII_electron->SetDirectory(0);
-      m_G4OverAFII_unconverted = (TH1D*) m_rootFile->Get("FastSim/es2015/ph_unconv_scale_full_fast_peak_gaussian"); m_G4OverAFII_unconverted->SetDirectory(0);
-      m_G4OverAFII_converted = (TH1D*) m_rootFile->Get("FastSim/es2015/ph_conv_scale_full_fast_peak_gaussian"); m_G4OverAFII_converted->SetDirectory(0);
+      m_G4OverAFII_electron.reset( dynamic_cast< TH1* >( m_rootFile->Get("FastSim/es2015/el_scale_full_fast_peak_gaussian"))); m_G4OverAFII_electron->SetDirectory(nullptr);
+      m_G4OverAFII_unconverted.reset( dynamic_cast< TH1* >( m_rootFile->Get("FastSim/es2015/ph_unconv_scale_full_fast_peak_gaussian"))); m_G4OverAFII_unconverted->SetDirectory(nullptr);
+      m_G4OverAFII_converted.reset( dynamic_cast< TH1* >( m_rootFile->Get("FastSim/es2015/ph_conv_scale_full_fast_peak_gaussian"))); m_G4OverAFII_converted->SetDirectory(nullptr);
+    }
+    else if (m_esmodel == egEnergyCorr::es2017 or m_esmodel == egEnergyCorr::es2017_summer
+             or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_summer_final
+             or m_esmodel == egEnergyCorr::es2017_R21_PRE or m_esmodel == egEnergyCorr::es2015_5TeV
+             or m_esmodel == egEnergyCorr::es2017_R21_v0) {
+      m_G4OverAFII_electron.reset( dynamic_cast< TH1* >( m_rootFile->Get("FastSim/es2017/el_scale_full_fast_peak_gaussian"))); m_G4OverAFII_electron->SetDirectory(nullptr);
+      m_G4OverAFII_unconverted.reset( dynamic_cast< TH1* >( m_rootFile->Get("FastSim/es2017/ph_unconv_scale_full_fast_peak_gaussian"))); m_G4OverAFII_unconverted->SetDirectory(nullptr);
+      m_G4OverAFII_converted.reset( dynamic_cast< TH1* >( m_rootFile->Get("FastSim/es2017/ph_conv_scale_full_fast_peak_gaussian"))); m_G4OverAFII_converted->SetDirectory(nullptr);
     }
-    else if (m_esmodel == egEnergyCorr::es2017 or m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_R21_PRE) {
-      m_G4OverAFII_electron = (TH1D*) m_rootFile->Get("FastSim/es2017/el_scale_full_fast_peak_gaussian"); m_G4OverAFII_electron->SetDirectory(0);
-      m_G4OverAFII_unconverted = (TH1D*) m_rootFile->Get("FastSim/es2017/ph_unconv_scale_full_fast_peak_gaussian"); m_G4OverAFII_unconverted->SetDirectory(0);
-      m_G4OverAFII_converted = (TH1D*) m_rootFile->Get("FastSim/es2017/ph_conv_scale_full_fast_peak_gaussian"); m_G4OverAFII_converted->SetDirectory(0);
+    else if (m_esmodel == egEnergyCorr::es2017_R21_v1 || m_esmodel == egEnergyCorr::es2017_R21_ofc0_v1 || m_esmodel == egEnergyCorr::es2018_R21_v0 || m_esmodel == egEnergyCorr::es2018_R21_v1) {
+      m_G4OverAFII_electron_2D.reset( dynamic_cast< TH2* >( m_rootFile->Get("FastSim/es2017_v1/scale_Af2ToG4_elec_rel21"))); m_G4OverAFII_electron_2D->SetDirectory(nullptr);
+      m_G4OverAFII_unconverted_2D.reset( dynamic_cast< TH2* >( m_rootFile->Get("FastSim/es2017_v1/scale_Af2ToG4_unco_rel21"))); m_G4OverAFII_unconverted_2D->SetDirectory(nullptr);
+      m_G4OverAFII_converted_2D.reset( dynamic_cast< TH2* >( m_rootFile->Get("FastSim/es2017_v1/scale_Af2ToG4_conv_rel21"))); m_G4OverAFII_converted_2D->SetDirectory(nullptr);
     }
     else { // run 1
-      m_G4OverAFII_electron = (TH1D*) m_rootFile->Get("FastSim/hG4OverAF");                 m_G4OverAFII_electron->SetDirectory(0);
+      m_G4OverAFII_electron.reset( dynamic_cast< TH1* >( m_rootFile->Get("FastSim/hG4OverAF")));                 m_G4OverAFII_electron->SetDirectory(nullptr);
     }
-    m_G4OverFrSh            = (TH1D*) m_rootFile->Get("FastSim/hG4OverFS");                 m_G4OverFrSh->SetDirectory(0);
+
+    m_G4OverFrSh.reset( dynamic_cast< TH1* >( m_rootFile->Get("FastSim/hG4OverFS")));                 m_G4OverFrSh->SetDirectory(nullptr);
 
     // ... Leakage systematics
-    
-    if(m_esmodel != egEnergyCorr::es2017_summer and m_esmodel != egEnergyCorr::es2017_summer_improved and m_esmodel != egEnergyCorr::es2017_R21_PRE){
-      m_leakageConverted      = (TH1D*) m_rootFile->Get("Leakage/LeakageDiffConverted");      m_leakageConverted->SetDirectory(0);
-      m_leakageUnconverted    = (TH1D*) m_rootFile->Get("Leakage/LeakageDiffUnconverted");    m_leakageUnconverted->SetDirectory(0);
+
+    if(m_esmodel != egEnergyCorr::es2017_summer and m_esmodel != egEnergyCorr::es2017_summer_improved
+       and m_esmodel != egEnergyCorr::es2017_summer_final and m_esmodel != egEnergyCorr::es2017_R21_PRE
+       and m_esmodel != egEnergyCorr::es2015_5TeV and m_esmodel != egEnergyCorr::es2017_R21_v0
+       and m_esmodel != egEnergyCorr::es2017_R21_v1 and m_esmodel != egEnergyCorr::es2017_R21_ofc0_v1 and m_esmodel != egEnergyCorr::es2018_R21_v0 and m_esmodel != egEnergyCorr::es2018_R21_v1){
+      m_leakageConverted.reset( dynamic_cast< TH1* >( m_rootFile->Get("Leakage/LeakageDiffConverted")));      m_leakageConverted->SetDirectory(nullptr);
+      m_leakageUnconverted.reset( dynamic_cast< TH1* >( m_rootFile->Get("Leakage/LeakageDiffUnconverted")));    m_leakageUnconverted->SetDirectory(nullptr);
     }
     else{
-      m_leakageConverted      = (TH1D*) m_rootFile->Get("Leakage/es2017_summer/LeakageDiffConverted");      m_leakageConverted->SetDirectory(0);
-      m_leakageUnconverted    = (TH1D*) m_rootFile->Get("Leakage/es2017_summer/LeakageDiffUnconverted");    m_leakageUnconverted->SetDirectory(0);
+      m_leakageConverted.reset( dynamic_cast< TH1* >( m_rootFile->Get("Leakage/es2017_summer/LeakageDiffConverted")));      m_leakageConverted->SetDirectory(nullptr);
+      m_leakageUnconverted.reset( dynamic_cast< TH1* >( m_rootFile->Get("Leakage/es2017_summer/LeakageDiffUnconverted")));    m_leakageUnconverted->SetDirectory(nullptr);
     }
-      
+
     // ... Zee S2 profile (needed for gain switch syst).
 
-    m_zeeES2Profile         = (TH1D*) m_rootFile->Get("ZeeEnergyProfiles/p2MC");    m_zeeES2Profile->SetDirectory(0);
+    m_zeeES2Profile.reset( dynamic_cast< TH1* >( m_rootFile->Get("ZeeEnergyProfiles/p2MC")));    m_zeeES2Profile->SetDirectory(nullptr);
 
     // OK, now we are all initialized and everything went fine
 
@@ -1167,7 +1250,7 @@ namespace AtlasRoot {
       fullyCorrectedEnergy = energy * this->applyFStoG4(cl_eta);
     else if ( dataType == PATCore::ParticleDataType::Fast ) // AtlFast2 sim
     {
-      fullyCorrectedEnergy = energy * this->applyAFtoG4(cl_eta, ptype);
+      fullyCorrectedEnergy = energy * this->applyAFtoG4(cl_eta, 0.001*energy/cosh(cl_eta),ptype);
     }
 
     // If nothing is to be done
@@ -1183,7 +1266,15 @@ namespace AtlasRoot {
 
       if( scaleVar == egEnergyCorr::Scale::Nominal ) {
         double alpha = getAlphaValue(runnumber, cl_eta, cl_etaCalo, fullyCorrectedEnergy, energyS2, eraw, ptype, scaleVar, varSF);
-        fullyCorrectedEnergy /= (1 + alpha);
+	fullyCorrectedEnergy /= (1 + alpha);
+        // apply additional k.E+b corrections if histograms exist (like in es2017_R21_v1)
+	if (m_zeeFwdk &&  m_zeeFwdb && fabs(cl_eta)>2.5){ //  calo eta?
+	  int ieta_k = m_zeeFwdk->GetXaxis()->FindBin(cl_eta);
+	  double value_k = m_zeeFwdk->GetBinContent(ieta_k);
+	  int ieta_b = m_zeeFwdb->GetXaxis()->FindBin(cl_eta);
+          double value_b = m_zeeFwdb->GetBinContent(ieta_b);
+	  fullyCorrectedEnergy = value_k*fullyCorrectedEnergy + value_b*GeV;   // value is stored in GeV in the histogram file
+	}
         ATH_MSG_DEBUG("after alpha = " << boost::format("%.2f") % fullyCorrectedEnergy);
       }
 
@@ -1198,6 +1289,23 @@ namespace AtlasRoot {
         ATH_MSG_DEBUG("after mc alpha = " << boost::format("%.2f") % fullyCorrectedEnergy);
       }
 
+       // AF2 systematics  (this will not be in the sum of all other NP in the 1 NP model)
+      if (dataType == PATCore::ParticleDataType::Fast && (m_esmodel== egEnergyCorr::es2017_R21_v0 || m_esmodel== egEnergyCorr::es2017_R21_v1 || m_esmodel== egEnergyCorr::es2017_R21_ofc0_v1 || m_esmodel == egEnergyCorr::es2018_R21_v0 || m_esmodel == egEnergyCorr::es2018_R21_v1) ) {
+        if (scaleVar==egEnergyCorr::Scale::af2Up or scaleVar==egEnergyCorr::Scale::af2Down) {
+           double daAF2=0.;
+           if (m_esmodel== egEnergyCorr::es2017_R21_v0) {
+              if (scaleVar==egEnergyCorr::Scale::af2Up) daAF2 = 0.005;
+              if (scaleVar==egEnergyCorr::Scale::af2Down) daAF2 = -0.005;
+           }
+           if (m_esmodel== egEnergyCorr::es2017_R21_v1 || m_esmodel== egEnergyCorr::es2017_R21_ofc0_v1 || m_esmodel == egEnergyCorr::es2018_R21_v0 || m_esmodel == egEnergyCorr::es2018_R21_v1) {
+              if (scaleVar==egEnergyCorr::Scale::af2Up) daAF2 = 0.001;
+              if (scaleVar==egEnergyCorr::Scale::af2Down) daAF2 = -0.001;
+           }
+           fullyCorrectedEnergy *= ( 1 + daAF2);
+        }
+      }
+
+
       // Do the resolution correction
       if ( resVar != egEnergyCorr::Resolution::None )
       fullyCorrectedEnergy *= getSmearingCorrection(cl_eta, cl_etaCalo, fullyCorrectedEnergy, ptype, dataType, resVar, resType);
@@ -1241,7 +1349,7 @@ namespace AtlasRoot {
 
     double daE4 = 0., linE4 = 0.;
     // E4 contribution
-    if ((m_esmodel == egEnergyCorr::es2015c_summer or m_esmodel == egEnergyCorr::es2016PRE or m_esmodel == egEnergyCorr::es2017 or m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_R21_PRE) and
+    if ((m_esmodel == egEnergyCorr::es2015c_summer or m_esmodel == egEnergyCorr::es2016PRE or m_esmodel == egEnergyCorr::es2017 or m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_summer_final or m_esmodel == egEnergyCorr::es2017_R21_PRE or m_esmodel == egEnergyCorr::es2015_5TeV or m_esmodel == egEnergyCorr::es2017_R21_v0 or m_esmodel == egEnergyCorr::es2017_R21_v1 or m_esmodel == egEnergyCorr::es2017_R21_ofc0_v1 or m_esmodel == egEnergyCorr::es2018_R21_v0 or m_esmodel == egEnergyCorr::es2018_R21_v1) and
         (var == egEnergyCorr::Scale::E4ScintillatorUp or var == egEnergyCorr::Scale::E4ScintillatorDown))
     {
       daE4 = getE4Uncertainty(cl_eta);
@@ -1251,7 +1359,7 @@ namespace AtlasRoot {
 
     //wtots1 contribution
     double daWtots1 = 0.;
-    if ((m_esmodel==egEnergyCorr::es2017 or m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_R21_PRE) and (var == egEnergyCorr::Scale::Wtots1Up or var == egEnergyCorr::Scale::Wtots1Down)){
+    if ((m_esmodel==egEnergyCorr::es2017 or m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_summer_final or m_esmodel == egEnergyCorr::es2017_R21_PRE or m_esmodel == egEnergyCorr::es2015_5TeV or m_esmodel == egEnergyCorr::es2017_R21_v0 or m_esmodel == egEnergyCorr::es2017_R21_v1 or m_esmodel == egEnergyCorr::es2017_R21_ofc0_v1 or m_esmodel == egEnergyCorr::es2018_R21_v0 or  m_esmodel == egEnergyCorr::es2018_R21_v1) and (var == egEnergyCorr::Scale::Wtots1Up or var == egEnergyCorr::Scale::Wtots1Down)){
       daWtots1 = getWtots1Uncertainty(cl_eta, energy, ptype);
       if(var == egEnergyCorr::Scale::Wtots1Down)
 	daWtots1 = -daWtots1;
@@ -1260,6 +1368,7 @@ namespace AtlasRoot {
     // ... Presampler contribution
 
     if( var==egEnergyCorr::Scale::PSUp || var==egEnergyCorr::Scale::PSDown ||
+	var==egEnergyCorr::Scale::PSb12Up || var==egEnergyCorr::Scale::PSb12Down ||
 	var==egEnergyCorr::Scale::LArElecUnconvUp || var==egEnergyCorr::Scale::LArElecUnconvDown ) {
 
       daPS  = getLayerUncertainty(  0, cl_eta, var, varSF );
@@ -1284,7 +1393,10 @@ namespace AtlasRoot {
     double daMatID, daMatCryo, daMatCalo;
     daMatID = daMatCryo = daMatCalo = 0;
 
-    if( ptype!=PATCore::ParticleType::Electron ) {
+    // for release 21 sensitivity use the same getMaterialNonLinearity for all particles
+    // while in sensitivities derived from run 1 this is only used for electrons
+
+    if( ptype!=PATCore::ParticleType::Electron  && (m_esmodel != egEnergyCorr::es2017_R21_v1 && m_esmodel != egEnergyCorr::es2017_R21_ofc0_v1 &&  m_esmodel != egEnergyCorr::es2018_R21_v0 && m_esmodel != egEnergyCorr::es2018_R21_v1) ) {
 
       daMatID   = getAlphaMaterial( cl_eta, egEnergyCorr::MatID,   ptype, var, varSF );
       daMatCryo = getAlphaMaterial( cl_eta, egEnergyCorr::MatCryo, ptype, var, varSF );
@@ -1293,11 +1405,11 @@ namespace AtlasRoot {
     } else {
 
       daMatID   = getMaterialNonLinearity( cl_eta, energy, egEnergyCorr::MatID,   ptype, var, varSF )
-	- getMaterialNonLinearity( cl_eta, meanE,  egEnergyCorr::MatID,   ptype, var, varSF );
+	- getMaterialNonLinearity( cl_eta, meanE,  egEnergyCorr::MatID,   PATCore::ParticleType::Electron, var, varSF );
       daMatCryo = getMaterialNonLinearity( cl_eta, energy, egEnergyCorr::MatCryo, ptype, var, varSF )
-	- getMaterialNonLinearity( cl_eta, meanE,  egEnergyCorr::MatCryo, ptype, var, varSF );
+	- getMaterialNonLinearity( cl_eta, meanE,  egEnergyCorr::MatCryo, PATCore::ParticleType::Electron, var, varSF );
       daMatCalo = getMaterialNonLinearity( cl_eta, energy, egEnergyCorr::MatCalo, ptype, var, varSF )
-	- getMaterialNonLinearity( cl_eta, meanE,  egEnergyCorr::MatCalo, ptype, var, varSF );
+	- getMaterialNonLinearity( cl_eta, meanE,  egEnergyCorr::MatCalo, PATCore::ParticleType::Electron, var, varSF );
 
     }
 
@@ -1368,26 +1480,54 @@ namespace AtlasRoot {
     double dapp0 = 0.;
     // values from the histogram already are 0 for the Z->ee electrons
     if (var == egEnergyCorr::Scale::MatPP0Up or var == egEnergyCorr::Scale::MatPP0Down) {
-      decltype(m_pp0_conv) histo = nullptr;
-      if (ptype == PATCore::ParticleType::Electron) histo = m_pp0_elec;
-      else if (ptype == PATCore::ParticleType::ConvertedPhoton) histo = m_pp0_conv;
-      else if (ptype == PATCore::ParticleType::UnconvertedPhoton) histo = m_pp0_unconv;
 
-      if (histo) {
-        const double aeta = std::abs(cl_eta);
-        dapp0 = getValueHistAt(*histo, aeta, energy / GeV / cosh(cl_eta), false, true, false, true);
-        if (var == egEnergyCorr::Scale::MatPP0Down) { dapp0 = -dapp0; }
+// new parameterization for release 21 reconstruction with mc16 geometries + distortions
+      if (m_esmodel == egEnergyCorr::es2017_R21_v1 || m_esmodel == egEnergyCorr::es2017_R21_ofc0_v1 || m_esmodel == egEnergyCorr::es2018_R21_v0 ||  m_esmodel == egEnergyCorr::es2018_R21_v1) {
+
+          if (fabs(cl_eta)<1.5)
+           dapp0 = getMaterialEffect(egEnergyCorr::ConfigIBL,ptype ,cl_eta,energy / GeV / cosh(cl_eta))
+                  -getMaterialEffect(egEnergyCorr::ConfigIBL,PATCore::ParticleType::Electron, cl_eta,getZeeMeanET(cl_eta)/GeV);
+          else
+           dapp0 = getMaterialEffect(egEnergyCorr::ConfigPP0,ptype ,cl_eta,energy / GeV / cosh(cl_eta))
+                  -getMaterialEffect(egEnergyCorr::ConfigPP0,PATCore::ParticleType::Electron, cl_eta,getZeeMeanET(cl_eta)/GeV);
 
-        // normalize to pp0 systematics
-        if (aeta > 1.5 and aeta < 2.0) { dapp0 *= 2.6; }
-        else if (aeta >= 2.0 and aeta <= 2.5) { dapp0 *= 2.3; }
+          if (var == egEnergyCorr::Scale::MatPP0Down) { dapp0 = -dapp0; }
       }
+
+      // release 20 run 2 systematics for mc15 like geometries
+      else {
+        //Just pick the owned one from a unique_ptr per case
+        TH2* histo = nullptr;
+        if (ptype == PATCore::ParticleType::Electron && m_pp0_elec) histo = dynamic_cast<TH2*>(m_pp0_elec.get());
+        else if (ptype == PATCore::ParticleType::ConvertedPhoton && m_pp0_conv ) histo = dynamic_cast<TH2*>(m_pp0_conv.get());
+        else if (ptype == PATCore::ParticleType::UnconvertedPhoton && m_pp0_unconv) histo = dynamic_cast<TH2*>(m_pp0_unconv.get());
+
+        if (histo) {
+          const double aeta = std::abs(cl_eta);
+          dapp0 = getValueHistAt(*histo, aeta, energy / GeV / cosh(cl_eta), false, true, false, true);
+          if (var == egEnergyCorr::Scale::MatPP0Down) { dapp0 = -dapp0; }
+
+          // normalize to pp0 systematics
+          if (aeta > 1.5 and aeta < 2.0) { dapp0 *= 2.6; }
+          else if (aeta >= 2.0 and aeta <= 2.5) { dapp0 *= 2.3; }
+        }
+     }
     }
 
     // Conversion systematics
 
     double daConvSyst = getAlphaConvSyst(cl_eta, energy, ptype, var, varSF);
 
+    // topo cluster threshold systematics for release 21
+    double daTopoCluster=0;
+    if ((var==egEnergyCorr::Scale::topoClusterThresUp || var==egEnergyCorr::Scale::topoClusterThresDown) && (m_esmodel== egEnergyCorr::es2017_R21_v0 || m_esmodel== egEnergyCorr::es2017_R21_v1 || m_esmodel== egEnergyCorr::es2017_R21_ofc0_v1 || m_esmodel == egEnergyCorr::es2018_R21_v0 || m_esmodel == egEnergyCorr::es2018_R21_v1)) {
+       double Et = energy/cosh(cl_eta);
+       double Et0=10000.;
+       //  Effect taken as 10**-3/(Et/10GeV) - order of magniture from https://indico.cern.ch/event/669895/contributions/2745266/attachments/1535612/2405452/slides.pdf
+       if (var==egEnergyCorr::Scale::topoClusterThresUp)      daTopoCluster = 1e-3*(1./(Et/Et0)-1./(getZeeMeanET(cl_eta)/Et0));
+       if (var==egEnergyCorr::Scale::topoClusterThresUp)      daTopoCluster = -1e-3*(1./(Et/Et0)-1./(getZeeMeanET(cl_eta)/Et0));
+    }
+
     // Total
 
     double alphaTot = alphaZee;
@@ -1402,6 +1542,7 @@ namespace AtlasRoot {
     alphaTot += daPedestal;
     alphaTot += daWtots1;
     alphaTot += dapp0;
+    alphaTot += daTopoCluster;
 
     ATH_MSG_DEBUG("alpha value for " << variationName(var) << " = " << alphaTot);
 
@@ -1637,8 +1778,9 @@ namespace AtlasRoot {
 
   // get fractional uncertainty on resolution
 
-  double egammaEnergyCorrectionTool::getResolutionError(double energy, double eta, double etaCalo, PATCore::ParticleType::Type ptype,egEnergyCorr::Resolution::Variation value,
-                                                        egEnergyCorr::Resolution::resolutionType resType ) const
+  double egammaEnergyCorrectionTool::getResolutionError(PATCore::ParticleDataType::DataType dataType,double energy, double eta, double etaCalo,
+                                                        PATCore::ParticleType::Type ptype,egEnergyCorr::Resolution::Variation value,
+                                                       egEnergyCorr::Resolution::resolutionType resType) const
 
   {
 
@@ -1654,24 +1796,8 @@ namespace AtlasRoot {
 
     int isys=0;
     if (value==egEnergyCorr::Resolution::AllUp || value==egEnergyCorr::Resolution::AllDown) {
-      // old code, seems to do a linear sum, Guillaume email 1 Jul 2016
       isys=0xFFFF;
-      /*const std::vector<egEnergyCorr::Resolution::Variation> list_up = { egEnergyCorr::Resolution::ZSmearingUp, egEnergyCorr::Resolution::SamplingTermUp,
-                                                                    egEnergyCorr::Resolution::MaterialIDUp, egEnergyCorr::Resolution::MaterialCaloUp,
-                                                                    egEnergyCorr::Resolution::MaterialGapUp, egEnergyCorr::Resolution::MaterialCryoUp,
-                                                                    egEnergyCorr::Resolution::PileUpUp };
-      const std::vector<egEnergyCorr::Resolution::Variation> list_down = { egEnergyCorr::Resolution::ZSmearingDown, egEnergyCorr::Resolution::SamplingTermDown,
-                                                                    egEnergyCorr::Resolution::MaterialIDDown, egEnergyCorr::Resolution::MaterialCaloDown,
-                                                                    egEnergyCorr::Resolution::MaterialGapDown, egEnergyCorr::Resolution::MaterialCryoDown,
-                                                                    egEnergyCorr::Resolution::PileUpDown };
-      const std::vector<egEnergyCorr::Resolution::Variation> list_sys_loop = value == egEnergyCorr::Resolution::AllUp ? list_up : list_down;
-      double acc_sys = 0.;
-      for (const auto var : list_sys_loop) {
-        acc_sys += std::pow(getResolutionError(energy, eta, etaCalo, ptype, var, resType), 2);
-      }
-      acc_sys = std::sqrt(acc_sys);
-      if (value == egEnergyCorr::Resolution::AllDown) return -acc_sys;
-      else return acc_sys;*/
+
     }
     if (value==egEnergyCorr::Resolution::ZSmearingUp || value==egEnergyCorr::Resolution::ZSmearingDown) {
       isys=0x1;
@@ -1701,20 +1827,26 @@ namespace AtlasRoot {
     if (value==egEnergyCorr::Resolution::MaterialPP0Up || value==egEnergyCorr::Resolution::MaterialPP0Down) {
       isys=0x100;
     }
+    if (value==egEnergyCorr::Resolution::af2Up || value==egEnergyCorr::Resolution::af2Down) {
+      isys=0x200;
+    }
 
     double sign = 1.;
     if (value==egEnergyCorr::Resolution::AllDown ||  value==egEnergyCorr::Resolution::ZSmearingDown ||
         value==egEnergyCorr::Resolution::SamplingTermDown ||  value==egEnergyCorr::Resolution::MaterialIDDown ||
         value==egEnergyCorr::Resolution::MaterialGapDown || value==egEnergyCorr::Resolution::MaterialCaloDown ||
         value==egEnergyCorr::Resolution::MaterialCryoDown || value==egEnergyCorr::Resolution::PileUpDown ||
-	value==egEnergyCorr::Resolution::MaterialIBLDown || value==egEnergyCorr::Resolution::MaterialPP0Down) sign=-1.;
+	value==egEnergyCorr::Resolution::MaterialIBLDown || value==egEnergyCorr::Resolution::MaterialPP0Down ||
+        value==egEnergyCorr::Resolution::af2Down) sign=-1.;
 
     double resolution;
     double resolution_error;
     double resolution_error_up;
     double resolution_error_down;
 
-    getResolution_systematics(eg_resolution_ptype, energy,  eta, etaCalo, isys,  resolution, resolution_error, resolution_error_up, resolution_error_down, resType);
+
+    getResolution_systematics(eg_resolution_ptype, energy,  eta, etaCalo, isys,  resolution, resolution_error, resolution_error_up, resolution_error_down, resType,
+          dataType == PATCore::ParticleDataType::Fast);
 
     // total resolution uncertainty
     if (value==egEnergyCorr::Resolution::AllUp || value==egEnergyCorr::Resolution::AllDown) {
@@ -1784,7 +1916,7 @@ namespace AtlasRoot {
     if (m_use_new_resolution_model) {
       sig2 = pow(m_resolution_tool->getResolution(eg_resolution_ptype, energy, cl_eta, resType), 2);
       const double et = energy / cosh(cl_eta);
-      sig2 += pow(pileUpTerm(cl_eta, eg_resolution_ptype) / et, 2);  // TODO: why et and not E?
+      sig2 += pow(pileUpTerm(energy, cl_eta, eg_resolution_ptype) / et, 2);  // TODO: why et and not E?
     } else { // OLD model
 
       double energyGeV = energy/GeV;
@@ -1801,16 +1933,27 @@ namespace AtlasRoot {
     }
 
     if (fast and std::abs(cl_eta) < 2.5) {
-      if (m_esmodel == egEnergyCorr::es2017 or m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_R21_PRE or m_esmodel == egEnergyCorr::es2015PRE or m_esmodel == egEnergyCorr::es2015PRE_res_improved or m_esmodel == egEnergyCorr::es2015cPRE or m_esmodel == egEnergyCorr::es2015cPRE_res_improved or m_esmodel == egEnergyCorr::es2015c_summer or m_esmodel == egEnergyCorr::es2016PRE) {
+      if (m_esmodel == egEnergyCorr::es2017 or m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_summer_final or m_esmodel == egEnergyCorr::es2017_R21_PRE or m_esmodel == egEnergyCorr::es2015_5TeV or m_esmodel == egEnergyCorr::es2015PRE or m_esmodel == egEnergyCorr::es2015PRE_res_improved or m_esmodel == egEnergyCorr::es2015cPRE or m_esmodel == egEnergyCorr::es2015cPRE_res_improved or m_esmodel == egEnergyCorr::es2015c_summer or m_esmodel == egEnergyCorr::es2016PRE or m_esmodel == egEnergyCorr::es2017_R21_v0 or m_esmodel == egEnergyCorr::es2017_R21_v1 or m_esmodel == egEnergyCorr::es2017_R21_ofc0_v1 or m_esmodel == egEnergyCorr::es2018_R21_v0 or m_esmodel == egEnergyCorr::es2018_R21_v1) {
 
         double ratio_IQR_full_fast = 1.;
         const double ptGeV = energy / cosh(cl_eta) / 1E3;
 
-        if (ptype == PATCore::ParticleType::Electron) { ratio_IQR_full_fast = getValueHistAt(*m_G4OverAFII_resolution_electron, ptGeV, cl_eta, true, false); }
-        else if (ptype == PATCore::ParticleType::UnconvertedPhoton) { ratio_IQR_full_fast = getValueHistAt(*m_G4OverAFII_resolution_unconverted, ptGeV, cl_eta, true, false); }
-        else if (ptype == PATCore::ParticleType::ConvertedPhoton) {  ratio_IQR_full_fast = getValueHistAt(*m_G4OverAFII_resolution_converted, ptGeV, cl_eta, true, false); }
+        if  ( m_esmodel == egEnergyCorr::es2017_R21_v1 || m_esmodel == egEnergyCorr::es2017_R21_ofc0_v1 || m_esmodel == egEnergyCorr::es2018_R21_v0 || m_esmodel == egEnergyCorr::es2018_R21_v1) {
+//
+// for es2017_R21_v1, histograms contain directly values of deltaSigma**2 of relative energy resolution (FastSIm-FulSim) so need to subtract this value to get the sigma**2 of FastSim
 
-        sig2 /= ratio_IQR_full_fast * ratio_IQR_full_fast;
+           if(ptype == PATCore::ParticleType::Electron) sig2 -=   getValueHistAt(*m_G4OverAFII_resolution_electron,cl_eta,ptGeV,true,true,true,true);
+           if (ptype == PATCore::ParticleType::UnconvertedPhoton) sig2 -=   getValueHistAt(*m_G4OverAFII_resolution_unconverted,cl_eta,ptGeV,true,true,true,true);
+           if (ptype == PATCore::ParticleType::ConvertedPhoton) sig2 -=   getValueHistAt(*m_G4OverAFII_resolution_converted,cl_eta,ptGeV,true,true,true,true);
+           if (sig2<0.) sig2=0.;
+        }
+        else {
+          if (ptype == PATCore::ParticleType::Electron) { ratio_IQR_full_fast = getValueHistAt(*m_G4OverAFII_resolution_electron, ptGeV, cl_eta, true, false); }
+          else if (ptype == PATCore::ParticleType::UnconvertedPhoton) { ratio_IQR_full_fast = getValueHistAt(*m_G4OverAFII_resolution_unconverted, ptGeV, cl_eta, true, false); }
+          else if (ptype == PATCore::ParticleType::ConvertedPhoton) {  ratio_IQR_full_fast = getValueHistAt(*m_G4OverAFII_resolution_converted, ptGeV, cl_eta, true, false); }
+
+          sig2 /= ratio_IQR_full_fast * ratio_IQR_full_fast;
+        }
       }
     }
 
@@ -1859,7 +2002,7 @@ namespace AtlasRoot {
     ATH_MSG_DEBUG("resolution in data: " << resData << " in MC: " << resMC);
 
     if (m_use_new_resolution_model) {
-      resData *= 1 + getResolutionError(energy, cl_eta, cl_etaCalo, ptype, value, resType);
+      resData *= 1 + getResolutionError(dataType,energy, cl_eta, cl_etaCalo, ptype, value, resType);
     } else { // OLD model
       double errUp, errDown;
       resolutionError( energyGeV, cl_eta, errUp, errDown );
@@ -1874,6 +2017,7 @@ namespace AtlasRoot {
     ATH_MSG_DEBUG("resolution in data after systematics: " << resData);
 
     const double sigma2 = std::pow(resData * energyGeV, 2 ) - std::pow(resMC * energyGeV, 2);
+
     // TODO: for nominal case it can be simplified to:
     // const double sigma = dataConstantTerm(m_use_etaCalo_scales ? cl_etaCalo : cl_eta) * energyGeV;
     // which is just the additional constant term
@@ -1930,7 +2074,7 @@ namespace AtlasRoot {
 
   // AF -> G4 correction
 
-  double egammaEnergyCorrectionTool::applyAFtoG4(double eta,
+  double egammaEnergyCorrectionTool::applyAFtoG4(double eta, double ptGeV,
 						 PATCore::ParticleType::Type ptype) const {
     const double aeta = fabs(eta);
     if (aeta > 2.47) return 1.;
@@ -1938,11 +2082,24 @@ namespace AtlasRoot {
     if (m_esmodel == egEnergyCorr::es2015PRE or m_esmodel == egEnergyCorr::es2015PRE_res_improved or
         m_esmodel == egEnergyCorr::es2015cPRE or m_esmodel == egEnergyCorr::es2015cPRE_res_improved or
         m_esmodel == egEnergyCorr::es2015c_summer or m_esmodel == egEnergyCorr::es2016PRE or m_esmodel == egEnergyCorr::es2017
-	or m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_R21_PRE) {
-      if (ptype == PATCore::ParticleType::Electron) { return getValueHistoAt(*m_G4OverAFII_electron, eta); }
-      else if (ptype == PATCore::ParticleType::ConvertedPhoton) { return getValueHistoAt(*m_G4OverAFII_converted, eta); }
-      else if (ptype == PATCore::ParticleType::UnconvertedPhoton) { return getValueHistoAt(*m_G4OverAFII_unconverted, eta); }
-      else { throw std::runtime_error("particle not valid"); }
+	or m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_summer_final
+	or m_esmodel == egEnergyCorr::es2017_R21_PRE or m_esmodel == egEnergyCorr::es2017_R21_v0 or m_esmodel == egEnergyCorr::es2017_R21_v1 or m_esmodel == egEnergyCorr::es2017_R21_ofc0_v1 or m_esmodel == egEnergyCorr::es2018_R21_v0 or m_esmodel == egEnergyCorr::es2018_R21_v1) {
+
+      if (m_esmodel == egEnergyCorr::es2017_R21_v1 || m_esmodel == egEnergyCorr::es2017_R21_ofc0_v1 || m_esmodel == egEnergyCorr::es2018_R21_v0 ||  m_esmodel == egEnergyCorr::es2018_R21_v1) {
+//
+// in es02017_R21_v1 : AF2 to FullSim correction is in a 2D eta-Pt histogram
+
+        if (ptype == PATCore::ParticleType::Electron) { return (1.+getValueHistAt(*m_G4OverAFII_electron_2D, aeta,ptGeV,true,true,true,true)); }
+        else if (ptype == PATCore::ParticleType::ConvertedPhoton) { return (1.+getValueHistAt(*m_G4OverAFII_converted_2D, aeta,ptGeV,true,true,true,true)); }
+        else if (ptype == PATCore::ParticleType::UnconvertedPhoton) { return (1.+getValueHistAt(*m_G4OverAFII_unconverted_2D, aeta,ptGeV,true,true,true,true)); }
+        else { throw std::runtime_error("particle not valid"); }
+      }
+      else {
+        if (ptype == PATCore::ParticleType::Electron) { return getValueHistoAt(*m_G4OverAFII_electron, aeta); }
+        else if (ptype == PATCore::ParticleType::ConvertedPhoton) { return getValueHistoAt(*m_G4OverAFII_converted, aeta); }
+        else if (ptype == PATCore::ParticleType::UnconvertedPhoton) { return getValueHistoAt(*m_G4OverAFII_unconverted, aeta); }
+        else { throw std::runtime_error("particle not valid"); }
+      }
     }
     else {
       // run 1
@@ -1975,7 +2132,39 @@ namespace AtlasRoot {
     int ieta = m_zeeNom->GetXaxis()->FindBin(eta);
     double value = m_zeeNom->GetBinContent(ieta);
 
-    if ((m_esmodel==egEnergyCorr::es2017 or m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved) && runnumber < 297000) {
+    // for es2018_R21_v0 and v1 different set of scales for 2018, 2017, 2016 and 2015 data
+    if ((m_esmodel == egEnergyCorr::es2018_R21_v0 || m_esmodel == egEnergyCorr::es2018_R21_v1)  && runnumber<=341649 && runnumber>=324320){
+      int ieta = m_zeeNom_data2017->GetXaxis()->FindBin(eta);
+      value = m_zeeNom_data2017->GetBinContent(ieta);
+    }
+
+     // for es2017_R21_v0 different set of scales for 2017, 2016 and 2015 data
+    if ( m_esmodel == egEnergyCorr::es2017_R21_v0 && runnumber<322817 && runnumber>=297000) {
+       int ieta = m_zeeNom_data2016->GetXaxis()->FindBin(eta);
+       value = m_zeeNom_data2016->GetBinContent(ieta);
+    }
+
+    if ( (m_esmodel == egEnergyCorr::es2017_R21_v1 || m_esmodel == egEnergyCorr::es2018_R21_v0 || m_esmodel == egEnergyCorr::es2018_R21_v1) && runnumber<322817 && runnumber>=297000) {
+      int ieta = m_zeeNom_data2016->GetXaxis()->FindBin(eta);
+      value = m_zeeNom_data2016->GetBinContent(ieta);
+    }
+
+    if (m_esmodel == egEnergyCorr::es2017_R21_ofc0_v1 && runnumber<322817 && runnumber>=297000) {
+      int ieta = m_zeeNom_data2016->GetXaxis()->FindBin(eta);
+      value = m_zeeNom_data2016->GetBinContent(ieta);
+    }
+
+    if (m_esmodel == egEnergyCorr::es2017_R21_ofc0_v1 && runnumber<297000) {
+       int ieta = m_zeeNom_data2015->GetXaxis()->FindBin(eta);
+       value = m_zeeNom_data2015->GetBinContent(ieta);
+    }
+
+    if (m_esmodel == egEnergyCorr::es2017_R21_ofc0_v1 && runnumber>347847) {
+        int ieta = m_zeeNom_data2018->GetXaxis()->FindBin(eta);
+        value = m_zeeNom_data2018->GetBinContent(ieta);
+    }
+
+    if ((m_esmodel==egEnergyCorr::es2017 or m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_summer_final or m_esmodel == egEnergyCorr::es2015_5TeV or m_esmodel == egEnergyCorr::es2017_R21_v0 or m_esmodel == egEnergyCorr::es2017_R21_v1 or m_esmodel == egEnergyCorr::es2018_R21_v0 or m_esmodel == egEnergyCorr::es2018_R21_v1) && runnumber < 297000) {
       // 2 sets of scales for this configuration
       // change histogram if 2015 data
       int ieta = m_zeeNom_data2015->GetXaxis()->FindBin(eta);
@@ -2035,20 +2224,37 @@ namespace AtlasRoot {
       }
     }
 
+
     if (var == egEnergyCorr::Scale::ZeeStatUp or var == egEnergyCorr::Scale::ZeeStatDown) {
       const double sign = (var == egEnergyCorr::Scale::ZeeStatUp) ? 1 : -1;
 
-      const TH1* h = m_zeeNom;
-      if ((m_esmodel == egEnergyCorr::es2017 or m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved) && runnumber < 297000) h = m_zeeNom_data2015; // special for 2015 with es2017
+      TH1* h= ((TH1*)m_zeeNom.get());
+
+      if ((m_esmodel == egEnergyCorr::es2017 or m_esmodel == egEnergyCorr::es2017_summer or
+           m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_summer_final or
+           m_esmodel == egEnergyCorr::es2015_5TeV or m_esmodel == egEnergyCorr::es2017_R21_v0 or
+           m_esmodel == egEnergyCorr::es2017_R21_v1 or m_esmodel == egEnergyCorr::es2017_R21_ofc0_v1 or m_esmodel == egEnergyCorr::es2018_R21_v0 or m_esmodel == egEnergyCorr::es2018_R21_v1) && runnumber < 297000){
+        h=((TH1*) m_zeeNom_data2015.get()); // special for 2015 with es2017
+      }
+      if ( (m_esmodel== egEnergyCorr::es2017_R21_v0 || m_esmodel== egEnergyCorr::es2017_R21_v1 ||
+            m_esmodel== egEnergyCorr::es2017_R21_ofc0_v1 || m_esmodel == egEnergyCorr::es2018_R21_v0 || m_esmodel == egEnergyCorr::es2018_R21_v1) && runnumber>=297000 && runnumber<322817){
+        h = m_zeeNom_data2016.get(); // 2016 data
+      }
+      if (  m_esmodel== egEnergyCorr::es2017_R21_ofc0_v1 && runnumber>347847) {
+        h = m_zeeNom_data2018.get();
+      }
+      if ( (m_esmodel == egEnergyCorr::es2018_R21_v0 || m_esmodel == egEnergyCorr::es2018_R21_v1) && runnumber>=324320 && runnumber<=341649 ){
+        h=((TH1*)m_zeeNom_data2017.get()); // 2017 data
+      }
       double stat_error = h->GetBinError(h->FindFixBin(eta));
 	    if (m_use_stat_error_scaling) {
         stat_error = stat_error / sqrt(h->GetNbinsX());
 	    }
 	    value += sign * stat_error * varSF;
-
     }
     else if( var==egEnergyCorr::Scale::ZeeSystUp && m_zeeSyst ) {
       value += get_ZeeSyst(eta) * varSF;
+
     } else if( var==egEnergyCorr::Scale::ZeeSystDown && m_zeeSyst ) {
       value -= get_ZeeSyst(eta) * varSF;
     } else if( var==egEnergyCorr::Scale::ZeePhysUp && m_zeePhys ) {
@@ -2105,7 +2311,7 @@ namespace AtlasRoot {
       double diff = pow(m_zeeNom->GetBinError(ieta) * varSF, 2);
 
       if( m_zeeSyst ) {
-        diff += pow(get_ZeeSyst(eta) * varSF, 2);
+	diff += pow(get_ZeeSyst(eta) * varSF, 2);
       }
 
       if( m_zeePhys ) {
@@ -2156,8 +2362,6 @@ namespace AtlasRoot {
     int bin = m_wstot_slope_A_data->FindFixBin(cl_eta);
     double A = m_wstot_slope_A_data->GetBinContent(bin);
     double B = m_wstot_slope_B_MC->GetBinContent(bin);
-    double wstot_40_data = m_wstot_40GeV_data->GetBinContent(bin);
-    double wstot_40_MC = m_wstot_40GeV_MC->GetBinContent(bin);
 
     //the wstot=f(pT) depends on the particle type
     double ETGeV = energy / cosh(cl_eta) / 1E3;
@@ -2166,6 +2370,9 @@ namespace AtlasRoot {
     double wstot_pT_MC_p0 = 0.;
     double wstot_pT_MC_p1 = 0.;
 
+    double wstot_40_data = m_wstot_pT_data_p0_electrons->GetBinContent(bin) + (m_wstot_pT_data_p1_electrons->GetBinContent(bin))/sqrt(40.);
+    double wstot_40_MC   = m_wstot_pT_MC_p0_electrons->GetBinContent(bin) + (m_wstot_pT_MC_p1_electrons->GetBinContent(bin))/sqrt(40.);
+
     if (ptype == PATCore::ParticleType::Electron ) {
       wstot_pT_data_p0 = m_wstot_pT_data_p0_electrons->GetBinContent(bin);
       wstot_pT_data_p1 = m_wstot_pT_data_p1_electrons->GetBinContent(bin);
@@ -2230,6 +2437,12 @@ namespace AtlasRoot {
       else if( var==egEnergyCorr::Scale::PSDown && m_aPSNom )
 	value = -m_aPSNom->GetBinError( m_aPSNom->FindBin(nearestEta) );
 
+      else if( var==egEnergyCorr::Scale::PSb12Up && m_daPSb12 )
+	value =  m_daPSb12->GetBinContent( m_daPSb12->FindBin(nearestEta) );
+
+      else if( var==egEnergyCorr::Scale::PSb12Down && m_daPSb12 )
+	value = -m_daPSb12->GetBinContent( m_daPSb12->FindBin(nearestEta) );
+
       else if( var==egEnergyCorr::Scale::LArElecUnconvUp && m_daPSCor )
 	value =  m_daPSCor->GetBinContent( m_daPSCor->FindBin(nearestEta) );
 
@@ -2244,20 +2457,21 @@ namespace AtlasRoot {
       else if (var == egEnergyCorr::Scale::S12Down && m_aS12Nom) { value = -m_aS12Nom->GetBinError(m_aS12Nom->FindBin(cl_eta)); }
       else if (var == egEnergyCorr::Scale::LArCalibUp && m_daS12Cor) { value = m_daS12Cor->GetBinContent(m_daS12Cor->FindBin(cl_eta)); }
       else if (var == egEnergyCorr::Scale::LArCalibDown && m_daS12Cor) { value = -m_daS12Cor->GetBinContent( m_daS12Cor->FindBin(cl_eta)); }
-      else if (var == egEnergyCorr::Scale::LArCalibExtra2015PreUp and 
+      else if (var == egEnergyCorr::Scale::LArCalibExtra2015PreUp and
 	       (m_esmodel == egEnergyCorr::es2015PRE or m_esmodel == egEnergyCorr::es2015PRE_res_improved or
 		m_esmodel == egEnergyCorr::es2015cPRE or m_esmodel == egEnergyCorr::es2015cPRE_res_improved or
 		m_esmodel == egEnergyCorr::es2015c_summer or m_esmodel == egEnergyCorr::es2016PRE or m_esmodel == egEnergyCorr::es2017
-		or m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_R21_PRE)) { 
+		or m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_R21_PRE
+		or m_esmodel == egEnergyCorr::es2015_5TeV)) {
 	// special case for es2015PRE and also for es2015c_summer and also for es2017
 	// numbers from Lydia and Christophe,
 	// https://indico.cern.ch/event/395345/contribution/2/material/slides/0.pdf
 	// assuming constant uncertainty
 	// es2017_summer: increased to 5% in the endcap
-	const double aeta = std::abs(cl_eta); 
+	const double aeta = std::abs(cl_eta);
 	//endcap
 	if ( aeta >= 1.37 and aeta < 2.5){
-	  if ( m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_R21_PRE) value = 5.0E-2;
+	  if ( m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_R21_PRE or m_esmodel == egEnergyCorr::es2015_5TeV) value = 5.0E-2;
 	  else value = 1.5E-2;
 	}
 	else{//barrel
@@ -2269,22 +2483,23 @@ namespace AtlasRoot {
                (m_esmodel == egEnergyCorr::es2015PRE or m_esmodel == egEnergyCorr::es2015PRE_res_improved or
                 m_esmodel == egEnergyCorr::es2015cPRE or m_esmodel == egEnergyCorr::es2015cPRE_res_improved or
                 m_esmodel == egEnergyCorr::es2015c_summer or m_esmodel == egEnergyCorr::es2016PRE or m_esmodel == egEnergyCorr::es2017
-		or m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_R21_PRE)) {
-	const double aeta = std::abs(cl_eta);  
-        //endcap 
-        if ( aeta >= 1.37 and aeta < 2.5){ 
-          if ( m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_R21_PRE) value = -5.0E-2; 
-          else value = -1.5E-2; 
-        } 
-        else{//barrel 
-          if (m_esmodel == egEnergyCorr::es2017_summer_improved) value = -2.5E-2; 
-          else value = -1.5E-2; 
-        } 
-      }
-      
+		or m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_R21_PRE
+		or m_esmodel == egEnergyCorr::es2015_5TeV)) {
+	const double aeta = std::abs(cl_eta);
+        //endcap
+        if ( aeta >= 1.37 and aeta < 2.5){
+          if ( m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_R21_PRE or m_esmodel == egEnergyCorr::es2015_5TeV) value = -5.0E-2;
+          else value = -1.5E-2;
+        }
+        else{//barrel
+          if (m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2015_5TeV) value = -2.5E-2;
+          else value = -1.5E-2;
+        }
+      }
+
       else if (var == egEnergyCorr::Scale::S12ExtraLastEtaBinRun2Up or var == egEnergyCorr::Scale::S12ExtraLastEtaBinRun2Down) {
         // special large sys for run2 in the last eta-bin in es2017, see ATLASEG-42
-        if (m_esmodel == egEnergyCorr::es2017 or m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_R21_PRE) {
+        if (m_esmodel == egEnergyCorr::es2017 or m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_R21_PRE or m_esmodel == egEnergyCorr::es2015_5TeV) {
 	  const double aeta = std::abs(cl_eta);
 	  if (aeta >= 2.4 and aeta < 2.5) {
 	    if (var == egEnergyCorr::Scale::S12ExtraLastEtaBinRun2Up) value = 25E-2;
@@ -2307,11 +2522,24 @@ namespace AtlasRoot {
     const double aeta = std::abs(cl_eta);
     const double ETGeV = energy / cosh(cl_eta) / 1E3;
 
-    TAxis* axis = nullptr;
-    TList* graphs = nullptr;
-    if (ptype == PATCore::ParticleType::Electron ) { axis = m_E4ElectronEtaBins; graphs = m_E4ElectronGraphs; }
-    else if (ptype == PATCore::ParticleType::UnconvertedPhoton) { axis = m_E4UnconvertedEtaBins; graphs = m_E4UnconvertedGraphs; }
-    else if (ptype == PATCore::ParticleType::ConvertedPhoton) { axis = m_E4ConvertedEtaBins; graphs = m_E4ConvertedGraphs; }
+    //This will point to the return of get() of a unique_ptr
+    TAxis* axis;
+    TList* graphs;
+
+    if (ptype == PATCore::ParticleType::Electron ) {
+      axis=(dynamic_cast<TAxis*>(m_E4ElectronEtaBins.get()));
+      graphs=(dynamic_cast<TList*>(m_E4ElectronGraphs.get()));
+      graphs->SetOwner();
+    } else if (ptype == PATCore::ParticleType::UnconvertedPhoton) {
+      axis=dynamic_cast<TAxis*>(m_E4UnconvertedEtaBins.get());
+      graphs=dynamic_cast<TList*>(m_E4UnconvertedGraphs.get());
+      graphs->SetOwner();
+    }
+    else if (ptype == PATCore::ParticleType::ConvertedPhoton) {
+      axis=dynamic_cast<TAxis*>(m_E4ConvertedEtaBins.get());
+      graphs=dynamic_cast<TList*>(m_E4ConvertedGraphs.get());
+      graphs->SetOwner();
+    }
     else { ATH_MSG_FATAL("invalid particle type"); return -1; }
 
 
@@ -2532,6 +2760,7 @@ namespace AtlasRoot {
 
     double DeltaX = getDeltaX(cl_eta, imat, var) - getDeltaX(cl_eta, imat, egEnergyCorr::Scale::Nominal);
 
+
     // calculate scale change per unit added material
 
     double DAlphaDXID, DAlphaDXCryo, DAlphaDXCalo, DAlphaDXGp;
@@ -2548,6 +2777,7 @@ namespace AtlasRoot {
       DAlphaDXCalo = m_matConvertedScale[geoCalo]->GetBinContent( m_matConvertedScale[geoCalo]->FindBin(cl_eta) );
     }
 
+
     // when in crack, use G', exit
 
     if( isInCrack(cl_eta) ) {
@@ -2580,6 +2810,7 @@ namespace AtlasRoot {
 
     // final value
 
+
     if( imat==egEnergyCorr::MatID )
       value = DeltaX * (DAlphaDXID - DAlphaDXCryo);
     else if( imat==egEnergyCorr::MatCryo )
@@ -2587,10 +2818,85 @@ namespace AtlasRoot {
     else if( imat==egEnergyCorr::MatCalo )
       value = DeltaX * DAlphaDXCalo;
 
+
     return value * varSF;
 
   }
 
+double egammaEnergyCorrectionTool::getMaterialEffect(egEnergyCorr::Geometry geo,PATCore::ParticleType::Type ptype,double cl_eta,double ET) const {
+
+  //Again this does no need to be ptr just get the one owned
+   TH2D* hmat;
+
+   if (ptype==PATCore::ParticleType::Electron) {
+      if (geo==egEnergyCorr::ConfigA) hmat=((TH2D*) m_electronBias_ConfigA.get());
+      else if (geo==egEnergyCorr::ConfigEL) hmat=((TH2D*)m_electronBias_ConfigEpLp.get());
+      else if (geo==egEnergyCorr::ConfigFMX) hmat=((TH2D*)m_electronBias_ConfigFpMX.get());
+      else if (geo==egEnergyCorr::ConfigN) hmat=((TH2D*)m_electronBias_ConfigN.get());
+      else if (geo==egEnergyCorr::ConfigIBL) hmat=((TH2D*)m_electronBias_ConfigIBL.get());
+      else if (geo==egEnergyCorr::ConfigPP0) hmat=((TH2D*)m_electronBias_ConfigPP0.get());
+      else return 0;
+   } else if (ptype==PATCore::ParticleType::UnconvertedPhoton) {
+      if (geo==egEnergyCorr::ConfigA) hmat=((TH2D*)m_unconvertedBias_ConfigA.get());
+      else if (geo==egEnergyCorr::ConfigEL) hmat=((TH2D*)m_unconvertedBias_ConfigEpLp.get());
+      else if (geo==egEnergyCorr::ConfigFMX) hmat=((TH2D*)m_unconvertedBias_ConfigFpMX.get());
+      else if (geo==egEnergyCorr::ConfigN) hmat=((TH2D*)m_unconvertedBias_ConfigN.get());
+      else if (geo==egEnergyCorr::ConfigIBL) hmat=((TH2D*)m_unconvertedBias_ConfigIBL.get());
+      else if (geo==egEnergyCorr::ConfigPP0) hmat=((TH2D*)m_unconvertedBias_ConfigIBL.get());
+      else return 0;
+   } else if (ptype==PATCore::ParticleType::ConvertedPhoton) {
+      if (geo==egEnergyCorr::ConfigA) hmat=((TH2D*)m_convertedBias_ConfigA.get());
+      else if (geo==egEnergyCorr::ConfigEL) hmat=((TH2D*)m_convertedBias_ConfigEpLp.get());
+      else if (geo==egEnergyCorr::ConfigFMX) hmat=((TH2D*)m_convertedBias_ConfigFpMX.get());
+      else if (geo==egEnergyCorr::ConfigN) hmat=((TH2D*)m_convertedBias_ConfigN.get());
+      else if (geo==egEnergyCorr::ConfigIBL) hmat=((TH2D*)m_convertedBias_ConfigIBL.get());
+      else if (geo==egEnergyCorr::ConfigPP0) hmat=((TH2D*)m_convertedBias_ConfigPP0.get());
+      else return 0;
+   } else return 0;
+
+
+
+
+
+   // use one bin in eta and linear interpolation in Et between 2 bins
+
+  double aeta=fabs(cl_eta);
+  int ieta = hmat->GetXaxis()->FindBin(aeta);
+
+  int ipt = hmat->GetYaxis()->FindBin(ET);
+  double ptBin = hmat->GetYaxis()->GetBinCenter(ipt);
+
+  int i1,i2;
+  double pt1,pt2;
+   if (ET>ptBin) {
+      i1=ipt;
+      i2=ipt+1;
+      pt1=ptBin;
+      pt2= hmat->GetYaxis()->GetBinCenter(i2);
+  }
+  else {
+     i1=ipt-1;
+     i2=ipt;
+     pt1=hmat->GetYaxis()->GetBinCenter(i1);
+     pt2=ptBin;
+  }
+
+  int nbins=hmat->GetYaxis()->GetNbins();
+  double value=0;
+  if (i1>=1 && i1 < nbins) {
+    double v1 = hmat->GetBinContent(ieta,i1);
+    double v2 = hmat->GetBinContent(ieta,i2);
+    value =  (v1*(pt2-ET) + v2*(ET-pt1)) / (pt2-pt1);
+  }
+  else{
+    if (ipt<1) ipt=1;
+    if (ipt>nbins) ipt=nbins;
+    value=hmat->GetBinContent(ieta,ipt);
+  }
+  return value;
+
+}
+
 
   // returns the energy dependence of the above (non-zero for electrons only).
 
@@ -2602,7 +2908,7 @@ namespace AtlasRoot {
     double value = 0;
     double ET = energy/cosh(cl_eta)/GeV;
 
-    if( ptype!=PATCore::ParticleType::Electron || var==egEnergyCorr::Scale::Nominal )
+    if( (ptype!=PATCore::ParticleType::Electron && (m_esmodel != egEnergyCorr::es2017_R21_v1 && m_esmodel != egEnergyCorr::es2017_R21_ofc0_v1 && m_esmodel != egEnergyCorr::es2018_R21_v0 &&  m_esmodel !=egEnergyCorr::es2018_R21_v1) )  || var==egEnergyCorr::Scale::Nominal )
       return value;
 
     egEnergyCorr::Geometry geoID, geoCryo, geoCalo, geoGp;
@@ -2611,23 +2917,43 @@ namespace AtlasRoot {
       geoCryo = egEnergyCorr::ConfigEL;
     else
       geoCryo = egEnergyCorr::ConfigFMX;
-    geoCalo = egEnergyCorr::ConfigFMX;
+
+    //   G.Unal 21.08.2018
+    // for Calo material use correctly ConfigN material for endcap (PS to Calo) in release 21 (not done for run 1, which used FMX in this case)
+    if (fabs(cl_eta)>1.52 && (m_esmodel == egEnergyCorr::es2017_R21_v1 || m_esmodel == egEnergyCorr::es2017_R21_ofc0_v1 || m_esmodel == egEnergyCorr::es2018_R21_v0 ||  m_esmodel == egEnergyCorr::es2018_R21_v1))
+      geoCalo = egEnergyCorr::ConfigN;
+    else
+      geoCalo = egEnergyCorr::ConfigFMX;
     geoGp = egEnergyCorr::ConfigGp;
 
     // look up material bias
 
     double DeltaX = getDeltaX(cl_eta, imat, var) - getDeltaX(cl_eta, imat, egEnergyCorr::Scale::Nominal);
 
+
     // calculate scale change per unit added material
 
-    int ialpha = m_matElectronEtaBins->FindBin( fabs(cl_eta) ) - 1;
-    if (ialpha<0 || ialpha>=m_matElectronGraphs[geoGp]->GetSize())
-      return 0.;
+    // G.Unal 21.08.2019 new code called for release 21 sensivitities
+
+    double DAlphaDXGp,DAlphaDXID,DAlphaDXCryo,DAlphaDXCalo;
+
+    if (m_esmodel == egEnergyCorr::es2017_R21_v1 || m_esmodel == egEnergyCorr::es2017_R21_ofc0_v1 || m_esmodel == egEnergyCorr::es2018_R21_v0 ||  m_esmodel == egEnergyCorr::es2018_R21_v1) {
+       DAlphaDXGp = getMaterialEffect(egEnergyCorr::ConfigFMX,ptype,cl_eta,ET);   // no G' in release 21, use FMX for the crack
+       DAlphaDXID = getMaterialEffect(geoID,ptype,cl_eta,ET);
+       DAlphaDXCryo = getMaterialEffect(geoCryo,ptype,cl_eta,ET);
+       DAlphaDXCalo = getMaterialEffect(geoCalo,ptype,cl_eta,ET);
+
+    } else {
+      int ialpha = m_matElectronEtaBins->FindBin( fabs(cl_eta) ) - 1;
+      if (ialpha<0 || ialpha>=m_matElectronGraphs[geoGp]->GetSize())
+        return 0.;
+
+      DAlphaDXGp   = ((TGraphErrors*)m_matElectronGraphs[geoGp]->At(ialpha))->GetFunction("fNonLin")->Eval( ET );
+      DAlphaDXID   = ((TGraphErrors*)m_matElectronGraphs[geoID]->At(ialpha))->GetFunction("fNonLin")->Eval( ET );
+      DAlphaDXCryo = ((TGraphErrors*)m_matElectronGraphs[geoCryo]->At(ialpha))->GetFunction("fNonLin")->Eval( ET );
+      DAlphaDXCalo = ((TGraphErrors*)m_matElectronGraphs[geoCalo]->At(ialpha))->GetFunction("fNonLin")->Eval( ET );
+    }
 
-    double DAlphaDXGp   = ((TGraphErrors*)m_matElectronGraphs[geoGp]->At(ialpha))->GetFunction("fNonLin")->Eval( ET );
-    double DAlphaDXID   = ((TGraphErrors*)m_matElectronGraphs[geoID]->At(ialpha))->GetFunction("fNonLin")->Eval( ET );
-    double DAlphaDXCryo = ((TGraphErrors*)m_matElectronGraphs[geoCryo]->At(ialpha))->GetFunction("fNonLin")->Eval( ET );
-    double DAlphaDXCalo = ((TGraphErrors*)m_matElectronGraphs[geoCalo]->At(ialpha))->GetFunction("fNonLin")->Eval( ET );
 
     // when in crack, use G', exit
 
@@ -2643,19 +2969,28 @@ namespace AtlasRoot {
     if(idx<1 || idx>m_matX0Additions[geoID]->GetNbinsX())
       DAlphaDXID = 0;
     else
-      DAlphaDXID /= m_matX0Additions[geoID]->GetBinContent(idx);
+    {
+      if (m_matX0Additions[geoID]->GetBinContent(idx) >0.) DAlphaDXID /= m_matX0Additions[geoID]->GetBinContent(idx);
+      else DAlphaDXID=0.;
+    }
 
     idx = m_matX0Additions[geoCryo]->FindBin( fabs(cl_eta) );
     if(idx<1 || idx>m_matX0Additions[geoCryo]->GetNbinsX())
       DAlphaDXCryo = 0;
     else
-      DAlphaDXCryo /= m_matX0Additions[geoCryo]->GetBinContent(idx);
+    {
+      if (m_matX0Additions[geoCryo]->GetBinContent(idx)>0.) DAlphaDXCryo /= m_matX0Additions[geoCryo]->GetBinContent(idx);
+      else DAlphaDXCryo=0.;
+    }
 
     idx = m_matX0Additions[geoCalo]->FindBin( fabs(cl_eta) );
     if(idx<1 || idx>m_matX0Additions[geoCalo]->GetNbinsX())
       DAlphaDXCalo = 0;
     else
-      DAlphaDXCalo /= m_matX0Additions[geoCalo]->GetBinContent(idx);
+    {
+      if (m_matX0Additions[geoCalo]->GetBinContent(idx)>0.) DAlphaDXCalo /= m_matX0Additions[geoCalo]->GetBinContent(idx);
+      else DAlphaDXCalo=0.;
+    }
 
     // final value
 
@@ -2666,6 +3001,7 @@ namespace AtlasRoot {
     else if( imat==egEnergyCorr::MatCalo )
       value = DeltaX * DAlphaDXCalo;
 
+
     return value * varSF;
 
   }
@@ -2746,7 +3082,7 @@ namespace AtlasRoot {
 	alpha = delta / (energy / cosh(cl_eta));
 	if (var == egEnergyCorr::Scale::PedestalDown) alpha *= -1;
       }
-      else if(m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_R21_PRE){
+      else if(m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_summer_final or m_esmodel == egEnergyCorr::es2017_R21_PRE or m_esmodel == egEnergyCorr::es2015_5TeV or m_esmodel == egEnergyCorr::es2017_R21_v0 or  m_esmodel == egEnergyCorr::es2017_R21_v1 or m_esmodel == egEnergyCorr::es2017_R21_ofc0_v1 or m_esmodel == egEnergyCorr::es2018_R21_v0 or m_esmodel == egEnergyCorr::es2018_R21_v1){
 	//Et uncertainty band: 10 MeV for the corrected cluster
 	alpha = 10. / (energy / cosh(cl_eta));
 	if (var == egEnergyCorr::Scale::PedestalDown) alpha *= -1;
@@ -2836,14 +3172,25 @@ namespace AtlasRoot {
   }
 
 
-  double egammaEnergyCorrectionTool::pileUpTerm(double eta, int particle_type) const {
+  double egammaEnergyCorrectionTool::pileUpTerm(double energy, double eta, int particle_type) const {
+
+    double pileupNoise;
 
-    // approximate pileup noise addition to the total noise in MeV   for <mu_data> (2012) = 20
-    // converted photons and electrons
-    double pileupNoise=240.;
-    // unconverted photons, different values in barrel and end-cap
-    if (particle_type==1) {
+    // release 21 for <mu> =32 (combined 2015-2016-2017 dataset), pileup noise = f(Et) for superclusters
+    if (m_esmodel == egEnergyCorr::es2017_R21_v0 or m_esmodel == egEnergyCorr::es2017_R21_v1 or m_esmodel == egEnergyCorr::es2017_R21_ofc0_v1 or m_esmodel == egEnergyCorr::es2018_R21_v0 or m_esmodel == egEnergyCorr::es2018_R21_v1) {
+       double et = energy/cosh(eta);
+       if (et<5000.) et=5000.;
+       if (et>50000.) et=50000.;
+       pileupNoise=sqrt(32.)*(60.+40.*log(et/10000.)/log(5.));
+    }
+    else {
+      // approximate pileup noise addition to the total noise in MeV   for <mu_data> (2012) = 20
+      // converted photons and electrons
+      pileupNoise=240.;
+      // unconverted photons, different values in barrel and end-cap
+      if (particle_type==1) {
       if (fabs(eta)<1.4) pileupNoise=200.;
+      }
     }
     return pileupNoise;
 
@@ -2859,9 +3206,10 @@ namespace AtlasRoot {
 							     double& resolution_error,
                                                              double& resolution_error_up,
                                                              double& resolution_error_down,
-							     int resol_type) const {
+							     int resol_type,
+                                                             bool fast) const {
 
-    double pileupNoise =  pileUpTerm(eta, particle_type);
+    double pileupNoise =  pileUpTerm(energy,eta, particle_type);
     double et = energy/cosh(eta);
 
     resolution = m_resolution_tool->getResolution(particle_type,energy,eta,resol_type);
@@ -2876,8 +3224,7 @@ namespace AtlasRoot {
     double sum_deltaDown=0.;
     double sum_deltaUp=0.;
 
-
-    for (int isys=0;isys<9;isys++) {
+    for (int isys=0;isys<10;isys++) {
 
       if (syst_mask & (1<<isys) ) {
 
@@ -2950,13 +3297,30 @@ namespace AtlasRoot {
 
 	// systematics from pileup noise  on total noise (200 MeV in quadrature, somewhat conservative)
 	if (isys==6) {
-	  double et = energy/cosh(eta);
-	  double deltaPileupNoise=100.; // MeV
-	  if (std::abs(eta)>=1.4 && std::abs(eta)<1.8) deltaPileupNoise=200.; // larger systematic in this eta bin
-	  double scaleNcells=1;
-	  if (particle_type==1 && std::abs(eta)<1.4) scaleNcells = sqrt(3./5.);   // cluster=3X5 instead of 3x7, rms scales with cluster area
-	  double sigmaPileUp = deltaPileupNoise*scaleNcells/et;
-	  double sigmaZ = deltaPileupNoise/(40000.); // effect for Z->ee at Et=40 GeV
+
+          double et = energy/cosh(eta);
+          double sigmaPileUp=0.;
+          double sigmaZ=0.;
+          // release 21 - 10% uncertainty on pileup noise
+          if (m_esmodel == egEnergyCorr::es2017_R21_v0 or m_esmodel == egEnergyCorr::es2017_R21_v1 or m_esmodel == egEnergyCorr::es2018_R21_v0 or  m_esmodel == egEnergyCorr::es2018_R21_v1) {
+              double deltaNoise = sqrt(1.1*1.1-1.0)*pileupNoise;  // uncertainty in quadrature 1.1*noise - noise
+              sigmaPileUp = deltaNoise/et;   // sigmaE/E impact
+              sigmaZ = deltaNoise/40000.;    // sigmaE/E for Z->ee electrons (absorbed in smearing correction)
+          }
+          // no pileup noise uncertainty for es2017_R21_ofc0_v1
+          else if (m_esmodel == egEnergyCorr::es2017_R21_ofc0_v1) {
+            sigmaPileUp=0.;
+            sigmaZ=0.;
+          }
+          else {
+           // older models
+	    double deltaPileupNoise=100.; // MeV
+	    if (std::abs(eta)>=1.4 && std::abs(eta)<1.8) deltaPileupNoise=200.; // larger systematic in this eta bin
+	    double scaleNcells=1;
+	    if (particle_type==1 && std::abs(eta)<1.4) scaleNcells = sqrt(3./5.);   // cluster=3X5 instead of 3x7, rms scales with cluster area
+	    sigmaPileUp = deltaPileupNoise*scaleNcells/et;
+	    sigmaZ = deltaPileupNoise/(40000.); // effect for Z->ee at Et=40 GeV
+          }
 	  sigma2=sigmaPileUp*sigmaPileUp-sigmaZ*sigmaZ;
 	  sigma2up = sigma2;
 	  sigma2down = -1.*sigma2;
@@ -2964,7 +3328,7 @@ namespace AtlasRoot {
 	}
 
 	// systematics from material in IBL+PP0 for barrel
-	if (isys==7 && fabs(eta)<1.5  && (m_esmodel==egEnergyCorr::es2017 or m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved)) {
+	if (isys==7 && fabs(eta)<1.5  && (m_esmodel==egEnergyCorr::es2017 or m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_summer_final or m_esmodel == egEnergyCorr::es2015_5TeV or m_esmodel == egEnergyCorr::es2017_R21_v0 or m_esmodel == egEnergyCorr::es2017_R21_v1 or m_esmodel == egEnergyCorr::es2017_R21_ofc0_v1 or m_esmodel == egEnergyCorr::es2018_R21_v0 or  m_esmodel == egEnergyCorr::es2018_R21_v1)) {
 	  double  sigmaE = m_getMaterialDelta->getDelta(particle_type,energy,eta,1,5);
 	  sigma2 = sigmaE*sigmaE;
 	  sigma2up = sigma2;
@@ -2973,7 +3337,7 @@ namespace AtlasRoot {
 	}
 
 	// systematics from material in IBL+PP0 for end-cap
-	if (isys==8 && fabs(eta)>1.5 && (m_esmodel==egEnergyCorr::es2017 or m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved)) {
+	if (isys==8 && fabs(eta)>1.5 && (m_esmodel==egEnergyCorr::es2017 or m_esmodel == egEnergyCorr::es2017_summer or m_esmodel == egEnergyCorr::es2017_summer_improved or m_esmodel == egEnergyCorr::es2017_summer_final or m_esmodel == egEnergyCorr::es2015_5TeV or m_esmodel == egEnergyCorr::es2017_R21_v0 or m_esmodel == egEnergyCorr::es2017_R21_v1 or m_esmodel == egEnergyCorr::es2017_R21_ofc0_v1 or m_esmodel == egEnergyCorr::es2018_R21_v0 or  m_esmodel == egEnergyCorr::es2018_R21_v1)) {
 	  double sigmaE =  m_getMaterialDelta->getDelta(particle_type,energy,eta,1,5);
 	  // scale factor 2.3 in X0 => sqrt(2) in resolution or 2 in resolution**2
 	  sigma2 = 2.3*sigmaE*sigmaE;
@@ -2983,6 +3347,17 @@ namespace AtlasRoot {
 
 	}
 
+        // AF2 resolution systematics for es2017_R21_v1 model (neglected before that...)
+
+        if (isys==9 && (m_esmodel == egEnergyCorr::es2017_R21_v1 || m_esmodel == egEnergyCorr::es2017_R21_ofc0_v1 || m_esmodel == egEnergyCorr::es2018_R21_v0 || m_esmodel == egEnergyCorr::es2018_R21_v1) && fast) {
+           const double ptGeV = et/1e3;
+           if(particle_type == 0) sigma2 = getValueHistAt(*m_G4OverAFII_resolution_electron,eta,ptGeV,true,true,true,true);
+           if(particle_type == 1) sigma2 = getValueHistAt(*m_G4OverAFII_resolution_unconverted,eta,ptGeV,true,true,true,true);
+           if(particle_type == 2) sigma2 = getValueHistAt(*m_G4OverAFII_resolution_converted,eta,ptGeV,true,true,true,true);
+           sigma2up = -1.*sigma2;  // AF2 resolution worse than full Sim, sigma2up gives back AF2 resolution
+           sigma2down = sigma2;
+        }
+
 
 //  old method to use max of up and down for All
 /*
@@ -3016,7 +3391,7 @@ namespace AtlasRoot {
 	else rr2=0.;
 	double deltaSigmaDown = (rr2-resolution)/resolution;
 	//std::cout << " relative resolution change Down " << deltaSigmaDown << std::endl;
-	
+
 	sum_deltaUp += deltaSigmaUp;
 	sum_deltaDown += deltaSigmaDown;
 
@@ -3030,7 +3405,7 @@ namespace AtlasRoot {
     resolution_error_up = sum_deltaUp*resolution;
     resolution_error_down = sum_deltaDown*resolution;
 
-    
+
     //std::cout << " Resolution (MeV): " << resolution << "   Resolution Error (MeV): " << resolution_error
     //	      << " Z smearing " << smearingZ << " +- " << esmearingZ << std::endl;
 
@@ -3064,6 +3439,8 @@ namespace AtlasRoot {
     case egEnergyCorr::Scale::G4Down: return "G4Down";
     case egEnergyCorr::Scale::PSUp: return "PSUp";
     case egEnergyCorr::Scale::PSDown: return "PSDown";
+    case egEnergyCorr::Scale::PSb12Up: return "PSb12Up";
+    case egEnergyCorr::Scale::PSb12Down: return "PSb12Down";
     case egEnergyCorr::Scale::S12Up: return "S12Up";
     case egEnergyCorr::Scale::S12Down: return "S12Down";
     case egEnergyCorr::Scale::S12ExtraLastEtaBinRun2Up: return "S12ExtraLastEtaBinRun2Up";
@@ -3133,116 +3510,27 @@ namespace AtlasRoot {
       case egEnergyCorr::Resolution::MaterialPP0Down: return "Resolution::MaterialPP0Down";
       case egEnergyCorr::Resolution::MaterialIBLUp: return "Resolution::MaterialIBLUp";
       case egEnergyCorr::Resolution::MaterialIBLDown: return "Resolution::MaterialIBLDown";
+      case egEnergyCorr::Resolution::af2Up: return "Resolution::af2Up";
+      case egEnergyCorr::Resolution::af2Down: return "Resolution::af2Down";
       case egEnergyCorr::Resolution::LastResolutionVariation: return "LastResolutionVariation";
       default: return "Resolution::Unknown";
     }
   }
 
 
-  egEnergyCorr::Scale::Variation egammaEnergyCorrectionTool::ScaleVariationFromString(string& var) {
-
-    egEnergyCorr::Scale::Variation TheVar = egEnergyCorr::Scale::None;
-
-    if( var == "None" )                        TheVar = egEnergyCorr::Scale::None;
-    else if( var == "Nominal" )                TheVar = egEnergyCorr::Scale::Nominal;
-    else if( var == "MomentumUp" )             TheVar = egEnergyCorr::Scale::MomentumUp;
-    else if( var == "MomentumDown" )           TheVar = egEnergyCorr::Scale::MomentumDown;
-    else if( var == "ZeeStatUp" )              TheVar = egEnergyCorr::Scale::ZeeStatUp;
-    else if( var == "ZeeStatDown" )            TheVar = egEnergyCorr::Scale::ZeeStatDown;
-    else if( var == "ZeeSystUp" )              TheVar = egEnergyCorr::Scale::ZeeSystUp;
-    else if( var == "ZeeSystDown" )            TheVar = egEnergyCorr::Scale::ZeeSystDown;
-    else if( var == "ZeePhysUp" )              TheVar = egEnergyCorr::Scale::ZeePhysUp;
-    else if( var == "ZeePhysDown" )            TheVar = egEnergyCorr::Scale::ZeePhysDown;
-    else if( var == "ZeeAllUp" )               TheVar = egEnergyCorr::Scale::ZeeAllUp;
-    else if( var == "ZeeAllDown" )             TheVar = egEnergyCorr::Scale::ZeeAllDown;
-    else if( var == "LArCalibUp" )             TheVar = egEnergyCorr::Scale::LArCalibUp;
-    else if( var == "LArCalibDown" )           TheVar = egEnergyCorr::Scale::LArCalibDown;
-    else if( var == "LArUnconvCalibUp" )       TheVar = egEnergyCorr::Scale::LArUnconvCalibUp;
-    else if( var == "LArUnconvCalibDown" )     TheVar = egEnergyCorr::Scale::LArUnconvCalibDown;
-    else if( var == "LArElecCalibUp" )         TheVar = egEnergyCorr::Scale::LArElecCalibUp;
-    else if( var == "LArElecCalibDown" )       TheVar = egEnergyCorr::Scale::LArElecCalibDown;
-    else if( var == "LArElecUnconvUp" )        TheVar = egEnergyCorr::Scale::LArElecUnconvUp;
-    else if( var == "LArElecUnconvDown" )      TheVar = egEnergyCorr::Scale::LArElecUnconvDown;
-    else if( var == "G4Up" )                   TheVar = egEnergyCorr::Scale::G4Up;
-    else if( var == "G4Down" )                 TheVar = egEnergyCorr::Scale::G4Down;
-    else if( var == "PSUp" )                   TheVar = egEnergyCorr::Scale::PSUp;
-    else if( var == "PSDown" )                 TheVar = egEnergyCorr::Scale::PSDown;
-    else if( var == "S12Up" )                  TheVar = egEnergyCorr::Scale::S12Up;
-    else if( var == "S12Down" )                TheVar = egEnergyCorr::Scale::S12Down;
-    else if( var == "S12ExtraLastEtaBinRun2Up") TheVar = egEnergyCorr::Scale::S12ExtraLastEtaBinRun2Up;
-    else if( var == "S12ExtraLastEtaBinRun2Down") TheVar = egEnergyCorr::Scale::S12ExtraLastEtaBinRun2Down;
-    else if( var == "MatPP0Up")                TheVar = egEnergyCorr::Scale::MatPP0Up;
-    else if( var == "MatPP0Down")                TheVar = egEnergyCorr::Scale::MatPP0Down;
-    else if( var == "MatIDUp" )                TheVar = egEnergyCorr::Scale::MatIDUp;
-    else if( var == "MatIDDown" )              TheVar = egEnergyCorr::Scale::MatIDDown;
-    else if( var == "MatCryoUp" )              TheVar = egEnergyCorr::Scale::MatCryoUp;
-    else if( var == "MatCryoDown" )            TheVar = egEnergyCorr::Scale::MatCryoDown;
-    else if( var == "MatCaloUp" )              TheVar = egEnergyCorr::Scale::MatCaloUp;
-    else if( var == "MatCaloDown" )            TheVar = egEnergyCorr::Scale::MatCaloDown;
-    else if( var == "L1GainUp" )               TheVar = egEnergyCorr::Scale::L1GainUp;
-    else if( var == "L1GainDown" )             TheVar = egEnergyCorr::Scale::L1GainDown;
-    else if( var == "L2GainUp" )               TheVar = egEnergyCorr::Scale::L2GainUp;
-    else if( var == "L2GainDown" )             TheVar = egEnergyCorr::Scale::L2GainDown;
-    else if( var == "LeakageConvUp" )          TheVar = egEnergyCorr::Scale::LeakageConvUp;
-    else if( var == "LeakageConvDown" )        TheVar = egEnergyCorr::Scale::LeakageConvDown;
-    else if( var == "LeakageUnconvUp" )        TheVar = egEnergyCorr::Scale::LeakageUnconvUp;
-    else if( var == "LeakageUnconvDown" )      TheVar = egEnergyCorr::Scale::LeakageUnconvDown;
-    else if( var == "ConvEfficiencyUp" )       TheVar = egEnergyCorr::Scale::ConvEfficiencyUp;
-    else if( var == "ConvEfficiencyDown" )     TheVar = egEnergyCorr::Scale::ConvEfficiencyDown;
-    else if( var == "ConvFakeRateUp" )         TheVar = egEnergyCorr::Scale::ConvFakeRateUp;
-    else if( var == "ConvFakeRateDown" )       TheVar = egEnergyCorr::Scale::ConvFakeRateDown;
-    else if( var == "ConvRadiusUp" )           TheVar = egEnergyCorr::Scale::ConvRadiusUp;
-    else if( var == "ConvRadiusDown" )         TheVar = egEnergyCorr::Scale::ConvRadiusDown;
-    else if( var == "PedestalUp" )             TheVar = egEnergyCorr::Scale::PedestalUp;
-    else if( var == "PedestalDown" )           TheVar = egEnergyCorr::Scale::PedestalDown;
-    else if( var == "AllUp" )                  TheVar = egEnergyCorr::Scale::AllUp;
-    else if( var == "AllDown" )                TheVar = egEnergyCorr::Scale::AllDown;
-    else if( var == "LastScaleVariation" )     TheVar = egEnergyCorr::Scale::LastScaleVariation;
-
-    return TheVar;
-
-  }
-
-
-  egEnergyCorr::Resolution::Variation egammaEnergyCorrectionTool::ResolutionVariationFromString(string& var) {
-
-    egEnergyCorr::Resolution::Variation TheVar  = egEnergyCorr::Resolution::None;
-
-    if ( var == "None") TheVar = egEnergyCorr::Resolution::None;
-    else if ( var == "Nominal")                   TheVar = egEnergyCorr::Resolution::Nominal;
-    else if ( var == "AllDown")                   TheVar = egEnergyCorr::Resolution::AllDown;
-    else if ( var == "AllUp")                     TheVar = egEnergyCorr::Resolution::AllUp;
-    else if ( var == "ZSmearingUp")               TheVar = egEnergyCorr::Resolution::ZSmearingUp;
-    else if ( var == "ZSmearingDown")             TheVar = egEnergyCorr::Resolution::ZSmearingDown;
-    else if ( var == "SamplingTermUp")            TheVar = egEnergyCorr::Resolution::SamplingTermUp;
-    else if ( var == "SamplingTermDown")          TheVar = egEnergyCorr::Resolution::SamplingTermDown;
-    else if ( var == "MaterialIDUp")              TheVar = egEnergyCorr::Resolution::MaterialIDUp;
-    else if ( var == "MaterialIDDown")            TheVar = egEnergyCorr::Resolution::MaterialIDDown;
-    else if ( var == "MaterialCaloUp")            TheVar = egEnergyCorr::Resolution::MaterialCaloUp;
-    else if ( var == "MaterialCaloDown")          TheVar = egEnergyCorr::Resolution::MaterialCaloDown;
-    else if ( var == "MaterialCryoUp")            TheVar = egEnergyCorr::Resolution::MaterialCryoUp;
-    else if ( var == "MaterialCryoDown")          TheVar = egEnergyCorr::Resolution::MaterialCryoDown;
-    else if ( var == "MaterialGapUp")             TheVar = egEnergyCorr::Resolution::MaterialGapUp;
-    else if ( var == "MaterialGapDown")           TheVar = egEnergyCorr::Resolution::MaterialGapDown;
-    else if ( var == "MaterialIBLUp")             TheVar = egEnergyCorr::Resolution::MaterialIBLUp;
-    else if ( var == "MaterialIBLDown")           TheVar = egEnergyCorr::Resolution::MaterialIBLDown;
-    else if ( var == "MaterialPP0Up")             TheVar = egEnergyCorr::Resolution::MaterialPP0Up;
-    else if ( var == "MaterialPP0Down")           TheVar = egEnergyCorr::Resolution::MaterialPP0Down;
-    else if ( var == "PileUpUp")                  TheVar = egEnergyCorr::Resolution::PileUpUp;
-    else if ( var == "PileUpDown")                TheVar = egEnergyCorr::Resolution::PileUpDown;
-    else if ( var == "LastResolutionVariation")   TheVar = egEnergyCorr::Resolution::LastResolutionVariation;
-
-    return TheVar;
-
-  }
-
   double egammaEnergyCorrectionTool::get_ZeeSyst(double eta) const
   {
     const auto ieta = m_zeeSyst->GetXaxis()->FindFixBin(eta);
     auto value_histo = m_zeeSyst->GetBinContent(ieta);
+
     return value_histo;
   }
 
+  const TAxis& egammaEnergyCorrectionTool::get_ZeeStat_eta_axis() const
+  {
+    return *m_zeeNom->GetXaxis();
+  }
+
 
 
 } // egRescaler
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/get_MaterialResolutionEffect.cxx b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/get_MaterialResolutionEffect.cxx
index 21cbd955decddd0849108144f795ebfd6fc9ccf4..bd90b147b6fd74f4c01d53c5f76d0fb475f79657 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/get_MaterialResolutionEffect.cxx
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/Root/get_MaterialResolutionEffect.cxx
@@ -1,24 +1,26 @@
 /*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #include "ElectronPhotonFourMomentumCorrection/get_MaterialResolutionEffect.h"
 
 #include "PathResolver/PathResolver.h"
 
-#include <stdlib.h>
-#include "TAxis.h"
 #include "Riostream.h"
 
+#include "TH1.h"
+#include "TH2.h"
+#include "TFile.h"
+#include "TArrayD.h"
+
 get_MaterialResolutionEffect::get_MaterialResolutionEffect()
   : asg::AsgMessaging("get_MaterialResolutionEffect")
 {
   //std::cout << " Initialize get_MaterialResolutionEffect " << std::endl;
 
   const std::string filename = PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v8/histos-systematics-material.root");
-  
-  
-  m_file0 = std::make_unique<TFile>(filename.c_str());
+
+  m_file0.reset(TFile::Open( filename.c_str(), "READ" ));
 
   for (Int_t isys=0;isys<4;isys++) {
     for (Int_t ieta=0;ieta<8;ieta++) {
@@ -37,9 +39,11 @@ get_MaterialResolutionEffect::get_MaterialResolutionEffect()
          if (isys==1 && iconv==2) sprintf(name,"systConv_CD_etaBin_%d",ieta);
          if (isys==2 && iconv==2) sprintf(name,"systConv_EL_etaBin_%d",ieta);
          if (isys==3 && iconv==2) sprintf(name,"systConv_FMX_etaBin_%d",ieta);
-         
-         if (!(m_hSystPeak[isys][ieta][iconv]=(TH1D*) m_file0->Get(name))) ATH_MSG_FATAL("cannot find histogram " << name << " in file '" << filename << "'");
-	 
+
+         m_hSystPeak.at(isys).at(ieta).at(iconv).reset( dynamic_cast<TH1*>(m_file0->Get(name)));
+         m_hSystPeak.at(isys).at(ieta).at(iconv)->SetDirectory( nullptr );
+         if (!m_hSystPeak.at(isys).at(ieta).at(iconv).get()) ATH_MSG_FATAL("cannot find histogram " << name << " in file '" << filename << "'");
+
 
          if (isys==0 && iconv==0) sprintf(name,"systElec_sigmaG_A_etaBin_%d",ieta);
          if (isys==1 && iconv==0) sprintf(name,"systElec_sigmaG_CD_etaBin_%d",ieta);
@@ -55,24 +59,32 @@ get_MaterialResolutionEffect::get_MaterialResolutionEffect()
          if (isys==2 && iconv==2) sprintf(name,"systConv_sigmaG_EL_etaBin_%d",ieta);
          if (isys==3 && iconv==2) sprintf(name,"systConv_sigmaG_FMX_etaBin_%d",ieta);
 
-         if (!(m_hSystResol[isys][ieta][iconv]=(TH1D*) m_file0->Get(name))) ATH_MSG_FATAL("cannot find histogram " << name << " in file '" << filename << "'");
-      }      
+         m_hSystResol.at(isys).at(ieta).at(iconv).reset( dynamic_cast<TH1*>(m_file0->Get(name)));
+         m_hSystResol.at(isys).at(ieta).at(iconv)->SetDirectory( nullptr );
+         if (!(m_hSystResol.at(isys).at(ieta).at(iconv).get())) ATH_MSG_FATAL("cannot find histogram " << name << " in file '" << filename << "'");
+      }
     }
   }
 
    // IBL+PP0 material systematics stored in 2D file
-  if (!(m_hsyst_IBL_PP0[0]=(TH2D*) m_file0->Get("systElec_IBLPP0"))) ATH_MSG_FATAL("cannot find histogram systElec_IBLPP0 in file '" << filename << "'");
-  if (!(m_hsyst_IBL_PP0[1]=(TH2D*) m_file0->Get("systUnconv_IBLPP0"))) ATH_MSG_FATAL("cannot find histogram systUnconv_IBLPP0 in file '" << filename << "'");
-  if (!(m_hsyst_IBL_PP0[2]=(TH2D*) m_file0->Get("systConv_IBLPP0"))) ATH_MSG_FATAL("cannot find histogram systConv_IBLPP0 in file '" << filename << "'");
-   
+  m_hsyst_IBL_PP0.at(0).reset(dynamic_cast<TH2*>(m_file0->Get("systElec_IBLPP0")));
+  m_hsyst_IBL_PP0.at(0)->SetDirectory( nullptr );
+  if (!(m_hsyst_IBL_PP0.at(0).get())) ATH_MSG_FATAL("cannot find histogram systElec_IBLPP0 in file '" << filename << "'");
+  m_hsyst_IBL_PP0.at(1).reset(dynamic_cast<TH2*>(m_file0->Get("systUnconv_IBLPP0")));
+  m_hsyst_IBL_PP0.at(1)->SetDirectory( nullptr );
+
+  if (!(m_hsyst_IBL_PP0.at(1).get())) ATH_MSG_FATAL("cannot find histogram systUnconv_IBLPP0 in file '" << filename << "'");
+  m_hsyst_IBL_PP0.at(2).reset(dynamic_cast<TH2*>(m_file0->Get("systConv_IBLPP0")));
+  m_hsyst_IBL_PP0.at(2)->SetDirectory( nullptr );
+  if (!(m_hsyst_IBL_PP0.at(2).get())) ATH_MSG_FATAL("cannot find histogram systConv_IBLPP0 in file '" << filename << "'");
+
 
-  TAxis* aa=m_hSystResol[0][0][1]->GetXaxis();
-  m_etBins = aa->GetXbins();
+  m_etBins=m_hSystResol.at(0).at(0).at(1)->GetXaxis()->GetXbins();
 }
 
 //=========================================================================
 get_MaterialResolutionEffect::~get_MaterialResolutionEffect(){
-  m_file0->Close();
+  ///m_file0->Close();
 }
 
 //============================================================================
@@ -99,7 +111,8 @@ double get_MaterialResolutionEffect::getDelta(int particle_type, double energy,
       double et2=et;
       if (et<5.) et2=5.1;
       if (et>2000) et2=1999.;
-      return 0.01*m_hsyst_IBL_PP0[particle_type]->GetBinContent(m_hsyst_IBL_PP0[particle_type]->GetXaxis()->FindBin(aeta),m_hsyst_IBL_PP0[particle_type]->GetYaxis()->FindBin(et2));
+      if (particle_type==3) particle_type=2;
+      return 0.01*m_hsyst_IBL_PP0.at(particle_type)->GetBinContent(m_hsyst_IBL_PP0.at(particle_type)->GetXaxis()->FindBin(aeta),m_hsyst_IBL_PP0.at(particle_type)->GetYaxis()->FindBin(et2));
    }
 
 
@@ -126,10 +139,10 @@ double get_MaterialResolutionEffect::getDelta(int particle_type, double energy,
    //cout << " m_hSystResol " << m_hSystResol[isyst][ieta][particle_type] << endl;
 
    if (response_type==0) {
-      return 0.01*m_hSystPeak[isyst][ieta][particle_type]->GetBinContent(ibinEt+1);
+      return 0.01*m_hSystPeak.at(isyst).at(ieta).at(particle_type)->GetBinContent(ibinEt+1);
    }
    else {
-      return 0.01*m_hSystResol[isyst][ieta][particle_type]->GetBinContent(ibinEt+1);
+      return 0.01*m_hSystResol.at(isyst).at(ieta).at(particle_type)->GetBinContent(ibinEt+1);
    }
 
 }
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/python/create_input.py b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/python/create_input.py
index 2ca30ec2f423869a92bbc7e005c0ede0dad357a0..f1b161dacf85c9de9a8ee08ee542c60e02e86e3a 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/python/create_input.py
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/python/create_input.py
@@ -2,8 +2,6 @@
 
 # this file do not work out of the box
 
-from __future__ import print_function
-
 import ROOT
 from array import array
 import numpy as np
@@ -41,7 +39,7 @@ assert ct_sys_christophe
 def qsum_histograms(histo1, histo2):
     new_histo = histo1.Clone()
     new_histo.Reset()
-    for ibin in range(histo1.GetNbinsX() + 2):
+    for ibin in xrange(histo1.GetNbinsX() + 2):
         value1 = histo1.GetBinContent(ibin)
         central_value = histo1.GetBinCenter(ibin)
         ibin2 = histo2.FindBin(central_value)
@@ -129,7 +127,7 @@ def merge_histograms(old, new, merge_error=True):
     UNDERFLOW = 0
     OVERFLOW = new.GetNbinsX() + 1
 
-    for iold in range(1, old.GetNbinsX()):
+    for iold in xrange(1, old.GetNbinsX()):
         l = old.GetBinLowEdge(iold)
         r = l + old.GetBinWidth(iold)
 
@@ -153,7 +151,7 @@ def merge_histograms(old, new, merge_error=True):
             break
     last_old = iold
 
-    for inew in range(1, new.GetNbinsX() + 1):
+    for inew in xrange(1, new.GetNbinsX() + 1):
         l = new.GetBinLowEdge(inew)
         r = l + new.GetBinWidth(inew)
         new_binning.append((l, r))
@@ -165,7 +163,7 @@ def merge_histograms(old, new, merge_error=True):
         new_values.append(old.GetBinContent(remainer))
         new_errors.append(old.GetBinError(remainer))
 
-    for iold in range(last_old, old.GetNbinsX() + 1):
+    for iold in xrange(last_old, old.GetNbinsX() + 1):
         l = old.GetBinLowEdge(iold)
         r = l + old.GetBinWidth(iold)
 
@@ -227,7 +225,7 @@ histo_ct.SetName("ctZee_errStat")
 # this created a file structured as the official one, with empty directories
 #output_file = create_structured_file("calibration_constants_run2.root")
 import shutil
-print (old_filename)
+print(old_filename)
 shutil.copy2(old_filename, "xxx.root")
 output_file = ROOT.TFile("xxx.root", "update")
 create_new_directories(output_file)
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/python/dump_layer.py b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/python/dump_layer.py
index 7b8f7d46ab6dc2e1be7d63aae40547854e8b2c0c..42f5aa849b457a45faf34b41d7af5b542d8a581c 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/python/dump_layer.py
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/python/dump_layer.py
@@ -11,8 +11,6 @@ The output of this tool is needed to generate single particle from scratch and
 then to compute the decomposition of the covariance matrix.
 """
 
-from __future__ import print_function
-
 import ROOT
 from glob import glob
 from array import array
@@ -23,7 +21,7 @@ def main(path, particle):
     chain = ROOT.TChain("egamma")
     for f in files:
         chain.Add(f)
-    print ("entries:", chain.GetEntries())
+    print("entries:", chain.GetEntries())
 
     selection = {"unconv": "(ph_Rconv >= 800 || ph_Rconv <= 0)",
                  "conv": "(ph_Rconv < 800 && ph_Rconv > 0)",
@@ -62,14 +60,14 @@ def main(path, particle):
         vars_to_plot.append("ph_zconv")
         title.append("ph_zconv")
 
-    print ("plotting counting")
+    print("plotting counting")
     histo_name = "histo_count_%s" % particle
     histo_count = ROOT.TH2F(histo_name, "count %s" % particle, len(pt_binning) - 1, pt_binning, len(aeta_binning) - 1, aeta_binning)
     chain.Draw(aetaCalo + ":" + truth_pt + ">>" + histo_name, selection)
 
     result = []
     for t, v in zip(title, vars_to_plot):
-        print ("plotting", v)
+        print("plotting", v)
         histo_name = "histo_%s_%s" % (particle, t)
         if "zconv" in v:
             sel = selection + " && abs(ph_zconv) < 5000"
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/python/merge_scale_histograms.py b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/python/merge_scale_histograms.py
index b1e6f84a0748dec3cc40f7ca8756920765c89433..12548deec608a8b987000f970a951dd89968082d 100755
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/python/merge_scale_histograms.py
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/python/merge_scale_histograms.py
@@ -2,8 +2,6 @@
 
 # Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 
-from __future__ import print_function
-
 
 doc = """
 This is an utility to merge histograms. The common case is when you have
@@ -18,16 +16,16 @@ logging.basicConfig(level=logging.INFO)
 from array import array
 
 def merge_histograms(old, new, merge_error=True):
-    print ("old binning: " + ", ".join(("%.3f" % old.GetBinLowEdge(ibin)) for ibin in range(1, old.GetNbinsX() + 2)))
-    print ("new binning: " + ", ".join(("%.3f" % new.GetBinLowEdge(ibin)) for ibin in range(1, new.GetNbinsX() + 2)))
-    
+    print("old binning: " + ", ".join(("%.3f" % old.GetBinLowEdge(ibin)) for ibin in xrange(1, old.GetNbinsX() + 2)))
+    print("new binning: " + ", ".join(("%.3f" % new.GetBinLowEdge(ibin)) for ibin in xrange(1, new.GetNbinsX() + 2)))
+
     new_binning = []
     new_values = []
     new_errors = []
     UNDERFLOW = 0
     OVERFLOW = new.GetNbinsX() + 1
 
-    for iold in range(1, old.GetNbinsX()):
+    for iold in xrange(1, old.GetNbinsX()):
         l = old.GetBinLowEdge(iold)
         r = l + old.GetBinWidth(iold)
 
@@ -36,7 +34,7 @@ def merge_histograms(old, new, merge_error=True):
         remainer = None
 
         if il_new == UNDERFLOW and ir_new == UNDERFLOW:
-            print ("1. adding %.3f - %.3f from old" % (l, r))
+            print("1. adding %.3f - %.3f from old" % (l, r))
             new_binning.append((l, r))
             new_values.append(old.GetBinContent(iold))
             new_errors.append(old.GetBinError(iold))
@@ -49,25 +47,25 @@ def merge_histograms(old, new, merge_error=True):
             new_errors.append(old.GetBinError(iold))
             if ir_new == OVERFLOW:
                 remainer = iold
-            print ("breaking")
+            print("breaking")
             break
     last_old = iold
 
-    for inew in range(1, new.GetNbinsX() + 1):
+    for inew in xrange(1, new.GetNbinsX() + 1):
         l = new.GetBinLowEdge(inew)
         r = l + new.GetBinWidth(inew)
-        print ("2. adding %.3f - %.3f from new" % (l, r))
+        print("2. adding %.3f - %.3f from new" % (l, r))
         new_binning.append((l, r))
         new_values.append(new.GetBinContent(inew))
         new_errors.append(new.GetBinError(inew))
     """
     if remainer is not None:
-        print ("3. adding %.3f - %.3f from old" % (new.GetBinLowEdge(new.GetNbinsX()), old.GetBinLowEdge(remainer) + old.GetBinWidth(remainer)))
+        print("3. adding %.3f - %.3f from old" % (new.GetBinLowEdge(new.GetNbinsX()), old.GetBinLowEdge(remainer) + old.GetBinWidth(remainer)))
         new_binning.append((new.GetBinLowEdge(new.GetNbinsX()), old.GetBinLowEdge(remainer) + old.GetBinWidth(remainer)))
         new_values.append(old.GetBinContent(remainer))
         new_errors.append(old.GetBinError(remainer))
     """
-    for iold in range(last_old, old.GetNbinsX() + 1):
+    for iold in xrange(last_old, old.GetNbinsX() + 1):
         l = old.GetBinLowEdge(iold)
         r = l + old.GetBinWidth(iold)
 
@@ -75,7 +73,7 @@ def merge_histograms(old, new, merge_error=True):
         ir_new = new.FindFixBin(r)
 
         if il_new == OVERFLOW and ir_new == OVERFLOW:
-            print ("4. adding %.3f - %.3f from old" % (l, r))
+            print("4. adding %.3f - %.3f from old" % (l, r))
             new_binning.append((l, r))
             new_values.append(old.GetBinContent(iold))
             new_errors.append(old.GetBinError(iold))
@@ -86,7 +84,7 @@ def merge_histograms(old, new, merge_error=True):
             new_values.append(old.GetBinContent(iold))
             new_errors.append(old.GetBinError(iold))
 
-    print (new_binning)
+    print(new_binning)
     new_edges = array('f', [x[0] for x in new_binning] + [new_binning[-1][1]])
     histo_type = type(new)
     result = histo_type(new.GetName(), new.GetTitle(), len(new_edges) - 1, new_edges)
@@ -95,9 +93,9 @@ def merge_histograms(old, new, merge_error=True):
         if merge_error:
             result.SetBinError(i, e)
 
-    print ("merged binning: " + ", ".join(("%.3f" % result.GetBinLowEdge(ibin)) for ibin in range(1, result.GetNbinsX() + 1)))
+    print("merged binning: " + ", ".join(("%.3f" % result.GetBinLowEdge(ibin)) for ibin in xrange(1, result.GetNbinsX() + 1)))
+
 
-            
     return result
 
 
@@ -160,7 +158,7 @@ example (merge ct sys 2015PRE + 2015 summer): ./merge_scale_histograms.py ../../
     legend.AddEntry(histo_new, "new")
     legend.SetBorderSize(0)
     legend.Draw()
-    
+
     fout = ROOT.TFile.Open(args.output_filename, "recreate" if args.recreate else "update")
     if args.title is not None:
         histo_merged.SetTitle(args.title)
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/python/plot.py b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/python/plot.py
index c160785459cce37f4da820337792d94551a3ab69..ad16fedfaff2bde5b5a6bbf843fb96462f156898 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/python/plot.py
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/python/plot.py
@@ -1,19 +1,25 @@
 #!/usr/bin/env python
-# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 
-from __future__ import print_function
+# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 
 import numpy as np
 import logging
 import os
-from itertools import tee, izip, cycle, chain
+from itertools import tee, izip, cycle, chain, product
 import matplotlib as mpl
+mpl.use('Agg')
 import matplotlib.pyplot as plt
 import matplotlib.patches as patches
-
+from matplotlib.ticker import MaxNLocator
+import matplotlib.lines as mlines
+import tqdm
+import colorlog
+import seaborn as sns
+from functools import wraps
+import time
+from fnmatch import fnmatch
 import ROOT
 ROOT.PyConfig.IgnoreCommandLineOptions = True
-logging.basicConfig(level=logging.INFO)
 
 plt.rcParams['image.cmap'] = 'coolwarm'  # RdBu_r
 
@@ -22,17 +28,13 @@ rcParams['font.family'] = 'sans-serif'
 rcParams['mathtext.fontset'] = 'stixsans'
 rcParams['mathtext.default'] = 'rm'
 rcParams['font.sans-serif'] = 'helvetica, Helvetica, Nimbus Sans L, Mukti Narrow, FreeSans'
-rcParams['figure.figsize'] = 8.75, 5.92
-#rcParams['figure.facecolor'] = 'white'
-rcParams['figure.subplot.bottom'] = 0.16
-rcParams['figure.subplot.top'] = 0.95
-rcParams['figure.subplot.left'] = 0.16
-rcParams['figure.subplot.right'] = 0.95
 
 # axes
 rcParams['axes.labelsize'] = 20
 rcParams['xtick.minor.visible'] = True
 rcParams['ytick.minor.visible'] = True
+rcParams['xtick.direction'] = 'in'
+rcParams['ytick.direction'] = 'in'
 rcParams['xtick.labelsize'] = 19
 rcParams['xtick.major.size'] = 12
 rcParams['xtick.minor.size'] = 6
@@ -40,6 +42,8 @@ rcParams['ytick.labelsize'] = 19
 rcParams['ytick.major.size'] = 14
 rcParams['ytick.minor.size'] = 7
 rcParams['lines.markersize'] = 8
+rcParams['ytick.right'] = True
+rcParams['xtick.top'] = True
 # rcParams['lines.markeredgewidth'] = 0. # not working, it changes other stuff
 
 # legend
@@ -50,6 +54,29 @@ rcParams['legend.labelspacing'] = 0.3
 
 extensions = 'pdf', 'png'
 
+
+def check_status_code(func):
+    def wrapper(self, *args):
+        status = func(self, *args)
+        if not status.isSuccess():
+            raise ValueError('status is not success')
+        return status
+    return wrapper
+
+ROOT.CP.EgammaCalibrationAndSmearingTool.initialize = check_status_code(ROOT.CP.EgammaCalibrationAndSmearingTool.initialize)
+
+
+def timed(method):
+    @wraps(method)
+    def timed(*args, **kw):
+        ts = time.time()
+        result = method(*args, **kw)
+        te = time.time()
+
+        log.info("function %s run in  %d second", method.__name__, te-ts)
+        return result
+    return timed
+
 def plot_ATLAS(fig, x, y, label='Internal', fontsize=20):
     l = fig.text(x, y, 'ATLAS', fontsize=fontsize, fontstyle='italic', fontweight='bold')
     def on_draw(event):
@@ -68,12 +95,27 @@ def pairwise(iterable):
     next(b, None)
     return izip(a, b)
 
+def divide_square(n, horizontal=True):
+    if horizontal:
+        x = np.ceil(np.sqrt(n))
+        y = np.floor(np.sqrt(n))
+        if (x * y) < n:
+            x += 1
+    else:
+        x = np.floor(np.sqrt(n))
+        y = np.ceil(np.sqrt(n))
+        if (x * y) < n:
+            y += 1
+    return int(x), int(y)
+
+
+
 def histo2data(histo):
     xs = []
     ys = []
     exs = []
     eys = []
-    for ibin in range(1, histo.GetNbinsX() + 1):
+    for ibin in xrange(1, histo.GetNbinsX() + 1):
         xs.append(histo.GetBinCenter(ibin))
         ys.append(histo.GetBinContent(ibin))
         eys.append(histo.GetBinError(ibin))
@@ -81,6 +123,19 @@ def histo2data(histo):
     return np.array(xs), np.array(exs), np.array(ys), np.array(eys)
 
 
+def systematics_from_tool(tool, only_scale=True, only_resolution=False, only_up=True):
+    _ = tool.recommendedSystematics()
+    for sys in _:
+        sys_name = sys.name()
+        if only_scale and 'RESOLUTION' in sys_name:
+            continue
+        if only_resolution and 'SCALE' in sys_name:
+            continue
+        if only_up and '1down' in sys_name:
+            continue
+        yield sys
+
+
 def partition(x, n):
     r = []
     for xx in x:
@@ -104,12 +159,14 @@ def generator_photon(self):
     store.clear()
 
 
-def eval_sys_eta_pt(tool, etas, pts, simulation=True, particle='unconverted'):
+def calibrate_eta_pt(tool, etas, pts, simulation=True, particle='unconverted'):
+    log.debug("creating TEvent and EgammaFactory")
     event = ROOT.xAOD.TEvent()
     factory = ROOT.EgammaFactory()
     result = np.ones((len(pts), len(etas)))
     ei = factory.create_eventinfo(simulation, 266904)
     assert ei.eventType(ROOT.xAOD.EventInfo.IS_SIMULATION) == simulation
+    log.debug("looping")
     for ieta, eta in enumerate(etas):
         for ipt, pt in enumerate(pts):
             if particle == 'unconverted':
@@ -121,7 +178,9 @@ def eval_sys_eta_pt(tool, etas, pts, simulation=True, particle='unconverted'):
             else:
                 raise ValueError()
             result[ipt, ieta] = tool.getEnergy(p, ei)
+    log.debug("deleting event")
     del event
+    log.debug("returning result %s" % result)
     return result
 
 
@@ -148,7 +207,7 @@ def eval_sys_eta_phi(tool, etas, phis, pt, simulation, particle='unconverted'):
 def eval_eta_slice(tool, etas, pts, ptype, only_material=False, only_up=True):
     sys_set = ROOT.CP.SystematicSet()
     tool.applySystematicVariation(sys_set)
-    nominal = eval_sys_eta_pt(tool, etas, pts, particle=ptype)
+    nominal = calibrate_eta_pt(tool, etas, pts, particle=ptype)
     all_syst = tool.recommendedSystematics()
 
     results = {}
@@ -161,16 +220,16 @@ def eval_eta_slice(tool, etas, pts, ptype, only_material=False, only_up=True):
         if only_material:
             if 'MAT' not in sys_name:
                 continue
-        logging.info("plotting sys %s", sys_name)
+        log.info("computing sys %s, %d eta samplings", sys_name, len(etas))
         sys_set = ROOT.CP.SystematicSet()
         sys_set.insert(sys)
         tool.applySystematicVariation(sys_set)
 
-        sys = eval_sys_eta_pt(tool, etas, pts, particle=ptype)
+        sys = calibrate_eta_pt(tool, etas, pts, particle=ptype)
 
         ratio = sys / nominal
 
-        ratio = np.average(ratio - 1, axis=1)
+        ratio = np.average(ratio - 1, axis=1)  # average the supersampling
         results[sys_name] = ratio
     return results
 
@@ -181,17 +240,22 @@ def beautify_sysname(sysname):
          "EG_SCALE_L1GAIN": "L1 gain",
          "EG_SCALE_PS": r"$\alpha_{PS}$",
          "EG_SCALE_S12": r"$\alpha_{1/2}$",
-         "EG_SCALE_ZEESYST": r"$Z\to ee$ calibration (sys)",
+         "EG_SCALE_S12EXTRALASTETABINRUN2": r"$\alpha_{1/2}$ [2.4-2.5]",
+         "EG_SCALE_ZEESYST": r"$Z\to ee$ cal. (sys)",
+         "EG_SCALE_ZEESTAT": r"$Z\to ee$ cal. (stat)",
          "PH_SCALE_LEAKAGEUNCONV": "Leakage unconverted",
          "EG_SCALE_MATID": "ID material",
          "EG_SCALE_MATCRYO": "Cryo material",
+         "EG_SCALE_MATPP0": "PP0 material",
+         "EG_SCALE_WTOTS1": "$w_{tots1}$ non-lin.",
          "EG_SCALE_CONVEFFICIENCY": "Conversion efficiency",
          "EG_SCALE_MATCALO": "Calo material",
          "EG_SCALE_ZEE_STAT": r"$Z\to ee$ (stat)",
          "EG_SCALE_G4": "Geant4",
-         "EG_SCALE_LEAKAGECONV": "Leakage converted",
-         "PH_SCALE_CONV_RATIUS": "Conversion radius",
-         "PH_SCALE_CONVFAKERATE": "Conversion fake rate",
+         "PH_SCALE_LEAKAGECONV": "Leakage converted",
+         "PH_SCALE_CONVRADIUS": "Conv. radius",
+         "PH_SCALE_CONVFAKERATE": "Conv. fake rate",
+         "PH_SCALE_CONVEFFICIENCY": "Conv. efficiency",
          "EG_SCALE_LARCALIB": r"$\alpha_{1/2}$ $\mu\to e$ extrap.",
          "EG_SCALE_E4SCINTILLATOR": "Scintillators",
          "EG_SCALE_LARTEMPERATURE_EXTRA2016PRE": r"Temp. 2015 $\to$ 2016",
@@ -205,14 +269,17 @@ def beautify_particle(particle):
          'unconverted': 'Unconverted photons'}
     return d.get(particle, particle).capitalize()
 
-def plot_all_syst_eta_slice(etabins, netas=3, esmodel='es2012c',
-                            decorrelation='FULL_v1', ptype='unconverted',
+def plot_all_syst_eta_slice(etabins, supersampling_eta=3, esmodel='es2012c', decorrelation='FULL_v1', ptype='unconverted', pts=np.logspace(np.log10(5E3), 6, 100),
                             basedir='plot', only_material=False, beautify_sysnames=False,
-                            sys_paper_order=False, superimpose_all=False, skip_null_sys=False, yrange=None, only_up=True, debug=False, legend_outside=False, symmetrize_labels=False):
+                            sys_order=None, superimpose_all=False, skip_null_sys=False, min_sys=-0.02, max_sys=0.02,
+                            only_up=True, debug=False, legend_outside=False, symmetrize_labels=False, log_x=False,
+                            plot_qsum=False, abs_sys=False, atlas_label='Internal'):
     tool = ROOT.CP.EgammaCalibrationAndSmearingTool("tool")
     tool.setProperty("ESModel", esmodel)
     tool.setProperty("decorrelationModel", decorrelation)
     tool.setProperty("int")("doSmearing", 0)
+    log.warning('setting randomRunNumber to 297730')
+    tool.setProperty("int")("randomRunNumber", 297730)
     if debug:
         tool.msg().setLevel(0)
 
@@ -223,38 +290,50 @@ def plot_all_syst_eta_slice(etabins, netas=3, esmodel='es2012c',
         tool_all.setProperty("ESModel", esmodel)
         tool_all.setProperty("decorrelationModel", "1NP_v1")
         tool_all.setProperty("int")("doSmearing", 0)
+        log.warning('setting randomRunNumber to 297730')
+        tool_all.setProperty("int")("randomRunNumber", 297730)
         tool_all.initialize()
 
 
-    pts = np.logspace(np.log10(5E3), 6, 100)
 
     # compute the eta-inclusive one, just to sort
+    log.info('compute sys inclusively, just to sort sys by importance')
     results = eval_eta_slice(tool, np.linspace(-2.5, 2.5, 20),
                              np.linspace(10E3, 200E3, 10),       # use this range to mimic the range in the paper
                              ptype, only_material)
     sorted_sys_name = sorted(list(results), key=lambda k: -np.max(np.abs(results[k])))
     if skip_null_sys:
         sorted_sys_name = [sys_name for sys_name in sorted_sys_name if np.sum(results[sys_name]) != 0]
-    if sys_paper_order:
-        partitions = [["EG_SCALE_PS__1up", "EG_SCALE_S12__1up", "EG_SCALE_LARCALIB__1up", "EG_SCALE_L2GAIN__1up"],
-                      ["EG_SCALE_MATID__1up", "EG_SCALE_MATCRYO__1up", "EG_SCALE_MATCALO__1up", "EG_SCALE_ZEESYST__1up"]]
-        if esmodel == "es2016PRE":
-            partitions += [["EG_SCALE_PEDESTAL__1up", "EG_SCALE_LARCALIB_EXTRA2015PRE__1up", "EG_SCALE_LARTEMPERATURE_EXTRA2016PRE__1up", "EG_SCALE_E4SCINTILLATOR__1up"]]
-
-        remainers = [item for item in sorted_sys_name if item not in list(np.array(partitions).flatten())]
+    if sys_order:
+        if sys_order == 'paper_run1':
+            partitions = [["EG_SCALE_PS__1up", "EG_SCALE_S12__1up", "EG_SCALE_LARCALIB__1up", "EG_SCALE_L2GAIN__1up"],
+                          ["EG_SCALE_MATID__1up", "EG_SCALE_MATCRYO__1up", "EG_SCALE_MATCALO__1up", "EG_SCALE_ZEESYST__1up"]]
+            if esmodel == "es2016PRE":
+                partitions += [["EG_SCALE_PEDESTAL__1up", "EG_SCALE_LARCALIB_EXTRA2015PRE__1up", "EG_SCALE_LARTEMPERATURE_EXTRA2016PRE__1up", "EG_SCALE_E4SCINTILLATOR__1up"]]
+        elif sys_order == 'paper_run2':
+            partitions = [["EG_SCALE_PS__1up", "EG_SCALE_S12__1up", "EG_SCALE_LARCALIB__1up", "EG_SCALE_LARCALIB_EXTRA2015PRE__1up", "EG_SCALE_S12EXTRALASTETABINRUN2"],
+                          ["EG_SCALE_MATID__1up", "EG_SCALE_MATCRYO__1up", "EG_SCALE_MATCALO__1up", "EG_SCALE_MATPP0__1up", "EG_SCALE_ZEESYST__1up"],
+                          ["EG_SCALE_L2GAIN__1up", "EG_SCALE_WTOTS1__1up", "EG_SCALE_PEDESTAL__1up", "EG_SCALE_E4SCINTILLATOR__1up"],
+                          ["PH_SCALE_CONVEFFICIENCY__1up", "PH_SCALE_CONVFAKERATE__1up", "PH_SCALE_CONVRADIUS__1up", "PH_SCALE_LEAKAGECONV__1up", "PH_SCALE_LEAKAGEUNCONV__1up"]]
+        flat_list = [item for sublist in partitions for item in sublist]
+        remainers = [item for item in sorted_sys_name if item not in flat_list]
         partitions = chain(partitions, partition(remainers, 4))
     else:
         partitions = partition(sorted_sys_name, 4)
     partitions = list(partitions)
 
-    for etamin, etamax in etabins:
-        etas = np.linspace(etamin, etamax, netas)
+    for etamin, etamax in tqdm.tqdm(etabins):
+        log.info('plotting eta range %.2f %.2f', etamin, etamax)
+        etas = np.linspace(etamin, etamax, supersampling_eta + 2)[1:-1]
         results = eval_eta_slice(tool, etas, pts, ptype, only_material, only_up=only_up)
+        qsum = np.sqrt((np.array(results.values()) ** 2).sum(axis=0))
 
         if superimpose_all:
             results_all = eval_eta_slice(tool_all, etas, pts, ptype, only_up=False)
 
         for ip, p in enumerate(partitions):
+            log.info('plotting %d/%d', ip + 1, len(partitions))
+
             f, ax = plt.subplots()
             if superimpose_all:
                 #max_up_down = np.max(np.abs([results_all["EG_SCALE_ALL__1down"],
@@ -263,12 +342,17 @@ def plot_all_syst_eta_slice(etabins, netas=3, esmodel='es2012c',
                                 #color='0.8', label='total')
                 #ax.plot(pts/1E3, np.sqrt(np.sum([r ** 2 for r in results.values()], axis=0)) * 100., 'r:')
                 if only_up:
-                    ax.fill_between(pts / 1E3, -results_all["EG_SCALE_ALL__1up"] * 100., results_all["EG_SCALE_ALL__1up"] * 100,
+                    if abs_sys:
+                        ax.fill_between(pts / 1E3, 0, results_all["EG_SCALE_ALL__1up"] * 100,
+                                    color='0.8', label='Total')
+                    else:
+                        ax.fill_between(pts / 1E3, -results_all["EG_SCALE_ALL__1up"] * 100., results_all["EG_SCALE_ALL__1up"] * 100,
                                     color='0.8', label='Total')
                 else:
                     ax.fill_between(pts / 1E3, results_all["EG_SCALE_ALL__1down"] * 100., results_all["EG_SCALE_ALL__1up"] * 100,
                                     color='0.8', label='Total')
-            for sys_name in p:
+            for isys, sys_name in enumerate(p):
+                color = 'C%d' % isys  # TODO: fix, use cycle
                 if sys_name not in results:
                     continue  ## TODO: FIXME
                 r = results[sys_name]
@@ -276,7 +360,13 @@ def plot_all_syst_eta_slice(etabins, netas=3, esmodel='es2012c',
                 sys_label = beautify_sysname(sys_name.replace('__1up', '')) if beautify_sysnames else sys_name
                 if not only_up:
                     sys_label += " UP"
-                ax.semilogx(pts / 1E3, r * 100., label=sys_label)
+                if abs_sys:
+                    mask_positive = r >= 0
+                    r = np.abs(r)
+                    ax.plot(pts[mask_positive] / 1E3, r[mask_positive] * 100., label=sys_label, color=color)
+                    ax.plot(pts[~mask_positive] / 1E3, r[~mask_positive] * 100., "--", color=color)
+                else:
+                    ax.plot(pts / 1E3, r * 100., label=sys_label, color=color)
 
             if not only_up:
                 ax.set_prop_cycle(None)
@@ -288,38 +378,46 @@ def plot_all_syst_eta_slice(etabins, netas=3, esmodel='es2012c',
                     r[np.isnan(r)] = 0
                     sys_label = beautify_sysname(sys_name.replace('__1down', '')) if beautify_sysnames else sys_name
                     sys_label += ' DOWN'
-                    ax.semilogx(pts / 1E3, r * 100., label=sys_label, linestyle='--')
+                    ax.plot(pts / 1E3, r * 100., label=sys_label, linestyle='--')
 
-            ax.set_xlabel('$E_T$ [GeV]', ha='right', x=1., fontsize=22)
-            ax.set_ylabel('Signed uncertainty [%]', ha='right', y=1., fontsize=22)
-            ax.tick_params(axis='both', which='major', labelsize=20)
+            if plot_qsum:
+                ax.plot(pts / 1E3, qsum * 100, label='quadrature sum', linestyle=':')
 
-            ax.axis('tight')
-            if yrange is None:
-                if only_material:
-                    vmax = 1.
-                else:
-                    vmax = max(2, np.max(np.abs(ax.get_ylim())))
-                ax.set_ylim(-vmax, vmax)
+            ax.set_xlabel('$E_T$ [GeV]', ha='right', x=1., fontsize=19)
+            if abs_sys:
+                ax.set_ylabel('Uncertainty [%]', ha='right', y=1., fontsize=19)
             else:
-                ax.set_ylim(*yrange)
+                ax.set_ylabel('Signed uncertainty [%]', ha='right', y=1., fontsize=19)
+
+            ax.tick_params(axis='both', which='major', labelsize=17)
+
+            ax.axis('tight')
+
+            if max_sys is None and min_sys is None:
+                max_sys = max(2, np.max(np.abs(ax.get_ylim())))
+                min_sys = -max_sys
+
+            ax.set_ylim(min_sys * 100, max_sys * 100)
 
             if legend_outside:
                 ax.legend(bbox_to_anchor=(0., 1., 1, 0.2), mode='expand', borderaxespad=0.,
                           loc=3, frameon=True, fontsize=17 if only_up else 14, borderpad=1, ncol=1 if only_up else 2)
                 f.subplots_adjust(top=0.65)
-                plot_ATLAS(f, 0.2, 0.58, label='Internal')
+                plot_ATLAS(f, 0.2, 0.58, label=atlas_label)
                 f.text(0.2, 0.2, beautify_particle(ptype), transform=ax.transAxes, fontsize=16)
                 f.text(0.2, 0.25, r'$%.2f < \eta < %.2f$' % (etamin, etamax), transform=ax.transAxes, fontsize=16)
             else:
-                ax.legend(loc=1, frameon=False, fontsize=17 if only_up else 14, borderpad=1, ncol=1 if only_up else 2)
+                ax.legend(loc=1, frameon=False, fontsize=13 if only_up else 9, borderpad=1, ncol=1 if only_up else 2)
+
+                plot_ATLAS(f, 0.16, 0.80, label=atlas_label, fontsize=19)
+                f.text(0.16, 0.74, beautify_particle(ptype), transform=ax.transAxes, fontsize=16)
+                f.text(0.16, 0.68, r'$%.2f < \eta < %.2f$' % (etamin, etamax), transform=ax.transAxes, fontsize=16)
 
-                plot_ATLAS(f, 0.2, 0.85, label='Internal', fontsize=21)
-                f.text(0.2, 0.80, beautify_particle(ptype), transform=ax.transAxes, fontsize=16)
-                f.text(0.2, 0.75, r'$%.2f < \eta < %.2f$' % (etamin, etamax), transform=ax.transAxes, fontsize=16)
+            if log_x:
+                ax.set_xscale('log')
 
             for extension in extensions:
-                f.savefig(os.path.join(basedir, "%s_%s_%.2f_%.2f_%d.%s" % (ptype, decorrelation, etamin, etamax, ip, extension)))
+                f.savefig(os.path.join(basedir, "%s_%s_%s_%.2f_%.2f_%d.%s" % (ptype, esmodel, decorrelation, etamin, etamax, ip, extension)), bbox_inches='tight')
             plt.close(f)
 
 
@@ -353,9 +451,9 @@ def plot_all_Zee_syst(etas, pt=100E3, basedir='plots'):
 
     tools = [tool_es2012c, tool_es2015PRE_notemp, tool_es2015PRE]
 
-    nominal_es2012c = eval_sys_eta_pt(tool_es2012c, etas, [pt], particle='electron')[0]
-    nominal_es2015PRE = eval_sys_eta_pt(tool_es2015PRE, etas, [pt], particle='electron')[0]
-    nominal_es2015PRE_notemp = eval_sys_eta_pt(tool_es2015PRE_notemp, etas, [pt], particle='electron')[0]
+    nominal_es2012c = calibrate_eta_pt(tool_es2012c, etas, [pt], particle='electron')[0]
+    nominal_es2015PRE = calibrate_eta_pt(tool_es2015PRE, etas, [pt], particle='electron')[0]
+    nominal_es2015PRE_notemp = calibrate_eta_pt(tool_es2015PRE_notemp, etas, [pt], particle='electron')[0]
 
     # up variations
     sys = ROOT.CP.SystematicVariation('EG_SCALE_ZEESYST', 1)
@@ -365,9 +463,9 @@ def plot_all_Zee_syst(etas, pt=100E3, basedir='plots'):
     for tool in tools:
         tool.applySystematicVariation(sys_set)
 
-    sys_up_es2012c = eval_sys_eta_pt(tool_es2012c, etas, [pt], particle='electron')[0]
-    sys_up_es2015PRE = eval_sys_eta_pt(tool_es2015PRE, etas, [pt], particle='electron')[0]
-    sys_up_es2015PRE_notemp = eval_sys_eta_pt(tool_es2015PRE_notemp, etas, [pt], particle='electron')[0]
+    sys_up_es2012c = calibrate_eta_pt(tool_es2012c, etas, [pt], particle='electron')[0]
+    sys_up_es2015PRE = calibrate_eta_pt(tool_es2015PRE, etas, [pt], particle='electron')[0]
+    sys_up_es2015PRE_notemp = calibrate_eta_pt(tool_es2015PRE_notemp, etas, [pt], particle='electron')[0]
 
     ratio_sys_up_es2012c = sys_up_es2012c / nominal_es2012c - 1
     ratio_sys_up_es2015PRE = sys_up_es2015PRE / nominal_es2015PRE - 1
@@ -381,9 +479,9 @@ def plot_all_Zee_syst(etas, pt=100E3, basedir='plots'):
     for tool in tools:
         tool.applySystematicVariation(sys_set)
 
-    sys_down_es2012c = eval_sys_eta_pt(tool_es2012c, etas, [pt], particle='electron')[0]
-    sys_down_es2015PRE = eval_sys_eta_pt(tool_es2015PRE, etas, [pt], particle='electron')[0]
-    sys_down_es2015PRE_notemp = eval_sys_eta_pt(tool_es2015PRE_notemp, etas, [pt], particle='electron')[0]
+    sys_down_es2012c = calibrate_eta_pt(tool_es2012c, etas, [pt], particle='electron')[0]
+    sys_down_es2015PRE = calibrate_eta_pt(tool_es2015PRE, etas, [pt], particle='electron')[0]
+    sys_down_es2015PRE_notemp = calibrate_eta_pt(tool_es2015PRE_notemp, etas, [pt], particle='electron')[0]
 
     ratio_sys_down_es2012c = sys_down_es2012c / nominal_es2012c - 1
     ratio_sys_down_es2015PRE = sys_down_es2015PRE / nominal_es2015PRE - 1
@@ -394,7 +492,7 @@ def plot_all_Zee_syst(etas, pt=100E3, basedir='plots'):
     sys_set = ROOT.CP.SystematicSet()
     sys_set.insert(sys)
     tool_es2015PRE.applySystematicVariation(sys_set)
-    stat_up_es2015PRE = eval_sys_eta_pt(tool_es2015PRE, etas, [pt], particle='electron')[0]
+    stat_up_es2015PRE = calibrate_eta_pt(tool_es2015PRE, etas, [pt], particle='electron')[0]
     ratio_stat_up = stat_up_es2015PRE / nominal_es2015PRE - 1
 
 
@@ -403,7 +501,7 @@ def plot_all_Zee_syst(etas, pt=100E3, basedir='plots'):
     sys_set = ROOT.CP.SystematicSet()
     sys_set.insert(sys)
     tool_es2015PRE.applySystematicVariation(sys_set)
-    stat_down_es2015PRE = eval_sys_eta_pt(tool_es2015PRE, etas, [pt], particle='electron')[0]
+    stat_down_es2015PRE = calibrate_eta_pt(tool_es2015PRE, etas, [pt], particle='electron')[0]
     ratio_stat_down = stat_down_es2015PRE / nominal_es2015PRE - 1
 
     ratio_full_down = -np.sqrt(ratio_stat_down ** 2 + ratio_sys_down_es2015PRE ** 2)
@@ -459,19 +557,19 @@ def plot_all_syst_fixed_pt(tools, names, labels, pt=100E3, ptype='unconverted',
         tool.applySystematicVariation(empty_set)
     etas_histo = np.linspace(-5, 5, 101, True)
     etas = 0.5 * (etas_histo[1:] + etas_histo[:-1])
-    nominals = [eval_sys_eta_pt(tool, etas, [pt], particle=ptype)[0] for tool in tools]
+    nominals = [calibrate_eta_pt(tool, etas, [pt], particle=ptype)[0] for tool in tools]
     all_syst = tools[0].recommendedSystematics()
     for sys in all_syst:
         sys_name = sys.name()
         sys_set = ROOT.CP.SystematicSet()
         sys_set.insert(sys)
-        logging.info("plotting sys %s %s", sys_name, ptype)
+        log.info("plotting sys %s %s", sys_name, ptype)
 
         f, ax = plt.subplots()
 
         for tool, nominal, name, label in zip(tools, nominals, names, labels):
             tool.applySystematicVariation(sys_set)
-            sys = eval_sys_eta_pt(tool, etas, [pt], particle=ptype)[0]
+            sys = calibrate_eta_pt(tool, etas, [pt], particle=ptype)[0]
             ratio = sys / nominal - 1
             ax.plot(etas, ratio * 100, label=label)
             histo = values2histo(name + "_" + sys_name, label, etas_histo, ratio * 100)
@@ -486,53 +584,251 @@ def plot_all_syst_fixed_pt(tools, names, labels, pt=100E3, ptype='unconverted',
             f.savefig(os.path.join(basedir, "%s_%s_pt_%.2f.%s" % (ptype, sys_name, pt / 1E3, extension)))
         plt.close(f)
 
+def get_property_from_tool(tool, property_name):
+    # really?
+    result = ROOT.std.string()
+    status = tool.getPropertyMgr().getProperty(property_name).getString(result)
+    if not status.isSuccess():
+        raise ValueError("cannot find property %s in tool %s" % (property_name, tool))
+    return str(ss)[1:-1]
+
+
+def compute_or_read_sys(tool, ptypes, eta_edges, pt_edges):
+    empty_set = ROOT.CP.SystematicSet()
+
+    eta_edges = np.asarray(eta_edges)
+    pt_edges = np.asarray(pt_edges)
+
+    # TODO: replace midpoints with supersampling
+    eta_midpoints = 0.5 * (eta_edges[1:] + eta_edges[:-1])
+    pt_midpoints = 0.5 * (pt_edges[1:] + pt_edges[:-1])
+
+    log.debug("getting list of systematics")
+    all_syst = tool.recommendedSystematics()
+    log.debug("%d systematics found", len(all_syst))
+
+    results = {ptype: {} for ptype in ptypes}
+
+    with tqdm.tqdm(total=len(ptypes) * (len(all_syst) + 1), leave=False) as pbar:
+        for iptype, ptype in enumerate(ptypes):
+            log.debug("computing for particle=%s", ptype)
+            tool.applySystematicVariation(empty_set)
+            log.debug("computing nominal energies for eta=%s, pt=%s, particle=%s", eta_midpoints, pt_midpoints, ptype)
+
+            values_nominal = calibrate_eta_pt(tool, eta_midpoints, pt_midpoints, particle=ptype)
+            pbar.update(1)
+
+            for isys, sys in enumerate(all_syst):
+                sys_name = sys.name()
+                sys_set = ROOT.CP.SystematicSet()
+                sys_set.insert(sys)
+                tool.applySystematicVariation(sys_set)
+                values_sys = calibrate_eta_pt(tool, eta_midpoints, pt_midpoints, particle=ptype)
+                ratio = values_sys / values_nominal - 1
+
+                results[ptype][sys_name] = ratio
+                pbar.update(1)
+
+    return results
+
+@timed
+def compare_sys(esmodels=None, ptypes=None, decorrelation='FULL_ETACORRELATED_v1', eta_edges=None, pt_edges=None, basedir='plots', smearing=False, only_up=True, abs_sys=False, log_x=False):
+    esmodels = esmodels or ['es2012c']
+    ptypes = ptypes or ['electron']
+    if pt_edges is None:
+        pt_edges = np.linspace(0, 100, 5)
+    if eta_edges is None:
+        eta_edges = np.array([0, 0.6, 1.0, 1.37, 1.55, 1.82, 2.47])
+    pt_edges = np.asarray(pt_edges)
+    eta_edges = np.asarray(eta_edges)
+
+    pt_midpoints = 0.5 * (pt_edges[1:] + pt_edges[:-1])
+    eta_midpoints = 0.5 * (eta_edges[1:] + eta_edges[:-1])
+    log.info('comparing systematics for esmodels=%s, ptypes=%s, #pt-bins=%d, #eta-bins=%d' % (esmodels, ptypes, len(pt_edges) - 1, len(eta_edges) - 1))
+
+    effects = {}
+    for esmodel in esmodels:
+        log.info("creating tool for %s" % esmodel)
+        tool = ROOT.CP.EgammaCalibrationAndSmearingTool("tool")
+        tool.setProperty("ESModel", esmodel)
+        tool.setProperty("decorrelationModel", decorrelation)
+        tool.setProperty("int")("randomRunNumber", 297730)
+        if not smearing:
+            tool.setProperty("int")("doSmearing", 0)
+        tool.initialize()
+
+        log.info('computing systematics for %s' % esmodel)
+
+        sys_values = compute_or_read_sys(tool, ptypes, eta_edges, pt_edges)
+        effects[esmodel] = sys_values
+
+        log.debug("delete tool")
+        del tool
+
+    def sorting_function(sys):
+        return max(np.abs(effects[esmodel][ptype].get(sys, np.zeros(1))).max() for esmodel in esmodels for ptype in ptypes)
+
+
+    all_sys = set()
+    for effects_esmodel in effects.values():
+        for effects_particle in effects_esmodel.values():
+            all_sys |= set(effects_particle.keys())
+
+    if only_up:
+        all_sys = set(s for s in all_sys if '__1up' in s)
+    all_sys = set(s for s in all_sys if 'RESOLUTION' not in s)
+    sorted_sys = sorted(all_sys, key=sorting_function, reverse=True)
+
+    log.info("plot")
+    log.info("sorted sys: %s" % sorted_sys)
+    colors = sns.color_palette("Set2", len(esmodels))
+    line_styles = '--', ':', '-'
+
+    for ptype, (ieta, (eta1, eta2)) in tqdm.tqdm(product(ptypes, enumerate(pairwise(eta_edges))), total=len(ptypes) * (len(eta_edges) - 1), desc='plotting', leave=False):
+        nsub_x, nsub_y = divide_square(len(sorted_sys))
+        fig, axs = plt.subplots(nsub_x, nsub_y, figsize=(14, 8), sharex=True)
+        if hasattr(axs, "flat"):
+            axs = axs.flat
+        else:
+            axs = [axs]
+        for ax, sys in zip(axs, sorted_sys):
+            for iesmodel, esmodel in enumerate(esmodels):
+                if sys in effects[esmodel][ptype]:
+                    values = effects[esmodel][ptype][sys][:, ieta]
+                    if abs_sys:
+                        values = np.abs(values)
+                else:
+                    values = np.zeros_like(pt_midpoints)
+                ax.plot(pt_midpoints / 1E3, values * 100, label=esmodel,
+                        ls=line_styles[iesmodel],
+                        color=colors[iesmodel])
+
+            ylimits = [0.01, 0.3, 0.7, 2.1, 5]  # possible y-axis maxima
+            for ylimit in ylimits:
+                if max(np.abs(values)) * 100 < ylimit:
+                    if abs_sys:
+                        ax.set_ylim(0, ylimit)
+                    else:
+                        ax.set_ylim(-ylimit, ylimit)
+                    break
+
+            title = sys.replace('EG_SCALE_', '').replace('PH_SCALE_', '').replace('__1up', '')
+            if len(title) > 17:
+                title = title[:17] + "..."
+            ax.set_title(title, fontsize=9)
+            ax.yaxis.set_major_locator(MaxNLocator(6, prune='both'))
+            ax.xaxis.set_major_locator(MaxNLocator(4))
+            ax.tick_params(axis='both', which='major', labelsize=8)
+            ax.tick_params(axis='y', which='minor', left='off', right='off')
+
+            if log_x:
+                ax.set_xscale('log')
+            ax.set_ylabel('')
+
+        for ax in axs:
+            if ax.is_last_row():
+                ax.set_xlabel('$p_{T}$ [GeV]', fontsize=11)
+            if ax.is_first_col():
+                ax.set_ylabel("effect [%]", fontsize=11)
+        fig.subplots_adjust(wspace=0.4, hspace=0.27, bottom=0.15)
+
+        handles = [mlines.Line2D([], [], color=colors[i], ls=line_styles[i]) for i in range(len(esmodels))]
+        labels = esmodels
+        fig.legend(handles,
+                   labels,
+                   ncol=len(esmodels), loc='upper center',
+                   bbox_to_anchor=(0.1, -0.14, 0.7, 0.2),
+                   mode='expand',
+                   borderaxespad=0.
+        )
+
+        fig.suptitle(r'%s $|\eta|\in [%.2f, %.2f]$' % (ptype, eta1, eta2), fontsize=14)
+
+        figname = 'compare_sys_%s_eta_%.2f_%.2f_vs_pT' % (ptype, eta1, eta2)
+        log.info("saving %s" % figname)
+        for extension in extensions:
+            fig.savefig(os.path.join(basedir, "%s.%s" % (figname, extension)))
+        plt.close(fig)
+
 
-def plot_all_syst(esmodel='es2012c', decorrelation='FULL_v1', ptype='unconverted', basedir='plots'):
+@timed
+def plot_all_syst_eta_pt(esmodel='es2012c', decorrelation='FULL_v1', ptype='unconverted',
+                         basedir='plots', eta_range=None, pt_range=None, log_pt=False, abs_sys=False, only_up=False, sys_filters=None, min_value=None, max_value=None):
+    """
+    Plot a 2D map (eta, pT) of the value of the systematic in %
+    """
+    log.debug("creating tool")
     tool = ROOT.CP.EgammaCalibrationAndSmearingTool("tool")
     tool.setProperty("ESModel", esmodel)
     tool.setProperty("decorrelationModel", decorrelation)
     tool.setProperty("int")("doSmearing", 0)
+    log.warning('setting randomRunNumber to 297730')
+    tool.setProperty("int")("randomRunNumber", 297730)
     tool.initialize()
 
-    etas = np.arange(-3, 3, 0.1)
-    pts = np.logspace(4, 7, 100)
-    X, Y = np.meshgrid(etas, pts)
-    nominal = eval_sys_eta_pt(tool, etas, pts, particle=ptype)
+    etas = eta_range if eta_range is not None else np.arange(-3, 3, 0.1)
+    pts = pt_range if pt_range is not None else np.logspace(4, 7, 100)
+
+    nominal = calibrate_eta_pt(tool, etas, pts, particle=ptype)
 
     all_syst = tool.recommendedSystematics()
-    for sys in all_syst:
+
+    nplotted = 0
+
+    for sys in tqdm.tqdm(all_syst):
         sys_name = sys.name()
         if "RESOLUTION" in sys_name:
+            log.debug('skipping %s', sys_name)
+            continue
+        if only_up and "1up" not in sys_name:
+            log.debug('skipping %s', sys_name)
             continue
-        logging.info("plotting sys %s", sys_name)
+        if sys_filters is not None:
+            if not any(fnmatch(sys_name, sys_filter) for sys_filter in sys_filters):
+                log.debug('skipping %s', sys_name)
+                continue
+        nplotted += 1
+        log.info("computing sys %s", sys_name)
 
         sys_set = ROOT.CP.SystematicSet()
         sys_set.insert(sys)
         tool.applySystematicVariation(sys_set)
 
-        sys = eval_sys_eta_pt(tool, etas, pts, particle=ptype)
+        sys = calibrate_eta_pt(tool, etas, pts, particle=ptype)
 
         ratio = sys / nominal
-        f, ax = plt.subplots()
         ratio[nominal == 0] = 1
         # TODO: check why nan
         ratio[np.isnan(ratio)] = 1
-        vmax = np.percentile(np.abs(ratio - 1), 90)
+        ratio = ratio - 1
+        vmax = max_value or np.percentile(np.abs(ratio), 95)
+        vmin = min_value or -vmax
+        if abs_sys:
+            ratio = np.abs(ratio)
 
-        p = ax.pcolormesh(etas, pts / 1E3, (ratio - 1) * 100., vmin=-vmax * 100, vmax=vmax * 100)
-        # ax.contour(X, Y / 10E3, ratio - 1, levels=[0], colors='k', linercParamss='dashed')
-        ax.set_title(sys_name)
-        ax.set_xlabel('$\eta$')
-        ax.set_ylabel('$p_T$ [GeV]')
-        ax.set_yscale('log')
+        f, ax = plt.subplots()
+        p = ax.pcolormesh(etas, pts / 1E3, ratio * 100., vmin=-vmax * 100, vmax=vmax * 100)
+        ax.set_title("%s\n%s\n%s" % (ptype, esmodel, sys_name), loc='left')
+        ax.set_xlabel('$\eta$', x=1., ha='right')
+        ax.set_ylabel('$p_T$ [GeV]', y=1., ha='right')
+        if log_pt:
+            ax.set_yscale('log')
         cb = f.colorbar(p)
-        cb.ax.set_ylabel('ratio to nominal [%]')
+        cb.ax.set_ylabel('systematic effect [%]')
         for extension in extensions:
-            f.savefig(os.path.join(basedir, "%s_%s_%s.%s" % (ptype, decorrelation, sys_name, extension)))
+            f.savefig(os.path.join(basedir, "%s_%s_%s_%s.%s" % (ptype, esmodel, decorrelation, sys_name, extension)))
         plt.close(f)
 
+    if nplotted == 0:
+        log.warning('no systematic plotted')
+    else:
+        log.info('%d systematic plotted' % nplotted)
+
 
-def plot_all_scales(esmodels, basedir, labels=None, etas=np.arange(-4.5, 4.5, 0.01), add_patch=False):
+@timed
+def plot_all_scales(esmodels, basedir, labels=None, etas=np.arange(-4.5, 4.5, 0.01), add_patch=False, debug=False):
+    log.info("comparing scale factors %s" % esmodels)
+    log.warning("<mu> fixed")
     labels = labels or esmodels
     scales = {}
     to_legend = []
@@ -549,11 +845,13 @@ def plot_all_scales(esmodels, basedir, labels=None, etas=np.arange(-4.5, 4.5, 0.
             value_properties = esmodel[2]
             type_properties = esmodel[3]
             esmodel = esmodel[0]
-        print (esmodel, key_properties)
 
         tool_with = ROOT.CP.EgammaCalibrationAndSmearingTool("tool_with")
         tool_without = ROOT.CP.EgammaCalibrationAndSmearingTool("tool_without")
+
         for tool in tool_with, tool_without:
+            if debug:
+                tool.msg().setLevel(0)
             tool.setProperty("ESModel", esmodel)
             tool.setProperty("int")("doSmearing", 0)
             for k, v, t in zip(key_properties, value_properties, type_properties):
@@ -565,10 +863,9 @@ def plot_all_scales(esmodels, basedir, labels=None, etas=np.arange(-4.5, 4.5, 0.
         tool_with.initialize()
         tool_without.initialize()
 
-
-
         event = ROOT.xAOD.TEvent()
         factory = ROOT.EgammaFactory()
+        log.warning("using eveninfo 266904")
         ei = factory.create_eventinfo(False, 266904)
 
         for eta in etas:
@@ -580,10 +877,10 @@ def plot_all_scales(esmodels, basedir, labels=None, etas=np.arange(-4.5, 4.5, 0.
         scales[label] = np.array(energy_without) / np.array(energy_with) - 1
 
     f, ax = plt.subplots()
-    for k, v in scales.items():
+    for k, v in scales.iteritems():
         ax.plot(etas, v * 100, label=k)
-    ax.set_xlabel("$\eta$")
-    ax.set_ylabel("energy without scale factors / energy with scale factors - 1 [%]")
+    ax.set_xlabel("$\eta$", fontsize=15, x=1, ha='right')
+    ax.set_ylabel("energy without scale factors / energy with scale factors - 1 [%]", fontsize=10)
     ax.grid()
 
     if add_patch:
@@ -600,6 +897,23 @@ def plot_all_scales(esmodels, basedir, labels=None, etas=np.arange(-4.5, 4.5, 0.
         f.savefig(os.path.join(basedir, "scales.%s" % extension))
     plt.close(f)
 
+    # ratio plot
+    reference = labels[0]
+    ratio = {label: scales[label] - scales[reference] for label in labels}
+    f, ax = plt.subplots()
+    for k, v in ratio.iteritems():
+        ax.plot(etas, v, label=k)
+    ax.set_xlabel("$\eta$", fontsize=15, x=1, ha='right')
+    ax.set_ylabel("scales - scales (%s)" % reference, fontsize=10)
+    ax.grid()
+    ax.legend()
+    f.tight_layout()
+
+    for extension in extensions:
+        f.savefig(os.path.join(basedir, "scales_difference_%s.%s" % (reference, extension)))
+    plt.close(f)
+
+
 
 def plot_all_cterms(esmodels, basedir, labels=None, etas=np.arange(-4.5, 4.5, 0.01)):
     labels = labels or esmodels
@@ -625,14 +939,14 @@ def plot_all_cterms(esmodels, basedir, labels=None, etas=np.arange(-4.5, 4.5, 0.
             el = factory.create_electron(eta, 0.1, 40E3)
             en_without = tool_without.getEnergy(el, ei)
             ratios = np.zeros(1000)
-            for repetition in range(1000):
+            for repetition in xrange(1000):
                 en_with = tool_with.getEnergy(el, ei)
                 ratios[repetition] = en_with / en_without
             cterms.append(np.std(ratios))
         cterms_all_models[label] = cterms
 
     f, ax = plt.subplots()
-    for k, v in cterms_all_models.items():
+    for k, v in cterms_all_models.iteritems():
         ax.plot(etas, v, label=k)
     ax.set_xlabel("$\eta$")
     ax.set_ylabel("std (energy with additional cterm / energy without)")
@@ -652,11 +966,11 @@ def plot_all_cterms(esmodels, basedir, labels=None, etas=np.arange(-4.5, 4.5, 0.
 
 def compare_two_tools_eta(tool1, tool2, pt, simulation, name, basedir, title, particle='unconverted'):
     etas = np.arange(-4.5, 4.5, 0.01)
-    r1 = eval_sys_eta_pt(tool1, etas, [pt], simulation, particle)
-    r2 = eval_sys_eta_pt(tool2, etas, [pt], simulation, particle)
+    r1 = calibrate_eta_pt(tool1, etas, [pt], simulation, particle)
+    r2 = calibrate_eta_pt(tool2, etas, [pt], simulation, particle)
     r = r1 / r2 - 1
     r = r[0]
-    print (r)
+    print(r)
     f, ax = plt.subplots()
     r = np.nan_to_num(r)
     ax.plot(etas, r * 100)
@@ -693,8 +1007,8 @@ def compare_two_tools_eta_phi(tool1, tool2, pt, simulation, name, basedir, title
 def compare_two_tools_eta_pt(tool1, tool2, simulation, name, basedir, title, particle='unconverted'):
     etas = np.arange(-4.5, 4.5, 0.05)
     pts = np.logspace(3.2, 6, 50)
-    r1 = eval_sys_eta_pt(tool1, etas, pts, simulation, particle)
-    r2 = eval_sys_eta_pt(tool2, etas, pts, simulation, particle)
+    r1 = calibrate_eta_pt(tool1, etas, pts, simulation, particle)
+    r2 = calibrate_eta_pt(tool2, etas, pts, simulation, particle)
     r = r1 / r2 - 1
     f, ax = plt.subplots()
     r = np.nan_to_num(r)
@@ -838,20 +1152,21 @@ def plot_resolution_eta_pt(basedir, tool, pts, etas, ptype, title):
 
 
 def plot_resolution_error(basedir, **kwargs):
-    esmodels = kwargs["esmodels"] or ('es2012c', 'es2015PRE', 'es2015PRE_res_improved', 'es2016PRE')
+    esmodels = kwargs["esmodels"] or ('es2012c', 'es2015PRE', 'es2015PRE_res_improved', 'es2016PRE', 'es2017')
     if kwargs["eta_bins"] is not None:
         eta_bins = pairwise(kwargs["eta_bins"])
     else:
         eta_bins = (0, 0.4), (0.4, 0.6), (0.6, 1.37), (1.52, 1.8), (1.8, 2.37)
     for esmodel in esmodels:
-        logging.debug("plotting resolution error for %s" % esmodel)
+        log.debug("plotting resolution error for %s" % esmodel)
         tool = ROOT.AtlasRoot.egammaEnergyCorrectionTool()
         if kwargs['debug']:
             tool.msg().setLevel(0)
         tool.setESModel(getattr(ROOT.egEnergyCorr, esmodel))
         tool.initialize()
         for particle in ('electron', 'converted', 'unconverted'):
-            for eta_min, eta_max in eta_bins:
+            log.info('plotting resolution %s', particle)
+            for eta_min, eta_max in tqdm.tqdm(eta_bins):
                 plot_resolution_error_bin(eta_min, eta_max, particle, esmodel, basedir, tool=tool, **kwargs)
 
 
@@ -891,26 +1206,39 @@ def plot_resolution_error_bin(eta_min, eta_max, particle, esmodel, basedir, tool
     all_errors = [{}, {}]  # up and down
 #                  ,--,
 
-    pt_range = np.linspace(10E3, 800E3, 100)
+    pt_range = kwargs.get('pt_bins')
+    if pt_range is None:
+        pr_range = np.linspace(10E3, 2000E3, 100)
+
     nsamples_eta = kwargs['super_sampling_eta'] or 5
     eta_range = np.linspace(eta_min, eta_max, nsamples_eta + 2)[1:-1]
 
+
+    only_up = True
+
     for side, errors, variations_name in zip(("up", "down"), all_errors, (variations_name_up, variations_name_down)):
+        if only_up and side == 'down':
+            continue
         quadrature_sum = np.zeros((len(pt_range), len(eta_range)))
-        for variation_name, variation_id in variations_name.items():
+        for variation_name, variation_id in variations_name.iteritems():
             errors_var_pt_eta = np.zeros((len(pt_range), len(eta_range)))
             for ipt, pt in enumerate(pt_range):
                 for ieta, eta in enumerate(eta_range):
                     energy = pt * np.cosh(eta)
-                    logging.debug("evaluating systematics %s in eta=%.2f pt=%.2f on resolution" % (variation_name, eta, pt))
+                    log.debug("evaluating systematics %s in eta=%.2f pt=%.2f on resolution" % (variation_name, eta, pt))
                     errors_var_pt_eta[ipt, ieta] = tool.getResolutionError(energy, eta, eta, ptype, variation_id)
             errors[variation_name] = errors_var_pt_eta.mean(axis=1)  # average over different eta points inside the eta-bin
+            if kwargs['abs_sys']:
+                errors[variation_name] = np.abs(errors[variation_name])
 
     sorted_keys_up = sorted(variations_name_up.keys(), key=lambda x: np.abs(all_errors[0][x].mean()))
-    totals = [np.sqrt(np.sum(e ** 2 for k, e in errors.items() if "all " not in k)) for errors in all_errors]
+    totals = [np.sqrt(np.sum(e ** 2 for k, e in errors.iteritems() if "all " not in k)) for errors in all_errors]
 
     fig, ax = plt.subplots()
-    ax.fill_between(pt_range / 1E3, all_errors[0]['all up'], all_errors[1]['all down'], color='0.8')
+    if only_up:
+        ax.fill_between(pt_range / 1E3, 0, all_errors[0]['all up'], color='0.8')
+    else:
+        ax.fill_between(pt_range / 1E3, all_errors[0]['all up'], all_errors[1]['all down'], color='0.8')
 #    ax.fill_between(pt_range / 1E3, totals[0], -totals[-1], color='0.8')
 #    totals[1] *= -1
 
@@ -918,6 +1246,8 @@ def plot_resolution_error_bin(eta_min, eta_max, particle, esmodel, basedir, tool
     props = mpl.rcParams["axes.prop_cycle"]
 
     for side, errors, total in zip(('up', 'down'), all_errors, totals):
+        if only_up and side == 'down':
+            continue
         #ax.plot(pt_range / 1E3, total, label='sum %s' % side, color='k')
         ax.plot(pt_range / 1E3, errors['all %s' % side], 'k', label='all %s' % side)
         colors_iter = cycle(colors)
@@ -932,38 +1262,106 @@ def plot_resolution_error_bin(eta_min, eta_max, particle, esmodel, basedir, tool
                 linestyle = ":"
             ax.plot(pt_range / 1E3, v, linestyle, label=k, color=next(colors_iter))
 
+    fig.text(0.16, 0.73, beautify_particle(particle), transform=ax.transAxes, fontsize=15)
+    fig.text(0.16, 0.67, r'$%.2f < \eta < %.2f$' % (eta_min, eta_max), transform=ax.transAxes, fontsize=15)
+
+    ax.set_title("%s" % esmodel)
+    ax.set_ylabel('relative resolution error [%]', ha='right', y=1., fontsize=19)
+    ax.set_xlabel('$E_T$ [GeV]', ha='right', x=1., fontsize=19)
+    if kwargs['abs_sys']:
+        ax.set_ylim(0, 0.6)
+    else:
+        ax_set_ylim(-1.7, 1.7)
+    ax.set_xlim(np.min(pt_range) / 1E3, np.max(pt_range) / 1E3)
 
-    ax.set_title("%s $\eta\in$ [%.2f-%.2f] - %s" % (particle, eta_min, eta_max, esmodel))
-    ax.set_ylabel('relative resolution error', ha='right', y=1.)
-    ax.set_xlabel('$p_T$ [GeV]', ha='right', x=1.)
-    ax.set_ylim(-0.7, 0.7)
     fig.subplots_adjust(bottom=0.35)
 
     ax.legend(loc=3, bbox_to_anchor=(0., -0.5, 1, 0.2), mode="expand",
               ncol=4, borderaxespad=0., fontsize=10)
 
-    #plot_ATLAS(fig, 0.6, 0.75, 'Internal')
+    plot_ATLAS(fig, 0.16, 0.8, 'Internal', fontsize=19)
 
-    ax.grid()
+    if kwargs['grid']:
+        ax.grid()
     filename = os.path.join(basedir, 'error_relresolution_%s_%s_eta%.2f-%.2f' % (esmodel, particle, eta_min, eta_max))
     for ext in 'png', 'pdf':
-        fig.savefig(filename + "." + ext)
+        fig.savefig(filename + "." + ext, bbox_inches='tight')
     plt.close(fig)
 
+def list_systematics(esmodels, decorrelation='FULL_ETACORRELATED_v1'):
+    if type(esmodels) is str:
+        esmodels = [esmodels]
+    elif esmodels is None:
+        log.warning('no esmodel specified, using es2012c')
+        esmodels = ['es2012c']
+    syslist_esmodel = {}
+    for esmodel in esmodels:
+        log.debug("creating tool for %s" % esmodel)
+        tool = ROOT.CP.EgammaCalibrationAndSmearingTool("tool")
+        tool.setProperty("ESModel", esmodel)
+        tool.setProperty("decorrelationModel", decorrelation)
+        tool.initialize()
+        syslist_esmodel[esmodel] = [s.name() for s in systematics_from_tool(tool, only_scale=False)]
+
+    for esmodel, sys_list in syslist_esmodel.iteritems():
+        print("esmodel: %s %s UP variations" % (esmodel, len(sys_list)))
+        for sysname in sys_list:
+            print("   {:10s}".format(sysname))
 
+    if len(esmodels) > 1:
+        log.info('comparing the %s esmodels' % len(esmodels))
+        all_sys = set([item for sublist in syslist_esmodel.values() for item in sublist])
+        print(' ' * 40 + ''.join(' [%d] ' % i for i in range(len(esmodels))))
+        for sysname in sorted(all_sys):
+            cross = ''.join(['  x  ' if sysname in syslist_esmodel[esmodel] else '     ' for esmodel in esmodels])
+            print(('{:40s}'.format(sysname) + cross))
+        for iesmodel, esmodel in enumerate(esmodels):
+            print("[%d] = %s" % (iesmodel, esmodel))
+
+
+@timed
 def main():
     from argparse import ArgumentParser, RawDescriptionHelpFormatter
     parser = ArgumentParser(formatter_class=RawDescriptionHelpFormatter,
-                            epilog="to produce paper plots for systematics: python plot.py sys_eta_slices --beautify-sysnames --sys-paper-order --superimpose-all --skip-null-sys --esmodels es2016PRE --yrange -1 2.0 --symmetrize-labels")
-    parser.add_argument('action', choices=['uA2MeV', 'zee', 'material', 'scale', 'cterm', 'all', 'gain', 'uniformity',
-                                           'sys_fixed_pt', 'sys_eta_slices', 'all_sys', 'resolution', 'fast', 'resolution-err'],
+                            epilog="""
+to produce paper plots for systematics:
+    python plot.py sys_eta_slices --beautify-sysnames --sys-order paper_run1 --superimpose-all --skip-null-sys --esmodels es2016PRE --min-sys-value -0.01 --max-sys-value 0.02 --symmetrize-labels  --pt-bins-logspace 5E3 1E6 100
+
+    # python plot.py sys_eta_slices --beautify-sysnames --sys-order paper_run1 --superimpose-all --skip-null-sys --esmodels es2016data_mc15c_summer_improved --min-sys-value -0.01 --max-sys-value 0.02 --symmetrize-labels  --pt-bins-logspace 5E3 1E6 100
+
+to produce paper plot for resolution (the name of the esmodels here are the ones used by the internal class)
+   python plot.py resolution-err --esmodels es2017 --abs-sys --pt-bins-linspace 5E3 200E3 200
+
+
+to compare systematics between tools vs pT:
+    python plot.py compare_sys --particles electron converted unconverted --esmodels es2016data_mc15c_summer_improved es2016data_mc15c_summer --eta-bins 0 0.6 1.0 1.37 1.55 1.82 2.47 --pt-bins-logspace 5E3 1500E3 50 --abs-sys --log-x
+
+to plot all systematics in a 2d plot (eta, pt):
+    python plot.py all_sys --esmodel es2016data_mc15c_summer es2012c --decorrelation=FULL_ETACORRELATED_v1 --eta-bins-linspace -2.5 2.5 50 --pt-bins-linspace 15E3 100E3 50 --particles converted unconverted --sys-filters *LARCALIB* *LARELECUNCONV*
+
+to produce scale factor correction (doScaleCorrection on/off):
+    python plot.py scale --esmodels es2015PRE es2016data_mc15c_summer
+
+to list the systematics:
+    python plot.py list-systematics --esmodels es2012c es2016data_mc15c_summer es2016data_mc15c_summer_improved es2017_R21_PRE
+""")
+    parser.add_argument('action', choices=['compare_sys', 'compute_sys', 'uA2MeV',
+                                           'zee', 'material', 'scale', 'cterm',
+                                           'all', 'gain', 'uniformity',
+                                           'sys_fixed_pt', 'sys_eta_slices',
+                                           'all_sys', 'resolution', 'fast', 'resolution-err', 'list-systematics'],
                         default='all', help='what to do')
     parser.add_argument('--esmodels', nargs='*', help='esmodel to consider')
+    parser.add_argument('--decorrelation', default='FULL_ETACORRELATED_v1')
+    parser.add_argument('--particles', nargs='*', help='the particle (electron/converted/unconverted)', default=['electron'])
     parser.add_argument('--beautify-sysnames', action='store_true')
     parser.add_argument('--eta-bins', nargs='*', type=float, help='edges of the eta-bins')
+    parser.add_argument('--eta-bins-linspace', nargs=3, type=float, help='edge of the eta-bins as min max nbins')
     parser.add_argument('--pt-bins', nargs='*', type=float, help='edges of the pt-bins')
+    parser.add_argument('--pt-bins-linspace', nargs=3, type=float, help='edge of the eta-bins as min max nbins')
+    parser.add_argument('--pt-bins-logspace', nargs=3, type=float, help='edge of the eta-bins as min max nbins')
     parser.add_argument('--super-sampling-eta', type=int, default=5, help='how many point to average inside a bin')
-    parser.add_argument('--sys-paper-order', action='store_true', default='use the same order of systeamatics as in run1 paper')
+    parser.add_argument('--sys-order', choices=['paper_run1', 'paper_run2'], default='how to order systematics, options: paper_run1, paper_run2')
     parser.add_argument('--debug', action='store_true')
     parser.add_argument('--superimpose-all', action='store_true', help='superimpose sum of systematics')
     parser.add_argument('--skip-null-sys', action='store_true', help='do not plot null systematics')
@@ -971,25 +1369,61 @@ def main():
     parser.add_argument('--add-down', action='store_true', help='plot also the down systematics')
     parser.add_argument('--legend-outside', action='store_true', help='draw the legend outside the plot')
     parser.add_argument('--symmetrize-labels', action='store_true')
+    parser.add_argument('--abs-sys', action='store_true', help='consider the abs value of the systeamatics')
+    parser.add_argument('--log-x', action='store_true', help='use log scale')
+    parser.add_argument('--log-pt', action='store_true', help='use log scale for pT')
+    parser.add_argument('--sys-filters', nargs='*', help='list of wildcard to filter systematic names')
+    parser.add_argument('--min-sys-value', type=float, help='min value for the systematic axis')
+    parser.add_argument('--max-sys-value', type=float, help='max value for the systematic axis')
+    parser.add_argument('--grid', action='store_true', help='show grid')
+    parser.add_argument('--plot-qsum', action='store_true', help='plot the quadrature sum of the systematics for debug (should be equal to 1NP up)')
+    parser.add_argument('--atlas-label', help='Internal, Preliminary, ..., use "" for papers')
     args = parser.parse_args()
 
     if args.debug:
-        logging.basicConfig(level=logging.DEBUG)
+        log.setLevel(logging.DEBUG)
+        log.debug("DEBUG activated")
+
+    if args.eta_bins_linspace:
+        args.eta_bins = np.linspace(args.eta_bins_linspace[0], args.eta_bins_linspace[1], args.eta_bins_linspace[2] + 1)
+    if args.pt_bins_linspace:
+        args.pt_bins = np.linspace(args.pt_bins_linspace[0], args.pt_bins_linspace[1], args.pt_bins_linspace[2] + 1)
+    if args.pt_bins_logspace:
+        args.pt_bins = np.logspace(np.log10(args.pt_bins_logspace[0]), np.log10(args.pt_bins_logspace[1]), args.pt_bins_logspace[2] + 1)
 
     basedir = 'plots'
     if not os.path.exists(basedir):
         os.makedirs(basedir)
 
+    if args.action == 'list-systematics':
+        list_systematics(args.esmodels, args.decorrelation)
+
+    if args.action == 'compute_sys':
+        log.info('computing systematics')
+        for esmodel in args.esmodels or ['es2012c']:
+            tool = ROOT.CP.EgammaCalibrationAndSmearingTool("tool")
+            tool.setProperty("ESModel", esmodel)
+            tool.setProperty("decorrelationModel", 'FULL_ETACORRELATED_v1')
+            tool.setProperty("int")("doSmearing", 0)
+            tool.initialize()
+            result = compute_or_read_sys(tool, ['electron'], args.eta_bins, args.pt_bins)
+            print(result)
+
+    if args.action == 'compare_sys':
+        log.info("comparing systematics")
+        compare_sys(args.esmodels, ptypes=args.particles, decorrelation=args.decorrelation,
+                    eta_edges=args.eta_bins, pt_edges=args.pt_bins, abs_sys=args.abs_sys, log_x=args.log_x)
+
     if args.action == 'resolution-err':
-        logging.info("plotting resolution error")
+        log.info("plotting resolution error")
         plot_resolution_error(basedir='plots', **vars(args))
 
     if args.action == 'zee' or args.action == 'all':
-        logging.info("plotting scale systematics")
+        log.info("plotting scale systematics")
         plot_all_Zee_syst(etas=np.arange(-2.5, 2.5, 0.01), pt=100E3, basedir='plots')
 
     if args.action == 'all' or args.action == 'uA2MeV':
-        logging.info("plotting uA2MeV")
+        log.info("plotting uA2MeV")
         tool_es2015PRE_nouA2MeV = ROOT.CP.EgammaCalibrationAndSmearingTool("tool_es2015PRE_nouA2MeV")
         tool_es2015PRE_nouA2MeV.setProperty("ESModel", "es2015PRE")
         tool_es2015PRE_nouA2MeV.setProperty("decorrelationModel", 'FULL_ETACORRELATED_v1')
@@ -1013,19 +1447,19 @@ def main():
         del tool_es2015PRE
 
     if args.action == 'all' or args.action == 'scale':
-        logging.info("plotting scales")
-        plot_all_scales(esmodels=("es2012c", "es2015PRE"),
-                        labels=("2012", "new + temp"),
+        log.info("plotting scales")
+        plot_all_scales(esmodels=args.esmodels,
+                        labels=args.esmodels,
                         basedir=basedir, etas=np.arange(-2.5, 2.5, 0.01),
-                        add_patch=True)
+                        add_patch=False, debug=args.debug)
     if args.action == 'all' or args.action == 'fast':
-        logging.info("plotting full / fast scale")
+        log.info("plotting full / fast scale")
         check_fast(basedir, "es2015PRE")
         plot_all_scales(esmodels=("es2015PRE", ("es2015PRE", ("useAFII",), (True,), (bool,))),
                         labels=("2015PRE", "2015PRE FAST"),
                         basedir=basedir, etas=np.arange(-2.5, 2.5, 0.01))
     if args.action == 'all' or args.action == 'cterm':
-        logging.info("plotting smearings")
+        log.info("plotting smearings")
         plot_all_cterms(esmodels=("es2012c", "es2012XX", "es2015PRE"), labels=("2012", "new", "new + temp"), basedir=basedir, etas=np.arange(-2.5, 2.5, 0.01))
 
     if args.action == 'gain' or args.action == "all":
@@ -1048,39 +1482,47 @@ def main():
                                   labels=('es2012c', '$\oplus$ 7/8 diff $\oplus$ 34/68 diff', '$\oplus$ LAr temperature'))
 
     if args.action == 'sys_eta_slices' or args.action == 'all':
-        etabins = ((0., 0.6), (0.6, 1.45), (1.52, 1.7), (1.7, 1.9), (1.9, 2.5), (1.4, 1.6))
+        if not args.eta_bins:
+            eta_bins = ((0., 0.6), (0.6, 1.45), (1.52, 1.7), (1.7, 1.9), (1.9, 2.5), (1.4, 1.6))
+            log.warning('no eta-binning specified using %s', eta_bins)
+        else:
+            eta_bins = list(pairwise(args.eta_bins))
+            log.info('eta-bin: %s', eta_bins)
         for ptype in 'electron', 'unconverted', 'converted':
-            logging.debug("plot all sys FULL_ETACORRELATED_v1 eta slice %s" % ptype)
-            plot_all_syst_eta_slice(etabins, netas=args.super_sampling_eta, esmodel=args.esmodels[0],
+            log.debug("plot all sys FULL_ETACORRELATED_v1 eta slice %s" % ptype)
+            plot_all_syst_eta_slice(eta_bins, supersampling_eta=args.super_sampling_eta, esmodel=args.esmodels[0],
                                     decorrelation='FULL_ETACORRELATED_v1', ptype=ptype, basedir=basedir,
-                                    beautify_sysnames=args.beautify_sysnames, sys_paper_order=args.sys_paper_order,
-                                    superimpose_all=args.superimpose_all, skip_null_sys=args.skip_null_sys, yrange=args.yrange, debug=args.debug,
+                                    beautify_sysnames=args.beautify_sysnames, sys_order=args.sys_order,
+                                    superimpose_all=args.superimpose_all, skip_null_sys=args.skip_null_sys,
+                                    max_sys=args.max_sys_value, min_sys=args.min_sys_value,
+                                    debug=args.debug,
                                     only_up=not args.add_down, symmetrize_labels=args.symmetrize_labels,
-                                    legend_outside=args.legend_outside)
-        for ptype in 'electron', 'unconverted', 'converted':
-            logging.debug("plot all sys 1NP_v1 eta slice %s" % ptype)
-            plot_all_syst_eta_slice(etabins, netas=args.super_sampling_eta, esmodel=args.esmodels[0],
-                                    decorrelation='1NP_v1', ptype=ptype, basedir=basedir,
-                                    beautify_sysnames=args.beautify_sysnames, sys_paper_order=args.sys_paper_order, yrange=args.yrange, debug=args.debug, only_up=not args.add_down,
-                                    legend_outside=args.legend_outside, symmetrize_labels=args.symmetrize_labels)
-
+                                    legend_outside=args.legend_outside, pts=args.pt_bins, log_x=args.log_x, plot_qsum=args.plot_qsum, abs_sys=args.abs_sys, atlas_label=args.atlas_label)
 
     if args.action == 'material' or args.action == 'all':
         if not os.path.exists('material'):
             os.makedirs('material')
         etabins = ((0., 0.6), (0.6, 1.45), (1.52, 1.7), (1.7, 1.9), (1.9, 2.5))
         for ptype in 'electron', 'unconverted', 'converted':
-            plot_all_syst_eta_slice(etabins, netas=args.super_sampling_eta, esmodel=args.esmodels[0],
+            plot_all_syst_eta_slice(etabins, supersampling_eta=args.super_sampling_eta, esmodel=args.esmodels[0],
                                     decorrelation='FULL_ETACORRELATED_v1', ptype=ptype, basedir="material",
                                     only_material=True, beautify_sysnames=args.beautify_sysnames,
-                                    sys_paper_order=args.sys_paper_order, skip_null_sys=args.skip_null_sys, yrange=args.yrange, debug=args.debug, only_up=not args.add_down,
-                                    legend_outside=args.legend_outside, symmetrize_labels=args.symmetrize_labels)
+                                    sys_order=args.sys_order,
+                                    skip_null_sys=args.skip_null_sys,
+                                    max_sys=args.max_sys_value, min_sys=args.min_sys_value,
+                                    debug=args.debug, only_up=not args.add_down,
+                                    legend_outside=args.legend_outside, symmetrize_labels=args.symmetrize_labels, log_x=args.log_x, plot_qsum=args.plot_qsum, abs_sys=args.abs_sys, atlas_label=args.atlas_label)
 
     if args.action == 'all_sys' or args.action == 'all':
-        for ptype in 'electron', 'unconverted', 'converted':
-            plot_all_syst(decorrelation="1NP_v1", ptype=ptype, basedir=basedir)
-            plot_all_syst(decorrelation="FULL_ETACORRELATED_v1", ptype=ptype, basedir=basedir)
-            plot_all_syst(decorrelation="FULL_v1", ptype=ptype, basedir=basedir)
+        for esmodel in args.esmodels:
+            for ptype in args.particles:
+                log.info("plotting sys for %s %s" % (ptype, esmodel))
+                plot_all_syst_eta_pt(esmodel=esmodel, decorrelation=args.decorrelation,
+                                     ptype=ptype, basedir=basedir,
+                                     eta_range=args.eta_bins, pt_range=args.pt_bins, log_pt=args.log_pt,
+                                     abs_sys=args.abs_sys, sys_filters=args.sys_filters,
+                                     min_value=args.min_sys_value, max_value=args.max_sys_value)
+
 
     if args.action == "resolution" or args.action == 'all':
         tool = ROOT.CP.EgammaCalibrationAndSmearingTool("tool")
@@ -1093,5 +1535,34 @@ def main():
         plot_resolution_eta_pt(basedir, tool, pts, etas, 'unconverted', title="resolution unconverted es2015PRE")
 
 if __name__ == '__main__':
+    class TqdmLoggingHandler(logging.Handler):
+        def __init__ (self, level = logging.NOTSET):
+            super (self.__class__, self).__init__ (level)
+
+        def emit (self, record):
+            try:
+                msg = self.format (record)
+                tqdm.tqdm.write (msg)
+                self.flush ()
+            except (KeyboardInterrupt, SystemExit):
+                raise
+            except:
+                self.handleError(record)
+
+
+    log = logging.getLogger(__name__)
+    log.setLevel(logging.INFO)
+    handler = TqdmLoggingHandler()
+    handler.setFormatter(colorlog.ColoredFormatter('%(log_color)s %(name)-23s %(levelname)-7s %(message)s',
+                                                   log_colors={
+                                                       'DEBUG': 'cyan',
+                                                       'INFO': 'blue',
+                                                       'SUCCESS:': 'green',
+                                                       'WARNING': 'yellow',
+                                                       'ERROR': 'red',
+                                                       'CRITICAL': 'red,bg_white'},))
+    log.addHandler(handler)
+
+    log.info("importing framework packages")
     ROOT.gROOT.ProcessLine(".x $ROOTCOREDIR/scripts/load_packages.C")
     main()
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/python/plot_paper_2017.sh b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/python/plot_paper_2017.sh
new file mode 100644
index 0000000000000000000000000000000000000000..a5f51421a8aa3894969308ead826e232d8cc0dba
--- /dev/null
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/python/plot_paper_2017.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+## This script produces the plots used in the internal notes and in
+## the calibration paper in 2017
+
+# PES vs ET in eta-bins per particles
+
+python plot.py sys_eta_slices --beautify-sysnames --sys-order paper_run2 --superimpose-all --skip-null-sys --esmodels es2016data_mc15c_summer_improved --min-sys-value 0 --max-sys-value 0.032 --symmetrize-labels  --pt-bins-linspace 7E3 200E3 200  --eta-bins 0.0 0.8 1.37 1.52 1.8 2.47 --super-sampling-eta 20 --abs-sys
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/python/plot_requirements.txt b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/python/plot_requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..abc34297f9a44d23536ef97afe8f80f745fbbaaa
--- /dev/null
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/python/plot_requirements.txt
@@ -0,0 +1,5 @@
+numpy
+matplotlib
+tqdm
+colorlog
+seaborn
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/python/run_xAOD_ElectronPhotonFourMomentumCorrection.py b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/python/run_xAOD_ElectronPhotonFourMomentumCorrection.py
index 6282d947eb9f52c397afb8717fc986b5ca68ded4..6a847f6627a54e0811054a888830f98375cc0664 100755
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/python/run_xAOD_ElectronPhotonFourMomentumCorrection.py
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/python/run_xAOD_ElectronPhotonFourMomentumCorrection.py
@@ -1,7 +1,6 @@
 #!/bin/env python
-# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 
-from __future__ import print_function
+# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 
 import ROOT
 import math
@@ -38,7 +37,7 @@ def xAOD_particle_generator(tree, collection_getter, newevent_function=None, end
     elif type(event_numbers) is int:
         event_numbers = [event_numbers]
 
-    for ievent in range(tree.GetEntries()):
+    for ievent in xrange(tree.GetEntries()):
         tree.GetEntry(ievent)
         ei = tree.EventInfo
         event_number = ei.eventNumber()
@@ -51,7 +50,7 @@ def xAOD_particle_generator(tree, collection_getter, newevent_function=None, end
 
         collection = collection_getter(tree)
 
-        for i in range(collection.size()):
+        for i in xrange(collection.size()):
             p = collection.at(i)
             if min_pt is not None and p.pt() < min_pt:
                 continue
@@ -99,6 +98,7 @@ def main(filename, **args):
     logging.debug("initializing tool")
     tool = ROOT.CP.EgammaCalibrationAndSmearingTool("tool")
     tool.setProperty("ESModel", args["esmodel"]).ignore()
+    tool.setProperty("decorrelationModel", args["decorrelation"]).ignore()
     if args["no_smearing"]:
         tool.setProperty("int")("doSmearing", 0).ignore()
     if args['debug']:
@@ -108,6 +108,11 @@ def main(filename, **args):
 
     tool.initialize()
 
+    if args['variation'] is not None:
+        logging.info("applying systematic variation %s", args['variation'])
+        sys_set = ROOT.CP.SystematicSet()
+        sys_set.insert(ROOT.CP.SystematicVariation(args['variation'], args['variation_sigma']))
+        tool.applySystematicVariation(sys_set)
 
     logging.debug("creating output tree")
     fout = ROOT.TFile("output.root", "recreate")
@@ -154,7 +159,8 @@ def main(filename, **args):
         tree_out.Fill(ei.eventNumber(), cluster.eta(), cluster.phi(),
                       true_e, pdgId, calibrated_energy, xAOD_energy, raw_e, raw_ps)
         if math.isnan(calibrated_energy) or math.isnan(calibrated_energy) or calibrated_energy < 1:
-            print ("==>", particle.author(), particle.eta(), particle.phi(), xAOD_energy, calibrated_energy)
+            print("==>", particle.author(), particle.eta(), particle.phi(), xAOD_energy, calibrated_energy)
+
 
     logging.info("%d events written", tree_out.GetEntries())
 
@@ -179,6 +185,9 @@ if __name__ == '__main__':
     parser.add_argument('--no-layer-correction', action='store_true', default=False)
     parser.add_argument('--no-smearing', action='store_true')
     parser.add_argument('--esmodel', default="es2015c_summer")
+    parser.add_argument('--decorrelation', default='1NP_v1')
+    parser.add_argument('--variation', type=str, help='variation to apply (optional)')
+    parser.add_argument('--variation-sigma', type=int, default=1, help='number of sigma for the variation (+1 or -1)')
     parser.add_argument('--use-afii', type=int)
 
     args = parser.parse_args()
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/python/test.py b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/python/test.py
deleted file mode 100755
index 2f7a1ecce7cbbd12f8432cd28d4666ac9a7f1dee..0000000000000000000000000000000000000000
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/python/test.py
+++ /dev/null
@@ -1,873 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
-
-import unittest
-import math
-import ROOT
-ROOT.PyConfig.IgnoreCommandLineOptions = True
-
-
-def arange(xmin, xmax, delta):
-    # just to don't inject dep from numpy
-    x = xmin
-    while True:
-        yield x
-        x += delta
-        if x >= xmax:
-            break
-
-
-def linspace(start, stop, n):
-    step = (stop - start) / float(n - 1)
-    for i in range(n):
-        yield start + step * i
-
-
-from PATCore.ParticleType import Electron, Photon, ConvertedPhoton, UnconvertedPhoton
-from PATCore.ParticleDataType import Data, Full
-
-
-class Test(unittest.TestCase):
-    def setUp(self):
-        self.all_systematics = [getattr (ROOT.egEnergyCorr.Scale, 'None'),
-                                ROOT.egEnergyCorr.Scale.Nominal,
-                                ROOT.egEnergyCorr.Scale.PSUp, ROOT.egEnergyCorr.Scale.PSDown,
-                                ROOT.egEnergyCorr.Scale.ZeeStatUp, ROOT.egEnergyCorr.Scale.ZeeStatDown,
-                                ROOT.egEnergyCorr.Scale.ZeeSystUp, ROOT.egEnergyCorr.Scale.ZeeSystDown,
-                                ROOT.egEnergyCorr.Scale.ZeeAllUp, ROOT.egEnergyCorr.Scale.ZeeAllDown,
-                                ROOT.egEnergyCorr.Scale.S12Up, ROOT.egEnergyCorr.Scale.S12Down,
-                                ROOT.egEnergyCorr.Scale.L1GainDown, ROOT.egEnergyCorr.Scale.L1GainUp,
-                                ROOT.egEnergyCorr.Scale.L2GainDown, ROOT.egEnergyCorr.Scale.L2GainUp,
-                                ROOT.egEnergyCorr.Scale.LeakageUnconvUp, ROOT.egEnergyCorr.Scale.LeakageUnconvDown,
-                                ROOT.egEnergyCorr.Scale.LeakageConvUp, ROOT.egEnergyCorr.Scale.LeakageConvDown,
-                                ROOT.egEnergyCorr.Scale.MatIDUp, ROOT.egEnergyCorr.Scale.MatIDDown,
-                                ROOT.egEnergyCorr.Scale.MatCryoUp, ROOT.egEnergyCorr.Scale.MatCryoDown,
-                                ROOT.egEnergyCorr.Scale.MatCaloUp, ROOT.egEnergyCorr.Scale.MatCaloDown,
-                                ROOT.egEnergyCorr.Scale.LArCalibUp, ROOT.egEnergyCorr.Scale.LArCalibDown,
-                                ROOT.egEnergyCorr.Scale.LArUnconvCalibUp, ROOT.egEnergyCorr.Scale.LArUnconvCalibDown,
-                                ROOT.egEnergyCorr.Scale.LArElecUnconvUp, ROOT.egEnergyCorr.Scale.LArElecUnconvDown,
-                                ROOT.egEnergyCorr.Scale.AllUp, ROOT.egEnergyCorr.Scale.AllDown]
-
-        # just a shortcut
-        self.EnergyCorrectionTool = ROOT.AtlasRoot.egammaEnergyCorrectionTool
-        self.es = [ROOT.egEnergyCorr.es2010,
-                   ROOT.egEnergyCorr.es2011c,
-                   #              ROOT.egEnergyCorr.es2011d,
-                   ROOT.egEnergyCorr.es2012a,
-                   ROOT.egEnergyCorr.es2012c]
-        self.labels = ["es2010", "es2011c",
-                       #  "es2011d",
-                       "es2012a", "es2012c"]
-        self.tools = {}
-        for es, label in zip(self.es, self.labels):
-            self.tools[label] = self.EnergyCorrectionTool()
-            self.tools[label].setESModel(es)
-            self.tools[label].initialize()
-
-        input_file = ROOT.TFile("$ROOTCOREBIN/data/ElectronPhotonFourMomentumCorrection/example.root")
-        self.electron_tree = input_file.Get("electron")
-        self.photon_tree = input_file.Get("photon")
-#        self.electron_tree = self.electron_tree.CloneTree()
-#        self.electron_tree.SetDirectory(0)
-#        self.photon_tree = self.photon_tree.CloneTree()
-#        self.photon_tree.SetDirectory(0)
-        self.E0MC = input_file.Get("ElectronProfiles/p0MC")
-        self.E1MC = input_file.Get("ElectronProfiles/p1MC")
-        self.E2MC = input_file.Get("ElectronProfiles/p2MC")
-        self.E3MC = input_file.Get("ElectronProfiles/p3MC")
-        self.E0MC.SetDirectory(0)
-        self.E1MC.SetDirectory(0)
-        self.E2MC.SetDirectory(0)
-        self.E3MC.SetDirectory(0)
-
-        self.output_file = ROOT.TFile("output_test.root", "recreate")
-
-    def example_input(self, particle=Electron, eta=0.0,
-                      std_energy=35E3, pdata=Full, phi=0.):
-        return (195848,                         # 0
-                pdata,
-                particle,
-                std_energy * 0.05,  # Es0
-                std_energy * 0.1,   # Es1
-                std_energy * 0.7,   # Es2       # 5
-                std_energy * 0.15,  # Es3
-                eta,                # cl_eta
-                phi,                # cl_phi
-                eta,                # trk_eta
-                std_energy,         # cl_E      # 10
-                eta,                # cl_etaCalo
-                phi,                # cl_phiCalo
-                std_energy * 1.1 if particle == Photon else -999,               # ptconv
-                std_energy * 0.4 if particle == Photon else -999,               # pt1conv   # 15
-                std_energy * 0.7 if particle == Photon else -999,               # pt2conv
-                3 if particle == Photon else -999,       # convtrk1nPixHits
-                5 if particle == Photon else -999,       # convtrk1nSCTHits
-                2 if particle == Photon else -999,       # convtrk2nPixHits
-                4 if particle == Photon else -999,                                          # 20
-                300 if particle == Photon else -999)     # RConv
-
-    def example_electron(self, eta=0.0, std_energy=35E3, pdata=Full, phi=0.):
-        inp = self.example_input(particle=Electron, eta=eta, std_energy=std_energy, pdata=pdata, phi=phi)
-        return inp[3:13]
-
-    def example_photon(self, eta=0.0, std_energy=35E3, pdata=Full, phi=0.):
-        inp = self.example_input(particle=Photon, eta=eta, std_energy=std_energy, pdata=pdata, phi=phi)
-        return inp[3:9] + inp[10:]
-
-    def iscrack(self, eta):
-        # ranges used by MVA calibration
-        return 1.37 <= abs(eta) <= 1.52
-
-    def test_init(self):
-        for es in [ROOT.egEnergyCorr.es2010, ROOT.egEnergyCorr.es2011c,
-                   ROOT.egEnergyCorr.es2011d, ROOT.egEnergyCorr.es2012a, ROOT.egEnergyCorr.es2012c]:
-            tool = self.EnergyCorrectionTool()
-            tool.setESModel(es)
-            self.assertTrue(tool)
-            try:
-                tool.initialize()
-            except Exception as exception:
-                self.fail("EnergyCorrectionTool.initialize raises exception %s" % str(exception))
-
-    def test_mva_working(self):
-        tool_mva = self.EnergyCorrectionTool()
-        tool_mva.setESModel(ROOT.egEnergyCorr.es2012c)
-        tool_std = self.EnergyCorrectionTool()
-        tool_std.setESModel(ROOT.egEnergyCorr.es2010)
-
-        tool_mva.initialize()
-        tool_std.initialize()
-
-        for eta in linspace(-2.5, 2.5, 200):
-            inputs = self.example_input(eta=eta)
-            std_energy_input = inputs[10]
-
-            energy_mva = tool_mva.getCorrectedEnergy(*inputs)
-            energy_std = tool_std.getCorrectedEnergy(*inputs)
-            self.assertAlmostEqual(std_energy_input, energy_std)
-            if (not self.iscrack(eta) and not abs(eta) >= 2.47):
-                self.assertNotAlmostEqual(energy_mva, energy_std)
-            else:
-                self.assertAlmostEqual(energy_mva, energy_std)
-
-    def test_intermodule_correction_working(self):
-        tool = self.EnergyCorrectionTool()
-        tool.setESModel(ROOT.egEnergyCorr.es2012c)
-        tool_no_correction = self.EnergyCorrectionTool()
-        tool_no_correction.setESModel(ROOT.egEnergyCorr.es2012c)
-
-        tool.initialize()
-        tool_no_correction.initialize()
-
-        tool_no_correction.useIntermoduleCorrection(False)
-
-        energy, energy_no_correction = [], []
-
-        for phi in linspace(-math.pi, math.pi, 400):
-            input_phi = self.example_input(phi=phi, eta=0.1, pdata=Data)
-            energy.append(tool.getCorrectedEnergy(*input_phi))
-            energy_no_correction.append(tool_no_correction.getCorrectedEnergy(*input_phi))
-
-        self.assertFalse(all([x == y for x, y in zip(energy, energy_no_correction)]))
-
-    def test_phicorrection_working(self):
-        tool = self.EnergyCorrectionTool()
-        tool.setESModel(ROOT.egEnergyCorr.es2012c)
-        tool_no_correction = self.EnergyCorrectionTool()
-        tool_no_correction.setESModel(ROOT.egEnergyCorr.es2012c)
-
-        tool.initialize()
-        tool_no_correction.initialize()
-
-        tool_no_correction.usePhiUniformCorrection(False)
-
-        h = ROOT.TH2F("phi_correction", "phi_correction", 200, -2.5, 2.5, 200, -math.pi, math.pi)
-
-        energy, energy_no_correction = [], []
-        for eta in linspace(-3, 3, 200):
-            for phi in linspace(-math.pi, math.pi, 200):
-                input_phi = self.example_input(phi=phi, pdata=Data, eta=eta)
-
-                e = tool.getCorrectedEnergy(*input_phi)
-                e_no_correction = tool_no_correction.getCorrectedEnergy(*input_phi)
-
-                energy.append(e)
-                energy_no_correction.append(e_no_correction)
-                h.Fill(eta, phi, e / e_no_correction)
-
-        self.assertFalse(all([x == y for x, y in zip(energy, energy_no_correction)]))
-        self.assertTrue(all([abs(x / y - 1) < 0.3 for x, y in zip(energy, energy_no_correction)]))
-
-        m = min([x / y for x, y in zip(energy, energy_no_correction)])
-        M = max([x / y for x, y in zip(energy, energy_no_correction)])
-
-        canvas_phicorrection = ROOT.TCanvas()
-        h.SetMaximum(m)
-        h.SetMinimum(M)
-        h.Draw("colz")
-        h.SetMaximum(m)
-        h.SetMinimum(M)
-        canvas_phicorrection.Update()
-        canvas_phicorrection.Modified()
-        canvas_phicorrection.SaveAs("canvas_phicorrection.png")
-
-    def test_interface_equivalence(self):
-        tool = self.EnergyCorrectionTool()
-        tool.setESModel(ROOT.egEnergyCorr.es2012c)
-        tool.initialize()
-
-        for eta in linspace(-2.5, 2.5, 200):
-            input_electron = self.example_input(pdata=Data, eta=eta, particle=Electron)
-            input_photon = self.example_input(pdata=Data, eta=eta, particle=Photon)
-
-            input_electron2 = self.example_electron(pdata=Data, eta=eta)
-            input_photon2 = self.example_photon(pdata=Data, eta=eta)
-
-            electron = ROOT.AtlasRoot.egammaEnergyCorrectionTool.ParticleInformation(*input_electron2)
-            photon = ROOT.AtlasRoot.egammaEnergyCorrectionTool.ParticleInformation(*input_photon2)
-
-            energy_electron2 = tool.getCorrectedEnergyElectron(input_electron[0],
-                                                               input_electron[1],
-                                                               *input_electron2)
-            energy_photon2 = tool.getCorrectedEnergyPhoton(input_electron[0],
-                                                           input_electron[1],
-                                                           *input_photon2)
-
-            energy_electron1 = tool.getCorrectedEnergy(*input_electron)
-            energy_photon1 = tool.getCorrectedEnergy(*input_photon)
-
-            energy_electron3 = tool.getCorrectedEnergy(input_electron[0],
-                                                       input_electron[1],
-                                                       electron)
-
-            energy_photon3 = tool.getCorrectedEnergy(input_electron[0],
-                                                     input_electron[1],
-                                                     photon)
-
-            self.assertAlmostEqual(energy_electron1, energy_electron2)
-            self.assertAlmostEqual(energy_electron2, energy_electron3)
-            self.assertAlmostEqual(energy_photon1, energy_photon2)
-            self.assertAlmostEqual(energy_photon2, energy_photon3)
-
-    def test_scale_factors(self):
-        graph_MC_nominal_ratio = {}
-        graph_data_nominal_ratio = {}
-        for label in self.labels:
-            graph_MC_nominal_ratio[label] = ROOT.TGraph()
-            graph_MC_nominal_ratio[label].SetTitle("MC " + label)
-            graph_data_nominal_ratio[label] = ROOT.TGraph()
-            graph_data_nominal_ratio[label].SetTitle("data " + label)
-
-            ipoint = 0
-
-            for eta in linspace(-2.5, 2.5, 250):
-                input_electron = self.example_input(eta=eta, particle=Electron)
-                particle_information = ROOT.AtlasRoot.egammaEnergyCorrectionTool.ParticleInformation(*(input_electron[3:13]))
-                nominal = ROOT.egEnergyCorr.Scale.Nominal
-                none = getattr(ROOT.egEnergyCorr.Scale, 'None')
-
-                energy_MC_none = self.tools[label].getCorrectedEnergy(0, Full, particle_information, none)
-                energy_data_none = self.tools[label].getCorrectedEnergy(0, Data, particle_information, none)
-
-                energy_MC_nominal = self.tools[label].getCorrectedEnergy(0, Full, particle_information, ROOT.egEnergyCorr.Scale.Nominal)
-                energy_data_nominal = self.tools[label].getCorrectedEnergy(0, Data, particle_information, ROOT.egEnergyCorr.Scale.Nominal)
-
-                # TODO: check also forward scales
-                if (-2.47 < eta < 2.47):
-                    self.assertAlmostEqual(energy_MC_nominal/energy_MC_none, 1.)
-                    self.assertNotAlmostEqual(energy_data_nominal/energy_data_none, 1.)
-                    graph_MC_nominal_ratio[label].SetPoint(ipoint, eta, energy_MC_nominal/energy_MC_none)
-                    graph_data_nominal_ratio[label].SetPoint(ipoint, eta, energy_data_nominal/energy_data_none)
-                    ipoint += 1
-
-        canvas_MC = ROOT.TCanvas("canvas_MC_ratio")
-        legend = ROOT.TLegend(0.6, 0.6, 0.9, 0.9)
-        for i, graph in enumerate(graph_MC_nominal_ratio.values()):
-            graph.SetLineColor(i + 1)
-            graph.GetYaxis().SetTitle("Nominal-corrected energy / None-corrected energy")
-            graph.GetXaxis().SetTitle("#eta")
-            graph.SetFillColor(0)
-            graph.SetMarkerColor(i + 1)
-            graph.SetMarkerStyle(24 + i)
-            graph.Draw("APL" if i==0 else "PL")
-            legend.AddEntry(graph)
-        legend.Draw()
-        canvas_MC.SaveAs(canvas_MC.GetTitle() + ".png")
-
-        canvas_data = ROOT.TCanvas("canvas_data_ratio")
-        legend2 = ROOT.TLegend(0.6, 0.6, 0.9, 0.9)
-        for i, graph in enumerate(graph_data_nominal_ratio.values()):
-            graph.SetLineColor(i + 1)
-            graph.GetYaxis().SetTitle("Nominal-corrected energy / None-corrected energy")
-            graph.GetXaxis().SetTitle("#eta")
-            graph.SetFillColor(0)
-            graph.SetMarkerColor(i + 1)
-            graph.SetMarkerStyle(24 + i)
-            graph.Draw("APL" if i==0 else "PL")
-            legend2.AddEntry(graph)
-        legend2.Draw()
-        canvas_data.SaveAs(canvas_data.GetTitle() + ".png")
-
-
-    def test_data_over_MC(self):
-        graph_none_ratio = {}
-        for label in self.labels:
-            graph_none_ratio[label] = ROOT.TGraph()
-            graph_none_ratio[label].SetTitle("data_over_MC_ " + label)
-
-            ipoint = 0
-
-            for eta in linspace(-2.5, 2.5, 250):
-                input_electron = self.example_input(eta=eta, particle=Electron)
-                particle_information = ROOT.AtlasRoot.egammaEnergyCorrectionTool.ParticleInformation(*(input_electron[3:13]))
-
-                energy_MC_none = self.tools[label].getCorrectedEnergy(0, Full, particle_information, getattr(ROOT.egEnergyCorr.Scale, 'None'))
-                energy_data_none = self.tools[label].getCorrectedEnergy(0, Data, particle_information, getattr (ROOT.egEnergyCorr.Scale, 'None'))
-
-                # TODO: check also forward scales
-                if (-2.47 < eta < 2.47):
-#                    self.assertNotAlmostEqual(energy_MC_none, energy_data_none)
-                    graph_none_ratio[label].SetPoint(ipoint, eta, energy_data_none / energy_MC_none)
-                    ipoint += 1
-
-        canvas_MC = ROOT.TCanvas("canvas_dataOverMC_ratio")
-        legend = ROOT.TLegend(0.6, 0.6, 0.9, 0.9)
-        multigraph = ROOT.TMultiGraph()
-        multigraph.SetTitle("Data / MC no scale;#eta; data/MC None corrected");
-        for i, graph in enumerate(graph_none_ratio.values()):
-            graph.SetLineColor(i + 1)
-            graph.SetMarkerStyle(24 + i)
-            graph.SetFillColor(0)
-            graph.GetYaxis().SetTitle("Data None corrected / MC None corrected")
-            graph.GetXaxis().SetTitle("#eta")
-            multigraph.Add(graph)
-            legend.AddEntry(graph)
-        multigraph.Draw("APL")
-        legend.Draw()
-        canvas_MC.SaveAs(canvas_MC.GetTitle() + ".png")
-
-    def test_compare_layer2_recalib(self):
-        tool_E2 = self.EnergyCorrectionTool()
-        tool_E2.setESModel(ROOT.egEnergyCorr.es2012c)
-        tool_E1 = self.EnergyCorrectionTool()
-        tool_E1.setESModel(ROOT.egEnergyCorr.es2012c)
-        tool_E1.useLayer2Recalibration(False)
-        tool_E1.initialize()
-        tool_E2.initialize()
-
-        tool_E1.useIntermoduleCorrection(False)
-        tool_E1.usePhiUniformCorrection(False)
-        tool_E2.useIntermoduleCorrection(False)
-        tool_E2.usePhiUniformCorrection(False)
-
-        graph_E1 = ROOT.TGraph()
-        graph_E1.SetName("graph_es2012c_data_E1recalib")
-        graph_E1.SetTitle("layer 1 recalib")
-        graph_E2 = ROOT.TGraph()
-        graph_E2.SetName("graph_es2012c_data_E2recalib")
-        graph_E2.SetTitle("layer 2 recalib")
-        ipoint = 0
-        for eta in linspace(-2.5, 2.5, 250):
-            E0 = self.E0MC.GetBinContent(self.E0MC.FindBin(eta)) * 1E3
-            E1 = self.E1MC.GetBinContent(self.E1MC.FindBin(eta)) * 1E3
-            E2 = self.E2MC.GetBinContent(self.E2MC.FindBin(eta)) * 1E3
-            E3 = self.E3MC.GetBinContent(self.E3MC.FindBin(eta)) * 1E3
-
-            phi = 0
-            particle_information = ROOT.AtlasRoot.egammaEnergyCorrectionTool.ParticleInformation(E0, E1, E2, E3,
-                                                                                                 eta,
-                                                                                                 phi,
-                                                                                                 eta,
-                                                                                                 40E3,
-                                                                                                 eta,
-                                                                                                 phi)
-            energy_E1_MC = tool_E1.getCorrectedEnergy(0, Full, particle_information, getattr(ROOT.egEnergyCorr.Scale, 'None'))
-            energy_E1_data = tool_E1.getCorrectedEnergy(0, Data, particle_information, getattr(ROOT.egEnergyCorr.Scale, 'None'))
-            energy_E2_MC = tool_E2.getCorrectedEnergy(0, Full, particle_information, getattr(ROOT.egEnergyCorr.Scale, 'None'))
-            energy_E2_data = tool_E2.getCorrectedEnergy(0, Data, particle_information, getattr(ROOT.egEnergyCorr.Scale, 'None'))
-            graph_E1.SetPoint(ipoint, eta, energy_E1_data / energy_E1_MC)
-            graph_E2.SetPoint(ipoint, eta, energy_E2_data / energy_E2_MC)
-            ipoint += 1
-            self.assertAlmostEqual(energy_E1_MC, energy_E2_MC)
-        graph_E1.SetLineColor(ROOT.kRed)
-        graph_E2.SetLineColor(ROOT.kBlue)
-        graph_E1.SetMarkerColor(ROOT.kRed)
-        graph_E2.SetMarkerColor(ROOT.kBlue)
-        legend = ROOT.TLegend(0.6, 0.6, 0.9, 0.9)
-        for g in (graph_E1, graph_E2):
-            g.GetXaxis().SetTitle("#eta")
-            g.GetYaxis().SetTitle("data None / MC None")
-            g.SetFillColor(0)
-            legend.AddEntry(g)
-        self.output_file.cd()
-        canvas = ROOT.TCanvas()
-        canvas.SetName("layer1_vs_layer2")
-        graph_E1.Draw("APL")
-        graph_E2.Draw("PLsame")
-        legend.Draw()
-        canvas.SaveAs("layer1_vs_layer2.png")
-        canvas.Write()
-
-    def do_test_layer(self, tool, canvas_name, function=None):
-        if function is not None:
-            function(tool)
-
-        tool.useIntermoduleCorrection(False)
-        tool.usePhiUniformCorrection(False)
-
-        canvas = ROOT.TCanvas()
-        canvas.SetName("canvas_" + canvas_name)
-        canvas.Divide(2, 2)
-        gr = []
-        for i in range(4):
-            gr.append(ROOT.TGraph())
-            gr[i].SetTitle(canvas_name + " layer %d" % i)
-            gr[i].GetXaxis().SetTitle("#eta")
-        ipoint = 0
-
-        for eta in linspace(-3.5, 3.5, 300):
-            E0 = self.E0MC.GetBinContent(self.E0MC.FindBin(eta)) * 1E3
-            E1 = self.E1MC.GetBinContent(self.E1MC.FindBin(eta)) * 1E3
-            E2 = self.E2MC.GetBinContent(self.E2MC.FindBin(eta)) * 1E3
-            E3 = self.E3MC.GetBinContent(self.E3MC.FindBin(eta)) * 1E3
-            input_electron = self.example_input(eta=eta, particle=Electron)
-            phi = 0
-            particle_information = ROOT.AtlasRoot.egammaEnergyCorrectionTool.ParticleInformation(E0, E1, E2, E3,
-                                                                                                 eta,
-                                                                                                 phi,
-                                                                                                 eta,
-                                                                                                 40E3,
-                                                                                                 eta,
-                                                                                                 phi)
-            energy = tool.getCorrectedEnergy(0, Data, particle_information, getattr(ROOT.egEnergyCorr.Scale, 'None'))
-            r = [1, 1, 1, 1]
-            r[0] = 1 if particle_information.rawcl_Es0==0 else tool.getCalibInputs(0) / particle_information.rawcl_Es0
-            r[1] = 1 if particle_information.rawcl_Es1==0 else tool.getCalibInputs(1) / particle_information.rawcl_Es1
-            r[2] = 1 if particle_information.rawcl_Es2==0 else tool.getCalibInputs(2) / particle_information.rawcl_Es2
-            r[3] = 1 if particle_information.rawcl_Es3==0 else tool.getCalibInputs(3) / particle_information.rawcl_Es3
-            for i in range(4):
-                gr[i].SetPoint(ipoint, eta, r[i])
-            ipoint += 1
-        for i in range(4):
-            canvas.cd(i + 1)
-            gr[i].Draw("APL")
-        canvas.SaveAs("canvas_" + canvas_name + ".png")
-        self.output_file.cd()
-        canvas.Write()
-
-
-    def test_layer(self):
-        tool_es2012c = self.EnergyCorrectionTool()
-        tool_es2012c.setESModel(ROOT.egEnergyCorr.es2012c)
-        tool_es2012c.initialize()
-
-        tool_es2011d = self.EnergyCorrectionTool()
-        tool_es2011d.setESModel(ROOT.egEnergyCorr.es2011d)
-        tool_es2011d.initialize()
-
-        self.do_test_layer(tool_es2012c, "es2012c")
-        self.do_test_layer(tool_es2011d, "es2011d")
-
-        tool_es2012c_layer1 = self.EnergyCorrectionTool()
-        tool_es2012c_layer1.setESModel(ROOT.egEnergyCorr.es2012c)
-        tool_es2012c_layer1.useLayer2Recalibration(False)
-        tool_es2012c_layer1.initialize()
-
-        tool_es2011d_layer1 = self.EnergyCorrectionTool()
-        tool_es2011d_layer1.setESModel(ROOT.egEnergyCorr.es2011d)
-        tool_es2011d_layer1.useLayer2Recalibration(False)
-        tool_es2011d_layer1.initialize()
-
-        self.do_test_layer(tool_es2012c_layer1, "es2012c_with_layer1")
-        self.do_test_layer(tool_es2011d_layer1, "es2011d_with_layer1")
-
-    def test_gain(self):
-        tool_es2012c = self.EnergyCorrectionTool()
-        tool_es2012c.setESModel(ROOT.egEnergyCorr.es2012c)
-        tool_es2012c.initialize()
-        tool_es2012c.useIntermoduleCorrection(False)
-        tool_es2012c.usePhiUniformCorrection(False)
-
-        tool_es2012c_nogain = self.EnergyCorrectionTool()
-        tool_es2012c_nogain.setESModel(ROOT.egEnergyCorr.es2012c)
-        tool_es2012c_nogain.initialize()
-        tool_es2012c_nogain.useGainCorrection(False)
-        tool_es2012c_nogain.useIntermoduleCorrection(False)
-        tool_es2012c_nogain.usePhiUniformCorrection(False)
-
-        graph = ROOT.TGraph()
-        ipoint = 0
-        for eta in linspace(-3, 3, 300):
-            input_electron = self.example_input(eta=eta, particle=Electron)
-            particle_information = ROOT.AtlasRoot.egammaEnergyCorrectionTool.ParticleInformation(*(input_electron[3:13]))
-            energy = tool_es2012c.getCorrectedEnergy(0, Data, particle_information, getattr(ROOT.egEnergyCorr.Scale, 'None'))
-            energy_nogain = tool_es2012c_nogain.getCorrectedEnergy(0, Data, particle_information, getattr(ROOT.egEnergyCorr.Scale, 'None'))
-
-            graph.SetPoint(ipoint, eta, energy/energy_nogain)
-            ipoint += 1
-
-        self.output_file.cd()
-        canvas = ROOT.TCanvas()
-        canvas.SetName("canvas_gain")
-        graph.GetXaxis().SetTitle("#eta")
-        graph.GetYaxis().SetTitle("E_{gain} / E_{no gain} data")
-        graph.Draw("APL")
-        canvas.SaveAs("canvas_gain.png")
-        canvas.Write()
-
-
-    def test_gain2(self):
-        tool_es2012c = self.EnergyCorrectionTool()
-        tool_es2012c.setESModel(ROOT.egEnergyCorr.es2012c)
-        tool_es2012c.initialize()
-        tool_es2012c.useIntermoduleCorrection(False)
-        tool_es2012c.usePhiUniformCorrection(False)
-
-        tool_es2012c_nogain = self.EnergyCorrectionTool()
-        tool_es2012c_nogain.setESModel(ROOT.egEnergyCorr.es2012c)
-        tool_es2012c_nogain.initialize()
-        tool_es2012c_nogain.useGainCorrection(False)
-        tool_es2012c_nogain.useIntermoduleCorrection(False)
-        tool_es2012c_nogain.usePhiUniformCorrection(False)
-
-        graph = ROOT.TGraph()
-        ipoint = 0
-        for eta in linspace(-3.5, 3.5, 300):
-            E0 = self.E0MC.GetBinContent(self.E0MC.FindBin(eta)) * 1E3
-            E1 = self.E1MC.GetBinContent(self.E1MC.FindBin(eta)) * 1E3
-            E2 = self.E2MC.GetBinContent(self.E2MC.FindBin(eta)) * 1E3
-            E3 = self.E3MC.GetBinContent(self.E3MC.FindBin(eta)) * 1E3
-
-            phi = 0
-
-            particle_information = ROOT.AtlasRoot.egammaEnergyCorrectionTool.ParticleInformation(E0, E1, E2, E3,
-                                                                                                 eta,
-                                                                                                 phi,
-                                                                                                 eta,
-                                                                                                 40E3,
-                                                                                                 eta,
-                                                                                                 phi)
-            energy = tool_es2012c.getCorrectedEnergy(0, Data, particle_information, getattr(ROOT.egEnergyCorr.Scale, 'None'))
-            energy_nogain = tool_es2012c_nogain.getCorrectedEnergy(0, Data, particle_information, getattr(ROOT.egEnergyCorr.Scale, 'None'))
-
-            if energy_nogain != 0:
-                graph.SetPoint(ipoint, eta, energy/energy_nogain)
-                ipoint += 1
-            elif energy_nogain == 0 and energy == 0:
-                graph.SetPoint(ipoint, eta, 1)
-                ipoint += 1
-
-        self.output_file.cd()
-        canvas = ROOT.TCanvas()
-        canvas.SetName("canvas_gain")
-        graph.GetXaxis().SetTitle("#eta")
-        graph.GetYaxis().SetTitle("E_{gain} / E_{no gain} data")
-        graph.Draw("APL")
-        canvas.SaveAs("canvas_gain2.png")
-        canvas.Write()
-
-    def energy_scan(self, tool, datatype, scale, smearing, etas):
-        energies = []
-        for eta in etas:
-            E0 = self.E0MC.GetBinContent(self.E0MC.FindBin(eta)) * 1E3
-            E1 = self.E1MC.GetBinContent(self.E1MC.FindBin(eta)) * 1E3
-            E2 = self.E2MC.GetBinContent(self.E2MC.FindBin(eta)) * 1E3
-            E3 = self.E3MC.GetBinContent(self.E3MC.FindBin(eta)) * 1E3
-
-            phi = 0
-
-            particle_information = ROOT.AtlasRoot.egammaEnergyCorrectionTool.ParticleInformation(E0, E1, E2, E3,
-                                                                                                 eta,
-                                                                                                 phi,
-                                                                                                 eta,
-                                                                                                 40E3,
-                                                                                                 eta,
-                                                                                                 phi)
-            energy = tool.getCorrectedEnergy(0, datatype, particle_information,
-                                             scale, smearing)
-            energies.append(energy)
-        return energies
-
-    def test_nan(self):
-        tool = self.EnergyCorrectionTool()
-        tool.setESModel(ROOT.egEnergyCorr.es2012c)
-        tool.initialize()
-
-        for particle in ("electron", "converted", "unconverted"):
-            for scale_energy in [0.05, 0.1, 0.5, 1., 2.0, 10., 100.]:
-                for sys in self.all_systematics:
-                    for eta in linspace(-5, 5, 500):
-                        E0 = self.E0MC.GetBinContent(self.E0MC.FindBin(eta)) * 1E3 * scale_energy
-                        E1 = self.E1MC.GetBinContent(self.E1MC.FindBin(eta)) * 1E3 * scale_energy
-                        E2 = self.E2MC.GetBinContent(self.E2MC.FindBin(eta)) * 1E3 * scale_energy
-                        E3 = self.E3MC.GetBinContent(self.E3MC.FindBin(eta)) * 1E3 * scale_energy
-                        if E0 == 0 and E1 == 0 and E2 == 0 and E3 == 0:
-                            E0 = self.E0MC.GetBinContent(self.E0MC.FindBin(2)) * 1E3 * scale_energy
-                            E1 = self.E1MC.GetBinContent(self.E1MC.FindBin(2)) * 1E3 * scale_energy
-                            E2 = self.E2MC.GetBinContent(self.E2MC.FindBin(2)) * 1E3 * scale_energy
-                            E3 = self.E3MC.GetBinContent(self.E3MC.FindBin(2)) * 1E3 * scale_energy
-                        cl_E = 40E3 * scale_energy
-
-                        phi = 0
-
-                        if particle == "converted":
-                            particle_information = ROOT.AtlasRoot.egammaEnergyCorrectionTool.ParticleInformation(E0, E1, E2, E3,
-                                                                                                                 eta,
-                                                                                                                 phi,
-                                                                                                                 cl_E,
-                                                                                                                 eta,
-                                                                                                                 phi,
-                                                                                                                 35E3 * scale_energy,
-                                                                                                                 20E3 * scale_energy,
-                                                                                                                 18E3 * scale_energy,
-                                                                                                                 1,
-                                                                                                                 1,
-                                                                                                                 1,
-                                                                                                                 1, 100)
-                            particle_str = "converted eta:%f, phi:%f, E0:%f, E1:%f, E2:%f, E3:%f, cl_E:%f, ptconv: %f, p1: %f, p2: %f, R: %f" % (eta, phi, E0, E1, E2, E3, cl_E, 35E3*scale_energy, 20E3*scale_energy, 18E3 * scale_energy, 100)
-
-                        elif particle == "unconverted":
-                            particle_information = ROOT.AtlasRoot.egammaEnergyCorrectionTool.ParticleInformation(E0, E1, E2, E3,
-                                                                                                                 eta,
-                                                                                                                 phi,
-                                                                                                                 cl_E,
-                                                                                                                 eta,
-                                                                                                                 phi,
-                                                                                                                 0,
-                                                                                                                 0,
-                                                                                                                 0,
-                                                                                                                 0,
-                                                                                                                 0,
-                                                                                                                 0,
-                                                                                                                 0, 0)
-                            particle_str = "unconverted eta:%f, phi:%f, E0:%f, E1:%f, E2:%f, E3:%f, cl_E:%f" % (eta, phi, E0, E1, E2, E3, cl_E)
-
-                        elif particle == "electron":
-                            particle_information = ROOT.AtlasRoot.egammaEnergyCorrectionTool.ParticleInformation(E0, E1, E2, E3,
-                                                                                                                 eta,
-                                                                                                                 phi,
-                                                                                                                 eta,
-                                                                                                                 cl_E,
-                                                                                                                 eta, phi)
-
-                            particle_str = "electron eta:%f, phi:%f, E0:%f, E1:%f, E2:%f, E3:%f, cl_E:%f" % (eta, phi, E0, E1, E2, E3, cl_E)
-
-                        energy = tool.getCorrectedEnergy(0, Full, particle_information, sys, getattr(ROOT.egEnergyCorr.Resolution, 'None'))
-                        self.assertFalse(math.isnan(energy), msg="got nan for sys=%f, %s" % (sys, particle_str))
-
-                        if sys in (getattr(ROOT.egEnergyCorr.Scale, 'None'), ROOT.egEnergyCorr.Scale.Nominal):
-                            energy = tool.getCorrectedEnergy(0, Full, particle_information, sys, ROOT.egEnergyCorr.Resolution.Nominal)
-                            self.assertFalse(math.isnan(energy), msg="got nan for Nominal res, %s" % particle_str)
-                            energy = tool.getCorrectedEnergy(0, Full, particle_information, sys, ROOT.egEnergyCorr.Resolution.AllUp)
-                            self.assertFalse(math.isnan(energy), msg="got nan for ErrorUp res, %s" % particle_str)
-                            energy = tool.getCorrectedEnergy(0, Full, particle_information, sys, ROOT.egEnergyCorr.Resolution.AllDown)
-                            self.assertFalse(math.isnan(energy), msg="got nan for ErrorDown res, %s" % particle_str)
-                            energy = tool.getCorrectedEnergy(0, Data, particle_information, sys, ROOT.getattr(egEnergyCorr.Resolution, 'None'))
-                            self.assertFalse(math.isnan(energy), msg="got nan for Data, sys=%s, %s" % (sys, particle_str))
-
-    def test_systematics(self):
-        tool = self.EnergyCorrectionTool()
-        tool.setESModel(ROOT.egEnergyCorr.es2012c)
-        tool.initialize()
-
-        etas = list(linspace(0, 2.4, 300))
-
-        datatype = Full
-
-        systematics = self.all_systematics
-
-        def create_graph(etas, nominal, distorted):
-            gr = ROOT.TGraph()
-            for i, (eta, n, d) in enumerate(zip(etas, nominal, distorted)):
-                gr.SetPoint(i, eta, d / n)
-            return gr
-
-        all_energies_smearing = {}
-        all_energies_nosmearing = {}
-
-        for sys in systematics + [ROOT.egEnergyCorr.Scale.Nominal]:
-            tool.setRandomSeed(1)
-            energies_sys_smearing = self.energy_scan(tool, datatype, sys, ROOT.egEnergyCorr.Resolution.Nominal, etas)
-            energies_sys_nosmearing = self.energy_scan(tool, datatype, sys, getattr(ROOT.egEnergyCorr.Resolution, 'None'), etas)
-            all_energies_smearing[sys] = energies_sys_smearing
-            all_energies_nosmearing[sys] = energies_sys_nosmearing
-
-        ratios_smearing = {}
-        ratios_nosmearing = {}
-        for sys in systematics:
-            ratios_smearing[sys] = create_graph(etas, all_energies_smearing[sys], all_energies_smearing[ROOT.egEnergyCorr.Scale.Nominal])
-            ratios_nosmearing[sys] = create_graph(etas, all_energies_nosmearing[sys], all_energies_nosmearing[ROOT.egEnergyCorr.Scale.Nominal])
-            ratios_smearing[sys].SetLineColor(ROOT.kRed)
-            ratios_smearing[sys].SetMarkerStyle(24)
-            ratios_smearing[sys].SetMarkerColor(ROOT.kRed)
-
-        canvas = ROOT.TCanvas()
-        multigraph = ROOT.TMultiGraph()
-        multigraph.SetTitle("All;#eta; E_{sys} / E_{nom}")
-        multigraph.Add(ratios_smearing[ROOT.egEnergyCorr.Scale.AllUp])
-        multigraph.Add(ratios_smearing[ROOT.egEnergyCorr.Scale.AllDown])
-        multigraph.Add(ratios_nosmearing[ROOT.egEnergyCorr.Scale.AllUp])
-        multigraph.Add(ratios_nosmearing[ROOT.egEnergyCorr.Scale.AllDown])
-        multigraph.Draw("APL")
-        canvas.SaveAs("sys_All_es2012c.png")
-
-        canvas = ROOT.TCanvas()
-        multigraph = ROOT.TMultiGraph()
-        multigraph.SetTitle("LeakageUnconv;#eta; E_{sys} / E_{nom}")
-        multigraph.Add(ratios_smearing[ROOT.egEnergyCorr.Scale.LeakageUnconvUp])
-        multigraph.Add(ratios_smearing[ROOT.egEnergyCorr.Scale.LeakageUnconvDown])
-        multigraph.Add(ratios_nosmearing[ROOT.egEnergyCorr.Scale.LeakageUnconvUp])
-        multigraph.Add(ratios_nosmearing[ROOT.egEnergyCorr.Scale.LeakageUnconvDown])
-        multigraph.Draw("APL")
-        canvas.SaveAs("sys_LeakageUnconv_es2012c.png")
-
-        canvas = ROOT.TCanvas()
-        multigraph = ROOT.TMultiGraph()
-        multigraph.SetTitle("LeakageConv;#eta; E_{sys} / E_{nom}")
-        multigraph.Add(ratios_smearing[ROOT.egEnergyCorr.Scale.LeakageConvUp])
-        multigraph.Add(ratios_smearing[ROOT.egEnergyCorr.Scale.LeakageConvDown])
-        multigraph.Add(ratios_nosmearing[ROOT.egEnergyCorr.Scale.LeakageConvUp])
-        multigraph.Add(ratios_nosmearing[ROOT.egEnergyCorr.Scale.LeakageConvDown])
-        multigraph.Draw("APL")
-        canvas.SaveAs("sys_LeakageConv_es2012c.png")
-
-        canvas = ROOT.TCanvas()
-        multigraph = ROOT.TMultiGraph()
-        multigraph.SetTitle("S12;#eta; E_{sys} / E_{nom}")
-        multigraph.Add(ratios_smearing[ROOT.egEnergyCorr.Scale.S12Up])
-        multigraph.Add(ratios_smearing[ROOT.egEnergyCorr.Scale.S12Down])
-        multigraph.Add(ratios_nosmearing[ROOT.egEnergyCorr.Scale.S12Up])
-        multigraph.Add(ratios_nosmearing[ROOT.egEnergyCorr.Scale.S12Down])
-        multigraph.Draw("APL")
-        canvas.SaveAs("sys_S12_es2012c.png")
-
-        canvas = ROOT.TCanvas()
-        multigraph = ROOT.TMultiGraph()
-        multigraph.SetTitle("PS;#eta; E_{sys} / E_{nom}")
-        multigraph.Add(ratios_smearing[ROOT.egEnergyCorr.Scale.PSUp])
-        multigraph.Add(ratios_smearing[ROOT.egEnergyCorr.Scale.PSDown])
-        multigraph.Add(ratios_nosmearing[ROOT.egEnergyCorr.Scale.PSUp])
-        multigraph.Add(ratios_nosmearing[ROOT.egEnergyCorr.Scale.PSDown])
-        multigraph.Draw("APL")
-        canvas.SaveAs("sys_PS_es2012c.png")
-
-        canvas = ROOT.TCanvas()
-        multigraph = ROOT.TMultiGraph()
-        multigraph.SetTitle("ZeeStat;#eta; E_{sys} / E_{nom}")
-        multigraph.Add(ratios_smearing[ROOT.egEnergyCorr.Scale.ZeeStatUp])
-        multigraph.Add(ratios_smearing[ROOT.egEnergyCorr.Scale.ZeeStatDown])
-        multigraph.Add(ratios_nosmearing[ROOT.egEnergyCorr.Scale.ZeeStatUp])
-        multigraph.Add(ratios_nosmearing[ROOT.egEnergyCorr.Scale.ZeeStatDown])
-        multigraph.Draw("APL")
-        canvas.SaveAs("sys_ZeeStat_es2012c.png")
-
-        canvas = ROOT.TCanvas()
-        multigraph = ROOT.TMultiGraph()
-        multigraph.SetTitle("ZeeSyst;#eta; E_{sys} / E_{nom}")
-        multigraph.Add(ratios_smearing[ROOT.egEnergyCorr.Scale.ZeeSystUp])
-        multigraph.Add(ratios_smearing[ROOT.egEnergyCorr.Scale.ZeeSystDown])
-        multigraph.Add(ratios_nosmearing[ROOT.egEnergyCorr.Scale.ZeeSystUp])
-        multigraph.Add(ratios_nosmearing[ROOT.egEnergyCorr.Scale.ZeeSystDown])
-        multigraph.Draw("APL")
-        canvas.SaveAs("sys_ZeeSyst_es2012c.png")
-
-        canvas = ROOT.TCanvas()
-        multigraph = ROOT.TMultiGraph()
-        multigraph.SetTitle("mg_Zeeall;#eta; E_{sys} / E_{nom}")
-        multigraph.Add(ratios_smearing[ROOT.egEnergyCorr.Scale.ZeeAllUp])
-        multigraph.Add(ratios_smearing[ROOT.egEnergyCorr.Scale.ZeeAllDown])
-        multigraph.Add(ratios_nosmearing[ROOT.egEnergyCorr.Scale.ZeeAllUp])
-        multigraph.Add(ratios_nosmearing[ROOT.egEnergyCorr.Scale.ZeeAllDown])
-        multigraph.Draw("APL")
-        canvas.SaveAs("sys_ZeeAll_es2012c.png")
-
-    def test_layer_invariance(self):
-        tool_es2012c_layer1 = self.EnergyCorrectionTool()
-        tool_es2012c_layer1.setESModel(ROOT.egEnergyCorr.es2012c)
-        tool_es2012c_layer1.useLayer2Recalibration(False)
-        tool_es2012c_layer1.initialize()
-
-        tool_es2012c_layer2 = self.EnergyCorrectionTool()
-        tool_es2012c_layer2.setESModel(ROOT.egEnergyCorr.es2012c)
-        tool_es2012c_layer2.initialize()
-
-        for eta in linspace(-3.5, 3.5, 300):
-            E0 = self.E0MC.GetBinContent(self.E0MC.FindBin(eta)) * 1E3
-            E1 = self.E1MC.GetBinContent(self.E1MC.FindBin(eta)) * 1E3
-            E2 = self.E2MC.GetBinContent(self.E2MC.FindBin(eta)) * 1E3
-            E3 = self.E3MC.GetBinContent(self.E3MC.FindBin(eta)) * 1E3
-
-            phi = 0
-
-            particle_information = ROOT.AtlasRoot.egammaEnergyCorrectionTool.ParticleInformation(E0, E1, E2, E3,
-                                                                                                 eta,
-                                                                                                 phi,
-                                                                                                 40E3,
-                                                                                                 eta,
-                                                                                                 phi,
-                                                                                                 35E3,
-                                                                                                 20E3,
-                                                                                                 18E3,
-                                                                                                 1,
-                                                                                                 1,
-                                                                                                 1,
-                                                                                                 1, 100)
-            energy1 = tool_es2012c_layer1.getCorrectedEnergy(0, Full, particle_information,
-                                                             getattr(ROOT.egEnergyCorr.Scale, 'None'),
-                                                             getattr(ROOT.egEnergyCorr.Resolution, 'None'))
-            energy2 = tool_es2012c_layer2.getCorrectedEnergy(0, Full, particle_information,
-                                                             getattr(ROOT.egEnergyCorr.Scale, 'None'),
-                                                             getattr(ROOT.egEnergyCorr.Resolution, 'None'))
-
-            self.assertEqual(energy1, energy2)
-
-
-class TestConsistencyEgammaMVACalib(unittest.TestCase):
-    def test_electron(self):
-        weight_version = "egammaMVACalib/v1"
-        tool_egammaMVACalib = ROOT.egammaMVACalib(ROOT.egammaMVACalib.egELECTRON,
-                                                  True, weight_version)
-        tool_egammaMVACalib.InitTree(0)
-        # egammaEnergyCorrectionTool uses as default v1
-        tool_EP4MC = ROOT.AtlasRoot.egammaEnergyCorrectionTool()
-        tool_EP4MC.setESModel(6)   # es2012c
-        tool_EP4MC.initialize()
-        from itertools import product
-        for eta, phi, phi_shift, eta_shift, el_cl_E in product(arange(-2.5, 2.5, 0.02),
-                                                               arange(-3, 3, 0.2),
-                                                               (-0.01, 0, 0.01),
-                                                               (-0.01, 0, 0.01),
-                                                               arange(1E3, 200E3, 20E3)):
-            Es0 = el_cl_E * 0.8 * 0.05
-            Es1 = el_cl_E * 0.8 * 0.10
-            Es2 = el_cl_E * 0.8 * 0.65
-            Es3 = el_cl_E * 0.8 * 0.20
-            phiCalo = phi + phi_shift
-            trk_eta = eta + eta_shift
-            etaCalo = eta - eta_shift
-            args = (0, 1,   # run number, Full simulation
-                    Es0, Es1, Es2, Es3,
-                    eta, phi, trk_eta,
-                    el_cl_E,
-                    etaCalo, phiCalo,
-                    0, 0)  # no scale factor, no smearing
-            energy_EP4MC = tool_EP4MC.getCorrectedEnergyElectron(*args)
-            args = (Es0, Es1, Es2, Es3, eta, el_cl_E, etaCalo, phiCalo)
-            energy_egammaMVACalib = tool_egammaMVACalib.getMVAEnergyElectron(*args)
-            self.assertAlmostEqual(energy_EP4MC, energy_egammaMVACalib,
-                                   msg="different energy eta=%f" % eta)
-
-if __name__ == '__main__':
-    ROOT.gROOT.ProcessLine(".x $ROOTCOREBIN/scripts/load_packages.C")
-#    ROOT.gROOT.LoadMacro("AtlasStyle.C")
-#    ROOT.SetAtlasStyle()
-    ROOT.gStyle.SetCanvasDefH(800)
-    ROOT.gStyle.SetCanvasDefW(800)
-    ROOT.gStyle.SetPadTickX(1)
-    ROOT.gStyle.SetPadTickY(1)
-    ROOT.gStyle.SetLabelSize(0.03, "X")
-    ROOT.gStyle.SetLabelSize(0.03, "Y")
-    ROOT.gStyle.SetTitleSize(0.03, "X")
-    ROOT.gStyle.SetTitleSize(0.03, "Y")
-    unittest.main()
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/share/CalibrationExample_jobOptions.py b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/share/CalibrationExample_jobOptions.py
index 1984849f94c56148aba5966f63d0847c17c5d83f..515ba965f3adab40a9fb2c2f5ff1634ba6d36b3a 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/share/CalibrationExample_jobOptions.py
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/share/CalibrationExample_jobOptions.py
@@ -15,6 +15,7 @@ alg = testAthenaEgammaCalibTool()
 alg.EgammaCalibrationAndSmearingTool.ESModel = "es2015cPRE"
 alg.EgammaCalibrationAndSmearingTool.OutputLevel = DEBUG
 theJob += alg
+print alg
 
 # Do some additional tweaking:
 from AthenaCommon.AppMgr import theApp
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/src/CalibratedEgammaProvider.h b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/src/CalibratedEgammaProvider.h
index 8876bad77329f13f27c3d375d1e2272f457b2058..47a27c33389223d1c5880be7d799a32fdf481186 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/src/CalibratedEgammaProvider.h
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/src/CalibratedEgammaProvider.h
@@ -1,12 +1,12 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 
 //athena friendly provider of egamma calibrations - applies the egammaCalibTool to collections 
 //author: will buttinger
 
-// Dear emacs, this is -*- c++ -*-
+
 #ifndef CALIBRATEDEGAMMAPROVIDER_H
 #define CALIBRATEDEGAMMAPROVIDER_H
 
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/src/components/ElectronPhotonFourMomentumCorrection_load.cxx b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/src/components/ElectronPhotonFourMomentumCorrection_load.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..c5db2c71b2a1530a11e9efeec83a00c5ea89242b
--- /dev/null
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/src/components/ElectronPhotonFourMomentumCorrection_load.cxx
@@ -0,0 +1,3 @@
+#include "GaudiKernel/LoadFactoryEntries.h"
+
+LOAD_FACTORY_ENTRIES( ElectronPhotonFourMomentumCorrection )
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/src/dumpAllSystematics.cxx b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/src/dumpAllSystematics.cxx
index a7cb4415e346ff2f0da585f671d9304cf6ea8b96..3625bf1e7173ffa8f2c70376566faf33e24fdc99 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/src/dumpAllSystematics.cxx
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/src/dumpAllSystematics.cxx
@@ -34,33 +34,7 @@
 #include "dumpAllSystematics.h"
 
 DumpAllSystematics::DumpAllSystematics(const std::string& name, ISvcLocator* svcLoc)
-  : AthAlgorithm(name, svcLoc),
-  m_EventNumber(0),
-  m_RunNumber(0),
-  m_instance_index(0),
-  m_actualIntPerXing(0.),
-  m_averageIntPerXing(0.),
-  m_truth_pt(0.),
-  m_truth_phi(0.),
-  m_truth_eta(0.),
-  m_truth_E(0.),
-  m_truth_pdgId(0),
-  m_truth_parent_pdgId(0),
-  m_truth_matched(false),
-  m_truth_isConv(false),
-  m_truth_Rconv(0.),
-  m_npv(0),
-  m_cl_phi(0.),
-  m_cl_eta(0.),
-  m_cl_etaCalo(0.),
-  m_cl_rawcl_Es0(0.),
-  m_cl_rawcl_Es1(0.),
-  m_cl_rawcl_Es2(0.),
-  m_cl_rawcl_Es3(0.),
-  m_cl_E(0.),
-  m_ph_Rconv(0.),
-  m_ph_convFlag(0),
-  m_wstot(0.)
+  : AthAlgorithm(name, svcLoc)
 {
   declareProperty("EgammaCalibrationAndSmearingTools", m_EgammaCalibrationAndSmearingTools);
   declareProperty("particle", m_particle_name="", "electron/photon");
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/src/dumpAllSystematics.h b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/src/dumpAllSystematics.h
index c99ef08367ad8b6f22dea9213a03443250d24455..268810729de2f1708141a0ad5ae9e3cecab649e8 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/src/dumpAllSystematics.h
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/src/dumpAllSystematics.h
@@ -1,7 +1,7 @@
-// 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 DUMPALLSYSTEMATICS_H
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/src/testAthenaEgammaCalibTool.cxx b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/src/testAthenaEgammaCalibTool.cxx
index 538b63bdaf60fd3464b4938afb57d56b6f3a0fa4..6d500b74c3eadfb4d5ebf46e88995d69daf246d6 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/src/testAthenaEgammaCalibTool.cxx
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/src/testAthenaEgammaCalibTool.cxx
@@ -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
 */
 
 // EDM include(s):
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/src/testAthenaEgammaCalibTool.h b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/src/testAthenaEgammaCalibTool.h
index a4b217e79fb17098a50066d6e1d0d6a3982b897f..014fe4745b7eeef68fcfc4ed6f4ed872d5ba9d95 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/src/testAthenaEgammaCalibTool.h
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/src/testAthenaEgammaCalibTool.h
@@ -1,7 +1,7 @@
-// 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 TESTATHENAEGAMMACALIBTOOL_H
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/test/ut_test.py b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/test/ut_test.py
index ff7f8a591d6a26f3913eb64d51434d115a8ef0af..ce598840a5fd4716323e1ba1d07406cbe4694a51 100755
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/test/ut_test.py
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/test/ut_test.py
@@ -522,7 +522,7 @@ class TestEgammaCalibrationAndSmearingTool(unittest.TestCase):
         tool_1NP.setProperty("int")("randomRunNumber", RUN2015).ignore()
         #tool_1NP.setProperty("int")("doSmearing", 0).ignore()   # remove
         #tool_1NP.msg().setLevel(ROOT.MSG.DEBUG)
-        
+
         tool_1NP.initialize().ignore()
 
         tool_FULL = ROOT.CP.EgammaCalibrationAndSmearingTool("tool_es2016data_mc15c_FULL")
@@ -536,7 +536,7 @@ class TestEgammaCalibrationAndSmearingTool(unittest.TestCase):
         tool_FULL.initialize().ignore()
 
         ei = self.factory.create_eventinfo(True, 100000)  # MC
-        for ptype, generator in self.generators().items():
+        for ptype, generator in self.generators().iteritems():
             for particle in generator:
                 sys_set = ROOT.CP.SystematicSet()
                 tool_FULL.applySystematicVariation(sys_set).ignore()
@@ -728,5 +728,5 @@ if __name__ == '__main__':
     ROOT.gROOT.ProcessLine(".x $ROOTCOREDIR/scripts/load_packages.C")
 #    from ROOT import EgammaCalibPeriodRunNumbersExample
 
-    #ROOT.StatusCode.enableChecking()
+    #ROOT.xAOD.TReturnCode.enableFailure()
     unittest.main()
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/test/ut_test_factory.py b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/test/ut_test_factory.py
index e3177ee80c5c784995ab9f18a46f575de420328a..ff2ae3998b8014c9efb8f7405a883bd8e030e215 100755
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/test/ut_test_factory.py
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/test/ut_test_factory.py
@@ -36,7 +36,7 @@ class TestEgammaFactory(unittest.TestCase):
         self.assertAlmostEqual(ph.caloCluster().auxdata("float")("phiCalo"), phi)
         self.assertAlmostEqual(ph.e(), e, delta=0.01)
         self.assertEqual(ph.caloCluster().e(), e)
-        for i in range(3):
+        for i in xrange(3):
             self.assertGreater(ph.caloCluster().energyBE(i), 0)
 
     def test_converted(self):
@@ -60,7 +60,7 @@ class TestEgammaFactory(unittest.TestCase):
         self.assertAlmostEqual(ph.caloCluster().auxdata("float")("phiCalo"), phi)
         self.assertAlmostEqual(ph.e(), e, delta=0.01)
         self.assertEqual(ph.caloCluster().e(), e)
-        for i in range(3):
+        for i in xrange(3):
             self.assertGreater(ph.caloCluster().energyBE(i), 0)
 
     def test_photon(self):
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/test/ut_test_resolution.py b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/test/ut_test_resolution.py
index da0420ee3617cf32506713a13fa48cd6fd31a630..b4a330f56aceeb8ef213a825043a182c0c7a807f 100755
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/test/ut_test_resolution.py
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/test/ut_test_resolution.py
@@ -97,7 +97,7 @@ class TestEgammaResolution(unittest.TestCase):
         f = ROOT.TFile(rootfile)
         tree = f.Get("test_resolution_nonregression_data_run1")
 
-        for ievent in range(tree.GetEntries()):
+        for ievent in xrange(tree.GetEntries()):
 
             tree.GetEntry(ievent)
             resolution = self.tool_run1.getResolution(tree.ptype,
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/util/ElectronPhotonFourMomentumCorrection_test_memory.cxx b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/util/ElectronPhotonFourMomentumCorrection_test_memory.cxx
index 28ac4b93e25ed79a1ad7e86d8aa8943f27d819b9..014e8ccf3785c8682e854789d1003d04d6592f8a 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/util/ElectronPhotonFourMomentumCorrection_test_memory.cxx
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/util/ElectronPhotonFourMomentumCorrection_test_memory.cxx
@@ -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
 */
 
 #include <ElectronPhotonFourMomentumCorrection/EgammaCalibrationAndSmearingTool.h>
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/util/testEgammaCalibTool.cxx b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/util/testEgammaCalibTool.cxx
index da495d0505f76a1aa860c21883fa5c065b2ee9aa..2ee5a17e0044792e67a4adf9dfe0dbd21335cc87 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/util/testEgammaCalibTool.cxx
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/util/testEgammaCalibTool.cxx
@@ -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
 */
 
 //simple macro to test the xAOD-based calibration tool
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/util/testMomentumSystematics.cxx b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/util/testMomentumSystematics.cxx
index 13a792906026de34afc75cfc6db3d4de437f3b5f..a2fa32076800ee81cc32e2d7c71e6a3d5c0b4e52 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/util/testMomentumSystematics.cxx
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/util/testMomentumSystematics.cxx
@@ -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
 */
 
 #include <ElectronPhotonFourMomentumCorrection/egammaEnergyCorrectionTool.h>
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/util/testResolutionParam.cxx b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/util/testResolutionParam.cxx
index 584c73b999f0ab21f306a809381c6fc0295a8f77..20f38592500c1f98c8e1dbd454de227e7588c939 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/util/testResolutionParam.cxx
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/util/testResolutionParam.cxx
@@ -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
 */
 
 #include <ElectronPhotonFourMomentumCorrection/egammaEnergyCorrectionTool.h>
@@ -10,6 +10,7 @@
 #include "TLegend.h"
 #include "TStyle.h"
 #include "TPad.h"
+#include "TFile.h"
 
 int main() {
 
diff --git a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/util/testUniformityCorrections.cxx b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/util/testUniformityCorrections.cxx
index 3b322cb82bc7b5952f4589815e6d527fec40742e..886545fee65dbe976577c466f5d78abe6b5ccf39 100644
--- a/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/util/testUniformityCorrections.cxx
+++ b/PhysicsAnalysis/ElectronPhotonID/ElectronPhotonFourMomentumCorrection/util/testUniformityCorrections.cxx
@@ -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
 */
 
 #include <ElectronPhotonFourMomentumCorrection/egammaEnergyCorrectionTool.h>
diff --git a/Reconstruction/egamma/egammaUtils/CMakeLists.txt b/Reconstruction/egamma/egammaUtils/CMakeLists.txt
index a62403a29994d6d05685c3232652d0f63988e7eb..ae76cabe806c99c6e5df52553a5f69c6b08e7ff3 100644
--- a/Reconstruction/egamma/egammaUtils/CMakeLists.txt
+++ b/Reconstruction/egamma/egammaUtils/CMakeLists.txt
@@ -13,10 +13,10 @@ atlas_add_library( egammaUtils
                    Root/*.cxx
                    PUBLIC_HEADERS egammaUtils
                    INCLUDE_DIRS ${ROOT_INCLUDE_DIRS}
-		   PRIVATE_INCLUDE_DIRS 
-		   LINK_LIBRARIES  ${ROOT_LIBRARIES} xAODCaloEvent xAODTracking xAODEgamma GeoPrimitives  
+		   PRIVATE_INCLUDE_DIRS
+         LINK_LIBRARIES  ${ROOT_LIBRARIES} AsgMessagingLib xAODCaloEvent xAODTracking xAODEgamma GeoPrimitives
 		   PRIVATE_LINK_LIBRARIES FourMomUtils PathResolver AnalysisUtilsLib)
-	  
+
 atlas_add_dictionary( egammaUtilsDict
 		      egammaUtils/egammaUtilsDict.h
 		      egammaUtils/selection.xml
diff --git a/Reconstruction/egamma/egammaUtils/Root/eg_resolution.cxx b/Reconstruction/egamma/egammaUtils/Root/eg_resolution.cxx
index 5332c3e0299c222b9bd877fec7c503a4091a9522..ada3bf0eeefba7daa45d5cfa1a18ed825704fc40 100644
--- a/Reconstruction/egamma/egammaUtils/Root/eg_resolution.cxx
+++ b/Reconstruction/egamma/egammaUtils/Root/eg_resolution.cxx
@@ -18,10 +18,10 @@ T* get_object(TFile& file, const std::string& name){
 }
 
 eg_resolution::eg_resolution(const std::string& configuration)
-  : m_file0()
-  , m_file1()
-  , m_file2()
-  , m_file3()
+  : m_file0(),
+    m_file1(),
+    m_file2(),
+    m_file3()
 {
   if (configuration == "run1") {
     m_file0 = std::make_unique<TFile> (PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v5/resolutionFit_electron_run1.root").c_str() );
@@ -35,10 +35,16 @@ eg_resolution::eg_resolution(const std::string& configuration)
     m_file2 = std::make_unique<TFile> (PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v5/resolutionFit_recoConv_run2_pre.root").c_str());
     m_file3 = std::make_unique<TFile> (PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v5/resolutionFit_trueUnconv_run2_pre.root").c_str());
   }
-
+  else if (configuration == "run2_R21_v1") {
+    m_file0 = std::make_unique<TFile> (PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v20/resolutionFit_electron_run2_release21_es2017_R21_v1.root").c_str());
+    m_file1 = std::make_unique<TFile> (PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v20/resolutionFit_recoUnconv_run2_release21_es2017_R21_v1.root").c_str());
+    m_file2 = std::make_unique<TFile> (PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v20/resolutionFit_recoConv_run2_release21_es2017_R21_v1.root").c_str());
+    m_file3 = std::make_unique<TFile> (PathResolverFindCalibFile("ElectronPhotonFourMomentumCorrection/v20/resolutionFit_trueUnconvertedPhoton_run2_release21_es2017_R21_v1.root").c_str()); // assume reco and true unconv having similar resolutions
+  }
   if (!m_file0 or !m_file1 or !m_file2 or !m_file3) {
     throw std::runtime_error("cannot find input file for resolutions");
   }
+
   m_hSampling[0][0] = get_object<TH1>(*m_file0, "hsamplingG");
   m_hSampling[0][1] = get_object<TH1>(*m_file0, "hsampling80");
   m_hSampling[0][2] = get_object<TH1>(*m_file0, "hsampling90");
@@ -120,6 +126,7 @@ double eg_resolution::getResolution(int particle_type, double energy, double eta
    const double rsampling = m_hSampling[particle_type][resolution_type]->GetBinContent(ibinEta + 1);
    const double rnoise    = m_hNoise[particle_type][resolution_type]->GetBinContent(ibinEta + 1);
    const double rconst    = m_hConst[particle_type][resolution_type]->GetBinContent(ibinEta + 1);
+
    const double sigma2 = rsampling*rsampling/energyGeV + rnoise*rnoise/energyGeV/energyGeV + rconst*rconst;
    return sqrt(sigma2);
 }
diff --git a/Reconstruction/egamma/egammaUtils/egammaUtils/eg_resolution.h b/Reconstruction/egamma/egammaUtils/egammaUtils/eg_resolution.h
index d214c49d9147ebed2fc140c3bb3ffa443663cfbd..0cf2365e0f26fbb081c6dbcea7031c124c814bb7 100644
--- a/Reconstruction/egamma/egammaUtils/egammaUtils/eg_resolution.h
+++ b/Reconstruction/egamma/egammaUtils/egammaUtils/eg_resolution.h
@@ -7,11 +7,12 @@
 
 #include <cstdlib>
 #include <cmath>
+#include <memory>
+
 #include "xAODEgamma/Egamma.h"
 #include "TH1.h"
 #include "TFile.h"
 #include "TArrayD.h"
-#include <memory>
 /**
   @class eg_resolution
   @brief get resolution for electron and photons (converted / unconverted) vs E,eta