From 79743063cc6fdbbb47bc109b89b75551761c8a67 Mon Sep 17 00:00:00 2001
From: Marcin Nowak <Marcin.Nowak@cern.ch>
Date: Wed, 23 Jan 2019 09:34:11 +0100
Subject: [PATCH] Fix HITS->RDO with standard EventLoopMgr

EventInfo reading and conversion code moved from PileUpStream to
PileUpMergeSvc. Restored option to read old EventInfo in PileUpMergeSvc.
Setting SG pointer in const xAOD::EventInfo now possible.
---
 .../PileUpComps/src/PileUpEventLoopMgr.cxx    |   8 -
 Control/PileUpComps/src/PileUpEventLoopMgr.h  |   6 -
 .../PileUpTools/PileUpTools/PileUpMergeSvc.h  |   9 +-
 .../PileUpTools/PileUpMergeSvc.icc            |  43 +++-
 .../PileUpTools/PileUpTools/PileUpStream.h    |  15 +-
 Control/PileUpTools/src/PileUpMergeSvc.cxx    | 187 +++++++++++++++++-
 Control/PileUpTools/src/PileUpStream.cxx      | 157 +--------------
 .../xAOD/xAODEventInfo/Root/EventInfo_v1.cxx  |   2 +-
 .../xAODEventInfo/versions/EventInfo_v1.h     |   4 +-
 9 files changed, 237 insertions(+), 194 deletions(-)

diff --git a/Control/PileUpComps/src/PileUpEventLoopMgr.cxx b/Control/PileUpComps/src/PileUpEventLoopMgr.cxx
index 276cfde7c452..3bae7b7e13ef 100644
--- a/Control/PileUpComps/src/PileUpEventLoopMgr.cxx
+++ b/Control/PileUpComps/src/PileUpEventLoopMgr.cxx
@@ -33,7 +33,6 @@
 
 // xAOD include(s):
 #include "xAODCore/tools/PrintHelpers.h"
-#include "xAODCnvInterfaces/IEventInfoCnvTool.h"
 #include "EventInfoUtils/EventInfoFromxAOD.h"
 
 // Gaudi headers
@@ -72,7 +71,6 @@ PileUpEventLoopMgr::PileUpEventLoopMgr(const std::string& name,
     m_failureMode(1),
     m_beamInt("FlatBM", name),
     m_beamLumi("LumiProfileSvc", name),
-    m_xAODCnvTool("xAODMaker::EventInfoCnvTool/EventInfoCnvTool", this),//Will need a special configuration here + extra config tweaks
     m_currentRun(0), m_firstRun(true),
     m_msg( name ),
     m_maxBunchCrossingPerOrbit(3564),
@@ -108,7 +106,6 @@ PileUpEventLoopMgr::PileUpEventLoopMgr(const std::string& name,
   declareProperty("BeamLuminosity", m_beamLumi,
                   "The service providing the beam luminosity distribution vs. run");
   declareProperty("PileUpMergeSvc", m_mergeSvc, "PileUp Merge Service");
-  declareProperty( "xAODCnvTool", m_xAODCnvTool );
   declareProperty("IsEmbedding", m_isEmbedding, "Set this to True for embedding jobs.");
   declareProperty("AllowSerialAndMPToDiffer", m_allowSerialAndMPToDiffer, "When set to False, this will allow the code to reproduce serial output in an AthenaMP job, albeit with a significant performance penalty.");
   //  m_caches.push_back("BkgStreamsCache/MinBiasCache");
@@ -153,9 +150,6 @@ StatusCode PileUpEventLoopMgr::initialize()
   //locate the IncidentSvc and initialize our local ptr
   CHECK(m_incidentSvc.retrieve());
 
-  // Retrieve the converter tool:
-  CHECK(m_xAODCnvTool.retrieve());
-
   //locate the PileUpMergeSvc and initialize our local ptr
   CHECK(m_mergeSvc.retrieve());
 
@@ -655,8 +649,6 @@ PileUpEventLoopMgr::setupStreams()
           return StatusCode::FAILURE;
         }
     }
-  // MN: FIX:  Pass the converter tool to PileUpStream in an ugly hack
-  PileUpStream::m_xAODCnvTool = &*m_xAODCnvTool;
 
   //now get the bkg stream caches, and set them up
   CHECK(m_caches.retrieve());
diff --git a/Control/PileUpComps/src/PileUpEventLoopMgr.h b/Control/PileUpComps/src/PileUpEventLoopMgr.h
index b964fa7e9a56..29e16890c438 100644
--- a/Control/PileUpComps/src/PileUpEventLoopMgr.h
+++ b/Control/PileUpComps/src/PileUpEventLoopMgr.h
@@ -29,10 +29,6 @@
 class IBeamIntensity;
 class IBeamLuminosity;
 class IBkgStreamsCache;
-namespace xAODMaker
-{
-  class IEventInfoCnvTool;
-}
 class IEvtSelector;
 class IIncidentSvc;
 class ITimeKeeper;
