diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/ExtendedJetCommon.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/ExtendedJetCommon.py
index b255d5cc77defe3f2b4dd7041b880f6fb4bed7ff..8d4942a7a588ed9821d241ccbf33cec705b07ad6 100644
--- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/ExtendedJetCommon.py
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/ExtendedJetCommon.py
@@ -265,7 +265,7 @@ def applyJetCalibration(jetalg,algname,sequence,largeRjetconfig = 'comb', suffix
                       'AntiKt4LCTopo':('JES_data2016_data2015_Recommendation_Dec2016_rel21.config',
                                        'JetArea_Residual_EtaJES_GSC'),
                       'AntiKt4EMPFlow':('JES_MC16Recommendation_Consolidated_PFlow_Apr2019_Rel21.config',
-                                        'JetArea_Residual_EtaJES_GSC_Smear'),
+                                        'JetArea_Residual_EtaJES_GSC'),
                       'AntiKt10LCTopoTrimmedPtFrac5SmallR20':('JES_MC15recommendation_FatJet_Nov2016_QCDCombinationUncorrelatedWeights.config',
                                                               'EtaJES_JMS'),
                       'AntiKt2LCTopo':('JES_2015_2016_data_Rscan2LC_18Dec2018_R21.config',
@@ -448,6 +448,79 @@ def addJetTruthLabel(jetalg,algname,labelname,sequence):
         extjetlog.info('ExtendedJetCommon: Applying JetTruthLabel augmentation to jet collection: ' + jetalg + 'Jets' + ' using ' + labelname +' definition')
         applyJetAugmentation(jetalg,algname,sequence,jetaugtool)
 
+##################################################################  
+
+def getPFlowfJVT(jetalg,algname,sequence,primaryVertexCont="PrimaryVertices",trackVertexAssociation="JetTrackVtxAssoc",overlapLabel="",outLabel="fJvt",includePV=False):
+    supportedJets = ['AntiKt4EMPFlow','AntiKt4PFlowCustomVtxHgg']
+    if jetalg not in supportedJets:
+        extjetlog.error('*** PFlow fJvt augmentation requested for unsupported jet collection {}! ***'.format(jetalg))
+        return
+    else:
+        from AthenaCommon.AppMgr import ToolSvc
+        jetaugtool = getJetAugmentationTool(jetalg,suffix=algname)
+
+        #Check if the calibration and JVT tools exist already
+        jetcalibtoolname_default = 'DFJetCalib_'+jetalg
+        jetjvttoolname_default = 'DFJetJvt_'+jetalg
+
+        if '_BTagging' in jetalg:
+            jetalg_basename = jetalg[:jetalg.find('_BTagging')]
+        elif 'PFlowCustomVtx' in jetalg:
+            jetalg_basename = 'AntiKt4EMPFlow'
+        else:
+            jetalg_basename = jetalg
+
+        jvtefftoolname = getJvtEffToolName(jetalg_basename)
+
+        #Jet calibration tool 
+        if hasattr(ToolSvc, jetcalibtoolname_default):
+            jetaugtool.JetCalibTool = getattr(ToolSvc, jetcalibtoolname_default)
+        else:
+            applyJetCalibration(jetalg,algname,sequence,suffix=algname)
+
+        #JVT tool
+        if hasattr(ToolSvc, jetjvttoolname_default) and hasattr(ToolSvc, jvtefftoolname):
+            jetaugtool.JetJvtTool = getattr(ToolSvc, jetjvttoolname_default)
+            jetaugtool.JetJvtEffTool = getattr(ToolSvc, jvtefftoolname)
+        else:
+            updateJVT(jetalg,algname,sequence,customVxColl=primaryVertexCont,suffix=algname)
+
+        # Calibration tool specific for pFlow fJVT: without GSC and smearing
+        jetcalibtoolname = 'DFJetCalib_PFfJvt_'+jetalg
+        if hasattr(ToolSvc, jetcalibtoolname):
+            jetaugtool.JetCalibToolfJvt = getattr(ToolSvc,jetcalibtoolname)
+        else:
+            jetcalibrationtool = CfgMgr.JetCalibrationTool(jetcalibtoolname,
+                                                           JetCollection=jetalg,
+                                                           ConfigFile="JES_MC16Recommendation_Consolidated_PFlow_Apr2019_Rel21.config",
+                                                           CalibSequence="JetArea_Residual_EtaJES",
+                                                           CalibArea="00-04-82",
+                                                           IsData=False)
+
+            ToolSvc += jetcalibrationtool
+
+        wpfotoolname = "DFwPFO_"+jetalg+algname
+        wpfotool = CfgMgr.CP__WeightPFOTool(wpfotoolname)
+
+        pffjvttoolname = 'DFJetPFfJvt_'+jetalg+algname
+        jetCont = jetalg+"Jets"
+
+        if hasattr(ToolSvc,pffjvttoolname):
+            jetaugtool.JetForwardPFlowJvtTool = getattr(ToolSvc,pffjvttoolname)
+            jetaugtool.fJvtMomentKey = outLabel
+        else:
+            pffjvttool = CfgMgr.JetForwardPFlowJvtTool(pffjvttoolname,
+                verticesName=primaryVertexCont, JetContainer=jetCont,
+                TrackVertexAssociation=jtm.tvassoc.TrackVertexAssociation,
+                WeightPFOTool=wpfotool, JetCalibrationTool=jetcalibrationtool,
+                ORName=overlapLabel, FjvtRawName='DFCommonJets_'+outLabel, includePV=includePV)
+            ToolSvc += pffjvttool
+            jetaugtool.JetForwardPFlowJvtTool = pffjvttool
+            jetaugtool.fJvtMomentKey = outLabel
+
+        extjetlog.info('ExtendedJetCommon: Applying PFlow fJvt augmentation to jet collection: '+jetalg+'Jets')
+        applyJetAugmentation(jetalg,algname,sequence,jetaugtool)
+
 ################################################################## 
 
 def applyBTaggingAugmentation(jetalg,algname='default',sequence=DerivationFrameworkJob,btagtooldict={}):
@@ -787,6 +860,8 @@ def addCHSPFlowObjects():
 ##################################################################
 applyJetCalibration_xAODColl("AntiKt4EMTopo")
 updateJVT_xAODColl("AntiKt4EMTopo")
+applyJetCalibration_xAODColl("AntiKt4EMPFlow")
+updateJVT_xAODColl("AntiKt4EMPFlow")
 
 applyOverlapRemoval()
 eventCleanLoose_xAODColl("AntiKt4EMTopo")
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/src/JetAugmentationTool.cxx b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/src/JetAugmentationTool.cxx
index dba95878b6dfac5f9acd1d202a1e04cc57b32c11..ce917ddba396d1e21bfeff1b53e0838f3715f256 100644
--- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/src/JetAugmentationTool.cxx
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/src/JetAugmentationTool.cxx
@@ -23,6 +23,7 @@ namespace DerivationFramework {
     m_jvtTool(""),
     m_jetJvtEfficiencyTool(""),
     m_dojvt(false),
+    m_dofjvt(false),
     m_dobtag(false),
     m_jetTrackSumMomentsTool(""),
     m_decoratetracksum(false),
@@ -44,6 +45,8 @@ namespace DerivationFramework {
     declareProperty("JvtMomentKey",   m_jvtMomentKey = "Jvt");
     declareProperty("JetJvtTool",     m_jvtTool);
     declareProperty("JetJvtEffTool",  m_jetJvtEfficiencyTool);
+    declareProperty("fJvtMomentKey",  m_fjvtMomentKey = "fJvt");
+    declareProperty("JetForwardPFlowJvtTool", m_fjvtTool);
     declareProperty("JetBtagTools",   m_btagSelTools);
     declareProperty("JetBtagWPs",     m_btagWP);
     declareProperty("JetTrackSumMomentsTool", m_jetTrackSumMomentsTool);
@@ -58,6 +61,9 @@ namespace DerivationFramework {
   {
     ATH_MSG_INFO("Initialising JetAugmentationTool");
 
+    m_container_key = m_containerName;
+    ATH_CHECK(m_container_key.initialize());
+
     if(!m_jetCalibTool.empty()) {
       CHECK(m_jetCalibTool.retrieve());
       ATH_MSG_INFO("Augmenting jets with calibration \"" << m_momentPrefix+m_calibMomentKey << "\"");
@@ -79,12 +85,27 @@ namespace DerivationFramework {
 	ATH_MSG_INFO("Augmenting jets with updated JVT \"" << m_momentPrefix+m_jvtMomentKey << "\"");
 	m_dojvt = true;
 
+	m_acc_JVT = std::make_unique< SG::AuxElement::ConstAccessor<float> >(m_momentPrefix+m_jvtMomentKey);
+	m_acc_passJVT = std::make_unique< SG::AuxElement::ConstAccessor<char> >(m_momentPrefix+"pass"+m_jvtMomentKey);
+
 	m_jvt_key = m_containerName + "." + m_momentPrefix + m_jvtMomentKey;
 	m_passJvt_key = m_containerName + "." + m_momentPrefix + "pass" + m_jvtMomentKey;
 
 	ATH_CHECK(m_jvt_key.initialize());
 	ATH_CHECK(m_passJvt_key.initialize());
 
+	// PFlow fJVT tool
+	if(!m_fjvtTool.empty()) {
+	  CHECK(m_fjvtTool.retrieve());
+	  ATH_MSG_INFO("Augmenting (PFlow) jets with fJVT \"" << m_momentPrefix+m_fjvtMomentKey << "\"");
+	  m_dofjvt = true;
+
+	  m_acc_fJVT = std::make_unique< SG::AuxElement::ConstAccessor<float> >(m_momentPrefix+m_fjvtMomentKey);
+
+	  m_fjvt_key = m_containerName + "." + m_momentPrefix + m_fjvtMomentKey;
+	  ATH_CHECK(m_fjvt_key.initialize());
+	}
+
 	if(!m_btagSelTools.empty()) {
 	  size_t ibtag(0);
 	  for(const auto& tool : m_btagSelTools) {
@@ -106,6 +127,7 @@ namespace DerivationFramework {
     }
 
     if(!m_jetTrackSumMomentsTool.empty()) {
+      ATH_MSG_INFO("Augmenting jets with track sum moments \"" << m_momentPrefix << "TrackSumMass,Pt\"");
       CHECK(m_jetTrackSumMomentsTool.retrieve());
       ATH_MSG_INFO("Augmenting jets with track sum moments \"" << m_momentPrefix << "TrackSumMass,Pt\"");
       m_decoratetracksum = true;
@@ -168,7 +190,7 @@ namespace DerivationFramework {
 	}
       }
     }
-    
+
     if(!m_jetTruthLabelingTool.empty()) {
       CHECK(m_jetTruthLabelingTool.retrieve());
       ATH_MSG_INFO("Augmenting jets with truthlabeling");
@@ -211,10 +233,11 @@ namespace DerivationFramework {
 
   StatusCode JetAugmentationTool::addBranches() const
   {
+
     // retrieve container
-    const xAOD::JetContainer* jets(0);
-    if( evtStore()->retrieve( jets, m_containerName ).isFailure() ) {
-      ATH_MSG_WARNING ("Couldn't retrieve jets with key: " << m_containerName );
+    SG::ReadHandle<xAOD::JetContainer> jets(m_container_key);
+    if( !jets.isValid() ) {
+      ATH_MSG_WARNING ("Couldn't retrieve jets with key: " << m_container_key.key() );
       return StatusCode::FAILURE;
     }
 
@@ -229,6 +252,31 @@ namespace DerivationFramework {
 	ATH_MSG_WARNING("Problem applying jet calibration");
 	return StatusCode::FAILURE;
       }
+
+      if(m_dojvt){
+
+	SG::WriteDecorHandle<xAOD::JetContainer, float> jvt_handle(m_jvt_key);
+	SG::WriteDecorHandle<xAOD::JetContainer, char> passJvt_handle(m_passJvt_key);
+
+	//First update the Jvt criteria (needed for fJVT)
+	for(const xAOD::Jet *jet : *jets_copy) { 
+	  
+	  float jvt_value = m_jvtTool->updateJvt(*jet);
+	  jvt_handle(*jet)= jvt_value;
+	  ATH_MSG_VERBOSE("Calibrated JVT: " << jvt_value);
+	  
+	  bool passJVT = m_jetJvtEfficiencyTool->passesJvtCut(*jet);
+	  passJvt_handle(*jet) = passJVT;
+	}
+
+	// pFlow fJVT
+	if(m_dofjvt){
+	  if((m_fjvtTool->modify(*jets_copy)).isFailure()){
+	    ATH_MSG_ERROR("Problem computing fJVT");
+	    return StatusCode::FAILURE;
+	  }
+	}
+      }
     }
 
     if(m_decoratetracksum){
@@ -291,16 +339,28 @@ namespace DerivationFramework {
 
 	if(m_dojvt) {
 
-	  SG::WriteDecorHandle<xAOD::JetContainer, float> jvt_handle(m_jvt_key);
-	  SG::WriteDecorHandle<xAOD::JetContainer, char> passJvt_handle(m_passJvt_key);
+	  SG::WriteDecorHandle<xAOD::JetContainer, float> jvt_handle(m_jvt_key); 
+	  SG::WriteDecorHandle<xAOD::JetContainer, char> passJvt_handle(m_passJvt_key); 
+
+	  if(m_acc_JVT->isAvailable(*jet)){
+	    jvt_handle(jet_orig) = (*m_acc_JVT)(*jet);
+	  }
+
+	  bool passJVT = false;
+
+	  if(m_acc_passJVT->isAvailable(*jet)){
+	    passJVT = (*m_acc_passJVT)(*jet);
+	    passJvt_handle(jet_orig) = passJVT;
+          }
+
+	  if(m_dofjvt){
+
+	    SG::WriteDecorHandle<xAOD::JetContainer, float> fjvt_handle(m_fjvt_key);
+	    if(m_acc_fJVT->isAvailable(*jet)){
+	      fjvt_handle(jet_orig) = (*m_acc_fJVT)(*jet);
+	    }
+	  }
 
-	  float jvt_value = m_jvtTool->updateJvt(*jet);
-	  jvt_handle(jet_orig)= jvt_value;
-	  ATH_MSG_VERBOSE("Calibrated JVT: " << jvt_value);
-	  
-	  bool passJVT = m_jetJvtEfficiencyTool->passesJvtCut(jet_orig);
-	  passJvt_handle(jet_orig) = passJVT;
-	  
 	  if(m_dobtag) {
 	    size_t ibtag(0);
 	    for(const auto& tool : m_btagSelTools) {
@@ -332,14 +392,14 @@ namespace DerivationFramework {
 
         if(m_acc_GhostTruthAssociationFraction->isAvailable(*jet)){
 	  ghostTruthAssocFrac_handle(jet_orig) = (*m_acc_GhostTruthAssociationFraction)(*jet);
-	  ATH_MSG_INFO("GhostTruthAssociationFraction: " << (*m_acc_GhostTruthAssociationFraction)(jet_orig) );
+	  ATH_MSG_VERBOSE("GhostTruthAssociationFraction: " << (*m_acc_GhostTruthAssociationFraction)(jet_orig) );
 	}
 	if(m_acc_GhostTruthAssociationLink->isAvailable(*jet)){
 	  ghostTruthAssocLink_handle(jet_orig) = (*m_acc_GhostTruthAssociationLink)(*jet);
-	  ATH_MSG_INFO("GhostTruthAssociationLink: " << (*m_acc_GhostTruthAssociationLink)(jet_orig) );
+	  ATH_MSG_VERBOSE("GhostTruthAssociationLink: " << (*m_acc_GhostTruthAssociationLink)(jet_orig) );
 	}
       }
-      
+
       if(m_decoratetruthlabel){
 
 	SG::WriteDecorHandle<xAOD::JetContainer, float> truthLabel_dRW_handle(m_truthLabel_dRW_key);
@@ -376,9 +436,12 @@ namespace DerivationFramework {
 	if(m_acc_Associated_truthjet_pt->isAvailable(*jet)) associated_truthjet_pt_handle(jet_orig) = (*m_acc_Associated_truthjet_pt)(*jet);
 	if(m_acc_Associated_truthjet_eta->isAvailable(*jet)) associated_truthjet_eta_handle(jet_orig) = (*m_acc_Associated_truthjet_eta)(*jet);
       }
-      
+
     }
 
     return StatusCode::SUCCESS;
   }
+
 }
+
+ 
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/src/JetAugmentationTool.h b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/src/JetAugmentationTool.h
index 9363efa601c402bd1d846b771ea68e48277aaa19..ff38519d9af77965cccec4eb6e4326bc64a44f7c 100644
--- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/src/JetAugmentationTool.h
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/src/JetAugmentationTool.h
@@ -43,6 +43,7 @@ namespace DerivationFramework {
   private:
     std::string m_momentPrefix;
     std::string m_containerName;
+    SG::ReadHandleKey<xAOD::JetContainer> m_container_key {this, "InputJetsKey", "", "Accessor for input JetContainer"};
     //
     // implement augmentations explicitly to avoid need to parse lists of moments to copy
     //
@@ -63,10 +64,15 @@ namespace DerivationFramework {
     ToolHandle<CP::IJetJvtEfficiency> m_jetJvtEfficiencyTool;
     std::string m_jvtMomentKey;
     bool m_dojvt;
+    std::unique_ptr< SG::AuxElement::ConstAccessor<float> > m_acc_JVT;
+    std::unique_ptr< SG::AuxElement::ConstAccessor<char> > m_acc_passJVT;
 
     //PFlow fJVT
-    std::unique_ptr< SG::AuxElement::ConstAccessor<float> > m_acc_fjvt;
+    SG::WriteDecorHandleKey<xAOD::JetContainer> m_fjvt_key {this, "fJVTKey", "", "Decoration for fJVT"};
+    ToolHandle<IJetModifier> m_fjvtTool;
     std::string m_fjvtMomentKey;
+    bool m_dofjvt;
+    std::unique_ptr< SG::AuxElement::ConstAccessor<float> > m_acc_fJVT;
 
     // b-tagging       @author tripiana@cern.ch
     std::vector<std::string> m_btagWP;
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkPhys/share/PHYS.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkPhys/share/PHYS.py
index e9e483b64cb86705e744435bbcf275589041544c..64a386f315ec1ed2b8bd09390d8b8d5ffc3924a6 100644
--- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkPhys/share/PHYS.py
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkPhys/share/PHYS.py
@@ -14,7 +14,7 @@ from DerivationFrameworkEGamma import EGammaCommon
 from DerivationFrameworkEGamma import ElectronsCPDetailedContent
 from DerivationFrameworkMuons import MuonsCommon
 from DerivationFrameworkJetEtMiss.JetCommon import OutputJets
-from DerivationFrameworkJetEtMiss.ExtendedJetCommon import replaceAODReducedJets, addDefaultTrimmedJets, addJetTruthLabel, addQGTaggerTool
+from DerivationFrameworkJetEtMiss.ExtendedJetCommon import replaceAODReducedJets, addDefaultTrimmedJets, addJetTruthLabel, addQGTaggerTool, getPFlowfJVT
 from DerivationFrameworkJetEtMiss import METCommon
 from TriggerMenu.api.TriggerAPI import TriggerAPI
 from TriggerMenu.api.TriggerEnums import TriggerPeriod, TriggerType
@@ -189,7 +189,7 @@ addQGTaggerTool(jetalg="AntiKt4EMTopo",sequence=SeqPHYS,algname="QGTaggerToolAlg
 addQGTaggerTool(jetalg="AntiKt4EMPFlow",sequence=SeqPHYS,algname="QGTaggerToolPFAlg")
 
 # fJVT
-# getPFlowfJVT(jetalg='AntiKt4EMPFlow',sequence=SeqPHYS, algname='PHYSJetForwardPFlowJvtToolAlg')
+getPFlowfJVT(jetalg='AntiKt4EMPFlow',sequence=SeqPHYS, algname='PHYSJetForwardPFlowJvtToolAlg')
 
 #====================================================================
 # EGAMMA
diff --git a/Reconstruction/Jet/JetMomentTools/CMakeLists.txt b/Reconstruction/Jet/JetMomentTools/CMakeLists.txt
index 3380b03d56bbe875b6b5c67ece4ba8a3b4f41d62..832412f363214f985b1eec465fbb37088995a27f 100644
--- a/Reconstruction/Jet/JetMomentTools/CMakeLists.txt
+++ b/Reconstruction/Jet/JetMomentTools/CMakeLists.txt
@@ -13,7 +13,7 @@ atlas_add_library( JetMomentToolsLib
    JetMomentTools/*.h Root/*.cxx
    PUBLIC_HEADERS JetMomentTools
    INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${FASTJET_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS}
-   LINK_LIBRARIES ${Boost_LIBRARIES} ${FASTJET_LIBRARIES} ${ROOT_LIBRARIES} AsgDataHandlesLib AsgTools InDetTrackSelectionToolLib JetEDM JetInterface JetRecLib JetUtils PFlowUtilsLib TrackVertexAssociationToolLib xAODCaloEvent xAODEventInfo xAODJet xAODMissingET xAODTracking xAODTruth
+   LINK_LIBRARIES ${Boost_LIBRARIES} ${FASTJET_LIBRARIES} ${ROOT_LIBRARIES} AsgDataHandlesLib AsgTools InDetTrackSelectionToolLib JetCalibToolsLib JetEDM JetInterface JetRecLib JetUtils PFlowUtilsLib TrackVertexAssociationToolLib xAODCaloEvent xAODEventInfo xAODJet xAODMissingET xAODTracking xAODTruth
    PRIVATE_LINK_LIBRARIES CaloGeoHelpers xAODMetaData xAODPFlow PathResolver )
 
 if( NOT XAOD_STANDALONE )
@@ -24,7 +24,7 @@ if( NOT XAOD_STANDALONE )
    atlas_add_component( JetMomentTools
       src/*.h src/*.cxx src/components/*.cxx
       INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${FASTJET_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS}
-      LINK_LIBRARIES ${Boost_LIBRARIES} ${FASTJET_LIBRARIES} ${ROOT_LIBRARIES} AsgTools CaloIdentifier xAODCaloEvent xAODJet GaudiKernel JetEDM JetInterface JetRecLib JetUtils PFlowUtilsLib PathResolver JetMomentToolsLib ${extra_libs} )
+      LINK_LIBRARIES ${Boost_LIBRARIES} ${FASTJET_LIBRARIES} ${ROOT_LIBRARIES} AsgTools CaloIdentifier xAODCaloEvent xAODJet GaudiKernel JetCalibToolsLib JetEDM JetInterface JetRecLib JetUtils PFlowUtilsLib PathResolver JetMomentToolsLib ${extra_libs} )
 endif()
 
 #if( XAOD_STANDALONE )
diff --git a/Reconstruction/Jet/JetMomentTools/JetMomentTools/JetForwardPFlowJvtTool.h b/Reconstruction/Jet/JetMomentTools/JetMomentTools/JetForwardPFlowJvtTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..7936f747f7bd0635d9a42fa0ec7c324f4d0f5f53
--- /dev/null
+++ b/Reconstruction/Jet/JetMomentTools/JetMomentTools/JetForwardPFlowJvtTool.h
@@ -0,0 +1,170 @@
+///////////////////////// -*- C++ -*- /////////////////////////////
+
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+// JetForwardPFlowJvtTool.h
+// Header file for class JetForwardPFlowJvtTool
+// Author: Anastasia Kotsokechagia <anastasia.kotsokechagia@cern.ch>
+
+// Tool for calculating fjvt values for pflow jets. 
+// Short describtion of the tool;
+//   First central PU jets are built per vertex.
+//   Reconstructed calibrated jets are then used to calculate the per vertex missing momentum (miss-mom). 
+//   The per vertex missing momentum is defined as: The vector some of the calibrated jet momenta (for jets with pt>20GeV && Rpt>0.1 wrt to the vertex) + tracks assosiated to the vertex (otherwise). 
+//   PU Jets closeby (dR<0.3) to a HS jet are not considered.
+//   The fJVT value for every forward jet (fj) of the event is then calculated choosing the vertex with the largest negative miss-mom projection on the fj.  
+//   User action: After initializing the tool the user has to call the modify(xAOD::JetContainer& jetCont) function. Argument in this fuction is the PFlow jet container of the event. 
+//   The fjvt value for every forward jet of the container is then calculated and can be retrieved.
+///////////////////////////////////////////////////////////////////
+    //Parameters
+    // m_orLabel:  ""  
+    // m_jetsName : "Container name for the output reconstructed PU jets " 
+    // m_tightOP: "If true a tight fjvt threshold value is applied" 
+    // m_outLabelFjvt: "Decorator for passing fJVT threshold (tight or loose)"                            
+    // m_jetchargedp4: "Name of the jet charged momentum 4-vector" 
+    // m_etaThresh: "Maximum eta value for considering a jet as central" 
+    // m_forwardMinPt: "Minimum forward jet pt" 
+    // m_forwardMaxPt: "Maximum forward jet pt. If -1 no threshold is applied" 
+    // m_centerMinPt: "Minimum central jet pt"  
+    // m_centerMaxPt: "Maximum central jet pt. If -1 no threshold is applied" 
+    // m_pvind: "Hard-Scatter primary vertex index of the event. If -1 it's automatically retrieved from the event"
+    // m_rptCut: "Rpt cut value for central PU jets contributing in the missing momentum calculation" 
+    // m_jvtCut: "JVT threshold value for considering a central PU jet as HS" 
+    // m_dzCut: "Dz=z-z0 cut value for pfo objects participating in the HS vertex jet reco" 
+    // m_vertices: "Number of vertices for which the missing momentum is calculated"
+    // m_maxRap: "Maximum rapidity value in fastjet::AreaDefinition" 
+    // m_neutMaxRap: "Maximum rapidity value for neutral pfos participating in jet reco"
+    // m_weight: "PFO weight value"
+    // m_pfoToolName: "Name of PFO retriever tool"
+    // m_wpfoToolName: "Name of PFO weighting tool"
+    // m_pfoJESName: "Name of jet calibration tool"
+    // m_jetAlgo: "Jet calibration collection name"
+    // m_calibconfig: "Calibration config for PFlow jets, need to be updated with latest one"
+    // m_calibSeq: "Calibration sequence to be applied"
+    // m_calibArea: "Calibration area" 
+    // m_isdata: "True if data"
+
+
+#ifndef FORWARDPFLOWJVTTOOL_JVT_FORWARDPFLOWJVTTOOL_H
+#define FORWARDPFLOWJVTTOOL_JVT_FORWARDPFLOWJVTTOOL_H 1
+
+// STL includes
+#include <string>
+
+// FrameWork includes
+#include "AsgTools/ToolHandle.h"
+#include "AsgTools/AsgTool.h"
+#include "AsgTools/PropertyWrapper.h"
+#include "JetInterface/IJetDecorator.h"
+#include "JetEDM/TrackVertexAssociation.h"
+#include "xAODJet/JetContainer.h"
+#include "xAODJet/JetAuxContainer.h"
+
+#include "AsgDataHandles/ReadDecorHandleKey.h"
+#include "AsgDataHandles/ReadDecorHandle.h"
+#include "AsgDataHandles/WriteDecorHandleKey.h"
+#include "AsgDataHandles/WriteDecorHandle.h"
+
+// Pflow tools 
+#include "PFlowUtils/IWeightPFOTool.h"
+#include "PFlowUtils/WeightPFOTool.h"
+#include "JetCalibTools/IJetCalibrationTool.h"
+
+#include "AsgTools/ToolHandle.h"
+#include "JetCalibTools/IJetCalibrationTool.h"
+
+namespace pflow {
+  struct puJets {
+    std::shared_ptr<xAOD::JetContainer> jetCont;
+    std::shared_ptr<xAOD::JetAuxContainer> jetAuxCont;
+  };
+}
+
+  class JetForwardPFlowJvtTool
+  : public asg::AsgTool,
+    virtual public IJetDecorator{
+    ASG_TOOL_CLASS(JetForwardPFlowJvtTool,IJetDecorator)
+
+    ///////////////////////////////////////////////////////////////////
+    // Public methods:
+    ///////////////////////////////////////////////////////////////////
+  public:
+
+    /// Constructor with parameters:
+    JetForwardPFlowJvtTool(const std::string& name);
+
+    /// Destructor:
+    virtual ~JetForwardPFlowJvtTool();
+
+    virtual StatusCode  initialize() override;
+ 
+
+    virtual StatusCode decorate(const xAOD::JetContainer& jetCont) const override;
+
+    float getFJVT(const xAOD::Jet *jet,std::vector<TVector2> pileupMomenta) const;
+    bool isForwardJet(const xAOD::Jet *jet) const;
+    bool isCentralJet(const xAOD::Jet *jet) const;
+
+    StatusCode tagTruth(const xAOD::JetContainer *jets,const xAOD::JetContainer *truthJets);
+    std::vector<TVector2> calculateVertexMomenta(const xAOD::JetContainer *jets,int pvind, int vertices) const;
+    pflow::puJets buildPFlowPUjets(const xAOD::Vertex &vx) const;
+    bool hasCloseByHSjet(const xAOD::Jet *jet, const xAOD::JetContainer *pjets ) const;
+    double getRpt(const xAOD::Jet *jet) const;
+    fastjet::PseudoJet pfoToPseudoJet(const xAOD::PFO* pfo, const CP::PFO_JetMETConfig_charge& theCharge, const xAOD::Vertex *vx) const;
+
+  private:
+
+    SG::ReadHandleKey<jet::TrackVertexAssociation> m_tvaKey{this, "TrackVertexAssociation", "", "Input track-vertex association"};
+    Gaudi::Property<std::string> m_jetContainerName{this, "JetContainer", "", "SG key for the input jet container"};
+    Gaudi::Property<std::string> m_jetsName{this, "jetsName", "AntiKt4PUPFlowJets", "Container name for the output reconstructed PU jets"};
+    Gaudi::Property<std::string> m_jetchargedp4{this, "jetchargedp4", "JetChargedScaleMomentum", "Name of the jet charged momentum 4-vector"};
+    Gaudi::Property<std::string> m_pfoToolName{this, "pfoToolName", "PFOTool", "Name of PFO retriever tool"};
+    Gaudi::Property<std::string> m_wpfoToolName{this, "wpfoToolName", "WPFOTool", "Name of PFO weighting tool"};
+    Gaudi::Property<std::string> m_pfoJESName{this, "pfoJESName", "pfoJES", "Name of jet claibration tool"};
+    Gaudi::Property<std::string> m_jetAlgo{this, "jetAlgo", "AntiKt4EMPFlow", "Jet calibration collection name"};
+    Gaudi::Property<std::string> m_calibconfig{this, "calibconfig", "JES_MC16Recommendation_Consolidated_PFlow_Apr2019_Rel21.config", "Calibration config for PFlow jets, need to be updated with latest one"};
+    Gaudi::Property<std::string> m_calibSeq{this, "calibSeq", "JetArea_Residual_EtaJES", "Calibration sequence to be applied"};
+    Gaudi::Property<std::string> m_calibArea{this, "calibArea", "00-04-82", "Calibration area"};
+    
+    Gaudi::Property<bool> m_isdata{this, "isdata", false, "True if data"};
+    Gaudi::Property<int> m_pvind{this, "pvind", -1, "Hard-Scatter primary vertex index of the event. If -1 it will be automatically retrieved from the event"};
+    Gaudi::Property<int> m_vertices{this, "vertices", 10, "Number of vertices for which the missing momentum is calculated"};
+    Gaudi::Property<bool> m_includePV{this, "includePV", false, "Flag to include jets and tracks associated to PV in the calculation"};
+    Gaudi::Property<double> m_etaThresh{this, "etaThresh", 2.5, "Maximum eta value for considering a jet as central"};
+    Gaudi::Property<double> m_forwardMinPt{this, "forwardMinPt", 20e3, "Minimum forward jet pt"};
+    Gaudi::Property<double> m_forwardMaxPt{this, "forwardMaxPt", -1, "Maximum forward jet pt. If -1 no threshold is applied"};
+    Gaudi::Property<double> m_centerMinPt{this, "centralMinPt", 20e3, "Minimum central jet pt"};
+    Gaudi::Property<double> m_centerMaxPt{this, "centralMaxPt", -1, "Maximum central jet pt. If -1 no threshold is applied"};
+    Gaudi::Property<double> m_fjvtThresh{this, "fjvtThresh", 15e3, "fjvt threshold value"};
+    Gaudi::Property<double> m_rptCut{this, "rptCut", 0.1, "Rpt cut value for central PU jets contributing in the missing momentum calculation"};
+    Gaudi::Property<double> m_jvtCut{this, "jvtCut", 0.2, "JVT threshold value for considering a central PU jet as HS"};
+    Gaudi::Property<double> m_dzCut{this, "dzCut", 2.0, "Dz=z=-z0 cut for pfo objects participating in the HS vertex jet reco"};
+    Gaudi::Property<double> m_maxRap{this, "maxRap", 2.5, "Maximum rapidity value in fastjet::AreaDefinition"};
+    Gaudi::Property<double> m_neutMaxRap{this, "neutMaxRap", 2.5, "Maximum rapidity value for neutral pfos participating in jet reco"};
+    Gaudi::Property<float>  m_weight{this, "weight", 0, "PFO weight value"};
+    Gaudi::Property<bool> m_tightOP{this, "tightOP", false, "If true a tight fjvt threshold value is applied"};
+
+    // not used?
+    //Gaudi::Property<std::string> m_jvtMomentName{"jvtMomentName", "", ""};
+    //Gaudi::Property<double> m_centerJvtThresh{"", 0, ""};
+
+    SG::ReadHandleKey<xAOD::VertexContainer> m_vxContKey{this, "verticesName", "PrimaryVertices", "Container name of vertices to be retrieved"};
+    SG::ReadHandleKey<xAOD::PFOContainer> m_PFOKey{this, "PFOName", "CHSParticleFlowObjects", "SG Key for CHS PFO Container"};
+
+    SG::ReadDecorHandleKey<xAOD::JetContainer> m_jvtKey{this, "jvtName", "Jvt", "SG key for the Jvt decoration"};
+    SG::ReadDecorHandleKey<xAOD::PFO> m_orKey{this, "ORName", "", "OR label"};
+    
+    SG::WriteDecorHandleKey<xAOD::JetContainer> m_fjvtKey{this, "FjvtName", "passOnlyFJVT", "Decorator for passing fJVT threshold (tight or loose)"};
+    SG::WriteDecorHandleKey<xAOD::JetContainer> m_fjvtRawKey{this, "FjvtRawName", "fJvt", "Decorator for raw fJVT variable"};
+    SG::WriteDecorHandleKey<xAOD::JetContainer> m_isHSKey{this, "isHSName", "isJVTHS", "SG key for output isJVTHS decoration"};
+    SG::WriteDecorHandleKey<xAOD::JetContainer> m_isPUKey{this, "isPUName", "isJvtPU", "SG key for output isJVTPU decoration"};
+    
+    ToolHandle<CP::WeightPFOTool> m_wpfotool{this,"WeightPFOTool", "", "Weight PFO tool name"};
+    ToolHandle<IJetCalibrationTool> m_pfoJES{this,"JetCalibrationTool", "", "Jet calibration tool name"};
+
+    std::size_t getPV() const;
+
+  };
+#endif //> !FORWARDJVTTOOL_JVT_FORWARDJVTTOOL_H
diff --git a/Reconstruction/Jet/JetMomentTools/Root/JetForwardPFlowJvtTool.cxx b/Reconstruction/Jet/JetMomentTools/Root/JetForwardPFlowJvtTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..18d25c6833317959d6ce707eb8b247d023e34f43
--- /dev/null
+++ b/Reconstruction/Jet/JetMomentTools/Root/JetForwardPFlowJvtTool.cxx
@@ -0,0 +1,328 @@
+///////////////////////// -*- C++ -*- /////////////////////////////
+
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+// JetForwardPFlowJvtTool.cxx
+// Implementation file for class JetForwardPFlowJvtTool
+// Author: Anastasia Kotsokechagia <anastasia.kotsokechagia@cern.ch>
+///////////////////////////////////////////////////////////////////
+
+// JetForwardPFlowJvtTool includes
+#include "JetMomentTools/JetForwardPFlowJvtTool.h"
+
+// Jet EDM
+#include "xAODJet/JetAttributes.h"
+
+// FastJet
+#include "fastjet/ClusterSequence.hh"
+#include "fastjet/ClusterSequenceArea.hh"
+#include <fastjet/AreaDefinition.hh>
+
+// Jet
+#include "JetRec/JetFromPseudojet.h"
+
+  ///////////////////////////////////////////////////////////////////
+  // Public methods:
+  ///////////////////////////////////////////////////////////////////
+
+  // Constructors
+  ////////////////
+  JetForwardPFlowJvtTool::JetForwardPFlowJvtTool(const std::string& name) :
+    AsgTool(name) {
+  }
+  
+ // Destructor
+  ///////////////
+  JetForwardPFlowJvtTool::~JetForwardPFlowJvtTool()
+  {}
+
+  // Athena algtool's Hooks
+  ////////////////////////////
+  StatusCode JetForwardPFlowJvtTool::initialize()
+  {
+    ATH_MSG_INFO ("Initializing " << name() << "...");
+    if (m_tightOP) m_fjvtThresh = 0.53;
+    else m_fjvtThresh = 0.72;
+
+    ATH_CHECK( m_tvaKey.initialize() );
+
+    if(m_jetContainerName.empty()){
+      ATH_MSG_ERROR("JetForwardPFlowJvtTool needs to have its input jet container configured!");
+      return StatusCode::FAILURE;
+    }
+
+    if(!m_orKey.key().empty()){
+      m_orKey = m_jetContainerName + "." + m_orKey.key();
+      ATH_CHECK(m_orKey.initialize());
+    }
+    m_fjvtKey = m_jetContainerName + "." + m_fjvtKey.key();
+    m_fjvtRawKey = m_jetContainerName + "." + m_fjvtRawKey.key();
+    m_isHSKey = m_jetContainerName + "." + m_isHSKey.key();
+    m_isPUKey = m_jetContainerName + "." + m_isPUKey.key();
+    m_jvtKey = m_jetContainerName + "." + m_jvtKey.key();
+
+    ATH_CHECK(m_fjvtKey.initialize());
+    ATH_CHECK(m_fjvtRawKey.initialize());
+    ATH_CHECK(m_isHSKey.initialize());
+    ATH_CHECK(m_isPUKey.initialize());
+    ATH_CHECK(m_jvtKey.initialize());
+
+    ATH_CHECK(m_vxContKey.initialize());
+    ATH_CHECK(m_PFOKey.initialize());
+    
+    return StatusCode::SUCCESS;
+  }
+
+  StatusCode JetForwardPFlowJvtTool::decorate(const xAOD::JetContainer& jetCont) const {
+    std::vector<TVector2> pileupMomenta;
+
+    pileupMomenta=calculateVertexMomenta(&jetCont,m_pvind, m_vertices);
+
+    SG::WriteDecorHandle<xAOD::JetContainer, char> fjvtHandle(m_fjvtKey);
+    SG::WriteDecorHandle<xAOD::JetContainer, float> fjvtRawHandle(m_fjvtRawKey);
+    if(pileupMomenta.size()==0) {
+      ATH_MSG_DEBUG( "pileupMomenta is empty, this can happen for events with no PU vertices."
+                     <<" fJVT won't be computed for this event and will be set to 0 instead." );
+      for(const xAOD::Jet* jetF : jetCont) {
+	fjvtHandle(*jetF) = 1;
+	fjvtRawHandle(*jetF) = 0;
+      }
+      return StatusCode::SUCCESS;
+    }
+
+    for(const xAOD::Jet* jetF : jetCont) {
+      fjvtHandle(*jetF) = 1;
+      fjvtRawHandle(*jetF) = 0;
+
+      if (isForwardJet(jetF)){
+       double fjvt = getFJVT(jetF,pileupMomenta);
+       if (fjvt>m_fjvtThresh) fjvtHandle(*jetF) = 0;
+       fjvtRawHandle(*jetF) = fjvt;
+      }
+    }
+    return StatusCode::SUCCESS;
+  }
+
+  float JetForwardPFlowJvtTool::getFJVT(const xAOD::Jet *jet, std::vector<TVector2> pileupMomenta) const {
+    TVector2 fjet(jet->pt()*cos(jet->phi()),jet->pt()*sin(jet->phi()));
+    double fjvt = 0;
+    for (const TVector2& pu : pileupMomenta) {
+      double projection = pu*fjet/fjet.Mod();
+      if (projection<fjvt) fjvt = projection;
+    }
+    return -1*fjvt/fjet.Mod();
+  }
+
+  std::vector<TVector2> JetForwardPFlowJvtTool::calculateVertexMomenta(const xAOD::JetContainer *pjets,
+                                                                       int pvind, int vertices) const {
+    std::vector<TVector2> pileupMomenta;
+    // -- Retrieve PV index if not provided by user
+    const std::size_t pv_index = (pvind==-1) ? getPV() : std::size_t(pvind);
+
+    SG::ReadHandle<xAOD::VertexContainer> vxContHandle(m_vxContKey);
+
+    for(const xAOD::Vertex* vx: *vxContHandle) {
+      if(vx->vertexType()!=xAOD::VxType::PriVtx && vx->vertexType()!=xAOD::VxType::PileUp) continue;
+      if(vx->index()==(size_t)pv_index) continue;
+
+      TString jname = m_jetsName.value();
+      jname += vx->index();
+
+      pflow::puJets vertjets = buildPFlowPUjets(*vx);
+      if( !vertjets.jetCont || !vertjets.jetAuxCont ){
+        ATH_MSG_WARNING(" Some issue appeared while building the pflow pileup jets for vertex "
+                        << vx->index() << " (vxType = " << vx->vertexType()<<" )!" );
+        return pileupMomenta;
+      }
+      
+      TVector2 vertex_met;
+      for( const xAOD::Jet *jet : *(vertjets.jetCont) ) {
+
+        // Remove jets which are close to hs
+        if (!m_includePV && hasCloseByHSjet(jet,pjets)) continue;
+
+        // Calculate vertex missing momentum
+        if (isCentralJet(jet) && getRpt(jet)> m_rptCut)
+        { 
+          vertex_met += TVector2(jet->pt()*cos(jet->phi()),jet->pt()*sin(jet->phi()) ) ;
+        } 
+        else{
+          vertex_met += TVector2(jet->jetP4(m_jetchargedp4).Pt()*cos(jet->jetP4(m_jetchargedp4).Phi()),
+                                 jet->jetP4(m_jetchargedp4).Pt()*sin(jet->jetP4(m_jetchargedp4).Phi()) );
+        }
+      }
+
+      pileupMomenta.push_back(vertex_met);
+      if(vertices!=-1 && int(vx->index())==vertices) break;
+    }
+    return pileupMomenta;
+  }
+
+  bool JetForwardPFlowJvtTool::hasCloseByHSjet(const xAOD::Jet *jet, const xAOD::JetContainer *pjets ) const {
+    for (const xAOD::Jet* pjet : *pjets) {
+      float jet_jvt=0;
+      SG::ReadDecorHandle<xAOD::JetContainer, float> jvtHandle(m_jvtKey);
+      jet_jvt = jvtHandle(*pjet);
+     if (pjet->p4().DeltaR(jet->p4())<0.3 && jet_jvt>m_jvtCut && isCentralJet(pjet) ) return true;
+    }
+    return false;
+  }
+
+  pflow::puJets JetForwardPFlowJvtTool::buildPFlowPUjets(const xAOD::Vertex &vx) const {
+    pflow::puJets pu_jets;
+    const std::size_t pv_index = (m_pvind==-1) ? getPV() : std::size_t (m_pvind);
+
+    std::vector<fastjet::PseudoJet> input_pfo;
+    std::set<int> charged_pfo;
+
+    SG::ReadHandle<jet::TrackVertexAssociation> tvaHandle(m_tvaKey);
+    SG::ReadHandle<xAOD::PFOContainer> PFOHandle(m_PFOKey);
+        
+    if (!tvaHandle.isValid()){
+      ATH_MSG_ERROR("Could not retrieve the TrackVertexAssociation: "
+                    << m_tvaKey.key());
+      return pu_jets;
+    }
+    for(const xAOD::PFO* pfo : *PFOHandle){
+      if (m_orKey.key().empty()) continue;
+      SG::ReadDecorHandle<xAOD::PFO, char> orHandle(m_orKey);
+      if (!orHandle(*pfo)) continue;
+      if (pfo->isCharged()) { 
+        if (vx.index()==pv_index && std::abs((vx.z()-pfo->track(0)->z0())*sin(pfo->track(0)->theta()))>m_dzCut)
+          continue;
+        if (vx.index()!=pv_index
+            && (!tvaHandle->associatedVertex(pfo->track(0))
+                || vx.index()!=tvaHandle->associatedVertex(pfo->track(0))->index())
+            ) continue;
+        input_pfo.push_back(pfoToPseudoJet(pfo, CP::charged, &vx) );
+        charged_pfo.insert(pfo->index());
+      } 
+      else if (std::abs(pfo->eta())<m_neutMaxRap && !pfo->isCharged() && pfo->eEM()>0)
+      { 
+        input_pfo.push_back(pfoToPseudoJet(pfo, CP::neutral, &vx) );
+      }
+    }
+    std::shared_ptr<xAOD::JetContainer> vertjets = std::make_shared<xAOD::JetContainer>();
+    std::shared_ptr<xAOD::JetAuxContainer> vertjetsAux = std::make_shared<xAOD::JetAuxContainer>();
+
+    vertjets->setStore(vertjetsAux.get());
+    TString newname = m_jetsName.value();
+    newname += vx.index();
+
+    fastjet::JetDefinition jet_def(fastjet::antikt_algorithm,0.4);
+    fastjet::AreaDefinition area_def(fastjet::active_area_explicit_ghosts,
+                                     fastjet::GhostedAreaSpec(fastjet::SelectorAbsRapMax(m_maxRap)));
+    fastjet::ClusterSequenceArea clust_pfo(input_pfo,jet_def,area_def);
+    std::vector<fastjet::PseudoJet> inclusive_jets = sorted_by_pt(clust_pfo.inclusive_jets(5000.));
+
+    for (size_t i = 0; i < inclusive_jets.size(); i++) {
+      xAOD::Jet* jet=  new xAOD::Jet();
+      xAOD::JetFourMom_t tempjetp4(inclusive_jets[i].pt(),
+                                   inclusive_jets[i].eta(),
+                                   inclusive_jets[i].phi(),
+                                   inclusive_jets[i].m());
+      xAOD::JetFourMom_t newArea(inclusive_jets[i].area_4vector().perp(),
+                                 inclusive_jets[i].area_4vector().eta(),
+                                 inclusive_jets[i].area_4vector().phi(),
+                                 inclusive_jets[i].area_4vector().m());
+      vertjets->push_back(jet);
+      jet->setJetP4(tempjetp4);
+      jet->setJetP4("JetConstitScaleMomentum",tempjetp4);
+      jet->setJetP4("JetPileupScaleMomentum",tempjetp4);
+      jet->setAttribute("ActiveArea4vec",newArea);
+      jet->setAttribute("DetectorEta",jet->eta());
+      std::vector<fastjet::PseudoJet> constituents = inclusive_jets[i].constituents();
+      float chargedpart = 0;
+      for (size_t j = 0; j < constituents.size(); j++) {
+        if (charged_pfo.count(constituents[j].user_index())>=1) {
+          chargedpart += constituents[j].perp(); 
+        }
+      }
+      xAOD::JetFourMom_t chargejetp4(chargedpart,inclusive_jets[i].eta(),inclusive_jets[i].phi(),inclusive_jets[i].m());
+      jet->setJetP4(m_jetchargedp4,chargejetp4);
+    }
+
+    if((m_pfoJES->modify(*vertjets)).isFailure()){
+      ATH_MSG_ERROR(" Failed to calibrate PU jet container ");
+      return pu_jets;
+    }
+
+    pu_jets.jetCont = vertjets;
+    pu_jets.jetAuxCont = vertjetsAux;
+    return pu_jets;
+  }
+
+  fastjet::PseudoJet JetForwardPFlowJvtTool::pfoToPseudoJet(const xAOD::PFO* pfo, const CP::PFO_JetMETConfig_charge& theCharge, const xAOD::Vertex *vx) const {
+    TLorentzVector pfo_p4;
+    if (CP::charged == theCharge){
+      float pweight = m_weight;
+      if( (m_wpfotool->fillWeight(*pfo,pweight)).isSuccess() ){
+	// Create a PSeudojet with the momentum of the selected IParticle
+	pfo_p4= TLorentzVector(pfo->p4().Px()*pweight,pfo->p4().Py()*pweight,pfo->p4().Pz()*pweight,pfo->e()*pweight);
+      }
+    } else if (CP::neutral == theCharge){ 
+      pfo_p4= pfo->GetVertexCorrectedEMFourVec(*vx);
+    }
+    fastjet::PseudoJet psj(pfo_p4);
+    // User index is used to identify the xAOD object used for the PSeudoJet
+    if (CP::charged == theCharge){
+      psj.set_user_index(pfo->index());
+    }else{
+      psj.set_user_index(-1);
+    }
+
+    return psj;
+  }
+
+  bool JetForwardPFlowJvtTool::isForwardJet(const xAOD::Jet *jet) const {
+    if (std::abs(jet->eta())<m_etaThresh) return false;
+    if (jet->pt()<m_forwardMinPt || (m_forwardMaxPt>0 && jet->pt()>m_forwardMaxPt) ) return false;
+    return true;
+  }
+
+  bool JetForwardPFlowJvtTool::isCentralJet(const xAOD::Jet *jet) const {
+    if (std::abs(jet->eta())>m_etaThresh) return false;
+    if (jet->pt()<m_centerMinPt || (m_centerMaxPt>0 && jet->pt()>m_centerMaxPt)) return false;
+    return true;
+  }
+
+  double JetForwardPFlowJvtTool::getRpt(const xAOD::Jet *jet) const {
+    double Rpt;
+    Rpt= jet->jetP4(m_jetchargedp4).Pt()/ jet->pt();
+    return Rpt;
+  }
+
+  std::size_t JetForwardPFlowJvtTool::getPV() const{
+    if (m_includePV) return -1;
+
+    //const xAOD::VertexContainer *vxCont = 0;
+    SG::ReadHandle<xAOD::VertexContainer> vxContHandle(m_vxContKey);
+      ATH_MSG_DEBUG("Successfully retrieved primary vertex container");
+      for(const xAOD::Vertex *vx : *vxContHandle) {
+        if(vx->vertexType()==xAOD::VxType::PriVtx) return vx->index();
+      }
+    ATH_MSG_WARNING("Couldn't identify the hard-scatter primary vertex (no vertex with \"vx->vertexType()==xAOD::VxType::PriVtx\" in the container)!");
+    // this almost certainly isn't what we should do here, the
+    // caller doesn't check this for errors
+    return 0;
+  }
+
+  StatusCode JetForwardPFlowJvtTool::tagTruth(const xAOD::JetContainer *jets,const xAOD::JetContainer *truthJets) {
+    SG::WriteDecorHandle<xAOD::JetContainer, bool> isHSHandle(m_isHSKey);
+    SG::WriteDecorHandle<xAOD::JetContainer, bool> isPUHandle(m_isPUKey);
+    
+    for(const xAOD::Jet *jet : *jets) {
+      bool ishs = false;
+      bool ispu = true;
+      for(const xAOD::Jet *tjet : *truthJets) {
+        if (tjet->p4().DeltaR(jet->p4())<0.3 && tjet->pt()>10e3) ishs = true;
+        if (tjet->p4().DeltaR(jet->p4())<0.6) ispu = false;
+      }
+      isHSHandle(*jet)=ishs;
+      isPUHandle(*jet)=ispu;
+    }
+    return StatusCode::SUCCESS;
+  }
+
diff --git a/Reconstruction/Jet/JetMomentTools/src/components/JetMomentTools_entries.cxx b/Reconstruction/Jet/JetMomentTools/src/components/JetMomentTools_entries.cxx
index e9286347a60537436517cceb7cabfe81abe004fc..674e1747036892b52be33ae7661bf7aafc257992 100644
--- a/Reconstruction/Jet/JetMomentTools/src/components/JetMomentTools_entries.cxx
+++ b/Reconstruction/Jet/JetMomentTools/src/components/JetMomentTools_entries.cxx
@@ -5,6 +5,7 @@
 #include "JetMomentTools/JetVertexFractionTool.h"
 #include "JetMomentTools/JetVertexTaggerTool.h"
 #include "JetMomentTools/JetForwardJvtTool.h"
+#include "JetMomentTools/JetForwardPFlowJvtTool.h"
 #include "JetMomentTools/JetTrackMomentsTool.h"
 #include "JetMomentTools/JetTrackSumMomentsTool.h"
 #include "JetMomentTools/JetClusterMomentsTool.h"
@@ -29,6 +30,7 @@ DECLARE_COMPONENT( JetWidthTool )
 DECLARE_COMPONENT( JetVertexFractionTool )
 DECLARE_COMPONENT( JetVertexTaggerTool )
 DECLARE_COMPONENT( JetForwardJvtTool )
+DECLARE_COMPONENT(JetForwardPFlowJvtTool)
 DECLARE_COMPONENT( JetTrackMomentsTool )
 DECLARE_COMPONENT( JetTrackSumMomentsTool )
 DECLARE_COMPONENT( JetClusterMomentsTool )