From 1e68415eb55381e0186c1be9d95beecd06c84b85 Mon Sep 17 00:00:00 2001
From: Bruno Lenzi <Bruno.Lenzi@cern.ch>
Date: Mon, 15 Sep 2014 17:35:22 +0200
Subject: [PATCH] Fixing config (egammaTools-01-00-62)

---
 .../egamma/egammaTools/cmt/requirements       |  81 ++
 .../egamma/egammaTools/doc/mainpage.h         |  57 ++
 .../python/EMBremCollectionBuilder.py         | 175 ++++
 .../egammaTools/python/EMPIDBuilderBase.py    |  78 ++
 .../egammaTools/python/EMShowerBuilder.py     |  92 ++
 .../egammaTools/python/EMTrackMatchBuilder.py |  30 +
 .../egammaTools/python/EMVertexBuilder.py     |  44 +
 .../egamma/egammaTools/python/InDetTools.py   | 111 +++
 .../python/egammaOQFlagsBuilder.py            |  22 +
 .../python/egammaToolsFactories.py            |  99 ++
 .../egammaTools/src/CandidateMatchHelpers.h   |  77 ++
 .../egamma/egammaTools/src/ConvVxSorter.h     |  52 +
 .../egammaTools/src/EMAmbiguityTool.cxx       | 165 ++++
 .../egamma/egammaTools/src/EMAmbiguityTool.h  |  42 +
 .../src/EMBremCollectionBuilder.cxx           | 551 +++++++++++
 .../egammaTools/src/EMBremCollectionBuilder.h | 117 +++
 .../egamma/egammaTools/src/EMClusterTool.cxx  | 238 +++++
 .../egamma/egammaTools/src/EMClusterTool.h    |  98 ++
 .../egammaTools/src/EMConversionBuilder.cxx   | 241 +++++
 .../egammaTools/src/EMConversionBuilder.h     | 101 ++
 .../egammaTools/src/EMFourMomBuilder.cxx      | 336 +++++++
 .../egamma/egammaTools/src/EMFourMomBuilder.h | 118 +++
 .../egamma/egammaTools/src/EMPIDBuilder.cxx   |  95 ++
 .../egamma/egammaTools/src/EMPIDBuilder.h     |  59 ++
 .../egammaTools/src/EMShowerBuilder.cxx       | 903 ++++++++++++++++++
 .../egamma/egammaTools/src/EMShowerBuilder.h  | 192 ++++
 .../egammaTools/src/EMTrackIsolationTool.cxx  | 130 +++
 .../egammaTools/src/EMTrackIsolationTool.h    |  93 ++
 .../egammaTools/src/EMTrackMatchBuilder.cxx   | 539 +++++++++++
 .../egammaTools/src/EMTrackMatchBuilder.h     | 127 +++
 .../egammaTools/src/EMVertexBuilder.cxx       | 210 ++++
 .../egamma/egammaTools/src/EMVertexBuilder.h  |  70 ++
 .../egammaTools/src/FourMomCombiner.cxx       | 836 ++++++++++++++++
 .../egamma/egammaTools/src/FourMomCombiner.h  | 148 +++
 .../egamma/egammaTools/src/TrackMatchSorter.h |  52 +
 .../src/components/egammaTools_entries.cxx    |  50 +
 .../src/components/egammaTools_load.cxx       |   4 +
 .../egamma/egammaTools/src/egammaBaseTool.cxx |  98 ++
 .../egamma/egammaTools/src/egammaBaseTool.h   |  56 ++
 .../src/egammaCheckEnergyDepositTool.cxx      | 165 ++++
 .../src/egammaCheckEnergyDepositTool.h        |  57 ++
 .../egammaTools/src/egammaOQFlagsBuilder.cxx  | 602 ++++++++++++
 .../egammaTools/src/egammaOQFlagsBuilder.h    |  97 ++
 .../egamma/egammaTools/src/egammaSwTool.cxx   | 341 +++++++
 .../egamma/egammaTools/src/egammaSwTool.h     |  80 ++
 45 files changed, 7929 insertions(+)
 create mode 100644 Reconstruction/egamma/egammaTools/cmt/requirements
 create mode 100644 Reconstruction/egamma/egammaTools/doc/mainpage.h
 create mode 100644 Reconstruction/egamma/egammaTools/python/EMBremCollectionBuilder.py
 create mode 100755 Reconstruction/egamma/egammaTools/python/EMPIDBuilderBase.py
 create mode 100644 Reconstruction/egamma/egammaTools/python/EMShowerBuilder.py
 create mode 100644 Reconstruction/egamma/egammaTools/python/EMTrackMatchBuilder.py
 create mode 100644 Reconstruction/egamma/egammaTools/python/EMVertexBuilder.py
 create mode 100644 Reconstruction/egamma/egammaTools/python/InDetTools.py
 create mode 100644 Reconstruction/egamma/egammaTools/python/egammaOQFlagsBuilder.py
 create mode 100644 Reconstruction/egamma/egammaTools/python/egammaToolsFactories.py
 create mode 100644 Reconstruction/egamma/egammaTools/src/CandidateMatchHelpers.h
 create mode 100644 Reconstruction/egamma/egammaTools/src/ConvVxSorter.h
 create mode 100644 Reconstruction/egamma/egammaTools/src/EMAmbiguityTool.cxx
 create mode 100644 Reconstruction/egamma/egammaTools/src/EMAmbiguityTool.h
 create mode 100644 Reconstruction/egamma/egammaTools/src/EMBremCollectionBuilder.cxx
 create mode 100644 Reconstruction/egamma/egammaTools/src/EMBremCollectionBuilder.h
 create mode 100644 Reconstruction/egamma/egammaTools/src/EMClusterTool.cxx
 create mode 100644 Reconstruction/egamma/egammaTools/src/EMClusterTool.h
 create mode 100644 Reconstruction/egamma/egammaTools/src/EMConversionBuilder.cxx
 create mode 100644 Reconstruction/egamma/egammaTools/src/EMConversionBuilder.h
 create mode 100644 Reconstruction/egamma/egammaTools/src/EMFourMomBuilder.cxx
 create mode 100644 Reconstruction/egamma/egammaTools/src/EMFourMomBuilder.h
 create mode 100644 Reconstruction/egamma/egammaTools/src/EMPIDBuilder.cxx
 create mode 100644 Reconstruction/egamma/egammaTools/src/EMPIDBuilder.h
 create mode 100644 Reconstruction/egamma/egammaTools/src/EMShowerBuilder.cxx
 create mode 100644 Reconstruction/egamma/egammaTools/src/EMShowerBuilder.h
 create mode 100644 Reconstruction/egamma/egammaTools/src/EMTrackIsolationTool.cxx
 create mode 100644 Reconstruction/egamma/egammaTools/src/EMTrackIsolationTool.h
 create mode 100644 Reconstruction/egamma/egammaTools/src/EMTrackMatchBuilder.cxx
 create mode 100644 Reconstruction/egamma/egammaTools/src/EMTrackMatchBuilder.h
 create mode 100644 Reconstruction/egamma/egammaTools/src/EMVertexBuilder.cxx
 create mode 100644 Reconstruction/egamma/egammaTools/src/EMVertexBuilder.h
 create mode 100644 Reconstruction/egamma/egammaTools/src/FourMomCombiner.cxx
 create mode 100644 Reconstruction/egamma/egammaTools/src/FourMomCombiner.h
 create mode 100644 Reconstruction/egamma/egammaTools/src/TrackMatchSorter.h
 create mode 100755 Reconstruction/egamma/egammaTools/src/components/egammaTools_entries.cxx
 create mode 100755 Reconstruction/egamma/egammaTools/src/components/egammaTools_load.cxx
 create mode 100644 Reconstruction/egamma/egammaTools/src/egammaBaseTool.cxx
 create mode 100644 Reconstruction/egamma/egammaTools/src/egammaBaseTool.h
 create mode 100644 Reconstruction/egamma/egammaTools/src/egammaCheckEnergyDepositTool.cxx
 create mode 100644 Reconstruction/egamma/egammaTools/src/egammaCheckEnergyDepositTool.h
 create mode 100644 Reconstruction/egamma/egammaTools/src/egammaOQFlagsBuilder.cxx
 create mode 100644 Reconstruction/egamma/egammaTools/src/egammaOQFlagsBuilder.h
 create mode 100644 Reconstruction/egamma/egammaTools/src/egammaSwTool.cxx
 create mode 100644 Reconstruction/egamma/egammaTools/src/egammaSwTool.h

diff --git a/Reconstruction/egamma/egammaTools/cmt/requirements b/Reconstruction/egamma/egammaTools/cmt/requirements
new file mode 100644
index 0000000000000..345df988a2ce5
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/cmt/requirements
@@ -0,0 +1,81 @@
+package egammaTools
+
+use AtlasPolicy                AtlasPolicy-*     
+
+private
+use AthenaBaseComps            AthenaBaseComps-*       Control
+use AthenaKernel               AthenaKernel-*          Control
+use AtlasROOT                  AtlasROOT-*             External
+use GaudiInterface	       GaudiInterface-*	       External
+use AtlasCLHEP                 AtlasCLHEP-*            External
+use StoreGate                  StoreGate-*             Control
+use Identifier                 Identifier-*            DetectorDescription
+
+use EventKernel                EventKernel-*           Event
+use FourMom                    FourMom-*               Event
+use NavFourMom                 NavFourMom-*            Event
+use FourMomUtils               FourMomUtils-*          Event
+use EventPrimitives            EventPrimitives-*       Event
+
+use LArRecConditions           LArRecConditions-*      LArCalorimeter 
+use LArTools                   LArTools-*              LArCalorimeter 
+
+use TrkVertexFitterInterfaces  TrkVertexFitterInterfaces-*   Tracking/TrkVertexFitter 
+use InDetConversionFinderTools InDetConversionFinderTools-*  InnerDetector/InDetRecTools
+use InDetRecToolInterfaces     InDetRecToolInterfaces-*      InnerDetector/InDetRecTools
+use InDetBeamSpotService       InDetBeamSpotService-*        InnerDetector/InDetConditions
+
+use CaloGeoHelpers             CaloGeoHelpers-*        Calorimeter	
+use CaloEvent		       CaloEvent-*             Calorimeter
+use CaloUtils		       CaloUtils-*	       Calorimeter
+use CaloRec		       CaloRec-*	       Calorimeter
+use CaloIdentifier	       CaloIdentifier-*        Calorimeter
+use CaloInterface	       CaloInterface-*         Calorimeter
+use CaloConditions	       CaloConditions-*        Calorimeter
+
+use Particle                   Particle-*              Reconstruction
+use IsolationTool	       IsolationTool-*	       Reconstruction/RecoTools
+
+#use TrkParameters              TrkParameters-*         Tracking/TrkEvent
+use TrkParticleBase    	       TrkParticleBase-*       Tracking/TrkEvent
+use TrkTrack                   TrkTrack-*              Tracking/TrkEvent
+use TrkEventPrimitives         TrkEventPrimitives-*    Tracking/TrkEvent
+use VxVertex                   VxVertex-*              Tracking/TrkEvent
+use TrkTrackLink               TrkTrackLink-*          Tracking/TrkEvent
+#use TrkNeutralParameters       TrkNeutralParameters-*  Tracking/TrkEvent
+use TrkVertexFitterInterfaces  TrkVertexFitterInterfaces-* Tracking/TrkVertexFitter
+use TrkToolInterfaces          TrkToolInterfaces-*     Tracking/TrkTools 
+use ParticleTruth              ParticleTruth-*         Reconstruction 
+
+
+use egammaInterfaces	       egammaInterfaces-*      Reconstruction/egamma
+use egammaRecEvent	       egammaRecEvent-*      Reconstruction/egamma
+use egammaUtils                egammaUtils-*           Reconstruction/egamma
+#use egammaConditions           egammaConditions-*      Reconstruction/egamma
+
+use xAODEgamma                 xAODEgamma-*            Event/xAOD
+use xAODTracking               xAODTracking-*          Event/xAOD
+use xAODCaloEvent              xAODCaloEvent-*         Event/xAOD
+use xAODPrimitives             xAODPrimitives-*        Event/xAOD
+use xAODTruth                  xAODTruth-*             Event/xAOD
+
+use xAODEventShape             xAODEventShape-*        Event/xAOD
+
+use PATCore                    PATCore-*               PhysicsAnalysis/AnalysisCommon
+#use ElectronPhotonFourMomentumCorrection ElectronPhotonFourMomentumCorrection-* PhysicsAnalysis/ElectronPhotonID
+
+
+end_private
+
+private
+apply_tag ROOTMathLibs
+# macro cppdebugflags '$(cppdebugflags_s)'
+# macro_remove componentshr_linkopts "-Wl,-s"
+end_private
+
+library egammaTools *.cxx components/*.cxx
+ 
+apply_pattern component_library
+
+apply_pattern declare_python_modules files="*.py"
+
diff --git a/Reconstruction/egamma/egammaTools/doc/mainpage.h b/Reconstruction/egamma/egammaTools/doc/mainpage.h
new file mode 100644
index 0000000000000..af8b3fd49bf92
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/doc/mainpage.h
@@ -0,0 +1,57 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/**
+
+@mainpage egammaTools Package
+
+This package contains electron and photon reconstruction and identification tools.
+These tools are called by main algorithms located in the egammaRec package.
+
+Following tools are used by egammaBuilder for the reconstruction of isolated high-pT electrons and photons :
+
+egammaSwTool : creation of the cluster
+
+EMClusterTool : define cluster size depending on type of object 
+
+EMClusterErrorsTool : associate error on cluster quantities
+
+EMShowerBuilder : Calculation of the EM shower shapes. It calls specialized tools located in egammaCaloTools package. When called from an analysis alg or tool it applies a special treatement to retrieve the original shower object to keep the "calorimetric isolation" variables which cannot be recalculated (due to lack of cells)
+
+EMTrackMatchBuilder : performs matching between cluster and a track
+
+EMPIDBuilder : performs identification of the object. It calls specialized tools located in egammaPID package
+
+EMConversionBuilder : retrieve and match conversion objects to an egamma one
+
+EMBremsstrahlungBuilder : retrieve bremsstrahlung. It calls specialized tools BremsstrahlungHit and BremsstrahlungHelix
+
+EMTrkRefitter : retrieve bremsstrahlung. It calls specialized tools like DNA and GSF.
+
+EMConversionRefitter : Refits the conversion tracks with dedicated e+- track fitters (like GSF and DNA) and refits the vertex (rebuilds the vertex from the first measurement in case of single-track conversions). Does not change the original tracks/vertices, but supplies the results in an egDetail.
+
+EMFourMomBuilder : build the 4-momentum of the candidates
+
+Following tools are called by softebuilder for the reconstruction of low-pT and non-isoalted electrons :
+
+EMClusterBuilderFromTrackSETool : take a track, extrapolate it to the EM and build a cluster
+
+egammaSelectClusterSETool : selection based on cluster
+
+egammaSelectSETool : pre and post-selection based on shower shape
+
+EMSofteCombinedTool :calculate variables which combine cluster and track
+
+Tools EMShowerBuilder, EMPIDBuilder, EMFourMomBuilder, EMConversionBuilder and EMBremsstrahlungBuilder are also called by softeBuilder.
+
+
+@author H. Ma <hma@bnl.gov>
+@author A. Poppleton <Alan.Poppleton@cern.ch>
+@author S. Rajagopalan <srinir@bnl.gov>
+@author M. Wielers <Monika.Wielers@cern.ch>
+@author A. Khodinov <khodinov@bnl.gov>
+@author F. Derue <derue@lpnhe.in2p3.fr>
+@author T. Koffas  <Thomas.Koffas@cern.ch>
+*/
+
diff --git a/Reconstruction/egamma/egammaTools/python/EMBremCollectionBuilder.py b/Reconstruction/egamma/egammaTools/python/EMBremCollectionBuilder.py
new file mode 100644
index 0000000000000..96e276b6d0ecd
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/python/EMBremCollectionBuilder.py
@@ -0,0 +1,175 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+# default configuration of the EMBremCollectionBuilder
+from AthenaCommon.Logging import logging
+from AthenaCommon.SystemOfUnits import *
+from AthenaCommon.Constants import *
+from AthenaCommon.AppMgr import ServiceMgr
+from AthenaCommon.AppMgr import ToolSvc
+from AthenaCommon.DetFlags import DetFlags
+from RecExConfig.RecFlags  import rec
+import traceback
+
+#import base class
+from egammaTools import egammaToolsConf
+from InDetTools import egammaExtrapolator
+
+class egammaBremCollectionBuilder ( egammaToolsConf.EMBremCollectionBuilder ) :
+    __slots__ = ()
+
+    def __init__(self, name="EMBremCollectionBuilder", **kw):
+        mlog = logging.getLogger(name+'::__init__')
+        mlog.info("entering")
+
+        super(egammaBremCollectionBuilder, self).__init__(name, **kw)
+
+        # do the configuration
+        import egammaRec.EMCommonRefitter
+        GSFBuildInDetExtrapolator= egammaExtrapolator()
+
+        from egammaTrackTools.egammaTrackToolsConf import egammaTrkRefitterTool
+        GSFRefitterTool = egammaTrkRefitterTool(name = 'GSFRefitterTool',
+                                                FitterTool = egammaRec.EMCommonRefitter.GSFTrackFitter,
+                                                useBeamSpot = False,
+                                                ReintegrateOutliers=True,
+                                                OutputLevel =7)
+        from AthenaCommon.AppMgr import ToolSvc
+        ToolSvc += GSFRefitterTool
+
+        # ----------- load association tool from Inner Detector to handle pixel ganged ambiguities
+        #
+        from InDetAssociationTools.InDetAssociationToolsConf import InDet__InDetPRD_AssociationToolGangedPixels
+        GSFBuildInDetPrdAssociationTool = InDet__InDetPRD_AssociationToolGangedPixels(name = "GSFBuildInDetPrdAssociationTool",
+                                                                                PixelClusterAmbiguitiesMapName = 'PixelClusterAmbiguitiesMap')
+        ToolSvc += GSFBuildInDetPrdAssociationTool        
+        #
+        # ----------- Load SummaryTool
+        #
+        # Loading Configurable HoleSearchTool
+        #
+        from InDetTrackHoleSearch.InDetTrackHoleSearchConf import InDet__InDetTrackHoleSearchTool
+        GSFBuildHoleSearchTool = InDet__InDetTrackHoleSearchTool(name = "GSFBuildHoleSearchTool",
+                                                                 Extrapolator = GSFBuildInDetExtrapolator,
+                                                                 usePixel      = DetFlags.haveRIO.pixel_on(),
+                                                                 useSCT        = DetFlags.haveRIO.SCT_on(),
+                                                                 CountDeadModulesAfterLastHit = True)
+
+        from AthenaCommon.AppMgr import ServiceMgr
+        if (DetFlags.haveRIO.SCT_on()):
+            from SCT_ConditionsServices.SCT_ConditionsServicesConf import SCT_ConditionsSummarySvc
+            InDetSCT_ConditionsSummarySvc = SCT_ConditionsSummarySvc(name = "InDetSCT_ConditionsSummarySvc")
+            ServiceMgr += InDetSCT_ConditionsSummarySvc
+            GSFBuildHoleSearchTool.SctSummarySvc = ServiceMgr.InDetSCT_ConditionsSummarySvc
+        else:
+            GSFBuildHoleSearchTool.SctSummarySvc = None
+            
+        ToolSvc += GSFBuildHoleSearchTool
+        print    GSFBuildHoleSearchTool
+        #
+        # Load BLayer tool
+        #
+        GSFBuildTestBLayerTool = None
+        if DetFlags.haveRIO.pixel_on() :
+            from InDetTestBLayer.InDetTestBLayerConf import InDet__InDetTestBLayerTool
+            from PixelConditionsServices.PixelConditionsServicesConf import PixelConditionsSummarySvc
+            ServiceMgr += PixelConditionsSummarySvc()            
+            GSFBuildTestBLayerTool = InDet__InDetTestBLayerTool(name            = "GSFBuildTestBLayerTool",
+                                                                PixelSummarySvc = ServiceMgr.PixelConditionsSummarySvc,
+                                                                Extrapolator    = GSFBuildInDetExtrapolator)
+            ToolSvc += GSFBuildTestBLayerTool
+            print  GSFBuildTestBLayerTool
+        #
+        # Configurable version of TRT_ElectronPidTools
+        #
+        GSFBuildTRT_ElectronPidTool = None
+        if DetFlags.haveRIO.TRT_on():
+            from TRT_ElectronPidTools.TRT_ElectronPidToolsConf import InDet__TRT_ElectronPidTool
+            GSFBuildTRT_ElectronPidTool = InDet__TRT_ElectronPidTool(name = "GSFBuildTRT_ElectronPidTool")
+                
+            ToolSvc += GSFBuildTRT_ElectronPidTool
+            print GSFBuildTRT_ElectronPidTool
+        #
+        # Configurable version of PixelToTPIDTOol
+        #
+        GSFBuildPixelToTPIDTool = None
+        if DetFlags.haveRIO.pixel_on():                 
+            from PixelToTPIDTool.PixelToTPIDToolConf import InDet__PixelToTPIDTool
+            GSFBuildPixelToTPIDTool = InDet__PixelToTPIDTool(name = "GSFBuildPixelToTPIDTool")
+            GSFBuildPixelToTPIDTool.ReadFromCOOL = True
+            ToolSvc += GSFBuildPixelToTPIDTool
+            print  GSFBuildPixelToTPIDTool
+        #
+        # Configrable version of loading the InDetTrackSummaryHelperTool
+        #
+        from InDetTrackSummaryHelperTool.InDetTrackSummaryHelperToolConf import InDet__InDetTrackSummaryHelperTool
+        GSFBuildTrackSummaryHelperTool = InDet__InDetTrackSummaryHelperTool(name            = "GSFBuildTrackSummaryHelperTool",
+                                                                             AssoTool        = GSFBuildInDetPrdAssociationTool,
+                                                                             PixelToTPIDTool = GSFBuildPixelToTPIDTool,
+                                                                             TestBLayerTool  = GSFBuildTestBLayerTool,
+                                                                             DoSharedHits    = False,
+                                                                             HoleSearch      = GSFBuildHoleSearchTool,
+                                                                             usePixel        = DetFlags.haveRIO.pixel_on(),
+                                                                             useSCT          = DetFlags.haveRIO.SCT_on(),
+                                                                             useTRT          = DetFlags.haveRIO.TRT_on())
+        ToolSvc += GSFBuildTrackSummaryHelperTool
+        print      GSFBuildTrackSummaryHelperTool
+        #
+        # Configurable version of TrkTrackSummaryTool: no TRT_PID tool needed here (no shared hits)
+        #
+        from TrkTrackSummaryTool.TrkTrackSummaryToolConf import Trk__TrackSummaryTool
+        GSFBuildInDetTrackSummaryTool = Trk__TrackSummaryTool(name = "GSFBuildInDetTrackSummaryTool",
+                                                              InDetSummaryHelperTool = GSFBuildTrackSummaryHelperTool,
+                                                              doSharedHits           = False,
+                                                              InDetHoleSearchTool    = GSFBuildHoleSearchTool,
+                                                              TRT_ElectronPidTool    = GSFBuildTRT_ElectronPidTool,
+                                                              PixelToTPIDTool        = GSFBuildPixelToTPIDTool)
+        ToolSvc += GSFBuildInDetTrackSummaryTool
+        print      GSFBuildInDetTrackSummaryTool
+        #
+        # --- load patricle creator tool
+        #
+        from TrkParticleCreator.TrkParticleCreatorConf import Trk__TrackParticleCreatorTool
+        GSFBuildInDetParticleCreatorTool = Trk__TrackParticleCreatorTool(name                    = "GSFBuildInDetParticleCreatorTool",
+                                                                         KeepParameters          = True,
+                                                                         Extrapolator            = GSFBuildInDetExtrapolator,
+                                                                         TrackSummaryTool        = GSFBuildInDetTrackSummaryTool,
+                                                                         UseTrackSummaryTool     = False,
+                                                                         ForceTrackSummaryUpdate = False)
+        # Otherwise Tracks and CombinedInDetTracks will be different when slimming
+
+        ToolSvc += GSFBuildInDetParticleCreatorTool
+        print GSFBuildInDetParticleCreatorTool
+        #
+        # --- do track slimming
+        #
+        from TrkTrackSlimmingTool.TrkTrackSlimmingToolConf import Trk__TrackSlimmingTool as ConfigurableTrackSlimmingTool
+        GSFBuildInDetTrkSlimmingTool = ConfigurableTrackSlimmingTool(name  = "GSFBuildInDetTrackSlimmingTool",
+                                                                     KeepParameters = True,
+                                                                     KeepOutliers   = True )
+        ToolSvc += GSFBuildInDetTrkSlimmingTool
+        print GSFBuildInDetTrkSlimmingTool
+
+
+        # do the configuration
+        self.ClusterContainerName="LArClusterEM"
+        from InDetRecExample.InDetKeys import InDetKeys
+        self.TrackParticleContainerName=InDetKeys.xAODTrackParticleContainer()
+        self.PrimaryVertexContainerName=InDetKeys.xAODVertexContainer()
+        self.TrackParticleTruthCollectionName="TrackParticleTruthCollection"
+        self.OutputTrkPartContainerName="GSFTrackParticles"
+        self.OutputTrackContainerName="GSFTracks"
+        self.TrackRefitTool= GSFRefitterTool
+        self.TrackParticleCreatorTool=GSFBuildInDetParticleCreatorTool
+        self.TrackSlimmingTool=GSFBuildInDetTrkSlimmingTool
+        self.TrackSummaryTool=GSFBuildInDetTrackSummaryTool
+
+        # do the configuration (from old EMBremCollectionBuilderBase)
+        self.minNoSiHits=4
+        self.broadDeltaEta=0.1   # this is multiplied by 2 for the Candidate Match , so +- 0.2 in eta
+        self.broadDeltaPhi=0.15   # this is multiplied by 2 for the Candidate Match , so +- 0.3 in phi
+        self.narrowDeltaEta=0.05 
+        #These have to be relaxed enough for the conversions
+        self.narrowDeltaPhi=0.05   
+        self.narrowDeltaPhiBrem=0.20 #Dominated by the needs of assymetric conversions
+        self.narrowDeltaPhiRescale=0.05  
+        self.narrowDeltaPhiRescaleBrem=0.1
diff --git a/Reconstruction/egamma/egammaTools/python/EMPIDBuilderBase.py b/Reconstruction/egamma/egammaTools/python/EMPIDBuilderBase.py
new file mode 100755
index 0000000000000..f2df693eb02c5
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/python/EMPIDBuilderBase.py
@@ -0,0 +1,78 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+# default configuration of the EMPIDBuilder
+from AthenaCommon.Logging import logging
+from AthenaCommon.DetFlags import DetFlags
+
+import traceback
+
+from ElectronPhotonSelectorTools.ElectronIsEMSelectorMapping import electronPIDmenu
+from ElectronPhotonSelectorTools.PhotonIsEMSelectorMapping import photonPIDmenu
+
+#import base class
+from egammaTools.egammaToolsConf import EMPIDBuilder
+
+import PyCintex
+PyCintex.loadDictionary('ElectronPhotonSelectorToolsDict')
+from ROOT import egammaPID
+
+class EMPIDBuilderElectronBase ( EMPIDBuilder ) :
+    __slots__ = ()
+
+    def __init__(self, name="EMPIDBuilderElectronBase", menu=electronPIDmenu.menu2012):
+        EMPIDBuilder.__init__(self,name)
+        mlog = logging.getLogger(name+'::__init__')
+        mlog.debug("entering")
+
+        from AthenaCommon.AppMgr import ToolSvc
+
+       # Electron Selectors
+        try:
+            from ElectronPhotonSelectorTools.ConfiguredAsgElectronIsEMSelectors import ConfiguredAsgElectronIsEMSelector
+            LooseElectronSelector = ConfiguredAsgElectronIsEMSelector("LooseElectronSelector", egammaPID.ElectronIDLoosePP)
+            ToolSvc+=LooseElectronSelector
+            MediumElectronSelector = ConfiguredAsgElectronIsEMSelector("MediumElectronSelector", egammaPID.ElectronIDMediumPP)
+            ToolSvc+=MediumElectronSelector
+            TightElectronSelector = ConfiguredAsgElectronIsEMSelector("TightElectronSelector", egammaPID.ElectronIDTightPP)
+            ToolSvc+=TightElectronSelector
+
+        except:
+            mlog.error("could not get configure tools")
+            print traceback.format_exc()
+            return False
+
+        electronSelectors = [LooseElectronSelector, MediumElectronSelector, TightElectronSelector]
+        electronSelectorNames = ["Loose", "Medium", "Tight"]
+            
+        self.selectors=electronSelectors
+        self.selectorResultNames=electronSelectorNames
+
+class EMPIDBuilderPhotonBase ( EMPIDBuilder ) :
+    __slots__ = ()
+
+    def __init__(self, name="EMPIDBuilderPhotonBase", menu=photonPIDmenu.menu2012):
+        EMPIDBuilder.__init__(self,name)
+        mlog = logging.getLogger(name+'::__init__')
+        mlog.debug("entering")
+
+        from AthenaCommon.AppMgr import ToolSvc
+
+        # photon Selectors
+        try:
+            from ElectronPhotonSelectorTools.ConfiguredAsgPhotonIsEMSelectors import ConfiguredAsgPhotonIsEMSelector
+            LoosePhotonSelector = ConfiguredAsgPhotonIsEMSelector("LoosePhotonSelector", egammaPID.PhotonIDLoose)
+            ToolSvc+=LoosePhotonSelector
+            TightPhotonSelector = ConfiguredAsgPhotonIsEMSelector("TightPhotonSelector", egammaPID.PhotonIDTight)
+            ToolSvc+=TightPhotonSelector
+
+
+        except:
+            mlog.error("could not get configure tools")
+            print traceback.format_exc()
+            return False
+
+        photonSelectors = [LoosePhotonSelector, TightPhotonSelector]
+        photonSelectorNames = ["Loose", "Tight"]
+            
+        self.selectors=photonSelectors
+        self.selectorResultNames=photonSelectorNames
diff --git a/Reconstruction/egamma/egammaTools/python/EMShowerBuilder.py b/Reconstruction/egamma/egammaTools/python/EMShowerBuilder.py
new file mode 100644
index 0000000000000..71c0ba2bdba71
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/python/EMShowerBuilder.py
@@ -0,0 +1,92 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+__doc__ = "ToolFactory to instantiate all EMShowerBuilder with default configuration"
+__author__ = "Bruno Lenzi"
+
+from AthenaCommon.Constants import INFO # OutputLevel
+from egammaTools import egammaToolsConf
+from egammaRec.Factories import ToolFactory, getPropertyValue
+from egammaRec import egammaKeys
+from egammaTools.egammaToolsFactories import EMTrackIsolationTool
+from egammaCaloTools.egammaCaloToolsFactories import egammaShowerShape, egammaTopoIso, \
+  egammaIso, egammaIsoPtCorrection
+
+import ROOT, PyCintex
+# Need to be sure base dict is loaded first.
+PyCintex.loadDictionary('xAODCoreRflxDict')
+PyCintex.loadDictionary('xAODEgammaDict')
+EgammaParameters = ROOT.xAOD.EgammaParameters
+
+from CaloIdentifier import SUBCALO        
+from RecExConfig.RecFlags import rec
+
+# TODO: not needed ?
+# from CaloDetDescr.CaloDepthToolBase import CaloDepthToolFactory
+# theCaloDepthTool=CaloDepthToolFactory(depth='showerdefault')
+
+def configureEDCorrection(tool):
+  """SL+JBdV: configure tools and algorithm for energy density correction 
+     (only if doEnergyDensityCorrection = True)"""
+  # Return if doEnergyDensityCorrection is false
+  if not getPropertyValue(tool, 'doEnergyDensityCorrection'):
+    return
+  # Set OutputLevel to INFO or higher if tool has it too (not working...)
+  OutputLevel = min(getPropertyValue(tool, 'doEnergyDensityCorrection'), INFO)
+  try:
+    from AthenaCommon.AppMgr import ToolSvc
+    from EventShapeTools.EventDensityConfig import configEventDensityTool, EventDensityAlg
+    from JetRec.JetRecStandard import jtm
+    tc=configEventDensityTool("EDEgammaCentralTool", jtm.emget,
+                              0.5,
+                              EtaRange            = [-1.5,1.5],
+                              UseAbsoluteEta      = True,
+                              UseAreaFourMomentum = True,
+                              VariableName = "DensityForEgammaCentral",
+#                               OutputLevel = OutputLevel,
+                              )
+                                                           
+    ToolSvc += tc
+    tf=configEventDensityTool("EDEgammaForwardTool", jtm.emget,
+                              0.5,
+                              EtaRange            = [1.5,3.0],
+                              UseAbsoluteEta      = True,
+                              UseAreaFourMomentum = True,
+                              VariableName = "DensityForEgammaForward",
+#                               OutputLevel = OutputLevel,
+                              )
+    ToolSvc += tf
+  except Exception:
+    print '\nERROR: could not get handle to EDEgammaXTool'
+    raise
+ 
+  # add to topsequence 
+  from AthenaCommon.AlgSequence import AlgSequence
+  topSequence = AlgSequence()
+  topSequence += EventDensityAlg("EDEgammaCentralAlg", EventDensityTool = tc)
+  topSequence += EventDensityAlg("EDEgammaForwardAlg", EventDensityTool = tf)
+
+
+EMShowerBuilder = ToolFactory( egammaToolsConf.EMShowerBuilder,
+        postInit = [configureEDCorrection],
+        TopoCaloClusterInputName="CaloCalTopoCluster",
+        CellsName = egammaKeys.caloCellKey(),
+        CaloNums  = [SUBCALO.LAREM, SUBCALO.LARHEC, SUBCALO.TILE],
+        ShowerShapeTool      = egammaShowerShape,
+        EMTopoCaloIsolationTool  = egammaTopoIso,
+        EMCaloIsolationTool  = egammaIso,
+        EMCaloIsoPtCorrectionTool = egammaIsoPtCorrection,
+        EMTrackIsolationTool = EMTrackIsolationTool,
+        IsoTypes = [
+            EgammaParameters.etcone20,
+            EgammaParameters.etcone30,
+            EgammaParameters.etcone40, 
+            ],
+       TopoIsoTypes = [] if rec.doHeavyIon() else \
+        [
+           EgammaParameters.topoetcone20, 
+           EgammaParameters.topoetcone30,
+           EgammaParameters.topoetcone40
+        ],
+        doIsolForTopoSeeded = False,
+        Print = False)
+
diff --git a/Reconstruction/egamma/egammaTools/python/EMTrackMatchBuilder.py b/Reconstruction/egamma/egammaTools/python/EMTrackMatchBuilder.py
new file mode 100644
index 0000000000000..1893e0bdb0530
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/python/EMTrackMatchBuilder.py
@@ -0,0 +1,30 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+__doc__ = "ToolFactory to instantiate EMTrackMatchBuilder with default configuration"
+__author__ = "Bruno Lenzi"
+
+import egammaToolsConf
+from egammaRec.Factories import FcnWrapper, ToolFactory
+from egammaRec import egammaKeys
+from RecExConfig.RecFlags import rec
+from AthenaCommon.BeamFlags import jobproperties
+from egammaTrackTools.egammaTrackToolsFactories import EMExtrapolationTools, ExtrapolateToCaloTool
+
+def appendToEMTrackMatchBuilder(tool):
+    "add track to calo tool (like it was done in egammaGetter)"
+    tool += ExtrapolateToCaloTool()
+    tool += EMExtrapolationTools()
+  
+EMTrackMatchBuilder = ToolFactory( egammaToolsConf.EMTrackMatchBuilder,
+      postInit = [appendToEMTrackMatchBuilder],
+      TrackParticlesName = egammaKeys.outputTrackParticleKey(),
+      ExtrapolationTool  = EMExtrapolationTools,
+      broadDeltaEta      = 0.1, #candidate match is done in 2 times this  so +- 0.2
+      broadDeltaPhi      = 0.15,  #candidate match is done in 2 times this  so +- 0.3
+      useLastMeasurement = False, #important for GSF!!!
+      useCandidateMatch  = True,
+      useScoring         = True,
+      SecondPassRescale  = True,
+      UseRescaleMetric   = True,
+      isCosmics          = (jobproperties.Beam.beamType()=="cosmics")
+)
diff --git a/Reconstruction/egamma/egammaTools/python/EMVertexBuilder.py b/Reconstruction/egamma/egammaTools/python/EMVertexBuilder.py
new file mode 100644
index 0000000000000..3918d0372aa39
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/python/EMVertexBuilder.py
@@ -0,0 +1,44 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+__doc__ = "ToolFactory to instantiate EMVertexBuilder with default configuration"
+__author__ = "Bruno Lenzi"
+
+import egammaToolsConf
+from egammaRec.Factories import FcnWrapper, ToolFactory
+from egammaRec import egammaKeys
+from RecExConfig.RecFlags import rec
+from AthenaCommon.BeamFlags import jobproperties
+from egammaTrackTools.egammaTrackToolsFactories import EMExtrapolationTools, ExtrapolateToCaloTool
+
+from InDetTools import egammaInDetTrackSummaryTool, \
+  InDet__SingleTrackConversionTool, \
+  egammaExtrapolator
+
+class VertexFinderToolInstance(FcnWrapper):
+  def __call__(self):
+    #
+    # Configured conversion vertex reconstruction cuts
+    #
+    from InDetRecExample.ConfiguredSecondaryVertexCuts import ConfiguredSecondaryVertexCuts
+    egammaConversionVertexCuts = ConfiguredSecondaryVertexCuts(mode ="EGammaPileUp")
+    
+    from InDetRecExample.ConfiguredSecVertexFinding import ConfiguredSecVertexFinding
+    theemvertexfindertool=ConfiguredSecVertexFinding (prefix         = "egammaConversion",
+                                                      VertexCuts     = egammaConversionVertexCuts,
+                                                      TrackParticles = egammaKeys.outputTrackParticleKey(),
+                                                      SecVertices    = egammaKeys.outputConversionKey(),
+                                                      Extrapolator   = egammaExtrapolator(),
+                                                      TrackSummaryTool = egammaInDetTrackSummaryTool(),
+                                                      printConfig      = True)
+
+    return theemvertexfindertool.toolInstance()
+
+
+EMVertexBuilder = ToolFactory( egammaToolsConf.EMVertexBuilder,
+    InputTrackParticleContainerName = egammaKeys.outputTrackParticleKey(),
+    OutputConversionContainerName   = egammaKeys.outputConversionKey(),
+    VertexFinderTool                = VertexFinderToolInstance(),
+    SingleTrackConversionTool = InDet__SingleTrackConversionTool,
+    ExtrapolationTool = EMExtrapolationTools)
+
+
diff --git a/Reconstruction/egamma/egammaTools/python/InDetTools.py b/Reconstruction/egamma/egammaTools/python/InDetTools.py
new file mode 100644
index 0000000000000..f9ed5bacaab02
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/python/InDetTools.py
@@ -0,0 +1,111 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+__doc__ = "ToolFactories to instantiate InDet tools for egamma with default configuration"
+__author__ = "Bruno Lenzi"
+
+from egammaRec.Factories import FcnWrapper, ToolFactory
+
+#########
+# What used to be egammaRec/python/EMCommonExtrapolator
+
+def configureExtrapolator( egammaExtrapolator ):
+  from AthenaCommon.AppMgr import ToolSvc
+  
+  egammaExtrapolator.DoCaloDynamic = False # this turns off dynamic calculation of eloss in calorimeters
+  # all left to MaterialEffects/EnergyLossUpdators
+
+  from TrkExTools.TrkExToolsConf import Trk__MaterialEffectsUpdator as MaterialEffectsUpdator
+  AtlasMaterialEffectsUpdator = MaterialEffectsUpdator(name = 'AtlasMaterialEffectsUpdator')
+  ToolSvc += AtlasMaterialEffectsUpdator #default material effects updator
+  NoElossMaterialEffectsUpdator = MaterialEffectsUpdator(name = 'NoElossMaterialEffectsUpdator')
+  NoElossMaterialEffectsUpdator.EnergyLoss = False
+  ToolSvc += NoElossMaterialEffectsUpdator
+
+  # setup MaterialEffectsUpdator arrays
+  MyUpdators = []
+  MyUpdators += [AtlasMaterialEffectsUpdator] # for ID
+  MyUpdators += [NoElossMaterialEffectsUpdator] # for Calo
+  # MyUpdators += [NoElossMaterialEffectsUpdator] # for muon
+
+  MySubUpdators = []
+  MySubUpdators += [AtlasMaterialEffectsUpdator.name()] # for ID
+  MySubUpdators += [NoElossMaterialEffectsUpdator.name()] # for Calo
+  MySubUpdators += [NoElossMaterialEffectsUpdator.name()] # for muon
+
+  egammaExtrapolator.MaterialEffectsUpdators = MyUpdators
+  egammaExtrapolator.SubMEUpdators = MySubUpdators
+
+from TrkExTools.AtlasExtrapolator import AtlasExtrapolator
+egammaExtrapolator = ToolFactory(AtlasExtrapolator,
+  postInit=[configureExtrapolator],
+  name = 'egammaExtrapolator')
+
+
+#########
+# What used to be egammaRec/python/EMCommonTrackSummary.py
+
+#
+# ----------- load association tool from Inner Detector to handle pixel ganged ambiguities
+#
+from InDetAssociationTools.InDetAssociationToolsConf import InDet__InDetPRD_AssociationToolGangedPixels
+egammaInDetPrdAssociationTool = ToolFactory( InDet__InDetPRD_AssociationToolGangedPixels,
+  doPrint = True,
+  name                           = "egammaInDetPrdAssociationTool",
+  PixelClusterAmbiguitiesMapName = 'PixelClusterAmbiguitiesMap')
+
+#
+# Loading Configurable HoleSearchTool
+#
+from InDetTrackHoleSearch.InDetTrackHoleSearchConf import InDet__InDetTrackHoleSearchTool
+egammaInDetHoleSearchTool = ToolFactory( InDet__InDetTrackHoleSearchTool,
+                                         doPrint = True,
+                                         name = "egammaInDetHoleSearchTool",
+                                         Extrapolator = egammaExtrapolator)
+
+#
+# Load the InDetTrackSummaryHelperTool
+#
+from AthenaCommon.DetFlags import DetFlags
+from InDetTrackSummaryHelperTool.InDetTrackSummaryHelperToolConf import InDet__InDetTrackSummaryHelperTool
+egammaInDetTrackSummaryHelperTool = ToolFactory( InDet__InDetTrackSummaryHelperTool,
+                       doPrint = True,
+                       name         = "egammaInDetSummaryHelper",
+								       AssoTool     = egammaInDetPrdAssociationTool,
+								       DoSharedHits = False,
+								       HoleSearch   = egammaInDetHoleSearchTool,
+                       usePixel     = DetFlags.haveRIO.pixel_on(),
+                       useSCT       = DetFlags.haveRIO.SCT_on(),
+                       useTRT       = DetFlags.haveRIO.TRT_on() )
+
+#
+from TrkTrackSummaryTool.TrkTrackSummaryToolConf import Trk__TrackSummaryTool
+egammaInDetTrackSummaryTool = ToolFactory( Trk__TrackSummaryTool,
+                doPrint = True,
+                name = "egammaInDetTrackSummaryTool",
+						    InDetSummaryHelperTool = egammaInDetTrackSummaryHelperTool,
+						    doSharedHits           = False,
+						    InDetHoleSearchTool    = egammaInDetHoleSearchTool)
+
+#########
+# What used to be egammaRec/python/EMCommonSingleTrackConversionTool.py
+
+def getTrkExtrapolator():
+  import egammaRec.EMCommonRefitter
+  return egammaRec.EMCommonRefitter.egTrkExtrapolator
+
+# Helper Tool
+#
+from InDetConversionFinderTools import InDetConversionFinderToolsConf
+InDet__ConversionFinderUtils = ToolFactory( InDetConversionFinderToolsConf.InDet__ConversionFinderUtils)
+
+#
+# Single track conversion tool
+#
+InDet__SingleTrackConversionTool = ToolFactory( InDetConversionFinderToolsConf.InDet__SingleTrackConversionTool,
+  name                       = "CPSingleTrackConversionTool",
+  ConversionFinderHelperTool = InDet__ConversionFinderUtils,
+  TrackSummaryTool           = egammaInDetTrackSummaryTool,
+  Extrapolator               = FcnWrapper(getTrkExtrapolator),
+  MinInitialHitRadius        = 70.,
+  MinRatioOfHLhits           = 0.95)
+
diff --git a/Reconstruction/egamma/egammaTools/python/egammaOQFlagsBuilder.py b/Reconstruction/egamma/egammaTools/python/egammaOQFlagsBuilder.py
new file mode 100644
index 0000000000000..cfd6c62e29d68
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/python/egammaOQFlagsBuilder.py
@@ -0,0 +1,22 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+import egammaToolsConf
+from egammaRec.Factories import FcnWrapper, ToolFactory
+from egammaRec import egammaKeys
+
+from LArBadChannelTool import LArBadChannelToolConf
+LArBadChanTool = ToolFactory( LArBadChannelToolConf.LArBadChanTool )
+
+from CaloTools import CaloAffectedToolDefault as CATD
+CaloAffectedToolDefault = ToolFactory( CATD.CaloAffectedToolDefault )
+
+egammaOQFlagsBuilder = ToolFactory( egammaToolsConf.egammaOQFlagsBuilder,
+  QCellCut = 4000.,
+  QCellHECCut = 60000.,
+  QCellSporCut = 4000.,
+  LArQCut = 0.8,
+  TCut = 10.,
+  TCutVsE = 2.,
+  CellsName = egammaKeys.caloCellKey(),
+  LArBadChannelTool = LArBadChanTool,
+  affectedTool = CaloAffectedToolDefault)
diff --git a/Reconstruction/egamma/egammaTools/python/egammaToolsFactories.py b/Reconstruction/egamma/egammaTools/python/egammaToolsFactories.py
new file mode 100644
index 0000000000000..35d34c94caac3
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/python/egammaToolsFactories.py
@@ -0,0 +1,99 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+__doc__ = "ToolFactories to instantiate all egammaTools with default configuration"
+__author__ = "Bruno Lenzi"
+
+import egammaToolsConf
+from egammaRec.Factories import FcnWrapper, ToolFactory, FullNameWrapper
+from egammaRec import egammaKeys
+from RecExConfig.RecFlags import rec
+
+def configureClusterCorrections(swTool):
+  "Add attributes ClusterCorrectionToolsXX to egammaSwTool object"
+  from CaloClusterCorrection.CaloSwCorrections import make_CaloSwCorrections
+  from CaloRec.CaloRecMakers import _process_tools
+  
+  clusterTypes = dict(
+    Ele35='ele35', Ele55='ele55', Ele37='ele37',
+    Gam35='gam35_unconv', Gam55='gam55_unconv',
+    Econv35='gam35_conv', Econv55='gam55_conv', Econv37='gam37_conv'
+  )
+
+  for attrName, clName in clusterTypes.iteritems():
+    x = 'ClusterCorrectionTools' + attrName
+    if not hasattr(swTool, x) or getattr(swTool, x):
+      continue
+    y = make_CaloSwCorrections(clName, suffix='EG', cells_name=egammaKeys.caloCellKey() )
+    setattr(swTool, x, _process_tools (swTool, y) )
+
+#-------------------------
+
+egammaSwTool = ToolFactory(egammaToolsConf.egammaSwTool,
+  postInit=[configureClusterCorrections])
+
+
+EMClusterTool = ToolFactory(egammaToolsConf.EMClusterTool,
+  OutputClusterContainerName = egammaKeys.outputClusterKey(),
+  ElectronContainerName = egammaKeys.outputElectronKey(),
+  PhotonContainerName = egammaKeys.outputPhotonKey(),
+  ClusterCorrectionToolName = FullNameWrapper(egammaSwTool)
+)
+
+
+egammaCheckEnergyDepositTool = ToolFactory(egammaToolsConf.egammaCheckEnergyDepositTool,
+                                           UseThrFmax=True, 
+                                           ThrF0max=0.9,
+                                           ThrF1max=0.8,
+                                           ThrF2max=0.98,
+                                           ThrF3max=0.8)
+
+
+from IsolationTool.IsolationToolConf import xAOD__TrackIsolationTool
+EMTrackIsolationTool = ToolFactory( egammaToolsConf.EMTrackIsolationTool,
+  TrackIsolationTool = ToolFactory(xAOD__TrackIsolationTool),
+  useBremAssoc = True)
+
+
+from EMBremCollectionBuilder import egammaBremCollectionBuilder
+from egammaTrackTools.egammaTrackToolsFactories import EMExtrapolationTools
+EMBremCollectionBuilder = ToolFactory( egammaBremCollectionBuilder,
+                                       name = 'EMBremCollectionBuilder',
+                                       ExtrapolationTool = EMExtrapolationTools,
+                                       OutputTrackContainerName=egammaKeys.outputTrackKey(),
+                                       ClusterContainerName=egammaKeys.inputClusterKey(),
+                                       DoTruth=rec.doTruth()
+)
+
+
+
+EMConversionBuilder = ToolFactory( egammaToolsConf.EMConversionBuilder,
+                                   egammaRecContainerName = egammaKeys.outputEgammaRecKey(),
+                                   ConversionContainerName = egammaKeys.outputConversionKey(),
+                                   ExtrapolationTool = EMExtrapolationTools)   
+
+
+EMAmbiguityTool = ToolFactory( egammaToolsConf.EMAmbiguityTool )
+
+
+
+from egammaTrackTools.egammaTrackToolsFactories import convUtils
+import EventKernel.ParticleDataType
+EMFourMomBuilder = ToolFactory( egammaToolsConf.EMFourMomBuilder,
+                                ConversionUtils          = convUtils,
+                                dataType=EventKernel.ParticleDataType.Full )
+
+# Electron Selectors
+from EMPIDBuilderBase import EMPIDBuilderElectronBase
+ElectronPIDBuilder = ToolFactory( EMPIDBuilderElectronBase, name = "ElectronPIDBuilder")
+
+# Photon Selectors
+from EMPIDBuilderBase import EMPIDBuilderPhotonBase
+PhotonPIDBuilder = ToolFactory( EMPIDBuilderPhotonBase, name = "PhotonPIDBuilder")
+
+#-------------------------
+
+# Import the factories that are not defined here
+from EMShowerBuilder import EMShowerBuilder
+from egammaOQFlagsBuilder import egammaOQFlagsBuilder
+from EMTrackMatchBuilder import EMTrackMatchBuilder
+from EMVertexBuilder import EMVertexBuilder
diff --git a/Reconstruction/egamma/egammaTools/src/CandidateMatchHelpers.h b/Reconstruction/egamma/egammaTools/src/CandidateMatchHelpers.h
new file mode 100644
index 0000000000000..67c047f9a8468
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/CandidateMatchHelpers.h
@@ -0,0 +1,77 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef CANDIDATEMATCHHELPERS_H
+#define CANDIDATEMATCHHELPERS_H
+#include <cmath>
+#include <iostream>
+class CandidateMatchHelpers
+{
+ public:
+  CandidateMatchHelpers(){}
+  ~CandidateMatchHelpers(){}
+
+  double CorrectedEta(double clusterEta,double z_first,bool isEndCap){
+    //===========================================================//
+    //These are at the face of the calorimeter
+    const  double Rcalo = 1500;
+    const  double Zcalo = 3700;
+    double Rclus=Rcalo;
+    double Zclus=Zcalo;    
+    if(clusterEta!=0){
+      //eta !=0
+      double tanthetaclus=(1/cosh(clusterEta))/tanh(clusterEta); 
+      if (isEndCap) {
+	Rclus=fabs(Zcalo*(tanthetaclus));
+	//Negative Eta ---> negative Z
+	if(clusterEta<0){
+	  Zclus = -Zclus;
+	}
+      } 	  
+      else{
+	if(tanthetaclus!=0){
+	  Zclus=Rcalo/(tanthetaclus);
+	}
+      }
+    }
+    else{
+      //eta 0
+      Zclus=0;
+    }
+    //===========================================================//    
+    //correct for a possible shift in the track perigee wrt to (0,0)
+    double thetaclus_corrected=atan2(Rclus,Zclus-z_first);
+    double etaclus_corrected = 99999; //if theta =0 or M_PI the eta +-inf this happens when Rclus =0 
+    if(Rclus!=0){
+      etaclus_corrected = -log(tan(thetaclus_corrected/2));
+    }
+    //===========================================================//
+    return etaclus_corrected;
+  }
+  double PhiROT(double Et,double Eta, int charge, double r_first ,bool isEndCap){
+    //===========================================================//
+    //Used in order to derive the formula below
+    const  double Rcalo = 1200;
+    //===========================================================//
+    // correct phi for extrapolation to calo
+    double phiRot = 0.0;
+    double ecCorr = 1.0;
+    if (isEndCap) {
+      double ecFactor = 1.0/(0.8*atan(15.0/34.0));
+      double sinTheta0 = 2.0*atan(exp(-fabs(Eta)));
+      ecCorr = sinTheta0*sqrt(sinTheta0)*ecFactor;
+    }
+    ////
+    double Rscaled =(Rcalo-r_first)/Rcalo;
+    phiRot = Rscaled*ecCorr*charge*430./(Et);    
+    return  phiRot;
+  }
+};
+
+
+
+
+
+
+#endif
diff --git a/Reconstruction/egamma/egammaTools/src/ConvVxSorter.h b/Reconstruction/egamma/egammaTools/src/ConvVxSorter.h
new file mode 100644
index 0000000000000..5ebdd018edcb2
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/ConvVxSorter.h
@@ -0,0 +1,52 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef EGAMMATOOLS_CONVVXSORTER_H
+#define EGAMMATOOLS_CONVVXSORTER_H
+
+#include "xAODTracking/Vertex.h"
+#include "xAODEgamma/EgammaxAODHelpers.h"
+
+/** Sort conversion vertices according to the following criteria:
+  - Vertices with more Si tracks have priority
+  - Vertices with more tracks have priority
+  - Vertices with smaller radii have priority
+  
+  OLD SCHEME:
+  - Vertices with 2 tracks have priority over the ones with 1 track
+  - Vertices with Si + Si tracks have priority (if m_preferSi > 0)
+  - Vertices with Si + TRT or TRT + TRT depending on m_preferSi
+  - Vertices with smaller radii have priority
+  **/ 
+class ConvVxSorter
+: public std::binary_function<xAOD::Vertex&, xAOD::Vertex&, bool> {
+ public:
+  bool operator()(const xAOD::Vertex& vx1, const xAOD::Vertex& vx2) const
+  {
+    xAOD::EgammaParameters::ConversionType convType1, convType2;
+    convType1 = xAOD::EgammaHelpers::conversionType(&vx1);
+    convType2 = xAOD::EgammaHelpers::conversionType(&vx2);
+    
+    if (convType1 != convType2)
+    {
+      // Different conversion type, preference to vertices with Si tracks
+      int nSi1 = xAOD::EgammaHelpers::numberOfSiTracks(convType1);
+      int nSi2 = xAOD::EgammaHelpers::numberOfSiTracks(convType2);
+      if (nSi1 != nSi2) return nSi1 > nSi2;
+      
+      // Same number of Si tracks: either 0 or 1 (Si+TRT vs. Si single)
+      // For 1 Si track, preference to Si+TRT
+      if (nSi1 != 0) return convType1 == xAOD::EgammaParameters::doubleSiTRT;
+      
+      // No Si track, preference to doubleTRT over single TRT
+      return convType1 == xAOD::EgammaParameters::doubleTRT;
+    }
+    
+    // Same conversion type, preference to lower radius
+    return (vx1.position().perp() < vx2.position().perp());
+  }
+
+};
+
+#endif
diff --git a/Reconstruction/egamma/egammaTools/src/EMAmbiguityTool.cxx b/Reconstruction/egamma/egammaTools/src/EMAmbiguityTool.cxx
new file mode 100644
index 0000000000000..d9dedee422cda
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/EMAmbiguityTool.cxx
@@ -0,0 +1,165 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/********************************************************************
+
+NAME:     EMAmbiguityTool.cxx
+PACKAGE:  offline/Reconstruction/egamma/egammaTrackTools
+
+CREATED:  12/06/2008
+AUTHOR : T. Koffas
+MODIFIED:
+          Dec. 28, 2009 (FD) add protections against bad pointers
+          May  06, 2010 (JM) use expectHitInBLayer for dead pixels
+          June 06, 2010 (JM) add expectHitInBLayer when tp != conversion tracks
+          June 07, 2010 (JM) remove LocationOfConversion function
+          June,    2010 (JM) expand role of tool and change interface
+          July 18, 2010 (JM) make it return AmbiguityResult instead of bool
+          Oct. 28, 2010 (JM) make it use expectHitInBLayer from track summary
+          Nov. 10, 2010 (JM) allow it to use outliers
+          Feb.  6, 2012 (JM) introduce MEDIUM AR for two-track conversions
+          Feb. 20, 2014 (BL) xAOD migration, changing logic
+********************************************************************/
+
+#include "EMAmbiguityTool.h"
+
+#include "xAODEgamma/EgammaDefs.h"
+#include "xAODEgamma/EgammaxAODHelpers.h"
+
+#include "xAODTracking/Vertex.h"
+#include "xAODTracking/TrackParticle.h"
+
+
+EMAmbiguityTool::EMAmbiguityTool(const std::string& type, const std::string& name, const IInterface* parent) :
+  AthAlgTool(type, name, parent)
+{
+  declareInterface<IEMAmbiguityTool>(this);
+  //Minimum silicon hits for electron
+
+  declareProperty("minNoSiHits",  m_MinNoSiHits = 4, "Minimum number of silicon hits to be an electron");
+  declareProperty("minNoPixHits", m_MinNoPixHits = 2, "Minimum number of Pixel hits to be an electron");
+
+}
+
+EMAmbiguityTool::~EMAmbiguityTool() {}
+
+StatusCode EMAmbiguityTool::initialize() {
+
+  ATH_MSG_DEBUG("Initializing " << name() << "...");
+  
+  return StatusCode::SUCCESS;
+}
+
+StatusCode EMAmbiguityTool::finalize() {
+  return StatusCode::SUCCESS;
+}
+
+// ====================================================================
+// return value: AuthorElectron, AuthorPhoton, AuthorAmbiguous, AuthorUnknown
+
+unsigned int EMAmbiguityTool::ambiguityResolve(const xAOD::Vertex* vx, 
+	                                             const xAOD::TrackParticle* tp) const
+{
+  uint8_t trkExpectBlayerHit(0), trkBlayerHits(0), trkPixelHits(0), trkSiHits(0);
+
+  if (tp && !tp->summaryValue(trkExpectBlayerHit,xAOD::expectBLayerHit))
+    ATH_MSG_WARNING("Could not retrieve expected BLayer hit from track");
+  
+  if (tp && !tp->summaryValue(trkBlayerHits,xAOD::numberOfBLayerHits))
+    ATH_MSG_WARNING("Could not retrieve number of BLayer hits from track");
+  
+  if (tp && !tp->summaryValue(trkPixelHits,xAOD::numberOfPixelHits))
+    ATH_MSG_WARNING("Could not retrieve number of pixel hits from track");
+  
+  if (tp && !tp->summaryValue(trkSiHits, xAOD::numberOfSCTHits))
+    ATH_MSG_WARNING("Could not retrieve number of SCT hits from track");
+  trkSiHits += trkPixelHits;
+  
+  xAOD::EgammaParameters::ConversionType convType(xAOD::EgammaHelpers::conversionType(vx));
+  bool vxDoubleSi = (convType == xAOD::EgammaParameters::doubleSi);
+  
+
+  //See if the Si+Si conversion shares one track with the electron
+  //if not we might have a trident.
+  //if yes and the track is not good we definetely matched the conversion as electron.
+
+  bool shareTrack=false;
+  if(tp && trkSiHits>=m_MinNoSiHits && vxDoubleSi){
+    const xAOD::TrackParticle *trk1 = ( vx->nTrackParticles() ? vx->trackParticle(0) : 0 );
+    const xAOD::TrackParticle *trk2 = ( vx->nTrackParticles() > 1 ? vx->trackParticle(1) : 0 );
+  
+    if( (tp==trk1) || (tp==trk2)) {
+      shareTrack=true;
+
+    }
+  }
+  
+  ATH_MSG_DEBUG("Vertex, SiSi: " << (vx != 0) << " , " << vxDoubleSi);
+  ATH_MSG_DEBUG("Track, Si hits, pixel hits, bLayerHits, expectBlayerHit: " 
+    << (tp != 0) << " , " << (int) trkSiHits << " , " << (int) trkPixelHits 
+    << " , " <<  (int) trkBlayerHits << " , " << (int) trkExpectBlayerHit);
+  ATH_MSG_DEBUG("Share track : " << shareTrack);
+
+  //The Electron collection will NOT contain Photons
+  //The Photon collection will NOT contain Electrons
+
+  //So for conversions vs electrons better to go to ambiguous 
+  //except  if we are sure.
+
+  //Practically a photon here means definetely not Electron
+  //And vice-versa
+
+  //Photon ==> Surely not electron
+  // - no track
+  // - or no track with the minimum requirent hits to be an electron
+  // - or Si+Si vertex and
+  //    - less than minimum pixel hits
+  //    - The electron track is part of the conversion
+  // In this case we do not want this to be in Electrons
+
+  if (!tp || 
+      trkSiHits<m_MinNoSiHits || 
+      (vxDoubleSi && trkPixelHits< m_MinNoPixHits && shareTrack)){
+    ATH_MSG_DEBUG("Returning Photon");
+    return xAOD::EgammaParameters::AuthorPhoton;
+  }
+  
+  //Electron ==> Surely not Photon
+  
+  // - Track with at least the minimum si hits (previous selection for photons)
+  // - No vertex Matched
+  // - Or if a vertex exists and is not  Si+Si
+  //    - Either Blayer hit
+  //    - Or 2 or more Pixel hits
+  // In this case we do not want this to be in Photons
+  
+  if(!vx || 
+     (trkBlayerHits && !vxDoubleSi) || 
+     (trkPixelHits>=m_MinNoPixHits  && !vxDoubleSi)){
+    ATH_MSG_DEBUG("Returning Electron");
+    return xAOD::EgammaParameters::AuthorElectron;
+  }
+
+  // Ambiguous all else, these will go to both electrons and photons
+
+  // This involves a matched Si+Si vertex and  a track with both silicon and pixel hits.
+  // Or a non Si+Si vertex matched and a track with enough Silicon but not Pixel hits
+  //i.e 
+
+  //1)
+  // - A track with minimum Si hits is matched
+  // - A Si+Si vertex is also matched
+  // - The track has also the minimum Pixel hit
+
+  //2)
+  // - A track with minimum Si hits is matched
+  // - A non Si+Si vertex is also matched
+  // - There is no b-layer hit or   
+  // - Less than the minimum pixel hits 
+
+
+  ATH_MSG_DEBUG("Returning Ambiguous");
+  return xAOD::EgammaParameters::AuthorAmbiguous;
+}
+
diff --git a/Reconstruction/egamma/egammaTools/src/EMAmbiguityTool.h b/Reconstruction/egamma/egammaTools/src/EMAmbiguityTool.h
new file mode 100644
index 0000000000000..2eb20a09c9a47
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/EMAmbiguityTool.h
@@ -0,0 +1,42 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef EMAMBIGUITYTOOL_H
+#define EMAMBIGUITYTOOL_H
+
+#include "AthenaBaseComps/AthAlgTool.h"
+// #include "GaudiKernel/ToolHandle.h"
+#include "egammaInterfaces/IEMAmbiguityTool.h"
+
+#include "xAODTracking/VertexFwd.h"
+#include "xAODTracking/TrackParticleFwd.h"
+
+/**
+   @class EMAmbiguityTool
+   This tool resolves the electron-converted photon ambiguity.
+   @author Thomas Koffas
+   @author Bruno Lenzi 
+   @author Christos Anastopoulos
+*/
+
+class EMAmbiguityTool : virtual public IEMAmbiguityTool, public AthAlgTool {
+
+public:
+  EMAmbiguityTool (const std::string& type,const std::string& name, const IInterface* parent);
+  virtual ~EMAmbiguityTool();
+
+  virtual StatusCode initialize();
+  virtual StatusCode finalize();
+
+  unsigned int ambiguityResolve(const xAOD::Vertex* vx, 
+				const xAOD::TrackParticle* trParticle) const;
+
+private:
+
+  /** @brief Minimum number of silicon hits to be an electron */
+  unsigned int m_MinNoSiHits;
+  unsigned int m_MinNoPixHits;
+};
+
+#endif // EMAMBIGUITYTOOL_H 
diff --git a/Reconstruction/egamma/egammaTools/src/EMBremCollectionBuilder.cxx b/Reconstruction/egamma/egammaTools/src/EMBremCollectionBuilder.cxx
new file mode 100644
index 0000000000000..e047942fc7dcc
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/EMBremCollectionBuilder.cxx
@@ -0,0 +1,551 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/********************************************************************
+
+NAME:     EMBremCollectionBuilder
+PACKAGE:  offline/Reconstruction/egamma/egammaTrackTools/EMBremCollectionBuilder
+
+AUTHORS:  Anastopoulos
+CREATED:  
+
+PURPOSE:  Performs Brem refit of all tracks 
+UPDATE :
+**********************************************************************/
+#include "EMBremCollectionBuilder.h"
+
+#include "Particle/TrackParticleContainer.h"
+#include "Particle/TrackParticle.h"
+#include "CaloEvent/CaloClusterContainer.h"
+#include "CaloEvent/CaloCluster.h"
+#include "ParticleTruth/TrackParticleTruthCollection.h"
+#include "ParticleTruth/TrackParticleTruth.h"
+#include "TrkTrack/LinkToTrack.h"
+#include "TrkTrackLink/ITrackLink.h"
+#include "TrkParticleBase/LinkToTrackParticleBase.h"
+#include "TrkToolInterfaces/ITrackParticleCreatorTool.h"
+#include "TrkToolInterfaces/ITrackSlimmingTool.h"
+#include "TrkToolInterfaces/ITrackSummaryTool.h"
+//Refit
+#include "egammaInterfaces/IegammaTrkRefitterTool.h"
+//extrapolation
+#include "egammaInterfaces/IEMExtrapolationTools.h"
+//
+#include "VxVertex/VxCandidate.h"
+#include "VxVertex/VxContainer.h"
+#include "TrkEventPrimitives/VertexType.h"
+#include "NavFourMom/INavigable4MomentumCollection.h"
+//
+#include "CandidateMatchHelpers.h"
+
+#include "AthenaKernel/errorcheck.h"
+
+#include "xAODTracking/Vertex.h"
+#include "xAODTracking/TrackParticle.h"
+
+#include "xAODTracking/VertexContainer.h"
+#include "xAODTracking/TrackParticleContainer.h"
+#include "xAODTracking/TrackParticleAuxContainer.h"
+
+#include "xAODCaloEvent/CaloCluster.h"
+#include "xAODCaloEvent/CaloClusterContainer.h"
+
+#include "xAODTruth/TruthParticleContainer.h"
+#include "xAODTruth/TruthParticle.h"
+
+//std includes
+#include <stdint.h>
+#include <algorithm>
+#include <cmath>
+
+//////////////////////////////////////////////////////////////////////////////////////
+/// Constructor
+EMBremCollectionBuilder::EMBremCollectionBuilder(const std::string& type, const std::string& name, const IInterface* parent) :
+  AthAlgTool(type, name, parent),
+  m_trkRefitTool("egamma/ElectronRefitterTool"),
+  m_particleCreatorTool("Trk::TrackParticleCreatorTool"),
+  m_slimTool("Trk::TrkTrackSlimmingTool/TrkTrackSlimmingTool"),
+  m_summaryTool("Trk::TrackSummaryTool/InDetTrackSummaryTool"),
+  m_extrapolationTool("EMExtrapolationTools")
+{
+  //options
+  declareProperty("DoTruth",                                m_doTruth=false);
+  //Collection
+  declareProperty("ClusterContainerName"  ,                 m_clusterContainerName   = "LArClusterEM");
+  declareProperty("TrackParticleContainerName"  ,           m_trackParticleContainerName   = "InDetTrackParticles");
+  declareProperty("PrimaryVertexContainerName"  ,           m_vxCandidatesPrimaryName   = "PrimaryVertices");
+  declareProperty("OutputTrkPartContainerName",             m_OutputTrkPartContainerName = "GSFTrackParticles");
+  declareProperty("TrackParticleTruthCollectionName",       m_trackParticleTruthCollectionName = "TrackParticleTruthCollection");
+  declareProperty("OutputTrackContainerName",               m_OutputTrackContainerName = "GSFTracks");
+
+  //=================================================================================
+  // Tools
+  declareProperty("TrackRefitTool",                         m_trkRefitTool);
+  declareProperty("TrackParticleCreatorTool",               m_particleCreatorTool);
+  declareProperty("TrackSlimmingTool",                      m_slimTool);
+  declareProperty("TrackSummaryTool",                       m_summaryTool);
+  declareProperty("ExtrapolationTool",                      m_extrapolationTool, "Handle of the extrapolation tool");
+  //=================================================================================
+  //Minimum silicon hits before doing GSF
+  declareProperty("minNoSiHits",                            m_MinNoSiHits = 4,         
+		  "Minimum number of silicon hits on track before it is allowed to be refitted");
+  //=================================================================================
+  // Value of broad cut for delta eta
+  declareProperty("broadDeltaEta",                           m_broadDeltaEta = 0.1, 
+		  "Value of broad cut for delta eta, it is mult by 2");
+  // Value of broad cut for delta phi
+  declareProperty("broadDeltaPhi",                           m_broadDeltaPhi = 0.15,
+		  "Value of broad cut for delta phi, it is mult by 2 ");
+  // Value of narrow cuts
+  declareProperty("narrowDeltaEta",                          m_narrowDeltaEta = 0.05,
+		  "Value of narrow cut for delta eta");
+  declareProperty("narrowDeltaPhi",                          m_narrowDeltaPhi = 0.05,
+		  "Value of narrow cut for delta phi");
+  declareProperty("narrowDeltaPhiBrem",                      m_narrowDeltaPhiBrem =0.15,
+		  "Value of the narrow cut for delta phi in the brem direction");
+  declareProperty("narrowDeltaPhiRescale",                   m_narrowRescale =0.05,
+		  "Value of the narrow cut for delta phi Rescale");
+  declareProperty("narrowDeltaPhiRescaleBrem",               m_narrowRescaleBrem =0.1,
+		  "Value of the narrow cut for delta phi Rescale Brem");
+  declareInterface<IEMBremCollectionBuilder>(this);
+}
+// ===================================================================
+EMBremCollectionBuilder::~EMBremCollectionBuilder() 
+{
+}
+
+// ==================================================================
+StatusCode EMBremCollectionBuilder::initialize() 
+{
+
+  // retrieve the track refitter tool:
+  if(m_trkRefitTool.retrieve().isFailure()) {
+    ATH_MSG_ERROR ( "Unable to retrieve " << m_trkRefitTool);
+    return StatusCode::FAILURE;
+  } 
+
+  /* Get the particle creation tool */
+  if ( m_particleCreatorTool.retrieve().isFailure() ) {
+    ATH_MSG_ERROR ("Failed to retrieve tool " << m_particleCreatorTool);
+    return StatusCode::FAILURE;
+  } 
+  
+  /* Get the track slimming tool */
+  if ( m_slimTool.retrieve().isFailure() ) {
+    ATH_MSG_ERROR ( "Failed to retrieve TrkTrackSlimmingTool tool "<< m_slimTool);
+    return StatusCode::FAILURE;
+  } 
+
+  /* Get the track summary tool */
+  if ( m_summaryTool.retrieve().isFailure() ) {
+    ATH_MSG_ERROR ( "Failed to retrieve TrkTrackSummaryTool tool "<< m_summaryTool);
+    return StatusCode::FAILURE;
+  } 
+  
+  /* the extrapolation tool*/
+  if(m_extrapolationTool.retrieve().isFailure()){
+    ATH_MSG_ERROR("initialize: Cannot retrieve extrapolationTool " << m_extrapolationTool);
+    return StatusCode::FAILURE;
+  }
+
+
+  //counters 
+  m_AllClusters=0;
+  m_AllTracks=0;
+  m_AllTRTTracks=0;
+  m_AllSiTracks=0;
+  m_SelectedTracks=0;
+  m_SelectedTRTTracks=0;
+  m_SelectedSiTracks=0;
+  m_FailedFitTracks=0;
+  m_FailedSiliconRequirFit=0;
+  m_RefittedTracks=0;
+
+  return StatusCode::SUCCESS;
+}  
+
+
+//*************************************************************************
+// Finalize
+StatusCode EMBremCollectionBuilder::EMBremCollectionBuilder::finalize(){ 
+
+  
+  ATH_MSG_INFO ("AllClusters " << m_AllClusters);
+  ATH_MSG_INFO ("AllTracks " << m_AllTracks);
+  ATH_MSG_INFO ("AllSiTracks " << m_AllSiTracks);
+  ATH_MSG_INFO ("AllTRTTracks " << m_AllTRTTracks);
+  ATH_MSG_INFO ("SelectedTracks " << m_SelectedTracks);
+  ATH_MSG_INFO ("SelectedSiTracks " << m_SelectedSiTracks);
+  ATH_MSG_INFO ("SelectedTRTTracks " << m_SelectedTRTTracks);
+  ATH_MSG_INFO ("Not refitted due to Silicon Requirements " << m_FailedSiliconRequirFit);
+  ATH_MSG_INFO ("Failed Fit Tracks " << m_FailedFitTracks);
+  ATH_MSG_INFO ("RefittedTracks " << m_RefittedTracks);
+
+  return StatusCode::SUCCESS;
+}
+
+StatusCode EMBremCollectionBuilder::contExecute()
+{
+  //======================================================================================================
+  StatusCode sc;
+  
+  //======================================================================================================
+  //Initialize list of track to truth  associations
+  //m_tpTruthMap.clear();
+
+  // Get the primary vertex container from TES
+  const xAOD::VertexContainer* primcontainer(0);
+  bool primVtxExists = evtStore()->contains<xAOD::VertexContainer>(m_vxCandidatesPrimaryName);
+  if (primVtxExists){
+    if (evtStore()->retrieve(primcontainer, m_vxCandidatesPrimaryName).isFailure()){
+      ATH_MSG_DEBUG("xAOD::VertexContainer with key " << m_vxCandidatesPrimaryName << "found!");
+    }
+  }
+  //
+  // Get the Cluster particle truth collection  from TES -/
+  const xAOD::CaloClusterContainer* clusterTES(0);
+  sc = evtStore()->retrieve( clusterTES, m_clusterContainerName);
+  if( sc.isFailure()  ||  !clusterTES ) {
+    ATH_MSG_ERROR(" No Cluster collection with key " << m_clusterContainerName <<" found in TES") ;
+    return StatusCode::FAILURE;
+  }
+  ATH_MSG_DEBUG( "Cluster container successfully retrieved");
+  //
+  // Get the Track particle collection  from TES -/
+  sc=evtStore()->retrieve( m_trackTES, m_trackParticleContainerName );
+  if( sc.isFailure()  ||  !m_trackTES ) {
+    ATH_MSG_ERROR("No AOD TrackParticle container found in TES: StoreGate Key = " <<m_trackParticleContainerName);
+    return StatusCode::FAILURE;
+  }
+  ATH_MSG_DEBUG("TrackParticle container successfully retrieved");
+  
+  // Record the final Track Particle container in StoreGate
+  m_finalTrkPartContainer = new xAOD::TrackParticleContainer();
+  sc = evtStore()->record(m_finalTrkPartContainer, m_OutputTrkPartContainerName);
+  if(sc.isFailure()){
+    ATH_MSG_ERROR("Unable to create new container " << m_OutputTrkPartContainerName);
+    return sc;
+  }
+  
+  xAOD::TrackParticleAuxContainer* aux = new xAOD::TrackParticleAuxContainer();
+  m_finalTrkPartContainer->setStore( aux );
+  CHECK( evtStore()->record( aux, m_OutputTrkPartContainerName + "Aux." ) );  
+
+  
+  //
+  //create container for slimmed tracks
+  m_finalTracks = new TrackCollection(0);
+  sc = evtStore()->record(m_finalTracks, m_OutputTrackContainerName);
+  if(sc.isFailure()){
+    ATH_MSG_ERROR("Unable to create new track container " << m_OutputTrackContainerName);
+    return sc;
+  }
+  //======================================================================================================
+  //Here is the new Logic
+  //Loop over tracks and clusters 
+  m_AllClusters+=clusterTES->size();
+  //
+  xAOD::TrackParticleContainer::const_iterator track_iter;
+  xAOD::CaloClusterContainer::const_iterator clus_iter;  
+  xAOD::TrackParticleContainer::const_iterator track_iter_end=m_trackTES->end();
+  xAOD::CaloClusterContainer::const_iterator clus_iter_end=clusterTES->end();
+
+  ATH_MSG_DEBUG ("Cluster container size: "  << clusterTES->size() );
+  ATH_MSG_DEBUG ("Track   container  size: "  << m_trackTES->size() );
+
+  track_iter = m_trackTES->begin();
+  for(unsigned int trackNumber = 0; track_iter !=  track_iter_end; ++track_iter,++trackNumber){
+    ATH_MSG_DEBUG ("Check Track with Eta "<< (*track_iter)->eta()<< " Phi " << (*track_iter)->phi()<<" Pt " <<(*track_iter)->pt());
+
+    m_AllTracks++;
+    bool isTRT=false;
+    
+    int nclus(0);
+    
+    uint8_t dummy(0); 
+    if( (*track_iter)->summaryValue(dummy,xAOD::numberOfPixelHits) )
+      nclus += dummy;
+    if( (*track_iter)->summaryValue(dummy,xAOD::numberOfSCTHits) )
+      nclus += dummy;
+    
+    if(nclus<4){
+      isTRT = true;
+      m_AllTRTTracks++;
+    } else{
+      isTRT = false;
+      m_AllSiTracks++;
+    }
+
+    //inner loop on clusters
+    clus_iter = clusterTES->begin();
+    for( ;clus_iter !=clus_iter_end;  ++clus_iter){
+
+      if(Select((*clus_iter), isTRT, (*track_iter))){
+        ATH_MSG_DEBUG ("Track Matched");
+        sc = refitTrack(*track_iter);	    
+	
+	if(sc.isFailure()) {
+          ATH_MSG_WARNING("Problem in EMBreCollection Builder Refit");
+        } 
+	else { 	
+	  // Add Auxiliary decorations to the GSFTrack
+	  // Set Element link to original Track Particle	  
+          ElementLink<xAOD::TrackParticleContainer> linkToOriginal(*m_trackTES,trackNumber);
+	  xAOD::TrackParticle* gsfTrack = m_finalTrkPartContainer->back();	  
+	  gsfTrack->auxdata< ElementLink< xAOD::TrackParticleContainer > >( "originalTrackParticle" ) = linkToOriginal;
+	  linkToOriginal.toPersistent();
+		  
+	  if(m_doTruth){
+	    //Add Truth decorations. Copy from the original.
+	    static SG::AuxElement::Accessor<ElementLink<xAOD::TruthParticleContainer> >  tPL ("truthParticleLink");
+	    if(tPL.isAvailable(*(*track_iter))){
+	      ElementLink<xAOD::TruthParticleContainer> linkToTruth= tPL(*(*track_iter));
+	      gsfTrack->auxdata< ElementLink<xAOD::TruthParticleContainer> >("truthParticleLink" ) = linkToTruth;	      
+	      linkToTruth.toPersistent();    
+	      
+	      if(!linkToTruth.isValid()){
+		ATH_MSG_DEBUG("Cannot create Valid Link to Truth Particle for GSFTrackParticle");
+	      }
+	    }
+	 
+	    static SG::AuxElement::Accessor<float >  tMP ("truthMatchProbability");
+	    if(tMP.isAvailable(*(*track_iter))){
+	      float originalProbability = tMP(*(*track_iter));
+	      gsfTrack->auxdata<float>("truthMatchProbability") = originalProbability ;
+	    }
+	    
+	    static SG::AuxElement::Accessor<int> tT("truthType") ;
+	    if(tT.isAvailable(*(*track_iter))){
+	      int truthType = tT(*(*track_iter));
+	      gsfTrack->auxdata<int>("truthType") = truthType ;
+	    }
+	    static SG::AuxElement::Accessor<int> tO("truthOrigin") ;
+	    if(tO.isAvailable(*(*track_iter))){
+	      int truthOrigin = tO(*(*track_iter));
+	      gsfTrack->auxdata<int>("truthOrigin") = truthOrigin ;
+	    } 
+	  }
+	}
+
+        m_SelectedTracks++;
+        if(isTRT) m_SelectedTRTTracks++;
+        else m_SelectedSiTracks++;
+        break;
+      }
+      else{
+        ATH_MSG_DEBUG ("Track did not match cluster--not added to collection");
+      }
+    }//Loop on clusters
+  }//Loop on tracks
+  
+
+  ATH_MSG_DEBUG ("Final Track container size: "  << m_finalTrkPartContainer->size() );
+  // Make readable from INav4mom
+  const INavigable4MomentumCollection* theNav4s(0);
+  sc = evtStore()->symLink(m_finalTrkPartContainer,theNav4s);
+  if (sc.isFailure()){
+    ATH_MSG_WARNING("Could not symLink TrackParticleContainer to INavigable4MomentumCollection");
+  }  
+
+  evtStore()->setConst(m_finalTrkPartContainer).ignore();  
+  evtStore()->setConst(m_finalTracks).ignore();
+  //======================================================================================================
+  return StatusCode::SUCCESS;
+}
+
+// ====================================================================
+StatusCode EMBremCollectionBuilder::refitTrack(const xAOD::TrackParticle* tmpTrkPart){
+
+  int nSiliconHits_trk =0;
+  
+  uint8_t dummy(0); 
+  if( tmpTrkPart->summaryValue(dummy,xAOD::numberOfSCTHits) )
+    nSiliconHits_trk += dummy;
+  if( tmpTrkPart->summaryValue(dummy,xAOD::numberOfPixelHits) )
+    nSiliconHits_trk += dummy;
+  if( tmpTrkPart->summaryValue(dummy,xAOD::numberOfSCTOutliers) )
+    nSiliconHits_trk += dummy;
+  if( tmpTrkPart->summaryValue(dummy,xAOD::numberOfPixelOutliers) )
+    nSiliconHits_trk += dummy;
+
+  ATH_MSG_DEBUG("Number of Silicon hits "<<nSiliconHits_trk);
+  //Get the vertex (may be pileup) and the vertex type that this track particle points to
+
+  const xAOD::Vertex* trkVtx(0);
+  if (tmpTrkPart->vertexLink().isValid()){ 
+    trkVtx = tmpTrkPart->vertex();
+  }
+    
+  //Get the original track that the track particle points to. Clone it in order to assume ownership
+  
+  const Trk::Track* tmpTrk(0);
+  if ( tmpTrkPart->trackLink().isValid() ){
+    tmpTrk =  tmpTrkPart->track();
+  }
+  else
+    {
+      ATH_MSG_ERROR ("TrackParticle has not Track --  are you running on AOD?");
+      return StatusCode::FAILURE;
+    }
+  
+  Trk::Track* trk_refit = 0;
+  //
+  if( nSiliconHits_trk >= m_MinNoSiHits ) {
+    StatusCode status = m_trkRefitTool->refitTrackParticle(tmpTrkPart);
+    if (status == StatusCode::SUCCESS){
+      ATH_MSG_DEBUG("FIT SUCCESS ");
+      m_RefittedTracks++;
+      trk_refit = m_trkRefitTool->refittedTrack(); //this is a Trk::Track
+      m_summaryTool->updateTrack(*trk_refit);   
+    }
+    else{
+      //We end up here due to a failed fit
+      ATH_MSG_DEBUG("FIT FAILED ");
+      m_FailedFitTracks++;
+      trk_refit = new Trk::Track(*tmpTrk);
+    }
+  }
+  else{
+    //We end up here if not enough silicons hits
+    ATH_MSG_DEBUG("NO FIT ATTEMPTED");
+    m_FailedSiliconRequirFit++;
+    trk_refit = new Trk::Track(*tmpTrk);
+  }
+  //Slim the tracks   
+  Trk::Track* slimmed = m_slimTool->slim(*trk_refit);
+  if(!slimmed){
+    ATH_MSG_ERROR ("TrackSlimming failed, this should never happen !");
+    delete trk_refit;
+    return StatusCode::FAILURE;
+  }
+  m_finalTracks->push_back(slimmed);
+
+  // Use the the refitted track and the original vertex to construct a new track particle
+  xAOD::TrackParticle* aParticle = m_particleCreatorTool->createParticle( *trk_refit, m_finalTrkPartContainer, trkVtx, xAOD::electron );
+  delete trk_refit;
+  if(aParticle!=0) { //store in containers
+    ElementLink<TrackCollection> trackLink( slimmed, *m_finalTracks);
+    aParticle->setTrackLink( trackLink );     
+    return StatusCode::SUCCESS;
+  } else {
+    return StatusCode::FAILURE;
+  }
+}
+// =================================================================
+bool EMBremCollectionBuilder::Select(const xAOD::CaloCluster*   cluster,
+                                     bool                       trkTRT,
+                                     const xAOD::TrackParticle* track) const
+{
+
+  ATH_MSG_DEBUG("EMBremCollectionBuilder::Select()" );
+  if (cluster == 0 || track == 0) return false;
+  const Trk::Perigee& candidatePerigee = track->perigeeParameters();
+  //Get Perigee Parameters
+  double  trkPhi = candidatePerigee.parameters()[Trk::phi];
+  double  trkEta = candidatePerigee.eta();
+  double  r_first=candidatePerigee.position().perp();
+  double  z_first=candidatePerigee.position().z();
+  //===========================================================//     
+  //Get Cluster parameters
+  double clusterEta=cluster->etaBE(2);
+  bool isEndCap= cluster->inEndcap();
+  double Et= cluster->e()/cosh(trkEta);
+  if(trkTRT){
+    Et = cluster->et();
+  }
+
+  //===========================================================//     
+  // a few sanity checks
+  if (fabs(clusterEta) > 10.0 || fabs(trkEta) > 10.0 || Et <= 0.0) {
+    ATH_MSG_DEBUG("FAILS sanity checks :  Track Eta : " << trkEta 
+		  << ", Cluster Eta " << clusterEta );
+    return false;
+  }
+
+  //===========================================================//     
+  //Calculate corrrected eta and Phi
+  CandidateMatchHelpers m_matchHelper;
+  double etaclus_corrected = m_matchHelper.CorrectedEta(clusterEta,z_first,isEndCap);
+  double phiRot = m_matchHelper.PhiROT(Et,trkEta, track->charge(),r_first ,isEndCap)  ;
+  double phiRotTrack = m_matchHelper.PhiROT(track->pt(),trkEta, track->charge(),r_first ,isEndCap);
+  //===========================================================//     
+  //Calcualate deltaPhis 
+  double deltaPhiStd = m_phiHelper.diff(cluster->phiBE(2), trkPhi);
+  double trkPhiCorr = m_phiHelper.diff(trkPhi, phiRot);
+  double deltaPhi2 = m_phiHelper.diff(cluster->phiBE(2), trkPhiCorr);
+  double trkPhiCorrTrack = m_phiHelper.diff(trkPhi, phiRotTrack);
+  double deltaPhi2Track = m_phiHelper.diff(cluster->phiBE(2), trkPhiCorrTrack);
+  //===========================================================//     
+  if ((!trkTRT)&& fabs(cluster->etaBE(2) - trkEta) > 2*m_broadDeltaEta && fabs( etaclus_corrected- trkEta) > 2.*m_broadDeltaEta){
+    ATH_MSG_DEBUG("FAILS broad window eta match (track eta, cluster eta, cluster eta corrected): ( " << trkEta << ", " << cluster->etaBE(2) <<", "<<etaclus_corrected<<")" );
+    return false;
+  }
+  //if it does not fail the eta cut, does it fail the phi?
+  else if ( (fabs(deltaPhi2) > 2*m_broadDeltaPhi) && (fabs(deltaPhi2Track) > 2.*m_broadDeltaPhi) && (fabs(deltaPhiStd) > 2*m_broadDeltaPhi)){
+    ATH_MSG_DEBUG("FAILS broad window phi match (track phi, phirotCluster , phiRotTrack ,cluster phi): ( " << trkPhi << ", " << phiRot<< ", "<<phiRotTrack<< ", " << cluster->phiBE(2) << ")" );
+    return false;
+  }
+
+  //Extrapolate from Perigee
+  IEMExtrapolationTools::TrkExtrapDef extrapFrom = IEMExtrapolationTools::fromPerigee;
+  std::vector<bool>    doSample(4, false);
+  doSample[2] = true; // Only extrapolate to second sampling
+  std::vector<double>  eta(4, -999.0);
+  std::vector<double>  phi(4, -999.0);
+  std::vector<double>  deltaEta(4, -999.0);
+  std::vector<double>  deltaPhi(4, -999.0);
+  if (m_extrapolationTool->getMatchAtCalo (cluster, 
+					   track, 
+					   Trk::alongMomentum, 
+					   doSample, 
+					   eta,
+					   phi,
+					   deltaEta, 
+					   deltaPhi, 
+					   extrapFrom).isFailure()) return false;  
+  // Selection in narrow eta/phi window
+  if(( trkTRT || fabs(deltaEta[2]) < m_narrowDeltaEta ) && 
+     deltaPhi[2] < m_narrowDeltaPhi && 
+     deltaPhi[2] > -m_narrowDeltaPhiBrem) {
+    ATH_MSG_DEBUG("Standard Match success " << deltaPhi[2] );
+    return true;
+  }
+  else if(!trkTRT && fabs(deltaEta[2]) < m_narrowDeltaEta ){ 
+    ATH_MSG_DEBUG("Normal matched Failed deltaPhi/deltaEta " << deltaPhi[2] <<" / "<< deltaEta[2]<<", Trying Rescale" );
+    //Extrapolate from Perigee Rescaled 
+    IEMExtrapolationTools::TrkExtrapDef extrapFrom1 = IEMExtrapolationTools::fromPerigeeRescaled;
+    std::vector<double>  eta1(4, -999.0);
+    std::vector<double>  phi1(4, -999.0);
+    std::vector<double>  deltaEta1(4, -999.0);
+    std::vector<double>  deltaPhi1(5, -999.0); // Set size to 5 to store deltaPhiRot
+    if (m_extrapolationTool->getMatchAtCalo (cluster, 
+                                             track, 
+                                             Trk::alongMomentum, 
+                                             doSample, 
+                                             eta1,
+                                             phi1,
+                                             deltaEta1, 
+                                             deltaPhi1, 
+                                             extrapFrom1).isFailure()) return false;
+    if( fabs(deltaEta1[2]) < m_narrowDeltaEta 
+        && deltaPhi1[2] < m_narrowRescale
+        && deltaPhi1[2] > -m_narrowRescaleBrem) {
+      ATH_MSG_DEBUG("Rescale Match success " << deltaPhi1[2] );
+      return true;
+    }
+    else {
+      ATH_MSG_DEBUG("Rescaled matched Failed deltaPhi/deltaEta " << deltaPhi1[2] <<" / "<< deltaEta1[2] );
+      return false;
+    }
+  }
+  else{
+    ATH_MSG_DEBUG("Normal matched Failed deltaPhi/deltaEta " << deltaPhi[2] <<" / "<< deltaEta[2]<<", No Rescale attempted isTRT, "<< trkTRT);
+    return false;
+  }
+  //Default
+  ATH_MSG_DEBUG("Default True");
+  return true;  
+}
+
+
diff --git a/Reconstruction/egamma/egammaTools/src/EMBremCollectionBuilder.h b/Reconstruction/egamma/egammaTools/src/EMBremCollectionBuilder.h
new file mode 100644
index 0000000000000..2e4537dbde8bc
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/EMBremCollectionBuilder.h
@@ -0,0 +1,117 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef EMBREMCOLLECTIONBUILDER_H
+#define EMBREMCOLLECTIONBUILDER_H
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "egammaInterfaces/IEMBremCollectionBuilder.h"
+#include "TrkTrack/TrackCollection.h"
+#include "CaloGeoHelpers/CaloPhiRange.h"
+
+class IegammaTrkRefitterTool;
+class IegammaCheckEnergyDepositTool;
+class IEMExtrapolationTools;
+
+
+#include "xAODTracking/Vertex.h"
+#include "xAODTracking/TrackParticle.h"
+
+#include "xAODTracking/VertexContainer.h"
+#include "xAODTracking/TrackParticleContainer.h"
+
+#include "xAODCaloEvent/CaloCluster.h"
+#include "xAODCaloEvent/CaloClusterContainer.h"
+
+
+namespace Trk
+{
+  class ITrackParticleCreatorTool;
+  class ITrackSlimmingTool;
+  class ITrackSummaryTool;
+}
+
+class CaloCluster;
+
+class EMBremCollectionBuilder : public AthAlgTool,virtual public IEMBremCollectionBuilder{
+    public:
+        EMBremCollectionBuilder(const std::string& type, const std::string& name, const IInterface* parent);
+        ~EMBremCollectionBuilder();
+
+        virtual StatusCode initialize();
+        virtual StatusCode finalize();
+        virtual StatusCode contExecute();
+    private:
+	//------------------------------------------------------------------------
+	//      methods
+	//------------------------------------------------------------------------
+	//
+        /** @brief Refit of track */
+	StatusCode refitTrack(const xAOD::TrackParticle* tmpTrkPart);
+        /** @brief broad track selection */
+	bool Select(const xAOD::CaloCluster*        cluster,
+              bool                      trkTRT,
+              const xAOD::TrackParticle* track) const;
+	//------------------------------------------------------------------------
+	//      configurable data members
+	//------------------------------------------------------------------------       
+	/** @brief The track refitter */
+	ToolHandle<IegammaTrkRefitterTool>  m_trkRefitTool;
+	/** @brief Tool to create track particle */
+	ToolHandle< Trk::ITrackParticleCreatorTool > m_particleCreatorTool;
+	/** @brief Tool to slim tracks  */
+	ToolHandle<Trk::ITrackSlimmingTool>     m_slimTool;
+	/** @brief Tool for Track summary  */
+	ToolHandle<Trk::ITrackSummaryTool>     m_summaryTool;
+	/** @brief Tool for extrapolation */
+	ToolHandle<IEMExtrapolationTools> m_extrapolationTool;
+
+	/** @brier Option to do truth*/
+	bool                              m_doTruth;
+	/** @brief Names of input output collections */
+	std::string                       m_clusterContainerName;
+	std::string                       m_trackParticleContainerName;
+	std::string                       m_trackParticleTruthCollectionName;
+	std::string                       m_OutputTrkPartContainerName;	
+	std::string                       m_OutputTrackContainerName;	
+	std::string                       m_vxCandidatesPrimaryName;
+	std::string                       m_trackAssocName;
+
+	/** @Cut on minimum silicon hits*/
+	int                               m_MinNoSiHits;
+	/** @brief broad cut on deltaEta*/
+	double                m_broadDeltaEta;
+	/** @brief broad cut on deltaPhi*/
+	double                m_broadDeltaPhi;
+	/** @narrow windows*/
+	double                m_narrowDeltaEta;
+	double                m_narrowDeltaPhi;
+	double                m_narrowDeltaPhiBrem;
+	double                m_narrowRescale;
+	double                m_narrowRescaleBrem;
+	/** @brief helper for */
+	CaloPhiRange          m_phiHelper;
+	//collections
+	const xAOD::TrackParticleContainer*  m_trackTES;
+//	const TrackParticleTruthCollection* m_trackTruthTES;
+	TrackCollection*                    m_finalTracks;
+	xAOD::TrackParticleContainer*        m_finalTrkPartContainer;
+//	std::list<std::pair<TrackParticleTruth, Rec::TrackParticle*> > m_tpTruthMap;
+	//counters
+	unsigned int m_AllClusters;
+	unsigned int m_AllTracks;
+	unsigned int m_AllTRTTracks;
+	unsigned int m_AllSiTracks;
+	unsigned int m_SelectedTracks;
+	unsigned int m_SelectedTRTTracks;
+	unsigned int m_SelectedSiTracks;
+	unsigned int m_FailedFitTracks;
+	unsigned int m_FailedSiliconRequirFit;
+	unsigned int m_RefittedTracks;
+
+//------------------------------------------------------------------------
+
+};
+#endif // ANA1_H
diff --git a/Reconstruction/egamma/egammaTools/src/EMClusterTool.cxx b/Reconstruction/egamma/egammaTools/src/EMClusterTool.cxx
new file mode 100644
index 0000000000000..cab07620347a4
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/EMClusterTool.cxx
@@ -0,0 +1,238 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+#include "EMClusterTool.h"
+
+#include "egammaInterfaces/IegammaSwTool.h"
+#include "xAODEgamma/EgammaxAODHelpers.h"
+#include "xAODCaloEvent/CaloCluster.h"
+#include "StoreGate/StoreGateSvc.h"
+
+#include "xAODEgamma/ElectronContainer.h"
+#include "xAODEgamma/PhotonContainer.h"
+
+#include "CaloUtils/CaloClusterStoreHelper.h"
+#include "CaloUtils/CaloCellDetPos.h"
+
+// =============================================================
+EMClusterTool::EMClusterTool(const std::string& type, const std::string& name, const IInterface* parent) :
+  egammaBaseTool(type, name, parent),
+  m_storeGate(0),
+  m_caloCellDetPos(0)
+{
+  declareProperty("ClusterCorrectionToolName", m_ClusterCorrectionToolName = "egammaSwTool/egammaswtool");
+  declareProperty("OutputClusterContainerName", m_outputClusterContainerName, 
+    "Name of the output cluster container");
+  declareProperty("ElectronContainerName", m_electronContainerName, 
+    "Name of the input electron container");
+  declareProperty("PhotonContainerName", m_photonContainerName, 
+    "Name of the input photon container");
+  declareProperty("DoPositionInCalo", m_doPositionInCalo = true, 
+    "Decorate clusters with positions in calo frame");
+
+  declareInterface<IEMClusterTool>(this);
+  
+  m_caloCellDetPos = new CaloCellDetPos();
+}
+
+EMClusterTool::~EMClusterTool() { delete m_caloCellDetPos; }
+
+// const InterfaceID& ClusterTool::interfaceID() {
+//   return IID_IClusterTool;
+// }
+
+// =============================================================
+StatusCode EMClusterTool::initialize() {
+
+  ATH_MSG_DEBUG("Initializing " << name() << "...");
+
+  if (service("StoreGateSvc", m_storeGate).isFailure()) 
+  {
+    ATH_MSG_ERROR("Unable to retrieve pointer to StoreGateSvc");
+    return StatusCode::FAILURE;
+  }
+  
+  // Get the cluster correction tool
+  m_clusterCorrectionTool = ToolHandle<IegammaSwTool>(m_ClusterCorrectionToolName);
+  if(m_clusterCorrectionTool.retrieve().isFailure()) {
+    ATH_MSG_ERROR("Failed to retrieve " << m_clusterCorrectionTool);
+    return StatusCode::SUCCESS;
+  } 
+  else {
+    ATH_MSG_DEBUG("Retrieved tool " << m_clusterCorrectionTool);   
+  }
+
+  ATH_MSG_DEBUG("Initialization successful");
+
+  return StatusCode::SUCCESS;
+}
+
+// =========================================================================
+StatusCode EMClusterTool::finalize() {
+  return StatusCode::SUCCESS;
+}
+
+// =========================================================================
+StatusCode EMClusterTool::contExecute() 
+{
+  // Create output cluster container and register in StoreGate
+  xAOD::CaloClusterContainer* outputClusterContainer = \
+    CaloClusterStoreHelper::makeContainer(m_storeGate, 
+                                          m_outputClusterContainerName, 
+                                          msg());
+  if (!outputClusterContainer){
+    ATH_MSG_ERROR("Failed to record Output Cluster Container " 
+		  << m_outputClusterContainerName);
+    return StatusCode::FAILURE;
+  }
+  
+  // Retrieve electron and photon containers
+  xAOD::ElectronContainer *electronContainer;
+  if (m_storeGate->retrieve(electronContainer, m_electronContainerName).isFailure())
+  {
+    ATH_MSG_ERROR("Cannot retrieve electron container " << m_electronContainerName);
+    return StatusCode::FAILURE;
+  }
+  
+  xAOD::PhotonContainer *photonContainer;
+  if (m_storeGate->retrieve(photonContainer, m_photonContainerName).isFailure())
+  {
+    ATH_MSG_ERROR("Cannot retrieve photon container " << m_photonContainerName);
+    return StatusCode::FAILURE;
+  }
+    
+  // Loop over electrons and create new clusters
+  xAOD::EgammaParameters::EgammaType egType = xAOD::EgammaParameters::electron;
+  for (auto electron : *electronContainer)
+    setNewCluster(electron, outputClusterContainer, egType);
+  
+  // Loop over photons and create new clusters
+  for (auto photon : *photonContainer)
+  {
+     egType = (xAOD::EgammaHelpers::isConvertedPhoton(photon) ? 
+               xAOD::EgammaParameters::convertedPhoton :
+               xAOD::EgammaParameters::unconvertedPhoton);
+
+    setNewCluster(photon, outputClusterContainer, egType);
+  }    
+  
+  if (CaloClusterStoreHelper::finalizeClusters(m_storeGate, 
+                                               outputClusterContainer,
+					       m_outputClusterContainerName,
+					       msg()).isFailure() )
+  {
+    ATH_MSG_ERROR("Failed to finalize Output Cluster Container " <<
+      m_outputClusterContainerName);
+    return StatusCode::FAILURE;
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+// ==========================================================================
+void EMClusterTool::setNewCluster(xAOD::Egamma *eg,
+                                  xAOD::CaloClusterContainer *outputClusterContainer,
+                                  xAOD::EgammaParameters::EgammaType egType)
+{
+  if (!eg) return;
+  
+  if (!eg->caloCluster())
+  {
+    ATH_MSG_DEBUG("egamma object does not have a cluster associated");
+    return;
+  }
+  typedef ElementLink<xAOD::CaloClusterContainer> ClusterLink_t;
+  
+  xAOD::CaloCluster* cluster =0;
+  if(eg->author(xAOD::EgammaParameters::AuthorCaloTopo35)) {
+    cluster = new xAOD::CaloCluster(*(eg->caloCluster()));
+  }
+  else {
+    cluster = makeNewCluster(*(eg->caloCluster()), egType);
+  }
+    outputClusterContainer->push_back(cluster);
+
+  // Set the link to the new cluster
+  ClusterLink_t clusterLink(cluster, *outputClusterContainer);
+  const std::vector<ClusterLink_t> clusterLinks{clusterLink};
+  eg->setCaloClusterLinks( clusterLinks );
+  
+}
+
+// ==========================================================================
+xAOD::CaloCluster* EMClusterTool::makeNewCluster(const xAOD::CaloCluster& cluster, xAOD::EgammaParameters::EgammaType egType)
+{
+  //
+  // Create new cluster based on an existing one
+  // const CaloCluster* cluster : input cluster
+  //
+  
+  // protection against cluster not in barrel nor endcap
+  if (!cluster.inBarrel() && !cluster.inEndcap() )
+  {
+    ATH_MSG_ERROR("Cluster neither in barrel nor in endcap, Skipping cluster");
+	  return 0;
+  }
+  
+  if ((int) egType < 0 || egType >= xAOD::EgammaParameters::NumberOfEgammaTypes)
+  {
+    ATH_MSG_WARNING("Invalid egamma type");
+    return 0;
+  }
+
+  bool isBarrel = xAOD::EgammaHelpers::isBarrel(&cluster);  
+  xAOD::CaloCluster::ClusterSize cluSize=xAOD::CaloCluster:: CSize_Unknown;
+  if (egType == xAOD::EgammaParameters::electron){
+    cluSize= (isBarrel ? xAOD::CaloCluster::SW_37ele : xAOD::CaloCluster::SW_55ele);
+  }
+  else if (egType == xAOD::EgammaParameters::convertedPhoton){
+    cluSize= (isBarrel ? xAOD::CaloCluster::SW_37Econv : xAOD::CaloCluster::SW_55Econv);
+  }
+  else  {//(egType == xAOD::EgammaParameters::unconvertedPhoton)
+    cluSize = (isBarrel ? xAOD::CaloCluster::SW_35gam : xAOD::CaloCluster::SW_55gam);
+  }
+
+  xAOD::CaloCluster* newClus = CaloClusterStoreHelper::makeCluster(cluster.getCellLinks()->getCellContainer(),
+								   cluster.eta0(),cluster.phi0(),
+								   cluSize);
+
+  //FIXME/WARNING: The CaloFillRectangularClusterTool does NOT set the overall eta/phi of the cluster
+  //For regular SW clusters, this is done by CaloClusterUpdate after all corrections are applied 
+  //To maintain the previous behavior, I set the eta/phi of the origial cluster
+  newClus->setEta(cluster.eta());
+  newClus->setPhi(cluster.phi());
+  
+  if (m_clusterCorrectionTool->execute(newClus).isFailure())
+    ATH_MSG_ERROR("Problem executing cluster correction tool");
+  
+  if (newClus) fillPositionsInCalo(*newClus);
+  return newClus;
+}
+
+// ==========================================================================
+void EMClusterTool::fillPositionsInCalo(xAOD::CaloCluster& cluster)
+{
+  bool isBarrel = xAOD::EgammaHelpers::isBarrel(&cluster);
+  CaloCell_ID::CaloSample sample = isBarrel ? CaloCell_ID::EMB2 : CaloCell_ID::EME2;
+  
+  // eta and phi of the cluster in the calorimeter frame
+  double eta, phi;
+  m_caloCellDetPos->getDetPosition(sample, cluster.eta(), cluster.phi0(), eta, phi);  
+  
+  cluster.auxdata<float>("etaCalo") = eta;
+  cluster.auxdata<float>("phiCalo") = phi;
+  
+  //  eta in the second sampling
+  m_caloCellDetPos->getDetPosition(sample, cluster.etaBE(2), cluster.phiBE(2), 
+    eta, phi);
+  cluster.auxdata<float>("etas2Calo") = eta;
+
+  //  eta in the first sampling  
+  sample = isBarrel ? CaloCell_ID::EMB1 : CaloCell_ID::EME1;
+  m_caloCellDetPos->getDetPosition(sample, cluster.etaBE(1), cluster.phiBE(1), 
+    eta, phi);
+  cluster.auxdata<float>("etas1Calo") = eta;
+
+}
diff --git a/Reconstruction/egamma/egammaTools/src/EMClusterTool.h b/Reconstruction/egamma/egammaTools/src/EMClusterTool.h
new file mode 100644
index 0000000000000..ac09ae80533fd
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/EMClusterTool.h
@@ -0,0 +1,98 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef EGAMMATOOLS_EMCLUSTERTOOL_H
+#define EGAMMATOOLs_EMCLUSTERTOOL_H
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/ToolHandle.h"
+
+#include "egammaInterfaces/IEMClusterTool.h"
+#include "egammaBaseTool.h"
+
+#include "xAODCaloEvent/CaloClusterFwd.h"
+#include "xAODCaloEvent/CaloClusterContainer.h"
+#include "xAODEgamma/EgammaEnums.h"
+
+class IegammaSwTool;
+class StoreGateSvc;
+class CaloCellDetPos;
+
+/**
+   @class EMClusterTool
+   This tool makes the EM CaloCluster used by egamma objects.
+   It also defines the cluster size 
+       - in barrel
+         3*7 for electrons
+         3*7 for converted photons with Rconv<800mm
+         3*5 for converted photons with Rconv>800mm
+         3*5 for unconverted photons 
+       - in end-caps
+         5*5 for electrons
+         5*5 for converted photons with Rconv<800mm
+         5*5 for converted photons with Rconv>800mm
+         5*5 for unconverted photons 
+    and applies the right cluster corrections depending on classification as electron, unconverted photon or converted photon
+    
+   @author Thomas Koffas
+   @author F. Derue
+   @author B. Lenzi
+   @author C. Anastopoulos
+*/
+
+class EMClusterTool : public egammaBaseTool, virtual public IEMClusterTool {
+
+ public:
+
+  /** @bried constructor */
+  EMClusterTool (const std::string& type,const std::string& name, const IInterface* parent);
+
+  /** @brief destructor */
+  virtual ~EMClusterTool();
+
+  /** @brief initialize method */
+  virtual StatusCode initialize();
+  /** @brief execute on container */
+  virtual StatusCode contExecute();
+  /** @brief finalize method */
+  virtual StatusCode finalize();
+  
+  /** @brief Set new cluster to the egamma object, decorate the new cluster
+    * with a link to the old one **/
+  void setNewCluster(xAOD::Egamma *eg,
+                     xAOD::CaloClusterContainer *outputClusterContainer,
+                     xAOD::EgammaParameters::EgammaType egType);
+
+  
+  /** @brief creation of new cluster based on existing one **/
+  virtual xAOD::CaloCluster* makeNewCluster(const xAOD::CaloCluster&, xAOD::EgammaParameters::EgammaType);
+
+  /** @brief Decorate cluster with positions in the calorimeter frame **/
+  void fillPositionsInCalo(xAOD::CaloCluster& cluster);
+
+ private:
+  /** @brief Name of the output cluster container **/
+  std::string m_outputClusterContainerName;
+  
+  /** @brief Name of the input electron container **/
+  std::string m_electronContainerName;
+
+  /** @brief Name of the input photon container **/
+  std::string m_photonContainerName;  
+ 
+  /** @brief Tool to handle cluster corrections */
+  ToolHandle<IegammaSwTool>   m_clusterCorrectionTool;
+  
+  /** @brief Name of tool for cluster corrections */
+  std::string            m_ClusterCorrectionToolName;
+  
+  /** @brief Decorate clusters with positions in calo frame? **/
+  bool m_doPositionInCalo;
+  
+  StoreGateSvc*   m_storeGate;
+  
+  CaloCellDetPos *m_caloCellDetPos;
+};
+
+#endif // EGAMMATOOLS_EMCLUSTERTOOL_H 
diff --git a/Reconstruction/egamma/egammaTools/src/EMConversionBuilder.cxx b/Reconstruction/egamma/egammaTools/src/EMConversionBuilder.cxx
new file mode 100644
index 0000000000000..d5fb4f16bde21
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/EMConversionBuilder.cxx
@@ -0,0 +1,241 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/********************************************************************
+
+NAME:     EMConversionBuilder.cxx
+PACKAGE:  offline/Reconstruction/egamma/egammaRec
+
+AUTHORS:  D. Zerwas, B. Lenzi
+CREATED:  Jul, 2005
+CHANGES:  Mar, 2014 (BL) xAOD migration
+
+PURPOSE:  subAlgorithm which creates an EMConversion object. 
+
+********************************************************************/
+
+// INCLUDE HEADER FILES:
+
+#include "EMConversionBuilder.h"
+#include "ConvVxSorter.h"
+#include "egammaInterfaces/IEMExtrapolationTools.h"
+#include "xAODTracking/VertexContainer.h"
+#include "egammaRecEvent/egammaRecContainer.h"
+#include "egammaRecEvent/egammaRec.h"
+
+//  END OF HEADER FILES INCLUDE
+
+/////////////////////////////////////////////////////////////////
+
+using CLHEP::GeV;
+
+EMConversionBuilder::EMConversionBuilder(const std::string& type,
+					 const std::string& name,
+					 const IInterface* parent)
+  : egammaBaseTool(type, name, parent),
+    m_extrapolationTool("EMExtrapolationTools")
+{
+  
+  // declare interface
+  declareInterface<IEMConversionBuilder>(this);
+  
+  // Name of the input conversion container
+  declareProperty("ConversionContainerName",                 
+		  m_conversionContainerName="PhotonConversionVertices",
+		  "Name of the input conversion container");
+	
+  // Name of the input egammaRec container
+  declareProperty("egammaRecContainerName",                 
+		  m_egammaRecContainerName="egammaRecs",
+		  "Name of the input egammaRec container");
+
+  // Name of the extrapolation tool
+  declareProperty("ExtrapolationTool",
+		  m_extrapolationTool,
+		  "Handle of the extrapolation tool");
+      
+  declareProperty("RejectAllTRTConversions", m_rejectAllTRT = false,
+		  "Ignore all conversion vertices containing exclusively TRT-only tracks");
+    
+  declareProperty("MinTRTHits", m_minTRTHits = 0,
+		  "minimum number of TRT hits for TRT-only tracks (both single and double track conversion vertices)");
+  
+  declareProperty("MinSiSingleTrackPt", m_minSiSingleTrackPt = 0*GeV,
+		  "minimum pT for Si tracks to be considered single-track conversion vertices");
+  
+  declareProperty("MinTRTOnlySingleTrackPt", m_minTRTonlySingleTrackPt = 2*GeV,
+		  "minimum pT for TRT-only tracks to be considered single-track conversion vertices");
+  
+  declareProperty("MinTRTOnlyTrackPt", m_minTRTonlyTrackPt = 0*GeV,
+		  "minimum pT for each track in TRT-only double-track conversion vertices");
+        
+  declareProperty("MinSumPt", m_minSumPt = 0*GeV,
+		  "minimum sum pT for double track conversion vertices");
+}
+
+// =================================================================
+// DESTRUCTOR:
+EMConversionBuilder::~EMConversionBuilder()
+{  
+}
+
+// ==================================================================
+// INITIALIZE METHOD:  
+StatusCode EMConversionBuilder::initialize()
+{
+
+  ATH_MSG_DEBUG("Initializing EMConversionBuilder");
+
+  // the extrapolation tool
+  if(m_extrapolationTool.retrieve().isFailure()){
+    ATH_MSG_ERROR("Cannot retrieve extrapolationTool " << m_extrapolationTool);
+    return StatusCode::FAILURE;
+  } else {
+    ATH_MSG_DEBUG("Retrieved extrapolationTool " << m_extrapolationTool);
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+// =============================================================
+StatusCode EMConversionBuilder::contExecute() 
+{
+
+  // retrieve Conversion Container
+  const xAOD::VertexContainer* conversions = 0;
+  if (evtStore()->contains<xAOD::VertexContainer>(m_conversionContainerName)) {
+    StatusCode sc = evtStore()->retrieve(conversions,m_conversionContainerName);
+    if(sc.isFailure()) {
+      ATH_MSG_WARNING("Could not retrieve Conversion container! EMConversionBuilder will stop.");
+      return StatusCode::SUCCESS;
+    }
+  } else {
+    ATH_MSG_DEBUG("Could not find conversion container! Acting as if there are 0 conversions."); 
+  }
+  
+  // retrieve egammaRec container
+  const EgammaRecContainer* egammaRecs = 0;
+  if (evtStore()->contains<EgammaRecContainer>(m_egammaRecContainerName)) {
+    StatusCode sc = evtStore()->retrieve(egammaRecs,m_egammaRecContainerName);
+    if(sc.isFailure()) {
+      ATH_MSG_WARNING("Could not retrieve egammaRec container! EMConversionBuilder will stop.");
+      return StatusCode::SUCCESS;
+    }
+  } else {
+    ATH_MSG_DEBUG("Could not find conversion container! Acting as if there are 0 egammaRecs."); 
+  }
+  
+  
+  // Extrapolate each vertex (keeping etatCalo, phiAtCalo)
+  // and try to match to each cluster
+  
+  // xAOD::Vertex does not have method isAvailable for the moment
+  // create a lambda function
+  auto isAvailable = [](const xAOD::Vertex& vertex, std::string name) { 
+    SG::AuxElement::Accessor<float> acc(name, "");
+    return acc.isAvailable(vertex); } ; 
+
+  float etaAtCalo, phiAtCalo;
+  for (unsigned int iVtx = 0; iVtx < conversions->size(); ++iVtx)
+  {
+    const xAOD::Vertex *vertex = conversions->at(iVtx);
+    
+    // Check if vertex was already decorated with etaAtCalo, phiAtCalo  
+    if (isAvailable(*vertex, "etaAtCalo") &&
+        isAvailable(*vertex, "phiAtCalo") )
+    {
+      etaAtCalo = vertex->auxdata<float>("etaAtCalo");
+      phiAtCalo = vertex->auxdata<float>("phiAtCalo");
+    }
+    // check extrapolation, skip vertex in case of failure
+    else if (!m_extrapolationTool->getEtaPhiAtCalo(vertex, &etaAtCalo, &phiAtCalo))
+      continue;
+    
+    for (auto& egRec : *egammaRecs)
+    {
+      const xAOD::CaloCluster *cluster = egRec->caloCluster();
+      if (!m_extrapolationTool->matchesAtCalo(cluster, vertex, etaAtCalo, phiAtCalo))
+        continue;
+      const ElementLink< xAOD::VertexContainer > vertexLink( *conversions, iVtx );
+      
+      // If this is the best (or the first) vertex, push front and keep deltaEta, deltaPhi
+      if (!egRec->getNumberOfVertices() || ConvVxSorter()(*vertex, *egRec->vertex()))
+      {
+        egRec->pushFrontVertex( vertexLink );
+        egRec->setDeltaEtaVtx( cluster->etaBE(2) - etaAtCalo );
+        egRec->setDeltaPhiVtx( m_phiHelper.diff(cluster->phiBE(2), phiAtCalo) );
+      }
+      else // Not the best vertex, push back
+        egRec->pushBackVertex( vertexLink );       
+    }
+    
+  }
+  
+  return StatusCode::SUCCESS;
+}
+
+// =============================================================
+StatusCode EMConversionBuilder::hltExecute(egammaRec* egRec, const xAOD::VertexContainer* conversions)
+{
+
+  if (!egRec || !conversions)
+  {
+    ATH_MSG_WARNING("trackExecute: NULL pointer to egammaRec or VertexContainer");
+    return StatusCode::SUCCESS;
+  }
+  
+  
+  // Extrapolate each vertex (keeping etatCalo, phiAtCalo)
+  // and try to match to each cluster
+  
+  // xAOD::Vertex does not have method isAvailable for the moment
+  // create a lambda function
+  auto isAvailable = [](const xAOD::Vertex& vertex, std::string name) { 
+    SG::AuxElement::Accessor<float> acc(name, "");
+    return acc.isAvailable(vertex); } ; 
+
+  float etaAtCalo, phiAtCalo;
+  for (unsigned int iVtx = 0; iVtx < conversions->size(); ++iVtx)
+  {
+    const xAOD::Vertex *vertex = conversions->at(iVtx);
+    
+    // Check if vertex was already decorated with etaAtCalo, phiAtCalo  
+    if (isAvailable(*vertex, "etaAtCalo") &&
+        isAvailable(*vertex, "phiAtCalo") )
+    {
+      etaAtCalo = vertex->auxdata<float>("etaAtCalo");
+      phiAtCalo = vertex->auxdata<float>("phiAtCalo");
+    }
+    // check extrapolation, skip vertex in case of failure
+    else if (!m_extrapolationTool->getEtaPhiAtCalo(vertex, &etaAtCalo, &phiAtCalo))
+      continue;
+    
+    const xAOD::CaloCluster *cluster = egRec->caloCluster();
+    if (!m_extrapolationTool->matchesAtCalo(cluster, vertex, etaAtCalo, phiAtCalo))
+      continue;
+    const ElementLink< xAOD::VertexContainer > vertexLink( *conversions, iVtx );
+    
+    // If this is the best (or the first) vertex, push front and keep deltaEta, deltaPhi
+    if (!egRec->getNumberOfVertices() || ConvVxSorter()(*vertex, *egRec->vertex()))
+      {
+        egRec->pushFrontVertex( vertexLink );
+        egRec->setDeltaEtaVtx( cluster->etaBE(2) - etaAtCalo );
+        egRec->setDeltaPhiVtx( m_phiHelper.diff(cluster->phiBE(2), phiAtCalo) );
+      }
+    else // Not the best vertex, push back
+      egRec->pushBackVertex( vertexLink );       
+  }
+  
+  return StatusCode::SUCCESS;
+}
+
+
+// ==================================================================
+// FINALIZE METHOD:  
+StatusCode EMConversionBuilder::finalize()
+{
+
+  return StatusCode::SUCCESS;
+
+}
diff --git a/Reconstruction/egamma/egammaTools/src/EMConversionBuilder.h b/Reconstruction/egamma/egammaTools/src/EMConversionBuilder.h
new file mode 100644
index 0000000000000..5ef4ac935a3c2
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/EMConversionBuilder.h
@@ -0,0 +1,101 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef EGAMMATOOLS_EMCONVERSIONBUILDER_H
+#define EGAMMATOOLS_EMCONVERSIONBUILDER_H
+/**
+  @class EMConversionBuilder
+          EMConversion data object builder. This is an Algorithm class.
+	  Selects conversion vertices reconstructed by the ID software
+	  after matching them to an EM calorimeter cluster.
+	  For normal two-track conversions the original photon track parameters
+	  at the conversion vertex are reconstructed. It is then extrapolated
+	  to the calorimeter and checked whether it matches the cluster.
+	  For single-track conversions, the reconstructed electron track is
+	  extrapolated to the calorimeter.
+	  A TrackToCalo extrapolation tool that can handle both neutral and charged
+	  track parameters (using a Trk::ParametersBase interface) is used throughout.
+	  The extrapolation starts at the last track measurement.
+	  Matching is done in both eta and phi. The eta matching WAS disabled for TRT-only
+	  tracks due to lack of accurate eta prediction BEFORE 12/2011.
+  @author D. Zerwas
+
+  changes: June 16, 2010 (JM) bring some stuff from PhotonRecoveryTool here
+           Mar, 2014 (BL) xAOD migration and new logic
+*/
+
+// INCLUDE HEADER FILES: 
+#include "GaudiKernel/ToolHandle.h"
+#include "egammaBaseTool.h"
+#include "egammaInterfaces/IEMConversionBuilder.h"
+#include "CaloGeoHelpers/CaloPhiRange.h"
+#include "xAODTracking/VertexContainer.h"
+
+class IEMExtrapolationTools;
+
+class EMConversionBuilder : public egammaBaseTool, virtual public IEMConversionBuilder
+{
+
+ public:
+
+  /** @brief Default constructor*/
+  EMConversionBuilder(const std::string& type,
+                      const std::string& name,
+                      const IInterface* parent);
+
+  /** @brief Destructor*/
+  ~EMConversionBuilder();
+	
+  /** @brief initialize method*/
+  StatusCode initialize();
+  /** @brief execute method*/
+  virtual StatusCode contExecute();
+  /** @brief execute method*/
+  virtual StatusCode hltExecute(egammaRec* egRec, const xAOD::VertexContainer* conversions);
+  /** @brief finalize method*/
+  StatusCode finalize();
+
+private:
+  
+  // configuration:
+  /** @brief Name of conversion container*/
+  std::string		m_conversionContainerName; 
+
+  /** @brief Name of egammaRec container*/
+  std::string		m_egammaRecContainerName; 
+
+  /** @brief Helper used to compute angle differences in phi. Corrects within the +/- pi range.*/
+  CaloPhiRange          m_phiHelper; 
+
+  /** @brief EMExtrapolationTools */
+  ToolHandle<IEMExtrapolationTools>  m_extrapolationTool;
+  
+ /** @brief Ignore all conversion vertices that contain exclusively TRT-only tracks */
+ bool m_rejectAllTRT;
+ /** @brief minimum number of TRT hits for TRT-only tracks (both single and double track conversion vertices) */
+ int m_minTRTHits;
+ /** @brief minimum pT for Si tracks to be considered single-track conversion vertices */
+ double m_minSiSingleTrackPt;
+ /** @brief minimum pT for TRT-only tracks considered to be single-track conversion vertices */
+ double m_minTRTonlySingleTrackPt;
+ /** @brief minimum pT for each tracks in TRT-only double-track conversion vertices */  
+ double m_minTRTonlyTrackPt;
+ /** @brief minimum sum pT for double track conversion vertices */
+ double m_minSumPt;
+ /** @brief Preference to vertices with more Si tracks when chosing a conversion vertex */
+ int m_preferSi;
+ 
+
+};
+
+#endif
+
+
+
+
+
+
+
+
+
diff --git a/Reconstruction/egamma/egammaTools/src/EMFourMomBuilder.cxx b/Reconstruction/egamma/egammaTools/src/EMFourMomBuilder.cxx
new file mode 100644
index 0000000000000..9715dd52ef5a2
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/EMFourMomBuilder.cxx
@@ -0,0 +1,336 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/********************************************************************
+
+NAME:     EMFourMomBuilder.cxx
+PACKAGE:  offline/Reconstruction/egamma/egammaTools
+
+AUTHORS:  D. Zerwas, DDV , JM , TK, FD
+CREATED:  August, 2005
+CHANGES:  March 2014, xAOD migration (David di Valentino)
+          May 2014, Bruno Lenzi. Simplify definitions: 
+            - cluster energy
+            - track eta, phi for electrons
+            - vertex eta, phi for Si+Si conversions
+            - cluster eta, phi for other photons
+          Combination will be done with a dual-use tool later
+          May 2014 Add some covariance matrix functionality
+          TODO: Maybe just fill the cluster with a parametrization
+          Use a different tool in the future
+PURPOSE:  subAlgorithm which sets the 4-mom of the egamma object
+
+
+
+********************************************************************/
+
+// INCLUDE HEADER FILES:
+#include "EMFourMomBuilder.h"
+#include "TrkTrack/LinkToTrack.h"
+#include "TrkTrackLink/ITrackLink.h"
+#include "TrkVertexFitterInterfaces/INeutralParticleParameterCalculator.h" 
+#include "FourMom/ErrorMatrixEEtaPhiM.h"
+#include "egammaInterfaces/IFourMomCombiner.h"
+
+//NEW xAOD INCLUDES.
+#include "xAODEgamma/EgammaDefs.h"
+#include "xAODEgamma/EgammaEnums.h"
+#include "xAODEgamma/EgammaxAODHelpers.h"
+
+#include "xAODTracking/Vertex.h"
+#include "xAODTracking/TrackParticle.h"
+#include "xAODEgamma/Egamma.h"
+#include "xAODEgamma/Electron.h"
+#include "xAODEgamma/Photon.h"
+#include "xAODEgamma/ElectronContainer.h"
+#include "xAODEgamma/PhotonContainer.h"
+
+#include "xAODCaloEvent/CaloCluster.h"
+#include "xAODCaloEvent/CaloClusterContainer.h" 
+#include "xAODTracking/TrackParticleContainer.h" 
+#include "xAODTracking/VertexContainer.h" 
+#include "xAODTracking/TrackingPrimitives.h" 
+#include "xAODEgamma/EgammaxAODHelpers.h"
+#include "EventPrimitives/EventPrimitives.h"
+#include "FourMom/EigenP5Jacobiand0z0PhiThetaqOverP2d0z0PhiEtaP.h"
+
+//  END OF HEADER FILES INCLUDE
+using CLHEP::GeV;
+
+/////////////////////////////////////////////////////////////////
+
+const double DEFAULT_QOVERP_ERROR = 1; // this is a huge error
+// this needs to be the same orsmaller than in EMErrorDetail
+//const double DEFAULT_MOMENTUM = 1e10;
+
+//  CONSTRUCTOR:
+   
+EMFourMomBuilder::EMFourMomBuilder(const std::string& type,
+                                 const std::string& name,
+                                 const IInterface* parent)
+  : egammaBaseTool(type, name, parent),
+    //m_tmp_dataType(ParticleDataType::Full),
+    m_convUtils("Trk::NeutralParticleParameterCalculator"),
+    m_FourMomCombiner("FourMomCombiner")
+{
+
+  // declare interface
+  declareInterface<IEMFourMomBuilder>(this);
+
+  // The following properties are specified at run-time
+  // (declared in jobOptions file)
+  
+  // Name of the seed for the analysis
+  declareProperty("AnalysisSeed", m_AnalysisSeed,
+		  "Name of the seed for the analysis");
+
+  // Name of the primary vertex candidates
+  declareProperty("PrimaryVertexContainer", 
+		  m_vxCandidatesName="PrimaryVertices",
+		  "Name of the primary vertex container");
+
+  // Name of conversion utility
+  declareProperty("ConversionUtils", m_convUtils,
+		  "Name of conversion utility");
+  
+  // Use E-p combination.
+  declareProperty("UseCombination",
+		  m_useCombination = false,
+		  "Use the E-p combination");
+
+  // Data type
+  declareProperty("dataType",  m_tmp_dataType,
+		  "Data type");
+
+  declareProperty("TreatElectronsAsPhotons", 
+		  m_treatElectronsAsPhotons = false,
+		  "Use this to treat electrons as nonconverted photons");
+
+  declareProperty("MinPtTRT", 
+		  m_minPtTRT = 2000.0, 
+		  "Minimum pT for TRT-only tracks for them to be combined");
+
+  declareProperty("m_FourMomCombiner",
+		  m_FourMomCombiner,
+		  "Tool for performing E-p combination");		  
+  
+}
+
+// =============================================================
+// DESTRUCTOR:
+EMFourMomBuilder::~EMFourMomBuilder()
+{ 
+}
+
+// =============================================================
+// INITIALIZE METHOD:  
+StatusCode EMFourMomBuilder::initialize()
+{
+  ATH_MSG_DEBUG(" Initializing EMFourMomBuilder");
+ 
+ return StatusCode::SUCCESS;
+}
+
+
+// =============================================================
+StatusCode EMFourMomBuilder::execute(xAOD::Egamma* eg)
+{
+  return  execute(eg, 0);
+}
+
+// =============================================================
+// EXECUTE METHOD :  (modified - xAOD::Egamma* is an input) 
+
+StatusCode EMFourMomBuilder::execute(xAOD::Egamma* eg, unsigned int index)
+{
+
+  // Protection against bad pointers.
+  if (!eg) return StatusCode::SUCCESS;
+  
+  const xAOD::CaloCluster *cluster = eg->caloCluster();
+  if (!cluster) {
+    ATH_MSG_WARNING("Null pointer to cluster");
+    return StatusCode::SUCCESS;
+  }
+    
+  xAOD::Electron *electron = dynamic_cast< xAOD::Electron* >(eg);
+  xAOD::Photon   *photon   = electron ? 0 : dynamic_cast< xAOD::Photon* >(eg);
+  bool doubleSiConversion  = ( xAOD::EgammaHelpers::conversionType(photon) == xAOD::EgammaParameters::doubleSi );
+
+  //If we have a good TrackParticle, use its eta and phi.
+  bool goodTrack(false);
+  if (electron) {
+    const xAOD::TrackParticle *trackParticle = electron->trackParticle();
+    if (trackParticle &&  xAOD::EgammaHelpers::numberOfSiHits(trackParticle)>=4) 
+      goodTrack=true;
+  }
+  
+  StatusCode sc = StatusCode::SUCCESS;
+
+  if (electron && goodTrack){
+    sc = setFromTrkCluster(electron, index);
+  }
+  else if (photon && doubleSiConversion ){
+    sc = setFromTrkCluster(photon);
+  }
+  else{
+    sc = setFromCluster(eg);
+  }
+  return sc;
+}
+
+// ======================================================================
+StatusCode EMFourMomBuilder::hltExecute(xAOD::Egamma* eg, unsigned int index)
+{
+  // This is for the HLT. It might change, which is why we don't just use combinationexecute directly
+  return execute(eg, index);
+}
+
+// ===================================================================
+StatusCode EMFourMomBuilder::setFromTrkCluster(xAOD::Electron* el, 
+					       unsigned int index){
+  if (m_useCombination) {
+    
+    //Get # of Si hits.
+    uint8_t nPixel(0), nSCT(0);
+    el->trackParticle()->summaryValue(nPixel, xAOD::numberOfPixelHits);
+    el->trackParticle()->summaryValue(nSCT,   xAOD::numberOfSCTHits);
+    bool hasSi (nPixel + nSCT > 4);
+
+    //Perform E-p combination.
+    StatusCode sc = m_FourMomCombiner->TrackClusterExecute(el, index, hasSi);
+    
+    //Put combined error matrix in EMErrorDetail.
+    saveParameters(el);
+  }
+  else {
+    
+    const xAOD::CaloCluster *cluster = el->caloCluster();
+    if (!cluster) {
+      ATH_MSG_WARNING("Null pointer to cluster");
+      return StatusCode::SUCCESS;
+    }
+
+    const xAOD::TrackParticle *trackParticle = el->trackParticle();
+    if (!trackParticle) {
+      ATH_MSG_WARNING("Null pointer to Track Particle");
+      return StatusCode::SUCCESS;
+    }
+    
+    float E = cluster->e();
+    float eta = 0., phi = 0. , mass=0.510998;        
+    AmgMatrix(4,4) matrix;
+    matrix.setZero();
+    
+    eta = trackParticle->eta();
+    phi = trackParticle->phi();    
+    
+    //Trying to Fill a covariance for the case of good Track
+    xAOD::ParametersCovMatrix_t covmat=trackParticle->definingParametersCovMatrix();
+    EigenP5Jacobiand0z0PhiThetaqOverP2d0z0PhiEtaP J(trackParticle->phi(),
+						    trackParticle->charge(),
+						    trackParticle->p4().P()); 
+    AmgMatrix(5,5) m;
+    m.setZero();
+    m = J * (covmat * J.transpose());
+    
+    //Rearrange the elements of the d0, z0, phi, eta, P representation to make the (E, eta, phi, M)     
+    matrix(0,0) = m(4,4); //This should come from the cluster E 
+    matrix(1,1) = m(3,3);
+    matrix(2,2) = m(2,2);     
+    matrix.fillSymmetric(0,1,m(4,3));
+    matrix.fillSymmetric(0,2,m(4,2));
+    matrix.fillSymmetric(1,2,m(3,2)); 
+    
+    //Set the four momentum.
+    ATH_MSG_DEBUG("Setting P4 using E=" << E << " eta=" << eta << " phi=" << phi <<" mass" << mass);
+    el->setP4( E/cosh(eta), eta, phi, mass);
+    
+    //Set the covariance matrix.
+    el->setCovMatrix(matrix.cast<float>());
+  }
+  
+  return StatusCode::SUCCESS;
+}
+
+StatusCode EMFourMomBuilder::setFromTrkCluster(xAOD::Photon* ph){
+  
+  const xAOD::CaloCluster *cluster = ph->caloCluster();
+  if (!cluster) {
+    ATH_MSG_WARNING("Null pointer to cluster");
+    return StatusCode::SUCCESS;
+  }
+    
+  float E = cluster->e();
+  float eta = cluster->eta(), phi = cluster->phi() , mass =0.;
+  
+  AmgMatrix(4,4) matrix;
+  matrix.setZero();
+  
+  Amg::Vector3D momentumAtVertex = xAOD::EgammaHelpers::momentumAtVertex(ph);
+  if (momentumAtVertex.mag() > 1e-5) { // protection against p = 0
+    eta = momentumAtVertex.eta();
+    phi = momentumAtVertex.phi();
+  }
+  
+  //Set the four momentum.
+  ATH_MSG_DEBUG("Setting P4 using E=" << E << " eta=" << eta << " phi=" << phi <<" mass" << mass);
+  ph->setP4( E/cosh(eta), eta, phi, mass);
+  //Set the covariance matrix.
+  ph->setCovMatrix(matrix.cast<float>()); 
+
+  return StatusCode::SUCCESS;
+}
+
+// ===================================================================
+StatusCode EMFourMomBuilder::setFromCluster(xAOD::Egamma* eg)
+{
+  // Protection against bad pointers.
+  if (!eg) return StatusCode::SUCCESS;
+  
+  const xAOD::CaloCluster *cluster = eg->caloCluster();
+  if (!cluster) {
+    ATH_MSG_WARNING("Null pointer to cluster");
+    return StatusCode::SUCCESS;
+  }
+
+  float eta  = cluster->eta(), phi = cluster->phi();
+  float E    = cluster->e();
+  float mass = 0.;
+
+  AmgMatrix(4,4) matrix;
+  matrix.setZero();
+  
+  xAOD::Electron *electron = dynamic_cast< xAOD::Electron* >(eg);
+  if (electron) mass = 0.510998;
+
+  //Set the four momentum and covariance matrix.
+  eg->setP4( E/cosh(eta), eta, phi, mass);
+  eg->setCovMatrix(matrix.cast<float>());
+
+  return StatusCode::SUCCESS;
+}
+
+// =================================================================
+// Fill egamma with the combined parameters + matrix.
+void EMFourMomBuilder::saveParameters(xAOD::Egamma *eg) {
+  saveCombinedParams(eg);
+}
+
+void EMFourMomBuilder::saveCombinedParams(xAOD::Egamma *eg) {
+
+  double mass(0.);
+  if (xAOD::EgammaHelpers::isElectron(eg))
+    mass = 0.510998;
+
+  //Fill in combined parameters + matrix.
+  Amg::VectorX m_combVector = m_FourMomCombiner->getCombinedVector();
+  eg->setPhi(m_combVector[2]);
+  eg->setEta(m_combVector[3]);
+  eg->setPt(m_combVector[4] / cosh(m_combVector[3]));
+  eg->setM(mass);
+
+  //Set error matrices in egamma object.
+  eg->setCovMatrix((m_FourMomCombiner->get4x4CombinedErrorMatrix()).cast<float>()); 
+}
diff --git a/Reconstruction/egamma/egammaTools/src/EMFourMomBuilder.h b/Reconstruction/egamma/egammaTools/src/EMFourMomBuilder.h
new file mode 100644
index 0000000000000..6ece39c6535ae
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/EMFourMomBuilder.h
@@ -0,0 +1,118 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef EGAMMATOOLS_EMFOURMOMBUILDER_H
+#define EGAMMATOOLS_EMFOURMOMBUILDER_H
+
+/**
+  @class EMFourMomBuilder
+          sets the fourmomentum : energy is taken from the cluster and angles either from tracking or cluster.
+	  In case the egamma object is a conversion :
+	   - if it is a single/double track conversion with TRT only tracks (i.e no more than 4 hits in pixel+SCT), take the cluster info, not the track info
+           - 
+  @author D. Zerwas
+*/
+
+// XAOD INCLUDES:
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "egammaInterfaces/IegammaBaseTool.h"
+#include "xAODEgamma/EgammaFwd.h"
+#include "xAODEgamma/PhotonFwd.h"
+#include "xAODEgamma/ElectronFwd.h"
+#include "xAODCaloEvent/CaloClusterFwd.h"
+#include "xAODTracking/TrackParticleContainer.h" 
+#include "xAODTracking/VertexContainer.h" 
+
+// INCLUDE HEADER FILES:
+#include "GaudiKernel/ToolHandle.h"
+#include "GaudiKernel/ServiceHandle.h"
+#include "egammaBaseTool.h"
+#include "egammaInterfaces/IEMFourMomBuilder.h"
+#include "EventKernel/IParticle.h"
+#include "CaloEvent/CaloCluster.h"
+#include "InDetBeamSpotService/IBeamCondSvc.h"
+#include "EventPrimitives/EventPrimitives.h"
+
+#include "egammaRecEvent/egammaRec.h"
+
+
+class EMShower;
+class EMTrackFit;
+class EMConvert;
+class FourMomCombiner;
+class IFourMomCombiner;
+
+namespace Trk
+{
+  class INeutralParticleParameterCalculator;
+  struct ParticleMasses;
+  class TrackParticleBase;
+}
+
+class EMFourMomBuilder : public egammaBaseTool, virtual public IEMFourMomBuilder
+{
+
+ public:
+
+  /** @brief Default constructor*/
+  EMFourMomBuilder(const std::string& type,
+		   const std::string& name,
+		   const IInterface* parent);
+
+  /** @brief Destructor*/
+  ~EMFourMomBuilder();
+	
+  /** @brief initialize method*/
+  StatusCode initialize();
+  /** @brief execute method*/
+  virtual StatusCode execute(xAOD::Egamma* eg);
+  /** @brief execute method*/
+  virtual StatusCode execute(xAOD::Egamma* eg, unsigned int index);
+  /** @brief execute method for the HLT*/
+  virtual StatusCode hltExecute(xAOD::Egamma* eg, unsigned int index);
+
+private:
+ 
+  /** @brief Method to set the 4-mom in case of electron */
+  StatusCode setFromTrkCluster(xAOD::Electron*,
+			       unsigned int);
+
+  StatusCode setFromTrkCluster(xAOD::Photon*);
+ 
+ 
+  /** @brief Method to set the 4-mom in case of unconverted photon */
+  StatusCode setFromCluster(xAOD::Egamma*);
+
+  //Method to save parameters in egamma object.
+  void saveParameters    (xAOD::Egamma*);
+  void saveCombinedParams(xAOD::Egamma*);
+  
+  /** @brief seed of the analysis*/
+  std::string		     m_AnalysisSeed; 
+  /** @brief Name of the vertex candidates*/
+  std::string                m_vxCandidatesName;
+  /** @brief */
+  ParticleDataType::DataType m_dataType;
+  /** @brief */
+  int                        m_tmp_dataType;
+
+  /** @brief Tool Handle for */
+  ToolHandle<Trk::INeutralParticleParameterCalculator> m_convUtils;
+
+  /** @brief Use E-p combination*/
+  bool   m_useCombination;
+
+  //Adding in separate combination tool - this should act as the shell that makes the decision.
+  ToolHandle<IFourMomCombiner> m_FourMomCombiner;
+  Amg::Vector3D m_vtxOrigin;
+  
+  /** @brief Treat electron as unconverted photon for photon perf studies */
+  bool   m_treatElectronsAsPhotons;
+
+  /** @brief Minimum pT for TRT-only tracks for them to be combined */
+  double m_minPtTRT;
+
+};
+
+#endif
diff --git a/Reconstruction/egamma/egammaTools/src/EMPIDBuilder.cxx b/Reconstruction/egamma/egammaTools/src/EMPIDBuilder.cxx
new file mode 100644
index 0000000000000..afb34e848380c
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/EMPIDBuilder.cxx
@@ -0,0 +1,95 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// INCLUDE HEADER FILES:
+
+#include "AthenaKernel/errorcheck.h"
+
+#include "EMPIDBuilder.h"
+#include "xAODEgamma/Egamma.h"
+#include "PATCore/IAsgSelectionTool.h"
+
+// ===========================================================================
+EMPIDBuilder::EMPIDBuilder(const std::string& type,
+					   const std::string& name,
+					   const IInterface* parent)
+  : egammaBaseTool(type, name, parent)
+{
+  //
+  // constructor
+  //
+
+  // declare interface
+  declareInterface<IegammaBaseTool>(this);
+
+  declareProperty("selectors", m_selectors,
+    "The selectors that we need to apply to the EGamma object");
+  declareProperty("selectorResultNames", m_selectorResultNames,
+    "The selector result names");
+}
+
+// ===============================================================
+EMPIDBuilder::~EMPIDBuilder()
+{ 
+  //
+  // destructor
+  //
+}
+
+// ==================================================================
+StatusCode EMPIDBuilder::initialize()
+{
+  //
+  // initialize method
+  //
+
+  ATH_MSG_DEBUG(" Initializing EMPIDBuilder");
+ 
+  for (const auto& selector : m_selectors) {
+    CHECK(selector.retrieve());
+  }
+
+  if (m_selectors.size() != m_selectorResultNames.size()) {
+    ATH_MSG_ERROR("The number of selectors does not match the number of given selector names");
+    return StatusCode::FAILURE;
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+// ====================================================================
+StatusCode EMPIDBuilder::finalize()
+{
+  //
+  // finalize method
+  //
+
+  return StatusCode::SUCCESS;
+}
+
+
+// =====================================================================
+StatusCode EMPIDBuilder::execute(xAOD::Egamma* eg)
+{ 
+  
+  ATH_MSG_DEBUG("Executing EMPIDBuilder::execute");
+
+  // Protection against bad pointers
+  if (eg==0) {
+    ATH_MSG_WARNING("NULL egamma object given to execute function");
+    return StatusCode::SUCCESS;
+  }
+  
+  size_t size = m_selectors.size();
+
+  for (size_t i = 0; i<size; i++) {
+    const Root::TAccept& accept = m_selectors[i]->accept(eg);
+    eg->setPassSelection(static_cast<bool>(accept), m_selectorResultNames[i]);
+  }
+  
+  return StatusCode::SUCCESS;
+}
+
+
+
diff --git a/Reconstruction/egamma/egammaTools/src/EMPIDBuilder.h b/Reconstruction/egamma/egammaTools/src/EMPIDBuilder.h
new file mode 100644
index 0000000000000..1fd02c07e3319
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/EMPIDBuilder.h
@@ -0,0 +1,59 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef EGAMMATOOLS_EMPIDBUILDER_H
+#define EGAMMATOOLS_EMPIDBUILDER_H
+/**
+  @class EMPIDBuilder
+  egamma tool to add selector outputs to the egamma objects 
+  Note:  Subject to change after the PAT selectors evolve
+ 
+  @author Jovan Mitrevski Jovan.Mitrevski@cern.ch
+
+*/
+
+// INCLUDE HEADER FILES: 
+#include "GaudiKernel/ToolHandle.h"
+#include "egammaBaseTool.h"
+
+#include <string>
+#include <vector>
+
+class IAsgSelectionTool;
+
+class EMPIDBuilder : public egammaBaseTool
+{
+ public:
+
+  /** @brief Default constructor*/
+  EMPIDBuilder(const std::string& type,
+	       const std::string& name,
+	       const IInterface* parent);
+   
+  /** @brief Destructor*/
+  ~EMPIDBuilder();
+	
+  /** @brief initialize method*/
+  StatusCode initialize();
+  /** @brief standard execute method */
+  virtual StatusCode execute(xAOD::Egamma*);
+  /** @brief finalize method*/
+  StatusCode finalize();
+
+ protected:
+  /** Handle to the selectors */
+  ToolHandleArray<IAsgSelectionTool> m_selectors;
+  std::vector<std::string> m_selectorResultNames;
+};
+
+#endif
+
+
+
+
+
+
+
+
+
diff --git a/Reconstruction/egamma/egammaTools/src/EMShowerBuilder.cxx b/Reconstruction/egamma/egammaTools/src/EMShowerBuilder.cxx
new file mode 100644
index 0000000000000..20fae575badb7
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/EMShowerBuilder.cxx
@@ -0,0 +1,903 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// INCLUDE HEADER FILES:
+#include "GaudiKernel/IChronoStatSvc.h"
+
+#include "EMShowerBuilder.h"
+
+#include "CaloUtils/CaloCellList.h"
+#include "CaloEvent/CaloCellContainer.h"
+#include "CaloEvent/CaloCluster.h"
+
+#include "egammaInterfaces/IegammaShowerShape.h"
+#include "egammaInterfaces/IegammaIso.h"
+#include "egammaInterfaces/IEMTrackIsolationTool.h"
+
+#include "xAODEgamma/Egamma.h"
+#include "xAODEgamma/Electron.h"
+#include "xAODEgamma/Photon.h"
+#include "xAODEgamma/ElectronContainer.h"
+#include "xAODEgamma/PhotonContainer.h"
+#include "xAODCaloEvent/CaloCluster.h"
+#include "xAODTracking/TrackParticleContainer.h" 
+#include "xAODTracking/VertexContainer.h" 
+
+#include "VxVertex/VxContainer.h"
+#include "Particle/TrackParticleContainer.h"
+
+#include "FourMomUtils/P4Helpers.h"
+
+#include <algorithm> 
+#include <cmath>
+#include <stdexcept>
+ 
+//  END OF HEADER FILES INCLUDE
+
+// ===========================================================================
+EMShowerBuilder::EMShowerBuilder(const std::string& type,
+                                 const std::string& name,
+                                 const IInterface* parent)
+  : egammaBaseTool(type, name, parent),
+    m_ShowerShapeTool("egammaShowerShape/egammashowershape")
+{
+  //
+  // constructor
+  //
+
+  // declare interface
+  declareInterface<IEMShowerBuilder>(this);
+  
+  // The following properties are specified at run-time
+  // (declared in jobOptions file)
+  
+  // Names of containers which contain cells  
+  declareProperty("CellsName",m_cellsName="AllCalo", "Names of containers which contain cells ");
+
+  // list of calo to treat
+  declareProperty("CaloNums",m_caloNums, "list of calo to treat");
+
+  // Boolean to call shower shape calculation and filling
+  // (NB: this could be important when redoing calculation from AODs)
+  declareProperty("UseShowerShapeTool", m_UseShowerShapeTool=true, "Boolean to call shower shape calculation and filling");
+  
+  // Boolean to call isolation variables calculation and filling
+  // (NB: this could be important when redoing calculation from AODs)
+  declareProperty("UseCaloIsoTool", m_UseCaloIsoTool=true, "Boolean to call calo isolation variables calculation and filling");
+  
+  // Boolean to use track iso tool
+  declareProperty("UseTrackIsoTool", m_UseTrackIsoTool= true, "Boolean to call track isolation variables calculation and filling");
+
+  // Handles of instance of egammaShowerShape Tool to be run 
+  declareProperty("ShowerShapeTool", m_ShowerShapeTool, "Handle of instance of egammaShowerShape Tool to be run");
+
+  // Handle of the calorimetric isolation tool
+  declareProperty("EMCaloIsolationTool", m_emCaloIsolationTool, "Handle of the EMCaloIsolationTool");
+
+  // Handle of the calorimetric isolation tool
+  declareProperty("EMCaloIsoPtCorrectionTool", m_emCaloIsoPtCorrectionTool, "Handle of the EMCaloIsoPtCorrectionTool");
+
+  // Handle of the calorimetric isolation tool
+  declareProperty("EMTopoCaloIsolationTool", m_emTopoCaloIsolationTool, "Handle of the EMTopoCaloIsolationTool");
+
+  // Handle of the EMTrackIsolationTool
+  declareProperty("EMTrackIsolationTool", m_emTrackIsolationTool,"Handle of the EMTrackIsolationTool");
+
+  // Boolean for use of cosmics
+  declareProperty("isCosmics",m_isCosmics=false,"Boolean for use of cosmics");
+
+  // Boolean to do isolation for TopoSeededPhoton 
+  declareProperty("doIsolForTopoSeeded",m_doIsolForTopoSeeded=true,"Boolean for doing isolation for TopoSeeded Photons");
+
+  // Name of the input Topo Calo container
+  declareProperty("TopoCaloClusterInputName",m_topoCaloClusterInputName="CaloCalTopoCluster","Topo CaloCluster input conainer to compute the isolation");
+  
+  // in case we want some extra print
+  declareProperty("Print",m_Print=false,"in case of extra prints");
+
+  // in case we want some extra print
+  declareProperty("Timing",m_timing=false,"do extra timing");
+      
+      
+  declareProperty("IsoTypes", m_isoTypes, "The isolation types to do: vector of enum type egammaParameter::ParamDef");
+      
+  declareProperty("TopoIsoTypes", m_topoIsoTypes,"The topo isolation types to do: vector of enum type egammaParameter::ParamDef");
+      
+  declareProperty("doEnergyDensityCorrection", m_doEnergyDensityCorrection=true,"Correct isolation variables based on energy density estimations");
+
+ }
+
+// ===============================================================
+EMShowerBuilder::~EMShowerBuilder()
+{
+  //
+  // destructor
+  // 
+}
+
+// ==================================================================
+StatusCode EMShowerBuilder::initialize()
+{
+  //
+  // initialize method
+  //
+
+  ATH_MSG_DEBUG(" Initializing EMShowerBuilder");;
+ 
+  unsigned int nSubCalo=static_cast<int>(CaloCell_ID::NSUBCALO) ;
+  //check calo number specified
+  m_caloSelection = false ;
+  if (m_caloNums.size()==0) {
+    ATH_MSG_DEBUG(" No calorimeter selection ");
+    return StatusCode::SUCCESS;
+  } else if  (m_caloNums.size()>nSubCalo ) {
+    ATH_MSG_ERROR(" More than "
+      << nSubCalo << " calo specified. Must be wrong. Stop.");
+    return StatusCode::FAILURE;
+  } else {
+    m_caloSelection = true ;
+    
+    for (unsigned int index=0; index < m_caloNums.size() ; ++index) {
+      if (m_caloNums[index]<0 ||  m_caloNums[index]>=(int)nSubCalo ) {
+        ATH_MSG_ERROR("Invalid calo specification:"
+          << m_caloNums[index] << "Stop.");
+        return StatusCode::FAILURE;
+  
+      } else {
+  ATH_MSG_DEBUG(" Select calorimeter " << m_caloNums[index]);
+      }
+    }
+  }
+  
+  // Pointer to Tool Service
+  IToolSvc* p_toolSvc = 0;
+  StatusCode sc = service("ToolSvc", p_toolSvc);
+  if (sc.isFailure()) {
+    ATH_MSG_FATAL(" Tool Service not found ");
+    return StatusCode::FAILURE;
+  } 
+    
+
+  m_doTopoIso = true;
+  if (m_topoIsoTypes.size() == 0) {
+    ATH_MSG_DEBUG("No topo iso requested, turning off");
+    m_doTopoIso = false;
+  }
+
+  // 
+  // call calorimeter isolation tool only if needed
+  //
+  if (m_UseCaloIsoTool) {
+    if ((sc = RetrieveEMCaloIsolationTool()).isFailure()) {
+      return sc;
+    }
+    if ((sc = RetrieveEMCaloIsoPtCorrectionTool()).isFailure()) {
+      return sc;
+    }
+    if (m_doTopoIso) {
+      if ((sc = RetrieveEMTopoCaloIsolationTool()).isFailure()) {
+	return sc;
+      }
+    }
+  }
+
+  // 
+  // call track isolation tool only if needed
+  //
+  if (m_UseTrackIsoTool) {
+    if ((sc = RetrieveEMTrackIsolationTool()).isFailure()) {
+      return sc;
+    }
+  }
+
+  // for measuring the timing
+  m_timingProfile = 0;
+  if (m_timing) {
+    sc = service("ChronoStatSvc",m_timingProfile);
+    if(sc.isFailure() || m_timingProfile == 0) {
+      ATH_MSG_ERROR("Cannot find the ChronoStatSvc " << m_timingProfile);
+      return sc;
+    }
+  }
+
+  // lets set up the isolation variables
+  m_doNoiseCalc = false; // initialize to false
+
+  for (unsigned int i = 0; i < m_isoTypes.size(); i++) {
+    m_specs.push_back(getSpecifier(static_cast<xAOD::EgammaParameters::IsolationType>(m_isoTypes.at(i))));
+  }
+
+  if (!m_doNoiseCalc) {
+    // let's optimize by using just Rs
+    for (std::vector<IegammaIso::IsoSpecifier>::const_iterator specsit = m_specs.begin();
+	 specsit != m_specs.end();
+	 ++specsit) {
+      m_Rs.push_back(specsit->R2);
+    }
+
+  }
+
+  return sc;
+}
+
+// ====================================================================
+StatusCode EMShowerBuilder::RetrieveShowerShapeTool()
+{
+  //
+  // retrieve shower shape tool
+  //
+
+  if (m_ShowerShapeTool.empty()) {
+    ATH_MSG_INFO("ShowerShape is empty");
+    return StatusCode::SUCCESS;
+  } 
+
+  // retrieve egammaShowerShape Tool
+  if(m_ShowerShapeTool.retrieve().isFailure()) {
+    ATH_MSG_ERROR("Unable to retrieve "<<m_ShowerShapeTool);
+    return StatusCode::FAILURE;
+  } 
+  else ATH_MSG_DEBUG("Retrieved Tool " << m_ShowerShapeTool); 
+  return StatusCode::SUCCESS;
+}
+
+
+// ====================================================================
+StatusCode EMShowerBuilder::RetrieveEMCaloIsolationTool()
+{
+  //
+  // retrieve EMCaloIsolationTool
+  //
+  
+  if (m_emCaloIsolationTool.empty()) {
+    ATH_MSG_INFO("EMCaloIsolation is empty");
+    return StatusCode::SUCCESS;
+  } 
+
+  if(m_emCaloIsolationTool.retrieve().isFailure()) {
+    ATH_MSG_ERROR("Unable to retrieve "<<m_emCaloIsolationTool);
+    return StatusCode::FAILURE;
+  } 
+  else ATH_MSG_DEBUG("Retrieved Tool "<<m_emCaloIsolationTool);
+  
+  return StatusCode::SUCCESS;
+}
+
+// ====================================================================
+StatusCode EMShowerBuilder::RetrieveEMTrackIsolationTool()
+{
+  //
+  // retrieve EMTrackIsolationTool
+  //
+  
+  if (m_emTrackIsolationTool.empty()) {
+    ATH_MSG_INFO("EMTrackIsolation is empty");
+    return StatusCode::SUCCESS;
+  } 
+
+  if(m_emTrackIsolationTool.retrieve().isFailure()) {
+    ATH_MSG_ERROR("Unable to retrieve "<<m_emTrackIsolationTool);
+    return StatusCode::FAILURE;
+  } 
+  else ATH_MSG_DEBUG("Retrieved Tool "<<m_emTrackIsolationTool);
+  return StatusCode::SUCCESS;
+}
+
+
+
+// ====================================================================
+StatusCode EMShowerBuilder::RetrieveEMCaloIsoPtCorrectionTool()
+{
+  //
+  // retrieve EMCaloIsolationPtCorrectionTool
+  //
+
+  if (m_emCaloIsoPtCorrectionTool.empty()) {
+    ATH_MSG_INFO("EMCaloIsolationPtCorrection is empty");
+    return StatusCode::SUCCESS;
+  }
+
+  if(m_emCaloIsoPtCorrectionTool.retrieve().isFailure()) {
+    ATH_MSG_ERROR("Unable to retrieve "<<m_emCaloIsoPtCorrectionTool);
+    return StatusCode::FAILURE;
+  }
+  else ATH_MSG_DEBUG("Retrieved Tool "<<m_emCaloIsoPtCorrectionTool);
+
+  return StatusCode::SUCCESS;
+}
+
+// ====================================================================
+StatusCode EMShowerBuilder::RetrieveEMTopoCaloIsolationTool()
+{
+  //
+  // retrieve EMTopoCaloIsolationTool
+  //
+
+  if (m_emTopoCaloIsolationTool.empty()) {
+    ATH_MSG_INFO("EMTopoCaloIsolation is empty");
+    m_doTopoIso = false;
+    return StatusCode::SUCCESS;
+  }
+
+  if(m_emTopoCaloIsolationTool.retrieve().isFailure()) {
+    ATH_MSG_ERROR("Unable to retrieve "<<m_emTopoCaloIsolationTool);
+    return StatusCode::FAILURE;
+  }
+  else ATH_MSG_DEBUG("Retrieved Tool "<<m_emTopoCaloIsolationTool);
+
+  return StatusCode::SUCCESS;
+}
+
+// ====================================================================
+StatusCode EMShowerBuilder::finalize()
+{
+  //
+  // finalize method
+  //
+
+  return StatusCode::SUCCESS;
+}
+
+// =====================================================================
+StatusCode EMShowerBuilder::execute(xAOD::Egamma* eg)
+{ 
+  // 
+  // execute method as used in offline reconstruction
+  // 
+
+  ATH_MSG_DEBUG("Executing EMShowerBuilder::execute");
+  
+  // protection against bad pointers
+  if (eg==0) return StatusCode::SUCCESS;
+
+  // retrieve the containers
+  StatusCode sc = retrieveContainers();
+  if (sc.isFailure()) {
+    ATH_MSG_WARNING("EMShowerBuilder returns failure on retrieveContainers");
+    return sc;
+  }
+
+  sc = recoExecute(eg,m_cellcoll);
+  if (sc.isFailure()) {
+    ATH_MSG_WARNING("execute(egamma* eg) returns failure on recoExecute");
+    return sc;
+  }
+  
+  return StatusCode::SUCCESS;
+}
+
+// ======================================================================
+StatusCode EMShowerBuilder::caloExecute(xAOD::Egamma* eg, const CaloCellContainer* cellcoll)
+{ 
+  // 
+  // execute method as used by Event Filter
+  // 
+  
+  ATH_MSG_DEBUG("Executing caloExecute");
+
+  // put the CaloCellContainer into the global variable
+  m_cellcoll = cellcoll;
+
+  // calculate shower shapes
+  CalcShowerShape(eg);
+
+  return StatusCode::SUCCESS;
+
+}
+
+StatusCode EMShowerBuilder::recoExecute(xAOD::Egamma* eg, const CaloCellContainer* cellcoll,
+					const xAOD::TrackParticleContainer* aTrackParticleContainer /*= 0*/)
+{ 
+  // 
+  // execute method as used by Offline reconstruction
+  // 
+  
+  ATH_MSG_DEBUG("Executing recoExecute");
+
+  // put the CaloCellContainer into the global variable
+  m_cellcoll = cellcoll;
+
+
+  //if We do not want to do isolation for topoSeeded 
+  //Do just Shower Shapes
+  if(!m_doIsolForTopoSeeded){ 
+    if(eg->author(xAOD::EgammaParameters::AuthorCaloTopo35)) {
+
+      m_clus = eg->caloCluster(); 
+      if (m_clus == 0 ) return StatusCode::SUCCESS; 
+    
+      if (m_ShowerShapeTool.empty())  return StatusCode::SUCCESS; 
+    
+      StatusCode sc  = m_ShowerShapeTool->execute(m_clus,m_cellcoll);
+      if ( sc.isFailure() ) {
+	ATH_MSG_WARNING("call to ShowerShape returns failure ");
+	return sc; 
+      } 
+      else {
+	FillEMShowerShape(eg);
+	return StatusCode::SUCCESS; 
+      }
+    }
+  }
+  
+   
+  // calculate shower shapes
+  CalcShowerShape(eg);
+  // calculate track isolation
+  CalcFromTracker(eg,aTrackParticleContainer);
+
+  ATH_MSG_DEBUG("Exiting recoExecute");
+  
+  return StatusCode::SUCCESS;
+  
+}
+
+// =====================================================================
+StatusCode EMShowerBuilder::retrieveContainers()
+{ 
+  //
+  // method shared by the various execute method to retrieve 
+  // the cell and cluster containers
+  //
+
+  // retrieve Calo Cell Container
+  if (m_UseShowerShapeTool || m_UseCaloIsoTool) {
+    StatusCode sc = evtStore()->retrieve(m_cellcoll, m_cellsName) ; 
+    if(sc.isFailure() || !m_cellcoll) {
+      ATH_MSG_WARNING("no Calo Cell Container " << m_cellsName << " found");
+      return sc;
+    }
+  }
+
+  //SL+JBdV
+  ATH_MSG_DEBUG("Will retrieve EMTopoEventShape");
+  if (evtStore()->contains<xAOD::EventShape>("EMTopoEventShape")) {
+    m_evtShape = evtStore()->retrieve<xAOD::EventShape>("EMTopoEventShape") ;
+  } else {
+    ATH_MSG_WARNING("EMTopoEventShape does not exist in evtStore");
+    m_evtShape = 0;
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+// =====================================================================
+void EMShowerBuilder::CalcShowerShape(xAOD::Egamma* eg)
+{ 
+  // 
+  // Estimate shower shapes and fill the EMShower object associated to eg
+  // 
+
+  ATH_MSG_DEBUG("Executing CalcShowerShape");
+
+  // protection against bad pointers
+  if (eg==0) return;
+
+  StatusCode sc = StatusCode::SUCCESS;
+
+  // retrieve the cluster 
+  m_clus = eg->caloCluster(); 
+  // Protect against non-existent structures.
+  if (m_clus == 0) return;  
+
+  // call calorimeter isolation tool only if needed
+  if (m_UseCaloIsoTool){
+  
+    if (m_timingProfile) {
+      std::string chronoName = this->name()+"_CalcCaloIsolation";         
+      m_timingProfile->chronoStart(chronoName);
+      CalcCaloIsolation(eg);
+      CalcCaloIsolationPtCorrection(eg);
+      m_timingProfile->chronoStop(chronoName);
+    } else {
+      CalcCaloIsolation(eg);
+      CalcCaloIsolationPtCorrection(eg);
+    }
+  } 
+
+  // Calculate shower shapes in all samplings
+  if (m_UseShowerShapeTool) {
+    // protection in case tool does not exist 
+    if (m_timingProfile) {
+      std::string chronoName = this->name()+"_ShowerShapeTool";         
+      m_timingProfile->chronoStart(chronoName);
+    }
+    if (!m_ShowerShapeTool.empty()) {
+      sc = m_ShowerShapeTool->execute(m_clus,m_cellcoll);
+      if ( sc.isFailure() ) {
+	ATH_MSG_WARNING("call to ShowerShape returns failure ");
+      } else {
+	FillEMShowerShape(eg);
+      }
+    }
+    if (m_timingProfile) {
+      std::string chronoName = this->name()+"_ShowerShapeTool";         
+      m_timingProfile->chronoStop(chronoName);
+    }
+  }
+}
+
+// =====================================================================
+void EMShowerBuilder::CalcFromTracker(xAOD::Egamma* eg,const xAOD::TrackParticleContainer* aTrackParticleContainer /*= 0*/)
+{ 
+  // 
+  // Estimate track isolation from tracker
+  // 
+
+  ATH_MSG_DEBUG("Executing CalcFromTracker");
+
+  if (m_timingProfile) {
+    std::string chronoName = this->name()+"_CalcFromTracker";         
+    m_timingProfile->chronoStart(chronoName);
+  }
+
+
+  // Apply Track Isolation calculation
+  if (m_UseTrackIsoTool && !m_isCosmics) {
+    
+    // protection in case tool is not available
+    // return as algorithm may be able to run without it 
+    // in degraded mode
+    if (m_emTrackIsolationTool.empty()) return;
+    
+    // execute the tool
+    StatusCode sc = m_emTrackIsolationTool->execute(eg,aTrackParticleContainer);
+    if (sc.isFailure()) {
+      ATH_MSG_WARNING("EMTrackisolation reports failure");
+      return;
+    }
+    
+    // retrieve and set value
+    float value=0;
+    value= static_cast<float>(m_emTrackIsolationTool->ptcone20());
+    eg->setIsolationValue(value, xAOD::EgammaParameters::ptcone20);
+    value= static_cast<float>(m_emTrackIsolationTool->ptcone30());
+    eg->setIsolationValue(value, xAOD::EgammaParameters::ptcone30);
+    value= static_cast<float>(m_emTrackIsolationTool->ptcone40());
+    eg->setIsolationValue(value, xAOD::EgammaParameters::ptcone40);
+    value= static_cast<float>(m_emTrackIsolationTool->nucone20());
+    eg->setIsolationValue(value, xAOD::EgammaParameters::nucone20);
+    value= static_cast<float>(m_emTrackIsolationTool->nucone30());
+    eg->setIsolationValue(value, xAOD::EgammaParameters::nucone30);
+    value= static_cast<float>(m_emTrackIsolationTool->nucone40());
+    eg->setIsolationValue(value, xAOD::EgammaParameters::nucone40);
+  }
+    
+  
+  if (m_timingProfile) {
+    std::string chronoName = this->name()+"_CalcFromTracker";         
+    m_timingProfile->chronoStop(chronoName);
+  }
+  return;
+}
+
+// ==========================================================================
+void EMShowerBuilder::CalcCaloIsolation(xAOD::Egamma* eg)
+{
+  //
+  // Call calorimeter isolation tool
+  //
+
+  ATH_MSG_DEBUG("Executing CalcCaloIsolation");
+
+  // protection in case tool does not exist
+  if (m_emCaloIsolationTool.empty()) {
+    return;
+  }
+  if (m_doTopoIso) {
+
+
+    // get topo calo container
+    const xAOD::CaloClusterContainer* calocontainer = 0;
+    StatusCode sc = evtStore()->retrieve(calocontainer, m_topoCaloClusterInputName);
+    if ( sc.isFailure() || calocontainer==0 ) {
+      ATH_MSG_WARNING("CaloClusters not found" );
+      return;
+    }
+    
+    // topo cluster isolation
+    sc = m_emTopoCaloIsolationTool->execute(eg, calocontainer, m_topoIsoTypes);
+    if ( sc.isFailure() ) {
+      ATH_MSG_WARNING("call to TopoIso returns failure for execute");
+      return;
+    }
+  }
+
+  if ( m_caloNums.size() < 3 ) {
+    ATH_MSG_WARNING("Less than 3 subCalos, skipping");
+    return;
+  }
+
+  // define a new Calo Cell list corresponding to EM Calo
+  // retrieve the corresponding CaloCell_ID
+  CaloCell_ID::SUBCALO theCalo = 
+    static_cast<CaloCell_ID::SUBCALO>(m_caloNums[0]) ;
+  // define a new Calo Cell list
+  CaloCellList* EMccl = new CaloCellList(m_cellcoll,theCalo); 
+    
+  // define a new Calo Cell list corresponding to HAD Calo
+  // retrieve the corresponding CaloCell_ID for Tile
+  CaloCell_ID::SUBCALO theCalo1 = 
+    static_cast<CaloCell_ID::SUBCALO>(m_caloNums[1]) ;
+  // retrieve the corresponding CaloCell_ID for FCAL
+  CaloCell_ID::SUBCALO theCalo2 = 
+    static_cast<CaloCell_ID::SUBCALO>(m_caloNums[2]) ;
+  
+  std::vector<CaloCell_ID::SUBCALO> theVecCalo;
+  theVecCalo.push_back(theCalo1);
+  theVecCalo.push_back(theCalo2);
+  // define a new Calo Cell list
+  CaloCellList* HADccl = new CaloCellList(m_cellcoll,theVecCalo); 
+
+
+  // calculate information concerning isolation behind em clusters in the 
+  // hadronic calorimeter and around the em cluster
+  // for isolation around em clustr use cone size 0.45
+  StatusCode sc =  m_emCaloIsolationTool->execute(m_clus,HADccl,EMccl,m_Rs,5,7); 
+
+  if ( sc.isFailure() ) {
+    ATH_MSG_WARNING("call to Iso returns failure for execute");
+    // delete ccls
+    delete EMccl;
+    delete HADccl;
+    return;
+  }
+  
+  float value=0;
+  value=static_cast<float>(m_emCaloIsolationTool->ethad1());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::ethad1);
+
+  value=static_cast<float>(m_emCaloIsolationTool->ethad());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::ethad);
+
+  value=static_cast<float>(m_emCaloIsolationTool->ehad1());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::ehad1);
+
+  
+  // pt correction for topoetcone40 
+  m_dotopoptcor = false;
+
+  try {
+    for (unsigned int i = 0; i < m_isoTypes.size(); i++) {
+      float isovalue=static_cast<float>(m_emCaloIsolationTool->etcone(i));
+      eg->setIsolationValue(isovalue,static_cast<xAOD::EgammaParameters::IsolationType>(m_isoTypes.at(i)));
+    }
+    if (m_doTopoIso) {
+      for (unsigned int i = 0; i < m_topoIsoTypes.size(); i++) {
+        if (m_topoIsoTypes.at(i) == xAOD::EgammaParameters::topoetcone40) {m_dotopoptcor = true;}
+	float isotopovalue=static_cast<float>(m_emTopoCaloIsolationTool->topoetcone(i));
+	eg->setIsolationValue(isotopovalue,static_cast<xAOD::EgammaParameters::IsolationType>(m_topoIsoTypes.at(i)));	
+      }
+    }
+  }
+  catch(std::out_of_range) {
+    ATH_MSG_WARNING("out of range exception caught");
+  }
+
+  // delete ccls
+  delete EMccl;
+  delete HADccl;
+}
+
+// ==========================================================================
+void EMShowerBuilder::CalcCaloIsolationPtCorrection(xAOD::Egamma* eg)
+{ 
+  //
+  // Call calorimeter pt corrected  isolation tool
+  //
+
+    float value=0;
+    float initialvalue=0;
+    if (eg->isolationValue(initialvalue,xAOD::EgammaParameters::etcone15)){
+    value= static_cast<float>(initialvalue - m_emCaloIsoPtCorrectionTool->CalcPtCorrection(eg,  0.15));
+    eg->setIsolationValue(value, xAOD::EgammaParameters::etcone15_ptcorrected);
+    }
+    if (eg->isolationValue(initialvalue,xAOD::EgammaParameters::etcone20)){
+    value= static_cast<float>(initialvalue - m_emCaloIsoPtCorrectionTool->CalcPtCorrection(eg,  0.20));
+    eg->setIsolationValue(value, xAOD::EgammaParameters::etcone20_ptcorrected);
+    }
+    if (eg->isolationValue(initialvalue,xAOD::EgammaParameters::etcone25)){
+    value= static_cast<float>(initialvalue - m_emCaloIsoPtCorrectionTool->CalcPtCorrection(eg,  0.25));
+    eg->setIsolationValue(value, xAOD::EgammaParameters::etcone25_ptcorrected);
+    }
+    if (eg->isolationValue(initialvalue,xAOD::EgammaParameters::etcone30)){
+    value= static_cast<float>(initialvalue - m_emCaloIsoPtCorrectionTool->CalcPtCorrection(eg,  0.30));
+    eg->setIsolationValue(value, xAOD::EgammaParameters::etcone30_ptcorrected);
+    }
+    if (eg->isolationValue(initialvalue,xAOD::EgammaParameters::etcone35)){
+    value= static_cast<float>(initialvalue - m_emCaloIsoPtCorrectionTool->CalcPtCorrection(eg,  0.35));
+    eg->setIsolationValue(value, xAOD::EgammaParameters::etcone35_ptcorrected);
+    }
+    if (eg->isolationValue(initialvalue,xAOD::EgammaParameters::etcone40)){
+    value= static_cast<float>(initialvalue - m_emCaloIsoPtCorrectionTool->CalcPtCorrection(eg,  0.40));
+    eg->setIsolationValue(value, xAOD::EgammaParameters::etcone40_ptcorrected);
+    }
+
+    if ( m_dotopoptcor ){
+      if (eg->isolationValue(initialvalue,xAOD::EgammaParameters::topoetcone40)){
+	value= static_cast<float>(initialvalue - m_emCaloIsoPtCorrectionTool->CalcPtCorrection(eg,  0.40, "topo"));
+	eg->setIsolationValue(value, xAOD::EgammaParameters::topoetcone40_ptcorrected);
+
+	// SL+JBdV
+	float toSub = 0.;
+	double rho  = 0.;
+	if (m_evtShape) {
+	  xAOD::EventShape::EventDensityID densityType = xAOD::EventShape::EventDensityID::DensityForEgammaCentral;
+	  ATH_MSG_DEBUG("Will get density");
+	  if (fabs(eg->eta())>1.5) 
+	    densityType = xAOD::EventShape::EventDensityID::DensityForEgammaForward;
+	  bool status = m_evtShape->getDensity(densityType,rho);
+	  if (!status)
+	    ATH_MSG_WARNING("EventDensity not OK");
+	}
+	toSub = rho*M_PI*(0.16-0.875/128.);
+	ATH_MSG_DEBUG("Density  = " << rho << ", to sub = " << toSub);
+	float edcor = static_cast<float>(value - toSub);
+	eg->setIsolationValue(edcor, xAOD::EgammaParameters::topoetcone40_corrected);
+
+      }	
+    }
+}
+
+// ==========================================================================
+void EMShowerBuilder::FillEMShowerShape(xAOD::Egamma* eg)
+{ 
+  //
+  // retrieve information from shower shape calculation at ESD level
+  //
+
+  // protection in case Tool does not exist
+  if (m_ShowerShapeTool.empty()) return;
+
+  //
+  // information in the presampler
+  //
+  // E in 1x1 cells in pre sampler
+
+  float value=0;
+  // E in 1x1 cells in pre sampler
+  value=static_cast<float>(m_ShowerShapeTool->e011());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::e011);
+  // E in 3x3 cells in pre sampler
+  value=static_cast<float>(m_ShowerShapeTool->e033());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::e033);
+  // E in 3x2 cells in S1
+  value=static_cast<float>(m_ShowerShapeTool->e132());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::e132);
+  // E in 15x2 cells in S1 
+  value=static_cast<float>(m_ShowerShapeTool->e1152());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::e1152);
+  // fraction of E in S1
+  value=static_cast<float>(m_ShowerShapeTool->f1());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::f1);
+  // fraction of E in the core(e132) in S1
+  value=static_cast<float>(m_ShowerShapeTool->f1core());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::f1core);
+  // corr width with 3 strips 
+  value=static_cast<float>(m_ShowerShapeTool->width3c());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::weta1);
+  // energy in second max
+  value=static_cast<float>(m_ShowerShapeTool->esec());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::e2ts1);
+  // energy strip of second max
+  value=static_cast<float>(m_ShowerShapeTool->esec1());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::e2tsts1);
+  // fraction of E outside core in S1
+  value=static_cast<float>(m_ShowerShapeTool->fracm());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::fracs1);
+  // width with 5 strips
+  value=static_cast<float>(m_ShowerShapeTool->width5());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::widths1);
+  //eta pos within cell in S1
+  value=static_cast<float>(m_ShowerShapeTool->poscs1());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::poscs1);
+  // asymmetry with 3 strips
+  value=static_cast<float>(m_ShowerShapeTool->asy3());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::asy1);
+  // diff position +/- 1 cells
+  value=static_cast<float>(m_ShowerShapeTool->pos());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::pos);
+  // diff position +/- 7 cells
+  value=static_cast<float>(m_ShowerShapeTool->pos7());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::pos7);
+  // E of strip with min E 
+  value=static_cast<float>(m_ShowerShapeTool->emin());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::emins1);
+  // E of strip with max E
+  value=static_cast<float>(m_ShowerShapeTool->emax());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::emaxs1);
+  // barycentre in eta in S1
+  value=static_cast<float>(m_ShowerShapeTool->eta1());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::barys1);
+  // total width in strips
+  value=static_cast<float>(m_ShowerShapeTool->wtot());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::wtots1);
+
+  //
+  // information in the 2nd sampling
+  //
+  // E in 3x3 cells in S2
+  value=static_cast<float>(m_ShowerShapeTool->e233());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::e233);
+  // E in 3x5 cells in S2
+  value=static_cast<float>(m_ShowerShapeTool->e235());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::e235);
+  // E in 3x7 cells in S2
+  value=static_cast<float>(m_ShowerShapeTool->e237());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::e237);
+  // E in 5x5 cells in S2
+  value=static_cast<float>(m_ShowerShapeTool->e255());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::e255);
+  // E in 7x7 cells in S2
+  value=static_cast<float>(m_ShowerShapeTool->e277());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::e277);
+  // corr width in S2
+  value=static_cast<float>(m_ShowerShapeTool->etaw());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::weta2);
+  // uncorr width in S2
+  value=static_cast<float>(m_ShowerShapeTool->width());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::widths2);
+  // position in eta within cell in S2
+  value=static_cast<float>(m_ShowerShapeTool->poscs2());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::poscs2);
+  //
+  // information in the 3rd sampling
+  //
+  // fraction of E in S3 
+  value=static_cast<float>(m_ShowerShapeTool->f3());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::f3);
+  // fraction of E in the core (e333) in S3 
+  value=static_cast<float>(m_ShowerShapeTool->f3core());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::f3core);
+  // E in 3x3 cells in S3
+  value=static_cast<float>(m_ShowerShapeTool->e333());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::e333);
+  // E in 3x5 cells in S3
+  value=static_cast<float>(m_ShowerShapeTool->e335());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::e335);
+  // E in 3x7 cells in S3
+  value=static_cast<float>(m_ShowerShapeTool->e337());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::e337);
+  // E in 7x7 cells in S3
+  value=static_cast<float>(m_ShowerShapeTool->e377());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::e377);
+
+  //
+  // information combining all samplings
+  //
+  // ratio of energy in 3x3/3x7 cells
+  value=static_cast<float>(m_ShowerShapeTool->reta3337_allcalo());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::r33over37allcalo);
+  // core energy
+  value=static_cast<float>(m_ShowerShapeTool->ecore());
+  eg->setShowerShapeValue(value, xAOD::EgammaParameters::ecore);
+
+  return;
+}
+
+// ==========================================================================
+IegammaIso::IsoSpecifier EMShowerBuilder::getSpecifier(xAOD::EgammaParameters::IsolationType par) const
+{
+  switch (par) {
+  case xAOD::EgammaParameters::etcone15:
+    return IegammaIso::IsoSpecifier(0, 0.15, -1);
+  case xAOD::EgammaParameters::etcone20:
+    return IegammaIso::IsoSpecifier(0, 0.20, -1);
+  case xAOD::EgammaParameters::etcone25:
+    return IegammaIso::IsoSpecifier(0, 0.25, -1);
+  case xAOD::EgammaParameters::etcone30:
+    return IegammaIso::IsoSpecifier(0, 0.30, -1);
+  case xAOD::EgammaParameters::etcone35:
+    return IegammaIso::IsoSpecifier(0, 0.35, -1);
+  case xAOD::EgammaParameters::etcone40:
+    return IegammaIso::IsoSpecifier(0, 0.40, -1);
+  case xAOD::EgammaParameters::etcone:
+    return IegammaIso::IsoSpecifier(0, 0.45, -1);
+
+  default:
+    ATH_MSG_WARNING("found an unrecognized isolation parameter: " << par);
+    return IegammaIso::IsoSpecifier();
+  }
+}
+
diff --git a/Reconstruction/egamma/egammaTools/src/EMShowerBuilder.h b/Reconstruction/egamma/egammaTools/src/EMShowerBuilder.h
new file mode 100644
index 0000000000000..462d16cd1fe79
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/EMShowerBuilder.h
@@ -0,0 +1,192 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef EGAMMATOOLS_EMSHOWERBUILDER_H
+#define EGAMMATOOLS_EMSHOWERBUILDER_H
+/**
+  @class EMShowerBuilder
+  EMShower data object builder : 
+  - Get pointing information associated to the cluster from the egammaqpoint tool
+  - Get shower depth associated to the cluster from the egammaqgcld tool
+  - Define a Calo Cell list corresponding to EM, HAD, FCAL Calo
+  - egammaIso calculates information concerning isolation behind em clusters 
+  in the hadronic calorimeter and around the em cluster
+  for isolation around em clustr use cone of different sizes
+  - EMTrackIsolation calculates isolation based on tracking information
+  - Calculate shower shapes in all samplings from egammaShowerShape tool
+  - When running on AOD data(defined as samples which do not contain AllCalo 
+    CaloCellContainer) as there is not enough cells, the showers are not 
+    recalculated. On the other hand we try to find the original 
+    electron/photon object which matches the cluster and 
+    keep this information in the new EMShower object 
+
+@author H. Ma 
+@author F. Derue
+*/
+
+// INCLUDE HEADER FILES: 
+#include "GaudiKernel/Algorithm.h"
+#include "GaudiKernel/AlgTool.h"
+#include "egammaBaseTool.h"
+#include "GaudiKernel/ToolHandle.h" 
+
+#include "egammaInterfaces/IEMShowerBuilder.h"
+#include "egammaInterfaces/IegammaShowerShape.h"
+#include "egammaInterfaces/IegammaIso.h"
+#include "egammaInterfaces/IegammaIsoPtCorrection.h"
+#include "egammaInterfaces/IegammaTopoIso.h"
+
+#include "xAODEgamma/EgammaEnums.h"
+#include "xAODEgamma/EgammaFwd.h"
+#include "xAODCaloEvent/CaloClusterFwd.h"
+#include "xAODTracking/TrackParticleContainer.h" 
+#include "xAODTracking/VertexContainer.h" 
+
+#include "xAODEventShape/EventShape.h"
+
+class StoreGateSvc;
+class CaloCellContainer;
+class IEMTrackIsolationTool;
+class IChronoStatSvc;
+
+class EMShowerBuilder : public egammaBaseTool, virtual public IEMShowerBuilder
+{
+ public:
+
+  /** @brief Default constructor*/
+  EMShowerBuilder(const std::string& type,
+                  const std::string& name,
+                  const IInterface* parent);
+
+  /** @brief Destructor*/
+  ~EMShowerBuilder();
+	
+  /** @brief initialize method*/
+  StatusCode initialize();
+  /** @brief standard execute method */
+  virtual StatusCode execute(xAOD::Egamma*);
+  /** @brief method to calculate shower shapes from a CaloCellContainer */
+  virtual StatusCode caloExecute(xAOD::Egamma* eg, const CaloCellContainer* cellcoll);
+  /** @brief method to calculate shower shapes from a CaloCellContainer */
+  virtual StatusCode recoExecute(xAOD::Egamma* eg, const CaloCellContainer* cellcoll,const xAOD::TrackParticleContainer* aTrackParticleContainer = 0);
+  /** @brief finalize method*/
+  StatusCode finalize();
+
+ private:
+  /** @brief method to find parent electron/photon of cluster */
+  const xAOD::Egamma* matchdRParent();
+  /** @brief method to retrieve ShowerBuilder tool */
+  StatusCode RetrieveShowerShapeTool();
+  /** @brief method to retrieve Calo isolation tool */
+  StatusCode RetrieveEMCaloIsolationTool();
+  /** @brief method to retrieve Track isolation tool */
+  StatusCode RetrieveEMTrackIsolationTool();
+  /** @brief method to retrieve pt correction for Calo isolation tool */
+  StatusCode RetrieveEMCaloIsoPtCorrectionTool();
+  /** @brief method to retrieve Topo Calo isolation tool */
+  StatusCode RetrieveEMTopoCaloIsolationTool();
+
+
+  /** @brief method shared by the various execute method to retrieve the cell and cluster containers */
+  StatusCode retrieveContainers();
+  /** @brief calculate shower shapes*/
+  void CalcShowerShape(xAOD::Egamma* eg);
+  /** @brief method to calculate isolation from tracker */
+  void CalcFromTracker(xAOD::Egamma* eg,const xAOD::TrackParticleContainer* aTrackParticleContainer = 0);
+  /** @brief calculate cluster isolation variables */
+  void CalcCaloIsolation(xAOD::Egamma* eg);
+  /** @brief calculate pt corrected cluster isolation variables */
+  void CalcCaloIsolationPtCorrection(xAOD::Egamma* eg);
+
+  /** @brief fill shower detail from shower shape calculation*/
+  void FillEMShowerShape(xAOD::Egamma* eg);
+
+  /** @brief fill local variables with information from calorimeter isolation calculation with default/dummy values */
+  void FillEMShowerIsoVarDefault();
+  /** @brief retrieve information from calorimeter isolation calculation */
+  void FillEMShowerIso(xAOD::Egamma* eg);
+
+  /** @brief method to return the isoSpecifier given parameter */
+  IegammaIso::IsoSpecifier getSpecifier(xAOD::EgammaParameters::IsolationType par) const;
+
+  std::string m_topoCaloClusterInputName;
+
+  /** @brief Cell container*/
+  std::string m_cellsName;     
+  /** @brief vector of calo-id to treat*/
+  std::vector<int> m_caloNums ;     
+
+  /** @brief Tool for shower shape calculation*/
+  ToolHandle<IegammaShowerShape> m_ShowerShapeTool;
+  /** @brief Tool for isolation calculation*/
+  ToolHandle<IegammaIso> m_emCaloIsolationTool;
+  /** @brief Pointer to the EMTrackIsolationTool*/
+  ToolHandle<IEMTrackIsolationTool> m_emTrackIsolationTool;
+  /** @brief Tool for pt-corrected isolation calculation*/
+  ToolHandle<IegammaIsoPtCorrection> m_emCaloIsoPtCorrectionTool;
+  /** @brief Tool for topo calo isolation calculation*/
+  ToolHandle<IegammaTopoIso> m_emTopoCaloIsolationTool;
+
+  /** @brief the CaloCell container */
+  const CaloCellContainer* m_cellcoll;
+  /** @brief the CaloCluster container */
+  const xAOD::CaloCluster* m_clus;
+
+  /** @brief the eventShape container */
+  const xAOD::EventShape* m_evtShape;
+
+
+  /** @brief boolean to print results*/
+  bool m_Print;
+  /** @brief Boolean to call shower shape calculation and filling
+      (NB: this could be important when redoing calculation from AODs) */
+  bool m_UseShowerShapeTool;
+  /** @brief Boolean to call calo isolation variables calculation and filling
+      (NB: this could be important when redoing calculation from AODs) */
+  bool m_UseCaloIsoTool;
+  /** @brief Boolean to call isolation variables calculation and filling */
+  bool m_UseTrackIsoTool;
+  /** @brief */
+  bool m_caloSelection ;
+
+  /** @brief Flag to do isolation for Topo Seeded Photons */
+  bool m_doIsolForTopoSeeded;
+
+  /** @brief boolean to know if we are looking at cosmic data */
+  bool m_isCosmics;
+  
+  /** @brief The isolation cones to do; really vector of enum type egammaParameter::ParamDef */
+  std::vector<int> m_isoTypes;
+
+  /** @brief The isolation cones to do; really vector of enum type egammaParameter::ParamDef */
+  std::vector<int> m_topoIsoTypes;
+
+  // Those below are just variables not configurables 
+
+  // /** @brief Turn on noise isolation calculation */
+  bool m_doNoiseCalc;
+
+  /** @brief the cone sizes for the isolation (used when no noise)*/
+  std::vector<double> m_Rs;
+
+  /** @brief the cone sizes for the isolation (used when at least one noised iso)*/
+  std::vector<IegammaIso::IsoSpecifier> m_specs;
+
+  /** @brief do topo isolation is it is requested */
+  bool m_doTopoIso;
+
+  /** @brief calculate topoetcone40_ptcorrected if topoetcone40 is in the topo isoType list */
+  bool m_dotopoptcor;
+  
+ /** @brief Correct isolation variables based on energy density estimations */
+ bool m_doEnergyDensityCorrection;
+
+
+  // for timing
+  bool m_timing;
+  IChronoStatSvc* m_timingProfile;
+
+};
+
+#endif
diff --git a/Reconstruction/egamma/egammaTools/src/EMTrackIsolationTool.cxx b/Reconstruction/egamma/egammaTools/src/EMTrackIsolationTool.cxx
new file mode 100644
index 0000000000000..72154585663d8
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/EMTrackIsolationTool.cxx
@@ -0,0 +1,130 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "EMTrackIsolationTool.h"
+#include "EventPrimitives/EventPrimitives.h"
+
+#include "xAODEgamma/Egamma.h"
+#include "xAODEgamma/Electron.h"
+#include "xAODEgamma/Photon.h"
+
+#include "xAODEgamma/ElectronxAODHelpers.h"
+#include "xAODEgamma/EgammaxAODHelpers.h"
+
+#include "IsolationTool/ITrackIsolationTool.h"
+#include "xAODPrimitives/IsolationType.h"
+// #include "xAODCaloEvent/CaloCluster.h"
+// #include "CaloUtils/CaloClusterVertexCorrection.h"
+
+
+// ==============================================================
+EMTrackIsolationTool::EMTrackIsolationTool(const std::string& type,
+					   const std::string& name,
+					   const IInterface* parent)
+  : AthAlgTool(type, name, parent)
+{
+  //
+  // default constructor
+  //
+
+  ATH_MSG_DEBUG( "in EMTrackIsolationTool::EMTrackIsolationTool()" );
+
+  // declare interface
+  declareInterface<IEMTrackIsolationTool>(this);
+
+  // track isolation tool
+  declareProperty( "TrackIsolationTool", m_trackIsolationTool,
+		   "the track isolation tool" );
+
+  // primary vertex container name
+  declareProperty( "VertexContainerName", 
+		   m_vertexContainerName="PrimaryVertices",
+		   "primary vertex container name" );
+
+  //To be used for brem associations
+  declareProperty("useBremAssoc", 
+		  m_useBremAssoc=false,
+		  "use track to track assoc after brem");
+  
+
+
+
+
+}
+
+// =================================================================
+EMTrackIsolationTool::~EMTrackIsolationTool()
+{
+  //
+  // destructor
+  //
+  //ATH_MSG_DEBUG( " in EMTrackIsolationTool::~EMTrackIsolationTool()" );
+}
+
+
+// ==================================================================
+StatusCode EMTrackIsolationTool::initialize()
+{
+  //
+  // initialize method
+  //
+
+  ATH_MSG_DEBUG( " in EMTrackIsolationTool::initialize()" );
+
+  // retrieve TrackIsolationTool
+  if ( m_trackIsolationTool.retrieve().isFailure() ) {
+    ATH_MSG_ERROR( "Can't get a handle on the TrackIsolationTool" );
+    return StatusCode::FAILURE;
+  }
+  else ATH_MSG_DEBUG( m_trackIsolationTool << "retrieved" );
+  
+  return StatusCode::SUCCESS;
+}
+
+// ==================================================================
+StatusCode EMTrackIsolationTool::execute(xAOD::Egamma* eg,const xAOD::TrackParticleContainer* aTrackParticleContainer /*= 0*/)
+{
+  //
+  // execute method starting simply from egamma object and EMShower detail
+  //
+
+  ATH_MSG_DEBUG( " in EMTrackIsolationTool::execute()" );
+
+  // protection against bad pointers
+  if (eg==0) return StatusCode::SUCCESS;
+  
+  xAOD::TrackIsolation result;
+  const std::set<const xAOD::TrackParticle*> tracksToExclude = xAOD::EgammaHelpers::getTrackParticles(eg, m_useBremAssoc);
+  
+  
+  const std::vector<xAOD::Iso::IsolationType> isolationTypes{
+    xAOD::Iso::ptcone40, xAOD::Iso::ptcone30, xAOD::Iso::ptcone20
+  };
+    
+  //This is needed due to the order of the arguments in the underlying tool
+  xAOD::Vertex *vx = 0;
+
+  
+
+  if (!m_trackIsolationTool->trackIsolation(result, *eg, isolationTypes,
+					    xAOD::ITrackIsolationTool::UsePointer, vx, 
+					    &tracksToExclude,aTrackParticleContainer ) 
+      || result.ptcones.size() != 3 || result.nucones.size() != 3) {
+    ATH_MSG_WARNING("TrackIsolationTool failed");
+    return StatusCode::SUCCESS;
+  }
+  
+  //The m_trackIsolationTool always returns from the larger to the smaller cone
+
+  m_ptcone20 = result.ptcones[2];
+  m_ptcone30 = result.ptcones[1];
+  m_ptcone40 = result.ptcones[0];
+  m_nucone20 = result.nucones[2];
+  m_nucone30 = result.nucones[1];
+  m_nucone40 = result.nucones[0];
+    
+  return StatusCode::SUCCESS;
+}
+
+
diff --git a/Reconstruction/egamma/egammaTools/src/EMTrackIsolationTool.h b/Reconstruction/egamma/egammaTools/src/EMTrackIsolationTool.h
new file mode 100644
index 0000000000000..21acd05064ad7
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/EMTrackIsolationTool.h
@@ -0,0 +1,93 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+#ifndef EGAMMATOOLS_EMTRACKISOLATIONTOOL_H
+#define EGAMMATOOLS_EMTRACKISOLATIONTOOL_H
+
+/** 
+    @class EMTrackIsolationTool
+    Wrapper tool that calls the TrackIsolationTool from 
+    Reconstruction/RecoTools/TrackIsolationTools to compute
+    the ptcone and regisers it to the EMShower.
+
+    @author Jochen Hartert
+    @author Christos Anastopoulos
+
+*/
+#include "GaudiKernel/ToolHandle.h"
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "egammaInterfaces/IEMTrackIsolationTool.h"
+#include "IsolationTool/ITrackIsolationTool.h"
+
+
+// forward declarations
+#include "xAODEgamma/EgammaFwd.h"
+#include "xAODCaloEvent/CaloClusterFwd.h"
+#include "xAODTracking/TrackParticleContainer.h" 
+#include "xAODTracking/VertexContainer.h" 
+
+class EMTrackIsolationTool : public AthAlgTool, virtual public IEMTrackIsolationTool
+{
+ public:
+  /** @brief Default constructor */
+  EMTrackIsolationTool(const std::string& type,
+		       const std::string& name,
+		       const IInterface* parent);
+
+  /** @brief Default destructor */
+  ~EMTrackIsolationTool();
+
+  /** @brief initialize method */
+  virtual StatusCode initialize();
+  
+
+  /** @brief execute method */
+  virtual StatusCode execute(xAOD::Egamma* eg,const xAOD::TrackParticleContainer* aTrackParticleContainer = 0);
+
+  /** @brief method to retrieve the value of ptcone in a cone 0.2 */
+  double ptcone20() const;
+  /** @brief method to retrieve the value of ptcone in a cone 0.3 */
+  double ptcone30() const;
+  /** @brief method to retrieve the value of ptcone in a cone 0.4 */
+  double ptcone40() const;
+
+  /** @brief method to retrieve the value of nucone in a cone 0.2 */
+  double nucone20() const;
+  /** @brief method to retrieve the value of nucone in a cone 0.3 */
+  double nucone30() const;
+  /** @brief method to retrieve the value of nucone in a cone 0.4 */
+  double nucone40() const;
+
+ private:
+
+  /** @brief the TrackIsolationTool */
+  ToolHandle<xAOD::ITrackIsolationTool> m_trackIsolationTool;
+ 
+  /** @brief vertex container name */
+  std::string m_vertexContainerName;
+
+  /** @brief variable to contain TrackIsolation value */
+  double m_ptcone20;
+  double m_ptcone30;
+  double m_ptcone40;
+  double m_nucone20;
+  double m_nucone30;
+  double m_nucone40;
+
+  /** @brief To be used for brem assoc */
+  bool m_useBremAssoc;
+
+
+};
+
+inline double EMTrackIsolationTool::ptcone20() const { return m_ptcone20;}
+inline double EMTrackIsolationTool::ptcone30() const { return m_ptcone30;}
+inline double EMTrackIsolationTool::ptcone40() const { return m_ptcone40;}
+inline double EMTrackIsolationTool::nucone20() const { return m_nucone20;}
+inline double EMTrackIsolationTool::nucone30() const { return m_nucone30;}
+inline double EMTrackIsolationTool::nucone40() const { return m_nucone40;}
+
+#endif // EGAMMATOOLS_EMTRACKISOLATIONTOOL_H
diff --git a/Reconstruction/egamma/egammaTools/src/EMTrackMatchBuilder.cxx b/Reconstruction/egamma/egammaTools/src/EMTrackMatchBuilder.cxx
new file mode 100644
index 0000000000000..d53e98575ca3a
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/EMTrackMatchBuilder.cxx
@@ -0,0 +1,539 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// INCLUDE HEADER FILES:
+
+#include "EMTrackMatchBuilder.h"
+
+#include "egammaRecEvent/egammaRec.h"
+
+#include "CaloUtils/CaloCellList.h"
+#include "xAODCaloEvent/CaloCluster.h"
+
+#include "xAODTracking/TrackParticle.h" 
+#include "xAODTracking/TrackParticleContainer.h" 
+#include "xAODEgamma/EgammaxAODHelpers.h"
+
+//extrapolation
+#include "egammaInterfaces/IEMExtrapolationTools.h"
+//
+#include "CandidateMatchHelpers.h"
+
+#include <cmath>
+
+//  END OF HEADER FILES INCLUDE
+
+/////////////////////////////////////////////////////////////////
+
+//  CONSTRUCTOR:
+   
+EMTrackMatchBuilder::EMTrackMatchBuilder(const std::string& type,
+                                         const std::string& name,
+                                         const IInterface* parent) : 
+  egammaBaseTool(type, name, parent),
+  m_extrapolationTool("EMExtrapolationTools"),
+  m_isCosmics(false)
+{
+
+  // declare interface
+  declareInterface<IEMTrackMatchBuilder>(this);
+
+  // The following properties are specified at run-time
+  // (declared in jobOptions file)
+
+  // Name of the input track particle container
+  declareProperty("TrackParticlesName", m_TrackParticlesName,
+                  "Name of the input track particle container");
+  
+  // Name of the extrapolation tool
+  declareProperty("ExtrapolationTool",
+                  m_extrapolationTool,
+                  "Name of the extrapolation tool");
+  
+  // Value of broad cut for delta eta
+  declareProperty("broadDeltaEta",m_broadDeltaEta = 0.1,
+                  "Value of broad cut for delta eta");
+
+  // Value of broad cut for delta phi
+  declareProperty("broadDeltaPhi",m_broadDeltaPhi = 0.1,
+                  "Value of broad cut for delta phi");
+
+  //Use rescale in the metric
+  declareProperty("UseRescaleMetric", m_UseRescaleMetric =true,
+		  "Use Rescale Metric");
+
+  // Do second pass with rescale
+  declareProperty("SecondPassRescale", m_SecondPassRescale =true,
+		  "Do second pass with rescale");  
+
+  // Value of narrow cuts
+  declareProperty("narrowDeltaEta", m_narrowDeltaEta = 0.05,
+		  "Value of narrow cut for delta eta");
+
+  declareProperty("narrowDeltaPhi", m_narrowDeltaPhi =0.05,
+		  "Value of the narrowd cut for delta phi ");
+
+  declareProperty("narrowDeltaPhiBrem", m_narrowDeltaPhiBrem =0.1,
+		  "Value of the narrow cut for delta phi  Brem");
+
+  declareProperty("narrowDeltaPhiRescale",  m_narrowDeltaPhiRescale =0.05,
+		  "Value of the narrow cut for delta phi Rescale");
+
+  declareProperty("narrowDeltaPhiRescaleBrem", m_narrowDeltaPhiRescaleBrem =0.1,
+		  "Value of the narrow cut for delta phi Rescale Brem");
+
+  declareProperty("MaxDeltaPhiRescale", m_MaxDeltaPhiRescale=0.2,
+		  "Maximum Value of the deltaPhi rescale");
+
+  // Boolean to use candidate matching
+  declareProperty("useCandidateMatch",
+                  m_useCandidateMatch = true,
+                  "Boolean to use candidate matching");
+
+  //Boolean to favor tracks with Pixel hits
+  declareProperty("useScoring",
+                  m_useScoring= true,
+                  "Boolean to favor tracks with Pixel hits");
+
+  // Boolean for use of cosmics
+  declareProperty("isCosmics",
+                  m_isCosmics=false,
+                  "Boolean for use of cosmics");
+
+  // Boolean to use last measurement for track extrapolation
+  // False means use perigee
+  declareProperty("useLastMeasurement",
+                  m_useLastMeasurement = false,
+                  "Boolean to use last measurement for extrapolation, otherwise use perigee");
+
+}
+
+// ==============================================================
+EMTrackMatchBuilder::~EMTrackMatchBuilder() 
+{ 
+  //
+  // destructor
+  //
+}
+
+// ==============================================================
+StatusCode EMTrackMatchBuilder::initialize()
+{
+  //
+  // initialize
+  //
+
+  ATH_MSG_DEBUG("Initializing EMTrackMatchBuilder");
+
+
+  // the extrapolation tool
+  if(m_extrapolationTool.retrieve().isFailure()){
+    ATH_MSG_ERROR("initialize: Cannot retrieve extrapolationTool " << m_extrapolationTool);
+    return StatusCode::FAILURE;
+  } else {
+    ATH_MSG_DEBUG("initialize: Retrieved extrapolationTool " << m_extrapolationTool);
+  }
+
+
+  // Boolean to use candidate matching
+  if (m_useCandidateMatch) { 
+    ATH_MSG_INFO("initialize: useCandidateMatch is true");
+  }
+  else ATH_MSG_INFO("initialize: useCandidateMatch is turned off");
+
+  return StatusCode::SUCCESS;
+}
+
+// ==============================================================
+StatusCode EMTrackMatchBuilder::executeRec(egammaRec* eg)
+{
+  //
+  // standard egamma execute method
+  // egamma* is an input
+  //
+
+  ATH_MSG_DEBUG("Executing EMTrackMatchBuilder");
+ 
+  // protection against bad pointers
+  if (eg==0) return StatusCode::SUCCESS;
+
+  // retrieve the cluster
+  const xAOD::CaloCluster* cluster = eg->caloCluster();
+  if (cluster == 0) return StatusCode::SUCCESS;
+
+  // check for 0 energy clusters
+  if (cluster->e() == 0.0) {
+    ATH_MSG_WARNING("execute: cluster energy is 0.0! Ignoring cluster.");
+    return StatusCode::SUCCESS;
+  }
+        
+  // retrieve the trackparticle container
+  const xAOD::TrackParticleContainer* trackPC = evtStore()->retrieve< const xAOD::TrackParticleContainer >(m_TrackParticlesName );
+  if( ! trackPC ) {
+    REPORT_MESSAGE( MSG::WARNING )
+      << "Couldn't retrieve TrackParticle container with key: "
+      << m_TrackParticlesName;
+    return StatusCode::SUCCESS;
+  }
+  // Check that the auxiliary store association was made successfully:
+  if( ! trackPC->hasStore() ) {
+    REPORT_MESSAGE( MSG::WARNING )
+      << "No auxiliary store got associated to the TrackParticle container "
+      << "with key: " << m_TrackParticlesName;
+    return StatusCode::SUCCESS;
+  }
+   
+  // call the execute method
+  CHECK( trackExecute(eg, trackPC) );
+  return StatusCode::SUCCESS;
+}
+
+// ===============================================================
+StatusCode EMTrackMatchBuilder::trackExecute(egammaRec* eg, const xAOD::TrackParticleContainer*    trackPC)
+{
+  if (!eg || !trackPC)
+  {
+    ATH_MSG_WARNING("trackExecute: NULL pointer to egammaRec or TrackParticleContainer");
+    return StatusCode::SUCCESS;
+  }
+  
+  // retrieve corresponding cluster
+  const xAOD::CaloCluster* cluster = eg->caloCluster();
+  
+  // check for 0 energy clusters
+  if (cluster && cluster->e() == 0.0) {
+    ATH_MSG_WARNING("trackExecute: cluster energy is 0.0! Ignoring cluster.");
+    return StatusCode::SUCCESS;
+  }
+  ATH_MSG_DEBUG("in trackExecute");
+  
+  // Loop over tracks and fill TrackMatch vector
+  std::vector<TrackMatch> trkMatches; 
+  xAOD::TrackParticleContainer::const_iterator trkIt = trackPC->begin();
+  for (unsigned int trackNumber = 0; trkIt != trackPC->end(); ++trkIt, ++trackNumber) 
+  {
+    bool isTRT = (xAOD::EgammaHelpers::numberOfSiHits(*trkIt) < 4);
+    
+    if (!(isCandidateMatch(cluster, isTRT, (*trkIt), false ) &&
+        inBroadWindow(trkMatches, cluster, trackNumber, isTRT, (*trkIt), Trk::alongMomentum)) && m_isCosmics)
+    {
+      // Second chance for cosmics, flip eta and phi
+      if (isCandidateMatch(cluster, isTRT, (*trkIt), true))
+        inBroadWindow(trkMatches, cluster,  trackNumber, isTRT,  (*trkIt), Trk::oppositeMomentum);
+    }
+  }
+
+  if(trkMatches.size()>0)
+  {
+    //sort the track matches
+    std::sort(trkMatches.begin(), trkMatches.end(), TrackMatchSorter());
+  
+  
+    //set the matching values
+    TrackMatch bestTrkMatch=trkMatches.at(0);
+    for(int i=0; i<4 ;++i){
+      eg->setDeltaEta (i, bestTrkMatch.deltaEta[i]); 
+      eg->setDeltaPhi (i, bestTrkMatch.deltaPhi[i]); 
+      eg->setDeltaPhiRescaled (i, bestTrkMatch.deltaPhiRescaled[i]); 
+    }
+    eg->setDeltaPhiLast(bestTrkMatch.deltaPhiLast);
+    
+    //set the element Links
+    ATH_MSG_DEBUG("============================================");
+    typedef ElementLink<xAOD::TrackParticleContainer> EL;
+    std::vector<EL> trackParticleLinks;
+    trackParticleLinks.reserve (trkMatches.size());
+    std::string key = EL(*trackPC, 0).dataID();
+    for (const TrackMatch& m : trkMatches) {
+      ATH_MSG_DEBUG("Match  dR: "<< m.dR
+		    <<" second  dR: "<< m.seconddR
+		    <<" score: "<< m.score
+		    <<" hitsScore: " << m.hitsScore 
+		    <<" isTRT : "<< m.isTRT);
+      if (key.empty())
+        trackParticleLinks.emplace_back (*trackPC, m.trackNumber);
+      else
+        trackParticleLinks.emplace_back (key, m.trackNumber);
+    }
+    eg->setTrackParticles(trackParticleLinks);
+  }
+  ATH_MSG_DEBUG("================================================");  
+
+  return StatusCode::SUCCESS;
+}
+
+// =================================================================
+bool
+EMTrackMatchBuilder::inBroadWindow(std::vector<TrackMatch>& trackMatches,
+                                   const xAOD::CaloCluster*   cluster, 
+                                   int                  trackNumber,
+                                   bool                 trkTRT,
+                                   const xAOD::TrackParticle* trkPB,
+                                   const Trk::PropDirection dir) const
+{
+  // make position match between cluster and TrackParameters at LAr calorimeter 
+  // 
+  
+  // protection against bad pointers
+  if (cluster==0 || trkPB==0) return false;
+
+  IEMExtrapolationTools::TrkExtrapDef extrapFrom;
+  if (m_useLastMeasurement) {
+    extrapFrom   = IEMExtrapolationTools::fromLastMeasurement;
+  }
+  else {
+    extrapFrom   = IEMExtrapolationTools::fromPerigee;
+  }
+  
+  ATH_MSG_DEBUG("inBroadWindow: extrapolation method From (0 Last, 1 perigee , 2 Rescale) " << extrapFrom);
+  
+  // Now get the delta eta/phi and eta correction at the calorimeter
+  std::vector<bool>    doSample(4, true);
+  std::vector<double>  eta(4, -999.0);
+  std::vector<double>  phi(4, -999.0);
+  // final arrays that we will write
+  // Save the value of deltaPhiRescale. If we do not use rescaled
+  // perigee, we recalculate deltaPhi using rescaled momentum. This
+  // will be saved in EMTrackMatch
+  double deltaPhiRescale  = -999.;
+  double deltaPhiLast     = -999.;
+  // temporary arrays
+  std::vector<double>  deltaEta(4, -999.0);
+  std::vector<double>  deltaPhi(4, -999.0);    
+  std::vector<double>  deltaEtaRes(4, -999.0);
+  std::vector<double>  deltaPhiRes(4, -999.0); 
+  ATH_MSG_DEBUG("### Matching #### ");  
+  if(trkTRT){//TRTSA
+    if(!m_extrapolationTool->matchesAtCalo (cluster, 
+					    trkPB, 
+					    trkTRT,
+					    dir, 
+					    doSample, 
+					    eta,
+					    phi,
+					    deltaEta, 
+					    deltaPhi, 
+					    extrapFrom)) {
+      ATH_MSG_DEBUG("Normal matched Failed deltaPhi/deltaEta " << deltaPhi[2] <<" / "<< deltaEta[2]<<", No Rescale attempted, isTRTSA = " <<trkTRT);
+      return false;
+    }
+  } //end if is TRTSA
+  else{//Silicon tracks
+    if (m_extrapolationTool->getMatchAtCalo (cluster, 
+					     trkPB, 
+					     dir, 
+					     doSample, 
+					     eta,
+					     phi,
+					     deltaEta, 
+					     deltaPhi, 
+					     extrapFrom).isFailure()) 
+		{
+		  if (m_useLastMeasurement) ATH_MSG_DEBUG("Extrapolation from last measurement failed");
+		  else ATH_MSG_DEBUG("Extrapolation from perigee failed");
+		  return false;
+		}
+    //=======================================================================================///
+    //Calculate both always std and rescale
+    IEMExtrapolationTools::TrkExtrapDef extrapFrom1 = IEMExtrapolationTools::fromPerigeeRescaled;
+    std::vector<bool>    doSample1(4, false);
+    doSample1[2] = true; // Only extrapolate to second sampling
+    std::vector<double>  eta1(4, -999.0);
+    std::vector<double>  phi1(4, -999.0);
+    if (m_extrapolationTool->getMatchAtCalo (cluster, 
+					     trkPB, 
+					     dir, 
+					     doSample, 
+					     eta1,
+					     phi1,
+					     deltaEtaRes, 
+					     deltaPhiRes, 
+					     extrapFrom1).isFailure())
+		{
+		  ATH_MSG_DEBUG("Extrapolation from rescaled perigee failed");
+		  return false;
+		}
+    
+    ATH_MSG_DEBUG("Done with extrapolations");
+    
+    deltaPhiRescale = deltaPhiRes[2];
+    //Try to match : First std , then rescale, else failure 
+    if(fabs(deltaEta[2]) < m_narrowDeltaEta &&deltaPhi[2] < m_narrowDeltaPhi && deltaPhi[2] > -m_narrowDeltaPhiBrem){
+      ATH_MSG_DEBUG("Matched with Perigee") ;
+    }
+    else if(m_SecondPassRescale && fabs(deltaEtaRes[2]) < m_narrowDeltaEta &&deltaPhiRes[2] < m_narrowDeltaPhiRescale && deltaPhiRes[2] > -m_narrowDeltaPhiRescaleBrem){
+      ATH_MSG_DEBUG("Not Perigee but matched with Rescale") ;
+    }
+    else{
+      ATH_MSG_DEBUG("Normal matched Failed deltaPhi/deltaEta " << deltaPhi[2] <<" / "<< deltaEta[2]<<", No Rescale attempted, isTRTSA = " <<trkTRT);
+      ATH_MSG_DEBUG("Rescaled matched Failed deltaPhi/deltaEta " << deltaPhiRes[2] <<" / "<< deltaEtaRes[2] );
+      return false;
+    }
+    if(fabs(deltaPhiRes[2]) > m_MaxDeltaPhiRescale)
+    {
+      ATH_MSG_DEBUG("DeltaPhiRescaled above maximum: " << deltaPhiRes[2] << 
+                    " (max: " << m_MaxDeltaPhiRescale << ")" );
+      return false;
+    }
+  } //end if is silicon
+  
+  //In case of extrapolation from perigee keep the dPhi from the last measurement
+  if (!m_useLastMeasurement ) {  
+    IEMExtrapolationTools::TrkExtrapDef extrapFrom1 = IEMExtrapolationTools::fromLastMeasurement;
+    std::vector<bool>    doSample1(4, false);
+    doSample1[2] = true; // Only extrapolate to second sampling
+    std::vector<double>  eta1(4, -999.0);
+    std::vector<double>  phi1(4, -999.0);
+    std::vector<double>  deltaEta1(4, -999.0);
+    std::vector<double>  deltaPhi1(4, -999.0);
+    if (m_extrapolationTool->getMatchAtCalo (cluster, 
+                                             trkPB, 
+                                             dir, 
+                                             doSample1, 
+                                             eta1,
+                                             phi1,
+                                             deltaEta1, 
+                                             deltaPhi1, 
+                                             extrapFrom1).isFailure())
+    {
+      ATH_MSG_DEBUG("Extrapolation from last measurement failed");
+      return false;
+    }
+    
+    //Always the deltaPhiLast will be from the last measurement
+    deltaPhiLast = deltaPhi1[2];
+  }
+  else{
+    //No need to overwrite deltaPhi2 , the deltaPhi2 should be always what used for the match!!!!
+    deltaPhiLast = deltaPhi[2];
+  }
+  ATH_MSG_DEBUG("Rescale dPhi " << deltaPhiRescale);
+  ATH_MSG_DEBUG("dPhi Last measurement " << deltaPhiLast);     
+  
+  //Create Track Match struct here
+  TrackMatch trkmatch;
+  
+  //Add the matching variable to the TrackMAtch
+  for(int i=0; i<4 ;++i){
+    trkmatch.deltaEta[i]=deltaEta.at(i); 
+    trkmatch.deltaPhi[i]=deltaPhi.at(i); 
+    trkmatch.deltaPhiRescaled[i]=deltaPhiRes.at(i); 
+  }  
+  trkmatch.deltaPhiLast=deltaPhiLast; 
+  
+  //Variables used for the sorting. Note both dPhi will be used.
+  trkmatch.isTRT=trkTRT;
+  trkmatch.trackNumber=trackNumber;
+  if (!trkTRT) {
+    if(m_UseRescaleMetric){
+      trkmatch.dR = sqrt(deltaEta[2]*deltaEta[2] + deltaPhiRescale*deltaPhiRescale);
+      trkmatch.seconddR = sqrt(deltaEta[2]*deltaEta[2] + deltaPhi[2]*deltaPhi[2]);
+    }
+    else{
+      trkmatch.dR = sqrt(deltaEta[2]*deltaEta[2] + deltaPhi[2]*deltaPhi[2]);
+      trkmatch.seconddR = sqrt(deltaEta[2]*deltaEta[2] + deltaPhiRescale*deltaPhiRescale);
+    }
+    ATH_MSG_DEBUG("TRTSA = " << trkTRT << " DR " << trkmatch.dR <<" deltaPhi " << deltaPhi[2] <<" deltaEta "<< deltaEta[2]);   
+  }
+  else if (trkTRT){
+    trkmatch.dR = fabs(deltaPhi[2]);
+    trkmatch.seconddR = -999;
+    ATH_MSG_DEBUG("TRTSA = " << trkTRT << " DPhi " << trkmatch.dR <<" deltaPhi " << deltaPhi[2]);   
+  }
+  //Score
+  trkmatch.score=0; 
+  trkmatch.hitsScore=0;
+  if(!trkTRT){  //10 points if it has more than 4 silicon 
+    trkmatch.score+=10 ;   
+    if(m_useScoring){
+      int nPixel=0;
+      uint8_t uint8_value=0;
+      if (trkPB->summaryValue(uint8_value,  xAOD::numberOfPixelDeadSensors)){
+	nPixel+=uint8_value;
+      }
+      if (trkPB->summaryValue(uint8_value,  xAOD::numberOfPixelHits)){
+	nPixel+=uint8_value;
+      }
+      //20 points if it also have pixel
+      if (nPixel > 0)  trkmatch.score+=20;
+      /*Score based on hits to be used for track that are very close to each other at the calo */
+      trkmatch.hitsScore+=(nPixel*5);
+      //Extra for Blayer
+      int nBL =0;
+      if (trkPB->summaryValue(uint8_value,  xAOD::numberOfBLayerHits)){
+	nBL+=uint8_value;
+      }
+      int expectBLayerHit = 0; 
+      if (trkPB->summaryValue(uint8_value,  xAOD::expectBLayerHit)){
+	expectBLayerHit+=uint8_value;
+      }
+      
+      if(!expectBLayerHit ||  nBL>0){
+	trkmatch.hitsScore+=5;
+      }
+      ATH_MSG_DEBUG("Pixel hits : " <<nPixel <<" Blayer : " <<nBL <<" Expected Blayer : " << expectBLayerHit);   
+    }  
+  }
+  ATH_MSG_DEBUG("Score : " <<trkmatch.score <<" hitsScore : " <<trkmatch.hitsScore);   
+
+  trackMatches.push_back(trkmatch);
+  return true;
+}
+
+// =================================================================
+bool
+EMTrackMatchBuilder::isCandidateMatch(const xAOD::CaloCluster*        cluster,
+                                      bool                      trkTRT,
+                                      const xAOD::TrackParticle* track,
+                                      bool                      flip) const
+{
+  // loose cluster-track matching
+  if ( m_useCandidateMatch ) {
+    ATH_MSG_DEBUG("EMTrackMatch builder , broad window");
+    if (cluster == 0 || track == 0) return false;
+    //////
+    const Trk::Perigee candidatePerigee =track->perigeeParameters();
+    double trkPhi = candidatePerigee.parameters()[Trk::phi];
+    double trkEta = candidatePerigee.eta();
+    //Decide whether to try the opposite direction (cosmics)
+    if(flip) {trkPhi = -trkPhi; trkEta = -trkEta;}
+    double r_first=candidatePerigee.position().perp();
+    double z_first=candidatePerigee.position().z();
+    //===========================================================//     
+    double clusterEta=cluster->etaBE(2);
+    bool isEndCap= cluster->inEndcap();
+    double Et= cluster->e()/cosh(trkEta);
+    if(trkTRT){
+      Et = cluster->et();
+    }
+    //===========================================================//     
+    CandidateMatchHelpers m_matchHelper;
+    double etaclus_corrected = m_matchHelper.CorrectedEta(clusterEta,z_first,isEndCap);
+    double phiRot = m_matchHelper.PhiROT(Et,trkEta, track->charge(),r_first ,isEndCap)  ;
+    double phiRotTrack = m_matchHelper.PhiROT(track->pt(),trkEta, track->charge(),r_first ,isEndCap)  ;
+    //===========================================================//     
+    double deltaPhiStd = m_phiHelper.diff(cluster->phiBE(2), trkPhi);
+    double trkPhiCorr = m_phiHelper.diff(trkPhi, phiRot);
+    double deltaPhi2 = m_phiHelper.diff(cluster->phiBE(2), trkPhiCorr);
+    double trkPhiCorrTrack = m_phiHelper.diff(trkPhi, phiRotTrack);
+    double deltaPhi2Track = m_phiHelper.diff(cluster->phiBE(2), trkPhiCorrTrack);
+    //===========================================================//     
+    //check eta match . Both metrics need to fail in order to disgard the track
+    if ( (!trkTRT) && (fabs(cluster->etaBE(2) - trkEta) > 2.*m_broadDeltaEta) && (fabs( etaclus_corrected- trkEta) > 2.*m_broadDeltaEta)){
+      ATH_MSG_DEBUG(" Fails broad window eta match (track eta, cluster eta, cluster eta corrected): ( " << trkEta << ", " << cluster->etaBE(2) <<", "<<etaclus_corrected<<")" );
+      return false;
+    }
+    //It has to fail all metrics in order to be disgarded
+    else if ( (fabs(deltaPhi2) > 2.*m_broadDeltaPhi) && (fabs(deltaPhi2Track) > 2.*m_broadDeltaPhi) && (fabs(deltaPhiStd) > 2.*m_broadDeltaPhi) ){
+      ATH_MSG_DEBUG(" Fails broad window eta match (track eta, cluster eta, cluster eta corrected): ( " << trkEta << ", " << cluster->etaBE(2) <<", "<<etaclus_corrected<<")" );
+      return false;
+    }
+    //if not false returned we end up here
+    return true;
+  }//use candidate match   
+  return true; 
+}
+
+
+
diff --git a/Reconstruction/egamma/egammaTools/src/EMTrackMatchBuilder.h b/Reconstruction/egamma/egammaTools/src/EMTrackMatchBuilder.h
new file mode 100644
index 0000000000000..983294596ae58
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/EMTrackMatchBuilder.h
@@ -0,0 +1,127 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef EGAMMATOOLS_EMTRACKMATCHBUILDER_H
+#define EGAMMATOOLS_EMTRACKMATCHBUILDER_H
+
+/**
+  @class EMTrackMatchBuilder
+          EMTrackMatch data object builder.
+  @author H. Ma
+  @author RD schaffer
+  @author Thomas Koffas
+  @author Christos Anastopoulos
+The matching of a track to a cluster is driven by the EMTrackMatchBuilder tool located in the Reconstruction/egamma/egammaTools package. 
+*/
+
+// INCLUDE HEADER FILES:
+#include "egammaBaseTool.h"
+#include "TrackMatchSorter.h"
+#include "egammaInterfaces/IEMTrackMatchBuilder.h"
+#include "CaloGeoHelpers/CaloPhiRange.h"
+#include "GaudiKernel/ToolHandle.h" 
+#include "xAODCaloEvent/CaloClusterFwd.h"
+#include "xAODTracking/TrackParticleContainerFwd.h" 
+#include "TrkEventPrimitives/PropDirection.h"
+
+class egammaRec;
+class IEMExtrapolationTools;
+
+namespace Reco  { class ITrackToVertex; }
+
+class EMTrackMatchBuilder : public egammaBaseTool, virtual public IEMTrackMatchBuilder
+{
+
+ public:
+
+  /** @brief Default constructor*/
+  EMTrackMatchBuilder(const std::string& type,
+                      const std::string& name,
+                      const IInterface* parent);
+
+  /** @brief Destructor*/
+  ~EMTrackMatchBuilder();
+        
+  /** @brief Gaudi algorithm hooks*/
+  StatusCode initialize();
+  /** @brief execute method*/
+  virtual StatusCode executeRec(egammaRec* eg);
+  /** @brief execute method*/
+  virtual StatusCode trackExecute(egammaRec* eg,  const xAOD::TrackParticleContainer * trackPC);
+
+private:
+
+  /** @brief Compute for tracks passing the loose matching
+   the distance between track extrapolated to 2nd sampling and cluster */
+  bool inBroadWindow(std::vector<TrackMatch>&      trackMatches,
+                     const xAOD::CaloCluster*      cluster, 
+                     int                           trackNumber,
+                     bool                          isTRT,
+                     const xAOD::TrackParticle*     trkPB,
+                     const Trk::PropDirection      dir) const;
+
+  /** @brief Loose track-cluster matching */
+//   bool isCandidateMatch(const CaloCluster&  cluster,
+//                      bool                isTRT,
+//                      const Trk::Perigee* candidatePerigee,
+//                      bool                flip) const;
+  bool isCandidateMatch(const xAOD::CaloCluster*  cluster,
+                        bool                      isTRT,
+                        const xAOD::TrackParticle* track,
+                        bool                       flip) const;
+   
+  
+  // configuration:
+  /** @brief name of TrackParticle container in TDS*/
+  std::string           m_TrackParticlesName; 
+  /** @brief broad cut on deltaEta*/
+  double                m_broadDeltaEta;
+  /** @brief broad cut on deltaPhi*/
+  double                m_broadDeltaPhi;
+  /** @brief narrow cut on deltaEta*/
+  double                m_narrowDeltaEta;
+  /** @brief narrow cut on deltaPhiRescale*/
+  double                m_narrowDeltaPhi;
+  /** @brief narrow cut on deltaPhi for electrons*/
+  double                m_narrowDeltaPhiBrem;
+  /** @brief narrow cut on deltaPhiRescale*/
+  double                m_narrowDeltaPhiRescale;
+  /** @brief narrow cut on deltaPhiRescale for electrons*/
+  double                m_narrowDeltaPhiRescaleBrem;
+  /** @Maximum deltaPhi (Res) allowed for a match */
+  double                m_MaxDeltaPhiRescale;
+  /** @brief flag to turn on/off use of isCandidateMatch*/
+  bool                  m_useCandidateMatch;
+  /** @brief flag to either use last measurement hit or perigee */
+  bool                  m_useLastMeasurement;
+  /** @brief Boolean to favor tracks with Pixel hits*/
+  bool                  m_useScoring;
+  /** @brief Boolean to use Rescale in the metric*/
+  bool m_UseRescaleMetric;
+  /** @brief Boolean to do second pass with Rescale*/
+  bool m_SecondPassRescale;
+  /** @brief helper for */
+  CaloPhiRange          m_phiHelper;
+  /** @brief TrackToCalo extrapolation tool. Handles Trk::ParametersBase as input.
+      Extrapolation starts from the last measurement of the track. The
+      InDetExtrapolator is used, with all proper material effects inside the
+      part of the ID that is traversed. Both charged and neutral particles
+      are handled. */
+  ToolHandle<IEMExtrapolationTools> m_extrapolationTool;
+  /** @brief */
+  bool                  m_isCosmics;
+  int                   m_nSi;
+  int                   m_nTrt;
+};
+
+#endif
+
+
+
+
+
+
+
+
+
diff --git a/Reconstruction/egamma/egammaTools/src/EMVertexBuilder.cxx b/Reconstruction/egamma/egammaTools/src/EMVertexBuilder.cxx
new file mode 100644
index 0000000000000..89a72b52f1923
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/EMVertexBuilder.cxx
@@ -0,0 +1,210 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/***************************************************************************
+EMVertexBuilder.cxx  -  Description
+-------------------
+begin   : 11-03-2011
+authors : Kerstin Tackmann, Bruno Lenzi
+email   : kerstin.tackmann@cern.ch, Bruno.Lenzi@cern.ch
+changes :
+          Nov 2011 (KT) Initial version
+          Mar 2014 (BL) xAOD migration, creates both double and single track vertices
+***************************************************************************/
+
+#include "GaudiKernel/MsgStream.h"
+#include "StoreGate/StoreGateSvc.h"
+
+#include "xAODTracking/TrackParticleContainer.h"
+#include "xAODTracking/VertexContainer.h"
+#include "xAODTracking/VertexAuxContainer.h"
+
+#include "InDetRecToolInterfaces/IVertexFinder.h"
+#include "InDetConversionFinderTools/SingleTrackConversionTool.h"
+
+#include "egammaInterfaces/IEMExtrapolationTools.h"
+
+#include "EMVertexBuilder.h"
+
+EMVertexBuilder::EMVertexBuilder(const std::string& type, const std::string& name, const IInterface* parent) :
+  egammaBaseTool(type, name, parent),
+  m_storeGate(0),
+  m_vertexFinderTool("InDet::InDetConversionFinderTools"),
+  m_singleTrkConvTool("InDet::SingleTrackConversionTool"),
+  m_EMExtrapolationTool("EMExtrapolationTools")
+{
+  declareProperty("InputTrackParticleContainerName", m_inputTrackParticleContainerName = "GSFTrackParticles");
+
+  declareProperty("OutputConversionContainerName",   m_outputConversionContainerName = "GSFConversionVertices");
+
+  declareProperty("VertexFinderTool",                m_vertexFinderTool);
+
+  // Name of the single track conversion tool
+  declareProperty("SingleTrackConversionTool", m_singleTrkConvTool,
+		  "Handle of the single-track conversion tool");
+
+  // Name of the extrapolation tool
+  declareProperty("ExtrapolationTool",
+		  m_EMExtrapolationTool,
+		  "Handle of the extrapolation tool");
+  
+  declareProperty("MaxRadius", m_maxRadius = 800., 
+      "Maximum radius accepted for conversion vertices");
+  
+  declareInterface<IEMVertexBuilder>(this);
+}
+
+// ============================================================
+EMVertexBuilder::~EMVertexBuilder() {}
+
+// ============================================================
+StatusCode EMVertexBuilder::initialize() {
+
+  ATH_MSG_DEBUG( "Initializing " << name() << "...");
+  
+  // Get pointer to StoreGateSvc and cache it :
+  if ( !service( "StoreGateSvc", m_storeGate ).isSuccess() ) {
+    ATH_MSG_ERROR("Unable to retrieve pointer to StoreGateSvc");
+    return StatusCode::FAILURE;
+  }
+
+  // Get the ID VertexFinderTool
+  if ( m_vertexFinderTool.retrieve().isFailure() ) {
+    ATH_MSG_ERROR("Failed to retrieve vertex finder tool " << m_vertexFinderTool);
+    return StatusCode::FAILURE;
+  } else {
+    ATH_MSG_DEBUG( "Retrieved tool " << m_vertexFinderTool);
+  }
+
+  //Retrieve Single Track Conversion Tool
+  if ( m_singleTrkConvTool.retrieve().isFailure() ) {
+    ATH_MSG_ERROR("Cannot retrieve single track conversion tool " << m_singleTrkConvTool);
+    return StatusCode::FAILURE;
+  }
+  else {
+    ATH_MSG_DEBUG("Retrieved  single track conversiontool " << m_singleTrkConvTool);
+  }
+
+  // Retrieve EMExtrapolationTool
+  if(m_EMExtrapolationTool.retrieve().isFailure()){
+    ATH_MSG_ERROR("Cannot retrieve extrapolationTool " << m_EMExtrapolationTool);
+    return StatusCode::FAILURE;
+  } else {
+    ATH_MSG_DEBUG("Retrieved extrapolationTool " << m_EMExtrapolationTool);
+  }
+
+  ATH_MSG_DEBUG( "Initialization successful");
+
+  return StatusCode::SUCCESS;
+}
+
+// ============================================================
+StatusCode EMVertexBuilder::finalize() {
+  return StatusCode::SUCCESS;
+}
+
+// ============================================================
+StatusCode EMVertexBuilder::contExecute()
+{  	
+  StatusCode sc;
+
+  //retrieve TrackParticleContainer and cast into non-const
+  const xAOD::TrackParticleContainer* TrackParticleInputContainer;
+  sc = evtStore()->retrieve(TrackParticleInputContainer, m_inputTrackParticleContainerName);
+  if(sc.isFailure()  ||  !TrackParticleInputContainer){
+    ATH_MSG_ERROR("No TrackParticleInputContainer found in TDS");
+    return sc;
+  }
+  
+  // Call vertex finder to build double-track vertices
+  xAOD::TrackParticleContainer * TPCol = const_cast<xAOD::TrackParticleContainer*>(TrackParticleInputContainer);
+  if (!TPCol)
+  {
+    ATH_MSG_ERROR("Could not cast TrackParticleContainer");
+    return StatusCode::SUCCESS;
+  }
+  std::pair<xAOD::VertexContainer*, xAOD::VertexAuxContainer*> vertices = m_vertexFinderTool->findVertex(TPCol);
+  if (!vertices.first || !vertices.second)
+  {
+    ATH_MSG_ERROR("Null pointer to conversion container");
+    return StatusCode::SUCCESS;
+  }
+  ATH_MSG_DEBUG("New conversion container size: " << vertices.first->size());
+  
+  // Add remaining tracks as single track vertices
+//   addSingleTrackVertices(TrackParticleInputContainer, vertices.first);
+//   ATH_MSG_DEBUG("Conversion container size with single tracks: " << vertices.first->size());
+  
+  // Remove vertices with radii above m_maxRadius   
+  xAOD::VertexContainer::iterator itVtx = vertices.first->begin();
+  while ( itVtx != vertices.first->end() )
+  {
+		if ( (*itVtx)->position().perp() > m_maxRadius )
+      itVtx = vertices.first->erase(itVtx);
+    else
+      ++itVtx;
+  }
+  
+  // Decorate the vertices with the momentum at the conversion point and 
+  // etaAtCalo, phiAtCalo (extrapolate each vertex)
+  float etaAtCalo = -9999., phiAtCalo = -9999.;
+  for (itVtx = vertices.first->begin(); itVtx != vertices.first->end(); ++itVtx )
+  {
+    xAOD::Vertex *vertex = *itVtx;
+    
+    // false is to force the extrapolation
+    Amg::Vector3D momentum = m_EMExtrapolationTool->getMomentumAtVertex(*vertex, false);
+    vertex->auxdata<float>("px") = momentum.x();
+    vertex->auxdata<float>("py") = momentum.y();
+    vertex->auxdata<float>("pz") = momentum.z();
+    
+    if (!m_EMExtrapolationTool->getEtaPhiAtCalo(vertex, &etaAtCalo, &phiAtCalo))
+    {
+      ATH_MSG_DEBUG("getEtaPhiAtCalo failed!");
+    }
+    
+    // Decorate vertex with etaAtCalo, phiAtCalo
+    vertex->auxdata<float>("etaAtCalo") = etaAtCalo;
+    vertex->auxdata<float>("phiAtCalo") = phiAtCalo;
+  }
+  
+  
+  //put the new conversion vertex container and its aux container into StoreGate
+  ATH_MSG_DEBUG("Writing container " << m_outputConversionContainerName);
+  CHECK( evtStore()->record(vertices.first, m_outputConversionContainerName) );
+  CHECK( evtStore()->record(vertices.second, m_outputConversionContainerName + "Aux.") );
+  
+  // FIXME: remove. Trying to retrieve the container to understand why it is not in the xAOD...
+  xAOD::VertexContainer *vx = 0;
+  CHECK( evtStore()->retrieve(vx, m_outputConversionContainerName) );
+  ATH_MSG_DEBUG("Vertex container: " << vx);
+  
+
+  return StatusCode::SUCCESS;
+}
+// ============================================================
+void EMVertexBuilder::addSingleTrackVertices(const xAOD::TrackParticleContainer* tracks,
+                                             xAOD::VertexContainer* vertices) const
+{
+  if (!tracks || !vertices) return;
+
+  // Create a set of tracks that do belong to vertices
+  std::set<const xAOD::TrackParticle*> tracksInVertices;
+  xAOD::VertexContainer::const_iterator itVtx = vertices->begin();
+  for ( ; itVtx != vertices->end(); ++itVtx)
+    for (const auto& trackElement : (*itVtx)->trackParticleLinks() )
+      tracksInVertices.insert( trackElement.cachedElement() );
+  
+  ATH_MSG_DEBUG("Size of set with tracks: " << tracksInVertices.size());
+    
+  // Loop over tracks and create vertices for those that are not in the set
+  xAOD::TrackParticleContainer::const_iterator itTP = tracks->begin();
+  for ( ; itTP != tracks->end(); ++itTP)
+  {
+    if ( tracksInVertices.find(*itTP) != tracksInVertices.end() ) continue;
+    m_singleTrkConvTool->buildSingleTrackParticleConversion(*itTP, vertices);
+  }
+
+}
+
diff --git a/Reconstruction/egamma/egammaTools/src/EMVertexBuilder.h b/Reconstruction/egamma/egammaTools/src/EMVertexBuilder.h
new file mode 100644
index 0000000000000..c8f00962b04de
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/EMVertexBuilder.h
@@ -0,0 +1,70 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef EMVERTEXBUILDER_H
+#define EMVERTEXBUILDER_H
+
+#include "GaudiKernel/ToolHandle.h"
+#include "egammaInterfaces/IEMVertexBuilder.h"
+#include "egammaBaseTool.h"
+#include "xAODTracking/TrackParticleContainerFwd.h"
+#include "xAODTracking/VertexContainerFwd.h"
+
+class  StoreGateSvc;
+
+namespace InDet
+{
+  class IVertexFinder;
+  class SingleTrackConversionTool;
+}
+
+class IEMExtrapolationTools;
+
+/**
+   @class EMVertexBuilder
+   This tool builds ID vertices from a given TrackParticleContainer
+   @author Kerstin Tackmann (based on work by many others)
+*/
+
+class EMVertexBuilder : virtual public IEMVertexBuilder, public egammaBaseTool {
+
+	public:
+		EMVertexBuilder (const std::string& type,const std::string& name, const IInterface* parent);
+		virtual ~EMVertexBuilder();
+
+		virtual StatusCode initialize();
+		virtual StatusCode finalize();
+
+		virtual StatusCode contExecute();
+
+	private:
+	
+	  /** Maximum radius accepted for conversion vertices **/
+	  float m_maxRadius;
+
+    /** @brief create single track vertices from tracks that are not part of other vertices **/
+    void addSingleTrackVertices(const xAOD::TrackParticleContainer*,
+                                xAOD::VertexContainer*) const;
+
+
+		StoreGateSvc          *m_storeGate;
+		
+		/** @brief TrackParticle container input name*/
+		std::string            m_inputTrackParticleContainerName;
+
+		/** @brief conversion container output name*/
+		std::string            m_outputConversionContainerName;
+
+    /** @brief Tool to find vertices (creates double-track conversions) */
+		ToolHandle<InDet::IVertexFinder>    m_vertexFinderTool;
+
+    /** @brief Tool to create single-track conversions */
+    ToolHandle<InDet::SingleTrackConversionTool> m_singleTrkConvTool;
+
+    /** @brief EMExtrapolationTool */
+    ToolHandle<IEMExtrapolationTools>  m_EMExtrapolationTool;
+    		
+};
+
+#endif // EMVERTEXBUILDER_H 
diff --git a/Reconstruction/egamma/egammaTools/src/FourMomCombiner.cxx b/Reconstruction/egamma/egammaTools/src/FourMomCombiner.cxx
new file mode 100644
index 0000000000000..6378a647d00f7
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/FourMomCombiner.cxx
@@ -0,0 +1,836 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "FourMomCombiner.h"
+
+#include "FourMom/EigenP5Jacobiand0z0PhiThetaqOverP2d0z0PhiEtaP.h"
+#include "FourMom/ErrorMatrixEEtaPhiM.h"
+
+#include "egammaUtils/ParameterDownWeighter.h"
+#include "egammaUtils/WeightedMeanCalc.h"
+#include "egammaUtils/EMConversionUtils.h"
+#include "CaloUtils/CaloVertexedCluster.h"
+//#include "egammaInterfaces/IEMExtrapolCaloConversion.h"
+
+//NEW xAOD INCLUDES.
+#include "xAODEgamma/EgammaDefs.h"
+#include "xAODEgamma/EgammaEnums.h"
+#include "xAODEgamma/EgammaxAODHelpers.h"
+#include "xAODTracking/Vertex.h"
+#include "xAODTracking/TrackParticle.h"
+
+#include "xAODEgamma/Egamma.h"
+#include "xAODEgamma/Electron.h"
+#include "xAODEgamma/Photon.h"
+#include "xAODEgamma/ElectronContainer.h"
+#include "xAODEgamma/PhotonContainer.h"
+#include "xAODCaloEvent/CaloCluster.h"
+#include  "xAODCaloEvent/CaloClusterContainer.h" 
+#include "xAODTracking/TrackParticleContainer.h" 
+#include "xAODTracking/VertexContainer.h" 
+
+#include "VxVertex/VxContainer.h"
+#include "xAODTracking/Vertex.h"
+#include "xAODTracking/TrackParticle.h"
+#include "xAODTracking/VertexContainer.h"
+#include "xAODTracking/TrackParticleContainer.h"
+#include "xAODCaloEvent/CaloCluster.h"
+#include "xAODCaloEvent/CaloClusterContainer.h"
+#include "xAODEgamma/EgammaxAODHelpers.h"
+
+using namespace CLHEP;
+using namespace CombinationFlags;
+using namespace CombinationTypes;
+
+using CLHEP::HepVector;
+
+//Constructor.
+FourMomCombiner::FourMomCombiner(const std::string& type,
+				 const std::string& name,
+				 const IInterface* parent) :
+  AthAlgTool(type, name, parent),
+  m_usedPoverP(false),
+  m_dPoverP(1.),
+  m_useCombination(false),
+  m_applyTrackOnly(false),
+  m_EPsigmacut(3.),
+  m_dPoverPcut(0.3),
+  m_EPoverPcut(0.2),
+  m_applytrackOnlyEcut(15*GeV),
+  m_minPtTRT(2E3),
+  m_trkVector(5),
+  m_trkMatrix(5,5),
+  m_clusVector(5),
+  m_clusMatrix(5,5),
+  m_combVector(5),
+  m_combMatrix(5,5),
+  m_combType(COVMAT),
+  DEFAULT_QOVERP_ERROR(1)
+  //m_EMExtrapolCaloConversion("EMExtrapolCaloConversion")
+  
+{
+
+  m_trkVector.setZero();
+  m_trkMatrix.setZero();
+  m_clusVector.setZero();
+  m_clusMatrix.setZero();
+  m_combVector.setZero();
+  m_combMatrix.setZero();
+    
+  // Declare interface.
+  declareInterface<IFourMomCombiner>(this);
+
+  declareProperty("m_combType",m_combType,
+		  "Decides whether to do full covariance method, or single-shot Kalman update");
+
+  declareProperty("MinPtTRT", 
+		  m_minPtTRT = 2000.0, 
+		  "Minimum pT for TRT-only tracks for them to be combined");
+
+  declareProperty( "applyTrackOnly",
+		   m_applyTrackOnly = false,
+		   "Use Track P if E/P and E < applytrackOnlyEcut");
+
+  declareProperty( "applytrackOnlyEcut",
+		   m_applytrackOnlyEcut = 15*GeV,
+		   "cut on E in order to use track P");
+
+  //Variables for dP/P.
+  declareProperty("usedPoverP",
+		  m_usedPoverP = false,
+		  "Judge combination by dP/P rather than sigma");
+
+  declareProperty("m_dPoverPcut",
+		  m_dPoverPcut=0.3,
+		  "Cutoff for combination when judging by dP/P + |E-p|/p");
+
+  declareProperty("m_EPoverPcut",
+		  m_EPoverPcut=0.2,
+		  "Cutoff for combination when judging by dP/P + |E-p|/p");
+
+}
+
+//Destructor.
+FourMomCombiner::~FourMomCombiner() {}
+
+StatusCode FourMomCombiner::initialize() {
+
+  ATH_MSG_DEBUG(" Initializing FourMomCombiner");
+
+  //NEW: Use egamma calibration tool for cluster energy resolution.
+  //Need a way to tell 2011 vs. 2012.
+  //bool m_is2012(true);
+  /*
+  eRescaler = new AtlasRoot::egammaEnergyCorrectionTool();
+  eRescaler->setFileName("ElectronPhotonFourMomentumCorrection/data/egammaEnergyCorrectionData.root");
+  if (m_is2012) {
+    eRescaler->setESModel(egEnergyCorr::es2012c);
+  }else {
+    eRescaler->setESModel(egEnergyCorr::es2011c);
+  }
+  eRescaler->initialize();
+  */
+
+  return StatusCode::SUCCESS;
+
+}
+
+StatusCode FourMomCombiner::ClusterExecute(xAOD::Egamma *eg,
+					   const Amg::Vector3D& vtx)
+
+{
+
+  //A few security checks.                                                                                                                                                         
+  if (eg == NULL) {
+    ATH_MSG_DEBUG("No Egamma Object");
+    return StatusCode::FAILURE;
+  }
+
+  //Fill only cluster, since there are no track parameters.
+  fillClusterParameters(eg, vtx);
+
+  return StatusCode::SUCCESS;
+
+}
+
+StatusCode FourMomCombiner::TrackClusterExecute(xAOD::Egamma *eg,
+						unsigned int index, 
+						bool hasSi)
+
+{
+
+  // This should only be called if it's a conversion or an electron;
+  // the other 
+
+  //A few security checks.
+  if (eg == NULL) {
+    ATH_MSG_ERROR("No Egamma Object");
+    return StatusCode::FAILURE;
+  }
+
+  //Do preliminary execution for cluster parameters.
+  if (!eg) {
+    ATH_MSG_WARNING("FourMomCombiner: Filling of cluster parameters failed!");
+    return StatusCode::SUCCESS;
+  }
+  
+  //Load track parameters from egamma object.
+  fillTrackVectorElements(eg,index);
+  
+  int charge(0);
+  if (isElectron(eg)) {
+    xAOD::Electron* el = dynamic_cast<xAOD::Electron*> (eg);
+    charge = el->trackParticle(index)->charge();
+  }
+  
+  //Fill matrix here.
+  fillTrackMatrixElements(eg,index,charge);
+
+  //Decide how to combine first.
+  MakeCombinationDecisionElectron(eg, index, hasSi);
+
+  //Perform combination.
+  StatusCode sc = execute();
+
+  if (sc.isFailure()) {
+    ATH_MSG_WARNING("FourMomCombiner: execute did not return success!");
+    return sc; 
+  }
+
+  return StatusCode::SUCCESS;
+
+}
+
+StatusCode FourMomCombiner::execute() {
+
+  if (m_combType==KALMAN) {
+    ATH_MSG_DEBUG("Performing E-p combination using Kalman update");
+    setFromKalmanUpdate();
+  } else {
+
+    ATH_MSG_DEBUG("Performing E-p combination using full covariance matrix method");
+
+    //enum parameters.
+    int is1  = m_par1;
+    int is2  = m_par2;
+    int is3  = m_par3;
+    
+    int flag = m_combFlag;
+    
+    //Get cluster and track vectors & matrices
+    EigenVectorAndMatrix clusVM(m_clusVector, m_clusMatrix);
+    EigenVectorAndMatrix trkVM (m_trkVector,  m_trkMatrix);
+    
+    //Downweight parameter(s): 
+    switch (flag) {
+    case TRACK:
+      ParameterDownWeighter::getDownWeightedVM(clusVM, trkVM, is1);
+      ParameterDownWeighter::getDownWeightedVM(clusVM, trkVM, is2);
+      break;
+    case TRACKONLY:
+      ParameterDownWeighter::getDownWeightedVM(clusVM, trkVM, is1);
+      ParameterDownWeighter::getDownWeightedVM(clusVM, trkVM, is2);
+      ParameterDownWeighter::getDownWeightedVM(clusVM, trkVM, is3);
+      break;
+    case TRACK_TRT:
+      ParameterDownWeighter::getDownWeightedVM(clusVM, trkVM, is1);
+      ParameterDownWeighter::getDownWeightedVM(trkVM, clusVM, is2);
+      break;
+    case CLUSTER:
+      ParameterDownWeighter::getDownWeightedVM(clusVM, trkVM, is1);
+      ParameterDownWeighter::getDownWeightedVM(clusVM, trkVM, is2);
+      ParameterDownWeighter::getDownWeightedVM(trkVM, clusVM, is3);
+      break;
+    case CLUSTER_TRT:
+      ParameterDownWeighter::getDownWeightedVM(clusVM, trkVM, is1);
+      ParameterDownWeighter::getDownWeightedVM(trkVM, clusVM, is2);
+      ParameterDownWeighter::getDownWeightedVM(trkVM, clusVM, is3);
+      break;
+    }
+    
+    EigenVectorAndMatrix wVM = WeightedMeanCalc::getWeightedMean(clusVM, trkVM);  
+    
+    //Set the combined parameters in the object.
+    m_combVector = wVM.getVector();
+    m_combMatrix = wVM.getMatrix();
+
+  }
+
+  return StatusCode::SUCCESS;
+  
+}
+
+StatusCode FourMomCombiner::finalize() {
+
+  return StatusCode::SUCCESS;
+  
+}
+
+void FourMomCombiner::setDownweightParameters(DownWeightPar s1, DownWeightPar s2, DownWeightPar s3, CombinationFlag flag) {        
+
+  //Set the enum parameters.
+  m_par1 = s1; m_par2 = s2; m_par3 = s3;
+  m_combFlag = flag;
+
+}
+
+//Alternate E-p combination method: Kalman update of track parameters
+//with cluster energy measurement.
+//(method provided by A. Morley).
+void FourMomCombiner::setFromKalmanUpdate() {
+
+  //Define dimensions for ease of use.
+  int first(1), second(5);
+
+  EigenVectorAndMatrix clusVM(m_clusVector,m_clusMatrix);
+  EigenVectorAndMatrix trkVM(m_trkVector, m_trkMatrix);
+
+  //Define track parameters, covariance matrix.
+  Amg::VectorX    pj(m_trkVector);
+  Amg::MatrixX    Cj(m_trkMatrix);
+
+  //Set a (first) size vector for cluster parameters to use in update, and (first) x (first) size matrix.
+  //Currently just using cluster energy to update. Could also use eta, phi, in principle.
+  Amg::VectorX m(first); 
+  m.setZero();
+  m[0] = (m_clusVector)[4];
+  Amg::MatrixX V(first,first); 
+  V.setZero();
+  V(0,0) = m_clusMatrix(4,4);
+
+  //Define observation model matrix, H.
+  Amg::MatrixX H(first,second);
+  H.setZero();
+  H(0,second) = 1.;
+
+  //Build measurement residual.
+  Amg::VectorX tmp1(m); tmp1 += H*pj;
+
+  //Define results objects.
+  Amg::VectorX    p(second);
+  p.setZero();
+  Amg::MatrixX    C(second,second);
+  C.setZero();
+
+  //Intermediate results.
+  Amg::MatrixX Rinv(first,first);
+  Rinv.setZero();
+  Amg::MatrixX Rtmp(first,first);
+  Rtmp.setZero();
+  Amg::MatrixX K(second,first);
+  K.setZero();
+  Amg::MatrixX Ctmp(second,second);
+  Ctmp.setZero();
+  Amg::MatrixX tmp2(second,first);
+  tmp2.setZero();
+  Amg::MatrixX HT(second,first);
+  HT.setZero();
+
+  //Perform the update.
+  tmp2 = Cj * H.transpose();
+  Rtmp = H * tmp2;
+  Rinv = (V + Rtmp).inverse();
+
+  K = tmp2 * Rinv;
+
+  //Pass updated measurement & covariance.
+  p = pj; p += K * tmp1;
+
+  Ctmp = K * tmp2.transpose();
+  //C.assign(Cj - Ctmp);
+  C = Cj - Ctmp;
+
+  // If track momentum is > 2sigma from the calo energy measurment, 
+  //use simple model instead.
+  if( tmp1[0]*tmp1[0] > 4.0 * ( Cj(4,4) + V(0,0)) ) {
+    
+    C(0,4) = 0;
+    C(1,4) = 0;
+    C(2,4) = 0;
+    C(3,4) = 0;
+    C(4,0) = 0;
+    C(4,1) = 0;
+    C(4,2) = 0;
+    C(4,3) = 0;    
+    C(4,4) = V(0,0);
+    
+    p[4]  = m[0];
+    
+  }
+
+  //Set the updated parameters, matrix.
+  m_combVector = p; m_combMatrix = C;
+
+}
+
+//NOTE: All we need to do here is rearrange the elements of the matrix we already
+//have in the (d0, z0, phi, eta, P) representation to make the (E, eta, phi, M)
+//representation.
+const AmgMatrix(4,4) FourMomCombiner::get4x4CombinedErrorMatrix() const{
+
+  AmgMatrix(4,4) combmatrix;
+  combmatrix.setZero();
+
+  combmatrix(0,0) = m_combMatrix(4,4);
+  combmatrix(1,1) = m_combMatrix(3,3);
+  combmatrix(2,2) = m_combMatrix(2,2);
+
+  combmatrix.fillSymmetric(0,1,m_combMatrix(4,3));
+  combmatrix.fillSymmetric(0,2,m_combMatrix(4,2));
+  combmatrix.fillSymmetric(1,2,m_combMatrix(3,2));
+
+
+  return combmatrix;
+
+}
+
+//Returns the track matrix, minus any correlations to energy, and sigma(Eclus,Eclus)
+//in place of momentum.
+
+const AmgMatrix(4,4) FourMomCombiner::get4x4ClusterErrorMatrix() const{
+
+  AmgMatrix(4,4) clustermatrix;
+  clustermatrix.setZero();
+
+  clustermatrix(0,0) = m_clusMatrix(4,4);
+  clustermatrix(1,1) = m_clusMatrix(3,3);
+  clustermatrix(2,2) = m_clusMatrix(2,2);
+
+  return clustermatrix;
+
+}
+
+//============================================
+//Routines to fill cluster, track parameters.
+
+
+//bool FourMomCombiner::fillTrackVectorElements(const Trk::Perigee* perigee) {
+bool FourMomCombiner::fillTrackVectorElements(xAOD::Egamma *eg, int index)
+{
+
+  if (eg == 0) return false;
+
+  xAOD::DefiningParameters_t perigee;
+  perigee.setZero();
+
+  if (isElectron(eg)) {
+    xAOD::Electron* el = dynamic_cast<xAOD::Electron*> (eg);
+    if (el) {
+      perigee            = el->trackParticle(index)->definingParameters();
+      m_trkVector[3]     = el->trackParticle(index)->eta();
+    }
+  } else {
+    return false;
+  }
+
+  //Load track parameters from egamma object.
+  double momentum(0.);
+  m_trkVector[0] = perigee(0);
+  m_trkVector[1] = perigee(1);
+  m_trkVector[2] = perigee(2);
+  //m_trkVector[3] = perigee->eta();
+  const double qOverP = perigee(4);
+  if (qOverP != 0) {
+    momentum = fabs(1./ qOverP);
+  } else {
+    momentum = DEFAULT_MOMENTUM;
+  }
+  m_trkVector[4] = momentum;
+
+  return true;
+  
+}
+
+//First make typical covariance matrix, then use Jacobian
+//to transform to the relevant representation (d0, z0, phi, eta, P).
+//bool FourMomCombiner::fillTrackMatrixElements(const Trk::Perigee* perigee, int charge) {
+bool FourMomCombiner::fillTrackMatrixElements(xAOD::Egamma *eg, int index, int charge)
+{
+
+  ATH_MSG_DEBUG("fillTrackMatrixElements: Getting covariance matrix ...");
+
+  if (eg == 0) return false;
+
+  xAOD::ParametersCovMatrix_t covmat;
+  covmat.setZero();
+
+  xAOD::DefiningParameters_t  perigee;
+  perigee.setZero();
+
+  if (isElectron(eg)) {
+    xAOD::Electron* el = dynamic_cast<xAOD::Electron*> (eg);
+    covmat  = el->trackParticle(index)->definingParametersCovMatrix();
+    perigee = el->trackParticle(index)->definingParameters();
+  } else {
+    return false;
+  }
+
+  //Get initial matrix in (theta, q/P) representation.
+  //const AmgSymMatrix(5) *covmat(perigee->covariance());
+  AmgSymMatrix(5)  emnew;
+  emnew.setZero();
+
+  ATH_MSG_DEBUG("fillTrackMatrixElements: Got covariance matrix ...");
+
+  //Case of old single conversion.
+  if ( covmat.rows() == 3) {
+    emnew(0,0) = emnew(1,1) = 10e10;
+    emnew(2,2) = covmat(0,0);
+    emnew(3,3) = covmat(1,1);
+    emnew(4,4) = covmat(2,2);
+
+    emnew.fillSymmetric(2,3,covmat(0,1));
+    emnew.fillSymmetric(2,4,covmat(0,2));
+    emnew.fillSymmetric(3,4,covmat(1,2));
+  } else {
+    emnew = covmat;
+  }
+
+  //Transform it to the one we want.
+  AmgMatrix(5,5) m;
+  m.setZero();
+  ATH_MSG_DEBUG("fillTrackMatrixElements: Creating Jacobian ...");
+
+  //EigenP5Jacobiand0z0PhiThetaqOverP2d0z0PhiEtaP J(perigee->parameters()[Trk::theta], 
+  //						  charge, 
+  //						  m_trkVector[4]);
+
+  EigenP5Jacobiand0z0PhiThetaqOverP2d0z0PhiEtaP J(perigee(3),
+						  charge, 
+						  m_trkVector[4]);
+
+  ATH_MSG_DEBUG("fillTrackMatrixElements: Got Jacobian, performing similarity transform ...");
+
+  //m = emnew.similarity(J);
+  m = J * (emnew * J.transpose());
+  m_trkMatrix = m;
+
+  ATH_MSG_DEBUG("From fillTrackMatrixElements: " << m_trkMatrix);
+
+  return true;
+}
+
+bool FourMomCombiner::fillClusterParameters(const xAOD::Egamma* eg)
+{
+
+  if (!eg) return false;
+
+  const xAOD::CaloCluster* aCluster = eg->caloCluster();
+  if (aCluster == NULL) return false;
+
+  //if (forcePhoton) ATH_MSG_DEBUG("Treating all objects as photons");
+  
+  //Set cluster parameter elements.
+  const double clusterPhi    = aCluster->phi();
+  const double clusterEta    = aCluster->eta();
+  const double clusterEnergy = aCluster->e();
+
+  //ATH_MSG_DEBUG("Cluster pointing eta:" << eg->detailValue(egammaParameters::etap));
+  
+  m_clusVector[2] = clusterPhi;
+  m_clusVector[3] = caloEta(eg, clusterEta);
+  m_clusVector[4] = clusterEnergy;
+  
+  ATH_MSG_DEBUG("From fillClusterParameters: " << m_clusVector);
+
+  //Set relevant cluster matrix elements.
+  const double clusterEtaError    = getClusterEtaError(eg);
+  const double clusterPhiError    = getClusterPhiError(eg);
+  const double clusterEnergyError = getClusterEnergyError(eg);
+  
+  m_clusMatrix(0,0) = m_clusMatrix(1,1) = 1E11;
+  m_clusMatrix(2,2) = clusterPhiError * clusterPhiError;
+  m_clusMatrix(3,3) = clusterEtaError * clusterEtaError;
+  m_clusMatrix(4,4) = clusterEnergyError * clusterEnergyError;
+
+  ATH_MSG_DEBUG("From fillClusterParameters: " << m_clusMatrix);
+   
+  return true;
+   
+}
+
+
+bool FourMomCombiner::fillClusterParameters(const xAOD::Egamma* eg, 
+					    const Amg::Vector3D& vtx)
+{
+
+  if (!eg) return false;
+
+  const xAOD::CaloCluster* aCluster = eg->caloCluster();
+  if (aCluster == NULL) return false;
+
+  //if (forcePhoton) ATH_MSG_DEBUG("Treating all objects as photons");
+
+  const Amg::Vector3D vect(vtx);
+
+  //CaloClusterChangeVertexState mychange(aCluster, &vect);
+  const xAOD::CaloVertexedCluster vtxCluster(*aCluster,xAOD::CaloCluster::CALIBRATED,vtx);
+  
+  //Set cluster parameter elements.
+  const double clusterPhi    = vtxCluster.phi();
+  const double clusterEta    = vtxCluster.eta();
+  const double clusterEnergy = vtxCluster.e();
+
+  //ATH_MSG_DEBUG("Cluster pointing eta:" << eg->detailValue(egammaParameters::etap));
+  
+  m_clusVector[2] = clusterPhi;
+  m_clusVector[3] = caloEta(eg, clusterEta);
+  m_clusVector[4] = clusterEnergy;
+  
+  ATH_MSG_DEBUG("From fillClusterParameters: " << m_clusVector);
+
+  //Set relevant cluster matrix elements.
+  const double clusterEtaError    = getClusterEtaError(eg);
+  const double clusterPhiError    = getClusterPhiError(eg);
+  const double clusterEnergyError = getClusterEnergyError(eg);
+  
+  m_clusMatrix(0,0) = m_clusMatrix(1,1) = 1E11;
+  m_clusMatrix(2,2) = clusterPhiError * clusterPhiError;
+  m_clusMatrix(3,3) = clusterEtaError * clusterEtaError;
+  m_clusMatrix(4,4) = clusterEnergyError * clusterEnergyError;
+
+  ATH_MSG_DEBUG("From fillClusterParameters: " << m_clusMatrix);
+   
+  return true;
+   
+}
+
+//============================================
+//Routines to calculate cluster errors.
+double FourMomCombiner::getClusterPhiError(const xAOD::Egamma* eg) const
+{
+
+  if (!eg) return 0.;
+  //if (forcePhoton) ATH_MSG_DEBUG("Treating all objects as photons");
+
+  /*  
+  EMClusterErrorsParametrizations::Type tp = isElectron(eg, forcePhoton) ? 
+    EMClusterErrorsParametrizations::ELECTRON : 
+    EMClusterErrorsParametrizations::PHOTON;
+  */
+  
+  const xAOD::CaloCluster* aCluster = eg->caloCluster();
+  if (aCluster == NULL /*|| pars == NULL*/) return 1E11;
+
+  return 1e-3;
+  
+  //return pars->getPhiMatrix(tp).getError(caloEta(eg, aCluster->eta()), aCluster->e());
+
+}
+
+double FourMomCombiner::getClusterEtaError(const xAOD::Egamma* eg) const 
+{
+
+  if (!eg) return 0.;
+  //if (forcePhoton) ATH_MSG_DEBUG("Treating all objects as photons");
+
+  /*
+  EMClusterErrorsParametrizations::Type tp = isElectron(eg, forcePhoton) ? 
+    EMClusterErrorsParametrizations::ELECTRON : 
+    EMClusterErrorsParametrizations::PHOTON;
+  */
+
+  const xAOD::CaloCluster* aCluster = eg->caloCluster();
+  double eta = (aCluster) ?  caloEta(eg, aCluster->eta()) : 0;
+  if (fabs(eta) > 8) eta = 8.0;
+  if (1 /*pars == NULL*/) {
+
+    const double clusterEnergyGeV = 100.0; //GeV - just use 100 as the default
+    const double sigma_theta = 0.07 /sqrt(clusterEnergyGeV);
+    const double theta = 2.*atan(exp(eta));
+    return ( fabs(sigma_theta/sin(theta)) );
+
+  }
+
+  return 0.;
+
+  //return pars->getEtaMatrix(tp).getError(eta, 
+  //                                     aCluster ? aCluster->e(): 0);
+}
+
+double FourMomCombiner::getClusterEtaPosError(const xAOD::Egamma* eg) const
+{
+
+  if (!eg) return 0.;
+  //if (forcePhoton) ATH_MSG_DEBUG("Treating all objects as photons");
+
+  /*
+  EMClusterErrorsParametrizations::Type tp = isElectron(eg, forcePhoton) ? 
+    EMClusterErrorsParametrizations::ELECTRON : 
+    EMClusterErrorsParametrizations::PHOTON;
+  */
+
+  double clusterE(1.);
+  double eta(0.);
+  if (fabs(eta) > 8.) eta = 8.;
+  const xAOD::CaloCluster* aCluster = eg->caloCluster();
+  if (aCluster) {
+    clusterE = eg->caloCluster()->e();
+    if (clusterE < 1.) clusterE = 1.;
+    eta = aCluster->eta();
+  } else {
+    return 0.30e-3*sqrt(100./(clusterE*0.001));
+  }
+    /*
+  if (!pars) {
+    return 0.30e-3*sqrt(100./(clusterE*0.001));
+  } else {
+
+    const EMClusterEtaPosErrorsMatrix& mat = pars->getEtaPosMatrix(tp);
+    const double err = mat.getError(eta, clusterE);
+
+    if (err != -1.0) {
+      return err;
+    } else {
+      // Use old  parametrization.
+      return 0.30e-3*sqrt(100./(clusterE*0.001));
+    }
+  }
+    */
+
+  return -1.;
+}
+
+
+double FourMomCombiner::getClusterEnergyError(const xAOD::Egamma* eg) const
+{
+
+  if (!eg) return 0.;
+  //if (forcePhoton) ATH_MSG_DEBUG("Treating all objects as photons");
+
+  const xAOD::CaloCluster* aCluster = eg->caloCluster();
+
+  if (aCluster == NULL /* || pars == NULL*/) return 1e-3; // In merging, use the cluster energy.
+  
+  double cl_err = 1E10;
+
+  /*
+  double cl_err = aCluster->e() * eRescaler->resolution(aCluster->e(), 
+							aCluster->eta(), 
+							isElectron(eg, forcePhoton) ? PATCore::ParticleType::Electron : PATCore::ParticleType::Photon, 
+							true);
+  */
+  
+  // Note The parametrization is in cluster eta, not pointing eta.
+  //return pars->getEnergyMatrix(tp).getError(aCluster->eta(), aCluster->e());
+
+  return cl_err;
+
+} 
+
+
+
+double FourMomCombiner::caloEta(const xAOD::Egamma* eg, double clusterEta) const {
+
+  if (!eg) return clusterEta;
+
+  //NOTE: Currently don't have access to pointing information in xAOD???
+  const double etaPointing(100.);// = eg->detailValue(egammaParameters::etap);
+  if ( fabs(etaPointing - clusterEta ) < 0.15 ) {
+    return etaPointing;
+  } else {
+    return clusterEta;
+  }
+
+}
+
+bool FourMomCombiner::isElectron(const xAOD::Egamma* eg) const
+{
+  return (xAOD::EgammaHelpers::isElectron(eg));
+}
+
+//Adaptation of routine from EMFourMomBuilder.cxx.
+void FourMomCombiner::MakeCombinationDecisionElectron(xAOD::Egamma *eg, 
+						      unsigned int index, 
+						      bool hasSi)
+{
+
+  ATH_MSG_DEBUG("Using CLUSTER flag (no combination) for now ");
+  if (hasSi)
+    setDownweightParameters(PHI, ETA, PMOM, CLUSTER);
+  else
+    setDownweightParameters(PHI, ETA, PMOM, CLUSTER_TRT);
+
+  return;
+
+  //Old combination code - not interested for now.
+
+  double momentum = -999999.;
+  double momentumError = -999999.;
+  
+  if (m_trkVector[4] > 0) {
+    momentum = m_trkVector[4];
+    momentumError = sqrt(m_trkMatrix(4,4));
+  }
+  
+  double energy(m_clusVector[4]);
+  double energyError(sqrt(m_clusMatrix(4,4)));
+  
+  // Cluster eta for (E-p)/p check on crack.
+  double cluster_eta(m_clusVector[3]);
+  
+  //const Rec::TrackParticle * trParticle;// = eg->trackParticle(index);
+  xAOD::Electron* el = dynamic_cast<xAOD::Electron*> (eg);
+  const xAOD::TrackParticle *trParticle = el->trackParticle(index);
+  
+  // require TRT-only tracks to have a minimum pT in order to combine
+  bool passMinPt = hasSi || trParticle->pt() > m_minPtTRT;
+  
+  //NEED xAOD HANDLE TO LAST MEASUREMENT PARAMETERS!
+  //Get last measurement parameters if using dP/P (or dPhi/Phi) as a metric.
+  /*
+  if (m_usedPoverP) {
+    
+    const Trk::TrackParticleBase*     trkbase = dynamic_cast<const Trk::TrackParticleBase* >(trParticle);
+    const Trk::TrackParameters*      pperigee = GetPerigeeParameters(trkbase);
+    const Trk::TrackParameters*  parametersLM = GetLastMeasurementParameters(trkbase);
+    
+    //Calculate dP/P.
+    double P(pperigee->momentum().mag());
+    double P_LM(parametersLM->momentum().mag());
+    m_dPoverP = fabs(P_LM-P) / P;
+    
+  }
+  */
+  
+  //Start the logic for combining track and cluster matrices , then set eg parameters
+  m_useCombination = (m_usedPoverP) ? 
+    m_dPoverP < m_dPoverPcut && fabs(momentum-energy)/momentum < m_EPoverPcut && passMinPt :
+    computeEPsigma(energy, energyError, momentum, momentumError ) < m_EPsigmacut && passMinPt;
+  
+  if (m_useCombination) {
+    // flag = "TRACK";
+    ATH_MSG_DEBUG("TRACK flag");
+    if (hasSi) {
+      setDownweightParameters(PHI, ETA, INVALID, TRACK);
+    } else {
+      setDownweightParameters(PHI, ETA, INVALID, TRACK_TRT);
+    }
+  }
+  //inconsistent measurements
+  else {
+    //flag = "CLUSTER";
+    ATH_MSG_DEBUG("CLUSTER flag ");
+    if (hasSi){
+      if( m_applyTrackOnly && energy<m_applytrackOnlyEcut) {
+	//Inconsistent measurements and low E
+	setDownweightParameters(PHI, ETA, PMOM, TRACKONLY);
+      }
+      
+      //For higher energies always go with the cluster, except in the crack.
+      else {
+	
+	if (fabs(cluster_eta) > 1.37 && fabs(cluster_eta) < 1.56 && energy/momentum < 1.)
+	  setDownweightParameters(PHI, ETA, PMOM, TRACKONLY);
+	else
+	  setDownweightParameters(PHI, ETA, PMOM, CLUSTER);
+	
+      }
+    }
+    else {
+      setDownweightParameters(PHI, ETA, PMOM, CLUSTER_TRT);
+    }
+  } // Chisquared test        
+  
+}
diff --git a/Reconstruction/egamma/egammaTools/src/FourMomCombiner.h b/Reconstruction/egamma/egammaTools/src/FourMomCombiner.h
new file mode 100644
index 0000000000000..00782678f2fce
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/FourMomCombiner.h
@@ -0,0 +1,148 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef EGAMMATOOLS_FOURMOMCOMBINER_H
+#define EGAMMATOOLS_FOURMOMCOMBINER_H
+
+//This class will hold all the variables relevant to the actual combination,
+//as well as eventually performing it. This will be the most modular, fundamental element of the
+//routine, capable (in principle) of being used outside of EMFourMomBuilder.cxx.
+
+// XAOD INCLUDES:
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "egammaInterfaces/IegammaBaseTool.h"
+#include "xAODEgamma/EgammaFwd.h"
+#include "xAODCaloEvent/CaloClusterFwd.h"
+#include "xAODTracking/TrackParticleContainer.h" 
+
+// INCLUDE HEADER FILES:
+#include "GaudiKernel/ToolHandle.h"
+#include "AthenaBaseComps/AthAlgTool.h"
+
+#include "egammaUtils/EigenVectorAndMatrix.h"
+#include "InDetBeamSpotService/IBeamCondSvc.h"
+#include "egammaInterfaces/IFourMomCombiner.h"
+#include "egammaBaseTool.h"
+#include "EventPrimitives/EventPrimitives.h"
+//#include "ElectronPhotonFourMomentumCorrection/egammaEnergyCorrectionTool.h"
+
+class IEMExtrapolCaloConversion;
+
+namespace Trk {
+  class TrackParticleBase;
+}
+
+namespace CombinationFlags {
+  enum DownWeightPar   {INVALID=999, D0=0, Z0=1, PHI=2, ETA=3, PMOM=4};
+  enum CombinationFlag {TRACK, TRACK_TRT, CLUSTER, CLUSTER_TRT,TRACKONLY};
+}
+
+
+class FourMomCombiner : public AthAlgTool, virtual public IFourMomCombiner {
+
+ public:
+
+  //Constructor/destructor.
+  FourMomCombiner(const std::string& type,
+		  const std::string& name,
+		  const IInterface* parent);
+
+  ~FourMomCombiner();
+
+  /** @brief AlgTool interface methods */
+  static const InterfaceID& interfaceID();
+
+  //Tool standard routines.
+  StatusCode initialize();
+
+  StatusCode ClusterExecute     (xAOD::Egamma*, 
+				 const Amg::Vector3D& vtx);
+
+  StatusCode TrackClusterExecute(xAOD::Egamma*, 
+				 unsigned int index, bool hasSi);
+  StatusCode finalize();
+  
+  const Amg::VectorX &getClusterVector()  const {return m_clusVector;}
+  const Amg::VectorX &getCombinedVector() const {return m_combVector;}
+
+  const Amg::MatrixX &getClusterMatrix()  const  {return m_clusMatrix;}
+  const Amg::MatrixX &getCombinedMatrix() const  {return m_combMatrix;}
+
+  //Returns matrices in (E, eta, phi, M) representation.
+  const AmgMatrix(4,4) get4x4ClusterErrorMatrix() const;
+  const AmgMatrix(4,4) get4x4CombinedErrorMatrix() const;
+
+ private:
+
+  //do the combination
+  StatusCode execute();
+
+  //Routine to do decision making (ported over from EMFourMomBuilder.cxx).
+  void MakeCombinationDecisionElectron(xAOD::Egamma*, unsigned int, bool hasSi);
+
+  //Routines to perform combination.
+  void setDownweightParameters(CombinationFlags::DownWeightPar s1, 
+			       CombinationFlags::DownWeightPar s2, 
+			       CombinationFlags::DownWeightPar s3, 
+			       CombinationFlags::CombinationFlag flag);
+
+  bool   fillClusterParameters (const xAOD::Egamma*, const Amg::Vector3D&);
+  bool   fillClusterParameters (const xAOD::Egamma*);
+  bool   fillTrackVectorElements        (xAOD::Egamma*, int index);
+  bool   fillTrackMatrixElements        (xAOD::Egamma*, int index, int charge);
+
+  //Variables for making decisions.
+  bool m_usedPoverP, m_dPoverP, m_useCombination, m_applyTrackOnly;
+  double m_EPsigmacut, m_dPoverPcut, m_EPoverPcut, m_applytrackOnlyEcut;
+  double m_minPtTRT;
+
+  //Energy rescaler tool for cluster energy resolution.
+  //AtlasRoot::egammaEnergyCorrectionTool *eRescaler;
+
+  //Track/cluster parameter vectors and matrices.
+  Amg::VectorX    m_trkVector;
+  Amg::MatrixX    m_trkMatrix;
+  Amg::VectorX    m_clusVector;
+  Amg::MatrixX    m_clusMatrix;
+
+  //Combined parameters.
+  Amg::VectorX    m_combVector;
+  Amg::MatrixX    m_combMatrix;
+  
+  //Downweighting/combination parameters.
+  int m_par1, m_par2, m_par3;
+  int m_combFlag;
+  int m_combType;
+
+  int m_NumberofSiHits;
+
+  double DEFAULT_QOVERP_ERROR;
+  double DEFAULT_MOMENTUM;
+
+  // Get the error on cluster energy, eta and phi.
+  double getClusterEnergyError (const xAOD::Egamma*) const;
+  double getClusterEtaError    (const xAOD::Egamma*) const;
+  double getClusterPhiError    (const xAOD::Egamma*) const;
+  double getClusterEtaPosError (const xAOD::Egamma*) const;
+
+  //Assorted routines.
+  bool   isElectron (const xAOD::Egamma*)  const;
+  double caloEta    (const xAOD::Egamma*, double clusterEta) const;
+
+  void setFromKalmanUpdate();
+
+  double computeEPsigma(double energy, double energyError, 
+			double momentum, double momentumError) const 
+  {
+    if (momentumError < 0) {
+      // this is the uninitialzed case, the -999999
+      return 9999; 
+    } else {
+      return (sqrt(((energy - momentum)*(energy - momentum))
+		   / ((energyError*energyError) + (momentumError*momentumError))));
+    }
+  }  
+};
+
+#endif
diff --git a/Reconstruction/egamma/egammaTools/src/TrackMatchSorter.h b/Reconstruction/egamma/egammaTools/src/TrackMatchSorter.h
new file mode 100644
index 0000000000000..465f01862c321
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/TrackMatchSorter.h
@@ -0,0 +1,52 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef EGAMMATOOLS_TRACKMATCHSORTER_H
+#define EGAMMATOOLS_TRACKMATCHSORTER_H
+class egammaRec;
+
+struct TrackMatch
+{
+ public:
+  int trackNumber;
+  double dR;
+  double seconddR;
+  bool isTRT;
+  int score;
+  int hitsScore;
+  double deltaPhiLast;
+  double deltaEta[4];
+  double deltaPhi[4];
+  double deltaPhiRescaled[4];
+
+};
+
+class TrackMatchSorter
+: public std::binary_function<TrackMatch, TrackMatch, bool> {
+ public:
+  bool operator()(TrackMatch match1, TrackMatch match2) const
+  {
+
+    if(match1.score!= match2.score) {//Higher score 
+      return match1.score>match2.score;
+    }
+    //sqrt(0.025**2)*sqrt(2)/sqrt(12) ~ 0.01
+    if(fabs(match1.dR-match2.dR)<1e-02) {
+      
+      if(fabs(match1.seconddR-match2.seconddR)>1e-02 ){ //Can the second distance separate them?
+	return match1.seconddR < match2.seconddR	;
+      }
+
+      if((match1.hitsScore!= match2.hitsScore)){ //use the one with more pixel
+	return match1.hitsScore>match2.hitsScore;
+      }
+
+    }
+
+    //closest DR
+    return match1.dR < match2.dR	;
+  }
+};
+
+#endif
diff --git a/Reconstruction/egamma/egammaTools/src/components/egammaTools_entries.cxx b/Reconstruction/egamma/egammaTools/src/components/egammaTools_entries.cxx
new file mode 100755
index 0000000000000..30b3d623cc518
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/components/egammaTools_entries.cxx
@@ -0,0 +1,50 @@
+#include "GaudiKernel/DeclareFactoryEntries.h"
+
+#include "../EMAmbiguityTool.h"
+#include "../EMBremCollectionBuilder.h"
+#include "../EMClusterTool.h"
+#include "../EMConversionBuilder.h"
+#include "../EMFourMomBuilder.h"
+#include "../EMShowerBuilder.h"
+#include "../EMTrackIsolationTool.h"
+#include "../EMTrackMatchBuilder.h"
+#include "../EMVertexBuilder.h"
+#include "../FourMomCombiner.h"
+#include "../egammaCheckEnergyDepositTool.h"
+#include "../egammaOQFlagsBuilder.h"
+#include "../EMPIDBuilder.h"
+#include "../egammaSwTool.h"
+
+DECLARE_TOOL_FACTORY     ( EMAmbiguityTool              )
+DECLARE_TOOL_FACTORY     ( EMBremCollectionBuilder      )
+DECLARE_TOOL_FACTORY     ( EMClusterTool                )
+DECLARE_TOOL_FACTORY     ( EMConversionBuilder          )
+DECLARE_TOOL_FACTORY     ( EMFourMomBuilder             )
+DECLARE_TOOL_FACTORY     ( EMShowerBuilder              )
+DECLARE_TOOL_FACTORY     ( EMTrackIsolationTool         )
+DECLARE_TOOL_FACTORY     ( EMTrackMatchBuilder          )
+DECLARE_TOOL_FACTORY     ( EMVertexBuilder              )
+DECLARE_TOOL_FACTORY     ( FourMomCombiner              )
+DECLARE_TOOL_FACTORY     ( egammaCheckEnergyDepositTool )
+DECLARE_TOOL_FACTORY     ( egammaOQFlagsBuilder         )
+DECLARE_TOOL_FACTORY     ( EMPIDBuilder                 )
+DECLARE_TOOL_FACTORY     ( egammaSwTool                 )
+
+
+DECLARE_FACTORY_ENTRIES(egammaTools) {
+    DECLARE_TOOL     ( EMAmbiguityTool              )
+    DECLARE_TOOL     ( EMBremCollectionBuilder      )
+    DECLARE_TOOL     ( EMClusterTool                )
+    DECLARE_TOOL     ( EMConversionBuilder          )
+    DECLARE_TOOL     ( EMFourMomBuilder             )
+    DECLARE_TOOL     ( EMShowerBuilder              )
+    DECLARE_TOOL     ( EMTrackIsolationTool         )
+    DECLARE_TOOL     ( EMTrackMatchBuilder          )
+    DECLARE_TOOL     ( EMVertexBuilder              )
+    DECLARE_TOOL     ( FourMomCombiner              )
+    DECLARE_TOOL     ( egammaCheckEnergyDepositTool )
+    DECLARE_TOOL     ( egammaOQFlagsBuilder         )
+    DECLARE_TOOL     ( EMPIDBuilder                 )
+    DECLARE_TOOL     ( egammaSwTool                 )
+}
+
diff --git a/Reconstruction/egamma/egammaTools/src/components/egammaTools_load.cxx b/Reconstruction/egamma/egammaTools/src/components/egammaTools_load.cxx
new file mode 100755
index 0000000000000..17c91b8ae805d
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/components/egammaTools_load.cxx
@@ -0,0 +1,4 @@
+#include "GaudiKernel/LoadFactoryEntries.h"
+
+LOAD_FACTORY_ENTRIES(egammaTools)
+
diff --git a/Reconstruction/egamma/egammaTools/src/egammaBaseTool.cxx b/Reconstruction/egamma/egammaTools/src/egammaBaseTool.cxx
new file mode 100644
index 0000000000000..76f0a50c5ad48
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/egammaBaseTool.cxx
@@ -0,0 +1,98 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "egammaBaseTool.h"
+#include "xAODEgamma/Egamma.h"
+#include "xAODCaloEvent/CaloCluster.h"
+#include "xAODTracking/TrackParticleContainer.h"
+#include "CaloEvent/CaloCellContainer.h"
+#include "GaudiKernel/IToolSvc.h"
+#include "egammaRecEvent/egammaRec.h"
+
+// INCLUDE Header Files:
+
+// ====================================================================================
+egammaBaseTool::egammaBaseTool(const std::string& type,
+			       const std::string& name,
+			       const IInterface* parent):
+  AthAlgTool(type, name, parent)
+{ 
+  declareInterface<IegammaBaseTool>(this);
+}
+
+// ====================================================================================
+egammaBaseTool::~egammaBaseTool() 
+{ 
+}
+
+// ====================================================================================
+StatusCode egammaBaseTool::initialize() 
+{  
+
+  return StatusCode::SUCCESS;
+
+}
+
+
+// ====================================================================================
+StatusCode egammaBaseTool::execute(xAOD::Egamma* eg)
+{
+  //
+  // standard execute method
+  //
+  if(eg)   return StatusCode::SUCCESS;
+
+  return StatusCode::SUCCESS;
+
+}
+
+// ====================================================================================
+StatusCode egammaBaseTool::executeRec(egammaRec* eg)
+{
+  //
+  // standard execute method
+  //
+  if(eg)   return StatusCode::SUCCESS;
+
+  return StatusCode::SUCCESS;
+
+}
+
+// =======================================================================================
+StatusCode  egammaBaseTool::caloExecute(xAOD::Egamma* eg , const CaloCellContainer*)
+{
+  //
+  // execute method for calo-based
+  //
+  if(eg) return StatusCode::SUCCESS;
+
+  return StatusCode::SUCCESS;
+}
+
+StatusCode egammaBaseTool::trackExecute(egammaRec* eg,  const xAOD::TrackParticleContainer* ) {
+
+  if(eg) return StatusCode::SUCCESS;
+  
+  return StatusCode::SUCCESS;
+}
+
+// ====================================================================================
+StatusCode egammaBaseTool::contExecute()
+{
+  //
+  // execute method for photon post processing
+  //
+
+  return StatusCode::SUCCESS;
+
+}
+
+// =========================================================================================
+StatusCode egammaBaseTool::finalize()
+{
+  
+  return StatusCode::SUCCESS;
+
+}
+
diff --git a/Reconstruction/egamma/egammaTools/src/egammaBaseTool.h b/Reconstruction/egamma/egammaTools/src/egammaBaseTool.h
new file mode 100644
index 0000000000000..12a9abda42238
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/egammaBaseTool.h
@@ -0,0 +1,56 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef EGAMMATOOLS_EGAMMABASETOOL_H
+#define EGAMMATOOLS_EGAMMABASETOOL_H
+
+/**
+  @class  egammaBaseTool
+          Base Tool for all egamma tool that require 
+          an egamma object as its input.  Hence the specific versions
+          will have access to all the framework services in addition
+          of being passed an 'egamma' object.  The derived 
+          tool must implement an execute(egamma*) method.
+  @author F. Derue, A. Kaczmarska
+*/
+
+// INCLUDE HEADER FILES:
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "egammaInterfaces/IegammaBaseTool.h"
+#include "xAODEgamma/EgammaFwd.h"
+#include "xAODCaloEvent/CaloClusterFwd.h"
+#include "xAODTracking/TrackParticleContainerFwd.h"
+ 
+class CaloCellContainer;
+class egammaRec;
+
+class egammaBaseTool : public AthAlgTool, virtual public IegammaBaseTool
+{
+
+ public:
+
+  /** @brief Default constructor*/
+  egammaBaseTool(const std::string& name, const std::string& description, 
+		 const IInterface* parent);
+  /** @brief destructor*/
+  virtual ~egammaBaseTool();
+
+  /** @brief initialize method*/
+  StatusCode initialize();
+  /** @brief finalize method*/
+  StatusCode finalize();
+  /** @brief execute method*/
+  virtual StatusCode execute(xAOD::Egamma* eg); 
+  /** @brief execute method*/
+  virtual StatusCode executeRec(egammaRec* eg); 
+  /** @brief execute method for calorimeter*/
+  virtual StatusCode  caloExecute(xAOD::Egamma* eg, const CaloCellContainer* cellcoll);
+  /** @brief execute method for TrackParticles*/
+  virtual StatusCode trackExecute(egammaRec* eg,  const xAOD::TrackParticleContainer * trackPC);
+  /** @brief execute method for methods working on containers*/
+  virtual StatusCode contExecute(); 
+ 
+};
+
+#endif // EGAMMATOOLS_EGAMMABASETOOL_H
diff --git a/Reconstruction/egamma/egammaTools/src/egammaCheckEnergyDepositTool.cxx b/Reconstruction/egamma/egammaTools/src/egammaCheckEnergyDepositTool.cxx
new file mode 100644
index 0000000000000..87717d03547b6
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/egammaCheckEnergyDepositTool.cxx
@@ -0,0 +1,165 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/********************************************************************
+
+NAME:     egammaCheckEnergyDepositTool
+PACKAGE:  offline/Reconstruction/egamma/egammaTools
+
+AUTHORS:  F. Derue 
+CREATED:  July 3, 2009
+
+PURPOSE:     Check in each sampling that fraction of energy 
+   reconstructed is not greater thana a certain threshold
+
+UPDATED :
+           Dec. 29, 2009 (FD) protection against bad pointers
+********************************************************************/
+
+#include "egammaCheckEnergyDepositTool.h"
+#include "xAODEgamma/Egamma.h"
+#include "xAODCaloEvent/CaloCluster.h"
+
+
+// =================================================================
+egammaCheckEnergyDepositTool::egammaCheckEnergyDepositTool(const std::string& type, 
+							   const std::string& name, 
+							   const IInterface* parent) :
+  AthAlgTool(type, name, parent),
+  m_useThrFmax(false),
+  m_thrF0max(0.9),
+  m_thrF1max(0.8),
+  m_thrF2max(0.98),
+  m_thrF3max(0.65)
+{
+  declareInterface<IegammaCheckEnergyDepositTool>(this);
+
+  // Boolean to apply threshold on maximal fraction of energy reconstructed in each sampling to write egamma objects
+  declareProperty("UseThrFmax", m_useThrFmax=false,
+                  "Boolean to apply threshold on maximal fraction of energy reconstructed in each sampling to write egamma objects");
+
+  // Threshold on maximal fraction of energy reconstructed in presampler
+  declareProperty("ThrF0max", m_thrF0max=0.9,
+                  "Threshold on maximal fraction of energy reconstructed in presampler");
+
+  // Threshold on maximal fraction of energy reconstructed in 1st sampling
+  declareProperty("ThrF1max", m_thrF1max=0.8,
+                  "Threshold on maximal fraction of energy reconstructed in 1st sampling");
+
+  // Threshold on maximal fraction of energy reconstructed in 2nd sampling
+  declareProperty("ThrF2max", m_thrF2max=0.98,
+                  "Threshold on maximal fraction of energy reconstructed in 2nd sampling");
+
+  // Threshold on maximal fraction of energy reconstructed in 3rd sampling
+  declareProperty("ThrF3max", m_thrF3max=0.65,
+                  "Threshold on maximal fraction of energy reconstructed in 3rd sampling");
+}
+
+// ===============================================================
+egammaCheckEnergyDepositTool::~egammaCheckEnergyDepositTool() 
+{
+}
+
+// =============================================================
+StatusCode egammaCheckEnergyDepositTool::initialize() 
+{
+
+  ATH_MSG_DEBUG("Initializing " << name() << "...");
+  
+  return StatusCode::SUCCESS;
+}
+
+// =========================================================================
+StatusCode egammaCheckEnergyDepositTool::finalize() 
+{
+  return StatusCode::SUCCESS;
+}
+
+// =========================================================================
+bool egammaCheckEnergyDepositTool::checkFractioninSampling(const xAOD::Egamma* eg) 
+{
+
+  // protection against bad pointers
+  if (eg==0) return false;
+
+  // retrieve associated cluster
+  const xAOD::CaloCluster*   cluster  = eg->caloCluster(); 
+
+  return checkFractioninSamplingCluster(cluster);
+}
+
+bool egammaCheckEnergyDepositTool::checkFractioninSamplingCluster(const xAOD::CaloCluster*   cluster) 
+{
+
+  // return true if no check to be done
+  if(!m_useThrFmax) return (true);
+
+  // retrieve associated cluster
+  if (cluster==0) return false;
+
+  // Retrieve energy in all samplings
+  double e0 = 0.;
+  double e1 = 0.;
+  double e2 = 0.;
+  double e3 = 0.;
+  double eallsamples = 0;
+  
+  if ( cluster->inBarrel() && !cluster->inEndcap() ){
+    e0 = cluster->eSample(CaloSampling::PreSamplerB);
+    e1 = cluster->eSample(CaloSampling::EMB1);
+    e2 = cluster->eSample(CaloSampling::EMB2);
+    e3 = cluster->eSample(CaloSampling::EMB3);
+  }
+  else if ( !cluster->inBarrel() && cluster->inEndcap() ){
+    e0 = cluster->eSample(CaloSampling::PreSamplerE);
+    e1 = cluster->eSample(CaloSampling::EME1);
+    e2 = cluster->eSample(CaloSampling::EME2);
+    e3 = cluster->eSample(CaloSampling::EME3);
+  }
+  // if both in barrel and end-cap then have to
+  // rely on energy deposition
+  // be careful to test 0 precisely either 
+  // 0 (no deposit) > noise (which is negative) !!!!
+  else if ( cluster->inBarrel() && cluster->inEndcap() ) {
+    if ( ( ( cluster->eSample(CaloSampling::EMB2) != 0. && 
+	     cluster->eSample(CaloSampling::EME2) != 0. ) && 
+	   ( cluster->eSample(CaloSampling::EMB2) >=
+	     cluster->eSample(CaloSampling::EME2) ) ) || 
+	 cluster->eSample(CaloSampling::EME2) == 0. ) {
+      e0 = cluster->eSample(CaloSampling::PreSamplerB);
+      e1 = cluster->eSample(CaloSampling::EMB1);
+      e2 = cluster->eSample(CaloSampling::EMB2);
+      e3 = cluster->eSample(CaloSampling::EMB3);
+    }
+    else {
+      e0 = cluster->eSample(CaloSampling::PreSamplerE);
+      e1 = cluster->eSample(CaloSampling::EME1);
+      e2 = cluster->eSample(CaloSampling::EME2);
+      e3 = cluster->eSample(CaloSampling::EME3);
+    }
+  }   
+  
+  // sum of energy in all samplings
+  eallsamples = e0+e1+e2+e3;
+
+  if (eallsamples!=0.) {
+    // check fraction of energy reconstructed in presampler
+    double f0 = e0/eallsamples;
+    if (f0 > m_thrF0max) return false;
+
+    // check fraction of energy reconstructed in first sampling
+    double f1 = e1/eallsamples;
+    if (f1 > m_thrF1max) return false;
+
+    // check fraction of energy reconstructed in second sampling
+    double f2 = e2/eallsamples;
+    if (f2 > m_thrF2max) return false;
+
+    // check fraction of energy reconstructed in third sampling
+    double f3 = e3/eallsamples;
+    if (f3 > m_thrF3max) return false;
+  }
+
+  return true;
+}
diff --git a/Reconstruction/egamma/egammaTools/src/egammaCheckEnergyDepositTool.h b/Reconstruction/egamma/egammaTools/src/egammaCheckEnergyDepositTool.h
new file mode 100644
index 0000000000000..28292cfcfb392
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/egammaCheckEnergyDepositTool.h
@@ -0,0 +1,57 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef EGAMMATOOLS_EGAMMACHECKENERGYDEPOSITTOOL_H
+#define EGAMMATOOLs_EGAMMACHECKENERGYDEPOSITTOOL_H
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/ToolHandle.h"
+
+#include "xAODEgamma/EgammaFwd.h"
+#include "xAODCaloEvent/CaloClusterFwd.h"
+
+#include "egammaInterfaces/IegammaCheckEnergyDepositTool.h"
+
+/**
+   @class egammaCheckEnergyDepositTool
+   Tool to check in each sampling that fraction of energy 
+   reconstructed is not greater thana a certain threshold
+
+   @author Frederic Derue
+*/
+
+class egammaCheckEnergyDepositTool : virtual public IegammaCheckEnergyDepositTool, public AthAlgTool {
+
+ public:
+
+  /** @bried constructor */
+  egammaCheckEnergyDepositTool (const std::string& type,const std::string& name, const IInterface* parent);
+
+  /** @brief destructor */
+  virtual ~egammaCheckEnergyDepositTool();
+
+  /** @brief initialize method */
+  virtual StatusCode initialize();
+  /** @brief finalize method */
+  virtual StatusCode finalize();
+  /** @brief execute method */
+  virtual bool checkFractioninSampling(const xAOD::Egamma* eg);
+  virtual bool checkFractioninSamplingCluster(const xAOD::CaloCluster* cluster) ;
+  /** @brief Boolean to apply threshold on maximal fraction of energy reconstructed in each sampling to write egamma objects */
+  bool m_useThrFmax;
+  /** @brief Threshold on maximal fraction of energy reconstructed in presampler */
+  double m_thrF0max;
+  /** @brief Threshold on maximal fraction of energy reconstructed in 1st sampling*/
+  double m_thrF1max;
+  /** @brief Threshold on maximal fraction of energy reconstructed in 2nd sampling */
+  double m_thrF2max;
+
+  /** @brief Threshold on maximal fraction of energy reconstructed in 3rd sampling */
+  double m_thrF3max;
+
+ private:
+
+};
+
+#endif // EGAMMATOOLS_EGAMMACHECKENERGYDEPOSITTOOL_H 
diff --git a/Reconstruction/egamma/egammaTools/src/egammaOQFlagsBuilder.cxx b/Reconstruction/egamma/egammaTools/src/egammaOQFlagsBuilder.cxx
new file mode 100644
index 0000000000000..23b77cea0e41c
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/egammaOQFlagsBuilder.cxx
@@ -0,0 +1,602 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// INCLUDE HEADER FILES:
+#include "egammaOQFlagsBuilder.h"
+#include "xAODEgamma/Egamma.h"
+#include "xAODCaloEvent/CaloCluster.h"
+
+#include <algorithm> 
+#include <math.h> 
+#include "StoreGate/StoreGateSvc.h"
+#include "CaloConditions/CaloAffectedRegionInfoVec.h"
+#include "LArTools/LArCablingService.h"
+#include "Identifier/HWIdentifier.h"
+#include "LArRecConditions/ILArBadChanTool.h"
+#include "CaloIdentifier/LArEM_ID.h"
+#include "CaloIdentifier/CaloCell_ID.h"
+#include "CLHEP/Units/SystemOfUnits.h"
+#include "CaloGeoHelpers/CaloPhiRange.h"
+
+
+//  END OF HEADER FILES INCLUDE
+
+
+using CLHEP::GeV;
+
+
+// ===========================================================================
+egammaOQFlagsBuilder::egammaOQFlagsBuilder(const std::string& type,
+					   const std::string& name,
+					   const IInterface* parent)
+  : egammaBaseTool(type, name, parent),
+    //m_toolSvc(0),
+    m_badChannelTool("LArBadChanTool"),
+    m_larCablingSvc("LArCablingService"),
+    m_affectedTool("CaloAffectedTool"), 
+    m_emHelper(0),
+    m_cellCentrId(0),
+    m_detStore(NULL)
+{
+  //
+  // constructor
+  //
+
+  // declare interface
+  declareInterface<IegammaBaseTool>(this);
+
+
+  // The following properties are specified at run-time
+  // (declared in jobOptions file)
+  declareProperty("LArBadChannelTool",m_badChannelTool,"This is the larBadChannelTool");
+  declareProperty("affectedTool"    , m_affectedTool); 
+  declareProperty("CellsName",m_cellsName="AODCellContainer","Names of container which contain cells ");
+  declareProperty("QCellCut", m_QCellCut = 4000.);
+  declareProperty("QCellHECCut", m_QCellHECCut = 60000.);
+  declareProperty("QCellSporCut", m_QCellSporCut = 4000.);
+  declareProperty("LArQCut", m_LArQCut = 0.8);
+  declareProperty("TCut", m_TCut = 10.0);
+  declareProperty("TCutVsE", m_TCutVsE = 2.0);
+  m_affRegVec = 0;
+  m_calocellId = 0;
+}
+
+// ===============================================================
+egammaOQFlagsBuilder::~egammaOQFlagsBuilder()
+{ 
+  //
+  // destructor
+  //
+}
+
+// ==================================================================
+StatusCode egammaOQFlagsBuilder::initialize()
+{
+  //
+  // initialize method
+  //
+
+  ATH_MSG_DEBUG(" Initializing egammaOQFlagsBuilder");
+ 
+  StatusCode sc;
+  
+  // get DetectorStore service
+  //StoreGateSvc* detStore;
+  sc=service("DetectorStore",m_detStore);
+  if (sc.isFailure()) {
+   msg(MSG::ERROR) << "DetectorStore service not found !" << endreq;
+    return StatusCode::FAILURE;
+  } else {
+    //if (msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << "Found DetectorStore" << endreq;
+  }
+
+ // Get BadChannelTool
+  sc=m_badChannelTool.retrieve();
+  if (sc.isFailure()) {
+    msg(MSG::ERROR) << "Could not retrieve LArBadChannelTool " << m_badChannelTool << endreq;
+    return StatusCode::FAILURE;
+  } else {
+    //if (msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << "LArBadChannelTool" << m_badChannelTool << " retrieved" << endreq;
+  }
+  
+
+  //Get CaloAffectedTool
+  sc = m_affectedTool.retrieve();
+  if (sc.isFailure()){
+    msg(MSG::ERROR) << "Could not retrieve CaloAffectedTool " << m_affectedTool << endreq;
+    return StatusCode::FAILURE;
+  } else {
+    //if (msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << "CaloAffectedTool" << m_affectedTool << " retrieved" << endreq;
+  }
+
+
+  //Get LArCablingService
+  sc=m_larCablingSvc.retrieve();
+  if (sc.isFailure()) {
+    msg(MSG::ERROR) << "Could not retrieve LArCablingService " << m_larCablingSvc << endreq;
+    return StatusCode::FAILURE;
+  } else {
+    //if (msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << "LArCablingService" << m_larCablingSvc << " retrieved" << endreq;
+  }
+
+
+  sc=m_detStore->retrieve(m_calocellId, "CaloCell_ID"); 
+  if(sc.isFailure()){
+    msg(MSG::WARNING) <<  "Cannot retrieve online_id" << endreq;
+    return StatusCode::FAILURE;
+  } else {
+    //if (msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << "CaloCell_ID" << m_calocellId << " retrieved" << endreq;
+  }
+  
+  sc=m_detStore->retrieve(m_emHelper); 
+  if(sc.isFailure()){
+    msg(MSG::WARNING) <<   "Cannot retrieve online_id" << endreq;
+    return StatusCode::FAILURE;
+  } else {
+    //if (msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << "CaloCell_ID  retrieved" << endreq;
+  }
+
+
+  return StatusCode::SUCCESS;
+}
+
+// ====================================================================
+StatusCode egammaOQFlagsBuilder::finalize()
+{
+  //
+  // finalize method
+  //
+
+  return StatusCode::SUCCESS;
+}
+
+
+
+// ===============================================================
+bool egammaOQFlagsBuilder::findCentralCell(const xAOD::CaloCluster* cluster)
+{
+
+  bool thereIsACentrCell = false;
+
+  //LOOP OVER CLUSTER TO FIND THE CENTRAL CELL IN S2
+  xAOD::CaloCluster::const_cell_iterator  cellIter    = cluster->cell_begin();
+  xAOD::CaloCluster::const_cell_iterator  cellIterEnd = cluster->cell_end();
+  float clusEta = cluster->eta();
+  float clusPhi = cluster->phi();
+  float energymax = -999999.;
+
+  for( ;cellIter!=cellIterEnd;cellIter++) {
+    const CaloCell* cell = (*cellIter);
+    if (!cell) continue;
+    float eta = cell->eta();
+    float phi = cell->phi();
+    float energy = cell->energy();
+    CaloSampling::CaloSample layer = cell->caloDDE()->getSampling() ;
+    if(fabs(eta - clusEta)<0.025 && fabs(CaloPhiRange::diff(phi, clusPhi))<0.025 && (layer==CaloSampling::EMB2 || layer==CaloSampling::EME2) && (energy>energymax)) { 
+      energymax=energy;
+      m_cellCentrId = cellIter->ID();
+      thereIsACentrCell = true;
+    }
+  }
+
+  return thereIsACentrCell;
+}
+
+
+// ===============================================================
+bool egammaOQFlagsBuilder::isCore(Identifier Id, const std::vector<IdentifierHash>& neighbourList) const {
+
+  const IdentifierHash hashId = m_calocellId->calo_cell_hash(Id);
+  std::vector<IdentifierHash>::const_iterator it=std::find(neighbourList.begin(),neighbourList.end(),hashId);
+  return (it!=neighbourList.end());
+
+  /*
+
+  bool status= false;
+
+  const IdentifierHash hashId = m_calocellId->calo_cell_hash(Id);
+
+  std::vector<IdentifierHash>::iterator first=neighbourList.begin();
+  std::vector<IdentifierHash>::iterator last=neighbourList.end();
+
+  for (;last!=first; first++){
+    if( hashId == (unsigned int)(*first) ) {
+      status= true;
+      continue; //should be break, no?
+    }
+  }
+
+  return status;
+  */
+}
+
+
+// ===============================================================
+std::vector<IdentifierHash> egammaOQFlagsBuilder::findNeighbours(Identifier cellCentrId)
+{
+
+  std::vector<IdentifierHash> neighbourList;
+
+  //
+  // ... loop on cells hash
+  //
+  const IdentifierHash hashId = m_calocellId->calo_cell_hash(cellCentrId);
+  m_emHelper->get_neighbours(hashId, LArNeighbours::all2D, neighbourList); 
+
+  return  neighbourList;
+
+}
+
+
+
+// =====================================================================
+StatusCode egammaOQFlagsBuilder::execute(xAOD::Egamma* eg)
+{ 
+  
+  // Protection against bad pointers
+  if (eg==0) return StatusCode::SUCCESS;
+  const xAOD::CaloCluster* cluster = eg->caloCluster(); 
+  if (!cluster) return StatusCode::SUCCESS; 
+  if (cluster->size()<=0) return StatusCode::SUCCESS; 
+  
+  unsigned int iflag = 0;
+  const float clusterEta = cluster->eta();
+  const float clusterPhi = cluster->phi();
+
+  //Find the central cell in the middle layer 
+  bool foundCentralCell = egammaOQFlagsBuilder::findCentralCell(cluster);
+  
+  //=================== Set timing bit ===================================================//
+  const double absEnergyGeV = fabs(cluster->e()/GeV);
+  if(absEnergyGeV != 0 &&  fabs(cluster->time()) > m_TCut + m_TCutVsE/absEnergyGeV) {
+    iflag |= ( 0x1 << xAOD::EgammaParameters::OutTime);
+  }
+  //======================================================================================//
+
+  //Declare totE and badE for LarQ cleaning
+  double totE=0;
+  double badE=0;
+
+  if (foundCentralCell) {
+    //Find the list of neighbours cells, to define the 3x3 cluster core
+    std::vector<IdentifierHash> neighbourList = findNeighbours(m_cellCentrId);
+    
+    //Loop over all the cluster cells
+    xAOD::CaloCluster::const_cell_iterator cellIter    = cluster->cell_begin();
+    xAOD::CaloCluster::const_cell_iterator cellIterEnd = cluster->cell_end();
+    for( ;cellIter!=cellIterEnd;cellIter++) {
+      //Find cell parameters and properties
+      const CaloCell* cell = (*cellIter);
+      if(!cell) continue;
+      float eta = cell->eta();
+      // float phi = cell->phi(); // no longer used
+      float qual = cell->quality();
+      CaloSampling::CaloSample layer = cell->caloDDE()->getSampling()  ;
+
+      //Calculate badE et totE    
+      if( (cell->provenance()  & 0x2000) &&!(cell->provenance()  & 0x0800 )) {
+	totE += cell->e();
+	if(cell->quality() > m_QCellCut ) badE += cell->e(); 
+      }       
+
+      bool isACoreCell =  false;
+      isACoreCell = isCore(cell->ID(),neighbourList);
+      
+      bool isStripCoreCell = false;
+      if ( (layer==CaloSampling::EMB1 || layer==CaloSampling::EME1) && fabs(eta-clusterEta)<0.025/2.) {
+	isStripCoreCell = true;
+      }
+      
+      //=======================   Set HEC bit ============================================//
+      if (layer>=CaloSampling::HEC0 && layer<=CaloSampling::HEC3 && qual>m_QCellHECCut) {
+	iflag |= ( 0x1 << xAOD::EgammaParameters::HECHighQ);
+      }
+      //==================================================================================//
+
+      //======================== Set LAr bits ============================================================//
+      HWIdentifier LArhwid = m_larCablingSvc->createSignalChannelIDFromHash(cell->caloDDE()->calo_hash());
+      LArBadChannel bc = m_badChannelTool->status(LArhwid);      
+      //      if (!bc.good()){  //If it is ok, skip all checks
+	if(isACoreCell) {
+	  if((cell->provenance() & 0x0A00) == 0x0A00) { 
+	    iflag |= ( 0x1 << xAOD::EgammaParameters::MissingFEBCellCore);
+	  }
+	  if((cell->provenance() & 0x0A00) == 0x0800) {
+	    iflag |= ( 0x1 << xAOD::EgammaParameters::MaskedCellCore); 
+	  }
+	  if(bc.sporadicBurstNoise() && qual<m_QCellSporCut) {
+	    iflag |= ( 0x1 << xAOD::EgammaParameters::SporadicNoiseLowQCore);
+	  }
+	  if(bc.deadCalib() || bc.lowNoiseHG() || bc.lowNoiseMG() ||
+	     bc.lowNoiseLG() || bc.distorted() || bc.unstable() || 
+	     bc.unstableNoiseHG() || bc.unstableNoiseMG() || 
+	     bc.unstableNoiseLG() || bc.peculiarCalibrationLine() 
+	     || bc.almostDead() ||  bc.shortProblem()) { 
+	    iflag |= ( 0x1 << xAOD::EgammaParameters::AffectedCellCore);
+	  }
+	  if (qual>=4000) {
+	    iflag |= ( 0x1 << xAOD::EgammaParameters::HighQCore);
+	  }
+	}else{
+	  if((cell->provenance() & 0x0A00) == 0x0A00) { 
+	    if( layer==CaloSampling::PreSamplerB || layer==CaloSampling::PreSamplerE) {
+	      iflag |= ( 0x1 << xAOD::EgammaParameters::MissingFEBCellEdgePS);
+	    }
+  	    if( layer==CaloSampling::EMB1 || layer==CaloSampling::EME1) {
+	      iflag |= ( 0x1 << xAOD::EgammaParameters::MissingFEBCellEdgeS1);
+	      if (isStripCoreCell)  iflag |= ( 0x1 << xAOD::EgammaParameters::BadS1Core);
+	    }
+  	    if( layer==CaloSampling::EMB2 || layer==CaloSampling::EME2) iflag |= ( 0x1 << xAOD::EgammaParameters::MissingFEBCellEdgeS2);
+  	    if( layer==CaloSampling::EMB3 || layer==CaloSampling::EME3) iflag |= ( 0x1 << xAOD::EgammaParameters::MissingFEBCellEdgeS3); 
+	  }
+	  if((cell->provenance() & 0x0A00)  == 0x0800) {
+	    if( layer==CaloSampling::PreSamplerB || layer==CaloSampling::PreSamplerE){
+	      iflag |= ( 0x1 << xAOD::EgammaParameters::MaskedCellEdgePS);
+	    }
+  	    if( layer==CaloSampling::EMB1 || layer==CaloSampling::EME1) {
+	      iflag |= ( 0x1 << xAOD::EgammaParameters::MaskedCellEdgeS1);
+	      if (isStripCoreCell)  iflag |= ( 0x1 << xAOD::EgammaParameters::BadS1Core);
+	    }
+  	    if( layer==CaloSampling::EMB2 || layer==CaloSampling::EME2) iflag |= ( 0x1 << xAOD::EgammaParameters::MaskedCellEdgeS2);
+  	    if( layer==CaloSampling::EMB3 || layer==CaloSampling::EME3) iflag |= ( 0x1 << xAOD::EgammaParameters::MaskedCellEdgeS3); 
+	  }
+	  if(bc.sporadicBurstNoise() && qual<m_QCellSporCut) {
+	    iflag |= ( 0x1 << xAOD::EgammaParameters::SporadicNoiseLowQEdge);
+	  }
+	  if(bc.deadCalib() || bc.lowNoiseHG() || bc.lowNoiseMG() ||
+	     bc.lowNoiseLG() || bc.distorted() || bc.unstable() ||
+	     bc.unstableNoiseHG() || bc.unstableNoiseMG() || 
+	     bc.unstableNoiseLG() || bc.peculiarCalibrationLine() 
+	     || bc.almostDead() ||  bc.shortProblem()) { 
+	    if( layer==CaloSampling::PreSamplerB || layer==CaloSampling::PreSamplerE) {
+	      iflag |= ( 0x1 << xAOD::EgammaParameters::AffectedCellEdgePS);
+	    }
+	    if( layer==CaloSampling::EMB1 || layer==CaloSampling::EME1) iflag |= ( 0x1 << xAOD::EgammaParameters::AffectedCellEdgeS1);
+	    if( layer==CaloSampling::EMB2 || layer==CaloSampling::EME2) iflag |= ( 0x1 << xAOD::EgammaParameters::AffectedCellEdgeS2);
+	    if( layer==CaloSampling::EMB3 || layer==CaloSampling::EME3) iflag |= ( 0x1 << xAOD::EgammaParameters::AffectedCellEdgeS3);
+	  }
+	  if (qual>=4000) {
+	    iflag |= ( 0x1 << xAOD::EgammaParameters::HighQEdge);
+	  }
+	}
+    }  // end loop over cells
+    //====================================================================================================================//
+
+    //==== Set LArQCleaning bit ===============//
+    double egammaLArQCleaning=0;
+    if(totE !=0) egammaLArQCleaning=badE/totE;
+    if(egammaLArQCleaning>m_LArQCut){
+      iflag |= (0x1 << xAOD::EgammaParameters::LArQCleaning);
+    }
+    //=========================================//
+
+  } //close if found central cell
+
+
+
+
+  //========================= Check the HV components ===================================================//
+  float deta=0;
+  float dphi=0;
+  CaloSampling::CaloSample layer;
+
+
+   //--------------> PRE SAMPLER
+  deta=0.5*0.025*cluster->getClusterEtaSize();
+  dphi=0.5*0.025*cluster->getClusterPhiSize();
+  layer=CaloSampling::PreSamplerE;
+//   deta=0.5*cluster->etasize(layer);
+//   dphi=0.5*cluster->phisize(layer);
+  bool checkNNHV_PSE   = m_affectedTool->isAffected(cluster ,deta , dphi ,layer,layer,1) ; //nnHVPS
+  bool checkDEADHV_PSE = m_affectedTool->isAffected(cluster ,deta , dphi ,layer,layer,2) ; //deadHVPS
+  layer=CaloSampling::PreSamplerB;
+//   deta=0.;
+//   dphi=0.;
+//   deta=0.5*cluster->etasize(layer);
+//   dphi=0.5*cluster->phisize(layer);
+  bool checkNNHV_PSB   = m_affectedTool->isAffected(cluster ,deta , dphi ,layer,layer,1) ; //nnHVPS
+  bool checkDEADHV_PSB = m_affectedTool->isAffected(cluster ,deta , dphi ,layer,layer,2) ; //deadHVPS
+  if(checkNNHV_PSE || checkNNHV_PSB)      iflag |= ( 0x1 << xAOD::EgammaParameters::NonNominalHVPS); 
+  if(checkDEADHV_PSE || checkDEADHV_PSB)  iflag |= ( 0x1 << xAOD::EgammaParameters::DeadHVPS);
+
+
+  //---------------> SAMPLING 2 : CLUSTER CORE
+  layer=CaloSampling::EMB2;
+//   deta=0.;
+//   dphi=0.;
+  deta=0.5*0.025*3.;
+  dphi=0.5*0.025*3.;
+  bool checkDEADHV_CORE_B = m_affectedTool->isAffected(cluster ,deta , dphi ,layer,layer,2) ; //deadHVPS
+  layer=CaloSampling::EME2;
+  bool checkDEADHV_CORE_E = m_affectedTool->isAffected(cluster ,deta , dphi ,layer,layer,2) ; //deadHVPS
+  if(checkDEADHV_CORE_B || checkDEADHV_CORE_E)  iflag |= ( 0x1 << xAOD::EgammaParameters::DeadHVS1S2S3Core); 
+
+  //----------------> SAMPLINGS 1,2,3 : CLUSTER EDGE
+  deta=0.5*0.025*cluster->getClusterEtaSize();
+  dphi=0.5*0.025*cluster->getClusterPhiSize();
+  layer=CaloSampling::EMB1;
+//   deta=0.;
+//   dphi=0.;
+//   deta=0.5*cluster->etasize(layer);
+//   dphi=0.5*cluster->phisize(layer);
+  bool checkNNHV_EMB1   = m_affectedTool->isAffected(cluster ,deta , dphi ,layer,layer,1) ; //nnHVPS
+  bool checkDEADHV_EMB1 = m_affectedTool->isAffected(cluster ,deta , dphi ,layer,layer,2) ; //deadHVPS
+  layer=CaloSampling::EMB2;
+//   deta=0.;
+//   dphi=0.;
+//   deta=0.5*cluster->etasize(layer);
+//   dphi=0.5*cluster->phisize(layer);
+  bool checkNNHV_EMB2   = m_affectedTool->isAffected(cluster ,deta , dphi ,layer,layer,1) ; //nnHVPS
+  bool checkDEADHV_EMB2 = m_affectedTool->isAffected(cluster ,deta , dphi ,layer,layer,2) ; //deadHVPS
+  layer=CaloSampling::EMB3;
+//   deta=0.;
+//   dphi=0.;
+//   deta=0.5*cluster->etasize(layer);
+//   dphi=0.5*cluster->phisize(layer);
+  bool checkNNHV_EMB3   = m_affectedTool->isAffected(cluster ,deta , dphi ,layer,layer,1) ; //nnHVPS
+  bool checkDEADHV_EMB3 = m_affectedTool->isAffected(cluster ,deta , dphi ,layer,layer,2) ; //deadHVPS
+  layer=CaloSampling::EME1;
+//   deta=0.;
+//   dphi=0.;
+//   deta=0.5*cluster->etasize(layer);
+//   dphi=0.5*cluster->phisize(layer);
+  bool checkNNHV_EME1   = m_affectedTool->isAffected(cluster ,deta , dphi ,layer,layer,1) ; //nnHVPS
+  bool checkDEADHV_EME1 = m_affectedTool->isAffected(cluster ,deta , dphi ,layer,layer,2) ; //deadHVPS
+  layer=CaloSampling::EME2;
+//   deta=0.;
+//   dphi=0.;
+//   deta=0.5*cluster->etasize(layer);
+//   dphi=0.5*cluster->phisize(layer);
+  bool checkNNHV_EME2   = m_affectedTool->isAffected(cluster ,deta , dphi ,layer,layer,1) ; //nnHVPS
+  bool checkDEADHV_EME2 = m_affectedTool->isAffected(cluster ,deta , dphi ,layer,layer,2) ; //deadHVPS
+  layer=CaloSampling::EME3;
+//   deta=0.;
+//   dphi=0.;
+//   deta=0.5*cluster->etasize(layer);
+//   dphi=0.5*cluster->phisize(layer);
+  bool checkNNHV_EME3   = m_affectedTool->isAffected(cluster ,deta , dphi ,layer,layer,1) ; //nnHVPS
+  bool checkDEADHV_EME3 = m_affectedTool->isAffected(cluster ,deta , dphi ,layer,layer,2) ; //deadHVPS
+  if(checkNNHV_EMB1 || checkNNHV_EME1 || checkNNHV_EMB2 || checkNNHV_EME2 ||checkNNHV_EMB3 || checkNNHV_EME3) 
+    iflag |= ( 0x1 << xAOD::EgammaParameters::NonNominalHVS1S2S3); 
+  if(checkDEADHV_EMB1 || checkDEADHV_EME1 || checkDEADHV_EMB2 || checkDEADHV_EME2 ||checkDEADHV_EMB3 || checkDEADHV_EME3)  
+    iflag |= ( 0x1 << xAOD::EgammaParameters::DeadHVS1S2S3Edge);
+  //========================================================================================================================//
+
+  //====================  Check the tile component  ==================================//
+  //Get CaloCellContainer
+  StatusCode sc = evtStore()->retrieve(m_cellcoll, m_cellsName) ; 
+  if(sc.isFailure() || !m_cellcoll) {
+    ATH_MSG_WARNING("no Calo Cell Container " << m_cellsName << " found");
+    return sc;
+  }
+  CaloCell_ID::SUBCALO HADCal = static_cast<CaloCell_ID::SUBCALO>(CaloCell_ID::TILE);
+  CaloCellList ccl(m_cellcoll,HADCal); 
+  double size = 0.12;
+  //------------------------ TileBar0 --------------------------------//
+  bool isbadtilebar0cell = false;
+  ccl.select(clusterEta,clusterPhi,size,size,CaloSampling::TileBar0);
+  CaloCellList::list_iterator cclIterBar0     = ccl.begin();
+  CaloCellList::list_iterator cclIterBar0End  = ccl.end();
+  for( ;cclIterBar0!=cclIterBar0End;cclIterBar0++) {
+    const CaloCell* cell = (*cclIterBar0);
+    if(cell->badcell() == true){//check of bad tile cell
+      isbadtilebar0cell = true;
+      break;
+    }
+  }
+  //------------------------ TileExt0 --------------------------------//
+  bool isbadtileext0cell = false;
+  ccl.select(clusterEta,clusterPhi,size,size,CaloSampling::TileExt0);
+  CaloCellList::list_iterator cclIterExt0     = ccl.begin();
+  CaloCellList::list_iterator cclIterExt0End  = ccl.end();
+  for( ;cclIterExt0!=cclIterExt0End;cclIterExt0++) {
+    const CaloCell* cell = (*cclIterExt0);
+    if(cell->badcell() == true){//check of bad tile cell
+      isbadtileext0cell = true;
+      break;
+    }
+  }
+  //----------------------------------------------------------------//
+
+  if( isbadtilebar0cell || isbadtileext0cell ){
+    iflag |= (0x1 << xAOD::EgammaParameters::DeadCellTileS0);    
+  }
+
+  if (evtStore()->contains<CaloCellContainer>("AllCalo")) {
+    //skipped if running on the AODs
+    //---------------------- TileBar1 ----------------------------------//
+    bool isbadtilebar1cell = false;
+    ccl.select(clusterEta,clusterPhi,size,size,CaloSampling::TileBar1);
+    CaloCellList::list_iterator cclIterBar1     = ccl.begin();
+    CaloCellList::list_iterator cclIterBar1End  = ccl.end();
+    for( ;cclIterBar1!=cclIterBar1End;cclIterBar1++) {
+      const CaloCell* cell = (*cclIterBar1);
+      if(cell->badcell() == true){//check of bad tile cell
+	isbadtilebar1cell = true;
+	break;
+      }
+    }
+    //---------------------- TileExt1 ----------------------------------//
+    bool isbadtileext1cell = false;
+    ccl.select(clusterEta,clusterPhi,size,size,CaloSampling::TileExt1);
+    CaloCellList::list_iterator cclIterExt1     = ccl.begin();
+    CaloCellList::list_iterator cclIterExt1End  = ccl.end();
+    for( ;cclIterExt1!=cclIterExt1End;cclIterExt1++) {
+      const CaloCell* cell = (*cclIterExt1);
+      if(cell->badcell() == true){//check of bad tile cell
+	isbadtileext1cell = true;
+	break;
+      }
+    }
+    //---------------------- TileGap1 ----------------------------------//
+    bool isbadtilegap1cell = false;
+    ccl.select(clusterEta,clusterPhi,size,size,CaloSampling::TileGap1);
+    CaloCellList::list_iterator cclIterGap1     = ccl.begin();
+    CaloCellList::list_iterator cclIterGap1End  = ccl.end();
+    for( ;cclIterGap1!=cclIterGap1End;cclIterGap1++) {
+      const CaloCell* cell = (*cclIterGap1);
+      if(cell->badcell() == true){//check of bad tile cell
+	isbadtilegap1cell = true;
+	break;
+      }
+    }
+    //---------------------- TileBar2 ----------------------------------//
+    bool isbadtilebar2cell = false;
+    ccl.select(clusterEta,clusterPhi,size,size,CaloSampling::TileBar2);
+    CaloCellList::list_iterator cclIterBar2     = ccl.begin();
+    CaloCellList::list_iterator cclIterBar2End  = ccl.end();
+    for( ;cclIterBar2!=cclIterBar2End;cclIterBar2++) {
+      const CaloCell* cell = (*cclIterBar2);
+      if(cell->badcell() == true){//check of bad tile cell
+	isbadtilebar2cell = true;
+	break;
+      }
+    }
+    //---------------------- TileExt2 ---------------------------------//
+    bool isbadtileext2cell = false;
+    ccl.select(clusterEta,clusterPhi,size,size,CaloSampling::TileExt2);
+    CaloCellList::list_iterator cclIterExt2     = ccl.begin();
+    CaloCellList::list_iterator cclIterExt2End  = ccl.end();
+    for( ;cclIterExt2!=cclIterExt2End;cclIterExt2++) {
+      const CaloCell* cell = (*cclIterExt2);
+      if(cell->badcell() == true){//check of bad tile cell
+	isbadtileext2cell = true;
+	break;
+      }
+    }
+    //---------------------- TileGap2 ----------------------------------//
+    bool isbadtilegap2cell = false;
+    ccl.select(clusterEta,clusterPhi,size,size,CaloSampling::TileGap2);
+    CaloCellList::list_iterator cclIterGap2     = ccl.begin();
+    CaloCellList::list_iterator cclIterGap2End  = ccl.end();
+    for( ;cclIterGap2!=cclIterGap2End;cclIterGap2++) {
+      const CaloCell* cell = (*cclIterGap2);
+      if(cell->badcell() == true){//check of bad tile cell
+	isbadtilegap2cell = true;
+	break;
+      }
+    }
+    //---------------------------------------------------------------//
+
+    if( isbadtilebar1cell || isbadtilebar2cell ||
+	isbadtileext1cell || isbadtileext2cell ||
+	isbadtilegap1cell || isbadtilegap2cell ){
+      iflag |= (0x1 << xAOD::EgammaParameters::DeadCellTileS1S2);    
+    }
+
+  }//End of the "AllCalo" condition
+  //=================================================================================//
+
+  // std::cout << "TOTO " << iflag << std::endl; 
+  eg->setOQ(iflag);
+  
+  
+  ATH_MSG_DEBUG("Executing egammaOQFlagsBuilder::execute");
+  
+  
+  return StatusCode::SUCCESS;
+}
+
+
+
diff --git a/Reconstruction/egamma/egammaTools/src/egammaOQFlagsBuilder.h b/Reconstruction/egamma/egammaTools/src/egammaOQFlagsBuilder.h
new file mode 100644
index 0000000000000..88dc9f65fe30a
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/egammaOQFlagsBuilder.h
@@ -0,0 +1,97 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef EGAMMATOOLS_EGAMMAOQFLAGSBUILDER_H
+#define EGAMMATOOLS_EGAMMAOQFLAGSBUILDER_H
+/**
+  @class egammaOQFlagsBuilder
+  egamma Object Quality flags data object builder : 
+    - This tool checks if any cell of the cluster associated to the egamma object is affected by a detector problem: non nominal or dead high voltage, readout problems, missing FEBs, high quality factor, timing, etc.... If this is the case, then a bit corresponding to a specific problem is filled ( see egammaEvent/egammaEvent/egammaPIDdefs.h for bits definition).
+Most of the informations are given separately for each layer of the EM calorimeter. They are also separately stored for the core (3x3 central cells in the middle layer of the EM calorimeter) and the edge (all the other cells) of the cluster.
+ 
+  @author Frederic Derue derue@lpnhe.in2p3.fr
+  @author Francesco Polci polci@lpsc.in2p3.fr
+  @author Quentin Buat quentin.buat@lpsc.in2p3.fr
+
+*/
+
+// INCLUDE HEADER FILES: 
+#include "egammaBaseTool.h"
+
+#include "GaudiKernel/ToolHandle.h"
+#include "LArRecConditions/ILArBadChanTool.h"
+#include "LArTools/LArCablingService.h"
+#include "CaloIdentifier/LArEM_ID.h"
+#include "Identifier/HWIdentifier.h"
+#include "CaloIdentifier/CaloCell_ID.h"
+#include "CaloConditions/CaloAffectedRegionInfoVec.h"
+#include "CaloInterface/ICaloAffectedTool.h"
+#include "CaloUtils/CaloCellList.h"
+
+#include "xAODEgamma/EgammaFwd.h"
+#include "xAODCaloEvent/CaloClusterFwd.h"
+
+class IToolSvc;
+class CaloCellContainer;
+class ILArBadChanTool;
+class HWIdentifier;
+class LArEM_ID;
+class CaloCell_ID;
+
+class egammaOQFlagsBuilder : public egammaBaseTool
+{
+ public:
+
+  /** @brief Default constructor*/
+  egammaOQFlagsBuilder(const std::string& type,
+		       const std::string& name,
+		       const IInterface* parent);
+   
+  /** @brief Destructor*/
+  ~egammaOQFlagsBuilder();
+	
+  /** @brief initialize method*/
+  StatusCode initialize();
+  /** @brief standard execute method */
+  virtual StatusCode execute(xAOD::Egamma*);
+  /** @brief finalize method*/
+  StatusCode finalize();
+
+
+ protected:
+  /** Handle to bad-channel tools */
+  ToolHandle<ILArBadChanTool> m_badChannelTool;
+  ToolHandle<LArCablingService> m_larCablingSvc;
+  ToolHandle<ICaloAffectedTool> m_affectedTool;
+  const LArEM_ID* m_emHelper;
+  const CaloCell_ID* m_calocellId;
+  const CaloAffectedRegionInfoVec* m_affRegVec;
+  const CaloCellContainer* m_cellcoll;
+  std::string m_cellsName;
+ private:
+  // IToolSvc* m_toolSvc;
+  bool isCore(Identifier Id, const std::vector<IdentifierHash>& neighbourList) const;
+  std::vector<IdentifierHash> findNeighbours( Identifier cellCentrId);
+  Identifier m_cellCentrId;
+  bool findCentralCell(const xAOD::CaloCluster* cluster);
+  StoreGateSvc*                 m_detStore;
+  double m_QCellCut;
+  double m_QCellHECCut;
+  double m_QCellSporCut;
+  double m_LArQCut;
+  double m_TCut;
+  double m_TCutVsE;
+
+};
+
+#endif
+
+
+
+
+
+
+
+
+
diff --git a/Reconstruction/egamma/egammaTools/src/egammaSwTool.cxx b/Reconstruction/egamma/egammaTools/src/egammaSwTool.cxx
new file mode 100644
index 0000000000000..e229941a5966f
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/egammaSwTool.cxx
@@ -0,0 +1,341 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+#include "egammaSwTool.h"
+
+
+#include "xAODCaloEvent/CaloCluster.h"
+#include "CaloUtils/CaloLayerCalculator.h"
+#include "CaloUtils/CaloClusterStoreHelper.h"
+#include "CaloRec/CaloClusterProcessor.h"
+
+#include "GaudiKernel/ListItem.h"
+
+#include <algorithm> 
+#include <math.h>
+
+//  END OF HEADER FILES INCLUDE
+
+/////////////////////////////////////////////////////////////////
+
+//  CONSTRUCTOR:
+
+egammaSwTool::egammaSwTool(const std::string& type,
+			   const std::string& name,
+			   const IInterface* parent)
+  : AthAlgTool(type, name, parent)
+{
+
+  // declare interface
+  declareInterface<IegammaSwTool>(this);
+
+  // The following properties are specified at run-time
+  // (declared in jobOptions file)   
+  
+  // Name(s) of Cluster Correction Tools
+  declareProperty("ClusterCorrectionToolsEle55",m_clusterCorrectionNamesEle55);
+  declareProperty("ClusterCorrectionToolsEle35",m_clusterCorrectionNamesEle35);
+  declareProperty("ClusterCorrectionToolsEle37",m_clusterCorrectionNamesEle37);
+
+  declareProperty("ClusterCorrectionToolsGam35",m_clusterCorrectionNamesGam35);
+  declareProperty("ClusterCorrectionToolsGam55",m_clusterCorrectionNamesGam55);
+
+  declareProperty("ClusterCorrectionToolsEconv55",m_clusterCorrectionNamesEconv55);
+  declareProperty("ClusterCorrectionToolsEconv35",m_clusterCorrectionNamesEconv35);
+  declareProperty("ClusterCorrectionToolsEconv37",m_clusterCorrectionNamesEconv37);
+}
+
+// ===============================================================
+// DESTRUCTOR:
+egammaSwTool::~egammaSwTool()
+{ 
+}
+
+// ===============================================================
+// INITIALIZE METHOD:
+StatusCode egammaSwTool::initialize()
+{
+  ATH_MSG_DEBUG(" Initializing egammaSwTool");
+  
+  StatusCode sc;
+
+  // the tool to extrapolate
+  IToolSvc* p_toolSvc = 0;
+  sc = service("ToolSvc",p_toolSvc);
+  if ( sc.isFailure() ){
+    ATH_MSG_ERROR("Cannot find ToolSvc! ");
+    return StatusCode::FAILURE;
+  }
+  else {
+    
+    // CaloClusterCorrections tools
+    std::vector<std::string>::const_iterator firstTool=m_clusterCorrectionNamesEle55.begin();
+    std::vector<std::string>::const_iterator lastTool =m_clusterCorrectionNamesEle55.end();
+    
+    for ( ; firstTool != lastTool; firstTool++ ) {
+      IAlgTool* algToolPtr;
+      ListItem  clusAlgoTool(*firstTool);
+      StatusCode sCode = p_toolSvc->retrieveTool(clusAlgoTool.type(),
+						 clusAlgoTool.name(),
+						 algToolPtr,
+						 this);
+      if ( sCode.isFailure() ) {
+	ATH_MSG_ERROR("Cannot find tool for " << *firstTool);
+      }
+      else {
+	ATH_MSG_DEBUG("Found tool for " << *firstTool);
+	// check for tool type
+	CaloClusterProcessor* 
+	  theTool = dynamic_cast<CaloClusterProcessor*>(algToolPtr);
+	if ( theTool != 0 ) { 
+	  m_clusterCorrectionPointersEle55.push_back(theTool); 
+	}
+      } 
+    }
+
+    firstTool=m_clusterCorrectionNamesEle35.begin();
+    lastTool =m_clusterCorrectionNamesEle35.end();
+    
+    for ( ; firstTool != lastTool; firstTool++ ) {
+      IAlgTool* algToolPtr;
+      ListItem  clusAlgoTool(*firstTool);
+      StatusCode sCode = p_toolSvc->retrieveTool(clusAlgoTool.type(),
+						 clusAlgoTool.name(),
+						 algToolPtr,
+						 this);
+      if ( sCode.isFailure() ) {
+	ATH_MSG_ERROR("Cannot find tool for " << *firstTool);
+      }
+      else {
+	ATH_MSG_DEBUG("Found tool for " << *firstTool);
+	// check for tool type
+	CaloClusterProcessor* 
+	  theTool = dynamic_cast<CaloClusterProcessor*>(algToolPtr);
+	if ( theTool != 0 ) { 
+	  m_clusterCorrectionPointersEle35.push_back(theTool); 
+	}
+      } 
+    }
+    
+    firstTool=m_clusterCorrectionNamesEle37.begin();
+    lastTool =m_clusterCorrectionNamesEle37.end();
+    
+    for ( ; firstTool != lastTool; firstTool++ ) {
+      IAlgTool* algToolPtr;
+      ListItem  clusAlgoTool(*firstTool);
+      StatusCode sCode = p_toolSvc->retrieveTool(clusAlgoTool.type(),
+						 clusAlgoTool.name(),
+						 algToolPtr,
+						 this);
+      if ( sCode.isFailure() ) {
+	ATH_MSG_ERROR("Cannot find tool for " << *firstTool);
+      }
+      else {
+	ATH_MSG_DEBUG("Found tool for " << *firstTool);
+	// check for tool type
+	CaloClusterProcessor* 
+	  theTool = dynamic_cast<CaloClusterProcessor*>(algToolPtr);
+	if ( theTool != 0 ) { 
+	  m_clusterCorrectionPointersEle37.push_back(theTool); 
+	}
+      } 
+    }
+
+    firstTool=m_clusterCorrectionNamesGam35.begin();
+    lastTool =m_clusterCorrectionNamesGam35.end();
+    
+    for ( ; firstTool != lastTool; firstTool++ ) {
+      IAlgTool* algToolPtr;
+      ListItem  clusAlgoTool(*firstTool);
+      StatusCode sCode = p_toolSvc->retrieveTool(clusAlgoTool.type(),
+						 clusAlgoTool.name(),
+						 algToolPtr,
+						 this);
+      if ( sCode.isFailure() ) {
+	ATH_MSG_ERROR("Cannot find tool for " << *firstTool);
+      }
+      else {
+	ATH_MSG_DEBUG("Found tool for " << *firstTool);
+	// check for tool type
+	CaloClusterProcessor* 
+	  theTool = dynamic_cast<CaloClusterProcessor*>(algToolPtr);
+	if ( theTool != 0 ) { 
+	  m_clusterCorrectionPointersGam35.push_back(theTool); 
+	}
+      } 
+    }
+    
+    firstTool=m_clusterCorrectionNamesGam55.begin();
+    lastTool =m_clusterCorrectionNamesGam55.end();
+    
+    for ( ; firstTool != lastTool; firstTool++ ) {
+      IAlgTool* algToolPtr;
+      ListItem  clusAlgoTool(*firstTool);
+      StatusCode sCode = p_toolSvc->retrieveTool(clusAlgoTool.type(),
+						 clusAlgoTool.name(),
+						 algToolPtr,
+						 this);
+      if ( sCode.isFailure() ) {
+	ATH_MSG_ERROR("Cannot find tool for " << *firstTool);
+      }
+      else {
+	ATH_MSG_DEBUG("Found tool for " << *firstTool);
+	// check for tool type
+	CaloClusterProcessor* 
+	  theTool = dynamic_cast<CaloClusterProcessor*>(algToolPtr);
+	if ( theTool != 0 ) { 
+	  m_clusterCorrectionPointersGam55.push_back(theTool); 
+	}
+      } 
+    }
+
+    firstTool=m_clusterCorrectionNamesEconv55.begin();
+    lastTool =m_clusterCorrectionNamesEconv55.end();
+    
+    for ( ; firstTool != lastTool; firstTool++ ) {
+      IAlgTool* algToolPtr;
+      ListItem  clusAlgoTool(*firstTool);
+      StatusCode sCode = p_toolSvc->retrieveTool(clusAlgoTool.type(),
+						 clusAlgoTool.name(),
+						 algToolPtr,
+						 this);
+      if ( sCode.isFailure() ) {
+	ATH_MSG_ERROR("Cannot find tool for " << *firstTool);
+      }
+      else {
+	ATH_MSG_DEBUG("Found tool for " << *firstTool);
+	// check for tool type
+	CaloClusterProcessor* 
+	  theTool = dynamic_cast<CaloClusterProcessor*>(algToolPtr);
+	if ( theTool != 0 ) { 
+	  m_clusterCorrectionPointersEconv55.push_back(theTool); 
+	}
+      } 
+    }
+
+    firstTool=m_clusterCorrectionNamesEconv35.begin();
+    lastTool =m_clusterCorrectionNamesEconv35.end();
+    
+    for ( ; firstTool != lastTool; firstTool++ ) {
+      IAlgTool* algToolPtr;
+      ListItem  clusAlgoTool(*firstTool);
+      StatusCode sCode = p_toolSvc->retrieveTool(clusAlgoTool.type(),
+						 clusAlgoTool.name(),
+						 algToolPtr,
+						 this);
+      if ( sCode.isFailure() ) {
+	ATH_MSG_ERROR("Cannot find tool for " << *firstTool);
+      }
+      else {
+	ATH_MSG_DEBUG("Found tool for " << *firstTool);
+	// check for tool type
+	CaloClusterProcessor* 
+	  theTool = dynamic_cast<CaloClusterProcessor*>(algToolPtr);
+	if ( theTool != 0 ) { 
+	  m_clusterCorrectionPointersEconv35.push_back(theTool); 
+	}
+      } 
+    }
+
+    firstTool=m_clusterCorrectionNamesEconv37.begin();
+    lastTool =m_clusterCorrectionNamesEconv37.end();
+    
+    for ( ; firstTool != lastTool; firstTool++ ) {
+      IAlgTool* algToolPtr;
+      ListItem  clusAlgoTool(*firstTool);
+      StatusCode sCode = p_toolSvc->retrieveTool(clusAlgoTool.type(),
+						 clusAlgoTool.name(),
+						 algToolPtr,
+						 this);
+      if ( sCode.isFailure() ) {
+	ATH_MSG_ERROR("Cannot find tool for " << *firstTool);
+      }
+      else {
+	ATH_MSG_DEBUG("Found tool for " << *firstTool);
+	// check for tool type
+	CaloClusterProcessor* 
+	  theTool = dynamic_cast<CaloClusterProcessor*>(algToolPtr);
+	if ( theTool != 0 ) { 
+	  m_clusterCorrectionPointersEconv37.push_back(theTool); 
+	}
+      } 
+    }
+
+    ATH_MSG_DEBUG("egammaSwTool initialisation completed successfully"); 
+  }    
+  
+  return sc;
+}
+
+// ==================================================================
+// FINALIZE METHOD:
+StatusCode egammaSwTool::finalize()
+{
+  return StatusCode::SUCCESS;
+}
+
+// ==============================================================
+// ATHENA EXECUTE METHOD:
+StatusCode egammaSwTool::execute(xAOD::CaloCluster *cluster)
+{ 
+  ATH_MSG_DEBUG("Executing egammaSwTool");
+  
+  // protection against bad clusters
+  if (cluster==0) return StatusCode::SUCCESS;
+
+  std::vector<CaloClusterProcessor*>::const_iterator firstTool, lastTool;
+  
+  xAOD::CaloCluster::ClusterSize requestedSize = cluster->clusterSize();
+  switch (requestedSize) {
+  case xAOD::CaloCluster::SW_55ele:
+    firstTool = m_clusterCorrectionPointersEle55.begin();
+    lastTool  = m_clusterCorrectionPointersEle55.end();
+    break;
+  case xAOD::CaloCluster::SW_35ele:
+    firstTool = m_clusterCorrectionPointersEle35.begin();
+    lastTool  = m_clusterCorrectionPointersEle35.end();
+    break;
+  case xAOD::CaloCluster::SW_37ele:
+    firstTool = m_clusterCorrectionPointersEle37.begin();
+    lastTool  = m_clusterCorrectionPointersEle37.end();
+    break;
+  case xAOD::CaloCluster::SW_35gam:
+    firstTool = m_clusterCorrectionPointersGam35.begin();
+    lastTool  = m_clusterCorrectionPointersGam35.end();
+    break;
+  case xAOD::CaloCluster::SW_55gam:
+    firstTool = m_clusterCorrectionPointersGam55.begin();
+    lastTool  = m_clusterCorrectionPointersGam55.end();
+    break;
+  case xAOD::CaloCluster::SW_55Econv:
+    firstTool = m_clusterCorrectionPointersEconv55.begin();
+    lastTool  = m_clusterCorrectionPointersEconv55.end();
+    break;
+  case xAOD::CaloCluster::SW_35Econv:
+    firstTool = m_clusterCorrectionPointersEconv35.begin();
+    lastTool  = m_clusterCorrectionPointersEconv35.end();
+    break;
+  case xAOD::CaloCluster::SW_37Econv:
+    firstTool = m_clusterCorrectionPointersEconv37.begin();
+    lastTool  = m_clusterCorrectionPointersEconv37.end();
+    break;
+  default:
+    ATH_MSG_DEBUG("Inexisting cluster type and calibration requested: " << requestedSize);
+    return StatusCode::FAILURE;
+    break;
+  }
+    
+  // loop tools
+  for ( ; firstTool != lastTool; firstTool++ ) {
+    StatusCode processCheck = (*firstTool)->execute(cluster);
+    if ( processCheck.isFailure() ) {
+      ATH_MSG_ERROR("Cluster corrections failed!");
+      //  return processCheck;
+    }
+  }
+
+  return StatusCode::SUCCESS;
+}
+
diff --git a/Reconstruction/egamma/egammaTools/src/egammaSwTool.h b/Reconstruction/egamma/egammaTools/src/egammaSwTool.h
new file mode 100644
index 0000000000000..1b159693a5f1d
--- /dev/null
+++ b/Reconstruction/egamma/egammaTools/src/egammaSwTool.h
@@ -0,0 +1,80 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef EGAMMATOOLS_EGAMMASWTOOL_H
+#define EGAMMATOOLS_EGAMMASWTOOL_H
+/**
+  @class egammaSwTool
+          Tool which applies positions and energy corrections to a CaloCluster
+@author D. Zerwas
+@author B. Lenzi 
+@author C. Anastopoulos 
+
+*/
+
+// INCLUDE HEADER FILES:
+ 
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "egammaInterfaces/IegammaSwTool.h" 
+#include "xAODCaloEvent/CaloClusterFwd.h"
+
+class CaloClusterProcessor;
+
+class egammaSwTool : public AthAlgTool, virtual public IegammaSwTool
+{
+
+ public:
+
+  /** @brief Default constructor*/
+  egammaSwTool(const std::string& type,
+	       const std::string& name,
+	       const IInterface* parent);
+
+  /** @brief Destructor*/
+  ~egammaSwTool();
+  
+  /** @brief initialize method*/
+  StatusCode initialize();
+  /** @brief finalize method*/
+  StatusCode finalize();
+  /** @brief execute method*/
+  StatusCode execute(xAOD::CaloCluster*);
+
+ private:
+  
+  /**
+   * @brief a list of names for tools to correct clusters
+   * 
+   * the tools in this list are executed after all maker tools are done
+   * and run one after each other on each cluster in the container.  */
+  std::vector<std::string> m_clusterCorrectionNamesEle55;
+  std::vector<std::string> m_clusterCorrectionNamesEle35;
+  std::vector<std::string> m_clusterCorrectionNamesEle37;
+  std::vector<std::string> m_clusterCorrectionNamesGam35;
+  std::vector<std::string> m_clusterCorrectionNamesGam55;
+  std::vector<std::string> m_clusterCorrectionNamesEconv55;
+  std::vector<std::string> m_clusterCorrectionNamesEconv35;
+  std::vector<std::string> m_clusterCorrectionNamesEconv37;
+
+  /** @brief the actual list of tools corresponding to above names */
+  std::vector<CaloClusterProcessor*>  m_clusterCorrectionPointersEle55; 
+  std::vector<CaloClusterProcessor*>  m_clusterCorrectionPointersEle35; 
+  std::vector<CaloClusterProcessor*>  m_clusterCorrectionPointersEle37; 
+  std::vector<CaloClusterProcessor*>  m_clusterCorrectionPointersGam35; 
+  std::vector<CaloClusterProcessor*>  m_clusterCorrectionPointersGam55; 
+  std::vector<CaloClusterProcessor*>  m_clusterCorrectionPointersEconv55; 
+  std::vector<CaloClusterProcessor*>  m_clusterCorrectionPointersEconv35; 
+  std::vector<CaloClusterProcessor*>  m_clusterCorrectionPointersEconv37; 
+};
+
+#endif
+
+
+
+
+
+
+
+
+
-- 
GitLab