@@ -156,8 +152,6 @@ private:
   ServiceHandle<IBeamIntensity> m_beamInt;
   /// property: beam intensity service handle for luminosity profile in iovtime
   ServiceHandle<IBeamLuminosity> m_beamLumi;
-  /// property: Handle to the EventInfo -> xAOD::EventInfo converter tool
-  ToolHandle< xAODMaker::IEventInfoCnvTool > m_xAODCnvTool;
   //@}
 
   /// current run number
diff --git a/Control/PileUpTools/PileUpTools/PileUpMergeSvc.h b/Control/PileUpTools/PileUpTools/PileUpMergeSvc.h
index 41df8acaf505..7a8d562ac389 100755
--- a/Control/PileUpTools/PileUpTools/PileUpMergeSvc.h
+++ b/Control/PileUpTools/PileUpTools/PileUpMergeSvc.h
@@ -16,6 +16,7 @@
 #include "EventInfo/PileUpTimeEventIndex.h"
 #include "xAODEventInfo/EventInfo.h"
 #include "PileUpTools/IPileUpTool.h"    /* subEventIterator*/
+#include "xAODCnvInterfaces/IEventInfoCnvTool.h"
 
 #include "AthenaBaseComps/AthService.h"
 #include "GaudiKernel/ClassID.h"
@@ -113,9 +114,11 @@ public:
   static const InterfaceID& interfaceID();
   virtual StatusCode queryInterface( const InterfaceID& riid, void** ppvInterface );
 
+  /// get EventInfo from SG, by default using p_overStore
+  const xAOD::EventInfo* getPileUpEvent( StoreGateSvc* sg = nullptr,
+                                         const std::string& einame = "OverlayEvent" ) const;
+
 private:
-  // hack to make gcc happy
-  const xAOD::EventInfo* getPileUpEvent() const;
   ServiceHandle<StoreGateSvc> p_overStore;      ///< overlaid SG (default)
   ServiceHandle<ActiveStoreSvc> p_activeStore;  ///< current active store
   ToolHandleArray<IPileUpXingFolder> m_intervals; ///< Property: bunch xing intervals
@@ -173,6 +176,8 @@ private:
 
   bool doRefresh(const Range& r, int iXing);
 
+  /// property: Handle to the EventInfo -> xAOD::EventInfo converter tool
+  ToolHandle< xAODMaker::IEventInfoCnvTool > m_xAODCnvTool;
 };
 #include "PileUpTools/PileUpMergeSvc.icc"
 #endif /* PILEUPTOOLS_PILEUPMERGESVC_H */
diff --git a/Control/PileUpTools/PileUpTools/PileUpMergeSvc.icc b/Control/PileUpTools/PileUpTools/PileUpMergeSvc.icc
index 2b26090dea05..018a47c519eb 100755
--- a/Control/PileUpTools/PileUpTools/PileUpMergeSvc.icc
+++ b/Control/PileUpTools/PileUpTools/PileUpMergeSvc.icc
@@ -112,9 +112,20 @@ PileUpMergeSvc::retrieveSubEvtsData(const KEY& dataKey, //orig evt key
     }  
     //reset active store pointer to default event store FIXME DANGEROUS
     p_activeStore->setStore(&*p_overStore);
-  } else {		
-     ATH_MSG_FATAL ( "no EventInfo object found!" );
-     return StatusCode::FAILURE;
+  } else {
+     ATH_MSG_DEBUG ( "default PileUpEventInfo not found, trying any EventInfo" ); 
+     // check for EventInfo with any key name
+     pEvent = getPileUpEvent( p_activeStore->activeStore(), "" );
+     if( pEvent ) {
+        DataLink_t dLink;
+        fillLink(dLink, dataKey);
+        if (dLink.isValid()) {
+           timedData.push_back(std::make_pair(0, dLink));
+        }
+     } else {
+        ATH_MSG_FATAL ( "no EventInfo object found!" );
+        return StatusCode::FAILURE;
+     }
   }
   return StatusCode::SUCCESS;
 }
@@ -188,7 +199,6 @@ PileUpMergeSvc::retrieveSingleSubEvtData(const KEY& dataKey, const DATA*& data,
 
 }
 
-
 ///retrieve keyed DATA objs for all sub-events and attach a time to them
 template <typename KEY, typename TIMEDDATA>
 StatusCode 
