diff --git a/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/CaloCellHelpers.h b/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/CaloCellHelpers.h
new file mode 100644
index 0000000000000000000000000000000000000000..24f6fb5040b585885c25ed9499ee9456dd61f749
--- /dev/null
+++ b/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/CaloCellHelpers.h
@@ -0,0 +1,99 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef REC_CALOCELLHELPERS_H
+#define REC_CALOCELLHELPERS_H
+
+#include <cmath>
+#include "CaloEvent/CaloCell.h"
+#include "CaloGeoHelpers/CaloPhiRange.h"
+
+inline double phiMean(double a, double b) { return 0.5*(a+b) + (a*b < 0)*M_PI; }
+
+/** Return true if the cell crossed was crossed by the track in phi **/
+inline bool crossedPhi(const CaloCell& cell, double phi_entrance, double phi_exit) {
+  double mean_phi = phiMean(phi_entrance, phi_exit);
+  double dphi = fabs( CaloPhiRange::diff(phi_entrance, phi_exit) );
+  double phi_min = mean_phi - dphi, phi_max = mean_phi + dphi;
+ 
+  return (CaloPhiRange::diff(cell.phi() + cell.caloDDE()->dphi()/2., phi_min) > 0 &&
+          CaloPhiRange::diff(phi_max, cell.phi() - cell.caloDDE()->dphi()/2.) > 0);
+}
+
+/** Return the % of path length crossed by the track inside a cell in eta **/
+inline double getPathLengthInEta(const CaloCell& cell, double eta_entrance, double eta_exit) {
+  double etaMin = cell.eta() - 0.5*cell.caloDDE()->deta();
+  double etaMax = cell.eta() + 0.5*cell.caloDDE()->deta();
+  if ( fabs(eta_entrance  - eta_exit) < 1e-6 ) // to avoid FPE
+    return eta_entrance > etaMin && eta_entrance < etaMax;
+   
+  double etaMinTrack = std::min(eta_entrance, eta_exit);
+  double etaMaxTrack = std::max(eta_entrance, eta_exit);
+  return (std::min(etaMax, etaMaxTrack) - std::max(etaMin, etaMinTrack))/(etaMaxTrack - etaMinTrack);
+}
+
+/** Return the % of path length crossed by the track inside a cell in Z **/
+inline double getPathLengthInZ(double zMin, double zMax, double z_entrance, double z_exit) {
+  if ( fabs(z_entrance  - z_exit) < 1e-6 ) // to avoid FPE
+    return z_entrance > zMin && z_entrance < zMax;
+ 
+  double zMinTrack = std::min(z_entrance, z_exit);
+  double zMaxTrack = std::max(z_entrance, z_exit);
+  return (std::min(zMax, zMaxTrack) - std::max(zMin, zMinTrack))/(zMaxTrack - zMinTrack);
+}
+
+/** Return the % of path length crossed by the track inside a cell in Z **/
+inline double getPathLengthInZ(const CaloCell& cell, double z_entrance, double z_exit) {
+  return getPathLengthInZ(cell.z() - 0.5*cell.caloDDE()->dz(), cell.z() + 0.5*cell.caloDDE()->dz(), z_entrance, z_exit);
+}
+
+// /** Return the % of path length crossed by the track inside a cell in Z for a ladder shaped cell **/
+// inline double getPathLengthInZTileBar1(const CaloCell& cell, double z_entrance, double z_exit) {
+//   // Divide the problem in 2 rectangles: the cell contains 6 tile rows, 3 in the bottom part, 3 in the top
+//   // Calculate the point where the track crossed the boundary between the bottom and top parts
+//   // and determine the path lenght inside each part
+//   TileCellDim *cell_dim = m_tileDDM->get_cell_dim(cell.caloDDE()->identify());
+//   if (!cell_dim || cell_dim->getNRows() != 6) // should always be the case for this sampling
+//     return 0;
+
+//   // Get the percentage in depth covered by the bottom part of the cell
+//   double R = (cell_dim->getRMax(2) - cell_dim->getRMin(0))/(cell_dim->getRMax(5) - cell_dim->getRMin(0));
+
+//   // The point where the track crossed the boundary
+//   double z_middle = z_entrance + R*(z_exit - z_entrance);
+
+//   // Get the boundaries of the 2 half-cells
+//   double zBottom_min = cell_dim->getZMin(0), zBottom_max = cell_dim->getZMax(0);
+//   double zTop_min = cell_dim->getZMin(3), zTop_max = cell_dim->getZMax(3);
+//   double pathBottom = getPathLengthInZ(zBottom_min, zBottom_max, z_entrance, z_middle);
+
+//   // Calculate the path traversed in the bottom and top parts
+//   if (zTop_min == zTop_max) { // top part of B9 cell has 0 width. Don't take the mean in this case 
+//     if ( fabs(z_middle) > fabs(zBottom_max) && pathBottom > 0)
+//       pathBottom = 1;
+//     return pathBottom;
+//   }
+//   double pathTop = getPathLengthInZ(zTop_min, zTop_max, z_middle, z_exit);
+//   // Take the weighted mean using the depth ratio since the method gives the %
+//   return R*pathBottom + (1.-R)*pathTop;
+// }
+
+/** Return the % of the path crossed inside the cell, given the parameters for the extrapolation at entrance and exit of the layer **/
+inline double pathInsideCell(const CaloCell& cell, const Amg::Vector3D& entry, const Amg::Vector3D& exit ) {
+  if (!crossedPhi(cell, entry.phi(), exit.phi()))
+    return 0;
+  double pathCrossed = 0;
+  if (cell.caloDDE()->getSubCalo() != CaloCell_ID::TILE)
+    pathCrossed = getPathLengthInEta(cell, entry.eta(), exit.eta());
+  else if (cell.caloDDE()->getSampling() == CaloCell_ID::TileBar1) // ladder shape cells, divide the problem in 2
+    pathCrossed = 0; //getPathLengthInZTileBar1(cell, entry.z(), exit.z());
+  else
+    pathCrossed = getPathLengthInZ(cell, entry.z(), exit.z());
+  if (pathCrossed <= 0)
+    return 0;
+  return pathCrossed;
+}
+
+
+#endif
diff --git a/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/CaloCellSelectorLayerdR.h b/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/CaloCellSelectorLayerdR.h
new file mode 100644
index 0000000000000000000000000000000000000000..6fef33a72e79fc729a0b4c9ea5e6aed27fd1c7b5
--- /dev/null
+++ b/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/CaloCellSelectorLayerdR.h
@@ -0,0 +1,43 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// CaloCellSelectorLayerdR.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+#ifndef CALOCELLSELECTORLAYERDR_H
+#define CALOCELLSELECTORLAYERDR_H
+
+#include "RecoToolInterfaces/ICaloCellSelector.h"
+#include "TrkParametersIdentificationHelpers/TrackParametersIdHelper.h"
+#include "GeoPrimitives/GeoPrimitives.h"
+#include "TrkCaloExtension/CaloExtensionHelpers.h"
+
+namespace Trk 
+{
+
+  //Recode of original method by TrackInCaloTools to select calo cells around track
+  //get mid point for each calo layer from the entry & exit point
+  //for each layer's mid point select calo cell within dR in the SAME layer
+  //Fast (?) but
+  //1. may miss calo cell at another layer which nevertheless is close to the crossing
+  //2. current implementation will fail in case where there's multiple entry to a calo layer
+
+  class CaloCellSelectorLayerdR : public ICaloCellSelector {
+  public:
+    CaloCellSelectorLayerdR(double coneSize);
+    ~CaloCellSelectorLayerdR ();
+
+    void setConeSize( double coneSize ) { m_coneSize2 = coneSize*coneSize; }
+
+    bool preSelectAction( const Trk::CaloExtension& caloExtension );
+    bool select( const CaloCell& cell ) const; // select or reject the cell
+
+  private:
+    CaloExtensionHelpers::EtaPhiHashLookupVector m_midPoints;
+    double m_coneSize2;
+    TrackParametersIdHelper  parsIdHelper;
+  };
+} // end of namespace
+
+#endif 
diff --git a/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/CaloCellSelectorMinPerp.h b/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/CaloCellSelectorMinPerp.h
new file mode 100644
index 0000000000000000000000000000000000000000..74b0ad91d00ab759ddcb81cf311c8c23a45be080
--- /dev/null
+++ b/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/CaloCellSelectorMinPerp.h
@@ -0,0 +1,41 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// CaloCellSelectorMinPerp.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+#ifndef CALOCELLSELECTORLAYERDR_H
+#define CALOCELLSELECTORLAYERDR_H
+
+#include "RecoToolInterfaces/ICaloCellSelector.h"
+#include "GeoPrimitives/GeoPrimitives.h"
+
+
+namespace Trk 
+{
+
+  //Using min perperdicular distance from the nearest interpolated track segment as selection criteria
+  //the nearest interpolation point need not be at the same layer as the cell
+  //so the "missing calo cell at another layer" problem in the "classic" method
+  //is avoided.
+  //Slower as need to find nearest interpoaltion point for each calo cell
+
+  class CaloCellSelectorMinPerp : public ICaloCellSelector {
+  public:
+    CaloCellSelectorMinPerp(double coneSize);
+    ~CaloCellSelectorMinPerp () = default;
+
+    bool preSelectAction( const Trk::CaloExtension& caloExtension );
+
+    bool select( const CaloCell& cell )const; // select or reject the cell
+
+  private:
+    const Trk::CaloExtension* m_caloExtension;
+    double m_coneSize;
+    Amg::Vector3D m_meanPos;
+    double m_perp2cut;
+  };
+} // end of namespace
+
+#endif 
diff --git a/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/CaloCellSelectorNearestdR.h b/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/CaloCellSelectorNearestdR.h
new file mode 100644
index 0000000000000000000000000000000000000000..4eee779133cedb022dadf690ad9c7830601daf65
--- /dev/null
+++ b/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/CaloCellSelectorNearestdR.h
@@ -0,0 +1,41 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// CaloCellSelectorNearestdR.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+#ifndef CALOCELLSELECTORLAYERDR_H
+#define CALOCELLSELECTORLAYERDR_H
+
+#include "RecoToolInterfaces/ICaloCellSelector.h"
+
+
+namespace Trk 
+{
+  class CaloExtension;
+
+  //Using dR from the nearest interpolation point as selection criteria
+  //the nearest interpolation point need not be at the same layer as the cell
+  //so the "missing calo cell at another layer" problem in the "classic" method
+  //is avoided.
+  //Slower as need to find nearest interpoaltion point for each calo cell
+
+  class CaloCellSelectorNearestdR : public ICaloCellSelector {
+  public:
+    CaloCellSelectorNearestdR(double coneSize);
+    ~CaloCellSelectorNearestdR ();
+
+    bool preSelectAction( const Trk::CaloExtension& caloExtension );
+
+    bool select( const CaloCell& cell )const; // select or reject the cell
+
+  private:
+    const Trk::CaloExtension* m_caloExtension;
+    double m_coneSize2;
+  };
+
+
+} // end of namespace
+
+#endif 
diff --git a/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/CaloCellSelectorRoughdR.h b/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/CaloCellSelectorRoughdR.h
new file mode 100644
index 0000000000000000000000000000000000000000..a6d4528bf45b6dcb1afcd09d68abf861314979c9
--- /dev/null
+++ b/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/CaloCellSelectorRoughdR.h
@@ -0,0 +1,45 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// CaloCellSelectorRoughdR.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+#ifndef CALOCELLSELECTORLAYERDR_H
+#define CALOCELLSELECTORLAYERDR_H
+
+#include "RecoToolInterfaces/ICaloCellSelector.h"
+#include "TrkParametersIdentificationHelpers/TrackParametersIdHelper.h"
+
+#include "TrkCaloExtension/CaloExtensionHelpers.h"
+
+namespace Trk 
+{
+  //Rough method to select calo cells around track
+  //mean eta phi was found for all the calorimeter layer crossing points
+  //cells within dR+tolerance around the mean are selected
+  //tolerance is the max deviation of individual cross points from the mean
+  //Fast and easy, but not very valid when the track is highly curved
+
+  class CaloCellSelectorRoughdR : public ICaloCellSelector {
+  public:
+    CaloCellSelectorRoughdR(double coneSize);
+    ~CaloCellSelectorRoughdR ();
+
+    bool preSelectAction( const Trk::CaloExtension& caloExtension );
+
+    bool select( const CaloCell& cell )const; // select or reject the cell
+
+  private:
+    double m_coneSize, m_coneSize2;
+    double m_midEta;
+    double m_midPhi;
+    double m_maxDiff;
+
+    TrackParametersIdHelper  parsIdHelper;
+    CaloExtensionHelpers::EntryExitPerLayerVector m_crossPoints;
+  };
+
+} // end of namespace
+
+#endif 
diff --git a/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/CaloCellSelectorUtils.h b/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/CaloCellSelectorUtils.h
new file mode 100644
index 0000000000000000000000000000000000000000..7547e9b5b29464f0f98fc94839d75bee88d676b3
--- /dev/null
+++ b/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/CaloCellSelectorUtils.h
@@ -0,0 +1,24 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef CALOCELLSELECTORUTILS_H
+#define CALOCELLSELECTORUTILS_H
+
+#include "TrkCaloExtension/CaloExtension.h"
+
+namespace Utils
+{
+  double deltaPhi(double phi1, double phi2);
+
+  double deltaR2(double eta1, double eta2, double phi1, double phi2);
+
+  double deltaR(double eta1, double eta2, double phi1, double phi2);
+
+  void findNearestPoint( const Amg::Vector3D& inputPos, const Trk::CaloExtension* caloExtension,
+                         int&           nearestIdx,
+                         Amg::Vector3D& nearestPos,
+                         Amg::Vector3D& nearestMom );
+}
+
+#endif
diff --git a/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/CrossedCaloCellHelper.h b/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/CrossedCaloCellHelper.h
new file mode 100644
index 0000000000000000000000000000000000000000..67c396a3e6a837fbefd8271472b476c333ece863
--- /dev/null
+++ b/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/CrossedCaloCellHelper.h
@@ -0,0 +1,42 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef CROSSEDCALOCELLHELPER_H
+#define CROSSEDCALOCELLHELPER_H
+
+#include "CaloUtils/CaloClusterStoreHelper.h"
+#include "CaloEvent/CaloCellContainer.h"
+#include "xAODCaloEvent/CaloClusterContainer.h"
+#include "xAODCaloEvent/CaloCluster.h"
+#include "ParticleCaloExtension/ParticleCellAssociation.h"
+
+namespace Rec {
+
+  class CrossedCaloCellHelper {
+  public:
+    
+    static xAOD::CaloCluster* crossedCells( const Rec::ParticleCellAssociation& association, 
+                                            const CaloCellContainer& cellContainer, 
+                                            xAOD::CaloClusterContainer& clusterContainer ) {
+      
+      // create cluster
+      xAOD::CaloCluster* cluster = CaloClusterStoreHelper::makeCluster(&clusterContainer,&cellContainer); 
+      if( !cluster ){
+        return nullptr;
+      }
+      
+      // loop over intersections and add cells to cluster
+      for( auto entry : association.cellIntersections() ){
+        if( !entry.first || !entry.first->caloDDE() ) continue;
+        int index = cellContainer.findIndex(entry.first->caloDDE()->calo_hash());
+        if( index == -1 ) continue;
+        cluster->addCell(index,1.);
+      }
+      return cluster;
+    }
+  };
+
+}
+
+#endif
diff --git a/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/ExtrapolateToCaloTool.h b/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/ExtrapolateToCaloTool.h
deleted file mode 100644
index ee4b80bb19b707ac8989c4cb8d68e62fd1faa2b8..0000000000000000000000000000000000000000
--- a/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/ExtrapolateToCaloTool.h
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-// ***************************************************************************
-// ExtrapolateToCaloTool
-// ***************************************************************************
-
-#ifndef TRACKTOCALO_EXTRAPOLATETOCALOTOOL_H
-#define TRACKTOCALO_EXTRAPOLATETOCALOTOOL_H
-
-#include "RecoToolInterfaces/IExtrapolateToCaloTool.h"
-
-#include "AthenaBaseComps/AthAlgTool.h"
-#include "GaudiKernel/ToolHandle.h"
-#include "TrkParameters/TrackParameters.h"  // typedef
-
-// xAOD
-#include "xAODTracking/NeutralParticle.h" // typedef
-#include "xAODTracking/TrackParticle.h" // typedef
-
-
-class CaloDepthTool;
-class ICaloSurfaceBuilder;
-
-class ImpactInCalo;
-
-namespace Trk {
-    class Track;
-    class IExtrapolator;
-    class Surface;
-}
-
-//<<<<<< INCLUDES >>>>>>
-
-/** @class ExtrapolateToCaloTool
-This class takes a given Trk::Track, extrapolates it to the Calo
-    and returns the variables needed to compare with the cluster
-    position.
- 
-    It heavily uses the Tracking Extrapolator class. 
- 
-    The client is asked to select explicitely the CaloCell_ID::CaloSample where he wants to extrapolate.
-    The 3 steps are combined :
-       - first guess of eta : take it from last point measured for Trk::Track or the input parameters
-       - CreateUserSurface(sample,offset,trketa)
-       - extrapolate
-       
-   Other methods exist which return a vector of Trk::TrackParameters at all calorimeter layers.
-   The CaloDepthTool is used to decide which sample is hit at a layer.
- 
- 
-   INTERFACE :
- 
-   Calorimeter : use CaloCell_ID::CaloSample to choose the sample to extrapolate to
- 
-   Trk::Trk  is recommended while running the full reconstruction or on ESD. If so, the 
-             extrapolation starts from the last measured point.
- 
-   Trk::TrackParameters  is mandatory while running on AOD's and can be used if you want to start
-                   the extrapolation from the perigee.
- 
-    @author Sebastian.Fleischmann@cern.ch
- */
-
-class ExtrapolateToCaloTool : public AthAlgTool,
-            virtual public IExtrapolateToCaloTool
-{
-public:
-
-    // Constructor:
-
-    ExtrapolateToCaloTool(const std::string& type,
-                          const std::string& name,
-                          const IInterface* parent);
-
-    ~ExtrapolateToCaloTool();
-    StatusCode initialize();
-    StatusCode finalize();
-
-    
-    /** get Trk::TrackParameters at the calorimeter sample from Trk::Track
-    Particle hypothesis of the track is used, if given hypothesis is set to Trk::undefined */
-    virtual const Trk::TrackParameters* extrapolate (const Trk::Track& trk,
-            const CaloCell_ID::CaloSample sample,
-            const double offset,
-            const Trk::PropDirection dir,
-            const Trk::ParticleHypothesis particle) const;
-
-
-    /** get Trk::TrackParameters at the calorimeter sample from Trk::TrackParticleBase.
-        If the Trk::ParticleHypothesis is undefined the tool tries to extract the hypothesis
-        from the given Trk::TrackParticleBase (if this does not succeed Trk::nonInteracting is used) */
-    virtual const Trk::TrackParameters* extrapolate (const Trk::TrackParticleBase& trk,
-            const CaloCell_ID::CaloSample sample,
-            const double offset,
-            const Trk::PropDirection dir,
-            const Trk::ParticleHypothesis particle) const;
-
-    /** get Trk::TrackParameters at the calorimeter sample from Trk::TrackParameters */
-    virtual const Trk::TrackParameters* extrapolate (const Trk::TrackParameters& trkPar,
-            const CaloCell_ID::CaloSample sample,
-            const double offset,
-            Trk::ParticleHypothesis particle,
-            const Trk::PropDirection dir) const;
-
-    /** get Trk::NeutralParameters at the calorimeter sample from Trk::NeutralParameters */
-    virtual const Trk::NeutralParameters* extrapolate (const Trk::NeutralParameters& trkPar,
-            const CaloCell_ID::CaloSample sample,
-            const double offset,
-            Trk::ParticleHypothesis particle,
-            const Trk::PropDirection dir) const;
-
-    /** get Trk::TrackParameters at the calorimeter sample from xAOD::TrackParticle */
-    virtual const Trk::TrackParameters* extrapolate (const  xAOD::TrackParticle& trk,
-            const CaloCell_ID::CaloSample sample,
-            const double offset,
-            const Trk::PropDirection dir=Trk::alongMomentum,
-            const Trk::ParticleHypothesis particle=Trk::undefined) const;
-
-    /** get Trk::NeutralParameters at the calorimeter sample from xAOD::NeutralParticle */
-    virtual const Trk::NeutralParameters* extrapolate (const xAOD::NeutralParticle& trk,
-            const CaloCell_ID::CaloSample sample,
-            const double offset,
-            const Trk::PropDirection dir=Trk::alongMomentum ) const;
-            
-    /** get vector of Trk::TrackParameters
-    at the different calorimeter samples from Trk::TrackParameters */
-    virtual const DataVector< const Trk::TrackParameters >* getParametersInCalo (const Trk::TrackParameters& parameters,
-            Trk::ParticleHypothesis particle,
-            const Trk::PropDirection dir) const;
-
-
-    /** get vector of Trk::NeutralParameters
-    at the different calorimeter samples from Trk::NeutralParameters */
-    virtual const DataVector< const Trk::NeutralParameters >* getParametersInCalo (const Trk::NeutralParameters& parameters,
-            Trk::ParticleHypothesis particle,
-            const Trk::PropDirection dir) const;
-
-
-    /** get DataVector of Trk::TrackParameters
-    at the different calorimeter samples from Trk::TrackParticleBase. The DataVector owns the Trk::TrackParameters,
-    but the DataVector itself needs to be deleted by the client.
-    If the Trk::ParticleHypothesis is undefined the tool tries to extract the hypothesis
-    from the given Trk::TrackParticleBase (if this does not succeed Trk::nonInteracting is used)*/
-    virtual const DataVector< const Trk::TrackParameters >* getParametersInCalo (const Trk::TrackParticleBase& trk,
-            const Trk::ParticleHypothesis particle,
-            const Trk::PropDirection dir) const;
-
-    virtual const DataVector< const Trk::TrackParameters >* getParametersInCalo (const xAOD::TrackParticle& trk,
-            const Trk::ParticleHypothesis particle=Trk::undefined,
-            const Trk::PropDirection dir=Trk::alongMomentum) const;
-
-    /** get DataVector of Trk::TrackParameters
-        at the different calorimeter samples from Trk::Track. The DataVector owns the Trk::TrackParameters,
-        but the DataVector itself needs to be deleted by the client.
-        Particle hypothesis of the track is used, if given hypothesis is set to Trk::undefined */
-    virtual const DataVector< const Trk::TrackParameters >* getParametersInCalo (const Trk::Track& trk,
-            const Trk::ParticleHypothesis particle,
-            const Trk::PropDirection dir) const;
-
-    /** get ImpactInCalo from Trk::Track
-        Particle hypothesis of the track is used, if given hypothesis is set to Trk::undefined */
-    virtual ImpactInCalo* getImpactInCalo ( const Trk::Track& trk,
-                                            const Trk::ParticleHypothesis particle,
-                                            const Trk::PropDirection dir) const;
-
-    /** get ImpactInCalo from Trk::TrackParticleBase
-        If the Trk::ParticleHypothesis is undefined the tool tries to extract the hypothesis
-        from the given Trk::TrackParticleBase (if this does not succeed Trk::nonInteracting is used)*/
-    virtual ImpactInCalo* getImpactInCalo ( const Trk::TrackParticleBase& trk,
-                                            const Trk::ParticleHypothesis particle,
-                                            const Trk::PropDirection dir) const;
-
-    /** get ImpactInCalo from Trk::TrackParameters*/
-    virtual ImpactInCalo* getImpactInCalo (const Trk::TrackParameters& parameters,
-            Trk::ParticleHypothesis particleHypo,
-            const Trk::PropDirection dir) const;
-
-    /** get ImpactInCalo from Trk::NeutralParameters*/
-    virtual ImpactInCalo* getImpactInCalo (const Trk::NeutralParameters& parameters,
-            Trk::ParticleHypothesis particleHypo,
-            const Trk::PropDirection dir) const;
-    
-    /** get sum of the momenta at the vertex (designed for conversions) 
-        If reuse=true, try to get it from auxdata first  **/
-    virtual Amg::Vector3D getMomentumAtVertex(const xAOD::Vertex&, bool reuse=true) const;
-    
-    /** get straight line intersection in calo given position and momentum vectors **/
-    virtual Trk::SurfaceIntersection getIntersectionInCalo(const Amg::Vector3D& position,
-            const Amg::Vector3D& momentum, const CaloCell_ID::CaloSample) const;
-
-    /** access to the private tool used to define the extrapolation depth, needed to play with delta-eta */
-    virtual ToolHandle<CaloDepthTool> getCaloDepth();
-
-private:
-
-    ImpactInCalo* getImpactInCaloFromParametersInCalo(
-                const DataVector< const Trk::TrackParameters >& parametersInCalo) const;
-
-    ImpactInCalo* getImpactInCaloFromParametersInCalo(
-                const DataVector< const Trk::NeutralParameters >& parametersInCalo) const;
-
-    /** helper function to take last known parameter in calo and extrapolate it stepwise to next samplings, adds parameters to the DataVector */
-    void extrapolateStepwiseInCalo ( const Trk::TrackParameters& parameters,
-            Trk::ParticleHypothesis particle,
-            const Trk::PropDirection dir,
-            DataVector< const Trk::TrackParameters >& parameterVector) const;
-
-    /** helper function to take last known parameter in calo and extrapolate it stepwise to next samplings, adds parameters to the DataVector */
-    void extrapolateStepwiseInCalo ( const Trk::NeutralParameters& parameters,
-            Trk::ParticleHypothesis particle,
-            const Trk::PropDirection dir,
-            DataVector< const Trk::NeutralParameters >& parameterVector) const;
-
-    // Defines the surfaces for extrapolation :
-    ToolHandle<ICaloSurfaceBuilder> m_calosurf;         //!< tool handle to the calo surface builder
-    // gives the distance to calo border to decide if barrel or endcap is hit
-    ToolHandle<CaloDepthTool>       m_calodepth;        //!< tool handle to the calo depth tool
-
-    // Pre-configured extrapolator
-    ToolHandle< Trk::IExtrapolator > m_extrapolator;    //!< tool handle to the extrapolator
-
-    double                          m_offsetPresampler; //!< jobOption: offset for presampler
-    double                          m_offsetStrip;      //!< jobOption: offset for strip
-    double                          m_offsetMiddle;     //!< jobOption: offset for em middle
-    double                          m_offsetBack;       //!< jobOption: offset for em back
-    double                          m_offsetTile;       //!< jobOption: offset for tile/hec
-    bool                            m_assumeOrderedTracks;  //!< jobOption: assume ordered tracks
-    bool                            m_ignoreMaterialEffectsInsideCalo;  //!< jobOption: ignore material effects inside calo, if step-wise extrapolation to all layers of calo samplings is performed (used for getParametersInCalo() and getImpactInCalo() )
-
-};
-
-
-#endif // TRACKTOCALO_EXTRAPOLATETOCALOTOOL_H
diff --git a/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/ImpactInCalo.h b/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/ImpactInCalo.h
deleted file mode 100755
index 8a31996edf30736581835f2ed1badff04cb5773a..0000000000000000000000000000000000000000
--- a/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/ImpactInCalo.h
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#ifndef IMPACTINCALO_H
-#define IMPACTINCALO_H
-/*************************************************************************
-	Package:
-	File: ImpactInCalo.h
-	Description:
-           
-*************************************************************************/
-
-//<<<<<< INCLUDES
-
-/**
-
-The ImpactInCalo collection is created by the TrackToCaloAlg algorithm, 
-which loops on all Tracks of a given collection and extrapolates them 
-to the LAr presampler (_0), strips (_1), middle (_2), back (_3) and to the Tiles.
-
-For each impact point, the cartesian coordinate x,y,z are in the 
-official coordinate system, whereas etaCaloLocal and phiCaloLocal are the variables
-to be compared with the CaloCluster's.
-
-The Track DIRECTION at the impact point is also given, to avoid confusion with the
-POSITION of the impact point.
-
-This collection is used by the CBNT_TrackToCalo class.
-
- */
-
-class ImpactInCalo  {
-
- public:
-  // constructors
-  ImpactInCalo() {};
-  
-  ImpactInCalo( double x_0, double y_0, double z_0, 
-		double etaCaloLocal_0, double phiCaloLocal_0,
-		double trketa_at_0, double trkphi_at_0,
-		double x_1, double y_1, double z_1,
-		double etaCaloLocal_1, double phiCaloLocal_1,
-		double trketa_at_1, double trkphi_at_1,
-		double x_2, double y_2, double z_2, 
-		double etaCaloLocal_2, double phiCaloLocal_2,
-		double trketa_at_2, double trkphi_at_2,
-		double x_3, double y_3, double z_3, 
-		double etaCaloLocal_3, double phiCaloLocal_3,
-		double trketa_at_3, double trkphi_at_3,
-		double x_tile, double y_tile, double z_tile, 
-		double etaCaloLocal_tile, double phiCaloLocal_tile,
-		double trketa_at_tile, double trkphi_at_tile )
-    :
-    m_x_0(x_0), m_y_0(y_0), m_z_0(z_0),
-    m_etaCaloLocal_0(etaCaloLocal_0), m_phiCaloLocal_0(phiCaloLocal_0),
-    m_trketa_at_0(trketa_at_0),m_trkphi_at_0(trkphi_at_0),
-    m_x_1(x_1), m_y_1(y_1), m_z_1(z_1),
-    m_etaCaloLocal_1(etaCaloLocal_1), m_phiCaloLocal_1(phiCaloLocal_1),
-    m_trketa_at_1(trketa_at_1),m_trkphi_at_1(trkphi_at_1),
-    m_x_2(x_2), m_y_2(y_2), m_z_2(z_2),
-    m_etaCaloLocal_2(etaCaloLocal_2), m_phiCaloLocal_2(phiCaloLocal_2),
-    m_trketa_at_2(trketa_at_2),m_trkphi_at_2(trkphi_at_2),
-    m_x_3(x_3), m_y_3(y_3), m_z_3(z_3),
-    m_etaCaloLocal_3(etaCaloLocal_3), m_phiCaloLocal_3(phiCaloLocal_3),
-    m_trketa_at_3(trketa_at_3),m_trkphi_at_3(trkphi_at_3),
-    m_x_tile(x_tile), m_y_tile(y_tile), m_z_tile(z_tile),
-    m_etaCaloLocal_tile(etaCaloLocal_tile), m_phiCaloLocal_tile(phiCaloLocal_tile),
-    m_trketa_at_tile(trketa_at_tile),m_trkphi_at_tile(trkphi_at_tile)
-    {};
-
-  // destructor
-  virtual ~ImpactInCalo(){};
-  //	virtual ~ImpactInCalo(){};
-  
-  void print() const ;
-  
-  // gets
-  
-  // Presampler
-  inline double x_0() const { return m_x_0; }
-  inline double y_0() const { return m_y_0; }
-  inline double z_0() const { return m_z_0; }
-  inline double etaCaloLocal_0() const { return m_etaCaloLocal_0; } 
-  inline double phiCaloLocal_0() const { return m_phiCaloLocal_0; }
-  inline double trketa_at_0() const { return m_trketa_at_0; };
-  inline double trkphi_at_0() const { return m_trkphi_at_0; };
-  
-  // Strip
-  inline double x_1() const { return m_x_1; }
-  inline double y_1() const { return m_y_1; }
-  inline double z_1() const { return m_z_1; }
-  inline double etaCaloLocal_1() const { return m_etaCaloLocal_1; } 
-  inline double phiCaloLocal_1() const { return m_phiCaloLocal_1; }
-  inline double trketa_at_1() const { return m_trketa_at_1; };
-  inline double trkphi_at_1() const { return m_trkphi_at_1; };
-  
-  // Middle
-  inline double x_2() const { return m_x_2; }
-  inline double y_2() const { return m_y_2; }
-  inline double z_2() const { return m_z_2; }
-  inline double etaCaloLocal_2() const { return m_etaCaloLocal_2; } 
-  inline double phiCaloLocal_2() const { return m_phiCaloLocal_2; }
-  inline double trketa_at_2() const { return m_trketa_at_2; };
-  inline double trkphi_at_2() const { return m_trkphi_at_2; };
-  
-  // Back
-  inline double x_3() const { return m_x_3; }
-  inline double y_3() const { return m_y_3; }
-  inline double z_3() const { return m_z_3; }
-  inline double etaCaloLocal_3() const { return m_etaCaloLocal_3; } 
-  inline double phiCaloLocal_3() const { return m_phiCaloLocal_3; }
-  inline double trketa_at_3() const { return m_trketa_at_3; };
-  inline double trkphi_at_3() const { return m_trkphi_at_3; };
-  
-  // Tile
-  inline double x_tile() const { return m_x_tile; }
-  inline double y_tile() const { return m_y_tile; }
-  inline double z_tile() const { return m_z_tile; }
-  inline double etaCaloLocal_tile() const { return m_etaCaloLocal_tile; } 
-  inline double phiCaloLocal_tile() const { return m_phiCaloLocal_tile; }	
-  inline double trketa_at_tile() const { return m_trketa_at_tile; };
-  inline double trkphi_at_tile() const { return m_trkphi_at_tile; };
-  
- private:
-  
-  // Presampler
-  double m_x_0;
-  double m_y_0;
-  double m_z_0;
-  double m_etaCaloLocal_0; 
-  double m_phiCaloLocal_0;
-  double m_trketa_at_0;
-  double m_trkphi_at_0;
-  
-  // Strip
-  double m_x_1;
-  double m_y_1;
-  double m_z_1;
-  double m_etaCaloLocal_1; 
-  double m_phiCaloLocal_1;
-  double m_trketa_at_1;
-  double m_trkphi_at_1;
-  
-  // Middle
-  double m_x_2;
-  double m_y_2;
-  double m_z_2;
-  double m_etaCaloLocal_2; 
-  double m_phiCaloLocal_2;
-  double m_trketa_at_2;
-  double m_trkphi_at_2;
-  
-  // Back
-  double m_x_3;
-  double m_y_3;
-  double m_z_3;
-  double m_etaCaloLocal_3; 
-  double m_phiCaloLocal_3;
-  double m_trketa_at_3;
-  double m_trkphi_at_3;
-  
-  // Tile
-  double m_x_tile;
-  double m_y_tile;
-  double m_z_tile;
-  double m_etaCaloLocal_tile; 
-  double m_phiCaloLocal_tile;
-  double m_trketa_at_tile;
-  double m_trkphi_at_tile;
-  
-};
-
-
-#endif // IMPACTINCALO_H
diff --git a/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/ImpactInCaloAlg.h b/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/ImpactInCaloAlg.h
deleted file mode 100755
index de50a6cd1167f38160258a938ac4de980ad15b65..0000000000000000000000000000000000000000
--- a/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/ImpactInCaloAlg.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-///////////////////////////////////////////////////////////////////
-// ImpactInCaloAlg.h
-//   Header file for class ImpactInCaloAlg
-///////////////////////////////////////////////////////////////////
-// Top algorithm class for extrapolating tracks to Calo
-///////////////////////////////////////////////////////////////////
-
-
-#ifndef IMPACTINCALOALG_H
-#define IMPACTINCALOALG_H
-
-// Base class
-#include "AthenaBaseComps/AthAlgorithm.h"
-#include "GaudiKernel/ToolHandle.h"
-//#include "StoreGate/DataHandle.h"
-
-//#include "TrkTrack/Track.h"
-#include "TrkTrack/TrackCollection.h"   // typedef
-
-// #include "Particle/TrackParticleContainer.h"
-// #include "Particle/TrackParticle.h"
-
-//#include "TrackToCalo/ImpactInCalo.h"
-
-//#include "CaloDetDescr/CaloPhiRange.h"
-#include "CaloIdentifier/CaloCell_ID.h"
-
-
-class StoreGateSvc;
-class IExtrapolateToCaloTool;
-class ICaloCoordinateTool;
-class CaloDetDescrManager;
-class CaloCellList;
-class CaloDepthTool;
-class ImpactInCalo;
-
-namespace Trk {
-    class Track;
-    class ITrackSelectorTool;
-}
-namespace Rec {
-    class TrackParticle;
-    class TrackParticleContainer;
-}
-
-/**
-@class ImpactInCaloAlg
-This Algorithm is meant to be an example of use of the TrackToCalo tools.
-It is based on the TrackToCaloAlg, but uses the IExtrapolateToCaloTool:
- 
- - It loops on a given Track collection ( choosen by jobOption ) and extrapolates all tracks
-   to the layers of the calorimeter using the IExtrapolateToCaloTool.
- 
- - Impacts are stored in an ImpactInCaloCollection, which can then be used to fill CBNT
- 
- - An example of primitive Track to Cluster matching is provided, as well as an example of how
-   one can retreive all the CaloCell's around a track extrapolation, using the CaloCellList
-   class ( these 2 are off by default )
- 
-    @author Sebastian.Fleischmann@cern.ch
-*/
-
-class ImpactInCaloAlg : public AthAlgorithm  {
-
-public:
-
-    // Constructor with parameters:
-    ImpactInCaloAlg(const std::string &name,ISvcLocator *pSvcLocator);
-
-    ///////////////////////////////////////////////////////////////////
-    // Non-const methods:
-    ///////////////////////////////////////////////////////////////////
-
-    // Basic algorithm methods:
-    virtual StatusCode initialize();
-    virtual StatusCode execute();
-    virtual StatusCode finalize();
-
-    /** Loop on Trk::Tracks and create ImpactInCaloCollection */
-    StatusCode CreateTrkImpactInCalo();
-
-    /** Retreive ImpactInCaloCollection and compare to CaloClusters */
-    StatusCode CompareImpactWithCluster();
-    /** Debug output of impacts */
-    StatusCode PrintImpact();
-
-    /** List of cells crossed by Trk::Tracks
-     ( neta and nphi are the total window width, e.g .5x5 ) */
-    CaloCellList* CellsCrossedByTrack(const Trk::Track& trk ,
-                                      const CaloCell_ID::CaloSample sam,
-                                      int neta, int nphi);
-    /** Debug output of cells crossed*/
-    StatusCode PrintCellsCrossed();
-
-    ///////////////////////////////////////////////////////////////////
-    // Private methods:
-    ///////////////////////////////////////////////////////////////////
-//private:
-//     ImpactInCaloAlg();
-//     ImpactInCaloAlg(const ImpactInCaloAlg&);
-//     ImpactInCaloAlg &operator=(const ImpactInCaloAlg&);
-
-    ///////////////////////////////////////////////////////////////////
-    // Private data:
-    ///////////////////////////////////////////////////////////////////
-private:
-
-    std::string m_TrackName;                    //!< jobOption: Track collection name
-    const TrackCollection *m_tracks;            //!< pointer to TrackCollection
-    std::string m_TrackParticleName;            //!< jobOption: TrackParticle collection name
-    const Rec::TrackParticleContainer *m_particle;
-    std::string m_trkinput;                     //!< jobOption: which input type to use
-
-    std::string m_cluster_container;            //!< jobOption: Cluster container name
-    std::string m_cell_container;               //!< jobOption: Cell container name
-    const CaloCell_ID* m_calo_id;
-    const CaloDetDescrManager* m_calo_dd;
-
-    std::string m_ImpactInCalosOutputName;          //!< jobOption: Output name of ImpactInCaloCollection
-    ToolHandle < IExtrapolateToCaloTool > m_toCalo; //!< the ExtrapolateToCaloTool
-    ToolHandle < Trk::ITrackSelectorTool> m_trackSelectorTool;//!< handle to ITrackSelectorTool
-    //CaloDepthTool* m_calodepth;
-    //CaloPhiRange m_phiRange;
-
-    bool m_extrapolateInBothDirections; //!< jobOption: extrapolate each track in both directions (along and opposite momentum)?
-    bool m_compareImpWithCluster;       //!< jobOption: compare impacts with clusters?
-    bool m_printCellsCrossed;           //!< jobOption: print cells crossed by track?
-
-};
-
-#endif //IMPACTINCALOALG_H
-
diff --git a/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/ImpactInCaloCollection.h b/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/ImpactInCaloCollection.h
deleted file mode 100755
index 2eed0a6c82f68695b622dc8531cae5b2f22b54d0..0000000000000000000000000000000000000000
--- a/Reconstruction/RecoTools/TrackToCalo/TrackToCalo/ImpactInCaloCollection.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#ifndef IMPACTINCALOCOLLECTION_H
-#define IMPACTINCALOCOLLECTION_H
-
-#include "DataModel/DataVector.h"
-#include "CLIDSvc/CLASS_DEF.h"
-#include "TrackToCalo/ImpactInCalo.h"
-
-//class ImpactInCalo;
-class ImpactInCaloCollection : public DataVector<ImpactInCalo> {
-public:
-  virtual ~ImpactInCaloCollection() {};
-  
-      
-  
-  void print() const;	
-};
-
-
-
-CLASS_DEF(ImpactInCaloCollection,1237752222,1)
-
-
-#endif // IMPACTINCALOCOLLECTION_H
diff --git a/Reconstruction/RecoTools/TrackToCalo/cmt/requirements b/Reconstruction/RecoTools/TrackToCalo/cmt/requirements
index bfc823f2260841b6a8dbb0f65bd72c1e7651da2e..7e6f900d9dd8b338f599584d4e1a35868716a3ec 100755
--- a/Reconstruction/RecoTools/TrackToCalo/cmt/requirements
+++ b/Reconstruction/RecoTools/TrackToCalo/cmt/requirements
@@ -1,46 +1,43 @@
 package TrackToCalo
 
