diff --git a/PhysicsAnalysis/AnalysisCommon/IsolationSelection/IsolationSelection/IIsolationSelectionTool.h b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/IsolationSelection/IIsolationSelectionTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..42fe382dea334d8226a5a9157dcc503bd7f335e5
--- /dev/null
+++ b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/IsolationSelection/IIsolationSelectionTool.h
@@ -0,0 +1,56 @@
+// Dear emacs, this is -*- c++ -*-
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: IIsolationSelectionTool.h 672685 2015-06-05 11:01:39Z dzhang $
+// #ifndef ISOLATIONSELECTION_IISOLATIONSELECTIONTOOL_H
+// #define ISOLATIONSELECTION_IISOLATIONSELECTIONTOOL_H
+#ifndef ELECTRONISOLATIONSELECTION_IISOLATIONSELECTIONTOOL_H
+#define ELECTRONISOLATIONSELECTION_IISOLATIONSELECTIONTOOL_H
+
+// Framework include(s):
+#include "AsgTools/IAsgTool.h"
+#include "PATCore/TAccept.h"
+
+// EDM include(s):
+#include "xAODPrimitives/IsolationType.h"
+#include "xAODEgamma/Photon.h"
+#include "xAODEgamma/Electron.h"
+#include "xAODMuon/Muon.h"
+// #include "IsolationSelection/strMuon.h"
+
+// std include(s):
+#include <map>
+#include <memory>
+
+  ///
+  /// @author John Morris <john.morris@cern.ch>
+  ///
+  /// $Revision: 672685 $
+  /// $Date: 2015-06-05 13:01:39 +0200 (Fri, 05 Jun 2015) $
+  ///
+  /// @brief Select isolated Photons, Electrons and Muons
+  ///  
+  
+namespace CP
+{
+  class IIsolationSelectionTool :  virtual public asg::IAsgTool {
+
+    /// Declare the interface that the class provides
+    ASG_TOOL_INTERFACE( CP::IIsolationSelectionTool )
+
+    public: 
+      // Cut on object
+      virtual const Root::TAccept& accept( const xAOD::Photon& x   ) const = 0;
+      virtual const Root::TAccept& accept( const xAOD::Electron& x ) const = 0;
+      virtual const Root::TAccept& accept( const xAOD::Muon& x     ) const = 0;
+      
+      virtual const Root::TAccept& getPhotonTAccept()   const = 0;
+      virtual const Root::TAccept& getElectronTAccept() const = 0;
+      virtual const Root::TAccept& getMuonTAccept()     const = 0;       
+      
+  };
+} // end namespace
+#endif
diff --git a/PhysicsAnalysis/AnalysisCommon/IsolationSelection/IsolationSelection/IsolationCondition.h b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/IsolationSelection/IsolationCondition.h
new file mode 100644
index 0000000000000000000000000000000000000000..4f4b2abf8f03bb9d6cd5d9730087f3915bddb33b
--- /dev/null
+++ b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/IsolationSelection/IsolationCondition.h
@@ -0,0 +1,53 @@
+// Dear emacs, this is -*- c++ -*-
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ISOLATIONSELECTION_ISOLATIONCONDITION_H
+#define ISOLATIONSELECTION_ISOLATIONCONDITION_H
+
+#include <memory>
+#include <vector>
+#include <map>
+#include "xAODPrimitives/IsolationType.h"
+#include <xAODPrimitives/tools/getIsolationAccessor.h>
+#include "AthContainers/AuxElement.h"
+#include "xAODBase/IParticle.h"
+
+// Forward Declaration(s)
+class TF1;
+class TH3F;
+  
+struct strObj{
+  float pt;
+  float eta;
+  std::vector< float > isolationValues;
+};
+
+namespace CP
+{
+  class IsolationCondition{
+    public:
+      IsolationCondition(std::string name, xAOD::Iso::IsolationType isoType):m_name(name),m_isolationType(isoType){
+        m_acc = xAOD::getIsolationAccessor(m_isolationType);
+        m_cutValue = -999;
+      };
+      virtual ~IsolationCondition(){}
+      
+      IsolationCondition() = delete;
+      IsolationCondition(const IsolationCondition& rhs) = delete;
+      IsolationCondition& operator=(const IsolationCondition& rhs) = delete;
+      
+      std::string name(){return m_name;}
+      virtual bool accept(const xAOD::IParticle& x, std::map< xAOD::Iso::IsolationType, float >* cutValues=0) = 0;
+      virtual bool accept(const strObj& x, std::map< xAOD::Iso::IsolationType, float >* cutValues=0) = 0;
+
+    protected:
+      std::string m_name;
+      xAOD::Iso::IsolationType m_isolationType;
+      SG::AuxElement::Accessor< float >* m_acc; 
+      float m_cutValue;
+  };
+}
+#endif
diff --git a/PhysicsAnalysis/AnalysisCommon/IsolationSelection/IsolationSelection/IsolationConditionFormula.h b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/IsolationSelection/IsolationConditionFormula.h
new file mode 100644
index 0000000000000000000000000000000000000000..6aeb1e6de88a5bd9a275c93ab0f2c9a50d065c4e
--- /dev/null
+++ b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/IsolationSelection/IsolationConditionFormula.h
@@ -0,0 +1,41 @@
+// Dear emacs, this is -*- c++ -*-
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ISOLATIONSELECTION_ISOLATIONCONDITIONFORMULA_H
+#define ISOLATIONSELECTION_ISOLATIONCONDITIONFORMULA_H
+
+#include <memory>
+#include <vector>
+#include <map>
+// #include "xAODPrimitives/IsolationType.h"
+// #include "AthContainers/AuxElement.h"
+// #include "xAODBase/IParticle.h"
+#include "IsolationCondition.h"
+
+// Forward Declaration(s)
+class TF1;
+class TH3F;
+  
+namespace CP
+{
+  class IsolationConditionFormula: public IsolationCondition{
+    public:
+      IsolationConditionFormula(std::string name, xAOD::Iso::IsolationType isoType, const std::string& cutFunction);
+      virtual ~IsolationConditionFormula(){}
+      
+      IsolationConditionFormula() = delete;
+      IsolationConditionFormula(const IsolationConditionFormula& rhs) = delete;
+      IsolationConditionFormula& operator=(const IsolationConditionFormula& rhs) = delete;
+      
+      bool accept(const xAOD::IParticle& x, std::map< xAOD::Iso::IsolationType, float >* cutValues=0);
+      bool accept(const strObj& x, std::map< xAOD::Iso::IsolationType, float >* cutValues=0);
+      void getCutValue(const float pt);
+
+    private:      
+      std::shared_ptr<TF1>  m_cutFunction;
+  };
+}
+#endif
diff --git a/PhysicsAnalysis/AnalysisCommon/IsolationSelection/IsolationSelection/IsolationConditionHist.h b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/IsolationSelection/IsolationConditionHist.h
new file mode 100644
index 0000000000000000000000000000000000000000..dc14a1cbc72cca12ff254f7d97835c80e80fdba4
--- /dev/null
+++ b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/IsolationSelection/IsolationConditionHist.h
@@ -0,0 +1,44 @@
+// Dear emacs, this is -*- c++ -*-
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ISOLATIONSELECTION_ISOLATIONCONDITIONHIST_H
+#define ISOLATIONSELECTION_ISOLATIONCONDITIONHIST_H
+
+#include <memory>
+#include <vector>
+#include <map>
+// #include "xAODPrimitives/IsolationType.h"
+// #include "AthContainers/AuxElement.h"
+// #include "xAODBase/IParticle.h"
+#include "IsolationCondition.h"
+
+// Forward Declaration(s)
+class TF1;
+class TH3F;
+  
+namespace CP
+{
+  class IsolationConditionHist: public IsolationCondition{
+    public:
+      IsolationConditionHist(std::string name, xAOD::Iso::IsolationType isoType, const std::string& isolationFunction, const std::shared_ptr<TH3F> efficiencyHisto3D);
+      virtual ~IsolationConditionHist(){}
+      
+      IsolationConditionHist() = delete;
+      IsolationConditionHist(const IsolationConditionHist& rhs) = delete;
+      IsolationConditionHist& operator=(const IsolationConditionHist& rhs) = delete;
+      
+      std::string name(){return m_name;}
+      bool accept(const xAOD::IParticle& x, std::map< xAOD::Iso::IsolationType, float >* cutValues=0);
+      bool accept(const strObj& x, std::map< xAOD::Iso::IsolationType, float >* cutValues=0);
+      void getCutValue(const float pt, const float eta);
+
+    private:      
+      std::shared_ptr<TH3F> m_efficiencyHisto3D;
+      std::shared_ptr<TF1>  m_isolationFunction;
+      bool m_ptGeV;
+  };
+}
+#endif
diff --git a/PhysicsAnalysis/AnalysisCommon/IsolationSelection/IsolationSelection/IsolationSelectionTool.h b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/IsolationSelection/IsolationSelectionTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..64f2a3b07b2f0bdedbc47e47cbea78023d2384ab
--- /dev/null
+++ b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/IsolationSelection/IsolationSelectionTool.h
@@ -0,0 +1,111 @@
+// Dear emacs, this is -*- c++ -*-
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: IsolationSelectionTool.h 680193 2015-07-03 15:30:37Z jdevivi $
+#ifndef ISOLATIONSELECTION_ISOLATIONSELECTIONTOOL_H
+#define ISOLATIONSELECTION_ISOLATIONSELECTIONTOOL_H
+
+// Framework include(s):
+#include "AsgTools/AsgTool.h"
+#include "AsgTools/ToolHandle.h"
+
+// Local include(s):
+#include "IsolationSelection/IIsolationSelectionTool.h"
+#include "IsolationSelection/IsolationWP.h"
+
+// Forward declaration(s):
+class TFile;
+class TH1F;
+
+namespace CP 
+{
+
+  /// Implementation of IIsolationSelectionTool
+  ///
+  ///
+  /// @author John Morris <john.morris@cern.ch>
+  /// @author Dongliang Zhang <dongliang.zhang@cern.ch>
+  ///
+  /// $Revision: 680193 $
+  /// $Date: 2015-07-03 17:30:37 +0200 (Fri, 03 Jul 2015) $
+  ///
+  
+  class IsolationSelectionTool :  public virtual CP::IIsolationSelectionTool,
+                                  public asg::AsgTool {
+
+    /// Create a proper constructor for Athena
+    ASG_TOOL_CLASS( IsolationSelectionTool , CP::IIsolationSelectionTool )
+
+    public:
+      /// Constructor for standalone usage, but please do use the interface and ToolHandle
+      IsolationSelectionTool( const std::string& name ); 
+      /// Destructor
+      virtual ~IsolationSelectionTool();
+      
+      /// Function initialising the tool
+      virtual StatusCode initialize();
+      /// Function finalizing the tool
+      virtual StatusCode finalize();   
+      
+      enum IsoWPType{Efficiency, Cut};
+      virtual const Root::TAccept& accept( const xAOD::Photon& x   ) const;
+      virtual const Root::TAccept& accept( const xAOD::Electron& x ) const;
+      virtual const Root::TAccept& accept( const xAOD::Muon& x     ) const;
+      virtual const Root::TAccept& accept( const strObj& x     ) const;
+      virtual const Root::TAccept& accept(const xAOD::IParticle& x) const; // for tracks, and others?
+      
+      virtual const Root::TAccept& getPhotonTAccept()   const;
+      virtual const Root::TAccept& getElectronTAccept() const;
+      virtual const Root::TAccept& getMuonTAccept()     const;
+      virtual const Root::TAccept& getObjTAccept()     const;
+     
+      StatusCode addWP(std::string WP, xAOD::Type::ObjectType type);
+      StatusCode addWP(IsolationWP* wp, xAOD::Type::ObjectType type);
+      StatusCode addMuonWP(std::string wpname);
+      StatusCode addPhotonWP(std::string wpname);
+      StatusCode addElectronWP(std::string wpname);
+      StatusCode addUserDefinedWP(std::string WPname, xAOD::Type::ObjectType ObjType, std::vector< std::pair<xAOD::Iso::IsolationType, std::string> >& cuts, std::string key="", IsoWPType type=Efficiency);
+      StatusCode setIParticleCutsFrom(xAOD::Type::ObjectType ObjType);
+      void addCutToWP(IsolationWP* wp, std::string key, const xAOD::Iso::IsolationType t, const std::string expression);
+      std::vector< IsolationWP* >& getMuonWPs(){return m_muWPs;}
+      std::vector< IsolationWP* >& getElectronWPs(){return m_elWPs;}
+      std::vector< IsolationWP* >& getPhotonWPs(){return m_phWPs;}
+      std::vector< IsolationWP* >& getObjWPs(){return m_objWPs;}
+
+    private:
+      // Stupid ROOT
+      TDirectory* getTemporaryDirectory(void) const;
+      
+      std::string m_muWPname;
+      std::string m_elWPname;
+      std::string m_phWPname;
+      std::string m_muWPKey;
+      std::string m_elWPKey;
+      std::string m_phWPKey;
+
+      /// input file 
+      std::string m_calibFileName;
+      std::shared_ptr<TFile> m_calibFile;
+
+      /// internal use 
+      std::vector< IsolationWP* > m_muWPs;
+      std::vector< IsolationWP* > m_elWPs;
+      std::vector< IsolationWP* > m_phWPs;
+      std::vector< IsolationWP* > m_objWPs;
+
+      /// TAccept's
+      mutable Root::TAccept m_photonAccept;
+      mutable Root::TAccept m_electronAccept;
+      mutable Root::TAccept m_muonAccept;
+      mutable Root::TAccept m_objAccept;
+
+      /// Iparticle interface
+      std::vector< IsolationWP* >* m_iparWPs;
+      mutable Root::TAccept* m_iparAccept;
+  };
+} // namespace
+
+#endif
diff --git a/PhysicsAnalysis/AnalysisCommon/IsolationSelection/IsolationSelection/IsolationWP.h b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/IsolationSelection/IsolationWP.h
new file mode 100644
index 0000000000000000000000000000000000000000..383aa679ea829fa5c9da97b5b50408ec2a9ae11e
--- /dev/null
+++ b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/IsolationSelection/IsolationWP.h
@@ -0,0 +1,38 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ISOLATIONSELECTION_ISOLATIONWP_H
+#define ISOLATIONSELECTION_ISOLATIONWP_H
+
+#include <xAODPrimitives/tools/getIsolationAccessor.h>
+#include <IsolationSelection/IsolationCondition.h>
+#include "PATCore/TAccept.h"
+#include <map>
+
+namespace CP
+{
+  class IsolationWP{
+   public:
+     IsolationWP(std::string name):m_name(name),m_cutValues(nullptr){};
+     ~IsolationWP();
+     std::string name(){return m_name;}
+
+     const Root::TAccept& accept(const xAOD::IParticle& p) const;
+     const Root::TAccept& accept(const strObj& p) const;
+     void addCut(IsolationCondition* cut);
+     const Root::TAccept& getAccept(){return m_accept;}
+     void saveCutValues(bool yes=true){
+       if(yes&&(!m_cutValues)) m_cutValues = new std::map< xAOD::Iso::IsolationType, float >();
+       else if((!yes)&&m_cutValues){delete m_cutValues;}
+      }
+     std::map< xAOD::Iso::IsolationType, float >* cutValues(){return m_cutValues;}
+
+   private:
+     std::string m_name;
+     std::vector< IsolationCondition* > m_cuts;
+     std::map< xAOD::Iso::IsolationType, float >* m_cutValues;
+     mutable Root::TAccept m_accept; 
+  };
+}
+#endif // ISOLATIONSELECTION_ISOLATIONWP_H
diff --git a/PhysicsAnalysis/AnalysisCommon/IsolationSelection/Root/IsolationConditionFormula.cxx b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/Root/IsolationConditionFormula.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..2ee77635e3255857a636f3fa5397212f26fb0698
--- /dev/null
+++ b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/Root/IsolationConditionFormula.cxx
@@ -0,0 +1,38 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "IsolationSelection/IsolationConditionFormula.h"
+// #include <xAODPrimitives/tools/getIsolationAccessor.h>
+#include <TF1.h>
+#include <TH3.h>
+#include <TString.h>
+#include <cmath>
+#include <algorithm>
+
+namespace CP
+{
+  IsolationConditionFormula::IsolationConditionFormula(std::string name, xAOD::Iso::IsolationType isoType, const std::string& cutFunction):
+    IsolationCondition(name, isoType)
+  {
+    m_cutFunction = std::shared_ptr<TF1>(new TF1(cutFunction.c_str(), cutFunction.c_str()));
+  }
+  
+  bool IsolationConditionFormula::accept(const xAOD::IParticle& x, std::map< xAOD::Iso::IsolationType, float >* c)
+  {
+    getCutValue(x.pt());
+    if(c) (*c)[m_isolationType] = m_cutValue;
+    return (*m_acc)(x)<=m_cutValue;
+  }
+  
+  bool IsolationConditionFormula::accept(const strObj& x, std::map< xAOD::Iso::IsolationType, float >* c)
+  {
+    getCutValue(x.pt);
+    if(c) (*c)[m_isolationType] = m_cutValue;
+    return x.isolationValues[m_isolationType]<=m_cutValue;
+  }
+
+  void IsolationConditionFormula::getCutValue(const float pt){
+    m_cutValue = m_cutFunction->Eval(pt);
+  }
+}
diff --git a/PhysicsAnalysis/AnalysisCommon/IsolationSelection/Root/IsolationConditionHist.cxx b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/Root/IsolationConditionHist.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..e91b9d02825850748652b3cc61c27f4be1b0b668
--- /dev/null
+++ b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/Root/IsolationConditionHist.cxx
@@ -0,0 +1,53 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: IsolationConditionHist.cxx 678002 2015-06-24 15:39:36Z morrisj $
+
+#include "IsolationSelection/IsolationConditionHist.h"
+// #include <xAODPrimitives/tools/getIsolationAccessor.h>
+#include <TF1.h>
+// #include <TH1.h>
+#include <TH3.h>
+#include <TString.h>
+#include <cmath>
+#include <algorithm>
+// #include <sstream>
+
+// #include <iostream>
+// using std::cout;
+// using std::endl;
+
+namespace CP
+{
+  IsolationConditionHist::IsolationConditionHist(std::string name, xAOD::Iso::IsolationType isoType, const std::string& isolationFunction, const std::shared_ptr<TH3F> efficiencyHisto3D):
+    IsolationCondition(name, isoType),
+    m_efficiencyHisto3D(efficiencyHisto3D)
+  {
+    m_isolationFunction = std::shared_ptr<TF1>( new TF1(isolationFunction.c_str(), isolationFunction.c_str(), 0.0, 1000.0));
+
+    /// check if pt is using GeV as unit
+    std::string xtitle(m_efficiencyHisto3D->GetXaxis()->GetTitle());
+    m_ptGeV = (xtitle.find("GeV")!=std::string::npos);
+    m_cutValue = -999;
+  }
+  
+  bool IsolationConditionHist::accept(const xAOD::IParticle& x, std::map< xAOD::Iso::IsolationType, float >* c)
+  {
+    getCutValue(x.pt(),x.eta());
+    if(c) (*c)[m_isolationType] = m_cutValue;
+    return (*m_acc)(x)<=m_cutValue*x.pt();
+  }
+  
+  bool IsolationConditionHist::accept(const strObj& x, std::map< xAOD::Iso::IsolationType, float >* c)
+  {
+    getCutValue(x.pt,x.eta);
+    if(c) (*c)[m_isolationType] = m_cutValue;
+    return x.isolationValues[m_isolationType]<=m_cutValue*x.pt;
+  }
+
+  void IsolationConditionHist::getCutValue(const float pt, const float eta){
+    float xpt = pt*0.001; // convert to GeV
+    m_cutValue = m_efficiencyHisto3D->GetBinContent(m_efficiencyHisto3D->GetXaxis()->FindBin(m_ptGeV?xpt:pt), m_efficiencyHisto3D->GetYaxis()->FindBin(eta), std::min(int(m_isolationFunction->Eval(xpt)), 99));
+  }
+}
diff --git a/PhysicsAnalysis/AnalysisCommon/IsolationSelection/Root/IsolationSelectionTool.cxx b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/Root/IsolationSelectionTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..9ab928710a9a764cab6f928daf92fe948c3ee7d3
--- /dev/null
+++ b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/Root/IsolationSelectionTool.cxx
@@ -0,0 +1,356 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include <xAODPrimitives/IsolationType.h>
+#include <IsolationSelection/IsolationSelectionTool.h>
+#include <IsolationSelection/IsolationConditionHist.h>
+#include <IsolationSelection/IsolationConditionFormula.h>
+#include "PathResolver/PathResolver.h"
+#include <TROOT.h>
+#include <TFile.h>
+#include <TObjString.h>
+#include <TH3.h>
+
+namespace CP
+{
+  IsolationSelectionTool::IsolationSelectionTool( const std::string& name ) :
+    asg::AsgTool( name ),  
+    /// input file 
+    m_calibFileName("IsolationSelection/v1/DC14_IsolationCutValues_TruthBased_Zee_Zmumu.root"),
+    m_calibFile(nullptr),
+    
+    /// TAccept's
+    m_photonAccept("IsolationSelectionToolPhotonTAccept"),
+    m_electronAccept("IsolationSelectionToolElectronTAccept"),
+    m_muonAccept("IsolationSelectionToolMuonTAccept"),
+    m_objAccept("IsolationSelectionToolObjTAccept"),
+    m_iparWPs(0),
+    m_iparAccept(0)
+  {
+    declareProperty("CalibFileName", m_calibFileName = "IsolationSelection/v1/MC15_Z_Jpsi_cutMap.root", "The config file to use");
+    declareProperty("MuonWP", m_muWPname = "Undefined" , "Working point for muon");
+    declareProperty("ElectronWP", m_elWPname = "Undefined" , "Working point for electron");
+    declareProperty("PhotonWP", m_phWPname = "Undefined" , "Working point for photon");
+    declareProperty("MuonKey", m_muWPKey = "/Muons/DFCommonGoodMuon/mu_cutValues_", "path of the cut map for muon");
+    declareProperty("ElectronKey", m_elWPKey = "/ElectronPhoton/LHTight/el_cutValues_", "path of the cut map for electron");
+    declareProperty("PhotonKey", m_phWPKey = "/ElectronPhoton/LHTight/el_cutValues_", "path of the cut map for photon");
+  }
+
+  IsolationSelectionTool::~IsolationSelectionTool(){
+    /// need a fix? Some wp might be create by external code..
+    for (auto c: m_muWPs) if(c){delete c; c=nullptr;}
+    for (auto c: m_elWPs) if(c){delete c; c=nullptr;}
+    for (auto c: m_phWPs) if(c){delete c; c=nullptr;}
+  }
+
+  StatusCode IsolationSelectionTool::initialize() 
+  {
+    /// Greet the user:
+    ATH_MSG_INFO( "Initialising..." );
+    std::string filename = PathResolverFindCalibFile(m_calibFileName);
+
+    ATH_MSG_INFO("Reading input file "<< m_calibFileName << " from " << filename);
+    m_calibFile = std::shared_ptr<TFile>(new TFile(filename.c_str() , "READ")); 
+    
+    TObjString* versionInfo = (TObjString*)m_calibFile->Get("VersionInfo");
+    if(versionInfo) ATH_MSG_INFO( "VersionInfo:" << versionInfo->String());
+    else ATH_MSG_WARNING( "VersionInfo of input file (" << filename << ") is missing.");
+
+    /// setup working points
+    if(m_phWPname != "Undefined") ATH_CHECK(addPhotonWP(m_phWPname));
+    if(m_elWPname != "Undefined") ATH_CHECK(addElectronWP(m_elWPname));
+    if(m_muWPname != "Undefined") ATH_CHECK(addMuonWP(m_muWPname));
+ 
+    /// Return gracefully:
+    return StatusCode::SUCCESS;
+  }
+
+  StatusCode IsolationSelectionTool::setIParticleCutsFrom(xAOD::Type::ObjectType ObjType){
+    if(ObjType==xAOD::Type::Electron) {m_iparAccept = &m_electronAccept; m_iparWPs = &m_elWPs;}
+    else if(ObjType==xAOD::Type::Muon){m_iparAccept = &m_muonAccept; m_iparWPs = &m_muWPs;}
+    else if(ObjType==xAOD::Type::Photon){m_iparAccept = &m_photonAccept; m_iparWPs = &m_phWPs;}
+    else {return StatusCode::FAILURE;}
+
+    return StatusCode::SUCCESS;
+  }
+
+  StatusCode IsolationSelectionTool::finalize()
+  {
+    /// Return gracefully:
+    return StatusCode::SUCCESS;
+  }  
+
+  void IsolationSelectionTool::addCutToWP(IsolationWP* wp, std::string key, const xAOD::Iso::IsolationType t, const std::string expression)
+  {
+    std::string varname(xAOD::Iso::toString(t));
+    key+=varname;
+    
+    // Stupid ROOT, this is silly, why do I need to do this????? why????
+    // Create a unique directory in memory to hold the histograms:
+    TDirectory* tempDir = getTemporaryDirectory();
+    tempDir->cd();    
+    
+    std::shared_ptr<TH3F> histogram((TH3F*)m_calibFile->Get(key.c_str())->Clone());
+    wp->addCut(new IsolationConditionHist(varname, t, expression, histogram));
+  }
+
+  StatusCode IsolationSelectionTool::addMuonWP(std::string muWPname)
+  {
+    auto wp = new IsolationWP(muWPname);
+//     if(muWPname == "VeryLooseTrackOnly"){
+    if(muWPname == "LooseTrackOnly"){
+      addCutToWP(wp, m_muWPKey, xAOD::Iso::ptvarcone30, "99");
+//     }else if(muWPname == "VeryLoose"){
+    }else if(muWPname == "Loose"){
+      addCutToWP(wp, m_muWPKey, xAOD::Iso::ptvarcone30, "99");
+      addCutToWP(wp, m_muWPKey, xAOD::Iso::topoetcone20, "99");
+//     }else if(muWPname == "Loose"){
+    }else if(muWPname == "Tight"){
+      addCutToWP(wp, m_muWPKey, xAOD::Iso::ptvarcone30, "99");
+      addCutToWP(wp, m_muWPKey, xAOD::Iso::topoetcone20, "96");
+//     }else if(muWPname == "Tight"){
+//       addCutToWP(wp, m_muWPKey, xAOD::Iso::ptvarcone30, "94");
+//       addCutToWP(wp, m_muWPKey, xAOD::Iso::topoetcone20, "89");
+    }else if(muWPname == "Gradient"){
+      addCutToWP(wp, m_muWPKey, xAOD::Iso::ptvarcone30, "0.1143*x+92.14");
+      addCutToWP(wp, m_muWPKey, xAOD::Iso::topoetcone20, "0.1143*x+92.14");
+    }else if(muWPname == "GradientLoose"){
+      addCutToWP(wp, m_muWPKey, xAOD::Iso::ptvarcone30, "0.057*x+95.57");
+      addCutToWP(wp, m_muWPKey, xAOD::Iso::topoetcone20, "0.057*x+95.57");
+    }else{
+      ATH_MSG_ERROR("Unknown muon isolaiton WP: " << muWPname);
+      delete wp;
+      return StatusCode::FAILURE;
+    }
+
+    m_muWPs.push_back(wp);
+    m_muonAccept.addCut(wp->name(), wp->name());
+
+    return StatusCode::SUCCESS; 
+  }
+
+  
+  StatusCode IsolationSelectionTool::addPhotonWP(std::string phWPname)
+  {   
+    auto wp = new IsolationWP(phWPname);
+    if(phWPname == "Cone40CaloOnly"){
+      wp->addCut(new IsolationConditionFormula("topoetcone40", xAOD::Iso::topoetcone40, "0.024*x+2900"));
+    }else if(phWPname == "Cone40"){
+      wp->addCut(new IsolationConditionFormula("Cone40_calo", xAOD::Iso::topoetcone40, "0.028*x+3400"));
+      wp->addCut(new IsolationConditionFormula("Cone40_track", xAOD::Iso::ptcone40, "0.12*x"));
+    }else if(phWPname == "Cone20"){
+      wp->addCut(new IsolationConditionFormula("Cone20_calo", xAOD::Iso::topoetcone20, "0.015*x+1500"));
+      wp->addCut(new IsolationConditionFormula("Cone20_track", xAOD::Iso::ptcone20, "0.04*x"));
+    }else{
+      ATH_MSG_ERROR("Unknown photon isolaiton WP: " << phWPname);
+      delete wp;
+      return StatusCode::FAILURE;
+    }
+
+    m_phWPs.push_back(wp);
+    m_photonAccept.addCut(wp->name(), wp->name());
+
+    // Return gracefully:
+    return StatusCode::SUCCESS;    
+  }
+  
+  
+  StatusCode IsolationSelectionTool::addElectronWP(std::string elWPname)
+  {
+    auto wp = new IsolationWP(elWPname);
+//     if(elWPname == "VeryLooseTrackOnly"){
+    if(elWPname == "LooseTrackOnly"){
+      addCutToWP(wp, m_elWPKey, xAOD::Iso::ptvarcone20, "99");
+//     }else if(elWPname == "VeryLoose"){
+    }else if(elWPname == "Loose"){
+      addCutToWP(wp, m_elWPKey, xAOD::Iso::ptvarcone20, "99");
+      addCutToWP(wp, m_elWPKey, xAOD::Iso::topoetcone20, "99");
+//     }else if(elWPname == "Loose"){
+    }else if(elWPname == "Tight"){
+      addCutToWP(wp, m_elWPKey, xAOD::Iso::ptvarcone20, "99");
+      addCutToWP(wp, m_elWPKey, xAOD::Iso::topoetcone20, "96");
+//     }else if(elWPname == "Tight"){
+//       addCutToWP(wp, m_elWPKey, xAOD::Iso::ptvarcone20, "94");
+//       addCutToWP(wp, m_elWPKey, xAOD::Iso::topoetcone20, "89");
+    }else if(elWPname == "Gradient"){
+      addCutToWP(wp, m_elWPKey, xAOD::Iso::ptvarcone20, "0.1143*x+92.14");
+      addCutToWP(wp, m_elWPKey, xAOD::Iso::topoetcone20, "0.1143*x+92.14");
+    }else if(elWPname == "GradientLoose"){
+      addCutToWP(wp, m_elWPKey, xAOD::Iso::ptvarcone20, "0.057*x+95.57");
+      addCutToWP(wp, m_elWPKey, xAOD::Iso::topoetcone20, "0.057*x+95.57");
+    }else{
+      ATH_MSG_ERROR("Unknown electron isolaiton WP: " << elWPname);
+      delete wp;
+      return StatusCode::FAILURE;
+    }
+
+    m_elWPs.push_back(wp);
+    m_electronAccept.addCut(wp->name(), wp->name());
+
+    // Return gracefully:
+    return StatusCode::SUCCESS;    
+  }
+
+  StatusCode IsolationSelectionTool::addUserDefinedWP(std::string WPname, xAOD::Type::ObjectType ObjType, std::vector< std::pair<xAOD::Iso::IsolationType, std::string> >& cuts, std::string key, IsoWPType type)
+  {
+    std::vector< IsolationWP* >* wps(nullptr);
+    Root::TAccept* ac(nullptr);
+    if(ObjType==xAOD::Type::Electron){
+      if(key=="") key = m_elWPKey;
+      wps = &m_elWPs;
+      ac = &m_electronAccept;
+    }else if(ObjType==xAOD::Type::Muon){
+      if(key=="") key = m_muWPKey;
+      wps = &m_muWPs;
+      ac = &m_muonAccept;
+    }else if(ObjType==xAOD::Type::Photon){
+      if(key=="") key = m_phWPKey;
+      wps = &m_phWPs;
+      ac = &m_photonAccept;
+    }else if(ObjType==xAOD::Type::Other){
+      if(key=="") return StatusCode::FAILURE;
+      wps = &m_objWPs;
+      ac = &m_objAccept;
+    }else{
+      return StatusCode::FAILURE;
+    }
+
+    auto wp = new IsolationWP(WPname);
+    if(type == Efficiency){
+      for(auto& c: cuts) addCutToWP(wp, key, c.first, c.second);
+    }
+    else if(type == Cut){
+      for(auto& c: cuts) wp->addCut(new IsolationConditionFormula(xAOD::Iso::toString(c.first), c.first, c.second));
+    }else{
+      ATH_MSG_ERROR("Unknown isolation WP type -- should not happen.");
+      delete wp;
+      return StatusCode::FAILURE;
+    }
+
+    wps->push_back(wp);
+    ac->addCut(wp->name(), wp->name());
+
+    return StatusCode::SUCCESS;
+  }
+
+  StatusCode IsolationSelectionTool::addWP(std::string WP, xAOD::Type::ObjectType ObjType){
+    if(ObjType==xAOD::Type::Electron) {return addElectronWP(WP);}
+    else if(ObjType==xAOD::Type::Muon){return addMuonWP(WP);}
+    else if(ObjType==xAOD::Type::Photon){return addPhotonWP(WP);}
+    else {return StatusCode::FAILURE;}
+
+    return StatusCode::SUCCESS;
+  }
+  StatusCode IsolationSelectionTool::addWP(IsolationWP* wp, xAOD::Type::ObjectType ObjType){
+    if(ObjType==xAOD::Type::Electron) {m_elWPs.push_back(wp); m_electronAccept.addCut(wp->name(), wp->name());}
+    else if(ObjType==xAOD::Type::Muon){m_muWPs.push_back(wp); m_muonAccept.addCut(wp->name(), wp->name());}
+    else if(ObjType==xAOD::Type::Photon){m_phWPs.push_back(wp); m_photonAccept.addCut(wp->name(), wp->name());}
+    else if(ObjType==xAOD::Type::Other){m_objWPs.push_back(wp); m_objAccept.addCut(wp->name(), wp->name());}
+    else {return StatusCode::FAILURE;}
+
+    return StatusCode::SUCCESS;
+  }
+
+  const Root::TAccept& IsolationSelectionTool::accept(const xAOD::Photon& x) const
+  {
+    m_photonAccept.clear();
+    for(auto i: m_phWPs){ 
+      if(i->accept(x)){
+        m_photonAccept.setCutResult(i->name(), true );
+      }
+    }    
+    return m_photonAccept;
+  }
+  
+  const Root::TAccept& IsolationSelectionTool::accept(const xAOD::Electron& x) const
+  {
+    m_electronAccept.clear();
+    for(auto i: m_elWPs){
+      if(i->accept(x)){
+        m_electronAccept.setCutResult(i->name(), true);
+      }
+    }
+    return m_electronAccept;
+  }
+
+  const Root::TAccept& IsolationSelectionTool::accept(const xAOD::Muon& x) const
+  {
+    m_muonAccept.clear();
+    for(auto i: m_muWPs){
+      if(i->accept(x)){
+        m_muonAccept.setCutResult(i->name(), true);
+      }
+    }
+    return m_muonAccept;
+  }
+
+  const Root::TAccept& IsolationSelectionTool::accept(const xAOD::IParticle& x) const
+  {
+    m_iparAccept->clear();
+    for(auto i: *m_iparWPs){
+      if(i->accept(x)){
+        m_iparAccept->setCutResult(i->name(), true);
+      }
+    }
+    return *m_iparAccept;
+  }
+
+  const Root::TAccept& IsolationSelectionTool::accept(const strObj& x) const
+  {
+    m_objAccept.clear();
+    for(auto i : m_objWPs){ 
+      if(i->accept(x)){
+        m_objAccept.setCutResult(i->name(), true);
+      }
+    }
+    return m_objAccept;
+  }
+  
+  const Root::TAccept& IsolationSelectionTool::getPhotonTAccept() const
+  {
+    return m_photonAccept;    
+  }
+  
+  const Root::TAccept& IsolationSelectionTool::getElectronTAccept() const
+  {
+    return m_electronAccept;    
+  }
+  
+  const Root::TAccept& IsolationSelectionTool::getMuonTAccept() const
+  {
+    return m_muonAccept;    
+  }
+  const Root::TAccept& IsolationSelectionTool::getObjTAccept() const
+  {
+    return m_objAccept;    
+  }
+  
+  TDirectory* IsolationSelectionTool::getTemporaryDirectory(void) const
+  {
+    //
+    // Create a unique directory in memory to hold the histograms:
+    //
+    gROOT->cd();
+    TDirectory* tempDir = 0;
+    int counter = 0;
+    while (not tempDir) {
+      // First, let's find a directory name that doesn't exist yet:
+      std::stringstream dirname;
+      dirname << "IsolationSelectionTempDir_%i" << counter;
+      if (gROOT->GetDirectory((dirname.str()).c_str())) {
+        ++counter;
+        continue;
+      }
+      // Let's try to make this directory:
+      tempDir = gROOT->mkdir((dirname.str()).c_str());
+      if (not tempDir) {
+        //      ::Fatal("IsolationSelectionTool::getTemporaryDirectory",
+        //      ERROR_MESSAGE("Temporary directory could not be created"));
+        throw std::runtime_error("Temporary directory could not be created");
+      }
+    }
+    
+    return tempDir;
+  }  
+}
diff --git a/PhysicsAnalysis/AnalysisCommon/IsolationSelection/Root/IsolationWP.cxx b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/Root/IsolationWP.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..c4aa19494d28444e0f37693c6e8e63940d7afcbd
--- /dev/null
+++ b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/Root/IsolationWP.cxx
@@ -0,0 +1,40 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include <IsolationSelection/IsolationWP.h>
+
+namespace CP
+{
+  IsolationWP::~IsolationWP(){
+    for(auto c: m_cuts) if(c) delete c;
+    if(m_cutValues) delete m_cutValues;
+  }
+
+  const Root::TAccept& IsolationWP::accept(const xAOD::IParticle& p) const
+  {
+    m_accept.clear();
+    if(m_cutValues) m_cutValues->clear();
+    for(auto c: m_cuts){
+      if(c->accept(p, m_cutValues)) m_accept.setCutResult(c->name(), true);
+    }
+    return m_accept;
+  }
+
+  const Root::TAccept& IsolationWP::accept(const strObj& p) const
+  {
+    m_accept.clear();
+    if(m_cutValues) m_cutValues->clear();
+    for(auto c: m_cuts){
+      if(c->accept(p, m_cutValues)){
+        m_accept.setCutResult(c->name(), true);
+      }
+    }
+    return m_accept;
+  }
+
+  void IsolationWP::addCut(IsolationCondition* i){
+    m_cuts.push_back(i);
+    m_accept.addCut(i->name(), i->name());
+  }
+}
diff --git a/PhysicsAnalysis/AnalysisCommon/IsolationSelection/cmt/Makefile.RootCore b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/cmt/Makefile.RootCore
new file mode 100644
index 0000000000000000000000000000000000000000..2f48a6b376df7317daa2862d9ff06d562bb3d461
--- /dev/null
+++ b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/cmt/Makefile.RootCore
@@ -0,0 +1,16 @@
+PACKAGE          = IsolationSelection
+PACKAGE_PRELOAD  = 
+PACKAGE_CXXFLAGS = -g
+PACKAGE_OBJFLAGS = 
+PACKAGE_LDFLAGS  = 
+PACKAGE_BINFLAGS = 
+PACKAGE_LIBFLAGS = 
+PACKAGE_DEP      = CxxUtils Asg_Boost AsgTools PATCore PathResolver xAODPrimitives xAODEgamma xAODMuon MuonIdHelpers xAODTracking
+PACKAGE_TRYDEP   = 
+PACKAGE_CLEAN    = 
+PACKAGE_NOGRID   = 
+PACKAGE_PEDANTIC = 1
+PACKAGE_NOOPT    = 0
+PACKAGE_NOCC     = 0
+PACKAGE_REFLEX   = 0
+include $(ROOTCOREDIR)/Makefile-common
diff --git a/PhysicsAnalysis/AnalysisCommon/IsolationSelection/cmt/requirements b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/cmt/requirements
new file mode 100644
index 0000000000000000000000000000000000000000..278dafebd846d008c699a66acfb96544b0276da2
--- /dev/null
+++ b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/cmt/requirements
@@ -0,0 +1,24 @@
+#################################################
+package IsolationSelection
+
+author John Morris <john.morris@cern.ch>
+author Dongliang Zhang <dongliang.zhang@cern.ch>
+
+public
+use  AtlasPolicy                AtlasPolicy-*                   
+use  AsgTools                   AsgTools-*                      Control/AthToolSupport
+use  AthContainers              AthContainers-*                 Control
+use  PATCore                    PATCore-*                       PhysicsAnalysis/AnalysisCommon
+use  xAODBase                   xAODBase-*                      Event/xAOD
+use  xAODEgamma                 xAODEgamma-*                    Event/xAOD
+use  xAODMuon                   xAODMuon-*                      Event/xAOD
+use  xAODPrimitives             xAODPrimitives-*                Event/xAOD
+private
+use  AthenaBaseComps            AthenaBaseComps-*               Control
+use  AtlasROOT                  AtlasROOT-*                     External
+use  GaudiInterface             GaudiInterface-*                External
+use  PathResolver               PathResolver-*                  Tools
+end_private
+
+apply_pattern dual_use_library files= "../Root/*.cxx ../src/*.cxx ../src/components/*.cxx"
+#################################################
diff --git a/PhysicsAnalysis/AnalysisCommon/IsolationSelection/share/testIsolation_jobOptions.py b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/share/testIsolation_jobOptions.py
new file mode 100644
index 0000000000000000000000000000000000000000..b76ef655919381835125390cd379df60c5b8134e
--- /dev/null
+++ b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/share/testIsolation_jobOptions.py
@@ -0,0 +1,25 @@
+# Input file
+# inputFile = "/data/atlas/19.X.Y/19.1.4.7_AtlasDerivation/mc14_13TeV/DAOD_TOPQ1.04987437._000035.pool.root.1"
+#inputFile = "/home/dzhang/links/SAMPLES/R20/MC15/mc15_13TeV.361107.PowhegPythia8EvtGen_AZNLOCTEQ6L1_Zmumu.recon.AOD.e3601_s2576_s2132_r6630_tid05348608_00/AOD.05348608._004042.pool.root.1"
+inputFile = "/afs/cern.ch/user/m/morrisj/scratch0/rtt/DAOD_TOPQ1.MC15.pool.root"
+
+# n events ( use -1 to process all events )
+nEvents = 20
+
+import AthenaPoolCnvSvc.ReadAthenaPool
+svcMgr.EventSelector.InputCollections= [ inputFile ]
+algseq = CfgMgr.AthSequencer("AthAlgSeq")
+
+## The Tool
+isoTool_2 = CfgMgr.CP__IsolationSelectionTool( "IsolationSelectionTool" )
+isoTool_2.CalibFileName = "IsolationSelection/v1/MC15_Z_Jpsi_cutMap.root"
+isoTool_2.MuonWP = "Gradient"
+isoTool_2.ElectronWP = "Gradient"
+isoTool_2.PhotonWP = "Gradient"
+svcMgr.ToolSvc += isoTool_2
+
+## Test algorithm
+from IsolationSelection.IsolationSelectionConf import CP__TestIsolationAthenaAlg 
+algseq += CfgMgr.CP__TestIsolationAthenaAlg( IsoTool = isoTool_2 ) 
+
+theApp.EvtMax = nEvents
diff --git a/PhysicsAnalysis/AnalysisCommon/IsolationSelection/src/TestIsolationAthenaAlg.cxx b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/src/TestIsolationAthenaAlg.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..386fbe32ba639fa74d8747ef312d360b30de7792
--- /dev/null
+++ b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/src/TestIsolationAthenaAlg.cxx
@@ -0,0 +1,88 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: TestIsolationAthenaAlg.cxx 672993 2015-06-06 16:55:34Z dzhang $
+
+// Local include(s):
+#include "TestIsolationAthenaAlg.h"
+
+// EDM include(s):
+#include "xAODEgamma/PhotonContainer.h"
+#include "xAODEgamma/ElectronContainer.h"
+#include "xAODMuon/MuonContainer.h"
+
+// other include(s):
+#include <cmath>
+
+namespace CP 
+{
+
+  TestIsolationAthenaAlg::TestIsolationAthenaAlg( const std::string& name, ISvcLocator* svcLoc ) :
+    AthAlgorithm( name, svcLoc ),
+    m_sgKeyPhotons("Photons"),
+    m_sgKeyElectrons("Electrons"),
+    m_sgKeyMuons("Muons")
+  {  
+    declareProperty( "sgKeyPhotons" , m_sgKeyPhotons );
+    declareProperty( "sgKeyElectrons" , m_sgKeyElectrons );
+    declareProperty( "sgKeyMuons" , m_sgKeyMuons );
+    declareProperty( "IsoTool", m_isoTool );
+  }
+
+  StatusCode TestIsolationAthenaAlg::initialize()
+  {
+    ATH_CHECK( m_isoTool.retrieve() );
+    
+    // Return gracefully:
+    return StatusCode::SUCCESS;  
+  }
+
+  StatusCode TestIsolationAthenaAlg::execute()
+  {
+    const xAOD::PhotonContainer* photons(nullptr);
+    ATH_CHECK( evtStore()->retrieve(photons,m_sgKeyPhotons) );
+    for (auto x : *photons) {
+      if (x->pt() > 7000.) {
+        if (x->caloCluster() != nullptr) {
+          if (fabs(x->caloCluster()->eta()) < 2.47) {
+            if (m_isoTool->accept( *x )) {
+              ATH_MSG_INFO(" Photon passes Isolation");
+            }
+          }       
+        }
+      }
+    }
+    
+    
+    const xAOD::ElectronContainer* electrons(nullptr);
+    ATH_CHECK( evtStore()->retrieve(electrons,m_sgKeyElectrons) );
+    for (auto x : *electrons) {
+      if (x->pt() > 7000.) {
+        if (x->caloCluster() != nullptr) {      
+          if (fabs(x->caloCluster()->eta()) < 2.47) {
+            if (m_isoTool->accept( *x )) {
+              ATH_MSG_INFO(" Electron passes Isolation");
+            }     
+          }
+        }
+      }
+    }
+    
+    const xAOD::MuonContainer* muons(nullptr);
+    ATH_CHECK( evtStore()->retrieve(muons,m_sgKeyMuons) );
+    for (auto x : *muons) {
+      if (x->pt() > 7000.) {
+        if (fabs(x->eta()) < 2.5) {
+          if (m_isoTool->accept( *x )) {
+            ATH_MSG_INFO(" Muon passes Isolation");
+          }
+        }
+      }
+    }
+    
+    
+    // Return gracefully:
+    return StatusCode::SUCCESS;  
+  }
+}
diff --git a/PhysicsAnalysis/AnalysisCommon/IsolationSelection/src/TestIsolationAthenaAlg.h b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/src/TestIsolationAthenaAlg.h
new file mode 100644
index 0000000000000000000000000000000000000000..99e9b97dc84f5150fa9e77345d0fa4c8ba894364
--- /dev/null
+++ b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/src/TestIsolationAthenaAlg.h
@@ -0,0 +1,36 @@
+// Dear emacs, this is -*- c++ -*-
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: TestIsolationAthenaAlg.h 672993 2015-06-06 16:55:34Z dzhang $
+#ifndef ELECTRONISOLATIONSELECTION_TESTISOLATIONATHENAALG_H
+#define ELECTRONISOLATIONSELECTION_TESTISOLATIONATHENAALG_H
+
+// Gaudi/Athena include(s):
+#include "AthenaBaseComps/AthAlgorithm.h"
+#include "AsgTools/ToolHandle.h"
+
+// Local include(s):
+#include "IsolationSelection/IIsolationSelectionTool.h"
+
+namespace CP
+{
+  class TestIsolationAthenaAlg : public AthAlgorithm{
+    public:
+      TestIsolationAthenaAlg( const std::string& name, ISvcLocator* svcLoc );
+      
+      /// Function initialising the algorithm
+      virtual StatusCode initialize();
+      /// Function executing the algorithm
+      virtual StatusCode execute();   
+      
+    private:
+      std::string m_sgKeyPhotons;
+      std::string m_sgKeyElectrons;
+      std::string m_sgKeyMuons;
+      ToolHandle< CP::IIsolationSelectionTool > m_isoTool;
+  };
+}
+#endif
diff --git a/PhysicsAnalysis/AnalysisCommon/IsolationSelection/src/components/IsolationSelection_entries.cxx b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/src/components/IsolationSelection_entries.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..7c52587f8625a18fb22fe9d71492de29865a3933
--- /dev/null
+++ b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/src/components/IsolationSelection_entries.cxx
@@ -0,0 +1,17 @@
+// $Id: IsolationSelection_entries.cxx 678002 2015-06-24 15:39:36Z morrisj $
+
+// Gaudi/Athena include(s):
+#include "GaudiKernel/DeclareFactoryEntries.h"
+
+// Local include(s):
+#include "IsolationSelection/IsolationSelectionTool.h"
+#include "../TestIsolationAthenaAlg.h"
+
+
+DECLARE_NAMESPACE_TOOL_FACTORY( CP , IsolationSelectionTool )
+DECLARE_NAMESPACE_ALGORITHM_FACTORY( CP , TestIsolationAthenaAlg )
+
+DECLARE_FACTORY_ENTRIES( IsolationSelection ) {
+   DECLARE_NAMESPACE_TOOL( CP , IsolationSelectionTool )
+   DECLARE_NAMESPACE_ALGORITHM( CP , TestIsolationAthenaAlg )
+}
diff --git a/PhysicsAnalysis/AnalysisCommon/IsolationSelection/src/components/IsolationSelection_load.cxx b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/src/components/IsolationSelection_load.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..a2a46bf091c4804b2e217f33e65336203e8c83d3
--- /dev/null
+++ b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/src/components/IsolationSelection_load.cxx
@@ -0,0 +1,7 @@
+// $Id: IsolationSelection_load.cxx 669782 2015-05-26 08:29:22Z dzhang $
+
+// Gaudi/Athena include(s):
+#include "GaudiKernel/LoadFactoryEntries.h"
+
+// Declare the library to the infrastructure:
+LOAD_FACTORY_ENTRIES( IsolationSelection )
diff --git a/PhysicsAnalysis/AnalysisCommon/IsolationSelection/util/testIsolationSelectionTool.cxx b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/util/testIsolationSelectionTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..f0a23be140167d9483284a890d018d1f53e10214
--- /dev/null
+++ b/PhysicsAnalysis/AnalysisCommon/IsolationSelection/util/testIsolationSelectionTool.cxx
@@ -0,0 +1,185 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: testIsolationSelectionTool.cxx 680194 2015-07-03 15:31:36Z jdevivi $
+
+// Mindlessly copied from CPAnalysisExamples
+#ifndef CPANALYSISEXAMPLES_ERRORCHECK_H
+#define CPANALYSISEXAMPLES_ERRORCHECK_H
+
+#define CHECK( ARG )                                     \
+   do {                                                  \
+      const bool result = ARG;                           \
+      if( ! result ) {                                   \
+         ::Error( APP_NAME, "Failed to execute: \"%s\"", \
+                  #ARG );                                \
+         return 1;                                       \
+      }                                                  \
+   } while( false )
+
+#endif // CPANALYSISEXAMPLES_ERRORCHECK_H
+
+// System include(s):
+#include <memory>
+#include <cstdlib>
+#include <utility>
+
+// ROOT include(s):
+#include <TFile.h>
+#include <TError.h>
+#include <TString.h>
+
+// Infrastructure include(s):
+#ifdef ROOTCORE
+#   include "xAODRootAccess/Init.h"
+#   include "xAODRootAccess/TEvent.h"
+#   include "xAODRootAccess/TStore.h"
+#endif // ROOTCORE
+
+// EDM include(s):
+#include "xAODEgamma/PhotonContainer.h"
+#include "xAODEgamma/ElectronContainer.h"
+#include "xAODMuon/MuonContainer.h"
+#include "xAODPrimitives/IsolationType.h"
+
+#include <iostream>
+using std::cout;
+using std::endl;
+#include <cmath>
+
+#include "IsolationSelection/IsolationSelectionTool.h"
+
+
+int main( int argc, char* argv[] ) {
+
+  // The application's name:
+  const char* APP_NAME = argv[ 0 ];
+
+  // Check if we received a file name:
+  if( argc < 2 ) {
+    Error( APP_NAME, "No file name received!" );
+    Error( APP_NAME, "  Usage: %s [xAOD file name]", APP_NAME );
+    return 1;
+  }
+  // Initialise the application:
+  CHECK( xAOD::Init( APP_NAME ) );
+
+  // Open the input file:
+  const TString fileName = argv[ 1 ];
+  Info( APP_NAME, "Opening file: %s", fileName.Data() );
+  std::auto_ptr< TFile > ifile( TFile::Open( fileName, "READ" ) );
+  CHECK( ifile.get() );
+
+  // Create a TEvent object:
+  xAOD::TEvent event( xAOD::TEvent::kClassAccess );
+  CHECK( event.readFrom( ifile.get() ) );
+  Info( APP_NAME, "Number of events in the file: %i",
+        static_cast< int >( event.getEntries() ) );
+
+  // Create a transient object store. Needed for the tools.
+  xAOD::TStore store;
+
+  // Decide how many events to run over:
+  Long64_t entries = event.getEntries();
+  if( argc > 2 ) {
+    const Long64_t e = atoll( argv[ 2 ] );
+    if( e < entries ) {
+        entries = e;
+    }
+  }
+
+  // This is a testing file, lets fail whenever we can
+  StatusCode::enableFailure();
+
+
+  // The most simple case, just select electron and muon
+  CP::IsolationSelectionTool iso_1( "iso_1" );
+  CHECK( iso_1.setProperty("MuonWP","Loose") );
+  CHECK( iso_1.setProperty("ElectronWP","Tight") );
+//   CHECK( iso_1.setProperty("PhotonWP","Cone40") );
+  CHECK( iso_1.initialize() );
+
+  // use a user configured Muon WP?
+  CP::IsolationSelectionTool iso_2( "iso_2" );
+  CHECK( iso_2.initialize() );
+
+  /// use "myTestWP" WP for muon
+  std::vector< std::pair<xAOD::Iso::IsolationType, std::string> > myCuts;
+  myCuts.push_back(std::make_pair<xAOD::Iso::IsolationType, std::string>(xAOD::Iso::ptcone20, "0.1*x+90"));
+  myCuts.push_back(std::make_pair<xAOD::Iso::IsolationType, std::string>(xAOD::Iso::topoetcone20, "0.2*x+80"));
+  CHECK( iso_2.addUserDefinedWP("myTestWP", xAOD::Type::Muon, myCuts));
+
+  std::vector< std::pair<xAOD::Iso::IsolationType, std::string> > myCuts2;
+  myCuts2.push_back(std::make_pair<xAOD::Iso::IsolationType, std::string>(xAOD::Iso::ptcone30, "0.1*(x+90000)"));
+  myCuts2.push_back(std::make_pair<xAOD::Iso::IsolationType, std::string>(xAOD::Iso::topoetcone30, "0.02*(x+80000)"));
+  CHECK( iso_2.addUserDefinedWP("myTestWP2", xAOD::Type::Photon, myCuts2, "", CP::IsolationSelectionTool::Cut));
+
+  strObj strMuon;
+  strMuon.isolationValues.resize(xAOD::Iso::numIsolationTypes);
+
+  std::string m_sgKeyPhotons("Photons");
+  std::string m_sgKeyElectrons("Electrons");
+  std::string m_sgKeyMuons("Muons");
+
+  // Loop over the events:
+  for( Long64_t entry = 0; entry < entries; ++entry ) {
+    Info(APP_NAME,"-----------");
+    // Tell the object which entry to look at:
+    event.getEntry( entry );
+
+    const xAOD::PhotonContainer* photons(nullptr);
+    CHECK( event.retrieve(photons,m_sgKeyPhotons) );
+    for (auto x : *photons) {
+      if (x->pt() > 7000.) {
+        if (x->caloCluster() != nullptr) {
+          if (fabs(x->caloCluster()->eta()) < 2.47) {
+            if (iso_2.accept( *x )) {
+              Info(APP_NAME," Photon passes Isolation");
+            }else{
+              Info(APP_NAME," Photon FAILS Isolation");
+            }
+          }
+        }
+      }
+    }
+
+
+    const xAOD::ElectronContainer* electrons(nullptr);
+    CHECK( event.retrieve(electrons,m_sgKeyElectrons) );
+    for (auto x : *electrons) {
+      if (x->pt() > 7000.) {
+        if (x->caloCluster() != nullptr) {
+          if (fabs(x->caloCluster()->eta()) < 2.47) {
+            if (iso_2.accept( *x )) {
+              Info(APP_NAME," Electron passes Isolation");
+            }
+          }
+        }
+      }
+    }
+
+
+    const xAOD::MuonContainer* muons(nullptr);
+    CHECK( event.retrieve(muons,m_sgKeyMuons) );
+    for (auto x : *muons) {
+      strMuon.pt = x->pt();
+      strMuon.eta = x->eta();
+      /// make sure the variable needed by your WP is passed
+      x->isolation(strMuon.isolationValues[xAOD::Iso::topoetcone20], xAOD::Iso::topoetcone20);
+      x->isolation(strMuon.isolationValues[xAOD::Iso::ptvarcone30], xAOD::Iso::ptvarcone30);
+
+      if (x->pt() > 7000.) {
+        if (fabs(x->eta()) < 2.5) {
+          if (iso_1.accept( strMuon )) {
+            Info(APP_NAME," Muon passes Isolation");
+          }
+        }
+      }
+    }
+
+
+
+  } // end loop over events
+  return 0;
+}