diff --git a/Event/xAOD/xAODMissingET/Root/MissingETAssociationMap_v1.cxx b/Event/xAOD/xAODMissingET/Root/MissingETAssociationMap_v1.cxx
index f3169e7bd1353626f3ac78437a34beb1b6fc8397..b7c030203a55fcf8d72967c75356a06db06cb58d 100644
--- a/Event/xAOD/xAODMissingET/Root/MissingETAssociationMap_v1.cxx
+++ b/Event/xAOD/xAODMissingET/Root/MissingETAssociationMap_v1.cxx
@@ -5,6 +5,7 @@
 #include "xAODMissingET/versions/MissingETAssociationMap_v1.h"
 
 #include "xAODTracking/TrackParticle.h"
+#include "xAODPFlow/FlowElement.h"
 #include "xAODJet/JetAttributes.h"
 
 #include "xAODBase/IParticleContainer.h"
@@ -222,6 +223,7 @@ const xAOD::IParticleContainer* MissingETAssociationMap_v1::getUniqueSignals(con
       else {continue;}
     case MissingETBase::UsageHandler::ParticleFlow:
       if((*iSig)->type()==xAOD::Type::ParticleFlow) {break;}
+      else if((*iSig)->type()==xAOD::Type::FlowElement && ((static_cast<const xAOD::FlowElement*>(*iSig))->signalType() & xAOD::FlowElement::PFlow)) {break;}
       else {continue;}
     case MissingETBase::UsageHandler::TruthParticle:
       if((*iSig)->type()==xAOD::Type::TruthParticle) {break;}
@@ -229,7 +231,7 @@ const xAOD::IParticleContainer* MissingETAssociationMap_v1::getUniqueSignals(con
     case MissingETBase::UsageHandler::AllCalo:
       if((*iSig)->type()!=xAOD::Type::TrackParticle) {break;}
       else {continue;}
-    default: continue;
+    default: {continue;}
     }
 
     size_t assocIndex = findIndexByJetConst(*iSig);
diff --git a/Event/xAOD/xAODMissingET/Root/MissingETAssociation_v1.cxx b/Event/xAOD/xAODMissingET/Root/MissingETAssociation_v1.cxx
index ca0755adeb1db6bac4ae679e7ac88d724dcc9dbf..7b15541dee16289431eb641dfdb797c5818af885 100644
--- a/Event/xAOD/xAODMissingET/Root/MissingETAssociation_v1.cxx
+++ b/Event/xAOD/xAODMissingET/Root/MissingETAssociation_v1.cxx
@@ -7,6 +7,7 @@
 #include "xAODJet/JetContainer.h"
 #include "xAODTruth/TruthParticle.h"
 #include "xAODPFlow/PFO.h"
+#include "xAODPFlow/FlowElement.h"
 
 #include <iterator>
 #include <cstdio>
@@ -138,32 +139,32 @@ namespace xAOD {
     // found - add const vectors
     if ( idx != MissingETBase::Numerical::invalidIndex() )
       { 
-	m_objConstLinks[idx].clear();
-	m_objConstLinks[idx].reserve(constlist.size());
-	for(const auto& signal : constlist) {
-	  const IParticleContainer* pCont = static_cast<const IParticleContainer*>(signal->container());
-	  MissingETBase::Types::objlink_t el(*pCont,signal->index());
-	  m_objConstLinks[idx].push_back(el);
-	}
-	return false; }
+        m_objConstLinks[idx].clear();
+        m_objConstLinks[idx].reserve(constlist.size());
+        for(const auto& signal : constlist) {
+          const IParticleContainer* pCont = static_cast<const IParticleContainer*>(signal->container());
+          MissingETBase::Types::objlink_t el(*pCont,signal->index());
+          m_objConstLinks[idx].push_back(el);
+        }
+        return false; }
     // new object
     else
       {
-	MissingETBase::Types::objlink_t oLnk; f_setObject<IParticle,MissingETBase::Types::objlink_t>(pPart,oLnk); 
-	// add to stores
-	this->f_objectLinks().push_back(oLnk);
-	vector<MissingETBase::Types::objlink_t > linklist;
-	linklist.reserve(constlist.size());
-	for(const auto& signal : constlist) {
-	  const IParticleContainer* pCont = static_cast<const IParticleContainer*>(signal->container());
-	  MissingETBase::Types::objlink_t el(*pCont,signal->index());
-	  linklist.push_back(el);
-	}
-	m_objConstLinks.push_back(linklist);
-	this->f_overlapIndices().push_back(vector<size_t>(0));
-	this->f_overlapTypes().push_back(vector<unsigned char>(0));
-	bool linkset = f_setLink<MissingETBase::Types::objlink_t>(oLnk);
-	return linkset;
+        MissingETBase::Types::objlink_t oLnk; f_setObject<IParticle,MissingETBase::Types::objlink_t>(pPart,oLnk); 
+        // add to stores
+        this->f_objectLinks().push_back(oLnk);
+        vector<MissingETBase::Types::objlink_t > linklist;
+        linklist.reserve(constlist.size());
+        for(const auto& signal : constlist) {
+          const IParticleContainer* pCont = static_cast<const IParticleContainer*>(signal->container());
+          MissingETBase::Types::objlink_t el(*pCont,signal->index());
+          linklist.push_back(el);
+        }
+        m_objConstLinks.push_back(linklist);
+        this->f_overlapIndices().push_back(vector<size_t>(0));
+        this->f_overlapTypes().push_back(vector<unsigned char>(0));
+        bool linkset = f_setLink<MissingETBase::Types::objlink_t>(oLnk);
+        return linkset;
       }
   }
 
@@ -173,7 +174,7 @@ namespace xAOD {
   //   static SG::AuxElement::Accessor<MissingETBase::Types::objlink_vector_t> acc("objectLinks");
   //   if(acc.isAvailableWritable(*this)) {
   //     for ( auto& link : this->f_objectLinks() ) { 
-  // 	link.toPersistent();
+  //         link.toPersistent();
   //     } 
   //   }
   // }
@@ -182,9 +183,9 @@ namespace xAOD {
   //   if(!this->isMisc()) {
   //     static SG::AuxElement::Accessor<MissingETBase::Types::jetlink_t> acc("jetLink");
   //     if(acc.isAvailableWritable(*this)) {
-  // 	if(f_setLink<MissingETBase::Types::jetlink_t>(this->f_jetLink())) {
-  // 	  this->f_jetLink().toPersistent();
-  // 	}
+  //         if(f_setLink<MissingETBase::Types::jetlink_t>(this->f_jetLink())) {
+  //           this->f_jetLink().toPersistent();
+  //         }
   //     }
   //   }
   // }
@@ -499,13 +500,13 @@ namespace xAOD {
     for ( size_t idx(0); idx < this->sizeTrk(); idx++) trkVecs[idx] = constvec_t(this->trkpx(idx),this->trkpy(idx),this->trkpz(idx),this->trke(idx),this->trksumpt(idx));
     return pVec;
   }
-										   
+                                                                                   
   std::vector<const IParticle*> MissingETAssociation_v1::objects(const std::vector<double>*& calpxPtr,const std::vector<double>*& calpyPtr,
-								 const std::vector<double>*& calpzPtr,const std::vector<double>*& calePtr,
-								 const std::vector<double>*& calsumptPtr,
-								 const std::vector<double>*& trkpxPtr,const std::vector<double>*& trkpyPtr,
-								 const std::vector<double>*& trkpzPtr,const std::vector<double>*& trkePtr,
-								 const std::vector<double>*& trksumptPtr) const
+                                                                 const std::vector<double>*& calpzPtr,const std::vector<double>*& calePtr,
+                                                                 const std::vector<double>*& calsumptPtr,
+                                                                 const std::vector<double>*& trkpxPtr,const std::vector<double>*& trkpyPtr,
+                                                                 const std::vector<double>*& trkpzPtr,const std::vector<double>*& trkePtr,
+                                                                 const std::vector<double>*& trksumptPtr) const
   {
     calpxPtr = &(this->calpx()); calpyPtr = &(this->calpy()); calpzPtr = &(this->calpz()); calePtr = &(this->cale()); calsumptPtr = &(this->calsumpt());
     trkpxPtr = &(this->trkpx()); trkpyPtr = &(this->trkpy()); trkpzPtr = &(this->trkpz()); trkePtr = &(this->trke()); trksumptPtr = &(this->trksumpt());
@@ -521,7 +522,7 @@ namespace xAOD {
     MissingETBase::Types::constvec_t totalvec;
     for (size_t iKey = 0; iKey < this->sizeCal(); iKey++) {
       if (this->calkey(iKey) & getObjMask(this->findIndex(pPart)))
-	totalvec+=this->calVec(iKey);
+        totalvec+=this->calVec(iKey);
     }
     return totalvec;
   }
@@ -531,7 +532,7 @@ namespace xAOD {
     MissingETBase::Types::constvec_t totalvec;
     for (size_t iKey = 0; iKey < this->sizeTrk(); iKey++) {
       if (this->trkkey(iKey) & getObjMask(this->findIndex(pPart)))
-	totalvec+=this->trkVec(iKey);
+        totalvec+=this->trkVec(iKey);
     }
     return totalvec;
   }
@@ -590,29 +591,48 @@ namespace xAOD {
       const IParticle* obj = *objpair.first;
       MissingETBase::Types::bitmask_t bm = objpair.second;
       if (obj->type()==xAOD::Type::TrackParticle) trkOverlaps[bm] += MissingETBase::Types::constvec_t(*obj);
+      else if (obj->type()==xAOD::Type::FlowElement) {
+        const xAOD::FlowElement* fe = static_cast<const xAOD::FlowElement*>(obj);
+        // Assume this FlowElement represents a PFO
+        if(fe->isCharged()) {
+          // apply cPFO weight if present, only for the inclusive PFO sum
+          if (m_override.find(obj)!=m_override.end()) {
+            calOverlaps[bm] += m_override[obj];
+          } else {
+            calOverlaps[bm] += MissingETBase::Types::constvec_t(*obj);
+          }
+          trkOverlaps[bm] += MissingETBase::Types::constvec_t(*obj);
+        } else {
+          if (m_override.find(obj)!=m_override.end()) {
+            calOverlaps[bm] += m_override[obj];
+          } else {
+            calOverlaps[bm] += MissingETBase::Types::constvec_t(*obj);
+          } // gets ignored otherwise?
+        }
+      }
       else if (obj->type()==xAOD::Type::ParticleFlow) {
-	const PFO* pfo = static_cast<const PFO*>(obj);
-	if(pfo->isCharged()) {
-	  // apply cPFO weight if present, only for the inclusive PFO sum
-	  if (m_override.find(obj)!=m_override.end()) {
-	    calOverlaps[bm] += m_override[obj];
-	  } else {
-	    calOverlaps[bm] += MissingETBase::Types::constvec_t(*obj);
-	  }
-	  trkOverlaps[bm] += MissingETBase::Types::constvec_t(*obj);
-	} else {
-	  if (m_override.find(obj)!=m_override.end()) {
-	    calOverlaps[bm] += m_override[obj];
-	  } else {
-	    calOverlaps[bm] += MissingETBase::Types::constvec_t(*obj);
-	  } // gets ignored otherwise?
-	}
+        const PFO* pfo = static_cast<const PFO*>(obj);
+        if(pfo->isCharged()) {
+          // apply cPFO weight if present, only for the inclusive PFO sum
+          if (m_override.find(obj)!=m_override.end()) {
+            calOverlaps[bm] += m_override[obj];
+          } else {
+            calOverlaps[bm] += MissingETBase::Types::constvec_t(*obj);
+          }
+          trkOverlaps[bm] += MissingETBase::Types::constvec_t(*obj);
+        } else {
+          if (m_override.find(obj)!=m_override.end()) {
+            calOverlaps[bm] += m_override[obj];
+          } else {
+            calOverlaps[bm] += MissingETBase::Types::constvec_t(*obj);
+          } // gets ignored otherwise?
+        }
       } else if(obj->type()==xAOD::Type::TruthParticle) {
-	const TruthParticle* tp = static_cast<const TruthParticle*>(obj);
-	if(fabs(tp->charge())>0.)
-	  trkOverlaps[bm] += MissingETBase::Types::constvec_t(*obj);
-	if(!tp->isMuon())
-	  calOverlaps[bm] += MissingETBase::Types::constvec_t(*obj);
+        const TruthParticle* tp = static_cast<const TruthParticle*>(obj);
+        if(fabs(tp->charge())>0.)
+          trkOverlaps[bm] += MissingETBase::Types::constvec_t(*obj);
+        if(!tp->isMuon())
+          calOverlaps[bm] += MissingETBase::Types::constvec_t(*obj);
       }
       else calOverlaps[bm] += MissingETBase::Types::constvec_t(*obj);
     }
@@ -648,25 +668,25 @@ namespace xAOD {
       unsigned char overlapTypes(0);
       // if we somehow already recorded an overlap for this one, skip
       for(vector<size_t>::const_iterator iOverlap=myOverlaps.begin();
-	  iOverlap!=myOverlaps.end() && !overlapFound; ++iOverlap) {
-	overlapFound = (*iOverlap) == iTargetObj;
+          iOverlap!=myOverlaps.end() && !overlapFound; ++iOverlap) {
+        overlapFound = (*iOverlap) == iTargetObj;
       }
       if(overlapFound) continue;
       // otherwise, compare constituents to check if any match
       for(const auto& mine : myConst) {
-	for(const auto& target : checkConst) {
-	  overlapFound |= ( mine == target );
-	  if(mine == target) {
-	    if((*mine)->type()==xAOD::Type::TruthParticle) overlapTypes |= 1;
-	    else if((*mine)->type()==xAOD::Type::Other) overlapTypes |= 1 << xAOD::Type::NeutralParticle;
-	    else overlapTypes |= 1 << (*mine)->type();
-	  }
-	}
+        for(const auto& target : checkConst) {
+          overlapFound |= ( mine == target );
+          if(mine == target) {
+            if((*mine)->type()==xAOD::Type::TruthParticle) overlapTypes |= 1;
+            else if((*mine)->type()==xAOD::Type::Other) overlapTypes |= 1 << xAOD::Type::NeutralParticle;
+            else overlapTypes |= 1 << (*mine)->type();
+          }
+        }
       }
       // record the overlap
       if(overlapFound) {
-	this->addOverlap(objIdx,iTargetObj,overlapTypes);
-	this->addOverlap(iTargetObj,objIdx,overlapTypes);
+        this->addOverlap(objIdx,iTargetObj,overlapTypes);
+        this->addOverlap(iTargetObj,objIdx,overlapTypes);
       }
     }
     return overlapIndices(objIdx).size()>0;
@@ -680,29 +700,31 @@ namespace xAOD {
     vector<unsigned char> types = this->overlapTypes(objIdx);
     for(size_t iOL=0; iOL<indices.size(); ++iOL) {
       if(helper->objSelected(this, indices[iOL])) {
-	// printf("Test object %lu for overlaps: OL type %i\n",indices[iOL],(int)types[iOL]);
-	switch(p) {
-	case MissingETBase::UsageHandler::TrackCluster:      
-	  if((types[iOL] & 1<<xAOD::Type::CaloCluster) || (types[iOL] & 1<<xAOD::Type::TrackParticle)) {break;}
-	  else {continue;}
-	case MissingETBase::UsageHandler::OnlyCluster:
-	  if(types[iOL] & 1<<xAOD::Type::CaloCluster) {break;}
-	  else {continue;}
-	case MissingETBase::UsageHandler::OnlyTrack:
-	  if(types[iOL] & 1<<xAOD::Type::TrackParticle) {break;}
-	  else {continue;}
-	case MissingETBase::UsageHandler::ParticleFlow:
-	  if(types[iOL] & 1<<xAOD::Type::ParticleFlow) {break;}
-	  else {continue;}
-	case MissingETBase::UsageHandler::TruthParticle:
-	  if(types[iOL] & 1) {break;}
-	  else {continue;}
-	case MissingETBase::UsageHandler::AllCalo:
-	  if(types[iOL] & ~(1<<xAOD::Type::TrackParticle)) {break;}
-	  else {continue;}
-	default: continue;
-	}
-	return true;
+        // printf("Test object %lu for overlaps: OL type %i\n",indices[iOL],(int)types[iOL]);
+        switch(p) {
+        case MissingETBase::UsageHandler::TrackCluster:      
+          if((types[iOL] & 1<<xAOD::Type::CaloCluster) || (types[iOL] & 1<<xAOD::Type::TrackParticle)) {break;}
+          else {continue;}
+        case MissingETBase::UsageHandler::OnlyCluster:
+          if(types[iOL] & 1<<xAOD::Type::CaloCluster) {break;}
+          else {continue;}
+        case MissingETBase::UsageHandler::OnlyTrack:
+          if(types[iOL] & 1<<xAOD::Type::TrackParticle) {break;}
+          else {continue;}
+        case MissingETBase::UsageHandler::ParticleFlow:
+          if(types[iOL] & 1<<xAOD::Type::ParticleFlow) {break;}
+          //TODO: Check with TJ that this is OK
+          if(types[iOL] & 1<<xAOD::Type::FlowElement) {break;}
+          else {continue;}
+        case MissingETBase::UsageHandler::TruthParticle:
+          if(types[iOL] & 1) {break;}
+          else {continue;}
+        case MissingETBase::UsageHandler::AllCalo:
+          if(types[iOL] & ~(1<<xAOD::Type::TrackParticle)) {break;}
+          else {continue;}
+        default: continue;
+        }
+        return true;
       }
     }
     return false;
@@ -752,9 +774,9 @@ namespace xAOD {
   {
     for(const auto& link : this->objectLinks()) {
       if(link.isValid()) {
-	if(pPhys == *link) {
-	  return true;
-	}
+        if(pPhys == *link) {
+          return true;
+        }
       }
     }
     return false;
@@ -764,11 +786,11 @@ namespace xAOD {
   {
     for(size_t iObj=0; iObj<this->objectLinks().size(); ++iObj) {
       for(const auto& link : m_objConstLinks[iObj]) {
-	if(link.isValid()) {
-	  if(pSig == *link) {
-	    return true;
-	  }
-	}
+        if(link.isValid()) {
+          if(pSig == *link) {
+            return true;
+          }
+        }
       }
     }
     return false;
@@ -836,7 +858,7 @@ namespace xAOD {
     switch(p) {
     case MissingETBase::UsageHandler::TrackCluster:      
       if(type==xAOD::Type::CaloCluster
-	 || type==xAOD::Type::TrackParticle) {return true;}
+         || type==xAOD::Type::TrackParticle) {return true;}
       else {return false;}
     case MissingETBase::UsageHandler::OnlyCluster:
       if(type==xAOD::Type::CaloCluster) {return true;}
@@ -846,6 +868,7 @@ namespace xAOD {
       else {return false;}
     case MissingETBase::UsageHandler::ParticleFlow:
       if(type==xAOD::Type::ParticleFlow) {return true;}
+      if(type==xAOD::Type::FlowElement) {return true;}
       else {return false;}
     case MissingETBase::UsageHandler::AllCalo:
       if(type!=xAOD::Type::TrackParticle) {return true;}
diff --git a/Reconstruction/MET/METReconstruction/METReconstruction/METAssociator.h b/Reconstruction/MET/METReconstruction/METReconstruction/METAssociator.h
index 9619c27fde221005683bd374e7f884698d369e53..010e74dbe5d9df4b6500f83cd06cf1c9d5dabb48 100644
--- a/Reconstruction/MET/METReconstruction/METReconstruction/METAssociator.h
+++ b/Reconstruction/MET/METReconstruction/METReconstruction/METAssociator.h
@@ -35,9 +35,9 @@
 
 #include "xAODTracking/TrackParticleContainer.h"
 #include "xAODTracking/Vertex.h"
-//#include "xAODCaloEvent/CaloClusterContainer.h"
 #include "xAODPFlow/PFOContainer.h"
 #include "xAODPFlow/PFO.h"
+#include "xAODPFlow/FlowElementContainer.h"
 
 namespace InDet {
   class IInDetTrackSelectionTool;
@@ -64,6 +64,7 @@ namespace met {
       // Use IParticleContainer for flexibility e.g. if combining clusters & towers
       const xAOD::IParticleContainer* tcCont = 0;
       const xAOD::PFOContainer* pfoCont = 0;
+      const xAOD::FlowElementContainer* feCont = 0;
       const xAOD::Vertex* pv = 0;
     };
 
@@ -95,6 +96,7 @@ namespace met {
     SG::ReadHandleKey<xAOD::IParticleContainer>  m_clcollKey;
     SG::ReadHandleKey<xAOD::TrackParticleContainer>  m_trkcollKey;
     SG::ReadHandleKey<xAOD::PFOContainer>  m_pfcollKey{this,"PFlowColl","CHSParticleFlowObjects","PFO Collection"};
+    SG::ReadHandleKey<xAOD::FlowElementContainer>  m_fecollKey{this,"FlowElementCollection","","FlowElement Collection (overrides PFO if not empty)"};
     SG::ReadHandleKey<xAOD::IParticleContainer>  m_forcollKey;
     SG::ReadHandleKey<xAOD::IParticleContainer>  m_hybridContKey;
 
@@ -122,17 +124,21 @@ namespace met {
     bool isGoodEoverP(const xAOD::TrackParticle* trk) const;
 
     virtual StatusCode fillAssocMap(xAOD::MissingETAssociationMap* metMap,
-				    const xAOD::IParticleContainer* hardObjs) const;
+                                    const xAOD::IParticleContainer* hardObjs) const;
     virtual StatusCode extractPFO(const xAOD::IParticle* obj,
-				  std::vector<const xAOD::IParticle*>& pfolist,
-				  const met::METAssociator::ConstitHolder& constits,
-				  std::map<const xAOD::IParticle*,MissingETBase::Types::constvec_t> &momenta) const = 0;
+                                  std::vector<const xAOD::IParticle*>& pfolist,
+                                  const met::METAssociator::ConstitHolder& constits,
+                                  std::map<const xAOD::IParticle*,MissingETBase::Types::constvec_t> &momenta) const = 0;
+    virtual StatusCode extractFE(const xAOD::IParticle* obj,
+                                 std::vector<const xAOD::IParticle*>& felist,
+                                 const met::METAssociator::ConstitHolder& constits,
+                                 std::map<const xAOD::IParticle*,MissingETBase::Types::constvec_t> &momenta) const = 0;
     virtual StatusCode extractTracks(const xAOD::IParticle* obj,
-				     std::vector<const xAOD::IParticle*>& constlist,
-				     const met::METAssociator::ConstitHolder& constits) const = 0;
+                                     std::vector<const xAOD::IParticle*>& constlist,
+                                     const met::METAssociator::ConstitHolder& constits) const = 0;
     virtual StatusCode extractTopoClusters(const xAOD::IParticle* obj,
-					   std::vector<const xAOD::IParticle*>& tclist,
-					   const met::METAssociator::ConstitHolder& constits) const = 0;
+                                           std::vector<const xAOD::IParticle*>& tclist,
+                                           const met::METAssociator::ConstitHolder& constits) const = 0;
     static inline bool greaterPt(const xAOD::IParticle* part1, const xAOD::IParticle* part2) {
       return part1->pt()>part2->pt();
     }
@@ -142,6 +148,11 @@ namespace met {
       if (part1->charge()==0 && part2->charge()==0) return part1->ptEM()>part2->ptEM();
       return part1->pt()>part2->pt();
     }
+    static inline bool greaterPtFE(const xAOD::FlowElement* part1, const xAOD::FlowElement* part2) {
+      if (!(part1->isCharged()) && part2->isCharged()) return false;
+      if (part1->isCharged() && !(part2->isCharged())) return true;
+      return part1->pt() > part2->pt();
+    }
     ///////////////////////////////////////////////////////////////////
     // Private methods:
     ///////////////////////////////////////////////////////////////////
diff --git a/Reconstruction/MET/METReconstruction/METReconstruction/METEgammaAssociator.h b/Reconstruction/MET/METReconstruction/METReconstruction/METEgammaAssociator.h
index 6be2a69aa0531b34f145f86506a8d7c35a7e1dd5..a5639d0d599470e231a553160bd0559a13b7342a 100644
--- a/Reconstruction/MET/METReconstruction/METReconstruction/METEgammaAssociator.h
+++ b/Reconstruction/MET/METReconstruction/METReconstruction/METEgammaAssociator.h
@@ -56,25 +56,30 @@ namespace met{
     protected: 
 
     StatusCode extractTopoClusters(const xAOD::IParticle* obj,
-				   std::vector<const xAOD::IParticle*>& tclist,
-				   const met::METAssociator::ConstitHolder& constits) const final;
+                                   std::vector<const xAOD::IParticle*>& tclist,
+                                   const met::METAssociator::ConstitHolder& constits) const final;
 
     StatusCode extractPFO(const xAOD::IParticle* obj,
-			  std::vector<const xAOD::IParticle*>& pfolist,
-			  const met::METAssociator::ConstitHolder& constits,
-			  std::map<const xAOD::IParticle*,MissingETBase::Types::constvec_t> &momenta) const final;
+                          std::vector<const xAOD::IParticle*>& pfolist,
+                          const met::METAssociator::ConstitHolder& constits,
+                          std::map<const xAOD::IParticle*,MissingETBase::Types::constvec_t> &momenta) const final;
+
+    StatusCode extractFE(const xAOD::IParticle* obj,
+                         std::vector<const xAOD::IParticle*>& felist,
+                         const met::METAssociator::ConstitHolder& constits,
+                         std::map<const xAOD::IParticle*,MissingETBase::Types::constvec_t> &momenta) const final;
 
     StatusCode extractTracks(const xAOD::IParticle* obj,
-			     std::vector<const xAOD::IParticle*>& constlist,
-			     const met::METAssociator::ConstitHolder& constits) const final;
+                             std::vector<const xAOD::IParticle*>& constlist,
+                             const met::METAssociator::ConstitHolder& constits) const final;
 
     StatusCode selectEgammaClusters(const xAOD::CaloCluster *swclus,
-				    const std::vector<const xAOD::IParticle*>& inputTC,
-				    std::vector<const xAOD::IParticle*>& tclist) const;
+                                    const std::vector<const xAOD::IParticle*>& inputTC,
+                                    std::vector<const xAOD::IParticle*>& tclist) const;
 
     StatusCode selectEgammaTracks(const xAOD::Egamma* el,
-				  const xAOD::TrackParticleContainer* trkCont,
-				  std::set<const xAOD::TrackParticle*>& tracklist) const;
+                                  const xAOD::TrackParticleContainer* trkCont,
+                                  std::set<const xAOD::TrackParticle*>& tracklist) const;
 
     double m_tcMatch_dR;
     double m_tcMatch_maxRat;
diff --git a/Reconstruction/MET/METReconstruction/METReconstruction/METJetAssocTool.h b/Reconstruction/MET/METReconstruction/METReconstruction/METJetAssocTool.h
index fe8d1c71b2800d4f1ab976f3a51a956728e7285f..d47674488760229ddad5cf305ec3cd778d9ada68 100644
--- a/Reconstruction/MET/METReconstruction/METReconstruction/METJetAssocTool.h
+++ b/Reconstruction/MET/METReconstruction/METReconstruction/METJetAssocTool.h
@@ -57,17 +57,22 @@ namespace met{
     StatusCode executeTool(xAOD::MissingETContainer* metCont, xAOD::MissingETAssociationMap* metMap) const;
 
     StatusCode extractPFO(const xAOD::IParticle*,
-			  std::vector<const xAOD::IParticle*>&,
-			  const met::METAssociator::ConstitHolder&,
-			  std::map<const xAOD::IParticle*,MissingETBase::Types::constvec_t>&) const
+                          std::vector<const xAOD::IParticle*>&,
+                          const met::METAssociator::ConstitHolder&,
+                          std::map<const xAOD::IParticle*,MissingETBase::Types::constvec_t>&) const
+    {return StatusCode::FAILURE;} // should not be called
+    StatusCode extractFE(const xAOD::IParticle*,
+                         std::vector<const xAOD::IParticle*>&,
+                         const met::METAssociator::ConstitHolder&,
+                         std::map<const xAOD::IParticle*,MissingETBase::Types::constvec_t>&) const
     {return StatusCode::FAILURE;} // should not be called
     StatusCode extractTracks(const xAOD::IParticle*,
-			     std::vector<const xAOD::IParticle*>&,
-			     const met::METAssociator::ConstitHolder&) const
+                             std::vector<const xAOD::IParticle*>&,
+                             const met::METAssociator::ConstitHolder&) const
     {return StatusCode::FAILURE;} // should not be called
     StatusCode extractTopoClusters(const xAOD::IParticle*,
-				   std::vector<const xAOD::IParticle*>&,
-				   const met::METAssociator::ConstitHolder&) const
+                                   std::vector<const xAOD::IParticle*>&,
+                                   const met::METAssociator::ConstitHolder&) const
     {return StatusCode::FAILURE;} // should not be called
 
     private:
diff --git a/Reconstruction/MET/METReconstruction/METReconstruction/METMuonAssociator.h b/Reconstruction/MET/METReconstruction/METReconstruction/METMuonAssociator.h
index 177feca2ed5db78e7989c621e122285b8b85a3be..60cacc269128f24f2a4ac90091dcaf762f9f36bd 100644
--- a/Reconstruction/MET/METReconstruction/METReconstruction/METMuonAssociator.h
+++ b/Reconstruction/MET/METReconstruction/METReconstruction/METMuonAssociator.h
@@ -54,15 +54,19 @@ namespace met{
     
     StatusCode executeTool(xAOD::MissingETContainer* metCont, xAOD::MissingETAssociationMap* metMap) const final;
     StatusCode extractTopoClusters(const xAOD::IParticle* obj,
-				   std::vector<const xAOD::IParticle*>& tclist,
-				   const met::METAssociator::ConstitHolder& constits) const final;
+                                   std::vector<const xAOD::IParticle*>& tclist,
+                                   const met::METAssociator::ConstitHolder& constits) const final;
     StatusCode extractPFO(const xAOD::IParticle* obj,
-			  std::vector<const xAOD::IParticle*>& pfolist,
-			  const met::METAssociator::ConstitHolder& constits,
-			  std::map<const xAOD::IParticle*,MissingETBase::Types::constvec_t> &momenta) const final;
+                          std::vector<const xAOD::IParticle*>& pfolist,
+                          const met::METAssociator::ConstitHolder& constits,
+                          std::map<const xAOD::IParticle*,MissingETBase::Types::constvec_t> &momenta) const final;
+    StatusCode extractFE(const xAOD::IParticle* obj,
+                         std::vector<const xAOD::IParticle*>& felist,
+                         const met::METAssociator::ConstitHolder& constits,
+                         std::map<const xAOD::IParticle*,MissingETBase::Types::constvec_t> &momenta) const final;
     StatusCode extractTracks(const xAOD::IParticle* obj,
-			     std::vector<const xAOD::IParticle*>& constlist,
-			     const met::METAssociator::ConstitHolder& constits) const final;
+                             std::vector<const xAOD::IParticle*>& constlist,
+                             const met::METAssociator::ConstitHolder& constits) const final;
 
     private:
 