-author Claire Adam <claire.bourdarios@cern.ch>
+author Niels van Eldik
+author Yat Long Chan
+author Marco van Woerden
 
 use AtlasPolicy         AtlasPolicy-*
 use GaudiInterface      GaudiInterface-*        External 
-use AthenaBaseComps     AthenaBaseComps-*       Control
-use CLIDSvc             CLIDSvc-*               Control
 use RecoToolInterfaces  RecoToolInterfaces-*    Reconstruction/RecoTools
-use CaloIdentifier      CaloIdentifier-*        Calorimeter       
-use DataModel           DataModel-*             Control
-use TrkTrack            TrkTrack-*              Tracking/TrkEvent
-use TrkParameters       TrkParameters-*         Tracking/TrkEvent
-use xAODTracking          xAODTracking-*          Event/xAOD 
-
+use TrkCaloExtension    TrkCaloExtension-*      Tracking/TrkEvent
+use GeoPrimitives       GeoPrimitives-*         DetectorDescription
+use TrkParametersIdentificationHelpers TrkParametersIdentificationHelpers-* Tracking/TrkEvent
+use CaloEvent           CaloEvent-*             Calorimeter
+use CaloUtils           CaloUtils-*             Calorimeter
+use CaloGeoHelpers      CaloGeoHelpers-*        Calorimeter
+use ParticleCaloExtension ParticleCaloExtension-* Reconstruction/RecoEvent
+use xAODCaloEvent         xAODCaloEvent-*         Event/xAOD 
 
 private
-use StoreGate             StoreGate-*             Control
-use TrkParticleBase       TrkParticleBase-*       Tracking/TrkEvent
+use AthenaBaseComps       AthenaBaseComps-*       Control
+use xAODTracking          xAODTracking-*          Event/xAOD 
+use xAODTruth             xAODTruth-*             Event/xAOD 
+use xAODMuon              xAODMuon-*              Event/xAOD 
+use TrkTrack              TrkTrack-*              Tracking/TrkEvent
+use TrkParameters         TrkParameters-*         Tracking/TrkEvent
 use TrkEventPrimitives    TrkEventPrimitives-*    Tracking/TrkEvent
-use EventPrimitives       EventPrimitives-*       Event
-use CaloEvent             CaloEvent-*             Calorimeter
 use CaloUtils             CaloUtils-*             Calorimeter
-use CaloDetDescr          CaloDetDescr-*          Calorimeter
-use CaloGeoHelpers        CaloGeoHelpers-*        Calorimeter
-use CaloTrackingGeometry  CaloTrackingGeometry-*  Calorimeter
+use CaloInterface         CaloInterface-*         Calorimeter
 use TrkExInterfaces       TrkExInterfaces-*       Tracking/TrkExtrapolation
 use TrkToolInterfaces     TrkToolInterfaces-*     Tracking/TrkTools
 use TrkSurfaces           TrkSurfaces-*           Tracking/TrkDetDescr
-use Particle              Particle-*              Reconstruction
 use AtlasDetDescr         AtlasDetDescr-*         DetectorDescription
-use MagFieldInterfaces    MagFieldInterfaces-*    MagneticField
-
+use ParticlesInConeTools  ParticlesInConeTools-*  Reconstruction/RecoTools
+use FourMomUtils           FourMomUtils-*         Event
 public
 
-apply_pattern declare_joboptions files="*.py"
-
-apply_pattern declare_python_modules files="*.py"
-
-#apply_pattern dual_use_library files=*.cxx
+apply_pattern dual_use_library files=*.cxx
 
