diff --git a/Generators/GeneratorObjects/CMakeLists.txt b/Generators/GeneratorObjects/CMakeLists.txt
index e7bb2316756b1963363cc2e0a44a39596d61ef5b..db05d754885ec23c5c3793346ca27ab0cff4585f 100644
--- a/Generators/GeneratorObjects/CMakeLists.txt
+++ b/Generators/GeneratorObjects/CMakeLists.txt
@@ -12,43 +12,41 @@ atlas_depends_on_subdirs( PUBLIC
                           Control/SGTools
                           Event/xAOD/xAODTruth
                           GaudiKernel
+                          Control/StoreGate
                           PRIVATE
                           AtlasTest/TestTools
                           Control/AthenaKernel
-                          Control/RootUtils
-                          Control/StoreGate )
+                          Control/CxxUtils
+                          Event/EventInfo
+                          Control/RootUtils )
 
 # External dependencies:
 find_package( CLHEP )
 find_package( HepMC )
 find_package( ROOT COMPONENTS Core Tree MathCore Hist RIO pthread )
+find_package( GTest )
 
 # Component(s) in the package:
 atlas_add_library( GeneratorObjects
                    src/HepMcParticleLink.cxx
                    src/McEventCollection.cxx
                    src/HijingEventParams.cxx
+                   src/McEventCollectionHelper.cxx
                    PUBLIC_HEADERS GeneratorObjects
                    INCLUDE_DIRS ${HEPMC_INCLUDE_DIRS}
                    PRIVATE_INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS}
                    PRIVATE_DEFINITIONS ${CLHEP_DEFINITIONS}
-                   LINK_LIBRARIES ${HEPMC_LIBRARIES} AthContainers AthLinks SGTools xAODTruth GaudiKernel RootUtilsPyROOT StoreGateLib SGtests
+                   LINK_LIBRARIES ${HEPMC_LIBRARIES} AthContainers AthLinks SGTools xAODTruth GaudiKernel EventInfo RootUtilsPyROOT StoreGateLib SGtests
                    PRIVATE_LINK_LIBRARIES ${ROOT_LIBRARIES} ${CLHEP_LIBRARIES} TestTools AthenaKernel RootUtils )
 
 atlas_add_dictionary( GeneratorObjectsDict
                       GeneratorObjects/McEventDict.h
                       GeneratorObjects/selection.xml
                       INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${HEPMC_INCLUDE_DIRS}
-                      LINK_LIBRARIES ${ROOT_LIBRARIES} ${CLHEP_LIBRARIES} ${HEPMC_LIBRARIES} AthContainers AthLinks SGTools xAODTruth GaudiKernel TestTools AthenaKernel RootUtils RootUtilsPyROOT StoreGateLib SGtests GeneratorObjects )
+                      LINK_LIBRARIES ${ROOT_LIBRARIES} ${CLHEP_LIBRARIES} ${HEPMC_LIBRARIES} AthContainers AthLinks SGTools xAODTruth GaudiKernel EventInfo TestTools AthenaKernel RootUtils RootUtilsPyROOT StoreGateLib SGtests GeneratorObjects )
 
 atlas_add_test( HepMcParticleLink_test
                 SOURCES
                 test/HepMcParticleLink_test.cxx
-                INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${HEPMC_INCLUDE_DIRS}
-                LINK_LIBRARIES ${ROOT_LIBRARIES} ${CLHEP_LIBRARIES} ${HEPMC_LIBRARIES} AthContainers AthLinks SGTools xAODTruth GaudiKernel TestTools AthenaKernel RootUtils RootUtilsPyROOT StoreGateLib SGtests GeneratorObjects
-                EXTRA_PATTERNS "ClassIDSvc Initialized successfully|^JobOptionsSvc +INFO"
-                ENVIRONMENT "JOBOPTSEARCHPATH=${CMAKE_CURRENT_SOURCE_DIR}/share" )
-
-# Install files from the package:
-atlas_install_joboptions( share/HepMcParticleLink_test.txt )
-
+                INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${HEPMC_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS}
+                LINK_LIBRARIES ${ROOT_LIBRARIES} ${CLHEP_LIBRARIES} ${HEPMC_LIBRARIES} AthContainers CxxUtils AthLinks SGTools xAODTruth GaudiKernel TestTools AthenaKernel RootUtils RootUtilsPyROOT StoreGateLib SGtests GeneratorObjects ${GTEST_LIBRARIES} )
diff --git a/Generators/GeneratorObjects/GeneratorObjects/HepMcParticleLink.h b/Generators/GeneratorObjects/GeneratorObjects/HepMcParticleLink.h
index c4a5378162059aaeeccc59f890ca32d546ff7efd..d282402a7cdd6c0f48a7f1ec19076b35550c2221 100644
--- a/Generators/GeneratorObjects/GeneratorObjects/HepMcParticleLink.h
+++ b/Generators/GeneratorObjects/GeneratorObjects/HepMcParticleLink.h
@@ -5,7 +5,7 @@
 #ifndef GENERATOROBJECTS_HEPMCPARTICLELINK_H
 #define GENERATOROBJECTS_HEPMCPARTICLELINK_H
 /** @class HepMcParticleLink
- * @brief a link optimized in size for a GenParticle in a McEventCollection 
+ * @brief a link optimized in size for a GenParticle in a McEventCollection
  *
  * @see McEventCollection, GenEvent, ElementLink
  * @author Paolo Calafiura
@@ -15,56 +15,60 @@
 #include <cstdint> /*int32_t etc*/
 #include <iostream>
 #include "GaudiKernel/MsgStream.h"
+#include <map>
 #include <limits>  /* numeric_limits */
 #include <string>
+#include "StoreGate/ReadHandle.h"
+
 
 namespace HepMC {
   class GenParticle;
   class GenEvent;
 }
 class IProxyDict;
