diff --git a/Reconstruction/eflowRec/eflowRec/PFLCCalibTool.h b/Reconstruction/eflowRec/eflowRec/PFLCCalibTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..ae9a48321e85c1a3cac9efa9df7630aefda57fe7
--- /dev/null
+++ b/Reconstruction/eflowRec/eflowRec/PFLCCalibTool.h
@@ -0,0 +1,67 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef PFLCCALIBTOOL_H
+#define PFLCCALIBTOOL_H
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "xAODCaloEvent/CaloCluster.h"
+#include "xAODCaloEvent/CaloClusterContainer.h"
+#include "CaloRec/CaloClusterCollectionProcessor.h"
+#include "eflowRec/IPFBaseTool.h"
+#include "eflowRec/IPFClusterCollectionTool.h"
+
+#include <cassert>
+
+class eflowCaloObjectContainer;
+class eflowRecCluster;
+
+static const InterfaceID IID_PFLCCalibTool("PFLCCalibTool", 1, 0);
+
+class PFLCCalibTool : virtual public IPFBaseTool, public AthAlgTool {
+
+  public:
+  
+  PFLCCalibTool(const std::string& type,const std::string& name,const IInterface* parent);
+
+  ~PFLCCalibTool() {}
+
+  static const InterfaceID& interfaceID();
+
+  StatusCode initialize();
+  void execute(eflowCaloObjectContainer* theEflowCaloObjectContainer, xAOD::CaloClusterContainer& theCaloClusterContainer);
+  StatusCode finalize();
+
+ private:
+
+  void apply(ToolHandle<CaloClusterCollectionProcessor>& calibTool, xAOD::CaloCluster* cluster);
+  void applyLocal(ToolHandle<CaloClusterCollectionProcessor>& calibTool, eflowRecCluster *cluster);
+  void applyLocalWeight(eflowRecCluster* theEFRecCluster);
+
+  /** Tool to put all clusters into a temporary container - then we use this to calculate moments, some of which depend on configuration of nearby clusters */
+  ToolHandle<IPFClusterCollectionTool> m_clusterCollectionTool;
+
+  /* Tool for applying local hadronc calibration weights to cells */
+  ToolHandle<CaloClusterCollectionProcessor> m_clusterLocalCalibTool;
+
+  /* Tool to deal with out of cluster corrections */
+  ToolHandle<CaloClusterCollectionProcessor> m_clusterLocalCalibOOCCTool;
+
+  /* Tool to do Pi0 corrections */
+  ToolHandle<CaloClusterCollectionProcessor> m_clusterLocalCalibOOCCPi0Tool;
+
+  /* Tool for correcting clusters at cell level for dead materia */
+  ToolHandle<CaloClusterCollectionProcessor> m_clusterLocalCalibDMTool;
+
+  bool m_useLocalWeight;
+
+};
+
+inline const InterfaceID& PFLCCalibTool::interfaceID()
+{ 
+  return IID_PFLCCalibTool;
+}
+
+#endif
diff --git a/Reconstruction/eflowRec/eflowRec/PFOChargedCreatorTool.h b/Reconstruction/eflowRec/eflowRec/PFOChargedCreatorTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..2ea32817837e319945ba2e0aae5d1e928effe6d0
--- /dev/null
+++ b/Reconstruction/eflowRec/eflowRec/PFOChargedCreatorTool.h
@@ -0,0 +1,63 @@
+#ifndef PFOCHARGEDCREATORTOOL_H
+#define PFOCHARGEDCREATORTOOL_H
+
+#include "eflowRec/IPFBaseTool.h"
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "StoreGate/DataHandle.h"
+
+#include "TrackVertexAssociationTool/ITrackVertexAssociationTool.h"
+
+#include "xAODPFlow/PFOContainer.h"
+#include "xAODTracking/VertexContainer.h"
+
+class eflowCaloObject;
+class eflowCaloObjectContainer;
+class eflowRecCluster;
+
+static const InterfaceID IID_PFOChargedCreatorTool("PFOChargedCreatorTool", 1, 0);
+
+class PFOChargedCreatorTool : virtual public IPFBaseTool, public AthAlgTool {
+  
+public:
+  
+  PFOChargedCreatorTool(const std::string& type,const std::string& name,const IInterface* parent);
+
+  ~PFOChargedCreatorTool() {}
+
+  static const InterfaceID& interfaceID();
+
+  StatusCode initialize();
+  StatusCode execute(eflowCaloObject* energyFlowCaloObject);
+  void execute(eflowCaloObjectContainer* theEflowCaloObjectContainer, xAOD::CaloClusterContainer& theCaloClusterContainer);
+  StatusCode finalize();
+
+private:
+  StatusCode setupPFOContainers();
+  /** Create the charged PFO */ 
+  void createChargedPFO(eflowCaloObject* energyFlowCaloObject, bool addClusters = false);
+  /** Function to add links to the vertex to which a charged PFO is matched (using the tracking CP loose vertex association tool) */
+  void addVertexLinksToChargedPFO(const xAOD::VertexContainer& theVertexContainer);
+
+  /** Toggle e/p mode */
+  bool m_eOverPMode;
+
+  /** ToolHandle to tracking CP loose vertex selection tool */
+  ToolHandle<CP::ITrackVertexAssociationTool> m_trackVertexAssociationTool;
+
+  /** ReadHandle for vertex container */
+  SG::ReadHandle<xAOD::VertexContainer> m_vertexContainerReadHandle;
+  
+  /** WriteHandle for charged PFO */
+  SG::WriteHandle<xAOD::PFOContainer> m_chargedPFOContainerWriteHandle;
+  
+  
+};
+
+inline const InterfaceID& PFOChargedCreatorTool::interfaceID()
+{ 
+  return IID_PFOChargedCreatorTool;
+}
+
+#endif
diff --git a/Reconstruction/eflowRec/share/PFlowHiveExOpts.py b/Reconstruction/eflowRec/share/PFlowHiveExOpts.py
index 9a8d491087b8fec572ce20ce32365ee04f53bbfb..59112ddeede41655615ab8a44fb2420eb2476e6d 100644
--- a/Reconstruction/eflowRec/share/PFlowHiveExOpts.py
+++ b/Reconstruction/eflowRec/share/PFlowHiveExOpts.py
@@ -179,7 +179,7 @@ topSequence += PFClusterSelector
 from eflowRec.eflowRecConf import PFAlgorithm
 PFAlgorithm = PFAlgorithm("PFAlgorithm")
 
