From 17d80ad53df3f3e883c9307796e23ea21ecf425d Mon Sep 17 00:00:00 2001
From: Pierre-Antoine Delsart <delsart@in2p3.fr>
Date: Thu, 5 Nov 2020 14:40:37 +0000
Subject: [PATCH] TCC and UFO reco for r22

---
 .../JetRecConfig/python/ConstModHelpers.py    |   3 -
 .../Jet/JetRecConfig/python/JetRecConfig.py   |  32 +-
 .../CMakeLists.txt                            |  15 +-
 .../TrackParticleClusterAssociationAlg.cxx    | 230 +++++-----
 .../src/TrackParticleClusterAssociationAlg.h  |  68 ++-
 .../IParticleCaloClusterAssociationTool.h     |   2 +-
 .../ParticleCaloClusterAssociationTool.cxx    | 230 ----------
 .../src/ParticleCaloClusterAssociationTool.h  |  89 ----
 .../src/ParticleCaloExtensionTool.cxx         |  13 +-
 .../src/ParticleCaloExtensionTool.h           |   5 +-
 .../src/components/TrackToCalo_entries.cxx    |   2 -
 .../TrackCaloClusterRecAlgs/CMakeLists.txt    |  19 +
 .../TrackCaloClusterAlg.h                     |  51 +++
 .../TrackCaloClusterInfoAlg.h                 |  97 +++++
 .../TrackCaloClusterExample_jobOptions.py     | 154 +++++++
 .../src/TrackCaloClusterAlg.cxx               |  71 ++++
 .../src/TrackCaloClusterInfoAlg.cxx           | 173 ++++++++
 .../TrackCaloClusterRecAlgs_entries.cxx       |   8 +
 .../IClusterFilterTool.h                      |   4 +-
 .../ITrackCaloClusterTool.h                   |  36 ++
 .../TrackCaloClusterRecTools/CMakeLists.txt   |  27 +-
 .../ClusterFilterTool.h                       |   6 +-
 .../TrackCaloClusterRecTools/TCCHelpers.h     | 107 +++++
 .../TrackCaloClusterCreatorTool.h             |  85 ----
 .../TrackCaloClusterInfo.h                    |  40 ++
 .../TrackCaloClusterTool.h                    | 140 ++++++
 .../TrackCaloClusterWeightsTool.h             |  41 --
 .../python/TrackCaloClusterConfig.py          | 261 ++++++++++++
 .../src/ClusterFilterTool.cxx                 |   4 +-
 .../src/ParticleToCaloExtrapolationTool.cxx   |   2 +-
 .../src/TrackCaloClusterCreatorTool.cxx       | 236 -----------
 .../src/TrackCaloClusterTool.cxx              | 398 ++++++++++++++++++
 .../src/TrackCaloClusterWeightsTool.cxx       |  68 ---
 ...articleToCaloExtrapolationTool_entries.cxx |   9 +-
 34 files changed, 1789 insertions(+), 937 deletions(-)
 delete mode 100644 Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloClusterAssociationTool.cxx
 delete mode 100644 Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloClusterAssociationTool.h
 create mode 100644 Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecAlgs/CMakeLists.txt
 create mode 100644 Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecAlgs/TrackCaloClusterRecAlgs/TrackCaloClusterAlg.h
 create mode 100644 Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecAlgs/TrackCaloClusterRecAlgs/TrackCaloClusterInfoAlg.h
 create mode 100644 Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecAlgs/share/TrackCaloClusterExample_jobOptions.py
 create mode 100644 Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecAlgs/src/TrackCaloClusterAlg.cxx
 create mode 100644 Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecAlgs/src/TrackCaloClusterInfoAlg.cxx
 create mode 100644 Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecAlgs/src/components/TrackCaloClusterRecAlgs_entries.cxx
 create mode 100644 Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecInterfaces/TrackCaloClusterRecInterfaces/ITrackCaloClusterTool.h
 create mode 100644 Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/TrackCaloClusterRecTools/TCCHelpers.h
 delete mode 100644 Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/TrackCaloClusterRecTools/TrackCaloClusterCreatorTool.h
 create mode 100644 Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/TrackCaloClusterRecTools/TrackCaloClusterInfo.h
 create mode 100644 Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/TrackCaloClusterRecTools/TrackCaloClusterTool.h
 delete mode 100644 Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/TrackCaloClusterRecTools/TrackCaloClusterWeightsTool.h
 create mode 100644 Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/python/TrackCaloClusterConfig.py
 delete mode 100644 Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/src/TrackCaloClusterCreatorTool.cxx
 create mode 100644 Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/src/TrackCaloClusterTool.cxx
 delete mode 100644 Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/src/TrackCaloClusterWeightsTool.cxx

diff --git a/Reconstruction/Jet/JetRecConfig/python/ConstModHelpers.py b/Reconstruction/Jet/JetRecConfig/python/ConstModHelpers.py
index d1b4f4ac84e..28ca378acd2 100644
--- a/Reconstruction/Jet/JetRecConfig/python/ConstModHelpers.py
+++ b/Reconstruction/Jet/JetRecConfig/python/ConstModHelpers.py
@@ -160,9 +160,6 @@ def getConstitModAlg(constit, monTool=None):
     return constitmodalg
 
 
-
-
-
 def constitModWithAlternateTrk(mod, trkopt):
     """Generates a new JetConstitModifier cloned from mod and stores it in the standard jetconstitmoddic.
     The cloned JetConstitModifier has all its track related properties changed according to trackcollectionmap[trkopt]
diff --git a/Reconstruction/Jet/JetRecConfig/python/JetRecConfig.py b/Reconstruction/Jet/JetRecConfig/python/JetRecConfig.py
index 4ba2d6d7e5b..88b0b327b36 100644
--- a/Reconstruction/Jet/JetRecConfig/python/JetRecConfig.py
+++ b/Reconstruction/Jet/JetRecConfig/python/JetRecConfig.py
@@ -94,26 +94,39 @@ def JetRecCfg(jetdef0, configFlags):
 
 
 ########################################################################
-def JetInputCfg(jetdef, configFlags, sequenceName):
+def JetInputCfg(jetOrConstitdef, configFlags, sequenceName='AthAlgSeq'):
     """Function for setting up inputs to jet finding
-    
+
     This includes constituent modifications, track selection, copying of
     input truth particles and event density calculations
+    
+    jetOrConstitdef can either be 
+     * a JetDefinition : this happens when called from JetRecCfg, then the jetdef._prereqDic/Order are used.
+     * a JetConstitSource : to allow scheduling the corresponding constituents algs independently of any jet alg. 
     """
 
     jetlog.info("Setting up jet inputs.")
     components = ComponentAccumulator(sequenceName)
 
+    
+    from .JetDefinition import JetConstitSource, JetDefinition
+    if isinstance(jetOrConstitdef, JetConstitSource):
+        jetdef = JetDefinition('Kt', 0., jetOrConstitdef.clone())
+        instantiateAliases(jetdef)        
+        removeComponentFailingConditions(jetdef, configFlags, raiseOnFailure= not jetdef.standardRecoMode)
+    else:
+        jetdef = jetOrConstitdef
+    
     jetlog.info("Inspecting input file contents")
     filecontents = configFlags.Input.Collections
 
     inputdeps = [ inputkey for inputkey in jetdef._prereqOrder if inputkey.startswith('input:')]
+
     
     for inputfull in inputdeps:
-        #inputkey = inputfull[6:] # remove 'input:'
         inputInstance = jetdef._prereqDic[inputfull]
-        from .JetDefinition import JetConstitSource
-
+        isprimary = False # actually not using it yet.
+        
         if isinstance(inputInstance, JetConstitSource):
             if inputInstance.containername in filecontents:
                 jetlog.debug("Input container {0} for label {1} already in input file.".format(inputInstance.containername, inputInstance.name))
@@ -124,12 +137,12 @@ def JetInputCfg(jetdef, configFlags, sequenceName):
                 from . import ConstModHelpers
                 constitalg = ConstModHelpers.getConstitModAlg(inputInstance)
                 if constitalg:
-                    components.addEventAlgo(constitalg)
+                    components.addEventAlgo(constitalg, primary=isprimary)
         else:
             jetlog.debug("Requesting input {} with function {} and specs {}".format(inputInstance.name, inputInstance.algoBuilder, inputInstance.specs) )
             # inputInstance must be a JetInputDef
             if inputInstance.algoBuilder:
-                components.addEventAlgo( inputInstance.algoBuilder( jetdef, inputInstance.specs )  )
+                components.addEventAlgo( inputInstance.algoBuilder( jetdef, inputInstance.specs ), primary=isprimary )
             else:
                 # for now just hope the input will be present... 
                 pass
@@ -314,8 +327,9 @@ def instantiateAliases( jetdef ):
       * implies calls to recursives function constH.aliasToInputDef and modH.aliasToModDef
     """
 
-    # start with the inputdef (replacing the jetdef attribute to ensure it really is an instance, not only a str)
-    jetdef.inputdef = constH.aliasToInputDef(jetdef.inputdef, jetdef)
+    # start with the inputdef, cloning it so we're not altering a private copy
+    jetdef.inputdef = jetdef.inputdef.clone()
+    constH.instantiateJetConstitAliases(jetdef.inputdef, jetdef)
 
     jetdef._prereqDic['input:'+jetdef.inputdef.name] = jetdef.inputdef
     jetdef._prereqOrder.append('input:'+jetdef.inputdef.name)
diff --git a/Reconstruction/RecoAlgs/TrackParticleAssociationAlgs/CMakeLists.txt b/Reconstruction/RecoAlgs/TrackParticleAssociationAlgs/CMakeLists.txt
index 1fbefe9c3c7..919b823866d 100644
--- a/Reconstruction/RecoAlgs/TrackParticleAssociationAlgs/CMakeLists.txt
+++ b/Reconstruction/RecoAlgs/TrackParticleAssociationAlgs/CMakeLists.txt
@@ -5,21 +5,10 @@
 # Declare the package name:
 atlas_subdir( TrackParticleAssociationAlgs )
 
