diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkTau/DerivationFrameworkTau/TauPVTrkSelectionTool.h b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkTau/DerivationFrameworkTau/TauPVTrkSelectionTool.h
index 96a650ba4f9e30918292abc8d6df84241b89a002..7cf7f3b3224617eb68a984a014f1c3f29c62108c 100644
--- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkTau/DerivationFrameworkTau/TauPVTrkSelectionTool.h
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkTau/DerivationFrameworkTau/TauPVTrkSelectionTool.h
@@ -44,8 +44,7 @@ namespace DerivationFramework {
       bool m_maxDeltaR;
       bool m_minPt;
 
-#warning FIXME: ToolHandle constness workaround.
-      mutable ToolHandle < TauAnalysisTools::ITauTruthTrackMatchingTool > m_T3MT;
+      ToolHandle < TauAnalysisTools::ITauTruthTrackMatchingTool > m_T3MT;
 
       StatusCode select(xAOD::TrackParticleContainer*& tauPVTracks) const;
 
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkTau/DerivationFrameworkTau/TauTruthMatchingWrapper.h b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkTau/DerivationFrameworkTau/TauTruthMatchingWrapper.h
index 176f524e326348caa4ec6d24359bf44dd22a5bd1..1991d85eaff50d6f67225a3694a805f5946f3966 100644
--- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkTau/DerivationFrameworkTau/TauTruthMatchingWrapper.h
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkTau/DerivationFrameworkTau/TauTruthMatchingWrapper.h
@@ -34,8 +34,7 @@ namespace DerivationFramework {
     private:
       std::string m_tauContainerName;
 
-#warning FIXME mutable to work around ToolHandle constness problem.
-      mutable ToolHandle < TauAnalysisTools::ITauTruthMatchingTool > m_tTauTruthMatchingTool;
+      ToolHandle < TauAnalysisTools::ITauTruthMatchingTool > m_tTauTruthMatchingTool;
 
   }; 
 }
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkTau/src/TauPVTrkSelectionTool.cxx b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkTau/src/TauPVTrkSelectionTool.cxx
index 56094f39e1cb8f835457a38653e50b50b268062c..17da08df363fbe3cc501873409c16884b4ed4c7e 100644
--- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkTau/src/TauPVTrkSelectionTool.cxx
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkTau/src/TauPVTrkSelectionTool.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
 */
 
 ///////////////////////////////////////////////////////////////////
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkTau/src/TauTruthMatchingWrapper.cxx b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkTau/src/TauTruthMatchingWrapper.cxx
index d0b30688c1348341e6caa968abb036c07a1797c4..c0f3cbf1bfb2bf7575d78137ab0862d6a4382e64 100644
--- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkTau/src/TauTruthMatchingWrapper.cxx
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkTau/src/TauTruthMatchingWrapper.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
 */
 
 ///////////////////////////////////////////////////////////////////
@@ -44,8 +44,10 @@ namespace DerivationFramework {
       return StatusCode::FAILURE;
     }
 
+    std::unique_ptr<TauAnalysisTools::ITauTruthMatchingTool::ITruthTausEvent>
+      truthTausEvent = m_tTauTruthMatchingTool->getEvent();
     for(auto xTau : *xTauContainer)
-      m_tTauTruthMatchingTool->applyTruthMatch(*xTau);
+      m_tTauTruthMatchingTool->getTruth(*xTau, *truthTausEvent);
     
     return StatusCode::SUCCESS;
   }  
diff --git a/PhysicsAnalysis/TauID/TauAnalysisTools/Root/BuildTruthTaus.cxx b/PhysicsAnalysis/TauID/TauAnalysisTools/Root/BuildTruthTaus.cxx
index 5de189b789a82dcc1814889b1846ff4af1e58504..7fbd99e53ba36526b53ea1ad9e8cf86fd1c9f3fb 100644
--- a/PhysicsAnalysis/TauID/TauAnalysisTools/Root/BuildTruthTaus.cxx
+++ b/PhysicsAnalysis/TauID/TauAnalysisTools/Root/BuildTruthTaus.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
 */
 
 // Local include(s)
@@ -27,26 +27,10 @@ BuildTruthTaus::BuildTruthTaus( const std::string& name )
   , m_bIsData(false)
   , m_bIsConfigured(false)
   , m_bTruthTauAvailable(true)
-  , m_xTruthTauContainerConst(0)
-  , m_xTruthMuonContainerConst(0)
-  , m_xTruthElectronContainerConst(0)
-  , m_xTruthJetContainerConst(0)
-  , m_xTruthTauContainer(0)
-  , m_bIsTruthMatchedAvailable(false)
-  , m_bIsTruthMatchedAvailableChecked(false)
-  , m_bNewEvent(false)
-  , m_xTruthParticleContainer(0)
-  , m_xTruthTauAuxContainer(0)
   , m_sNewTruthTauContainerNameAux("TruthTausAux.")
   , m_bTruthMuonAvailable(true)
   , m_bTruthElectronAvailable(true)
   , m_bTruthJetAvailable(true)