diff --git a/Reconstruction/MET/METReconstruction/METReconstruction/METSoftAssociator.h b/Reconstruction/MET/METReconstruction/METReconstruction/METSoftAssociator.h
index e371d63cfea9af763b090dcefd3b0585cfecd90f..d833630d07dfb8e40bdcb1fb91c0647c4caf101f 100644
--- a/Reconstruction/MET/METReconstruction/METReconstruction/METSoftAssociator.h
+++ b/Reconstruction/MET/METReconstruction/METReconstruction/METSoftAssociator.h
@@ -54,17 +54,22 @@ namespace met{
     StatusCode executeTool(xAOD::MissingETContainer* metCont, xAOD::MissingETAssociationMap* metMap) const final;
 
     StatusCode extractPFO(const xAOD::IParticle*,
-			  std::vector<const xAOD::IParticle*>&,
-			  const met::METAssociator::ConstitHolder&,
-			  std::map<const xAOD::IParticle*,MissingETBase::Types::constvec_t>&) const final
+                          std::vector<const xAOD::IParticle*>&,
+                          const met::METAssociator::ConstitHolder&,
+                          std::map<const xAOD::IParticle*,MissingETBase::Types::constvec_t>&) const final
+    {return StatusCode::FAILURE;} // should not be called
+    StatusCode extractFE(const xAOD::IParticle*,
+                         std::vector<const xAOD::IParticle*>&,
+                         const met::METAssociator::ConstitHolder&,
+                         std::map<const xAOD::IParticle*,MissingETBase::Types::constvec_t>&) const final
     {return StatusCode::FAILURE;} // should not be called
     StatusCode extractTracks(const xAOD::IParticle*,
-			     std::vector<const xAOD::IParticle*>&,
-			     const met::METAssociator::ConstitHolder&) const final
+                             std::vector<const xAOD::IParticle*>&,
+                             const met::METAssociator::ConstitHolder&) const final
     {return StatusCode::FAILURE;} // should not be called
     StatusCode extractTopoClusters(const xAOD::IParticle*,
-				   std::vector<const xAOD::IParticle*>&,
-				   const met::METAssociator::ConstitHolder&) const final
+                                   std::vector<const xAOD::IParticle*>&,
+                                   const met::METAssociator::ConstitHolder&) const final
     {return StatusCode::FAILURE;} // should not be called
 
     private:
diff --git a/Reconstruction/MET/METReconstruction/METReconstruction/METSoftTermsTool.h b/Reconstruction/MET/METReconstruction/METReconstruction/METSoftTermsTool.h
index b206bb0aef81681a9e0b5b85b59b2f2fa66e0dc7..58432ce9c00e0987c9bdce89f981585ba4fa8455 100644
--- a/Reconstruction/MET/METReconstruction/METReconstruction/METSoftTermsTool.h
+++ b/Reconstruction/MET/METReconstruction/METReconstruction/METSoftTermsTool.h
@@ -1,7 +1,7 @@
 ///////////////////////// -*- C++ -*- /////////////////////////////
 
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 // METSoftTermsTool.h 
@@ -10,6 +10,9 @@
 // This is a scheduler for the MET Reconstruction, and sets up
 // the sequence in which the individual terms are constructed.
 //
+// Note that this tool is now quite outdated and should be used only
+// for basic monitoring purposes.
+//
 //  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 //
 // Author: P Loch, S Resconi, TJ Khoo
@@ -26,14 +29,10 @@
 //Framework includes
 #include "StoreGate/DataHandle.h"
 
-// Forward declaration
-#include "xAODCaloEvent/CaloClusterFwd.h"
-#include "xAODTracking/TrackParticleFwd.h"
-
-// PFlow EDM and helpers
-#include "xAODPFlow/PFOContainer.h"
-#include "PFlowUtils/IRetrievePFOTool.h"
-
+//#include "xAODCaloEvent/CaloClusterFwd.h"
+#include "xAODCaloEvent/CaloClusterContainer.h"
+//#include "xAODTracking/TrackParticleFwd.h"
+#include "xAODTracking/TrackParticleContainer.h"
 
 namespace met{
 
@@ -43,11 +42,7 @@ namespace met{
     // This macro defines the constructor with the interface declaration
     ASG_TOOL_CLASS(METSoftTermsTool, IMETToolBase)
 
-
-    /////////////////////////////////////////////////////////////////// 
-    // Public methods: 
-    /////////////////////////////////////////////////////////////////// 
-    public: 
+  public: 
 
     // Constructor with name (does this have to be a non-const
     // std::string and not a const reference?)
@@ -58,24 +53,12 @@ namespace met{
     StatusCode  initialize();
     StatusCode  finalize();
 
-    /////////////////////////////////////////////////////////////////// 
-    // Const methods: 
-    ///////////////////////////////////////////////////////////////////
-
-    /////////////////////////////////////////////////////////////////// 
-    // Non-const methods: 
-    /////////////////////////////////////////////////////////////////// 
-
-    /////////////////////////////////////////////////////////////////// 
-    // Private data: 
-    /////////////////////////////////////////////////////////////////// 
   protected: 
     StatusCode  executeTool(xAOD::MissingET* metTerm, xAOD::MissingETComponentMap* metMap) const;
     // Accept functions
     bool accept            (const xAOD::IParticle* object) const;
     bool accept            (const xAOD::CaloCluster* clus) const;
     bool accept            (const xAOD::TrackParticle* trk) const;
-    bool accept            (const xAOD::PFO* pfo, const xAOD::Vertex* pv) const;
     // Overlap resolver function
     bool resolveOverlap    (const xAOD::IParticle* object,
                             xAOD::MissingETComponentMap* metMap,
@@ -89,27 +72,15 @@ namespace met{
     METSoftTermsTool();
     // Use Case - Clusters OR Tracks OR PFOs
     std::string m_inputType;
-    unsigned short m_st_objtype{0}; // should make this an enum somewhere
+    xAOD::Type::ObjectType m_st_objtype;
     // Cluster selection
     bool m_cl_vetoNegE;
     bool m_cl_onlyNegE;
-    // temporary, until a track-vertex association tool is available
-    //std::string m_pv_inputkey;
-    SG::ReadHandleKey<xAOD::VertexContainer>  m_pv_inputkey{this,"InputPVKey","PrimaryVertices",""};
     SG::ReadHandleKey<xAOD::CaloClusterContainer>  m_caloClusterKey{""};
     SG::ReadHandleKey<xAOD::TrackParticleContainer>  m_trackParticleKey{""};
 
-    ToolHandle<CP::IRetrievePFOTool> m_pfotool{this,"PFOTool","",""};
   }; 
 
 }
 
-// I/O operators
-//////////////////////
-
-/////////////////////////////////////////////////////////////////// 
-// Inline methods: 
-/////////////////////////////////////////////////////////////////// 
-
-
 #endif //> !METRECONSTRUCTION_METSOFTTERMSTOOL_H
diff --git a/Reconstruction/MET/METReconstruction/METReconstruction/METTauAssociator.h b/Reconstruction/MET/METReconstruction/METReconstruction/METTauAssociator.h
index ade7512f6307086d897659b39e1d7c0d4ca6bc77..1a41e1a510d5f0ac56545b68af8ec7658e0362fb 100644
--- a/Reconstruction/MET/METReconstruction/METReconstruction/METTauAssociator.h
+++ b/Reconstruction/MET/METReconstruction/METReconstruction/METTauAssociator.h
@@ -56,17 +56,22 @@ namespace met{
 
     StatusCode executeTool(xAOD::MissingETContainer* metCont, xAOD::MissingETAssociationMap* metMap) const final;
     StatusCode extractTopoClusters(const xAOD::IParticle* obj,
-				   std::vector<const xAOD::IParticle*>& tclist,
-				   const met::METAssociator::ConstitHolder& constits) const final;
+                                   std::vector<const xAOD::IParticle*>& tclist,
+                                   const met::METAssociator::ConstitHolder& constits) const final;
 
     StatusCode extractPFO(const xAOD::IParticle* obj,
-			  std::vector<const xAOD::IParticle*>& pfolist,
-			  const met::METAssociator::ConstitHolder& constits,
-			  std::map<const xAOD::IParticle*,MissingETBase::Types::constvec_t> &momenta) const final;
+                          std::vector<const xAOD::IParticle*>& pfolist,
+                          const met::METAssociator::ConstitHolder& constits,
+                          std::map<const xAOD::IParticle*,MissingETBase::Types::constvec_t> &momenta) const final;
+
+    StatusCode extractFE(const xAOD::IParticle* obj,
+                         std::vector<const xAOD::IParticle*>& felist,
+                         const met::METAssociator::ConstitHolder& constits,
+                         std::map<const xAOD::IParticle*,MissingETBase::Types::constvec_t> &momenta) const final;
     
     StatusCode extractTracks(const xAOD::IParticle* obj,
-			     std::vector<const xAOD::IParticle*>& constlist,
-			     const met::METAssociator::ConstitHolder& constits) const final;
+                             std::vector<const xAOD::IParticle*>& constlist,
+                             const met::METAssociator::ConstitHolder& constits) const final;
 
     private:
  
diff --git a/Reconstruction/MET/METReconstruction/METReconstruction/METTruthAssociator.h b/Reconstruction/MET/METReconstruction/METReconstruction/METTruthAssociator.h
index 093c518d5ba42573cc3a6ad54ceda496ec77bec7..d25652b0ba60328c02cc9c1779c33aae10240ec5 100644
--- a/Reconstruction/MET/METReconstruction/METReconstruction/METTruthAssociator.h
+++ b/Reconstruction/MET/METReconstruction/METReconstruction/METTruthAssociator.h
@@ -57,36 +57,41 @@ namespace met{
     protected: 
 
     StatusCode fillAssocMap(xAOD::MissingETAssociationMap* metMap,
-			    const xAOD::IParticleContainer* hardObjs) const final;
+                            const xAOD::IParticleContainer* hardObjs) const final;
     StatusCode executeTool(xAOD::MissingETContainer* metCont, xAOD::MissingETAssociationMap* metMap) const;
     //
     StatusCode associateJets(xAOD::MissingETAssociationMap* metMap) const;
     //
     StatusCode extractTruthParticles(const xAOD::IParticle* obj,
-				     std::vector<const xAOD::IParticle*>& truthlist) const;
+                                     std::vector<const xAOD::IParticle*>& truthlist) const;
     StatusCode extractTruthFromElectron(const xAOD::IParticle* obj,
-					std::vector<const xAOD::IParticle*>& truthlist) const;
+                                        std::vector<const xAOD::IParticle*>& truthlist) const;
     StatusCode extractTruthFromPhoton(const xAOD::IParticle* obj,
-				      std::vector<const xAOD::IParticle*>& truthlist) const;
+                                      std::vector<const xAOD::IParticle*>& truthlist) const;
     StatusCode extractTruthFromMuon(const xAOD::IParticle* obj,
-				    std::vector<const xAOD::IParticle*>& truthlist) const;
+                                    std::vector<const xAOD::IParticle*>& truthlist) const;
     StatusCode extractTruthFromTau(const xAOD::IParticle* obj,
-				     std::vector<const xAOD::IParticle*>& truthlist) const;
+                                     std::vector<const xAOD::IParticle*>& truthlist) const;
     //
     StatusCode computeSoftTerms(xAOD::MissingETContainer* metCont, xAOD::MissingETAssociationMap* metMap) const;
     //
     StatusCode extractPFO(const xAOD::IParticle*,
-			  std::vector<const xAOD::IParticle*>&,
-			  const met::METAssociator::ConstitHolder&,
-			  std::map<const xAOD::IParticle*,MissingETBase::Types::constvec_t>&) const final
+                          std::vector<const xAOD::IParticle*>&,
+                          const met::METAssociator::ConstitHolder&,
+                          std::map<const xAOD::IParticle*,MissingETBase::Types::constvec_t>&) const final
+    {return StatusCode::FAILURE;} // should not be called
+    StatusCode extractFE(const xAOD::IParticle*,
+                         std::vector<const xAOD::IParticle*>&,
+                         const met::METAssociator::ConstitHolder&,
+                         std::map<const xAOD::IParticle*,MissingETBase::Types::constvec_t>&) const final
     {return StatusCode::FAILURE;} // should not be called
     StatusCode extractTracks(const xAOD::IParticle*,
-			     std::vector<const xAOD::IParticle*>&,
-			     const met::METAssociator::ConstitHolder&) const final
+                             std::vector<const xAOD::IParticle*>&,
+                             const met::METAssociator::ConstitHolder&) const final
     {return StatusCode::FAILURE;} // should not be called
     StatusCode extractTopoClusters(const xAOD::IParticle*,
-				   std::vector<const xAOD::IParticle*>&,
-				   const met::METAssociator::ConstitHolder&) const final
+                                   std::vector<const xAOD::IParticle*>&,
+                                   const met::METAssociator::ConstitHolder&) const final
     {return StatusCode::FAILURE;} // should not be called
 
     private:
diff --git a/Reconstruction/MET/METReconstruction/Root/METAssociator.cxx b/Reconstruction/MET/METReconstruction/Root/METAssociator.cxx
index 20b1a7a925a7243bdcd78f74a52d3887a9a84856..a26caa214dd30ee10571b65d75227589298cd926 100644
--- a/Reconstruction/MET/METReconstruction/Root/METAssociator.cxx
+++ b/Reconstruction/MET/METReconstruction/Root/METAssociator.cxx
@@ -61,7 +61,7 @@ namespace met {
     declareProperty( "PrimVxColl",         m_pvcoll      = "PrimaryVertices"     );
     declareProperty( "TrkColl",            m_trkcoll     = "InDetTrackParticles" );
     declareProperty( "ClusColl",           m_clcoll      = "CaloCalTopoClusters" );
-    declareProperty( "UseModifiedClus",    m_useModifiedClus = false            );
+    declareProperty( "UseModifiedClus",    m_useModifiedClus = false             );
     declareProperty( "UseTracks",          m_useTracks   = true                  );
     declareProperty( "PFlow",              m_pflow       = false                 );
     declareProperty( "UseRapidity",        m_useRapidity = false                 );
@@ -69,7 +69,7 @@ namespace met {
     declareProperty( "TrackIsolationTool", m_trkIsolationTool                    );
     declareProperty( "CaloIsolationTool",  m_caloIsolationTool                   );
     declareProperty( "IgnoreJetConst",     m_skipconst = false                   );
-    declareProperty( "ForwardColl",        m_forcoll   = ""                       );
+    declareProperty( "ForwardColl",        m_forcoll   = ""                      );
     declareProperty( "ForwardDef",         m_foreta    = 2.5                     );
     declareProperty( "CentralTrackPtThr",  m_cenTrackPtThr = 30e+3               );
     declareProperty( "ForwardTrackPtThr",  m_forTrackPtThr = 30e+3               );
@@ -93,17 +93,17 @@ namespace met {
 
     if(m_clcoll == "CaloCalTopoClusters") {
       if(m_useModifiedClus) {
-	ATH_MSG_ERROR("Configured to use modified topocluster collection but \"CaloCalTopoClusters\" collection specified!");
-	return StatusCode::FAILURE;
+        ATH_MSG_ERROR("Configured to use modified topocluster collection but \"CaloCalTopoClusters\" collection specified!");
+        return StatusCode::FAILURE;
       } else {
-	ATH_MSG_INFO("Configured to use standard topocluster collection.");
+        ATH_MSG_INFO("Configured to use standard topocluster collection.");
       }
     } else {
       if(m_useModifiedClus) {
-	ATH_MSG_INFO("Configured to use modified topocluster collection \"" << m_clcoll << "\".");
+        ATH_MSG_INFO("Configured to use modified topocluster collection \"" << m_clcoll << "\".");
       } else {
-	ATH_MSG_ERROR("Configured to use topocluster collection \"" << m_clcoll << "\", but modified clusters flag not set!");
-	return StatusCode::FAILURE;
+        ATH_MSG_ERROR("Configured to use topocluster collection \"" << m_clcoll << "\", but modified clusters flag not set!");
+        return StatusCode::FAILURE;
       }
     }
 
@@ -114,7 +114,11 @@ namespace met {
       ATH_CHECK( m_trkcollKey.assign(m_trkcoll));
       ATH_CHECK( m_trkcollKey.initialize());
     }
-    if(m_pflow){
+    if(!m_fecollKey.key().empty()){
+      ATH_CHECK(m_fecollKey.initialize());
+      ATH_MSG_INFO("Configured to use FlowElement collection \"" << m_fecollKey.key() << "\".");
+    }
+    else if(m_pflow){
       ATH_CHECK( m_pfcollKey.initialize());
       if(m_pfcollKey.key() == "JetETMissParticleFlowObjects") {
         ATH_MSG_ERROR("Configured to use standard pflow collection \"" << m_pfcollKey.key() << "\".");
@@ -151,8 +155,8 @@ namespace met {
       ATH_MSG_WARNING("Invalid pointer to MissingETAssociationMap supplied! Abort.");
       return StatusCode::FAILURE;
     }
-    if(m_pflow && !m_useTracks ){
-      ATH_MSG_WARNING("Attempting to build PFlow without a track collection.");
+    if((m_pflow || !m_fecollKey.key().empty())&& !m_useTracks ){
+      ATH_MSG_WARNING("Attempting to build PFlow/FlowElement MET without a track collection.");
       return StatusCode::FAILURE;
     }
 
@@ -231,8 +235,8 @@ namespace met {
     }else{
       SG::ReadHandle<VertexContainer> vxCont(m_pvcollKey);
       if (!vxCont.isValid()) {
-	ATH_MSG_WARNING("Unable to retrieve primary vertex container " << m_pvcoll);
-	//this is actually really bad.  If it's empty that's okay
+        ATH_MSG_WARNING("Unable to retrieve primary vertex container " << m_pvcoll);
+        //this is actually really bad.  If it's empty that's okay
         return StatusCode::FAILURE;
       }
 
@@ -240,31 +244,41 @@ namespace met {
       ATH_MSG_DEBUG("Container holds " << vxCont->size() << " vertices");
 
       for(const auto& vx : *vxCont) {
-	ATH_MSG_VERBOSE( "Testing vertex " << vx->index() );
-	if(vx->vertexType()==VxType::PriVtx)
-	  {constits.pv = vx; break;}
+        ATH_MSG_VERBOSE( "Testing vertex " << vx->index() );
+        if(vx->vertexType()==VxType::PriVtx)
+          {constits.pv = vx; break;}
       }
       if(!constits.pv) {
-	ATH_MSG_DEBUG("Failed to find primary vertex! Reject all tracks.");
+        ATH_MSG_DEBUG("Failed to find primary vertex! Reject all tracks.");
       } else {
-	ATH_MSG_VERBOSE("Primary vertex has z = " << constits.pv->z());
+        ATH_MSG_VERBOSE("Primary vertex has z = " << constits.pv->z());
       }
 
       constits.trkCont=0;
       ATH_MSG_DEBUG("Retrieving Track collection " << m_trkcoll);
       SG::ReadHandle<TrackParticleContainer> trCont(m_trkcollKey);
       if (!trCont.isValid()) {
-	ATH_MSG_WARNING("Unable to retrieve track particle container");
+        ATH_MSG_WARNING("Unable to retrieve track particle container");
         return StatusCode::FAILURE;
       }
       constits.trkCont=trCont.cptr();
 
-      if(m_pflow) {
-	ATH_MSG_DEBUG("Retrieving PFlow collection " << m_pfcollKey.key());
-	constits.pfoCont = 0;
+      if(!m_fecollKey.key().empty()){
+        ATH_MSG_DEBUG("Retrieving FlowElement collection " << m_fecollKey.key());
+        constits.feCont = 0;
+        SG::ReadHandle<xAOD::FlowElementContainer> feCont(m_fecollKey);
+        if (!feCont.isValid()) {
+          ATH_MSG_ERROR("Unable to retrieve FlowElement container");
+          return StatusCode::FAILURE;
+        }
+        constits.feCont=feCont.cptr();
+      }
+      else if(m_pflow) {
+        ATH_MSG_DEBUG("Retrieving PFlow collection " << m_pfcollKey.key());
+        constits.pfoCont = 0;
         SG::ReadHandle<PFOContainer> pfCont(m_pfcollKey);
         if (!pfCont.isValid()) {
-	  ATH_MSG_WARNING("Unable to PFlow object container");
+          ATH_MSG_WARNING("Unable to PFlow object container");
           return StatusCode::FAILURE;
         }
         constits.pfoCont=pfCont.cptr();
@@ -285,7 +299,7 @@ namespace met {
   ///////////////////////////////////////////////////////////////////
 
   StatusCode METAssociator::fillAssocMap(xAOD::MissingETAssociationMap* metMap,
-					 const xAOD::IParticleContainer* hardObjs) const
+                                         const xAOD::IParticleContainer* hardObjs) const
   {
     ConstitHolder constits;
 
@@ -306,28 +320,37 @@ namespace met {
       if(obj->pt()<5e3 && obj->type()!=xAOD::Type::Muon) continue;
       constlist.clear();
       ATH_MSG_VERBOSE( "Object type, pt, eta, phi = " << obj->type() << ", " << obj->pt() << ", " << obj->eta() << "," << obj->phi() );
-      if (m_pflow) {
-	if(!m_useTracks){
-	  ATH_MSG_DEBUG("Attempting to build PFlow without a track collection.");
-	  return StatusCode::FAILURE;
-	}else{
-	  std::map<const IParticle*,MissingETBase::Types::constvec_t> momentumOverride;
-	  ATH_CHECK( this->extractPFO(obj,constlist,constits,momentumOverride) );
-	  MissingETComposition::insert(metMap,obj,constlist,momentumOverride);
-	}
+      if(!m_fecollKey.key().empty()){
+        if(!m_useTracks){
+          ATH_MSG_ERROR("Attempting to build FlowElement MET without a track collection.");
+          return StatusCode::FAILURE;
+        }
+        std::map<const IParticle*, MissingETBase::Types::constvec_t> momentumOverride;
+        ATH_CHECK( this->extractFE(obj, constlist, constits, momentumOverride) );
+        MissingETComposition::insert(metMap, obj, constlist, momentumOverride);
+      }
+      else if (m_pflow) {
+        if(!m_useTracks){
+          ATH_MSG_DEBUG("Attempting to build PFlow without a track collection.");
+          return StatusCode::FAILURE;
+        }else{
+          std::map<const IParticle*,MissingETBase::Types::constvec_t> momentumOverride;
+          ATH_CHECK( this->extractPFO(obj,constlist,constits,momentumOverride) );
+          MissingETComposition::insert(metMap,obj,constlist,momentumOverride);
+        }
       } else {
-	std::vector<const IParticle*> tclist;
-	tclist.reserve(20);
+        std::vector<const IParticle*> tclist;
+        tclist.reserve(20);
         ATH_CHECK( this->extractTopoClusters(obj,tclist,constits) );
-	if(m_useModifiedClus) {
-	  for(const auto& cl : tclist) {
-	    // use index-parallelism to identify shallow copied constituents
-	    constlist.push_back((*constits.tcCont)[cl->index()]);
-	  }
-	} else {
-	  constlist = tclist;
-	}
-	if(m_useTracks) ATH_CHECK( this->extractTracks(obj,constlist,constits) );
+        if(m_useModifiedClus) {
+          for(const auto& cl : tclist) {
+            // use index-parallelism to identify shallow copied constituents
+            constlist.push_back((*constits.tcCont)[cl->index()]);
+          }
+        } else {
+          constlist = tclist;
+        }
+        if(m_useTracks) ATH_CHECK( this->extractTracks(obj,constlist,constits) );
         MissingETComposition::insert(metMap,obj,constlist);
       }
     }
@@ -348,7 +371,7 @@ namespace met {
   {
 
     if( (fabs(trk->eta())<1.5 && trk->pt()>m_cenTrackPtThr) ||
-	(fabs(trk->eta())>=1.5 && trk->pt()>m_forTrackPtThr) ) {
+        (fabs(trk->eta())>=1.5 && trk->pt()>m_forTrackPtThr) ) {
 
       // Get relative error on qoverp
       float Rerr = Amg::error(trk->definingParametersCovMatrix(),4)/fabs(trk->qOverP());
@@ -363,9 +386,9 @@ namespace met {
       xAOD::TrackCorrection trkIsoCorr;
       trkIsoCorr.trackbitset.set(xAOD::Iso::IsolationTrackCorrection::coreTrackPtr); 
       m_trkIsolationTool->trackIsolation(trkIsoResult,
-					 *trk,
-					 trkIsoCones,
-					 trkIsoCorr);
+                                         *trk,
+                                         trkIsoCones,
+                                         trkIsoCorr);
       ptcone20 = trkIsoResult.ptcones.size() > 0 ? trkIsoResult.ptcones[0] : 0;
       isolfrac = ptcone20/trk->pt();
       // etcone
@@ -378,15 +401,15 @@ namespace met {
       xAOD::CaloCorrection caloIsoCorr_coreCone;
       caloIsoCorr_coreCone.calobitset.set(xAOD::Iso::IsolationCaloCorrection::coreCone); // this is etcone10
       m_caloIsolationTool->caloTopoClusterIsolation(caloIsoResult,
-						    *trk,
-						    caloIsoCones,
-						    caloIsoCorr_coreCone);
+                                                    *trk,
+                                                    caloIsoCones,
+                                                    caloIsoCorr_coreCone);
       if(caloIsoResult.etcones.size() > 0) {
-	// retrieve the correction value for the core cone
-	etcone10 = caloIsoResult.coreCorrections[xAOD::Iso::IsolationCaloCorrection::coreCone][xAOD::Iso::IsolationCorrectionParameter::coreEnergy];
+        // retrieve the correction value for the core cone
+        etcone10 = caloIsoResult.coreCorrections[xAOD::Iso::IsolationCaloCorrection::coreCone][xAOD::Iso::IsolationCorrectionParameter::coreEnergy];
       } else {
-	ATH_MSG_WARNING("isGoodEoverP: Failed to retrieve the isolation core correction (etcone10)! Setting etcone10=0");
-	etcone10 = 0.;
+        ATH_MSG_WARNING("isGoodEoverP: Failed to retrieve the isolation core correction (etcone10)! Setting etcone10=0");
+        etcone10 = 0.;
       }
       EoverP   =  etcone10/trk->pt(); 
       /////////////////////////////////////////////////////////////////////////
@@ -394,13 +417,13 @@ namespace met {
       ATH_MSG_VERBOSE( "Track E/P = " << EoverP );
 
       if(isolfrac<0.1) {
-	    // isolated track cuts
-	    if(Rerr>0.4) return false;
-	    else if (EoverP<0.65 && ((EoverP>0.1 && Rerr>0.05) || Rerr>0.1)) return false;
+            // isolated track cuts
+            if(Rerr>0.4) return false;
+            else if (EoverP<0.65 && ((EoverP>0.1 && Rerr>0.05) || Rerr>0.1)) return false;
       } else {
-	    // non-isolated track cuts
-	    float trkptsum = ptcone20+trk->pt();
-	    if(etcone10/trkptsum<0.6 && trk->pt()/trkptsum>0.6) return false;
+            // non-isolated track cuts
+            float trkptsum = ptcone20+trk->pt();
+            if(etcone10/trkptsum<0.6 && trk->pt()/trkptsum>0.6) return false;
       }
     }
     return true;
diff --git a/Reconstruction/MET/METReconstruction/Root/METEgammaAssociator.cxx b/Reconstruction/MET/METReconstruction/Root/METEgammaAssociator.cxx
index c69c6977dba2625f59972293a9d100d394e20804..92f077f6ae757949ed488e2e346c68a7ef442b9e 100644
--- a/Reconstruction/MET/METReconstruction/Root/METEgammaAssociator.cxx
+++ b/Reconstruction/MET/METReconstruction/Root/METEgammaAssociator.cxx
@@ -88,8 +88,8 @@ namespace met {
   //**********************************************************************
   // Get Egamma constituents
   StatusCode METEgammaAssociator::extractTopoClusters(const xAOD::IParticle* obj,
-						      std::vector<const xAOD::IParticle*>& tclist,
-						      const met::METAssociator::ConstitHolder& constits) const
+                                                      std::vector<const xAOD::IParticle*>& tclist,
+                                                      const met::METAssociator::ConstitHolder& constits) const
   {
     const Egamma *eg = static_cast<const Egamma*>(obj);
     // safe to assume a single SW cluster?
@@ -104,11 +104,11 @@ namespace met {
     
     if(m_tcMatch_method==DeltaR) {
       for(const auto& cl : *constits.tcCont) {
-	// this can probably be done more elegantly
-	if(P4Helpers::isInDeltaR(*swclus,*cl,m_tcMatch_dR,m_useRapidity) && cl->e()>FLT_MIN) {
-	  // could consider also requirements on the EM fraction or depth
-	  inputTC.push_back(cl);
-	} // match TC in a cone around SW cluster
+        // this can probably be done more elegantly
+        if(P4Helpers::isInDeltaR(*swclus,*cl,m_tcMatch_dR,m_useRapidity) && cl->e()>FLT_MIN) {
+          // could consider also requirements on the EM fraction or depth
+          inputTC.push_back(cl);
+        } // match TC in a cone around SW cluster
       }
       ATH_MSG_VERBOSE("Found " << inputTC.size() << " nearby topoclusters");
       std::sort(inputTC.begin(),inputTC.end(),greaterPt);
@@ -116,7 +116,7 @@ namespace met {
       static const SG::AuxElement::ConstAccessor<std::vector<ElementLink<CaloClusterContainer> > > tcLinkAcc("constituentClusterLinks");
       // Fill a vector of vectors
       for(const auto& el : tcLinkAcc(*swclus)) {
-	inputTC.push_back(*el);
+        inputTC.push_back(*el);
       }
       ATH_MSG_VERBOSE("Found " << inputTC.size() << " linked topoclusters");
     } else {
@@ -131,24 +131,24 @@ namespace met {
 
 
   StatusCode METEgammaAssociator::extractTracks(const xAOD::IParticle* obj,
-						std::vector<const xAOD::IParticle*>& constlist,
-						const met::METAssociator::ConstitHolder& constits) const
+                                                std::vector<const xAOD::IParticle*>& constlist,
+                                                const met::METAssociator::ConstitHolder& constits) const
   {
     const xAOD::Egamma *eg = static_cast<const xAOD::Egamma*>(obj);
     std::set<const xAOD::TrackParticle*> trackset; // use a set for duplicate-free retrieval
     ATH_CHECK( selectEgammaTracks(eg, constits.trkCont, trackset) );
     for(const auto& track : trackset) {
       if(acceptTrack(track,constits.pv) && isGoodEoverP(track)) {
-	constlist.push_back(track);
+        constlist.push_back(track);
       }
     }
     return StatusCode::SUCCESS;
   }
 
   StatusCode METEgammaAssociator::extractPFO(const xAOD::IParticle* obj,
-					     std::vector<const xAOD::IParticle*>& pfolist,
-					     const met::METAssociator::ConstitHolder& constits,
-					     std::map<const IParticle*,MissingETBase::Types::constvec_t> &/*momenta*/) const
+                                             std::vector<const xAOD::IParticle*>& pfolist,
+                                             const met::METAssociator::ConstitHolder& constits,
+                                             std::map<const IParticle*,MissingETBase::Types::constvec_t> &/*momenta*/) const
   {
     const xAOD::Egamma *eg = static_cast<const xAOD::Egamma*>(obj);
     // safe to assume a single SW cluster?
@@ -160,15 +160,15 @@ namespace met {
     nearbyPFO.reserve(20);
     for(const auto& pfo : *constits.pfoCont) {
       if(P4Helpers::isInDeltaR(*pfo, *swclus, 0.4, m_useRapidity)) {
-	// We set a small -ve pt for cPFOs that were rejected
-	// by the ChargedHadronSubtractionTool
-	const static SG::AuxElement::ConstAccessor<char> PVMatchedAcc("matchedToPV");	
-	if( ( !pfo->isCharged() && pfo->e() > FLT_MIN ) ||
-	    ( pfo->isCharged() && PVMatchedAcc(*pfo)
-	      && ( !m_cleanChargedPFO || isGoodEoverP(pfo->track(0)) ) )
-	    ) {
-	  nearbyPFO.push_back(pfo);
-	} // retain +ve E neutral PFOs and charged PFOs passing PV association
+        // We set a small -ve pt for cPFOs that were rejected
+        // by the ChargedHadronSubtractionTool
+        const static SG::AuxElement::ConstAccessor<char> PVMatchedAcc("matchedToPV");        
+        if( ( !pfo->isCharged() && pfo->e() > FLT_MIN ) ||
+            ( pfo->isCharged() && PVMatchedAcc(*pfo)
+              && ( !m_cleanChargedPFO || isGoodEoverP(pfo->track(0)) ) )
+            ) {
+          nearbyPFO.push_back(pfo);
+        } // retain +ve E neutral PFOs and charged PFOs passing PV association
       } // DeltaR check
     } // PFO loop
     ATH_MSG_VERBOSE("Found " << nearbyPFO.size() << " nearby pfos");
@@ -177,9 +177,9 @@ namespace met {
     ATH_CHECK( selectEgammaTracks(eg, constits.trkCont, trackset) );
     for(const auto& track : trackset) {
       for(const auto& pfo : nearbyPFO) {
-	if(pfo->isCharged() && pfo->track(0) == track) {
-	  pfolist.push_back(pfo);
-	} // PFO/track match
+        if(pfo->isCharged() && pfo->track(0) == track) {
+          pfolist.push_back(pfo);
+        } // PFO/track match
       } // PFO loop
     } // Track loop
     double eg_cl_e = swclus->e();
@@ -200,35 +200,118 @@ namespace met {
       // skip cluster if it's above our bad match threshold or outside the matching radius
       if(pfo_e>m_tcMatch_maxRat*eg_cl_e) {
         ATH_MSG_VERBOSE("Reject topocluster in sum. Ratio vs eg cluster: " << (pfo_e/eg_cl_e));
-    	if( !bestbadmatch || (fabs(pfo_e/eg_cl_e-1.) < fabs(bestbadmatch->e()/eg_cl_e-1.)) ) bestbadmatch = pfo;
-	continue;
+            if( !bestbadmatch || (fabs(pfo_e/eg_cl_e-1.) < fabs(bestbadmatch->e()/eg_cl_e-1.)) ) bestbadmatch = pfo;
+        continue;
       }
 
       ATH_MSG_VERBOSE("E match with new nPFO: " << fabs(sumE_pfo+pfo_e - eg_cl_e) / eg_cl_e);
       if( (doSum = fabs(sumE_pfo+pfo_e-eg_cl_e) < fabs(sumE_pfo - eg_cl_e)) ) {
-	pfolist.push_back(pfo);
-	sumE_pfo += pfo_e;
-    	ATH_MSG_VERBOSE("Accept pfo with pt " << pfo->pt() << ", e " << pfo->e() << " in sum.");
-    	ATH_MSG_VERBOSE("Energy ratio of nPFO to eg: " << pfo_e / eg_cl_e);
-    	ATH_MSG_VERBOSE("E match with new PFO: " << fabs(sumE_pfo+pfo_e - eg_cl_e) / eg_cl_e);
+        pfolist.push_back(pfo);
+        sumE_pfo += pfo_e;
+            ATH_MSG_VERBOSE("Accept pfo with pt " << pfo->pt() << ", e " << pfo->e() << " in sum.");
+            ATH_MSG_VERBOSE("Energy ratio of nPFO to eg: " << pfo_e / eg_cl_e);
+            ATH_MSG_VERBOSE("E match with new PFO: " << fabs(sumE_pfo+pfo_e - eg_cl_e) / eg_cl_e);
       } // if we will retain the topocluster
       else {break;}
     } // loop over nearby clusters
     if(sumE_pfo<FLT_MIN && bestbadmatch) {
       ATH_MSG_VERBOSE("No better matches found -- add bad match topocluster with pt "
-    		      << bestbadmatch->pt() << ", e " << bestbadmatch->e() << ".");
+                          << bestbadmatch->pt() << ", e " << bestbadmatch->e() << ".");
       pfolist.push_back(bestbadmatch);
     }
 
     return StatusCode::SUCCESS;
   }
 
+  StatusCode METEgammaAssociator::extractFE(const xAOD::IParticle* obj,
+                                            std::vector<const xAOD::IParticle*>& felist,
+                                            const met::METAssociator::ConstitHolder& constits,
+                                            std::map<const IParticle*,MissingETBase::Types::constvec_t> &/*momenta*/) const
+  {
+    const xAOD::Egamma *eg = static_cast<const xAOD::Egamma*>(obj);
+    // safe to assume a single SW cluster?
+    // will do so for now...
+    const xAOD::IParticle* swclus = eg->caloCluster();
+
+    // Preselect PFOs based on proximity: dR<0.4
+    std::vector<const xAOD::FlowElement*> nearbyFE;
+    nearbyFE.reserve(20);
+    for(const xAOD::FlowElement* fe : *constits.feCont) {
+      if(!(fe->signalType() & xAOD::FlowElement::PFlow)){
+        ATH_MSG_ERROR("Attempted to extract non-PFlow FlowElements. This is not supported!");
+        return StatusCode::FAILURE;
+      }
+      if(P4Helpers::isInDeltaR(*fe, *swclus, 0.4, m_useRapidity)) {
+        // We set a small -ve pt for cPFOs that were rejected
+        // by the ChargedHadronSubtractionTool
+        const static SG::AuxElement::ConstAccessor<char> PVMatchedAcc("matchedToPV");        
+        if( ( !fe->isCharged() && fe->e() > FLT_MIN ) ||
+            ( fe->isCharged() && PVMatchedAcc(*fe)
+              && ( !m_cleanChargedPFO || isGoodEoverP(static_cast<const xAOD::TrackParticle*>(fe->chargedObject(0))) ) )
+            ) {
+          nearbyFE.push_back(fe);
+        } // retain +ve E neutral PFOs and charged PFOs passing PV association
+      } // DeltaR check
+    } // PFO loop
+    ATH_MSG_VERBOSE("Found " << nearbyFE.size() << " nearby FlowElements (PFOs)");
+
+    std::set<const xAOD::TrackParticle*> trackset; // use a set for duplicate-free retrieval
+    ATH_CHECK( selectEgammaTracks(eg, constits.trkCont, trackset) );
+    for(const xAOD::TrackParticle* track : trackset) {
+      for(const xAOD::FlowElement* fe : nearbyFE) {
+        if(fe->isCharged() && fe->chargedObject(0) == track) {
+          felist.push_back(fe);
+        } // PFO/track match
+      } // PFO loop
+    } // Track loop
+    double eg_cl_e = swclus->e();
+
+    // the matching strategy depends on how the cluster container is sorted
+    // easier if it's sorted in descending pt order
+    // ideally this should be done using cell matching, but we can't use the links from topoclusters reliably
+    // because some PFOs don't correspond to the original TC
+    bool doSum = true;
+    double sumE_pfo = 0.;
+    const IParticle* bestbadmatch = 0;
+    std::sort(nearbyFE.begin(),nearbyFE.end(),greaterPtFE);
+    for(const xAOD::FlowElement* fe : nearbyFE) {
+      // Skip charged PFOs, as we already matched them
+      if(fe->isCharged() || !P4Helpers::isInDeltaR(*fe, *swclus, m_tcMatch_dR, m_useRapidity)) continue;
+      // Handle neutral PFOs like topoclusters
+      // TODO: Use EM-scale energy here in the future? No way to access from FlowElement in general.
+      double pfo_e = fe->e();
+      // skip cluster if it's above our bad match threshold or outside the matching radius
+      if(pfo_e > m_tcMatch_maxRat*eg_cl_e) {
+        ATH_MSG_VERBOSE("Reject topocluster in sum. Ratio vs eg cluster: " << (pfo_e/eg_cl_e));
+        if( !bestbadmatch || (fabs(pfo_e/eg_cl_e-1.) < fabs(bestbadmatch->e()/eg_cl_e-1.)) ) bestbadmatch = fe;
+        continue;
+      }
+
+      ATH_MSG_VERBOSE("E match with new nPFO: " << fabs(sumE_pfo+pfo_e - eg_cl_e) / eg_cl_e);
+      if( (doSum = fabs(sumE_pfo+pfo_e-eg_cl_e) < fabs(sumE_pfo - eg_cl_e)) ) {
+        felist.push_back(fe);
+        sumE_pfo += pfo_e;
+        ATH_MSG_VERBOSE("Accept pfo with pt " << fe->pt() << ", e " << fe->e() << " in sum.");
+        ATH_MSG_VERBOSE("Energy ratio of nPFO to eg: " << pfo_e / eg_cl_e);
+        ATH_MSG_VERBOSE("E match with new PFO: " << fabs(sumE_pfo+pfo_e - eg_cl_e) / eg_cl_e);
+      } // if we will retain the topocluster
+      else break;
+    } // loop over nearby clusters
+    if(sumE_pfo<FLT_MIN && bestbadmatch) {
+      ATH_MSG_VERBOSE("No better matches found -- add bad match topocluster with pt "
+                          << bestbadmatch->pt() << ", e " << bestbadmatch->e() << ".");
+      felist.push_back(bestbadmatch);
+    }
+
+    return StatusCode::SUCCESS;
+  }
+
   //**********************************************************************
   // Select Egamma tracks & clusters
 
   StatusCode METEgammaAssociator::selectEgammaClusters(const xAOD::CaloCluster* swclus,
-						       const std::vector<const IParticle*>& inputTC,
-						       std::vector<const xAOD::IParticle*>& tclist) const
+                                                       const std::vector<const IParticle*>& inputTC,
+                                                       std::vector<const xAOD::IParticle*>& tclist) const
   {    
     double eg_cl_e = swclus->e();
 
@@ -240,38 +323,38 @@ namespace met {
       // skip cluster if it's above our bad match threshold
       // retain pointer of the closest matching cluster in case no better is found
       if(tcl_e>m_tcMatch_maxRat*eg_cl_e) {
-    	ATH_MSG_VERBOSE("Reject topocluster in sum. Ratio vs eg cluster: " << (tcl_e/eg_cl_e));
-    	if( !bestbadmatch || (fabs(tcl_e/eg_cl_e-1.) < fabs(bestbadmatch->e()/eg_cl_e-1.)) ) bestbadmatch = cl;
-    	continue;
+            ATH_MSG_VERBOSE("Reject topocluster in sum. Ratio vs eg cluster: " << (tcl_e/eg_cl_e));
+            if( !bestbadmatch || (fabs(tcl_e/eg_cl_e-1.) < fabs(bestbadmatch->e()/eg_cl_e-1.)) ) bestbadmatch = cl;
+            continue;
       }
 
       ATH_MSG_VERBOSE("E match with new cluster: " << fabs(sumE_tc+tcl_e - eg_cl_e) / eg_cl_e);
       if( (doSum = (fabs(sumE_tc+tcl_e - eg_cl_e) < fabs(sumE_tc - eg_cl_e))) ) {
-    	ATH_MSG_VERBOSE("Accept topocluster with pt " << cl->pt() << ", e " << cl->e() << " in sum.");
-    	ATH_MSG_VERBOSE("Energy ratio of nPFO to eg: " << tcl_e / eg_cl_e);
-    	ATH_MSG_VERBOSE("E match with new cluster: " << fabs(sumE_tc+tcl_e - eg_cl_e) / eg_cl_e);
-    	tclist.push_back(cl);
-    	sumE_tc += tcl_e;
+            ATH_MSG_VERBOSE("Accept topocluster with pt " << cl->pt() << ", e " << cl->e() << " in sum.");
+            ATH_MSG_VERBOSE("Energy ratio of nPFO to eg: " << tcl_e / eg_cl_e);
+            ATH_MSG_VERBOSE("E match with new cluster: " << fabs(sumE_tc+tcl_e - eg_cl_e) / eg_cl_e);
+            tclist.push_back(cl);
+            sumE_tc += tcl_e;
       } // if we will retain the topocluster
     } // loop over nearby clusters
     if(sumE_tc<FLT_MIN && bestbadmatch) {
       ATH_MSG_VERBOSE("No better matches found -- add bad match topocluster with pt "
-    		      << bestbadmatch->pt() << ", e " << bestbadmatch->e() << ".");
+                          << bestbadmatch->pt() << ", e " << bestbadmatch->e() << ".");
       tclist.push_back(bestbadmatch);
     }
     return StatusCode::SUCCESS;
   }
 
   StatusCode METEgammaAssociator::selectEgammaTracks(const xAOD::Egamma* eg,
-						     const xAOD::TrackParticleContainer* trkCont,
-						     std::set<const xAOD::TrackParticle*>& tracklist) const
+                                                     const xAOD::TrackParticleContainer* trkCont,
+                                                     std::set<const xAOD::TrackParticle*>& tracklist) const
   {
     // switch to using egamma helpers for track extraction
     // set ensures that there's no duplication
     const std::set<const xAOD::TrackParticle*> egtracks = EgammaHelpers::getTrackParticles(eg);
     for(const auto& track : egtracks) {
-	ATH_MSG_VERBOSE("Accept " << eg->type() << " track " << track << " px, py = " << track->p4().Px() << ", " << track->p4().Py());
-	tracklist.insert(track);
+        ATH_MSG_VERBOSE("Accept " << eg->type() << " track " << track << " px, py = " << track->p4().Px() << ", " << track->p4().Py());
+        tracklist.insert(track);
     } // end initial egamma track loop
 
     // for objects with ambiguous author, grab the tracks matched to the counterpart ambiguous object too
@@ -279,44 +362,44 @@ namespace met {
     if (eg->author() & xAOD::EgammaParameters::AuthorAmbiguous && eg->ambiguousObject()) {
       const std::set<const xAOD::TrackParticle*> ambitracks = EgammaHelpers::getTrackParticles(eg->ambiguousObject());
       for(const auto& track : egtracks) {
-	ATH_MSG_VERBOSE("Accept ambiguous " << eg->type() << " track " << track << " px, py = " << track->p4().Px() << ", " << track->p4().Py());
-	tracklist.insert(track);
+        ATH_MSG_VERBOSE("Accept ambiguous " << eg->type() << " track " << track << " px, py = " << track->p4().Px() << ", " << track->p4().Py());
+        tracklist.insert(track);
       }
     } // end ambiguous track case
 
     // in a small dR window, also accept tracks without an IBL hit
     for(const auto& track : *trkCont) {
       if(P4Helpers::isInDeltaR(*track, *eg, m_extraTrkMatch_dR, m_useRapidity)) {
-	// dR check should be faster than track summary retrieval
-	uint8_t expect_innermostHit(false);
-	uint8_t N_innermostHit(false);
-	uint8_t expect_nextToInnermostHit(false);
-	uint8_t N_nextToInnermostHit(false);
-	if( !track->summaryValue(expect_innermostHit, expectInnermostPixelLayerHit)
-	    || !track->summaryValue(expect_nextToInnermostHit, expectNextToInnermostPixelLayerHit)) {
-	  ATH_MSG_WARNING("Track summary retrieval failed for 'expect(NextTo)InnermostPixelLayerHit'");
-	  return StatusCode::FAILURE;
-	}
-	if(expect_innermostHit) {
-	  if( !track->summaryValue(N_innermostHit, numberOfInnermostPixelLayerHits) ) {
-	    ATH_MSG_WARNING("Track summary retrieval failed for 'numberOfInnermostPixelLayerHits'");
-	    return StatusCode::FAILURE;
-	    if(N_innermostHit==0 ) {
-	      ATH_MSG_VERBOSE("Accept nearby track w/o innermost hit");
-	      tracklist.insert(track);
-	    }
-	  }
-	} else if(expect_nextToInnermostHit) {
-	  if( !track->summaryValue(N_nextToInnermostHit, numberOfNextToInnermostPixelLayerHits) ) {
-	    ATH_MSG_WARNING("Track summary retrieval failed for 'numberOfNextToInnermostPixelLayerHits'");
-	    return StatusCode::FAILURE;
-	    if(N_nextToInnermostHit==0 ) {
-	      ATH_MSG_VERBOSE("Accept nearby track w/o next-to-innermost hit");
-	      tracklist.insert(track);
-	    }
-	  }
-	}
-	
+        // dR check should be faster than track summary retrieval
+        uint8_t expect_innermostHit(false);
+        uint8_t N_innermostHit(false);
+        uint8_t expect_nextToInnermostHit(false);
+        uint8_t N_nextToInnermostHit(false);
+        if( !track->summaryValue(expect_innermostHit, expectInnermostPixelLayerHit)
+            || !track->summaryValue(expect_nextToInnermostHit, expectNextToInnermostPixelLayerHit)) {
+          ATH_MSG_WARNING("Track summary retrieval failed for 'expect(NextTo)InnermostPixelLayerHit'");
+          return StatusCode::FAILURE;
+        }
+        if(expect_innermostHit) {
+          if( !track->summaryValue(N_innermostHit, numberOfInnermostPixelLayerHits) ) {
+            ATH_MSG_WARNING("Track summary retrieval failed for 'numberOfInnermostPixelLayerHits'");
+            return StatusCode::FAILURE;
+            if(N_innermostHit==0 ) {
+              ATH_MSG_VERBOSE("Accept nearby track w/o innermost hit");
+              tracklist.insert(track);
+            }
+          }
+        } else if(expect_nextToInnermostHit) {
+          if( !track->summaryValue(N_nextToInnermostHit, numberOfNextToInnermostPixelLayerHits) ) {
+            ATH_MSG_WARNING("Track summary retrieval failed for 'numberOfNextToInnermostPixelLayerHits'");
+            return StatusCode::FAILURE;
+            if(N_nextToInnermostHit==0 ) {
+              ATH_MSG_VERBOSE("Accept nearby track w/o next-to-innermost hit");
+              tracklist.insert(track);
+            }
+          }
+        }
+        
       } // end dR check
     } // end extra track loop
     return StatusCode::SUCCESS;
diff --git a/Reconstruction/MET/METReconstruction/Root/METJetAssocTool.cxx b/Reconstruction/MET/METReconstruction/Root/METJetAssocTool.cxx
index 04f995d3105c570ad9299d0133f1180a071316b4..8fb15c6b2061e321999355753c3d7d90a0d72abc 100644
--- a/Reconstruction/MET/METReconstruction/Root/METJetAssocTool.cxx
+++ b/Reconstruction/MET/METReconstruction/Root/METJetAssocTool.cxx
@@ -1,7 +1,7 @@
 ///////////////////////// -*- C++ -*- /////////////////////////////
 
 /*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 // METJetAssocTool.cxx
@@ -72,20 +72,6 @@ namespace met {
     return StatusCode::SUCCESS;
   }
 
-  ///////////////////////////////////////////////////////////////////
-  // Const methods:
-  ///////////////////////////////////////////////////////////////////
-
-  ///////////////////////////////////////////////////////////////////
-  // Non-const methods:
-  ///////////////////////////////////////////////////////////////////
-
-  ///////////////////////////////////////////////////////////////////
-  // Protected methods:
-  ///////////////////////////////////////////////////////////////////
-
-  // executeTool
-  ////////////////
   StatusCode METJetAssocTool::executeTool(xAOD::MissingETContainer* /*metCont*/, xAOD::MissingETAssociationMap* metMap) const
   {
     ATH_MSG_VERBOSE ("In execute: " << name() << "...");
@@ -113,30 +99,43 @@ namespace met {
     // Create jet associations
     for(const auto& jet : *jetCont) {
       std::vector<const IParticle*> selectedTracks;
-      bool mismatchedPFlow = m_pflow && jet->rawConstituent(0)->type()!=xAOD::Type::ParticleFlow;
+      bool mismatchedPFlow = m_pflow && (jet->rawConstituent(0)->type()!=xAOD::Type::ParticleFlow && jet->rawConstituent(0)->type()!=xAOD::Type::FlowElement);
       bool mismatchedState = !m_skipconst && !m_pflow && jet->rawConstituent(0)->type()==xAOD::Type::CaloCluster && ((static_cast<const xAOD::CaloCluster*>(jet->rawConstituent(0))->signalState()==xAOD::CaloCluster::CALIBRATED && jet->getConstituentsSignalState()==xAOD::UncalibratedJetConstituent) || (static_cast<const xAOD::CaloCluster*>(jet->rawConstituent(0))->signalState()==xAOD::CaloCluster::UNCALIBRATED && jet->getConstituentsSignalState()==xAOD::CalibratedJetConstituent));
       bool newConstVec = m_skipconst || mismatchedPFlow || mismatchedState;
       if (m_pflow && !mismatchedPFlow) {
-        for (size_t consti = 0; consti < jet->numConstituents(); consti++) {
-          const xAOD::PFO *pfo = static_cast<const xAOD::PFO*>(jet->rawConstituent(consti));
-	  ATH_MSG_VERBOSE("Jet constituent PFO, pt :" << pfo->pt() << ", charge: " << pfo->charge());
-          if (pfo->isCharged() && (!m_cleanChargedPFO || isGoodEoverP(pfo->track(0)))) {
-	    ATH_MSG_VERBOSE("  Accepted charged PFO, pt " << pfo->pt());
-	    selectedTracks.push_back(pfo);
-	  }
+        if(jet->rawConstituent(0)->type() == xAOD::Type::FlowElement){
+          for (size_t consti = 0; consti < jet->numConstituents(); consti++) {
+            const xAOD::FlowElement *pfo = static_cast<const xAOD::FlowElement*>(jet->rawConstituent(consti));
+            ATH_MSG_VERBOSE("Jet constituent PFO, pt :" << pfo->pt() << ", charge: " << pfo->charge());
+            if ((pfo->isCharged()) && (!m_cleanChargedPFO || isGoodEoverP(static_cast<const xAOD::TrackParticle*>(pfo->chargedObject(0))))) {
+              ATH_MSG_VERBOSE("  Accepted charged PFO, pt " << pfo->pt());
+              selectedTracks.push_back(pfo);
+            }
+          }
+        }
+        else{
+          // constituents are xAOD::PFO
+          for (size_t consti = 0; consti < jet->numConstituents(); consti++) {
+            const xAOD::PFO *pfo = static_cast<const xAOD::PFO*>(jet->rawConstituent(consti));
+            ATH_MSG_VERBOSE("Jet constituent PFO, pt :" << pfo->pt() << ", charge: " << pfo->charge());
+            if (pfo->isCharged() && (!m_cleanChargedPFO || isGoodEoverP(pfo->track(0)))) {
+              ATH_MSG_VERBOSE("  Accepted charged PFO, pt " << pfo->pt());
+              selectedTracks.push_back(pfo);
+            }
+          }
         }
       } else {
         std::vector<const IParticle*> jettracks;
         jet->getAssociatedObjects<IParticle>(JetAttribute::GhostTrack,jettracks);
 
-	selectedTracks.reserve(jettracks.size());
-	for(const auto& trk : jettracks) {
-	  const TrackParticle* pTrk = static_cast<const TrackParticle*>(trk);
+        selectedTracks.reserve(jettracks.size());
+        for(const auto& trk : jettracks) {
+          const TrackParticle* pTrk = static_cast<const TrackParticle*>(trk);
           if(acceptTrack(pTrk,constits.pv) && isGoodEoverP(pTrk)) {
-	    selectedTracks.push_back(trk);
-	    ATH_MSG_VERBOSE("Accept track " << trk << " px, py = " << trk->p4().Px() << ", " << trk->p4().Py());
-	  }
-	}
+            selectedTracks.push_back(trk);
+            ATH_MSG_VERBOSE("Accept track " << trk << " px, py = " << trk->p4().Px() << ", " << trk->p4().Py());
+          }
+        }
       }
       std::vector<const IParticle*> consts;
       std::map<const IParticle*,MissingETBase::Types::constvec_t> momenta;
@@ -157,44 +156,74 @@ namespace met {
   }
 
   void METJetAssocTool::getPFOs(const xAOD::Jet *jet,
-				std::vector<const xAOD::IParticle*> &consts,
-				const met::METAssociator::ConstitHolder& constits,
-				std::map<const xAOD::IParticle*,MissingETBase::Types::constvec_t> &momenta) const {
+                                std::vector<const xAOD::IParticle*> &consts,
+                                const met::METAssociator::ConstitHolder& constits,
+                                std::map<const xAOD::IParticle*,MissingETBase::Types::constvec_t> &momenta) const {
 
     std::vector<const IParticle*> jettracks;
     jet->getAssociatedObjects<IParticle>(JetAttribute::GhostTrack,jettracks);
 
-    for(const auto& pfo : *constits.pfoCont) {
-      if (pfo->isCharged()) {
-	const TrackParticle* pfotrk = pfo->track(0);
-	for(const auto& trk : jettracks) {
-	  if (trk==pfotrk) {
-	    consts.push_back(pfo);
-	    break;
-	  }
-	}
-      } else {
-        bool marked = false;
-        for (size_t consti = 0; consti < jet->numConstituents(); consti++) if (pfo->p4().DeltaR(jet->rawConstituent(consti)->p4())<0.05) marked = true;
-        if (marked) {
-          consts.push_back(pfo);
-          TLorentzVector momentum = pfo->p4();
-          momenta[pfo] = MissingETBase::Types::constvec_t(momentum.Px(),momentum.Py(),momentum.Pz(),
-							  momentum.E(),momentum.Pt());
+    if(constits.feCont != nullptr){
+      // We have PFOs in FlowElement format
+      for(const xAOD::FlowElement* pfo : *constits.feCont) {
+        if (pfo->isCharged()) {
+          const TrackParticle* pfotrk = static_cast<const xAOD::TrackParticle*>(pfo->chargedObject(0));
+          for(const xAOD::IParticle* track : jettracks) {
+            const TrackParticle* jettrk = static_cast<const xAOD::TrackParticle*>(track);
+            if (jettrk==pfotrk) {
+              consts.push_back(pfo);
+              break;
+            }
+          }
+        }
+        else {
+          bool marked = false;
+          for (size_t consti = 0; consti < jet->numConstituents(); consti++){
+            if (pfo->p4().DeltaR(jet->rawConstituent(consti)->p4())<0.05) marked = true;
+          }
+          if (marked) {
+            consts.push_back(pfo);
+            TLorentzVector momentum = pfo->p4();
+            momenta[pfo] = MissingETBase::Types::constvec_t(momentum.Px(),momentum.Py(),momentum.Pz(),
+                                                            momentum.E(),momentum.Pt());
+          }
+        }
+      }
+    }
+    else{
+      // No FlowElements, assume xAOD::PFO format
+      for(const auto& pfo : *constits.pfoCont) {
+        if (pfo->isCharged()) {
+          const TrackParticle* pfotrk = pfo->track(0);
+          for(const auto& trk : jettracks) {
+            if (trk==pfotrk) {
+              consts.push_back(pfo);
+              break;
+            }
+          }
+        } else {
+          bool marked = false;
+          for (size_t consti = 0; consti < jet->numConstituents(); consti++) if (pfo->p4().DeltaR(jet->rawConstituent(consti)->p4())<0.05) marked = true;
+          if (marked) {
+            consts.push_back(pfo);
+            TLorentzVector momentum = pfo->p4();
+            momenta[pfo] = MissingETBase::Types::constvec_t(momentum.Px(),momentum.Py(),momentum.Pz(),
+                                                            momentum.E(),momentum.Pt());
+          }
         }
       }
     }
   }
 
   void METJetAssocTool::getClus(const xAOD::Jet *jet,
-				std::vector<const xAOD::IParticle*> &consts) const {
+                                std::vector<const xAOD::IParticle*> &consts) const {
     std::vector<ElementLink<IParticleContainer> > jetconst = jet->constituentLinks();
     for(const auto& clus : jetconst) consts.push_back(*clus);
   }
 
   void METJetAssocTool::getOther(const xAOD::Jet *jet,
-				 std::vector<const xAOD::IParticle*> &consts,
-				 std::set<const xAOD::IParticle*> *newConst) const {
+                                 std::vector<const xAOD::IParticle*> &consts,
+                                 std::set<const xAOD::IParticle*> *newConst) const {
     std::vector<ElementLink<IParticleContainer> > jetconst = jet->constituentLinks();
     for(const auto& clus : *newConst) if (clus->container()!=jet->rawConstituent(0)->container() && clus->e()>0 && xAOD::P4Helpers::isInDeltaR(*jet,*clus,m_matchRadius,m_useRapidity)) consts.push_back(clus);
     //for(const auto& clus : *newConst) if (clus->type()!=jet->rawConstituent(0)->type() && clus->e()>0 && xAOD::P4Helpers::isInDeltaR(*jet,*clus,m_matchRadius,m_useRapidity)) consts.push_back(clus);
diff --git a/Reconstruction/MET/METReconstruction/Root/METMuonAssociator.cxx b/Reconstruction/MET/METReconstruction/Root/METMuonAssociator.cxx
index 4b87255a851c07b4713ca33b9dfc83e3ef9a79a5..7d00b4456544d38828796d906a5840303b07d4ec 100644
--- a/Reconstruction/MET/METReconstruction/Root/METMuonAssociator.cxx
+++ b/Reconstruction/MET/METReconstruction/Root/METMuonAssociator.cxx
@@ -99,32 +99,32 @@ namespace met {
   //*********************************************************************************************************
   // Get constituents
   StatusCode METMuonAssociator::extractTopoClusters(const xAOD::IParticle* obj,
-						    std::vector<const xAOD::IParticle*>& tclist,
-						    const met::METAssociator::ConstitHolder& /*constits*/) const
+                                                    std::vector<const xAOD::IParticle*>& tclist,
+                                                    const met::METAssociator::ConstitHolder& /*constits*/) const
   {
     const xAOD::Muon *mu = static_cast<const xAOD::Muon*>(obj);
     const CaloCluster* muclus = mu->cluster();
     if(muclus && m_doMuonClusterMatch) {
       ATH_MSG_VERBOSE("Muon " << mu->index() << " with pt " << mu->pt()
-		   << ", eta "   << mu->eta()
-		   << ", phi " << mu->phi()
-		   << " has cluster with "
-		   << "eta "   << muclus->calEta()
-		   << ", phi " << muclus->calPhi()
-		   << ", E "   << muclus->calE()
-		   << " formed of " << muclus->size() << " cells.");
+                   << ", eta "   << mu->eta()
+                   << ", phi " << mu->phi()
+                   << " has cluster with "
+                   << "eta "   << muclus->calEta()
+                   << ", phi " << muclus->calPhi()
+                   << ", E "   << muclus->calE()
+                   << " formed of " << muclus->size() << " cells.");
       ATH_MSG_VERBOSE("Muon Eloss type: " << mu->energyLossType()
-		   << " Eloss: " << mu->floatParameter(xAOD::Muon::EnergyLoss)
-		   << " MeasuredEloss: " << mu->floatParameter(xAOD::Muon::MeasEnergyLoss)
-		   << " FSR E: " << mu->floatParameter(xAOD::Muon::FSR_CandidateEnergy) );
+                   << " Eloss: " << mu->floatParameter(xAOD::Muon::EnergyLoss)
+                   << " MeasuredEloss: " << mu->floatParameter(xAOD::Muon::MeasEnergyLoss)
+                   << " FSR E: " << mu->floatParameter(xAOD::Muon::FSR_CandidateEnergy) );
       
       SG::ReadDecorHandle<CaloClusterContainer, std::vector<ElementLink<CaloClusterContainer> > > tcLinkAcc(m_elementLinkName); 
       for(const auto& matchel : tcLinkAcc(*muclus)) {
-	if(!matchel.isValid()) {continue;} // In case of thinned cluster collection
-	ATH_MSG_VERBOSE("Tool found cluster " << (*matchel)->index() << " with pt " << (*matchel)->pt() );
-	if((*matchel)->e()>1e-9) { // +ve E
-	  tclist.push_back(*matchel);
-	}
+        if(!matchel.isValid()) {continue;} // In case of thinned cluster collection
+        ATH_MSG_VERBOSE("Tool found cluster " << (*matchel)->index() << " with pt " << (*matchel)->pt() );
+        if((*matchel)->e()>1e-9) { // +ve E
+          tclist.push_back(*matchel);
+        }
       }
     } // muon has linked cluster
     
@@ -132,8 +132,8 @@ namespace met {
   }
 
   StatusCode METMuonAssociator::extractTracks(const xAOD::IParticle *obj,
-					      std::vector<const xAOD::IParticle*>& constlist,
-					      const met::METAssociator::ConstitHolder& constits) const
+                                              std::vector<const xAOD::IParticle*>& constlist,
+                                              const met::METAssociator::ConstitHolder& constits) const
   {
     const xAOD::Muon *mu = static_cast<const xAOD::Muon*>(obj);
     const TrackParticle* idtrack = mu->trackParticle(xAOD::Muon::InnerDetectorTrackParticle);
@@ -152,61 +152,123 @@ namespace met {
   //*********************************************************************************************************
   // Get constituents
   StatusCode METMuonAssociator::extractPFO(const xAOD::IParticle* obj,
-					   std::vector<const xAOD::IParticle*>& pfolist,
-					   const met::METAssociator::ConstitHolder& constits,
-					   std::map<const IParticle*,MissingETBase::Types::constvec_t>& /*momenta*/) const
+                                           std::vector<const xAOD::IParticle*>& pfolist,
+                                           const met::METAssociator::ConstitHolder& constits,
+                                           std::map<const IParticle*,MissingETBase::Types::constvec_t>& /*momenta*/) const
   {  
     const xAOD::Muon *mu = static_cast<const xAOD::Muon*>(obj);
     const TrackParticle* idtrack = mu->trackParticle(xAOD::Muon::InnerDetectorTrackParticle);
     const CaloCluster* muclus = mu->cluster();
 
     ATH_MSG_VERBOSE("Muon " << mu->index() << " with pt " << mu->pt()
-		    << ", eta "   << mu->eta()
-		    << ", phi " << mu->phi());
+                    << ", eta "   << mu->eta()
+                    << ", phi " << mu->phi());
     if(muclus) {
       ATH_MSG_VERBOSE(" has cluster with "
-		      << "eta "   << muclus->calEta()
-		      << ", phi " << muclus->calPhi()
-		      << ", E "   << muclus->calE()
-		      << " formed of " << muclus->size() << " cells.");
+                      << "eta "   << muclus->calEta()
+                      << ", phi " << muclus->calPhi()
+                      << ", E "   << muclus->calE()
+                      << " formed of " << muclus->size() << " cells.");
     }
     ATH_MSG_VERBOSE("Muon Eloss type: " << mu->energyLossType()
-		    << " Eloss: " << mu->floatParameter(xAOD::Muon::EnergyLoss)
-		    << " MeasuredEloss: " << mu->floatParameter(xAOD::Muon::MeasEnergyLoss)
-		    << " FSR E: " << mu->floatParameter(xAOD::Muon::FSR_CandidateEnergy) );
+                    << " Eloss: " << mu->floatParameter(xAOD::Muon::EnergyLoss)
+                    << " MeasuredEloss: " << mu->floatParameter(xAOD::Muon::MeasEnergyLoss)
+                    << " FSR E: " << mu->floatParameter(xAOD::Muon::FSR_CandidateEnergy) );
 
     // One loop over PFOs
     for(const auto& pfo : *constits.pfoCont) {
       if(pfo->isCharged()) {
-	// get charged PFOs by matching the muon ID track
-	// We set a small -ve pt for cPFOs that were rejected
-	// by the ChargedHadronSubtractionTool
-	const static SG::AuxElement::ConstAccessor<char> PVMatchedAcc("matchedToPV");
-	if(idtrack && pfo->track(0) == idtrack && PVMatchedAcc(*pfo) &&
-	   ( !m_cleanChargedPFO || isGoodEoverP(pfo->track(0)) )
-	   ) {
-	  ATH_MSG_VERBOSE("Accept muon PFO " << pfo << " px, py = " << pfo->p4().Px() << ", " << pfo->p4().Py());
-	  ATH_MSG_VERBOSE("Muon PFO index: " << pfo->index() << ", pt: " << pfo->pt() << ", eta: " << pfo->eta() << ", phi: " << pfo->phi() );
-	  ATH_MSG_VERBOSE("Muon ID Track index: " << idtrack->index() << ", pt: " << idtrack->pt() << ", eta: " << idtrack->eta() << ", phi: " << idtrack->phi() );
-	  pfolist.push_back(pfo);
-	  break;
-	} // track match
+        // get charged PFOs by matching the muon ID track
+        // We set a small -ve pt for cPFOs that were rejected
+        // by the ChargedHadronSubtractionTool
+        const static SG::AuxElement::ConstAccessor<char> PVMatchedAcc("matchedToPV");
+        if(idtrack && pfo->track(0) == idtrack && PVMatchedAcc(*pfo) &&
+           ( !m_cleanChargedPFO || isGoodEoverP(pfo->track(0)) )
+           ) {
+          ATH_MSG_VERBOSE("Accept muon PFO " << pfo << " px, py = " << pfo->p4().Px() << ", " << pfo->p4().Py());
+          ATH_MSG_VERBOSE("Muon PFO index: " << pfo->index() << ", pt: " << pfo->pt() << ", eta: " << pfo->eta() << ", phi: " << pfo->phi() );
+          ATH_MSG_VERBOSE("Muon ID Track index: " << idtrack->index() << ", pt: " << idtrack->pt() << ", eta: " << idtrack->eta() << ", phi: " << idtrack->phi() );
+          pfolist.push_back(pfo);
+          break;
+        } // track match
       } else {
-      	// get neutral PFOs by matching the muon cluster
-      	if(muclus && m_doMuonClusterMatch) {
-
-	  SG::ReadDecorHandle<CaloClusterContainer, std::vector<ElementLink<CaloClusterContainer> > > tcLinkAcc(m_elementLinkName); 
-      	  for(const auto& matchel : tcLinkAcc(*muclus)) {
-	    if(!matchel.isValid()) {
-	      ATH_MSG_DEBUG("Invalid muon-cluster elementLink");
-	    } else {
-	      if((*matchel)->e()>FLT_MIN && pfo->cluster(0) == *matchel) { // +ve E && matches cluster
-		ATH_MSG_VERBOSE("Tool found cluster " << (*matchel)->index() << " with pt " << (*matchel)->pt() );
-		pfolist.push_back(pfo);
-	      }
-	    }
-      	  }
-      	} // muon has linked cluster
+        // get neutral PFOs by matching the muon cluster
+        if(muclus && m_doMuonClusterMatch) {
+
+          SG::ReadDecorHandle<CaloClusterContainer, std::vector<ElementLink<CaloClusterContainer> > > tcLinkAcc(m_elementLinkName); 
+                for(const auto& matchel : tcLinkAcc(*muclus)) {
+            if(!matchel.isValid()) {
+              ATH_MSG_DEBUG("Invalid muon-cluster elementLink");
+            } else {
+              if((*matchel)->e()>FLT_MIN && pfo->cluster(0) == *matchel) { // +ve E && matches cluster
+                ATH_MSG_VERBOSE("Tool found cluster " << (*matchel)->index() << " with pt " << (*matchel)->pt() );
+                pfolist.push_back(pfo);
+              }
+            }
+          }
+        } // muon has linked cluster
+      } 
+    } // end of cluster loop
+
+    return StatusCode::SUCCESS;
+  }
+
+  StatusCode METMuonAssociator::extractFE(const xAOD::IParticle* obj,
+                                          std::vector<const xAOD::IParticle*>& felist,
+                                          const met::METAssociator::ConstitHolder& constits,
+                                          std::map<const IParticle*,MissingETBase::Types::constvec_t>& /*momenta*/) const
+  {  
+    const xAOD::Muon *mu = static_cast<const xAOD::Muon*>(obj);
+    const TrackParticle* idtrack = mu->trackParticle(xAOD::Muon::InnerDetectorTrackParticle);
+    const CaloCluster* muclus = mu->cluster();
+
+    ATH_MSG_VERBOSE("Muon " << mu->index() << " with pt " << mu->pt()
+                    << ", eta "   << mu->eta()
+                    << ", phi " << mu->phi());
+    if(muclus) {
+      ATH_MSG_VERBOSE(" has cluster with "
+                      << "eta "   << muclus->calEta()
+                      << ", phi " << muclus->calPhi()
+                      << ", E "   << muclus->calE()
+                      << " formed of " << muclus->size() << " cells.");
+    }
+    ATH_MSG_VERBOSE("Muon Eloss type: " << mu->energyLossType()
+                    << " Eloss: " << mu->floatParameter(xAOD::Muon::EnergyLoss)
+                    << " MeasuredEloss: " << mu->floatParameter(xAOD::Muon::MeasEnergyLoss)
+                    << " FSR E: " << mu->floatParameter(xAOD::Muon::FSR_CandidateEnergy) );
+
+    // One loop over PFOs
+    for(const xAOD::FlowElement* fe : *constits.feCont) {
+      if(fe->isCharged()) {
+        // get charged FEs by matching the muon ID track
+        // We set a small -ve pt for cPFOs that were rejected
+        // by the ChargedHadronSubtractionTool
+        const static SG::AuxElement::ConstAccessor<char> PVMatchedAcc("matchedToPV");
+        if(idtrack && fe->chargedObject(0) == idtrack && PVMatchedAcc(*fe) &&
+           ( !m_cleanChargedPFO || isGoodEoverP(static_cast<const xAOD::TrackParticle*>(fe->chargedObject(0))) )
+           ) {
+          ATH_MSG_VERBOSE("Accept muon PFO (FE) " << fe << " px, py = " << fe->p4().Px() << ", " << fe->p4().Py());
+          ATH_MSG_VERBOSE("Muon PFO index: " << fe->index() << ", pt: " << fe->pt() << ", eta: " << fe->eta() << ", phi: " << fe->phi() );
+          ATH_MSG_VERBOSE("Muon ID Track index: " << idtrack->index() << ", pt: " << idtrack->pt() << ", eta: " << idtrack->eta() << ", phi: " << idtrack->phi() );
+          felist.push_back(fe);
+          break;
+        } // track match
+      } else {
+        // get neutral PFOs by matching the muon cluster
+        if(muclus && m_doMuonClusterMatch) {
+
+          SG::ReadDecorHandle<CaloClusterContainer, std::vector<ElementLink<CaloClusterContainer> > > tcLinkAcc(m_elementLinkName); 
+          for(const auto& matchel : tcLinkAcc(*muclus)) {
+            if(!matchel.isValid()) {
+              ATH_MSG_DEBUG("Invalid muon-cluster elementLink");
+            } else {
+              if((*matchel)->e()>FLT_MIN && fe->otherObject(0) == *matchel) { // +ve E && matches cluster
+                ATH_MSG_VERBOSE("Tool found cluster " << (*matchel)->index() << " with pt " << (*matchel)->pt() );
+                felist.push_back(fe);
+              }
+            }
+          }
+        } // muon has linked cluster
       } 
     } // end of cluster loop
 
diff --git a/Reconstruction/MET/METReconstruction/Root/METSoftAssociator.cxx b/Reconstruction/MET/METReconstruction/Root/METSoftAssociator.cxx
index 0681270d3d11e5c475753cdbac7a15bfc8e459dd..ee4a4e315ca09972bbed3ef7b82976adf7d52b48 100644
--- a/Reconstruction/MET/METReconstruction/Root/METSoftAssociator.cxx
+++ b/Reconstruction/MET/METReconstruction/Root/METSoftAssociator.cxx
@@ -89,7 +89,45 @@ namespace met {
       return StatusCode::FAILURE;
     }
 
-    if (m_pflow) {
+    if(!m_fecollKey.key().empty()){
+      // PFOs have been provided as FlowElements
+      const IParticleContainer* uniquePFOs = metMap->getUniqueSignals(constits.pfoCont,MissingETBase::UsageHandler::Policy::ParticleFlow);
+      if(m_decorateSoftTermConst) {
+        dec_softConst(*metCoreTrk) = std::vector<ElementLink<IParticleContainer> >();
+        dec_softConst(*metCoreTrk).reserve(uniquePFOs->size());
+        dec_softConst(*metCoreCl) = std::vector<ElementLink<IParticleContainer> >();
+        dec_softConst(*metCoreCl).reserve(uniquePFOs->size());
+      }
+      for(const IParticle* sig : *uniquePFOs) {
+        const xAOD::FlowElement *pfo = static_cast<const xAOD::FlowElement*>(sig);
+        if (pfo->isCharged()) { // Charged PFOs
+          // We set a small -ve pt for cPFOs that were rejected
+          // by the ChargedHadronSubtractionTool
+          const static SG::AuxElement::ConstAccessor<char> PVMatchedAcc("matchedToPV");        
+          if (PVMatchedAcc(*pfo) && ( !m_cleanChargedPFO || isGoodEoverP(static_cast<const xAOD::TrackParticle*>(pfo->chargedObject(0))) ) ) {
+            // For the TST, we add the track pt, as this need not be
+            // corrected for nearby energy in the calo
+            *metCoreTrk += pfo->chargedObject(0);
+            // For CST we add the PFO pt, which is weighted down
+            // to account for energy in the calo that may not have
+            // been subtracted
+            *metCoreCl  += sig;
+            if(m_decorateSoftTermConst) {
+              dec_softConst(*metCoreTrk).push_back(ElementLink<IParticleContainer>(*static_cast<const IParticleContainer*>(sig->container()),sig->index()));
+              dec_softConst(*metCoreCl).push_back(ElementLink<IParticleContainer>(*static_cast<const IParticleContainer*>(sig->container()),sig->index()));
+            }
+          }
+        } else { // Neutral PFOs
+          if (pfo->e()>FLT_MIN) {
+            // This is a non-issue; just add the four-vector
+             *metCoreCl += sig;
+             if(m_decorateSoftTermConst) dec_softConst(*metCoreCl).push_back(ElementLink<IParticleContainer>(*static_cast<const IParticleContainer*>(sig->container()),sig->index()));
+          }
+        }
+      }
+      delete uniquePFOs;
+    }
+    else if (m_pflow) {
       const IParticleContainer* uniquePFOs = metMap->getUniqueSignals(constits.pfoCont,MissingETBase::UsageHandler::Policy::ParticleFlow);
       if(m_decorateSoftTermConst) {
         dec_softConst(*metCoreTrk) = std::vector<ElementLink<IParticleContainer> >();
@@ -98,31 +136,31 @@ namespace met {
         dec_softConst(*metCoreCl).reserve(uniquePFOs->size());
       }
       for(const auto& sig : *uniquePFOs) {
-	const PFO *pfo = static_cast<const PFO*>(sig);
-	if (pfo->isCharged()) { // Charged PFOs
-	  // We set a small -ve pt for cPFOs that were rejected
-	  // by the ChargedHadronSubtractionTool
-	  const static SG::AuxElement::ConstAccessor<char> PVMatchedAcc("matchedToPV");	
-	  if (PVMatchedAcc(*pfo) && ( !m_cleanChargedPFO || isGoodEoverP(pfo->track(0)) ) ) {
-	    // For the TST, we add the track pt, as this need not be
-	    // corrected for nearby energy in the calo
-	    *metCoreTrk += pfo->track(0);
-	    // For CST we add the PFO pt, which is weighted down
-	    // to account for energy in the calo that may not have
-	    // been subtracted
-	    *metCoreCl  += sig;
-	    if(m_decorateSoftTermConst) {
-	      dec_softConst(*metCoreTrk).push_back(ElementLink<IParticleContainer>(*static_cast<const IParticleContainer*>(sig->container()),sig->index()));
-	      dec_softConst(*metCoreCl).push_back(ElementLink<IParticleContainer>(*static_cast<const IParticleContainer*>(sig->container()),sig->index()));
-	    }
-	  }
-	} else { // Neutral PFOs
-	  if (pfo->e()>FLT_MIN) {
-	    // This is a non-issue; just add the four-vector
- 	    *metCoreCl += sig;
- 	    if(m_decorateSoftTermConst) dec_softConst(*metCoreCl).push_back(ElementLink<IParticleContainer>(*static_cast<const IParticleContainer*>(sig->container()),sig->index()));
-	  }
-	}
+        const PFO *pfo = static_cast<const PFO*>(sig);
+        if (pfo->isCharged()) { // Charged PFOs
+          // We set a small -ve pt for cPFOs that were rejected
+          // by the ChargedHadronSubtractionTool
+          const static SG::AuxElement::ConstAccessor<char> PVMatchedAcc("matchedToPV");        
+          if (PVMatchedAcc(*pfo) && ( !m_cleanChargedPFO || isGoodEoverP(pfo->track(0)) ) ) {
+            // For the TST, we add the track pt, as this need not be
+            // corrected for nearby energy in the calo
+            *metCoreTrk += pfo->track(0);
+            // For CST we add the PFO pt, which is weighted down
+            // to account for energy in the calo that may not have
+            // been subtracted
+            *metCoreCl  += sig;
+            if(m_decorateSoftTermConst) {
+              dec_softConst(*metCoreTrk).push_back(ElementLink<IParticleContainer>(*static_cast<const IParticleContainer*>(sig->container()),sig->index()));
+              dec_softConst(*metCoreCl).push_back(ElementLink<IParticleContainer>(*static_cast<const IParticleContainer*>(sig->container()),sig->index()));
+            }
+          }
+        } else { // Neutral PFOs
+          if (pfo->e()>FLT_MIN) {
+            // This is a non-issue; just add the four-vector
+             *metCoreCl += sig;
+             if(m_decorateSoftTermConst) dec_softConst(*metCoreCl).push_back(ElementLink<IParticleContainer>(*static_cast<const IParticleContainer*>(sig->container()),sig->index()));
+          }
+        }
       }
       delete uniquePFOs;
     } else {
@@ -140,44 +178,44 @@ namespace met {
       SG::ReadHandle<xAOD::CaloClusterContainer> emtc(m_emmodclus_key);
 
       for(const auto& cl : *uniqueClusters) {
-	if (cl->e()>FLT_MIN) {
-	  if(m_useModifiedClus) {
-	    if(lctc.isValid() && emtc.isValid()) {
-	      size_t cl_idx(cl->index());
-	      // clusters at LC scale
-	      *metCoreCl += (*lctc)[cl_idx];
-	      if(m_decorateSoftTermConst) dec_softConst(*metCoreCl).push_back(ElementLink<IParticleContainer>(*static_cast<const IParticleContainer*>(lctc.cptr()),cl->index()));
-	      // clusters at EM scale
-	      *metCoreEMCl += (*emtc)[cl_idx];
-	    } else {
-	      ATH_MSG_WARNING("Invalid LC/EM modified cluster collections -- cannot add cluster to soft term!");
-	    }
-	  } else {
-	    // clusters at LC scale
-	    if (cl->type()==xAOD::Type::CaloCluster) {
+        if (cl->e()>FLT_MIN) {
+          if(m_useModifiedClus) {
+            if(lctc.isValid() && emtc.isValid()) {
+              size_t cl_idx(cl->index());
+              // clusters at LC scale
+              *metCoreCl += (*lctc)[cl_idx];
+              if(m_decorateSoftTermConst) dec_softConst(*metCoreCl).push_back(ElementLink<IParticleContainer>(*static_cast<const IParticleContainer*>(lctc.cptr()),cl->index()));
+              // clusters at EM scale
+              *metCoreEMCl += (*emtc)[cl_idx];
+            } else {
+              ATH_MSG_WARNING("Invalid LC/EM modified cluster collections -- cannot add cluster to soft term!");
+            }
+          } else {
+            // clusters at LC scale
+            if (cl->type()==xAOD::Type::CaloCluster) {
         CaloVertexedClusterBase stateClLC(*(static_cast<const CaloCluster*>(cl)),xAOD::CaloCluster::CALIBRATED);
-	      *metCoreCl += (&stateClLC);
-	    } else *metCoreCl += cl;
-	    if(m_decorateSoftTermConst) dec_softConst(*metCoreCl).push_back(ElementLink<IParticleContainer>(*static_cast<const IParticleContainer*>(cl->container()),cl->index()));
-	    // clusters at EM scale
-	    if (cl->type()==xAOD::Type::CaloCluster) {
+              *metCoreCl += (&stateClLC);
+            } else *metCoreCl += cl;
+            if(m_decorateSoftTermConst) dec_softConst(*metCoreCl).push_back(ElementLink<IParticleContainer>(*static_cast<const IParticleContainer*>(cl->container()),cl->index()));
+            // clusters at EM scale
+            if (cl->type()==xAOD::Type::CaloCluster) {
         CaloVertexedClusterBase stateClEM( *(static_cast<const CaloCluster*>(cl)),xAOD::CaloCluster::UNCALIBRATED);
         *metCoreEMCl += (&stateClEM);
-	    } else *metCoreEMCl += cl;
-	  }
-	}
+            } else *metCoreEMCl += cl;
+          }
+        }
       }
 
       if(constits.pv) {
-	for(const auto& trk : *uniqueTracks) {
-	  ATH_MSG_VERBOSE("Test core track with pt " << trk->pt());
-	  if(acceptTrack(static_cast<const TrackParticle*>(trk),constits.pv) && isGoodEoverP(static_cast<const TrackParticle*>(trk))) {
-	    ATH_MSG_VERBOSE("Add core track with pt " << trk->pt());
-	    *metCoreTrk += trk;
-	    if(m_decorateSoftTermConst) dec_softConst(*metCoreTrk).push_back(ElementLink<IParticleContainer>(*static_cast<const IParticleContainer*>(trk->container()),trk->index()));
-
-	  }
-	}
+        for(const auto& trk : *uniqueTracks) {
+          ATH_MSG_VERBOSE("Test core track with pt " << trk->pt());
+          if(acceptTrack(static_cast<const TrackParticle*>(trk),constits.pv) && isGoodEoverP(static_cast<const TrackParticle*>(trk))) {
+            ATH_MSG_VERBOSE("Add core track with pt " << trk->pt());
+            *metCoreTrk += trk;
+            if(m_decorateSoftTermConst) dec_softConst(*metCoreTrk).push_back(ElementLink<IParticleContainer>(*static_cast<const IParticleContainer*>(trk->container()),trk->index()));
+
+          }
+        }
       }
       delete uniqueClusters;
       delete uniqueTracks;
diff --git a/Reconstruction/MET/METReconstruction/Root/METSoftTermsTool.cxx b/Reconstruction/MET/METReconstruction/Root/METSoftTermsTool.cxx
index 9364356484b7ea07157d8be9fcc3457a4a93e29a..84d4eee35b2ef912bfe7ca504c21a374b29afdce 100644
--- a/Reconstruction/MET/METReconstruction/Root/METSoftTermsTool.cxx
+++ b/Reconstruction/MET/METReconstruction/Root/METSoftTermsTool.cxx
@@ -30,7 +30,6 @@
 // Calo helpers
 #include "xAODCaloEvent/CaloVertexedClusterBase.h"
 
-
 namespace met {
 
   using std::vector;
@@ -44,26 +43,18 @@ namespace met {
   using xAOD::CaloCluster;
   using xAOD::CaloClusterContainer;
   //
-  using xAOD::PFO;
-  using xAOD::PFOContainer;
-  //
   using xAOD::MissingET;
   using xAOD::MissingETComposition;
   using xAOD::MissingETComponent;
   using xAOD::MissingETComponentMap;
 
-  /////////////////////////////////////////////////////////////////// 
-  // Public methods: 
-  /////////////////////////////////////////////////////////////////// 
-
   // Constructors
   ////////////////
   METSoftTermsTool::METSoftTermsTool(const std::string& name) : 
     AsgTool(name),
     METBuilderTool(name)
   {
-    declareProperty( "InputComposition", m_inputType = "Clusters" ); // Options : Clusters (default) OR Tracks OR PFOs
-    //declareProperty( "InputPVKey",      m_pv_inputkey = "PrimaryVertices"    );
+    declareProperty( "InputComposition", m_inputType = "Clusters" ); // Options : Clusters (default) OR Tracks
     declareProperty( "VetoNegEClus",     m_cl_vetoNegE = true     );
     declareProperty( "OnlyNegEClus",     m_cl_onlyNegE = false    );
   }
@@ -81,29 +72,20 @@ namespace met {
     ATH_MSG_VERBOSE ("Initializing " << name() << "...");
 
     // use string property and convert to int?
-    if(m_inputType == "Clusters")    m_st_objtype = 0;
-    else if(m_inputType == "Tracks") m_st_objtype = 1;
-    else if(m_inputType == "PFlow") {
-      m_st_objtype = 2;
-      if( m_pfotool.retrieve().isFailure() ) {
-	ATH_MSG_FATAL("Failed to retrieve tool: " << m_pfotool->name());
-	return StatusCode::FAILURE;
-      };
-    }
+    if(m_inputType == "Clusters")    m_st_objtype = xAOD::Type::CaloCluster;
+    else if(m_inputType == "Tracks") m_st_objtype = xAOD::Type::TrackParticle;
     else {
       ATH_MSG_FATAL("Invalid input collection type " << m_inputType << " supplied!");
     }
-    // ReadHandleKey(s)
 
-    ATH_CHECK( m_pv_inputkey.initialize() );
-    if(m_st_objtype==0){
+    // ReadHandleKey(s)
+    if(m_st_objtype==xAOD::Type::CaloCluster){
       ATH_CHECK( m_caloClusterKey.assign(m_input_data_key));
       ATH_CHECK( m_caloClusterKey.initialize());
     }
-    else if(m_st_objtype==1){
+    else if(m_st_objtype==xAOD::Type::TrackParticle){
       ATH_CHECK( m_trackParticleKey.assign(m_input_data_key));
       ATH_CHECK( m_trackParticleKey.initialize());
-
     }
     return StatusCode::SUCCESS;
   }
@@ -115,54 +97,30 @@ namespace met {
     return StatusCode::SUCCESS;
   }
 
-  /////////////////////////////////////////////////////////////////// 
-  // Const methods: 
-  ///////////////////////////////////////////////////////////////////
-
-  /////////////////////////////////////////////////////////////////// 
-  // Non-const methods: 
-  /////////////////////////////////////////////////////////////////// 
-
-  /////////////////////////////////////////////////////////////////// 
-  // Protected methods: 
-  /////////////////////////////////////////////////////////////////// 
-
   // Will need to have different treatments here for clusters and tracks
   bool METSoftTermsTool::accept(const xAOD::IParticle* object) const
   {
+
+    if(object->type() != m_st_objtype){
+      ATH_MSG_WARNING("Type mismatch: Expected " << m_st_objtype << ", given " << object->type());
+      return false;
+    }
+
     // Apply cuts 
-    if ( m_st_objtype==0 ) {
+    if ( m_st_objtype == xAOD::Type::CaloCluster ) {
       ATH_MSG_VERBOSE("Check if cluster is accepted");
 
-      if(object->type()!=xAOD::Type::CaloCluster) {
-	ATH_MSG_WARNING("Expected CaloCluster, given " << object->type());
-	return false;
-      }
       const xAOD::CaloCluster* clus = static_cast<const xAOD::CaloCluster*>(object);
       return (clus) ? accept(clus) : false;
 
     } // end of if using clusters 
-    else if (  m_st_objtype==1 ) {
+    else if (  m_st_objtype == xAOD::Type::TrackParticle ) {
       ATH_MSG_VERBOSE("Check if track is accepted");
 
-      if(object->type()!=xAOD::Type::TrackParticle) {
-	ATH_MSG_WARNING("Expected TrackParticle, given " << object->type());
-	return false;
-      }
       const xAOD::TrackParticle* track = static_cast<const xAOD::TrackParticle*>(object);
       return (track) ? accept(track) : false;
 
     } // end of if using tracks
-    else if (  m_st_objtype==2 ) {
-      ATH_MSG_VERBOSE("Check if PFO is accepted");
-
-      if(object->type()!=xAOD::Type::ParticleFlow) {
-	ATH_MSG_WARNING("Expected PFlow Object, given " << object->type());
-	return false;
-      }
-
-      ATH_MSG_ERROR("Should use PFO accept() overload with PV check.");
-    } // end of if using PFOs
     
     return false; // Default 
   }
@@ -192,33 +150,22 @@ namespace met {
     return true;
   }
 
-  bool METSoftTermsTool::accept(const xAOD::PFO* pfo, const xAOD::Vertex* pv) const
-  {
-    if(!pfo->isCharged()) return true;
-    if(fabs(pfo->track(0)->z0() - pv->z())>2) return false;
-    return true;
-  }
-
   bool METSoftTermsTool::resolveOverlap(const xAOD::IParticle* /*object*/,
-				        xAOD::MissingETComponentMap* metMap,
-				        std::vector<const xAOD::IParticle*>& acceptedSignals,
-				        MissingETBase::Types::weight_t& /*objWeight*/) const
+                                        xAOD::MissingETComponentMap* metMap,
+                                        std::vector<const xAOD::IParticle*>& acceptedSignals,
+                                        MissingETBase::Types::weight_t& /*objWeight*/) const
   {
 
     // Check/Resolve overlap
     bool objsused = false;
-    if( m_st_objtype==0 ) {
+    if( m_st_objtype == xAOD::Type::CaloCluster ) {
       ATH_MSG_DEBUG("Check for used clusters");
       objsused = metMap->checkUsage(acceptedSignals,MissingETBase::UsageHandler::OnlyCluster);
     }
-    else if( m_st_objtype==1 ) { 
+    else if( m_st_objtype == xAOD::Type::TrackParticle ) { 
       ATH_MSG_DEBUG("Check for used tracks");
       objsused = metMap->checkUsage(acceptedSignals,MissingETBase::UsageHandler::OnlyTrack);
     }
-    else if( m_st_objtype==2 ) { 
-      ATH_MSG_DEBUG("Check for used PFOs: DUMMY");
-      //      objsused = metMap->checkUsage(acceptedSignals,MissingETBase::UsageHandler::OnlyTrack);
-    }
     if(!objsused) {
       ATH_MSG_DEBUG("No objects used.");
     }
@@ -230,7 +177,7 @@ namespace met {
 
   // overload for convenience
   bool METSoftTermsTool::resolveOverlap(xAOD::MissingETComponentMap* metMap,
-				        std::vector<const xAOD::IParticle*>& acceptedSignals) const
+                                        std::vector<const xAOD::IParticle*>& acceptedSignals) const
   {
     const xAOD::IParticle* dummyObject = 0;                  // Just a dummy object
     MissingETBase::Types::weight_t dummyObjWeight(1.,1.,1.); // Currently use a default value
@@ -242,11 +189,8 @@ namespace met {
 
     ATH_MSG_DEBUG ("In execute: " << name() << "...");
 
-    // First retrieve the necessary container
-    // Currently rely on only one: either CaloClusterContainer or TrackParticleContainer
-    const PFOContainer* pfoCont = 0;
-     vector<const IParticle*> signalList;
-    if( m_st_objtype == 0 ) {
+    vector<const IParticle*> signalList;
+    if( m_st_objtype == xAOD::Type::CaloCluster ) {
       // Retrieve the calo container
       SG::ReadHandle<xAOD::CaloClusterContainer> caloClusCont(m_caloClusterKey);
       if (!caloClusCont.isValid()) {
@@ -279,7 +223,7 @@ namespace met {
       ATH_MSG_DEBUG("Selected " << signalList.size() << " topoclusters for soft MET");
 
     } // end if Clusters
-    else if( m_st_objtype == 1 ) {
+    else if( m_st_objtype == xAOD::Type::TrackParticle ) {
 
       // Retrieve the track container
       SG::ReadHandle<xAOD::TrackParticleContainer> trackParCont(m_trackParticleKey);
@@ -293,8 +237,8 @@ namespace met {
 
       MissingETComponentMap::iterator iter = MissingETComposition::find(metMap,metTerm);
       if(iter==metMap->end()) {
-	ATH_MSG_WARNING("Could not find current METComponent in MET Map!");
-	return StatusCode::SUCCESS;
+        ATH_MSG_WARNING("Could not find current METComponent in MET Map!");
+        return StatusCode::SUCCESS;
       }
       MissingETComponent* newComp = *iter;
       newComp->setStatusWord(MissingETBase::Status::contributedSoftTerm());
@@ -303,62 +247,14 @@ namespace met {
       for( TrackParticleContainer::const_iterator iTrk=trackParCont->begin(); iTrk!=trackParCont->end(); ++iTrk ) {
         // Check if track satisfies the requirements
         if( this->accept(*iTrk) ) {
-	  // Add the selected track particles to the list
-	  signalList.push_back(*iTrk);
-	}
+          // Add the selected track particles to the list
+          signalList.push_back(*iTrk);
+        }
       } // end loop over tracks
 
       ATH_MSG_DEBUG("Selected " << signalList.size() << " tracks for soft MET");
 
     }  // end if Tracks
-    else if( m_st_objtype == 2 ) {
-      // Retrieve the pfo container
-      pfoCont = m_pfotool->retrievePFO(CP::EM, CP::all);
-      if(!pfoCont) {
-        ATH_MSG_WARNING("Unable to retrieve input pfo container");
-        return StatusCode::SUCCESS;
-      }
-      SG::ReadHandle<xAOD::VertexContainer> pv_cont(m_pv_inputkey);
-      if (!pv_cont.isValid()) {
-        ATH_MSG_WARNING("Unable to retrieve input primary vertex container");
-        return StatusCode::SUCCESS;
-      }
-      const xAOD::Vertex* pv(0);
-      for(const auto& vx : *pv_cont) {
-	if(vx->vertexType()==xAOD::VxType::PriVtx) {pv = vx; break;}
-      }
-      if(pv) {
-	ATH_MSG_DEBUG("Main primary vertex has z = " << pv->z());
-      } else{
-	ATH_MSG_WARNING("Event has no primary vertices");
-	return StatusCode::SUCCESS;
-      }
-
-      signalList.reserve(pfoCont->size());
-
-      MissingETBase::Types::bitmask_t source = MissingETBase::Source::SoftEvent; // need to add PFlow source tag
-      metTerm->setSource(source);
-
-      MissingETComponentMap::iterator iter = MissingETComposition::find(metMap,metTerm);
-      if(iter==metMap->end()) {
-	ATH_MSG_WARNING("Could not find current METComponent in MET Map!");
-	return StatusCode::SUCCESS;
-      }
-      MissingETComponent* newComp = *iter;
-      newComp->setStatusWord(MissingETBase::Status::contributedSoftTerm());
-
-      // Loop over all pfos
-      for( PFOContainer::const_iterator iPfo=pfoCont->begin(); iPfo!=pfoCont->end(); ++iPfo ) {
-        // Check if pfo satisfies the requirements
-        if( this->accept(*iPfo,pv) ) {
-	  // Add the selected pfo particles to the list
-	  signalList.push_back(*iPfo);
-	}
-      } // end loop over pfos
-
-      ATH_MSG_DEBUG("Selected " << signalList.size() << " pfos for soft MET");
-
-    }  // end if PFOs
 
     // Resolve overlap: signalList is accessed by reference and updated w/ content that is not
     // associated to any object. True if signalList size 0, i.e. nothing to add to MET
@@ -368,46 +264,12 @@ namespace met {
     vector<const IParticle*> dummyList;
     MissingETBase::Types::weight_t unitWeight(1.,1.,1.);
 
-    if(m_st_objtype == 2) {
-      for( vector<const IParticle*>::const_iterator iPart=signalList.begin();
-	   iPart!=signalList.end(); ++iPart) {
-	const PFO* pfo = dynamic_cast<const PFO*>(*iPart);
-        if(pfo) {
-	    metTerm->add(pfo->ptEM()*cos(pfo->phiEM()),
-		         pfo->ptEM()*sin(pfo->phiEM()),
-		         pfo->ptEM());
-	  } else {
-	  // In principle for the charged PFOs we should perhaps add the weights
-	  // but this shouldn't happen if we don't have a jet. 
-	  if(!pfo->isCharged()) {
-	    metTerm->add(pfo->pt()*cos(pfo->phi()),
-		         pfo->pt()*sin(pfo->phi()),
-		         pfo->pt());
-	  }
-
-	  MissingETComposition::insert(metMap,metTerm,pfo,dummyList,unitWeight);
-        }
-      }
-    } else {
-      for( vector<const IParticle*>::const_iterator iPart=signalList.begin();
-           iPart!=signalList.end(); ++iPart) {
-        this->addToMET(*iPart,dummyList,metTerm,metMap,unitWeight);
-      }
-    }
+    for(const IParticle* part : signalList) this->addToMET(part,dummyList,metTerm,metMap,unitWeight);
 
     ATH_MSG_DEBUG( "Map contains " << (*MissingETComposition::find(metMap,metTerm))->objects().size() << " soft signals" );
 
-    if(pfoCont) delete pfoCont;
     return StatusCode::SUCCESS;
   }
 
-  /////////////////////////////////////////////////////////////////// 
-  // Const methods: 
-  ///////////////////////////////////////////////////////////////////
-
-  /////////////////////////////////////////////////////////////////// 
-  // Non-const methods: 
-  /////////////////////////////////////////////////////////////////// 
-
 }
 
diff --git a/Reconstruction/MET/METReconstruction/Root/METTauAssociator.cxx b/Reconstruction/MET/METReconstruction/Root/METTauAssociator.cxx
index fa51d52c50cd55cf0f9da668554b697640e9a098..cfafb090b375c531bd022679f1a6648b14150860 100644
--- a/Reconstruction/MET/METReconstruction/Root/METTauAssociator.cxx
+++ b/Reconstruction/MET/METReconstruction/Root/METTauAssociator.cxx
@@ -103,23 +103,23 @@ namespace met {
   //*********************************************************************************************************
   // Get tau constituents
   StatusCode METTauAssociator::extractTopoClusters(const xAOD::IParticle *obj,
-						   std::vector<const xAOD::IParticle*>& tclist,
-				        	   const met::METAssociator::ConstitHolder& /*tcCont*/) const
+                                                   std::vector<const xAOD::IParticle*>& tclist,
+                                                   const met::METAssociator::ConstitHolder& /*tcCont*/) const
   {
     const TauJet* tau = static_cast<const TauJet*>(obj);
     for( ElementLink< xAOD::IParticleContainer > cluster_link : tau->clusterLinks() ){
       const xAOD::IParticle* ipart = *cluster_link;
       if (ipart->type() == xAOD::Type::ParticleFlow){
-	// If using PFO, get cluster
+        // If using PFO, get cluster
         const xAOD::PFO *pfo = static_cast<const xAOD::PFO*>(ipart);
-	if (pfo->isCharged()){ continue; }
-	else {
-	  ipart = pfo->cluster(0);
-	}
+        if (pfo->isCharged()){ continue; }
+        else {
+          ipart = pfo->cluster(0);
+        }
       }
       if(ipart->type() != xAOD::Type::CaloCluster) {
-    	ATH_MSG_WARNING("Unexpected jet constituent type " << ipart->type() << " received! Skip.");
-	continue;
+            ATH_MSG_WARNING("Unexpected jet constituent type " << ipart->type() << " received! Skip.");
+        continue;
       }      
       // Link set in Reconstruction/tauRecTools/src/TauAxisSetter.cxx
       // Internal defaults are m_clusterCone = 0.2, m_doCellCorrection = false, m_doAxisCorrection = True
@@ -132,8 +132,8 @@ namespace met {
 
 
   StatusCode METTauAssociator::extractTracks(const xAOD::IParticle *obj,
-					     std::vector<const xAOD::IParticle*>& constlist,
-					     const met::METAssociator::ConstitHolder& constits) const
+                                             std::vector<const xAOD::IParticle*>& constlist,
+                                             const met::METAssociator::ConstitHolder& constits) const
   {
     const TauJet* tau = static_cast<const TauJet*>(obj);
     for( const xAOD::TauTrack* tauTrk : tau->tracks(xAOD::TauJetParameters::coreTrack) ){//all tracks dR<0.2 regardless of quality
@@ -149,9 +149,9 @@ namespace met {
   //*********************************************************************************************************
   // Get tau constituents
   StatusCode METTauAssociator::extractPFO(const xAOD::IParticle* obj,
-					  std::vector<const xAOD::IParticle*>& pfolist,
-					  const met::METAssociator::ConstitHolder& constits,
-					  std::map<const IParticle*,MissingETBase::Types::constvec_t> &/*momenta*/) const
+                                          std::vector<const xAOD::IParticle*>& pfolist,
+                                          const met::METAssociator::ConstitHolder& constits,
+                                          std::map<const IParticle*,MissingETBase::Types::constvec_t> &/*momenta*/) const
   {
     const TauJet* tau = static_cast<const TauJet*>(obj);
     const Jet* seedjet = *tau->jetLink();
@@ -159,26 +159,62 @@ namespace met {
     for(const auto& pfo : *constits.pfoCont) {
       bool match = false;
       if (!pfo->isCharged()) {
-	if(xAOD::P4Helpers::isInDeltaR(*seedjet,*pfo,0.2,m_useRapidity) && pfo->eEM()>0) {
-	  ATH_MSG_VERBOSE("Found nPFO with dR " << seedjet->p4().DeltaR(pfo->p4EM()));
-	  match = true;
-	}
+        if(xAOD::P4Helpers::isInDeltaR(*seedjet,*pfo,0.2,m_useRapidity) && pfo->eEM()>0) {
+          ATH_MSG_VERBOSE("Found nPFO with dR " << seedjet->p4().DeltaR(pfo->p4EM()));
+          match = true;
+        }
       }
       else {
         const TrackParticle* pfotrk = pfo->track(0);
         for( const xAOD::TauTrack* ttrk : tau->tracks(xAOD::TauJetParameters::coreTrack) ){//all tracks <0.2, no quality
           const TrackParticle* tautrk = ttrk->track();
           if(tautrk==pfotrk) {
-	    ATH_MSG_VERBOSE("Found cPFO with dR " << seedjet->p4().DeltaR(ttrk->p4()));
-	    // We set a small -ve pt for cPFOs that were rejected
-	    // by the ChargedHadronSubtractionTool
-	    const static SG::AuxElement::ConstAccessor<char> PVMatchedAcc("matchedToPV");	
-	    if(PVMatchedAcc(*pfo) && ( !m_cleanChargedPFO || isGoodEoverP(pfotrk) )) match = true;
+            ATH_MSG_VERBOSE("Found cPFO with dR " << seedjet->p4().DeltaR(ttrk->p4()));
+            // We set a small -ve pt for cPFOs that were rejected
+            // by the ChargedHadronSubtractionTool
+            const static SG::AuxElement::ConstAccessor<char> PVMatchedAcc("matchedToPV");        
+            if(PVMatchedAcc(*pfo) && ( !m_cleanChargedPFO || isGoodEoverP(pfotrk) )) match = true;
+          }
+        }
+      }
+      if(match) {
+        pfolist.push_back(pfo);
+      }
+    }
+    return StatusCode::SUCCESS;
+  }
+
+  StatusCode METTauAssociator::extractFE(const xAOD::IParticle* obj,
+                                         std::vector<const xAOD::IParticle*>& felist,
+                                         const met::METAssociator::ConstitHolder& constits,
+                                         std::map<const IParticle*,MissingETBase::Types::constvec_t> &/*momenta*/) const
+  {
+    const TauJet* tau = static_cast<const TauJet*>(obj);
+    const Jet* seedjet = *tau->jetLink();
+    TLorentzVector momentum;
+    for(const xAOD::FlowElement* pfo : *constits.feCont) {
+      bool match = false;
+      if (!pfo->isCharged()) {
+        if(xAOD::P4Helpers::isInDeltaR(*seedjet,*pfo,0.2,m_useRapidity) && pfo->e()>0) {
+          ATH_MSG_VERBOSE("Found nPFO with dR " << seedjet->p4().DeltaR(pfo->p4()));
+          match = true;
+        }
+      }
+      else {
+        const TrackParticle* pfotrk = static_cast<const xAOD::TrackParticle*>(pfo->chargedObject(0));
+        for( const xAOD::TauTrack* ttrk : tau->tracks(xAOD::TauJetParameters::coreTrack) ){//all tracks <0.2, no quality
+          const TrackParticle* tautrk = ttrk->track();
+          if(tautrk==pfotrk) {
+            ATH_MSG_VERBOSE("Found cPFO with dR " << seedjet->p4().DeltaR(ttrk->p4()));
+            // We set a small -ve pt for cPFOs that were rejected
+            // by the ChargedHadronSubtractionTool
+            const static SG::AuxElement::ConstAccessor<char> PVMatchedAcc("matchedToPV");        
+            if(PVMatchedAcc(*pfo) && ( !m_cleanChargedPFO || isGoodEoverP(pfotrk) )) match = true;
           }
         }
       }
       if(match) {
-	pfolist.push_back(pfo);
+        felist.push_back(pfo);
       }
     }
     return StatusCode::SUCCESS;
diff --git a/Reconstruction/MET/METReconstruction/python/LegacyRunII/METAssocConfig.py b/Reconstruction/MET/METReconstruction/python/LegacyRunII/METAssocConfig.py
index 5dc91c5fb16a796938e7f6f73b0b7ab36287e247..6f2972858f92f1534b1ce2b0f9911e4a3d50f75d 100644
--- a/Reconstruction/MET/METReconstruction/python/LegacyRunII/METAssocConfig.py
+++ b/Reconstruction/MET/METReconstruction/python/LegacyRunII/METAssocConfig.py
@@ -15,11 +15,13 @@ defaultInputKey = {
    'LCJet'     :'AntiKt4LCTopoJets',
    'EMJet'     :'AntiKt4EMTopoJets',
    'PFlowJet'  :'AntiKt4EMPFlowJets',
+   'PFlowFEJet':'AntiKt4EMPFlowFEJets',
    'Muon'      :'Muons',
    'Soft'      :'',
    'Clusters'  :'CaloCalTopoClusters',
    'Tracks'    :'InDetTrackParticles',
    'PFlowObj'  :'CHSParticleFlowObjects',
+   'PFlowObjFE':'CHSFlowElements',
    'PrimVxColl':'PrimaryVertices',
    'Truth'     :'TruthEvents',
    }
@@ -63,6 +65,8 @@ def getAssociator(config,suffix,doPFlow=False,
         tool = CfgMgr.met__METJetAssocTool('MET_EMJetAssocTool_'+suffix)
     if config.objType == 'PFlowJet':
         tool = CfgMgr.met__METJetAssocTool('MET_PFlowJetAssocTool_'+suffix)
+    if config.objType == 'PFlowFEJet':
+        tool = CfgMgr.met__METJetAssocTool('MET_PFlowFEJetAssocTool_'+suffix)
     if config.objType == 'Muon':
         tool = CfgMgr.met__METMuonAssociator('MET_MuonAssociator_'+suffix)
     if config.objType == 'Soft':
@@ -74,9 +78,14 @@ def getAssociator(config,suffix,doPFlow=False,
     if config.objType == 'Truth':
         tool = CfgMgr.met__METTruthAssociator('MET_TruthAssociator_'+suffix)
         tool.RecoJetKey = config.inputKey
+
+    from METReconstruction.METRecoFlags import metFlags
     if doPFlow:
         tool.PFlow = True
-        tool.PFlowColl = modConstKey if modConstKey!="" else defaultInputKey["PFlowObj"]
+        if metFlags.UseFlowElements() :
+            tool.FlowElementCollection = modConstKey if modConstKey!="" else defaultInputKey["PFlowObjFE"]
+        else:
+            tool.PFlowColl = modConstKey if modConstKey!="" else defaultInputKey["PFlowObj"]
     else:
         tool.UseModifiedClus = doModClus
     # set input/output key names
@@ -146,7 +155,11 @@ class METAssocConfig:
         modConstKey_tmp = modConstKey
         modClusColls_tmp = modClusColls
         if doPFlow:
-            if modConstKey_tmp == "": modConstKey_tmp = "CHSParticleFlowObjects"
+            from METReconstruction.METRecoFlags import metFlags
+            if metFlags.UseFlowElements():
+                if modConstKey_tmp == "": modConstKey_tmp = "CHSFlowElements"
+            else:
+                if modConstKey_tmp == "": modConstKey_tmp = "CHSParticleFlowObjects"
         else:
             if modConstKey_tmp == "": modConstKey_tmp = "OriginCorr"
             if modClusColls_tmp == {}: modClusColls_tmp = {'LCOriginCorrClusters':'LCOriginTopoClusters',
diff --git a/Reconstruction/MET/METReconstruction/python/LegacyRunII/METAssocConfig_readAOD.py b/Reconstruction/MET/METReconstruction/python/LegacyRunII/METAssocConfig_readAOD.py
index 0257b283e2ee31f1c069067be3046c8872dc3ca0..61b3897355cc0e8d590bad07fb7b25c82bb0e378 100644
--- a/Reconstruction/MET/METReconstruction/python/LegacyRunII/METAssocConfig_readAOD.py
+++ b/Reconstruction/MET/METReconstruction/python/LegacyRunII/METAssocConfig_readAOD.py
@@ -21,6 +21,7 @@ defaultInputKey = {
    'LCJet'     :'AntiKt4LCTopoJets',
    'EMJet'     :'AntiKt4EMTopoJets',
    'PFlowJet'  :'AntiKt4EMPFlowJets',
+   'PFlowFEJet':'AntiKt4EMPFlowFEJets',
    'Muon'      :'Muons',
    'Soft'      :'',
    'ClusColl'  :'CaloCalTopoClusters',
@@ -82,6 +83,8 @@ def getAssociator(config,suffix,doPFlow=False,
         tool = CfgMgr.met__METJetAssocTool('MET_EMJetAssocTool_'+suffix)
     if config.objType == 'PFlowJet':
         tool = CfgMgr.met__METJetAssocTool('MET_PFlowJetAssocTool_'+suffix)
+    if config.objType == 'PFlowFEJet':
+        tool = CfgMgr.met__METJetAssocTool('MET_PFlowFEJetAssocTool_'+suffix)
     if config.objType == 'Muon':
         tool = CfgMgr.met__METMuonAssociator('MET_MuonAssociator_'+suffix,DoClusterMatch=False)
     if config.objType == 'Soft':
@@ -94,9 +97,6 @@ def getAssociator(config,suffix,doPFlow=False,
         ToolSvc == tool
         tool.RecoJetKey = config.inputKey
     if doPFlow:
-        pfotool = CfgMgr.CP__RetrievePFOTool('MET_PFOTool_'+suffix)
-        ToolSvc += pfotool
-        tool.PFOTool = pfotool
         tool.PFlow = True
     else:
         tool.UseModifiedClus = doOriginCorrClus
diff --git a/Reconstruction/MET/METReconstruction/python/LegacyRunII/METConfig_Associator.py b/Reconstruction/MET/METReconstruction/python/LegacyRunII/METConfig_Associator.py
index 600e5e9b69102bbb6298a3d0fe4fa5c7403df9cb..de6c00f8784d0b986e836194e497096bee7197b4 100644
--- a/Reconstruction/MET/METReconstruction/python/LegacyRunII/METConfig_Associator.py
+++ b/Reconstruction/MET/METReconstruction/python/LegacyRunII/METConfig_Associator.py
@@ -70,3 +70,23 @@ if metFlags.DoPFlow() and metFlags.UseTracks():
 
     metFlags.METAssocConfigs()[cfg_akt4pf.suffix] = cfg_akt4pf
     metFlags.METAssocOutputList().append(cfg_akt4pf.suffix)
+
+
+############################################################################
+# PFlow (FlowElement)
+if metFlags.DoPFlow() and metFlags.UseTracks() and metFlags.UseFlowElements():
+    JetType = 'PFlowFEJet'
+    
+    associators = [AssocConfig(JetType),
+                   AssocConfig('Muon'),
+                   AssocConfig('Ele'),
+                   AssocConfig('Gamma'),
+                   AssocConfig('Tau'),
+                   AssocConfig('Soft')]
+    cfg_akt4pffe = METAssocConfig('AntiKt4EMPFlowFE',
+                                  associators,
+                                  doPFlow=True
+                                  )
+
+    metFlags.METAssocConfigs()[cfg_akt4pffe.suffix] = cfg_akt4pffe
+    metFlags.METAssocOutputList().append(cfg_akt4pffe.suffix)
\ No newline at end of file
diff --git a/Reconstruction/MET/METReconstruction/python/LegacyRunII/METRecoConfig.py b/Reconstruction/MET/METReconstruction/python/LegacyRunII/METRecoConfig.py
index 01a0c21dc61f775bb5af306a809f5e43e4c3079d..a689ef77774f9aac7a59c829c99a9aba7eb11f7f 100644
--- a/Reconstruction/MET/METReconstruction/python/LegacyRunII/METRecoConfig.py
+++ b/Reconstruction/MET/METReconstruction/python/LegacyRunII/METRecoConfig.py
@@ -26,7 +26,6 @@ defaultInputKey = {
    'Muon'     :'Muons',
    'SoftTrk'  :'InDetTrackParticles',
    'SoftClus' :'CaloCalTopoClusters',
-   'SoftPFlow':'JetETMissNeutralParticleFlowObjects',
    'PrimaryVx':'PrimaryVertices',
    'Truth'    :'TruthEvents',
    'Calo'     :'AllCalo',
@@ -42,7 +41,6 @@ defaultOutputKey = {
     'Muon'     :'Muons',
     'SoftTrk'  :'SoftTrk',
     'SoftClus' :'SoftClus',
-    'SoftPFlow':'SoftPFlow',
     'Total'    :'Final',
     'Truth'    :'Truth',
     'Calo'     :'Calo'
@@ -86,11 +84,6 @@ def getBuilder(config,suffix,doTracks,doCells,doTriggerMET,doOriginCorrClus):
     if config.objType.endswith('SoftClus'):
         tool = CfgMgr.met__METSoftTermsTool('MET_SoftClusTool_'+suffix)
         tool.InputComposition = 'Clusters'
-    if config.objType == 'SoftPFlow':
-        tool = CfgMgr.met__METSoftTermsTool('MET_SoftPFlowTool_'+suffix)
-        tool.InputComposition = 'PFlow'
-        pfotool = CfgMgr.CP__RetrievePFOTool('MET_PFOTool_'+suffix)
-        tool.PFOTool = pfotool
     if suffix == 'Truth':
         tool = CfgMgr.met__METTruthTool('MET_TruthTool_'+config.objType)
         tool.InputComposition = config.objType
diff --git a/Reconstruction/MET/METReconstruction/python/LegacyRunII/METRecoFlags.py b/Reconstruction/MET/METReconstruction/python/LegacyRunII/METRecoFlags.py
index 462fb16051c5e1daa444e94edd93d0634e07cf1e..99b0482d4042531a1c7f1e61341f2d525ecb9e5d 100644
--- a/Reconstruction/MET/METReconstruction/python/LegacyRunII/METRecoFlags.py
+++ b/Reconstruction/MET/METReconstruction/python/LegacyRunII/METRecoFlags.py
@@ -16,6 +16,11 @@ class DoPFlow(JobProperty):
     allowedTypes = ['bool'] 
     StoredValue  = True
 
+class UseFlowElements(JobProperty):
+    statusOn = True
+    allowedTypes = ['bool'] 
+    StoredValue  = False
+
 class UseTracks(JobProperty):
     statusOn = True
     allowedTypes = ['bool']
@@ -65,6 +70,7 @@ jobproperties.add_Container(METRecoFlags)
 
 jobproperties.METRecoFlags.add_JobProperty(DoRegions)
 jobproperties.METRecoFlags.add_JobProperty(DoPFlow)
+jobproperties.METRecoFlags.add_JobProperty(UseFlowElements)
 jobproperties.METRecoFlags.add_JobProperty(UseTracks)
 jobproperties.METRecoFlags.add_JobProperty(DecorateSoftConst)
 jobproperties.METRecoFlags.add_JobProperty(AllowOverwrite)
diff --git a/Reconstruction/PFlow/PFlowUtils/PFlowUtils/IRetrievePFOTool.h b/Reconstruction/PFlow/PFlowUtils/PFlowUtils/IRetrievePFOTool.h
deleted file mode 100644
index 1cc02f589ea0f59bfa5f84f7b67b3b914d05d51c..0000000000000000000000000000000000000000
--- a/Reconstruction/PFlow/PFlowUtils/PFlowUtils/IRetrievePFOTool.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#ifndef IRETRIEVEPFOTOOL_H
-#define IRETRIEVEPFOTOOL_H
-
-/** Simple class to retrieve PFO for jets and met in the two possible configurations we provide */
-
-#include "AsgTools/IAsgTool.h"
-
-#include "xAODPFlow/PFOContainer.h"
-#include "PFlowUtils/PFODefs.h"
-
-namespace CP {
-
-  class IRetrievePFOTool : public virtual asg::IAsgTool {
-
-    /** Declare the interface that the class provides */
-    ASG_TOOL_INTERFACE( CP::IRetrievePFOTool )
-      
-    public:
-
-    /** Fills theContainer with PFO from EM or LC mode in eflowRec */
-    virtual const xAOD::PFOContainer* retrievePFO(const CP::PFO_JetMETConfig_inputScale& theScale) const = 0;
-    
-     /** Fills theContainer with PFO from EM or LC mode in eflowRec - additionally allows to choose one of charged, neutral or all PFO configurations */
-    virtual const xAOD::PFOContainer* retrievePFO(const CP::PFO_JetMETConfig_inputScale& theScale, const CP::PFO_JetMETConfig_charge& theCharge) const = 0;
-
-  };
-
-}
-#endif
diff --git a/Reconstruction/PFlow/PFlowUtils/PFlowUtils/RetrievePFOTool.h b/Reconstruction/PFlow/PFlowUtils/PFlowUtils/RetrievePFOTool.h
deleted file mode 100644
index 4c5cc906609783748713b01832c595897e523be9..0000000000000000000000000000000000000000
--- a/Reconstruction/PFlow/PFlowUtils/PFlowUtils/RetrievePFOTool.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#ifndef RETRIEVEPFOTOOL_H
-#define RETRIEVEPFOTOOL_H
-
-/** Simple class to retrieve PFO for jets and met in the two possible configurations we provide */
-
-#include "AsgTools/AsgTool.h"
-
-#include "PFlowUtils/IRetrievePFOTool.h"
-
-#include <string>
-
-namespace CP {
-
-  class RetrievePFOTool : public virtual IRetrievePFOTool, public asg::AsgTool {
-
-    /** Athena constructor */
-    ASG_TOOL_CLASS( RetrievePFOTool, IRetrievePFOTool )
-
-  public:
-    /** Rootcore constructor */
-    RetrievePFOTool(const std::string& name);
-    
-    /** Fills theContainer with PFO from EM or LC mode in eflowRec - the client owns theContainer */
-    virtual const xAOD::PFOContainer* retrievePFO(const CP::PFO_JetMETConfig_inputScale& theScale) const override;
-
-    /** Fills theContainer with PFO from EM or LC mode in eflowRec - additionally allows to choose one of charged, neutral or all PFO configurations - the client owns theContainer */
-    virtual const xAOD::PFOContainer* retrievePFO(const CP::PFO_JetMETConfig_inputScale& theScale, const CP::PFO_JetMETConfig_charge& theCharge) const override; 
-
-  private:
-
-    /** Fills theContainer with neutral PFO from EM or LC mode in eflowRec */
-    StatusCode retrieve_neutralPFO(const CP::PFO_JetMETConfig_inputScale& theScale, xAOD::PFOContainer* theContainer) const;
-
-    /** This retrieves a PFO container with theName and adds the PFO* to newContainer */
-    StatusCode fillPFOContainer( xAOD::PFOContainer* newContainer, const std::string& theName) const;
-
-    std::string m_inCharged;
-    std::string m_inNeutral;
-
-  };
-
-}
-#endif
diff --git a/Reconstruction/PFlow/PFlowUtils/Root/RetrievePFOTool.cxx b/Reconstruction/PFlow/PFlowUtils/Root/RetrievePFOTool.cxx
deleted file mode 100644
index a5ce20b1bf6ea9abf2082deee809a60a66efabed..0000000000000000000000000000000000000000
--- a/Reconstruction/PFlow/PFlowUtils/Root/RetrievePFOTool.cxx
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#include "PFlowUtils/RetrievePFOTool.h"
-
-namespace CP {
-
-  RetrievePFOTool::RetrievePFOTool(const std::string& name) : asg::AsgTool( name ) {     
-    declareProperty("ChargedInputContainer", m_inCharged="");
-    declareProperty("NeutralInputContainer", m_inNeutral="");
-}
-
-  const xAOD::PFOContainer* RetrievePFOTool::retrievePFO(const CP::PFO_JetMETConfig_inputScale& theScale) const {
-    return this->retrievePFO(theScale, CP::all);
-  }
-
-  const xAOD::PFOContainer* RetrievePFOTool::retrievePFO(const CP::PFO_JetMETConfig_inputScale& theScale, const CP::PFO_JetMETConfig_charge& theCharge) const {
-    
-    //This is a new VIEW container that we will fill with the clients chosen PFO - the client owns this object, and should delete it
-    xAOD::PFOContainer* newContainer = new xAOD::PFOContainer(SG::VIEW_ELEMENTS);
-
-    StatusCode sc;
-    //Then we retrieve the charged PFO - this is the same for both EM and LC modes
-    if (CP::charged == theCharge || CP::all == theCharge) {
-      if(m_inCharged!="") sc = this->fillPFOContainer(newContainer, m_inCharged);
-      else sc = this->fillPFOContainer(newContainer, "JetETMissChargedParticleFlowObjects");
-      if (sc.isFailure()) ATH_MSG_WARNING( " could not fill charged pfo container ");
-    }
-
-    //Then we retrieve the neutral PFO - thu is different in the EM and LC modes
-    if (CP::neutral == theCharge || CP::all == theCharge) {
-      sc = this->retrieve_neutralPFO(theScale,newContainer);
-      if (sc.isFailure()) ATH_MSG_WARNING(" could not fill neutral pfo container ");
-    }
-
-    //The client is only allowed a const pointer, to prevent them modifying the PFO
-    const xAOD::PFOContainer* newPFO = const_cast<xAOD::PFOContainer*>(newContainer);
-
-    return newPFO;
-
-  }
-
-  StatusCode RetrievePFOTool::retrieve_neutralPFO(const CP::PFO_JetMETConfig_inputScale& theScale, xAOD::PFOContainer* theContainer) const {
-
-    if (CP::EM == theScale) {
-      //Get neutral PFO for EM mode - stored in one container
-      if(m_inNeutral!="") ATH_CHECK(this->fillPFOContainer(theContainer, m_inNeutral));
-      else ATH_CHECK(this->fillPFOContainer(theContainer, "JetETMissNeutralParticleFlowObjects"));
-    }// EM mode
-    else if (CP::LC == theScale){
-      //Get neutral PFO for LC mode - stored in two containers
-      if(m_inNeutral!="")
-        ATH_CHECK(this->fillPFOContainer(theContainer, m_inNeutral));
-      else{
-        //Get neutral PFO for LC mode - stored in two containers
-        ATH_CHECK(this->fillPFOContainer(theContainer, "JetETMissLCNeutralParticleFlowObjects"));
-        ATH_CHECK(this->fillPFOContainer(theContainer, "JetETMissLCNonModifiedNeutralParticleFlowObjects"));
-      }
-    }//LC mode
-
-    return StatusCode::SUCCESS;
-
-  }
-
-
-  StatusCode RetrievePFOTool::fillPFOContainer( xAOD::PFOContainer* newContainer, const std::string& theName) const {
-
-    const xAOD::PFOContainer* thePFO = NULL;
-    ATH_CHECK( evtStore()->retrieve(thePFO, theName));
-      
-    xAOD::PFOContainer::const_iterator firstPFO = thePFO->begin();
-    xAOD::PFOContainer::const_iterator lastPFO = thePFO->end();
-
-    for (; firstPFO != lastPFO; ++firstPFO) {
-      xAOD::PFO* thePFO = const_cast<xAOD::PFO*>(*firstPFO);
-      newContainer->push_back(thePFO);
-    }//PFO loop
-
-    return StatusCode::SUCCESS;
-  }
-
-}
diff --git a/Reconstruction/PFlow/PFlowUtils/python/DefaultTools.py b/Reconstruction/PFlow/PFlowUtils/python/DefaultTools.py
index ea54bb2f515ef0b378b7632d58f039592c7e6203..f7d399db7e9051ffb77fe83f36d55ed4256df436 100644
--- a/Reconstruction/PFlow/PFlowUtils/python/DefaultTools.py
+++ b/Reconstruction/PFlow/PFlowUtils/python/DefaultTools.py
@@ -1,77 +1,11 @@
 # Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 
-
-from PFlowUtils.PFlowUtilsConf import CP__RetrievePFOTool as RetrievePFOTool
 from PFlowUtils.PFlowUtilsConf import CP__WeightPFOTool as WeightPFOTool
 
 def declareDefaultTools():
 
-  from JetRecConfig.JetRecFlags import jetFlags
   from JetRecConfig.JetRecStandardToolManager import jtm
-  from JetRecTools.JetRecToolsConf import PFlowPseudoJetGetter
-  from eflowRec.eflowRecFlags import jobproperties
-
-  # Retriever for pflow objects.
-  jtm += RetrievePFOTool("pflowretriever")
 
   # Weight tool for charged pflow objects.
   jtm += WeightPFOTool("pflowweighter")
   jtm += WeightPFOTool("pflowweighter_LC",NeutralPFOScale="LC")
-
-  useVertices = True
-  if False is jetFlags.useVertices:
-    useVertices = False
-
-  if True is jobproperties.eflowRecFlags.useUpdated2015ChargedShowerSubtraction:
-    useChargedWeights = True
-  else:
-    useChargedWeights = False
-
-  useTrackVertexTool = False
-  if True is jetFlags.useTrackVertexTool:
-    useTrackVertexTool = True
-
-  # EM-scale pflow.
-  jtm += PFlowPseudoJetGetter(
-    "empflowget",
-    Label = "EMPFlow",
-    OutputContainer = "PseudoJetEMPFlow",
-    RetrievePFOTool = jtm.pflowretriever,
-    WeightPFOTool = jtm.pflowweighter,
-    InputIsEM = True,
-    CalibratePFO = False,
-    SkipNegativeEnergy = True,
-    UseChargedWeights = useChargedWeights,
-    UseVertices = useVertices,
-    UseTrackToVertexTool = useTrackVertexTool
-  )
-
-  # Calibrated EM-scale pflow.
-  jtm += PFlowPseudoJetGetter(
-    "emcpflowget",
-    Label = "EMCPFlow",
-    OutputContainer = "PseudoJetEMCPFlow",
-    RetrievePFOTool = jtm.pflowretriever,
-    WeightPFOTool = jtm.pflowweighter_LC,
-    InputIsEM = True,
-    CalibratePFO = True,
-    SkipNegativeEnergy = True,
-    UseChargedWeights = useChargedWeights,
-    UseVertices = useVertices,
-    UseTrackToVertexTool = useTrackVertexTool
-  )
-
-  # LC-scale pflow.
-  jtm += PFlowPseudoJetGetter(
-    "lcpflowget",
-    Label = "LCPFlow",
-    OutputContainer = "PseudoJetLCPFlow",
-    RetrievePFOTool = jtm.pflowretriever,
-    WeightPFOTool = jtm.pflowweighter_LC,
-    InputIsEM = False,
-    CalibratePFO = False,
-    SkipNegativeEnergy = True,
-    UseChargedWeights = useChargedWeights,
-    UseVertices = useVertices,
-    UseTrackToVertexTool = useTrackVertexTool
-  )
diff --git a/Reconstruction/PFlow/PFlowUtils/src/components/PFlowUtils_entries.cxx b/Reconstruction/PFlow/PFlowUtils/src/components/PFlowUtils_entries.cxx
index bacff888094dd73f1deec60ccbc899acd9acbb9f..3dfc7d7d6e6284c2e6e9b174f10f358af444659e 100644
--- a/Reconstruction/PFlow/PFlowUtils/src/components/PFlowUtils_entries.cxx
+++ b/Reconstruction/PFlow/PFlowUtils/src/components/PFlowUtils_entries.cxx
@@ -1,10 +1,8 @@
-#include "PFlowUtils/RetrievePFOTool.h"
 #include "PFlowUtils/WeightPFOTool.h"
 #include "../ParticleFlowEventFilter_r207.h"
 #include "../CombinePFO.h"
 #include "../PFlowCalibPFODecoratorAlgorithm.h"
 
-DECLARE_COMPONENT( CP::RetrievePFOTool )
 DECLARE_COMPONENT( CP::WeightPFOTool )
 DECLARE_COMPONENT( ParticleFlowEventFilter_r207 )
 DECLARE_COMPONENT( CombinePFO )