-# Declare the package's dependencies:
-atlas_depends_on_subdirs( PRIVATE
-                          Calorimeter/CaloUtils
-                          Control/AthenaBaseComps
-                          Event/xAOD/xAODAssociations
-                          Event/xAOD/xAODCaloEvent
-                          Event/xAOD/xAODTracking
-                          GaudiKernel
-                          Reconstruction/RecoTools/RecoToolInterfaces
-                          Reconstruction/RecoTools/TrackToCalo
-                          Tracking/TrkTools/TrkToolInterfaces )
-
 # Component(s) in the package:
 atlas_add_component( TrackParticleAssociationAlgs
                      src/*.cxx
                      src/components/*.cxx
-                     LINK_LIBRARIES CaloUtilsLib AthenaBaseComps xAODAssociations xAODCaloEvent xAODTracking GaudiKernel RecoToolInterfaces TrackToCaloLib TrkToolInterfaces )
+		     INCLUDE_DIRS 
+                     LINK_LIBRARIES  CaloUtilsLib AthenaBaseComps xAODAssociations xAODCaloEvent xAODTracking FourMomUtils GaudiKernel RecoToolInterfaces TrackToCaloLib TrkToolInterfaces )
 
diff --git a/Reconstruction/RecoAlgs/TrackParticleAssociationAlgs/src/TrackParticleClusterAssociationAlg.cxx b/Reconstruction/RecoAlgs/TrackParticleAssociationAlgs/src/TrackParticleClusterAssociationAlg.cxx
index 7209bced179..c506ebdd1b0 100644
--- a/Reconstruction/RecoAlgs/TrackParticleAssociationAlgs/src/TrackParticleClusterAssociationAlg.cxx
+++ b/Reconstruction/RecoAlgs/TrackParticleAssociationAlgs/src/TrackParticleClusterAssociationAlg.cxx
@@ -1,135 +1,173 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #include "TrackParticleClusterAssociationAlg.h"
-#include "xAODTracking/TrackParticleContainer.h"
-#include "xAODCaloEvent/CaloClusterContainer.h"
-#include "xAODCaloEvent/CaloClusterAuxContainer.h"
-#include "xAODCaloEvent/CaloCluster.h"
-#include "xAODAssociations/TrackParticleClusterAssociation.h"
-#include "xAODAssociations/TrackParticleClusterAssociationContainer.h"
-#include "xAODAssociations/TrackParticleClusterAssociationAuxContainer.h"
-
-#include "TrkToolInterfaces/ITrackSelectorTool.h"
-#include "RecoToolInterfaces/IParticleCaloClusterAssociationTool.h"
-#include "TrackToCalo/CrossedCaloCellHelper.h"
-#include "CaloUtils/CaloClusterStoreHelper.h"
 
-TrackParticleClusterAssociationAlg::TrackParticleClusterAssociationAlg(const std::string& name, ISvcLocator* pSvcLocator):
-  AthAlgorithm(name,pSvcLocator),
-  m_caloClusterAssociationTool("Rec::ParticleCaloClusterAssociationTool/ParticleCaloClusterAssociationTool"),
-  m_trackSelector("InDet::InDetDetailedTrackSelectorTool/MuonCombinedInDetDetailedTrackSelectorTool") {  
-
-  declareProperty("ParticleCaloClusterAssociationTool"  ,   m_caloClusterAssociationTool);
-  declareProperty("TrackParticleContainerName"          ,   m_trackParticleCollectionName = "InDetTrackParticles" );
-  declareProperty("PtCut"                               ,   m_ptCut                       = 25000. );
-  declareProperty("OutputCollectionPostFix"             ,   m_outputPostFix               = "" );
-  declareProperty("CaloClusterLocation"                 ,   m_caloClusters                = "CaloCalTopoClusters"   );
-}
+#include "StoreGate/WriteDecorHandle.h"
 
-TrackParticleClusterAssociationAlg::~TrackParticleClusterAssociationAlg()
-{
+#include "FourMomUtils/P4Helpers.h"
+
+#include "AthContainers/AuxElement.h"
 
-}
+
+TrackParticleClusterAssociationAlg::TrackParticleClusterAssociationAlg(const std::string& name, ISvcLocator* pSvcLocator):
+  AthAlgorithm(name,pSvcLocator) {  }
 
 StatusCode TrackParticleClusterAssociationAlg::initialize()
 {
-  ATH_CHECK(m_caloClusterAssociationTool.retrieve());
-  // ATH_CHECK(m_trackSelector.retrieve());
 
+  ATH_CHECK( m_caloExtKey.initialize() );
+  ATH_CHECK( m_trackParticleCollectionHandle.initialize() );
+  ATH_CHECK( m_caloClusters.initialize() );
+  ATH_CHECK( m_assocClustersDecor.initialize() );
+
+  ATH_CHECK(m_caloEntryParsDecor.initialize( !m_caloEntryParsDecor.empty() ) );
+
+  ATH_CHECK( m_vertexContHandle.initialize( !m_vertexContHandle.empty() ) );
+  if(!m_vertexContHandle.empty() ) {
+    ATH_CHECK(m_trackvertexassoTool.retrieve() );
+  }
+
+  ATH_MSG_DEBUG(" cluster decoration = "<< m_assocClustersDecor.key() );
   return StatusCode::SUCCESS; 
 }
 
 StatusCode TrackParticleClusterAssociationAlg::execute()
 {
 
+  ATH_MSG_DEBUG("excute()");
   // get track particles
-  const xAOD::TrackParticleContainer* trackParticles = 0;
-  if(evtStore()->contains<xAOD::TrackParticleContainer>(m_trackParticleCollectionName)) {
-    if(evtStore()->retrieve(trackParticles,m_trackParticleCollectionName).isFailure()) {
-      ATH_MSG_FATAL( "Unable to retrieve " << m_trackParticleCollectionName );
-      return StatusCode::FAILURE;
-    }
-  }else{
-    // in case nothing is found return
-    return StatusCode::SUCCESS;
+  SG::ReadHandle<xAOD::TrackParticleContainer> trackParticles(m_trackParticleCollectionHandle);  
+  ATH_MSG_DEBUG("retrieved "<< m_trackParticleCollectionHandle.key()<< " size ="<< trackParticles->size() );
+  
+  // pre-calculate a width of clusters, set it as dynamica attribute so we don't have to recalculate it
+  SG::ReadHandle<xAOD::CaloClusterContainer> clusterContainer(m_caloClusters);
+  ATH_MSG_DEBUG("retrieved "<< m_caloClusters.key() << " size = "<< clusterContainer->size() );
+  static SG::AuxElement::Decorator<float> sig_dec("sigmaWidth");
+  //for(const xAOD::CaloCluster *cl : *clusterContainer){
+  for(const xAOD::CaloCluster *cl : *clusterContainer){
+    double rad;
+    cl->retrieveMoment(xAOD::CaloCluster::SECOND_R,rad);
+    double cent;
+    cl->retrieveMoment(xAOD::CaloCluster::CENTER_MAG,cent);
+    double sigmaWidth = atan(sqrt(rad)/cent)*cosh(cl->eta());
+    sig_dec(*cl) = sigmaWidth;
   }
 
-  // create strings for locations based on input track collection
-  // std::string clusterContainerName = m_trackParticleCollectionName + "AssociatedClusters" + m_outputPostFix;
-  std::string associationContainerName = m_trackParticleCollectionName + "ClusterAssociations" + m_outputPostFix;
 
-  // Create the xAOD container and its auxiliary store:
-  xAOD::TrackParticleClusterAssociationContainer* xaoda = new xAOD::TrackParticleClusterAssociationContainer();
-  ATH_CHECK( evtStore()->record( xaoda, associationContainerName ) );
+  // obtain the CaloExtension from the map in the event store
+  SG::ReadHandle<CaloExtensionCollection> caloExts( m_caloExtKey );
+  ATH_MSG_DEBUG("CaloExtensionCollection "<< m_caloExtKey.key() << "  : size="<< caloExts->size() );
 
-  xAOD::TrackParticleClusterAssociationAuxContainer* auxa = new xAOD::TrackParticleClusterAssociationAuxContainer();
-  ATH_CHECK( evtStore()->record( auxa, associationContainerName + "Aux." ) );
-  xaoda->setStore( auxa );
-  ATH_MSG_DEBUG( "Recorded TrackParticleClusterAssociationContainer with key: " << associationContainerName );    
+  const xAOD::Vertex * pv0 = nullptr;
+  if(!m_vertexContHandle.empty()){
+    SG::ReadHandle<xAOD::VertexContainer> vxCont(m_vertexContHandle);
+    if(!vxCont->empty()) pv0=(*vxCont)[0]; // Hard code HS vertex as PV0
+  }
 
+  SG::WriteDecorHandle<xAOD::TrackParticleContainer,
+		       std::vector<ElementLink<xAOD::CaloClusterContainer>> > assoClustDecor(m_assocClustersDecor);
+    
+  ATH_MSG_DEBUG("will decorate with "<<assoClustDecor.key()<< " and adding trkParam : "<< m_caloEntryParsDecor.key()  );
+
+  // ******************************************
+  // main loop over tracks 
   unsigned int ntracks = 0;
-  for( unsigned int i=0;i<trackParticles->size();++i ){
+  for( const xAOD::TrackParticle* tp : *trackParticles){
+
 
-    // slect track
-    const xAOD::TrackParticle* tp = (*trackParticles)[i];
-    // if( !m_trackSelector->decision(*tp) || tp->pt() < m_ptCut ) continue;
     if( tp->pt() < m_ptCut ) continue;
 
-    // get ParticleCellAssociation
-    ATH_MSG_DEBUG(" Selected track: pt " << tp->pt() << " eta " << tp->eta() << " phi " << tp->phi() );
-    const Rec::ParticleClusterAssociation* association = 0;
-    if( !m_caloClusterAssociationTool->particleClusterAssociation(*tp,association,0.1) ){
-      ATH_MSG_DEBUG("failed to obtain the ParticleClusterAssociation");
-      continue;
-    }
+    if( pv0 != nullptr) if(! m_trackvertexassoTool->isCompatible(*tp, *pv0 )) continue;
+    
+    ATH_MSG_DEBUG(" Selected track " << tp->index() << "  pt " << tp->pt() << " eta " << tp->eta() << " phi " << tp->phi() );
 
-    // require container as it should be there
-    if( !association->container() ){
-      ATH_MSG_WARNING("Failed to obtain CaloClusterContainer from ParticleCellAssociation");
+
+    // IMMPORTANT : this assumes a correspondance between the TrackParticleContainer and the CaloExtensionCollection !
+    const Trk::CaloExtension * caloExtension = (*caloExts)[tp->index() ] ;
+    if (caloExtension == nullptr ) {
+      ATH_MSG_DEBUG(" Selected track "<< tp->index() << " has no caloExtension ");
       continue;
     }
-    
-    // create element links
-    ElementLink< xAOD::TrackParticleContainer > trackLink(m_trackParticleCollectionName,i);
-    std::vector< ElementLink< xAOD::CaloClusterContainer > > caloClusterLinks;
-    
-    for(auto cluster : association->data())
-    {
-        ElementLink< xAOD::CaloClusterContainer >   clusterLink(m_caloClusters,cluster->index());
-        // if valid create TrackParticleClusterAssociation
-        if( clusterLink.isValid() ){
-            caloClusterLinks.push_back( clusterLink );
-        }
-        ATH_MSG_DEBUG(" New cluster: eta " << cluster->eta() << " phi " << cluster->phi() );
-    }
-    
-    if( trackLink.isValid() && caloClusterLinks.size()!=0){
-        xAOD::TrackParticleClusterAssociation* trackAssociation = new xAOD::TrackParticleClusterAssociation();
-        xaoda->push_back(trackAssociation);
-        trackAssociation->setTrackParticleLink( trackLink );
-        trackAssociation->setCaloClusterLinks(caloClusterLinks);
-        ATH_MSG_DEBUG("added association");
-        ++ntracks;
-    }
-    else{
-        if( !trackLink.isValid() )   ATH_MSG_WARNING("Failed to create track ElementLink ");
-        if( caloClusterLinks.size()==0 ) ATH_MSG_VERBOSE("Failed to create cluster ElementLink - this is probably a trackonly TCC ");
+
+
+    // build the associated clusters
+    std::vector<const xAOD::CaloCluster*> assoClusters = associatedClusters( *caloExtension, *clusterContainer); 
+
+
+    // retrieve the vector of links to cluster (and creating it )
+    std::vector< ElementLink< xAOD::CaloClusterContainer > > & caloClusterLinks = assoClustDecor(*tp);
+    // translate in ElementLink
+    caloClusterLinks.reserve( assoClusters.size() );
+    for(const xAOD::CaloCluster* cluster : assoClusters) caloClusterLinks.emplace_back( *clusterContainer,cluster->index() );
+    ntracks++;     
+  }// end loop over tracks
+
+  // 2nd loop over track, only to decorate with Track parameter if requested.
+  if (! m_caloEntryParsDecor.empty() ){
+    // we can not do this in the above loop because declaring a WriteDecorHandle requires a non empty key
+    //  (otherwise : run-time error).
+    SG::WriteDecorHandle<xAOD::TrackParticleContainer,  const Trk::TrackParameters*> trkParamDecor( m_caloEntryParsDecor );
+    for( const xAOD::TrackParticle* tp : *trackParticles){
+      const Trk::CaloExtension * caloExtension = (*caloExts)[tp->index() ] ;
+      if (caloExtension == nullptr ) trkParamDecor( *tp ) =  nullptr ;
+      else trkParamDecor( *tp ) = caloExtension->caloEntryLayerIntersection();      
     }
-   
-  }
 
+  }
+  
   ATH_MSG_DEBUG(" Total number of selected tracks: " << ntracks );
 
-  // if (CaloClusterStoreHelper::finalizeClusters(&(*evtStore()), xaod,clusterContainerName,msg()).isFailure() ) 
-    // ATH_MSG_WARNING("finalizeClusters failed");
-
   return StatusCode::SUCCESS;
 }
 
 
-StatusCode TrackParticleClusterAssociationAlg::finalize()
-{
-  return StatusCode::SUCCESS;
+std::vector<const xAOD::CaloCluster* > TrackParticleClusterAssociationAlg::associatedClusters(const Trk::CaloExtension & caloExtension, const xAOD::CaloClusterContainer & allClusters ){
+
+  std::vector<const xAOD::CaloCluster* > clusters;
+
+  const Trk::TrackParameters*  pars = caloExtension.caloEntryLayerIntersection();
+  if(!pars) {
+    ATH_MSG_WARNING( " NO TrackParameters caloExtension.caloEntryLayerIntersection() ");
+    return clusters;
+  } 
+    
+  float eta = pars->position().eta();
+  float phi = pars->position().phi();
+
+  double uncertEta = 0.;
+  double uncertPhi = 0.;
+  if(pars->covariance()) {
+    uncertEta = -2.*sin(pars->position().theta()) / (cos(2.*pars->position().theta())-1.) * sqrt((*pars->covariance())(Trk::theta,Trk::theta));
+    uncertPhi = sqrt((*pars->covariance())(Trk::phi,Trk::phi));
+  } 
+  double uncertExtrp = uncertEta*uncertEta + uncertPhi*uncertPhi;
+
+  float dr2Cut0 = m_dr*m_dr;
+  // to access the pre-calculated width :
+  static SG::AuxElement::ConstAccessor<float> sig_acc("sigmaWidth");
+
+  for(const xAOD::CaloCluster * cl : allClusters){
+
+    float dPhi = P4Helpers::deltaPhi( cl->phi(), phi);
+    float dEta = cl->eta()-eta;
+    float dr2  = dPhi*dPhi+ dEta*dEta;
+    float dr2Cut = dr2Cut0;
+    
+    if(m_useCovariance) {                        
+      
+      double sigmaWidth = sig_acc(*cl);          
+      double uncertClus  = 2.*sigmaWidth*sigmaWidth;
+      if(uncertExtrp>uncertClus){
+	ATH_MSG_DEBUG("Extrapolation uncertainty larger than cluster width! Returning without association.");
+	continue;
+      }
+      
+      dr2Cut = (sigmaWidth+uncertEta)*(sigmaWidth+uncertEta)+(sigmaWidth+uncertPhi)*(sigmaWidth+uncertPhi);   
+    }
+    if( dr2 < dr2Cut ) clusters.push_back( cl );    
+  }
+
+  return clusters;
 }
diff --git a/Reconstruction/RecoAlgs/TrackParticleAssociationAlgs/src/TrackParticleClusterAssociationAlg.h b/Reconstruction/RecoAlgs/TrackParticleAssociationAlgs/src/TrackParticleClusterAssociationAlg.h
index c1fe43b908c..8399686db44 100644
--- a/Reconstruction/RecoAlgs/TrackParticleAssociationAlgs/src/TrackParticleClusterAssociationAlg.h
+++ b/Reconstruction/RecoAlgs/TrackParticleAssociationAlgs/src/TrackParticleClusterAssociationAlg.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef TRACKPARTICLEASSOCIATIONALGS_TRACKPARTICLECLUSTERASSOCIATIONALG_H
@@ -7,37 +7,67 @@
 
 #include "AthenaBaseComps/AthAlgorithm.h"
 #include "GaudiKernel/ToolHandle.h"
-#include <string>
+#include "StoreGate/ReadHandleKey.h"
+#include "StoreGate/WriteHandleKey.h"
+#include "StoreGate/WriteDecorHandleKey.h"
+
+#include "xAODCaloEvent/CaloClusterContainer.h"
+#include "xAODTracking/VertexContainer.h"
+#include "xAODTracking/TrackParticleContainer.h"
+#include "TrkCaloExtension/CaloExtensionCollection.h"
 
+#include "TrackVertexAssociationTool/ITrackVertexAssociationTool.h"
 
-namespace Rec {
-  class IParticleCaloClusterAssociationTool;
-}
-namespace Trk {
-  class ITrackSelectorTool;
-}
+#include <string>
 
+//////////////////////////////////////////////////////////
+/// \class TrackParticleClusterAssociationAlg
+/// Associate clusters to each track based on its extrapolation to the calo.
+///
+/// This alg reads in a CaloExtensionCollection corresponding to a TrackParticleContainer.
+/// It then decorates each TrackParticleContainer with a vector<EL<CaloCluster>> containing
+/// the clusters close enough (DeltaR property) w.r.t CaloExtension corresponding to the track.
+/// Optionnaly tracks are also decorated with a const Trk::TrackParameters* obtain from
+/// caloExtension->caloEntryLayerIntersection().
+///
+/// Note: In earlier versions this alg was creating 2 maps a xAODAssociations/TrackParticleClusterAssociationContainer
+/// and a Rec::ParticleClusterAssociation and was using ParticleCaloClusterAssociationTool to retrieve the extrapolation
+/// and perform the clusters association.
+/// All of this was suppress or replaced in order to simplify the procedure.
 class TrackParticleClusterAssociationAlg : public AthAlgorithm
 {
  public:
   TrackParticleClusterAssociationAlg(const std::string& name, ISvcLocator* pSvcLocator);
 
-  ~TrackParticleClusterAssociationAlg();
 
-  StatusCode initialize();
-  StatusCode execute();
-  StatusCode finalize();
+  StatusCode initialize() override ;
+  StatusCode execute() override ;
+
 
  private:
 
-  ToolHandle<Rec::IParticleCaloClusterAssociationTool> m_caloClusterAssociationTool;
-  ToolHandle <Trk::ITrackSelectorTool>              m_trackSelector; //!< Tool to select tracks
+  /// returns the clusters from allClusters which are close enough to caloExtensions
+  std::vector<const xAOD::CaloCluster* > associatedClusters(const Trk::CaloExtension & caloExtensions, const xAOD::CaloClusterContainer & allClusters) ;
+  
+  
 
-  std::string m_trackParticleCollectionName;
-  double m_ptCut;
-  std::string m_outputPostFix;
-  std::string m_caloClusters;
-};
+  Gaudi::Property<float> m_dr {this, "DeltaR", 0.1, "max deltaR to match track and cluster" };
+  Gaudi::Property<bool> m_useCovariance {this, "UseCovariance", true, "use covariance from TrkParameters to evaluate angular uncertainties"};
+  Gaudi::Property<double> m_ptCut {this, "PtCut", 25000., ""};
 
+  // input containers
+  SG::ReadHandleKey<CaloExtensionCollection> m_caloExtKey {this, "CaloExtensionName", "", ""};
+  SG::ReadHandleKey<xAOD::TrackParticleContainer> m_trackParticleCollectionHandle {this,"TrackParticleContainerName",  "InDetTrackParticles", "input tracks" };
+  SG::ReadHandleKey<xAOD::CaloClusterContainer> m_caloClusters {this, "CaloClusterLocation", "CaloCalTopoClusters","input calo clusters"};
+
+  // vertex handling
+  SG::ReadHandleKey<xAOD::VertexContainer> m_vertexContHandle {this, "VertexContainerName", "", "if empty all tracks will be decorated. if not only those corresponding to the PV[0] will."};
+  ToolHandle<CP::ITrackVertexAssociationTool> m_trackvertexassoTool {this, "TrackVertexAssoTool", "" };
+
+
+  // decorations 
+  SG::WriteDecorHandleKey<xAOD::TrackParticleContainer> m_assocClustersDecor {this, "AssociatedClusterDecorKey" , "", "Decoration key to store associated clusters. IMPORTANT  must be consistent with TrackParticleContainer" };
+  SG::WriteDecorHandleKey<xAOD::TrackParticleContainer> m_caloEntryParsDecor {this, "CaloEntryParsDecorKey" , "", "Decoration name to store trk parameters to calo entry (if non blank). IMPORTANT : must be consistent with TrackParticleContainer" };
+};
 
 #endif
diff --git a/Reconstruction/RecoTools/RecoToolInterfaces/RecoToolInterfaces/IParticleCaloClusterAssociationTool.h b/Reconstruction/RecoTools/RecoToolInterfaces/RecoToolInterfaces/IParticleCaloClusterAssociationTool.h
index 2790b2d7bd5..51d32bdcbf5 100644
--- a/Reconstruction/RecoTools/RecoToolInterfaces/RecoToolInterfaces/IParticleCaloClusterAssociationTool.h
+++ b/Reconstruction/RecoTools/RecoToolInterfaces/RecoToolInterfaces/IParticleCaloClusterAssociationTool.h
@@ -40,7 +40,7 @@ namespace Rec
         @return true if the call was successful
     */
     virtual bool particleClusterAssociation( const xAOD::IParticle& particle,  const ParticleClusterAssociation*& association, float dr, 
-                                             const xAOD::CaloClusterContainer* container = 0, bool useCaching = true ) const = 0;
+                                             const xAOD::CaloClusterContainer* container, bool useCaching = true ) const = 0;
 
     static const InterfaceID& interfaceID( ) ;
   };