@@ -202,9 +212,13 @@ PileUpMergeSvc::retrieveSubEvtsData(const KEY& dataKey, //orig evt key
   //FIXME we still have to check we are dealing with a sequence:
   //  boost::function_requires < boost::SequenceConcept<TIMEDDATA> > ();
   const xAOD::EventInfo* pEvent = getPileUpEvent();
+
+  void dumpPileup( const xAOD::EventInfo* );
+  dumpPileup( pEvent );  //MN: remove
+ 
   if (pEvent) {
-    // access the sub events DATA objects...
-    for( const xAOD::EventInfo::SubEvent& subEv : pEvent->subEvents() ) {
+     // access the sub events DATA objects...
+     for( const xAOD::EventInfo::SubEvent& subEv : pEvent->subEvents() ) {
       //skip if dobj not active for this xing 
       //FIXME      if (!isLive<data_t>(dataKey, int(iEvt->time()))) {
       //FIXME turning the double iEvt->time() is fraught with peril. Luckily 
@@ -251,9 +265,20 @@ PileUpMergeSvc::retrieveSubEvtsData(const KEY& dataKey, //orig evt key
     }  
     //reset active store pointer to default event store FIXME DANGEROUS
     p_activeStore->setStore(&*p_overStore);
-  } else {		
-     ATH_MSG_FATAL ( "no EventInfo object found!" );
-     return StatusCode::FAILURE;
+  } else {
+     ATH_MSG_DEBUG ( "default PileUpEventInfo not found, trying any EventInfo" ); 
+     // check for EventInfo with any key name
+     pEvent = getPileUpEvent( p_activeStore->activeStore(), "" );
+     if( pEvent ) {
+        DataLink_t dLink;
+        fillLink(dLink, dataKey);
+        if (dLink.isValid()) {
+           timedData.push_back(std::make_pair(0, dLink));
+        }
+     } else {
+        ATH_MSG_FATAL ( "no EventInfo object found!" );
+        return StatusCode::FAILURE;
+     }
   }
   return StatusCode::SUCCESS;
 }
diff --git a/Control/PileUpTools/PileUpTools/PileUpStream.h b/Control/PileUpTools/PileUpTools/PileUpStream.h
index faff1bb2c51e..1bba5bdf8632 100755
--- a/Control/PileUpTools/PileUpTools/PileUpStream.h
+++ b/Control/PileUpTools/PileUpTools/PileUpStream.h
@@ -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
 */
 
 #ifndef PILEUPSTREAM_PILEUPSTREAM_H
@@ -23,10 +23,7 @@ class IMessageSvc;
 class ISvcLocator;
 class StoreGateSvc;
 class ActiveStoreSvc;
-namespace xAODMaker
-{
-  class IEventInfoCnvTool;
-}
+class PileUpMergeSvc;
 
 /** @class PileUpStream
  * @brief a triple selector/context/store defines a stream
@@ -74,8 +71,6 @@ public:
   /// backward compatibility
   inline bool setupStore(bool ) { return setupStore();}
 
-  void setEICnvTool( xAODMaker::IEventInfoCnvTool *tool ) { m_xAODCnvTool = tool; }
-
   /// finalize and release store. To be called on ... finalize()
   StatusCode finalize();
 
@@ -127,6 +122,8 @@ private:
   /// Input Iterators
   EvtIterator* p_iter; 
 
+  PileUpMergeSvc* p_mergeSvc;
+  
   ActiveStoreSvc* p_activeStore;
 
   //mutable so that ownership can be passed upon copy
@@ -139,10 +136,6 @@ private:
   bool m_used; ///has this stream already been used? (for the current event)
   bool m_hasRing;
   unsigned int m_iOriginalRing; ///> original ring in which event was used
-
-public:
-  /// EventInfo -> xAOD::EventInfo converter tool
-  static xAODMaker::IEventInfoCnvTool *m_xAODCnvTool;
 };
 #endif // PILEUPSTREAM_PILEUPSTREAM_H
 
diff --git a/Control/PileUpTools/src/PileUpMergeSvc.cxx b/Control/PileUpTools/src/PileUpMergeSvc.cxx
index 37d4402681f2..c66694462834 100755
--- a/Control/PileUpTools/src/PileUpMergeSvc.cxx
+++ b/Control/PileUpTools/src/PileUpMergeSvc.cxx
@@ -9,6 +9,21 @@
 #include "SGTools/DataStore.h"
 #include "PileUpTools/IPileUpXingFolder.h"
 
+#include "EventInfo/EventInfo.h"
+#include "xAODEventInfo/EventInfoContainer.h"
+
+#include "EventInfo/EventInfo.h"
+#include "EventInfo/EventID.h"
+#include "EventInfo/EventType.h" 
+#include "EventInfo/PileUpEventInfo.h" 
+#include "EventInfo/PileUpTimeEventIndex.h"
+#include "xAODCore/tools/PrintHelpers.h"
+
+#include "xAODEventInfo/EventInfo.h"             // NEW EDM
+#include "xAODEventInfo/EventAuxInfo.h"          // NEW EDM
+#include "xAODEventInfo/EventInfoContainer.h"    // NEW EDM
+#include "xAODEventInfo/EventInfoAuxContainer.h" // NEW EDM
+
 #include "GaudiKernel/ISvcLocator.h"
 #include "GaudiKernel/IAlgTool.h"
 #include "GaudiKernel/GaudiException.h"
@@ -24,6 +39,28 @@ using std::bind1st;
 using std::mem_fun;
 using std::string;
 
+
+#include <iostream>
+using namespace std;
+#include "xAODCore/tools/PrintHelpers.h"
+
+void dumpPileup( const xAOD::EventInfo* ev ) {
+   std::cout << "MN: dumpPileup: ";
+   if( ev ) {  
+      cout << ev->subEvents().size() << " subevents" << std::endl;
+      xAOD::dump( *ev );
+      int n = 0;
+      for( const xAOD::EventInfo::SubEvent& subEv : ev->subEvents() ) {
+         std::cout << "   MN: subev " << n << " : time =" <<  subEv.time() << std::endl;
+         std::cout << "             : index =" <<  subEv.index() << std::endl;
+         std::cout << "             : ptr =" <<  subEv.ptr() << std::endl;
+         std::cout << "             : link =" <<  subEv.link() << std::endl;
+         if( n++ > 0 ) break;
+      }
+   }
+   cout << endl;
+}
+
 /// Standard Constructor
 PileUpMergeSvc::PileUpMergeSvc(const std::string& name,ISvcLocator* svc)
   : AthService(name,svc), 
@@ -31,12 +68,14 @@ PileUpMergeSvc::PileUpMergeSvc(const std::string& name,ISvcLocator* svc)
     p_activeStore("ActiveStoreSvc", "ActiveStoreSvc"),
     m_intervals(this),
     m_pITriggerTime(""),
-    m_returnTimedData(true)
+    m_returnTimedData(true),
+    m_xAODCnvTool("xAODMaker::EventInfoCnvTool/EventInfoCnvTool", this)
 {
   declareProperty("Intervals", m_intervals, "Folders specifying bunch xing intervals for different data objects");
   declareProperty("TriggerTimeTool", m_pITriggerTime, "allows to apply a trigger time offset");
   declareProperty("ReturnTimedData", m_returnTimedData, 
 		  "determine whether the TimedData returned by retrieveSubEvts have non trivial PileUpTimeEventIndex. May be set to false for overlay with real events ");
+  declareProperty( "xAODCnvTool", m_xAODCnvTool );
 }
 
 /// setup PileUpIntervals
@@ -99,6 +138,8 @@ PileUpMergeSvc::initialize()    {
           << endmsg;
       return StatusCode::FAILURE;
   }
+  // Retrieve the converter tool:
+  CHECK(m_xAODCnvTool.retrieve());
 
   decodeIntervals();
   
@@ -107,16 +148,148 @@ PileUpMergeSvc::initialize()    {
 
 }
 
-const xAOD::EventInfo* PileUpMergeSvc::getPileUpEvent() const {
-   const xAOD::EventInfo* p = nullptr;
-   if( p_overStore->contains<xAOD::EventInfo>("OverlayEvent") ) {
-      if (p_overStore->retrieve(p).isFailure()) {
-         ATH_MSG_FATAL("Cannot retrieve OverlayEvent from " << p_overStore->name());
+
+const xAOD::EventInfo* PileUpMergeSvc::getPileUpEvent( StoreGateSvc* sg, const std::string& einame ) const
+{
+   if( !sg ) sg = p_overStore.get();
+   const xAOD::EventInfo* xAODEventInfo = einame.empty()?
+      sg->tryConstRetrieve<xAOD::EventInfo>()
+      : sg->tryConstRetrieve<xAOD::EventInfo>( einame );
+   cout << "MN: getPileUpEvent: xAODEI=" << (void*)xAODEventInfo << endl;
+   if( xAODEventInfo ) {
+      ATH_MSG_INFO("Found xAOD::EventInfo");
+      ATH_MSG_INFO(" EventInfo has" <<   xAODEventInfo->subEvents().size() << " subevents" );
+      // the loop below serves 2 purposes: to recreate subevent links cache
+      // and set SG pointer in subevents
+      for( auto& subev : xAODEventInfo->subEvents() ) {
+         const_cast<xAOD::EventInfo*>(subev.ptr())->setEvtStore( sg );
+      }
+   } else {
+      // Try reading old EventInfo
+      const EventInfo* pEvent = einame.empty()?
+         sg->tryConstRetrieve< ::EventInfo >()
+         : sg->tryConstRetrieve< ::EventInfo >( einame );
+      cout << "MN: getPileUpEvent: EI<" << einame << "> =" << (void*)pEvent << endl;
+      if( pEvent ) {
+         ATH_MSG_INFO("Found OverlayEvent old type EventInfo" );
+
+         ATH_MSG_DEBUG("Converting (PileUp)EventInfo to xAOD::EventInfo");
+         // Create the xAOD object(s):
+         std::unique_ptr< xAOD::EventInfo >  pxAODEventInfo( new xAOD::EventInfo() );
+         std::unique_ptr< xAOD::EventAuxInfo > pxAODEventAuxInfo(new xAOD::EventAuxInfo());
+         pxAODEventInfo->setStore( pxAODEventAuxInfo.get() );
+         if( !m_xAODCnvTool->convert( pEvent, pxAODEventInfo.get(), false, false ).isSuccess() ) {
+            ATH_MSG_ERROR("Failed to convert  xAOD::EventInfo in SG");
+            return nullptr;
+         }
+
+         //ATH_MSG_INFO ("Dumping xAOD::EventInfo prior to adding SubEvents");
+         //xAOD::dump( *xAODEventInfo );
+
+         const PileUpEventInfo* pileupEvent(dynamic_cast<const PileUpEventInfo*>(pEvent));
+         if( pileupEvent ) {
+            cout << "MN: PileUpStream: converting PileUpEventInfo" << endl;
+            // Create an EventInfoContainer for the pileup events:
+            std::unique_ptr< xAOD::EventInfoContainer > puei(new xAOD::EventInfoContainer());
+            std::unique_ptr< xAOD::EventInfoAuxContainer > puaux(new xAOD::EventInfoAuxContainer());
+            puei->setStore( puaux.get() );
+
+            // Sub-events for the main EventInfo object:
+            std::vector< xAOD::EventInfo::SubEvent > subEvents;
+
+            // A map translating between the AOD and xAOD pileup event types:
+            static std::map< PileUpEventInfo::SubEvent::pileup_type,
+               xAOD::EventInfo::PileUpType > pileupTypeMap;
+            if( ! pileupTypeMap.size() ) {
+#define DECLARE_SE_TYPE( TYPE )                                         \
+               pileupTypeMap[ PileUpTimeEventIndex::TYPE ] = xAOD::EventInfo::TYPE
+
+               DECLARE_SE_TYPE( Unknown );
+               DECLARE_SE_TYPE( Signal );
+               DECLARE_SE_TYPE( MinimumBias );
+               DECLARE_SE_TYPE( Cavern );
+               DECLARE_SE_TYPE( HaloGas );
+               DECLARE_SE_TYPE( ZeroBias );
+
+#undef DECLARE_SE_TYPE
+            }
+
+            // A convenience type declaration:
+            typedef ElementLink< xAOD::EventInfoContainer > EiLink;
+
+            // Create xAOD::EventInfo objects for each pileup EventInfo object:
+            auto pu_itr = pileupEvent->beginSubEvt();
+            auto pu_end = pileupEvent->endSubEvt();
+            const unsigned int countEvents = std::distance(pu_itr,pu_end);
+            ATH_MSG_VERBOSE( "CHECKING: There are " << countEvents << " subevents in this Event." );
+            cout << "MN: There are " << countEvents << " subevents in this Event." <<endl;
+
+            for( ; pu_itr != pu_end; ++pu_itr ) {
+               // Create a new xAOD::EventInfo object:
+               std::unique_ptr< xAOD::EventInfo > ei( new xAOD::EventInfo() );
+               // Fill it with information:
+               if( ! m_xAODCnvTool->convert( pu_itr->pSubEvt, ei.get(), true, false ).isSuccess() ) {
+                  ATH_MSG_ERROR("Failed to convert EventInfo to xAOD::EventInfo");
+                  continue;
+               }
+
+               StoreGateSvc* tmpSG = pu_itr->pSubEvtSG;
+               if(tmpSG) {
+                  ei->setEvtStore(tmpSG);
+                  ATH_MSG_VERBOSE("FOUND A STOREGATE");
+               } else {
+                  ATH_MSG_ERROR("FAILED TO FIND A STOREGATE");
+               }
+               // Store new EI into the container
+               puei->push_back( ei.release() );
+      
+               // And now add a sub-event to the temporary list:
+               auto typeItr = pileupTypeMap.find( pu_itr->type() );
+               xAOD::EventInfo::PileUpType type = xAOD::EventInfo::Unknown;
+               if( typeItr == pileupTypeMap.end() ) {
+                  ATH_MSG_WARNING( "PileUpType not recognised: " << pu_itr->type() );
+               } else {
+                  type = typeItr->second;
+               }
+               ATH_MSG_VERBOSE("PileUpEventInfo: time = " << pu_itr->time() << ", index = " << pu_itr->index());
+               subEvents.push_back( xAOD::EventInfo::SubEvent( pu_itr->time(),
+                                                               pu_itr->index(),
+                                                               type,
+                                                               EiLink( "PileUpEventInfo", puei->size()-1, sg )));  // p_SG?
+               ATH_MSG_VERBOSE("PileUpEventInfo: time = " << subEvents.back().time() << ", index = " << subEvents.back().index());
+            }
+
+            if( subEvents.size() ) {
+               // And now update the main EventInfo object with the sub-events:
+               pxAODEventInfo->setSubEvents( subEvents );
+
+               // Record the xAOD object(s):
+               if( !sg->record( std::move( puaux ), "PileUpEventInfoAux." ).isSuccess()
+                   || !sg->record( std::move( puei ), "PileUpEventInfo" ).isSuccess() ) {  //MN: FIX - make keys configurable
+                  ATH_MSG_ERROR("Failed to record xAOD::EventInfoContainer in SG");
+               }
+            }
+         }
+         xAODEventInfo = pxAODEventInfo.get();  // remember pointer to return the new EventInfo
+         // Record the xAOD object(s):
+         if( ! sg->record( std::move( pxAODEventAuxInfo ), "EventInfoAux." ).isSuccess() //MN: FIX? key
+             || ! sg->record( std::move( pxAODEventInfo ), "EventInfo" ).isSuccess() ) {
+            ATH_MSG_ERROR("Failed to record the new xAOD::EventInfo in SG");
+         }
       }
    }
-   return p;
+
+   if( xAODEventInfo ) {
+      const_cast<xAOD::EventInfo*>(xAODEventInfo)->setEvtStore( sg );
+      ATH_MSG_INFO("Dumping xAOD::EventInfo");
+      xAOD::dump( *xAODEventInfo );
+   } else {
+      ATH_MSG_DEBUG("Could not find EventInfo '" << einame << "' in store " << sg->name());
+   }
+   return xAODEventInfo;
 }
 
+
 const InterfaceID& 
 PileUpMergeSvc::interfaceID() {
   static const InterfaceID IID_IPileUpMergeSvc(9991, 1, 0); //FIXME
diff --git a/Control/PileUpTools/src/PileUpStream.cxx b/Control/PileUpTools/src/PileUpStream.cxx
index c02356703097..680458381852 100755
--- a/Control/PileUpTools/src/PileUpStream.cxx
+++ b/Control/PileUpTools/src/PileUpStream.cxx
@@ -18,35 +18,21 @@
 
 #include "SGTools/DataProxy.h"
 
-#include "EventInfo/EventInfo.h"
-#include "EventInfo/EventID.h"
-#include "EventInfo/EventType.h" 
-#include "EventInfo/PileUpEventInfo.h" 
-#include "EventInfo/PileUpTimeEventIndex.h" 
-
 #include "xAODEventInfo/EventInfo.h"             // NEW EDM
-#include "xAODEventInfo/EventAuxInfo.h"          // NEW EDM
-#include "xAODEventInfo/EventInfoContainer.h"    // NEW EDM
-#include "xAODEventInfo/EventInfoAuxContainer.h" // NEW EDM
-#include "xAODCnvInterfaces/IEventInfoCnvTool.h"
-#include "xAODCore/tools/PrintHelpers.h"
 
 #include "StoreGate/ActiveStoreSvc.h"
 #include "AthenaBaseComps/AthMsgStreamMacros.h"
+#include "PileUpTools/PileUpMergeSvc.h"
 
-/* #include "GaudiKernel/IOpaqueAddress.h" */
 class IOpaqueAddress;
 
 #include <iostream>
 using namespace std;
 
-// EventInfo -> xAOD::EventInfo converter tool
-xAODMaker::IEventInfoCnvTool* PileUpStream::m_xAODCnvTool = nullptr;
-
 /// Structors
 PileUpStream::PileUpStream():
   m_name("INVALID"), p_svcLoc(0), p_sel(0), p_SG(0), p_iter(0), 
-  p_activeStore(0), m_ownEvtIterator(false),
+  p_mergeSvc(nullptr), p_activeStore(0), m_ownEvtIterator(false),
   m_msg("PileUpStream"), m_neverLoaded(true), m_ownStore(false),
   m_used(false), m_hasRing(false), m_iOriginalRing(0)
 { 
@@ -54,7 +40,7 @@ PileUpStream::PileUpStream():
 
 PileUpStream::PileUpStream(const PileUpStream& rhs):
   m_name(rhs.m_name), p_svcLoc(rhs.p_svcLoc), p_sel(rhs.p_sel), 
-  p_SG(rhs.p_SG), p_iter(rhs.p_iter), p_activeStore(rhs.p_activeStore),
+  p_SG(rhs.p_SG), p_iter(rhs.p_iter), p_mergeSvc(rhs.p_mergeSvc), p_activeStore(rhs.p_activeStore),
   m_ownEvtIterator(rhs.m_ownEvtIterator), m_msg(rhs.m_msg),
   m_neverLoaded(rhs.m_neverLoaded), m_ownStore(rhs.m_ownStore),
   m_used(rhs.m_used), m_hasRing(rhs.m_hasRing), m_iOriginalRing(rhs.m_iOriginalRing)
@@ -72,6 +58,7 @@ PileUpStream::operator=(const PileUpStream& rhs) {
     p_sel=rhs.p_sel; 
     p_SG=rhs.p_SG; 
     p_iter=rhs.p_iter;
+    p_mergeSvc = rhs.p_mergeSvc;
     p_activeStore=rhs.p_activeStore;
     m_ownEvtIterator=rhs.m_ownEvtIterator;
     rhs.m_ownEvtIterator=false;
@@ -96,8 +83,9 @@ PileUpStream::PileUpStream(const std::string& name,
 { 
   assert(p_sel);
   assert(p_svcLoc);
-  if (!(p_sel->createContext(p_iter).isSuccess() &&
-	serviceLocator()->service("ActiveStoreSvc", p_activeStore).isSuccess() ) ) {
+  if( !( p_sel->createContext(p_iter).isSuccess() &&
+         serviceLocator()->service("ActiveStoreSvc", p_activeStore).isSuccess() &&
+         serviceLocator()->service("PileUpMergeSvc", p_mergeSvc, true).isSuccess() ) ) {
 
     const string errMsg("PileUpStream:: can not create stream");
     ATH_MSG_ERROR ( errMsg );
@@ -117,6 +105,7 @@ PileUpStream::PileUpStream(const std::string& name,
   assert(p_svcLoc);
   if (!(serviceLocator()->service("ActiveStoreSvc", p_activeStore).isSuccess() && 
 	serviceLocator()->service(selecName, p_sel).isSuccess() &&
+        serviceLocator()->service("PileUpMergeSvc", p_mergeSvc, true).isSuccess() &&
 	p_sel->createContext(p_iter).isSuccess() )) {
     const string errMsg("PileUpStream: can not create stream");
     ATH_MSG_ERROR ( errMsg );
@@ -258,135 +247,7 @@ const xAOD::EventInfo* PileUpStream::nextEventPre(bool readRecord)
       return nullptr;
    }
 
-   const xAOD::EventInfo* xAODEventInfo = store().tryConstRetrieve<xAOD::EventInfo>();
-
-   if( !xAODEventInfo ) {
-      // Try reading old EventInfo
-      const EventInfo* pEvent(0);
-      if( !(this->store().retrieve(pEvent)).isSuccess() ) {
-         ATH_MSG_DEBUG ( "nextEventPre():	Unable to retrieve Event root object" );
-         return nullptr;
-      }
-      ATH_MSG_DEBUG("Converting PileUpEventInfo to xAOD::EventInfo");
-      // Create the xAOD object(s):
-      std::unique_ptr< xAOD::EventInfo >  pxAODEventInfo( new xAOD::EventInfo() );
-      std::unique_ptr< xAOD::EventAuxInfo > pxAODEventAuxInfo(new xAOD::EventAuxInfo());
-      pxAODEventInfo->setStore( pxAODEventAuxInfo.get() );
-      if( !m_xAODCnvTool->convert( pEvent, pxAODEventInfo.get(), false, false ).isSuccess() ) {
-         ATH_MSG_ERROR("Failed to convert  xAOD::EventInfo in SG");
-         return nullptr;
-      }
-
-      //ATH_MSG_INFO ("Dumping xAOD::EventInfo prior to adding SubEvents");
-      //xAOD::dump( *xAODEventInfo );
-
-      const PileUpEventInfo* pileupEvent(dynamic_cast<const PileUpEventInfo*>(pEvent));
-      if( pileupEvent ) {
-         cout << "MN: PileUpStream: converting PileUpEventInfo" << endl;
-         // Create an EventInfoContainer for the pileup events:
-         std::unique_ptr< xAOD::EventInfoContainer > puei(new xAOD::EventInfoContainer());
-         std::unique_ptr< xAOD::EventInfoAuxContainer > puaux(new xAOD::EventInfoAuxContainer());
-         puei->setStore( puaux.get() );
-
-         // Sub-events for the main EventInfo object:
-         std::vector< xAOD::EventInfo::SubEvent > subEvents;
-
-         // A map translating between the AOD and xAOD pileup event types:
-         static std::map< PileUpEventInfo::SubEvent::pileup_type,
-            xAOD::EventInfo::PileUpType > pileupTypeMap;
-         if( ! pileupTypeMap.size() ) {
-#define DECLARE_SE_TYPE( TYPE )                                         \
-            pileupTypeMap[ PileUpTimeEventIndex::TYPE ] = xAOD::EventInfo::TYPE
-
-            DECLARE_SE_TYPE( Unknown );
-            DECLARE_SE_TYPE( Signal );
-            DECLARE_SE_TYPE( MinimumBias );
-            DECLARE_SE_TYPE( Cavern );
-            DECLARE_SE_TYPE( HaloGas );
-            DECLARE_SE_TYPE( ZeroBias );
-
-#undef DECLARE_SE_TYPE
-         }
-
-         // A convenience type declaration:
-         typedef ElementLink< xAOD::EventInfoContainer > EiLink;
-
-         // Create xAOD::EventInfo objects for each pileup EventInfo object:
-         auto pu_itr = pileupEvent->beginSubEvt();
-         auto pu_end = pileupEvent->endSubEvt();
-         const unsigned int countEvents = std::distance(pu_itr,pu_end);
-         ATH_MSG_VERBOSE( "CHECKING: There are " << countEvents << " subevents in this Event." );
-         cout << "MN: There are " << countEvents << " subevents in this Event." <<endl;
-
-         for( ; pu_itr != pu_end; ++pu_itr ) {
-            // Create a new xAOD::EventInfo object:
-            std::unique_ptr< xAOD::EventInfo > ei( new xAOD::EventInfo() );
-            // Fill it with information:
-            if( ! m_xAODCnvTool->convert( pu_itr->pSubEvt, ei.get(), true, false ).isSuccess() ) {
-               ATH_MSG_ERROR("Failed to convert EventInfo to xAOD::EventInfo");
-               continue;
-            }
-
-            StoreGateSvc* tmpSG = pu_itr->pSubEvtSG;
-            cout << "MN: PileUpStream: SG comparison:  p_SG=" << p_SG << "  tmpSG= " << tmpSG << endl;
-            if(tmpSG) {
-               ei->setEvtStore(tmpSG);
-               ATH_MSG_VERBOSE("FOUND A STOREGATE");
-            } else {
-               ATH_MSG_ERROR("FAILED TO FIND A STOREGATE");
-            }
-            // Store new EI into the container
-            puei->push_back( ei.release() );
-      
-            // And now add a sub-event to the temporary list:
-            auto typeItr = pileupTypeMap.find( pu_itr->type() );
-            xAOD::EventInfo::PileUpType type = xAOD::EventInfo::Unknown;
-            if( typeItr == pileupTypeMap.end() ) {
-               ATH_MSG_WARNING( "PileUpType not recognised: " << pu_itr->type() );
-            } else {
-               type = typeItr->second;
-            }
-            ATH_MSG_VERBOSE("PileUpEventInfo: time = " << pu_itr->time() << ", index = " << pu_itr->index());
-            subEvents.push_back( xAOD::EventInfo::SubEvent( pu_itr->time(),
-                                                            pu_itr->index(),
-                                                            type,
-                                                            EiLink( "PileUpEventInfo", puei->size()-1, p_SG )));  // p_SG?
-//                                                               m_evtStore.operator->() ) ) );
-            ATH_MSG_VERBOSE("PileUpEventInfo: time = " << subEvents.back().time() << ", index = " << subEvents.back().index());
-         }
-
-         if( subEvents.size() ) {
-            // And now update the main EventInfo object with the sub-events:
-            pxAODEventInfo->setSubEvents( subEvents );
-
-            // Record the xAOD object(s):
-            if( !store().record( std::move( puaux ), "PileUpEventInfoAux." ).isSuccess()
-                || !store().record( std::move( puei ), "PileUpEventInfo" ).isSuccess() ) {  //MN: FIX - make keys configurable
-               ATH_MSG_ERROR("Failed to record xAOD::EventInfoContainer in SG");
-            }
-         }
-      }
-      
-      xAODEventInfo = pxAODEventInfo.get();  // remember pointer to return the new EventInfo
-      // Record the xAOD object(s):
-      if( ! store().record( std::move( pxAODEventAuxInfo ), "EventInfoAux." ).isSuccess() //MN: FIX? key
-          || ! store().record( std::move( pxAODEventInfo ), "EventInfo" ).isSuccess() ) {
-         ATH_MSG_ERROR("Failed to record the new xAOD::EventInfo in SG");
-      }
-   } else {
-      ATH_MSG_INFO("Found xAOD::EventInfo");
-      ATH_MSG_INFO(" EventInfo has" <<   xAODEventInfo->subEvents().size() << " subevents" );
-      // the loop below serves 2 purposes: to recreate subevent links cache
-      // and set SG pointer in subevents
-      for( auto& subev : xAODEventInfo->subEvents() ) {
-         const_cast<xAOD::EventInfo*>(subev.ptr())->setEvtStore( &store() );
-      }
-   }
-
-   const_cast<xAOD::EventInfo*>(xAODEventInfo)->setEvtStore( &store() );
-   ATH_MSG_INFO("Dumping xAOD::EventInfo");
-   xAOD::dump( *xAODEventInfo );
-
+   const xAOD::EventInfo* xAODEventInfo = p_mergeSvc->getPileUpEvent( p_SG, "" );
    if (readRecord) {
       ATH_MSG_DEBUG ( "nextEventPre(): read new event " 
 		      <<  xAODEventInfo->eventNumber() 
diff --git a/Event/xAOD/xAODEventInfo/Root/EventInfo_v1.cxx b/Event/xAOD/xAODEventInfo/Root/EventInfo_v1.cxx
index 96e21f730351..25d866d30cb0 100644
--- a/Event/xAOD/xAODEventInfo/Root/EventInfo_v1.cxx
+++ b/Event/xAOD/xAODEventInfo/Root/EventInfo_v1.cxx
@@ -825,7 +825,7 @@ namespace xAOD {
       return m_evtStore;
    }
 
-   void EventInfo_v1::setEvtStore( StoreGateSvc* svc ) {
+   void EventInfo_v1::setEvtStore( StoreGateSvc* svc ) const {
 
       m_evtStore = svc;
       return;
diff --git a/Event/xAOD/xAODEventInfo/xAODEventInfo/versions/EventInfo_v1.h b/Event/xAOD/xAODEventInfo/xAODEventInfo/versions/EventInfo_v1.h
index 4ccede2cf6da..320fa495a232 100644
--- a/Event/xAOD/xAODEventInfo/xAODEventInfo/versions/EventInfo_v1.h
+++ b/Event/xAOD/xAODEventInfo/xAODEventInfo/versions/EventInfo_v1.h
@@ -462,7 +462,7 @@ namespace xAOD {
       /// Get the pointer to the event store associated with this event
       StoreGateSvc* evtStore() const;
       /// Set the pointer to the event store associated with this event
-      void setEvtStore( StoreGateSvc* svc );
+      void setEvtStore( StoreGateSvc* svc ) const;
 #endif // not genreflex or rootcint/rootcling
 
       /// @}
@@ -485,7 +485,7 @@ namespace xAOD {
 #ifndef __GCCXML__
       /// Transient pointer to the StoreGateSvc instance associated with the
       /// event (Needed for pile-up digitisation)
-      StoreGateSvc* m_evtStore;
+      mutable StoreGateSvc* m_evtStore;
 #endif // not __GCCXML__
 
    }; // class EventInfo_v1
-- 
GitLab