+class McEventCollection;
+
+enum EBC_EVCOLL{
+  EBC_MAINEVCOLL=0,   //Usually contains the HS GenEvent
+  EBC_FIRSTPUEVCOLL,  //Low pt minbias PU, or full PU collection where applicable (i.e. Fast Chain)
+  EBC_SECONDPUEVCOLL, //High pt minbias PU
+  EBC_THIRDPUEVCOLL,  //Reserved for cavern background
+  EBC_NCOLLKINDS      //Just contains the maximum of the enum (for loops)
+};
 
 class HepMcParticleLink {
-public:  
+public:
   typedef uint32_t barcode_type;
   typedef uint16_t index_type;
 
   /// \name structors
   //@{
-  HepMcParticleLink() { init_dict(); }
-  HepMcParticleLink(IProxyDict* sg)
-    : m_have_particle(false)
-  {
-    m_ptrs.m_dict = sg;
-  }
-  HepMcParticleLink(barcode_type barCode, uint32_t eventIndex = 0) :
-    m_extBarcode(barCode, eventIndex) { init_dict(); }
-  HepMcParticleLink(barcode_type barCode, uint32_t eventIndex,
-                    IProxyDict* sg)
-    : m_extBarcode(barCode, eventIndex),
-      m_have_particle(false)
-  {
-    m_ptrs.m_dict = sg;
-  }
-  HepMcParticleLink(const HepMC::GenParticle* p, uint32_t eventIndex = 0);
-  HepMcParticleLink(const HepMcParticleLink& rhs) : 
-    m_ptrs(rhs.m_ptrs),
+  HepMcParticleLink() : m_particle(nullptr), m_have_particle(false) { }
+  HepMcParticleLink(barcode_type barCode, uint32_t eventIndex = 0, EBC_EVCOLL evColl=EBC_MAINEVCOLL) : m_particle(nullptr), m_have_particle(false)
+  { m_extBarcode = ExtendedBarCode(barCode, eventIndex, evColl, (!barCode && !eventIndex));}
+  HepMcParticleLink(barcode_type barCode, uint32_t eventIndex, std::string evCollName) : m_particle(nullptr), m_have_particle(false)
+  { m_extBarcode = ExtendedBarCode(barCode, eventIndex, find_enumFromKey(evCollName), (!barCode && !eventIndex));}
+  HepMcParticleLink(const HepMC::GenParticle* p, uint32_t eventIndex = 0, EBC_EVCOLL evColl=EBC_MAINEVCOLL);
+  HepMcParticleLink(const HepMC::GenParticle* p, uint32_t eventIndex, std::string evCollName);
+  HepMcParticleLink(const HepMcParticleLink& rhs) :
+    m_particle(rhs.m_particle),
     m_extBarcode(rhs.m_extBarcode),
-    m_have_particle (rhs.m_have_particle){  }
+    m_have_particle (rhs.m_have_particle){ if (!rhs.m_have_particle) {m_particle = nullptr;} }
 
   HepMcParticleLink& operator= (const HepMcParticleLink& rhs)
   {
     if (this != &rhs) {
-      m_ptrs = rhs.m_ptrs;
+      m_particle = rhs.m_particle;
       m_extBarcode = rhs.m_extBarcode;
       m_have_particle = rhs.m_have_particle;
+      if (!rhs.m_have_particle) {m_particle = nullptr;}
     }
     return *this;
   }
-////  HepMcParticleLink(const HepMC::GenParticle* part, 
-////		    const HepMC::GenEvent* pevt); //FIXME NOT YET 
+  ////  HepMcParticleLink(const HepMC::GenParticle* part,
+  ////                const HepMC::GenEvent* pevt); //FIXME NOT YET
   //@}
-  
+
   /// \name pointer interface
   //@{
   /// @throws std::runtime_error when the element is not found
@@ -72,12 +76,37 @@ public:
   const HepMC::GenParticle* operator->() const { return cptr(); }
   operator const HepMC::GenParticle* () const { return cptr(); }
   bool operator!() const {return !isValid();}
-  bool operator == (const HepMcParticleLink& rhs) const { 
-    return ( m_extBarcode== rhs.m_extBarcode ); }
-  bool operator != (const HepMcParticleLink& rhs) const { 
+  bool operator == (const HepMcParticleLink& rhs) const {
+    if (m_extBarcode==rhs.m_extBarcode)
+      return true;
+    else if (m_extBarcode.barcode()==rhs.m_extBarcode.barcode() && m_extBarcode.getEventCollectionAsChar()==rhs.m_extBarcode.getEventCollectionAsChar()) {
+      if (m_extBarcode.isIndexAsEventPosition()==rhs.m_extBarcode.isIndexAsEventPosition())
+        return false; //No need to check m_extBarcode.eventIndex() since if they were similar the first 'if' would have been passed
+      else {
+        index_type num1=getEventPositionInCollection(), num2=rhs.getEventPositionInCollection();
+        return (num1==num2);
+      }
+    }
+    else
+      return false;
+  }
+  bool operator != (const HepMcParticleLink& rhs) const {
     return !(operator==(rhs)); }
   bool operator < (const HepMcParticleLink& rhs) const {
-    return ( m_extBarcode < rhs.m_extBarcode ); }
+    if (m_extBarcode.getEventCollectionAsChar() < rhs.m_extBarcode.getEventCollectionAsChar()) return true;
+    if (!m_extBarcode.isIndexAsEventPosition() && !rhs.m_extBarcode.isIndexAsEventPosition())
+      return ( m_extBarcode < rhs.m_extBarcode );
+    if (m_extBarcode.getEventCollectionAsChar()==rhs.m_extBarcode.getEventCollectionAsChar()) {
+      index_type num1=m_extBarcode.eventIndex(), num2=rhs.m_extBarcode.eventIndex();
+      if (m_extBarcode.isIndexAsEventPosition())
+        num1=getEventNumberForEventPosition(num1);
+      if (rhs.m_extBarcode.isIndexAsEventPosition())
+        num2=getEventNumberForEventPosition(num2);
+      if (num1<num2) return true;
+      if (num1==num2) return (m_extBarcode.barcode() < rhs.m_extBarcode.barcode());
+    }
+    return false;
+  }
   friend std::ostream& operator << (std::ostream&, const HepMcParticleLink&);
   friend MsgStream& operator << (MsgStream&, const HepMcParticleLink&);
 
@@ -86,98 +115,135 @@ public:
   /// \name indexing accessors (e.g. for writing)
   //@{
   int barcode() const { return int(m_extBarcode.barcode()); } //FIXME ret type
-  index_type eventIndex() const { return index_type(m_extBarcode.eventIndex()); }
+  static index_type getEventNumberForEventPosition(EBC_EVCOLL evColl, index_type position) ; //if the an old event index (position in the collection) is stored, returns the event number of the corresponding GenEvent in the specified collection
+  index_type getEventNumberForEventPosition(index_type position) const; //if the an old event index (position in the collection) is stored, returns the event number of the corresponding GenEvent
+  static index_type getEventPositionForEventNumber(EBC_EVCOLL evColl, index_type evNumber); //Returns the position/index in the specified collection of the event having the given event number
+  index_type getEventPositionInCollection() const { if (m_extBarcode.isIndexAsEventPosition()) return m_extBarcode.eventIndex(); else return getEventPositionForEventNumber(this->getEventCollection(),m_extBarcode.eventIndex());};//Returns the position/index of the event in the collection
+  index_type eventIndex() const { if (m_extBarcode.isIndexAsEventPosition()) return getEventNumberForEventPosition(m_extBarcode.eventIndex()); else return index_type(m_extBarcode.eventIndex()); }
+  EBC_EVCOLL getEventCollection() const { return m_extBarcode.getEventCollection(); };
+  void setEventCollection(EBC_EVCOLL evColl) { m_extBarcode.setEventCollection(evColl); };
+  static std::string getEventCollectionAsString(EBC_EVCOLL evColl);
+  std::string getEventCollectionAsString() const {return getEventCollectionAsString(m_extBarcode.getEventCollection());};
+  char getEventCollectionAsChar() const {return m_extBarcode.getEventCollectionAsChar();};
   ///hash the 32 bit barcode and 16 bit eventindex into a 32bit int
-  barcode_type compress() const { 
-    return ( ((m_extBarcode.barcode()&0xFFFF) << 16) | 
-	     m_extBarcode.eventIndex() ); 
+  barcode_type compress() const {
+    return ( ((m_extBarcode.barcode()&0xFFFF) << 16) |
+             eventIndex() );
   };
   //@}
-  
-  static const std::string s_DEFAULTKEY;
-  static const std::string s_DC2DEFAULTKEY;
-  static const std::string s_AODKEY;
 
   bool isValid() const { return (0 != cptr()); }
   const HepMC::GenParticle* cptr() const;
 
+  //Return the corresponding enum from a McEventCollection name
+  static EBC_EVCOLL find_enumFromKey(std::string evCollName);
+
+  //Returns the McEventCollection
+  static const McEventCollection* retrieveMcEventCollection(EBC_EVCOLL evColl);
+  const  McEventCollection* retrieveMcEventCollection() const { return retrieveMcEventCollection(this->getEventCollection());};
+
   class ExtendedBarCode {
   public:
-    ExtendedBarCode() : m_BC(0), m_evtIndex(0) {}
-    ExtendedBarCode(barcode_type barcode, index_type eventIndex) :
-      m_BC(barcode), m_evtIndex(eventIndex)
+    ExtendedBarCode() : m_BC(0), m_evtIndex(0), m_isIndexEventPosition(0) {setEventCollection(EBC_MAINEVCOLL);}
+    ExtendedBarCode(barcode_type barcode, index_type eventIndex, EBC_EVCOLL evtColl=EBC_MAINEVCOLL, bool isIndexEventPosition=false) :
+      m_BC(barcode), m_evtIndex(eventIndex), m_isIndexEventPosition(isIndexEventPosition)
     {
-      assert(eventIndex < std::numeric_limits<unsigned short>::max()); 
+      assert(eventIndex < std::numeric_limits<unsigned short>::max());
+      setEventCollection(evtColl);
     }
-
-    barcode_type barcode() const { return m_BC; }
-    index_type eventIndex() const { return m_evtIndex; }
+    ExtendedBarCode(barcode_type barcode, index_type eventIndex, char evtColl, bool isIndexEventPosition=false) :
+      m_BC(barcode), m_evtIndex(eventIndex), m_isIndexEventPosition(isIndexEventPosition)
+    {
+      assert(eventIndex < std::numeric_limits<unsigned short>::max());
+      setEventCollection(getEventCollection(evtColl));
+    }
+    ExtendedBarCode(const ExtendedBarCode& rhs) { m_BC=rhs.m_BC; m_evtIndex=rhs.m_evtIndex; m_evtColl=rhs.m_evtColl; m_isIndexEventPosition=rhs.m_isIndexEventPosition; };
+    ExtendedBarCode& operator= (const ExtendedBarCode& rhs) { if (this != &rhs) { m_BC=rhs.m_BC; m_evtIndex=rhs.m_evtIndex; m_evtColl=rhs.m_evtColl; m_isIndexEventPosition=rhs.m_isIndexEventPosition;} return *this; };
+
+    inline barcode_type barcode() const { return m_BC; }
+    inline index_type eventIndex() const { return m_evtIndex; }
+    inline bool isIndexAsEventPosition() const { return m_isIndexEventPosition; }
+    void setEventCollection(EBC_EVCOLL evColl);
+    static EBC_EVCOLL getEventCollection(char evtColl);
+    EBC_EVCOLL getEventCollection() const {return getEventCollection(m_evtColl);} ;
+    std::string getEventCollectionAsString() const {return HepMcParticleLink::getEventCollectionAsString(this->getEventCollection());};
+    inline char getEventCollectionAsChar() const {return m_evtColl;};
     bool operator == (const ExtendedBarCode& rhs ) const
-    { 
-      return ( (this->m_BC)==(rhs.m_BC) && (this->m_evtIndex)==(rhs.m_evtIndex) ) ;
+    {
+      return ( (this->m_BC)==(rhs.m_BC) && (this->m_evtColl)==(rhs.m_evtColl) && (this->m_evtIndex)==(rhs.m_evtIndex) && (this->m_isIndexEventPosition)==(rhs.m_isIndexEventPosition) ) ;
     }
     bool operator != (const ExtendedBarCode& rhs ) const {
       return !(operator==(rhs));
     }
     bool operator < (const ExtendedBarCode& rhs ) const
-    { 
-      return ((m_evtIndex < rhs.m_evtIndex)  ||
-	      ((m_evtIndex == rhs.m_evtIndex) && (m_BC < rhs.m_BC)) ) ;
+    {
+      return ((m_evtColl < rhs.m_evtColl) ||
+              ((m_evtColl == rhs.m_evtColl) && (m_evtIndex < rhs.m_evtIndex))  ||
+              ((m_evtColl == rhs.m_evtColl) && (m_evtIndex == rhs.m_evtIndex) && (m_BC < rhs.m_BC)) ) ;
     }
     void print(std::ostream& os) const {
-      os << "Event index " << m_evtIndex
-	 << ", Barcode " << m_BC;
+      os << "Event index " << m_evtIndex << ((m_isIndexEventPosition) ? " (position in collection) " : "")
+         << ", Barcode " << m_BC
+         << ", McEventCollection " << this->getEventCollectionAsString() << "(" << m_evtColl << ")";
     }
     void print(MsgStream& os) const {
-      os << "Event index " << m_evtIndex
-	 << ", Barcode " << m_BC;
+      os << "Event index " << m_evtIndex << ((m_isIndexEventPosition) ? " (position in collection) " : "")
+         << ", Barcode " << m_BC
+         << ", McEventCollection " << this->getEventCollectionAsString() << "(" << m_evtColl << ")";
     }
-    
+
   private:
+    friend class HepMcParticleLinkCnv_p1;
+    friend class HepMcParticleLinkCnv_p2;
+
     barcode_type m_BC;
     index_type m_evtIndex;
+    char m_evtColl;
+    bool m_isIndexEventPosition;
   }
 #ifdef __GNUC__
-  __attribute__ ((packed))
+    __attribute__ ((packed))
 #endif
-;
+    ;
+  void setExtendedBarcode(ExtendedBarCode extBarcode) { m_extBarcode = extBarcode; m_particle=nullptr; m_have_particle=false; };
 
-
- private:
+private:
   friend class HepMcParticleLinkCnv_p1;
   friend class HepMcParticleLinkCnv_p2;
 
-  static std::string s_HOSTKEY;
-
-  // We need to remember the default data source when we're constructed.
-  // But once we have the particle pointer, we don't need it any more.
-  // Thus, we can put them in a union.  If m_have_particle is true,
+  static const std::string s_MAINEVCOLKEYS[4];
+  static const std::string s_FIRSTPUEVCOLKEYS[4];
+  static const std::string s_SECONDPUEVCOLKEYS[4];
+  static const std::string s_THIRDPUEVCOLKEYS[4];
+  static std::string s_HOSTKEY_MAINEVCOL;
+  static std::string s_HOSTKEY_FIRSTPUEVCOL;
+  static std::string s_HOSTKEY_SECONDPUEVCOL;
+  static std::string s_HOSTKEY_THIRDPUEVCOL;
+  static SG::ReadHandle<McEventCollection>* s_MAP_MCEVENTCOLLECTION_READHANDLE[EBC_NCOLLKINDS];
+
+  // If m_have_particle is true,
   // then m_particle is valid; otherwise, m_dict.  Note that adding
   // m_have_particle doesn't add to the aligned size of this structure
   // due to the trailing short in ExtendedBarCode.  But we have to use
   // the __packed__ attribute on ExtendedBarCode above to prevent
   // it from being padded out.
-  mutable union {
-    HepMC::GenParticle* m_particle;
-    IProxyDict* m_dict;
-  } m_ptrs; /* transient */
+  mutable HepMC::GenParticle* m_particle;
   ExtendedBarCode m_extBarcode;
   mutable bool m_have_particle; /* transient */
 
-  void init_dict();
-  bool find_hostkey() const;
+  static std::string * find_hostkey(EBC_EVCOLL evColl);
 };
 
 inline
-std::ostream& 
+std::ostream&
 operator << (std::ostream& os, const HepMcParticleLink& link) {
-  link.m_extBarcode.print(os); return os; 
+  link.m_extBarcode.print(os); return os;
 }
 
 inline
-MsgStream& 
+MsgStream&
 operator << (MsgStream& os, const HepMcParticleLink& link) {
-  link.m_extBarcode.print(os); return os; 
+  link.m_extBarcode.print(os); return os;
 }
 
 #endif
diff --git a/Generators/GeneratorObjects/GeneratorObjects/McEventCollectionHelper.h b/Generators/GeneratorObjects/GeneratorObjects/McEventCollectionHelper.h
new file mode 100644
index 0000000000000000000000000000000000000000..8094d3f3f1460ab16bb97bf5f9d1a978df5daffe
--- /dev/null
+++ b/Generators/GeneratorObjects/GeneratorObjects/McEventCollectionHelper.h
@@ -0,0 +1,23 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef MCTRUTHSIMALGS_MCEVENTCOLLECTIONHELPER_H
+#define MCTRUTHSIMALGS_MCEVENTCOLLECTIONHELPER_H
+
+#include "GeneratorObjects/HepMcParticleLink.h"
+
+#include <string>
+
+/** @namespace McEventCollectionHelper McEventCollectionHelper.h "McEventCollectionHelper.h"
+ *
+ *  Helper functions for mapping pileUpTypes onto McEventCollection names
+ */
+
+namespace McEventCollectionHelper {
+  EBC_EVCOLL getMcEventCollectionHMPLEnumFromPileUpType(const int pileupType) ;
+  std::string getMcEventCollectionNameFromPileUpType(const int pileupType) ;
+}
+
+#endif //MCTRUTHSIMALGS_MCEVENTCOLLECTIONHELPER_H
+
diff --git a/Generators/GeneratorObjects/share/HepMcParticleLink_test.ref b/Generators/GeneratorObjects/share/HepMcParticleLink_test.ref
deleted file mode 100644
index 9ae672472e2f2173acbdd587cb0a6f10e714b245..0000000000000000000000000000000000000000
--- a/Generators/GeneratorObjects/share/HepMcParticleLink_test.ref
+++ /dev/null
@@ -1,27 +0,0 @@
-*** GenParticleLink_test starts ***
-
-
-Initializing Gaudi ApplicationMgr using job opts ../share/HepMcParticleLink_test.txt
-JobOptionsSvc        INFO # =======> /afs/cern.ch/user/s/ssnyder/atlas-work3/Generators/GeneratorObjects/run/../share/HepMcParticleLink_test.txt)
-JobOptionsSvc        INFO # (1,1): ApplicationMgr.ExtSvc += ["StoreGateSvc/DetectorStore"]
-JobOptionsSvc        INFO Job options successfully read in from ../share/HepMcParticleLink_test.txt
-ApplicationMgr    SUCCESS 
-====================================================================================================================================
-                                                   Welcome to ApplicationMgr (GaudiCoreSvc v1r3p4)
-                                          running on lxplus403.cern.ch on Mon Apr 29 22:58:06 2013
-====================================================================================================================================
-ApplicationMgr       INFO Application Manager Configured successfully
-DetectorStore        INFO Initializing DetectorStore - package version StoreGate-02-39-03
-ClassIDSvc           INFO Initializing ClassIDSvc - package version CLIDComps-00-06-07
-ClassIDSvc           INFO  getRegistryEntries: read 139 CLIDRegistry entries for module ALL
-ClassIDSvc           INFO  getRegistryEntries: read 139 CLIDRegistry entries for module ALL
-ProxyProviderSvc     INFO Initializing ProxyProviderSvc - package version SGComps-00-01-03
-EventLoopMgr      WARNING Unable to locate service "EventSelector" 
-EventLoopMgr      WARNING No events will be processed from external input.
-HistogramPersis...WARNING Histograms saving not required.
-ApplicationMgr       INFO Application Manager Initialized successfully
-ApplicationMgr Ready
-StoreGateSvc         INFO Initializing StoreGateSvc - package version StoreGate-02-39-03
-Testing HepMcParticleLink streamer Event index 0, Barcode 10005 --- Event index 1, Barcode 10005
-HepMcParticleLink    INFO find_hostkey: Using TruthEvent as McEventCollection key for this job 
-*** GenParticleLink_test OK ***
diff --git a/Generators/GeneratorObjects/share/HepMcParticleLink_test.txt b/Generators/GeneratorObjects/share/HepMcParticleLink_test.txt
deleted file mode 100755
index c517b36ea7401a32f77d389d41a12cd53d3196a1..0000000000000000000000000000000000000000
--- a/Generators/GeneratorObjects/share/HepMcParticleLink_test.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-ApplicationMgr.ExtSvc += { "StoreGateSvc/DetectorStore" };
-
diff --git a/Generators/GeneratorObjects/src/HepMcParticleLink.cxx b/Generators/GeneratorObjects/src/HepMcParticleLink.cxx
index 65ad1ef34ea6de30630816515a43768e26142d7c..7b0b6cc83cede856d0153cbb86f175ffdc70c303 100644
--- a/Generators/GeneratorObjects/src/HepMcParticleLink.cxx
+++ b/Generators/GeneratorObjects/src/HepMcParticleLink.cxx
@@ -19,10 +19,15 @@
 
 #include "GeneratorObjects/HepMcParticleLink.h"
 
-const std::string HepMcParticleLink::s_DEFAULTKEY("TruthEvent");
-const std::string HepMcParticleLink::s_DC2DEFAULTKEY("G4Truth");
-const std::string HepMcParticleLink::s_AODKEY("GEN_AOD");
-std::string HepMcParticleLink::s_HOSTKEY;
+SG::ReadHandle<McEventCollection>* HepMcParticleLink::s_MAP_MCEVENTCOLLECTION_READHANDLE[EBC_NCOLLKINDS];
+std::string HepMcParticleLink::s_HOSTKEY_MAINEVCOL;
+std::string HepMcParticleLink::s_HOSTKEY_FIRSTPUEVCOL;
+std::string HepMcParticleLink::s_HOSTKEY_SECONDPUEVCOL;
+std::string HepMcParticleLink::s_HOSTKEY_THIRDPUEVCOL;
+const std::string HepMcParticleLink::s_MAINEVCOLKEYS[4]={"TruthEvent","G4Truth","GEN_AOD","GEN_EVENT"};
+const std::string HepMcParticleLink::s_FIRSTPUEVCOLKEYS[4]={"TruthEvent_PU","G4Truth_PU","GEN_AOD_PU","GEN_EVENT_PU"};
+const std::string HepMcParticleLink::s_SECONDPUEVCOLKEYS[4]={"TruthEvent_HighPtPU","G4Truth_HighPtPU","GEN_AOD_HighPtPU","GEN_EVENT_HighPtPU"};
+const std::string HepMcParticleLink::s_THIRDPUEVCOLKEYS[4]={"TruthEvent_Cavern","G4Truth_Cavern","GEN_AOD_Cavern","GEN_EVENT_Cavern"};
 
 namespace {
   MsgStream& mlog() {
@@ -32,85 +37,159 @@ namespace {
   const unsigned short CPTRMAXMSGCOUNT(100);
 }
 
-HepMcParticleLink::HepMcParticleLink(const HepMC::GenParticle* part, 
-				     uint32_t eventIndex) :
-    m_extBarcode((0 != part) ? part->barcode() : 0, eventIndex),
-    m_have_particle (true)
+HepMcParticleLink::HepMcParticleLink(const HepMC::GenParticle* part,
+                                     uint32_t eventIndex,
+                                     EBC_EVCOLL evColl) :
+  m_extBarcode((0 != part) ? part->barcode() : 0, eventIndex, evColl)
 {
-  m_ptrs.m_particle = const_cast<HepMC::GenParticle*>(part);
+  m_particle = const_cast<HepMC::GenParticle*>(part);
+  m_have_particle=true;
   assert(part);
 }
 
+HepMcParticleLink::HepMcParticleLink(const HepMC::GenParticle* part,
+                                     uint32_t eventIndex,
+                                     std::string evCollName) :
+    m_extBarcode((0 != part) ? part->barcode() : 0, eventIndex, find_enumFromKey(evCollName))
+{
+  m_particle = const_cast<HepMC::GenParticle*>(part);
+  m_have_particle=true;
+  assert(part);
+}
+
+
+uint16_t HepMcParticleLink::getEventNumberForEventPosition(EBC_EVCOLL evColl, index_type position) {
+  const McEventCollection* pEvtColl = retrieveMcEventCollection(evColl);
+  if (pEvtColl && position<pEvtColl->size()) {
+    const HepMC::GenEvent * pEvt(pEvtColl->at(position));
+    if (pEvt) {
+      return pEvt->event_number();
+    }
+  }
+  return 0;
+}
+
+uint16_t HepMcParticleLink::getEventNumberForEventPosition(index_type position) const { return getEventNumberForEventPosition(this->getEventCollection(),position);}
+
+
+uint16_t HepMcParticleLink::getEventPositionForEventNumber(EBC_EVCOLL evColl, index_type evNumber) {
+  const McEventCollection* pEvtColl = retrieveMcEventCollection(evColl);
+  if (pEvtColl) {
+    for (unsigned int position=0; position<pEvtColl->size(); position++) {
+      const HepMC::GenEvent * pEvt(pEvtColl->at(position));
+      if (pEvt && pEvt->event_number()==evNumber) { return position; }
+    }
+  }
+  return evNumber;
+}
+
+const McEventCollection* HepMcParticleLink::retrieveMcEventCollection(EBC_EVCOLL evColl) {
+  if (s_MAP_MCEVENTCOLLECTION_READHANDLE[evColl] && s_MAP_MCEVENTCOLLECTION_READHANDLE[evColl]->isValid()) {
+    return s_MAP_MCEVENTCOLLECTION_READHANDLE[evColl]->ptr();
+  }
+  else {
+    //Let's first determine the McEventCollection name to use
+    std::string * hostkeyToGetFrom=nullptr;
+    if (evColl==EBC_MAINEVCOLL)
+      hostkeyToGetFrom=&s_HOSTKEY_MAINEVCOL;
+    else if (evColl==EBC_FIRSTPUEVCOLL)
+      hostkeyToGetFrom=&s_HOSTKEY_FIRSTPUEVCOL;
+    else if (evColl==EBC_SECONDPUEVCOLL)
+      hostkeyToGetFrom=&s_HOSTKEY_SECONDPUEVCOL;
+    else if (evColl==EBC_THIRDPUEVCOLL)
+      hostkeyToGetFrom=&s_HOSTKEY_THIRDPUEVCOL;
+    else {
+      //Should not reach this
+      mlog() << MSG::ERROR << " Looking for incorrect event collection in HepMcParticleLink !!!" << endreq;
+      return nullptr;
+    }
+
+    if (! (hostkeyToGetFrom=find_hostkey(evColl))) return nullptr;
+    if (s_MAP_MCEVENTCOLLECTION_READHANDLE[evColl]) delete s_MAP_MCEVENTCOLLECTION_READHANDLE[evColl];
+    s_MAP_MCEVENTCOLLECTION_READHANDLE[evColl] = new SG::ReadHandle<McEventCollection>(*hostkeyToGetFrom);
+  }//if not already-existing ReadHandle
+
+  return s_MAP_MCEVENTCOLLECTION_READHANDLE[evColl]->ptr();
+}
+
+
 const HepMC::GenParticle* HepMcParticleLink::cptr() const {
-  if (!m_have_particle) {
+  if (m_have_particle) { return m_particle; }
+  else {
     if (0 == barcode()) {
 #if 0
       mlog() << MSG::DEBUG
-	     << "cptr: no truth particle associated with this hit (barcode==0)."
-	     << " Probably this is a noise hit" << endmsg;
+             << "cptr: no truth particle associated with this hit (barcode==0)."
+             << " Probably this is a noise hit" << endmsg;
 #endif
-      return 0;
+      return nullptr;
     }
-    CLID clid = ClassID_traits<McEventCollection>::ID();
-    const McEventCollection* pEvtColl(0);
-    if(s_HOSTKEY.empty() ) {
-      if (!find_hostkey()) return 0;
-    }
-    SG::DataProxy* proxy = m_ptrs.m_dict->proxy (clid, s_HOSTKEY);
-    if (!proxy) {
-      if (!find_hostkey()) return 0;
-      proxy = m_ptrs.m_dict->proxy (clid, s_HOSTKEY);
-    }
-    if (proxy && 
-	(0 != (pEvtColl = SG::DataProxy_cast<McEventCollection> (proxy)))) {
-      const HepMC::GenEvent *pEvt((0 == eventIndex()) ?
-				  pEvtColl->at(0) : //original event is at EvtColl[0]
-				  pEvtColl->find(eventIndex()));
-      if (0 != pEvt) {
-	m_ptrs.m_particle = pEvt->barcode_to_particle(barcode());
-        m_have_particle = true;
-      } else {
-	mlog() << MSG::WARNING 
-	       << "cptr: Mc Truth not stored for event " << eventIndex() 
-	       << endreq;
+
+    const McEventCollection* pEvtColl(nullptr);
+    if ((pEvtColl = retrieveMcEventCollection())) {
+      if(!pEvtColl->empty()) {
+        const HepMC::GenEvent *pEvt((0 == eventIndex()) ?
+                                    pEvtColl->at(0) : //original event is at EvtColl[0]
+                                    pEvtColl->find(eventIndex()));
+        if (nullptr != pEvt) {
+          m_particle = pEvt->barcode_to_particle(barcode());
+          m_have_particle = true;
+          return m_particle;
+        }
+        else {
+          mlog() << MSG::WARNING
+                 << "cptr: Mc Truth not stored for event " << eventIndex()
+                 << endreq;
+        }
       }
-    } else {
+    }
+    else {
       mlog() << MSG::WARNING << "cptr: McEventCollection not found" << endreq;
     }
-  }
+  }//if (!m_have_particle)
 
-  if (m_have_particle)
-    return m_ptrs.m_particle;
-  return 0;
+  return nullptr;
 }
 
 
-
-// This is a bit overly complicated at the moment in order to work
-// with both the old and new DataModel.
-void HepMcParticleLink::init_dict()
+std::string * HepMcParticleLink::find_hostkey(EBC_EVCOLL evColl)
 {
-  m_have_particle = false;
-  m_ptrs.m_dict = SG::CurrentEventStore::store();
-}
+  static unsigned short msgCount(0);
 
+  const std::string * colNames;
+  std::string * hostkeyToSet=nullptr;
+  if (evColl==EBC_MAINEVCOLL) {
+    colNames=s_MAINEVCOLKEYS;
+    hostkeyToSet=&s_HOSTKEY_MAINEVCOL;
+  }
+  else if (evColl==EBC_FIRSTPUEVCOLL) {
+    colNames=s_FIRSTPUEVCOLKEYS;
+    hostkeyToSet=&s_HOSTKEY_FIRSTPUEVCOL;
+  }
+  else if (evColl==EBC_SECONDPUEVCOLL) {
+    colNames=s_SECONDPUEVCOLKEYS;
+    hostkeyToSet=&s_HOSTKEY_SECONDPUEVCOL;
+  }
+  else if (evColl==EBC_THIRDPUEVCOLL) {
+    colNames=s_THIRDPUEVCOLKEYS;
+    hostkeyToSet=&s_HOSTKEY_THIRDPUEVCOL;
+  }
+  else {
+    //Should not reach this
+    mlog() << MSG::ERROR << " Looking for incorrect event collection in HepMcParticleLink !!!" << endreq;
+    return nullptr;
+  }
 
-bool HepMcParticleLink::find_hostkey() const
-{
-  static unsigned short msgCount(0);
-  assert (!m_have_particle);
-  CLID clid = ClassID_traits<McEventCollection>::ID();
-  s_HOSTKEY.clear();
-  if (m_ptrs.m_dict->proxy (clid, s_DEFAULTKEY))
-    s_HOSTKEY=s_DEFAULTKEY;
-  else if (m_ptrs.m_dict->proxy (clid, s_DC2DEFAULTKEY))
-    s_HOSTKEY=s_DC2DEFAULTKEY;
-  else if (m_ptrs.m_dict->proxy (clid, s_AODKEY))
-    s_HOSTKEY=s_AODKEY;
-  if (!s_HOSTKEY.empty()) {
-    mlog() << MSG::INFO << "find_hostkey: Using " << s_HOSTKEY
-        <<" as McEventCollection key for this job " << endreq;
-    return true;
+  hostkeyToSet->clear();
+  for (unsigned int iName=0; iName<4 && hostkeyToSet->empty(); iName++) {
+    if (SG::ReadHandle<McEventCollection>(colNames[iName]).isValid()) {
+      *hostkeyToSet=colNames[iName];
+    }
+  }
+  if (!hostkeyToSet->empty()) {
+    mlog() << MSG::INFO << "find_hostkey: Using " << *hostkeyToSet
+	   <<" as McEventCollection key for this job " << endreq;
+    return hostkeyToSet;
   }
   if (msgCount<CPTRMAXMSGCOUNT) {
     mlog() << MSG::WARNING << "find_hostkey: No Valid MC event Collection found "
@@ -125,7 +204,111 @@ bool HepMcParticleLink::find_hostkey() const
     mlog() << MSG::VERBOSE << "find_hostkey: No Valid MC event Collection found "
 	   << endreq;
   }
-  return false;
+  return nullptr;
 }
 
 
+EBC_EVCOLL HepMcParticleLink::find_enumFromKey(std::string evCollName) {
+  const std::string * colNames;
+  for (unsigned int iEnum=0; iEnum<EBC_NCOLLKINDS; iEnum++) {
+    switch (iEnum) {
+     case 0:
+      colNames=s_MAINEVCOLKEYS;    break;
+     case 1:
+      colNames=s_FIRSTPUEVCOLKEYS; break;
+     case 2:
+      colNames=s_SECONDPUEVCOLKEYS; break;
+     case 3:
+      colNames=s_THIRDPUEVCOLKEYS; break;
+    }
+    for (unsigned int iName=0;iName<4;iName++)
+      if (evCollName==colNames[iName])
+	return (EBC_EVCOLL)iEnum;
+  }
+
+  mlog() << MSG::WARNING << "HepMcParticleLink::find_enumFromKey(" << evCollName << "): trying to find enum for unknown McEventCollection, returning " << EBC_MAINEVCOLL << endreq;
+  return EBC_MAINEVCOLL;
+}
+
+
+
+//Returns the stored name for the collection found in SG for the types of GenEvents passed as argument
+std::string HepMcParticleLink::getEventCollectionAsString(EBC_EVCOLL evColl) {
+  switch (evColl) {
+    case EBC_MAINEVCOLL:
+      if (s_HOSTKEY_MAINEVCOL.empty()) {
+	std::string * pStr = find_hostkey(evColl);
+	if (pStr)
+	  return (s_HOSTKEY_MAINEVCOL=*pStr);
+	else
+	  return "CollectionNotSet";
+      }
+      return s_HOSTKEY_MAINEVCOL;
+      break;
+    case EBC_FIRSTPUEVCOLL:
+      if (s_HOSTKEY_FIRSTPUEVCOL.empty()) {
+	std::string * pStr = find_hostkey(evColl);
+	if (pStr)
+	  return (s_HOSTKEY_FIRSTPUEVCOL=*pStr);
+	else
+	  return "PUCollectionNotSet";
+      }
+      return s_HOSTKEY_FIRSTPUEVCOL;
+      break;
+     case EBC_SECONDPUEVCOLL:
+      if (s_HOSTKEY_SECONDPUEVCOL.empty()) {
+	std::string * pStr = find_hostkey(evColl);
+	if (pStr)
+	  return (s_HOSTKEY_SECONDPUEVCOL=*pStr);
+	else
+	  return "PUCollectionNotSet";
+      }
+      return s_HOSTKEY_SECONDPUEVCOL;
+      break;
+     case EBC_THIRDPUEVCOLL:
+      if (s_HOSTKEY_THIRDPUEVCOL.empty()) {
+	std::string * pStr = find_hostkey(evColl);
+	if (pStr)
+	  return (s_HOSTKEY_THIRDPUEVCOL=*pStr);
+	else
+	  return "PUCollectionNotSet";
+      }
+      return s_HOSTKEY_THIRDPUEVCOL;
+      break;
+     default:
+       //Should not reach this
+       mlog() << MSG::ERROR << " Trying to retrieve collection name for wrong event collection enum in HepMcParticleLink !!!" << endreq;
+       return (!s_HOSTKEY_MAINEVCOL.empty()) ? s_HOSTKEY_MAINEVCOL : s_HOSTKEY_MAINEVCOL=*find_hostkey(evColl);
+  }
+}
+
+//Accessors serving as interface between enums defining the kind of collections used and the format in memory (char)
+void HepMcParticleLink::ExtendedBarCode::setEventCollection(EBC_EVCOLL evColl) {
+  if (evColl==EBC_MAINEVCOLL)
+    m_evtColl='a';
+  else if (evColl==EBC_FIRSTPUEVCOLL)
+    m_evtColl='b';
+  else if (evColl==EBC_SECONDPUEVCOLL)
+    m_evtColl='c';
+  else if (evColl==EBC_THIRDPUEVCOLL)
+    m_evtColl='d';
+  else {
+    //Should not reach this
+    mlog() << MSG::ERROR << " Trying to set wrong event collection (" << evColl << ") to HepMcParticleLink ExtendedBarCode object !!!" << endreq;
+    m_evtColl='a';
+  }
+}
+EBC_EVCOLL HepMcParticleLink::ExtendedBarCode::getEventCollection(char evtColl) {
+  if (evtColl=='a')
+    return EBC_MAINEVCOLL;
+  else if (evtColl=='b')
+    return EBC_FIRSTPUEVCOLL;
+  else if (evtColl=='c')
+    return EBC_SECONDPUEVCOLL;
+  else if (evtColl=='d')
+    return EBC_THIRDPUEVCOLL;
+  //Should not reach this
+  mlog() << MSG::ERROR << " Wrong event collection (" << std::string(&evtColl,1) << ") set in HepMcParticleLink ExtendedBarCode object !!!" << endreq;
+  return EBC_MAINEVCOLL;
+}
+
diff --git a/Generators/GeneratorObjects/src/McEventCollection.cxx b/Generators/GeneratorObjects/src/McEventCollection.cxx
index 3a89978a61cbe1e7aa948eebf409e83dc69c113c..94c8d449345194971131b556b59528bb135d1c2b 100644
--- a/Generators/GeneratorObjects/src/McEventCollection.cxx
+++ b/Generators/GeneratorObjects/src/McEventCollection.cxx
@@ -39,6 +39,3 @@ McEventCollection::find(int eventNumber) const {
 
 
 }
-
-
-template class ClassName<McEventCollection>;
diff --git a/Generators/GeneratorObjects/src/McEventCollectionHelper.cxx b/Generators/GeneratorObjects/src/McEventCollectionHelper.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..0032bb3aa28b902d46ef67a67eb53813185eaee6
--- /dev/null
+++ b/Generators/GeneratorObjects/src/McEventCollectionHelper.cxx
@@ -0,0 +1,34 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "GeneratorObjects/McEventCollectionHelper.h"
+#include "EventInfo/PileUpTimeEventIndex.h"
+
+/** @class McEventCollectionHelper McEventCollectionHelper.cxx "McEventCollectionHelper.cxx"
+ *
+ *  Abstract interface to service for mapping pileUpTypes onto McEventCollection names
+ */
+
+EBC_EVCOLL McEventCollectionHelper::getMcEventCollectionHMPLEnumFromPileUpType(const int pileupType) {
+    switch(pileupType)      {
+      case PileUpTimeEventIndex::Signal: return EBC_MAINEVCOLL; break;
+      case PileUpTimeEventIndex::MinimumBias: return EBC_FIRSTPUEVCOLL; break;
+      case PileUpTimeEventIndex::HighPtMinimumBias: return EBC_SECONDPUEVCOLL; break;
+      case PileUpTimeEventIndex::Cavern: return EBC_THIRDPUEVCOLL; break;
+    }
+    std::cout << "Warning: McEventCollectionHelper::getMcEventCollectionHMPLEnumFromPileUpType(" << pileupType << "): Unexpected pileupType!!" << std::endl;
+    return EBC_MAINEVCOLL;
+}
+
+std::string McEventCollectionHelper::getMcEventCollectionNameFromPileUpType(const int pileupType) {
+    switch(pileupType)      {
+      case PileUpTimeEventIndex::Signal:            return "TruthEvent";           break;
+      case PileUpTimeEventIndex::MinimumBias:       return "TruthEvent_PU";        break;
+      case PileUpTimeEventIndex::HighPtMinimumBias: return "TruthEvent_HighPtPU";  break;
+      case PileUpTimeEventIndex::Cavern:            return "TruthEvent_Cavern";    break;
+    }
+    std::cout << "Warning: McEventCollectionHelper::getMcEventCollectionNameFromPileUpType(" << pileupType << "): Unexpected pileupType!!" << std::endl;
+    return "";
+}
+
diff --git a/Generators/GeneratorObjects/test/GeneratorObjects.xml b/Generators/GeneratorObjects/test/GeneratorObjects.xml
index 2d5290f66e840941643fdf348cdb5a261d6d7130..444f6c544625067800444546ec46368cb4cca96a 100755
--- a/Generators/GeneratorObjects/test/GeneratorObjects.xml
+++ b/Generators/GeneratorObjects/test/GeneratorObjects.xml
@@ -1,14 +1,14 @@
 <?xml version="1.0"?>
 <atn>
-   <TEST name=T name="GeneratorObjectsTest" type="makecheck" suite="Examples">
+   <TEST name="UnitTests" type="makecheck">
       <package>Generator/GeneratorObjects</package>
       <timelimit>5</timelimit>
       <author> Paolo Calafiura </author>
-      <mailto> pcalafiura@lbl.gov, George.Stavropoulos@cern.ch> </mailto>
+      <mailto> pcalafiura@lbl.gov, George.Stavropoulos@cern.ch>, atlas-srl-Sim-ISF-Core</mailto>
       <expectations>
          <errorMessage>Athena exited abnormally</errorMessage>
          <warningMessage> # WARNING_MESSAGE : post.sh> ERROR</warningMessage>
-          <successMessage>check ok</successMessage>
+          <successMessage>OK</successMessage>
           <returnValue>0</returnValue>
        </expectations>
     </TEST>
diff --git a/Generators/GeneratorObjects/test/HepMcParticleLink_test.cxx b/Generators/GeneratorObjects/test/HepMcParticleLink_test.cxx
index 1cf65ff0c8dfd07f5e873a544361580e0bbd0523..9bebef51a4ac0fef551d19efbde4cba896064e74 100755
--- a/Generators/GeneratorObjects/test/HepMcParticleLink_test.cxx
+++ b/Generators/GeneratorObjects/test/HepMcParticleLink_test.cxx
@@ -2,33 +2,64 @@
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
-/***************************************************************************
- * @file test the special element link for GenParticle in the default
- * McEventCollection
- * @author Paolo Calafiura
- * $Id: HepMcParticleLink_test.cxx,v 1.5 2008-08-23 00:04:04 ianh Exp $
- ***************************************************************************/
-/* #define GENP_DEBUG 1 */
+/**
+ * @author John Chapman
+ * @date June, 2016
+ * @brief Tests for BeamEffectsAlg.
+ */
 
-#include "TestTools/initGaudi.h"
+#undef NDEBUG
 
 #include <iostream>
-#include "GeneratorObjects/McEventCollection.h"
-#include "GeneratorObjects/HepMcParticleLink.h"
+#include <list>
+// Framework
+#include "TestTools/initGaudi.h"
+
+// ATLAS C++
+#include "CxxUtils/make_unique.h"
 
+// Google Test
+#include "gtest/gtest.h"
+
+// HepMC includes
 #include "HepMC/GenEvent.h"
-#include "HepMC/GenParticle.h"
+
+// CLHEP includes
 #include "CLHEP/Vector/LorentzVector.h"
+#include "CLHEP/Units/SystemOfUnits.h"
+
+// Athena headers
+#include "CxxUtils/make_unique.h"
+#include "StoreGate/WriteHandle.h"
 #include "StoreGate/StoreGateSvc.h"
+#include "GeneratorObjects/McEventCollection.h"
+#include "GeneratorObjects/HepMcParticleLink.h"
+
+namespace MCTesting {
+
+  // needed every time an AthAlgorithm, AthAlgTool or AthService is instantiated
+  ISvcLocator* g_svcLoc = nullptr;
+
+  // global test environment takes care of setting up Gaudi
+  class GaudiEnvironment : public ::testing::Environment {
+  protected:
+    virtual void SetUp() override {
+      Athena_test::initGaudi(MCTesting::g_svcLoc);
+    }
+  };
+
+  class HepMcParticleLink_test : public ::testing::Test {
 
+  protected:
+    virtual void SetUp() override {
+    }
 
-using namespace Athena_test;
-using namespace std;
-using namespace HepMC;
-using namespace CLHEP;
+    virtual void TearDown() override {
+    }
+  };
 
-//cut-and-paste from HepMC/examples/example_BuildEventFromScratch.cxx
-GenEvent* buildEvent() {
+  //cut-and-paste from HepMC/examples/example_BuildEventFromScratch.cxx
+  HepMC::GenEvent* buildEvent() {
     //
     // In this example we will place the following event into HepMC "by hand"
     //
@@ -51,55 +82,55 @@ GenEvent* buildEvent() {
     // pdt.insert( new ParticleData( "d",  1,  -2./3., 0,      -1, .5 ) );
     // pdt.insert( new ParticleData( "u~", -2, -1./3., 0,      -1, .5 ) );
     // pdt.insert( new ParticleData( "W-", -24,    -1, 80.396,
-	// 			  clifetime_from_width(2.06), 1 )    );
+    //                    clifetime_from_width(2.06), 1 )    );
     // pdt.insert( new ParticleData( "gamma", 22,   0, 0,      -1, 1  ) );
 
     // // print out the GenParticle Data to the screen
     // //    pdt.print();
 
     // First create the event container, with Signal Process 20, event number 1
-    GenEvent* evt = new GenEvent( 20, 1 );
+    HepMC::GenEvent* evt = new HepMC::GenEvent( 20, 1 );
     //
     // create vertex 1 and vertex 2, together with their inparticles
-    GenVertex* v1 = new GenVertex();
+    HepMC::GenVertex* v1 = new HepMC::GenVertex();
     evt->add_vertex( v1 );
-    v1->add_particle_in( new GenParticle( HepLorentzVector(0,0,7000,7000),
-				       2212, 3 ) );
-    GenVertex* v2 = new GenVertex();
+    v1->add_particle_in( new HepMC::GenParticle( CLHEP::HepLorentzVector(0,0,7000,7000),
+                                                 2212, 3 ) );
+    HepMC::GenVertex* v2 = new HepMC::GenVertex();
     evt->add_vertex( v2 );
-    v2->add_particle_in( new GenParticle( HepLorentzVector(0,0,-7000,7000),
-				       2212, 3 ) );
+    v2->add_particle_in( new HepMC::GenParticle( CLHEP::HepLorentzVector(0,0,-7000,7000),
+                                                 2212, 3 ) );
     //
     // create the outgoing particles of v1 and v2
-    GenParticle* p3 =
-	new GenParticle( HepLorentzVector(.750,-1.569,32.191,32.238), 1, 3 );
+    HepMC::GenParticle* p3 =
+      new HepMC::GenParticle( CLHEP::HepLorentzVector(.750,-1.569,32.191,32.238), 1, 3 );
     v1->add_particle_out( p3 );
-    GenParticle* p4 =
-	new GenParticle( HepLorentzVector(-3.047,-19.,-54.629,57.920), -2, 3 );
+    HepMC::GenParticle* p4 =
+      new HepMC::GenParticle( CLHEP::HepLorentzVector(-3.047,-19.,-54.629,57.920), -2, 3 );
     v2->add_particle_out( p4 );
     //
     // create v3
-    GenVertex* v3 = new GenVertex();
+    HepMC::GenVertex* v3 = new HepMC::GenVertex();
     evt->add_vertex( v3 );
     v3->add_particle_in( p3 );
     v3->add_particle_in( p4 );
     v3->add_particle_out(
-	new GenParticle( HepLorentzVector(-3.813,0.113,-1.833,4.233 ), 22, 1 )
-	);
-    GenParticle* p5 =
-	new GenParticle( HepLorentzVector(1.517,-20.68,-20.605,85.925), -24,3);
+                         new HepMC::GenParticle( CLHEP::HepLorentzVector(-3.813,0.113,-1.833,4.233 ), 22, 1 )
+                         );
+    HepMC::GenParticle* p5 =
+      new HepMC::GenParticle( CLHEP::HepLorentzVector(1.517,-20.68,-20.605,85.925), -24,3);
     v3->add_particle_out( p5 );
     //
     // create v4
-    GenVertex* v4 = new GenVertex();
+    HepMC::GenVertex* v4 = new HepMC::GenVertex();
     evt->add_vertex( v4 );
     v4->add_particle_in( p5 );
     v4->add_particle_out(
-	new GenParticle( HepLorentzVector(-2.445,28.816,6.082,29.552), 1,1 )
-	);
+                         new HepMC::GenParticle( CLHEP::HepLorentzVector(-2.445,28.816,6.082,29.552), 1,1 )
+                         );
     v4->add_particle_out(
-	new GenParticle( HepLorentzVector(3.962,-49.498,-26.687,56.373), -2,1 )
-	);
+                         new HepMC::GenParticle( CLHEP::HepLorentzVector(3.962,-49.498,-26.687,56.373), -2,1 )
+                         );
     //
     // tell the event which vertex is the signal process vertex
     evt->set_signal_process_vertex( v3 );
@@ -111,79 +142,266 @@ GenEvent* buildEvent() {
     // delete all particle data objects in the particle data table pdt
     //pdt.delete_all();
     return evt;
-}
-
-class is_photon {
-public:
-  bool operator() ( const GenParticle* p ) {
-    return ( p && p->pdg_id() == 22 );
   }
-};
-#include <algorithm>
-    // where is_photon() is a predicate like:
-int main() {
-  cout << "*** GenParticleLink_test starts ***" <<endl;
-  ISvcLocator* pSvcLoc;
-  if (!initGaudi("HepMcParticleLink_test.txt", pSvcLoc)) {
-    cerr << "This test can not be run" << endl;
-    return 0;
+
+  class is_photon {
+  public:
+    bool operator() ( const HepMC::GenParticle* p ) {
+      return ( p && p->pdg_id() == 22 );
+    }
+  };
+
+
+  HepMC::GenParticle* populateGenEvent(HepMC::GenEvent & ge)
+  {
+    CLHEP::HepLorentzVector myPos( 0.0, 0.0, 0.0, 0.0);
+    HepMC::GenVertex *myVertex = new HepMC::GenVertex( myPos, -1 );
+    HepMC::FourVector fourMomentum1( 0.0, 0.0, 1.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle1 = new HepMC::GenParticle(fourMomentum1, 2, 10);
+    myVertex->add_particle_in(inParticle1);
+    HepMC::FourVector fourMomentum2( 0.0, 0.0, -1.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle2 = new HepMC::GenParticle(fourMomentum2, -2, 10);
+    myVertex->add_particle_in(inParticle2);
+    HepMC::FourVector fourMomentum3( 0.0, 1.0, 0.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle3 = new HepMC::GenParticle(fourMomentum3, 2, 10);
+    myVertex->add_particle_out(inParticle3);
+    HepMC::FourVector fourMomentum4( 0.0, -1.0, 0.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle4 = new HepMC::GenParticle(fourMomentum4, -2, 10);
+    myVertex->add_particle_out(inParticle4);
+    ge.add_vertex( myVertex );
+    ge.set_signal_process_vertex( myVertex );
+    ge.set_beam_particles(inParticle1,inParticle2);
+    return inParticle3;
   }
-  assert(pSvcLoc);
 
-  StoreGateSvc* pStore(0);
-  assert((pSvcLoc->service("StoreGateSvc", pStore)).isSuccess());
-  assert(pStore);
+  HepMC::GenParticle* populateGenEvent2(HepMC::GenEvent & ge)
+  {
+    CLHEP::HepLorentzVector myPos( 0.0, 0.0, 0.0, 0.0);
+    HepMC::GenVertex *myVertex = new HepMC::GenVertex( myPos, -1 );
+    HepMC::FourVector fourMomentum1( 0.0, 0.0, 1.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle1 = new HepMC::GenParticle(fourMomentum1, 2, 10);
+    myVertex->add_particle_in(inParticle1);
+    HepMC::FourVector fourMomentum2( 0.0, 0.0, -1.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle2 = new HepMC::GenParticle(fourMomentum2, -2, 10);
+    myVertex->add_particle_in(inParticle2);
+    HepMC::FourVector fourMomentum3( 0.0, 1.0, 0.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle3 = new HepMC::GenParticle(fourMomentum3, 2, 10);
+    myVertex->add_particle_out(inParticle3);
+    HepMC::FourVector fourMomentum4( 0.0, -1.0, 0.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle4 = new HepMC::GenParticle(fourMomentum4, -2, 10);
+    myVertex->add_particle_out(inParticle4);
+    ge.add_vertex( myVertex );
+    ge.set_signal_process_vertex( myVertex );
+    ge.set_beam_particles(inParticle1,inParticle2);
+    return inParticle4;
+  }
 
-  McEventCollection* pTruth = new McEventCollection();
+  TEST_F(HepMcParticleLink_test, old_test) {
+    std::cout << "*** HepMcParticleLink_test starts ***" <<std::endl;
 
+    SG::WriteHandle<McEventCollection> inputTestDataHandle{"TruthEvent"};
+    inputTestDataHandle = CxxUtils::make_unique<McEventCollection>();
 
-  GenEvent* pEvent(buildEvent());
-  pTruth->push_back(pEvent);
-  pTruth->push_back(buildEvent());  //a copy
-  const bool SETCONST(false);
-  pStore->record(pTruth, HepMcParticleLink::s_DEFAULTKEY, SETCONST); //non-modifiable
-  list<GenParticle*> theGammas;
-  HepMC::copy_if( pEvent->particles_begin(), pEvent->particles_end(),
-		  back_inserter(theGammas), is_photon() );
-  assert(theGammas.size() == 1);
-  const GenParticle* pGamma(theGammas.front());
+    HepMC::GenEvent* pEvent(buildEvent());
+    inputTestDataHandle->push_back(pEvent);
+    inputTestDataHandle->push_back(buildEvent());  //a copy
+    std::list<HepMC::GenParticle*> theGammas;
+    HepMC::copy_if( pEvent->particles_begin(), pEvent->particles_end(),
+                    back_inserter(theGammas), is_photon() );
+    ASSERT_EQ((unsigned int)1, theGammas.size());
+    const HepMC::GenParticle* pGamma(theGammas.front());
 #ifdef GENP_DEBUG
-  pGamma->print();
-  cout << "gamma barcode " << hex << pGamma->barcode() << endl;
+    pGamma->print();
+    std::cout << "gamma barcode " << hex << pGamma->barcode() << std::endl;
 #endif
 
-  HepMcParticleLink gammaLink1(pGamma);
-  HepMcParticleLink gammaLink2(pGamma->barcode());
-  HepMcParticleLink gammaLink11(pGamma, 1);
-  HepMcParticleLink gammaLink12(pGamma->barcode(), 1);
+    HepMcParticleLink gammaLink1(pGamma);
+    HepMcParticleLink gammaLink2(pGamma->barcode());
+    HepMcParticleLink gammaLink11(pGamma, 1);
+    HepMcParticleLink gammaLink12(pGamma->barcode(), 1);
 
-  cout << "Testing HepMcParticleLink streamer "
-       << gammaLink1 << " --- " << gammaLink11 <<endl;
+    std::cout << "Testing HepMcParticleLink streamer "
+         << gammaLink1 << " --- " << gammaLink11 <<std::endl;
 
 
 #ifdef GENP_DEBUG
-  cout << "link barcode " << hex << gammaLink1.barcode() << endl;
-  cout << "link index " << hex << gammaLink1.eventIndex() << endl;
-  cout << "link1 barcode " << hex << gammaLink11.barcode() << endl;
-  cout << "link1 index " << hex << gammaLink11.eventIndex() << endl;
+    std::cout << "link barcode " << hex << gammaLink1.barcode() << std::endl;
+    std::cout << "link index " << hex << gammaLink1.eventIndex() << std::endl;
+    std::cout << "link1 barcode " << hex << gammaLink11.barcode() << std::endl;
+    std::cout << "link1 index " << hex << gammaLink11.eventIndex() << std::endl;
 #endif
-  assert (*gammaLink1 == *gammaLink2);
-  assert (gammaLink1 == gammaLink2);
-  assert (gammaLink1.barcode() == pGamma->barcode());
+    ASSERT_EQ(*gammaLink1, *gammaLink2);
+    ASSERT_EQ(gammaLink1, gammaLink2);
+    ASSERT_EQ(gammaLink1.barcode(), pGamma->barcode());
 
-  assert (*gammaLink11 == *gammaLink12);
-  assert (gammaLink11 == gammaLink12);
+    ASSERT_EQ(*gammaLink11, *gammaLink12);
+    ASSERT_EQ(gammaLink11, gammaLink12);
 
-  assert (*gammaLink1 == *gammaLink11);
-  assert ( gammaLink1 != gammaLink11 ); //FIXME weird! Can't check ptr...
-  assert ( gammaLink1 < gammaLink11 );  //FIXME weird! Can't check ptr...
+    ASSERT_EQ(*gammaLink1, *gammaLink11);
+    ASSERT_NE( gammaLink1, gammaLink11 ); //FIXME weird! Can't check ptr...
+    ASSERT_LT( gammaLink1, gammaLink11 );  //FIXME weird! Can't check ptr...
+    StoreGateSvc* pStore(nullptr);
+    ASSERT_TRUE(MCTesting::g_svcLoc->service("StoreGateSvc", pStore).isSuccess());
+    pStore->clearStore();
+    std::cout << "*** HepMcParticleLink_test OK ***" <<std::endl;
+  }
 
+  TEST_F(HepMcParticleLink_test, broken_event_link) {
+    // create dummy input McEventCollection with a name that
+    // HepMcParticleLink does not know about
+    SG::WriteHandle<McEventCollection> inputTestDataHandle{"GEN_EVENT"};
+    inputTestDataHandle = CxxUtils::make_unique<McEventCollection>();
+    // Fill it with a dummy GenEvent
+    inputTestDataHandle->push_back(new HepMC::GenEvent(20,1));
+    HepMC::GenEvent& ge1 = *(inputTestDataHandle->at(0));
+    const HepMC::GenParticle* particle1 = populateGenEvent(ge1);
+    // A HepMcParticleLink built using a GenParticle pointer should
+    // still work.
+    HepMcParticleLink testLink1a(particle1,0);
+    ASSERT_TRUE( testLink1a.isValid() );
+    // A HepMcParticleLink built using the barcode and the position of
+    // the GenEvent in the McEventCollection should still work.
+    HepMcParticleLink testLink1b(particle1->barcode(),0);
+    ASSERT_TRUE( testLink1b.isValid() );
+    StoreGateSvc* pStore(nullptr);
+    ASSERT_TRUE(MCTesting::g_svcLoc->service("StoreGateSvc", pStore).isSuccess());
+    pStore->clearStore();
+  }
+
+  TEST_F(HepMcParticleLink_test, truth_event_link) {
+    // create dummy input McEventCollection with a name that
+    // HepMcParticleLink knows about
+    SG::WriteHandle<McEventCollection> inputTestDataHandle{"TruthEvent"};
+    inputTestDataHandle = CxxUtils::make_unique<McEventCollection>();
+
+    // Add a dummy GenEvent
+    const int process_id1(20);
+    const int event_number1(17);
+    inputTestDataHandle->push_back(new HepMC::GenEvent(process_id1, event_number1));
+    HepMC::GenEvent& ge1 = *(inputTestDataHandle->at(0));
+    const HepMC::GenParticle* particle1 = populateGenEvent(ge1);
+    // Add a second dummy GenEvent
+    const int process_id2(20);
+    const int event_number2(25);
+    inputTestDataHandle->push_back(new HepMC::GenEvent(process_id2, event_number2));
+    HepMC::GenEvent& ge2 = *(inputTestDataHandle->at(1));
+    const HepMC::GenParticle* particle2 = populateGenEvent2(ge2);
+    // Add a third dummy GenEvent (identical to the first)
+    const int process_id3(20);
+    const int event_number3(17);
+    inputTestDataHandle->push_back(new HepMC::GenEvent(process_id3, event_number3));
+    HepMC::GenEvent& ge3 = *(inputTestDataHandle->at(2));
+    const HepMC::GenParticle* particle3 = populateGenEvent(ge3);
+
+    //Testing links to the first dummy GenEvent
+
+    // HepMcParticleLink built using a GenParticle pointer and the
+    // position of the GenEvent.
+    HepMcParticleLink testLink1a(particle1,0);
+    ASSERT_TRUE( testLink1a.isValid() );
+    ASSERT_EQ( particle1->barcode(), testLink1a.barcode());
+    ASSERT_EQ(  0, testLink1a.eventIndex());
+    ASSERT_NE( event_number1, testLink1a.eventIndex());
+    ASSERT_EQ(particle1,testLink1a.cptr());
+    // A HepMcParticleLink built using the barcode and the position of
+    // the GenEvent.
+    HepMcParticleLink testLink1b(particle1->barcode(),0);
+    ASSERT_TRUE( testLink1b.isValid() );
+    ASSERT_EQ( particle1->barcode(), testLink1b.barcode());
+    ASSERT_EQ(  0, testLink1b.eventIndex());
+    ASSERT_NE( event_number1, testLink1b.eventIndex());
+    ASSERT_EQ(*(testLink1a.cptr()),*(testLink1b.cptr()));
+    // HepMcParticleLink built using a GenParticle pointer and the
+    // event_number of the GenEvent.
+    HepMcParticleLink testLink1c(particle1,event_number1);
+    ASSERT_TRUE( testLink1c.isValid() );
+    ASSERT_EQ( particle1->barcode(), testLink1c.barcode());
+    ASSERT_NE(  0, testLink1c.eventIndex());
+    ASSERT_EQ( event_number1, testLink1c.eventIndex());
+    ASSERT_EQ(particle1,testLink1c.cptr());
+    // A HepMcParticleLink built using the barcode and the event_number of
+    // the GenEvent.
+    HepMcParticleLink testLink1d(particle1->barcode(),event_number1);
+    ASSERT_TRUE( testLink1d.isValid() );
+    ASSERT_EQ( particle1->barcode(), testLink1d.barcode());
+    ASSERT_NE(  0, testLink1d.eventIndex());
+    ASSERT_EQ( event_number1, testLink1d.eventIndex());
+    ASSERT_EQ(particle1,testLink1d.cptr());
+
+    //Testing links to the second dummy GenEvent
+
+    // HepMcParticleLink built using a GenParticle pointer and the
+    // position of the GenEvent.
+    HepMcParticleLink testLink2a(particle2,1);
+    ASSERT_TRUE( testLink2a.isValid() );
+    ASSERT_EQ( particle2->barcode(), testLink2a.barcode());
+    ASSERT_EQ(  1, testLink2a.eventIndex());
+    ASSERT_NE( event_number2, testLink2a.eventIndex());
+    ASSERT_EQ(particle2,testLink2a.cptr());
+    // A HepMcParticleLink built using the barcode and the position of
+    // the GenEvent. BROKEN
+    HepMcParticleLink testLink2b(particle2->barcode(),1);
+    ASSERT_FALSE( testLink2b.isValid() );
+    // HepMcParticleLink built using a GenParticle pointer and the
+    // event_number of the GenEvent.
+    HepMcParticleLink testLink2c(particle2,event_number2);
+    ASSERT_TRUE( testLink2c.isValid() );
+    ASSERT_EQ( particle2->barcode(), testLink2c.barcode());
+    ASSERT_NE(  1, testLink2c.eventIndex());
+    ASSERT_EQ( event_number2, testLink2c.eventIndex());
+    ASSERT_EQ(particle2,testLink2c.cptr());
+    // A HepMcParticleLink built using the barcode and the event_number of
+    // the GenEvent.
+    HepMcParticleLink testLink2d(particle2->barcode(),event_number2);
+    ASSERT_TRUE( testLink2d.isValid() );
+    ASSERT_EQ( particle2->barcode(), testLink2d.barcode());
+    ASSERT_NE(  1, testLink2d.eventIndex());
+    ASSERT_EQ( event_number2, testLink2d.eventIndex());
+    ASSERT_EQ(particle2,testLink2d.cptr());
+
+    //Testing links to the third dummy GenEvent
+
+    // HepMcParticleLink built using a GenParticle pointer and the
+    // position of the GenEvent.
+    HepMcParticleLink testLink3a(particle3,2);
+    ASSERT_TRUE( testLink3a.isValid() );
+    ASSERT_EQ( particle3->barcode(), testLink3a.barcode());
+    ASSERT_EQ(  2, testLink3a.eventIndex());
+    ASSERT_NE( event_number3, testLink3a.eventIndex());
+    ASSERT_EQ(particle3,testLink3a.cptr());
+    // A HepMcParticleLink built using the barcode and the position of
+    // the GenEvent. BROKEN
+    HepMcParticleLink testLink3b(particle3->barcode(),2);
+    ASSERT_FALSE( testLink3b.isValid() );
+    // HepMcParticleLink built using a GenParticle pointer and the
+    // event_number of the GenEvent.
+    HepMcParticleLink testLink3c(particle3,event_number3);
+    ASSERT_TRUE( testLink3c.isValid() );
+    ASSERT_EQ( particle3->barcode(), testLink3c.barcode());
+    ASSERT_NE(  2, testLink3c.eventIndex());
+    ASSERT_EQ( event_number3, testLink3c.eventIndex());
+    ASSERT_EQ(particle3,testLink3c.cptr());
+    // A HepMcParticleLink built using the barcode and the event_number of
+    // the GenEvent. BROKEN
+    HepMcParticleLink testLink3d(particle3->barcode(),event_number3);
+    ASSERT_TRUE( testLink3d.isValid() );
+    ASSERT_EQ( particle3->barcode(), testLink3d.barcode());
+    ASSERT_NE(  2, testLink3d.eventIndex());
+    ASSERT_EQ( event_number3, testLink3d.eventIndex());
+    ASSERT_NE(particle3,testLink3d.cptr());
+    ASSERT_EQ(particle1,testLink3d.cptr()); //POINTS AT THE IDENTICAL PARTICLE IN FIRST GenEvent!!
+
+    StoreGateSvc* pStore(nullptr);
+    ASSERT_TRUE(MCTesting::g_svcLoc->service("StoreGateSvc", pStore).isSuccess());
+    pStore->clearStore();
+  }
+
+} // <-- namespace MCTesting
 
-#ifdef GENP_DEBUG
-  cout << pStore->dump() << endl;
-#endif
-  pStore->clearStore();
 
-  cout << "*** GenParticleLink_test OK ***" <<endl;
-  return 0;
+int main(int argc, char *argv[])
+{
+  ::testing::InitGoogleTest( &argc, argv );
+  ::testing::AddGlobalTestEnvironment( new MCTesting::GaudiEnvironment );
+  return RUN_ALL_TESTS();
 }
diff --git a/Generators/GeneratorObjectsTPCnv/CMakeLists.txt b/Generators/GeneratorObjectsTPCnv/CMakeLists.txt
index 83119611a11adb6136d3e905006b750151a8617e..fdf20c952d3128d5a80d905e7ac6650048a20552 100644
--- a/Generators/GeneratorObjectsTPCnv/CMakeLists.txt
+++ b/Generators/GeneratorObjectsTPCnv/CMakeLists.txt
@@ -59,3 +59,9 @@ atlas_add_test( HepMcParticleLinkCnv_p1_test
                 test/HepMcParticleLinkCnv_p1_test.cxx
                 INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${HEPMC_INCLUDE_DIRS}
                 LINK_LIBRARIES ${ROOT_LIBRARIES} ${CLHEP_LIBRARIES} ${HEPMC_LIBRARIES} AthenaPoolCnvSvcLib GaudiKernel GeneratorObjects TestTools StoreGateLib SGtests GeneratorObjectsTPCnv )
+
+atlas_add_test( HepMcParticleLinkCnv_p2_test
+                SOURCES
+                test/HepMcParticleLinkCnv_p2_test.cxx
+                INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${HEPMC_INCLUDE_DIRS}
+                LINK_LIBRARIES ${ROOT_LIBRARIES} ${CLHEP_LIBRARIES} ${HEPMC_LIBRARIES} AthenaPoolCnvSvcLib GaudiKernel GeneratorObjects TestTools StoreGateLib SGtests GeneratorObjectsTPCnv )
diff --git a/Generators/GeneratorObjectsTPCnv/share/HepMcParticleLinkCnv_p2.ref b/Generators/GeneratorObjectsTPCnv/share/HepMcParticleLinkCnv_p2.ref
new file mode 100644
index 0000000000000000000000000000000000000000..9f71d140ff7712ec3a6dda42c09078fd290a3a61
--- /dev/null
+++ b/Generators/GeneratorObjectsTPCnv/share/HepMcParticleLinkCnv_p2.ref
@@ -0,0 +1,2 @@
+test1
+
diff --git a/Generators/GeneratorObjectsTPCnv/src/HepMcParticleLinkCnv_p1.cxx b/Generators/GeneratorObjectsTPCnv/src/HepMcParticleLinkCnv_p1.cxx
index 77481f2295b7b95a8088c284f8eed6ec36c2c447..b2566ddd56b9d818c94d76fceca51ffb9d875148 100755
--- a/Generators/GeneratorObjectsTPCnv/src/HepMcParticleLinkCnv_p1.cxx
+++ b/Generators/GeneratorObjectsTPCnv/src/HepMcParticleLinkCnv_p1.cxx
@@ -4,10 +4,10 @@
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
-// HepMcParticleLinkCnv_p1.cxx 
+// HepMcParticleLinkCnv_p1.cxx
 // Implementation file for class HepMcParticleLinkCnv_p1
 // Author: S.Binet<binet@cern.ch>
-/////////////////////////////////////////////////////////////////// 
+///////////////////////////////////////////////////////////////////
 
 // STL includes
 
@@ -17,48 +17,41 @@
 // GeneratorObjectsAthenaPool includes
 #include "GeneratorObjectsTPCnv/HepMcParticleLinkCnv_p1.h"
 
-/////////////////////////////////////////////////////////////////// 
-/// Public methods: 
-/////////////////////////////////////////////////////////////////// 
+///////////////////////////////////////////////////////////////////
+/// Public methods:
+///////////////////////////////////////////////////////////////////
 
-/////////////////////////////////////////////////////////////////// 
-/// Const methods: 
-/////////////////////////////////////////////////////////////////// 
+///////////////////////////////////////////////////////////////////
+/// Const methods:
+///////////////////////////////////////////////////////////////////
 
+#undef NDEBUG
 
 void HepMcParticleLinkCnv_p1::persToTrans( const HepMcParticleLink_p1* persObj,
-					   HepMcParticleLink* transObj, 
-					   MsgStream &/*msg*/ ) 
+                                           HepMcParticleLink* transObj,
+                                           MsgStream &/*msg*/ )
 {
-//   msg << MSG::DEBUG << "Loading HepMcParticleLink from persistent state..."
-//       << endreq;
-  if (transObj->m_ptrs.m_dict == nullptr)
-    transObj->init_dict();
-  transObj->m_extBarcode = 
+  transObj->m_extBarcode =
     HepMcParticleLink::ExtendedBarCode( persObj->m_barcode,
-					persObj->m_mcEvtIndex );
-  
+                                        persObj->m_mcEvtIndex,
+                                        EBC_MAINEVCOLL,
+                                        true);
+  transObj->m_have_particle = false;
+  transObj->m_particle = nullptr;
 
-//   msg << MSG::DEBUG << "Loaded HepMcParticleLink from persistent state [OK]"
-//       << endreq;
   return;
 }
 
-void HepMcParticleLinkCnv_p1::transToPers( const HepMcParticleLink* transObj, 
-					   HepMcParticleLink_p1* persObj, 
-					   MsgStream &/*msg*/ ) 
+void HepMcParticleLinkCnv_p1::transToPers( const HepMcParticleLink* transObj,
+                                           HepMcParticleLink_p1* persObj,
+                                           MsgStream &/*msg*/ )
 {
-//   msg << MSG::DEBUG << "Creating persistent state of HepMcParticleLink..."
-//       << endreq;
-  persObj->m_mcEvtIndex = transObj->eventIndex();
+  persObj->m_mcEvtIndex = transObj->getEventPositionInCollection();
   persObj->m_barcode    = transObj->m_extBarcode.barcode();
 
-//   msg << MSG::DEBUG << "Created persistent state of HepMcGenParticleLink [OK]"
-//       << endreq;
   return;
 }
 
-/////////////////////////////////////////////////////////////////// 
-// Protected methods: 
-/////////////////////////////////////////////////////////////////// 
-
+///////////////////////////////////////////////////////////////////
+// Protected methods:
+///////////////////////////////////////////////////////////////////
diff --git a/Generators/GeneratorObjectsTPCnv/src/HepMcParticleLinkCnv_p2.cxx b/Generators/GeneratorObjectsTPCnv/src/HepMcParticleLinkCnv_p2.cxx
index 68febd9d29381161681e99ddb6afc0b6cd8e440f..51d251f1a695af5e53ef931a62fc1735301edba7 100755
--- a/Generators/GeneratorObjectsTPCnv/src/HepMcParticleLinkCnv_p2.cxx
+++ b/Generators/GeneratorObjectsTPCnv/src/HepMcParticleLinkCnv_p2.cxx
@@ -23,25 +23,26 @@ void HepMcParticleLinkCnv_p2::persToTrans( const HepMcParticleLink_p2* persObj,
                                            HepMcParticleLink* transObj,
                                            MsgStream &/*msg*/ )
 {
-  //   msg << MSG::DEBUG << "Loading HepMcParticleLink from persistent state..."
-  //       << endreq;
-  if (transObj->m_ptrs.m_dict == nullptr)
-    transObj->init_dict();
   transObj->m_extBarcode =
     HepMcParticleLink::ExtendedBarCode( persObj->m_barcode,
-                                        persObj->m_mcEvtIndex );
+                                        persObj->m_mcEvtIndex,
+                                        persObj->m_evtColl,
+                                        false);
+  transObj->m_have_particle = false;
+  transObj->m_particle = nullptr;
 
-
-  //   msg << MSG::DEBUG << "Loaded HepMcParticleLink from persistent state [OK]"
-  //       << endreq;
   return;
 }
 
-void HepMcParticleLinkCnv_p2::transToPers( const HepMcParticleLink*,
-                                           HepMcParticleLink_p2*,
+void HepMcParticleLinkCnv_p2::transToPers( const HepMcParticleLink* transObj,
+                                           HepMcParticleLink_p2* persObj,
                                            MsgStream &/*msg*/ )
 {
-  throw std::runtime_error("HepMcParticleLinkCnv_p2::transToPers is not supported in this release!");
+  persObj->m_mcEvtIndex = transObj->eventIndex();
+  persObj->m_barcode    = transObj->m_extBarcode.barcode();
+  persObj->m_evtColl    = transObj->m_extBarcode.m_evtColl;
+
+  return;
 }
 
 ///////////////////////////////////////////////////////////////////
diff --git a/Generators/GeneratorObjectsTPCnv/test/HepMcParticleLinkCnv_p1_test.cxx b/Generators/GeneratorObjectsTPCnv/test/HepMcParticleLinkCnv_p1_test.cxx
index 6102c52d7d8412882384e3ad82c8c00f2bfd1ed8..bafa1012db056ecbdbad82cc86d381c702a02a73 100644
--- a/Generators/GeneratorObjectsTPCnv/test/HepMcParticleLinkCnv_p1_test.cxx
+++ b/Generators/GeneratorObjectsTPCnv/test/HepMcParticleLinkCnv_p1_test.cxx
@@ -31,6 +31,7 @@ void compare (const HepMcParticleLink& p1,
   assert ( p1.isValid() == p2.isValid() );
   assert ( p1.barcode() == p2.barcode() );
   assert ( p1.eventIndex() == p2.eventIndex() );
+  assert ( p1.getEventCollectionAsChar() == p2.getEventCollectionAsChar() );
   assert ( p1.cptr() == p2.cptr() );
   assert ( p1 == p2 );
 }
diff --git a/Generators/GeneratorObjectsTPCnv/test/HepMcParticleLinkCnv_p2_test.cxx b/Generators/GeneratorObjectsTPCnv/test/HepMcParticleLinkCnv_p2_test.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..5284dfa1a0c6b9cac1184ddc85f1b5cb238605e0
--- /dev/null
+++ b/Generators/GeneratorObjectsTPCnv/test/HepMcParticleLinkCnv_p2_test.cxx
@@ -0,0 +1,103 @@
+/**
+ * @file GeneratorObjectsTPCnv/test/HepMcParticleLinkCnv_p2_test.cxx
+ * @brief Tests for HepMcParticleLinkCnv_p2.
+ */
+
+
+#undef NDEBUG
+#include <cassert>
+#include <iostream>
+// HepMC includes
+#include "HepMC/GenEvent.h"
+
+// CLHEP includes
+#include "CLHEP/Vector/LorentzVector.h"
+#include "CLHEP/Units/SystemOfUnits.h"
+
+#include "GeneratorObjectsTPCnv/HepMcParticleLinkCnv_p2.h"
+#include "StoreGate/WriteHandle.h"
+#include "GeneratorObjects/McEventCollection.h"
+
+#include "TestTools/initGaudi.h"
+
+void compare (const HepMcParticleLink& p1,
+              const HepMcParticleLink& p2)
+{
+  assert ( p1.isValid() == p2.isValid() );
+  assert ( p1.barcode() == p2.barcode() );
+  assert ( p1.eventIndex() == p2.eventIndex() );
+  assert ( p1.getEventCollectionAsChar() == p2.getEventCollectionAsChar() );
+  assert ( p1.cptr() == p2.cptr() );
+  assert ( p1 == p2 );
+}
+
+HepMC::GenParticle* populateGenEvent(HepMC::GenEvent & ge)
+{
+  CLHEP::HepLorentzVector myPos( 0.0, 0.0, 0.0, 0.0);
+  HepMC::GenVertex *myVertex = new HepMC::GenVertex( myPos, -1 );
+  HepMC::FourVector fourMomentum1( 0.0, 0.0, 1.0, 1.0*CLHEP::TeV);
+  HepMC::GenParticle* inParticle1 = new HepMC::GenParticle(fourMomentum1, 2, 10);
+  myVertex->add_particle_in(inParticle1);
+  HepMC::FourVector fourMomentum2( 0.0, 0.0, -1.0, 1.0*CLHEP::TeV);
+  HepMC::GenParticle* inParticle2 = new HepMC::GenParticle(fourMomentum2, -2, 10);
+  myVertex->add_particle_in(inParticle2);
+  HepMC::FourVector fourMomentum3( 0.0, 1.0, 0.0, 1.0*CLHEP::TeV);
+  HepMC::GenParticle* inParticle3 = new HepMC::GenParticle(fourMomentum3, 2, 10);
+  myVertex->add_particle_out(inParticle3);
+  HepMC::FourVector fourMomentum4( 0.0, -1.0, 0.0, 1.0*CLHEP::TeV);
+  HepMC::GenParticle* inParticle4 = new HepMC::GenParticle(fourMomentum4, -2, 10);
+  myVertex->add_particle_out(inParticle4);
+  ge.add_vertex( myVertex );
+  ge.set_signal_process_vertex( myVertex );
+  ge.set_beam_particles(inParticle1,inParticle2);
+  return inParticle3;
+}
+
+HepMC::GenParticle* createMcEventCollectionInStoreGate()
+{
+  // create dummy input McEventCollection with a name that
+  // HepMcParticleLink knows about
+  SG::WriteHandle<McEventCollection> inputTestDataHandle{"TruthEvent"};
+  inputTestDataHandle = std::make_unique<McEventCollection>();
+  // Add a dummy GenEvent
+  const int process_id1(20);
+  const int event_number1(17);
+  inputTestDataHandle->push_back(new HepMC::GenEvent(process_id1, event_number1));
+  HepMC::GenEvent& ge1 = *(inputTestDataHandle->at(0));
+  return populateGenEvent(ge1);
+}
+
+void testit (const HepMcParticleLink& trans1)
+{
+  MsgStream log (0, "test");
+  HepMcParticleLinkCnv_p2 cnv;
+  HepMcParticleLink_p2 pers;
+  cnv.transToPers (&trans1, &pers, log);
+  HepMcParticleLink trans2;
+  cnv.persToTrans (&pers, &trans2, log);
+
+  compare (trans1, trans2);
+}
+
+void test1()
+{
+  std::cout << "test1\n";
+  const HepMC::GenParticle * particle = createMcEventCollectionInStoreGate();
+
+  HepMcParticleLink trans1(particle->barcode(),particle->parent_event()->event_number());
+
+  testit (trans1);
+}
+
+
+int main()
+{
+  ISvcLocator* pSvcLoc = nullptr;
+  if (!Athena_test::initGaudi(pSvcLoc)) {
+    std::cerr << "This test can not be run" << std::endl;
+    return 0;
+  }
+
+  test1();
+  return 0;
+}