-PFAlgorithm.PrivateToolList  = []
+PFAlgorithm.SubtractionToolList  = []
 
 from eflowRec.eflowRecConf import PFCellLevelSubtractionTool
 PFCellLevelSubtractionTool = PFCellLevelSubtractionTool("PFCellLevelSubtractionTool")
@@ -219,10 +219,125 @@ if jobproperties.eflowRecFlags.eflowAlgType == "EOverP":
    MatchingTool.DistanceType        = 'EtaPhiSquareDistance'
    MatchingTool.MatchCut = 0.2*0.2 # float
    
+PFAlgorithm.SubtractionToolList += [PFCellLevelSubtractionTool]
 
+from eflowRec.eflowRecConf import PFRecoverSplitShowersTool
+PFRecoverSplitShowersTool = PFRecoverSplitShowersTool("PFRecoverSplitShowersTool")
+
+CellEOverPTool_Recover=eflowCellEOverPTool_mc12_JetETMiss("eflowCellEOverPTool_mc12_JetETMiss_Recover")
+
+PFRecoverSplitShowersTool.eflowCellEOverPTool=CellEOverPTool_Recover
+
+if jobproperties.eflowRecFlags.recoverIsolatedTracks == True:
+   PFRecoverSplitShowersTool.RecoverIsolatedTracks = True
    
+if jobproperties.eflowRecFlags.useUpdated2015ChargedShowerSubtraction == False:
+   PFRecoverSplitShowersTool.useUpdated2015ChargedShowerSubtraction = False
+
+MatchingTool_Recover = PFTrackClusterMatchingTool()
+MatchingTool_Recover.TrackPositionType   = 'EM2EtaPhi' # str
+MatchingTool_Recover.ClusterPositionType = 'PlainEtaPhi' # str
+MatchingTool_Recover.DistanceType        = 'EtaPhiSquareDistance' # str
+MatchingTool_Recover.MatchCut = 0.2*0.2 # float
+PFRecoverSplitShowersTool.PFTrackClusterMatchingTool = MatchingTool
+
+PFAlgorithm.SubtractionToolList += [PFRecoverSplitShowersTool]
 