-library TrackToCalo *.cxx components/*.cxx
-apply_pattern component_library 
+#library TrackToCalo *.cxx components/*.cxx
+#apply_pattern component_library 
 
 #private
 #macro cppdebugflags '$(cppdebugflags_s)'
diff --git a/Reconstruction/RecoTools/TrackToCalo/doc/mainpage.h b/Reconstruction/RecoTools/TrackToCalo/doc/mainpage.h
index 5e04e6c0c4db5db0f2b0fede2ec8a149333949ee..5f70ef7498b78ee990810c4e074319ff3ace49eb 100755
--- a/Reconstruction/RecoTools/TrackToCalo/doc/mainpage.h
+++ b/Reconstruction/RecoTools/TrackToCalo/doc/mainpage.h
@@ -15,14 +15,7 @@ The following classes are defined in this package:
 
 @htmlinclude annotated.html
 
-   - ExtrapolateToCaloTool : Extrapolates Trk::Track, Trk::TrackParameters to the calorimeter samplings using the Trk::IExtrapolator (extended and revised version of ExtrapolTrackToCaloTool)
-   - ExtrapolTrackToCaloTool : Extrapolates Trk::Track to the calorimeter samplings
-   - TrackToCaloAlg : Example algorithm which uses ExtrapolTrackToCaloTool to create a ImpactInCaloCollection
-   - ImpactInCaloAlg : Example algorithm which uses ExtrapolateToCaloTool to create a ImpactInCaloCollection
-   - CBNT_TrackToCalo : Writes contents of ImpactInCaloCollection into CBNT
-   - CBNTAA_TrackToCalo : Writes contents of ImpactInCaloCollection into CBNTAA
-   - ImpactInCalo : data class containing impact positions and directions at the various calorimter samplings
-   - ImpactInCaloCollection : collection of ImpactInCalo
+
 
 @section ExtrasTrackToCalo Extra Pages
 
diff --git a/Reconstruction/RecoTools/TrackToCalo/python/ExtrapolateToCaloToolBase.py b/Reconstruction/RecoTools/TrackToCalo/python/ExtrapolateToCaloToolBase.py
deleted file mode 100644
index 476e780459201f84e986d5205bebb149140255a1..0000000000000000000000000000000000000000
--- a/Reconstruction/RecoTools/TrackToCalo/python/ExtrapolateToCaloToolBase.py
+++ /dev/null
@@ -1,98 +0,0 @@
-# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-
-
-from TrackToCalo.TrackToCaloConf import ExtrapolateToCaloTool
-
-class ExtrapolateToCaloToolBase ( ExtrapolateToCaloTool )  :
-
-    def __init__(self):
-        mlog = logging.getLogger( name+'(Base)::__init__ dummy for instance copy' )
-        mlog.info('entering')
-        ExtrapolateToCaloTool.__init__( self) # call base class constructor
-        pass
-
-    def __init__(self, name="ExtrapolateToCaloToolBaseUNSET", depth="showerdefault", straightLine=False):
-
-        ExtrapolateToCaloTool.__init__( self,name) # call base class constructor
-
-        from AthenaCommon.Logging import logging
-        mlog = logging.getLogger( name+'(Base)::__init__ ' )
-        mlog.info("entering")
-
-
-        if name=="ExtrapolateToCaloToolBaseUNSET":
-            mlog.info ("name should be explicitly set")
-            return
-
-        # this creates CaloDepthTool and a CaloSurfaceBuilder where the depth is set to the given value:
-        from CaloTrackingGeometry.CaloSurfaceBuilderBase import CaloSurfaceBuilderFactory
-        theCaloSurfaceBuilder = CaloSurfaceBuilderFactory(depth)
-        # set as public tool
-        from AthenaCommon.AppMgr import ToolSvc
-        ToolSvc += theCaloSurfaceBuilder
-        # use the CaloSurfaceBuilder and the CaloDepthTool
-        self.CaloSurfaceBuilder = theCaloSurfaceBuilder
-        self.CaloDepthTool = theCaloSurfaceBuilder.CaloDepthTool
-
-        #if not straightLine:
-            #theExtrapolator=AtlasExtrapolator(name = 'TrackToCaloExtrapolator')
-            #theExtrapolator.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
-
-            #theExtrapolator.MaterialEffectsUpdators = MyUpdators
-            #theExtrapolator.SubMEUpdators = MySubUpdators
-        #else:
-            ##theExtrapolator=AtlasExtrapolator("ATLASExtrapolatorStraightLine")
-            ##from TrkExSlPropagator.TrkExSlPropagatorConf import Trk__StraightLinePropagator as Propagator
-            ##SlPropagator =  Propagator(name='TTC_SlPropagator')
-            ##ToolSvc += SlPropagator
-            ##theExtrapolator.Propagators = [ SlPropagator ]
-            
-            #theExtrapolator=AtlasExtrapolator("TrackToCaloExtrapolatorStraightLine")
-            #from TrkExSlPropagator.TrkExSlPropagatorConf import Trk__StraightLinePropagator as Propagator
-            #SlPropagator =  Propagator(name='TTC_SlPropagator')
-            #ToolSvc += SlPropagator
-            #theExtrapolator.Propagators = [ SlPropagator ]
-
-        #Get the extrapolator
-        from TrkExTools.AtlasExtrapolator import AtlasExtrapolator
-
-        theExtrapolator=AtlasExtrapolator()
-
-        ## need to add to ToolSvc before putting in ToolHandle
-        ToolSvc+=theExtrapolator
-        self.Extrapolator=theExtrapolator
-
-
-
-# factory : autogenerates the name
-# usage :
-# from TrackToCalo.ExtrapolateToCaloToolBase import ExtrapolateToCaloToolFactory
-# exToCalo = ExtrapolateToCaloToolFactory(depth="showerdefault")
-# ToolSvc+=exToCalo
-def ExtrapolateToCaloToolFactory( depth="showerdefault", straightLine=False ):
-    # build the tool name by appending  depth valure
-    #if straightLine:
-        #straightName="Straight"
-    #else:
-        #straightName=""
-    #return ExtrapolateToCaloToolBase( "ExtrapolateToCaloTool"+depth+straightName, depth=depth,straightLine=straightLine )
-    return ExtrapolateToCaloToolBase( "ExtrapolateToCaloTool"+depth, depth=depth ) 
diff --git a/Reconstruction/RecoTools/TrackToCalo/share/ExtrapolToCaloTool_joboptions.py b/Reconstruction/RecoTools/TrackToCalo/share/ExtrapolToCaloTool_joboptions.py
deleted file mode 100755
index 4c3916e8d94aed643dd3d7ca5c1d5ef1413434bd..0000000000000000000000000000000000000000
--- a/Reconstruction/RecoTools/TrackToCalo/share/ExtrapolToCaloTool_joboptions.py
+++ /dev/null
@@ -1,16 +0,0 @@
-print "WARNING obsolete joboption. Please Reconstruction/RecoTools/TrackToCalo/python/ExtrapolTrackToCalo configurables instead "
-
-
-if not 'TTC_ExtrapolatorInstance' in dir():
-    TTC_ExtrapolatorInstance = 'TTC_Extrapolator'
-# from AW 
-from TrkConfigurableWrapper.ConfigurableWrapper import ConfigurableWrapper
-
-
-from TrkExTools.AtlasExtrapolator import AtlasExtrapolator
-
-theAtlasExtrapolator=AtlasExtrapolator()
-ToolSvc+=theAtlasExtrapolator
-TTC_Extrapolator = ConfigurableWrapper(theAtlasExtrapolator)
-# default name Trk::Extrapolator/AtlasExtrapolor used by default ( to be changed)
-
diff --git a/Reconstruction/RecoTools/TrackToCalo/share/MuToCaloAlg_jobOptions.py b/Reconstruction/RecoTools/TrackToCalo/share/MuToCaloAlg_jobOptions.py
deleted file mode 100755
index a2ab9b54976b87c0113cf140ceb49827864376a5..0000000000000000000000000000000000000000
--- a/Reconstruction/RecoTools/TrackToCalo/share/MuToCaloAlg_jobOptions.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# JobOptions to extrapolate a track to Calorimeters
-
-# ------ Specific to this alg :
-
-theApp.Dlls += [ "TrackToCalo" ]
-theApp.TopAlg += ["TrackToCaloAlg/MuToCaloAlg"]
-MuToCaloAlg = Algorithm( "MuToCaloAlg" )
-
-MuToCaloAlg.ClusterContainerName = "CaloTopoClusterEM"
-MuToCaloAlg.CaloCellContainerName = "AllCalo"
-MuToCaloAlg.ImpactInCaloContainerName = "MuImpactInCalo"
-
-# If type is anything else than TrackParticleCandidates, will take Tracks
-# MuToCaloAlg.TrackInputType = "TrackParticleCandidates"
-# MuToCaloAlg.TrackParticleName = "TrackParticleCandidate"
-MuToCaloAlg.TrackInputType = "Tracks"
-MuToCaloAlg.TrackName = "ConvertedMBoyTracks"
-
-# ------ More general part to be used as an example : setup Extrapolator instance
-
-TTC_ExtrapolatorInstance = 'MuToCaloExtrapolator'
-include( "TrackToCalo/ExtrapolToCaloTool_joboptions.py" )
-
-# configure private ExtrapolTrackToCaloTool tool
-MuToCaloAlg.ExtrapolTrackToCaloTool.ExtrapolatorName = TTC_Extrapolator.name()
-MuToCaloAlg.ExtrapolTrackToCaloTool.ExtrapolatorInstanceName = TTC_Extrapolator.instance()
-MuToCaloAlg.ExtrapolTrackToCaloTool.CaloDepthTool.DepthChoice= "entrance"
-
-# the type of extrapolation is set automatically. To force it add here :
-#    doStraightToCalo=False    will use RungeKutta (default for Atlas)
-#    doStraightToCalo=True     will use StraightLine (default for ctb)
diff --git a/Reconstruction/RecoTools/TrackToCalo/share/TrackToCaloAlg_jobOptions.py b/Reconstruction/RecoTools/TrackToCalo/share/TrackToCaloAlg_jobOptions.py
deleted file mode 100755
index a8cc6b6aa1e8a02e9a6c7f519287be012301b966..0000000000000000000000000000000000000000
--- a/Reconstruction/RecoTools/TrackToCalo/share/TrackToCaloAlg_jobOptions.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# JobOptions to extrapolate a track to Calorimeters
-
-# ------ Specific to this alg :
-
-theApp.Dlls += [ "TrackToCalo" ]
-theApp.TopAlg += ["TrackToCaloAlg"]
-TrackToCaloAlg = Algorithm( "TrackToCaloAlg" )
-TrackToCaloAlg.ClusterContainerName = "CaloTopoClusterEM"
-TrackToCaloAlg.CaloCellContainerName = "AllCalo"
-TrackToCaloAlg.ImpactInCaloContainerName = "ImpactInCalo"
-
-# If type is anything else than TrackParticleCandidates, will take Tracks
-#TrackToCaloAlg.TrackInputType = "Tracks"
-TrackToCaloAlg.TrackInputType = "TrackParticleCandidates"
-TrackToCaloAlg.TrackName = "Tracks"
-TrackToCaloAlg.TrackParticleName = "TrackParticleCandidate"
-
-# ------ More general part to be used as an example : setup Extrapolator instance
-
-TTC_ExtrapolatorInstance = 'TrackToCaloExtrapolator'
-include( "TrackToCalo/ExtrapolToCaloTool_joboptions.py" )
-
-# configure private ExtrapolTrackToCaloTool tool
-TrackToCaloAlg.ExtrapolTrackToCaloTool.ExtrapolatorName = TTC_Extrapolator.name()
-TrackToCaloAlg.ExtrapolTrackToCaloTool.ExtrapolatorInstanceName = TTC_Extrapolator.instance()
-TrackToCaloAlg.ExtrapolTrackToCaloTool.CaloDepthTool.DepthChoice= "entrance"
-
-# the type of extrapolation is set automatically. To force it add here :
-#    doStraightToCalo=False    will use RungeKutta (default for Atlas)
-#    doStraightToCalo=True     will use StraightLine (default for ctb)
-
-
-
diff --git a/Reconstruction/RecoTools/TrackToCalo/src/CaloCellSelectorLayerdR.cxx b/Reconstruction/RecoTools/TrackToCalo/src/CaloCellSelectorLayerdR.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..0eb73e0173b370f7a0740a659316ba625442fe56
--- /dev/null
+++ b/Reconstruction/RecoTools/TrackToCalo/src/CaloCellSelectorLayerdR.cxx
@@ -0,0 +1,54 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// CaloCellSelectorLayerdR.cxx, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#include "TrackToCalo/CaloCellSelectorUtils.h"
+#include "TrackToCalo/CaloCellSelectorLayerdR.h"
+#include "CaloEvent/CaloCell.h"
+#include "TrkCaloExtension/CaloExtension.h"
+namespace Trk 
+{
+
+  CaloCellSelectorLayerdR::CaloCellSelectorLayerdR(double coneSize):
+    m_coneSize2( coneSize*coneSize ){
+  }
+
+  CaloCellSelectorLayerdR::~CaloCellSelectorLayerdR(){}
+
+  bool CaloCellSelectorLayerdR::preSelectAction( const Trk::CaloExtension& caloExtension ){
+
+    //std::cout << "CaloCellSelectorLayerdR p00" << std::endl;
+    if( caloExtension.caloLayerIntersections().empty() ) return false;
+    //std::cout << "CaloCellSelectorLayerdR p01" << std::endl;
+    CaloExtensionHelpers::midPointEtaPhiHashLookupVector( caloExtension, m_midPoints );
+    return true;
+  }
+
+  bool CaloCellSelectorLayerdR::select( const CaloCell& cell )const {
+    // select cell within dR from the midPoint of the same calo layer
+    const CaloDetDescrElement* dde = cell.caloDDE();
+    //std::cout << "CaloCellSelectorLayerdR p1" << std::endl;
+    if(!dde) return false;
+
+    int samplingID = dde->getSampling();
+    //std::cout << "CaloCellSelectorLayerdR p2 " << samplingID << std::endl;
+    //for (auto entry : m_midPoints){
+    //  std::cout << std::get<0>(entry) << std::endl;
+    //}
+    if ( !std::get<0>(m_midPoints[samplingID]) ) return false;
+    double dr = Utils::deltaR2( std::get<1>(m_midPoints[samplingID]),dde->eta(),std::get<2>(m_midPoints[samplingID]),dde->phi());
+    if( dr < m_coneSize2){
+      //std::cout << "CaloCellSelectorLayerdR p3" << std::endl;
+      return true;
+    }
+    //std::cout << "CaloCellSelectorLayerdR p4" << std::endl;
+    return false;
+  }
+
+
+} // end of namespace
+
diff --git a/Reconstruction/RecoTools/TrackToCalo/src/CaloCellSelectorMinPerp.cxx b/Reconstruction/RecoTools/TrackToCalo/src/CaloCellSelectorMinPerp.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..eba7154f683f48e01ac9fbbf8e403e976d2b0640
--- /dev/null
+++ b/Reconstruction/RecoTools/TrackToCalo/src/CaloCellSelectorMinPerp.cxx
@@ -0,0 +1,93 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// CaloCellSelectorMinPerp.cxx, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#include "TrackToCalo/CaloCellSelectorUtils.h"
+#include "TrackToCalo/CaloCellSelectorMinPerp.h"
+#include "CaloEvent/CaloCell.h"
+#include "TrkCaloExtension/CaloExtension.h"
+
+
+namespace Trk 
+{
+
+  CaloCellSelectorMinPerp::CaloCellSelectorMinPerp(double coneSize ):
+    m_caloExtension(0),
+    m_coneSize( coneSize ),
+    m_perp2cut(0) {
+  }
+
+
+  bool CaloCellSelectorMinPerp::preSelectAction( const Trk::CaloExtension& caloExtension ){
+
+    m_caloExtension = &caloExtension;
+
+    //find a circular cone (defined by cut in perpendicular distance form track i.e. perp2)
+    //with approx area as the dR cone
+    //the dR cone is roughly thought as an elipse
+    if( m_caloExtension->caloLayerIntersections().empty() ) return false;
+
+    Amg::Vector3D pos = m_caloExtension->caloLayerIntersections()[0]->position();
+
+    double a = fabs(pos.eta());
+    double b = exp(-a);      // = tan(theta/2)
+    double c = 2.*b/(1.-b*b); // = tan(theta)
+    double r = c/sqrt(1.+c*c);  // distance from beam axis
+    double t1 = 2.*atan(exp(-(a-m_coneSize)));
+    double t2 = 2.*atan(exp(-(a+m_coneSize)));
+    double dRad1 = fabs(t1-t2)/2.;
+    //double dRad1 = 2.*b/(1.+b*b) * m_coneSize; //semi-major axis of the dR cone elipse
+    double dRad2 = r * m_coneSize; //semi minor axis of the dR cone elipse
+    m_perp2cut = dRad1*dRad2; // force area of circle = area of elipse, i.e. pi*r*r = pi*dRad1*dRad2
+    return true;
+  }
+
+  bool CaloCellSelectorMinPerp::select( const CaloCell& cell )const {
+    
+    if( !m_caloExtension || m_caloExtension->caloLayerIntersections().empty() ) return false;
+
+    const CaloDetDescrElement* dde = cell.caloDDE();
+    if(!dde) return false;
+
+    Amg::Vector3D cellPos(dde->x(), dde->y(), dde->z());
+
+    int nearestIdx;
+    Amg::Vector3D nearestPos,nearestMom;
+    Utils::findNearestPoint( cellPos, m_caloExtension, nearestIdx, nearestPos, nearestMom);
+
+
+    //get the perp2 from track
+    Amg::Vector3D dPos = cellPos-nearestPos;
+    float perp2 = dPos.perp2(nearestMom);
+
+    //get the total track length from IP to point of cloest approach to the cell
+    //scale the perp2 cut with this length
+    float totTrkLen = sqrt(dPos.mag2() - perp2);
+    if (dPos.dot(nearestMom)<0) {totTrkLen = -totTrkLen;}
+
+    Amg::Vector3D pos;
+    Amg::Vector3D oldPos(0.,0.,0.);
+    const std::vector<const Trk::CurvilinearParameters*>& intersections = m_caloExtension->caloLayerIntersections();
+    for (int i=0;i<=nearestIdx;++i){
+      pos = intersections[i]->position();
+      totTrkLen += (pos-oldPos).mag();
+      std::swap(oldPos, pos);
+    }
+
+    //prevent cell at exact opposite of the track from being selected..
+    if (totTrkLen<0) return false;
+
+    if( perp2 < (m_perp2cut*totTrkLen*totTrkLen)){
+      return true;
+    } // IF
+    
+    return false;
+  
+  }
+
+} // end of namespace
+
diff --git a/Reconstruction/RecoTools/TrackToCalo/src/CaloCellSelectorNearestdR.cxx b/Reconstruction/RecoTools/TrackToCalo/src/CaloCellSelectorNearestdR.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..ee413f527c6443301a0cd7638bf8d1d711e1bb3c
--- /dev/null
+++ b/Reconstruction/RecoTools/TrackToCalo/src/CaloCellSelectorNearestdR.cxx
@@ -0,0 +1,49 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// CaloCellSelectorNearestdR.cxx, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#include "TrackToCalo/CaloCellSelectorUtils.h"
+#include "TrackToCalo/CaloCellSelectorNearestdR.h"
+#include "CaloEvent/CaloCell.h"
+#include "TrkCaloExtension/CaloExtension.h"
+
+namespace Trk 
+{
+
+  CaloCellSelectorNearestdR::CaloCellSelectorNearestdR( double coneSize ):
+    m_coneSize2( coneSize*coneSize ){
+  }
+
+  CaloCellSelectorNearestdR::~CaloCellSelectorNearestdR(){}
+
+  bool CaloCellSelectorNearestdR::preSelectAction( const Trk::CaloExtension& caloExtension ) {
+    m_caloExtension = &caloExtension;
+    return true;
+  }
+
+
+  bool CaloCellSelectorNearestdR::select( const CaloCell& cell )const {
+    if( !m_caloExtension ) return false;
+
+    const CaloDetDescrElement* dde = cell.caloDDE();
+    if(!dde) return false;
+
+    Amg::Vector3D cellPos(dde->x(), dde->y(), dde->z());
+
+    int nearestIdx;
+    Amg::Vector3D nearestPos,nearestMom;
+    Utils::findNearestPoint( cellPos, m_caloExtension, nearestIdx, nearestPos, nearestMom);
+
+    if( Utils::deltaR2( nearestPos.eta(),dde->eta(),nearestPos.phi(),dde->phi()) < m_coneSize2){
+      return true;
+    }
+
+    return false;
+  }
+
+} // end of namespace
+
diff --git a/Reconstruction/RecoTools/TrackToCalo/src/CaloCellSelectorRoughdR.cxx b/Reconstruction/RecoTools/TrackToCalo/src/CaloCellSelectorRoughdR.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..e530ddff2f5ea22f1ab538b3af322defb3c56ba7
--- /dev/null
+++ b/Reconstruction/RecoTools/TrackToCalo/src/CaloCellSelectorRoughdR.cxx
@@ -0,0 +1,106 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// CaloCellSelectorRoughdR.cxx, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#include "TrackToCalo/CaloCellSelectorUtils.h"
+#include "TrackToCalo/CaloCellSelectorRoughdR.h"
+#include "CaloEvent/CaloCell.h"
+#include "TrkCaloExtension/CaloExtension.h"
+
+
+namespace Trk 
+{
+
+  CaloCellSelectorRoughdR::CaloCellSelectorRoughdR(double coneSize):
+    m_coneSize( coneSize ), m_midEta(0),m_midPhi(0),m_maxDiff(0)
+  {
+  }
+
+  CaloCellSelectorRoughdR::~CaloCellSelectorRoughdR(){}
+
+  bool CaloCellSelectorRoughdR::preSelectAction( const Trk::CaloExtension& caloExtension ){
+    
+    if( caloExtension.caloLayerIntersections().empty() ) return false;
+
+    //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+    CaloExtensionHelpers::entryExitPerLayerVector( caloExtension, m_crossPoints );
+    // get mean direction of the calo crossings
+    Amg::Vector3D meanPos(0., 0., 0.);
+    for (auto entry : m_crossPoints){
+      int code = std::get<0>(entry);
+      if ( !(code >= 0 && code < 24) )  { continue; } // not a intersection with a calo layer
+      meanPos += std::get<1>(entry).unit();
+    }
+
+    m_midEta = meanPos.eta();
+    m_midPhi = meanPos.phi();
+
+    //get individual crossings max deviation from the mean direction as tolerance
+    m_maxDiff = 0.;
+    for (auto entry : m_crossPoints){  
+      int code = std::get<0>(entry);
+      if ( !(code >= 0 && code < 24) )  { continue; } // not a intersection with a calo layer
+      Amg::Vector3D pos = std::get<1>(entry);
+      double rDiff = Utils::deltaR(pos.eta(), m_midEta, pos.phi(), m_midPhi);
+      if (rDiff>m_maxDiff) m_maxDiff = rDiff;
+    }
+    m_maxDiff += m_coneSize;
+    m_maxDiff *= m_maxDiff; //do comparison in dR*dR
+    //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+
+
+
+    //const std::vector<const CurvilinearParameters*>& intersections = caloExtension.caloLayerIntersections();
+    //int nPts = intersections.size();
+
+    //Amg::Vector3D meanPos(0., 0., 0.);
+    //m_maxDiff = 0.;
+
+    //// get mean direction of the calo crossings
+    //for (int i=0;i<nPts;++i){  
+    //  //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+    //  int code = parsIdHelper.caloSample(intersections[i]->cIdentifier());
+    //  if (!parsIdHelper.isEntryToVolume(intersections[i]->cIdentifier())) code = -code;
+    //  //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+    //  if ( !(code >= 0 && code < 24) )  { continue; } // not a intersection with a calo layer
+    //  meanPos += intersections[i]->position().unit();
+    //}
+
+    //m_midEta = meanPos.eta();
+    //m_midPhi = meanPos.phi();
+
+    ////get individual crossings max deviation from the mean direction as tolerance
+    //for (int i=0;i<nPts;++i){  
+    //  //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+    //  int code = parsIdHelper.caloSample(intersections[i]->cIdentifier());
+    //  if (!parsIdHelper.isEntryToVolume(intersections[i]->cIdentifier())) code = -code;
+    //  //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+    //  if ( !(code >= 0 && code < 24) )  { continue; } // not a intersection with a calo layer
+    //  Amg::Vector3D pos = intersections[i]->position();
+    //  double rDiff = Utils::deltaR(pos.eta(), m_midEta, pos.phi(), m_midPhi);
+    //  if (rDiff>m_maxDiff) m_maxDiff = rDiff;
+    //}
+
+    ////select cell within requested cone size+tolerence
+    //m_maxDiff += m_coneSize;
+    //m_maxDiff *= m_maxDiff; //do comparison in dR*dR
+
+    return true;
+  }
+
+  bool CaloCellSelectorRoughdR::select( const CaloCell& cell )const {
+    const CaloDetDescrElement* dde = cell.caloDDE();
+    if(!dde) return false;
+    if( Utils::deltaR2( m_midEta,dde->eta(),m_midPhi,dde->phi()) < m_maxDiff){
+      return true;
+    }
+    return false;
+  }
+
+} // end of namespace
+
diff --git a/Reconstruction/RecoTools/TrackToCalo/src/CaloCellSelectorUtils.cxx b/Reconstruction/RecoTools/TrackToCalo/src/CaloCellSelectorUtils.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..56505c177f8234de139f9d4eda3bb66d130af0d7
--- /dev/null
+++ b/Reconstruction/RecoTools/TrackToCalo/src/CaloCellSelectorUtils.cxx
@@ -0,0 +1,76 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include <cmath>
+#include <algorithm>
+#include "TrackToCalo/CaloCellSelectorUtils.h"
+
+
+namespace Utils
+{
+  double deltaPhi(double phi1, double phi2) {
+    double dPhi=std::fabs(phi1-phi2);
+    if (dPhi>M_PI) dPhi=2*M_PI-dPhi;
+    return dPhi;
+  }
+
+  double deltaR2(double eta1, double eta2, double phi1, double phi2) {
+    double dPhi=deltaPhi(phi1,phi2);
+    double dEta=std::fabs(eta1-eta2);
+    return dEta*dEta + dPhi*dPhi;
+  }
+
+  double deltaR(double eta1, double eta2, double phi1, double phi2) {
+    return std::sqrt(deltaR2(eta1, eta2, phi1, phi2));
+  }
+
+  void findNearestPoint( const Amg::Vector3D& inputPos, const Trk::CaloExtension* caloExtension,
+                         int&           nearestIdx,
+                         Amg::Vector3D& nearestPos,
+                         Amg::Vector3D& nearestMom ){
+
+    const std::vector<const Trk::CurvilinearParameters*>& intersections = caloExtension->caloLayerIntersections();
+    int nPts = intersections.size();
+
+    int idxL, idxR, idxMid;
+    Amg::Vector3D pos (0,0,0), mom (0,0,0); //initialization should be(?) unnecessary, just to suppress scary warning msg...
+    Amg::Vector3D posL(0,0,0), momL(0,0,0);
+    Amg::Vector3D posR(0,0,0), momR(0,0,0);
+
+    // find nearest crossing point
+    idxL = 0;
+    idxR = nPts-1;
+    while ((idxR-idxL)>1){
+      idxMid = (idxL+idxR)/2;
+      pos = intersections[idxMid]->position();
+      mom = intersections[idxMid]->momentum();
+
+      if ( (inputPos-pos).dot(mom)>0) { 
+        idxL = idxMid;
+        std::swap(posL, pos);
+        std::swap(momL, mom);
+      }
+      else { 
+        idxR = idxMid;
+        std::swap(posR, pos);
+        std::swap(momR, mom);
+      }
+    }
+
+    if (idxL==0){
+      posL = intersections[0]->position();
+      momL = intersections[0]->momentum();
+    }
+    if (idxR==(nPts-1)){
+      posR = intersections[nPts-1]->position();
+      momR = intersections[nPts-1]->momentum();
+    }
+
+    float mag2L = (inputPos-posL).mag2();
+    float mag2R = (inputPos-posR).mag2();
+    nearestIdx = (mag2L<mag2R)? idxL : idxR;
+    nearestPos = (mag2L<mag2R)? posL : posR;
+    nearestMom = (mag2L<mag2R)? momL : momR;
+  }
+}
diff --git a/Reconstruction/RecoTools/TrackToCalo/src/ExtrapolateToCaloTool.cxx b/Reconstruction/RecoTools/TrackToCalo/src/ExtrapolateToCaloTool.cxx
deleted file mode 100644
index fe5b7b8693c56b138e4d12ade0ba0767b26c2fb9..0000000000000000000000000000000000000000
--- a/Reconstruction/RecoTools/TrackToCalo/src/ExtrapolateToCaloTool.cxx
+++ /dev/null
@@ -1,969 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-// ***************************************************************************
-// ExtrapolateToCaloTool
-//****************************************************************************
-
-#include "TrackToCalo/ExtrapolateToCaloTool.h"
-#include "TrackToCalo/ImpactInCalo.h"
-
-#include "GaudiKernel/MsgStream.h"
-/*#include "GaudiKernel/Property.h"
-#include "GaudiKernel/IService.h"
-#include "GaudiKernel/IToolSvc.h"
-#include "GaudiKernel/IMessageSvc.h"
-#include "StoreGate/StoreGateSvc.h"*/
-#include "GaudiKernel/ISvcLocator.h"
-#include <vector>
-
-// Stuff needed for the extrapolation :
-//#include "TrkSurfaces/CylinderSurface.h"
-#include "TrkSurfaces/PerigeeSurface.h"
-#include "TrkParameters/TrackParameters.h"
-// #include "TrkNeutralParameters/NeutralParameters.h"
-// #include "TrkNeutralParameters/NeutralPerigee.h"
-#include "TrkTrack/Track.h"
-#include "TrkParticleBase/TrackParticleBase.h"
-#include "TrkEventPrimitives/PropDirection.h"
-#include "TrkEventPrimitives/ParticleHypothesis.h"
-#include "TrkExInterfaces/IExtrapolator.h"
-// CLHEP
-// #include "CLHEP/Units/SystemOfUnits.h"
-// #include "CLHEP/Vector/Rotation.h"
-// #include "CLHEP/Vector/ThreeVector.h"
-
-// Calo specific stuff :
-/*#include "CaloDetDescr/CaloDetDescrManager.h"
-#include "CaloDetDescr/ICaloCoordinateTool.h"*/
-#include "CaloTrackingGeometry/ICaloSurfaceBuilder.h"
-#include "CaloDetDescr/CaloDepthTool.h"
-
-#include "xAODTracking/Vertex.h"
-//#include <cmath>
-
-
-ExtrapolateToCaloTool::ExtrapolateToCaloTool(const std::string& type,
-        const std::string& name,
-        const IInterface* parent) :
-        AthAlgTool(type, name, parent),
-        m_calosurf("CaloSurfaceBuilder"),
-        m_calodepth("CaloDepthTool"),
-        m_extrapolator("Trk::Extrapolator/AtlasExtrapolator"),
-        m_offsetPresampler(0.),
-        m_offsetStrip(0.),
-        m_offsetMiddle(0.),
-        m_offsetBack(0.),
-        m_offsetTile(0.),
-        m_assumeOrderedTracks(true),
-        m_ignoreMaterialEffectsInsideCalo(true) {
-    declareInterface<IExtrapolateToCaloTool>( this );
-
-    declareProperty ("Extrapolator",        m_extrapolator, "Extrapolation tool");
-    declareProperty ("CaloSurfaceBuilder",  m_calosurf,     "Calo Surface builder tool");
-    declareProperty ("CaloDepthTool",       m_calodepth,    "Calo Depth tool");
-    declareProperty ("OffsetPresampler",    m_offsetPresampler, "extrapolation depth (offset) for presampler");
-    declareProperty ("OffsetStrip",         m_offsetStrip,      "extrapolation depth (offset) for strip");
-    declareProperty ("OffsetMiddle",        m_offsetMiddle,     "extrapolation depth (offset) for em middle");
-    declareProperty ("OffsetBack",          m_offsetBack,       "extrapolation depth (offset) for em back");
-    declareProperty ("OffsetTile",          m_offsetTile,       "extrapolation depth (offset) for em tile");
-    declareProperty ("OrderedTracks",       m_assumeOrderedTracks, "assume ordered tracks");
-    declareProperty ("IgnoreMaterialEffectsInsideCalo",       m_ignoreMaterialEffectsInsideCalo, "ignore material effects inside calo, if step-wise extrapolation to all layers of calo samplings is performed (used for getParametersInCalo() and getImpactInCalo() )");
-}
-
-ExtrapolateToCaloTool::~ExtrapolateToCaloTool() {}
-
-StatusCode ExtrapolateToCaloTool::initialize() {
-    ATH_MSG_INFO("ExtrapolateToCaloTool initialize()" );
-
-    // Get Extrapolator from ToolService
-    if (m_extrapolator.retrieve().isFailure()) {
-        ATH_MSG_FATAL( "Could not retrieve " << m_extrapolator );
-        return StatusCode::FAILURE;
-    }
-    // Get CaloSurfaceBuilder from ToolService
-    if (m_calosurf.retrieve().isFailure()) {
-        ATH_MSG_FATAL( "Could not retrieve " << m_calosurf );
-        return StatusCode::FAILURE;
-    }
-    // Get CaloDepthTool from ToolService
-    if (m_calodepth.retrieve().isFailure()) {
-        ATH_MSG_FATAL( "Could not retrieve " << m_calodepth );
-        return StatusCode::FAILURE;
-    }
-    return StatusCode::SUCCESS;
-}
-
-StatusCode ExtrapolateToCaloTool::finalize() {
-    return StatusCode::SUCCESS;
-}
-
-const Trk::TrackParameters* ExtrapolateToCaloTool::extrapolate (const Trk::Track& trk,
-        const CaloCell_ID::CaloSample sample,
-        const double offset,
-        const Trk::PropDirection dir,
-        const Trk::ParticleHypothesis particle) const {
-
-    const Trk::TrackParameters* parametersAtCalo = 0;
-    // get the DataVector of TrackParameters
-    const DataVector<const Trk::TrackParameters>* parameterVector = trk.trackParameters();
-    if (parameterVector) {
-        // use last track parameters on track
-        DataVector<const Trk::TrackParameters>::const_iterator curParIter = parameterVector->end();
-        --curParIter;
-        const Trk::TrackParameters* startParameters = (*curParIter);
-        // get the destination Surface
-        const double etaDir = (dir==Trk::oppositeMomentum ? -1.*(startParameters->eta()) : startParameters->eta());
-        const Trk::Surface* destinationSurface = m_calosurf->CreateUserSurface (sample, offset, etaDir);
-        if (!destinationSurface)
-            return 0;
-        // use particle hypothesis of the track, if given hypothesis is set to undefined
-        Trk::ParticleHypothesis particleHypo = (particle == Trk::undefined ? trk.info().particleHypothesis() : particle);
-        // extrapolate to calorimeter surface
-        if (m_assumeOrderedTracks)
-            parametersAtCalo = m_extrapolator->extrapolate(*startParameters,
-                               *destinationSurface,
-                               dir,
-                               false,
-                               particleHypo);
-        else
-            parametersAtCalo = m_extrapolator->extrapolate(trk,
-                               *destinationSurface,
-                               dir,
-                               false,
-                               particleHypo);
-        delete destinationSurface;
-        destinationSurface = 0;
-    }
-    return parametersAtCalo;
-}
-
-const Trk::TrackParameters* ExtrapolateToCaloTool::extrapolate (const Trk::TrackParticleBase& trk,
-            const CaloCell_ID::CaloSample sample,
-            const double offset,
-            const Trk::PropDirection dir,
-            const Trk::ParticleHypothesis particle) const {
-
-    // if the TrackParticle contains the pointer to the original track, use this one:
-    if (trk.originalTrack()) {
-        return extrapolate(*(trk.originalTrack()), sample, offset, dir, particle);
-    }
-
-    // get the destination Surface
-    const double etaDir = (dir==Trk::oppositeMomentum ? -1.*(trk.definingParameters().momentum().eta()) : trk.definingParameters().momentum().eta());
-    const Trk::Surface* destinationSurface = m_calosurf->CreateUserSurface (sample, offset, etaDir);
-    if (!destinationSurface) return 0;
-    // Without the original track we cannot get the particle hypothesis used during the track fit
-    // TODO: (will be added to TrackParticle at some point)!
-    // use nonInteracting, if no hypothesis given:
-    Trk::ParticleHypothesis hypo = (particle == Trk::undefined ? Trk::nonInteracting : particle);
-
-    const Trk::TrackParameters* parametersAtCalo = m_extrapolator->extrapolate(trk.definingParameters(),
-                                                          *destinationSurface,
-                                                          dir,
-                                                          false,
-                                                          hypo);
-    delete destinationSurface;
-    return parametersAtCalo;
-}
-
-
-const Trk::TrackParameters* ExtrapolateToCaloTool::extrapolate (const Trk::TrackParameters& trkPar,
-        const CaloCell_ID::CaloSample sample,
-        const double offset, Trk::ParticleHypothesis particle,
-        const Trk::PropDirection dir) const {
-    const Trk::TrackParameters* parametersAtCalo = 0;
-    // get the destination Surface
-    const double etaDir = (dir==Trk::oppositeMomentum ? -1.*(trkPar.eta()) : trkPar.eta());
-    const Trk::Surface* destinationSurface = m_calosurf->CreateUserSurface (sample, offset, etaDir);
-    if (!destinationSurface)
-        return 0;
-    // extrapolate to calorimeter surface
-    parametersAtCalo = m_extrapolator->extrapolate(trkPar,
-                       *destinationSurface,
-                       dir,
-                       false,
-                       particle);
-    delete destinationSurface;
-    destinationSurface = 0;
-    return parametersAtCalo;
-}
-            
-const Trk::NeutralParameters* ExtrapolateToCaloTool::extrapolate (const Trk::NeutralParameters& parameters,
-            const CaloCell_ID::CaloSample sample,
-            const double offset,
-            Trk::ParticleHypothesis, // TODO: drop!
-            const Trk::PropDirection dir) const {
-    const Trk::NeutralParameters* parametersAtCalo = 0;
-    // get the destination Surface
-    const double etaDir = (dir==Trk::oppositeMomentum ? -1.*(parameters.momentum().eta()) : parameters.momentum().eta());
-    const Trk::Surface* destinationSurface = m_calosurf->CreateUserSurface (sample, offset, etaDir);
-    if (!destinationSurface) return 0;
-    // extrapolate to calorimeter surface
-    parametersAtCalo = m_extrapolator->extrapolate(parameters,
-                       *destinationSurface,
-                       dir,
-                       false);
-    delete destinationSurface;
-    destinationSurface = 0;
-    return parametersAtCalo;
-}
-
-const Trk::TrackParameters* ExtrapolateToCaloTool::extrapolate (const  xAOD::TrackParticle& trk,
-            const CaloCell_ID::CaloSample sample,
-            const double offset,
-            const Trk::PropDirection dir,
-            const Trk::ParticleHypothesis particle) const {
-    const Trk::TrackParameters* parametersAtCalo = 0;
-    // get the destination Surface
-    const double etaDir = (dir==Trk::oppositeMomentum ? -1.*(trk.eta()) : trk.eta());
-    const Trk::Surface* destinationSurface = m_calosurf->CreateUserSurface (sample, offset, etaDir);
-    if (!destinationSurface)
-        return 0;
-
-    Trk::ParticleHypothesis hypo = (particle == Trk::undefined ? Trk::nonInteracting : particle);
-
-    // extrapolate to calorimeter surface
-    parametersAtCalo = m_extrapolator->extrapolate(trk,
-                       *destinationSurface,
-                       dir,
-                       false,
-                       hypo);
-    delete destinationSurface;
-    destinationSurface = 0;
-    return parametersAtCalo;
-}
-
-const Trk::NeutralParameters* ExtrapolateToCaloTool::extrapolate (const xAOD::NeutralParticle& trk,
-            const CaloCell_ID::CaloSample sample,
-            const double offset,
-            const Trk::PropDirection dir ) const {
-    const Trk::NeutralParameters* parametersAtCalo = 0;
-    // get the destination Surface
-    const double etaDir = (dir==Trk::oppositeMomentum ? -1.*(trk.eta()) : trk.eta());
-    const Trk::Surface* destinationSurface = m_calosurf->CreateUserSurface (sample, offset, etaDir);
-    if (!destinationSurface) return 0;
-    // extrapolate to calorimeter surface
-    parametersAtCalo = m_extrapolator->extrapolate(trk,
-                       *destinationSurface,
-                       dir,
-                       false);
-    delete destinationSurface;
-    destinationSurface = 0;
-    return parametersAtCalo;
-}
-
-const DataVector< const Trk::TrackParameters >* ExtrapolateToCaloTool::getParametersInCalo (
-            const Trk::TrackParameters& parameters,
-            Trk::ParticleHypothesis particle,
-            const Trk::PropDirection dir) const {
-
-    // the return vector
-    DataVector< const Trk::TrackParameters >* parameterVector = new DataVector< const Trk::TrackParameters >(IExtrapolateToCaloTool::NCaloLayers, SG::OWN_ELEMENTS);
-    // variables to select sampler (barrel or endcap)
-    double distbar = 0.;    // distance to barrel
-    double distec = 0.;     // distance to end caps
-    CaloCell_ID::CaloSample sample;
-    // get eta direction of particle:
-    double trketa = parameters.momentum().eta();
-
-    // PreSampler :
-    // figure out which sampling will be hit
-    distbar = m_calodepth->deta(CaloCell_ID::PreSamplerB,trketa);
-    distec = m_calodepth->deta(CaloCell_ID::PreSamplerE,trketa);
-    
-    ATH_MSG_DEBUG(" TrackTo ...PS : for eta= " << trketa << " dist to Barrel =" << distbar 
-        << " to endcap =" << distec);
-    if (distbar < 0 )  sample = CaloCell_ID::PreSamplerB;
-    else if (distec < 0 ) sample = CaloCell_ID::PreSamplerE;
-    else if ( distbar < distec) sample = CaloCell_ID::PreSamplerB;
-    else sample = CaloCell_ID::PreSamplerE;
-    ATH_MSG_DEBUG( "  => will shoot in sample " << sample );
-
-    (*parameterVector)[IExtrapolateToCaloTool::PreSampler] = extrapolate(parameters, sample, m_offsetPresampler, particle, dir);
-
-    // do rest of the extrapolation step-wise:
-    extrapolateStepwiseInCalo ( parameters,
-            particle,
-            dir,
-            *parameterVector);
-
-    return parameterVector;
-}
-
-const DataVector< const Trk::NeutralParameters >* ExtrapolateToCaloTool::getParametersInCalo (
-            const Trk::NeutralParameters& parameters,
-            Trk::ParticleHypothesis particle,
-            const Trk::PropDirection dir) const {
-
-    // the return vector
-    DataVector< const Trk::NeutralParameters >* parameterVector = new DataVector< const Trk::NeutralParameters >(IExtrapolateToCaloTool::NCaloLayers, SG::OWN_ELEMENTS);
-    // variables to select sampler (barrel or endcap)
-    double distbar = 0.;    // distance to barrel
-    double distec = 0.;     // distance to end caps
-    CaloCell_ID::CaloSample sample;
-    // get eta direction of particle:
-    double trketa = parameters.momentum().eta();
-
-    // PreSampler :
-    // figure out which sampling will be hit
-    distbar = m_calodepth->deta(CaloCell_ID::PreSamplerB,trketa);
-    distec = m_calodepth->deta(CaloCell_ID::PreSamplerE,trketa);
-    
-    ATH_MSG_DEBUG(" TrackTo ...PS : for eta= " << trketa << " dist to Barrel =" << distbar 
-        << " to endcap =" << distec);
-    if (distbar < 0 )  sample = CaloCell_ID::PreSamplerB;
-    else if (distec < 0 ) sample = CaloCell_ID::PreSamplerE;
-    else if ( distbar < distec) sample = CaloCell_ID::PreSamplerB;
-    else sample = CaloCell_ID::PreSamplerE;
-    ATH_MSG_DEBUG( "  => will shoot in sample " << sample );
-
-    (*parameterVector)[IExtrapolateToCaloTool::PreSampler] = extrapolate(parameters, sample, m_offsetPresampler, particle, dir);
-
-    // do rest of the extrapolation step-wise:
-    extrapolateStepwiseInCalo ( parameters,
-            particle,
-            dir,
-            *parameterVector);
-
-    return parameterVector;
-}
-
-
-ImpactInCalo* ExtrapolateToCaloTool::getImpactInCalo (const Trk::Track& trk,
-            const Trk::ParticleHypothesis particle,
-            const Trk::PropDirection dir) const {
-    const DataVector< const Trk::TrackParameters >* parametersInCalo = getParametersInCalo (trk, particle, dir);
-    if (!parametersInCalo) return 0;
-    ImpactInCalo* imp = getImpactInCaloFromParametersInCalo(*parametersInCalo);
-    // delete extrapolated parameters
-    delete parametersInCalo;
-    return imp;
-}
-
-ImpactInCalo* ExtrapolateToCaloTool::getImpactInCalo (const Trk::TrackParticleBase& trk,
-            const Trk::ParticleHypothesis particle,
-            const Trk::PropDirection dir) const {
-    const DataVector< const Trk::TrackParameters >* parametersInCalo = getParametersInCalo (trk, particle, dir);
-    if (!parametersInCalo) return 0;
-    ImpactInCalo* imp = getImpactInCaloFromParametersInCalo(*parametersInCalo);
-    // delete extrapolated parameters
-    delete parametersInCalo;
-    return imp;
-}
-
-ImpactInCalo* ExtrapolateToCaloTool::getImpactInCalo (const Trk::TrackParameters& parameters,
-            Trk::ParticleHypothesis particleHypo,
-            const Trk::PropDirection dir) const {
-
-    const DataVector< const Trk::TrackParameters >* parametersInCalo = getParametersInCalo (parameters, particleHypo, dir);
-    if (!parametersInCalo) return 0;
-    ImpactInCalo* imp = getImpactInCaloFromParametersInCalo(*parametersInCalo);
-    // delete extrapolated parameters
-    delete parametersInCalo;
-    return imp;
-}
-
-ImpactInCalo* ExtrapolateToCaloTool::getImpactInCalo (const Trk::NeutralParameters& parameters,
-            Trk::ParticleHypothesis particleHypo,
-            const Trk::PropDirection dir) const {
-
-    const DataVector< const Trk::NeutralParameters >* parametersInCalo = getParametersInCalo (parameters, particleHypo, dir);
-    if (!parametersInCalo) return 0;
-    ImpactInCalo* imp = getImpactInCaloFromParametersInCalo(*parametersInCalo);
-    // delete extrapolated parameters
-    delete parametersInCalo;
-    return imp;
-}
-
-ImpactInCalo* ExtrapolateToCaloTool::getImpactInCaloFromParametersInCalo(const DataVector< const Trk::TrackParameters >& parametersInCalo) const {
-    double x_0 = 0.;                double y_0 = 0.;            double z_0 = 0.;
-    double etaCaloLocal_0 = 0.;     double phiCaloLocal_0 = 0.;
-    double trketa_at_0 = 0.;        double trkphi_at_0 = 0.;
-    double x_1 = 0.;                double y_1 = 0.;            double z_1 = 0.;
-    double etaCaloLocal_1 = 0.;     double phiCaloLocal_1 = 0.;
-    double trketa_at_1 = 0.;        double trkphi_at_1 = 0.;
-    double x_2 = 0.;                double y_2 = 0.;            double z_2 = 0.;
-    double etaCaloLocal_2 = 0.;     double phiCaloLocal_2 = 0.;
-    double trketa_at_2 = 0.;        double trkphi_at_2 = 0.;
-    double x_3 = 0.;                double y_3 = 0.;            double z_3 = 0.;
-    double etaCaloLocal_3 = 0.;     double phiCaloLocal_3 = 0.;
-    double trketa_at_3 = 0.;        double trkphi_at_3 = 0.;
-    double x_tile = 0.;             double y_tile = 0.;         double z_tile = 0.;
-    double etaCaloLocal_tile = 0.;  double phiCaloLocal_tile = 0.;
-    double trketa_at_tile = 0.;     double trkphi_at_tile = 0.;
-
-    if (parametersInCalo[IExtrapolateToCaloTool::PreSampler]) {
-        x_0             = parametersInCalo[IExtrapolateToCaloTool::PreSampler]->position().x();
-        y_0             = parametersInCalo[IExtrapolateToCaloTool::PreSampler]->position().y();
-        z_0             = parametersInCalo[IExtrapolateToCaloTool::PreSampler]->position().z();
-        etaCaloLocal_0  = parametersInCalo[IExtrapolateToCaloTool::PreSampler]->position().eta();
-        phiCaloLocal_0  = parametersInCalo[IExtrapolateToCaloTool::PreSampler]->position().phi();
-        trketa_at_0     = parametersInCalo[IExtrapolateToCaloTool::PreSampler]->momentum().eta();
-        trkphi_at_0     = parametersInCalo[IExtrapolateToCaloTool::PreSampler]->momentum().phi();
-    }
-    if (parametersInCalo[IExtrapolateToCaloTool::Strips]) {
-        x_1             = parametersInCalo[IExtrapolateToCaloTool::Strips]->position().x();
-        y_1             = parametersInCalo[IExtrapolateToCaloTool::Strips]->position().y();
-        z_1             = parametersInCalo[IExtrapolateToCaloTool::Strips]->position().z();
-        etaCaloLocal_1  = parametersInCalo[IExtrapolateToCaloTool::Strips]->position().eta();
-        phiCaloLocal_1  = parametersInCalo[IExtrapolateToCaloTool::Strips]->position().phi();
-        trketa_at_1     = parametersInCalo[IExtrapolateToCaloTool::Strips]->momentum().eta();
-        trkphi_at_1     = parametersInCalo[IExtrapolateToCaloTool::Strips]->momentum().phi();
-    }
-    if (parametersInCalo[IExtrapolateToCaloTool::Middle]) {
-        x_2             = parametersInCalo[IExtrapolateToCaloTool::Middle]->position().x();
-        y_2             = parametersInCalo[IExtrapolateToCaloTool::Middle]->position().y();
-        z_2             = parametersInCalo[IExtrapolateToCaloTool::Middle]->position().z();
-        etaCaloLocal_2  = parametersInCalo[IExtrapolateToCaloTool::Middle]->position().eta();
-        phiCaloLocal_2  = parametersInCalo[IExtrapolateToCaloTool::Middle]->position().phi();
-        trketa_at_2     = parametersInCalo[IExtrapolateToCaloTool::Middle]->momentum().eta();
-        trkphi_at_2     = parametersInCalo[IExtrapolateToCaloTool::Middle]->momentum().phi();
-    }
-    if (parametersInCalo[IExtrapolateToCaloTool::Back]) {
-        x_3             = parametersInCalo[IExtrapolateToCaloTool::Back]->position().x();
-        y_3             = parametersInCalo[IExtrapolateToCaloTool::Back]->position().y();
-        z_3             = parametersInCalo[IExtrapolateToCaloTool::Back]->position().z();
-        etaCaloLocal_3  = parametersInCalo[IExtrapolateToCaloTool::Back]->position().eta();
-        phiCaloLocal_3  = parametersInCalo[IExtrapolateToCaloTool::Back]->position().phi();
-        trketa_at_3     = parametersInCalo[IExtrapolateToCaloTool::Back]->momentum().eta();
-        trkphi_at_3     = parametersInCalo[IExtrapolateToCaloTool::Back]->momentum().phi();
-    }
-    if (parametersInCalo[IExtrapolateToCaloTool::Tile]) {
-        x_tile             = parametersInCalo[IExtrapolateToCaloTool::Tile]->position().x();
-        y_tile             = parametersInCalo[IExtrapolateToCaloTool::Tile]->position().y();
-        z_tile             = parametersInCalo[IExtrapolateToCaloTool::Tile]->position().z();
-        etaCaloLocal_tile  = parametersInCalo[IExtrapolateToCaloTool::Tile]->position().eta();
-        phiCaloLocal_tile  = parametersInCalo[IExtrapolateToCaloTool::Tile]->position().phi();
-        trketa_at_tile     = parametersInCalo[IExtrapolateToCaloTool::Tile]->momentum().eta();
-        trkphi_at_tile     = parametersInCalo[IExtrapolateToCaloTool::Tile]->momentum().phi();
-    }
-    return new ImpactInCalo(x_0, y_0, z_0, 
-                            etaCaloLocal_0, phiCaloLocal_0,
-                            trketa_at_0, trkphi_at_0,
-                            x_1, y_1, z_1,
-                            etaCaloLocal_1, phiCaloLocal_1,
-                            trketa_at_1, trkphi_at_1,
-                            x_2, y_2, z_2, 
-                            etaCaloLocal_2, phiCaloLocal_2,
-                            trketa_at_2, trkphi_at_2,
-                            x_3, y_3, z_3, 
-                            etaCaloLocal_3, phiCaloLocal_3,
-                            trketa_at_3, trkphi_at_3,
-                            x_tile, y_tile, z_tile, 
-                            etaCaloLocal_tile, phiCaloLocal_tile,
-                            trketa_at_tile, trkphi_at_tile );
-
-}
-
-ImpactInCalo* ExtrapolateToCaloTool::getImpactInCaloFromParametersInCalo(const DataVector< const Trk::NeutralParameters >& parametersInCalo) const {
-    double x_0 = 0.;                double y_0 = 0.;            double z_0 = 0.;
-    double etaCaloLocal_0 = 0.;     double phiCaloLocal_0 = 0.;
-    double trketa_at_0 = 0.;        double trkphi_at_0 = 0.;
-    double x_1 = 0.;                double y_1 = 0.;            double z_1 = 0.;
-    double etaCaloLocal_1 = 0.;     double phiCaloLocal_1 = 0.;
-    double trketa_at_1 = 0.;        double trkphi_at_1 = 0.;
-    double x_2 = 0.;                double y_2 = 0.;            double z_2 = 0.;
-    double etaCaloLocal_2 = 0.;     double phiCaloLocal_2 = 0.;
-    double trketa_at_2 = 0.;        double trkphi_at_2 = 0.;
-    double x_3 = 0.;                double y_3 = 0.;            double z_3 = 0.;
-    double etaCaloLocal_3 = 0.;     double phiCaloLocal_3 = 0.;
-    double trketa_at_3 = 0.;        double trkphi_at_3 = 0.;
-    double x_tile = 0.;             double y_tile = 0.;         double z_tile = 0.;
-    double etaCaloLocal_tile = 0.;  double phiCaloLocal_tile = 0.;
-    double trketa_at_tile = 0.;     double trkphi_at_tile = 0.;
-
-    if (parametersInCalo[IExtrapolateToCaloTool::PreSampler]) {
-        x_0             = parametersInCalo[IExtrapolateToCaloTool::PreSampler]->position().x();
-        y_0             = parametersInCalo[IExtrapolateToCaloTool::PreSampler]->position().y();
-        z_0             = parametersInCalo[IExtrapolateToCaloTool::PreSampler]->position().z();
-        etaCaloLocal_0  = parametersInCalo[IExtrapolateToCaloTool::PreSampler]->position().eta();
-        phiCaloLocal_0  = parametersInCalo[IExtrapolateToCaloTool::PreSampler]->position().phi();
-        trketa_at_0     = parametersInCalo[IExtrapolateToCaloTool::PreSampler]->momentum().eta();
-        trkphi_at_0     = parametersInCalo[IExtrapolateToCaloTool::PreSampler]->momentum().phi();
-    }
-    if (parametersInCalo[IExtrapolateToCaloTool::Strips]) {
-        x_1             = parametersInCalo[IExtrapolateToCaloTool::Strips]->position().x();
-        y_1             = parametersInCalo[IExtrapolateToCaloTool::Strips]->position().y();
-        z_1             = parametersInCalo[IExtrapolateToCaloTool::Strips]->position().z();
-        etaCaloLocal_1  = parametersInCalo[IExtrapolateToCaloTool::Strips]->position().eta();
-        phiCaloLocal_1  = parametersInCalo[IExtrapolateToCaloTool::Strips]->position().phi();
-        trketa_at_1     = parametersInCalo[IExtrapolateToCaloTool::Strips]->momentum().eta();
-        trkphi_at_1     = parametersInCalo[IExtrapolateToCaloTool::Strips]->momentum().phi();
-    }
-    if (parametersInCalo[IExtrapolateToCaloTool::Middle]) {
-        x_2             = parametersInCalo[IExtrapolateToCaloTool::Middle]->position().x();
-        y_2             = parametersInCalo[IExtrapolateToCaloTool::Middle]->position().y();
-        z_2             = parametersInCalo[IExtrapolateToCaloTool::Middle]->position().z();
-        etaCaloLocal_2  = parametersInCalo[IExtrapolateToCaloTool::Middle]->position().eta();
-        phiCaloLocal_2  = parametersInCalo[IExtrapolateToCaloTool::Middle]->position().phi();
-        trketa_at_2     = parametersInCalo[IExtrapolateToCaloTool::Middle]->momentum().eta();
-        trkphi_at_2     = parametersInCalo[IExtrapolateToCaloTool::Middle]->momentum().phi();
-    }
-    if (parametersInCalo[IExtrapolateToCaloTool::Back]) {
-        x_3             = parametersInCalo[IExtrapolateToCaloTool::Back]->position().x();
-        y_3             = parametersInCalo[IExtrapolateToCaloTool::Back]->position().y();
-        z_3             = parametersInCalo[IExtrapolateToCaloTool::Back]->position().z();
-        etaCaloLocal_3  = parametersInCalo[IExtrapolateToCaloTool::Back]->position().eta();
-        phiCaloLocal_3  = parametersInCalo[IExtrapolateToCaloTool::Back]->position().phi();
-        trketa_at_3     = parametersInCalo[IExtrapolateToCaloTool::Back]->momentum().eta();
-        trkphi_at_3     = parametersInCalo[IExtrapolateToCaloTool::Back]->momentum().phi();
-    }
-    if (parametersInCalo[IExtrapolateToCaloTool::Tile]) {
-        x_tile             = parametersInCalo[IExtrapolateToCaloTool::Tile]->position().x();
-        y_tile             = parametersInCalo[IExtrapolateToCaloTool::Tile]->position().y();
-        z_tile             = parametersInCalo[IExtrapolateToCaloTool::Tile]->position().z();
-        etaCaloLocal_tile  = parametersInCalo[IExtrapolateToCaloTool::Tile]->position().eta();
-        phiCaloLocal_tile  = parametersInCalo[IExtrapolateToCaloTool::Tile]->position().phi();
-        trketa_at_tile     = parametersInCalo[IExtrapolateToCaloTool::Tile]->momentum().eta();
-        trkphi_at_tile     = parametersInCalo[IExtrapolateToCaloTool::Tile]->momentum().phi();
-    }
-    return new ImpactInCalo(x_0, y_0, z_0, 
-                            etaCaloLocal_0, phiCaloLocal_0,
-                            trketa_at_0, trkphi_at_0,
-                            x_1, y_1, z_1,
-                            etaCaloLocal_1, phiCaloLocal_1,
-                            trketa_at_1, trkphi_at_1,
-                            x_2, y_2, z_2, 
-                            etaCaloLocal_2, phiCaloLocal_2,
-                            trketa_at_2, trkphi_at_2,
-                            x_3, y_3, z_3, 
-                            etaCaloLocal_3, phiCaloLocal_3,
-                            trketa_at_3, trkphi_at_3,
-                            x_tile, y_tile, z_tile, 
-                            etaCaloLocal_tile, phiCaloLocal_tile,
-                            trketa_at_tile, trkphi_at_tile );
-
-}
-
-// ==================================================
-ToolHandle<CaloDepthTool> ExtrapolateToCaloTool::getCaloDepth()
-{
-  //std::cout << " m_calodepth = " << m_calodepth << std::endl;
-  return m_calodepth;
-}
-
-const DataVector< const Trk::TrackParameters >* ExtrapolateToCaloTool::getParametersInCalo (const Trk::TrackParticleBase& trk,
-            const Trk::ParticleHypothesis particle,
-            const Trk::PropDirection dir) const {
-
-    DataVector< const Trk::TrackParameters >* parametersInCalo = new DataVector< const Trk::TrackParameters >(IExtrapolateToCaloTool::NCaloLayers, SG::OWN_ELEMENTS);
-    // variables to select sampler (barrel or endcap)
-    double distbar = 0.;    // distance to barrel
-    double distec = 0.;     // distance to end caps
-    CaloCell_ID::CaloSample sample;
-    // get eta direction of particle:
-    double trketa = trk.definingParameters().momentum().eta();
-
-    // PreSampler :
-    // figure out which sampling will be hit
-    distbar = m_calodepth->deta(CaloCell_ID::PreSamplerB,trketa);
-    distec = m_calodepth->deta(CaloCell_ID::PreSamplerE,trketa);
-    
-    ATH_MSG_DEBUG(" TrackTo ...PS : for eta= " << trketa << " dist to Barrel =" << distbar 
-        << " to endcap =" << distec);
-    if (distbar < 0 )  sample = CaloCell_ID::PreSamplerB;
-    else if (distec < 0 ) sample = CaloCell_ID::PreSamplerE;
-    else if ( distbar < distec) sample = CaloCell_ID::PreSamplerB;
-    else sample = CaloCell_ID::PreSamplerE;
-    ATH_MSG_DEBUG( "  => will shoot in sample " << sample );
-
-    (*parametersInCalo)[IExtrapolateToCaloTool::PreSampler] = extrapolate(trk, sample, m_offsetPresampler, dir, particle);
-
-    Trk::ParticleHypothesis hypo = particle;
-    if (particle == Trk::undefined) {
-        if (trk.originalTrack()) {
-            hypo = trk.originalTrack()->info().particleHypothesis();
-        } else {
-            // Without the original track we cannot get the particle hypothesis used during the track fit
-            // TODO: (will be added to TrackParticle at some point)!
-            // use nonInteracting, if no hypothesis given:
-            hypo = Trk::nonInteracting;
-        }
-    }
-    // do rest of the extrapolation step-wise:
-    extrapolateStepwiseInCalo ( trk.definingParameters(),
-            hypo,
-            dir,
-            *parametersInCalo);
-
-    return parametersInCalo;
-}
-
-const DataVector< const Trk::TrackParameters >* ExtrapolateToCaloTool::getParametersInCalo (const xAOD::TrackParticle& trk,
-            const Trk::ParticleHypothesis particle,
-            const Trk::PropDirection dir) const {
-
-    DataVector< const Trk::TrackParameters >* parametersInCalo = new DataVector< const Trk::TrackParameters >(IExtrapolateToCaloTool::NCaloLayers, SG::OWN_ELEMENTS);
-    // variables to select sampler (barrel or endcap)
-    double distbar = 0.;    // distance to barrel
-    double distec = 0.;     // distance to end caps
-    CaloCell_ID::CaloSample sample;
-    // get eta direction of particle:
-    double trketa = trk.eta();
-
-    // PreSampler :
-    // figure out which sampling will be hit
-    distbar = m_calodepth->deta(CaloCell_ID::PreSamplerB,trketa);
-    distec = m_calodepth->deta(CaloCell_ID::PreSamplerE,trketa);
-    
-    ATH_MSG_DEBUG(" TrackTo ...PS : for eta= " << trketa << " dist to Barrel =" << distbar 
-        << " to endcap =" << distec);
-    if (distbar < 0 )  sample = CaloCell_ID::PreSamplerB;
-    else if (distec < 0 ) sample = CaloCell_ID::PreSamplerE;
-    else if ( distbar < distec) sample = CaloCell_ID::PreSamplerB;
-    else sample = CaloCell_ID::PreSamplerE;
-    ATH_MSG_DEBUG( "  => will shoot in sample " << sample );
-
-    (*parametersInCalo)[IExtrapolateToCaloTool::PreSampler] = extrapolate(trk, sample, m_offsetPresampler, dir, particle);
-
-    Trk::ParticleHypothesis hypo = particle;
-    if (particle == Trk::undefined) {
-        // not very nice, will hopefully have only a single (forwarded) enum at some point,
-        // instead of having xAOD::ParticleHypothesis and Trk::ParticleHypothesis
-        hypo = static_cast<Trk::ParticleHypothesis>(trk.particleHypothesis());
-    }
-    // do rest of the extrapolation step-wise:
-    extrapolateStepwiseInCalo ( trk.perigeeParameters(),
-            hypo,
-            dir,
-            *parametersInCalo);
-
-    return parametersInCalo;
-}
-
-const DataVector< const Trk::TrackParameters >* ExtrapolateToCaloTool::getParametersInCalo (const Trk::Track& trk,
-            const Trk::ParticleHypothesis particle,
-            const Trk::PropDirection dir) const {
-
-    DataVector< const Trk::TrackParameters >* parametersInCalo = new DataVector< const Trk::TrackParameters >(IExtrapolateToCaloTool::NCaloLayers, SG::OWN_ELEMENTS);
-    // variables to select sampler (barrel or endcap)
-    double distbar = 0.;    // distance to barrel
-    double distec = 0.;     // distance to end caps
-    CaloCell_ID::CaloSample sample;
-
-    double trketa = 0;
-    const Trk::TrackParameters* firstParam = 0;
-    if (trk.perigeeParameters()) {
-        trketa = trk.perigeeParameters()->eta();
-        firstParam = trk.perigeeParameters();
-    } else {
-        if (trk.trackParameters()) {
-            firstParam = *(trk.trackParameters()->begin());
-            trketa = firstParam->momentum().eta();
-        } else {
-            return parametersInCalo;
-        }
-    }
-
-    // PreSampler :
-    // figure out which sampling will be hit
-    distbar = m_calodepth->deta(CaloCell_ID::PreSamplerB,trketa);
-    distec = m_calodepth->deta(CaloCell_ID::PreSamplerE,trketa);
-    
-    ATH_MSG_DEBUG(" TrackTo ...PS : for eta= " << trketa << " dist to Barrel =" << distbar 
-        << " to endcap =" << distec);
-    if (distbar < 0 )  sample = CaloCell_ID::PreSamplerB;
-    else if (distec < 0 ) sample = CaloCell_ID::PreSamplerE;
-    else if ( distbar < distec) sample = CaloCell_ID::PreSamplerB;
-    else sample = CaloCell_ID::PreSamplerE;
-    ATH_MSG_DEBUG( "  => will shoot in sample " << sample );
-
-    (*parametersInCalo)[IExtrapolateToCaloTool::PreSampler] = extrapolate(trk, sample, m_offsetPresampler, dir, particle);
-
-    Trk::ParticleHypothesis hypo = (particle == Trk::undefined ? trk.info().particleHypothesis() : particle);
-    // do rest of the extrapolation step-wise:
-    extrapolateStepwiseInCalo ( *firstParam,
-            hypo,
-            dir,
-            *parametersInCalo);
-
-    return parametersInCalo;
-}
-
-
-void ExtrapolateToCaloTool::extrapolateStepwiseInCalo (
-            const Trk::TrackParameters& parameters,
-            Trk::ParticleHypothesis particle,
-            const Trk::PropDirection dir,
-            DataVector< const Trk::TrackParameters >& parameterVector) const {
-    double distbar = 0.;    // distance to barrel
-    double distec = 0.;     // distance to end caps
-    CaloCell_ID::CaloSample sample;
-
-    // check whether we got the parameters at the first sampling:
-    if (parameterVector[IExtrapolateToCaloTool::PreSampler] == 0) return;
-    // the last successfully extrapolated parameter in the calo:
-    const Trk::TrackParameters* lastParamInCalo = parameterVector[IExtrapolateToCaloTool::PreSampler];
-    // take position on first sampling to decide which sampling will be hit next:
-    double trketa = lastParamInCalo->position().eta();
-    // particle hypo for extrapolation inside calo
-    Trk::ParticleHypothesis particleHypoStepWiseInCalo = (m_ignoreMaterialEffectsInsideCalo ? Trk::nonInteracting : particle);
-
-    // strip :
-    distbar = m_calodepth->deta(CaloCell_ID::EMB1,trketa);
-    distec = m_calodepth->deta(CaloCell_ID::EME1,trketa);
-    ATH_MSG_DEBUG(" TrackTo ...Strip : for eta= " << trketa << " dist to Barrel =" << distbar 
-        << " to endcap =" << distec);
-    if (distbar < 0 ) sample = CaloCell_ID::EMB1;
-    else if (distec < 0 ) sample = CaloCell_ID::EME1;
-    else if ( distbar < distec) sample = CaloCell_ID::EMB1;
-    else sample = CaloCell_ID::EME1;
-    ATH_MSG_DEBUG( "  => will shoot in sample " << sample );
-
-    parameterVector[IExtrapolateToCaloTool::Strips] = extrapolate(*lastParamInCalo, sample, m_offsetStrip, particleHypoStepWiseInCalo, dir);
-
-    // fall back to original parameters if extrapolation did not succeed:
-    if (!parameterVector[IExtrapolateToCaloTool::Strips]) {
-        parameterVector[IExtrapolateToCaloTool::Strips] = extrapolate(parameters, sample, m_offsetStrip, particle, dir);
-    }
-    if (parameterVector[IExtrapolateToCaloTool::Strips]) {
-        lastParamInCalo = parameterVector[IExtrapolateToCaloTool::Strips];
-    }
-
-    // EM middle :
-    distbar = m_calodepth->deta(CaloCell_ID::EMB2,trketa);
-    distec = m_calodepth->deta(CaloCell_ID::EME2,trketa);
-    ATH_MSG_DEBUG(" TrackTo ...Middle : for eta= " << trketa << " dist to Barrel =" << distbar 
-        << " to endcap =" << distec);
-    if (distbar < 0 ) sample = CaloCell_ID::EMB2;
-    else if (distec < 0 ) sample = CaloCell_ID::EME2;
-    else if ( distbar < distec) sample = CaloCell_ID::EMB2;
-    else sample = CaloCell_ID::EME2;
-    ATH_MSG_DEBUG( "  => will shoot in sample " << sample );
-    parameterVector[IExtrapolateToCaloTool::Middle] = extrapolate(*lastParamInCalo, sample, m_offsetMiddle, particleHypoStepWiseInCalo, dir);
-    if (!parameterVector[IExtrapolateToCaloTool::Middle]) {
-        parameterVector[IExtrapolateToCaloTool::Middle] = extrapolate(parameters, sample, m_offsetMiddle, particle, dir);
-    }
-    if (parameterVector[IExtrapolateToCaloTool::Middle]) {
-        lastParamInCalo = parameterVector[IExtrapolateToCaloTool::Middle];
-    }
-
-    // EM back :
-    distbar = m_calodepth->deta(CaloCell_ID::EMB3,trketa);
-    distec = m_calodepth->deta(CaloCell_ID::EME3,trketa);
-    ATH_MSG_DEBUG(" TrackTo ...Back : for eta= " << trketa << " dist to Barrel =" << distbar 
-        << " to endcap =" << distec);
-    if (distbar < 0 ) sample = CaloCell_ID::EMB3;
-    else if (distec < 0 ) sample = CaloCell_ID::EME3;
-    else if ( distbar < distec) sample = CaloCell_ID::EMB3;
-    else sample = CaloCell_ID::EME3;
-    ATH_MSG_DEBUG( "  => will shoot in sample " << sample );
-    parameterVector[IExtrapolateToCaloTool::Back] = extrapolate(*lastParamInCalo, sample, m_offsetBack, particleHypoStepWiseInCalo, dir);
-    if (!parameterVector[IExtrapolateToCaloTool::Back]) {
-        parameterVector[IExtrapolateToCaloTool::Back] = extrapolate(parameters, sample, m_offsetBack, particle, dir);
-    }
-    if (parameterVector[IExtrapolateToCaloTool::Back]) {
-        lastParamInCalo = parameterVector[IExtrapolateToCaloTool::Back];
-    }
-
-    // Tile or HEC0 :
-    distbar = m_calodepth->deta(CaloCell_ID::TileBar0,trketa);
-    distec = m_calodepth->deta(CaloCell_ID::HEC0,trketa);
-    ATH_MSG_DEBUG(" TrackTo ...Tile : for eta= " << trketa << " dist to Barrel =" << distbar 
-        << " to endcap =" << distec);
-    if (distbar < 0 ) sample = CaloCell_ID::TileBar0;
-    else if (distec < 0 ) sample = CaloCell_ID::HEC0;
-    else if ( distbar > distec && distec < 10. ) sample = CaloCell_ID::HEC0;
-    else sample = CaloCell_ID::TileBar0;
-    ATH_MSG_DEBUG( "  => will shoot in sample " << sample );
-    parameterVector[IExtrapolateToCaloTool::Tile] = extrapolate(*lastParamInCalo, sample, m_offsetTile, particleHypoStepWiseInCalo, dir);
-    if (!parameterVector[IExtrapolateToCaloTool::Tile]) {
-        parameterVector[IExtrapolateToCaloTool::Tile] = extrapolate(parameters, sample, m_offsetTile, particle, dir);
-    }
-    return;
-}
-
-
-void ExtrapolateToCaloTool::extrapolateStepwiseInCalo (
-            const Trk::NeutralParameters& parameters,
-            Trk::ParticleHypothesis particle,
-            const Trk::PropDirection dir,
-            DataVector< const Trk::NeutralParameters >& parameterVector) const {
-    double distbar = 0.;    // distance to barrel
-    double distec = 0.;     // distance to end caps
-    CaloCell_ID::CaloSample sample;
-
-    // check whether we got the parameters at the first sampling:
-    if (parameterVector[IExtrapolateToCaloTool::PreSampler] == 0) return;
-    // the last successfully extrapolated parameter in the calo:
-    const Trk::NeutralParameters* lastParamInCalo = parameterVector[IExtrapolateToCaloTool::PreSampler];
-    // take position on first sampling to decide which sampling will be hit next:
-    double trketa = lastParamInCalo->position().eta();
-    // particle hypo for extrapolation inside calo
-    Trk::ParticleHypothesis particleHypoStepWiseInCalo = (m_ignoreMaterialEffectsInsideCalo ? Trk::nonInteracting : particle);
-
-    // strip :
-    distbar = m_calodepth->deta(CaloCell_ID::EMB1,trketa);
-    distec = m_calodepth->deta(CaloCell_ID::EME1,trketa);
-    ATH_MSG_DEBUG(" TrackTo ...Strip : for eta= " << trketa << " dist to Barrel =" << distbar 
-        << " to endcap =" << distec);
-    if (distbar < 0 ) sample = CaloCell_ID::EMB1;
-    else if (distec < 0 ) sample = CaloCell_ID::EME1;
-    else if ( distbar < distec) sample = CaloCell_ID::EMB1;
-    else sample = CaloCell_ID::EME1;
-    ATH_MSG_DEBUG( "  => will shoot in sample " << sample );
-
-    parameterVector[IExtrapolateToCaloTool::Strips] = extrapolate(*lastParamInCalo, sample, m_offsetStrip, particleHypoStepWiseInCalo, dir);
-
-    // fall back to original parameters if extrapolation did not succeed:
-    if (!parameterVector[IExtrapolateToCaloTool::Strips]) {
-        parameterVector[IExtrapolateToCaloTool::Strips] = extrapolate(parameters, sample, m_offsetStrip, particle, dir);
-    }
-    if (parameterVector[IExtrapolateToCaloTool::Strips]) {
-        lastParamInCalo = parameterVector[IExtrapolateToCaloTool::Strips];
-    }
-
-    // EM middle :
-    distbar = m_calodepth->deta(CaloCell_ID::EMB2,trketa);
-    distec = m_calodepth->deta(CaloCell_ID::EME2,trketa);
-    ATH_MSG_DEBUG(" TrackTo ...Middle : for eta= " << trketa << " dist to Barrel =" << distbar 
-        << " to endcap =" << distec);
-    if (distbar < 0 ) sample = CaloCell_ID::EMB2;
-    else if (distec < 0 ) sample = CaloCell_ID::EME2;
-    else if ( distbar < distec) sample = CaloCell_ID::EMB2;
-    else sample = CaloCell_ID::EME2;
-    ATH_MSG_DEBUG( "  => will shoot in sample " << sample );
-    parameterVector[IExtrapolateToCaloTool::Middle] = extrapolate(*lastParamInCalo, sample, m_offsetMiddle, particleHypoStepWiseInCalo, dir);
-    if (!parameterVector[IExtrapolateToCaloTool::Middle]) {
-        parameterVector[IExtrapolateToCaloTool::Middle] = extrapolate(parameters, sample, m_offsetMiddle, particle, dir);
-    }
-    if (parameterVector[IExtrapolateToCaloTool::Middle]) {
-        lastParamInCalo = parameterVector[IExtrapolateToCaloTool::Middle];
-    }
-
-    // EM back :
-    distbar = m_calodepth->deta(CaloCell_ID::EMB3,trketa);
-    distec = m_calodepth->deta(CaloCell_ID::EME3,trketa);
-    ATH_MSG_DEBUG(" TrackTo ...Back : for eta= " << trketa << " dist to Barrel =" << distbar 
-        << " to endcap =" << distec);
-    if (distbar < 0 ) sample = CaloCell_ID::EMB3;
-    else if (distec < 0 ) sample = CaloCell_ID::EME3;
-    else if ( distbar < distec) sample = CaloCell_ID::EMB3;
-    else sample = CaloCell_ID::EME3;
-    ATH_MSG_DEBUG( "  => will shoot in sample " << sample );
-    parameterVector[IExtrapolateToCaloTool::Back] = extrapolate(*lastParamInCalo, sample, m_offsetBack, particleHypoStepWiseInCalo, dir);
-    if (!parameterVector[IExtrapolateToCaloTool::Back]) {
-        parameterVector[IExtrapolateToCaloTool::Back] = extrapolate(parameters, sample, m_offsetBack, particle, dir);
-    }
-    if (parameterVector[IExtrapolateToCaloTool::Back]) {
-        lastParamInCalo = parameterVector[IExtrapolateToCaloTool::Back];
-    }
-
-    // Tile or HEC0 :
-    distbar = m_calodepth->deta(CaloCell_ID::TileBar0,trketa);
-    distec = m_calodepth->deta(CaloCell_ID::HEC0,trketa);
-    ATH_MSG_DEBUG(" TrackTo ...Tile : for eta= " << trketa << " dist to Barrel =" << distbar 
-        << " to endcap =" << distec);
-    if (distbar < 0 ) sample = CaloCell_ID::TileBar0;
-    else if (distec < 0 ) sample = CaloCell_ID::HEC0;
-    else if ( distbar > distec && distec < 10. ) sample = CaloCell_ID::HEC0;
-    else sample = CaloCell_ID::TileBar0;
-    ATH_MSG_DEBUG( "  => will shoot in sample " << sample );
-    parameterVector[IExtrapolateToCaloTool::Tile] = extrapolate(*lastParamInCalo, sample, m_offsetTile, particleHypoStepWiseInCalo, dir);
-    if (!parameterVector[IExtrapolateToCaloTool::Tile]) {
-        parameterVector[IExtrapolateToCaloTool::Tile] = extrapolate(parameters, sample, m_offsetTile, particle, dir);
-    }
-    return;
-}
-
-Amg::Vector3D ExtrapolateToCaloTool::getMomentumAtVertex(const xAOD::Vertex& vertex, 
-                                                         bool reuse /* = true */) const
-{
-  Amg::Vector3D momentum(0., 0., 0.);
-  
-  // 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); } ; 
-  
-  if (vertex.nTrackParticles() == 0)
-  {
-    ATH_MSG_WARNING("getMomentumAtVertex : vertex has no track particles!");
-    return momentum;
-  }
-  
-  if (reuse &&
-      isAvailable(vertex, "px") && 
-      isAvailable(vertex, "py") && 
-      isAvailable(vertex, "pz") )
-  {
-    // Already decorated with parameters at vertex
-    ATH_MSG_DEBUG("getMomentumAtVertex : getting from auxdata");
-    return Amg::Vector3D( vertex.auxdata<float>("px"),
-                          vertex.auxdata<float>("py"),
-                          vertex.auxdata<float>("pz") );
-  }
-  else if (vertex.vxTrackAtVertexAvailable() && vertex.vxTrackAtVertex().size())
-  {
-    // Use the parameters at the vertex 
-    // (the tracks should be parallel but we will do the sum anyway)
-    ATH_MSG_DEBUG("getMomentumAtVertex : getting from vxTrackAtVertex");
-    for (const auto& trkAtVertex : vertex.vxTrackAtVertex())
-    {
-      const Trk::TrackParameters* paramAtVertex = trkAtVertex.perigeeAtVertex();
-      if (!paramAtVertex)
-        ATH_MSG_WARNING("VxTrackAtVertex does not have perigee at vertex");
-      else
-        momentum += paramAtVertex->momentum();
-    }
-  }
-  else if (vertex.nTrackParticles() == 1)
-  {
-    // Use the first measurement
-    ATH_MSG_DEBUG("getMomentumAtVertex : 1 track only, getting from first measurement");
-    const xAOD::TrackParticle *tp = vertex.trackParticle(0);
-    unsigned int index(0);
-    if (!tp || !tp->indexOfParameterAtPosition(index, xAOD::FirstMeasurement))
-    {
-      ATH_MSG_WARNING("No TrackParticle or no have first measurement");
-    }
-    else
-      momentum += tp->curvilinearParameters(index).momentum();
-    // OR last 3 values of trackParameters(index)
-  }
-  else
-  {
-    // Extrapolate track particles to vertex
-    // (the tracks should be parallel but we will do the sum anyway)
-    ATH_MSG_DEBUG("getMomentumAtVertex : extrapolating to perigee surface");    
-    const Trk::PerigeeSurface *surface = new Trk::PerigeeSurface(vertex.position());
-    for (unsigned int i = 0; i < vertex.nTrackParticles(); ++i)
-    {
-      const xAOD::TrackParticle* tp = vertex.trackParticle( i );
-      if (!tp)
-      {
-        ATH_MSG_WARNING("NULL pointer to TrackParticle in vertex");
-        continue;
-      }
-      const Trk::TrackParameters* params = m_extrapolator->extrapolate(*tp, *surface, Trk::alongMomentum);
-      if (!params)
-        ATH_MSG_DEBUG("Extrapolation to vertex (perigee) failed");
-      else
-      {
-        momentum += params->momentum();
-        delete params;
-      }
-    }
-    delete surface;
-  }
-  
-  return momentum;
-}
-
-Trk::SurfaceIntersection ExtrapolateToCaloTool::getIntersectionInCalo(const Amg::Vector3D& position, const Amg::Vector3D& momentum, const CaloCell_ID::CaloSample sample) const
-{
-  Trk::SurfaceIntersection result{Amg::Vector3D(0., 0., 0.), 0., false};
-
-  // get the destination Surface
-  const Trk::Surface* surface = m_calosurf->CreateUserSurface (sample, 0. /* offset */, momentum.eta());
-  if (!surface)
-    return result;
-  
-  // intersect with calorimeter surface
-  result = surface->straightLineIntersection(position, momentum, true);     
-  delete surface;
-  return result;
-}
diff --git a/Reconstruction/RecoTools/TrackToCalo/src/ImpactInCalo.cxx b/Reconstruction/RecoTools/TrackToCalo/src/ImpactInCalo.cxx
deleted file mode 100755
index 8d7a1a4133bd322afb058c9a69035fbf2c9ee49c..0000000000000000000000000000000000000000
--- a/Reconstruction/RecoTools/TrackToCalo/src/ImpactInCalo.cxx
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-
-#include "TrackToCalo/ImpactInCalo.h"
-
-#ifdef HAVE_NEW_IOSTREAMS
-#include <iostream>
-#else
-#include <iostream.h>
-#define std
-#endif
-
-
-
-void ImpactInCalo::print() const {
-
-  std::cout << "Impact in PS: x,y,z=" << m_x_0 << " " << m_y_0 
-	    << " " << m_z_0
-	    << " local eta,phi=" << m_etaCaloLocal_0 << " " 
-	    << m_phiCaloLocal_0
-	    << std::endl;
-
-  std::cout << "Impact in Strip: x,y,z=" << m_x_1 << " " << m_y_1 
-	    << " " << m_z_1
-	    << " local eta,phi=" << m_etaCaloLocal_1 << " " 
-	    << m_phiCaloLocal_1
-	    << std::endl;
-
-  std::cout << "Impact in Middle: x,y,z=" << m_x_2 << " " << m_y_2 
-	    << " " << m_z_2
-	    << " local eta,phi=" << m_etaCaloLocal_2 
-	    << " " << m_phiCaloLocal_2
-	    << std::endl;
-
-  std::cout << "Impact in Back: x,y,z=" << m_x_3 << " " << m_y_3 
-	    << " " << m_z_3
-	    << " local eta,phi=" << m_etaCaloLocal_3 << " " 
-	    << m_phiCaloLocal_3
-	    << std::endl;
-
-  std::cout << "Impact in Tiles: x,y,z=" << m_x_tile << " " 
-	    << m_y_tile << " " << m_z_tile
-	    << " local eta,phi=" << m_etaCaloLocal_tile 
-	    << " " << m_phiCaloLocal_tile
-	    << std::endl;
-}
diff --git a/Reconstruction/RecoTools/TrackToCalo/src/ImpactInCaloAlg.cxx b/Reconstruction/RecoTools/TrackToCalo/src/ImpactInCaloAlg.cxx
deleted file mode 100755
index 6090ce695ccc0c55e68e171165fd1f38d76605cf..0000000000000000000000000000000000000000
--- a/Reconstruction/RecoTools/TrackToCalo/src/ImpactInCaloAlg.cxx
+++ /dev/null
@@ -1,463 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-///////////////////////////////////////////////////////////////////
-// ImpactInCaloAlg.cxx
-//   Implementation file for class ImpactInCaloAlg
-///////////////////////////////////////////////////////////////////
-
-#include "TrackToCalo/ImpactInCaloAlg.h"
-
-// Gaudi includes
-#include "GaudiKernel/MsgStream.h"
-#include "StoreGate/StoreGate.h"
-//#include "GaudiKernel/AlgFactory.h"
-#include "StoreGate/StoreGateSvc.h"
-
-// Tracking includes
-#include "TrkParameters/TrackParameters.h"
-#include <vector>
-#include "Particle/TrackParticleContainer.h"
-#include "Particle/TrackParticle.h"
-
-#include "TrackToCalo/ImpactInCalo.h"
-
-#include "CaloEvent/CaloCluster.h"
-#include "CaloEvent/CaloClusterContainer.h"
-#include "CaloDetDescr/CaloDetDescrManager.h"
-#include "CaloGeoHelpers/CaloPhiRange.h"
-#include "CaloUtils/CaloCellList.h"
-#include "CaloEvent/CaloCell.h"
-#include "CaloEvent/CaloCellContainer.h"
-#include "CaloDetDescr/ICaloCoordinateTool.h"
-#include "CaloDetDescr/CaloDepthTool.h"
-
-#include "RecoToolInterfaces/IExtrapolateToCaloTool.h"
-#include "TrackToCalo/ImpactInCaloCollection.h"
-#include "TrkToolInterfaces/ITrackSelectorTool.h"
-
-// Constructor with parameters:
-ImpactInCaloAlg::ImpactInCaloAlg(const std::string &name,
-                                 ISvcLocator *pSvcLocator) :
-        AthAlgorithm(name,pSvcLocator),
-        m_TrackName("Tracks"),
-        m_tracks(0),
-	m_particle(0),
-	m_calo_id(0),
-	m_calo_dd(0),
-        m_toCalo("ExtrapolateToCaloTool"),
-        m_trackSelectorTool(""),
-        m_extrapolateInBothDirections(false),
-        m_compareImpWithCluster(false),
-        m_printCellsCrossed(false) {
-    // Get parameter values from jobOptions file
-    declareProperty("TrackName", m_TrackName);
-    declareProperty("TrackParticleName", m_TrackParticleName);
-    declareProperty("ClusterContainerName", m_cluster_container);
-    declareProperty("CaloCellContainerName", m_cell_container);
-    declareProperty("ImpactInCaloContainerName", m_ImpactInCalosOutputName);
-    declareProperty("TrackInputType", m_trkinput);
-    declareProperty("ExtrapolateToCaloTool", m_toCalo, "the extrapolate to calo tool");
-    declareProperty("TrackSelectorTool", m_trackSelectorTool, "Tool handle to TrackSelectorTool (if no tool given: use all tracks)");
-    declareProperty("CompareImpactWithCluster", m_compareImpWithCluster, "compare impact with clusters?");
-    declareProperty("PrintCellsCrossed", m_printCellsCrossed, "print all cells crossed by tracks?");
-    declareProperty("ExtrapolateInBothDirections", m_extrapolateInBothDirections, "extrapolate each track in both directions (along and opposite momentum)?");
-}
-
-// Initialize method:
-StatusCode ImpactInCaloAlg::initialize() {
-
-    // Get the messaging service, print where you are
-    ATH_MSG_DEBUG( "ImpactInCaloAlg::initialize()" );
-
-    //StatusCode sc;
-
-    m_calo_dd = CaloDetDescrManager::instance();
-    m_calo_id = m_calo_dd->getCaloCell_ID();
-
-    if (m_toCalo.retrieve().isFailure()) {
-        ATH_MSG_FATAL( "Could not retrieve " << m_toCalo );
-        return StatusCode::FAILURE;
-    }
-
-    ATH_MSG_INFO( "ImpactInCaloAlg initialisation OK" );
-    return StatusCode::SUCCESS;
-}
-
-// Execute method:
-StatusCode ImpactInCaloAlg::execute() {
-    // Get the messaging service, print where you are
-    //StatusCode sc;
-    //ATH_MSG_DEBUG( "ImpactInCaloAlg::execute()" );
-
-    // Create the impacts :
-    StatusCode sc = CreateTrkImpactInCalo();
-    if (sc.isFailure())
-        return StatusCode::SUCCESS;
-
-    // Example 1 : you want to read the impacts and compare to clusters
-    if (m_compareImpWithCluster) {
-        sc = PrintImpact();
-        if (sc.isFailure())
-	  return StatusCode::SUCCESS;
-        sc = CompareImpactWithCluster();
-        if (sc.isFailure())
-	  return StatusCode::SUCCESS;
-    }
-
-    // Example 2 : you want to know the list of cells crossed by the track
-    if (m_printCellsCrossed) {
-        sc = PrintCellsCrossed();
-        if (sc.isFailure())
-	  return StatusCode::SUCCESS;
-    }
-
-    return StatusCode::SUCCESS;
-}
-
-// Finalize method:
-StatusCode ImpactInCaloAlg::finalize() {
-    ATH_MSG_DEBUG( "ImpactInCaloAlg::finalize()" );
-
-    return StatusCode::SUCCESS;
-}
-
-
-// Loop on Tracks/TrackParticles and create ImpactInCaloCollection
-StatusCode ImpactInCaloAlg::CreateTrkImpactInCalo() {
-    //StatusCode sc;
-    ATH_MSG_DEBUG( "ImpactInCaloAlg::CreateTrkImpactInCalo()" );
-
-    //create and record new ImpactInCalo container
-    ImpactInCaloCollection* outputContainer = new ImpactInCaloCollection();
-    StatusCode sc=evtStore()->record(outputContainer,m_ImpactInCalosOutputName,false); //"false" indicates it can't be modified by another algorithm
-    if(sc != StatusCode::SUCCESS) {
-        ATH_MSG_WARNING(" Could not record ImpactInCaloCollection"
-        << m_ImpactInCalosOutputName);
-        return StatusCode::FAILURE;
-    }
-
-    m_particle = 0;
-    m_tracks = 0;
-
-    if( m_trkinput == "TrackParticleCandidates") {
-        // use track particle collection
-        if (m_TrackParticleName == "") {
-            ATH_MSG_WARNING("TrackParticleName not set" );
-            return StatusCode::FAILURE;
-        }
-
-        sc = evtStore()->retrieve(m_particle, m_TrackParticleName);
-
-        if (sc.isFailure()) {
-            ATH_MSG_WARNING("TrackParticle not found: " << m_TrackParticleName );
-            return StatusCode::FAILURE;
-        }
-        ATH_MSG_DEBUG("TrackParticle found in StoreGate" );
-        // loop over track particles and get impacts in calo:
-        for (Rec::TrackParticleContainer::const_iterator itr = (*m_particle).begin(); itr != (*m_particle).end(); itr++) {
-            if (!(*itr)) continue;
-            if (!m_trackSelectorTool.empty()) {
-                if (!m_trackSelectorTool->decision(**itr)) {
-                    // track out of selection cuts
-                    continue;
-                }
-            }
-            // get impacts from ExtrapolateToCaloTool
-            ImpactInCalo* imp = m_toCalo->getImpactInCalo(**itr, Trk::undefined, Trk::alongMomentum);
-            if(imp)
-                outputContainer->push_back(imp);
-            else
-                ATH_MSG_DEBUG(" ImpactInCalo pointer not valid for this track");
-            if (m_extrapolateInBothDirections) {
-                ImpactInCalo* imp = m_toCalo->getImpactInCalo(**itr, Trk::undefined, Trk::oppositeMomentum);
-                if (imp) outputContainer->push_back(imp);
-            }
-        } // end loop over track particles
-    } else {
-        // use track collection
-        if (m_TrackName == "") {
-            ATH_MSG_WARNING("TrackName not set" );
-            return StatusCode::FAILURE;
-        }
-
-        sc = evtStore()->retrieve(m_tracks, m_TrackName);
-
-        if (sc.isFailure()) {
-            ATH_MSG_WARNING("Tracks not found: " << m_TrackName );
-            return StatusCode::FAILURE;
-        }
-        ATH_MSG_DEBUG("Tracks found in StoreGate" );
-        // loop over tracks
-        for (TrackCollection::const_iterator itr = (*m_tracks).begin(); itr < (*m_tracks).end(); itr++) {
-            if (!(*itr))
-                continue;
-            if (!m_trackSelectorTool.empty()) {
-                if (!m_trackSelectorTool->decision(**itr)) {
-                    // track out of selection cuts
-                    continue;
-                }
-            }
-            // get impacts from ExtrapolateToCaloTool
-            ImpactInCalo* imp = m_toCalo->getImpactInCalo(*(*itr), Trk::undefined, Trk::alongMomentum);
-            if(imp)
-                outputContainer->push_back(imp);
-            else
-                ATH_MSG_DEBUG(" ImpactInCalo pointer not valid for this track");
-            if (m_extrapolateInBothDirections) {
-                ImpactInCalo* imp = m_toCalo->getImpactInCalo(*(*itr), Trk::undefined, Trk::oppositeMomentum);
-                if (imp) outputContainer->push_back(imp);
-            }
-        }  // end loop over tracks
-    }
-    return  StatusCode::SUCCESS;
-}
-
-
-// Retreive ImpactInCaloCollection and compare to CaloClusters
-StatusCode ImpactInCaloAlg::CompareImpactWithCluster() {
-    StatusCode sc;
-
-    ATH_MSG_DEBUG( "ImpactInCaloAlg::CompareImpactWithCluster()" );
-
-    // loop on clusters
-
-    const CaloClusterContainer* cluster_container;
-    sc=evtStore()->retrieve(cluster_container,m_cluster_container);
-    if (sc.isFailure()) {
-        ATH_MSG_WARNING( "Cluster Container could not be retrieved: " << m_cluster_container );
-        return sc;
-    }
-
-    const ImpactInCaloCollection* impact_collection;
-    sc=evtStore()->retrieve(impact_collection,m_ImpactInCalosOutputName);
-    if (sc.isFailure()) {
-        ATH_MSG_WARNING( "Impact collection could not be retrieved: " << m_ImpactInCalosOutputName );
-        return sc;
-    }
-
-    typedef CaloClusterContainer::const_iterator cluster_iterator;
-    cluster_iterator f_clu =cluster_container->begin();
-    cluster_iterator l_clu = cluster_container->end();
-
-    typedef ImpactInCaloCollection::const_iterator impact_iterator;
-    impact_iterator f_imp = impact_collection->begin();
-    impact_iterator l_imp = impact_collection->end();
-
-    for ( ; f_clu!=l_clu; f_clu++) {
-        const CaloCluster* cluster = (*f_clu);
-        double hecluster = cluster->energy()/1000.;
-        double heta = cluster->eta();
-        double hphi = cluster->phi();
-
-        ATH_MSG_INFO("Found a cluster : E= " << hecluster
-        << "(GeV), etaCaloLocal=" <<  heta
-        << ", phiCaloLocal=" << hphi);
-
-        for ( ; f_imp!=l_imp; f_imp++) {
-            const ImpactInCalo* impact = (*f_imp);
-
-            ATH_MSG_INFO("==> Comparison between cluster and impact in Middle : deta="
-            << heta - impact->etaCaloLocal_2()
-            << " , dphi=" << hphi - impact->phiCaloLocal_2());
-        }
-    }
-    return StatusCode::SUCCESS;
-}
-
-// Retreive ImpactInCaloCollection and print content
-StatusCode ImpactInCaloAlg::PrintImpact() {
-    StatusCode sc;
-
-
-    ATH_MSG_INFO( " Method PrintImpacts : " );
-
-    ATH_MSG_INFO( " " );
-    ATH_MSG_INFO( " Start with Impacts : " );
-
-    const ImpactInCaloCollection* impact_collection;
-    sc=evtStore()->retrieve(impact_collection,m_ImpactInCalosOutputName);
-
-    if(sc.isFailure()) {
-        ATH_MSG_WARNING( "Could not retrieve impact colection: " << m_ImpactInCalosOutputName );
-        return sc;
-    }
-
-    typedef ImpactInCaloCollection::const_iterator impact_iterator;
-    impact_iterator f_imp = impact_collection->begin();
-    impact_iterator l_imp = impact_collection->end();
-
-    for ( ; f_imp!=l_imp; f_imp++) {
-        const ImpactInCalo* impact = (*f_imp);
-
-        const double impPhi = impact->phiCaloLocal_1();
-        const double impeta = impact->etaCaloLocal_1();
-
-        ATH_MSG_INFO("Found an impact in strips : parameters are eta = " << impeta
-        << " phi = " << impPhi);
-
-        //impact->print();
-    }
-
-    if (m_tracks) {
-
-        ATH_MSG_INFO( " " );
-        ATH_MSG_INFO(" Now loop on Trk::Track collection " );
-        ATH_MSG_INFO( " " );
-
-        for (TrackCollection::const_iterator itr  =
-                    (*m_tracks).begin(); itr < (*m_tracks).end(); itr++) {
-            const Trk::Perigee *aPer=(*itr)->perigeeParameters();
-            if (!aPer) {
-                ATH_MSG_WARNING( "Could not get Trk::Perigee from Track" );
-            } else {
-
-                const double trkphi = aPer->parameters()[Trk::phi];
-                const double trketa = aPer->eta();
-
-                ATH_MSG_INFO("Found a Trk::Track : parameters are eta = " << trketa
-                << " phi = " << trkphi);
-            }
-        }
-    }
-
-    if (m_particle) {
-
-        ATH_MSG_INFO( " " );
-        ATH_MSG_INFO(" Now loop on Trk::TrackParticle collection " );
-        ATH_MSG_INFO( " " );
-
-        for (Rec::TrackParticleContainer::const_iterator itr = m_particle->begin();
-                itr != m_particle->end(); ++itr ) {
-            if (!(*itr)->originalTrack()) {
-                ATH_MSG_WARNING( "Could not get Track from TrackParticle" );
-                continue;
-            }
-            const Trk::Perigee *aPer=((*itr)->originalTrack())->perigeeParameters();
-            if (!aPer) {
-                ATH_MSG_WARNING( "Could not get Perigee from TrackParticle" );
-            } else {
-
-                const double partphi = aPer->parameters()[Trk::phi];
-                const double parteta = aPer->eta();
-
-                ATH_MSG_INFO("Found a trackparticle : parameters are eta = " << parteta
-                << " phi = " << partphi);
-            }
-        }
-    }
-    return StatusCode::SUCCESS;
-}
-
-// List of cells crossed by Trk::Tracks in CaloSample
-// ( neta and nphi are the total window width, e.g .5x5 )
-CaloCellList* ImpactInCaloAlg::CellsCrossedByTrack(const Trk::Track& trk,
-        const CaloCell_ID::CaloSample sam,
-        int neta, int nphi) {
-    CaloCellList* my_list = 0;
-
-    // Retreive CaloCell's from StoreGate :
-
-    const CaloCellContainer* cell_container;
-    StatusCode sc=evtStore()->retrieve(cell_container,m_cell_container);
-    if ( sc.isFailure()  )
-        return 0;
-
-    // Where is the track shooting ?
-    double offset = 0.;
-
-    const Trk::TrackParameters* parametersInCalo = m_toCalo->extrapolate (trk, sam, offset);
-
-    if (!parametersInCalo)
-        return 0;
-
-    double eta = parametersInCalo->position().eta();
-    double phi = parametersInCalo->position().phi();
-
-    // CaloCellList needs both enums: subCalo and CaloSample
-    CaloCell_ID::SUBCALO subcalo;
-    bool barrel;
-    int sampling_or_module;
-    m_calo_dd->decode_sample (subcalo, barrel, sampling_or_module, sam);
-
-    // Get the corresponding granularities : needs to know where you are
-    //                  the easiest is to look for the CaloDetDescrElement
-    const CaloDetDescrElement* dde =
-      m_calo_dd->get_element(subcalo,sampling_or_module,barrel,eta,phi);
-
-    double deta = int(neta/2)*dde->deta();
-    double dphi = int(nphi/2)*dde->dphi();
-
-    // Construct the list :
-    my_list = new CaloCellList(cell_container,subcalo);
-    my_list->select(eta,phi,deta,dphi, (int) sam);
-
-    // cleanup
-    delete parametersInCalo;
-
-    return my_list ;
-}
-
-StatusCode ImpactInCaloAlg::PrintCellsCrossed() {
-
-    // Get the messaging service, print where you are
-    StatusCode sc;
-    ATH_MSG_INFO( "ImpactInCaloAlg::PrintCellsCrossed()" );
-
-    // Here we are :
-    CaloCell_ID::CaloSample sam = CaloCell_ID::EMB2;
-    int neta = 5;
-    int nphi = 5;
-
-    // get tracks from TDS
-    if (m_TrackName == "") {
-        ATH_MSG_WARNING("TrackName not set" );
-        return StatusCode::FAILURE;
-    }
-
-    sc = evtStore()->retrieve(m_tracks, m_TrackName);
-    if (sc.isFailure()) {
-        ATH_MSG_WARNING("Tracks not found: " << m_TrackName );
-        return sc;
-    }
-    ATH_MSG_DEBUG("Tracks found in StoreGate" );
-
-    for (TrackCollection::const_iterator itr  = (*m_tracks).begin(); itr != (*m_tracks).end(); itr++) {
-        if (!(*itr)) {
-            ATH_MSG_INFO( "Trackcollection contains empty entry" );
-            continue;
-        }
-        const Trk::Perigee *aPer= (*itr)->perigeeParameters();
-        if (!aPer) {
-            ATH_MSG_INFO( "Could not get Trk::Perigee from Track" );
-        } else {
-            double d0 = aPer->parameters()[Trk::d0];
-            double z0 = aPer->parameters()[Trk::z0];
-            double phi0 = aPer->parameters()[Trk::phi0];
-            double theta = aPer->parameters()[Trk::theta];
-            double qOverP = aPer->parameters()[Trk::qOverP];
-            ATH_MSG_INFO( " " );
-            ATH_MSG_INFO("Found a track: parameters are (" << d0  << ", "
-            << z0  << ", " << phi0 << ", " << theta << ", " << qOverP << ")");
-        }
-
-        // Warning : if anything fails, CellsCrossedByTrack will
-        //           simply return a null pointer
-        //           if it works, it does a new CaloCellList
-        //           ==> the client has to do the delete !!!!
-
-        CaloCellList* my_list = CellsCrossedByTrack(*(*itr), sam, neta, nphi);
-
-        if (my_list) {
-
-            for ( CaloCellList::list_iterator itr  = my_list->begin(); itr < my_list->end(); itr++) {
-                ATH_MSG_INFO("found cell ! eta=" << (*itr)->eta()
-                << " phi=" << (*itr)->phi() << " energy=" << (*itr)->energy());
-            }
-            delete my_list;
-        } else
-            ATH_MSG_INFO( "could not get cell list " );
-    }
-    return StatusCode::SUCCESS;
-}
diff --git a/Reconstruction/RecoTools/TrackToCalo/src/ImpactInCaloCollection.cxx b/Reconstruction/RecoTools/TrackToCalo/src/ImpactInCaloCollection.cxx
deleted file mode 100755
index 70a1c72fbba557caaeb55707352a44605a5b320e..0000000000000000000000000000000000000000
--- a/Reconstruction/RecoTools/TrackToCalo/src/ImpactInCaloCollection.cxx
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-
-#include "TrackToCalo/ImpactInCaloCollection.h"
-#include "TrackToCalo/ImpactInCalo.h"
-
-void ImpactInCaloCollection::print() const{
-	ImpactInCaloCollection::const_iterator iter;
-	for( iter=begin(); iter!=end(); ++iter ) (*iter)->print();
-}
-
diff --git a/Reconstruction/RecoTools/TrackToCalo/src/MuonCaloEnergyTool.cxx b/Reconstruction/RecoTools/TrackToCalo/src/MuonCaloEnergyTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..1175e27a17ed57b815dc97ec4be27e0f1eaf2fde
--- /dev/null
+++ b/Reconstruction/RecoTools/TrackToCalo/src/MuonCaloEnergyTool.cxx
@@ -0,0 +1,428 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "MuonCaloEnergyTool.h"
+// forward declares
+#include "ParticleCaloExtension/ParticleCellAssociationCollection.h"
+
+#include "TrackToCalo/CaloCellHelpers.h"
+#include "ParticleCaloExtension/ParticleCellIntersection.h"
+#include "ParticleCaloExtension/ParticleCaloAssociation.h"
+
+#include "CaloUtils/CaloCellList.h"
+#include "CaloEvent/CaloCellContainer.h"
+#include "TrkCaloExtension/CaloExtension.h"
+#include "TrkCaloExtension/CaloExtensionHelpers.h"
+
+#include "xAODTracking/TrackParticle.h"
+#include "xAODTracking/TrackingPrimitives.h"
+#include <math.h>
+
+namespace Rec {
+
+  MuonCaloEnergyTool::MuonCaloEnergyTool(const std::string& t, const std::string& n, const IInterface*  p )
+    : AthAlgTool(t,n,p),
+    m_caloExtensionTool("Trk::ParticleCaloExtensionTool/ParticleCaloExtensionTool"),
+    m_caloCellAssociationTool("Rec::ParticleCaloCellAssociationTool/ParticleCaloCellAssociationTool"),
+    m_particleCreator("Trk::TrackParticleCreatorTool/MuonCaloParticleCreator"),
+    m_caloNoiseTool("CaloNoiseToolDefault"),
+    m_sigmasAboveNoise(4.),
+    m_emEtCut(2.5*CLHEP::GeV),
+    m_emF1Cut(0.15),
+    m_emipEM(0.78),
+    m_emipTile(0.86),
+    m_emipHEC(0.94)
+  {
+    declareInterface<IMuonCaloEnergyTool>(this);
+    declareProperty("ParticleCaloExtensionTool",      m_caloExtensionTool );
+    declareProperty("ParticleCaloCellAssociationTool",m_caloCellAssociationTool );
+    declareProperty("TrackParticleCreator",           m_particleCreator );
+    declareProperty("CaloNoiseTool",                  m_caloNoiseTool);
+    declareProperty("TrackParticleLocation",          m_indetTrackParticleLocation = "InDetTrackParticles");
+    declareProperty("MuonSpectrometerTrackPArticleLocation",m_muonTrackParticleLocation = "MuonSpectrometerTrackParticles");    
+
+    //coneSize for including calo cells around track
+    declareProperty("SigmasAboveNoise", m_sigmasAboveNoise = 4.);
+    declareProperty("EmEtCut",          m_emEtCut = 2.5*1000.);  // in MeV
+    declareProperty("EmF1Cut",          m_emF1Cut = 0.15);
+  }
+
+  MuonCaloEnergyTool::~MuonCaloEnergyTool() {}
+
+  StatusCode MuonCaloEnergyTool::initialize() {
+
+    // RETRIEVE TOOLS
+    ATH_CHECK(m_caloExtensionTool.retrieve());
+    ATH_CHECK(m_caloCellAssociationTool.retrieve());
+    ATH_CHECK(m_particleCreator.retrieve());
+    ATH_CHECK(m_caloNoiseTool.retrieve());
+
+    m_indetTrackParticles = 0;
+    if(evtStore()->contains<xAOD::TrackParticleContainer>(m_indetTrackParticleLocation)) {
+      if(evtStore()->retrieve(m_indetTrackParticles,m_indetTrackParticleLocation).isFailure()) {
+        ATH_MSG_FATAL( "Unable to retrieve " << m_indetTrackParticleLocation );
+        return StatusCode::FAILURE;
+      }
+    }
+
+    m_muonTrackParticles = 0;
+    if(evtStore()->contains<xAOD::TrackParticleContainer>(m_muonTrackParticleLocation)) {
+      if(evtStore()->retrieve(m_muonTrackParticles,m_muonTrackParticleLocation).isFailure()) {
+        ATH_MSG_FATAL( "Unable to retrieve " << m_muonTrackParticleLocation );
+        return StatusCode::FAILURE;
+      }
+    }
+
+
+    return StatusCode::SUCCESS;
+  }
+
+  StatusCode MuonCaloEnergyTool::finalize() {
+    return StatusCode::SUCCESS;
+  }
+
+  void MuonCaloEnergyTool::calculateMuonEnergies( const Trk::Track* trk, 
+                                                  double deltaE, double meanIoni, double sigmaIoni,
+                                                  double& E,     double& sigma,   double& E_FSR   , double& E_expected, 
+                                          double &E_em_meas, double &E_em_exp, double &E_tile_meas, double &E_tile_exp, 
+                                          double &E_HEC_meas, double &E_HEC_exp, double &E_dead_exp ) const {
+
+//
+// Input parameters trk:        (muon) track pointer
+//                  deltaE:     Mean Energy loss in Calorimeter
+//                  meanIoni:   Mean ionization Energy loss in Calorimeter 
+//                  sigmaIoni:  sigma of the ionization Energy loss in Calorimeter
+//
+// Ouput parameters E:          Calorimeter energy measured (corrected for dead material etc.)
+//                  sigma:      Error on measured energy
+//                  E_FSR:      Energy of Final State Radiation: e.m. = photon energy (if above ET and F1 cut)   
+//                              if EFSR>0 the corrected hadronic energy is used for the measured Energy E 
+//                  E_expected: expected meanIonization Energyloss from the TrackingGeometry
+
+    E          = 0.;
+    sigma      = 0.;
+    E_FSR      = 0.;
+    E_expected = 0.;
+
+//
+// For the expected Eloss in the dead or not instrumented material we will use the meanIonization loss
+//     this meanIoni is stored on the extended Eloss object
+//     the sigmaIoni corresponds to the Landau width
+//     a factor 3.59524 gives the sigma of the upper tail
+//
+// The Eloss derived from the momentum differences on the calo extension correponds to 
+//     deltaE on the Eloss object = mean Eloss including ionization and radiation
+//
+// To go to the  meanIonization loss one needs a scale factor scale_Ionization    
+//
+    double scale_Ionization = 0.9;
+    if(fabs(deltaE)>0&&fabs(meanIoni)>0) scale_Ionization = meanIoni / deltaE;
+    double error_ratio = 0.3;
+    if(fabs(meanIoni)>0&&sigmaIoni>0) error_ratio = 3.59524*fabs(sigmaIoni/meanIoni);
+
+    ATH_MSG_DEBUG( " Inputs deltaE " << deltaE << " meanIoni " << meanIoni << " sigmaIoni " << sigmaIoni );
+    if(deltaE==0||meanIoni==0||sigmaIoni<0) ATH_MSG_WARNING( " Strange Inputs deltaE " << deltaE << " meanIoni " << meanIoni << " sigmaIoni " << sigmaIoni );
+
+    // associate muon to calorimeter 
+
+    const xAOD::TrackParticle* tp = 0;
+
+// check ID trackparticles
+
+    if(m_indetTrackParticles) {
+      for(auto it : *m_indetTrackParticles){
+        if((*it).track()==trk) {
+           tp = &(*it);
+           break;
+        }
+      }
+      if(tp) ATH_MSG_DEBUG( " ID xAOD::TrackParticle found " << tp );
+    }
+
+// look for Muon trackparticles 
+
+    if(m_muonTrackParticles&&!tp) {
+      for(auto it : *m_muonTrackParticles){
+        if((*it).track()==trk) {
+           tp = &(*it);
+           break;
+        }
+      }
+      if(tp) ATH_MSG_DEBUG( " Muon xAOD::TrackParticle found " << tp );
+    }
+    
+    if(!tp) {
+      tp = m_particleCreator->createParticle(*trk, NULL, NULL, xAOD::muon);
+      if(tp) ATH_MSG_DEBUG( " xAOD::TrackParticle created from scratch " << tp );
+    }
+
+    if(!tp) return;
+
+    const Rec::ParticleCellAssociation* association = 0;
+    m_caloCellAssociationTool->particleCellAssociation(*tp,association,0.1,NULL,true);
+
+    if(!association) return;
+    ATH_MSG_DEBUG( " particleCellAssociation done  " << association );
+
+    std::vector< std::pair<const CaloCell*,Rec::ParticleCellIntersection*> > cellIntersections = association->cellIntersections();
+
+    const Trk::CaloExtension& caloExtension = association->caloExtension();
+
+    if(!(&caloExtension)) {
+      ATH_MSG_WARNING( " No caloExtension found ");
+      return;
+    }
+
+    if(!caloExtension.caloEntryLayerIntersection()) {
+      ATH_MSG_WARNING( " No caloEntryLayerIntersection found ");
+      return;
+    }   
+
+    ATH_MSG_DEBUG( " nr of cell intersections " << cellIntersections.size() );
+    if( cellIntersections.size() < 3) ATH_MSG_WARNING( " Strange nr of calorimeter cell intersections " << cellIntersections.size() );
+
+    double theta = caloExtension.caloEntryLayerIntersection()->position().theta();
+
+    double Eloss = 0.;
+    if(!caloExtension.muonEntryLayerIntersection()) {
+      ATH_MSG_WARNING( " No muonEntryLayerIntersection found and therefore the expected Eloss is not calculated properly ");
+    } else {     
+      Eloss = caloExtension.caloEntryLayerIntersection()->momentum().mag() - caloExtension.muonEntryLayerIntersection()->momentum().mag();
+      ATH_MSG_DEBUG( " Energy loss from CaloExtension " << Eloss << " R muon Entry " << caloExtension.muonEntryLayerIntersection()->position().perp() << " Z muon Entry " << caloExtension.muonEntryLayerIntersection()->position().z() << " R calo entry " << caloExtension.caloEntryLayerIntersection()->position().perp() << " Z calo entry " << caloExtension.caloEntryLayerIntersection()->position().z() );
+    }
+
+    //auto cellcoll = association->data();
+
+    // measured and expected energies 
+
+    double E_em1  = 0.;
+    double E_em   = 0.;
+    double E_em_expected = 0.;
+    double E_em_exptot = 0.;
+    double E_em_expall = 0.;
+    double E_em_threshold = 0.;
+    int    nlay_em = 0;
+    double sigma_Noise_em = 0.;
+
+    double E_HEC  = 0.;
+    double E_HEC_expected = 0.;
+    double E_HEC_threshold = 0.;
+    double E_HEC_exptot = 0.;
+    double E_HEC_expall = 0.;
+    int    nlay_HEC = 0;
+    double sigma_Noise_HEC = 0.;
+
+    double E_tile = 0.;
+    double E_tile_expected = 0.;
+    double E_tile_threshold = 0.;
+    double E_tile_exptot = 0.;
+    double E_tile_expall = 0.;
+    int    nlay_tile = 0;
+    double sigma_Noise_tile = 0.;
+
+//    const char* sampname[24] = {
+//    	"PreSamplerB", "EMB1", "EMB2", "EMB3",
+//    	"PreSamplerE", "EME1", "EME2", "EME3",
+//    	"HEC0", "HEC1","HEC2", "HEC3",
+//    	"TileBar0", "TileBar1", "TileBar2",
+//    	"TileExt0", "TileExt1", "TileExt2",
+//    	"TileGap1", "TileGap2", "TileGap3",
+//    	"FCAL0", "FCAL1", "FCAL2"};
+//    for(const auto& curr_cell : cellcoll ){
+   
+    E_expected = 0.;
+    double phiPos = caloExtension.caloEntryLayerIntersection()->position().phi();
+    double thetaPos = caloExtension.caloEntryLayerIntersection()->position().theta();
+
+    for(auto it : cellIntersections){ 
+
+      const CaloCell* curr_cell = it.first;
+      int cellSampling = curr_cell->caloDDE()->getSampling();
+      bool badCell     = curr_cell->badcell();
+      double cellEn    = curr_cell->energy();
+
+      double f_exp = (it.second)->pathLength(); 
+      double E_exp = (it.second)->expectedEnergyLoss();
+
+//      if(f_exp<0.1) f_exp = 0.1;
+
+//    cellnoisedb = m_caloNoiseTool->getNoise(cell,ICalorimeterNoiseTool::ELECTRONICNOISE);
+      double sigma_Noise = m_caloNoiseTool->getEffectiveSigma(curr_cell,ICalorimeterNoiseTool::MAXSYMMETRYHANDLING,ICalorimeterNoiseTool::ELECTRONICNOISE);
+//      double sigma_NoiseA  = m_caloNoiseTool->totalNoiseRMS(curr_cell);
+      double thetaCell = atan2(sqrt(curr_cell->x()*curr_cell->x()+curr_cell->y()*curr_cell->y()),curr_cell->z());
+      double phiCell = atan2(curr_cell->y(),curr_cell->x());
+
+      double dtheta = thetaCell - thetaPos;
+      double dphi = acos(cos(phiPos)*cos(phiCell)+sin(phiPos)*sin(phiCell));
+      double celldr = curr_cell->caloDDE()->dr();
+      double celldz = curr_cell->caloDDE()->dz();
+      double celldtheta = celldr/sqrt(curr_cell->x()*curr_cell->x()+curr_cell->y()*curr_cell->y());
+      double celldphi = curr_cell->caloDDE()->dphi();
+ 
+ 
+      ATH_MSG_DEBUG( " cell sampling " << cellSampling << " energy " << cellEn << " position R " << sqrt(curr_cell->x()*curr_cell->x()+curr_cell->y()*curr_cell->y()) << " z " << curr_cell->z() << " f_exp " << f_exp << " E_exp " << E_exp << " dtheta " << dtheta << " dphi " << dphi <<  " cell dtheta " << celldtheta << " cell dr " << celldr <<  " cell dz " << celldz << " cell dphi " << celldphi );
+//      ATH_MSG_DEBUG( " sigma_Noise totalNoiseRMS from Alan " << sigma_NoiseA << " sigma_Noise getEffectiveSigma " << sigma_Noise);
+
+//   Use expected energy if measured energy below noise level
+// - this will bias the energy measurement towards too high values
+// - the bias is corrected in the thresholdCorrection function below
+//
+// sum measured, expected energies for crossed cells after noise cuts 
+//
+      if(cellSampling == CaloSampling::PreSamplerB || cellSampling == CaloSampling::PreSamplerE) {
+        if(f_exp>0&&cellEn>m_sigmasAboveNoise*sigma_Noise&&!badCell)  E_em1 += cellEn; 
+      }
+      if(curr_cell->caloDDE()->getSubCalo() == CaloCell_ID::LAREM) {
+        E_em_exptot += scale_Ionization*f_exp*E_exp;
+        if(f_exp>0) E_em_expall += scale_Ionization*E_exp;
+        if(f_exp>0&&cellEn>m_sigmasAboveNoise*sigma_Noise&&!badCell) {
+          E_em  += cellEn;
+          E_em_expected += scale_Ionization*f_exp*E_exp;
+          ATH_MSG_VERBOSE( " EM cell " << cellEn << " sigma_Noise " << sigma_Noise << " f_exp " << f_exp << " E_exp " << E_exp);
+        }
+        if(f_exp>0&&!badCell) nlay_em++; 
+        if(f_exp>0&&!badCell) sigma_Noise_em += sigma_Noise; 
+      } else if(curr_cell->caloDDE()->getSubCalo() == CaloCell_ID::TILE) {
+        E_tile_exptot += scale_Ionization*f_exp*E_exp;
+        if(f_exp>0) E_tile_expall += scale_Ionization*E_exp;
+        if(f_exp>0&&cellEn>m_sigmasAboveNoise*sigma_Noise&&!badCell) {
+//                       &&f_exp*E_exp>m_sigmasAboveNoise*sigma_Noise/4) {
+          E_tile  += cellEn;
+          E_tile_expected += scale_Ionization*f_exp*E_exp;
+          ATH_MSG_VERBOSE( " Tile cell " << cellEn << " sigma_Noise " << sigma_Noise << " f_exp " << f_exp << " E_exp " << E_exp);
+        }
+        if(f_exp>0&&!badCell) nlay_tile++; 
+        if(f_exp>0&&!badCell) sigma_Noise_tile += sigma_Noise; 
+      } else if(curr_cell->caloDDE()->getSubCalo() == CaloCell_ID::LARHEC) {
+        E_HEC_exptot += scale_Ionization*f_exp*E_exp;
+        if(f_exp>0) E_HEC_expall += scale_Ionization*E_exp;
+// lower threshold for HEC 
+        if(f_exp>0&&cellEn>m_sigmasAboveNoise*sigma_Noise/2.&&!badCell) {
+//                        &&f_exp*E_exp>m_sigmasAboveNoise*sigma_Noise/4) {
+          E_HEC  += cellEn;
+          E_HEC_expected += scale_Ionization*f_exp*E_exp;
+          ATH_MSG_VERBOSE( " HEC cell " << cellEn << " sigma_Noise " << sigma_Noise << " f_exp " << f_exp << " E_exp " << E_exp);
+        } 
+        if(f_exp>0&&!badCell) nlay_HEC++; 
+        if(f_exp>0&&!badCell) sigma_Noise_HEC += sigma_Noise; 
+      } 
+      E_expected += scale_Ionization*f_exp*E_exp;
+    } 
+    ATH_MSG_DEBUG( " After cuts measured Energies em " << E_em << " tile " << E_tile << " HEC " << E_HEC);
+    ATH_MSG_DEBUG( " After cuts expected Energies em " << E_em_expected << " tile " << E_tile_expected << " HEC " << E_HEC_expected);
+    ATH_MSG_DEBUG( " No cuts with length expected Energies em " << E_em_exptot << " tile " << E_tile_exptot << " HEC " << E_HEC_exptot);
+    ATH_MSG_DEBUG( " No cuts NO length expected Energies em " << E_em_expall << " tile " << E_tile_expall << " HEC " << E_HEC_expall);
+
+// E resolution of calorimeters 
+
+    double sigma_em   = sqrt( 500.*E_em);    
+    double sigma_tile = sqrt(1000.*E_tile);    
+    double sigma_HEC  = sqrt(1000.*E_HEC);    
+    
+// go from e.m. scale to Muon Energy scale
+
+    E_em   /= m_emipEM;
+    E_tile /= m_emipTile;
+    E_HEC  /= m_emipHEC;
+    ATH_MSG_DEBUG( " e.m. to Muon scale measured Energies em " << E_em << " tile " << E_tile << " HEC " << E_HEC);
+
+// also for errors
+
+    sigma_em   /= m_emipEM;
+    sigma_tile /= m_emipTile;
+    sigma_HEC  /= m_emipHEC;
+
+// Average Noise per layer 
+
+    if(nlay_em>0)   sigma_Noise_em   /= nlay_em;
+    if(nlay_tile>0) sigma_Noise_tile /= nlay_tile;
+    if(nlay_HEC>0)  sigma_Noise_HEC  /= nlay_HEC;
+    ATH_MSG_DEBUG( " Average Noise em " << sigma_Noise_em << " nlay " << nlay_em << "  tile " << sigma_Noise_tile << " nlay " << nlay_tile << "  HEC " << sigma_Noise_HEC << " nlay " << nlay_HEC );
+
+//  apply energy correction using the expected Eloss for noise cut 
+
+    E_em_threshold   += thresholdCorrection(E_em,E_em_expected,m_sigmasAboveNoise*sigma_Noise_em/m_emipEM/4);
+    E_tile_threshold += thresholdCorrection(E_tile,E_tile_expected,m_sigmasAboveNoise*sigma_Noise_tile/m_emipTile/4);
+    E_HEC_threshold  += thresholdCorrection(E_HEC,E_HEC_expected,m_sigmasAboveNoise*sigma_Noise_HEC/m_emipHEC/8);
+
+    ATH_MSG_DEBUG( " Threshold correction to Energies em " << E_em_threshold << " tile " << E_tile_threshold << " HEC " << E_HEC_threshold);
+
+    ATH_MSG_DEBUG( " total Energies em " << E_em+E_em_threshold << " tile " << E_tile+E_tile_threshold << " HEC " << E_HEC+E_HEC_threshold);
+
+//  Eloss in dead material (so everything not accounted for in the measurement)
+
+     if(scale_Ionization*Eloss>E_expected) E_expected = scale_Ionization*Eloss;
+
+     double E_dead = E_expected - E_em_expected - E_tile_expected - E_HEC_expected;
+
+//  treatment of FSR
+
+     E_FSR = 0.;
+     double E_measured = 0.;
+     double E_measured_expected = E_em_expected + E_tile_expected + E_HEC_expected;
+//     if(E_em*cos(theta)>m_emEtCut&&E_em1>0.15*E_em) {
+     if(E_em*cos(theta)>m_emEtCut) {
+// large e.m. deposit starting in first e.m. layer
+       E_FSR = E_em;
+// do not use measured e.m. energy for muons and use expected (tile and HEC are fine)
+       E = E_em_expected + E_tile + E_tile_threshold + E_HEC + E_HEC_threshold + E_dead;
+       double sigma_expdead = error_ratio*(E_em_expected + E_dead);
+       sigma = sqrt(sigma_tile*sigma_tile + sigma_HEC*sigma_HEC + sigma_expdead*sigma_expdead);
+       E_measured = E_tile + E_tile_threshold + E_HEC + E_HEC_threshold;
+     } else {
+// no FSR 
+       E = E_em + E_em_threshold + E_tile + E_tile_threshold + E_HEC + E_HEC_threshold + E_dead;
+       double sigma_threshold = error_ratio*E_dead;
+       sigma = sqrt(sigma_em*sigma_em + sigma_tile*sigma_tile + sigma_HEC*sigma_HEC+sigma_threshold*sigma_threshold);
+       E_measured = E_em + E_em_threshold + E_tile + E_tile_threshold + E_HEC + E_HEC_threshold;
+     }
+
+    ATH_MSG_DEBUG( " Total energy " << E << " sigma " << sigma  << " E calo measured in cells " << E_measured << " E calo expected in cells " << E_measured_expected << " E_expected meanIoni from TG " << E_expected );
+//    
+// add for validation (temporarily) 
+//
+//   E_em_meas,E_em_exp,E_tile_meas,E_tile_exp,E_HEC_meas,E_HEC_exp,E_dead_exp
+//
+     E_em_meas   = E_em + E_em_threshold;
+     E_em_exp    = E_em_expected;
+     E_tile_meas = E_tile + E_tile_threshold;
+     E_tile_exp  = E_tile_expected;
+     E_HEC_meas  = E_HEC + E_HEC_threshold;
+     E_HEC_exp   = E_HEC_expected;
+     E_dead_exp  = E_dead; 
+
+  } // calculateMuonEnergies
+
+
+  double MuonCaloEnergyTool::thresholdCorrection(double E_observed,double E_expected,double sigma_Noise) const {
+
+//
+// Total energy observed and expected in cells of LAr, Tile, or HEC after 4*sigma_Noise cut
+//
+// returns a correction to the energy based on the expected energy
+//
+//   one should so use: Etotal = E_observed + E_dead + ThresholdCorrection(E_observed,E_expected,sigma_Noise)
+
+    Double_t par[5] = {1.33548e+00,-1.00854e+01,5.38111e+01,-9.33379e+00,5.32913e+01};
+
+    double E = E_expected;
+
+    if(E==0) return 0.;
+ 
+    double x = sigma_Noise/E;
+    if(x>1.) x = 1.;
+
+  // formula is for a 4 sigma Noise cut and obtained by a small simulation programm
+
+    double fraction = (par[0]+par[1]*x+par[2]*x*x)/(1.+par[3]*x+par[4]*x*x);
+
+  // for low x values (low thresholds) the fraction is bigger than 1 
+  // (1.33) because the observed energy overestimates
+
+    ATH_MSG_DEBUG( " ThresholdCorrection E "  << E << " E_observed not used " << E_observed  << " sigma_Noise " << sigma_Noise <<   " x = sigma_Noise/E  " << x << " fraction " << fraction << " E correction " << (1-fraction)*E );
+
+    return (1.-fraction)*E;
+  } // thresholdCorrection
+
+} // end of namespace Trk
diff --git a/Reconstruction/RecoTools/TrackToCalo/src/MuonCaloEnergyTool.h b/Reconstruction/RecoTools/TrackToCalo/src/MuonCaloEnergyTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..1903eaa3e148d834d94b6c98cc82f7c4afa2d323
--- /dev/null
+++ b/Reconstruction/RecoTools/TrackToCalo/src/MuonCaloEnergyTool.h
@@ -0,0 +1,89 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/***************************************************************************
+MuonCaloEnergyTool.h  -  Description
+-------------------
+begin   : Summer 2014
+authors : Niels van Eldik (CERN PH-ATC)
+***************************************************************************/
+#ifndef MUONCALOENERGYTOOL_H
+#define MUONCALOENERGYTOOL_H
+
+#include "RecoToolInterfaces/IMuonCaloEnergyTool.h"
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/ToolHandle.h"
+
+#include "ParticleCaloExtension/ParticleCellAssociation.h"
+#include "TrackToCalo/CaloCellSelectorLayerdR.h"
+
+#include "RecoToolInterfaces/IParticleCaloExtensionTool.h"
+#include "RecoToolInterfaces/IParticleCaloCellAssociationTool.h"
+#include "CaloInterface/ICaloNoiseTool.h"
+
+#include "TrkToolInterfaces/ITrackParticleCreatorTool.h"
+
+#include "PathLengthUtils.h"
+
+class ICaloNoiseTool;
+
+namespace Rec {
+  class IParticleCaloCellAssociationTool;
+}
+
+namespace Trk {
+  class IParticleCaloExtensionTool;
+  class ITrackParticleCreatorTool;
+  class CaloExtension;
+}
+
+namespace Rec {
+
+  class MuonCaloEnergyTool : virtual public IMuonCaloEnergyTool, public AthAlgTool {
+  public:
+    
+    MuonCaloEnergyTool(const std::string&,const std::string&,const IInterface*);
+
+    virtual ~MuonCaloEnergyTool();
+
+    virtual StatusCode initialize();
+    virtual StatusCode finalize();
+
+    void calculateMuonEnergies( const Trk::Track* trk, 
+                                double deltaE, double meanIoni, double sigmaIoni,
+                                double& E, double& sigma, double& E_FSR, double& E_expected,
+                                double &E_em_meas, double &E_em_exp, double &E_tile_meas, double &E_tile_exp,
+                                double &E_HEC_meas, double &E_HEC_exp, double &E_dead_exp ) const;
+ 
+  private:
+
+    StoreGateSvc* m_storeGate;
+    ToolHandle <Trk::IParticleCaloExtensionTool>       m_caloExtensionTool; //!< Tool to make the step-wise extrapolation
+    ToolHandle <Rec::IParticleCaloCellAssociationTool> m_caloCellAssociationTool; //!< Tool to make the step-wise extrapolation
+    ToolHandle< Trk::ITrackParticleCreatorTool >       m_particleCreator;     /**< The CB Particle Creator Tool */
+    
+    ToolHandle <ICaloNoiseTool>  m_caloNoiseTool; //!< Tool to quantify electronic noise in calorimeter
+
+    // DATA MEMBERS
+    double m_sigmasAboveNoise; // 4.
+    double m_emEtCut; // 2.5 GeV
+    double m_emF1Cut; // 0.15
+    const double m_emipEM; // 0.78
+    const double m_emipTile; // 0.86
+    const double m_emipHEC; // 0.94
+
+    std::string m_indetTrackParticleLocation;
+    const xAOD::TrackParticleContainer* m_indetTrackParticles;
+    std::string m_muonTrackParticleLocation;
+    const xAOD::TrackParticleContainer* m_muonTrackParticles;
+
+    // PRIVATE METHODS
+    double thresholdCorrection(double E_observed,double E_expected,double sigma_Noise) const;
+
+  };
+
+
+}
+
+#endif
diff --git a/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloCellAssociationTool.cxx b/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloCellAssociationTool.cxx
index 0dc158941f1a6eee37c93848ef4a97c65ec4058a..136c0fec5005cf49bdf383d3eab806526d091ada 100644
--- a/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloCellAssociationTool.cxx
+++ b/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloCellAssociationTool.cxx
@@ -6,15 +6,37 @@
 // forward declares
 #include "RecoToolInterfaces/IParticleCaloExtensionTool.h"
 
