diff --git a/PhysicsAnalysis/AnalysisCommon/ParticleJetTools/ParticleJetTools/JetTruthLabelingTool.h b/PhysicsAnalysis/AnalysisCommon/ParticleJetTools/ParticleJetTools/JetTruthLabelingTool.h
index 5b9ef017f7d16906a6a9b30dc59c8f0d8ace82b5..aeec10d8d0723a81768d48737c231f3aed3806f8 100644
--- a/PhysicsAnalysis/AnalysisCommon/ParticleJetTools/ParticleJetTools/JetTruthLabelingTool.h
+++ b/PhysicsAnalysis/AnalysisCommon/ParticleJetTools/ParticleJetTools/JetTruthLabelingTool.h
@@ -20,39 +20,41 @@ class JetTruthLabelingTool :   virtual public asg::AsgTool,
 
 public:
 
-  // default constructor - to be used in all derived classes
+  /// default constructor - to be used in all derived classes
   JetTruthLabelingTool(const std::string& name = "JetTruthLabelingTool");
   virtual StatusCode initialize() override;
 
-  // decorate truth label to a jet collection
+  /// decorate truth label to a jet collection
   StatusCode modify(xAOD::JetContainer& jets) const override;
 
-  // decorate truth label to a const jet
+  /// decorate truth label to a const jet
   StatusCode modifyJet(const xAOD::Jet& jet) const;
 
-  // Print configured parameters
+  /// Print configured parameters
   void print() const override;
   
-  // returns the name of large-R jet truth label
+  /// returns the name of large-R jet truth label
   std::string getLargeRJetTruthLabelName() const {
     return m_truthLabelName;
   };
 
 protected:
   
-  // truth label name
+  /// truth label name
   std::string m_truthLabelName;
 
-  // Flag indicating whether input collection is a truth jet container
+  /// Flag indicating whether input collection is a truth jet container
   bool m_isTruthJetCol;
 
-  // TRUTH1 or TRUTH3
+  /// TRUTH1 or TRUTH3
   bool m_useTRUTH3;
   std::string m_truthParticleContainerName;
   std::string m_truthBosonContainerName;
   std::string m_truthTopQuarkContainerName;
 
-  // parameters for truth labeling
+  /// parameters for truth labeling
+  std::string m_truthJetCollectionName;
+  bool m_useDRMatch;
   double m_dRTruthJet;
   double m_dRTruthPart;
   double m_mLowTop;
@@ -61,22 +63,34 @@ protected:
   double m_mLowZ;
   double m_mHighZ;
 
-  // Label truth jet collection
+  /// Label truth jet collection
   StatusCode labelTruthJets() const;
-  StatusCode labelTruthJets(const xAOD::JetContainer &jets) const;
+  StatusCode labelTruthJets( const xAOD::JetContainer &jets ) const;
 
-  // Apply label to a single jet
-  // This method is included for backwards compatibility with BoostedJetTaggers
-  StatusCode labelRecoJet(const xAOD::Jet& jet, const xAOD::JetContainer *truthJets=nullptr) const;
+  /// Apply label to a single jet
+  /// This method is included for backwards compatibility with BoostedJetTaggers
+  StatusCode labelRecoJet( const xAOD::Jet &jet, const xAOD::JetContainer *truthJets = nullptr ) const;
 
-  // Apply labels to all jets in a container
-  StatusCode labelRecoJets(xAOD::JetContainer& jets) const;
+  /// Apply labels to all jets in a container
+  StatusCode labelRecoJets( xAOD::JetContainer &jets ) const;
 
-  // Get truth label using R21Consolidated definition
-  int getTruthJetLabelR21Consolidated( const xAOD::Jet &jet, std::vector<std::pair<TLorentzVector,int> > tlv_truthParts ) const;
+  /// Get truth label using dR-matched particles
+  int getTruthJetLabelDR( const xAOD::Jet &jet, std::vector<std::pair<TLorentzVector,int> > tlv_truthParts ) const;
   
