From bb3e2245316cdb96739cf83473fdf6daef2f02e9 Mon Sep 17 00:00:00 2001
From: christos <christos@cern.ch>
Date: Wed, 6 Jan 2021 01:20:57 +0100
Subject: [PATCH] ATLASRECTS-5840 :  Make egammaTruthAssociationAlg re-entrant

---
 .../src/egammaTruthAssociationAlg.cxx         | 159 ++++++++++++------
 .../src/egammaTruthAssociationAlg.h           |  26 ++-
 2 files changed, 114 insertions(+), 71 deletions(-)

diff --git a/Reconstruction/egamma/egammaAlgs/src/egammaTruthAssociationAlg.cxx b/Reconstruction/egamma/egammaAlgs/src/egammaTruthAssociationAlg.cxx
index c02b7197cd35..643c7e50af63 100644
--- a/Reconstruction/egamma/egammaAlgs/src/egammaTruthAssociationAlg.cxx
+++ b/Reconstruction/egamma/egammaAlgs/src/egammaTruthAssociationAlg.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
 */
 
 #include "egammaTruthAssociationAlg.h"
@@ -19,7 +19,7 @@ using PhotonLink_t = ElementLink<xAOD::PhotonContainer>;
 
 egammaTruthAssociationAlg::egammaTruthAssociationAlg(const std::string& name,
                                                      ISvcLocator* pSvcLocator)
-  : AthAlgorithm(name, pSvcLocator)
+  : AthReentrantAlgorithm(name, pSvcLocator)
 {}
 
 egammaTruthAssociationAlg::~egammaTruthAssociationAlg() {}
@@ -32,7 +32,8 @@ egammaTruthAssociationAlg::initialize()
 
   // initialize the data handles
   ATH_CHECK(m_truthEventContainerKey.initialize(m_doEgammaTruthContainer));
-  ATH_CHECK(m_egammaTruthParticleContainerKey.initialize(m_doEgammaTruthContainer));
+  ATH_CHECK(
+    m_egammaTruthParticleContainerKey.initialize(m_doEgammaTruthContainer));
   ATH_CHECK(m_truthParticleContainerKey.initialize());
 
   // Now the standard decoration handles
@@ -73,77 +74,105 @@ egammaTruthAssociationAlg::finalize()
 }
 
 StatusCode