diff --git a/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloClusterAssociationTool.cxx b/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloClusterAssociationTool.cxx
deleted file mode 100644
index bc87f568f39..00000000000
--- a/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloClusterAssociationTool.cxx
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
-  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
-*/
-
-#include "ParticleCaloClusterAssociationTool.h"
-// forward declares
-
-#include "ParticleCaloExtension/ParticleClusterAssociationCollection.h"
-#include "ParticlesInConeTools/ICaloClustersInConeTool.h"
-
-#include "TrkCaloExtension/CaloExtension.h"
-#include "TrkCaloExtension/CaloExtensionHelpers.h"
-
-#include "FourMomUtils/P4Helpers.h"
-
-#include "CaloGeoHelpers/CaloSampling.h"
-
-#include "TrackCaloClusterRecTools/IParticleToCaloExtensionMap.h"
-#include "xAODTracking/VertexContainer.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"),
-      m_caloClusters("CaloCalTopoClusters"),
-      m_caloEntryMapName("ParticleToCaloExtensionMap")
-  {
-    declareInterface<IParticleCaloClusterAssociationTool>(this);
-    declareProperty("ParticleCaloExtensionTool",   m_caloExtensionTool );
-    declareProperty("ClustersInConeTool",          m_clustersInConeTool);
-    declareProperty("CaloClusterLocation",         m_caloClusters);
-    declareProperty("AssociationCollectionName",   m_assCollection);
-    declareProperty("ParticleCaloEntryMapName",    m_caloEntryMapName);
-    //coneSize for including calo cells around track
-    declareProperty("ConeSize",                    m_coneSize = 0.1);
-    declareProperty("UseCovariance",               m_useCovariance = true);
-  }
-
-  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(" particleClusterAssociation: ptr " << &particle << " dr " << dr << " useCaching " << useCaching);
-
-    // reset pointer
-    association = nullptr;
-    // 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,particle);    
-            theAssociation->updateData(std::move(clusters),dr);
-          }
-          association = theAssociation;
-          ATH_MSG_DEBUG("Found existing calo extension");
-          return true;
-        }
-      }
-    }
-
-    // get the extrapolation into the calo
-    std::unique_ptr<Trk::CaloExtension> caloExtension = m_caloExtensionTool->caloExtension(particle);
-    if( caloExtension==nullptr ) {
-      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 cluster container if not provided, return false it retrieval failed
-    if( !container && !(container = getClusterContainer()) ) {
-      ATH_MSG_DEBUG("Failed to get calo cluster container");      
-      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.get()),dr,clusters,particle);    
-    
-    association = new ParticleClusterAssociation( caloExtension.release(), std::move(clusters), dr, container );
-
-    // now add particle and CaloExtension to the container
-    IParticleToCaloExtensionMap * caloExtensionMap = nullptr;
-    if(not evtStore()->contains<IParticleToCaloExtensionMap>(m_caloEntryMapName)) {
-      caloExtensionMap = new IParticleToCaloExtensionMap();
-      if (evtStore()->record(caloExtensionMap, m_caloEntryMapName).isFailure()) {
-	ATH_MSG_WARNING( "Failed to record output collection, will leak the ParticleCaloExtension");
-	delete caloExtensionMap;
-	caloExtensionMap = nullptr;
-      }
-    } else {
-      if(evtStore()->retrieve(caloExtensionMap,m_caloEntryMapName).isFailure()) {
-	ATH_MSG_WARNING( "Unable to retrieve ParticleToCaloExtensionMap will leak the ParticleCaloExtension" );
-      }
-    }
-    if (caloExtensionMap)
-      caloExtensionMap->addEntry(&particle,caloExtension->caloEntryLayerIntersection());
-         
-    return true;
-    
-  }
-  
-  void ParticleCaloClusterAssociationTool::associateClusters( const xAOD::CaloClusterContainer* container, 
-                                                              const Trk::CaloExtension& caloExtension,
-                                                              float dr,
-                                                              ParticleClusterAssociation::Data& clusters, 
-                                                              const xAOD::IParticle& particle) const {    
-
-    particle.auxdecor<int>("ParticleCaloClusterAssociationTool")    = 1;
-
-    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(m_useCovariance) {
-            double uncertEta = 0.;
-            double uncertPhi = 0.;
-            if(pars->covariance()) {
-              uncertEta = -2.*sin(pars->position().theta()) / (cos(2.*pars->position().theta())-1.) * sqrt((*pars->covariance())(Trk::theta,Trk::theta));
-              uncertPhi = sqrt((*pars->covariance())(Trk::phi,Trk::phi));
-            } 
-            
-            float eInSample = 0.; 
-            float eInSampleFull = 0.; 
-            float emfrac = 0.; 
-            for (int s=0;s<CaloSampling::Unknown; s++){
-                eInSampleFull += (*container)[i]->eSample(CaloSampling::CaloSample(s));
-            }
-            eInSample += (*container)[i]->eSample(CaloSampling::EMB1);
-            eInSample += (*container)[i]->eSample(CaloSampling::EMB2);
-            eInSample += (*container)[i]->eSample(CaloSampling::EMB3);
-            eInSample += (*container)[i]->eSample(CaloSampling::EME1);
-            eInSample += (*container)[i]->eSample(CaloSampling::EME2);
-            eInSample += (*container)[i]->eSample(CaloSampling::EME3);
-            eInSample += (*container)[i]->eSample(CaloSampling::FCAL1);
-            
-            emfrac  = eInSample/eInSampleFull;
-            if ( emfrac > 1.0 ) emfrac = 1.;
-            if ( emfrac < 0.0 ) emfrac = 0.;
-            
-            double rad;
-            (*container)[i]->retrieveMoment(xAOD::CaloCluster::SECOND_R,rad);
-            double cent;
-            (*container)[i]->retrieveMoment(xAOD::CaloCluster::CENTER_MAG,cent);
-            double sigmaWidth = atan(sqrt(rad)/cent)*cosh((*container)[i]->eta());
-            double uncertExtrp = uncertEta*uncertEta + uncertPhi*uncertPhi;
-            double uncertClus  = 2.*sigmaWidth*sigmaWidth;
-	    	    
-            if(uncertExtrp>uncertClus){
-              ATH_MSG_DEBUG("Extrapolation uncertainty larger than cluster width! Returning without association.");
-	      continue;
-            }
-            
-            double dr2CutTmp = (sigmaWidth+uncertEta)*(sigmaWidth+uncertEta)+(sigmaWidth+uncertPhi)*(sigmaWidth+uncertPhi);
-            
-            if(sqrt(dr2)<sqrt(dr2Cut) && dr2 < dr2CutTmp) ATH_MSG_DEBUG("1. selections match! dR " << sqrt(dr2) << " new cut value " << sqrt(dr2CutTmp) << " pt trk " << pars->pT() << " sigma(phi) trk " << uncertPhi << " sigma(eta) trk " << uncertEta << " energy cluster " << (*container)[i]->e() << " sigma width " << sigmaWidth << " em frac " << emfrac);
-	    if(sqrt(dr2)<sqrt(dr2Cut) && dr2 > dr2CutTmp) ATH_MSG_DEBUG("2. only  dR matches! dR " << sqrt(dr2) << " new cut value " << sqrt(dr2CutTmp) << " pt trk " << pars->pT() << " sigma(phi) trk " << uncertPhi << " sigma(eta) trk " << uncertEta << " energy cluster " << (*container)[i]->e() << " sigma width " << sigmaWidth << " em frac " << emfrac);
-	    if(sqrt(dr2)>sqrt(dr2Cut) && dr2 < dr2CutTmp) ATH_MSG_DEBUG("3. only new matches! dR " << sqrt(dr2) << " new cut value " << sqrt(dr2CutTmp) << " pt trk " << pars->pT() << " sigma(phi) trk " << uncertPhi << " sigma(eta) trk " << uncertEta << " energy cluster " << (*container)[i]->e() << " sigma width " << sigmaWidth << " em frac " << emfrac);           
-            
-	    dr2Cut = dr2CutTmp;
-        }
-        
-        if( dr2 < dr2Cut )
-	  clusters.push_back( (*container)[i]);
-      }
-    } else {
-      ATH_MSG_DEBUG("We're at the clustersinconetool." );
-      if( !m_clustersInConeTool->particlesInCone(eta,phi,dr,clusters) ) {
-        ATH_MSG_WARNING("Failed to get clusters");
-      }
-    }
-  }
-  
-  const xAOD::CaloClusterContainer* ParticleCaloClusterAssociationTool::getClusterContainer() const {
-
-    const xAOD::CaloClusterContainer* container = nullptr;
-    //retrieve the cell container
-    if( evtStore()->retrieve(container, m_caloClusters).isFailure() || !container ) {
-      ATH_MSG_WARNING( "Unable to retrieve the cluster container  " << m_caloClusters << " container ptr " << container );
-      return nullptr;
-    }
-    if( container ) ATH_MSG_DEBUG("Retrieved cluster container " << container->size());
-    return container;
-  }
-
-} // end of namespace Rec
diff --git a/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloClusterAssociationTool.h b/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloClusterAssociationTool.h
deleted file mode 100644
index 13ec089aa7d..00000000000
--- a/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloClusterAssociationTool.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
-  Copyright (C) 2002-2018 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"
-
-#include "RecoToolInterfaces/IParticleCaloExtensionTool.h"
-#include "TrackVertexAssociationTool/ITrackVertexAssociationTool.h"
-#include "CxxUtils/checker_macros.h"
-namespace Trk {
-  class CaloExtension;
-}
-namespace xAOD {
-  class ICaloClustersInConeTool;
-}
-namespace Rec {
-
-  /* Mark as not ATLAS_NOT_THREAD_SAFE
-   * as it still uses the old style caching
-   * to be updated if needed
-   */
-  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 xAOD::IParticle& particle) const;
-    
-    const xAOD::CaloClusterContainer* getClusterContainer() const;
-
-    ToolHandle< Trk::IParticleCaloExtensionTool >  m_caloExtensionTool;
-    // FIXME: mutable
-    ToolHandle< xAOD::ICaloClustersInConeTool >     m_clustersInConeTool;
-    std::string m_caloClusters;
-    std::string m_assCollection;
-    std::string m_caloEntryMapName;
-    double      m_coneSize;
-    bool        m_useCovariance;
-
-  };
-
-
-}
-
-#endif
diff --git a/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloExtensionTool.cxx b/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloExtensionTool.cxx
index 512ba3a7994..42aaa002f06 100644
--- a/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloExtensionTool.cxx
+++ b/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloExtensionTool.cxx
@@ -183,6 +183,8 @@ ParticleCaloExtensionTool::caloExtension( const EventContext& ctx,
    */
 
   ParticleHypothesis particleType = m_particleType;
+
+  ATH_MSG_DEBUG("caloExtension for tracks. "<< particleType << "  index= "<< particle.index() );
   
   if(m_particleType == electron || 
      particle.particleHypothesis() ==  xAOD::electron ){  
@@ -248,13 +250,12 @@ ParticleCaloExtensionTool::caloExtension( const EventContext& ctx,
  
   /* The last argument to the extrapolate  overload 
    * corresponds  to a GeometrySignature value from
-   * TrkDetDescrUtils/TrkGeometrySignature.h
-   * The extrapolation stop at 
-   * the indicated subdetector exit
+   * TrkDetDescrUtils/GeometrySignature.h
+   * The extrapolation stop at the indicated subdetector exit
    */
-
   const std::vector<std::pair<const Trk::TrackParameters *,int>>* caloParameters=
-    m_extrapolator->extrapolate(ctx, startPars, propDir, particleType, material, 3);
+    m_extrapolator->extrapolate(ctx, startPars, propDir, particleType, material, m_extrapolDetectorID); 
+
   if (material) {
     ATH_MSG_DEBUG("Got material " << material->size() );
     for( auto& m : *material ) {
@@ -279,7 +280,7 @@ ParticleCaloExtensionTool::caloExtension( const EventContext& ctx,
   const TrackParameters* muonEntry = nullptr;
   std::vector<const CurvilinearParameters*> caloLayers;
   caloLayers.reserve(caloParameters->size()-1);
-  ATH_MSG_DEBUG( " Found calo parameters: " << caloParameters->size() );
+  ATH_MSG_DEBUG( " Found calo parameters: " << caloParameters->size() << "  extrapolation exit ID="<<m_extrapolDetectorID);
 
   for( const auto& p : *caloParameters ){
     if( !p.first ) {
diff --git a/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloExtensionTool.h b/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloExtensionTool.h
index 8fee32cea60..a0587bddbca 100644
--- a/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloExtensionTool.h
+++ b/Reconstruction/RecoTools/TrackToCalo/src/ParticleCaloExtensionTool.h
@@ -22,7 +22,7 @@
 
 #include "TrkExInterfaces/IExtrapolator.h"
 #include "TrkEventPrimitives/ParticleHypothesis.h" 
-
+#include "TrkDetDescrUtils/GeometrySignature.h"
 /* 
  * xAOD includes
  */
@@ -91,6 +91,9 @@ private:
   Gaudi::Property<bool>  m_startFromPerigee{this,"StartFromPerigee",false, "Start from Perigee"};
   const AtlasDetectorID* m_detID;
   ParticleHypothesis  m_particleType ;
+
+  Gaudi::Property<unsigned int>  m_extrapolDetectorID{this,"ExtrapolationDetectorID", Trk::Calo, "The detector this tool should extrapolate through. Expects a Trk::GeometrySignature enum value."};
+  
 };
 }
 
diff --git a/Reconstruction/RecoTools/TrackToCalo/src/components/TrackToCalo_entries.cxx b/Reconstruction/RecoTools/TrackToCalo/src/components/TrackToCalo_entries.cxx
index 9f92120cee8..2795b9bb967 100644
--- a/Reconstruction/RecoTools/TrackToCalo/src/components/TrackToCalo_entries.cxx
+++ b/Reconstruction/RecoTools/TrackToCalo/src/components/TrackToCalo_entries.cxx
@@ -1,6 +1,5 @@
 #include "../ParticleCaloExtensionTool.h"
 #include "../ParticleCaloCellAssociationTool.h"
-#include "../ParticleCaloClusterAssociationTool.h"
 #include "../MuonCaloEnergyTool.h"
 #include "../CaloExtensionBuilderAlg.h"
 
@@ -8,6 +7,5 @@ using namespace Trk;
 using namespace Rec;
 DECLARE_COMPONENT( ParticleCaloExtensionTool )
 DECLARE_COMPONENT( ParticleCaloCellAssociationTool )
-DECLARE_COMPONENT( ParticleCaloClusterAssociationTool )
 DECLARE_COMPONENT( MuonCaloEnergyTool )
 DECLARE_COMPONENT( CaloExtensionBuilderAlg )
diff --git a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecAlgs/CMakeLists.txt b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecAlgs/CMakeLists.txt
new file mode 100644
index 00000000000..5d4f2610d78
--- /dev/null
+++ b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecAlgs/CMakeLists.txt
@@ -0,0 +1,19 @@
+ ################################################################################
+ # Package: TrackCaloClusterRecAlgs
+ ################################################################################
+ 
+ # Declare the package name:
+ atlas_subdir( TrackCaloClusterRecAlgs )
+ 
+ 
+ find_package( FastJet )
+ find_package( FastJetContrib ) 
+                           
+ # Component(s) in the package:
+ atlas_add_component( TrackCaloClusterRecAlgs
+                      src/*.cxx
+                      src/components/*.cxx
+                      INCLUDE_DIRS ${FASTJET_INCLUDE_DIRS} ${FASTJETCONTRIB_INCLUDE_DIRS}
+                      LINK_LIBRARIES ${FASTJET_LIBRARIES} ${FASTJETCONTRIB_LIBRARIES} AthenaBaseComps GaudiKernel AtlasDetDescr xAODBase 
+                      xAODTracking xAODAssociations xAODPFlow TrackCaloClusterRecToolsLib TrkParametersIdentificationHelpers )
+                      
diff --git a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecAlgs/TrackCaloClusterRecAlgs/TrackCaloClusterAlg.h b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecAlgs/TrackCaloClusterRecAlgs/TrackCaloClusterAlg.h
new file mode 100644
index 00000000000..c5151092e69
--- /dev/null
+++ b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecAlgs/TrackCaloClusterRecAlgs/TrackCaloClusterAlg.h
@@ -0,0 +1,51 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+#ifndef TRACKCALOCLUSTERREC_TRACKCALOCLUSTERALGS_TRACKCALOCLUSTERALG_H
+#define TRACKCALOCLUSTERREC_TRACKCALOCLUSTERALGS_TRACKCALOCLUSTERALG_H
+
+#include "AthenaBaseComps/AthAlgorithm.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "StoreGate/ReadDecorHandleKey.h"
+#include "StoreGate/WriteDecorHandleKey.h"
+
+
+#include "xAODPFlow/FlowElementContainer.h"
+#include "TrackCaloClusterRecInterfaces/ITrackCaloClusterTool.h"
+
+#include "TrackCaloClusterRecTools/TrackCaloClusterInfo.h"
+
+
+////////////////////////////////////////////////////////
+/// \class TrackCaloClusterAlg
+///
+/// Builds TrackCaloCluster after a TrackCaloClusterInfo object has been prepared and is available in
+/// the event store.
+///
+/// The 'taste' or type (TCC or UFO) of the TrackCaloCluster objects being build depends on the
+/// TCC creator tools (ITrackCaloClusterTool) attached to this alg. See the TCCTools property.
+/// 
+class TrackCaloClusterAlg: public ::AthAlgorithm { 
+public: 
+  TrackCaloClusterAlg( const std::string& name, ISvcLocator* pSvcLocator );
+    
+  virtual StatusCode  initialize() override;
+  virtual StatusCode  execute() override;
+  
+ 
+private:
+  
+  /// The tools implementting the creation of TCC
+  ToolHandleArray <ITrackCaloClusterTool> m_tccTools {this, "TCCTools", {},"List of TrackCaloClusterTool"};
+     
+  ///TrackCaloClusterInfo used by this alg
+  SG::ReadHandleKey<TrackCaloClusterInfo> m_tccInfoHandle {this, "TCCInfo", "", "the TrackCaloClusterInfo which contain the energy weights needed to split clusters/PFO onto tracks" };
+  
+  ///Cluster Collection container
+  SG::WriteHandleKey<xAOD::FlowElementContainer>  m_outputTCCHandle {this, "OutputTCCName", "TrackCaloClusters", "Name of output container to be created" };
+
+  SG::ReadHandleKey<xAOD::FlowElementContainer> m_copiedTCCHandle {this, "AppendToTCCName", "", "optionnaly, read-in an existing container, recopy and append to it with new FlowElements build by this alg."};
+
+};
+
+#endif //
diff --git a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecAlgs/TrackCaloClusterRecAlgs/TrackCaloClusterInfoAlg.h b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecAlgs/TrackCaloClusterRecAlgs/TrackCaloClusterInfoAlg.h
new file mode 100644
index 00000000000..fa710bb4ebd
--- /dev/null
+++ b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecAlgs/TrackCaloClusterRecAlgs/TrackCaloClusterInfoAlg.h
@@ -0,0 +1,97 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRACKCALOCLUSTERREC_TRACKCALOCLUSTERALGS_TRACKCALOCLUSTERINFOALG_H
+#define TRACKCALOCLUSTERREC_TRACKCALOCLUSTERALGS_TRACKCALOCLUSTERINFOALG_H
+
+#include "AthenaBaseComps/AthAlgorithm.h"
+#include "GaudiKernel/ToolHandle.h" 
+#include "StoreGate/ReadHandleKey.h"
+#include "StoreGate/ReadDecorHandleKey.h"
+#include "StoreGate/WriteHandleKey.h"
+
+#include "xAODCaloEvent/CaloClusterContainer.h"
+#include "xAODTracking/VertexContainer.h"
+#include "xAODTracking/TrackParticleContainer.h"
+#include "xAODPFlow/PFOContainer.h"
+
+#include "TrackVertexAssociationTool/ITrackVertexAssociationTool.h"
+
+#include "TrackCaloClusterRecTools/TrackCaloClusterInfo.h"
+
+
+////////////////////////////////////////////////////////
+/// \class TrackCaloClusterInfoAlg
+///
+/// Builds a TrackCaloClusterInfo map which contains the weights needed to build TrackCaloCluster objects.
+/// This TrackCaloClusterInfo is then expected to be used by a TrackCaloClusterAlg and its tools.
+///
+/// \authors : Naomie Calace, P-A Delsart
+
+class TrackCaloClusterInfoAlg: public ::AthAlgorithm { 
+public: 
+  TrackCaloClusterInfoAlg( const std::string& name, ISvcLocator* pSvcLocator );
+  virtual ~TrackCaloClusterInfoAlg() {}
+  
+  virtual StatusCode  initialize() override;
+  virtual StatusCode  execute() override ;
+  
+  
+protected:
+  virtual  StatusCode fillInfo(SG::WriteHandle<TrackCaloClusterInfo> & tccInfo) const ;
+  
+  ///TrackCaloClusterInfo created by this alg
+  SG::WriteHandleKey<TrackCaloClusterInfo> m_tccInfoHandle {this, "TCCInfoName","TCCInfo","Name of TrackCaloClusterInfo to be created" };
+
+
+  
+  ///Tracks  used by this alg
+  SG::ReadHandleKey< xAOD::TrackParticleContainer > m_inputTracksHandle {this, "InputTracks", "InDetTrackParticles", ""};
+  /// Decoration of tracks expected by this alg (set by TrackParticleClusterAssociationAlg)
+  SG::ReadDecorHandleKey<xAOD::TrackParticleContainer> m_assoClustersKey{this, "AssoClustersDecor", "", "Key to access clusters associated to a track. IMPORTANT must be consistent with TrackParticleContainer "};
+
+  ///Original clusters from which the m_inputObjectName are build ()
+  SG::ReadHandleKey<xAOD::CaloClusterContainer> m_inputClustersHandle {this, "InputClusters", "CaloCalTopoClusters","input calo clusters"};
+  
+  SG::ReadHandleKey<xAOD::VertexContainer> m_inputVertexHandle {this, "VertexContainer", "PrimaryVertices", "IMPORTANT : if blank all tracks will be considered, else only those from the PV[0] of VertexContainer"};
+  
+  /// use cluster energy or pt?
+  Gaudi::Property<bool> m_useEnergy {this, "UseEnergy", false,"wether to cut on E or pT"};
+
+};
+
+
+
+
+
+////////////////////////////////////////////////////////
+/// \class TrackCaloClusterInfoUFOAlg
+///
+/// Builds a TrackCaloClusterInfo map using PFO as input.
+///
+/// \authors : P-A Delsart, Jennifer Roloff
+
+class TrackCaloClusterInfoUFOAlg: public TrackCaloClusterInfoAlg { 
+public: 
+  TrackCaloClusterInfoUFOAlg( const std::string& name, ISvcLocator* pSvcLocator );
+
+  virtual StatusCode  initialize() override;
+  
+protected:
+
+  virtual StatusCode fillInfo(SG::WriteHandle<TrackCaloClusterInfo> & tccInfo) const override;
+
+
+  SG::ReadHandleKey< xAOD::PFOContainer > m_inputPFOHandle {this, "InputPFO", "", ""};
+  SG::ReadDecorHandleKey<xAOD::PFOContainer> m_orig_pfo{this, "OriginPFO", "Origin_pfo", "Key to access original un-modified pfo"};
+
+  
+  /// cluster with E below this cut won't be considered in the TCC alg. WARNING cut must be configured as in UFOTool
+  Gaudi::Property<float> m_clusterEcut{this , "ClusterECut", 0, " Impotant !! : must be the same value as in UFOTool"};
+
+  ToolHandle<CP::ITrackVertexAssociationTool> m_trackVertexAssoTool {this, "TrackVertexAssoTool", "" };
+
+};
+
+#endif //
diff --git a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecAlgs/share/TrackCaloClusterExample_jobOptions.py b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecAlgs/share/TrackCaloClusterExample_jobOptions.py
new file mode 100644
index 00000000000..1c5b42b8163
--- /dev/null
+++ b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecAlgs/share/TrackCaloClusterExample_jobOptions.py
@@ -0,0 +1,154 @@
+#########################################################
+## This jobOptions demonstrates how to run reconstruction of
+##  TCC and UFO objects.
+##
+## See also older (and probably deprecated) example for TCC only in TrackCaloClusterReco_Standalone.py and TrackCaloClusterReco_TrackClusterInfo.py
+##########################################################
+
+
+# ***************************
+# Set-up input and athena geometry
+import AthenaPoolCnvSvc.ReadAthenaPool
+
+from AthenaCommon import CfgMgr
+
+InputFiles = ["AOD.13485488._000001.pool.root.1"]
+
+svcMgr.EventSelector.InputCollections = InputFiles
+
+from AthenaCommon.AthenaCommonFlags import athenaCommonFlags
+athenaCommonFlags.FilesInput = svcMgr.EventSelector.InputCollections
+
+# not sure the lines below are strictlyy necessary (?)
+from AthenaCommon.GlobalFlags import globalflags
+DetDescrVersion = 'ATLAS-R2-2016-01-00-01' #ATLAS-R2-2015-03-01-00
+globalflags.DetDescrVersion = DetDescrVersion
+
+from IOVDbSvc.CondDB import conddb
+conddb.setGlobalTag('OFLCOND-MC15c-SDR-09')
+
+print "globalflags.DetDescrVersion = ", globalflags.DetDescrVersion
+# Set up geometry and BField
+include("RecExCond/AllDet_detDescr.py")
+
+
+
+# ***************************
+# Access the algorithm sequence:
+from AthenaCommon.AlgSequence import AlgSequence
+topSequence = AlgSequence()
+
+
+
+# *********************************************
+# *********************************************
+# Setup TCC and UFO
+
+# Set the source of cluster and tracks :
+caloClusterName="CaloCalTopoClusters"
+trackParticleName="InDetTrackParticles"
+
+from TrackCaloClusterRecTools.TrackCaloClusterConfig import runTCCReconstruction, setupTrackCaloAssoc, runUFOReconstruction
+
+# Schedule TCC in the topSequence
+tccAlg = runTCCReconstruction(topSequence,ToolSvc, caloClusterName, trackParticleName)
+
+
+# scheduling UFO is a bit more complex.
+# We firts need to prepar a unified PFlow collection.
+# We choose a LC scale pflow, with origin of neutrals corrected to the PV0
+
+# we need to import the jet config helpers :
+from JetRec.JetRecStandardToolManager import jtm
+from JetRecTools.JetRecToolsConfig import ctm
+from JetRecTools.JetRecToolsConf import  JetConstituentModSequence, SoftKillerWeightTool, ConstituentSubtractorTool, ChargedHadronSubtractionTool, CorrectPFOTool
+  
+ctm.add(CorrectPFOTool("correctpfoLC",   WeightPFOTool = jtm.pflowweighter, InputIsEM=True, CalibratePFO=True, CorrectNeutral=True,InputType = 3), alias='correctpfoLC')
+ctm.add(ChargedHadronSubtractionTool("pfochs", InputType = 3), alias='pfochs')
+
+import ROOT
+from ROOT import xAOD
+xAOD.Type.ObjectType
+
+
+# here we prepare a tool building our unified PFlow container. The prefix of the output collection is 'PlainLC'
+pflowLCSeq = ctm.buildConstitModifSequence( 'ConstitLCSeq',
+                                              OutputContainer = 'PlainLC',
+                                              InputContainer= 'JetETMiss',
+                                              InputType = 3,
+                                              modList = [ 'correctpfoLC', 'pfochs'] ,
+)
+
+
+# now schedule this tool as par of a JetAlgorithm (this doesn't run a jet alg, just the above pflowLCSeq tool)
+from JetRec.JetRecConf import JetAlgorithm
+clustSeqAlg = JetAlgorithm("ClusterModifiers", Tools = [pflowLCSeq])
+topSequence += clustSeqAlg
+
+# Finally we can run the UFO building taking our unified PFlow container as input
+lcufoAlg = runUFOReconstruction(topSequence,ToolSvc, PFOPrefix="PlainLC")
+
+
+
+
+# *********************************************
+# *********************************************
+# We create a DAOD output using the DerivationFramework
+# We just put the container we created
+
+from DerivationFrameworkCore.DerivationFrameworkMaster import *
+streamName = 'StreamDAOD_TESTTCC'
+fileName = "TestTCCDAOD.root"
+TESTTCCStream = MSMgr.NewPoolRootStream( streamName, fileName )
+
+from DerivationFrameworkCore.DerivationFrameworkCoreConf import DerivationFramework__DerivationKernel
+DerivationFrameworkJob += CfgMgr.DerivationFramework__DerivationKernel("TESTTCCKernel")
+TESTTCCStream.AcceptAlgs(["TESTTCCKernel"])
+
+from DerivationFrameworkCore.SlimmingHelper import SlimmingHelper
+TESTTCCSlimmingHelper = SlimmingHelper("TESTTCCSlimmingHelper")
+
+
+
+
+TESTTCCSlimmingHelper.AppendToDictionary["EventInfo"] = 'xAOD::EventInfo'
+TESTTCCSlimmingHelper.AppendToDictionary['EventInfoAux'] = 'xAOD::EventAuxInfo'
+TESTTCCSlimmingHelper.ExtraVariables +=[ 'EventInfo.mcChannelNumber.mcEventNumber.streamTagRobs.streamTagDets.mcEventWeights.averageInteractionsPerCrossing.actualInteractionsPerCrossing.eventNumber.runNumber.nPV' ]
+
+cont = 'CaloCalTopoClusters'
+TESTTCCSlimmingHelper.AppendToDictionary[cont] = 'xAOD::CaloClusterContainer'
+TESTTCCSlimmingHelper.AppendToDictionary[cont+'Aux'] = 'xAOD::CaloClusterContainer'
+TESTTCCSlimmingHelper.ExtraVariables +=[ cont+'.calE.calEta.calPhi.rawE' ]
+
+
+# we can not output directly our PlainLC pflow container. Technically this container is a 'view' container
+# and I'm not sure the DerivationFramework is able to deal with them. A solution is to add a custom alg which
+# fully copies this view container into a new one, which we can then write out as below.
+# cont = 'PlainLCPFO'
+# TESTTCCSlimmingHelper.AppendToDictionary[cont] = 'xAOD::PFOContainer'
+# TESTTCCSlimmingHelper.AppendToDictionary[cont+'Aux'] = 'xAOD::PFOAuxContainer'
+# TESTTCCSlimmingHelper.ExtraVariables +=[ cont+'.pt.eta.phi.charged' ]
+
+cont = 'TrackCaloClusters'
+TESTTCCSlimmingHelper.AppendToDictionary[cont] = 'xAOD::TrackCaloClusterContainer'
+TESTTCCSlimmingHelper.AppendToDictionary[cont+'Aux'] = 'xAOD::PFOAuxContainer'
+TESTTCCSlimmingHelper.ExtraVariables +=[ cont+'.pt.eta.phi.taste' ]
+
+cont = 'PlainLCUFO'
+TESTTCCSlimmingHelper.AppendToDictionary[cont] = 'xAOD::TrackCaloClusterContainer'
+TESTTCCSlimmingHelper.AppendToDictionary[cont+'Aux'] = 'xAOD::TrackCaloClusterAuxContainer'
+TESTTCCSlimmingHelper.ExtraVariables +=[ cont+'.pt.eta.phi.taste' ]
+
+
+
+
+
+TESTTCCSlimmingHelper.SmartCollections = [
+]
+
+TESTTCCSlimmingHelper.AppendContentToStream(TESTTCCStream)
+
+
+
+# only a fraction of event 
+theApp.EvtMax = 10 # -1 for all events
diff --git a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecAlgs/src/TrackCaloClusterAlg.cxx b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecAlgs/src/TrackCaloClusterAlg.cxx
new file mode 100644
index 00000000000..659fa9598f6
--- /dev/null
+++ b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecAlgs/src/TrackCaloClusterAlg.cxx
@@ -0,0 +1,71 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+// TrackCaloClusterAlgs includes
+#include "TrackCaloClusterRecAlgs/TrackCaloClusterAlg.h"
+
+#include "TrkParametersIdentificationHelpers/TrackParametersIdHelper.h"
+#include "AtlasDetDescr/AtlasDetectorID.h"
+
+#include "xAODPFlow/TrackCaloClusterAuxContainer.h"
+#include "xAODPFlow/FlowElementContainer.h"
+#include "xAODPFlow/FlowElementAuxContainer.h"
+
+#include "StoreGate/ReadDecorHandle.h"
+#include "StoreGate/WriteDecorHandle.h"
+
+
+
+TrackCaloClusterAlg::TrackCaloClusterAlg( const std::string& name, ISvcLocator* pSvcLocator ) : 
+  AthAlgorithm( name, pSvcLocator ) { }
+  
+  
+// *****************************************************
+StatusCode TrackCaloClusterAlg::initialize() {
+  ATH_MSG_DEBUG ("Initializing " << name() << "...");    
+  ATH_CHECK(m_tccTools.retrieve());
+  ATH_CHECK(m_tccInfoHandle.initialize());
+  ATH_CHECK(m_outputTCCHandle.initialize());
+  ATH_CHECK(m_copiedTCCHandle.initialize(! m_copiedTCCHandle.empty()) );
+
+  return StatusCode::SUCCESS;
+}
+
+// *****************************************************
+StatusCode TrackCaloClusterAlg::execute() {  
+  ATH_MSG_DEBUG ("Executing " << name() << "...");
+
+  SG::ReadHandle<TrackCaloClusterInfo> tccInfo(m_tccInfoHandle);
+  
+  // Create containers
+  SG::WriteHandle<xAOD::FlowElementContainer> tccContainer(m_outputTCCHandle) ;
+  ATH_CHECK( tccContainer.record (std::make_unique<xAOD::FlowElementContainer>(),
+				  std::make_unique<xAOD::FlowElementAuxContainer>()) );
+  ATH_MSG_DEBUG( "Recorded TrackCaloClusterContainer with key: " << m_outputTCCHandle.key()  );    
+
+  // Optionnaly recopy an existing container.
+  // This option is mainly to enable functionalities of the original alg. 
+  if(! m_copiedTCCHandle.empty() ){
+    SG::ReadHandle<xAOD::FlowElementContainer> tccToCopy(m_copiedTCCHandle) ;
+    for(const xAOD::FlowElement* tobecopied: *tccToCopy){
+      xAOD::FlowElement* tcc = new xAOD::FlowElement;
+      tccContainer->push_back(tcc);
+      *tcc = *tobecopied;
+    }
+  }
+
+
+  // Loop over each TCC tool  ...
+  for(const ToolHandle<ITrackCaloClusterTool> & tool : m_tccTools){
+    // .. and have it fill  tccContainer
+    ATH_MSG_DEBUG("executing "<<tool.name() );
+    StatusCode sc=tool->fillTCC(tccContainer.ptr(), *tccInfo);
+    if(sc.isFailure()){
+      ATH_MSG_ERROR(" TCC tool "<< tool->name() << "  failed. "); return sc;
+    }
+    ATH_MSG_DEBUG("executed "<<tool.name() << " num object= "<< tccContainer->size() );
+  }
+         
+  return StatusCode::SUCCESS;
+}
diff --git a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecAlgs/src/TrackCaloClusterInfoAlg.cxx b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecAlgs/src/TrackCaloClusterInfoAlg.cxx
new file mode 100644
index 00000000000..b1c04a86746
--- /dev/null
+++ b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecAlgs/src/TrackCaloClusterInfoAlg.cxx
@@ -0,0 +1,173 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+// TrackCaloClusterInfoAlgs includes
+#include "TrackCaloClusterRecAlgs/TrackCaloClusterInfoAlg.h"
+
+#include "StoreGate/ReadDecorHandle.h"
+
+#include "TrackCaloClusterRecTools/TCCHelpers.h"
+
+TrackCaloClusterInfoAlg::TrackCaloClusterInfoAlg( const std::string& name, ISvcLocator* pSvcLocator ) : 
+  AthAlgorithm( name, pSvcLocator ) {}
+  
+  
+StatusCode TrackCaloClusterInfoAlg::initialize() {
+  ATH_MSG_DEBUG ("Initializing " << name() << "...");
+  ATH_CHECK(m_inputClustersHandle.initialize() );
+  ATH_CHECK(m_inputTracksHandle.initialize() );
+  ATH_CHECK(m_inputVertexHandle.initialize());
+  ATH_CHECK(m_tccInfoHandle.initialize());
+
+  ATH_CHECK(m_assoClustersKey.initialize());
+
+  return StatusCode::SUCCESS;
+}
+  
+
+StatusCode TrackCaloClusterInfoAlg::execute()  {  
+  ATH_MSG_DEBUG ("Executing " << name() << "...");
+
+  // Prepare a TrackCaloClusterInfo map : 
+  SG::WriteHandle<TrackCaloClusterInfo> tccInfo(m_tccInfoHandle);    
+  ATH_CHECK( tccInfo.record( std::make_unique<TrackCaloClusterInfo>() ) );
+
+  // Retrieve the input containers 
+  SG::ReadHandle<xAOD::CaloClusterContainer> clusterContainer(m_inputClustersHandle);
+  SG::ReadHandle<xAOD::TrackParticleContainer> tracks(m_inputTracksHandle);
+  SG::ReadHandle<xAOD::VertexContainer> vertices(m_inputVertexHandle);
+
+  tccInfo->allClusters = &*clusterContainer;
+  tccInfo->allTracks = &*tracks;
+
+  // retrieve PV0 if it exists
+  if(!vertices->empty()) {
+    tccInfo->pv0=(*vertices)[0]; // Hard code HS vertex as PV0 : WARNING we expect it is the same as was used for m_inputTrackCaloAssocName !!
+  } else {    
+    ATH_MSG_ERROR ("Vertex container " << m_inputVertexHandle << " is empty! Can't perform TVA!");
+    return StatusCode::FAILURE;
+  }
+
+  // Fill the maps 
+  ATH_CHECK( fillInfo(tccInfo) );  
+  
+  return StatusCode::SUCCESS;
+}
+
+
+StatusCode TrackCaloClusterInfoAlg::fillInfo(SG::WriteHandle<TrackCaloClusterInfo> & tccInfo) const {
+
+  std::multimap <const xAOD::IParticle*, const xAOD::TrackParticle*> clusterToTracksMap;
+
+  SG::ReadDecorHandle<xAOD::TrackParticleContainer, std::vector<ElementLink<xAOD::CaloClusterContainer>> > clusterLinks(m_assoClustersKey);
+  static const xAOD::IParticle::FourMom_t nullV(0,0,0,0);
+  
+  for(const xAOD::TrackParticle* trk : *tccInfo->allTracks){
+    const auto & clustLinks = clusterLinks( *trk );
+    if(clustLinks.empty() ) continue;
+    // follow the link to the calorimeter clusters
+    for( const auto& clLink : clustLinks) {
+      const xAOD::IParticle* cluster = *clLink;
+      clusterToTracksMap.insert(std::make_pair(cluster, trk));
+      // find FourMom_t for trk or insert (0,0,0,0) if not yet in map :
+      xAOD::IParticle::FourMom_t & totalP4 = ( tccInfo->trackTotalClusterPt.insert( {trk, nullV} ) ).first->second;
+      totalP4 += cluster->p4(); // add the cluster p4 into the map.      
+    }
+  }
+  
+
+  // Create cluster-to-tracks weight map
+  for (std::pair<const xAOD::IParticle*, const xAOD::TrackParticle*>  entry : clusterToTracksMap)
+    {
+      const xAOD::IParticle* cluster = entry.first;
+      double cluster_pt       = m_useEnergy ? cluster->e() : cluster->pt();
+      double totalcluster_pt  = m_useEnergy ? tccInfo->trackTotalClusterPt.at(entry.second).E() : tccInfo->trackTotalClusterPt.at(entry.second).Pt();
+
+      // find FourMom_t for trk or insert (0,0,0,0) if not yet in map :
+      xAOD::IParticle::FourMom_t & totalP4 = ( tccInfo->clusterToTracksWeightMap.insert( {cluster, nullV} ) ).first->second;
+      totalP4 += entry.second->p4() * (cluster_pt/totalcluster_pt); // add the track p4 into the map.
+    }
+
+  
+  return StatusCode::SUCCESS;  
+}
+
+
+
+
+
+
+
+namespace TCCHelpers{
+
+  ///////////////////////////////////////////////////////
+  /// Implement a concrete CombinedUFOLoop dedicated to collection of energy sharing weights for UFO
+  ///  see TCCHelpers.h in TrackCaloClusterRecTools/
+  struct WeightsCollector : public CombinedUFOLoop {
+
+    // additional members 
+    std::multimap <const xAOD::IParticle*, const xAOD::TrackParticle*> pfoToTracksMap;
+    TrackCaloClusterInfo * tccInfo_nonconst;
+
+    const xAOD::IParticle::FourMom_t nullV = {0,0,0,0};
+    
+    virtual void processPFO(const xAOD::TrackParticle* trk, const xAOD::PFO* pfo) {
+      /// collect pfo momentum and register the pair (trk,pfo) in the relevant tccInfo map 
+      pfoToTracksMap.insert(std::make_pair(pfo, trk));
+      // get the total p4 for this track, creating it from nullV  if not existing.
+      xAOD::IParticle::FourMom_t & totalP4 = ( tccInfo_nonconst->trackTotalClusterPt.insert( {trk, nullV} ) ).first->second;
+      totalP4 += pfo->p4(); // this modifies the totalP4 stored inside the map (reference access)
+    }
+    
+    virtual void processTrk(const xAOD::TrackParticle* ) { }
+        
+  };
+}
+
+
+
+TrackCaloClusterInfoUFOAlg::TrackCaloClusterInfoUFOAlg( const std::string& name, ISvcLocator* pSvcLocator ) : 
+  TrackCaloClusterInfoAlg( name, pSvcLocator ) {}
+  
+  
+StatusCode TrackCaloClusterInfoUFOAlg::initialize() {
+  ATH_CHECK(m_trackVertexAssoTool.retrieve() );
+  ATH_CHECK(m_inputPFOHandle.initialize() );
+  return StatusCode::SUCCESS;
+}
+
+StatusCode TrackCaloClusterInfoUFOAlg::fillInfo(SG::WriteHandle<TrackCaloClusterInfo> & tccInfo) const {
+
+
+
+  SG::ReadHandle<xAOD::PFOContainer> pfos(m_inputPFOHandle);
+
+  // We use a dedicated helper to collect the weights mapping tracks to PFO.  
+  TCCHelpers::WeightsCollector wcoll;
+  wcoll.m_orig_pfoK = m_orig_pfo.key();
+  wcoll.m_clustersLinkK = m_assoClustersKey.key();
+  wcoll.m_trackVertexAssoTool = m_trackVertexAssoTool.get();
+  wcoll.m_clusterEcut = m_clusterEcut;
+  wcoll.m_useEnergy = m_useEnergy;
+  wcoll.tccInfo_nonconst = tccInfo.ptr();
+
+  // perform the weight collection : this populates tccInfo.trackTotalClusterPt and tccInfo.pfoToTracksMap maps
+  wcoll.combinedUFOLoop(tccInfo.cptr(), pfos.cptr());
+  
+
+  static const xAOD::IParticle::FourMom_t nullV(0,0,0,0);
+  
+  // Create cluster-to-tracks weight map
+  for (std::pair<const xAOD::IParticle*, const xAOD::TrackParticle*>  entry : wcoll.pfoToTracksMap){
+    double cluster_pt       = m_useEnergy ? entry.first->e() : entry.first->pt();
+    double totalcluster_pt  = m_useEnergy ? tccInfo->trackTotalClusterPt.at(entry.second).E() : tccInfo->trackTotalClusterPt.at(entry.second).Pt();
+    
+    // find FourMom_t for trk or insert (0,0,0,0) if not yet in map :
+    xAOD::IParticle::FourMom_t & totalP4 = ( tccInfo->clusterToTracksWeightMap.insert( {entry.first, nullV} ) ).first->second;
+    totalP4 += entry.second->p4() * (cluster_pt/totalcluster_pt); // add the track p4 into the map.
+  }
+
+  return StatusCode::SUCCESS;
+  
+}
diff --git a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecAlgs/src/components/TrackCaloClusterRecAlgs_entries.cxx b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecAlgs/src/components/TrackCaloClusterRecAlgs_entries.cxx
new file mode 100644
index 00000000000..9cfce5b9e23
--- /dev/null
+++ b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecAlgs/src/components/TrackCaloClusterRecAlgs_entries.cxx
@@ -0,0 +1,8 @@
+
+#include "TrackCaloClusterRecAlgs/TrackCaloClusterAlg.h"
+#include "TrackCaloClusterRecAlgs/TrackCaloClusterInfoAlg.h"
+
+DECLARE_COMPONENT(TrackCaloClusterAlg)
+DECLARE_COMPONENT(TrackCaloClusterInfoAlg)
+DECLARE_COMPONENT(TrackCaloClusterInfoUFOAlg)
+
diff --git a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecInterfaces/TrackCaloClusterRecInterfaces/IClusterFilterTool.h b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecInterfaces/TrackCaloClusterRecInterfaces/IClusterFilterTool.h
index 9b7af3924e5..21012e399e1 100644
--- a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecInterfaces/TrackCaloClusterRecInterfaces/IClusterFilterTool.h
+++ b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecInterfaces/TrackCaloClusterRecInterfaces/IClusterFilterTool.h
@@ -23,7 +23,7 @@ class IClusterFilterTool : virtual public IAlgTool {
      * 
      */
     
-    virtual bool rejectCluster(const xAOD::CaloCluster& cluster) = 0;
+    virtual bool rejectCluster(const xAOD::CaloCluster& cluster) const = 0;
     
     static const InterfaceID& interfaceID( ) ;
 };
@@ -32,4 +32,4 @@ inline const InterfaceID& IClusterFilterTool::interfaceID() {
   return IID_IClusterFilterTool; 
 }
 
-#endif // TRACKCALOCLUSTERREC_TRACKCALOCLUSTERRECINTERFACES_ICLUSTERFILTERTOOL_H
\ No newline at end of file
+#endif // TRACKCALOCLUSTERREC_TRACKCALOCLUSTERRECINTERFACES_ICLUSTERFILTERTOOL_H
diff --git a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecInterfaces/TrackCaloClusterRecInterfaces/ITrackCaloClusterTool.h b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecInterfaces/TrackCaloClusterRecInterfaces/ITrackCaloClusterTool.h
new file mode 100644
index 00000000000..801c5092ad6
--- /dev/null
+++ b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecInterfaces/TrackCaloClusterRecInterfaces/ITrackCaloClusterTool.h
@@ -0,0 +1,36 @@
+// this file is -*- C++ -*-
+/*
+  Copyright (C) 2019-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// ITrackCaloClusterTool.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+#ifndef TRACKCALOCLUSTERREC_TRACKCALOCLUSTERRECINTERFACES_ITRACKCALOCLUSTTOOL_H
+#define TRACKCALOCLUSTERREC_TRACKCALOCLUSTERRECINTERFACES_ITRACKCALOCLUSTTOOL_H
+
+#include "GaudiKernel/IAlgTool.h"
+#include "xAODBase/IParticle.h"
+#include "xAODPFlow/FlowElementContainer.h"
+
+static const InterfaceID IID_ITrackCaloClusterTool("ITrackCaloClusterTool", 1, 0);
+
+
+class TrackCaloClusterInfo;
+
+/** @brief Interface for tools creating particles using TCC methods and filling a FlowElementContainer */
+class ITrackCaloClusterTool : virtual public IAlgTool {
+public:
+    
+    
+  
+  virtual StatusCode fillTCC(xAOD::FlowElementContainer* container, const TrackCaloClusterInfo & wmap ) const = 0;
+  
+  static const InterfaceID& interfaceID( ) ;
+};
+
+inline const InterfaceID& ITrackCaloClusterTool::interfaceID() {
+  return IID_ITrackCaloClusterTool; 
+}
+
+#endif // TRACKCALOCLUSTERREC_TRACKCALOCLUSTERRECINTERFACES_IPARTICLEEXTRAPOLATIONTOOL_H
diff --git a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/CMakeLists.txt b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/CMakeLists.txt
index 4fc2fe77186..a5ffd41218a 100644
--- a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/CMakeLists.txt
+++ b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/CMakeLists.txt
@@ -5,32 +5,6 @@
 # Declare the package name:
 atlas_subdir( TrackCaloClusterRecTools )
 
-# Declare the package's dependencies:
-atlas_depends_on_subdirs(
-   PUBLIC
-   GaudiKernel
-   Control/AthenaBaseComps
-   Control/StoreGate
-   Event/xAOD/xAODAssociations
-   Event/xAOD/xAODCaloEvent
-   Event/xAOD/xAODPFlow
-   Event/xAOD/xAODTracking
-   Event/xAOD/xAODTruth
-   InnerDetector/InDetRecTools/TrackVertexAssociationTool
-   Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecInterfaces
-   Tracking/TrkEvent/TrkEventPrimitives
-   PRIVATE
-   Control/CxxUtils
-   DetectorDescription/AtlasDetDescr
-   Event/FourMomUtils
-   Event/xAOD/xAODMuon
-   Tracking/TrkDetDescr/TrkSurfaces
-   Tracking/TrkEvent/TrkCaloExtension
-   Tracking/TrkEvent/TrkParameters
-   Tracking/TrkEvent/TrkParametersIdentificationHelpers
-   Tracking/TrkEvent/TrkTrack
-   Tracking/TrkExtrapolation/TrkExInterfaces )
-
 # Component(s) in the package:
 atlas_add_library( TrackCaloClusterRecToolsLib
    TrackCaloClusterRecTools/*.h src/*.cxx
@@ -47,3 +21,4 @@ atlas_add_library( TrackCaloClusterRecToolsLib
 atlas_add_component( TrackCaloClusterRecTools
    src/components/*.cxx
    LINK_LIBRARIES GaudiKernel TrackCaloClusterRecToolsLib )
+atlas_install_python_modules( python/*.py )
diff --git a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/TrackCaloClusterRecTools/ClusterFilterTool.h b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/TrackCaloClusterRecTools/ClusterFilterTool.h
index ca93d4c58fc..06e803cb6e5 100644
--- a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/TrackCaloClusterRecTools/ClusterFilterTool.h
+++ b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/TrackCaloClusterRecTools/ClusterFilterTool.h
@@ -32,11 +32,11 @@ class ClusterFilterTool : virtual public IClusterFilterTool, public AthAlgTool {
      *  @return true if the cluster has been rejected
      * 
      */
-    bool rejectCluster(const xAOD::CaloCluster& cluster) final;
+    bool rejectCluster(const xAOD::CaloCluster& cluster) const final;
     
   private:    
     // Get a data container; implementation at end of this header file
-    template<class T> const T* getContainer( const std::string & containerName);
+    template<class T> const T* getContainer( const std::string & containerName) const ;
   
     std::string m_caloEntryMapName;
     
@@ -54,7 +54,7 @@ class ClusterFilterTool : virtual public IClusterFilterTool, public AthAlgTool {
 };
 
 template<class T>
-inline const T* ClusterFilterTool::getContainer(const std::string & containerName){
+inline const T* ClusterFilterTool::getContainer(const std::string & containerName) const{
   const T * ptr = evtStore()->retrieve< const T >( containerName );
   if (!ptr) {
     ATH_MSG_WARNING("Container '"<<containerName<<"' could not be retrieved");
diff --git a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/TrackCaloClusterRecTools/TCCHelpers.h b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/TrackCaloClusterRecTools/TCCHelpers.h
new file mode 100644
index 00000000000..9240016d33b
--- /dev/null
+++ b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/TrackCaloClusterRecTools/TCCHelpers.h
@@ -0,0 +1,107 @@
+// this file is -*- C++ -*-
+/*
+  Copyright (C) 2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRACKCALOCLUSTERREC_TRACKCALOCLUSTERRECTOOLS_TCCHELPERS_H
+#define TRACKCALOCLUSTERREC_TRACKCALOCLUSTERRECTOOLS_TCCHELPERS_H
+
+/////////////////////////////////////////////////////////
+/// \bried Internal helper class for TCC & UFO building.
+/// 
+/// This header is meant to be included only from dedicated implementation files.
+///
+/// \author P-A Delsart
+
+namespace TCCHelpers {
+
+  ///////////////////////////////////////////////////////
+  /// Implements a loop over tracks and pflow object to build UFOs
+  ///
+  /// Building UFO implies running a nested loop on tracks and pflows 2 times :
+  ///  - to collect and normalize energy sharing weights
+  ///  - to use these weights to actually build the UFO
+  /// The loop contains several condition and tests and so is relatively complex.
+  /// Thus it is factorized in this helper base class so we avoid to copy-paste it
+  /// and risk to introduce buggy differences.
+  ///
+  /// The 2 clients : TrackCaloClusterInfoAlg (in TrackCaloClusterRecAlgs/) UFOTool (in TrackCaloClusterRecTools/)
+  /// define derived classes which implement the only differing parts : the 
+  /// methods processPFO() and processTrk()
+  ///
+  struct CombinedUFOLoop {
+
+    virtual ~CombinedUFOLoop(){}
+    
+    // These members are used to collect info.
+    // They are expected to be set by the clients.
+    std::string m_orig_pfoK;
+    std::string m_clustersLinkK;
+    const CP::ITrackVertexAssociationTool* m_trackVertexAssoTool;
+    float m_clusterEcut;
+    bool m_useEnergy;
+    
+
+    virtual void processPFO(const xAOD::TrackParticle* trk, const xAOD::PFO* pfo) = 0;
+    virtual void processTrk(const xAOD::TrackParticle* trk) = 0;
+    
+    virtual void combinedUFOLoop(const TrackCaloClusterInfo *tccInfo, const xAOD::PFOContainer* pfos){
+      SG::AuxElement::ConstAccessor<ElementLink<xAOD::PFOContainer> > orig_pfo(m_orig_pfoK);
+      SG::AuxElement::ConstAccessor< std::vector<ElementLink<xAOD::CaloClusterContainer> > > clusterLinks(m_clustersLinkK);
+				     
+	
+      // For performance reasons, we create a map<track, bool> before looping on the tracks.
+      std::map<const xAOD::TrackParticle*, bool> isIsolatedMatchedTrack;
+      for(const xAOD::PFO* pfo: *pfos ){
+	if( ! pfo->isCharged() ) continue;
+	int isInDenseEnvironment = false;
+	pfo->attribute(xAOD::PFODetails::PFOAttributes::eflowRec_isInDenseEnvironment,isInDenseEnvironment);
+	if(isInDenseEnvironment) continue;
+	isIsolatedMatchedTrack[pfo->track(0)] = true;
+      }
+      
+
+      for(const xAOD::TrackParticle * trk: *tccInfo->allTracks){
+	// Only include tracks which aren't associated to a charged PFO -- don't want to double count!
+	if (isIsolatedMatchedTrack.find(trk) != isIsolatedMatchedTrack.end() ) continue;
+
+	// if not matched to PV0, ignore track
+	if (! m_trackVertexAssoTool->isCompatible(*trk, *tccInfo->pv0) ) continue ;
+    
+
+	const auto & clustLinks = clusterLinks( *trk );
+	if(clustLinks.empty() ) continue;
+
+
+	// follow the link to the calorimeter clusters
+	for( const auto& clLink : clustLinks) {
+	  const xAOD::CaloCluster* cluster = *clLink;
+      
+	  // See if any of the PFO are matched to this cluster
+	  for ( const xAOD::PFO* pfo : *pfos ){
+	    if(pfo->pt()<=0.) continue;
+
+	    const xAOD::PFO* pfo_orig = *orig_pfo( *pfo );
+	    if( !(fabs(pfo_orig->eta() - cluster->rawEta() )<0.01 && fabs( pfo_orig->phi()  - cluster->rawPhi() )<0.01)) continue;
+	
+
+	    if( ! pfo->isCharged() ){
+	      // Only want to apply this to PFO which aren't able to be subtracted with E/p
+	      if(cluster->rawE() < m_clusterEcut) continue;
+	    }
+
+	    processPFO(trk, pfo);
+	  } // pfo loop
+	} // cluster associated to trk loop    
+	processTrk(trk);
+    
+      } // track loop
+
+      
+    }
+    
+  };
+
+}
+
+#endif
diff --git a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/TrackCaloClusterRecTools/TrackCaloClusterCreatorTool.h b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/TrackCaloClusterRecTools/TrackCaloClusterCreatorTool.h
deleted file mode 100644
index 70b994bcf16..00000000000
--- a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/TrackCaloClusterRecTools/TrackCaloClusterCreatorTool.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
-  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
-*/
-/***************************************************************************
-TrackCaloClusterCreatorTool.h  -  Description
--------------------
-begin   : March 2017
-authors : Roland Jansky
-***************************************************************************/
-#ifndef TRACKCALOCLUSTERREC_TRACKCALOCLUSTERRECTOOLS_TRACKCALOCLUSTERCREATORTOOL_H
-#define TRACKCALOCLUSTERREC_TRACKCALOCLUSTERRECTOOLS_TRACKCALOCLUSTERCREATORTOOL_H
-
-#include "AthenaBaseComps/AthAlgTool.h"
-#include "GaudiKernel/ToolHandle.h" //included under assumption you'll want to use some tools! Remove if you don't!
-#include "xAODPFlow/TrackCaloClusterContainer.h"
-#include "xAODTracking/TrackParticleContainer.h"
-#include "xAODAssociations/TrackParticleClusterAssociationContainer.h"
-
-#include "TrackVertexAssociationTool/ITrackVertexAssociationTool.h"
-
-#include "TrackCaloClusterRecInterfaces/IClusterFilterTool.h"
-
-class TrackCaloClusterCreatorTool : public AthAlgTool {
-  public:
-    TrackCaloClusterCreatorTool(const std::string&,const std::string&,const IInterface*);
-    virtual ~TrackCaloClusterCreatorTool();
-
-    virtual StatusCode initialize();
-    virtual StatusCode finalize();
-    
-    /// Definition of the 4-momentum type.
-    typedef xAOD::IParticle::FourMom_t FourMom_t;
-
-    /** Method to calculate weights for TCC
-     */
-    void createCombinedTCCs(xAOD::TrackCaloClusterContainer* tccContainer, 
-			    const xAOD::TrackParticleClusterAssociationContainer* assocContainer, 
-			    std::map <const xAOD::TrackParticle*, FourMom_t>* TrackTotalClusterPt, 
-			    std::map <const xAOD::CaloCluster*, FourMom_t>* clusterToTracksWeightMap    );
-    
-    void createNeutralTCCs(xAOD::TrackCaloClusterContainer* tccContainer,
-			   const xAOD::CaloClusterContainer* assocContainer,
-			   std::map <const xAOD::CaloCluster*, FourMom_t>* clusterToTracksWeightMap    );
-    
-    void createChargedTCCs(xAOD::TrackCaloClusterContainer* tccContainer,
-			   const xAOD::TrackParticleContainer* assocContainer, 
-			   std::map <const xAOD::TrackParticle*, FourMom_t>* TrackTotalClusterPt   );
-   
-  private:  
-    
-    void computeVertexCorr(double& eta, double& phi, const Amg::Vector3D& vertex, double radius);
-    
-//     double DetectorEta(const xAOD::CaloCluster& cluster, const Amg::Vector3D& vertex);
-    
-    // ToolHandle<IJetFromPseudojet> m_bld;  // Tool to build jets.
-    ToolHandle<CP::ITrackVertexAssociationTool> m_loosetrackvertexassoTool;
-    
-    /// Vertex container's name
-    std::string m_vertexContname;
-    
-    /// Particle to CaloEntry container name
-    std::string m_caloEntryMapName;
-    
-    /// use cluster energy or pt?
-    bool m_useEnergy;
-    
-    // enable origin correction
-    bool m_doOriginCorrection;
-    bool m_storeCorrectedPosition;
-    
-    // enable cluster filtering on the neutralOnly collection
-    bool m_applyFilter;
-    ToolHandle<IClusterFilterTool> m_clusterFilterTool;
-    
-    // this is saving the detector eta to be used in calibration
-    // --> For charged and combined TCC this is using eta of the extrapolated position at the calo entry
-    //     in the ATLAS global frame, i.e. origin (0., 0., 0.)
-    // --> For neutral TCC this is evaluated using the cluster moment CaloCluster::CENTER_MAG
-    //     inverting what is done for CaloVertexedTopoCluster objects
-    bool m_saveDetectorEta;
-    
-};
-
-
-#endif // TRACKCALOCLUSTERREC_TRACKCALOCLUSTERRECTOOLS_TRACKCALOCLUSTERCREATORTOOL_H
diff --git a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/TrackCaloClusterRecTools/TrackCaloClusterInfo.h b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/TrackCaloClusterRecTools/TrackCaloClusterInfo.h
new file mode 100644
index 00000000000..087d08b3b81
--- /dev/null
+++ b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/TrackCaloClusterRecTools/TrackCaloClusterInfo.h
@@ -0,0 +1,40 @@
+// this file is -*- C++ -*-
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRACKCALOCLUSTERREC_TRACKCALOCLUSTERRECTOOLS_TRACKCALOCLUSTERINFO_H
+#define TRACKCALOCLUSTERREC_TRACKCALOCLUSTERRECTOOLS_TRACKCALOCLUSTERINFO_H
+
+#include <map>
+#include "xAODCore/CLASS_DEF.h"
+
+#include "xAODTracking/TrackParticleContainer.h"
+#include "xAODCaloEvent/CaloClusterContainer.h"
+#include "xAODTracking/Vertex.h"
+#include "xAODAssociations/TrackParticleClusterAssociationContainer.h"
+
+////////////////////////////////////////////////////////
+/// \class TrackCaloClusterInfo
+///
+/// Holds all the necessary information to build TrackCaloCluster objects.
+/// In particular the map of weights relating tracks and clusters (or PFO objects)
+struct TrackCaloClusterInfo
+{
+
+  /// Definition of the 4-momentum type.
+  typedef xAOD::IParticle::FourMom_t FourMom_t;
+  
+  const xAOD::TrackParticleClusterAssociationContainer* assocContainer =  nullptr;
+  std::map <const xAOD::TrackParticle*, FourMom_t> trackTotalClusterPt; 
+  std::map <const xAOD::IParticle*, FourMom_t> clusterToTracksWeightMap ;
+
+  const xAOD::TrackParticleContainer * allTracks =  nullptr;
+  const xAOD::CaloClusterContainer * allClusters =  nullptr;
+  const xAOD::Vertex * pv0 =  nullptr;
+  
+  
+};
+CLASS_DEF( TrackCaloClusterInfo , 111448884 , 1 )
+
+#endif
diff --git a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/TrackCaloClusterRecTools/TrackCaloClusterTool.h b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/TrackCaloClusterRecTools/TrackCaloClusterTool.h
new file mode 100644
index 00000000000..cc0ec9beddf
--- /dev/null
+++ b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/TrackCaloClusterRecTools/TrackCaloClusterTool.h
@@ -0,0 +1,140 @@
+// this file is -*- C++ -*-
+/*
+  Copyright (C) 2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////////
+///
+/// \file TrackCaloClusterTool.h  
+///
+/// Defines implementions of ITrackCaloClusterTool in charge of building different taste of TCC or UFO
+/// 
+/// \authors : Naomie Calace, P-A Delsart, Jennifer Roloff
+///////////////////////////////////////////////////////////////////////
+
+#ifndef TRACKCALOCLUSTERREC_TRACKCALOCLUSTERRECTOOLS_TRACKCALOCLUSTER_H
+#define TRACKCALOCLUSTERREC_TRACKCALOCLUSTERRECTOOLS_TRACKCALOCLUSTER_H
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "xAODPFlow/PFOContainer.h"
+#include "StoreGate/ReadDecorHandleKey.h"
+
+#include "TrackCaloClusterRecInterfaces/ITrackCaloClusterTool.h"
+#include "TrackVertexAssociationTool/ITrackVertexAssociationTool.h"
+#include "TrackCaloClusterRecInterfaces/IClusterFilterTool.h"
+
+
+
+///////////////////////////////////////////////////////////////////////
+/// \class TrackCaloClusterBaseTool
+/// A base class for tools implementing ITrackCaloClusterTool
+///
+/// simply holds a few properties shared by most implementations.
+class TrackCaloClusterBaseTool : virtual public ITrackCaloClusterTool, public AthAlgTool {
+public:
+  TrackCaloClusterBaseTool(const std::string&,const std::string&,const IInterface*);
+  virtual ~TrackCaloClusterBaseTool();
+
+  virtual StatusCode initialize() override ;
+
+  virtual StatusCode fillTCC(xAOD::FlowElementContainer* container, const TrackCaloClusterInfo & tccInfo ) const =0;
+    
+protected:    
+
+  /// The tool used to make sure a track is associated to PV0
+  ToolHandle<CP::ITrackVertexAssociationTool> m_trackVertexAssoTool {this ,"TrackVertexAssoTool", ""};
+  
+  /// use cluster energy or pt?
+  Gaudi::Property<bool> m_useEnergy {this, "UseEnergy", false, "if false will use pT for weights evaluation"};
+
+
+  SG::ReadDecorHandleKey<xAOD::TrackParticleContainer> m_assoClustersKey{this, "AssoClustersDecor", "TCCAssoClusters", "Key to access clusters associated to a track. IMPORTANT must be constistent with the TrackParticleContainer the parent alg will operate on"};
+  
+
+  
+  SG::ReadDecorHandleKey<xAOD::TrackParticleContainer> m_caloEntryParsDecor {this, "CaloEntryParsDecorKey" , "","IMPORTANT must be constistent with the TrackParticleContainer the parent alg will operate on, REQUIRED if SaveDetectorEta or DoOriginCorrection, else leave blank so the scheduler won't require it unnecessarily."};
+
+  /// flag to add dectetor eta decoration onto the produced TrackCaloClusters
+  Gaudi::Property<bool> m_saveDetectorEta {this, "SaveDetectorEta", false, ""};       
+};
+
+
+
+///////////////////////////////////////////////////////////////////////
+/// \class TCCCombinedTool
+///
+/// Implements the creation of "combined" TCC objects
+///
+class TCCCombinedTool : public TrackCaloClusterBaseTool {
+public:
+  TCCCombinedTool(const std::string&,const std::string&,const IInterface*);
+  virtual ~TCCCombinedTool() {}
+
+  virtual StatusCode fillTCC(xAOD::FlowElementContainer* container, const TrackCaloClusterInfo & tccInfo ) const override;
+
+protected:  
+  // enable origin correction
+  Gaudi::Property<bool> m_doOriginCorrection {this, "DoOriginCorrection", false, ""};
+  Gaudi::Property<bool> m_storeCorrectedPosition{this, "StoreCorrectedPosition", false, ""};
+};
+
+
+///////////////////////////////////////////////////////////////////////
+/// \class TCCChargedTool
+///
+/// Implements the creation of "charged" TCC objects (that is tracks matched 0 clusters)
+///
+class TCCChargedTool : public TrackCaloClusterBaseTool {
+public:
+  TCCChargedTool(const std::string&,const std::string&,const IInterface*);
+
+  virtual StatusCode fillTCC(xAOD::FlowElementContainer* container, const TrackCaloClusterInfo & tccInfo ) const override;
+
+protected:
+  
+};
+
+
+
+///////////////////////////////////////////////////////////////////////
+/// \class TCCNeutralTool
+///
+/// Implements the creation of "neutral" TCC objects (that is clusters matched to 0 tracks)
+///
+class TCCNeutralTool : public TrackCaloClusterBaseTool {
+public:
+  TCCNeutralTool(const std::string&,const std::string&,const IInterface*);
+
+  virtual StatusCode fillTCC(xAOD::FlowElementContainer* container, const TrackCaloClusterInfo & tccInfo ) const override ;
+  virtual StatusCode initialize() override;
+
+protected:
+  /// optionnal tool to filter cluster we don't want to consider as TCC
+  ToolHandle<IClusterFilterTool> m_clusterFilterTool {this, "ClusterFilterTool", ""};
+  bool m_applyFilter ; // set automatically according to ClusterFilterTool
+};
+
+
+
+///////////////////////////////////////////////////////////////////////
+/// \class UFOTool
+///
+/// Implements the creation of UFO objects. These are build similarly as TCC but using PFO in the place of CaloClusters.
+/// All Combined, Charged and Neutral are build together within this class.
+///
+class UFOTool : public TrackCaloClusterBaseTool {
+public:
+  UFOTool(const std::string&,const std::string&,const IInterface*);
+
+  virtual StatusCode fillTCC(xAOD::FlowElementContainer* container, const TrackCaloClusterInfo & tccInfo ) const override;
+
+protected:
+
+  SG::ReadHandleKey<xAOD::PFOContainer> m_inputPFOHandle {this, "InputPFO", "CHSParticleFlowObjects", ""};
+  SG::ReadDecorHandleKey<xAOD::PFOContainer> m_orig_pfo{this, "OriginPFO", "Origin_pfo", "Key to access original un-modified pfo"};
+
+  /// cluster with E below this cut won't be considered in the TCC alg. WARNING cut must be configured as in TrackCaloClusterInfoUFOAlg
+  Gaudi::Property<float> m_clusterEcut{this , "ClusterECut", 0, " Impotant !! : must be the same value as in TrackCaloClusterInfoUFOAlg"};
+};
+
+#endif // TRACKCALOCLUSTERREC_TRACKCALOCLUSTERRECTOOLS_PARTICLETOCALOEXTRAPOLATIONTOOL_H
diff --git a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/TrackCaloClusterRecTools/TrackCaloClusterWeightsTool.h b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/TrackCaloClusterRecTools/TrackCaloClusterWeightsTool.h
deleted file mode 100644
index e3c137971e2..00000000000
--- a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/TrackCaloClusterRecTools/TrackCaloClusterWeightsTool.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
-*/
-/***************************************************************************
-TrackCaloClusterWeightsTool.h  -  Description
--------------------
-begin   : March 2017
-authors : Roland Jansky
-***************************************************************************/
-#ifndef TRACKCALOCLUSTERREC_TRACKCALOCLUSTERRECTOOLS_TRACKCALOCLUSTERWEIGHTSTOOL_H
-#define TRACKCALOCLUSTERREC_TRACKCALOCLUSTERRECTOOLS_TRACKCALOCLUSTERWEIGHTSTOOL_H
-
-#include "AthenaBaseComps/AthAlgTool.h"
-#include "xAODPFlow/TrackCaloCluster.h"
-#include "xAODTracking/TrackParticle.h"
-#include "xAODAssociations/TrackParticleClusterAssociationContainer.h"
-
-class TrackCaloClusterWeightsTool : public AthAlgTool {
-  public:
-    TrackCaloClusterWeightsTool(const std::string&,const std::string&,const IInterface*);
-    virtual ~TrackCaloClusterWeightsTool();
-
-    virtual StatusCode initialize();
-    virtual StatusCode finalize();
-    
-    /// Definition of the 4-momentum type.
-    typedef xAOD::IParticle::FourMom_t FourMom_t;
-
-    /** Method to calculate weights for TCC
-     */
-    void fillWeightMaps(const xAOD::TrackParticleClusterAssociationContainer* assocContainer, std::multimap <const xAOD::CaloCluster*, const xAOD::TrackParticle*>* clusterToTracksMap, std::map <const xAOD::TrackParticle*, FourMom_t>* TrackTotalClusterPt, std::map <const xAOD::CaloCluster*, FourMom_t>* clusterToTracksWeightMap    );
-   
-  private:    
-
-    /// use cluster energy or pt?
-    bool m_useEnergy;
-
-};
-
-
-#endif // TRACKCALOCLUSTERREC_TRACKCALOCLUSTERRECTOOLS_TRACKCALOCLUSTERWEIGHTSTOOL_H
diff --git a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/python/TrackCaloClusterConfig.py b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/python/TrackCaloClusterConfig.py
new file mode 100644
index 00000000000..21a7337581d
--- /dev/null
+++ b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/python/TrackCaloClusterConfig.py
@@ -0,0 +1,261 @@
+#   Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+from AthenaCommon import Logging
+from AthenaConfiguration.ComponentFactory import CompFactory
+from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
+ufolog = Logging.logging.getLogger('TCCorUFO')
+
+from AthenaConfiguration import UnifyProperties
+
+
+
+def _unifyPV0onlyTrkClustAssoc( vxContName1, vxContName2):
+    if vxContName2 == vxContName1 : return vxContName1
+    if "" in [vxContName1, vxContName2] : return vxContName1 or vxContName2
+    raise Exception(" Error : incompatible VertexContainerName of 2 instance of TrackParticleClusterAssociationAlg : '{}' and '{}'".format(vxContName1, vxContName2))
+
+
+# we make sure a unique TrackParticleAssociationAlg is well behaved when configured for both TCC and UFOInfo
+# in the same job. The function below will be used in the de-duplication and implies all tracks (not only PV0)
+# have associated clusters only if TCC is scheduled.
+#  !! Doesn't seem to work yet ??!!
+UnifyProperties.setUnificationFunction( "TrackParticleClusterAssociationAlg.VertexContainerName", _unifyPV0onlyTrkClustAssoc)
+    
+
+
+
+def setupTrackVertexAssocTool():
+    #from AthenaCommon import CfgMgr
+    # do as in jet config :
+    return CompFactory.getComp("CP::TrackVertexAssociationTool")("jetLooseTVAtool", WorkingPoint='Loose')
+
+
+def tmpSetupTrackServices(inputFlags):
+    """This temporary function ensure the tracking services necessary for TCC/UFO building are set up in a RunIII compatible way"""
+    
+    result=ComponentAccumulator()
+    StoreGateSvc=CompFactory.StoreGateSvc
+    result.addService(StoreGateSvc("DetectorStore"))
+    
+    #Setup up general geometry
+    from AtlasGeoModel.InDetGMConfig import InDetGeometryCfg
+    result.merge(InDetGeometryCfg(inputFlags))
+ 
+    #Setup TRT conditions                                                                                                                                  
+    TRTAlignCondAlg=CompFactory.TRTAlignCondAlg
+    result.addCondAlgo(TRTAlignCondAlg(name = "TRTAlignCondAlg",UseDynamicFolders = inputFlags.GeoModel.Align.Dynamic))
+ 
+    #Setup Pixel conditions
+    PixelAlignCondAlg=CompFactory.PixelAlignCondAlg
+    result.addCondAlgo(PixelAlignCondAlg(name = "PixelAlignCondAlg",UseDynamicAlignFolders = inputFlags.GeoModel.Align.Dynamic))
+ 
+    PixelDetectorElementCondAlg=CompFactory.PixelDetectorElementCondAlg
+    result.addCondAlgo(PixelDetectorElementCondAlg(name = "PixelDetectorElementCondAlg"))
+ 
+    #Setup SCT conditions
+    SCT_AlignCondAlg=CompFactory.SCT_AlignCondAlg
+    result.addCondAlgo(SCT_AlignCondAlg(name = "SCT_AlignCondAlg",UseDynamicAlignFolders = inputFlags.GeoModel.Align.Dynamic))
+ 
+    SCT_DetectorElementCondAlg=CompFactory.SCT_DetectorElementCondAlg
+    result.addCondAlgo(SCT_DetectorElementCondAlg(name = "SCT_DetectorElementCondAlg"))
+ 
+    GeometryDBSvc=CompFactory.GeometryDBSvc
+    result.addService(GeometryDBSvc("InDetGeometryDBSvc"))
+    
+ 
+    #Setup TRT geometry
+    TRT_DetectorTool=CompFactory.TRT_DetectorTool
+    trtDetectorTool = TRT_DetectorTool()
+    #These two lines fix ATLASRECTS-5053. I expect eventually we can remove them, once the underlying issue is fixed.
+    trtDetectorTool.DoXenonArgonMixture = False
+    trtDetectorTool.DoKryptonMixture = False
+    result.getService("GeoModelSvc").DetectorTools += [ trtDetectorTool ]
+ 
+    #Setup up material for inner detector
+    InDetServMatTool=CompFactory.InDetServMatTool
+    result.getService("GeoModelSvc").DetectorTools += [ InDetServMatTool() ]
+    
+    #Setup up tracking geometry
+    from TrkConfig.AtlasTrackingGeometrySvcConfig import TrackingGeometrySvcCfg
+    acc = TrackingGeometrySvcCfg(inputFlags)
+    result.merge(acc)
+    
+    #load folders needed for Run2 ID alignment
+    from IOVDbSvc.IOVDbSvcConfig import addFolders
+    result.merge(addFolders(inputFlags,['/TRT/Align'],'TRT_OFL'))
+    
+    #Setup up muon geometry
+    from MuonConfig.MuonGeometryConfig import MuonGeoModelCfg
+    result.merge(MuonGeoModelCfg(inputFlags))    
+ 
+    #setup magnetic field service
+    from MagFieldServices.MagFieldServicesConfig import MagneticFieldSvcCfg
+    result.merge(MagneticFieldSvcCfg(inputFlags))
+ 
+    #hard-code MC conditions tag needed for my ESD file - must be a better way? how to auto-configure?
+    #iovDbSvc=result.getService("IOVDbSvc")
+    #iovDbSvc.GlobalTag="OFLCOND-MC16-SDR-20"    
+
+    return result 
+
+
+def getDecorationKeyFunc(trackParticleName, assocPostfix):
+    """Simple helper returning a function to build decoration keys """
+    return lambda d : trackParticleName+'.'+d+assocPostfix
+
+def setupTrackCaloAssoc(configFlags, caloClusterName="CaloCalTopoClusters",trackParticleName="InDetTrackParticles", assocPostfix = "TCC", onlyPV0Tracks=False):
+    """ Schedule a TrackParticleClusterAssociationAlg in the top sequence, taking as input clusters and tracks defined 
+    by the keys caloClusterName and trackParticleName.
+
+    onlyPV0Tracks : calculate associated clusters only for PV0 tracks. Avoids unnecessary calculation (used in the UFO case).
+       (IMPORTANT CaloExtensionBuilderAlg does extrapolate all tracks : if too much time consuming, it needs a new option to mask non-PV0 tracks)
+    """
+    ###################################
+
+
+    decorKey = getDecorationKeyFunc(trackParticleName,assocPostfix)
+    
+    components = ComponentAccumulator()
+
+    components.merge( tmpSetupTrackServices(configFlags) )
+
+    from TrackToCalo.CaloExtensionBuilderAlgCfg import getCaloExtenstionBuilderAlgorithm 
+    caloExtAlg =getCaloExtenstionBuilderAlgorithm( configFlags )
+    caloExtAlg.LastCaloExtentionTool.ExtrapolationDetectorID = 3
+    #caloExtAlg.LastCaloExtentionTool.ParticleType = "pion"
+    caloExtAlg.TrkPartContainerName = trackParticleName
+    caloExtAlg.LastCaloExtentionTool.OutputLevel = 3
+    caloExtAlg.LastCaloExtentionTool.Extrapolator.OutputLevel = 3
+    components.addEventAlgo(  caloExtAlg  )
+    
+    
+    trackParticleClusterAssociation = CompFactory.TrackParticleClusterAssociationAlg(
+        "TrackClusterAssociationAlg"+assocPostfix,
+        #ParticleCaloClusterAssociationTool = particleCaloClusterAssociation,
+        TrackParticleContainerName = trackParticleName,
+        PtCut = 400.,
+        CaloExtensionName = caloExtAlg.ParticleCache,
+        CaloClusterLocation = caloClusterName,
+        TrackVertexAssoTool=setupTrackVertexAssocTool(), # will associate trks from PV0 only
+        VertexContainerName = "PrimaryVertices" if onlyPV0Tracks else "",
+        AssociatedClusterDecorKey = decorKey("AssoClusters"),
+        OutputLevel=2)
+
+
+    components.addEventAlgo( trackParticleClusterAssociation )
+    return components
+
+    
+def runTCCReconstruction(configFlags, caloClusterName="CaloCalTopoClusters",trackParticleName="InDetTrackParticles",
+                         assocPostfix="TCC", doCombined=True, doNeutral=True, doCharged=False, outputTCCName="TrackCaloClusters"):
+    """Create a TrackCaloCluster collection from clusters and tracks (caloClusterName and trackParticleName). 
+    Depending on options, the collection contains combined, neutral and/or charged TCC.
+    This functions schedules 2 TCC spécific algs : 
+       * a TrackCaloClusterInfoAlg to build the TrackCaloClusterInfo object
+       * a TrackCaloClusterAlg to build the TCC
+    
+    """
+
+    from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
+
+    decorKey = getDecorationKeyFunc(trackParticleName,assocPostfix)
+
+    components = ComponentAccumulator()    
+    
+    components.merge(
+        setupTrackCaloAssoc(configFlags, caloClusterName, trackParticleName, assocPostfix, onlyPV0Tracks=False)
+    )
+
+    
+
+
+        
+    ###################################
+    # Schedule the TrackCaloClusterInfoAlg to create the weights for clusters/tracks and store them in a TrackCaloClusterInfo object.
+    #from TrackCaloClusterRecAlgs.TrackCaloClusterRecAlgsConf import TrackCaloClusterAlg, TrackCaloClusterInfoAlg
+    tccInfoAlg = CompFactory.TrackCaloClusterInfoAlg(
+        "TCCInfoAlg",
+        TCCInfoName = "TCCInfo",
+        InputTracks = trackParticleName,
+        InputClusters = caloClusterName,
+        VertexContainer = "PrimaryVertices",
+        AssoClustersDecor = decorKey("AssoClusters"),
+    )
+
+    components.addEventAlgo( tccInfoAlg) 
+    
+    ###################################
+    # Create the TCC creator alg. TrackCaloClusterAlg makes use of the TrackCaloClusterInfo object
+    # and a list of tools to build the various TCC types.
+    tccTools = []
+    commonArgs = dict( TrackVertexAssoTool = setupTrackVertexAssocTool(),
+                       AssoClustersDecor = decorKey("AssoClusters") )
+    if doCombined:
+        tccCombined = CompFactory.TCCCombinedTool("TCCcombined", **commonArgs)
+        tccTools.append(tccCombined)
+    if doCharged:
+        tccCharged = CompFactory.TCCChargedTool("TCCCharged", **commonArgs )
+        tccTools.append(tccCharged)
+    if doNeutral:
+        tccNeutral = CompFactory.TCCNeutralTool("TCCNeutral", **commonArgs )        
+        tccTools.append(tccNeutral)
+
+    tccAlg = CompFactory.TrackCaloClusterAlg(name = "TrackCaloClusterAlg",
+                                             OutputTCCName = outputTCCName,
+                                             TCCInfo = "TCCInfo",
+                                             TCCTools = tccTools,
+                                             OutputLevel = 2,
+                                             
+                                 )
+
+    components.addEventAlgo( tccAlg)
+    return components
+
+
+def runUFOReconstruction( constits, configFlags, caloClusterName="CaloCalTopoClusters", trackParticleName="InDetTrackParticles",
+                         assocPostfix="TCC", ):
+    """Create a TrackCaloCluster collection from PFlow and tracks (PFO retrieved from PFOPrefix and tracks directly from trackParticleName). 
+    This functions schedules 2 UFO specific algs : 
+       * a TrackCaloClusterInfoUFOAlg to build the TrackCaloClusterInfo object
+       * a TrackCaloClusterAlg to build the UFO
+    """
+
+    from JetRecConfig.JetRecConfig import JetInputCfg
+
+    components = JetInputCfg(constits, configFlags)
+    constitAlg = components.getEventAlgos()[0]
+    PFOPrefix = constitAlg.Tools[0].OutputContainer
+    
+    
+    components.merge(
+        setupTrackCaloAssoc(configFlags, caloClusterName, trackParticleName, assocPostfix, onlyPV0Tracks=True)
+    )
+
+        
+
+    tccInfoAlg = CompFactory.TrackCaloClusterInfoUFOAlg("UFOInfoAlg_"+PFOPrefix,
+                                            TCCInfoName = PFOPrefix+"UFOInfo",
+                                            InputTrackCaloAssoc = trackParticleName+"ClusterAssociationsTCC",
+                                            InputTracks = trackParticleName,
+                                            InputClusters = caloClusterName,
+                                            VertexContainer = "PrimaryVertices",
+                                            TrackVertexAssoTool = setupTrackVertexAssocTool(), 
+                                            PFOPrefix = PFOPrefix,
+                                            ClusterECut = 0.,
+    )
+
+    components.addEventAlgo( tccInfoAlg) 
+
+    tccUFO = CompFactory.UFOTool("UFOtool",
+                                 TrackVertexAssoTool = setupTrackVertexAssocTool(), 
+                                 PFOPrefix = PFOPrefix,
+                                 ClusterECut = tccInfoAlg.ClusterECut,                     
+                                 )
+
+    tccAlg = CompFactory.TrackCaloClusterAlg(name = "TrackCaloClusterAlgUFO"+PFOPrefix,
+                                 OutputTCCName = "UFO"+PFOPrefix,
+                                 TCCInfo = tccInfoAlg.TCCInfoName,
+                                 TCCTools = [tccUFO,]
+    )
+    components.addEventAlgo( tccAlg)
+    return components
+
diff --git a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/src/ClusterFilterTool.cxx b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/src/ClusterFilterTool.cxx
index 276449c2ada..b0b4b73b7d3 100644
--- a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/src/ClusterFilterTool.cxx
+++ b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/src/ClusterFilterTool.cxx
@@ -36,7 +36,7 @@ StatusCode ClusterFilterTool::finalize() {
   return StatusCode::SUCCESS;
 }
 
-bool ClusterFilterTool::rejectCluster(const xAOD::CaloCluster& cluster) {
+bool ClusterFilterTool::rejectCluster(const xAOD::CaloCluster& cluster) const {
       
   // loop on all the tracks
   const auto allTracks   = getContainer<xAOD::TrackParticleContainer>(m_trackParticleCollectionName);
@@ -95,4 +95,4 @@ bool ClusterFilterTool::rejectCluster(const xAOD::CaloCluster& cluster) {
  
   return false;
   
-}
\ No newline at end of file
+}
diff --git a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/src/ParticleToCaloExtrapolationTool.cxx b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/src/ParticleToCaloExtrapolationTool.cxx
index c6f23eebceb..aa5939aa407 100644
--- a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/src/ParticleToCaloExtrapolationTool.cxx
+++ b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/src/ParticleToCaloExtrapolationTool.cxx
@@ -185,7 +185,7 @@ Trk::CaloExtension* ParticleToCaloExtrapolationTool::caloExtension( const Trk::T
 
   // pointers to hold results and go
   std::vector<const Trk::TrackStateOnSurface*>* material = 0;//new std::vector<const Trk::TrackStateOnSurface*>();
-  const auto* caloParameters = m_extrapolator->extrapolate( startPars, propDir, particleType, material, 3 ); 
+  const auto* caloParameters = m_extrapolator->extrapolate( startPars, propDir, particleType, material, 1 ); // last parameter is the "destination" interpreted as a GeometrySignature (1=include ID, 3=include clo)
   if( material ) {
     ATH_MSG_DEBUG("Got material " << material->size() );
     for( auto& m : *material ) {
diff --git a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/src/TrackCaloClusterCreatorTool.cxx b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/src/TrackCaloClusterCreatorTool.cxx
deleted file mode 100644
index 1bd6f56061c..00000000000
--- a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/src/TrackCaloClusterCreatorTool.cxx
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
-  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
-*/
-#include "TrackCaloClusterRecTools/TrackCaloClusterCreatorTool.h"
-#include "TrackCaloClusterRecTools/IParticleToCaloExtensionMap.h"
-#include "TrkCaloExtension/CaloExtension.h"
-
-#include "xAODTracking/VertexContainer.h"
-
-#include "CxxUtils/sincos.h"
-#include <cmath>
-
-TrackCaloClusterCreatorTool::TrackCaloClusterCreatorTool(const std::string& t, const std::string& n, const IInterface*  p )
-  : AthAlgTool(t,n,p),
-  m_loosetrackvertexassoTool("LooseTrackVertexAssociationTool"),
-  m_caloEntryMapName("ParticleToCaloExtensionMap"),
-  m_useEnergy(false),
-  m_doOriginCorrection(false),
-  m_storeCorrectedPosition(false),
-  m_applyFilter(true),
-  m_clusterFilterTool("ClusterFilterTool"),
-  m_saveDetectorEta(false)
-{
-    declareProperty("VertexContainerName"          ,    m_vertexContname                  = "PrimaryVertices"   );
-    declareProperty("ParticleCaloEntryMapName"     ,    m_caloEntryMapName                                      );
-    declareProperty("LooseTrackVertexAssoTool"     ,    m_loosetrackvertexassoTool                              );
-    declareProperty("UseEnergy"                    ,    m_useEnergy                                             );
-    declareProperty("DoOriginCorrection"           ,    m_doOriginCorrection                                    );
-    declareProperty("StoreCorrectedPosition"       ,    m_storeCorrectedPosition                                );
-    declareProperty("ApplyClusterFilter"           ,    m_applyFilter                                           );
-    declareProperty("ClusterFilterTool"            ,    m_clusterFilterTool                                     );
-    declareProperty("SaveDetectorEta"              ,    m_saveDetectorEta                                       );    
-}
-
-TrackCaloClusterCreatorTool::~TrackCaloClusterCreatorTool() {}
-
-StatusCode TrackCaloClusterCreatorTool::initialize() {
-  ATH_CHECK(m_loosetrackvertexassoTool.retrieve());
-  if (m_applyFilter)
-    ATH_CHECK(m_clusterFilterTool.retrieve());
-  return StatusCode::SUCCESS;
-}
-
-StatusCode TrackCaloClusterCreatorTool::finalize() {
-  return StatusCode::SUCCESS;
-}
-
-void TrackCaloClusterCreatorTool::createCombinedTCCs(xAOD::TrackCaloClusterContainer* tccContainer, 
-						     const xAOD::TrackParticleClusterAssociationContainer* assocContainer, 
-						     std::map <const xAOD::TrackParticle*, FourMom_t>* TrackTotalClusterPt, 
-						     std::map <const xAOD::CaloCluster*, FourMom_t>* clusterToTracksWeightMap ) {
-    
-    const xAOD::VertexContainer *vxCont=0;
-    StatusCode sc = evtStore()->retrieve(vxCont, m_vertexContname);
-    if (sc.isFailure()) {
-        ATH_MSG_WARNING ("Vertex container " << m_vertexContname << " not found! Can't perform TVA!");
-    }
-
-    for ( const auto* assocClusters : *assocContainer ) {
-        ATH_MSG_VERBOSE ("InDetTrackParticlesClusterAssociations index = " << assocClusters->index());
-        // flollow the link to the track particle
-        const xAOD::TrackParticle* trk = 0;
-        if (assocClusters->trackParticleLink().isValid()) {
-            trk = *(assocClusters->trackParticleLink());
-            bool isMatched = true;
-            if (vxCont && vxCont->size()!=0) {
-	      isMatched = m_loosetrackvertexassoTool->isCompatible(*trk, *(vxCont->at(0)) );
-            } else {
-	      ATH_MSG_WARNING ("Vertex container " << m_vertexContname << " is empty! Can't perform TVA!");
-            }
-            if (!isMatched) continue;
-        } else {
-	  ATH_MSG_ERROR ("trackParticleLink is not valid! " );
-        }
-	FourMom_t tcc_4p(0.,0.,0.,0.);
-        // follow the link to the calorimeter clusters
-        ATH_MSG_VERBOSE ("#(CaloCluster) = " << assocClusters->caloClusterLinks().size());
-        if (assocClusters->caloClusterLinks().size()) {
-            for (size_t c = 0; c < assocClusters->caloClusterLinks().size(); ++c) {
-                    const xAOD::CaloCluster* cluster = *(assocClusters->caloClusterLinks().at(c));
-                    double cluster_pt       = m_useEnergy ? cluster->e() : cluster->pt();
-                    double totalcluster_pt  = m_useEnergy ? TrackTotalClusterPt->at(trk).E() : TrackTotalClusterPt->at(trk).Pt();
-                    tcc_4p += cluster->p4()*(( trk->pt() * cluster_pt / totalcluster_pt) / ((clusterToTracksWeightMap->at(cluster)).Pt()));
-                    ATH_MSG_VERBOSE ("cluster->pt() " << cluster_pt << " cluster->eta() " << cluster->eta() << " cluster->phi() " 
-		    << cluster->phi() << " track pt " << trk->pt() << " (clusterToTracksWeightMap.at(cluster)).Pt() " << (clusterToTracksWeightMap->at(cluster)).Pt());
-            } // for caloClusterLinks
-        } // if caloClusterLinks().size
-        
-        double eta = trk->eta();
-	double phi = trk->phi();
-	
-	if (m_doOriginCorrection) {
-	  // retrieve the caloExtensionContainer to get the track direction at the calo entrance
-	  IParticleToCaloExtensionMap * caloExtensionMap = 0;
-	  if(evtStore()->retrieve(caloExtensionMap,m_caloEntryMapName).isFailure())
-	    ATH_MSG_WARNING( "Unable to retrieve " << m_caloEntryMapName << " will leak the ParticleCaloExtension" );
-	  
-	  const Trk::TrackParameters* pars = caloExtensionMap->readCaloEntry(trk);
-	  eta = pars->position().eta();
-	  phi = pars->position().phi();
-	  
-	  computeVertexCorr(eta, phi, (vxCont->at(0))->position(), pars->position().perp());
-	  if (m_storeCorrectedPosition) {
-	    trk->auxdecor<int>("Corrected") = 1;
-	    trk->auxdecor<float>("CaloEntryPosEtaCorr") = eta;
-	    trk->auxdecor<float>("CaloEntryPosPhiCorr") = phi;
-	  }
-	}
-	
-	xAOD::TrackCaloCluster* tcc = new xAOD::TrackCaloCluster;
-	tccContainer->push_back(tcc);
-	tcc->setParameters(tcc_4p.Pt(),eta,phi,tcc_4p.M(),xAOD::TrackCaloCluster::Taste::Combined,assocClusters->trackParticleLink(),assocClusters->caloClusterLinks());
-	// Commenting this for the moment... We can decide if we want this back later.
-	//         tcc->setParameters(tcc_4p.Pt(),eta,phi,tcc_4p.M(),xAOD::TrackCaloCluster::Taste::Combined,assocClusters->trackParticleLink(),assocClusters->caloClusterLinks());
-	
-        ATH_MSG_VERBOSE ("Created TCC with pt " << tcc->pt() << " eta " << tcc->eta() << " phi " << tcc->phi() << " mass " << tcc->m() << " taste " << tcc->taste());
-	
-	if(m_saveDetectorEta) {
-	  // retrieve the caloExtensionContainer to get the track direction at the calo entrance
-	  IParticleToCaloExtensionMap * caloExtensionMap = 0;
-	  if(evtStore()->retrieve(caloExtensionMap,m_caloEntryMapName).isFailure())
-	    ATH_MSG_WARNING( "Unable to retrieve " << m_caloEntryMapName << " will leak the ParticleCaloExtension" );
-	  
-	  const Trk::TrackParameters* pars = caloExtensionMap->readCaloEntry(trk);
-	  double det_eta = pars->position().eta();
-	  tcc->auxdecor<float>("DetectorEta") = det_eta;
-	}
-    } // for assoc clusters
-    
-}
-
-void TrackCaloClusterCreatorTool::createNeutralTCCs(xAOD::TrackCaloClusterContainer* tccContainer, 
-							const xAOD::CaloClusterContainer* assocContainer, 
-							std::map <const xAOD::CaloCluster*, FourMom_t>* clusterToTracksWeightMap  ) {
-//   const xAOD::VertexContainer* vxCont=0;
-//   if (m_saveDetectorEta) {
-//     StatusCode sc = evtStore()->retrieve(vxCont, m_vertexContname);
-//     if (sc.isFailure()) {
-//         ATH_MSG_WARNING ("Vertex container " << m_vertexContname << " not found!");
-//     }
-//   }
-  unsigned int i = 0;
-  for ( const auto* cluster : *assocContainer ) {
-      if(clusterToTracksWeightMap->find(cluster)==clusterToTracksWeightMap->end()){
-	  if (m_applyFilter and m_clusterFilterTool->rejectCluster(*cluster)) continue;
-          xAOD::TrackCaloCluster* tcc = new xAOD::TrackCaloCluster;
-          tccContainer->push_back(tcc);
-	  ElementLink< xAOD::CaloClusterContainer > clusterLink(*assocContainer,i);
-	  const std::vector< ElementLink<xAOD::CaloClusterContainer> > ClusterLink {clusterLink};
-	  tcc->setParameters(cluster->pt(),cluster->eta(),cluster->phi(),cluster->m(),xAOD::TrackCaloCluster::Taste::Neutral,ElementLink<xAOD::TrackParticleContainer>(),ClusterLink);
-          ATH_MSG_VERBOSE ("Created TCC with pt " << tcc->pt() << " eta " << tcc->eta() << " phi " << tcc->phi() << " mass " << tcc->m() << " taste " << tcc->taste());
-	  static SG::AuxElement::Accessor< float > acc_det_eta ( "DetectorEta" );
-	  if(m_saveDetectorEta and acc_det_eta.isAvailable(*cluster)) {
-// 	    double det_eta = DetectorEta(*cluster, vxCont->at(0)->position());
-	    tcc->auxdecor<float>("DetectorEta") = acc_det_eta(*cluster);
-	  }
-      }
-      i++;
-  } // for all clusters
-}
-
-void TrackCaloClusterCreatorTool::createChargedTCCs(xAOD::TrackCaloClusterContainer* tccContainer, 
-						      const xAOD::TrackParticleContainer* assocContainer, 
-						      std::map <const xAOD::TrackParticle*, FourMom_t>* TrackTotalClusterPt  ) {
-    
-    const xAOD::VertexContainer *vxCont=0;
-    StatusCode sc = evtStore()->retrieve(vxCont, m_vertexContname);
-    if (sc.isFailure()) {
-        ATH_MSG_WARNING ("Vertex container " << m_vertexContname << " not found! Can't perform TVA!");
-    }
-
-    unsigned int i = 0;
-    for ( const auto* track : *assocContainer ) {
-        if(TrackTotalClusterPt->find(track)==TrackTotalClusterPt->end()){
-            bool isMatched = true;
-            if (vxCont && vxCont->size()!=0) {
-                isMatched = m_loosetrackvertexassoTool->isCompatible(*track, *(vxCont->at(0)) );
-            }
-            else{
-                ATH_MSG_WARNING ("Vertex container " << m_vertexContname << " is empty! Can't perform TVA!");
-            }
-            if (!isMatched) continue;
-            xAOD::TrackCaloCluster* tcc = new xAOD::TrackCaloCluster;
-            tccContainer->push_back(tcc);
-	    ElementLink< xAOD::TrackParticleContainer > trkLink(*assocContainer,i);
-            tcc->setParameters(track->pt(),track->eta(),track->phi(),track->m(),xAOD::TrackCaloCluster::Taste::Charged,trkLink,std::vector<ElementLink<xAOD::CaloClusterContainer>>());
-            ATH_MSG_VERBOSE ("Created TCC with pt " << tcc->pt() << " eta " << tcc->eta() << " phi " << tcc->phi() << " mass " << tcc->m() << " taste " << tcc->taste());
-
-	    if(m_saveDetectorEta) {
-	      // retrieve the caloExtensionContainer to get the track direction at the calo entrance
-	      IParticleToCaloExtensionMap * caloExtensionMap = 0;
-	      if(evtStore()->retrieve(caloExtensionMap,m_caloEntryMapName).isFailure())
-		ATH_MSG_WARNING( "Unable to retrieve " << m_caloEntryMapName << " will leak the ParticleCaloExtension" );
-	      
-	      const Trk::TrackParameters* pars = caloExtensionMap->readCaloEntry(track);
-	      double det_eta = track->eta();
-	      if(pars)
-		det_eta = pars->position().eta();
-	      tcc->auxdecor<float>("DetectorEta") = det_eta;
-	    }
-        }
-        i++;
-    } // for all tracks
-    
-}
-
-void TrackCaloClusterCreatorTool::computeVertexCorr(double& eta, double& phi, const Amg::Vector3D& vertex, double radius) {
-  
-  if (radius<1.) return;
-  
-  if (std::fabs(eta)>10. || std::fabs(phi)>10.) return;
-  
-  CxxUtils::sincos sc (phi);
-  double iradius = 1 / radius;
-  eta += (-vertex[2]/std::cosh(eta) + sc.apply (vertex[1], vertex[0])*std::tanh(eta)) * iradius;
-  phi += sc.apply (vertex[0], -vertex[1]) * iradius;
-}
-
-// double TrackCaloClusterCreatorTool::DetectorEta(const xAOD::CaloCluster& cluster, const Amg::Vector3D& vertex) {
-//   
-//   // this is the origin corrected eta
-//   double eta = cluster.eta();
-//     
-//   double radius = 0;
-//   double mag = 0;
-//   if (cluster.retrieveMoment (xAOD::CaloCluster::CENTER_MAG, mag))  
-//     radius = mag/std::cosh(eta);
-//  
-//   if (radius<1. || std::fabs(eta)>10.) return eta;
-//   
-//   double theta = 2.*std::atan(std::exp(-eta));
-//   double eta_det = std::atan(radius/(radius/std::tan(theta)-vertex[2]));
-//   
-//   return eta_det;
-//   
-// }
\ No newline at end of file
diff --git a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/src/TrackCaloClusterTool.cxx b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/src/TrackCaloClusterTool.cxx
new file mode 100644
index 00000000000..5fa6e4896e3
--- /dev/null
+++ b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/src/TrackCaloClusterTool.cxx
@@ -0,0 +1,398 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+#include "StoreGate/ReadDecorHandle.h"
+
+#include "AthContainers/AuxElement.h"
+
+#include "TrackCaloClusterRecTools/TrackCaloClusterTool.h"
+#include "TrackCaloClusterRecTools/TrackCaloClusterInfo.h"
+
+
+#include "CxxUtils/sincos.h"
+
+#include "TrackCaloClusterRecTools/TCCHelpers.h"
+
+
+namespace {
+  // helper functions needed only in this file are defined in this anonymous namespace
+  
+  typedef xAOD::IParticle::FourMom_t  FourMom_t; // this is actually 
+
+  // update the given eta and phi coordinates by shifting the origin to the position of vertex
+  void computeVertexCorr(double& eta, double& phi, const Amg::Vector3D& vertex, double radius) {
+  
+    if (radius<1.) return;
+    
+    if (std::fabs(eta)>10. || std::fabs(phi)>10.) return;
+  
+    CxxUtils::sincos sc (phi);
+    double iradius = 1 / radius;
+    eta += (-vertex[2]/std::cosh(eta) + sc.apply (vertex[1], vertex[0])*std::tanh(eta)) * iradius;
+    phi += sc.apply (vertex[0], -vertex[1]) * iradius;
+  }
+
+
+
+  template<typename T>
+  void setParameters(xAOD::FlowElement* fe, float pt, float eta, float phi, float m,
+		     xAOD::FlowElement::SignalType stype,
+		     const ElementLink<xAOD::IParticleContainer> &trackLink,
+		     const std::vector<ElementLink<T> >& neutralLinks){
+    std::vector<ElementLink<xAOD::IParticleContainer> > ipLinks(neutralLinks.size());
+    for(size_t i=0;i<neutralLinks.size();i++) ipLinks[i] = neutralLinks[i];
+    setParameters(fe,pt,eta,phi, m, stype,trackLink, ipLinks);
+  }
+
+  template<>
+  void setParameters<xAOD::IParticleContainer>(xAOD::FlowElement* fe, float pt, float eta, float phi, float m,
+		     xAOD::FlowElement::SignalType stype,
+		     const ElementLink<xAOD::IParticleContainer> &trackLink,
+		     const std::vector<ElementLink<xAOD::IParticleContainer> >& neutralLinks){
+    fe->setP4(pt,eta,phi,m);
+    fe->setSignalType(stype);
+    fe->setChargedObjectLinks( {trackLink} );
+    fe->setOtherObjectLinks( neutralLinks);
+  }
+  
+
+  /// help work around limitation of ReadDecorHandle
+  template<typename DTYPE, typename CTYPE>
+  SG::AuxElement::ConstAccessor<DTYPE> asConstAccessor(const SG::ReadDecorHandleKey<CTYPE> & wh){
+    static const std::string ts = typeid(DTYPE).name();
+    if(wh.empty() ) return SG::AuxElement::ConstAccessor<DTYPE>( typeid(DTYPE).name() );
+    const auto split = wh.key().rfind ('.');
+    if (split == std::string::npos)
+      throw std::runtime_error ("decor key does not contain a .: " + wh.key());
+    return SG::AuxElement::ConstAccessor<DTYPE>( wh.key().substr (split + 1) );
+  }
+  
+  
+
+}
+
+
+//*******************************************************************************
+
+TrackCaloClusterBaseTool::TrackCaloClusterBaseTool(const std::string& t, const std::string& n, const IInterface*  p )
+  : AthAlgTool(t,n,p)
+{
+  declareInterface<ITrackCaloClusterTool>(this);
+}
+TrackCaloClusterBaseTool::~TrackCaloClusterBaseTool() {}
+
+
+StatusCode TrackCaloClusterBaseTool::initialize() {
+  if(!m_trackVertexAssoTool.empty()) ATH_CHECK(m_trackVertexAssoTool.retrieve());
+
+  ATH_CHECK(m_assoClustersKey.initialize());
+
+  ATH_CHECK(m_caloEntryParsDecor.initialize(!m_caloEntryParsDecor.empty()) );
+  return StatusCode::SUCCESS;
+}
+
+
+
+
+
+
+
+//*******************************************************************************
+
+TCCCombinedTool::TCCCombinedTool(const std::string& t, const std::string& n, const IInterface*  p )
+  : TrackCaloClusterBaseTool(t,n,p) { }
+
+
+StatusCode TCCCombinedTool::fillTCC(xAOD::FlowElementContainer* tccContainer, const TrackCaloClusterInfo & tccInfo ) const {
+
+  if(tccInfo.pv0==nullptr){
+    ATH_MSG_ERROR ("No PV0 available ! ");
+    return StatusCode::FAILURE;
+  }
+
+  // declare Decorator in case we want to save out corrected positions
+  static SG::AuxElement::Decorator<int> dec_isCorrected("Corrected");
+  static SG::AuxElement::Decorator<float> dec_calEntryEta("CaloEntryPosEtaCorr") ;
+  static SG::AuxElement::Decorator<float> dec_calEntryPhi("CaloEntryPosPhiCorr") ;
+  static SG::AuxElement::Decorator<float> dec_detEta("DetectorEta") ;
+
+  // it is not possible to prepare a blank ReadDecorHandle (which we need if !m_caloEntryParsDecor.empty()), so instead or re-instantiating a ReadDecorHandle on each
+  // track in the loop below, we just instantiate a ConstAccessor  
+  SG::ReadDecorHandle<xAOD::TrackParticleContainer, std::vector<ElementLink<xAOD::CaloClusterContainer>> > clusterLinksH(m_assoClustersKey);
+  auto caloEntryParams = asConstAccessor<const Trk::TrackParameters*>(m_caloEntryParsDecor);
+  
+  
+  for ( const xAOD::TrackParticle* trk : *tccInfo.allTracks ) {
+
+    if (! m_trackVertexAssoTool->isCompatible(*trk, *tccInfo.pv0) ) continue ;
+   
+    const auto & clusterLinks = clusterLinksH(*trk);
+    if( clusterLinks.empty() ) continue;
+    
+    FourMom_t tcc_4p(0.,0.,0.,0.); // will be the TCC 4-vector
+
+    // Loop over associated clusters to sum the 4-vectors x weigths
+    for( const ElementLink<xAOD::CaloClusterContainer> & clLink : clusterLinks){
+      const xAOD::CaloCluster* cluster = *clLink;
+
+      double cluster_pt       = m_useEnergy ? cluster->e() : cluster->pt();
+      double totalcluster_pt  = m_useEnergy ? tccInfo.trackTotalClusterPt.at(trk).E() : tccInfo.trackTotalClusterPt.at(trk).Pt();
+      
+      tcc_4p += cluster->p4()*(( trk->pt() * cluster_pt / totalcluster_pt) / ((tccInfo.clusterToTracksWeightMap.at(cluster)).Pt()));
+      
+      ATH_MSG_VERBOSE ("cluster->pt() " << cluster_pt << " cluster->eta() " << cluster->eta() << " cluster->phi() " 
+                       << cluster->phi() << " track pt " << trk->pt() << " (tccInfo.clusterToTracksWeightMap.at(cluster)).Pt() " << (tccInfo.clusterToTracksWeightMap.at(cluster)).Pt());
+    } // for caloClusterLinks
+    
+
+    // get angular position from tracks
+    double eta = trk->eta();
+    double phi = trk->phi();
+    
+    if (m_doOriginCorrection) {
+      // retrieve the caloExtensionContainer to get the track direction at the calo entrance
+      
+      const Trk::TrackParameters* pars = caloEntryParams(*trk);
+      eta = pars->position().eta();
+      phi = pars->position().phi();
+	  
+      computeVertexCorr(eta, phi, tccInfo.pv0->position(), pars->position().perp());
+      if (m_storeCorrectedPosition) {
+        dec_isCorrected(*trk) = 1;
+	dec_calEntryEta(*trk) = eta;
+	dec_calEntryPhi(*trk) = phi;
+      }
+    }
+	
+    // Build the final TCC
+    xAOD::FlowElement* tcc = new xAOD::FlowElement;
+    tccContainer->push_back(tcc);
+    setParameters(tcc, tcc_4p.Pt(),eta,phi,tcc_4p.M(),xAOD::FlowElement::SignalType::Combined,
+		  ElementLink<xAOD::TrackParticleContainer>(*tccInfo.allTracks, trk->index() ),clusterLinks);
+    
+    ATH_MSG_VERBOSE ("Created TCC with pt " << tcc->pt() << " eta " << tcc->eta() << " phi " << tcc->phi() << " mass " << tcc->m() << " signalType= " << tcc->signalType());
+    
+    if(m_saveDetectorEta) {	  
+      const Trk::TrackParameters* pars = caloEntryParams(*trk);
+      double det_eta = pars->position().eta();      
+      dec_detEta(*tcc) = det_eta;
+    }
+  } // for assoc clusters
+
+  
+  return StatusCode::SUCCESS;
+}
+
+
+
+
+
+
+
+//*******************************************************************************
+
+TCCChargedTool::TCCChargedTool(const std::string& t, const std::string& n, const IInterface*  p )
+  : TrackCaloClusterBaseTool(t,n,p) { }
+
+
+    
+StatusCode TCCChargedTool::fillTCC(xAOD::FlowElementContainer* tccContainer, const TrackCaloClusterInfo & tccInfo ) const {
+      
+
+  // it is not possible to prepare a blank ReadDecorHandle (which we need if !m_caloEntryParsDecor.empty()), so instead or re-instantiating a ReadDecorHandle on each
+  // track in the loop below, we just instantiate a ConstAccessor  
+  auto caloEntryParams = asConstAccessor<const Trk::TrackParameters*>(m_caloEntryParsDecor);
+  
+  SG::ReadDecorHandle<xAOD::TrackParticleContainer, std::vector<ElementLink<xAOD::CaloClusterContainer>> > clusterLinksH(m_assoClustersKey);
+  
+  // declare Decorator in case we want to save out corrected positions  
+  static SG::AuxElement::Decorator<float> dec_detEta("DetectorEta") ;
+  
+  unsigned int i = 0;
+  // Loop over ALL tracks at the source of TCC
+  for ( const xAOD::TrackParticle* track : *tccInfo.allTracks ) {
+    if( ! clusterLinksH(*track).empty() ) continue; // because if not empty, it is matched to a cluster
+    // considre ONLY tracks NOT matched to a cluster :
+    if(tccInfo.trackTotalClusterPt.find(track)==tccInfo.trackTotalClusterPt.end()){
+      bool isMatched = m_trackVertexAssoTool->isCompatible(*track, *tccInfo.pv0 );
+      if (!isMatched) continue;
+      
+      xAOD::FlowElement* tcc = new xAOD::FlowElement;
+      tccContainer->push_back(tcc);
+      ElementLink< xAOD::TrackParticleContainer > trkLink(*tccInfo.allTracks,i);
+      setParameters(tcc, track->pt(),track->eta(),track->phi(),track->m(),xAOD::FlowElement::SignalType::Charged,trkLink,std::vector<ElementLink<xAOD::CaloClusterContainer>>());
+      ATH_MSG_VERBOSE ("Created TCC with pt " << tcc->pt() << " eta " << tcc->eta() << " phi " << tcc->phi() << " mass " << tcc->m() << " taste " << tcc->signalType());
+
+      if(m_saveDetectorEta) {
+        // retrieve the caloExtensionContainer to get the track direction at the calo entrance
+        double det_eta = track->eta();
+	const Trk::TrackParameters* pars = caloEntryParams(*track);
+        if(pars) det_eta = pars->position().eta();
+        dec_detEta(*tcc) = det_eta;
+      }
+    }
+    i++;
+  }
+  return StatusCode::SUCCESS;
+}
+    
+
+
+
+
+//*******************************************************************************
+
+TCCNeutralTool::TCCNeutralTool(const std::string& t, const std::string& n, const IInterface*  p )
+  : TrackCaloClusterBaseTool(t,n,p) {}
+
+StatusCode TCCNeutralTool::initialize() {
+  ATH_CHECK(TrackCaloClusterBaseTool::initialize());
+  if (!m_clusterFilterTool.empty()){
+    ATH_CHECK(m_clusterFilterTool.retrieve());
+    m_applyFilter=true;
+  } else m_applyFilter=false;
+  return StatusCode::SUCCESS;
+}
+
+
+    
+StatusCode TCCNeutralTool::fillTCC(xAOD::FlowElementContainer* tccContainer, const TrackCaloClusterInfo & tccInfo ) const {
+  
+  unsigned int i = 0;
+  // declare Decorator in case we want to save out corrected positions  
+  static SG::AuxElement::Decorator<float> dec_detEta("DetectorEta") ;
+
+  // Loop over ALL clusters 
+  for ( const xAOD::CaloCluster* cluster : *tccInfo.allClusters ) {
+    // consider only clusters NOT matched to a track :
+    if(tccInfo.clusterToTracksWeightMap.find(cluster)==tccInfo.clusterToTracksWeightMap.end()){
+      if (m_applyFilter and m_clusterFilterTool->rejectCluster(*cluster)) continue;
+      
+      // create a neutral TCC
+      xAOD::FlowElement* tcc = new xAOD::FlowElement;
+      tccContainer->push_back(tcc);
+      ElementLink< xAOD::CaloClusterContainer > clusterLink(*tccInfo.allClusters,i);
+      const std::vector< ElementLink<xAOD::CaloClusterContainer> > ClusterLink {clusterLink};
+      setParameters(tcc, cluster->pt(),cluster->eta(),cluster->phi(),cluster->m(),xAOD::FlowElement::SignalType::Neutral,ElementLink<xAOD::TrackParticleContainer>(),ClusterLink);
+      ATH_MSG_VERBOSE ("Created TCC with pt " << tcc->pt() << " eta " << tcc->eta() << " phi " << tcc->phi() << " mass " << tcc->m() << " taste " << tcc->signalType());
+      
+      static SG::AuxElement::Accessor< float > acc_det_eta ( "DetectorEta" );        
+      if(m_saveDetectorEta && acc_det_eta.isAvailable(*cluster)) {
+        dec_detEta(*tcc) = dec_detEta(*cluster);
+      }
+    }
+    i++;
+  } // for all clusters
+  return StatusCode::SUCCESS;
+}
+
+
+
+
+
+
+
+
+
+
+//*******************************************************************************
+
+
+
+namespace TCCHelpers{
+  ///////////////////////////////////////////////////////
+  /// Implement a concrete CombinedUFOLoop dedicated to building UFO
+  ///  see TCCHelpers.h in TrackCaloClusterRecTools/
+  struct UFOBuilder : public CombinedUFOLoop {
+
+    const xAOD::PFOContainer * m_pfoContainer;
+    const TrackCaloClusterInfo* m_tccInfo;
+    xAOD::FlowElementContainer * m_tccContainer;
+    
+    std::vector<ElementLink< xAOD::PFOContainer > > m_pfoLinks;
+    FourMom_t m_tcc_4p = {0.,0.,0.,0.};
+    
+    virtual void processPFO(const xAOD::TrackParticle* trk, const xAOD::PFO* pfo) {
+      /// accumulate the total P4 and the pfos linked to trk
+      
+      ElementLink< xAOD::PFOContainer > pfoLink(*m_pfoContainer,pfo->index());
+      m_pfoLinks.push_back(pfoLink);
+      double pfo_pt       = m_useEnergy ? pfo->e() : pfo->pt();
+      const FourMom_t & totalP = m_tccInfo->trackTotalClusterPt.at(trk);
+      double totalpfo_pt  = m_useEnergy ? totalP.E() : totalP.Pt();
+      m_tcc_4p += pfo->p4()*(( trk->pt() * pfo_pt / totalpfo_pt) / ((m_tccInfo->clusterToTracksWeightMap.at(pfo)).Pt()));
+    }
+    
+    virtual void processTrk(const xAOD::TrackParticle* trk ) {
+      // build the actual combined UFO
+      if(m_tcc_4p.Pt() <=0) return;
+      
+      xAOD::FlowElement* tcc = new xAOD::FlowElement;
+      m_tccContainer->push_back(tcc);
+      setParameters(tcc, m_tcc_4p.Pt(), trk->eta(), trk->phi(),m_tcc_4p.M(),xAOD::FlowElement::SignalType::Combined,
+		    ElementLink<xAOD::TrackParticleContainer>(*m_tccInfo->allTracks,trk->index()),m_pfoLinks);
+
+      // reset accumulators for next track :
+      m_pfoLinks.clear();
+      m_tcc_4p = {0.,0.,0.,0.};
+    }
+  };
+}
+
+
+
+UFOTool::UFOTool(const std::string& t, const std::string& n, const IInterface*  p )
+  : TrackCaloClusterBaseTool(t,n,p) {}
+
+
+StatusCode UFOTool::fillTCC(xAOD::FlowElementContainer* tccContainer, const TrackCaloClusterInfo & tccInfo ) const {
+
+  SG::ReadHandle<xAOD::PFOContainer> pfos(m_inputPFOHandle);
+
+  SG::ReadDecorHandle<xAOD::PFOContainer, ElementLink<xAOD::PFOContainer> > orig_pfo(m_orig_pfo);
+  SG::ReadDecorHandle<xAOD::TrackParticleContainer, std::vector<ElementLink<xAOD::CaloClusterContainer>> > clusterLinksH(m_assoClustersKey);
+
+
+  // We use a dedicated helper to build the combined UFO. Initialize it :  
+  TCCHelpers::UFOBuilder ufoB;
+  ufoB.m_orig_pfoK = m_orig_pfo.key();
+  ufoB.m_clustersLinkK = m_assoClustersKey.key();
+  ufoB.m_trackVertexAssoTool = m_trackVertexAssoTool.get();
+  ufoB.m_clusterEcut = m_clusterEcut;
+  ufoB.m_useEnergy = m_useEnergy;
+
+  ufoB.m_pfoContainer = pfos.ptr();
+  ufoB.m_tccInfo = &tccInfo;
+  ufoB.m_tccContainer = tccContainer;
+
+  // create a combined UFO for each track matched to some PFO 
+  ufoB.combinedUFOLoop(&tccInfo, pfos.cptr());
+  
+  
+  // Create a UFO for all neutral and charged PFO which are not matched to any tracks
+  unsigned int i = -1;
+  for ( const xAOD::PFO* pfo : *pfos ) {
+    i++;
+    if(pfo->pt() <= 0) continue;
+    if(tccInfo.clusterToTracksWeightMap.find(pfo)!=tccInfo.clusterToTracksWeightMap.end()) continue; // combined
+
+    if(pfo->isCharged()) {
+      // this decoration is set by JetRecTools/Root/ChargedHadronSubtractionTool.cxx !
+      const static SG::AuxElement::Accessor<char> PVMatchedAcc("matchedToPV"); 
+      if(!PVMatchedAcc(*pfo)) continue;
+    }
+    
+    ElementLink< xAOD::PFOContainer > pfoLink(*pfos,i);
+    const std::vector< ElementLink<xAOD::PFOContainer> > PFOLink {pfoLink};    
+    xAOD::FlowElement* tcc = new xAOD::FlowElement;
+    tccContainer->push_back(tcc);
+
+    if(pfo->isCharged()) {
+      setParameters(tcc, pfo->pt(), pfo->eta(), pfo->phi(), pfo->m(), xAOD::FlowElement::SignalType::Charged, ElementLink<xAOD::TrackParticleContainer>(*tccInfo.allTracks, pfo->track(0)->index()), PFOLink);
+    }else{
+      setParameters(tcc, pfo->pt(),pfo->eta(),pfo->phi(),pfo->m(),xAOD::FlowElement::SignalType::Neutral,ElementLink<xAOD::TrackParticleContainer>(),PFOLink);      
+    }
+  } //  PFO
+    
+  return StatusCode::SUCCESS;
+}
diff --git a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/src/TrackCaloClusterWeightsTool.cxx b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/src/TrackCaloClusterWeightsTool.cxx
deleted file mode 100644
index cc266823f70..00000000000
--- a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/src/TrackCaloClusterWeightsTool.cxx
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
-  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
-*/
-#include "TrackCaloClusterRecTools/TrackCaloClusterWeightsTool.h"
-
-
-TrackCaloClusterWeightsTool::TrackCaloClusterWeightsTool(const std::string& t, const std::string& n, const IInterface*  p )
-  : AthAlgTool(t,n,p),
-    m_useEnergy(false)
-{
-    declareProperty("UseEnergy",        m_useEnergy );
-}
-
-TrackCaloClusterWeightsTool::~TrackCaloClusterWeightsTool() {}
-
-StatusCode TrackCaloClusterWeightsTool::initialize() {
-  return StatusCode::SUCCESS;
-}
-
-StatusCode TrackCaloClusterWeightsTool::finalize() {
-  return StatusCode::SUCCESS;
-}
-
-void TrackCaloClusterWeightsTool::fillWeightMaps( const xAOD::TrackParticleClusterAssociationContainer* assocContainer, 
-						  std::multimap <const xAOD::CaloCluster*, const xAOD::TrackParticle*>* clusterToTracksMap, 
-						  std::map <const xAOD::TrackParticle*, FourMom_t>* TrackTotalClusterPt, 
-						  std::map <const xAOD::CaloCluster*, FourMom_t>* clusterToTracksWeightMap ) {
-
-    // First loop to fill cluster-to-tracks map
-    for ( const auto* assocClusters : *assocContainer ) {
-        // flollow the link to the track particle
-        const xAOD::TrackParticle* trk = 0;
-        if (assocClusters->trackParticleLink().isValid()) {
-            trk = *(assocClusters->trackParticleLink());
-        }
-        else if ( !assocClusters->trackParticleLink().isValid() ){
-            ATH_MSG_ERROR ("trackParticleLink is not valid! " );
-        }
-        // follow the link to the calorimeter clusters
-        if (assocClusters->caloClusterLinks().size()) {
-            for (size_t c = 0; c < assocClusters->caloClusterLinks().size(); ++c) {
-                    const xAOD::CaloCluster* cluster = *(assocClusters->caloClusterLinks().at(c));
-                    clusterToTracksMap->insert(std::make_pair(cluster, trk));
-                    if(TrackTotalClusterPt->find(trk)==TrackTotalClusterPt->end()){
-                        TrackTotalClusterPt->insert(std::make_pair(trk, cluster->p4()));
-                    }
-                    else{
-                        TrackTotalClusterPt->at(trk) = TrackTotalClusterPt->at(trk) + cluster->p4();
-                    }
-            } // for caloClusterLinks
-        } // if caloClusterLinks().size
-    } // for assoc clusters
-    
-    // Create cluster-to-tracks weight map
-    for (auto entry : *clusterToTracksMap)
-    {
-        double cluster_pt       = m_useEnergy ? entry.first->e() : entry.first->pt();
-        double totalcluster_pt  = m_useEnergy ? TrackTotalClusterPt->at(entry.second).E() : TrackTotalClusterPt->at(entry.second).Pt();
-        if(clusterToTracksWeightMap->find(entry.first)==clusterToTracksWeightMap->end()){
-            clusterToTracksWeightMap->insert(std::make_pair(entry.first, entry.second->p4() * (cluster_pt/totalcluster_pt)));
-        }
-        else{
-            clusterToTracksWeightMap->at(entry.first) = clusterToTracksWeightMap->at(entry.first) + entry.second->p4() * (cluster_pt/totalcluster_pt);
-        }
-    }
-    
-}
-
diff --git a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/src/components/ParticleToCaloExtrapolationTool_entries.cxx b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/src/components/ParticleToCaloExtrapolationTool_entries.cxx
index c5a37e62da6..7ad7dbf42be 100644
--- a/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/src/components/ParticleToCaloExtrapolationTool_entries.cxx
+++ b/Reconstruction/TrackCaloClusterRec/TrackCaloClusterRecTools/src/components/ParticleToCaloExtrapolationTool_entries.cxx
@@ -1,10 +1,11 @@
 #include "TrackCaloClusterRecTools/ParticleToCaloExtrapolationTool.h"
-#include "TrackCaloClusterRecTools/TrackCaloClusterWeightsTool.h"
-#include "TrackCaloClusterRecTools/TrackCaloClusterCreatorTool.h"
+#include "TrackCaloClusterRecTools/TrackCaloClusterTool.h"
 #include "TrackCaloClusterRecTools/ClusterFilterTool.h"
  
 DECLARE_COMPONENT( ParticleToCaloExtrapolationTool )
-DECLARE_COMPONENT( TrackCaloClusterWeightsTool )
-DECLARE_COMPONENT( TrackCaloClusterCreatorTool )
+DECLARE_COMPONENT( TCCCombinedTool )
+DECLARE_COMPONENT( TCCChargedTool )
+DECLARE_COMPONENT( TCCNeutralTool )
+DECLARE_COMPONENT( UFOTool )
 DECLARE_COMPONENT( ClusterFilterTool )
 
-- 
GitLab