-  // Check for Sherpa DSIDs
-  bool getIsSherpa(const int DSID) const {
+  /// Get truth label using ghost-associated particles
+  int getTruthJetLabelGA( const xAOD::Jet &jet ) const;
+
+  /// Get label based on matching and containment criteria
+  int getLabel( const xAOD::Jet &jet, bool matchH, bool matchW, bool matchZ, bool matchTop ) const;
+
+  /// Get R21Precision top label Split23 cut
+  float getTopSplit23CutR21Precision( float pt ) const;
+
+  /// Get number of ghost associated particles
+  int getNGhostParticles( const xAOD::Jet &jet, std::string collection ) const;
+
+  /// Check for Sherpa DSIDs
+  bool getIsSherpa( const int DSID ) const {
     if(
         (304307 <= DSID && DSID <= 304309) || // Sherpa 2.2.1 W+jets
         (304707 <= DSID && DSID <= 304709) // Sherpa 2.2.1 Z+jets
@@ -86,19 +100,20 @@ protected:
     return false;
   };
 
-  // Extract heavy particle 4-vectors from truth record
-  void getTLVs(std::vector< std::pair<TLorentzVector,int> > &tlvs, const xAOD::TruthParticleContainer *truthBosons, const xAOD::TruthParticleContainer *truthTop, bool isSherpa = false) const;
+  /// Extract heavy particle 4-vectors from truth record
+  void getTLVs( std::vector< std::pair<TLorentzVector,int> > &tlvs, const xAOD::TruthParticleContainer *truthBosons, const xAOD::TruthParticleContainer *truthTop, bool isSherpa = false ) const;
 
-  // Check if truth particle has correct DSID and isn't self decay
-  bool selectTruthParticle(const xAOD::TruthParticle *tp, int pdgId) const;
+  /// Check if truth particle has correct DSID and isn't self decay
+  bool selectTruthParticle( const xAOD::TruthParticle *tp, int pdgId ) const;
 
-  // Accessors and decorators
+  /// Accessors and decorators
   std::unique_ptr< SG::AuxElement::Accessor<int> > m_acc_label;
   std::unique_ptr< SG::AuxElement::Accessor<float> > m_acc_dR_W;
   std::unique_ptr< SG::AuxElement::Accessor<float> > m_acc_dR_Z;
   std::unique_ptr< SG::AuxElement::Accessor<float> > m_acc_dR_H;
   std::unique_ptr< SG::AuxElement::Accessor<float> > m_acc_dR_Top;
   std::unique_ptr< SG::AuxElement::Accessor<int> > m_acc_NB;
+  std::unique_ptr< SG::AuxElement::Accessor<float> > m_acc_Split23;
 
   std::unique_ptr< SG::AuxElement::Decorator<int> > m_dec_label;
   std::unique_ptr< SG::AuxElement::Decorator<float> > m_dec_dR_W;
@@ -107,6 +122,7 @@ protected:
   std::unique_ptr< SG::AuxElement::Decorator<float> > m_dec_dR_Top;
   std::unique_ptr< SG::AuxElement::Decorator<int> > m_dec_NB;
   std::unique_ptr< SG::AuxElement::Decorator<float> > m_dec_TruthJetMass;
+  std::unique_ptr< SG::AuxElement::Decorator<float> > m_dec_TruthJetSplit23;
 
 };
 
diff --git a/PhysicsAnalysis/AnalysisCommon/ParticleJetTools/Root/JetTruthLabelingTool.cxx b/PhysicsAnalysis/AnalysisCommon/ParticleJetTools/Root/JetTruthLabelingTool.cxx
index 73d3ff2ea82384da65fbf785d4aefbbbff4ce77b..e04c8b6428381dfdff9e527b4f5bb0074a232477 100644
--- a/PhysicsAnalysis/AnalysisCommon/ParticleJetTools/Root/JetTruthLabelingTool.cxx
+++ b/PhysicsAnalysis/AnalysisCommon/ParticleJetTools/Root/JetTruthLabelingTool.cxx
@@ -15,9 +15,11 @@ JetTruthLabelingTool::JetTruthLabelingTool(const std::string& name) :
     declareProperty( "TruthBosonContainerName",       m_truthBosonContainerName = "TruthBosonsWithDecayParticles");
     declareProperty( "TruthTopQuarkContainerName",    m_truthTopQuarkContainerName = "TruthTopQuarkWithDecayParticles");
     
-    // Hard-code some values for R10TruthLabel_R21Consolidated
-    // Functionality to customize labeling will be added later
+    /// Hard-code some values for R10TruthLabel_R21Consolidated
+    /// Functionality to customize labeling will be added later
     if(m_truthLabelName == "R10TruthLabel_R21Consolidated") {
+      m_truthJetCollectionName="AntiKt10TruthTrimmedPtFrac5SmallR20Jets";
+      m_useDRMatch = true;
       m_dRTruthJet = 0.75;
       m_dRTruthPart = 0.75;
       m_mLowTop = 140.0;
@@ -26,6 +28,20 @@ JetTruthLabelingTool::JetTruthLabelingTool(const std::string& name) :
       m_mLowZ = 60.0;
       m_mHighZ = 110.0;
     }
+
+    /// Hard-code some values for R10TruthLabel_R21Precision
+    if(m_truthLabelName == "R10TruthLabel_R21Precision") {
+      m_truthJetCollectionName="AntiKt10TruthJets";
+      m_useDRMatch = false;
+      m_dRTruthJet = 0.75;
+      m_dRTruthPart = 0.75;
+      m_mLowTop = 140.0;
+      m_mLowW = 50.0;
+      m_mHighW = 100.0;
+      m_mLowZ = 60.0;
+      m_mHighZ = 110.0;
+    }
+
 }
 
 StatusCode JetTruthLabelingTool::initialize(){
@@ -33,9 +49,13 @@ StatusCode JetTruthLabelingTool::initialize(){
   ATH_MSG_INFO("Initializing " << name());
   print();
 
-  // Check if TruthLabelName is supported. If not, give an error and
-  // return FAILURE
-  if(m_truthLabelName != "R10TruthLabel_R21Consolidated") {
+  /// Check if TruthLabelName is supported. If not, give an error and return FAILURE
+  
+  bool isSupportedLabel = false;
+  isSupportedLabel = isSupportedLabel || (m_truthLabelName=="R10TruthLabel_R21Consolidated");
+  isSupportedLabel = isSupportedLabel || (m_truthLabelName=="R10TruthLabel_R21Precision");
+
+  if(!isSupportedLabel) {
     ATH_MSG_ERROR("TruthLabelName " << m_truthLabelName << " is not supported. Exiting...");
     return StatusCode::FAILURE;
   }
@@ -46,6 +66,7 @@ StatusCode JetTruthLabelingTool::initialize(){
   m_acc_dR_H = std::make_unique< SG::AuxElement::Accessor<float> >(m_truthLabelName+"_dR_H");
   m_acc_dR_Top = std::make_unique< SG::AuxElement::Accessor<float> >(m_truthLabelName+"_dR_Top");
   m_acc_NB = std::make_unique< SG::AuxElement::Accessor<int> >(m_truthLabelName+"_NB");
+  m_acc_Split23 = std::make_unique< SG::AuxElement::Accessor<float> >("Split23");
 
   m_dec_label = std::make_unique< SG::AuxElement::Decorator<int> >(m_truthLabelName);
   m_dec_dR_W = std::make_unique< SG::AuxElement::Decorator<float> >(m_truthLabelName+"_dR_W");
@@ -54,6 +75,7 @@ StatusCode JetTruthLabelingTool::initialize(){
   m_dec_dR_Top = std::make_unique< SG::AuxElement::Decorator<float> >(m_truthLabelName+"_dR_Top");
   m_dec_NB = std::make_unique< SG::AuxElement::Decorator<int> >(m_truthLabelName+"_NB");
   m_dec_TruthJetMass = std::make_unique< SG::AuxElement::Decorator<float> >(m_truthLabelName+"_TruthJetMass");
+  m_dec_TruthJetSplit23 = std::make_unique< SG::AuxElement::Decorator<float> >(m_truthLabelName+"_TruthJetSplit23");
 
   return StatusCode::SUCCESS;
 }
@@ -64,6 +86,7 @@ void JetTruthLabelingTool::print() const {
   ATH_MSG_INFO("xAOD information:");
   ATH_MSG_INFO("TruthLabelName:               " << m_truthLabelName);
   ATH_MSG_INFO("UseTRUTH3:                    " << ( m_useTRUTH3 ? "True" : "False"));
+  
   if(m_useTRUTH3) {
     ATH_MSG_INFO("TruthBosonContainerName:      " << m_truthBosonContainerName);
     ATH_MSG_INFO("TruthTopQuarkContainerName:   " << m_truthTopQuarkContainerName);
@@ -71,25 +94,31 @@ void JetTruthLabelingTool::print() const {
   else {
     ATH_MSG_INFO("TruthParticleContainerName:   " << m_truthParticleContainerName);
   }
-  if(m_truthLabelName == "R10TruthLabel_R21Consolidated") {
-    ATH_MSG_INFO("dRTruthJet:    " << std::to_string(m_dRTruthJet));
+  
+  ATH_MSG_INFO("TruthJetCollectionName:         " << m_truthJetCollectionName);
+  ATH_MSG_INFO("dRTruthJet:    " << std::to_string(m_dRTruthJet));
+
+  if ( m_useDRMatch ) {
     ATH_MSG_INFO("dRTruthPart:   " << std::to_string(m_dRTruthPart));
-    ATH_MSG_INFO("mLowTop:       " << std::to_string(m_mLowTop));
-    ATH_MSG_INFO("mLowW:         " << std::to_string(m_mLowW));
-    ATH_MSG_INFO("mHighW:        " << std::to_string(m_mHighW));
-    ATH_MSG_INFO("mLowZ:         " << std::to_string(m_mLowZ));
-    ATH_MSG_INFO("mHighZ:        " << std::to_string(m_mHighZ));
   }
+
+  ATH_MSG_INFO("mLowTop:       " << std::to_string(m_mLowTop));
+  ATH_MSG_INFO("mLowW:         " << std::to_string(m_mLowW));
+  ATH_MSG_INFO("mHighW:        " << std::to_string(m_mHighW));
+  ATH_MSG_INFO("mLowZ:         " << std::to_string(m_mLowZ));
+  ATH_MSG_INFO("mHighZ:        " << std::to_string(m_mHighZ));
+
 }
 
-int JetTruthLabelingTool::getTruthJetLabelR21Consolidated( const xAOD::Jet &jet, std::vector<std::pair<TLorentzVector,int> > tlv_truthParts ) const {
+int JetTruthLabelingTool::getTruthJetLabelDR( const xAOD::Jet &jet, std::vector<std::pair<TLorentzVector,int> > tlv_truthParts ) const {
 
-  bool isMatchW = false;
-  bool isMatchZ = false;
-  bool isMatchH = false;
-  bool isMatchTop = false;
+  /// Booleans to check associated heavy particles
+  bool matchW = false;
+  bool matchZ = false;
+  bool matchH = false;
+  bool matchTop = false;
 
-  // Distances to truth particles
+  /// Distances to truth particles
   float dR_W = 9999;
   float dR_Z = 9999;
   float dR_H = 9999;
@@ -99,113 +128,110 @@ int JetTruthLabelingTool::getTruthJetLabelR21Consolidated( const xAOD::Jet &jet,
     float dR = tlv_truth.first.DeltaR(jet.p4());
     if( dR < m_dRTruthPart ) {
 
-      if ( std::abs(tlv_truth.second) == 23 && !isMatchZ) {
+      if ( std::abs(tlv_truth.second) == 23 && !matchZ ) {
         dR_Z = dR;
-        isMatchZ = true;
+        matchZ = true;
       }
 
-      if ( std::abs(tlv_truth.second) == 24 && !isMatchW) {
+      if ( std::abs(tlv_truth.second) == 24 && !matchW ) {
         dR_W = dR;
-        isMatchW = true;
+        matchW = true;
       }
 
-      if ( std::abs(tlv_truth.second) == 25 && !isMatchH) {
+      if ( std::abs(tlv_truth.second) == 25 && !matchH ) {
         dR_H = dR;
-        isMatchH = true;
+        matchH = true;
       }
 
-      if ( std::abs(tlv_truth.second) == 6 && !isMatchTop) {
+      if ( std::abs(tlv_truth.second) == 6 && !matchTop ) {
         dR_Top = dR;
-        isMatchTop = true;
+        matchTop = true;
       }
 
     }
   }
 
-  // find ghost associated B-hadrons
-  int nMatchB = 0;
-  if( !jet.getAttribute<int>( "GhostBHadronsFinalCount", nMatchB ) ){
-
-    std::vector<const xAOD::TruthParticle*> ghostB; // Ghost associated B hadrons after FSR
-    if( !jet.getAssociatedObjects<xAOD::TruthParticle>( "GhostBHadronsFinal", ghostB ) ){      
-      ATH_MSG_ERROR("GhostBHadronsFinal cannot be retrieved! Truth label definition of W/top tagger might be wrong");
-    } 
-    nMatchB = ghostB.size();
-  }
-
-  // Add matching criteria decorations
+  /// Add matching criteria decorations
   (*m_dec_dR_W)(jet) = dR_W;
   (*m_dec_dR_Z)(jet) = dR_Z;
   (*m_dec_dR_H)(jet) = dR_H;
   (*m_dec_dR_Top)(jet) = dR_Top;
-  (*m_dec_NB)(jet) = nMatchB;
 
-  if( !isMatchTop && !isMatchW && !isMatchZ && !isMatchH) {
-    return LargeRJetTruthLabel::enumToInt(LargeRJetTruthLabel::qcd);
-  }
+  return getLabel( jet, matchH, matchW, matchZ, matchTop );
 
-  if(isMatchH) {
-    if(nMatchB > 1) return LargeRJetTruthLabel::enumToInt(LargeRJetTruthLabel::Hbb);
-    else return LargeRJetTruthLabel::enumToInt(LargeRJetTruthLabel::other_From_H);
-  }
-  else if( isMatchTop && nMatchB > 0 && m_mLowTop < jet.m()*0.001 ) {
-    return LargeRJetTruthLabel::enumToInt(LargeRJetTruthLabel::tqqb); 
+}
+
+int JetTruthLabelingTool::getTruthJetLabelGA( const xAOD::Jet &jet ) const {
+
+  /// Booleans to check ghost-associated heavy particles
+  bool matchW = false;
+  bool matchZ = false;
+  bool matchH = false;
+  bool matchTop = false;
+
+  /// Find ghost associated W bosons
+  int nMatchW = getNGhostParticles( jet, "GhostWBosons" );
+
+  if ( nMatchW ) {
+    matchW = true;
   }
-  else if( isMatchW && nMatchB == 0 && m_mLowW < jet.m()*0.001 && jet.m()*0.001 < m_mHighW ) {
-    if ( isMatchTop ) {
-      return LargeRJetTruthLabel::enumToInt(LargeRJetTruthLabel::Wqq_From_t);
-    }
-    else {
-      return LargeRJetTruthLabel::enumToInt(LargeRJetTruthLabel::Wqq);
-    } 
+
+  /// Find ghost associated Z bosons
+  int nMatchZ = getNGhostParticles( jet, "GhostZBosons" );
+  
+  if ( nMatchZ ) {
+    matchZ = true;
   }
-  else if( isMatchZ && m_mLowZ < jet.m()*0.001 && jet.m()*0.001 < m_mHighZ ) {
-    return LargeRJetTruthLabel::enumToInt(LargeRJetTruthLabel::Zqq);
+
+  /// Find ghost associated H bosons
+  int nMatchH = getNGhostParticles( jet, "GhostHBosons" );
+  
+  if ( nMatchH ) {
+    matchH = true;
   }
-  else {
-    if ( isMatchTop ) {
-      return LargeRJetTruthLabel::enumToInt(LargeRJetTruthLabel::other_From_t); 
-    }
-    else {
-      return LargeRJetTruthLabel::enumToInt(LargeRJetTruthLabel::other_From_V);
-    }
+
+  /// Find ghost associated top quarks
+  int nMatchTop = getNGhostParticles( jet, "GhostTQuarksFinal" );
+
+  if ( nMatchTop ) {
+    matchTop = true;
   }
 
-  return LargeRJetTruthLabel::enumToInt(LargeRJetTruthLabel::qcd);
+  return getLabel( jet, matchH, matchW, matchZ, matchTop );
+
 }
 
 StatusCode JetTruthLabelingTool::modify(xAOD::JetContainer& jets) const {
 
-  // Apply label to truth jet collections
-  if(m_isTruthJetCol) ATH_CHECK( labelTruthJets(jets) );
+  /// Apply label to truth jet collections
+  if(m_isTruthJetCol) {
+    return labelTruthJets(jets);
+  }
 
-  // Copy label to matched reco jets
-  if(!m_isTruthJetCol) {
+  /// Copy label to matched reco jets
+  else {
     ATH_CHECK( labelTruthJets() );
-    ATH_CHECK( labelRecoJets(jets) );
+    return labelRecoJets(jets);
   }
 
   return StatusCode::SUCCESS;
 }
 
-StatusCode JetTruthLabelingTool::modifyJet(const xAOD::Jet& jet) const {
+StatusCode JetTruthLabelingTool::modifyJet( const xAOD::Jet& jet ) const {
 
-  // Apply label to truth jet collections
+  /// Apply label to truth jet collections
   ATH_CHECK( labelTruthJets() );
 
-  // Copy label to matched reco jets
-  ATH_CHECK( labelRecoJet(jet) );
-
-  return StatusCode::SUCCESS;
+  /// Copy label to matched reco jets
+  return labelRecoJet(jet);
 }
 
-StatusCode JetTruthLabelingTool::labelRecoJets(xAOD::JetContainer& jets) const {
+StatusCode JetTruthLabelingTool::labelRecoJets( xAOD::JetContainer& jets ) const {
 
-  // Retrieve appropriate truth jet container
-  const xAOD::JetContainer* truthJets=nullptr;
-  if(m_truthLabelName == "R10TruthLabel_R21Consolidated") {
-    ATH_CHECK( evtStore()->retrieve(truthJets, "AntiKt10TruthTrimmedPtFrac5SmallR20Jets") );
-  }
+  /// Retrieve appropriate truth jet container
+  const xAOD::JetContainer* truthJets = nullptr;
+  
+  ATH_CHECK( evtStore()->retrieve(truthJets, m_truthJetCollectionName) );
 
   for(xAOD::Jet *jet : jets) {
 
@@ -216,75 +242,96 @@ StatusCode JetTruthLabelingTool::labelRecoJets(xAOD::JetContainer& jets) const {
   return StatusCode::SUCCESS;
 }
 
-StatusCode JetTruthLabelingTool::labelRecoJet(const xAOD::Jet& jet, const xAOD::JetContainer *truthJets) const {
+StatusCode JetTruthLabelingTool::labelRecoJet( const xAOD::Jet& jet, const xAOD::JetContainer *truthJets ) const {
 
-  // Retrieve appropriate truth jet container
-  if(!truthJets) {
-    if(m_truthLabelName == "R10TruthLabel_R21Consolidated") {
-      ATH_CHECK( evtStore()->retrieve(truthJets, "AntiKt10TruthTrimmedPtFrac5SmallR20Jets") );
+  /// Retrieve appropriate truth jet container
+  if ( !truthJets ) {
+    
+    ATH_CHECK( evtStore()->retrieve(truthJets, m_truthJetCollectionName) );
+  
+  }
+
+  /// Get parent ungroomed reco jet for R21Precision
+  const xAOD::Jet* parent = nullptr;
+  if ( m_truthLabelName == "R10TruthLabel_R21Precision" ) {
+    ElementLink<xAOD::JetContainer> element_link = jet.auxdata<ElementLink<xAOD::JetContainer> >("Parent");
+    if ( element_link.isValid() ) {
+      parent = *element_link;
+    }
+    else {
+      ATH_MSG_ERROR("Unable to get a link to the parent jet! Returning a NULL pointer."); 
+      return StatusCode::FAILURE;
     }
   }
 
-  // Find matched truth jet
+  /// Find matched truth jet
   float dRmin = 9999;
   const xAOD::Jet* matchTruthJet = nullptr;
   for ( const xAOD::Jet* truthJet : *truthJets ) {
     float dR = jet.p4().DeltaR( truthJet->p4() );
-    if ( m_dRTruthJet < 0 || dR < m_dRTruthJet ) { // if m_dRTruthJet < 0, the closest truth jet is used as matched jet. Otherwise, only match if dR < m_dRTruthJet
-      if( dR < dRmin ){
+    /// If parent jet has been retrieved, calculate dR w.r.t. it instead
+    if ( parent ) dR = parent->p4().DeltaR( truthJet->p4() );
+    /// If m_dRTruthJet < 0, the closest truth jet is used as matched jet. Otherwise, only match if dR < m_dRTruthJet
+    if ( m_dRTruthJet < 0 || dR < m_dRTruthJet ) { 
+      if ( dR < dRmin ) {
         dRmin = dR;
         matchTruthJet = truthJet;
       }
     }
   }
 
-  int label = LargeRJetTruthLabel::enumToInt(LargeRJetTruthLabel::notruth);
+  int label = LargeRJetTruthLabel::enumToInt( LargeRJetTruthLabel::notruth );
   float dR_truthJet_W = 9999;
   float dR_truthJet_Z = 9999;
   float dR_truthJet_Top = 9999;
   float dR_truthJet_H = 9999;
   float truthJetNB = -1;
+  float truthJetSplit23 = -9999;
   float truthJetMass = -9999;
 
   if ( matchTruthJet ) {
     label = (*m_acc_label)(*matchTruthJet);
-    if(m_truthLabelName == "R10TruthLabel_R21Consolidated") {
-      if(m_acc_dR_W->isAvailable(*matchTruthJet)) dR_truthJet_W = (*m_acc_dR_W)(*matchTruthJet);
-      if(m_acc_dR_Z->isAvailable(*matchTruthJet)) dR_truthJet_Z = (*m_acc_dR_Z)(*matchTruthJet);
-      if(m_acc_dR_H->isAvailable(*matchTruthJet)) dR_truthJet_H = (*m_acc_dR_H)(*matchTruthJet);
-      if(m_acc_dR_Top->isAvailable(*matchTruthJet)) dR_truthJet_Top = (*m_acc_dR_Top)(*matchTruthJet);
-      if(m_acc_NB->isAvailable(*matchTruthJet)) truthJetNB = (*m_acc_NB)(*matchTruthJet);
-      truthJetMass = matchTruthJet->m();
+    if ( m_useDRMatch ) {
+      if ( m_acc_dR_W->isAvailable(*matchTruthJet) ) dR_truthJet_W = (*m_acc_dR_W)(*matchTruthJet);
+      if ( m_acc_dR_Z->isAvailable(*matchTruthJet) ) dR_truthJet_Z = (*m_acc_dR_Z)(*matchTruthJet);
+      if ( m_acc_dR_H->isAvailable(*matchTruthJet) ) dR_truthJet_H = (*m_acc_dR_H)(*matchTruthJet);
+      if ( m_acc_dR_Top->isAvailable(*matchTruthJet) ) dR_truthJet_Top = (*m_acc_dR_Top)(*matchTruthJet);
     }
+    if ( m_truthLabelName == "R10TruthLabel_R21Precision" ) {
+      if ( m_acc_Split23->isAvailable(*matchTruthJet) ) truthJetSplit23 = (*m_acc_Split23)(*matchTruthJet);
+    }
+    if ( m_acc_NB->isAvailable(*matchTruthJet) ) truthJetNB = (*m_acc_NB)(*matchTruthJet);
+    truthJetMass = matchTruthJet->m();
   }
 
-  // decorate truth label
+  /// Decorate truth label
   (*m_dec_label)(jet) = label;
 
-  // decorate additional information used for truth labeling
-  if(m_truthLabelName == "R10TruthLabel_R21Consolidated") {
-    // These most likely won't be used in the R21Precision labeling definition
+  /// Decorate additional information used for truth labeling
+  if ( m_useDRMatch ) {
     (*m_dec_dR_W)(jet) = dR_truthJet_W;
     (*m_dec_dR_Z)(jet) = dR_truthJet_Z;
     (*m_dec_dR_H)(jet) = dR_truthJet_H;
     (*m_dec_dR_Top)(jet) = dR_truthJet_Top;
-    (*m_dec_NB)(jet) = truthJetNB;
-    (*m_dec_TruthJetMass)(jet) = truthJetMass;
   }
+  if ( m_truthLabelName == "R10TruthLabel_R21Precision" ) {
+    (*m_dec_TruthJetSplit23)(jet) = truthJetSplit23;
+  }
+  (*m_dec_NB)(jet) = truthJetNB;
+  (*m_dec_TruthJetMass)(jet) = truthJetMass;
 
   return StatusCode::SUCCESS;
 }
 
 StatusCode JetTruthLabelingTool::labelTruthJets() const {
 
-  // Retrieve appropriate truth jet container
+  /// Retrieve appropriate truth jet container
   const xAOD::JetContainer* truthJets = nullptr;
-  if(m_truthLabelName == "R10TruthLabel_R21Consolidated") {
-    ATH_CHECK( evtStore()->retrieve(truthJets, "AntiKt10TruthTrimmedPtFrac5SmallR20Jets") );
-  }
+  
+  ATH_CHECK( evtStore()->retrieve(truthJets, m_truthJetCollectionName) );
 
-  // Make sure the truth jet collection has been retrieved
-  if(!truthJets) {
+  /// Make sure the truth jet collection has been retrieved
+  if ( !truthJets ) {
     ATH_MSG_ERROR("No truth jet container retrieved. Please make sure you are using a supported TruthLabelName.");
     return StatusCode::FAILURE;
   }
@@ -293,89 +340,98 @@ StatusCode JetTruthLabelingTool::labelTruthJets() const {
 
 }
 
-StatusCode JetTruthLabelingTool::labelTruthJets(const xAOD::JetContainer &truthJets) const {
+StatusCode JetTruthLabelingTool::labelTruthJets( const xAOD::JetContainer &truthJets ) const {
 
-  // Make sure there is at least 1 jet in truth collection
-  if(!(truthJets.size())) return StatusCode::SUCCESS;
+  /// Make sure there is at least 1 jet in truth collection
+  if ( !(truthJets.size()) ) return StatusCode::SUCCESS;
 
-  // Check if the truth jet collection already has labels applied
+  /// Check if the truth jet collection already has labels applied
   const xAOD::Jet *jet = truthJets.at(0);
-  if(m_acc_label->isAvailable(*jet)) {
+  if ( m_acc_label->isAvailable(*jet) ) {
     ATH_MSG_DEBUG("labelTruthJets: Truth jet collection already labelled with " << m_truthLabelName);
     return StatusCode::SUCCESS;
   }
 
-  // Get MC channel number
+  /// Get MC channel number
   int channelNumber = -999;
 
-  //Get the EventInfo to identify Sherpa samples
+  /// Get the EventInfo to identify Sherpa samples
   const xAOD::EventInfo * eventInfo = nullptr;
   if ( evtStore()->retrieve(eventInfo,"EventInfo").isFailure() || !eventInfo ) {
     ATH_MSG_ERROR("Failed to retrieve event information.");
     return StatusCode::FAILURE;
   }
 
-  channelNumber = eventInfo->mcChannelNumber();
-
-  if( channelNumber < 0 ) {
-    ATH_MSG_ERROR("Channel number was not set correctly");
-    return StatusCode::FAILURE;
-  }
-
-  // Check if it is a Sherpa sample
-  bool isSherpa = getIsSherpa(channelNumber);
-
-  if(m_useTRUTH3 && isSherpa) {
-    ATH_MSG_ERROR("Cannot apply truth labels to Sherpa 2.2.1 samples using TRUTH3 containers");
-    return StatusCode::FAILURE;
-  }
+  /// Vectors of W/Z/H/Top TLorentzVectors
+  std::vector<std::pair<TLorentzVector,int> > tlv_truthParts;
 
-  int label = LargeRJetTruthLabel::enumToInt(LargeRJetTruthLabel::notruth);
-  const xAOD::TruthParticleContainer* truthPartsBoson = nullptr;
-  const xAOD::TruthParticleContainer* truthPartsTop = nullptr;
+  /// Get truth particles directly if using dR matching
+  if ( m_useDRMatch ) {
+  
+    channelNumber = eventInfo->mcChannelNumber();
 
-  // TRUTH3
-  if( m_useTRUTH3 ) {
-    // Check for boson container
-    if( evtStore()->contains<xAOD::TruthParticleContainer>( m_truthBosonContainerName ) ) ATH_CHECK(evtStore()->retrieve(truthPartsBoson, m_truthBosonContainerName));
-    else {
-      ATH_MSG_ERROR("Unable to find " << m_truthBosonContainerName << ". Please check the content of your input file.");
+    if ( channelNumber < 0 ) {
+      ATH_MSG_ERROR("Channel number was not set correctly");
       return StatusCode::FAILURE;
     }
-    
-    // Check for top quark container
-    if( evtStore()->contains<xAOD::TruthParticleContainer>( m_truthTopQuarkContainerName ) ) ATH_CHECK(evtStore()->retrieve(truthPartsTop, m_truthTopQuarkContainerName));
-    else {
-      ATH_MSG_ERROR("Unable to find " << m_truthTopQuarkContainerName << ". Please check the content of your input file.");
+
+    /// Check if it is a Sherpa sample
+    bool isSherpa = getIsSherpa(channelNumber);
+
+    if ( m_useTRUTH3 && isSherpa ) {
+      ATH_MSG_ERROR("Cannot apply truth labels to Sherpa 2.2.1 samples using TRUTH3 containers");
       return StatusCode::FAILURE;
     }
-  }
-  
-  // TRUTH1
-  else {
-    if( evtStore()->contains<xAOD::TruthParticleContainer>( m_truthParticleContainerName ) ) {
-      ATH_CHECK(evtStore()->retrieve(truthPartsBoson, m_truthParticleContainerName));
-      ATH_CHECK(evtStore()->retrieve(truthPartsTop, m_truthParticleContainerName));
+
+    const xAOD::TruthParticleContainer* truthPartsBoson = nullptr;
+    const xAOD::TruthParticleContainer* truthPartsTop = nullptr;
+
+    /// TRUTH3
+    if( m_useTRUTH3 ) {
+      /// Check for boson container
+      if ( evtStore()->contains<xAOD::TruthParticleContainer>( m_truthBosonContainerName ) ) ATH_CHECK(evtStore()->retrieve(truthPartsBoson, m_truthBosonContainerName));
+      else {
+        ATH_MSG_ERROR("Unable to find " << m_truthBosonContainerName << ". Please check the content of your input file.");
+        return StatusCode::FAILURE;
+      }
+
+      /// Check for top quark container
+      if ( evtStore()->contains<xAOD::TruthParticleContainer>( m_truthTopQuarkContainerName ) ) ATH_CHECK(evtStore()->retrieve(truthPartsTop, m_truthTopQuarkContainerName));
+      else {
+        ATH_MSG_ERROR("Unable to find " << m_truthTopQuarkContainerName << ". Please check the content of your input file.");
+        return StatusCode::FAILURE;
+      }
     }
+
+    /// TRUTH1
     else {
-      ATH_MSG_ERROR("Unable to find " << m_truthParticleContainerName << ". Please check the content of your input file.");
-      return StatusCode::FAILURE;
+      if ( evtStore()->contains<xAOD::TruthParticleContainer>( m_truthParticleContainerName ) ) {
+        ATH_CHECK(evtStore()->retrieve(truthPartsBoson, m_truthParticleContainerName));
+        ATH_CHECK(evtStore()->retrieve(truthPartsTop, m_truthParticleContainerName));
+      }
+      else {
+        ATH_MSG_ERROR("Unable to find " << m_truthParticleContainerName << ". Please check the content of your input file.");
+        return StatusCode::FAILURE;
+      }
     }
-  }
-
-  // Vectors of W/Z/H/Top TLorentzVectors
-  std::vector<std::pair<TLorentzVector,int> > tlv_truthParts;
 
-  // Get truth particle TLVs
-  if(m_truthLabelName == "R10TruthLabel_R21Consolidated") {
+    /// Get truth particle TLVs
     getTLVs(tlv_truthParts, truthPartsBoson, truthPartsTop, isSherpa);
+  
   }
 
-  // Apply label to truth jet
-  for(const xAOD::Jet* jet : truthJets) {
+  int label = LargeRJetTruthLabel::enumToInt(LargeRJetTruthLabel::notruth);
+  /// Apply label to truth jet
+  for ( const xAOD::Jet *jet : truthJets ) {
 
-    if(m_truthLabelName == "R10TruthLabel_R21Consolidated") {
-      label = getTruthJetLabelR21Consolidated(*jet, tlv_truthParts);
+    if ( m_useDRMatch ) {
+      ATH_MSG_DEBUG("Getting truth label using dR matching");
+      label = getTruthJetLabelDR(*jet, tlv_truthParts);
+    }
+    
+    else {
+      ATH_MSG_DEBUG("Getting truth label using ghost-association");
+      label = getTruthJetLabelGA(*jet);
     }
 
     (*m_dec_label)(*jet) = label;
@@ -384,83 +440,95 @@ StatusCode JetTruthLabelingTool::labelTruthJets(const xAOD::JetContainer &truthJ
   return StatusCode::SUCCESS;
 }
 
-void JetTruthLabelingTool::getTLVs(std::vector<std::pair<TLorentzVector,int> > &tlvs, const xAOD::TruthParticleContainer *truthBosons, const xAOD::TruthParticleContainer *truthTop, bool isSherpa) const {
+void JetTruthLabelingTool::getTLVs( std::vector<std::pair<TLorentzVector,int> > &tlvs, const xAOD::TruthParticleContainer *truthBosons, const xAOD::TruthParticleContainer *truthTop, bool isSherpa ) const {
 
   tlvs.clear();
 
-  // Sherpa W/Z+jets samples need special treatment
+  /// Sherpa W/Z+jets samples need special treatment
   if(isSherpa) {
     int countStatus3 = 0;
-    
-    // Decay products
+
+    /// Decay products
     TLorentzVector p1(0,0,0,0);
     TLorentzVector p2(0,0,0,0);
 
-    // W candidate
+    /// W candidate
     TLorentzVector WZCand(0,0,0,0);
 
-    // Flag for W or Z candidates
+    /// Flag for W or Z candidates
     bool isWPCand = false;
     bool isWMCand = false;
     bool isZCand = false;
 
-    // Flag to check if qq' pair is in the mass window
+    /// Flag to check if qq' pair is in the mass window
     bool inMassWindow = false;
 
     for ( unsigned int ipart = 0; ipart < truthBosons->size(); ipart++ ){
 
       const xAOD::TruthParticle* part1 = truthBosons->at(ipart);
 
-      if ( part1->status() != 3 ) continue; /// Skip particles without status == 3
+      /// Skip particles without status == 3
+      if ( part1->status() != 3 ) continue;
 
-      if ( std::abs(part1->pdgId()) > 5 ) continue; /// Skip anything that isn't a light quark
+      /// Skip anything that isn't a light quark
+      if ( std::abs(part1->pdgId()) > 5 ) continue;
 
       countStatus3++;
-      if ( countStatus3 > 3 ) continue; /// We want to look at first 2 partons except beam particles. Sometimes beam particles are dropped from DxAODs...
-      p1 = part1->p4(); /// Keep particles as first daughter
+      /// We want to look at first 2 partons except beam particles. Sometimes beam particles are dropped from DxAODs...
+      if ( countStatus3 > 3 ) continue;
+      /// Keep particles as first daughter
+      p1 = part1->p4();
 
-      // Find the next particle in the list with status == 3
+      /// Find the next particle in the list with status == 3
       for ( unsigned int jpart = ipart+1; jpart < truthBosons->size(); jpart++ ) {
 
         const xAOD::TruthParticle* part2 = truthBosons->at(jpart);
 
-        if ( part2->status() != 3 ) continue; /// Skip particles without status == 3
+        /// Skip particles without status == 3
+        if ( part2->status() != 3 ) continue;
 
-        if ( std::abs(part2->pdgId()) > 5 ) continue; /// Skip anything that isn't a light quark
+        /// Skip anything that isn't a light quark
+        if ( std::abs(part2->pdgId()) > 5 ) continue;
 
         p2 = part2->p4();
-  
+
+        /// Daughters of Z decay should be same-flavor but opposite charge
         if ( part1->pdgId() + part2->pdgId() == 0 ) {
-          isZCand = true; /// Daughters of Z decay should be same-flavor but opposite charge
+          isZCand = true;
         }
+        /// W+ daughters should have a positive u or c
         else if ( part1->pdgId() == 2 || part1->pdgId() == 4 || part2->pdgId() == 2 || part2->pdgId() == 4 ) {
-          isWPCand = true; /// W+ daughters should have a positive u or c
+          isWPCand = true;
         }
+        /// W+ daughters should have a positive u or c
         else {
-          isWMCand = true; /// W+ daughters should have a positive u or c
+          isWMCand = true;
         }
-        
-        break; /// If p1 is a daughter of W/Z decay, the next one is the other daughter
+
+        /// If p1 is a daughter of W/Z decay, the next one is the other daughter
+        break;
+
       }
 
       WZCand = p1 + p2;
 
+      /// ~98% efficiency to W/Z signals. (95% if it is changed to [65, 105]GeV and 90% if [70,100]GeV)
       if ( 60000 < WZCand.M() && WZCand.M() < 140000. ) {
         inMassWindow = true;
-        break; /// ~98% efficiency to W/Z signals. (95% if it is changed to [65, 105]GeV and 90% if [70,100]GeV)
+        break;
       }
 
     }
 
-    if( inMassWindow && (isWPCand || isWMCand || isZCand) ) {
+    if ( inMassWindow && (isWPCand || isWMCand || isZCand) ) {
       std::pair<TLorentzVector,int> WZ;
-      if(isZCand) {
+      if ( isZCand ) {
         WZ = std::make_pair(WZCand,23);
       }
-      if(isWPCand) {
+      if ( isWPCand ) {
         WZ = std::make_pair(WZCand,24);
       }
-      if(isWMCand) {
+      if ( isWMCand ) {
         WZ = std::make_pair(WZCand,-24);
       }
       tlvs.push_back(WZ);
@@ -468,26 +536,131 @@ void JetTruthLabelingTool::getTLVs(std::vector<std::pair<TLorentzVector,int> > &
 
   }
 
-  // Store W/Z/H bosons
-  for( const xAOD::TruthParticle* part : *truthBosons ){
-    if(!(selectTruthParticle(part,23) || selectTruthParticle(part,24) || selectTruthParticle(part,25))) continue;
-    tlvs.push_back(std::make_pair(part->p4(),part->pdgId())); /// Save 4-vector and pdgId
+  /// Store W/Z/H bosons
+  for ( const xAOD::TruthParticle* part : *truthBosons ) {
+    if ( !(selectTruthParticle(part,23) || selectTruthParticle(part,24) || selectTruthParticle(part,25)) ) continue;
+    /// Save 4-vector and pdgId
+    tlvs.push_back(std::make_pair(part->p4(),part->pdgId()));
   }
 
-  // Store top quarks
-  for( const xAOD::TruthParticle* part : *truthTop ){
-    if(!selectTruthParticle(part,6)) continue;
-    tlvs.push_back(std::make_pair(part->p4(),part->pdgId())); /// Save 4-vector and pdgId
+  /// Store top quarks
+  for ( const xAOD::TruthParticle* part : *truthTop ) {
+    if ( !selectTruthParticle(part,6) ) continue;
+    /// Save 4-vector and pdgId
+    tlvs.push_back(std::make_pair(part->p4(),part->pdgId()));
   }
 
 }
 
-bool JetTruthLabelingTool::selectTruthParticle(const xAOD::TruthParticle *tp, int pdgId) const {
-  if(std::abs(tp->pdgId())!=pdgId) return false;
-  for(unsigned int iChild = 0; iChild < tp->nChildren(); iChild++) {
+bool JetTruthLabelingTool::selectTruthParticle( const xAOD::TruthParticle *tp, int pdgId ) const {
+  if ( std::abs(tp->pdgId()) != pdgId ) return false;
+  for ( unsigned int iChild = 0; iChild < tp->nChildren(); iChild++ ) {
     const xAOD::TruthParticle *child = tp->child(iChild);
-    if(!child) continue;
-    if(child->pdgId() == tp->pdgId()) return false;
+    if ( !child ) continue;
+    if ( child->pdgId() == tp->pdgId() ) return false;
   }
   return true;
 }
+
+float JetTruthLabelingTool::getTopSplit23CutR21Precision( float pt ) const {
+
+  /// The functional form and parameters come from optimization studies:
+  /// https://indico.cern.ch/event/931498/contributions/3921872/attachments/2064188/3463746/JSS_25June.pdf
+
+  const float c0 = 3.3;
+  const float c1 = -6.98e-4;
+
+  float split23 = -1.0;
+
+  split23 = std::exp( c0 + c1 * pt );
+
+  return split23;
+}
+
+int JetTruthLabelingTool::getNGhostParticles( const xAOD::Jet &jet, std::string collection ) const {
+
+  int nMatchPart = 0;
+
+  if( !jet.getAttribute<int>( collection+"Count", nMatchPart ) ){
+
+    std::vector<const xAOD::TruthParticle*> ghostParts;
+    if( !jet.getAssociatedObjects<xAOD::TruthParticle>( collection, ghostParts ) ){      
+      ATH_MSG_ERROR( collection + " cannot be retrieved! Truth label definition might be wrong" );
+    } 
+    nMatchPart = ghostParts.size();
+  }
+
+  return nMatchPart;
+}
+
+int JetTruthLabelingTool::getLabel( const xAOD::Jet &jet, bool matchH, bool matchW, bool matchZ, bool matchTop ) const {
+
+  /// Find ghost associated B-hadrons
+  int nMatchB = getNGhostParticles( jet, "GhostBHadronsFinal" );
+  (*m_dec_NB)(jet) = nMatchB;
+
+  /// Booleans for containment selections
+  bool isHbb = false;
+  bool isTop = false;
+  bool isW = false;
+  bool isZ = false;
+
+  /// Use R21Consolidated definition
+  if ( m_truthLabelName == "R10TruthLabel_R21Consolidated" ) {
+    isHbb = ( nMatchB > 1 );
+    isTop = ( matchTop && nMatchB > 0 && jet.m() / 1000. > m_mLowTop );
+    isW = matchW && nMatchB == 0 && jet.m() / 1000. > m_mLowW && jet.m() / 1000. < m_mHighW;
+    isZ = matchZ && jet.m() / 1000. > m_mLowZ && jet.m() / 1000. < m_mHighZ;
+  }
+
+  /// Use R21Precision definition
+  if ( m_truthLabelName == "R10TruthLabel_R21Precision" ) {
+    isHbb = ( nMatchB > 1 );
+    isTop = ( matchTop && matchW && nMatchB > 0 && jet.m() / 1000. > m_mLowTop && (*m_acc_Split23)(jet) / 1000. > getTopSplit23CutR21Precision( jet.pt() / 1000. ) );
+    isW = matchW && nMatchB == 0 && jet.m() / 1000. > m_mLowW && jet.m() / 1000. < m_mHighW;
+    isZ = matchZ && jet.m() / 1000. > m_mLowZ && jet.m() / 1000. < m_mHighZ;
+  }
+
+  /// This method can be expanded to include custom label priorities
+
+  /* The default priority of labels is:
+   * 1) H
+   * 2) Contained top
+   * 3) Contained W
+   * 4) Contained Z
+   * 4) Uncontained top
+   * 5) Uncontained V
+   */
+
+  /// If it isn't matched to any heavy particles, is it QCD
+  if( !(matchTop || matchW || matchZ || matchH) ) {
+    return LargeRJetTruthLabel::enumToInt(LargeRJetTruthLabel::qcd);
+  }
+
+  if ( matchH ) {
+    /// Contained H->bb
+    if ( isHbb ) return LargeRJetTruthLabel::enumToInt(LargeRJetTruthLabel::Hbb);
+    /// Other from H
+    return LargeRJetTruthLabel::enumToInt(LargeRJetTruthLabel::other_From_H);
+  }
+
+  /// Contained top
+  if ( isTop ) return LargeRJetTruthLabel::enumToInt(LargeRJetTruthLabel::tqqb); 
+
+  if ( isW ) {
+    /// Contained W from a top
+    if ( matchTop ) return LargeRJetTruthLabel::enumToInt(LargeRJetTruthLabel::Wqq_From_t);
+    /// Contained W not from a top
+    return LargeRJetTruthLabel::enumToInt(LargeRJetTruthLabel::Wqq);
+  }
+
+  /// Contained Z
+  if ( isZ ) return LargeRJetTruthLabel::enumToInt(LargeRJetTruthLabel::Zqq);
+
+  /// Uncontained top
+  if ( matchTop ) return LargeRJetTruthLabel::enumToInt(LargeRJetTruthLabel::other_From_t); 
+
+  /// Uncontained V
+  return LargeRJetTruthLabel::enumToInt(LargeRJetTruthLabel::other_From_V);
+
+}
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10EMPFlowTrimmedPtFrac5SmallR20JetsCPContent.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10EMPFlowTrimmedPtFrac5SmallR20JetsCPContent.py
index 75733a6ec109b0974693adb2a8d1e94893777ddc..9e84335316c0cce65a871b9927c0da7960cfdd43 100644
--- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10EMPFlowTrimmedPtFrac5SmallR20JetsCPContent.py
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10EMPFlowTrimmedPtFrac5SmallR20JetsCPContent.py
@@ -5,7 +5,7 @@ AntiKt10EMPFlowTrimmedPtFrac5SmallR20JetsCPContent = [
 "AntiKt10EMPFlowTrimmedPtFrac5SmallR20JetsAux.JetConstitScaleMomentum_pt.JetConstitScaleMomentum_eta.JetConstitScaleMomentum_phi.JetConstitScaleMomentum_m",
 "AntiKt10EMPFlowTrimmedPtFrac5SmallR20JetsAux.ECF1.ECF2.ECF3.Tau1_wta.Tau2_wta.Tau3_wta.Split12.Split23.Qw.PlanarFlow.FoxWolfram2.FoxWolfram0.Angularity.Aplanarity.KtDR.ZCut12",
 "AntiKt10EMPFlowTrimmedPtFrac5SmallR20JetsAux.NTrimSubjets.Parent.DetectorEta.DetectorY",
-"AntiKt10EMPFlowTrimmedPtFrac5SmallR20JetsAux.R10TruthLabel_R21Consolidated",
+"AntiKt10EMPFlowTrimmedPtFrac5SmallR20JetsAux.R10TruthLabel_R21Consolidated.R10TruthLabel_R21Precision",
 "AntiKt10EMPFlowJets",
 "AntiKt10EMPFlowJetsAux.NumTrkPt500",
 "AntiKt10TruthTrimmedPtFrac5SmallR20Jets.pt.eta.phi.m.ECF1.ECF2.ECF3.Tau2_wta.Tau3_wta.Qw.GhostBHadronsFinalCount",
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10LCTopoCSSKSoftDropBeta100Zcut10JetsCPContent.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10LCTopoCSSKSoftDropBeta100Zcut10JetsCPContent.py
index 71891ba2dbd580616c99eca5963d51d0484b5817..d433103dc00ad8ae4882b137f27f5d418ac11368 100644
--- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10LCTopoCSSKSoftDropBeta100Zcut10JetsCPContent.py
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10LCTopoCSSKSoftDropBeta100Zcut10JetsCPContent.py
@@ -5,5 +5,5 @@ AntiKt10LCTopoCSSKSoftDropBeta100Zcut10JetsCPContent = [
 "AntiKt10LCTopoCSSKSoftDropBeta100Zcut10JetsAux.JetConstitScaleMomentum_pt.JetConstitScaleMomentum_eta.JetConstitScaleMomentum_phi.JetConstitScaleMomentum_m",
 "AntiKt10LCTopoCSSKSoftDropBeta100Zcut10JetsAux.ECF1.ECF2.ECF3.Tau1_wta.Tau2_wta.Tau3_wta.Split12.Split23.Qw.PlanarFlow.FoxWolfram2.FoxWolfram0.Angularity.Aplanarity.KtDR.ZCut12",
 "AntiKt10LCTopoCSSKSoftDropBeta100Zcut10JetsAux.Parent.DetectorEta.DetectorY",
-"AntiKt10LCTopoCSSKSoftDropBeta100Zcut10JetsAux.R10TruthLabel_R21Consolidated",
+"AntiKt10LCTopoCSSKSoftDropBeta100Zcut10JetsAux.R10TruthLabel_R21Consolidated.R10TruthLabel_R21Precision",
 ]
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10LCTopoTrimmedPtFrac5SmallR20JetsCPContent.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10LCTopoTrimmedPtFrac5SmallR20JetsCPContent.py
index 2a768d3aacf55aa120e181cc61063174bc24749b..38c0669bfed8dbf9e63867e09fe9eb6ccab20cfb 100644
--- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10LCTopoTrimmedPtFrac5SmallR20JetsCPContent.py
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10LCTopoTrimmedPtFrac5SmallR20JetsCPContent.py
@@ -6,7 +6,7 @@ AntiKt10LCTopoTrimmedPtFrac5SmallR20JetsCPContent = [
 "AntiKt10LCTopoTrimmedPtFrac5SmallR20JetsAux.ECF1.ECF2.ECF3.Tau1_wta.Tau2_wta.Tau3_wta.Split12.Split23.Qw.PlanarFlow.FoxWolfram2.FoxWolfram0.Angularity.Aplanarity.KtDR.ZCut12",
 "AntiKt10LCTopoTrimmedPtFrac5SmallR20JetsAux.NTrimSubjets.Parent.TrackSumPt.TrackSumMass.DetectorEta.DetectorY",
 "AntiKt10LCTopoTrimmedPtFrac5SmallR20JetsAux.GhostAntiKt2TrackJet.GhostBHadronsFinalCount",
-"AntiKt10LCTopoTrimmedPtFrac5SmallR20JetsAux.R10TruthLabel_R21Consolidated",
+"AntiKt10LCTopoTrimmedPtFrac5SmallR20JetsAux.R10TruthLabel_R21Consolidated.R10TruthLabel_R21Precision",
 "AntiKt10LCTopoJets",
 "AntiKt10LCTopoJetsAux.GhostAntiKt2TrackJet.GhostVR30Rmax4Rmin02TrackJet.GhostVR30Rmax4Rmin02TrackJetGhostTag.GhostVR30Rmax4Rmin02TrackJet_BTagging201810.GhostVR30Rmax4Rmin02TrackJet_BTagging201810GhostTag.GhostVR30Rmax4Rmin02TrackJet_BTagging201903.NumTrkPt500",
 "AntiKt10TruthTrimmedPtFrac5SmallR20Jets.pt.eta.phi.m.ECF1.ECF2.ECF3.Tau2_wta.Tau3_wta.Qw.GhostBHadronsFinalCount",
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10TrackCaloClusterTrimmedPtFrac5SmallR20JetsCPContent.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10TrackCaloClusterTrimmedPtFrac5SmallR20JetsCPContent.py
index fbcfe42a53fbf4c6676537c000a61416de27115c..2aa637dd685054d42d6c3c6e7a71867bf3fa20c8 100644
--- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10TrackCaloClusterTrimmedPtFrac5SmallR20JetsCPContent.py
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10TrackCaloClusterTrimmedPtFrac5SmallR20JetsCPContent.py
@@ -6,7 +6,7 @@ AntiKt10TrackCaloClusterTrimmedPtFrac5SmallR20JetsCPContent = [
 "AntiKt10TrackCaloClusterTrimmedPtFrac5SmallR20JetsAux.ECF1.ECF2.ECF3.Tau1_wta.Tau2_wta.Tau3_wta.Split12.Split23.Qw.PlanarFlow.FoxWolfram2.FoxWolfram0.Angularity.Aplanarity.KtDR.ZCut12",
 "AntiKt10TrackCaloClusterTrimmedPtFrac5SmallR20JetsAux.NTrimSubjets.Parent.DetectorEta.DetectorY",
 "AntiKt10TrackCaloClusterTrimmedPtFrac5SmallR20JetsAux.GhostAntiKt2TrackJet.GhostBHadronsFinalCount",
-"AntiKt10TrackCaloClusterTrimmedPtFrac5SmallR20JetsAux.R10TruthLabel_R21Consolidated",
+"AntiKt10TrackCaloClusterTrimmedPtFrac5SmallR20JetsAux.R10TruthLabel_R21Consolidated.R10TruthLabel_R21Precision",
 "AntiKt10TrackCaloClusterJets",
 "AntiKt10TrackCaloClusterJetsAux.GhostAntiKt2TrackJet.GhostVR30Rmax4Rmin02TrackJet.NumTrkPt500",
 "AntiKt10TruthTrimmedPtFrac5SmallR20Jets.pt.eta.phi.m.ECF1.ECF2.ECF3.Tau2_wta.Tau3_wta.Qw.GhostBHadronsFinalCount",
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10TruthJetsCPContent.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10TruthJetsCPContent.py
index 698abaf7c970b02d9943422d2c542c555b404b75..e2145b1d415ea23076d8ecf11b8d7ab0beaa3f5e 100644
--- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10TruthJetsCPContent.py
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10TruthJetsCPContent.py
@@ -5,4 +5,5 @@ AntiKt10TruthJetsCPContent = [
 "AntiKt10TruthJetsAux.PartonTruthLabelID",
 "AntiKt10TruthJetsAux.GhostBHadronsFinal.GhostBHadronsFinalCount.GhostTQuarksFinal.GhostTQuarksFinalCount",
 "AntiKt10TruthJetsAux.GhostHBosons.GhostHBosonsCount.GhostWBosons.GhostWBosonsCount.GhostZBosons.GhostZBosonsCount",
+"AntiKt10TruthJetsAux.R10TruthLabel_R21Precision",
 ]
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10UFOCHSSoftDropBeta100Zcut10JetsCPContent.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10UFOCHSSoftDropBeta100Zcut10JetsCPContent.py
index fffec50d0a8b3a79015aa5e4e757bd2bb00588e6..7079bccaef1f74b3311379088958a303d94b5043 100644
--- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10UFOCHSSoftDropBeta100Zcut10JetsCPContent.py
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10UFOCHSSoftDropBeta100Zcut10JetsCPContent.py
@@ -5,7 +5,7 @@ AntiKt10UFOCHSSoftDropBeta100Zcut10JetsCPContent = [
 "AntiKt10UFOCHSSoftDropBeta100Zcut10JetsAux.JetConstitScaleMomentum_pt.JetConstitScaleMomentum_eta.JetConstitScaleMomentum_phi.JetConstitScaleMomentum_m",
 "AntiKt10UFOCHSSoftDropBeta100Zcut10JetsAux.ECF1.ECF2.ECF3.Tau1_wta.Tau2_wta.Tau3_wta.Split12.Split23.Qw.PlanarFlow.FoxWolfram2.FoxWolfram0.Angularity.Aplanarity.KtDR.ZCut12",
 "AntiKt10UFOCHSSoftDropBeta100Zcut10JetsAux.Parent.DetectorEta.DetectorY",
-"AntiKt10UFOCHSSoftDropBeta100Zcut10JetsAux.R10TruthLabel_R21Consolidated",
+"AntiKt10UFOCHSSoftDropBeta100Zcut10JetsAux.R10TruthLabel_R21Consolidated.R10TruthLabel_R21Precision",
 "AntiKt10UFOCHSJets",
 "AntiKt10UFOCHSJetsAux.NumTrkPt500",
 "AntiKt10TruthSoftDropBeta100Zcut10Jets.pt.eta.phi.m.ECF1.ECF2.ECF3.Tau2_wta.Tau3_wta.Qw.GhostBHadronsFinalCount",
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10UFOCHSTrimmedPtFrac5SmallR20JetsCPContent.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10UFOCHSTrimmedPtFrac5SmallR20JetsCPContent.py
index d1f9a68e357f20eefa342c2f7e66b77102e793bd..15e6bc6ddfa9d96c8cdd6c6ea7172803f7d74179 100644
--- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10UFOCHSTrimmedPtFrac5SmallR20JetsCPContent.py
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10UFOCHSTrimmedPtFrac5SmallR20JetsCPContent.py
@@ -5,7 +5,7 @@ AntiKt10UFOCHSTrimmedPtFrac5SmallR20JetsCPContent = [
 "AntiKt10UFOCHSTrimmedPtFrac5SmallR20JetsAux.JetConstitScaleMomentum_pt.JetConstitScaleMomentum_eta.JetConstitScaleMomentum_phi.JetConstitScaleMomentum_m",
 "AntiKt10UFOCHSTrimmedPtFrac5SmallR20JetsAux.ECF1.ECF2.ECF3.Tau1_wta.Tau2_wta.Tau3_wta.Split12.Split23.Qw.PlanarFlow.FoxWolfram2.FoxWolfram0.Angularity.Aplanarity.KtDR.ZCut12",
 "AntiKt10UFOCHSTrimmedPtFrac5SmallR20JetsAux.NTrimSubjets.Parent.DetectorEta.DetectorY",
-"AntiKt10UFOCHSTrimmedPtFrac5SmallR20JetsAux.R10TruthLabel_R21Consolidated",
+"AntiKt10UFOCHSTrimmedPtFrac5SmallR20JetsAux.R10TruthLabel_R21Consolidated.R10TruthLabel_R21Precision",
 "AntiKt10UFOCHSJets",
 "AntiKt10UFOCHSJetsAux.NumTrkPt500",
 "AntiKt10TruthTrimmedPtFrac5SmallR20Jets.pt.eta.phi.m.ECF1.ECF2.ECF3.Tau2_wta.Tau3_wta.Qw.GhostBHadronsFinalCount",
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10UFOCSSKBottomUpSoftDropBeta100Zcut5JetsCPContent.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10UFOCSSKBottomUpSoftDropBeta100Zcut5JetsCPContent.py
index 027cd8ee0cc52645aa09b0b71e90de1b3c8ceb96..5efa31bcb28196095047a27f1d78d7a2ac122b7a 100644
--- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10UFOCSSKBottomUpSoftDropBeta100Zcut5JetsCPContent.py
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10UFOCSSKBottomUpSoftDropBeta100Zcut5JetsCPContent.py
@@ -5,7 +5,7 @@ AntiKt10UFOCSSKBottomUpSoftDropBeta100Zcut5JetsCPContent = [
 "AntiKt10UFOCSSKBottomUpSoftDropBeta100Zcut5JetsAux.JetConstitScaleMomentum_pt.JetConstitScaleMomentum_eta.JetConstitScaleMomentum_phi.JetConstitScaleMomentum_m",
 "AntiKt10UFOCSSKBottomUpSoftDropBeta100Zcut5JetsAux.ECF1.ECF2.ECF3.Tau1_wta.Tau2_wta.Tau3_wta.Split12.Split23.Qw.PlanarFlow.FoxWolfram2.FoxWolfram0.Angularity.Aplanarity.KtDR.ZCut12",
 "AntiKt10UFOCSSKBottomUpSoftDropBeta100Zcut5JetsAux.Parent.DetectorEta.DetectorY",
-"AntiKt10UFOCSSKBottomUpSoftDropBeta100Zcut5JetsAux.R10TruthLabel_R21Consolidated",
+"AntiKt10UFOCSSKBottomUpSoftDropBeta100Zcut5JetsAux.R10TruthLabel_R21Consolidated.R10TruthLabel_R21Precision",
 "AntiKt10UFOCSSKJets",
 "AntiKt10UFOCSSKJetsAux.NumTrkPt500",
 "AntiKt10TruthBottomUpSoftDropBeta100Zcut5Jets.pt.eta.phi.m.ECF1.ECF2.ECF3.Tau2_wta.Tau3_wta.Qw.GhostBHadronsFinalCount",
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10UFOCSSKRecursiveSoftDropBeta100Zcut5NinfJetsCPContent.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10UFOCSSKRecursiveSoftDropBeta100Zcut5NinfJetsCPContent.py
index 05af8c71cd1670c770038dd91c81d348f854bee8..390c8d28f1270cbed55df3749d9af9e9bf5cb276 100644
--- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10UFOCSSKRecursiveSoftDropBeta100Zcut5NinfJetsCPContent.py
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10UFOCSSKRecursiveSoftDropBeta100Zcut5NinfJetsCPContent.py
@@ -5,7 +5,7 @@ AntiKt10UFOCSSKRecursiveSoftDropBeta100Zcut5NinfJetsCPContent = [
 "AntiKt10UFOCSSKRecursiveSoftDropBeta100Zcut5NinfJetsAux.JetConstitScaleMomentum_pt.JetConstitScaleMomentum_eta.JetConstitScaleMomentum_phi.JetConstitScaleMomentum_m",
 "AntiKt10UFOCSSKRecursiveSoftDropBeta100Zcut5NinfJetsAux.ECF1.ECF2.ECF3.Tau1_wta.Tau2_wta.Tau3_wta.Split12.Split23.Qw.PlanarFlow.FoxWolfram2.FoxWolfram0.Angularity.Aplanarity.KtDR.ZCut12",
 "AntiKt10UFOCSSKRecursiveSoftDropBeta100Zcut5NinfJetsAux.Parent.DetectorEta.DetectorY",
-"AntiKt10UFOCSSKRecursiveSoftDropBeta100Zcut5NinfJetsAux.R10TruthLabel_R21Consolidated",
+"AntiKt10UFOCSSKRecursiveSoftDropBeta100Zcut5NinfJetsAux.R10TruthLabel_R21Consolidated.R10TruthLabel_R21Precision",
 "AntiKt10UFOCSSKJets",
 "AntiKt10UFOCSSKJetsAux.NumTrkPt500",
 "AntiKt10TruthRecursiveSoftDropBeta100Zcut5NinfJets.pt.eta.phi.m.ECF1.ECF2.ECF3.Tau2_wta.Tau3_wta.Qw.GhostBHadronsFinalCount",
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10UFOCSSKSoftDropBeta100Zcut10JetsCPContent.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10UFOCSSKSoftDropBeta100Zcut10JetsCPContent.py
index fe124c35e316f50bb6dfd9d90d4aba5b0242a95b..d19db4f14131f75282acb4df1e218dacf875639c 100644
--- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10UFOCSSKSoftDropBeta100Zcut10JetsCPContent.py
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10UFOCSSKSoftDropBeta100Zcut10JetsCPContent.py
@@ -5,7 +5,7 @@ AntiKt10UFOCSSKSoftDropBeta100Zcut10JetsCPContent = [
 "AntiKt10UFOCSSKSoftDropBeta100Zcut10JetsAux.JetConstitScaleMomentum_pt.JetConstitScaleMomentum_eta.JetConstitScaleMomentum_phi.JetConstitScaleMomentum_m",
 "AntiKt10UFOCSSKSoftDropBeta100Zcut10JetsAux.ECF1.ECF2.ECF3.Tau1_wta.Tau2_wta.Tau3_wta.Split12.Split23.Qw.PlanarFlow.FoxWolfram2.FoxWolfram0.Angularity.Aplanarity.KtDR.ZCut12",
 "AntiKt10UFOCSSKSoftDropBeta100Zcut10JetsAux.Parent.DetectorEta.DetectorY",
-"AntiKt10UFOCSSKSoftDropBeta100Zcut10JetsAux.R10TruthLabel_R21Consolidated",
+"AntiKt10UFOCSSKSoftDropBeta100Zcut10JetsAux.R10TruthLabel_R21Consolidated.R10TruthLabel_R21Precision",
 "AntiKt10UFOCSSKJets",
 "AntiKt10UFOCSSKJetsAux.NumTrkPt500",
 "AntiKt10TruthSoftDropBeta100Zcut10Jets.pt.eta.phi.m.ECF1.ECF2.ECF3.Tau2_wta.Tau3_wta.Qw.GhostBHadronsFinalCount",
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10UFOCSSKTrimmedPtFrac5SmallR20JetsCPContent.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10UFOCSSKTrimmedPtFrac5SmallR20JetsCPContent.py
index fe78c2a57b489fd9d2e90a467682811607fa44e7..3876891fa3e031a5339981f7f887ef6acb3b3a7d 100644
--- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10UFOCSSKTrimmedPtFrac5SmallR20JetsCPContent.py
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/AntiKt10UFOCSSKTrimmedPtFrac5SmallR20JetsCPContent.py
@@ -5,7 +5,7 @@ AntiKt10UFOCSSKTrimmedPtFrac5SmallR20JetsCPContent = [
 "AntiKt10UFOCSSKTrimmedPtFrac5SmallR20JetsAux.JetConstitScaleMomentum_pt.JetConstitScaleMomentum_eta.JetConstitScaleMomentum_phi.JetConstitScaleMomentum_m",
 "AntiKt10UFOCSSKTrimmedPtFrac5SmallR20JetsAux.ECF1.ECF2.ECF3.Tau1_wta.Tau2_wta.Tau3_wta.Split12.Split23.Qw.PlanarFlow.FoxWolfram2.FoxWolfram0.Angularity.Aplanarity.KtDR.ZCut12",
 "AntiKt10UFOCSSKTrimmedPtFrac5SmallR20JetsAux.NTrimSubjets.Parent.DetectorEta.DetectorY",
-"AntiKt10UFOCSSKTrimmedPtFrac5SmallR20JetsAux.R10TruthLabel_R21Consolidated",
+"AntiKt10UFOCSSKTrimmedPtFrac5SmallR20JetsAux.R10TruthLabel_R21Consolidated.R10TruthLabel_R21Precision",
 "AntiKt10UFOCSSKJets",
 "AntiKt10UFOCSSKJetsAux.NumTrkPt500",
 "AntiKt10TruthTrimmedPtFrac5SmallR20Jets.pt.eta.phi.m.ECF1.ECF2.ECF3.Tau2_wta.Tau3_wta.Qw.GhostBHadronsFinalCount",
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/ExtendedJetCommon.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/ExtendedJetCommon.py
index 608b87894bb5b1fc2a2d845491679332ecfdc902..739e6b3bfa324ad820e6d6ab9fc5214100b03dc3 100644
--- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/ExtendedJetCommon.py
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/ExtendedJetCommon.py
@@ -115,12 +115,12 @@ def addAntiKt4TruthDressedWZJets(sequence,outputlist):
         addStandardJets("AntiKt", 0.4, "TruthDressedWZ", ptmin=5000, mods="truth_ungroomed", algseq=sequence, outputGroup=outputlist)
 
 def addAntiKt10TruthJets(sequence,outputlist):
-    if DerivationFrameworkIsMonteCarlo:
-        addStandardJets("AntiKt", 1.0, "Truth", ptmin=40000, mods="truth_ungroomed", algseq=sequence, outputGroup=outputlist)
+    if DerivationFrameworkHasTruth:
+        addStandardJets("AntiKt", 1.0, "Truth", ptmin=40000, mods="truth_ungroomed_larger", algseq=sequence, outputGroup=outputlist)
 
 def addAntiKt10TruthWZJets(sequence,outputlist):
-    if DerivationFrameworkIsMonteCarlo:
-        addStandardJets("AntiKt", 1.0, "TruthWZ", ptmin=40000, mods="truth_ungroomed", algseq=sequence, outputGroup=outputlist)
+    if DerivationFrameworkHasTruth:
+        addStandardJets("AntiKt", 1.0, "TruthWZ", ptmin=40000, mods="truth_ungroomed_larger", algseq=sequence, outputGroup=outputlist)
 
 def addAntiKt4EMPFlowJetsFE(sequence, outputlist):
     addCHSPFlowObjectsFE()
@@ -409,8 +409,8 @@ def addJetPtAssociation(jetalg, truthjetalg, sequence, algname):
 ##################################################################
 
 def addJetTruthLabel(jetalg,algname,labelname,sequence):
-    supportedLabelNames = ['R10TruthLabel_R21Consolidated']
-    supportedTruthJets = ['AntiKt10TruthTrimmedPtFrac5SmallR20']
+    supportedLabelNames = ['R10TruthLabel_R21Consolidated','R10TruthLabel_R21Precision']
+    supportedTruthJets = ['AntiKt10Truth','AntiKt10TruthTrimmedPtFrac5SmallR20']
     supportedRecoJets = ['AntiKt10LCTopoTrimmedPtFrac5SmallR20','AntiKt10TrackCaloClusterTrimmedPtFrac5SmallR20','AntiKt10UFOCSSKTrimmedPtFrac5SmallR20','AntiKt10UFOCSSKSoftDropBeta100Zcut10','AntiKt10UFOCSSKBottomUpSoftDropBeta100Zcut5','AntiKt10UFOCSSKRecursiveSoftDropBeta100Zcut5Ninf','AntiKt10UFOCHSTrimmedPtFrac5SmallR20']
     supportedJets = supportedRecoJets + supportedTruthJets
     if not jetalg in supportedJets:
@@ -779,26 +779,6 @@ def addCHSPFlowObjects():
             job.jetalg.Tools.append(jtm.jetconstitCHSPFlow)
             extjetlog.info("Added CHS PFlow sequence to \'jetalg\'")
             extjetlog.info(job.jetalg.Tools)
-
-def addCHSPFlowObjectsFE():
-    # Only act if the collection does not already exist
-    from RecExConfig.AutoConfiguration import IsInInputFile
-    if not IsInInputFile("xAOD::FlowElementContainer","CHSFlowElements"):
-        # Check that an alg doing this has not already been inserted
-        from AthenaCommon.AlgSequence import AlgSequence
-        job = AlgSequence()
-        from JetRec.JetRecStandard import jtm
-        if not hasattr(job,"jetalgCHSPFlowFE") and not hasattr(jtm,"jetconstitCHSPFlowFE"):
-            from JetRec.JetRecConf import JetToolRunner
-            jtm += JetToolRunner("jetconstitCHSPFlowFE",
-                                 EventShapeTools=[],
-                                 Tools=[jtm.JetConstitSeq_PFlowCHS_FE])
-            # Add this tool runner to the JetAlgorithm instance "jetalg"
-            # which runs all preparatory tools
-            # This was added by JetCommon
-            job.jetalg.Tools.append(jtm.jetconstitCHSPFlowFE)
-            extjetlog.info("Added CHS PFlow (FlowElement) sequence to \'jetalg\'")
-            extjetlog.info(job.jetalg.Tools)
 ##################################################################
 applyJetCalibration_xAODColl("AntiKt4EMTopo")
 updateJVT_xAODColl("AntiKt4EMTopo")
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/share/JETM6.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/share/JETM6.py
index 64dd2e7ef538a86a000bd356b9e94b065d652f87..9013ca9aaceff1865e98cd7caa9908b657fb062c 100644
--- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/share/JETM6.py
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/share/JETM6.py
@@ -339,6 +339,7 @@ for alg in largeRJetAlgs:
 if DerivationFrameworkIsMonteCarlo:
   for alg in largeRJetAlgs:
     addJetTruthLabel(jetalg=alg,sequence=jetm6Seq,algname="JetTruthLabelingAlg",labelname="R10TruthLabel_R21Consolidated")
+    addJetTruthLabel(jetalg=alg,sequence=jetm6Seq,algname="JetTruthLabelingAlg",labelname="R10TruthLabel_R21Precision")
 
 addVRJets(jetm6Seq, largeRColls = largeRJetCollections)
 addVRJets(jetm6Seq, largeRColls = largeRJetCollections, training='201903')
@@ -404,6 +405,7 @@ JETM6SlimmingHelper.AllVariables = [
 JETM6SlimmingHelper.ExtraVariables  = ['CaloCalTopoClusters.calE.calEta.calM.calPhi.CENTER_MAG']
 JETM6SlimmingHelper.ExtraVariables += ['Electrons.'+NewTrigVars["Electrons"],'Muons.'+NewTrigVars["Muons"],'Photons.'+NewTrigVars["Photons"]]
 JETM6SlimmingHelper.ExtraVariables += [
+    'AntiKt10TruthJets.Split12.Split23',
     'HLT_xAOD__JetContainer_a4tcemsubjesFS.ActiveArea.ActiveArea4vec_eta.ActiveArea4vec_m.ActiveArea4vec_phi.ActiveArea4vec_pt.AverageLArQF.BchCorrCell.CentroidR.DetectorEta.EMFrac.EnergyPerSampling.FracSamplingMax.FracSamplingMaxIndex.HECFrac.HECQuality.JetConstitScaleMomentum_eta.JetConstitScaleMomentum_m.JetConstitScaleMomentum_phi.JetConstitScaleMomentum_pt.JetEtaJESScaleMomentum_eta.JetEtaJESScaleMomentum_m.JetEtaJESScaleMomentum_phi.JetEtaJESScaleMomentum_pt.JetPileupScaleMomentum_eta.JetPileupScaleMomentum_m.JetPileupScaleMomentum_phi.JetPileupScaleMomentum_pt.LArQuality.N90Constituents.NegativeE.Timing.eta.kinematics.m.phi.pt',
     'HLT_xAOD__JetContainer_a4tcemsubjesISFS.ActiveArea.ActiveArea4vec_eta.ActiveArea4vec_m.ActiveArea4vec_phi.ActiveArea4vec_pt.AverageLArQF.BchCorrCell.CentroidR.DetectorEta.EMFrac.EnergyPerSampling.FracSamplingMax.FracSamplingMaxIndex.HECFrac.HECQuality.JetConstitScaleMomentum_eta.JetConstitScaleMomentum_m.JetConstitScaleMomentum_phi.JetConstitScaleMomentum_pt.JetEtaJESScaleMomentum_eta.JetEtaJESScaleMomentum_m.JetEtaJESScaleMomentum_phi.JetEtaJESScaleMomentum_pt.JetPileupScaleMomentum_eta.JetPileupScaleMomentum_m.JetPileupScaleMomentum_phi.JetPileupScaleMomentum_pt.LArQuality.N90Constituents.NegativeE.Timing.eta.kinematics.m.phi.pt',
     'HLT_xAOD__JetContainer_a10tclcwsubjesFS.ActiveArea.ActiveArea4vec_eta.ActiveArea4vec_m.ActiveArea4vec_phi.ActiveArea4vec_pt.AverageLArQF.BchCorrCell.CentroidR.DetectorEta.EMFrac.EnergyPerSampling.FracSamplingMax.FracSamplingMaxIndex.HECFrac.HECQuality.JetConstitScaleMomentum_eta.JetConstitScaleMomentum_m.JetConstitScaleMomentum_phi.JetConstitScaleMomentum_pt.JetEMScaleMomentum_eta.JetEMScaleMomentum_m.JetEMScaleMomentum_phi.JetEMScaleMomentum_pt.JetEtaJESScaleMomentum_eta.JetEtaJESScaleMomentum_m.JetEtaJESScaleMomentum_phi.JetEtaJESScaleMomentum_pt.JetPileupScaleMomentum_eta.JetPileupScaleMomentum_m.JetPileupScaleMomentum_phi.JetPileupScaleMomentum_pt.LArQuality.N90Constituents.NegativeE.Timing.eta.kinematics.m.phi.pt',
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/share/JETM8.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/share/JETM8.py
index db856c075f4858737a44bd758ba179060b8116ad..d665c01aa80fa7a07508e6418b14f29cc3b95a03 100644
--- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/share/JETM8.py
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/share/JETM8.py
@@ -210,6 +210,7 @@ for alg in largeRJetAlgs:
 if DerivationFrameworkIsMonteCarlo:
   for alg in largeRJetAlgs:
     addJetTruthLabel(jetalg=alg,sequence=jetm8Seq,algname="JetTruthLabelingAlg",labelname="R10TruthLabel_R21Consolidated")
+    addJetTruthLabel(jetalg=alg,sequence=jetm8Seq,algname="JetTruthLabelingAlg",labelname="R10TruthLabel_R21Precision")
 
 # Add VR track jets for b-tagging
 addVRJets(jetm8Seq, largeRJetCollections)
@@ -300,6 +301,8 @@ JETM8SlimmingHelper.AppendToDictionary["CSSKUFOAux"] = "xAOD::TrackCaloClusterAu
 JETM8SlimmingHelper.ExtraVariables += ["CSSKUFO.pt.eta.phi.taste"]
 JETM8SlimmingHelper.ExtraVariables += ['AntiKt10LCTopoJets.SizeParameter',
                                        'AntiKt10TruthJets.SizeParameter',
+                                       'AntiKt10TruthJets.Split12',
+                                       'AntiKt10TruthJets.Split23',
                                        'AntiKt10TrackCaloClusterJets.SizeParameter',
                                        'AntiKt10UFOCSSKJets.SizeParameter',
                                        'AntiKt10LCTopoTrimmedPtFrac5SmallR20Jets.SizeParameter',
diff --git a/Reconstruction/Jet/JetRec/python/JetRecStandardToolManager.py b/Reconstruction/Jet/JetRec/python/JetRecStandardToolManager.py
index 971154b1de1448b329c7b0d889f4682aac71e295..4c1f68fb192209aa4b83c269981c2ba01199bbbe 100644
--- a/Reconstruction/Jet/JetRec/python/JetRecStandardToolManager.py
+++ b/Reconstruction/Jet/JetRec/python/JetRecStandardToolManager.py
@@ -197,6 +197,11 @@ if jetFlags.useTruth():
   if jtm.haveParticleJetTools:
     truth_ungroomed_modifiers += [jtm.jetdrlabeler]
 
+  # Modifiers for ungroomed truth large-R jets
+  truth_ungroomed_larger_modifiers = truth_ungroomed_modifiers
+  # Add splitting scale modifiers for truth labeling
+  truth_ungroomed_larger_modifiers += [jtm.ktsplitter]
+
 # Modifiers for track jets.
 track_ungroomed_modifiers = list(common_ungroomed_modifiers)
 if jetFlags.useTruth() and jtm.haveParticleJetTools:
@@ -340,9 +345,10 @@ jtm.modifiersMap["lctopo_reduced"]        =       list(lctopo_reduced_modifiers)
 jtm.modifiersMap["pflow_reduced"]         =        list(pflow_reduced_modifiers)
 
 if jetFlags.useTruth():
-  jtm.modifiersMap["truth_ungroomed"]     =      list(truth_ungroomed_modifiers)
-  jtm.modifiersMap["truth_groomed"]       =      list(truth_groomed_modifiers)
-jtm.modifiersMap["track_ungroomed"]       =      list(track_ungroomed_modifiers)
+  jtm.modifiersMap["truth_ungroomed"]        =      list(truth_ungroomed_modifiers)
+  jtm.modifiersMap["truth_ungroomed_larger"] =      list(truth_ungroomed_larger_modifiers)
+  jtm.modifiersMap["truth_groomed"]          =      list(truth_groomed_modifiers)
+jtm.modifiersMap["track_ungroomed"]          =      list(track_ungroomed_modifiers)
 
 # Also index modifier type names by input type name.
 # These are used when the modifier list is omitted.