-PFAlgorithm.PrivateToolList += [PFCellLevelSubtractionTool]
+from eflowRec.eflowRecConf import PFMomentCalculatorTool
+PFMomentCalculatorTool = PFMomentCalculatorTool("PFMomentCalculatorTool")
+
+from CaloRec.CaloRecConf import CaloClusterMomentsMaker
+PFClusterMomentsMaker = CaloClusterMomentsMaker("PFClusterMomentsMaker")
+
+from CaloRec.CaloTopoClusterFlags import jobproperties
+
+from CaloTools.CaloNoiseToolDefault import CaloNoiseToolDefault
+theCaloNoiseTool = CaloNoiseToolDefault()
+from AthenaCommon.AppMgr import ToolSvc
+ToolSvc += theCaloNoiseTool
+
+PFClusterMomentsMaker.MaxAxisAngle = 20*deg
+PFClusterMomentsMaker.WeightingOfNegClusters = jobproperties.CaloTopoClusterFlags.doTreatEnergyCutAsAbsolute() 
+PFClusterMomentsMaker.MinBadLArQuality = 4000
+PFClusterMomentsMaker.CaloNoiseTool = theCaloNoiseTool
+PFClusterMomentsMaker.UsePileUpNoise = True
+PFClusterMomentsMaker.TwoGaussianNoise = jobproperties.CaloTopoClusterFlags.doTwoGaussianNoise()
+PFClusterMomentsMaker.OutputLevel = INFO
+PFClusterMomentsMaker.MomentsNames = [
+   "FIRST_PHI" 
+   ,"FIRST_ETA"
+   ,"SECOND_R" 
+   ,"SECOND_LAMBDA"
+   ,"DELTA_PHI"
+   ,"DELTA_THETA"
+   ,"DELTA_ALPHA" 
+   ,"CENTER_X"
+   ,"CENTER_Y"
+   ,"CENTER_Z"
+   ,"CENTER_MAG"
+   ,"CENTER_LAMBDA"
+   ,"LATERAL"
+   ,"LONGITUDINAL"
+   ,"FIRST_ENG_DENS" 
+   ,"ENG_FRAC_EM" 
+   ,"ENG_FRAC_MAX" 
+   ,"ENG_FRAC_CORE" 
+   ,"FIRST_ENG_DENS" 
+   ,"SECOND_ENG_DENS"
+   ,"ISOLATION"
+   ,"EM_PROBABILITY"
+   ,"ENG_POS"
+   ,"ENG_BAD_CELLS"
+   ,"N_BAD_CELLS"
+   ,"BADLARQ_FRAC"
+   ,"AVG_LAR_Q"
+   ,"AVG_TILE_Q"
+   ,"SIGNIFICANCE"
+]
+
+PFMomentCalculatorTool.CaloClusterMomentsMaker = PFClusterMomentsMaker
+
+from eflowRec.eflowRecConf import PFClusterCollectionTool
+PFClusterCollectionTool_default = PFClusterCollectionTool("PFClusterCollectionTool")
+
+PFMomentCalculatorTool.PFClusterCollectionTool = PFClusterCollectionTool_default
+
+PFAlgorithm.BaseToolList = [PFMomentCalculatorTool]
+
+from eflowRec.eflowRecConf import PFLCCalibTool
+PFLCCalibTool = PFLCCalibTool("PFLCCalibTool")
+
+from eflowRec.eflowLocalHadCal import eflowLocalHadCal
+LocalHadCal = eflowLocalHadCal()
+Calib = LocalHadCal.eflowCaloClusterLocalCalib("PFLCCalibTool")
+CalibOO = LocalHadCal.eflowCaloClusterLocalCalibOO("PFLCCalibTool")
+CalibOOPi0 = LocalHadCal.eflowCaloClusterLocalCalibOOPi0("PFLCCalibTool")
+CalibDM = LocalHadCal.eflowCaloClusterLocalCalibDM("PFLCCalibTool")
+
+from CaloRec.CaloTopoClusterFlags import jobproperties
+if not (jobproperties.CaloTopoClusterFlags.doTopoClusterLocalCalib()):
+   #load local hadron calibration database, if not done so by CaloRec already
+   from CaloRec import CaloClusterTopoCoolFolder
+
+PFLCCalibTool.CaloClusterLocalCalib=Calib
+PFLCCalibTool.CaloClusterLocalCalibOOCC=CalibOO
+PFLCCalibTool.CaloClusterLocalCalibOOCCPi0=CalibOOPi0
+PFLCCalibTool.CaloClusterLocalCalibDM=CalibDM
+
+PFClusterCollectionTool_LCCalib = PFClusterCollectionTool("PFClusterCollectionTool_LCCalib")
+PFLCCalibTool.eflowRecClusterCollectionTool=PFClusterCollectionTool_LCCalib
+PFLCCalibTool.UseLocalWeight = False
+
+PFAlgorithm.BaseToolList += [PFLCCalibTool]
+
+from eflowRec.eflowRecConf import PFOChargedCreatorTool
+PFOChargedCreatorTool = PFOChargedCreatorTool("PFOChargedCreatorTool")
+
+from TrackVertexAssociationTool.TrackVertexAssociationToolConf import CP__TightTrackVertexAssociationTool        
+PFlowTrackVertexAssociationTool = CP__TightTrackVertexAssociationTool(name="PFlowTightCPTool", dzSinTheta_cut=2.0, doPV=True)
+PFOChargedCreatorTool.TrackVertexAssociationTool = PFlowTrackVertexAssociationTool
+
+PFAlgorithm.BaseToolList += [PFOChargedCreatorTool]
 
 topSequence += PFAlgorithm
 