-  , m_iNChargedPions(0)
-  , m_iNNeutralPions(0)
-  , m_iNChargedOthers(0)
-  , m_iNNeutralOthers(0)
-  , m_iNChargedDaughters(0)
-  , m_bIsHadronicTau(false)
   , m_tMCTruthClassifier("MCTruthClassifier", this)
 {
   declareProperty( "WriteTruthTaus", m_bWriteTruthTaus = false);
@@ -89,7 +73,7 @@ xAOD::TruthParticleContainer* BuildTruthTaus::getTruthTauContainer()
   if (m_bIsData)
     return 0;
   if (!m_bTruthTauAvailable)
-    return m_xTruthTauContainer;
+    return m_truthTausEvent.m_xTruthTauContainer;
   else
   {
     ATH_MSG_WARNING("TruthTau container was available from the event store and not rebuilt. Please get it from the event store");
@@ -103,7 +87,7 @@ xAOD::TruthParticleAuxContainer* BuildTruthTaus::getTruthTauAuxContainer()
   if (m_bIsData)
     return 0;
   if (!m_bTruthTauAvailable)
-    return m_xTruthTauAuxContainer;
+    return m_truthTausEvent.m_xTruthTauAuxContainer;
   else
   {
     ATH_MSG_WARNING("TruthTau auxiliary container was available from the event store and not rebuilt. Please get it from the event store");
@@ -114,7 +98,7 @@ xAOD::TruthParticleAuxContainer* BuildTruthTaus::getTruthTauAuxContainer()
 //______________________________________________________________________________
 StatusCode BuildTruthTaus::beginEvent()
 {
-  m_bNewEvent = true;
+  m_truthTausEvent.m_valid = false;
   if (m_bIsConfigured)
     return StatusCode::SUCCESS;
 
@@ -127,19 +111,30 @@ StatusCode BuildTruthTaus::beginEvent()
 }
 
 StatusCode BuildTruthTaus::retrieveTruthTaus()
+{
+  return retrieveTruthTaus (m_truthTausEvent);
+}
+
+
+StatusCode BuildTruthTaus::retrieveTruthTaus(ITruthTausEvent& truthTausEvent) const
+{
+  return retrieveTruthTaus (dynamic_cast<TruthTausEvent&> (truthTausEvent));
+}
+
+
+StatusCode BuildTruthTaus::retrieveTruthTaus(TruthTausEvent& truthTausEvent) const
 {
   if (m_bIsData)
     return StatusCode::SUCCESS;
 
-  if (m_bNewEvent)
-    m_bNewEvent = false;
-  else
+  if (truthTausEvent.m_valid)
     return StatusCode::SUCCESS;
+  truthTausEvent.m_valid = true;
 
   if ( m_bTruthTauAvailable )
   {
     if (evtStore()->contains<xAOD::TruthParticleContainer>(m_sTruthTauContainerName))
-      ATH_CHECK( evtStore()->retrieve(m_xTruthTauContainerConst,m_sTruthTauContainerName));
+      ATH_CHECK( evtStore()->retrieve(truthTausEvent.m_xTruthTauContainerConst,m_sTruthTauContainerName));
     else
     {
       ATH_MSG_INFO("TruthTaus container with name " << m_sTruthTauContainerName << " is not available, will generate the container for each event from TruthParticles container");
@@ -150,7 +145,7 @@ StatusCode BuildTruthTaus::retrieveTruthTaus()
   if ( m_bTruthMuonAvailable )
   {
     if (evtStore()->contains<xAOD::TruthParticleContainer>(m_sTruthMuonContainerName))
-      ATH_CHECK(evtStore()->retrieve(m_xTruthMuonContainerConst,m_sTruthMuonContainerName));
+      ATH_CHECK(evtStore()->retrieve(truthTausEvent.m_xTruthMuonContainerConst,m_sTruthMuonContainerName));
     else
     {
       ATH_MSG_INFO("TruthMuons container with name " << m_sTruthMuonContainerName << " is not available, won't perform matching to truth muons");
@@ -161,7 +156,7 @@ StatusCode BuildTruthTaus::retrieveTruthTaus()
   if ( m_bTruthElectronAvailable )
   {
     if (evtStore()->contains<xAOD::TruthParticleContainer>(m_sTruthElectronContainerName))
-      ATH_CHECK(evtStore()->retrieve(m_xTruthElectronContainerConst,m_sTruthElectronContainerName));
+      ATH_CHECK(evtStore()->retrieve(truthTausEvent.m_xTruthElectronContainerConst,m_sTruthElectronContainerName));
     else
     {
       ATH_MSG_INFO("TruthElectrons container with name " << m_sTruthElectronContainerName << " is not available, won't perform matching to truth electrons");
@@ -172,7 +167,7 @@ StatusCode BuildTruthTaus::retrieveTruthTaus()
   if ( m_bTruthJetAvailable )
   {
     if (evtStore()->contains<xAOD::JetContainer>(m_sTruthJetContainerName))
-      ATH_CHECK(evtStore()->retrieve(m_xTruthJetContainerConst,m_sTruthJetContainerName));
+      ATH_CHECK(evtStore()->retrieve(truthTausEvent.m_xTruthJetContainerConst,m_sTruthJetContainerName));
     else
     {
       ATH_MSG_INFO("TruthJets container with name " << m_sTruthJetContainerName << " is not available, won't perform matching to truth jets");
@@ -185,8 +180,8 @@ StatusCode BuildTruthTaus::retrieveTruthTaus()
   {
     if (evtStore()->contains<xAOD::TruthParticleContainer>(m_sTruthParticlesContainerName))
     {
-      if ( evtStore()->retrieve(m_xTruthParticleContainer,m_sTruthParticlesContainerName).isSuccess() )
-        return buildTruthTausFromTruthParticles();
+      if ( evtStore()->retrieve(truthTausEvent.m_xTruthParticleContainer,m_sTruthParticlesContainerName).isSuccess() )
+        return buildTruthTausFromTruthParticles(truthTausEvent);
       else
         return StatusCode::FAILURE;
     }
@@ -203,27 +198,28 @@ StatusCode BuildTruthTaus::retrieveTruthTaus()
 //=================================PRIVATE-PART=================================
 //______________________________________________________________________________
 //______________________________________________________________________________
-StatusCode BuildTruthTaus::buildTruthTausFromTruthParticles()
+StatusCode
+BuildTruthTaus::buildTruthTausFromTruthParticles(TruthTausEvent& truthTausEvent) const
 {
-  if(m_xTruthTauContainer && !m_bWriteTruthTaus)
+  if(truthTausEvent.m_xTruthTauContainer && !m_bWriteTruthTaus)
   {
-    delete m_xTruthTauContainer;
-    delete m_xTruthTauAuxContainer;
+    delete truthTausEvent.m_xTruthTauContainer;
+    delete truthTausEvent.m_xTruthTauAuxContainer;
   }
 
   // Create the new containers
-  m_xTruthTauContainer = new xAOD::TruthParticleContainer();
-  m_xTruthTauAuxContainer = new xAOD::TruthParticleAuxContainer();
-  m_xTruthTauContainer->setStore( m_xTruthTauAuxContainer );
+  truthTausEvent.m_xTruthTauContainer = new xAOD::TruthParticleContainer();
+  truthTausEvent.m_xTruthTauAuxContainer = new xAOD::TruthParticleAuxContainer();
+  truthTausEvent.m_xTruthTauContainer->setStore( truthTausEvent.m_xTruthTauAuxContainer );
 
   if (m_bWriteTruthTaus)
   {
-    if ( evtStore()->record( m_xTruthTauContainer, m_sNewTruthTauContainerName ).isFailure() )
+    if ( evtStore()->record( truthTausEvent.m_xTruthTauContainer, m_sNewTruthTauContainerName ).isFailure() )
     {
       ATH_MSG_FATAL("Couldn't create truth tau container with key " << m_sNewTruthTauContainerName);
       return StatusCode::FAILURE;
     }
-    if ( evtStore()->record( m_xTruthTauAuxContainer, m_sNewTruthTauContainerNameAux ).isFailure() )
+    if ( evtStore()->record( truthTausEvent.m_xTruthTauAuxContainer, m_sNewTruthTauContainerNameAux ).isFailure() )
     {
       ATH_MSG_FATAL("Couldn't create truth tau container with key " << m_sNewTruthTauContainerNameAux);
       return StatusCode::FAILURE;
@@ -231,7 +227,7 @@ StatusCode BuildTruthTaus::buildTruthTausFromTruthParticles()
     ATH_MSG_DEBUG( "Recorded new TruthParticleContainer with key: " <<  m_sNewTruthTauContainerName);
   }
 
-  for (auto xTruthParticle : *m_xTruthParticleContainer)
+  for (auto xTruthParticle : *truthTausEvent.m_xTruthParticleContainer)
   {
     if ( xTruthParticle->isTau() )
     {
@@ -246,24 +242,24 @@ StatusCode BuildTruthTaus::buildTruthTausFromTruthParticles()
 
       // Run classification
       std::pair<MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin> pClassification = m_tMCTruthClassifier->particleTruthClassifier(xTruthTau);
-      static SG::AuxElement::Decorator<unsigned int> decClassifierParticleType("classifierParticleType");
-      static SG::AuxElement::Decorator<unsigned int> decClassifierParticleOrigin("classifierParticleOrigin");
+      static const SG::AuxElement::Decorator<unsigned int> decClassifierParticleType("classifierParticleType");
+      static const SG::AuxElement::Decorator<unsigned int> decClassifierParticleOrigin("classifierParticleOrigin");
       decClassifierParticleType(*xTruthTau) = pClassification.first;
       decClassifierParticleOrigin(*xTruthTau) = pClassification.second;
 
       // create link to the original TruthParticle
-      ElementLink < xAOD::TruthParticleContainer > lTruthParticleLink(xTruthParticle, *m_xTruthParticleContainer);
-      static SG::AuxElement::Accessor<ElementLink< xAOD::TruthParticleContainer > > accOriginalTruthParticle("originalTruthParticle");
+      ElementLink < xAOD::TruthParticleContainer > lTruthParticleLink(xTruthParticle, *truthTausEvent.m_xTruthParticleContainer);
+      static const SG::AuxElement::Accessor<ElementLink< xAOD::TruthParticleContainer > > accOriginalTruthParticle("originalTruthParticle");
       accOriginalTruthParticle(*xTruthTau) = lTruthParticleLink;
 
-      m_xTruthTauContainer->push_back(xTruthTau);
+      truthTausEvent.m_xTruthTauContainer->push_back(xTruthTau);
     }
   }
   return StatusCode::SUCCESS;
 }
 
 //______________________________________________________________________________
-StatusCode BuildTruthTaus::examineTruthTau(const xAOD::TruthParticle& xTruthParticle)
+StatusCode BuildTruthTaus::examineTruthTau(const xAOD::TruthParticle& xTruthParticle) const
 {
   // skip this tau if it has no decay vertex, should not happen
   if ( !xTruthParticle.hasDecayVtx() )
@@ -271,21 +267,7 @@ StatusCode BuildTruthTaus::examineTruthTau(const xAOD::TruthParticle& xTruthPart
 
   ATH_MSG_VERBOSE("looking for charged daughters of a truth tau");
 
-  m_iNChargedPions = 0;
-  m_iNNeutralPions = 0;
-  m_iNChargedOthers = 0;
-  m_iNNeutralOthers = 0;
-  m_iNChargedDaughters = 0;
-  m_vDecayMode.clear();
-
-  // define truth visible kinematic variables
-  m_vTruthVisTLV = TLorentzVector();
-  m_vTruthVisTLVCharged = TLorentzVector();
-  m_vTruthVisTLVNeutral = TLorentzVector();
-
-  // default false, if there is a hadron in decay products, it is
-  // switched to true
-  m_bIsHadronicTau = false;
+  TauTruthInfo truthInfo;
 
   const xAOD::TruthVertex* xDecayVertex = xTruthParticle.decayVtx();
   if ( !xDecayVertex )
@@ -307,48 +289,48 @@ StatusCode BuildTruthTaus::examineTruthTau(const xAOD::TruthParticle& xTruthPart
     }
   }
 
-  examineTruthTauDecay(xTruthParticle).ignore();
+  examineTruthTauDecay(xTruthParticle, truthInfo).ignore();
 
-  if (m_bIsHadronicTau)
-    ATH_MSG_VERBOSE(m_iNChargedDaughters << " prong hadronic truth tau was found with barcode "<<xTruthParticle.barcode());
+  if (truthInfo.m_bIsHadronicTau)
+    ATH_MSG_VERBOSE(truthInfo.m_iNChargedDaughters << " prong hadronic truth tau was found with barcode "<<xTruthParticle.barcode());
   else
-    ATH_MSG_VERBOSE(m_iNChargedDaughters << " prong leptonic truth tau was found with barcode "<<xTruthParticle.barcode());
-  if ( m_iNChargedDaughters%2 == 0 )
+    ATH_MSG_VERBOSE(truthInfo.m_iNChargedDaughters << " prong leptonic truth tau was found with barcode "<<xTruthParticle.barcode());
+  if ( truthInfo.m_iNChargedDaughters%2 == 0 )
   {
-    ATH_MSG_WARNING("found tau with even multiplicity: " << m_iNChargedDaughters);
+    ATH_MSG_WARNING("found tau with even multiplicity: " << truthInfo.m_iNChargedDaughters);
     printDecay(xTruthParticle);
   }
 
-  static SG::AuxElement::Decorator<double> decPtVis("pt_vis");
-  static SG::AuxElement::Decorator<double> decEtaVis("eta_vis");
-  static SG::AuxElement::Decorator<double> decPhiVis("phi_vis");
-  static SG::AuxElement::Decorator<double> accMVis("m_vis");
+  static const SG::AuxElement::Decorator<double> decPtVis("pt_vis");
+  static const SG::AuxElement::Decorator<double> decEtaVis("eta_vis");
+  static const SG::AuxElement::Decorator<double> decPhiVis("phi_vis");
+  static const SG::AuxElement::Decorator<double> accMVis("m_vis");
 
-  static SG::AuxElement::Decorator<size_t> decNumCharged("numCharged");
-  static SG::AuxElement::Decorator<size_t> decNumChargedPion("numChargedPion");
-  static SG::AuxElement::Decorator<size_t> decNumNeutral("numNeutral");
-  static SG::AuxElement::Decorator<size_t> accNumNeutralPion("numNeutralPion");
+  static const SG::AuxElement::Decorator<size_t> decNumCharged("numCharged");
+  static const SG::AuxElement::Decorator<size_t> decNumChargedPion("numChargedPion");
+  static const SG::AuxElement::Decorator<size_t> decNumNeutral("numNeutral");
+  static const SG::AuxElement::Decorator<size_t> accNumNeutralPion("numNeutralPion");
 
-  decPtVis(xTruthParticle) = m_vTruthVisTLV.Pt();
-  decEtaVis(xTruthParticle) = m_vTruthVisTLV.Eta();
-  decPhiVis(xTruthParticle) = m_vTruthVisTLV.Phi();
-  accMVis(xTruthParticle) = m_vTruthVisTLV.M();
+  decPtVis(xTruthParticle) = truthInfo.m_vTruthVisTLV.Pt();
+  decEtaVis(xTruthParticle) = truthInfo.m_vTruthVisTLV.Eta();
+  decPhiVis(xTruthParticle) = truthInfo.m_vTruthVisTLV.Phi();
+  accMVis(xTruthParticle) = truthInfo.m_vTruthVisTLV.M();
 
-  decNumCharged(xTruthParticle) = m_iNChargedDaughters;
-  decNumChargedPion(xTruthParticle) = m_iNChargedPions;
-  decNumNeutral(xTruthParticle) = m_iNNeutralPions+m_iNNeutralOthers;
-  accNumNeutralPion(xTruthParticle) = m_iNNeutralPions;
+  decNumCharged(xTruthParticle) = truthInfo.m_iNChargedDaughters;
+  decNumChargedPion(xTruthParticle) = truthInfo.m_iNChargedPions;
+  decNumNeutral(xTruthParticle) = truthInfo.m_iNNeutralPions+truthInfo.m_iNNeutralOthers;
+  accNumNeutralPion(xTruthParticle) = truthInfo.m_iNNeutralPions;
 
-  static SG::AuxElement::Decorator<char> decIsHadronicTau("IsHadronicTau");
-  decIsHadronicTau(xTruthParticle) = (char)m_bIsHadronicTau;
+  static const SG::AuxElement::Decorator<char> decIsHadronicTau("IsHadronicTau");
+  decIsHadronicTau(xTruthParticle) = (char)truthInfo.m_bIsHadronicTau;
 
   if ( m_bWriteInvisibleFourMomentum )
   {
-    TLorentzVector vTruthInvisTLV = xTruthParticle.p4() - m_vTruthVisTLV;
-    static SG::AuxElement::Decorator<double> decPtInvis("pt_invis");
-    static SG::AuxElement::Decorator<double> decEtaInvis("eta_invis");
-    static SG::AuxElement::Decorator<double> decPhiInvis("phi_invis");
-    static SG::AuxElement::Decorator<double> accMInvis("m_invis");
+    TLorentzVector vTruthInvisTLV = xTruthParticle.p4() - truthInfo.m_vTruthVisTLV;
+    static const SG::AuxElement::Decorator<double> decPtInvis("pt_invis");
+    static const SG::AuxElement::Decorator<double> decEtaInvis("eta_invis");
+    static const SG::AuxElement::Decorator<double> decPhiInvis("phi_invis");
+    static const SG::AuxElement::Decorator<double> accMInvis("m_invis");
     decPtInvis(xTruthParticle)  = vTruthInvisTLV.Pt();
     decEtaInvis(xTruthParticle) = vTruthInvisTLV.Eta();
     decPhiInvis(xTruthParticle) = vTruthInvisTLV.Phi();
@@ -357,39 +339,40 @@ StatusCode BuildTruthTaus::examineTruthTau(const xAOD::TruthParticle& xTruthPart
 
   if ( m_bWriteVisibleChargedFourMomentum )
   {
-    static SG::AuxElement::Decorator<double> decPtVisCharged("pt_vis_charged");
-    static SG::AuxElement::Decorator<double> decEtaVisCharged("eta_vis_charged");
-    static SG::AuxElement::Decorator<double> decPhiVisCharged("phi_vis_charged");
-    static SG::AuxElement::Decorator<double> accMVisCharged("m_vis_charged");
-    decPtVisCharged(xTruthParticle)  = m_vTruthVisTLVCharged.Pt();
-    decEtaVisCharged(xTruthParticle) = m_vTruthVisTLVCharged.Eta();
-    decPhiVisCharged(xTruthParticle) = m_vTruthVisTLVCharged.Phi();
-    accMVisCharged(xTruthParticle)   = m_vTruthVisTLVCharged.M();
+    static const SG::AuxElement::Decorator<double> decPtVisCharged("pt_vis_charged");
+    static const SG::AuxElement::Decorator<double> decEtaVisCharged("eta_vis_charged");
+    static const SG::AuxElement::Decorator<double> decPhiVisCharged("phi_vis_charged");
+    static const SG::AuxElement::Decorator<double> accMVisCharged("m_vis_charged");
+    decPtVisCharged(xTruthParticle)  = truthInfo.m_vTruthVisTLVCharged.Pt();
+    decEtaVisCharged(xTruthParticle) = truthInfo.m_vTruthVisTLVCharged.Eta();
+    decPhiVisCharged(xTruthParticle) = truthInfo.m_vTruthVisTLVCharged.Phi();
+    accMVisCharged(xTruthParticle)   = truthInfo.m_vTruthVisTLVCharged.M();
   }
 
   if ( m_bWriteVisibleNeutralFourMomentum )
   {
-    static SG::AuxElement::Decorator<double> decPtVisNeutral("pt_vis_neutral");
-    static SG::AuxElement::Decorator<double> decEtaVisNeutral("eta_vis_neutral");
-    static SG::AuxElement::Decorator<double> decPhiVisNeutral("phi_vis_neutral");
-    static SG::AuxElement::Decorator<double> accMVisNeutral("m_vis_neutral");
-    decPtVisNeutral(xTruthParticle)  = m_vTruthVisTLVNeutral.Pt();
-    decEtaVisNeutral(xTruthParticle) = m_vTruthVisTLVNeutral.Eta();
-    decPhiVisNeutral(xTruthParticle) = m_vTruthVisTLVNeutral.Phi();
-    accMVisNeutral(xTruthParticle)   = m_vTruthVisTLVNeutral.M();
+    static const SG::AuxElement::Decorator<double> decPtVisNeutral("pt_vis_neutral");
+    static const SG::AuxElement::Decorator<double> decEtaVisNeutral("eta_vis_neutral");
+    static const SG::AuxElement::Decorator<double> decPhiVisNeutral("phi_vis_neutral");
+    static const SG::AuxElement::Decorator<double> accMVisNeutral("m_vis_neutral");
+    decPtVisNeutral(xTruthParticle)  = truthInfo.m_vTruthVisTLVNeutral.Pt();
+    decEtaVisNeutral(xTruthParticle) = truthInfo.m_vTruthVisTLVNeutral.Eta();
+    decPhiVisNeutral(xTruthParticle) = truthInfo.m_vTruthVisTLVNeutral.Phi();
+    accMVisNeutral(xTruthParticle)   = truthInfo.m_vTruthVisTLVNeutral.M();
   }
 
   if ( m_bWriteDecayModeVector )
   {
-    static SG::AuxElement::Decorator<std::vector<int> > decDecayModeVector("DecayModeVector");
-    decDecayModeVector(xTruthParticle) = m_vDecayMode;
+    static const SG::AuxElement::Decorator<std::vector<int> > decDecayModeVector("DecayModeVector");
+    decDecayModeVector(xTruthParticle) = truthInfo.m_vDecayMode;
   }
 
   return StatusCode::SUCCESS;
 }
 
 //______________________________________________________________________________
-StatusCode BuildTruthTaus::examineTruthTauDecay(const xAOD::TruthParticle& xTruthParticle)
+StatusCode BuildTruthTaus::examineTruthTauDecay (const xAOD::TruthParticle& xTruthParticle,
+                                                 TauTruthInfo& truthInfo) const
 {
   // get vertex and check if it exists
   const xAOD::TruthVertex* xDecayVertex = xTruthParticle.decayVtx();
@@ -413,7 +396,7 @@ StatusCode BuildTruthTaus::examineTruthTauDecay(const xAOD::TruthParticle& xTrut
     {
       if ( iAbsPdgId != 111 and iAbsPdgId != 311 and iAbsPdgId != 310 and iAbsPdgId != 130 )
       {
-        examineTruthTauDecay(*xTruthDaughter).ignore();
+        examineTruthTauDecay(*xTruthDaughter, truthInfo).ignore();
         continue;
       }
     }
@@ -423,12 +406,12 @@ StatusCode BuildTruthTaus::examineTruthTauDecay(const xAOD::TruthParticle& xTrut
       continue;
 
     // add pdgID to vector for decay mode classification
-    m_vDecayMode.push_back(iPdgId);
+    truthInfo.m_vDecayMode.push_back(iPdgId);
 
     // if tau decays leptonically, indicated by an electron/muon neutrino then
     // it is not a hadronic decay
     if ( xTruthDaughter->isHadron() )
-      m_bIsHadronicTau = true;
+      truthInfo.m_bIsHadronicTau = true;
 
     // ignore neutrinos for further progress
     if ( xTruthDaughter->isNeutrino() )
@@ -438,29 +421,29 @@ StatusCode BuildTruthTaus::examineTruthTauDecay(const xAOD::TruthParticle& xTrut
     }
 
     // add momentum of non-neutrino particle to visible momentum
-    m_vTruthVisTLV += xTruthDaughter->p4();
+    truthInfo.m_vTruthVisTLV += xTruthDaughter->p4();
     if ( m_bWriteVisibleChargedFourMomentum )
       if ( xTruthDaughter->isCharged() )
-        m_vTruthVisTLVCharged += xTruthDaughter->p4();
+        truthInfo.m_vTruthVisTLVCharged += xTruthDaughter->p4();
     if ( m_bWriteVisibleNeutralFourMomentum )
       if ( xTruthDaughter->isNeutral() )
-        m_vTruthVisTLVNeutral += xTruthDaughter->p4();
+        truthInfo.m_vTruthVisTLVNeutral += xTruthDaughter->p4();
 
     // only count charged decay particles
     if ( xTruthDaughter->isCharged() )
     {
       ATH_MSG_VERBOSE("found charged decay particle with PdgId "<<iPdgId);
-      m_iNChargedDaughters++;
+      truthInfo.m_iNChargedDaughters++;
       // count charged pions
-      if (iAbsPdgId==211) m_iNChargedPions++;
-      else m_iNChargedOthers++;
+      if (iAbsPdgId==211) truthInfo.m_iNChargedPions++;
+      else truthInfo.m_iNChargedOthers++;
     }
     else
     {
       ATH_MSG_VERBOSE("found neutral decay particle with PdgId "<<iPdgId);
       // count neutral pions
-      if (iAbsPdgId==111) m_iNNeutralPions++;
-      else m_iNNeutralOthers++;
+      if (iAbsPdgId==111) truthInfo.m_iNNeutralPions++;
+      else truthInfo.m_iNNeutralOthers++;
     }
   }
   return StatusCode::SUCCESS;
diff --git a/PhysicsAnalysis/TauID/TauAnalysisTools/Root/DiTauTruthMatchingTool.cxx b/PhysicsAnalysis/TauID/TauAnalysisTools/Root/DiTauTruthMatchingTool.cxx
index 8b766b83249ac2ae5a6f78694e6424d9011824ed..015074bb714caf7dae60743a7691ed20a281d768 100644
--- a/PhysicsAnalysis/TauID/TauAnalysisTools/Root/DiTauTruthMatchingTool.cxx
+++ b/PhysicsAnalysis/TauID/TauAnalysisTools/Root/DiTauTruthMatchingTool.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
 */
 
 // Local include(s)
@@ -85,23 +85,17 @@ void DiTauTruthMatchingTool::applyTruthMatch(const std::vector<const xAOD::DiTau
 StatusCode DiTauTruthMatchingTool::findTruthTau(const xAOD::DiTauJet& xDiTau)
 {
   // check if decorations were already added to the first passed tau
-  if (!m_bIsTruthMatchedAvailableChecked)
-  {
-    m_bIsTruthMatchedAvailable = xDiTau.isAvailable<char>("IsTruthMatched");
-    m_bIsTruthMatchedAvailableChecked = true;
-    if (m_bIsTruthMatchedAvailable)
-    {
-      ATH_MSG_DEBUG("IsTruthMatched decoration is available on first tau processed, switched of rerun for further taus.");
-      ATH_MSG_DEBUG("If a truth matching needs to be redone, please pass a shallow copy of the original tau.");
-    }
+  if (!m_bIsTruthMatchedAvailable.isValid()) {
+    bool avail = xDiTau.isAvailable<char>("IsTruthMatched");
+    m_bIsTruthMatchedAvailable.set (avail);
   }
-  if (m_bIsTruthMatchedAvailable)
+  if (*m_bIsTruthMatchedAvailable.ptr())
     return StatusCode::SUCCESS;
 
   if (m_bTruthTauAvailable)
-    return checkTruthMatch(xDiTau, *m_xTruthTauContainerConst);
+    return checkTruthMatch(xDiTau, *m_truthTausEvent.m_xTruthTauContainerConst);
   else
-    return checkTruthMatch(xDiTau, *m_xTruthTauContainer);
+    return checkTruthMatch(xDiTau, *m_truthTausEvent.m_xTruthTauContainer);
 }
 
 //______________________________________________________________________________
@@ -174,12 +168,12 @@ StatusCode DiTauTruthMatchingTool::checkTruthMatch (const xAOD::DiTauJet& xDiTau
       }
       else if (eTruthMatchedParticleType == TruthMuon)
       {
-        ElementLink <xAOD::TruthParticleContainer> lTruthParticleLink(xTruthMatch, *m_xTruthMuonContainerConst);
+        ElementLink <xAOD::TruthParticleContainer> lTruthParticleLink(xTruthMatch, *m_truthTausEvent.m_xTruthMuonContainerConst);
         vTruthLinks.push_back(lTruthParticleLink);
       }
       else if (eTruthMatchedParticleType  == TruthElectron)
       {
-        ElementLink <xAOD::TruthParticleContainer> lTruthParticleLink(xTruthMatch, *m_xTruthElectronContainerConst);
+        ElementLink <xAOD::TruthParticleContainer> lTruthParticleLink(xTruthMatch, *m_truthTausEvent.m_xTruthElectronContainerConst);
         vTruthLinks.push_back(lTruthParticleLink);
       }
     }
@@ -243,10 +237,10 @@ StatusCode DiTauTruthMatchingTool::truthMatch(const TLorentzVector& vSubjetTLV,
     }
   }
 
-  if (!xTruthMatch and m_xTruthMuonContainerConst)
+  if (!xTruthMatch and m_truthTausEvent.m_xTruthMuonContainerConst)
   {
     double dPtMax = 0;
-    for (auto xTruthMuonIt : *m_xTruthMuonContainerConst)
+    for (auto xTruthMuonIt : *m_truthTausEvent.m_xTruthMuonContainerConst)
     {
       if (vSubjetTLV.DeltaR(xTruthMuonIt->p4()) <= m_dMaxDeltaR)
       {
@@ -260,10 +254,10 @@ StatusCode DiTauTruthMatchingTool::truthMatch(const TLorentzVector& vSubjetTLV,
     }
   }
 
-  if (!xTruthMatch and m_xTruthElectronContainerConst)
+  if (!xTruthMatch and m_truthTausEvent.m_xTruthElectronContainerConst)
   {
     double dPtMax = 0;
-    for (auto xTruthElectronIt : *m_xTruthElectronContainerConst)
+    for (auto xTruthElectronIt : *m_truthTausEvent.m_xTruthElectronContainerConst)
     {
       if (vSubjetTLV.DeltaR(xTruthElectronIt->p4()) <= m_dMaxDeltaR)
       {
diff --git a/PhysicsAnalysis/TauID/TauAnalysisTools/Root/TauTruthMatchingTool.cxx b/PhysicsAnalysis/TauID/TauAnalysisTools/Root/TauTruthMatchingTool.cxx
index 0833d8a5788ecd9ced7584cb83b85883078602f2..fb6ee6433bdbccd7ab71ae63a0131bf27379c334 100644
--- a/PhysicsAnalysis/TauID/TauAnalysisTools/Root/TauTruthMatchingTool.cxx
+++ b/PhysicsAnalysis/TauID/TauAnalysisTools/Root/TauTruthMatchingTool.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
 */
 
 // Local include(s)
@@ -44,16 +44,34 @@ StatusCode TauTruthMatchingTool::initialize()
   return StatusCode::SUCCESS;
 }
 
+//______________________________________________________________________________
+std::unique_ptr<TauTruthMatchingTool::ITruthTausEvent>
+TauTruthMatchingTool::getEvent() const
+{
+  auto truthTausEvent = std::make_unique<TruthTausEvent>();
+  if (retrieveTruthTaus(*truthTausEvent).isFailure()) {
+    truthTausEvent.reset();
+  }
+  return truthTausEvent;
+}
+
 //______________________________________________________________________________
 const xAOD::TruthParticle* TauTruthMatchingTool::getTruth(const xAOD::TauJet& xTau)
 {
+  return getTruth (xTau, m_truthTausEvent);
+}
+const xAOD::TruthParticle*
+TauTruthMatchingTool::getTruth(const xAOD::TauJet& xTau,
+                               ITruthTausEvent& itruthTausEvent) const
+{
+  TruthTausEvent& truthTausEvent = dynamic_cast<TruthTausEvent&> (itruthTausEvent);
   if (m_bIsData)
     return nullptr;
 
-  if (retrieveTruthTaus().isFailure())
+  if (retrieveTruthTaus(truthTausEvent).isFailure())
     return nullptr;
 
-  if (findTruthTau(xTau).isFailure())
+  if (findTruthTau(xTau, truthTausEvent).isFailure())
     ATH_MSG_WARNING("There was a failure in finding the matched truth tau");
 
   // if matched to a truth tau return its pointer, else return a null pointer
@@ -333,20 +351,15 @@ xAOD::TauJetParameters::DecayMode TauTruthMatchingTool::getDecayMode(const xAOD:
 ////////////////////////////////////////////////////////////////////////////////
 
 //______________________________________________________________________________
-StatusCode TauTruthMatchingTool::findTruthTau(const xAOD::TauJet& xTau)
+StatusCode TauTruthMatchingTool::findTruthTau(const xAOD::TauJet& xTau,
+                                              TruthTausEvent& truthTausEvent) const
 {
   // check if decorations were already added to the first passed tau
-  if (!m_bIsTruthMatchedAvailableChecked)
-  {
-    m_bIsTruthMatchedAvailable = xTau.isAvailable<char>("IsTruthMatched");
-    m_bIsTruthMatchedAvailableChecked = true;
-    if (m_bIsTruthMatchedAvailable)
-    {
-      ATH_MSG_DEBUG("IsTruthMatched decoration is available on first tau processed, switched of rerun for further taus.");
-      ATH_MSG_DEBUG("If a truth matching needs to be redone, please pass a shallow copy of the original tau.");
-    }
+  if (!m_bIsTruthMatchedAvailable.isValid()) {
+    bool avail = xTau.isAvailable<char>("IsTruthMatched");
+    m_bIsTruthMatchedAvailable.set (avail);
   }
-  if (m_bIsTruthMatchedAvailable)
+  if (*m_bIsTruthMatchedAvailable.ptr())
     return StatusCode::SUCCESS;
 
   // only search for truth taus once
@@ -360,9 +373,9 @@ StatusCode TauTruthMatchingTool::findTruthTau(const xAOD::TauJet& xTau)
   // || (xTau.auxdata<char>("IsTruthMatched") && xTau.auxdata< ElementLink< xAOD::TruthParticleContainer > >("truthParticleLink") == NULL ))
   // {
   if (m_bTruthTauAvailable)
-    return checkTruthMatch(xTau, *m_xTruthTauContainerConst);
+    return checkTruthMatch(xTau, *truthTausEvent.m_xTruthTauContainerConst);
   else
-    return checkTruthMatch(xTau, *m_xTruthTauContainer);
+    return checkTruthMatch(xTau, *truthTausEvent.m_xTruthTauContainer);
   // }
 
   // return StatusCode::SUCCESS;
@@ -401,10 +414,10 @@ StatusCode TauTruthMatchingTool::checkTruthMatch (const xAOD::TauJet& xTau, cons
     }
   }
 
-  if (!xTruthMatch and m_xTruthMuonContainerConst)
+  if (!xTruthMatch and m_truthTausEvent.m_xTruthMuonContainerConst)
   {
     double dPtMax = 0;
-    for (auto xTruthMuonIt : *m_xTruthMuonContainerConst)
+    for (auto xTruthMuonIt : *m_truthTausEvent.m_xTruthMuonContainerConst)
     {
       if (xTau.p4().DeltaR(xTruthMuonIt->p4()) <= m_dMaxDeltaR)
       {
@@ -418,10 +431,10 @@ StatusCode TauTruthMatchingTool::checkTruthMatch (const xAOD::TauJet& xTau, cons
     }
   }
 
-  if (!xTruthMatch and m_xTruthElectronContainerConst)
+  if (!xTruthMatch and m_truthTausEvent.m_xTruthElectronContainerConst)
   {
     double dPtMax = 0;
-    for (auto xTruthElectronIt : *m_xTruthElectronContainerConst)
+    for (auto xTruthElectronIt : *m_truthTausEvent.m_xTruthElectronContainerConst)
     {
       if (xTau.p4().DeltaR(xTruthElectronIt->p4()) <= m_dMaxDeltaR)
       {
@@ -434,10 +447,10 @@ StatusCode TauTruthMatchingTool::checkTruthMatch (const xAOD::TauJet& xTau, cons
     }
   }
 
-  if (m_xTruthJetContainerConst)
+  if (m_truthTausEvent.m_xTruthJetContainerConst)
   {
     double dPtMax = 0;
-    for (auto xTruthJetIt : *m_xTruthJetContainerConst)
+    for (auto xTruthJetIt : *m_truthTausEvent.m_xTruthJetContainerConst)
     {
       if (xTau.p4().DeltaR(xTruthJetIt->p4()) <= m_dMaxDeltaR)
       {
@@ -456,7 +469,7 @@ StatusCode TauTruthMatchingTool::checkTruthMatch (const xAOD::TauJet& xTau, cons
 
   if (xTruthJetMatch)
   {
-    ElementLink < xAOD::JetContainer > lTruthParticleLink(xTruthJetMatch, *m_xTruthJetContainerConst);
+    ElementLink < xAOD::JetContainer > lTruthParticleLink(xTruthJetMatch, *m_truthTausEvent.m_xTruthJetContainerConst);
     decTruthJetLink(xTau) = lTruthParticleLink;
   }
   else
@@ -488,12 +501,12 @@ StatusCode TauTruthMatchingTool::checkTruthMatch (const xAOD::TauJet& xTau, cons
     }
     else if (eTruthMatchedParticleType == TruthMuon)
     {
-      ElementLink < xAOD::TruthParticleContainer > lTruthParticleLink(xTruthMatch, *m_xTruthMuonContainerConst);
+      ElementLink < xAOD::TruthParticleContainer > lTruthParticleLink(xTruthMatch, *m_truthTausEvent.m_xTruthMuonContainerConst);
       decTruthParticleLink(xTau) = lTruthParticleLink;
     }
     else if (eTruthMatchedParticleType == TruthElectron)
     {
-      ElementLink < xAOD::TruthParticleContainer > lTruthParticleLink(xTruthMatch, *m_xTruthElectronContainerConst);
+      ElementLink < xAOD::TruthParticleContainer > lTruthParticleLink(xTruthMatch, *m_truthTausEvent.m_xTruthElectronContainerConst);
       decTruthParticleLink(xTau) = lTruthParticleLink;
     }
   }
diff --git a/PhysicsAnalysis/TauID/TauAnalysisTools/Root/TauTruthTrackMatchingTool.cxx b/PhysicsAnalysis/TauID/TauAnalysisTools/Root/TauTruthTrackMatchingTool.cxx
index cdfbb3653d18c5fe72b581f4db7a9ffeaa48eea1..82bf80a8d9f034f8b770e05272d1ee57986f48d0 100644
--- a/PhysicsAnalysis/TauID/TauAnalysisTools/Root/TauTruthTrackMatchingTool.cxx
+++ b/PhysicsAnalysis/TauID/TauAnalysisTools/Root/TauTruthTrackMatchingTool.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
 */
 
 #include <TauAnalysisTools/TauTruthTrackMatchingTool.h>
@@ -13,8 +13,6 @@ using namespace TauAnalysisTools;
 //______________________________________________________________________________
 TauTruthTrackMatchingTool::TauTruthTrackMatchingTool( const std::string& name )
   : AsgTool(name)
-  , m_bIsHadronicTrackAvailable(false)
-  , m_bIsHadronicTrackAvailableChecked(false)
 {
 }
 
@@ -30,20 +28,20 @@ StatusCode TauTruthTrackMatchingTool::initialize()
 }
 
 //______________________________________________________________________________
-StatusCode TauTruthTrackMatchingTool::classifyTrack(const TAUTRACKPARTICLE& xTrackParticle)
+StatusCode TauTruthTrackMatchingTool::classifyTrack(const TAUTRACKPARTICLE& xTrackParticle) const
 {
   // don't classify tracks if this was already done
-  if (!m_bIsHadronicTrackAvailableChecked)
+  if (!m_bIsHadronicTrackAvailable.isValid())
   {
-    m_bIsHadronicTrackAvailable = xTrackParticle.isAvailable<char>("IsHadronicTrack");
-    m_bIsHadronicTrackAvailableChecked = true;
-    if (m_bIsHadronicTrackAvailable)
+    bool avail = xTrackParticle.isAvailable<char>("IsHadronicTrack");
+    m_bIsHadronicTrackAvailable.set (avail);
+    if (avail)
     {
       ATH_MSG_DEBUG("IsHadronicTrack decoration is available on first track processed, switched of rerun for further taus.");
       ATH_MSG_DEBUG("If a truth track matching needs to be redone, please pass a shallow copy of the original track.");
     }
   }
-  if (m_bIsHadronicTrackAvailable)
+  if (*m_bIsHadronicTrackAvailable.ptr())
     return StatusCode::SUCCESS;
 
   ATH_CHECK(checkTrackIsTauInheritant(xTrackParticle));
@@ -52,7 +50,7 @@ StatusCode TauTruthTrackMatchingTool::classifyTrack(const TAUTRACKPARTICLE& xTra
 }
 
 //______________________________________________________________________________
-StatusCode TauTruthTrackMatchingTool::classifyTracks(std::vector<const TAUTRACKPARTICLE*>& vTrackParticles)
+StatusCode TauTruthTrackMatchingTool::classifyTracks(std::vector<const TAUTRACKPARTICLE*>& vTrackParticles) const
 {
   for (auto xTrackParticle : vTrackParticles)
   {
@@ -64,18 +62,18 @@ StatusCode TauTruthTrackMatchingTool::classifyTracks(std::vector<const TAUTRACKP
 
 //=================================PRIVATE-PART=================================
 //______________________________________________________________________________
-StatusCode TauTruthTrackMatchingTool::checkTrackType(const TAUTRACKPARTICLE& xTrackParticle)
+StatusCode TauTruthTrackMatchingTool::checkTrackType(const TAUTRACKPARTICLE& xTrackParticle) const
 {
   const xAOD::TruthParticle* xTruthParticle = getTruthParticle(xTrackParticle);
 
-  static SG::AuxElement::Decorator<int> decTruthType("TruthType");
+  static const SG::AuxElement::Decorator<int> decTruthType("TruthType");
   if (!xTruthParticle)
   {
     decTruthType(xTrackParticle) = TauAnalysisTools::UnclassifiedTrack;
     return StatusCode::SUCCESS;
   }
 
-  static SG::AuxElement::ConstAccessor<float> accTruthMatchProbability("truthMatchProbability");
+  static const SG::AuxElement::ConstAccessor<float> accTruthMatchProbability("truthMatchProbability");
 #ifndef XAODTAU_VERSIONS_TAUJET_V3_H
   if (accTruthMatchProbability(xTrackParticle) < 0.5)
 #else
@@ -86,8 +84,8 @@ StatusCode TauTruthTrackMatchingTool::checkTrackType(const TAUTRACKPARTICLE& xTr
     return StatusCode::SUCCESS;
   }
 
-  static SG::AuxElement::ConstAccessor< char > accIsHadronicTrack("IsHadronicTrack");
-  static SG::AuxElement::ConstAccessor< int > accIsHadronicTrackDecayDepth("IsHadronicTrackDecayDepth");
+  static const SG::AuxElement::ConstAccessor< char > accIsHadronicTrack("IsHadronicTrack");
+  static const SG::AuxElement::ConstAccessor< int > accIsHadronicTrackDecayDepth("IsHadronicTrackDecayDepth");
   if ((bool)accIsHadronicTrack(xTrackParticle) and accIsHadronicTrackDecayDepth(xTrackParticle) == 0)
   {
     decTruthType(xTrackParticle) = TauAnalysisTools::TauTrack;
@@ -105,9 +103,9 @@ StatusCode TauTruthTrackMatchingTool::checkTrackType(const TAUTRACKPARTICLE& xTr
 }
 
 //______________________________________________________________________________
-StatusCode TauTruthTrackMatchingTool::classifyConversion(const TAUTRACKPARTICLE& xTrackParticle, const xAOD::TruthParticle& xTruthParticle)
+StatusCode TauTruthTrackMatchingTool::classifyConversion(const TAUTRACKPARTICLE& xTrackParticle, const xAOD::TruthParticle& xTruthParticle) const
 {
-  static SG::AuxElement::Decorator<int> decTruthType("TruthType");
+  static const SG::AuxElement::Decorator<int> decTruthType("TruthType");
   if (!xTruthParticle.isElectron())
   {
     decTruthType(xTrackParticle) = TauAnalysisTools::SecondaryTrack;
@@ -162,9 +160,9 @@ StatusCode TauTruthTrackMatchingTool::classifyConversion(const TAUTRACKPARTICLE&
 }
 
 //______________________________________________________________________________
-const xAOD::TruthParticle* TauTruthTrackMatchingTool::getTruthParticle(const TAUTRACKPARTICLE& xTrackParticle)
+const xAOD::TruthParticle* TauTruthTrackMatchingTool::getTruthParticle(const TAUTRACKPARTICLE& xTrackParticle) const
 {
-  static SG::AuxElement::ConstAccessor< ElementLink<xAOD::TruthParticleContainer> > accTruthParticleLink("truthParticleLink");
+  static const SG::AuxElement::ConstAccessor< ElementLink<xAOD::TruthParticleContainer> > accTruthParticleLink("truthParticleLink");
 #ifdef XAODTAU_VERSIONS_TAUJET_V3_H
   auto xTruthParticleContainer = accTruthParticleLink(*(xTrackParticle.track()));
 #else
@@ -177,11 +175,11 @@ const xAOD::TruthParticle* TauTruthTrackMatchingTool::getTruthParticle(const TAU
 }
 
 //______________________________________________________________________________
-StatusCode TauTruthTrackMatchingTool::checkTrackIsTauInheritant(const TAUTRACKPARTICLE& xTrackParticle)
+StatusCode TauTruthTrackMatchingTool::checkTrackIsTauInheritant(const TAUTRACKPARTICLE& xTrackParticle) const
 {
-  static SG::AuxElement::Decorator< char > decIsHadronicTrack("IsHadronicTrack");
-  static SG::AuxElement::Decorator< int > decIsHadronicTrackDecayDepth("IsHadronicTrackDecayDepth");
-  static SG::AuxElement::Decorator< std::string > decDecayHistory("DecayHistory");
+  static const SG::AuxElement::Decorator< char > decIsHadronicTrack("IsHadronicTrack");
+  static const SG::AuxElement::Decorator< int > decIsHadronicTrackDecayDepth("IsHadronicTrackDecayDepth");
+  static const SG::AuxElement::Decorator< std::string > decDecayHistory("DecayHistory");
   decIsHadronicTrack(xTrackParticle) = (char)false;
   int iDepth = -1;
   const xAOD::TruthParticle* xTruthParticle = getTruthParticle(xTrackParticle);
@@ -201,7 +199,7 @@ StatusCode TauTruthTrackMatchingTool::checkTrackIsTauInheritant(const TAUTRACKPA
 }
 
 //______________________________________________________________________________
-bool TauTruthTrackMatchingTool::checkTruthParent(const xAOD::TruthParticle& xTruthParticle, int& iDepth, std::string& sHistory)
+bool TauTruthTrackMatchingTool::checkTruthParent(const xAOD::TruthParticle& xTruthParticle, int& iDepth, std::string& sHistory) const
 {
   iDepth++;
   if (xTruthParticle.hasProdVtx())
diff --git a/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/BuildTruthTaus.h b/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/BuildTruthTaus.h
index f3b4ff90a50b8803845180caf06c4545607c770b..92ce175a84dd6eebfc261953de56b123d64d5001 100644
--- a/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/BuildTruthTaus.h
+++ b/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/BuildTruthTaus.h
@@ -1,7 +1,7 @@
 // Dear emacs, this is -*- c++ -*-
 
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef  TAUANALYSISTOOLS_BUILDTRUTHTAUS_H
@@ -30,6 +30,9 @@
 // Local include(s):
 #include "TauAnalysisTools/IBuildTruthTaus.h"
 
+#include "CxxUtils/CachedValue.h"
+#include <atomic>
+
 namespace TauAnalysisTools
 {
 
@@ -43,28 +46,66 @@ class BuildTruthTaus
 
 public:
 
+  struct TruthTausEvent
+    : public ITruthTausEvent
+  {
+    bool m_valid = false;
+    const xAOD::TruthParticleContainer* m_xTruthTauContainerConst = nullptr;
+    const xAOD::TruthParticleContainer* m_xTruthMuonContainerConst = nullptr;
+    const xAOD::TruthParticleContainer* m_xTruthElectronContainerConst = nullptr;
+    const xAOD::JetContainer* m_xTruthJetContainerConst = nullptr;
+    xAOD::TruthParticleContainer* m_xTruthTauContainer = nullptr;
+    xAOD::TruthParticleAuxContainer* m_xTruthTauAuxContainer = nullptr;
+    const xAOD::TruthParticleContainer* m_xTruthParticleContainer = nullptr;
+  };
+
   BuildTruthTaus( const std::string& name );
 
   virtual ~BuildTruthTaus();
 
   // initialize the tool
-  virtual StatusCode initialize();
+  virtual StatusCode initialize() override;
 
   // get TruthTauContainer
-  virtual xAOD::TruthParticleContainer* getTruthTauContainer();
+  virtual xAOD::TruthParticleContainer* getTruthTauContainer() override;
 
   // get TruthTauAuxContainer
-  virtual xAOD::TruthParticleAuxContainer* getTruthTauAuxContainer();
+  virtual xAOD::TruthParticleAuxContainer* getTruthTauAuxContainer() override;
+
+  virtual StatusCode retrieveTruthTaus() override;
+  virtual StatusCode retrieveTruthTaus(ITruthTausEvent& truthTausEvent) const override;
+
+
+protected:
+  StatusCode retrieveTruthTaus(TruthTausEvent& truthTausEvent) const;
 
-  StatusCode retrieveTruthTaus();
 
 private:
+
+  struct TauTruthInfo
+  {
+    size_t m_iNChargedPions = 0;
+    size_t m_iNNeutralPions = 0;
+    size_t m_iNChargedOthers = 0;
+    size_t m_iNNeutralOthers = 0;
+    size_t m_iNChargedDaughters = 0;
+    std::vector<int> m_vDecayMode;
+    // default false, if there is a hadron in decay products, it is switched to true
+    bool m_bIsHadronicTau = false;
+
+    // truth visible kinematic variables
+    TLorentzVector m_vTruthVisTLV;
+    TLorentzVector m_vTruthVisTLVCharged;
+    TLorentzVector m_vTruthVisTLVNeutral;
+  };
+
   // Execute at each event
-  virtual StatusCode beginEvent();
+  virtual StatusCode beginEvent() override;
 
-  StatusCode buildTruthTausFromTruthParticles();
-  StatusCode examineTruthTau(const xAOD::TruthParticle& xTruthParticle);
-  StatusCode examineTruthTauDecay(const xAOD::TruthParticle& xTruthParticle);
+  StatusCode buildTruthTausFromTruthParticles(TruthTausEvent& truthTausEvent) const;
+  StatusCode examineTruthTau(const xAOD::TruthParticle& xTruthParticle) const;
+  StatusCode examineTruthTauDecay(const xAOD::TruthParticle& xTruthParticle,
+                                  TauTruthInfo& truthInfo) const;
   void printDecay(const xAOD::TruthParticle& xTruthParticle, int depth = 0) const;
 
 protected:
@@ -73,23 +114,14 @@ protected:
 
   // steering variables
   bool m_bWriteTruthTaus;
-  bool m_bTruthTauAvailable;
+  mutable std::atomic<bool> m_bTruthTauAvailable;
 
-  const xAOD::TruthParticleContainer* m_xTruthTauContainerConst;
-  const xAOD::TruthParticleContainer* m_xTruthMuonContainerConst;
-  const xAOD::TruthParticleContainer* m_xTruthElectronContainerConst;
-  const xAOD::JetContainer* m_xTruthJetContainerConst;
-  xAOD::TruthParticleContainer* m_xTruthTauContainer;
+  TruthTausEvent m_truthTausEvent;
 
-  bool m_bIsTruthMatchedAvailable;
-  bool m_bIsTruthMatchedAvailableChecked;
-  bool m_bNewEvent;
+  CxxUtils::CachedValue<bool> m_bIsTruthMatchedAvailable;
 
 private:
 
-  const xAOD::TruthParticleContainer* m_xTruthParticleContainer;
-  xAOD::TruthParticleAuxContainer* m_xTruthTauAuxContainer;
-
   // steering variables
   std::string m_sNewTruthTauContainerName;
   std::string m_sNewTruthTauContainerNameAux;
@@ -99,27 +131,15 @@ private:
   std::string m_sTruthJetContainerName;
   std::string m_sTruthParticlesContainerName;
 
-  bool m_bTruthMuonAvailable;
-  bool m_bTruthElectronAvailable;
-  bool m_bTruthJetAvailable;
+  mutable std::atomic<bool> m_bTruthMuonAvailable;
+  mutable std::atomic<bool> m_bTruthElectronAvailable;
+  mutable std::atomic<bool> m_bTruthJetAvailable;
 
   bool m_bWriteInvisibleFourMomentum;
   bool m_bWriteVisibleChargedFourMomentum;
   bool m_bWriteVisibleNeutralFourMomentum;
   bool m_bWriteDecayModeVector;
 
-  size_t m_iNChargedPions;
-  size_t m_iNNeutralPions;
-  size_t m_iNChargedOthers;
-  size_t m_iNNeutralOthers;
-  size_t m_iNChargedDaughters;
-  std::vector<int> m_vDecayMode;
-
-  TLorentzVector m_vTruthVisTLV;
-  TLorentzVector m_vTruthVisTLVCharged;
-  TLorentzVector m_vTruthVisTLVNeutral;
-
-  bool m_bIsHadronicTau;
 
 private:
 
diff --git a/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/IBuildTruthTaus.h b/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/IBuildTruthTaus.h
index 4b7a34934956e9af75c4a42823dc0df0f6c56aea..79701eade69ee0a81ee95c69ec02d399dfb67409 100644
--- a/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/IBuildTruthTaus.h
+++ b/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/IBuildTruthTaus.h
@@ -1,7 +1,7 @@
 // Dear emacs, this is -*- c++ -*-
 
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef TAUANALYSISTOOLS_IBUILDTRUTHTAUS_H
@@ -35,6 +35,12 @@ class IBuildTruthTaus :
   ASG_TOOL_INTERFACE( TauAnalysisTools::IBuildTruthTaus )
 
 public:
+  class ITruthTausEvent
+  {
+  public:
+    virtual ~ITruthTausEvent() = default;
+  };
+  
   // initialize the tool
   virtual StatusCode initialize() = 0;
 
@@ -45,6 +51,7 @@ public:
   virtual xAOD::TruthParticleAuxContainer* getTruthTauAuxContainer() = 0;
 
   virtual StatusCode retrieveTruthTaus() = 0;
+  virtual StatusCode retrieveTruthTaus(ITruthTausEvent& truthTausEvent) const = 0;
 
 }; // class IBuildTruthTaus
 
diff --git a/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/ITauTruthMatchingTool.h b/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/ITauTruthMatchingTool.h
index 50346f3fd12e367349328a8f3f8068192ac1ade4..4eefa0812382fe8fb761585d78769705cf1fe456 100644
--- a/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/ITauTruthMatchingTool.h
+++ b/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/ITauTruthMatchingTool.h
@@ -1,7 +1,7 @@
 // Dear emacs, this is -*- c++ -*-
 
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef TAUANALYSISTOOLS_ITAUTRUTHMATCHINGTOOL_H
@@ -50,8 +50,12 @@ public:
   // apply match to all taus in a vector
   virtual std::vector<const xAOD::TruthParticle*> applyTruthMatch(const std::vector<const xAOD::TauJet*>& vTaus) = 0;
 
+  virtual std::unique_ptr<ITruthTausEvent> getEvent() const = 0;
+
   // get pointer to truth tau, if no truth tau was found a null pointer is returned
   virtual const xAOD::TruthParticle* getTruth(const xAOD::TauJet& xTau) = 0;
+  virtual const xAOD::TruthParticle* getTruth(const xAOD::TauJet& xTau,
+                                              ITruthTausEvent& truthTausEvent) const = 0;
 
   // wrapper function to get truth tau visible TLorentzvector
   virtual TLorentzVector getTruthTauP4Vis(const xAOD::TauJet& xTau) = 0;
diff --git a/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/ITauTruthTrackMatchingTool.h b/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/ITauTruthTrackMatchingTool.h
index 37da4c1213aad774c25139117541ff6ed002e641..113d759f9a4a38f935eaaf8d68af8a5c47125bad 100644
--- a/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/ITauTruthTrackMatchingTool.h
+++ b/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/ITauTruthTrackMatchingTool.h
@@ -1,7 +1,7 @@
 // Dear emacs, this is -*- c++ -*-
 
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef TAUANALYSISTOOLS_ITAUTRUTHTRACKMATCHINGTOOL_H
@@ -48,10 +48,10 @@ public:
   virtual StatusCode initialize() = 0;
 
   // classify vector of tracks
-  virtual StatusCode classifyTracks(std::vector<const TAUTRACKPARTICLE*>& vTracks) = 0;
+  virtual StatusCode classifyTracks(std::vector<const TAUTRACKPARTICLE*>& vTracks) const = 0;
 
   // classify a single track
-  virtual StatusCode classifyTrack(const TAUTRACKPARTICLE& xTrackParticle) = 0;
+  virtual StatusCode classifyTrack(const TAUTRACKPARTICLE& xTrackParticle) const = 0;
 
 }; // class ITauTruthTrackMatchingTool
 
diff --git a/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/TauTruthMatchingTool.h b/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/TauTruthMatchingTool.h
index 042a537ffe54950149861870dba5544c7ad384c3..2c5e9dbe82dbefa0f678c9d76a7dace3442c6638 100644
--- a/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/TauTruthMatchingTool.h
+++ b/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/TauTruthMatchingTool.h
@@ -1,7 +1,7 @@
 // Dear emacs, this is -*- c++ -*-
 
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef  TAUANALYSISTOOLS_TAUTRUTHMATCHINGTOOL_H
@@ -42,8 +42,12 @@ public:                         // Interface functions
   // initialize the tool
   virtual StatusCode initialize() override final;
 
+  virtual std::unique_ptr<ITruthTausEvent> getEvent() const override final;
+
   // get pointer to the truth matched particle, if no truth particle was found a null pointer is returned
   virtual const xAOD::TruthParticle* getTruth(const xAOD::TauJet& xTau) override final;
+  virtual const xAOD::TruthParticle* getTruth(const xAOD::TauJet& xTau,
+                                              ITruthTausEvent& truthTausEVent) const override final;
 
   // apply match to a single tau
   virtual const xAOD::TruthParticle* applyTruthMatch(const xAOD::TauJet& xTau) override final;
@@ -78,7 +82,8 @@ public:                         // Wrapper functions
 
 private:                        // private helper functions
 
-  StatusCode findTruthTau(const xAOD::TauJet& xTau);
+  StatusCode findTruthTau(const xAOD::TauJet& xTau,
+                          TruthTausEvent& truthTausEvent) const;
   StatusCode checkTruthMatch (const xAOD::TauJet& xTau, const xAOD::TruthParticleContainer& xTauContainer) const;
 
 private:                        // steering variables
diff --git a/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/TauTruthTrackMatchingTool.h b/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/TauTruthTrackMatchingTool.h
index 00a8bf3cbc3ceabb1e3f41165983ff665f3a2a3f..91097535d96588d62d211828dd370c8df70422ce 100644
--- a/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/TauTruthTrackMatchingTool.h
+++ b/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/TauTruthTrackMatchingTool.h
@@ -1,7 +1,7 @@
 // Dear emacs, this is -*- c++ -*-
 
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef  TAUANALYSISTOOLS_TAUTRUTHTRACKMATCHINGTOOL_H
@@ -27,6 +27,8 @@
 // EDM include(s)
 #include "xAODTruth/TruthVertex.h"
 
+#include "CxxUtils/CachedValue.h"
+
 
 namespace TauAnalysisTools
 {
@@ -56,25 +58,24 @@ public:
 
   virtual ~TauTruthTrackMatchingTool();
 
-  virtual StatusCode initialize();
+  virtual StatusCode initialize() override;
 
   // classify vector of tracks
-  virtual StatusCode classifyTracks(std::vector<const TAUTRACKPARTICLE*>& vTracks);
+  virtual StatusCode classifyTracks(std::vector<const TAUTRACKPARTICLE*>& vTracks) const override;
 
   // classify a single track
-  virtual StatusCode classifyTrack(const TAUTRACKPARTICLE& xTrackParticle);
+  virtual StatusCode classifyTrack(const TAUTRACKPARTICLE& xTrackParticle) const override;
 
 private:
 
-  StatusCode classifyConversion(const TAUTRACKPARTICLE& xTrackParticle, const xAOD::TruthParticle& xTruthParticle);
-  StatusCode checkTrackType(const TAUTRACKPARTICLE& xTrackParticle);
-  StatusCode checkTrackIsTauInheritant(const TAUTRACKPARTICLE& xTrackParticle);
-  bool checkTruthParent(const xAOD::TruthParticle& xTruthParticle, int& iDepth, std::string& sHistory);
-  const xAOD::TruthParticle* getTruthParticle(const TAUTRACKPARTICLE& xTrackParticle);
+  StatusCode classifyConversion(const TAUTRACKPARTICLE& xTrackParticle, const xAOD::TruthParticle& xTruthParticle) const;
+  StatusCode checkTrackType(const TAUTRACKPARTICLE& xTrackParticle) const;
+  StatusCode checkTrackIsTauInheritant(const TAUTRACKPARTICLE& xTrackParticle) const;
+  bool checkTruthParent(const xAOD::TruthParticle& xTruthParticle, int& iDepth, std::string& sHistory) const;
+  const xAOD::TruthParticle* getTruthParticle(const TAUTRACKPARTICLE& xTrackParticle) const;
 
 private:
-  bool m_bIsHadronicTrackAvailable;
-  bool m_bIsHadronicTrackAvailableChecked;
+  CxxUtils::CachedValue<bool> m_bIsHadronicTrackAvailable;
 
 }; // class TauTruthTrackMatchingTool