-egammaTruthAssociationAlg::execute_r(const EventContext& ctx) const
+egammaTruthAssociationAlg::execute(const EventContext& ctx) const
 {
 
   SG::WriteHandle<xAOD::TruthParticleContainer> egammaTruthContainer;
 
   if (m_doEgammaTruthContainer) {
 
-    egammaTruthContainer =
-      SG::WriteHandle<xAOD::TruthParticleContainer>(m_egammaTruthParticleContainerKey, ctx);
-    ATH_CHECK(egammaTruthContainer.record(std::make_unique<xAOD::TruthParticleContainer>(),
-                                          std::make_unique<xAOD::TruthParticleAuxContainer>()));
+    egammaTruthContainer = SG::WriteHandle<xAOD::TruthParticleContainer>(
+      m_egammaTruthParticleContainerKey, ctx);
+    ATH_CHECK(egammaTruthContainer.record(
+      std::make_unique<xAOD::TruthParticleContainer>(),
+      std::make_unique<xAOD::TruthParticleAuxContainer>()));
 
     // Add a copy of electrons and photons to the truth egamma container
-    SG::ReadHandle<xAOD::TruthEventContainer> truthEvtContainer(m_truthEventContainerKey, ctx);
+    SG::ReadHandle<xAOD::TruthEventContainer> truthEvtContainer(
+      m_truthEventContainerKey, ctx);
 
     // only for serial running. Can remove check later
     if (!truthEvtContainer.isValid() || truthEvtContainer->empty()) {
-      ATH_MSG_WARNING("Could not retrieve " << m_truthEventContainerKey.key()
-                                            << " or container empty, returning");
+      ATH_MSG_WARNING("Could not retrieve "
+                      << m_truthEventContainerKey.key()
+                      << " or container empty, returning");
       return StatusCode::SUCCESS;
     }
 
-    for (const auto& truthParticleLink : truthEvtContainer->front()->truthParticleLinks()) {
+    for (const auto& truthParticleLink :
+         truthEvtContainer->front()->truthParticleLinks()) {
       if (!truthParticleLink.isValid())
         continue;
       const xAOD::TruthParticle* truthParticle = *truthParticleLink;
       if (!isPromptEgammaParticle(truthParticle))
         continue;
-      getNewTruthParticle(*egammaTruthContainer, truthParticle, truthParticleLink.getDataPtr());
+      getNewTruthParticle(
+        *egammaTruthContainer, truthParticle, truthParticleLink.getDataPtr());
     }
   }
   // Decorate containers with truth info, including links to truth particles
   // Decorate the truth particles with links to the reco ones
 
-  // note that in multithreading this must be valid; can't just fail with success.
-  SG::ReadHandle<xAOD::TruthParticleContainer> truthParticles(m_truthParticleContainerKey, ctx);
+  // note that in multithreading this must be valid; can't just fail with
+  // success.
+  SG::ReadHandle<xAOD::TruthParticleContainer> truthParticles(
+    m_truthParticleContainerKey, ctx);
 
   // accessors
-  static const SG::AuxElement::Accessor<ClusterLink_t> accClusLink("recoClusterLink");
-  static const SG::AuxElement::Accessor<ElectronLink_t> accElLink("recoElectronLink");
-  static const SG::AuxElement::Accessor<PhotonLink_t> accPhLink("recoPhotonLink");
+  static const SG::AuxElement::Accessor<ClusterLink_t> accClusLink(
+    "recoClusterLink");
+  static const SG::AuxElement::Accessor<ElectronLink_t> accElLink(
+    "recoElectronLink");
+  static const SG::AuxElement::Accessor<PhotonLink_t> accPhLink(
+    "recoPhotonLink");
 
   if (m_matchElectrons) {
     ATH_MSG_DEBUG("About to match electrons");
-    ATH_CHECK(match(*truthParticles, m_electronDecKeys, accElLink, egammaTruthContainer.ptr()));
+    ATH_CHECK(match(ctx,
+                    *truthParticles,
+                    m_electronDecKeys,
+                    accElLink,
+                    egammaTruthContainer.ptr()));
   }
 
   if (m_matchPhotons) {
     ATH_MSG_DEBUG("About to match photons");
-    ATH_CHECK(match(*truthParticles, m_photonDecKeys, accPhLink, egammaTruthContainer.ptr()));
+    ATH_CHECK(match(ctx,
+                    *truthParticles,
+                    m_photonDecKeys,
+                    accPhLink,
+                    egammaTruthContainer.ptr()));
   }
 
   if (m_matchClusters) {
     ATH_MSG_DEBUG("About to match clusters");
-    ATH_CHECK(match(*truthParticles, m_clusterDecKeys, accClusLink, egammaTruthContainer.ptr()));
+    ATH_CHECK(match(ctx,
+                    *truthParticles,
+                    m_clusterDecKeys,
+                    accClusLink,
+                    egammaTruthContainer.ptr()));
   }
 
   if (m_matchForwardElectrons) {
     ATH_MSG_DEBUG("About to match fwd electrons");
-    ATH_CHECK(match(*truthParticles, m_fwdElectronDecKeys, accElLink, egammaTruthContainer.ptr()));
+    ATH_CHECK(match(ctx,
+                    *truthParticles,
+                    m_fwdElectronDecKeys,
+                    accElLink,
+                    egammaTruthContainer.ptr()));
   }
 
   return StatusCode::SUCCESS;
 }
 
 bool
-egammaTruthAssociationAlg::isPromptEgammaParticle(const xAOD::TruthParticle* truth) const
+egammaTruthAssociationAlg::isPromptEgammaParticle(
+  const xAOD::TruthParticle* truth) const
 {
 
-  if ((truth->pdgId() != 22 && abs(truth->pdgId()) != 11) || truth->status() == 2 ||
-      truth->status() == 3 || truth->barcode() > m_barcodeOffset || truth->pt() < m_minPt){
+  if ((truth->pdgId() != 22 && abs(truth->pdgId()) != 11) ||
+      truth->status() == 2 || truth->status() == 3 ||
+      truth->barcode() > m_barcodeOffset || truth->pt() < m_minPt) {
     return false;
   }
 
@@ -185,10 +214,14 @@ egammaTruthAssociationAlg::getNewTruthParticle(
   truthParticle->setProdVtxLink(truth->prodVtxLink());
   truthParticle->setDecayVtxLink(truth->decayVtxLink());
 
-  static const SG::AuxElement::Accessor<ClusterLink_t> accClusLink("recoClusterLink");
-  static const SG::AuxElement::Accessor<ElectronLink_t> accElLink("recoElectronLink");
-  static const SG::AuxElement::Accessor<PhotonLink_t> accPhLink("recoPhotonLink");
-  static const SG::AuxElement::Accessor<TruthLink_t> accTruthLink("truthParticleLink");
+  static const SG::AuxElement::Accessor<ClusterLink_t> accClusLink(
+    "recoClusterLink");
+  static const SG::AuxElement::Accessor<ElectronLink_t> accElLink(
+    "recoElectronLink");
+  static const SG::AuxElement::Accessor<PhotonLink_t> accPhLink(
+    "recoPhotonLink");
+  static const SG::AuxElement::Accessor<TruthLink_t> accTruthLink(
+    "truthParticleLink");
   static const SG::AuxElement::Accessor<int> accType("truthType");
   static const SG::AuxElement::Accessor<int> accOrigin("truthOrigin");
 
@@ -213,7 +246,7 @@ egammaTruthAssociationAlg::getEgammaTruthParticle(
   const xAOD::TruthParticle* truth,
   xAOD::TruthParticleContainer& egammaTruthContainer) const
 {
-  if (!truth){
+  if (!truth) {
     return nullptr;
   }
   // Find the original truth particle for electrons from conversions
@@ -226,7 +259,7 @@ egammaTruthAssociationAlg::getEgammaTruthParticle(
   }
 
   // In case truth became null in the above loop
-  if (!truth){
+  if (!truth) {
     return nullptr;
   }
   for (auto egammaTruth : egammaTruthContainer) {
@@ -240,8 +273,9 @@ egammaTruthAssociationAlg::getEgammaTruthParticle(
 //// The templated functions
 template<class T>
 StatusCode
-egammaTruthAssociationAlg::initializeDecorKeys(SG::WriteDecorHandleKeyArray<T>& keys,
-                                               const std::string& name)
+egammaTruthAssociationAlg::initializeDecorKeys(
+  SG::WriteDecorHandleKeyArray<T>& keys,
+  const std::string& name)
 {
   if (!keys.empty()) {
     ATH_MSG_FATAL("The WriteDecorHandle should not be configured directly.");
@@ -258,16 +292,17 @@ egammaTruthAssociationAlg::initializeDecorKeys(SG::WriteDecorHandleKeyArray<T>&
 // constructor
 template<class T>
 egammaTruthAssociationAlg::writeDecorHandles<T>::writeDecorHandles(
-  const SG::WriteDecorHandleKeyArray<T>& hkeys)
-  : el(hkeys.at(0))
-  , type(hkeys.at(1))
-  , origin(hkeys.at(2))
+  const SG::WriteDecorHandleKeyArray<T>& hkeys,const EventContext& ctx)
+  : el(hkeys.at(0),ctx)
+  , type(hkeys.at(1),ctx)
+  , origin(hkeys.at(2),ctx)
 {}
 
 template<class T>
 egammaTruthAssociationAlg::MCTruthInfo_t
-egammaTruthAssociationAlg::particleTruthClassifier(const T* particle,
-                                                   Cache* extrapolationCache) const
+egammaTruthAssociationAlg::particleTruthClassifier(
+  const T* particle,
+  Cache* extrapolationCache) const
 {
   MCTruthInfo_t info;
   IMCTruthClassifier::Info mcinfo;
@@ -283,17 +318,20 @@ egammaTruthAssociationAlg::particleTruthClassifier(const T* particle,
  * second pass based on the cluster to find true photons **/
 template<>
 egammaTruthAssociationAlg::MCTruthInfo_t
-egammaTruthAssociationAlg::particleTruthClassifier<xAOD::Electron>(const xAOD::Electron* electron,
-                                                                   Cache* extrapolationCache) const
+egammaTruthAssociationAlg::particleTruthClassifier<xAOD::Electron>(
+  const xAOD::Electron* electron,
+  Cache* extrapolationCache) const
 {
   MCTruthInfo_t info;
   IMCTruthClassifier::Info mcinfo;
   mcinfo.extrapolationCache = extrapolationCache;
   auto ret = m_mcTruthClassifier->particleTruthClassifier(electron, &mcinfo);
   if (ret.first == MCTruthPartClassifier::Unknown &&
-      !xAOD::EgammaHelpers::isFwdElectron(electron) && electron->caloCluster()) {
+      !xAOD::EgammaHelpers::isFwdElectron(electron) &&
+      electron->caloCluster()) {
     ATH_MSG_DEBUG("Trying cluster-based truth classification for electron");
-    ret = m_mcTruthClassifier->particleTruthClassifier(electron->caloCluster(), &mcinfo);
+    ret = m_mcTruthClassifier->particleTruthClassifier(electron->caloCluster(),
+                                                       &mcinfo);
   }
   info.genPart = mcinfo.genPart;
   info.first = ret.first;
@@ -303,13 +341,15 @@ egammaTruthAssociationAlg::particleTruthClassifier<xAOD::Electron>(const xAOD::E
 
 template<class T, class L>
 StatusCode
-egammaTruthAssociationAlg::match(const xAOD::TruthParticleContainer& truthParticles,
-                                 const SG::WriteDecorHandleKeyArray<T>& hkeys,
-                                 const SG::AuxElement::Accessor<L>& linkAccess,
-                                 xAOD::TruthParticleContainer* egammaTruthContainer) const
+egammaTruthAssociationAlg::match(
+  const EventContext& ctx,
+  const xAOD::TruthParticleContainer& truthParticles,
+  const SG::WriteDecorHandleKeyArray<T>& hkeys,
+  const SG::AuxElement::Accessor<L>& linkAccess,
+  xAOD::TruthParticleContainer* egammaTruthContainer) const
 {
 
-  writeDecorHandles<T> decoHandles(hkeys);
+  writeDecorHandles<T> decoHandles(hkeys,ctx);
 
   // Extrapolation Cache
   Cache extrapolationCache{};
@@ -320,14 +360,17 @@ egammaTruthAssociationAlg::match(const xAOD::TruthParticleContainer& truthPartic
 
     const xAOD::TruthParticle* truthParticle = info.genPart;
     if (truthParticle) {
-      ElementLink<xAOD::TruthParticleContainer> link(truthParticle, truthParticles);
-      ATH_MSG_DEBUG("Decorating object with link to truth, index = " << link.index());
+      ElementLink<xAOD::TruthParticleContainer> link(
+        truthParticle, truthParticles, ctx);
+      ATH_MSG_DEBUG(
+        "Decorating object with link to truth, index = " << link.index());
       decoHandles.el(*particle) = link;
     } else {
       decoHandles.el(*particle) = ElementLink<xAOD::TruthParticleContainer>();
     }
     decoHandles.el(*particle).toPersistent();
-    ATH_MSG_DEBUG("truthType = " << info.first << " truthOrigin = " << info.second);
+    ATH_MSG_DEBUG("truthType = " << info.first
+                                 << " truthOrigin = " << info.second);
     decoHandles.type(*particle) = static_cast<int>(info.first);
     decoHandles.origin(*particle) = static_cast<int>(info.second);
 
@@ -337,11 +380,14 @@ egammaTruthAssociationAlg::match(const xAOD::TruthParticleContainer& truthPartic
         ATH_MSG_ERROR("The egammaTruthContainer needs to be valid");
         return StatusCode::FAILURE;
       }
-      const xAOD::TruthParticle* truth = xAOD::TruthHelpers::getTruthParticle(*particle);
+      const xAOD::TruthParticle* truth =
+        xAOD::TruthHelpers::getTruthParticle(*particle);
       if (truth) {
-        xAOD::TruthParticle* truthEgamma = getEgammaTruthParticle(truth, *egammaTruthContainer);
+        xAOD::TruthParticle* truthEgamma =
+          getEgammaTruthParticle(truth, *egammaTruthContainer);
         if (truthEgamma) {
-          // we found a truthEgamma object we should annotate if this is the best link
+          // we found a truthEgamma object we should annotate if this is the
+          // best link
           bool annotateLink = true;                   // by default we annotate
           const auto link = linkAccess(*truthEgamma); // what already exists
           if (link.isValid()) {
@@ -351,13 +397,14 @@ egammaTruthAssociationAlg::match(const xAOD::TruthParticleContainer& truthPartic
                   std::abs(particle->e() / truthEgamma->e() - 1)) {
               ATH_MSG_DEBUG(truthEgamma
                             << ": "
-                            << " already set to a better matched particle: " << particle);
+                            << " already set to a better matched particle: "
+                            << particle);
               annotateLink = false;
             }
           }
 
           if (annotateLink) {
-            L link(particle, *decoHandles.readHandle());
+            L link(particle, *decoHandles.readHandle(), ctx);
             linkAccess(*truthEgamma) = link;
             linkAccess(*truthEgamma).toPersistent();
           }
diff --git a/Reconstruction/egamma/egammaAlgs/src/egammaTruthAssociationAlg.h b/Reconstruction/egamma/egammaAlgs/src/egammaTruthAssociationAlg.h
index f695fba988b8..363cb365e7b3 100644
--- a/Reconstruction/egamma/egammaAlgs/src/egammaTruthAssociationAlg.h
+++ b/Reconstruction/egamma/egammaAlgs/src/egammaTruthAssociationAlg.h
@@ -5,7 +5,7 @@
 #ifndef EGAMMAALGS_EGAMMATRUTHASSOCIATIONALG_H
 #define EGAMMAALGS_EGAMMATRUTHASSOCIATIONALG_H
 
-#include "AthenaBaseComps/AthAlgorithm.h"
+#include "AthenaBaseComps/AthReentrantAlgorithm.h"
 #include "GaudiKernel/EventContext.h"
 #include "GaudiKernel/ToolHandle.h"
 #include "MCTruthClassifier/IMCTruthClassifier.h"
@@ -38,7 +38,7 @@
    @author B. Lenzi J. Mitrevski C. Anastopoulos
 */
 
-class egammaTruthAssociationAlg : public AthAlgorithm
+class egammaTruthAssociationAlg : public AthReentrantAlgorithm
 {
 
 public:
@@ -56,13 +56,7 @@ public:
   virtual StatusCode finalize() override final;
 
   /** @brief execute on container */
-  virtual StatusCode execute() override final
-  {
-    return execute_r(Algorithm::getContext());
-  }
-  // This will become the normal execute when
-  // inheriting from AthReentrantAlgorithm
-  StatusCode execute_r(const EventContext& ctx) const;
+  virtual StatusCode execute(const EventContext& ctx) const override final;
 
 private:
   struct MCTruthInfo_t
@@ -82,8 +76,8 @@ private:
   template<class T>
   struct writeDecorHandles
   {
-    writeDecorHandles(
-      const SG::WriteDecorHandleKeyArray<T>& keys); // constructor
+    writeDecorHandles(const SG::WriteDecorHandleKeyArray<T>& keys,
+                      const EventContext& ctx); // constructor
 
     SG::WriteDecorHandle<T, ElementLink<xAOD::TruthParticleContainer>> el;
     SG::WriteDecorHandle<T, int> type;
@@ -97,7 +91,8 @@ private:
    * info and decorate the truth particles with links to the reco ones
    * (reco<typeName>Link) **/
   template<class T, class L>
-  StatusCode match(const xAOD::TruthParticleContainer& truthParticles,
+  StatusCode match(const EventContext& ctx,
+                   const xAOD::TruthParticleContainer& truthParticles,
                    const SG::WriteDecorHandleKeyArray<T>& hkeys,
                    const SG::AuxElement::Accessor<L>& linkAccess,
                    xAOD::TruthParticleContainer* egammaTruthContainer) const;
@@ -110,9 +105,10 @@ private:
 
   /** @brief Create a copy a truth particle, add it to the new container and
    * decorate it with a link to the original particle **/
-  void getNewTruthParticle(xAOD::TruthParticleContainer& egammaTruthContainer,
-                           const xAOD::TruthParticle* truth,
-                           const xAOD::TruthParticleContainer* oldContainer) const;
+  void getNewTruthParticle(
+    xAOD::TruthParticleContainer& egammaTruthContainer,
+    const xAOD::TruthParticle* truth,
+    const xAOD::TruthParticleContainer* oldContainer) const;
 
   /** @brief Return true if the truth particle is a prompt electron or photon
    * **/
-- 
GitLab