@@ -235,6 +350,9 @@ StreamESD=createOutputStream("StreamESD","myESD.pool.root",True)
 include ("CaloRecEx/CaloRecOutputItemList_jobOptions.py")
 StreamESD.ItemList+=CaloESDList
 
+StreamESD.ItemList += [ "xAOD::PFOContainer#JetETMissChargedParticleFlowObjectsV2"]
+StreamESD.ItemList += [ "xAOD::PFOAuxContainer#JetETMissChargedParticleFlowObjectsV2Aux."]
+
 print StreamESD.ItemList
 
 #---------------------------------------------------------------------------------#
diff --git a/Reconstruction/eflowRec/src/PFLCCalibTool.cxx b/Reconstruction/eflowRec/src/PFLCCalibTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..80d61f4637faece149e191c96e59f1e6efff7828
--- /dev/null
+++ b/Reconstruction/eflowRec/src/PFLCCalibTool.cxx
@@ -0,0 +1,130 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "eflowRec/PFLCCalibTool.h"
+#include "eflowRec/eflowCaloObject.h"
+#include "eflowRec/eflowRecCluster.h"
+
+#include "xAODCaloEvent/CaloCluster.h"
+#include "xAODCaloEvent/CaloClusterContainer.h"
+#include "xAODCaloEvent/CaloClusterKineHelper.h"
+#include "CaloRec/CaloClusterProcessor.h"
+
+#include "CaloDetDescr/CaloDetDescrManager.h"
+#include "CaloIdentifier/CaloCell_ID.h"
+#include "CaloUtils/CaloClusterStoreHelper.h"
+
+PFLCCalibTool::PFLCCalibTool(const std::string& type, const std::string& name, const IInterface* parent) :
+  AthAlgTool(type, name, parent),
+  m_clusterCollectionTool("eflowRecClusterCollectionTool", this),
+  m_clusterLocalCalibTool("CaloClusterLocalCalib", this),
+  m_clusterLocalCalibOOCCTool("CaloClusterLocalCalib", this),
+  m_clusterLocalCalibOOCCPi0Tool("CaloClusterLocalCalib", this),
+  m_clusterLocalCalibDMTool("CaloClusterLocalCalib", this),
+  m_useLocalWeight(false) {
+  declareInterface<PFLCCalibTool>(this);
+  declareProperty("eflowRecClusterCollectionTool", m_clusterCollectionTool,       "Tool to choose clusters to use");
+  declareProperty("CaloClusterLocalCalib",        m_clusterLocalCalibTool,        "Cluster Calibration for EFlowRec");
+  declareProperty("CaloClusterLocalCalibOOCC",    m_clusterLocalCalibOOCCTool,    "Cluster CalibrationOOCC for EFlowRec");
+  declareProperty("CaloClusterLocalCalibOOCCPi0", m_clusterLocalCalibOOCCPi0Tool, "Cluster CalibrationOOCCPi0 for EFlowRec");
+  declareProperty("CaloClusterLocalCalibDM",      m_clusterLocalCalibDMTool,      "Cluster CalibrationDM for EFlowRec");
+  declareProperty("UseLocalWeight",               m_useLocalWeight,               "Use weight before subtraction");
+}
+
+StatusCode PFLCCalibTool::initialize() {
+
+  /* Retrieve the cluster collection tool */
+  ATH_CHECK(m_clusterCollectionTool.retrieve());
+
+  /* Retrieve basic local-hadron calibration tool */
+  ATH_CHECK(m_clusterLocalCalibTool.retrieve());
+
+  /* Retrieve tools for out-of-cluster corrections */
+  ATH_CHECK(m_clusterLocalCalibOOCCTool.retrieve());
+
+  ATH_CHECK(m_clusterLocalCalibOOCCPi0Tool.retrieve());
+
+  /* Retrieve tool for DM corrections */
+  ATH_CHECK(m_clusterLocalCalibDMTool.retrieve());
+
+  return StatusCode::SUCCESS;
+
+}
+
+void PFLCCalibTool::execute(eflowCaloObjectContainer* theEflowCaloObjectContainer, xAOD::CaloClusterContainer& theCaloClusterContainer) {
+
+  if (m_useLocalWeight) {
+    std::unique_ptr<eflowRecClusterContainer> theEFRecCluster = m_clusterCollectionTool->retrieve(theEflowCaloObjectContainer, true);
+    /* Calibrate each cluster */
+    eflowRecClusterContainer::iterator itCluster = theEFRecCluster->begin();
+    eflowRecClusterContainer::iterator endCluster = theEFRecCluster->end();
+    for (; itCluster != endCluster; ++itCluster) {
+      eflowRecCluster* cluster = (*itCluster);
+      applyLocalWeight(cluster);
+    }
+  } else {
+    /* Collect all the clusters in a temporary container (with VIEW_ELEMENTS!) */
+    std::unique_ptr<xAOD::CaloClusterContainer> tempClusterContainer = m_clusterCollectionTool->execute(theEflowCaloObjectContainer, true, theCaloClusterContainer);
+
+    /* Calibrate each cluster */
+    xAOD::CaloClusterContainer::iterator itCluster = tempClusterContainer->begin();
+    xAOD::CaloClusterContainer::iterator endCluster = tempClusterContainer->end();
+    for (; itCluster != endCluster; ++itCluster) {
+      xAOD::CaloCluster* cluster = (*itCluster);
+      /* Subsequently apply all ClusterLocalCalibTools, print debug output at each stage, if DEBUG it set */
+
+      apply(m_clusterLocalCalibTool, cluster);
+
+      apply(m_clusterLocalCalibOOCCTool, cluster);
+
+      apply(m_clusterLocalCalibOOCCPi0Tool, cluster);
+
+      apply(m_clusterLocalCalibDMTool, cluster);
+
+    }
+
+  }
+}
+
+StatusCode PFLCCalibTool::finalize() {
+  return StatusCode::SUCCESS;
+}
+
+
+void PFLCCalibTool::apply(ToolHandle<CaloClusterCollectionProcessor>& calibTool, xAOD::CaloCluster* cluster) {
+
+  assert(!m_useLocalWeight);
+  CaloClusterCollectionProcessor* myCollectionProcessor = &(*calibTool);
+  CaloClusterProcessor* myCalibProcessor = dynamic_cast<CaloClusterProcessor*>(myCollectionProcessor);
+  if (myCalibProcessor) {
+    if (myCalibProcessor->execute(cluster).isFailure()) {
+      if (msgLvl(MSG::WARNING))
+        msg(MSG::WARNING) << "Could not execute " << calibTool.name() << endmsg;
+    }
+  } else if (msgLvl(MSG::WARNING))
+    msg(MSG::WARNING) << " dynamic_cast provided NULL pointer to CaloClusterProcessor " << endmsg;
+}
+
+void PFLCCalibTool::applyLocalWeight(eflowRecCluster* theEFRecClusters) {
+  xAOD::CaloCluster* theCluster = theEFRecClusters->getClusterForModification(
+      eflowCaloObject::getClusterContainerPtr());
+
+  /* Iterate over cells of old cluster and replicate them with energy weighted by -1 if negative and add it to the new cluster */
+  const std::map<IdentifierHash, double> weightMap = theEFRecClusters->getCellsWeight();
+  const CaloCell_ID* calo_id = CaloDetDescrManager::instance()->getCaloCell_ID();
+  xAOD::CaloCluster::cell_iterator cellIter = theCluster->cell_begin();
+
+  for (int cellIndex = 0; cellIter != theCluster->cell_end(); cellIter++) {
+    const CaloCell* pCell = *cellIter;
+    IdentifierHash myHashId = calo_id->calo_cell_hash(pCell->ID());
+    double weight = weightMap.find(myHashId)->second;
+    theCluster->reweightCell(cellIter, weight);
+    cellIndex++;
+  }
+
+  CaloClusterKineHelper::calculateKine(theCluster, true, false);
+
+  theCluster->recoStatus().setStatus(CaloRecoStatus::CALIBRATEDLHC);
+
+}
diff --git a/Reconstruction/eflowRec/src/PFOChargedCreatorTool.cxx b/Reconstruction/eflowRec/src/PFOChargedCreatorTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..a29ec3aa36f560344eb66fd400ff30dd79005f23
--- /dev/null
+++ b/Reconstruction/eflowRec/src/PFOChargedCreatorTool.cxx
@@ -0,0 +1,155 @@
+#include "eflowRec/PFOChargedCreatorTool.h"
+
+#include "eflowRec/eflowCaloObject.h"
+#include "eflowRec/eflowRecCluster.h"
+#include "eflowRec/eflowRecTrack.h"
+
+#include "xAODPFlow/PFOAuxContainer.h"
+
+PFOChargedCreatorTool::PFOChargedCreatorTool(const std::string& type, const std::string& name, const IInterface* parent) :
+    AthAlgTool(type, name, parent),
+    m_eOverPMode(false),
+    m_trackVertexAssociationTool("",this),
+    m_vertexContainerReadHandle("PrimaryVertices"),
+    m_chargedPFOContainerWriteHandle("JetETMissChargedParticleFlowObjectsV2")
+{
+  declareInterface<PFOChargedCreatorTool>(this);
+  /* Name of  eflow Container to be created */
+  declareProperty("EOverPMode", m_eOverPMode);
+  declareProperty("TrackVertexAssociationTool", m_trackVertexAssociationTool);
+  declareProperty("VertexContainerName",m_vertexContainerReadHandle);
+  declareProperty("PFOOutputName", m_chargedPFOContainerWriteHandle);
+}
+
+StatusCode PFOChargedCreatorTool::initialize(){
+
+  ATH_CHECK(m_trackVertexAssociationTool.retrieve());
+
+  ATH_CHECK(m_vertexContainerReadHandle.initialize());
+
+  ATH_CHECK(m_chargedPFOContainerWriteHandle.initialize());
+  
+  return StatusCode::SUCCESS;
+}
+
+StatusCode  PFOChargedCreatorTool::execute(eflowCaloObject* energyFlowCaloObject){
+
+  ATH_MSG_DEBUG("Executing eflowObjectCreatorTool ");
+  
+  if (m_eOverPMode) createChargedPFO(energyFlowCaloObject, true);
+  else createChargedPFO(energyFlowCaloObject);
+
+  const xAOD::VertexContainer* theVertexContainer = m_vertexContainerReadHandle.ptr();  
+  addVertexLinksToChargedPFO(*theVertexContainer);
+
+  return StatusCode::SUCCESS;
+  
+}
+
+void PFOChargedCreatorTool::execute(eflowCaloObjectContainer* theEflowCaloObjectContainer, xAOD::CaloClusterContainer& theCaloClusterContainer){
+
+  ATH_MSG_DEBUG("Processing eflowCaloObjectContainer");
+
+  m_chargedPFOContainerWriteHandle.record(std::make_unique<xAOD::PFOContainer>(),std::make_unique<xAOD::PFOAuxContainer>());
+
+  /* Create Charged PFOs from all eflowCaloObjects */
+  unsigned int nEFCaloObs = theEflowCaloObjectContainer->size();
+  for (unsigned int iEFCalOb = 0; iEFCalOb < nEFCaloObs; ++iEFCalOb){
+    eflowCaloObject* thisEflowCaloObject = theEflowCaloObjectContainer->at(iEFCalOb);
+    if (execute(thisEflowCaloObject).isFailure()){
+      ATH_MSG_WARNING("Execute failed for one eflowCaloObject. ");
+      continue;
+    }
+  }
+
+  
+}
+
+StatusCode PFOChargedCreatorTool::finalize(){ return StatusCode::SUCCESS; }
+
+void PFOChargedCreatorTool::createChargedPFO(eflowCaloObject* energyFlowCaloObject, bool addClusters){
+
+  /* Loop over all tracks in the eflowCaloObject */
+  int nTracks = energyFlowCaloObject->nTracks();
+  for (int iTrack = 0; iTrack < nTracks; ++iTrack) {
+
+    eflowRecTrack* efRecTrack = energyFlowCaloObject->efRecTrack(iTrack);
+
+    /* Skip tracks that haven't been subtracted */
+    if (false == m_eOverPMode){
+      if (!efRecTrack->isSubtracted()){ continue; }
+    }
+    
+    /* Create new xAOD::PFO */
+    xAOD::PFO* thisPFO = new xAOD::PFO();
+    m_chargedPFOContainerWriteHandle->push_back(thisPFO);
+
+    /* Get the track elementLink and add it to the xAOD:PFO  */
+    ElementLink<xAOD::TrackParticleContainer> theTrackLink = efRecTrack->getTrackElemLink();
+    bool isSet = thisPFO->setTrackLink(theTrackLink);
+    if (!isSet) { msg(MSG::WARNING) << "Could not set Track B in PFO " << endmsg; }
+    thisPFO->setCharge(efRecTrack->getTrack()->charge());
+
+    std::pair<double,double> etaPhi(0.0,0.0);
+
+    if (m_eOverPMode){
+      /* In EOverPMode want charged eflowObjects to have extrapolated eta,phi as coordinates
+       * (needed for analysis of EOverP Data) */
+      etaPhi = efRecTrack->getTrackCaloPoints().getEM2etaPhi();
+        
+      /*add information to xAOD*/
+      xAOD::PFODetails::PFOAttributes myAttribute_layerHED = xAOD::PFODetails::PFOAttributes::eflowRec_layerHED;
+      thisPFO->setAttribute<int>(myAttribute_layerHED,efRecTrack->getLayerHED() );
+      
+      xAOD::PFODetails::PFOAttributes myAttribute_layerVectorCellOrdering = xAOD::PFODetails::PFOAttributes::eflowRec_layerVectorCellOrdering;
+      thisPFO->setAttribute<std::vector<int> >(myAttribute_layerVectorCellOrdering,efRecTrack->getLayerCellOrderVector() );
+      
+      xAOD::PFODetails::PFOAttributes myAttribute_radiusVectorCellOrdering = xAOD::PFODetails::PFOAttributes::eflowRec_radiusVectorCellOrdering;
+      thisPFO->setAttribute<std::vector<float> >(myAttribute_radiusVectorCellOrdering,efRecTrack->getRadiusCellOrderVector() );
+        
+      xAOD::PFODetails::PFOAttributes myAttribute_avgEdensityVectorCellOrdering = xAOD::PFODetails::PFOAttributes::eflowRec_avgEdensityVectorCellOrdering;
+      thisPFO->setAttribute<std::vector<float> >(myAttribute_avgEdensityVectorCellOrdering,efRecTrack->getAvgEDensityCellOrderVector() );              
+    } else {
+      /* In normal mode we want te track eta,phi at the perigee */
+      etaPhi.first = efRecTrack->getTrack()->eta();
+      etaPhi.second = efRecTrack->getTrack()->phi();
+    }
+    /* Set the 4-vector of the xAOD::PFO */
+    thisPFO->setP4(efRecTrack->getTrack()->pt(), etaPhi.first, etaPhi.second, efRecTrack->getTrack()->m());
+
+    /* Add the amount of energy the track was expected to deposit in the calorimeter - this is needed to calculate the charged weight in the jet finding */
+    xAOD::PFODetails::PFOAttributes myAttribute_tracksExpectedEnergyDeposit = xAOD::PFODetails::PFOAttributes::eflowRec_tracksExpectedEnergyDeposit;
+    thisPFO->setAttribute<float>(myAttribute_tracksExpectedEnergyDeposit,efRecTrack->getEExpect() );
+    
+    /* Flag if this track was in a dense environment for later checking */
+    xAOD::PFODetails::PFOAttributes myAttribute_isInDenseEnvironment = xAOD::PFODetails::PFOAttributes::eflowRec_isInDenseEnvironment;
+    //There is some issue using bools - when written to disk they convert to chars. So lets store the bool as an int.
+    thisPFO->setAttribute<int>(myAttribute_isInDenseEnvironment, (efRecTrack->isInDenseEnvironment()));
+
+    /* Optionally we add the links to clusters to the xAOD::PFO */
+    if (true == addClusters){
+       unsigned int nClusters = energyFlowCaloObject->nClusters();
+       for (unsigned int iCluster = 0; iCluster < nClusters; ++iCluster){
+	 eflowRecCluster* thisEfRecCluster = energyFlowCaloObject->efRecCluster(iCluster);
+	 ElementLink<xAOD::CaloClusterContainer> theClusLink = thisEfRecCluster->getClusElementLink();
+	 bool isSet = thisPFO->addClusterLink(theClusLink);
+	 if (!isSet) msg(MSG::WARNING) << "Could not set Cluster in PFO " << endmsg;
+       }//cluster loop
+    }//addClusters is set to true - so we added the clusters to the xAOD::PFO   
+
+  }//loop over the tracks on the eflowCaloObject
+}
+
+void PFOChargedCreatorTool::addVertexLinksToChargedPFO(const xAOD::VertexContainer& theVertexContainer){
+
+  //This is a loop on all xAOD::PFO with non-zero charge
+  for (auto theChargedPFO : *m_chargedPFOContainerWriteHandle){
+    const xAOD::TrackParticle* theTrack = theChargedPFO->track(0);
+    if (theTrack){
+      ElementLink< xAOD::VertexContainer> theVertexLink = m_trackVertexAssociationTool->getUniqueMatchVertexLink(*theTrack,theVertexContainer);
+      bool haveSetLink = theChargedPFO->setVertexLink(theVertexLink);
+      if (!haveSetLink) msg(MSG::WARNING) << " Could not set vertex link on charged PFO " << endmsg;
+    }//if valid pointer to xAOD::TrackParticle
+  }
+
+}
diff --git a/Reconstruction/eflowRec/src/components/eflowRec_entries.cxx b/Reconstruction/eflowRec/src/components/eflowRec_entries.cxx
index a54861e592227334a27a4a7f418730cb38357384..b6f2d2b02eac082fc45aac844da33b109f63e272 100644
--- a/Reconstruction/eflowRec/src/components/eflowRec_entries.cxx
+++ b/Reconstruction/eflowRec/src/components/eflowRec_entries.cxx
@@ -23,6 +23,8 @@
 #include "eflowRec/PFRecoverSplitShowersTool.h"
 #include "eflowRec/PFMomentCalculatorTool.h"
 #include "eflowRec/PFClusterCollectionTool.h"
