diff --git a/Reconstruction/eflowRec/eflowRec/IPFClusterSelectorTool.h b/Reconstruction/eflowRec/eflowRec/IPFClusterSelectorTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..47a1415a4e23d500d670a3030efeb322463ffc4c
--- /dev/null
+++ b/Reconstruction/eflowRec/eflowRec/IPFClusterSelectorTool.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef IPFCLUSTERSELECTIONTOOL_H
+#define IPFCLUSTERSELECTORTOOL_H
+
+#include "GaudiKernel/IAlgTool.h"
+#include "xAODCaloEvent/CaloClusterContainer.h"
+
+class IPFClusterSelectorTool : virtual public IAlgTool {
+
+ public:
+
+  /** Execute method to modify xAOD::CaloClusterContainer */
+  virtual StatusCode execute(xAOD::CaloClusterContainer&) = 0;
+
+  DeclareInterfaceID(IPFClusterSelectorTool,1,0);
+
+};
+#endif
diff --git a/Reconstruction/eflowRec/eflowRec/PFClusterSelectorTool.h b/Reconstruction/eflowRec/eflowRec/PFClusterSelectorTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..def29509865ce7ca5b767393283da71ae745032f
--- /dev/null
+++ b/Reconstruction/eflowRec/eflowRec/PFClusterSelectorTool.h
@@ -0,0 +1,42 @@
+#ifndef PFCLUSTERSELECTORTOOL_H
+#define PFCLUSTERSELECTORTOOL_H
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "eflowRec/IPFClusterSelectorTool.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "xAODCaloEvent/CaloClusterContainer.h"
+
+#include <map>
+
+class eflowRecClusterContainer;
+
+class PFClusterSelectorTool : public extends<AthAlgTool, IPFClusterSelectorTool> {
+
+public:
+  /** Default constructor */
+  PFClusterSelectorTool(const std::string& type,const std::string& name,const IInterface* parent);
+  /** Default destructor */
+  ~PFClusterSelectorTool() {};
+
+  /** Gaudi AthAlgorithm hooks */
+  StatusCode initialize();
+  StatusCode execute(xAOD::CaloClusterContainer&);
+  StatusCode finalize();
+
+private:
+  /** for EM mode, LC weight for cells are retrieved before doing any subtraction; they will be used after subtraction */
+  void retrieveLCCalCellWeight(const double& energy, const unsigned& index, std::map<IdentifierHash,double>& cellsWeight,const xAOD::CaloClusterContainer& caloCalClustersContainer);
+  
+  /** ReadHandleKey for the CaloClusterContainer to be used as input */
+  SG::ReadHandleKey<xAOD::CaloClusterContainer> m_caloClustersReadHandleKey{this,"clustersName","CaloTopoCluster","ReadHandleKey for the CaloClusterContainer to be used as input"};
+
+  /** ReadHandleKey for the CaloClusterContainer, at LC scale, to be used as input */
+  SG::ReadHandleKey<xAOD::CaloClusterContainer> m_caloCalClustersReadHandleKey{this,"calClustersName","CaloCalTopoClusters","ReadHandleKey for the CaloClusterContainer, at LC scale, to be used as input"};
+
+  /** WriteHandleKey for the eflowRecClusterContainer to write out */
+  SG::WriteHandleKey<eflowRecClusterContainer> m_eflowRecClustersWriteHandleKey{this,"eflowRecClustersOutputName","eflowRecClusters","WriteHandleKey for the eflowRecClusterContainer to write out"};
+  
+
+  
+};
+#endif
diff --git a/Reconstruction/eflowRec/src/PFClusterSelectorTool.cxx b/Reconstruction/eflowRec/src/PFClusterSelectorTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..7a033a60c36f5d02316f529c08c23a26ae16e5ff
--- /dev/null
+++ b/Reconstruction/eflowRec/src/PFClusterSelectorTool.cxx
@@ -0,0 +1,113 @@
+#include "CaloDetDescr/CaloDetDescrManager.h"
+#include "CaloIdentifier/CaloCell_ID.h"
+#include "eflowRec/eflowRecCluster.h"
+#include "eflowRec/PFClusterSelectorTool.h"
+#include "xAODCaloEvent/CaloCluster.h"
+
+PFClusterSelectorTool::PFClusterSelectorTool(const std::string& type,const std::string& name,const IInterface* parent):
+  base_class(type, name, parent)
+{
+}
+
+StatusCode PFClusterSelectorTool::initialize(){
+
+  ATH_CHECK(m_caloClustersReadHandleKey.initialize());
+  ATH_CHECK(m_caloCalClustersReadHandleKey.initialize());
+
+  ATH_CHECK(m_eflowRecClustersWriteHandleKey.initialize());
+
+  return StatusCode::SUCCESS;
+}
+
+StatusCode PFClusterSelectorTool::execute(xAOD::CaloClusterContainer&){
+
+  SG::ReadHandle<xAOD::CaloClusterContainer> caloClustersReadHandle(m_caloClustersReadHandleKey);
+  
+  /* Verify the read handle has a valid pointer, and if not return */
+  if (!caloClustersReadHandle.isValid()){
+    ATH_MSG_WARNING(" Invalid ReadHandle for xAOD::CaloCluster with key: " <<  caloClustersReadHandle.key());
+    return StatusCode::SUCCESS;
+  }
+  /* Record the eflowRecCluster output container */
+  SG::WriteHandle<eflowRecClusterContainer> eflowRecClustersWriteHandle(m_eflowRecClustersWriteHandleKey);
+  ATH_CHECK(eflowRecClustersWriteHandle.record(std::make_unique<eflowRecClusterContainer>()));
+
+  SG::ReadHandle<xAOD::CaloClusterContainer> caloCalClustersReadHandle(m_caloCalClustersReadHandleKey);
+  
+  /* Fill the vector of eflowRecClusters */
+  unsigned int nClusters = caloClustersReadHandle->size();
+  for (unsigned int iCluster = 0; iCluster < nClusters; ++iCluster) {
+    /* Create the eflowRecCluster and put it in the container */
+    std::unique_ptr<eflowRecCluster> thisEFRecCluster  = std::make_unique<eflowRecCluster>(ElementLink<xAOD::CaloClusterContainer>(*caloClustersReadHandle, iCluster));
+    
+    if (caloCalClustersReadHandle.isValid()){
+      std::map<IdentifierHash,double> cellsWeightMap;
+      retrieveLCCalCellWeight(caloClustersReadHandle->at(iCluster)->e(), iCluster, cellsWeightMap, *caloCalClustersReadHandle);
+
+      if (msgLvl(MSG::DEBUG)) {
+        //zhangr
+        std::map<IdentifierHash, double>::iterator it = cellsWeightMap.begin();
+        for (; it != cellsWeightMap.end(); ++it) {
+	  ATH_MSG_DEBUG("zhangrui eflowPreparation " << iCluster << "/" << nClusters << ": e="
+                    << caloClustersReadHandle->at(iCluster)->e() << " (" << it->first << "  "
+			<< it->second << ")");
+        }
+      }
+
+      thisEFRecCluster->setCellsWeight(cellsWeightMap);
+    }
+
+    thisEFRecCluster->setClusterId(iCluster);
+    eflowRecClustersWriteHandle->push_back(std::move(thisEFRecCluster));
+
+    if (msgLvl(MSG::DEBUG)) {
+      const xAOD::CaloCluster* thisCluster = caloClustersReadHandle->at(iCluster);
+      ATH_MSG_DEBUG("eflowPreparation clus = " << thisCluster->eta() << " " << thisCluster->phi() << " " << thisCluster->e()/cosh(thisCluster->eta()));
+    }
+  }
+  
+  return StatusCode::SUCCESS;
+}
+
+StatusCode PFClusterSelectorTool::finalize(){
+  return StatusCode::SUCCESS;
+}
+
+void PFClusterSelectorTool::retrieveLCCalCellWeight(const double& energy, const unsigned& index, std::map<IdentifierHash,double>& cellsWeight, const xAOD::CaloClusterContainer& caloCalClustersContainer) {
+  
+  /* match CaloCluster with CaloCalCluster to obtain cell weight */
+  /* first try the position at 'index'. If we are lucky, the loop can be avoided. */
+  /* Note the read handle has been tested to be valid prior to the call of this function */
+  const xAOD::CaloCluster* matchedCalCluster = caloCalClustersContainer.at(index);
+
+  if (matchedCalCluster){
+
+    if (!(fabs(energy - matchedCalCluster->rawE()) < 0.001)) {
+      matchedCalCluster = nullptr;
+      for (unsigned iCalCalCluster = 0; iCalCalCluster < caloCalClustersContainer.size();
+	   ++iCalCalCluster) {
+	matchedCalCluster = caloCalClustersContainer.at(iCalCalCluster);
+	if (fabs(energy - matchedCalCluster->rawE()) < 0.001) {
+	  break;
+	}
+      }
+      if (!matchedCalCluster) ATH_MSG_WARNING("Invalid pointer to matched cluster - failed to find cluster match");
+    }
+    assert(matchedCalCluster);
+
+    /* obtain cell index and cell weight */
+    const CaloDetDescrManager*   calo_dd_man  = CaloDetDescrManager::instance();
+    const CaloCell_ID*               calo_id  = calo_dd_man->getCaloCell_ID();
+    xAOD::CaloCluster::const_cell_iterator itCell = matchedCalCluster->cell_begin();
+    xAOD::CaloCluster::const_cell_iterator endCell = matchedCalCluster->cell_end();
+    for (; itCell != endCell; ++itCell) {
+      const CaloCell* pCell = *itCell;
+      Identifier myId = pCell->ID();
+      IdentifierHash myHashId = calo_id->calo_cell_hash(myId);
+      cellsWeight[myHashId] = itCell.weight();
+    }
+  }
+  else ATH_MSG_WARNING("Invalid pointer to matched cluster - could not look up local hadron cell weights");
+
+  return ;
+}