+#include "ParticleCaloExtension/ParticleCellAssociationCollection.h"
 
-namespace Trk {
+#include "TrackToCalo/CaloCellHelpers.h"
+
+#include "CaloUtils/CaloCellList.h"
+#include "CaloEvent/CaloCellContainer.h"
+#include "TrkCaloExtension/CaloExtension.h"
+#include "TrkCaloExtension/CaloExtensionHelpers.h"
+
+#include "CaloUtils/CaloCellList.h"
+
+#include "xAODTracking/TrackingPrimitives.h"
+#include <math.h>
+
+namespace Rec {
 
   ParticleCaloCellAssociationTool::ParticleCaloCellAssociationTool(const std::string& t, const std::string& n, const IInterface*  p )
     : AthAlgTool(t,n,p),
-      m_caloExtensionTool("Trk::ParticleCaloExtensionTool/ParticleCaloExtensionTool") {
+      m_caloExtensionTool("Trk::ParticleCaloExtensionTool/ParticleCaloExtensionTool"),
+      m_defaultSelector(0.4)
+  {
 
     declareInterface<IParticleCaloCellAssociationTool>(this);
     declareProperty("ParticleCaloExtensionTool",   m_caloExtensionTool );
+
+    //Default data source for the calocells
+    declareProperty("CaloCellContainer", m_cellContainerName="AllCalo");
+
+    //coneSize for including calo cells around track
+    declareProperty("ConeSize", m_coneSize = 0.1);
+
   }
 
   ParticleCaloCellAssociationTool::~ParticleCaloCellAssociationTool() {}
@@ -23,6 +45,8 @@ namespace Trk {
     /* Retrieve track extrapolator from ToolService */
     ATH_CHECK( m_caloExtensionTool.retrieve() );
 
+    m_defaultSelector.setConeSize(m_coneSize);
+
     return StatusCode::SUCCESS;
   }
 
@@ -30,15 +54,307 @@ namespace Trk {
     return StatusCode::SUCCESS;
   }
 
-  const xAOD::ParticleCaloExtension* ParticleCaloCellAssociationTool::caloAssociation( xAOD::TrackParticle& trackParticle ) const {
-  
+  const CaloCellContainer* ParticleCaloCellAssociationTool::getCellContainer() const {
+
+    const CaloCellContainer* container = 0;
+    //retrieve the cell container
+    if( evtStore()->retrieve(container, m_cellContainerName).isFailure() || !container ) {
+      ATH_MSG_WARNING( "Unable to retrieve the cell container  " << m_cellContainerName << " container ptr " << container );
+      return 0;
+    }
+    if( container ) ATH_MSG_DEBUG("Retrieved cell container " << container->size());
+    return container;
+  }
+
+  void ParticleCaloCellAssociationTool::getCellIntersections( const Trk::CaloExtension& extension,
+                                                              const std::vector<const CaloCell*>& cells,
+                                                              ParticleCellAssociation::CellIntersections& cellIntersections ) const { 
+    
+// use 3D pathlength in cells
+
+    bool use3D = true;
+
+    cellIntersections.reserve(extension.caloLayerIntersections().size()*1.3);
+
+
+    CaloExtensionHelpers::EntryExitLayerMap  entryExitLayerMap;
+    CaloExtensionHelpers::entryExitLayerMap( extension, entryExitLayerMap );
+    ATH_MSG_DEBUG("EntryExitLayerMap " << entryExitLayerMap.size() );
+
+    CaloExtensionHelpers::ScalarLayerMap  eLossLayerMap, pathLenLayerMap;
+    CaloExtensionHelpers::eLossLayerMap( extension, eLossLayerMap );
+    CaloExtensionHelpers::pathLenLayerMap( extension, pathLenLayerMap );
+    
+    ATH_MSG_DEBUG("Getting cells intersections using cells " << cells.size() );
+    for( auto cell : cells ){
+      // get sampling and look up entry/exit points
+      CaloSampling::CaloSample sample = cell->caloDDE()->getSampling();
+
+      auto pos = entryExitLayerMap.find(sample);
+      if( pos == entryExitLayerMap.end() ) continue;
+
+      //// calculate 3D path length
+      double path = 0.;
+
+      double drFix = cell->caloDDE()->dr();
+      double dzFix = cell->caloDDE()->dz();
+//      double dphi = cell->caloDDE()->dphi();
+
+      int isample = cell->caloDDE()->getSampling();
+      bool barrel = false;
+      if(cell->caloDDE()->getSubCalo() == CaloCell_ID::TILE) barrel = true;
+      if(sample== CaloSampling::PreSamplerB ||  sample== CaloSampling::EMB1 ||  sample== CaloSampling::EMB2 || sample== CaloSampling::EMB3) barrel = true;
+
+    
+     double drTG =  fabs((pos->second.first-pos->second.second).perp());
+     double dzTG =  fabs((pos->second.first-pos->second.second).z());
+
+     if(barrel) ATH_MSG_VERBOSE(" barrel cell sampling " << cell->caloDDE()->getSampling() <<  " dr " << cell->caloDDE()->dr() << " drTG " << drTG ); 
+     if(!barrel) ATH_MSG_VERBOSE(" endcap cell sampling " << cell->caloDDE()->getSampling() <<  " dz " << cell->caloDDE()->dz() << " dzTG " << dzTG ); 
+// 
+// always use fixed values that correspond to the Calorimeter Tracking Geometry
+// these are different from the CaloCell values
+//
+      if(!barrel) dzFix = dzTG;
+      if(barrel)  drFix = drTG;
+
+
+      if(drFix==0.) { 
+// recalculate the r values from the other cells 
+// BUG: extract dr from cell container for sampling 4 5 6 7 needed EME 
+// BUG: extract dr from cell container for sampling 8 9 10 11 needed HEC 
+        if(cell->caloDDE()->deta()>0) {
+          double dtheta = cell->caloDDE()->deta();
+          double theta = atan2(cell->caloDDE()->r(),cell->z());
+          if( theta+dtheta < M_PI ) {
+            double deta = -log(tan((theta+dtheta)/2.)) + log(tan((theta)/2.));  
+            double scale = fabs(deta)/cell->caloDDE()->deta();
+            double dr = fabs(cell->z()*tan(theta+dtheta/scale) - cell->z()*tan(theta));
+            drFix = dr; 
+            ATH_MSG_VERBOSE(" FIX cell sampling " << cell->caloDDE()->getSampling() << " deta " << cell->caloDDE()->deta() << " drFix " << drFix);
+          }else{
+            ATH_MSG_WARNING(" FIXR cell sampling failed: theta " << theta << " dtheta " << dtheta << " sum/pi " << (theta+dtheta)/M_PI 
+                            << " deta " << cell->caloDDE()->deta());
+          }
+//          ATH_MSG_VERBOSE(" FIX cell sampling deta " << deta << " dtheta " << dtheta  << "  scale " <<  scale << " theta " << theta );
+        } else {
+          double drMin = 100000.;
+          int dscut = 1;
+          if(!barrel) dscut = 0;
+          const CaloCell* cellFound = 0;
+          for( auto celln : cells ){
+            if(cell==celln) continue;
+            if(cell->caloDDE()->getSubCalo() == celln->caloDDE()->getSubCalo()) {
+              int dsample = isample-celln->caloDDE()->getSampling();
+              if(abs(dsample)==dscut) {
+                double drNew = fabs(cell->caloDDE()->r()-celln->caloDDE()->r()); 
+                if(drNew<1) continue;
+                if(drNew<drMin) { 
+                  drMin = drNew;
+                  cellFound = celln;   
+                }
+              }
+            }
+          }
+          drFix = drMin;
+          ATH_MSG_VERBOSE(" Problem cell sampling " << cell->caloDDE()->getSampling() << " x " << cell->caloDDE()->x() << " y " << cell->caloDDE()->y() << " z " << cell->caloDDE()->z() << " dr " << cell->caloDDE()->dr() << " drFix "  << drFix << " drTG " << drTG ); 
+        if(cellFound) ATH_MSG_VERBOSE(" cellFound sampling " << cellFound->caloDDE()->getSampling() << " x " << cellFound->caloDDE()->x() << " y " << cellFound->caloDDE()->y() << " z " << cellFound->caloDDE()->z() << " dr " << cellFound->caloDDE()->dr() << " dscut " << dscut  << " drFix "  << drFix );
+        }
+      }
+
+      if(dzFix==0.) { 
+// recalculate z values from the other cells 
+// BUG: extract dz from cell container for sampling 0 1 2 3 needed EMB  
+        if(cell->caloDDE()->deta()>0) {
+          double dtheta = cell->caloDDE()->deta();
+          double theta = atan2(cell->caloDDE()->r(),cell->z());
+          if( theta+dtheta < M_PI ) {
+            double deta = -log(tan((theta+dtheta)/2.)) + log(tan((theta)/2.));  
+            double scale = fabs(deta)/cell->caloDDE()->deta();
+            double dz = fabs(cell->caloDDE()->r()/tan(theta+dtheta/scale) - cell->caloDDE()->r()/tan(theta));
+            dzFix = dz; 
+          }else{
+            ATH_MSG_WARNING(" FIXZ cell sampling failed: theta " << theta << " dtheta " << dtheta << " sum/pi " << (theta+dtheta)/M_PI 
+                            << " deta " << cell->caloDDE()->deta());
+          }
+          ATH_MSG_VERBOSE(" Fix cell sampling " << cell->caloDDE()->getSampling() << " deta " << cell->caloDDE()->deta() << " dzFix " << dzFix);
+          //          ATH_MSG_VERBOSE(" FIX cell sampling deta " << deta << " dtheta " << dtheta  << "  scale " <<  scale << " theta " << theta );
+        } else {
+          double dzMin = 100000.;
+          int dscut = 1;
+          if(barrel) dscut = 0;
+          const CaloCell* cellFound = 0;
+          for( auto celln : cells ){
+            if(cell==celln) continue;
+            if(cell->caloDDE()->getSubCalo() == celln->caloDDE()->getSubCalo()) {
+              int isample2 = celln->caloDDE()->getSampling();
+              if(abs(isample-isample2)==dscut) {
+                double dzNew = fabs(cell->caloDDE()->z()-celln->caloDDE()->z()); 
+                if(dzNew<1) continue;
+                if(dzNew<dzMin) { 
+                  dzMin = dzNew;
+                  cellFound = celln;   
+                }
+              }
+            }
+          }
+          dzFix = dzMin;
+          ATH_MSG_VERBOSE(" Problem cell sampling " << cell->caloDDE()->getSampling() << " x " << cell->caloDDE()->x() << " y " << cell->caloDDE()->y() << " z " << cell->caloDDE()->z() << " dz " << cell->caloDDE()->dz() << " dzFix "  << dzFix << " dzTG " << dzTG  ); 
+          if(cellFound) ATH_MSG_VERBOSE(" cellFound sampling " << cellFound->caloDDE()->getSampling() << " x " << cellFound->caloDDE()->x() << " y " << cellFound->caloDDE()->y() << " z " << cellFound->caloDDE()->z() << " dz " << cellFound->caloDDE()->dz()  << " dscut " << dscut << " dzFix "  << dzFix );
+        }    
+      }
+
+      if(use3D) {
+      //pathLenUtil.pathInsideCell( *cell, entryExitLayerMap);
+        double pathInMM = pathLenUtil.get3DPathLength(*cell, pos->second.first, pos->second.second,drFix,dzFix);
+        double totpath =  (pos->second.first-pos->second.second).mag();
+        path = totpath!=0 ? pathInMM / totpath : 0.; 
+      }
+
+      //// calculate 2D path length (method2)
+      double path2 = 0.;
+
+      if(!use3D) path2 = pathInsideCell(*cell, pos->second.first, pos->second.second );
+
+      if( path2 <= 0. && path <= 0. ) continue;
+
+      // auto entrancePair = entryExitLayerMap.find(entranceID);
+      auto eLossPair = eLossLayerMap.find(sample);
+      double eLoss = 0.;
+//
+// DO NOT scale eloss with tracklength in cell just store total expected eloss
+//
+      if( eLossPair != eLossLayerMap.end() ){
+        eLoss = eLossPair->second;
+      } // IF
+
+      ATH_MSG_DEBUG(" PATH3D = " << path << " PATH2D = " << path2 << " eLoss " << eLoss << " cell energy " << (cell)->energy() << " radius " << cell->caloDDE()->r() << " phi " << cell->caloDDE()->phi() << " dr " << cell->caloDDE()->dr() << " dphi " << cell->caloDDE()->dphi()  << " x " << cell->caloDDE()->x() << " y " << cell->caloDDE()->y() << " z " << cell->caloDDE()->z() << " dx " << cell->caloDDE()->dx() << " dy " << cell->caloDDE()->dy() << " dz " << cell->caloDDE()->dz() << " volume " << cell->caloDDE()->volume());
+
+      cellIntersections.push_back( std::make_pair(cell, new ParticleCellIntersection( *cell, eLoss, use3D?path:path2) ) );
+      //cellIntersections.push_back( std::make_pair(cell, new ParticleCellIntersection( *cell, eLoss, path/pathLenLayerMap[sample]) ) );
+      //cellIntersections.push_back( std::make_pair(cell, new ParticleCellIntersection( *cell, path2, path/pathLenLayerMap[sample]) ) ); //tmp hack
+    } 
+    ATH_MSG_DEBUG(" added cell intersections  " << cellIntersections.size() );
+  }
+
+
+  bool ParticleCaloCellAssociationTool::particleCellAssociation( const xAOD::IParticle& particle,  
+                                                                 const ParticleCellAssociation*& association, float dr, 
+                                                                 const CaloCellContainer* container, bool useCaching ) const {
+
+
+    ATH_MSG_DEBUG(" particleCellAssociation: ptr " << &particle << " dr " << dr << " useCaching " << useCaching);
+
+    // reset pointer
+    association = 0;
+    // check if link is already there
+    if( useCaching ){
+      if( particle.isAvailable< ParticleCellAssociation* >("cellAssociation") ){
+        ParticleCellAssociation* theAssociation = particle.auxdata< ParticleCellAssociation* >("cellAssociation");
+        if( theAssociation ){
+          // check whether the cached association is from the same container
+          if( container && theAssociation->container() != container ){
+            ATH_MSG_WARNING("Calling cached version with different container pointer");
+            return false;
+          }
+          // check if we need to resize the cone
+          if( dr > theAssociation->associationConeSize() ){
+            std::vector<const CaloCell*> cells;
+            ATH_MSG_DEBUG(" dr larger then cached dr: " << dr << " cached dr " << theAssociation->associationConeSize());
+            associateCells(*theAssociation->container(),theAssociation->caloExtension(),dr,cells);
+            theAssociation->updateData(std::move(cells),dr);
+          }
+          association = theAssociation;
+          ATH_MSG_DEBUG("Found existing calo extension");
+          return true;
+        }
+      }
+    }
+
     // get the extrapolation into the calo
-    const xAOD::ParticleCaloExtension* caloExtension = m_caloExtensionTool->caloExtension(trackParticle);
-    if( !caloExtension ) return 0;
+    const Trk::CaloExtension* caloExtension = 0;
+    if( !m_caloExtensionTool->caloExtension(particle,caloExtension) ) {
+      ATH_MSG_DEBUG("Failed to get calo extension");      
+      return false;
+    }
+    if( caloExtension->caloLayerIntersections().empty()){
+      ATH_MSG_DEBUG( "Received a caloExtension object without track extrapolation");
+      return false;
+    }
+    
+    //retrieve the cell container if not provided, return false it retrieval failed
+    if( !container && !(container = getCellContainer()) ) {
+      ATH_MSG_DEBUG("Failed to get calo cell container");      
+      return false;
+    }
+    std::vector<const CaloCell*> cells;
+    // update cone size in case it is smaller than the default
+    if( dr < m_coneSize ) dr = m_coneSize;
+    associateCells(*container,*caloExtension,dr,cells);    
+    
+    // get cell intersections
+    ParticleCellAssociation::CellIntersections cellIntersections;
+    getCellIntersections(*caloExtension,cells,cellIntersections);
+    
+//    for(auto it : cellIntersections){
+//      double f_exp = (it.second)->pathLength();
+//      double E_exp = (it.second)->expectedEnergyLoss();
+//      ATH_MSG_DEBUG( " path " << f_exp << " expected Eloss " << E_exp );
+//    }
+
+    ParticleCellAssociation* theAssocation = new ParticleCellAssociation( *caloExtension, std::move(cells), dr, 
+                                                                          std::move(cellIntersections), container );
+
+    // now add the extension to the output collection so we are not causing any leaks
+    ParticleCellAssociationCollection* collection = 0;
+    if( !evtStore()->contains<ParticleCellAssociationCollection>(m_cellContainerName) ){
+      collection = new ParticleCellAssociationCollection();
+      if( evtStore()->record( collection, m_cellContainerName).isFailure() ) {
+        ATH_MSG_WARNING( "Failed to record output collection, will leak the ParticleCaloExtension");
+        delete collection;
+        collection = 0;
+      }
+    }else{
+      if(evtStore()->retrieve(collection,m_cellContainerName).isFailure()) {
+        ATH_MSG_WARNING( "Unable to retrieve " << m_cellContainerName << " will leak the ParticleCaloExtension" );
+      }
+    }
+    if( collection ) collection->push_back(theAssocation);
+    else{
+      ATH_MSG_WARNING( "No ParticleCaloCellAssociationCollection, failing extension to avoid memory leak");
+      delete theAssocation;
+      theAssocation = 0;
+    }
+
+    association = theAssocation;
+    if( useCaching ) particle.auxdecor< ParticleCellAssociation* >("cellAssociation") = theAssocation;
+
+
+    return true;
+
+  }
+
+  void ParticleCaloCellAssociationTool::associateCells( const CaloCellContainer& container, 
+                                                        const Trk::CaloExtension& caloExtension,
+                                                        float dr,
+                                                        std::vector<const CaloCell*>& cells ) const {    
+
+    const Trk::TrackParameters*  pars = caloExtension.caloEntryLayerIntersection();
+    if(!pars) {
+      ATH_MSG_WARNING( " NO TrackParameters caloExtension.caloEntryLayerIntersection() ");
+      return;
+    } 
+
+    double eta = pars->position().eta();
+    double phi = pars->position().phi();
+
+    // Use Calorimeter list for CPU reasons
+    CaloCellList myList(&container);
+    myList.select(eta,phi,dr);
+    cells.reserve(myList.ncells());
+    cells.insert(cells.end(),myList.begin(),myList.end());
 
-    // now collect the cells
-  
-    return caloExtension;
+    ATH_MSG_DEBUG("associated cells " << cells.size() << " using cone " << dr );
   }
 
 } // end of namespace Trk
diff --git a/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloCellAssociationTool.h b/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloCellAssociationTool.h
index 3fec827c3f93a926c431d6b5bc7a1bc928e089cc..a00fcacd3a6a42c90d089fd1809c6971b6c67cf4 100644
--- a/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloCellAssociationTool.h
+++ b/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloCellAssociationTool.h
@@ -15,12 +15,17 @@ authors : Niels van Eldik (CERN PH-ATC)
 #include "AthenaBaseComps/AthAlgTool.h"
 #include "GaudiKernel/ToolHandle.h"
 
-#include "xAODTracking/TrackParticle.h"
+#include "ParticleCaloExtension/ParticleCellAssociation.h"
+#include "TrackToCalo/CaloCellSelectorLayerdR.h"
 
+#include "PathLengthUtils.h"
 
 namespace Trk {
-  
   class IParticleCaloExtensionTool;
+  class CaloExtension;
+}
+
+namespace Rec {
 
   class ParticleCaloCellAssociationTool : virtual public IParticleCaloCellAssociationTool, public AthAlgTool {
   public:
@@ -32,15 +37,44 @@ namespace Trk {
     virtual StatusCode initialize();
     virtual StatusCode finalize();
 
-    /** Method to dress a TrackParticle with the calo cells crossed by its track
-        @param trackParticle 
-        @return ParticleCaloExtension, caller does not obtain ownership of the pointer and should not delete it
+    /** Method to get the ParticleCellAssociation of a given TrackParticle
+        @param trackParticle  input track particle
+        @param extension      reference to a pointer to a ParticleCellAssociation, will be updated if call is successfull
+                              NEVER delete the pointer, you will cause a crash! 
+        @param dr             cone size used for the association
+                              If caching is enabled, the cells associated to the association contain at least all cells
+                              in dr but could contain more. Users ALWAYS have to recalculate the associated cells in their cone.
+        @param container      cell container to be used if provided 
+        @param useCaching     configure whether the tool caches the result on the track particle
+                              The default behavior is 'true' to ensure optimal performance
+                              If caching is enabled, the code will perform a consistency check on the container pointer
+                              If the function is called twice on the same particle with different containers, the call will fail.
+                              The same is true if the function is called once without container and once with on the same particle.
+        @return true if the call was successful
     */
-    const xAOD::ParticleCaloExtension* caloAssociation( xAOD::TrackParticle& trackParticle ) const;
-
+    bool particleCellAssociation( const xAOD::IParticle& particle,  const ParticleCellAssociation*& association, float dr, 
+                                  const CaloCellContainer* container = 0, bool useCaching = true ) const final;
+    
   private:
-    ToolHandle< IParticleCaloExtensionTool >  m_caloExtensionTool;
+
+    void getCellIntersections( const Trk::CaloExtension& caloExtension,
+                               const std::vector<const CaloCell*>& cells,
+                               ParticleCellAssociation::CellIntersections& cellIntersections) const;
+
+    const CaloCellContainer* getCellContainer() const;
+    void associateCells( const CaloCellContainer& container, const Trk::CaloExtension& caloExtension, float dr,
+                         std::vector<const CaloCell*>& cells ) const;
+
+    ToolHandle< Trk::IParticleCaloExtensionTool >  m_caloExtensionTool;
+    std::string m_cellContainerName;
+    double      m_coneSize;
+    mutable Trk::CaloCellSelectorLayerdR m_defaultSelector;
+
+    mutable PathLengthUtils pathLenUtil;
+
   };
+
+
 }
 
 #endif
diff --git a/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloClusterAssociationTool.cxx b/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloClusterAssociationTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..ab136705f51f28206fb1de1620ad20ca12e38cb9
--- /dev/null
+++ b/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloClusterAssociationTool.cxx
@@ -0,0 +1,159 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "ParticleCaloClusterAssociationTool.h"
+// forward declares
+#include "RecoToolInterfaces/IParticleCaloExtensionTool.h"
+
+#include "ParticleCaloExtension/ParticleClusterAssociationCollection.h"
+#include "ParticlesInConeTools/ICaloClustersInConeTool.h"
+
+#include "TrkCaloExtension/CaloExtension.h"
+#include "TrkCaloExtension/CaloExtensionHelpers.h"
+
+#include "FourMomUtils/P4Helpers.h"
+
+namespace Rec {
+
+  ParticleCaloClusterAssociationTool::ParticleCaloClusterAssociationTool(const std::string& t, const std::string& n, const IInterface*  p )
+    : AthAlgTool(t,n,p),
+      m_caloExtensionTool("Trk::ParticleCaloExtensionTool/ParticleCaloExtensionTool"),
+      m_clustersInConeTool("xAOD::CaloClustersInConeTool/CaloClustersInConeTool")
+  {
+
+    declareInterface<IParticleCaloClusterAssociationTool>(this);
+    declareProperty("ParticleCaloExtensionTool",   m_caloExtensionTool );
+    declareProperty("ClustersInConeTool",          m_clustersInConeTool);
+
+    //coneSize for including calo cells around track
+    declareProperty("ConeSize", m_coneSize = 0.1);
+
+  }
+
+  ParticleCaloClusterAssociationTool::~ParticleCaloClusterAssociationTool() {}
+
+  StatusCode ParticleCaloClusterAssociationTool::initialize() {
+    /* Retrieve track extrapolator from ToolService */
+    ATH_CHECK( m_caloExtensionTool.retrieve() );
+
+    if (!m_clustersInConeTool.empty()) ATH_CHECK(m_clustersInConeTool.retrieve());
+
+    return StatusCode::SUCCESS;
+  }
+
+  StatusCode ParticleCaloClusterAssociationTool::finalize() {
+    return StatusCode::SUCCESS;
+  }
+
+  bool ParticleCaloClusterAssociationTool::particleClusterAssociation( const xAOD::IParticle& particle,  const ParticleClusterAssociation*& association, float dr, 
+                                                                       const xAOD::CaloClusterContainer* container, bool useCaching ) const {
+
+
+    ATH_MSG_DEBUG(" particleCellAssociation: ptr " << &particle << " dr " << dr << " useCaching " << useCaching);
+
+    // reset pointer
+    association = 0;
+    // check if link is already there
+    if( useCaching ){
+      if( particle.isAvailable< ParticleClusterAssociation* >("clusterAssociation") ){
+        ParticleClusterAssociation* theAssociation = particle.auxdata< ParticleClusterAssociation* >("clusterAssociation");
+        if( theAssociation ){
+          // check whether the cached association is from the same container
+          if( container && theAssociation->container() != container ){
+            ATH_MSG_WARNING("Calling cached version with different container pointer");
+            return false;
+          }
+          // check if we need to resize the cone
+          if( dr > theAssociation->associationConeSize() ){
+            ATH_MSG_DEBUG(" dr larger then cached dr: " << dr << " cached dr " << theAssociation->associationConeSize());
+            ParticleClusterAssociation::Data clusters;
+            associateClusters(container,theAssociation->caloExtension(),dr,clusters);    
+            theAssociation->updateData(std::move(clusters),dr);
+          }
+          association = theAssociation;
+          ATH_MSG_DEBUG("Found existing calo extension");
+          return true;
+        }
+      }
+    }
+
+    // get the extrapolation into the calo
+    const Trk::CaloExtension* caloExtension = 0;
+    if( !m_caloExtensionTool->caloExtension(particle,caloExtension) ) {
+      ATH_MSG_DEBUG("Failed to get calo extension");      
+      return false;
+    }
+    if( caloExtension->caloLayerIntersections().empty()){
+      ATH_MSG_DEBUG( "Received a caloExtension object without track extrapolation");
+      return false;
+    }
+    
+
+    // update cone size in case it is smaller than the default
+    if( dr < m_coneSize ) dr = m_coneSize;
+    ParticleClusterAssociation::Data clusters;
+    associateClusters(container,*caloExtension,dr,clusters);    
+    
+    ParticleClusterAssociation* theAssocation = new ParticleClusterAssociation( *caloExtension, std::move(clusters), dr, container );
+
+    // now add the extension to the output collection so we are not causing any leaks
+    ParticleClusterAssociationCollection* collection = 0;
+    if( !evtStore()->contains<ParticleClusterAssociationCollection>(m_containerName) ){
+      collection = new ParticleClusterAssociationCollection();
+      if( evtStore()->record( collection, m_containerName).isFailure() ) {
+        ATH_MSG_WARNING( "Failed to record output collection, will leak the ParticleCaloExtension");
+        delete collection;
+        collection = 0;
+      }
+    }else{
+      if(evtStore()->retrieve(collection,m_containerName).isFailure()) {
+        ATH_MSG_WARNING( "Unable to retrieve " << m_containerName << " will leak the ParticleCaloExtension" );
+      }
+    }
+    if( collection ) collection->push_back(theAssocation);
+    else{
+      ATH_MSG_WARNING( "No ParticleCaloCellAssociationCollection, failing extension to avoid memory leak");
+      delete theAssocation;
+      theAssocation = 0;
+    }
+
+    association = theAssocation;
+    if( useCaching ) particle.auxdecor< ParticleClusterAssociation* >("clusterAssociation") = theAssocation;
+
+
+    return true;
+
+  }
+
+  void ParticleCaloClusterAssociationTool::associateClusters( const xAOD::CaloClusterContainer* container, 
+                                                              const Trk::CaloExtension& caloExtension,
+                                                              float dr,
+                                                              ParticleClusterAssociation::Data& clusters ) const {    
+
+    const Trk::TrackParameters*  pars = caloExtension.caloEntryLayerIntersection();
+    if(!pars) {
+      ATH_MSG_WARNING( " NO TrackParameters caloExtension.caloEntryLayerIntersection() ");
+      return;
+    } 
+
+    float eta = pars->position().eta();
+    float phi = pars->position().phi();
+    if( container ){
+      float dr2Cut = dr*dr;
+      for( unsigned int i=0;i<container->size();++i ){
+        
+        float dPhi = P4Helpers::deltaPhi( (*container)[i]->phi(), phi);
+        float dEta = (*container)[i]->eta()-eta;
+        float dr2  = dPhi*dPhi+ dEta*dEta;
+        if( dr2 < dr2Cut ) clusters.push_back( ElementLink<xAOD::CaloClusterContainer>(*container,i) );
+      }
+    }else{
+      if( !m_clustersInConeTool->particlesInCone(eta,phi,dr,clusters) ) {
+        ATH_MSG_WARNING("Failed to get clusters");
+      }
+    }
+    ATH_MSG_DEBUG("associated cells " << clusters.size() << " using cone " << dr );
+  }
+
+} // end of namespace Trk
diff --git a/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloClusterAssociationTool.h b/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloClusterAssociationTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..ed3b22a595acda5dca8d0c6f7bb964cd5110e081
--- /dev/null
+++ b/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloClusterAssociationTool.h
@@ -0,0 +1,75 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/***************************************************************************
+ParticleCaloClusterAssociationTool.h  -  Description
+-------------------
+begin   : Summer 2014
+authors : Niels van Eldik (CERN PH-ATC)
+***************************************************************************/
+#ifndef TRACKTOCALO_PARTICLECALOCLUSTERASSOCIATION_H
+#define TRACKTOCALO_PARTICLECALOCLUSTERASSOCIATION_H
+
+#include "RecoToolInterfaces/IParticleCaloClusterAssociationTool.h"
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/ToolHandle.h"
+
+#include "ParticleCaloExtension/ParticleClusterAssociation.h"
+
+namespace Trk {
+  class IParticleCaloExtensionTool;
+  class CaloExtension;
+}
+namespace xAOD {
+  class ICaloClustersInConeTool;
+}
+namespace Rec {
+
+  class ParticleCaloClusterAssociationTool : virtual public IParticleCaloClusterAssociationTool, public AthAlgTool {
+  public:
+    
+    ParticleCaloClusterAssociationTool(const std::string&,const std::string&,const IInterface*);
+
+    virtual ~ParticleCaloClusterAssociationTool();
+
+    virtual StatusCode initialize();
+    virtual StatusCode finalize();
+
+    /** Method to get the ParticleClusterAssociation of a given TrackParticle
+        @param particle       input particle
+        @param extension      reference to a pointer to a ParticleClusterAssociation, will be updated if call is successfull
+                              NEVER delete the pointer, you will cause a crash! 
+        @param dr             cone size used for the association
+                              If caching is enabled, the cells associated to the association contain at least all cells
+                              in dr but could contain more. Users ALWAYS have to recalculate the associated cells in their cone.
+        @param container      cluster container to be used if provided 
+        @param useCaching     configure whether the tool caches the result on the track particle
+                              The default behavior is 'true' to ensure optimal performance
+                              If caching is enabled, the code will perform a consistency check on the container pointer
+                              If the function is called twice on the same particle with different containers, the call will fail.
+                              The same is true if the function is called once without container and once with on the same particle.
+        @return true if the call was successful
+    */
+    bool particleClusterAssociation( const xAOD::IParticle& particle,  const ParticleClusterAssociation*& association, float dr, 
+                                     const xAOD::CaloClusterContainer* container = 0, bool useCaching = true ) const final;
+    
+  private:
+
+
+    void associateClusters( const xAOD::CaloClusterContainer* container, 
+                            const Trk::CaloExtension& caloExtension,
+                            float dr,
+                            ParticleClusterAssociation::Data& clusters ) const;
+
+    ToolHandle< Trk::IParticleCaloExtensionTool >  m_caloExtensionTool;
+    ToolHandle< xAOD::ICaloClustersInConeTool >     m_clustersInConeTool;
+    std::string m_containerName;
+    double      m_coneSize;
+
+  };
+
+
+}
+
+#endif
diff --git a/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloExtensionTool.cxx b/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloExtensionTool.cxx
index 2eac44ca3cd1204a1807b944c43c102fc8250926..5feb23a00d6d66a299b9d763cdd91a8162b15fd2 100644
--- a/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloExtensionTool.cxx
+++ b/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloExtensionTool.cxx
@@ -4,34 +4,34 @@
 
 #include "ParticleCaloExtensionTool.h"
 // forward declares
-#include "TrkExInterfaces/IExtrapolator.h"
-#include "TrkTrack/Track.h"
 #include "TrkSurfaces/PerigeeSurface.h"
 #include "TrkTrack/TrackStateOnSurface.h"
+#define private public
 #include "TrkParameters/TrackParameters.h"
-
+#include "TrkTrack/Track.h"
+#include "TrkExInterfaces/IExtrapolator.h"
+#include "TrkCaloExtension/CaloExtension.h"
+#include "TrkCaloExtension/CaloExtensionCollection.h"
+#define public private 
 #include "xAODTracking/TrackingPrimitives.h"
 #include "AtlasDetDescr/AtlasDetectorID.h"
-#include "MagFieldInterfaces/IMagFieldSvc.h"
-#include "EventPrimitives/EventPrimitivesHelpers.h"
-#include "TrkEventPrimitives/PropDirection.h" 
-#include "TrkEventPrimitives/CurvilinearUVT.h"
-#include "TrkEventPrimitives/JacobianLocalToCurvilinear.h"
+#include "TrkParametersIdentificationHelpers/TrackParametersIdHelper.h"
+#include "xAODTruth/TruthVertex.h"
+#include "xAODMuon/Muon.h"
 
 namespace Trk
 {
   ParticleCaloExtensionTool::ParticleCaloExtensionTool(const std::string& t, const std::string& n, const IInterface*  p )
     : AthAlgTool(t,n,p),
       m_extrapolator("Trk::Extrapolator/AtlasExtrapolator"),
-      m_magFieldSvc("AtlasFieldSvc", n),
-      m_particleType(Trk::muon)
+      m_particleType(muon)
   {
 
     declareInterface<IParticleCaloExtensionTool>(this);
     declareProperty("Extrapolator",   m_extrapolator );
-    declareProperty("MagFieldSvc",    m_magFieldSvc);
     declareProperty("ParticleType",   m_particleTypeName = "muon" );
     declareProperty("OutputContainerName", m_containerName = n );
+    declareProperty("StartFromPerigee", m_startFromPerigee = false);
   }
   
   ParticleCaloExtensionTool::~ParticleCaloExtensionTool() {}
@@ -40,11 +40,10 @@ namespace Trk
     /* Retrieve track extrapolator from ToolService */
     ATH_CHECK(detStore()->retrieve(m_detID, "AtlasID" ));
     ATH_CHECK( m_extrapolator.retrieve() );
-    ATH_CHECK( m_magFieldSvc.retrieve() );
 
-    if( m_particleTypeName == "nonInteracting" ) m_particleType = Trk::nonInteracting;
-    else if( m_particleTypeName == "muon" )      m_particleType = Trk::muon;
-    else if( m_particleTypeName == "pion" )      m_particleType = Trk::pion;
+    if( m_particleTypeName == "nonInteracting" ) m_particleType = nonInteracting;
+    else if( m_particleTypeName == "muon" )      m_particleType = muon;
+    else if( m_particleTypeName == "pion" )      m_particleType = pion;
     else ATH_MSG_WARNING("Unsupported particle type, using muon " << m_particleTypeName );
     ATH_MSG_INFO(" Using particle type " << m_particleTypeName << " enum value " << m_particleType );
     return StatusCode::SUCCESS;
@@ -54,26 +53,132 @@ namespace Trk
     return StatusCode::SUCCESS;
   }
 
-  const xAOD::ParticleCaloExtension* ParticleCaloExtensionTool::caloExtension( xAOD::TrackParticle& trackParticle ) const {
+  const xAOD::TrackParticle* ParticleCaloExtensionTool::getTrackParticle(const xAOD::IParticle& particle ) const {
+
+    const xAOD::TrackParticle* trackParticle = dynamic_cast< const xAOD::TrackParticle*>(&particle);
+    if( trackParticle ) return trackParticle;
+ 
+    const xAOD::Muon* muon = dynamic_cast< const xAOD::Muon*>(&particle);
+    if( muon && muon->primaryTrackParticle() ) return muon->primaryTrackParticle();
+    return nullptr;
+  }
+
+  bool ParticleCaloExtensionTool::caloExtension( const xAOD::IParticle& particle, const Trk::CaloExtension*& extension, 
+                                                 bool useCaching ) const {
     
+    // reset input
+    extension = 0;
+
+    ATH_MSG_DEBUG(" caloExtension: ptr " << &particle << " useCaching " << useCaching);
+
     // check if link is already there
-    if( trackParticle.isAvailable< xAOD::ParticleCaloExtension* >("caloExtension") ){
-      xAOD::ParticleCaloExtension* extension = trackParticle.auxdata< xAOD::ParticleCaloExtension* >("caloExtension");
+    if( useCaching && particle.isAvailable< CaloExtension* >("caloExtension") ){
+      extension = particle.auxdata< CaloExtension* >("caloExtension");
       if( extension ){
         ATH_MSG_DEBUG("Found existing calo extension");
-        return trackParticle.auxdata< xAOD::ParticleCaloExtension* >("caloExtension");
+        return true;
       }
     }
+
+    // work out the type of particle and get the extension
+    CaloExtension* theExtension = 0;
+    const xAOD::TrackParticle* trackParticle = getTrackParticle(particle);
+    if( trackParticle ) theExtension = caloExtension(*trackParticle);
+    else{
+      const xAOD::NeutralParticle* neutralParticle = dynamic_cast< const xAOD::NeutralParticle*>(&particle);
+      if( neutralParticle ) theExtension = caloExtension(*neutralParticle);
+      else{
+        const xAOD::TruthParticle* truthParticle = dynamic_cast< const xAOD::TruthParticle*>(&particle);
+        if( truthParticle ) theExtension = caloExtension(*truthParticle);
+        else{
+          ATH_MSG_WARNING("Unsupported IParticle type");
+          return false;
+        }
+      }
+    }
+
+    // create and assign extension dressing 
+    if( useCaching ) particle.auxdecor< CaloExtension* >("caloExtension") = theExtension;
+    extension = theExtension;
+
+    // return false is extension failed
+    return extension != nullptr;
+  }
+
+  Trk::CaloExtension* ParticleCaloExtensionTool::caloExtension( const xAOD::TruthParticle& particle ) const {
+
+    // get particle type
+    ParticleHypothesis                     particleType = muon; //nonInteracting;
+    if( abs(particle.pdgId()) == 11 )      particleType = muon; // we dont want the electron to loose energy when extrpolating in the calo
+    else if( abs(particle.pdgId()) == 13 ) particleType = muon;
+
+    // get start parameters
+    const xAOD::TruthVertex* pvtx = particle.prodVtx();
+    if ( pvtx == 0 ) return nullptr;
+
+    double charge = particle.charge();
+    Amg::Vector3D  pos( pvtx->x() , pvtx->y() , pvtx->z() );
+    Amg::Vector3D  mom( particle.px() , particle.py() , particle.pz() );
+
+    // hack, extrapolate neutral particles as infinit momentum for the time being
+    if( particle.isNeutral() ){
+      charge = 1.;
+      mom.normalize();
+      mom *= 1e10;
+    }
+    Trk::CurvilinearParameters startPars(pos,mom,charge);
+
+    // get extension
+    return caloExtension( startPars, alongMomentum, particleType );
+  }
+
+  Trk::CaloExtension* ParticleCaloExtensionTool::caloExtension( const xAOD::NeutralParticle& particle ) const {
+
+    // create start parameters
+    const Trk::NeutralPerigee& perigee = particle.perigeeParameters();
     
-    // if not create it
-    xAOD::ParticleCaloExtension*& caloExtension = trackParticle.auxdata< xAOD::ParticleCaloExtension* >("caloExtension");
+    double charge = 1.;
+    Amg::Vector3D  pos( perigee.position() );
+    Amg::Vector3D  mom( perigee.momentum() );
+    // hack, extrapolate neutral particles as infinit momentum for the time being
+    mom.normalize();
+    mom *= 1e10;
+    Trk::CurvilinearParameters startPars(pos,mom,charge);
 
-    // check if there is a track
-    if( !trackParticle.track() ){
-      ATH_MSG_WARNING("No valid track, failing extension" );
-      return 0;
+    // get extension
+    return caloExtension( startPars, alongMomentum, muon );
+  }
+
+  Trk::CaloExtension* ParticleCaloExtensionTool::caloExtension( const xAOD::TrackParticle& particle ) const {
+
+    //Determine if the track was fit electron hypothesis -- so extrapolate as if the particles is non interacting
+    ParticleHypothesis particleType = m_particleType;
+    if( particle.particleHypothesis() ==  xAOD::electron )
+    { 
+      ATH_MSG_DEBUG("Fitting using electron hypothesis");
+      particleType = muon;//nonInteracting;
+      
+      if(!m_startFromPerigee){
+        unsigned int index(0);
+        if (!particle.indexOfParameterAtPosition(index, xAOD::LastMeasurement))        {    
+          ATH_MSG_WARNING("No TrackParticle or no have first measurement");
+        } else {
+          return caloExtension(particle.curvilinearParameters(index),alongMomentum,particleType);
+        }
+      }
+    }
+
+    if(m_startFromPerigee || !particle.track())
+    {
+      bool idExit = true;
+// Muon Entry is around z 6783 and r  4255 
+      if(fabs(particle.perigeeParameters().position().z())>6700.) idExit = false; 
+      if(particle.perigeeParameters().position().perp()>4200.) idExit = false; 
+      PropDirection propDir = idExit ? alongMomentum : oppositeMomentum;
+      return caloExtension(particle.perigeeParameters(),propDir,particleType);
     }
-    const Trk::Track& track = *trackParticle.track();
+  
+    const Track& track = *particle.track();
 
     // look-up the parameters closest to the calorimeter in ID and muon system
     ATH_MSG_DEBUG("trying to add calo layers" );
@@ -90,83 +195,101 @@ namespace Trk
       
     // require at least one of them
     if( !idExitParamers && !muonEntryParamers) {
-      ATH_MSG_WARNING("Failed to find ID and Muon parameters");
-      return 0;
+      idExitParamers = track.perigeeParameters();
     }
 
     // pick start parameters, start in ID if possible
     const TrackParameters* startPars = idExitParamers ? idExitParamers : muonEntryParamers;
+    if( !startPars ){
+      ATH_MSG_WARNING("Failed to find  start parameters");
+      return nullptr;
+    }
     PropDirection propDir = idExitParamers ? alongMomentum : oppositeMomentum;
+    
+    return caloExtension(*startPars,propDir,particleType);
+  }
+
 
-    ATH_MSG_DEBUG("looking up calo states: r " << startPars->position().perp() << " z " << startPars->position().z()
-                  << " momentum " << startPars->momentum().mag() );
+  Trk::CaloExtension* ParticleCaloExtensionTool::caloExtension( const TrackParameters& startPars, PropDirection propDir, 
+                                                                ParticleHypothesis particleType ) const {
+
+    ATH_MSG_DEBUG("looking up calo states: r " << startPars.position().perp() << " z " << startPars.position().z()
+                  << " momentum " << startPars.momentum().mag() );
 
     // pointers to hold results and go
-    std::vector<const TrackStateOnSurface*>* material = 0;
-    const std::vector< std::pair< const TrackParameters*, int > >* caloParameters = 
-      m_extrapolator->extrapolate( *startPars, propDir, m_particleType, material, 3 ); 
-    if( !caloParameters ) return 0;
+    std::vector<const TrackStateOnSurface*>* material = 0;//new std::vector<const TrackStateOnSurface*>();
+    const auto* caloParameters = m_extrapolator->extrapolate( startPars, propDir, particleType, material, 3 ); 
+    if( material ) {
+      ATH_MSG_DEBUG("Got material " << material->size() );
+      for( auto& m : *material ) {
+        if( msgLvl(MSG::DEBUG) ){
+          msg(MSG::DEBUG) << " layer ";
+          const TrackParameters* param = m->trackParameters();
+          if( param ) msg(MSG::DEBUG) << " param " << param << " pos: r " << param->position().perp() << " z " << param->position().z() 
+                                      << " pt " << param->momentum().perp();
+          const Trk::MaterialEffectsBase* mat = m->materialEffectsOnTrack();
+          if( mat ) msg(MSG::DEBUG) << " mat: " <<  mat->thicknessInX0();
+          msg(MSG::DEBUG) << endreq;
+        }
+        delete m;
+      }
+      delete material;
+    }
+    if( !caloParameters ) return nullptr;
+    TrackParametersIdHelper  parsIdHelper;
 
     // create final object
-    std::vector< std::vector<float> > parameters;
-    std::vector< std::vector<float> > parametersCovariance;
-    std::vector< int >       identifiers;
-    parameters.reserve(caloParameters->size());
-    parametersCovariance.reserve(caloParameters->size());
+    const TrackParameters* caloEntry = 0;
+    const TrackParameters* muonEntry = 0;
+    std::vector<const CurvilinearParameters*> caloLayers;
+    caloLayers.reserve(caloParameters->size()-1);
     ATH_MSG_DEBUG( " Found calo parameters: " << caloParameters->size() );
     for( const auto& p : *caloParameters ){
 
-      const Trk::TrackParameters* param = p.first;
+      const TrackParameters* param = p.first;
       if( !param ) continue;
-      ATH_MSG_DEBUG( " id " << p.second << " pos: r " << param->position().perp() << " z " << param->position().z() 
-                     << " momentum " << param->momentum().perp() << " cov " << param->covariance() );
-
-      std::vector<float> pars(6);
-      pars[0] = param->position().x();
-      pars[1] = param->position().y();
-      pars[2] = param->position().z();
-      pars[3] = param->momentum().x();
-      pars[4] = param->momentum().y();
-      pars[5] = param->momentum().z();
-      parameters.push_back(pars);
-      identifiers.push_back(p.second);
-
-      std::vector<float> covVec;
-      if( param->covariance() ){
-        //now convert from to Curvilinear -- to be double checked for correctness
-        Amg::Vector3D magnFieldVect; magnFieldVect.setZero();
-        m_magFieldSvc->getField( &param->position(), &magnFieldVect );
-
-        Trk::CurvilinearUVT curvilinearUVT(param->momentum());     
-        const Amg::Transform3D& localToGlobalTransform = param->associatedSurface().transform();
-     
-        Trk::JacobianLocalToCurvilinear jacobian(magnFieldVect,
-                                                 param->parameters()[Trk::qOverP],
-                                                 sin(param->parameters()[Trk::theta]),
-                                                 curvilinearUVT,
-                                                 localToGlobalTransform.rotation().col(0),
-                                                 localToGlobalTransform.rotation().col(1));     
-     
-        AmgSymMatrix(5) covarianceMatrix = param->covariance()->similarity(jacobian);
-        Amg::compress(covarianceMatrix,covVec);
-      }
-      parametersCovariance.push_back(covVec);
-      delete param;
+      ATH_MSG_DEBUG( " param " << param << " id " << p.second /*<< " type " << p.first->type()*/ << " pos: r " << param->position().perp() << " z " << param->position().z() 
+                     << " pt " << param->momentum().perp() << " cov " << param->covariance() );
+      
+      // assign parameters
+      if( p.second == 1 && propDir == Trk::alongMomentum)         caloEntry = p.first;
+      else if( p.second == 3 && propDir == Trk::oppositeMomentum) caloEntry = p.first;
+      else if( p.second == 3 && propDir == Trk::alongMomentum)    muonEntry = p.first;
+      else if( p.second == 4 && propDir == Trk::oppositeMomentum) muonEntry = p.first;
+      else{
+        bool isEntry = p.second > 0 ? true : false;
+        TrackParametersIdentifier id = parsIdHelper.encode( AtlasDetDescr::fFirstAtlasCaloTechnology, 
+                                                            static_cast<CaloSampling::CaloSample>( abs(p.second)%1000 ),
+                                                            isEntry );
+        const CurvilinearParameters* cpars = dynamic_cast<const CurvilinearParameters*>(p.first);
+        if( !cpars ){ /*p.first->type() == Curvilinear*/
+          cpars = new CurvilinearParameters(p.first->position(),p.first->momentum(),p.first->charge(),nullptr,id);
+          delete p.first;
+        }else{
+          const_cast<CurvilinearParameters*>(cpars)->m_cIdentifier = id;
+        }
+        caloLayers.push_back( cpars );
+      }      
+    }
+
+    if(!muonEntry && propDir == Trk::oppositeMomentum && fabs(startPars.position().perp()-4255.)<1.) {
+// muonEntry is right at the startPars position
+      muonEntry = &startPars;
+    } 
+
+    if( muonEntry ) {
+       if( muonEntry->covariance() ) { 
+       ATH_MSG_VERBOSE (" p at MuonEntry " << muonEntry->momentum().mag() << " cov 00 " << (*(muonEntry->covariance()))(0,0) << " cov 11 " << (*(muonEntry->covariance()))(1,1));
+       }
     }
-    
     // clean-up memory
     delete caloParameters;
-    if( material ) {
-      for( auto& m : *material ) delete m;
-      delete material;
-    }
-    caloExtension = new xAOD::ParticleCaloExtension(trackParticle.charge(),std::move(parameters),
-                                                    std::move(parametersCovariance),std::move(identifiers));
+    CaloExtension* theExtension = new CaloExtension(caloEntry,muonEntry,std::move(caloLayers));
 
     // now add the extension to the output collection so we are not causing any leaks
-    ParticleCaloExtensionCollection* collection = 0;
-    if( !evtStore()->contains<ParticleCaloExtensionCollection>(m_containerName) ){
-      collection = new ParticleCaloExtensionCollection();
+    CaloExtensionCollection* collection = 0;
+    if( !evtStore()->contains<CaloExtensionCollection>(m_containerName) ){
+      collection = new CaloExtensionCollection();
       if( evtStore()->record( collection, m_containerName).isFailure() ) {
         ATH_MSG_WARNING( "Failed to record output collection, will leak the ParticleCaloExtension");
         delete collection;
@@ -175,12 +298,17 @@ namespace Trk
     }else{
       if(evtStore()->retrieve(collection,m_containerName).isFailure()) {
         ATH_MSG_WARNING( "Unable to retrieve " << m_containerName << " will leak the ParticleCaloExtension" );
+        collection = 0;
       }
     }
-    if( collection ) collection->push_back(caloExtension);
-
-    return caloExtension;
+    if( collection ) collection->push_back(theExtension);
+    else{
+      ATH_MSG_WARNING( "No CaloExtension Collection, failing extension to avoid memory leak");
+      delete theExtension;
+      theExtension = 0;
+    }
+    return theExtension;
   }
-
-  
 } // end of namespace Trk
+
+
diff --git a/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloExtensionTool.h b/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloExtensionTool.h
index 7f45eaae5037b7292b9fd49886075755935db5e1..411ee8869eec456b6b0944047ef4995574b52984 100644
--- a/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloExtensionTool.h
+++ b/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloExtensionTool.h
@@ -11,26 +11,26 @@ authors : Niels van Eldik (CERN PH-ATC)
 #ifndef TRKPARTICLECREATOR_PARTICLECALOEXTENSIONTOOL_H
 #define TRKPARTICLECREATOR_PARTICLECALOEXTENSIONTOOL_H
 
-#include "RecoToolInterfaces/IParticleCaloExtensionTool.h"
+
 #include "AthenaBaseComps/AthAlgTool.h"
 #include "GaudiKernel/ToolHandle.h"
 #include "GaudiKernel/ServiceHandle.h"
 
+#define private public
+#include "RecoToolInterfaces/IParticleCaloExtensionTool.h"
 #include "xAODTracking/TrackParticle.h"
-#include "xAODTracking/ParticleCaloExtension.h"
+#define public private
 #include "TrkEventPrimitives/ParticleHypothesis.h" 
+#include "xAODTracking/NeutralParticle.h"
+#include "xAODTruth/TruthParticle.h"
 
 class AtlasDetectorID;
 
-namespace MagField 
-{
-  class IMagFieldSvc;
-}
-
 
 namespace Trk {
   
   class IExtrapolator;
+  class CaloExtension;
 
   class ParticleCaloExtensionTool : virtual public IParticleCaloExtensionTool, public AthAlgTool {
   public:
@@ -42,20 +42,33 @@ namespace Trk {
     virtual StatusCode initialize();
     virtual StatusCode finalize();
 
-    /** Method to dress a TrackParticle with the calo layers crossed by its track
-        @param trackParticle 
-        @return ParticleCaloExtension, caller does not obtain ownership of the pointer and should not delete it
+    /** Method to dress a IParticle with the calo layers crossed by its track
+        @param IParticle     reference to the particle
+        @param extension     reference to a pointer to a CaloExtesion, will be updated if call is successfull
+                             NEVER delete the pointer, you will cause a crash! 
+        @param useCaching    configure whether the tool caches the result on the track particle
+                             The default behavior is 'true' to ensure optimal performance
+        @return true if the call was successful
     */
-    const xAOD::ParticleCaloExtension* caloExtension( xAOD::TrackParticle& trackParticle ) const;
-
+    bool caloExtension( const xAOD::IParticle& particle, const Trk::CaloExtension*& extension, bool useCaching = true  ) const final;
+    Trk::CaloExtension* caloExtension( const TrackParameters& startPars, PropDirection propDir, ParticleHypothesis particleType ) const;
   private:
+    
+    const xAOD::TrackParticle* getTrackParticle(const xAOD::IParticle& particle ) const;
+
+    Trk::CaloExtension* caloExtension( const xAOD::TruthParticle& particle ) const;
+    Trk::CaloExtension* caloExtension( const xAOD::NeutralParticle& particle ) const;
+    Trk::CaloExtension* caloExtension( const xAOD::TrackParticle& particle ) const;
+    
+
+
+
     const AtlasDetectorID*       m_detID;
     ToolHandle< IExtrapolator >  m_extrapolator;
-    ServiceHandle<MagField::IMagFieldSvc>  m_magFieldSvc;
-
-    Trk::ParticleHypothesis      m_particleType;
-    std::string                  m_particleTypeName;
-    std::string                  m_containerName;
+    ParticleHypothesis      m_particleType;
+    std::string             m_particleTypeName;
+    std::string             m_containerName;
+    bool                    m_startFromPerigee;
   };
 }
 
diff --git a/Reconstruction/RecoTools/TrackToCalo/src/PathLengthUtils.cxx b/Reconstruction/RecoTools/TrackToCalo/src/PathLengthUtils.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..473be9d53b604ae8c58ec231a4bdbdf97db75c38
--- /dev/null
+++ b/Reconstruction/RecoTools/TrackToCalo/src/PathLengthUtils.cxx
@@ -0,0 +1,782 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "PathLengthUtils.h"
+#include "CaloGeoHelpers/CaloSampling.h"
+#include <iostream>
+
+//=================================
+PathLengthUtils::PathLengthUtils(){
+//=================================
+
+}
+
+//==================================
+PathLengthUtils::~PathLengthUtils(){
+//==================================
+ 
+}
+
+//=========================================================================================================================
+double PathLengthUtils::get3DPathLength(const CaloCell& cell, const Amg::Vector3D& entrance, const Amg::Vector3D& exit, double drFix, double dzFix){
+//=========================================================================================================================
+
+    int debugLevel = 0;
+
+    if(debugLevel>=1)  std::cout << std::endl; 
+
+    double dmin = 10.;
+    double dphimin = dmin/cell.caloDDE()->r();
+
+// Get cell parameters 
+
+    double dphi = cell.caloDDE()->dphi();
+    if(dphi<dphimin) dphi = dphimin;
+    double CellPhimin = cell.caloDDE()->phi()-dphi*0.5;
+    double CellPhimax = cell.caloDDE()->phi()+dphi*0.5;
+
+// Order according to IP to follow track convention with entry and exit planes
+
+    int isign = 1;
+    if(cell.caloDDE()->z()<0) isign = -1;
+    double dr = cell.caloDDE()->dr();
+//
+// always use fixed values that correspond to the Calorimeter Tracking Geometry
+// these are different from the CaloCell values
+//
+    if(dr==0) dr = drFix;
+    dr = drFix;
+    if(dr<dmin) dr = dmin;
+    double dz = cell.caloDDE()->dz();
+    if(dz==0) dz = dzFix;
+    dz = dzFix;
+    if(dz<dmin) dz = dmin;
+
+    double CellZmin = cell.caloDDE()->z()-isign*dz*0.5;
+    double CellZmax = cell.caloDDE()->z()+isign*dz*0.5;
+    double CellRmin = cell.caloDDE()->r()-dr*0.5;
+    double CellRmax = cell.caloDDE()->r()+dr*0.5;
+
+// fix cells with zero R or Z width 
+
+//    if(cell.caloDDE()->dr() == 0){
+//        // V = dr*dphi*r*dz
+//        double CellVolume = cell.caloDDE()->volume();
+//        double product = cell.caloDDE()->dphi() * cell.caloDDE()->r() * cell.caloDDE()->dz();
+//        double drFormula = dmin;
+//        if(product!=0){
+//            drFormula = CellVolume / product;
+//        } 
+//        if(drFormula<dmin) drFormula = dmin;
+//        CellRmin = cell.caloDDE()->r() - drFormula*0.5;
+//        CellRmax = cell.caloDDE()->r() + drFormula*0.5;
+//        dr = drFormula;
+//        if(debugLevel>=2) std::cout << "drFormula " << drFormula << " new CellRmin " << CellRmin << " new CellRmax " << CellRmax << std::endl;
+//    } 
+
+//    if(cell.caloDDE()->dz() == 0){ 
+//        // V = dr*dphi*r*dz
+//        double CellVolume = cell.caloDDE()->volume();
+//        double product = cell.caloDDE()->dphi() * cell.caloDDE()->r() * cell.caloDDE()->dr();
+//        double dzFormula = dmin;
+//        if(product!=0){
+//            dzFormula = CellVolume / product;
+//        } 
+//        if(dzFormula<dmin) dzFormula = dmin;
+//        CellZmin = cell.caloDDE()->z() - isign*dzFormula*0.5;
+//        CellZmax = cell.caloDDE()->z() + isign*dzFormula*0.5;
+//        dz = dzFormula;
+//        if(debugLevel>=2) std::cout << "dzFormula " << dzFormula << " new CellZmin " << CellZmin << " new CellZmax " << CellZmax << std::endl;
+//    } 
+//
+// For CPU reason do a fast check on crossing 
+//
+// track direction 
+//
+    Amg::Vector3D dir = exit - entrance; 
+    if(dir.mag()==0) return 0.;
+    dir = dir/dir.mag();
+//
+// point of closest approach in x,y 
+//
+    double r0 = (entrance.x()-cell.caloDDE()->x())*sin(dir.phi()) - (entrance.y()-cell.caloDDE()->y())*cos(dir.phi()); 
+    bool crossing = true;
+    if(fabs(r0)>sqrt(cell.caloDDE()->r()*cell.caloDDE()->r()*dphi*dphi + dr*dr)) crossing = false;
+//
+// point of closest approach in r,z 
+//
+    double rz0 = (entrance.perp()-cell.caloDDE()->r())*cos(dir.theta()) - (entrance.z()-cell.caloDDE()->z())*sin(dir.theta()); 
+    if(fabs(rz0)>sqrt(dr*dr+dz*dz)) crossing = false;
+
+    if(debugLevel>=2&&crossing) {
+      std::cout << " get3DPathMatch distance xy " << r0 << " distance rz " << rz0 << std::endl;
+      std::cout << std::endl;  
+    } 
+
+    if(!crossing) return 0.;
+
+// construct 8 corners of the volume
+  
+    Amg::Vector3D Corner0(CellRmin*cos(CellPhimin),CellRmin*sin(CellPhimin),CellZmin);
+    Amg::Vector3D Corner1(CellRmin*cos(CellPhimax),CellRmin*sin(CellPhimax),CellZmin);
+    Amg::Vector3D Corner2(CellRmin*cos(CellPhimin),CellRmin*sin(CellPhimin),CellZmax);
+    Amg::Vector3D Corner3(CellRmin*cos(CellPhimax),CellRmin*sin(CellPhimax),CellZmax);
+
+    Amg::Vector3D Corner4(CellRmax*cos(CellPhimin),CellRmax*sin(CellPhimin),CellZmin);
+    Amg::Vector3D Corner5(CellRmax*cos(CellPhimax),CellRmax*sin(CellPhimax),CellZmin);
+    Amg::Vector3D Corner6(CellRmax*cos(CellPhimin),CellRmax*sin(CellPhimin),CellZmax);
+    Amg::Vector3D Corner7(CellRmax*cos(CellPhimax),CellRmax*sin(CellPhimax),CellZmax);
+
+    if(debugLevel>=1) {
+      double volume_ratio = cell.caloDDE()->dr()*cell.caloDDE()->r()*cell.caloDDE()->dphi()*cell.caloDDE()->dz() /(cell.caloDDE()->volume() + 1.) ; 
+      std::cout << " sampling " << cell.caloDDE()->getSampling() << " CellPhimin " << CellPhimin << " CellPhimax " << CellPhimax << " CellZmin " << CellZmin << " CellZmax " << CellZmax << " CellRmin " << CellRmin << " CellRmax " <<  CellRmax << " cell.caloDDE()->dz() " << cell.caloDDE()->dz() << " cell.caloDDE()->dr() " << cell.caloDDE()->dr() << " cell.caloDDE()->dx() " << cell.caloDDE()->dx() << " cell.caloDDE()->dy() " << cell.caloDDE()->dy() << " volume_ratio " << volume_ratio << std::endl;
+    }
+    if(debugLevel>=2) {
+      std::cout << " Corner0 x " << Corner0.x() << " y " << Corner0.y() << " z " << Corner0.z() << std::endl;
+      std::cout << " Corner1 x " << Corner1.x() << " y " << Corner1.y() << " z " << Corner1.z() << std::endl;
+      std::cout << " Corner2 x " << Corner2.x() << " y " << Corner2.y() << " z " << Corner2.z() << std::endl;
+      std::cout << " Corner3 x " << Corner3.x() << " y " << Corner3.y() << " z " << Corner3.z() << std::endl;
+      std::cout << " Corner4 x " << Corner4.x() << " y " << Corner4.y() << " z " << Corner4.z() << std::endl;
+      std::cout << " Corner5 x " << Corner5.x() << " y " << Corner5.y() << " z " << Corner5.z() << std::endl;
+      std::cout << " Corner6 x " << Corner6.x() << " y " << Corner6.y() << " z " << Corner6.z() << std::endl;
+      std::cout << " Corner7 x " << Corner7.x() << " y " << Corner7.y() << " z " << Corner7.z() << std::endl;
+    } 
+
+// Entry plane vectors through Corner0
+
+    Amg::Vector3D dir01 = Corner1 - Corner0;   // direction along Phi
+    Amg::Vector3D dir02 = Corner2 - Corner0;   // direction along Z
+// Second (side) plane through Corner0 has dir20 and dir40
+    Amg::Vector3D dir04 = Corner4 - Corner0;   // direction along R
+// Third plane through Corner0 has dir10 and dir40
+   
+    
+// Exit plane vectors through Corner6
+
+    Amg::Vector3D dir67 = Corner7 - Corner6;  // direction along Phi
+    Amg::Vector3D dir64 = Corner4 - Corner6;  // direction along Z
+// Second (side) plane through Corner dir62 and dir64
+    Amg::Vector3D dir62 = Corner2 - Corner6;  // direction along R
+// Third plane through Corner dir67 and dir62
+
+// minus direction of track
+    Amg::Vector3D dirT = exit - entrance; 
+    dirT = -dirT;
+
+// check positions
+
+   if(debugLevel>=2) {
+     if(entrance.perp()>Corner0.perp()) {
+       std::cout << " PROBLEM radius entrance larger than cell corner " << std::endl;
+     } 
+     if(entrance.mag()>Corner0.mag()||fabs(exit.z())<fabs(Corner0.z())) {
+       std::cout << " PROBLEM 3D or z distance to IP entrance larger than cell corner " << std::endl;
+     } 
+ 
+     if(exit.perp()<Corner6.perp()) {
+       std::cout << " PROBLEM radius exit small than cell corner " << std::endl;
+     } 
+     if(entrance.mag()>Corner6.mag()||fabs(exit.z())<fabs(Corner6.z())) {
+       std::cout << " PROBLEM 3D or Z distance to IP exit smaller than cell corner " << std::endl;
+     } 
+   } 
+
+// dot products of track with plane vectors 
+
+    if(debugLevel>=2) { 
+      std::cout << " dir01 " << dir01.x() << " y " << dir01.y() << " z " << dir01.z() << " mag " << dir01.mag() << std::endl;
+      std::cout << " dir02 " << dir02.x() << " y " << dir02.y() << " z " << dir02.z() << " mag " << dir02.mag() << std::endl;
+      std::cout << " dir04 " << dir04.x() << " y " << dir04.y() << " z " << dir04.z() << " mag " << dir04.mag() << std::endl;
+    }
+
+    double dotp1 = fabs(dirT.dot(dir01)/dir01.mag()/dirT.mag());
+    double dotp2=  fabs(dirT.dot(dir02)/dir02.mag()/dirT.mag());
+    double dotp4 = fabs(dirT.dot(dir04)/dir04.mag()/dirT.mag());
+//
+// order planes according to dotproduct and calculate Matrices 
+//        mEntry matrix 
+//               column(0) vector for first plane  e.g. dir01
+//               column(1) second vector for first plane e.g. dir02
+//               column(2) = minus track direction 
+//               type = 124 here plane made by 1 and 2  = dir01 and dir02 
+//                          later also plane made by 14 = dir01 and dir04 can be tried (second try)
+//                          or                       24 = dir02 and dir04 (third try)     
+//
+    Amg::MatrixX mEntry(3,3);
+    mEntry.col(2) = dirT;
+    Amg::MatrixX mExit(3,3);
+    mExit.col(2) = dirT;
+
+    int type = 0;
+    double dotmax = 0.;
+    if(dotp1<=dotp2&&dotp2<=dotp4) {
+      type = 124;
+      dotmax = dotp4;
+      mEntry.col(0) = dir01;          
+      mEntry.col(1) = dir02;          
+      mExit.col(0) = dir67;          
+      mExit.col(1) = dir64;          
+    } else if (dotp1<=dotp4&&dotp4<=dotp2) {
+      type = 142;
+      dotmax = dotp2;
+      mEntry.col(0) = dir01;          
+      mEntry.col(1) = dir04;          
+      mExit.col(0) = dir67;          
+      mExit.col(1) = dir62;          
+    } else if (dotp2<=dotp1&&dotp1<=dotp4) {
+      type = 214;
+      dotmax = dotp4;
+      mEntry.col(0) = dir02;          
+      mEntry.col(1) = dir01;          
+      mExit.col(0) = dir64;          
+      mExit.col(1) = dir67;          
+    } else if (dotp2<=dotp4&&dotp4<=dotp1) {
+      type = 241;
+      dotmax = dotp1;
+      mEntry.col(0) = dir02;          
+      mEntry.col(1) = dir04;          
+      mExit.col(0) = dir64;          
+      mExit.col(1) = dir62;          
+    } else if (dotp4<=dotp2&&dotp2<=dotp1) {
+      type = 421;
+      dotmax = dotp1;
+      mEntry.col(0) = dir04;          
+      mEntry.col(1) = dir02;          
+      mExit.col(0) = dir62;          
+      mExit.col(1) = dir64;          
+    } else if (dotp4<=dotp1&&dotp1<=dotp2) {
+      type = 412;
+      dotmax = dotp2;
+      mEntry.col(0) = dir04;          
+      mEntry.col(1) = dir01;          
+      mExit.col(0) = dir62;          
+      mExit.col(1) = dir67;          
+    }
+
+// position of track w.r.t. all planes 
+
+    Amg::Vector3D posEn = entrance-(Corner1+Corner2+Corner4)/2.;
+    Amg::Vector3D posEx = entrance-(Corner2+Corner4+Corner7)/2.;
+//
+// put posEn en posEx in the middle of the plane
+//
+//  this makes it possible to check that the Matrix solution lies within the bounds 
+//              |x|<0.5 and |y|<0.5  
+//          x corresponds to the first  column(0) e.g. dir01
+//          y corresponds to the second column(1) e.g. dir02
+//
+    int type0 = type-10*int(type/10);
+    if(type0==1) { 
+// last plane 1 not used 
+      posEn += Corner1/2.;
+      posEx += Corner7/2.;
+    }
+    if(type0==2) { 
+// last plane 2 not used 
+      posEn += Corner2/2.;
+      posEx += Corner4/2.;
+    }
+    if(type0==4) { 
+// last plane 4 not used 
+      posEn += Corner4/2.;
+      posEx += Corner2/2.;
+    }
+
+    if(debugLevel>=2) {
+      std::cout << " not normalized direction track " << dirT.x() << " y " << dirT.y() << " z "  << dirT.z() << " eta " << dirT.eta() << " type " << type << " dotmax " << dotmax << std::endl;
+      std::cout << " dotp1 " << dotp1 <<  " dotp2 " << dotp2 <<  " dotp4 " << dotp4 << std::endl;
+      std::cout << " entry position " << entrance.x() << " y " << entrance.y() << " z " << entrance.z() << std::endl;
+      std::cout << " mEntry Matrix " << std::endl;
+      std::cout << mEntry << std::endl;
+      std::cout << " exit position " << exit.x() << " y " << exit.y() << " z " << exit.z() << std::endl;
+      std::cout << " mExit Matrix " << std::endl;
+      std::cout << mExit << std::endl;
+    }
+
+// cross with entry plane
+    int typeCheck = type0; 
+
+    Amg::Vector3D pathEn;
+    if(debugLevel>=2) std::cout << " Try crossing Entry first try for type " << type << std::endl;
+    bool crossingEn = crossingMatrix(mEntry,posEn,pathEn);
+// if dotmax near to 1 Matrix is singular (track is parallel to the plane)
+    if(debugLevel>=2&&crossingEn) std::cout << " Succesfull crossing Entry first try for type " << type << " type 0 " << type0 << std::endl;
+    if(!crossingEn) {
+      int type1 = int((type-100*int(type/100))/10);
+      int type2 = int(type/100);
+      if(type1==1) posEn += Corner1/2.;
+      if(type1==2) posEn += Corner2/2.;
+      if(type1==4) posEn += Corner4/2.;
+      if(type0==1) {
+        mEntry.col(1) = dir01;          
+        posEn -= Corner1/2.;
+      }  
+      if(type0==2) {
+        mEntry.col(1) = dir02;          
+        posEn -= Corner2/2.;
+      }  
+      if(type0==4) {
+        mEntry.col(1) = dir04;          
+        posEn -= Corner4/2.;
+      }  
+      if(debugLevel>=2) std::cout << " Try crossing Entry second try for type " << type << std::endl;
+      crossingEn = crossingMatrix(mEntry,posEn,pathEn);
+      typeCheck = type1; 
+      if(debugLevel>=2&&crossingEn) std::cout << " Succesfull crossing Entry second try for type " <<type  << std::endl;
+      if(!crossingEn) {
+        if(type2==1) posEn += Corner1/2.;
+        if(type2==2) posEn += Corner2/2.;
+        if(type2==4) posEn += Corner4/2.;
+        if(type1==1) {
+          mEntry.col(0) = dir01;          
+          posEn -= Corner1/2.;
+        }  
+        if(type1==2) {
+          mEntry.col(0) = dir02;          
+          posEn -= Corner2/2.;
+        }  
+        if(type1==4) {
+          mEntry.col(0) = dir04;          
+          posEn -= Corner4/2.;
+        }  
+        if(debugLevel>=2) std::cout << " Try crossing Entry third try for type " << type << std::endl;
+        crossingEn = crossingMatrix(mEntry,posEn,pathEn);
+        typeCheck = type2; 
+        if(debugLevel>=2&&crossingEn) std::cout << " Succesfull crossing Entry third try for type " << type << std::endl;
+        if(debugLevel>=2&&!crossingEn) std::cout << " No crossing Entry third try for type " << type << std::endl;
+      } 
+    }
+  
+    Amg::Vector3D posXEn = entrance;
+    if(crossingEn) {
+      posXEn = entrance - dirT*pathEn.z(); 
+      if(typeCheck==1) {
+        double dphiCheck = acos(cos(posXEn.phi())*cos((CellPhimax+CellPhimin)/2.)+sin(posXEn.phi())*sin((CellPhimax+CellPhimin)/2.));
+        if(dphiCheck>fabs(CellPhimax-CellPhimin)) {
+           crossingEn = false;
+        } 
+        if(debugLevel>=1&&!crossingEn) std::cout << " check crossing in phi " << crossingEn << " dphiCheck " << dphiCheck << " CellPhimin " << CellPhimin << " CellPhimax " << CellPhimax  << " position crossing phi " << posXEn.phi() << std::endl; 
+      }
+      if(typeCheck==2) {
+        if(posXEn.perp()<CellRmin) crossingEn = false;
+        if(posXEn.perp()>CellRmax) crossingEn = false;
+        if(debugLevel>=1&&!crossingEn) std::cout << " check crossing in R " << crossingEn << " CellRmin " << CellRmin << " CellRmax " << CellRmax  << " position crossing R " << posXEn.perp() << std::endl; 
+      }
+      if(typeCheck==4) {
+        if(isign*posXEn.z()<isign*CellZmin) crossingEn = false;
+        if(isign*posXEn.z()>isign*CellZmax) crossingEn = false;
+        if(debugLevel>=1&&!crossingEn) std::cout << " check crossing in Z " << crossingEn << " CellZmin " << CellZmin << " CellZmax " << CellZmax  << " position crossing Z " << posXEn.z() << std::endl; 
+      }
+    }
+
+     
+
+    if(debugLevel>=2) {
+      std::cout << " Entry pathE solution " << pathEn.x() << " y " << pathEn.y() << " z " << pathEn.z()  << " crossing " << crossingEn << std::endl;
+      std::cout << " crossing entrance plane with bounds " << posXEn.x() << " y " << posXEn.y() << " z " << posXEn.z() << std::endl;
+      Amg::Vector3D check = entrance - dirT*pathEn.z();
+      std::cout << " crossing entrance plane check " << check.x() << " y " << check.y() << " z " << check.z() << std::endl;
+    }
+
+    if(!crossingEn) return 0.;
+
+
+// cross with exit plane 
+
+    Amg::Vector3D pathEx;
+   if(debugLevel>=2) std::cout << " Try crossing Exit first try for type " << type << std::endl;
+    bool crossingEx = crossingMatrix(mExit,posEx,pathEx);
+    if(debugLevel>=2&&crossingEx) std::cout << " Succesfull crossing Exit first try for type " << type << " type0 " << std::endl;
+    typeCheck = type0; 
+    if(!crossingEx) {
+      int type1 = int((type-100*int(type/100))/10);
+      int type2 = int(type/100);
+      if(type1==1) posEx += Corner7/2.;
+      if(type1==2) posEx += Corner4/2.;
+      if(type1==4) posEx += Corner2/2.;
+      if(type0==1) {
+        mExit.col(1) = dir67;          
+        posEx -= Corner7/2.;
+      }  
+      if(type0==2) {
+        mExit.col(1) = dir64;          
+        posEx -= Corner4/2.;
+      }  
+      if(type0==4) {
+        mExit.col(1) = dir62;          
+        posEx -= Corner2/2.;
+      }  
+      if(debugLevel>=2) std::cout << " Try crossing Exit second try for type " << type << std::endl;
+      crossingEx = crossingMatrix(mExit,posEx,pathEx);
+      typeCheck = type1;
+      if(debugLevel>=2&&crossingEx) std::cout << " Succesfull crossing Exit second try for type " << type  << std::endl;
+      if(!crossingEx) {
+        if(type2==1) posEx += Corner7/2.;
+        if(type2==2) posEx += Corner4/2.;
+        if(type2==4) posEx += Corner2/2.;
+        if(type1==1) {
+          mExit.col(0) = dir67;          
+          posEx -= Corner7/2.;
+        }  
+        if(type1==2) {
+          mExit.col(0) = dir64;          
+          posEx -= Corner4/2.;
+        }  
+        if(type1==4) {
+          mExit.col(0) = dir62;          
+          posEx -= Corner2/2.;
+        }  
+        if(debugLevel>=2) std::cout << " Try crossing Exit third try for type " << type << std::endl;
+        crossingEx = crossingMatrix(mExit,posEx,pathEx);
+        typeCheck = type2;
+        if(debugLevel>=2&&crossingEx) std::cout << " Succesfull crossing Exit third try for type " << type << std::endl;
+      } 
+    }
+   
+    Amg::Vector3D posXEx = posXEn;
+    if(crossingEx) {
+      posXEx = entrance - dirT*pathEx.z(); 
+      if(typeCheck==1) {
+        double dphiCheck = acos(cos(posXEx.phi())*cos((CellPhimax+CellPhimin)/2.)+sin(posXEx.phi())*sin((CellPhimax+CellPhimin)/2.));
+        if(dphiCheck>fabs(CellPhimax-CellPhimin)) {
+           crossingEx = false;
+        } 
+        if(debugLevel>=1&&!crossingEx) std::cout << " check crossing in phi " << crossingEx << " dphiCheck " << dphiCheck << " CellPhimin " << CellPhimin << " CellPhimax " << CellPhimax  << " position crossing phi " << posXEx.phi() << std::endl; 
+      }
+      if(typeCheck==2) {
+        if(posXEx.perp()<CellRmin) crossingEx = false;
+        if(posXEx.perp()>CellRmax) crossingEx = false;
+        if(debugLevel>=1&&!crossingEx) std::cout << " check crossing in R " << crossingEx << " CellRmin " << CellRmin << " CellRmax " << CellRmax  << " position crossing R " << posXEx.perp() << std::endl; 
+      }
+      if(typeCheck==4) {
+        if(isign*posXEx.z()<isign*CellZmin) crossingEx = false;
+        if(isign*posXEx.z()>isign*CellZmax) crossingEx = false;
+        if(debugLevel>=1&&!crossingEx) std::cout << " check crossing in Z " << crossingEx << " CellZmin " << CellZmin << " CellZmax " << CellZmax  << " position crossing Z " << posXEx.z() << std::endl; 
+      }
+    }
+
+    if(debugLevel>=2) {
+      std::cout << " Exit pathEx solution " << pathEx.x() << " y " <<  pathEx.y() << " z " <<  pathEx.z()  << " crossing " << crossingEx << std::endl;
+      std::cout << " crossing exit plane with bounds " << posXEx.x() << " y " << posXEx.y() << " z " << posXEx.z() << std::endl;
+      Amg::Vector3D check = entrance - dirT*pathEx.z();
+      std::cout << " crossing exit plane check " << check.x() << " y " << check.y() << " z " << check.z() << std::endl;
+    }
+
+    double pathT = (entrance-exit).mag();
+    double path = 0.;
+    if(crossingEn&&crossingEx) {
+      path = (posXEx-posXEn).mag();
+      if(debugLevel>=1) {
+        std::cout << std::endl;
+        std::cout << " pathT " << pathT  << " path " << path << std::endl;
+        std::cout << " entrance position                   " << entrance.x() << " y " << entrance.y() << " z " << entrance.z() << std::endl;
+        std::cout << " crossing entrance plane with bounds " << posXEn.x() << " y " << posXEn.y() << " z " << posXEn.z() << std::endl;
+        std::cout << " exit position                       " << exit.x() << " y " << exit.y() << " z " << exit.z() << std::endl;
+        std::cout << " crossing exit plane with bounds     " << posXEx.x() << " y " << posXEx.y() << " z " << posXEx.z() << std::endl;
+      } 
+    } 
+    if(debugLevel>=2) { 
+      std::cout << " pathT " << pathT  << " path " << path << std::endl;
+    }
+
+    return path; 
+ 
+}
+bool PathLengthUtils::crossingMatrix(Amg::MatrixX Matrix ,Amg::Vector3D entry, Amg::Vector3D& path) {
+
+//    std::cout << " Matrix determinant " << Matrix.determinant() << std::endl;
+//    std::cout << " Matrix " << std::endl; 
+//    std::cout << Matrix << std::endl;
+
+    if(Matrix.determinant()==0) {
+ //      std::cout << " PathLengthUtils::crossingMatrix Matrix determinant ZERO " << std::endl; 
+       return false;
+    }
+    Amg::MatrixX Minv = Matrix.inverse();
+
+//    std::cout << " inverse Matrix " << std::endl;
+//    std::cout << Minv << std::endl;
+
+    path = Minv*entry;
+
+    bool crossing = false;
+//
+// Inside middle of the plane ?   range -0.5 to 0.5
+//
+    if(fabs(path.x())<0.5&&fabs(path.y())<0.5) crossing = true;
+
+    return crossing;
+}
+
+double PathLengthUtils::getPathLengthInTile(const CaloCell& cell, const Amg::Vector3D& entrance, const Amg::Vector3D& exit){
+//=========================================================================================================================
+    // OBTAIN LAYER INDICES FOR LINEAR INTERPOLATION
+    unsigned int SampleID = cell.caloDDE()->getSampling();
+
+    double CellZB[9]  = {141.495, 424.49, 707.485, 999.605, 1300.855, 1615.8, 1949., 2300.46, 2651.52};
+    double CellDZB[9] = {282.99, 283., 282.99, 301.25, 301.25, 328.64, 337.76, 365.16, 336.96};
+    double CellZC[9]  = {159.755, 483.83, 812.465, 1150.23, 1497.125, 1857.71, 2241.12, 2628.695,0};
+    double CellDZC[9] = {319.51, 328.64, 328.63, 346.9, 346.89, 374.28, 392.54, 382.61,0};
+    
+    // OBTAIN TRACK AND CELL PARAMETERS
+    double pathl = 0.;
+
+    double Layer1X(exit.x()),Layer1Y(exit.y()),Layer1Z(exit.z());
+    double Layer2X(entrance.x()),Layer2Y(entrance.y()),Layer2Z(entrance.z());
+
+    double CellPhimin = cell.caloDDE()->phi()-cell.caloDDE()->dphi()*0.5;
+    double CellPhimax = cell.caloDDE()->phi()+cell.caloDDE()->dphi()*0.5;
+    double CellZmin = cell.caloDDE()->z()-cell.caloDDE()->dz()*0.5;
+    double CellZmax = cell.caloDDE()->z()+cell.caloDDE()->dz()*0.5;
+    double CellRmin = cell.caloDDE()->r()-cell.caloDDE()->dr()*0.5;
+    double CellRmax = cell.caloDDE()->r()+cell.caloDDE()->dr()*0.5;
+
+    // FIX FOR CELLS WITH ZERO WIDTH IN R
+    if(cell.caloDDE()->dr() == 0){
+        // V = dr*dphi*r*dz
+        double CellVolume = cell.caloDDE()->volume();
+        double product = cell.caloDDE()->dphi() * cell.caloDDE()->r() * cell.caloDDE()->dz();
+        double drFormula = 0;
+        if(product!=0){
+            drFormula = CellVolume / product;
+        } // IF 
+        CellRmin = cell.caloDDE()->r() - drFormula*0.5;
+        CellRmax = cell.caloDDE()->r() + drFormula*0.5;
+    } // IF
+
+    //TileCellDim *cell_dim = m_tileDDM->get_cell_dim(cell->caloDDE()->identify());
+
+    double CellXimp[2], CellYimp[2], CellZimp[2];
+    double X(0), Y(0), Z(0), R(0), Phi(0);
+    double DeltaPhi;
+    
+    // COMPUTE PATH
+    bool compute = true;
+    int lBC(0);
+    // LOOP IS USUALLY RUN ONCE, EXCEPT FOR LADDER SHAPED TILECAL CELLS
+    while(compute){
+        if(lBC==1) break;
+        int Np = 0;
+        if(sqrt((Layer1X-Layer2X)*(Layer1X-Layer2X)+(Layer1Y-Layer2Y)*(Layer1Y-Layer2Y)) < 3818.5){
+            if(SampleID == 13 && lBC == 0){
+                int cpos = fabs(cell.caloDDE()->eta())/0.1;
+
+                CellRmin = 2600.; //cell_dim->getRMin(0);
+                CellRmax = 2990.; //cell_dim->getRMax(2);
+                CellZmin = CellZB[cpos] - 0.5*CellDZB[cpos]; //cell_dim->getZMin(0);
+                CellZmax = CellZB[cpos] + 0.5*CellDZB[cpos]; //cell_dim->getZMax(0);
+            } // ELSE IF
+            else if(SampleID == 13 && lBC == 1){
+                int cpos = fabs(cell.caloDDE()->eta())/0.1;
+
+                CellRmin = 2990.; //cell_dim->getRMin(3);
+                CellRmax = 3440.; //cell_dim->getRMax(5);
+                CellZmin = CellZC[cpos] - 0.5*CellDZC[cpos]; //cell_dim->getZMin(3);
+                CellZmax = CellZC[cpos] + 0.5*CellDZC[cpos]; //cell_dim->getZMax(3);
+            } // ELSE IF
+            
+            // CALCULATE GRADIENTS
+            double Sxy = (Layer2X-Layer1X)/(Layer2Y-Layer1Y);
+            double Sxz = (Layer2X-Layer1X)/(Layer2Z-Layer1Z);
+            double Syz = (Layer2Y-Layer1Y)/(Layer2Z-Layer1Z);
+
+            // CALCULATE POINTS OF INTERSECTION
+            // INTERSECTIONS R PLANES
+            double Radius(CellRmin);
+            
+            double x0int(exit.x()), x1int(entrance.x()),
+            y0int(exit.y()), y1int(entrance.y()),
+            z0int(exit.z()), z1int(entrance.z());
+            double S((y1int-y0int)/(x1int-x0int));
+            double a(1+S*S), b(2*S*y0int-2*S*S*x0int), c(y0int*y0int-Radius*Radius+S*S*x0int*x0int-2*y0int*S*x0int);
+            double x1((-b+sqrt(b*b-4*a*c))/(2*a)), x2((-b-sqrt(b*b-4*a*c))/(2*a));
+            double y1(y0int+S*(x1-x0int)), y2(y0int+S*(x2-x0int));
+            double S1 = ((z1int-z0int)/(x1int-x0int));
+            double z1(z0int+S1*(x1-x0int)), z2(z0int+S1*(x2-x0int));
+            
+            X = x1;
+            Y = y1;
+            Z = z1;
+            
+            if( ((x1-x0int)*(x1-x0int)+(y1-y0int)*(y1-y0int)+(z1-z0int)*(z1-z0int)) >
+               ((x2-x0int)*(x2-x0int)+(y2-y0int)*(y2-y0int)+(z2-z0int)*(z2-z0int)) ){
+                X=x2;
+                Y=y2;
+                Z=z2;
+            } // IF
+
+            if(CellRmin != CellRmax){
+            Phi = acos(X/sqrt(X*X+Y*Y));
+            if(Y <= 0) Phi = -Phi;
+            R = CellRmin;
+            
+            if(Z>=CellZmin && Z<=CellZmax && Phi>=CellPhimin && Phi<=CellPhimax){
+                CellXimp[Np]=X;
+                CellYimp[Np]=Y;
+                CellZimp[Np]=Z;
+                Np=Np+1;
+               
+            } // IF
+            
+            Radius = CellRmax;
+            
+            c  = y0int*y0int-Radius*Radius+S*S*x0int*x0int-2*y0int*S*x0int;
+            x1 = ((-b+sqrt(b*b-4*a*c))/(2*a));
+            x2 = ((-b-sqrt(b*b-4*a*c))/(2*a));
+            y1 = (y0int+S*(x1-x0int));
+            y2 = (y0int+S*(x2-x0int));
+            z1 = (z0int+S1*(x1-x0int));
+            z2 = (z0int+S1*(x2-x0int));
+            S1 = ((z1int-z0int)/(x1int-x0int));
+
+            X = x1;
+            Y = y1;
+            Z = z1;
+
+            if( ((x1-x0int)*(x1-x0int)+(y1-y0int)*(y1-y0int)+(z1-z0int)*(z1-z0int)) >
+               ((x2-x0int)*(x2-x0int)+(y2-y0int)*(y2-y0int)+(z2-z0int)*(z2-z0int)) ){
+                X = x2;
+                Y = y2;
+                Z = z2;
+            } // IF
+
+            Phi=std::acos(X/sqrt(X*X+Y*Y));
+            if (Y <= 0) Phi=-Phi;
+            R=CellRmax;
+            
+            if(Z>=CellZmin && Z<=CellZmax && Phi>=CellPhimin && Phi<=CellPhimax){
+                CellXimp[Np]=X; CellYimp[Np]=Y; CellZimp[Np]=Z;
+                Np=Np+1;
+            } // IF
+            } // IF
+            
+            // INTERSECTIONS Z PLANES
+            if(CellZmin != CellZmax){
+            if(Np < 2){
+                Z = CellZmin;
+                X = Layer1X+Sxz*(Z-Layer1Z);
+                Y = Layer1Y+Syz*(Z-Layer1Z);
+                R = sqrt(X*X+Y*Y);
+                Phi = std::acos(X/R);
+                if(Y <= 0) Phi=-Phi;
+                if(R>=CellRmin && R<=CellRmax && Phi>=CellPhimin && Phi<=CellPhimax){
+                    CellXimp[Np]=X; CellYimp[Np]=Y; CellZimp[Np]=Z;
+                    Np=Np+1;
+                } // IF
+            } // IF
+
+            if(Np < 2){
+                Z = CellZmax;
+                X = Layer1X+Sxz*(Z-Layer1Z);
+                Y = Layer1Y+Syz*(Z-Layer1Z);
+                R = sqrt(X*X+Y*Y);
+                Phi = std::acos(X/R);
+                if(Y <= 0) Phi=-Phi;
+                if(R>=CellRmin && R<=CellRmax && Phi>=CellPhimin && Phi<=CellPhimax){
+                    CellXimp[Np]=X; CellYimp[Np]=Y; CellZimp[Np]=Z;
+                    Np=Np+1;
+                } // IF
+            } // IF
+            } // IF
+
+            // INTERSECTIONS PHI PLANES
+            if(CellPhimin != CellPhimax){
+            if(Np < 2){
+                X = (Layer1X-Sxy*Layer1Y)/(1-Sxy*tan(CellPhimin));
+                Y = X*std::tan(CellPhimin);
+                Z = Layer1Z+(1/Sxz)*(X-Layer1X);
+                R = sqrt(X*X+Y*Y);
+                Phi = std::acos(X/R);
+                if(Y <= 0) Phi=-Phi;
+                DeltaPhi=fabs(Phi-CellPhimin);
+                if(DeltaPhi > 3.141593) DeltaPhi=fabs(Phi+CellPhimin);
+                if(R>=CellRmin && R<=CellRmax && Z>=CellZmin && Z<=CellZmax && DeltaPhi<0.0001){
+                    CellXimp[Np]=X; CellYimp[Np]=Y; CellZimp[Np]=Z;
+                    Np=Np+1;                  
+                } // IF
+            } // IF
+
+            if(Np < 2){
+                X = (Layer1X-Sxy*Layer1Y)/(1-Sxy*tan(CellPhimax));
+                Y = X*std::tan(CellPhimax);
+                Z = Layer1Z+(1/Sxz)*(X-Layer1X);
+                R = sqrt(X*X+Y*Y);
+                Phi=acos(X/R);
+                if(Y <= 0) Phi=-Phi;
+                DeltaPhi=fabs(Phi-CellPhimax);
+                if(DeltaPhi > 3.141593) DeltaPhi=fabs(Phi+CellPhimax);
+                if(R>=CellRmin && R<=CellRmax && Z>=CellZmin && Z<=CellZmax && DeltaPhi<0.0001){
+                    CellXimp[Np]=X; CellYimp[Np]=Y; CellZimp[Np]=Z;
+                    Np=Np+1;
+                } // IF
+            } // IF
+            } // IF
+
+            // CALCULATE PATH IF TWO INTERSECTIONS WERE FOUND
+            if(Np == 2){                
+                pathl += sqrt( (CellXimp[0]-CellXimp[1])*(CellXimp[0]-CellXimp[1]) +
+                               (CellYimp[0]-CellYimp[1])*(CellYimp[0]-CellYimp[1]) +
+                               (CellZimp[0]-CellZimp[1])*(CellZimp[0]-CellZimp[1]) );
+            } // IF
+        } // IF
+        if(SampleID == 13 && lBC == 0) ++lBC;
+        else compute = false;
+    } // WHILE (FOR LBBC LAYER)
+
+    return pathl;
+} // PathLengthUtils::getPathLengthInTile
+
+
+
+CaloSampling::CaloSample PathLengthUtils::tileEntrance(CaloSampling::CaloSample sample){
+    if(sample==CaloSampling::TileBar0||sample==CaloSampling::TileBar1||sample==CaloSampling::TileBar2||sample==CaloSampling::TileGap2) return CaloSampling::TileBar0;
+    if(sample==CaloSampling::TileGap1)                                                       return CaloSampling::TileBar1;
+    if(sample==CaloSampling::TileGap3||sample==CaloSampling::TileExt0||sample==CaloSampling::TileExt1||sample==CaloSampling::TileExt2) return CaloSampling::TileExt0;
+    return CaloSampling::Unknown;
+    //return sample;
+} // PathLengthUtils::entrance 
+
+CaloSampling::CaloSample PathLengthUtils::tileExit(CaloSampling::CaloSample sample){
+    if(sample==CaloSampling::TileBar0||sample==CaloSampling::TileBar1||sample==CaloSampling::TileBar2||sample==CaloSampling::TileGap1) return CaloSampling::TileBar2;
+    if(sample==CaloSampling::TileGap2)                                                       return CaloSampling::TileBar1;
+    if(sample==CaloSampling::TileGap3)                                                       return CaloSampling::TileExt1;
+    if(sample==CaloSampling::TileExt0||sample==CaloSampling::TileExt1||sample==CaloSampling::TileExt2)                   return CaloSampling::TileExt2;
+    return CaloSampling::Unknown;
+    //return sample;
+} // PathLengthUtils::exit 
+
+/** Return the length(mm) of the path crossed inside the cell, given the parameters for the extrapolation at entrance and exit of the layer **/
+double PathLengthUtils::pathInsideCell(const CaloCell& cell, const CaloExtensionHelpers::EntryExitLayerMap&  entryExitLayerMap) {
+  
+  CaloSampling::CaloSample sample = cell.caloDDE()->getSampling();
+
+  //------------------------------------------------------------------------------------------
+  //special treatment for tile calo cells
+  CaloSampling::CaloSample tileEntranceID = tileEntrance(sample);
+  CaloSampling::CaloSample tileExitID     = tileExit(sample);
+
+  auto tileEntrancePair = entryExitLayerMap.find(tileEntranceID);
+  auto tileExitPair     = entryExitLayerMap.find(tileExitID);
+  if( tileEntrancePair != entryExitLayerMap.end() && tileExitPair != entryExitLayerMap.end() ){
+    return getPathLengthInTile( cell, tileEntrancePair->second.first, tileExitPair->second.second);
+  }
+  //------------------------------------------------------------------------------------------
+
+  auto entryExitPair = entryExitLayerMap.find(sample);
+  if( entryExitPair == entryExitLayerMap.end() ) return -1.;
+  
+  const Amg::Vector3D& entry = entryExitPair->second.first;
+  const Amg::Vector3D& exit  = entryExitPair->second.second;
+
+  if (!crossedPhi(cell, entry.phi(), exit.phi())) return -1.;
+  double pathCrossed = -1;
+  if (cell.caloDDE()->getSubCalo() != CaloCell_ID::TILE){
+    pathCrossed = getPathLengthInEta(cell, entry.eta(), exit.eta());
+  }
+  else{
+    pathCrossed = getPathLengthInZ(cell, entry.z(), exit.z());
+  }
+  if (pathCrossed <= 0) return -1.;
+  return pathCrossed * (exit-entry).mag();
+}
diff --git a/Reconstruction/RecoTools/TrackToCalo/src/PathLengthUtils.h b/Reconstruction/RecoTools/TrackToCalo/src/PathLengthUtils.h
new file mode 100755
index 0000000000000000000000000000000000000000..17de47b05a3e1be4715ce8103fa6888791caa63b
--- /dev/null
+++ b/Reconstruction/RecoTools/TrackToCalo/src/PathLengthUtils.h
@@ -0,0 +1,101 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/***************************************************************************
+ PathLengthUtils.h  -  Description
+ -------------------
+ begin   : Summer 2014
+ authors : Marius Cornelis van Woerden
+ email   : mvanwoer@cern.ch
+ changes :
+ 
+ ***************************************************************************/
+
+#ifndef PATHLENGTUTILS_H
+#define PATHLENGTUTILS_H
+
+#include "xAODTracking/TrackParticle.h"
+#include "xAODTracking/TrackParticleContainer.h"
+
+#include "CaloEvent/CaloCellContainer.h"
+#include "CaloEvent/CaloCell.h"
+
+#include "CaloGeoHelpers/CaloSampling.h"
+#include "CaloGeoHelpers/CaloPhiRange.h"
+
+#include <cmath>
+
+#include "TrkCaloExtension/CaloExtensionHelpers.h"
+
+  class PathLengthUtils{
+  public:
+      PathLengthUtils();
+      ~PathLengthUtils();
+
+
+      double pathInsideCell(const CaloCell& cell, const CaloExtensionHelpers::EntryExitLayerMap&  entryExitLayerMap);
+      double get3DPathLength(const CaloCell& cell, const Amg::Vector3D& entry, const Amg::Vector3D& exit, double drFix, double dzFix );
+
+      double getPathLengthInTile(const CaloCell& cell, const Amg::Vector3D& entry, const Amg::Vector3D& exit );
+      //double path(xAOD::TrackParticle& trackParticle, const CaloCell* cell);
+      //double path(xAOD::TrackParticle& trackParticle, const CaloCell_ID::CaloSample sample); 
+      
+  private:
+      CaloSampling::CaloSample tileEntrance(CaloSampling::CaloSample sample);
+      CaloSampling::CaloSample tileExit(CaloSampling::CaloSample sample);
+
+      double phiMean(double a, double b);
+      bool   crossedPhi(const CaloCell& cell, double phi_entrance, double phi_exit);
+      double getPathLengthInEta(const CaloCell& cell, double eta_entrance, double eta_exit);
+      double getPathLengthInZ(double zMin, double zMax, double z_entrance, double z_exit);
+      double getPathLengthInZ(const CaloCell& cell, double z_entrance, double z_exit);
+      bool   crossingMatrix(Amg::MatrixX Matrix ,Amg::Vector3D entry, Amg::Vector3D& path);
+      //static double CellZB[9];
+      //static double CellDZB[9];
+      //static double CellZC[9];
+      //static double CellDZC[9];
+  }; 
+
+inline double PathLengthUtils::phiMean(double a, double b) { return 0.5*(a+b) + (a*b < 0)*M_PI; }
+
+/** Return true if the cell crossed was crossed by the track in phi **/
+inline bool PathLengthUtils::crossedPhi(const CaloCell& cell, double phi_entrance, double phi_exit) {
+  double mean_phi = phiMean(phi_entrance, phi_exit);
+  double dphi = fabs( CaloPhiRange::diff(phi_entrance, phi_exit) );
+  double phi_min = mean_phi - dphi, phi_max = mean_phi + dphi;
+ 
+  return (CaloPhiRange::diff(cell.phi() + cell.caloDDE()->dphi()/2., phi_min) > 0 &&
+          CaloPhiRange::diff(phi_max, cell.phi() - cell.caloDDE()->dphi()/2.) > 0);
+}
+
+/** Return the % of path length crossed by the track inside a cell in eta **/
+inline double PathLengthUtils::getPathLengthInEta(const CaloCell& cell, double eta_entrance, double eta_exit) {
+  double etaMin = cell.eta() - 0.5*cell.caloDDE()->deta();
+  double etaMax = cell.eta() + 0.5*cell.caloDDE()->deta();
+  if ( fabs(eta_entrance  - eta_exit) < 1e-6 ) // to avoid FPE
+    return eta_entrance > etaMin && eta_entrance < etaMax;
+   
+  double etaMinTrack = std::min(eta_entrance, eta_exit);
+  double etaMaxTrack = std::max(eta_entrance, eta_exit);
+  return (std::min(etaMax, etaMaxTrack) - std::max(etaMin, etaMinTrack))/(etaMaxTrack - etaMinTrack);
+}
+
+/** Return the % of path length crossed by the track inside a cell in Z **/
+inline double PathLengthUtils::getPathLengthInZ(double zMin, double zMax, double z_entrance, double z_exit) {
+  if ( fabs(z_entrance  - z_exit) < 1e-6 ) // to avoid FPE
+    return z_entrance > zMin && z_entrance < zMax;
+ 
+  double zMinTrack = std::min(z_entrance, z_exit);
+  double zMaxTrack = std::max(z_entrance, z_exit);
+  return (std::min(zMax, zMaxTrack) - std::max(zMin, zMinTrack))/(zMaxTrack - zMinTrack);
+}
+
+/** Return the % of path length crossed by the track inside a cell in Z **/
+inline double PathLengthUtils::getPathLengthInZ(const CaloCell& cell, double z_entrance, double z_exit) {
+  return getPathLengthInZ(cell.z() - 0.5*cell.caloDDE()->dz(), cell.z() + 0.5*cell.caloDDE()->dz(), z_entrance, z_exit);
+}
+
+
+#endif //> !PATHLENGTUTILS_H
+
diff --git a/Reconstruction/RecoTools/TrackToCalo/src/TrackParticleCaloExtensionAlg.cxx b/Reconstruction/RecoTools/TrackToCalo/src/TrackParticleCaloExtensionAlg.cxx
index edf896bafc74d0e076bc286ee4a3514722400c3f..95a02e6102737cc6c2c81d87dea97619effa1078 100644
--- a/Reconstruction/RecoTools/TrackToCalo/src/TrackParticleCaloExtensionAlg.cxx
+++ b/Reconstruction/RecoTools/TrackToCalo/src/TrackParticleCaloExtensionAlg.cxx
@@ -61,28 +61,28 @@ StatusCode TrackParticleCaloExtensionAlg::execute() {
     if( !m_trackSelector.empty() && !m_trackSelector->decision(*tp) ) continue;
     ++m_processedTracks;
 
-    // call calo Extension
-    if( !m_caloExtensionTool.empty() ){
-      const xAOD::ParticleCaloExtension* extension = m_caloExtensionTool->caloExtension(const_cast<xAOD::TrackParticle&>(*tp));
-      if( extension ) ++m_extensions;
+    // // call calo Extension
+    // if( !m_caloExtensionTool.empty() ){
+    //   const Trk::CaloExtension* extension = m_caloExtensionTool->caloExtension(const_cast<xAOD::TrackParticle&>(*tp));
+    //   if( extension ) ++m_extensions;
 
-      if( msgLvl(MSG::DEBUG) && extension && extension->numberOfParameters() != 0 ){
-        ATH_MSG_DEBUG("Got calo extension " << extension->numberOfParameters() << " cells " << extension->caloCells().size() );
-        for( unsigned int i=0;i<extension->numberOfParameters();++i){
-          xAOD::CurvilinearParameters_t pars = extension->trackParameters(i);
-          unsigned int id = extension->parameterIdentifier(i);
-          ATH_MSG_DEBUG( " id " << id << " pos: r " << sqrt(pars[0]*pars[0]+pars[1]*pars[1]) << " z " << pars[2]
-                         << " momentum " << sqrt(pars[3]*pars[3]+pars[4]*pars[4]+pars[5]*pars[5]) );
-        }
-      }
-    }
-    // call calo cell association
-    if( !m_caloCellAssociationTool.empty() ){
-      const xAOD::ParticleCaloExtension* extension = m_caloCellAssociationTool->caloAssociation(const_cast<xAOD::TrackParticle&>(*tp));
-      if( msgLvl(MSG::DEBUG) && extension && extension->numberOfParameters() != 0 ){
-        ATH_MSG_DEBUG("Got calo cell extension " << extension->numberOfParameters() << " cells " << extension->caloCells().size() );
-      }
-    }
+    //   if( msgLvl(MSG::DEBUG) && extension && extension->numberOfParameters() != 0 ){
+    //     ATH_MSG_DEBUG("Got calo extension " << extension->numberOfParameters() << " cells " << extension->caloCells().size() );
+    //     for( unsigned int i=0;i<extension->numberOfParameters();++i){
+    //       xAOD::CurvilinearParameters_t pars = extension->trackParameters(i);
+    //       unsigned int id = extension->parameterIdentifier(i);
+    //       ATH_MSG_DEBUG( " id " << id << " pos: r " << sqrt(pars[0]*pars[0]+pars[1]*pars[1]) << " z " << pars[2]
+    //                      << " momentum " << sqrt(pars[3]*pars[3]+pars[4]*pars[4]+pars[5]*pars[5]) );
+    //     }
+    //   }
+    // }
+    // // call calo cell association
+    // if( !m_caloCellAssociationTool.empty() ){
+    //   const xAOD::ParticleCaloExtension* extension = m_caloCellAssociationTool->caloAssociation(const_cast<xAOD::TrackParticle&>(*tp));
+    //   if( msgLvl(MSG::DEBUG) && extension && extension->numberOfParameters() != 0 ){
+    //     ATH_MSG_DEBUG("Got calo cell extension " << extension->numberOfParameters() << " cells " << extension->caloCells().size() );
+    //   }
+    // }
   }
 
   return StatusCode::SUCCESS;
diff --git a/Reconstruction/RecoTools/TrackToCalo/src/TrackParticleCaloExtensionAlg.h b/Reconstruction/RecoTools/TrackToCalo/src/TrackParticleCaloExtensionAlg.h
index 270206409535466d5f483d08862daa2c2c8cf50b..07be8ae1ea356171d3da2e20773b611289cb19cb 100644
--- a/Reconstruction/RecoTools/TrackToCalo/src/TrackParticleCaloExtensionAlg.h
+++ b/Reconstruction/RecoTools/TrackToCalo/src/TrackParticleCaloExtensionAlg.h
@@ -20,6 +20,8 @@
 namespace Trk {
   class ITrackSelectorTool;
   class IParticleCaloExtensionTool;
+}
+namespace Rec {
   class IParticleCaloCellAssociationTool;
 }
 
@@ -37,7 +39,7 @@ public:
 
 private:
   ToolHandle <Trk::IParticleCaloExtensionTool>       m_caloExtensionTool; //!< Tool to make the step-wise extrapolation
-  ToolHandle <Trk::IParticleCaloCellAssociationTool> m_caloCellAssociationTool; //!< Tool to make the step-wise extrapolation
+  ToolHandle <Rec::IParticleCaloCellAssociationTool> m_caloCellAssociationTool; //!< Tool to make the step-wise extrapolation
   ToolHandle <Trk::ITrackSelectorTool>               m_trackSelector; //!< Tool to select tracks
 
   std::string m_trackParicleContainerName;
diff --git a/Reconstruction/RecoTools/TrackToCalo/src/components/TrackToCalo_entries.cxx b/Reconstruction/RecoTools/TrackToCalo/src/components/TrackToCalo_entries.cxx
index 521442589ce1c36f7d45c4962f28768fbcbdec13..602b2a965dfb7d88d790a5b6a15ec1d023bd0229 100755
--- a/Reconstruction/RecoTools/TrackToCalo/src/components/TrackToCalo_entries.cxx
+++ b/Reconstruction/RecoTools/TrackToCalo/src/components/TrackToCalo_entries.cxx
@@ -1,24 +1,25 @@
 //====================================================================
 
 #include "GaudiKernel/DeclareFactoryEntries.h"
-#include "TrackToCalo/ExtrapolateToCaloTool.h"
 #include "../ParticleCaloExtensionTool.h"
 #include "../ParticleCaloCellAssociationTool.h"
+#include "../ParticleCaloClusterAssociationTool.h"
 #include "../TrackParticleCaloExtensionAlg.h"
-#include "TrackToCalo/ImpactInCaloAlg.h"
+#include "../MuonCaloEnergyTool.h"
 
 using namespace Trk;
-DECLARE_TOOL_FACTORY( ExtrapolateToCaloTool )
+using namespace Rec;
 DECLARE_TOOL_FACTORY( ParticleCaloExtensionTool )
 DECLARE_TOOL_FACTORY( ParticleCaloCellAssociationTool )
-DECLARE_ALGORITHM_FACTORY( ImpactInCaloAlg )
+DECLARE_TOOL_FACTORY( ParticleCaloClusterAssociationTool )
+DECLARE_TOOL_FACTORY( MuonCaloEnergyTool )
 DECLARE_ALGORITHM_FACTORY( TrackParticleCaloExtensionAlg )
 
 DECLARE_FACTORY_ENTRIES	( TrackToCalo ) {
-    DECLARE_TOOL( ExtrapolateToCaloTool );
     DECLARE_TOOL( ParticleCaloExtensionTool );
     DECLARE_TOOL( ParticleCaloCellAssociationTool );
-    DECLARE_ALGORITHM( ImpactInCaloAlg );
+    DECLARE_TOOL( ParticleCaloClusterAssociationTool );
+    DECLARE_TOOL( MuonCaloEnergyTool );
     DECLARE_ALGORITHM( TrackParticleCaloExtensionAlg );
 }