+#include "eflowRec/PFLCCalibTool.h"
+#include "eflowRec/PFOChargedCreatorTool.h"
 #include "GaudiKernel/DeclareFactoryEntries.h"
 
 DECLARE_ALGORITHM_FACTORY( eflowBuilder )
@@ -39,6 +41,8 @@ DECLARE_TOOL_FACTORY( PFCellLevelSubtractionTool )
 DECLARE_TOOL_FACTORY( PFRecoverSplitShowersTool )
 DECLARE_TOOL_FACTORY( PFMomentCalculatorTool )
 DECLARE_TOOL_FACTORY( PFClusterCollectionTool )
+DECLARE_TOOL_FACTORY( PFLCCalibTool )
+DECLARE_TOOL_FACTORY( PFOChargedCreatorTool )
 DECLARE_TOOL_FACTORY( eflowRecoverSplitShowersTool )
 DECLARE_TOOL_FACTORY( eflowCellLevelSubtractionTool )
 DECLARE_TOOL_FACTORY( eflowLCCalibTool )
@@ -66,6 +70,8 @@ DECLARE_FACTORY_ENTRIES(eflowRec) {
     DECLARE_TOOL( PFRecoverSplitShowersTool )
     DECLARE_TOOL( PFMomentCalculatorTool )
     DECLARE_TOOL( PFClusterCollectionTool )
+    DECLARE_TOOL( PFLCCalibTool )
+    DECLARE_TOOL( PFOChargedCreatorTool )
     DECLARE_TOOL ( eflowRecoverSplitShowersTool )
     DECLARE_TOOL ( eflowCellLevelSubtractionTool )
     DECLARE_TOOL ( eflowMomentCalculatorTool )