diff --git a/Event/EventOverlay/IDC_OverlayBase/CMakeLists.txt b/Event/EventOverlay/IDC_OverlayBase/CMakeLists.txt
index 99c2cc620c69a811a9a22a2771145f565002283b..f17f9b0b758ccbee2c5649da439b9b6fcc16bcd2 100644
--- a/Event/EventOverlay/IDC_OverlayBase/CMakeLists.txt
+++ b/Event/EventOverlay/IDC_OverlayBase/CMakeLists.txt
@@ -7,13 +7,10 @@ atlas_subdir( IDC_OverlayBase )
 
 # Declare the package's dependencies:
 atlas_depends_on_subdirs( PUBLIC
-                          Control/AthenaBaseComps
-                          Control/AthContainers
                           DetectorDescription/Identifier
                           Event/EventOverlay/OverlayAlgBase )
 
 # Component(s) in the package:
 atlas_add_library( IDC_OverlayBase
                    PUBLIC_HEADERS IDC_OverlayBase
-                   LINK_LIBRARIES AthenaBaseComps AthContainers Identifier OverlayAlgBase )
-
+                   LINK_LIBRARIES Identifier OverlayAlgBase )
diff --git a/Event/EventOverlay/IDC_OverlayBase/IDC_OverlayBase/IDC_OverlayBase.h b/Event/EventOverlay/IDC_OverlayBase/IDC_OverlayBase/IDC_OverlayBase.h
index ad713366ef142121eff1536f3441c319fc1f389f..ec933f9e5958d38b2ae1d8901b50bc37aeed660b 100644
--- a/Event/EventOverlay/IDC_OverlayBase/IDC_OverlayBase/IDC_OverlayBase.h
+++ b/Event/EventOverlay/IDC_OverlayBase/IDC_OverlayBase/IDC_OverlayBase.h
@@ -10,79 +10,29 @@
  * Common base class and generic overlaying code for boolean-like hits.
  * Factored out from InDetOverlay.
  *
+ * @author Tadej Novak
  * @author Andrei Gaponenko <agaponenko@lbl.gov>, 2006-2009
- *
  */
 
 #ifndef IDC_OVERLAYBASE_H
 #define IDC_OVERLAYBASE_H
 
-#include <string>
-
-#include "OverlayAlgBase/OverlayAlgBase.h"
-#include "IDC_OverlayBase/IDC_OverlayCommon.h"
-#include "IDC_OverlayBase/IDC_OverlayHelpers.h"
-
-class IDC_OverlayBase;
-
-namespace Overlay {
-
-  /**
-   *  Merging of hits on the same channel.  Modifies the first argument by adding data from the second..
-   *  Implementations can assume that the arguments have the same Id.  (That is, correspond to the same readout channel.)
-   *  
-   *  A generic implementation of this template is provided in this package, 
-   *  but subdetectors can provide specializations suitable for their RDO type.
-   *  A simple example of providing a specialization is in InDetOverlay.cxx (for TRT_RDORawData).
-   *  A more elaborate implementation can be found e.g. in MdtOverlay.cxx
-   *  
-   *  Note that a declaration of a specialized template must occur before it is used
-   *  by overlayContainer()/mergeCollections() [typically from the execute() method of your algorithm].
-   */
-  template<class Datum> void mergeChannelData(Datum& r1, const Datum& r2, IDC_OverlayBase* parent);
-
-  /**
-   *  Adds data and mc from the second collection to the output one merging where necessary.
-   *  After this data and mc collections stay unchanged and output collection contains all information
-   * 
-   *  A generic implementation in the .icc file can be overriden by a
-   *  specialization, see above.
-   */
+#include <OverlayAlgBase/OverlayAlgBase.h>
 
-  template<class Collection> void mergeCollectionsNew(Collection *mc_coll, Collection *data_coll, Collection *out_coll, IDC_OverlayBase* parent);
-}
-
-
-class IDC_OverlayBase : public OverlayAlgBase  {
+class IDC_OverlayBase : public OverlayAlgBase
+{
 public:
-  
   IDC_OverlayBase(const std::string &name, ISvcLocator *pSvcLocator)
-    : OverlayAlgBase(name, pSvcLocator)
-  {}
-
-  /**
-   *  Transfers all collections from the first and second arguments to the output the first merging where necessary.
-   */
-  template<class IDC_Container> void overlayContainer(const IDC_Container* data, const IDC_Container* mc, IDC_Container* out ) {
-    Overlay::overlayContainer(data, mc, out, this);
-  }
-
-  template<class IDC_Container> void overlayContainerNew(const IDC_Container* data, const IDC_Container* mc, IDC_Container* out ) {
-    Overlay::overlayContainerNew(data, mc, out, this);
-  }
-
-  template<class IDC_Container> std::string shortPrint(const IDC_Container *container, unsigned numprint = 25) {
-    return Overlay::debugPrint(container, numprint);
-  }
+    : OverlayAlgBase(name, pSvcLocator) {}
 
-  /**
-   *  Adds data and mc from the second collection to the output one merging where necessary.
-   *  After this data and mc collections stay unchanged and output collection contains all information
-   */
-  template<class Collection> void mergeCollections(Collection *mc_coll, Collection *data_coll, Collection *out_coll);
+protected:
+  template <class IDC_Container>
+  StatusCode overlayContainer(const IDC_Container *bkgContainer,
+                              const IDC_Container *signalContainer,
+                              IDC_Container *outputContainer);
 
 };
 
 #include "IDC_OverlayBase/IDC_OverlayBase.icc"
 
-#endif/*IDC_OVERLAYBASE_H*/
+#endif
diff --git a/Event/EventOverlay/IDC_OverlayBase/IDC_OverlayBase/IDC_OverlayBase.icc b/Event/EventOverlay/IDC_OverlayBase/IDC_OverlayBase/IDC_OverlayBase.icc
index 711db40f69f1452f37554c7d48f2549aa4dcf7fb..dc932208f9524fcb40f14f51e39208571deee394 100644
--- a/Event/EventOverlay/IDC_OverlayBase/IDC_OverlayBase/IDC_OverlayBase.icc
+++ b/Event/EventOverlay/IDC_OverlayBase/IDC_OverlayBase/IDC_OverlayBase.icc
@@ -1,172 +1,107 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
 */
 
-// Generic overlaying code for boolean-like hits.
-// Factored out from InDetOverlay.
-//
-// Andrei Gaponenko <agaponenko@lbl.gov>, 2006-2009
+/// @author Tadej Novak
+/// @author Andrei Gaponenko <agaponenko@lbl.gov>, 2006-2009
 
-#include "Identifier/Identifier.h"
-#include "Identifier/IdentifierHash.h"
+#include <Identifier/Identifier.h>
+#include <Identifier/IdentifierHash.h>
 
-#include "AthenaBaseComps/AthMsgStreamMacros.h"
+#include "IDC_OverlayCommon.h"
 
-#include "AthContainers/DataVector.h"
-
-#include <sstream>
-#include <typeinfo>
 
+template <class IDC_Container>
+StatusCode IDC_OverlayBase::overlayContainer(const IDC_Container *bkgContainer,
+                                             const IDC_Container *signalContainer,
+                                             IDC_Container *outputContainer)
+{
+  ATH_MSG_DEBUG("overlayContainer<>() begin");
 
-namespace Overlay {
-  
-  //================================================================
-  template<class Datum>
-  void mergeChannelData(Datum& /*r1*/, const Datum& /*r2*/, IDC_OverlayBase* parent) {
-    // this is the default implementation. 
-    // We do not touch the data here, just print a warning.
-    static bool first_time = true;
-    if(first_time) {
-      first_time = false;
-      parent->msg(MSG::WARNING)<<"Overlay::mergeChannelData(): Merging of hits on the same channel is not implemented for "
-			       <<typeid(Datum).name()
-			       <<endmsg;
-    }
-  }
+  typedef typename IDC_Container::base_value_type Collection;
 
+  // Get all the hashes for the signal container
+  const std::vector<IdentifierHash> signalHashes = signalContainer->GetAllCurrentHashes();
 
-  //================================================================
-  template<class Collection>
-  void mergeCollectionsNew(Collection *mc_coll, Collection *data_coll, Collection *out_coll, IDC_OverlayBase *parent) {
-    
-    if(mc_coll->identify() != data_coll->identify()) {
-      std::ostringstream os;
-      os<<"mergeCollectionsNew<generic>(): collection Id mismatch";
-      parent->msg(MSG::FATAL)<<os.str()<<endmsg;
-      throw std::runtime_error(os.str());
-    }
+  // There are some use cases where background is empty
+  if (!bkgContainer) {
+    // Only loop through the signal collections and copy them over
+    for (const IdentifierHash &hashId : signalHashes) {
+      // Copy the signal collection
+      std::unique_ptr<Collection> signalCollection = Overlay::copyCollection(hashId, signalContainer->indexFindPtr(hashId));
 
-    const Identifier idColl = mc_coll->identify();
-
-    // ----------------------------------------------------------------
-    // debug
-    static bool first_time = true;
-    if(first_time) {
-      first_time = false;
-      parent->msg(MSG::INFO)<<"IDC_OverlayBase::mergeCollectionsNew(): "
-			    <<"generic code is called for "
-			    <<typeid(*mc_coll).name() 
-			    <<endmsg;
-    }
-  
-    // ----------------------------------------------------------------
-
-    //DataVector<typename Collection::base_value_type> data(data_coll->identifyHash());
-    Collection data(data_coll->identifyHash());
-    data.setIdentifier(idColl);
-    data_coll->swap(data);
-
-    //DataVector<typename Collection::base_value_type> mc(mc_coll->identifyHash());
-    Collection mc(mc_coll->identifyHash());
-    mc.setIdentifier(idColl);
-    mc_coll->swap(mc);
-
-    //################################################################
-    // Merge by copying ptrs from data and mc to mc_coll
-
-    typename Collection::size_type idata = 0;
-    typename Collection::size_type imc = 0;
-   
-    while( (idata < data.size()) || (imc < mc.size())) {
-
-      // The RDO that goes to the output at the end of this step.
-      typename Collection::base_value_type *p_rdo(0);
-    
-      if(imc == mc.size()) {
-	// just copy the remaining data inputs
-	data.swapElement(idata++, 0, p_rdo);
-      }
-      else if(idata == data.size()) {
-	//just copy the remaining MC digits
-	mc.swapElement(imc++, 0, p_rdo);
-      }
-      else {
-	// Need to decide which one goes first.  
-	// See comments in TRTDigitization.cxx about the assumption that id1<id2 <=> hash1<hash2
-	if( mc[imc]->identify() < data[idata]->identify() ) {
-	  mc.swapElement(imc++, 0, p_rdo);
-	}
-	else if(data[idata]->identify() < mc[imc]->identify()) {
-	  data.swapElement(idata++, 0, p_rdo);
-	}
-	else {
-	  // The hits are on the same channel.
-	  typename Collection::base_value_type *p2(0);
-	  data.swapElement(idata++, 0, p2);
-	  mc.swapElement(imc++, 0, p_rdo);
-	  Overlay::mergeChannelData(*p_rdo, *p2, parent);
-	  delete p2;
-	}
+      if (outputContainer->addCollection(signalCollection.get(), hashId).isFailure()) {
+        ATH_MSG_ERROR("Adding signal Collection with hashId " << hashId << " failed");
+        return StatusCode::FAILURE;
+      } else {
+        signalCollection.release();
       }
+    }
 
-      out_coll->push_back(p_rdo);
-    } // <= while
+    return StatusCode::SUCCESS;
   }
 
-} // namespace Overlay
-
-
-//================================================================
-template<class Collection>
-void IDC_OverlayBase::mergeCollections(Collection *mc_coll, 
-				       Collection *data_coll,
-				       Collection *out_coll)
-{
-  DataVector<typename Collection::base_value_type> data;
-  data_coll->swap(data);
-
-  DataVector<typename Collection::base_value_type> mc;
-  mc_coll->swap(mc);
+  // Get all the hashes for the background container
+  const std::vector<IdentifierHash> bkgHashes = bkgContainer->GetAllCurrentHashes();
   
-  //################################################################
-  // Merge by copying ptrs from data and mc to mc_coll
-
-  typename Collection::size_type idata = 0;
-  typename Collection::size_type imc = 0;
-   
-  while( (idata < data.size()) || (imc < mc.size())) {
-
-    // The RDO that goes to the output at the end of this step.
-    typename Collection::base_value_type *p_rdo(0);
-    
-    if(idata == data.size()) {
-      // just copy the remaining MC inputs
-      mc.swapElement(imc++, 0, p_rdo);
-    }
-    else if(imc == mc.size()) {
-      //just copy the remaining data digits
-      data.swapElement(idata++, 0, p_rdo);
-    }
-    else {
-      // Need to decide which one goes first.  
-      // See comments in TRTDigitization.cxx about the assumption that id1<id2 <=> hash1<hash2
-      if( data[idata]->identify() < mc[imc]->identify() ) {
-	data.swapElement(idata++, 0, p_rdo);
+  // The MC signal container should typically be smaller than bkgContainer,
+  // because the latter contains all the noise, minimum bias and pile up.
+  // Thus we firstly iterate over signal hashes and store them in a map.
+  std::map<IdentifierHash, bool> overlapMap;
+  for (const IdentifierHash &hashId : signalHashes) {
+    overlapMap.emplace(hashId, false);
+  }
+
+  // Now loop through the background hashes and copy unique ones over
+  for (const IdentifierHash &hashId : bkgHashes) {
+    auto search = overlapMap.find(hashId);
+    if (search == overlapMap.end()) {
+      // Copy the background collection
+      std::unique_ptr<Collection> bkgCollection = Overlay::copyCollection(hashId, bkgContainer->indexFindPtr(hashId));
+
+      if (outputContainer->addCollection(bkgCollection.get(), hashId).isFailure()) {
+        ATH_MSG_ERROR("Adding background Collection with hashId " << hashId << " failed");
+        return StatusCode::FAILURE;
+      } else {
+        bkgCollection.release();
       }
-      else if(mc[imc]->identify() < data[idata]->identify()) {
-	mc.swapElement(imc++, 0, p_rdo);
+    } else {
+      // Flip the overlap flag
+      search->second = true;
+    }
+  }
+
+  // Finally loop through the map and process the signal and overlay if
+  // necessary
+  for (const auto &[hashId, overlap] : overlapMap) {
+    // Copy the signal collection
+    std::unique_ptr<Collection> signalCollection = Overlay::copyCollection(hashId, signalContainer->indexFindPtr(hashId));
+
+    if (overlap) { // Do overlay
+      // Create the output collection, only works for Inner Detector
+      auto outputCollection = std::make_unique<Collection>(hashId);
+      outputCollection->setIdentifier(signalCollection->identify());
+      // Copy the background collection
+      std::unique_ptr<Collection> bkgCollection = Overlay::copyCollection(hashId, bkgContainer->indexFindPtr(hashId));
+
+      // Merge collections
+      Overlay::mergeCollections(bkgCollection.get(), signalCollection.get(), outputCollection.get(), this);
+
+      if (outputContainer->addCollection(outputCollection.get(), hashId).isFailure()) {
+        ATH_MSG_ERROR("Adding overlaid Collection with hashId " << hashId << " failed");
+        return StatusCode::FAILURE;
+      } else {
+        outputCollection.release();
       }
-      else {
-	// The hits are on the same channel.
-	typename Collection::base_value_type *p2(0);
-	data.swapElement(idata++, 0, p2);
-	mc.swapElement(imc++, 0, p_rdo);
-	Overlay::mergeChannelData(*p_rdo, *p2, this);
-	delete p2;
+    } else { // Only write signal out
+      if (outputContainer->addCollection(signalCollection.get(), hashId).isFailure()) {
+        ATH_MSG_ERROR("Adding signal Collection with hashId " << hashId << " failed");
+        return StatusCode::FAILURE;
+      } else {
+        signalCollection.release();
       }
     }
+  }
 
-    out_coll->push_back(p_rdo);
-  } // <= while
+  return StatusCode::SUCCESS;
 }
-
diff --git a/Event/EventOverlay/IDC_OverlayBase/IDC_OverlayBase/IDC_OverlayCommon.h b/Event/EventOverlay/IDC_OverlayBase/IDC_OverlayBase/IDC_OverlayCommon.h
index fe26915711d82ca200549c14676081028fa2c214..f2913969b8808e50df5d5b8a96aaf01966c45a7f 100644
--- a/Event/EventOverlay/IDC_OverlayBase/IDC_OverlayBase/IDC_OverlayCommon.h
+++ b/Event/EventOverlay/IDC_OverlayBase/IDC_OverlayBase/IDC_OverlayCommon.h
@@ -2,46 +2,46 @@
   Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
 */
 
-// Dear emacs, this is -*-c++-*- 
+// Dear emacs, this is -*-c++-*-
 
 /**
  * @file
- * 
+ *
  * Overlaying of Identifiable Containers.  Functions common to the
  * single-hit-per-readout-channel-in-an-event case and the
  * possible-multiple-hits-on-a-channel case are declared in this file.
  *
+ * @author Tadej Novak
  * @author Andrei Gaponenko <agaponenko@lbl.gov>, 2009
- *
  */
 
 #ifndef IDC_OVERLAYCOMMON_H
 #define IDC_OVERLAYCOMMON_H
 
-#include <string>
-
-#include "OverlayAlgBase/OverlayAlgBase.h"
-
-class IDC_OverlayBase;
+#include <memory>
 
-namespace Overlay {
+#include <Identifier/IdentifierHash.h>
 
-  template<class Collection> void copyCollection(const Collection *input_coll, Collection *copy_coll);
+namespace Overlay
+{
 
-  //Forward decl for compiling ...
-  template<class Collection> void mergeCollectionsNew(Collection*, Collection*, Collection*, IDC_OverlayBase*);
+template <class Collection>
+std::unique_ptr<Collection> copyCollection(const IdentifierHash &hashId,
+                                           const Collection *collection);
 
-  /**
-   *  Transfers all collection from the second argument the first merging where necessary.
-   *  After this call the "data" container contains all information, and the "mc" 
-   *  container is empty.
-   */
-  template<class IDC_Container, class OvlAlg> void overlayContainer(const IDC_Container* data, const IDC_Container* mc,  IDC_Container* out, OvlAlg *parent);
+template<class Datum, class Alg>
+void mergeChannelData(Datum &baseDatum,
+                      const Datum &additionalDatum,
+                      Alg *algorithm);
 
-  template<class IDC_Container, class OvlAlg> void overlayContainerNew(const IDC_Container* dataContainer, const IDC_Container* mcContainer, IDC_Container* outputContainer, OvlAlg *parent);
+template <class Collection, class Alg>
+void mergeCollections(Collection *bkgCollection,
+                      Collection *signalCollection,
+                      Collection *outputCollection,
+                      Alg *algorithm);
 
-}
+} // namespace Overlay
 
 #include "IDC_OverlayBase/IDC_OverlayCommon.icc"
 
-#endif/*IDC_OVERLAYCOMMON_H*/
+#endif
diff --git a/Event/EventOverlay/IDC_OverlayBase/IDC_OverlayBase/IDC_OverlayCommon.icc b/Event/EventOverlay/IDC_OverlayBase/IDC_OverlayBase/IDC_OverlayCommon.icc
index c5741622d528fc51ce8b4d384f922c75ec858ed6..5aaf601297fbe2ca3f6bbcacd8ea4b4511664e3a 100644
--- a/Event/EventOverlay/IDC_OverlayBase/IDC_OverlayBase/IDC_OverlayCommon.icc
+++ b/Event/EventOverlay/IDC_OverlayBase/IDC_OverlayBase/IDC_OverlayCommon.icc
@@ -2,172 +2,73 @@
   Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
 */
 
-// Generic overlaying code for Identifiable Containers.
-//
-// Andrei Gaponenko <agaponenko@lbl.gov>, 2006-2009
+/// Generic overlaying code for Identifiable Containers.
 
-#include "Identifier/Identifier.h"
-#include "Identifier/IdentifierHash.h"
+/// @author Tadej Novak
+/// @author Andrei Gaponenko <agaponenko@lbl.gov>, 2006-2009
 
-#include "StoreGate/ReadHandle.h"
-#include "StoreGate/WriteHandle.h"
- 
+#include <string>
+#include <typeinfo>
 
-#include "AthenaBaseComps/AthMsgStreamMacros.h"
 
-#include "AthContainers/DataVector.h"
+namespace Overlay
+{
 
-#include <sstream>
+template <class Datum, class Alg>
+void mergeChannelData(Datum &/* baseDatum */,
+                      const Datum &/* additionalDatum */,
+                      Alg */* algorithm */)
+{
+  throw std::logic_error("Merging of data on the same channel is not implemented for "
+                 + std::string(typeid(Datum).name()));
+}
 
-namespace Overlay {
 
-  //================================================================
-  template<class IDC_Container, class OvlAlg>
-  void overlayContainerNew(const IDC_Container *dataContainer,
-			const IDC_Container *mcContainer,
-                        IDC_Container *outputContainer,       
-			OvlAlg *parent)
-  {
-   typedef typename IDC_Container::base_value_type Collection;
-   std::cout<<"start overlayContainer"<<std::endl;
-   if(parent->msgLvl(MSG::DEBUG)) { parent->msg(MSG::DEBUG)<<"overlayContainerNew<>() begin"<<endmsg; }
-
-   //There are some use cases where this is empty
-   if(dataContainer != nullptr){
-   /** Add data from the data container to the output one */
-      typename IDC_Container::const_iterator p_data = dataContainer->begin();
-      typename IDC_Container::const_iterator p_data_end = dataContainer->end();
-
-      for(; p_data != p_data_end; ++p_data) {
-         IdentifierHash hashId = p_data.hashId();
-         auto coll_data = std::make_unique<Collection>(hashId); 
-         copyCollection(*p_data,coll_data.get());
-   
-         if ( outputContainer->addCollection(coll_data.release(), p_data.hashId()).isFailure() ) {
-            parent->msg(MSG::WARNING) <<"add data Collection failed for output "<< p_data.hashId   ()<<endmsg; //" collectionNo "<<collectionNo<<endmsg; 
-         } 
-      }
-   }
-
-   /** Add data from the ovl container to the output one */
-   typename IDC_Container::const_iterator p_ovl = mcContainer->begin(); 
-   typename IDC_Container::const_iterator p_ovl_end = mcContainer->end();
-
-   for(; p_ovl != p_ovl_end; ++p_ovl) {
- 
-      IdentifierHash coll_id = p_ovl.hashId();//(*p_ovl)->identify();
-      auto coll_ovl = std::make_unique<Collection>(coll_id);	
-      copyCollection(*p_ovl,coll_ovl.get());
-
-      /** The newly created stuff will go to the output EventStore SG */
-      auto coll_out = std::make_unique<Collection>(coll_id);
-      coll_out->setIdentifier((*p_ovl)->identify());
-
-      /** Look for the same ID in the main StoreGate EventStore */ 
-      typename IDC_Container::const_iterator q = outputContainer->indexFind( coll_id );
-      if( q != outputContainer->end() ) {
-      /**Need to merge the collections
-         Retrieve q */
-         std::unique_ptr <Collection> coll_data ((Collection *) *q);
-         mergeCollectionsNew(coll_data.get(),coll_ovl.get(),coll_out.get(),parent);
-
-         outputContainer->removeCollection(p_ovl.hashId());
-         if (outputContainer->addCollection(coll_out.release(), p_ovl.hashId()).isFailure() ) {
-      	    parent->msg(MSG::WARNING) << "overlay addCollection failed " << endmsg; 
-         }
-      }
-    else {
-       /** Copy the complete collection from ovl to output, 
-           hopefully preserving the "most derived" type of its raw data */ 
-       if ( outputContainer->addCollection(coll_ovl.release(), coll_id).isFailure() ) {
-       	  parent->msg(MSG::WARNING) << "add mc Collection failed " << endmsg; 
-      }
-    }   
-   }
+template <class Collection, class Alg>
+void mergeCollections(Collection *bkgCollection,
+                      Collection *signalCollection,
+                      Collection *outputCollection,
+                      Alg *algorithm)
+{
+  if (bkgCollection->identify() != signalCollection->identify()) {
+    throw std::runtime_error("mergeCollections<>(): collection Id mismatch");
   }
 
-
-  //================================================================
-  template<class IDC_Container, class OvlAlg>
-  void overlayContainer(const IDC_Container *dataContainer,
-			const IDC_Container *mcContainer,
-			IDC_Container *outputContainer,	      
-			OvlAlg *parent)
-  {
-    typedef typename IDC_Container::base_value_type Collection;
-    typedef typename Collection::base_value_type Datum;		
- 
-    if(parent->msgLvl(MSG::DEBUG)) { parent->msg(MSG::DEBUG)<<"overlayContainer<>() begin"<<endmsg; }
-    
-    // The  MC signal container should typically be smaller than
-    // dataContainer, because the latter contains all the noise,
-    // min bias and pile up.   Thus we firstly copy data collection to the 
-    // output and then merge with MC inputs.
-
-    /** Add data from the data container to the output one */
-    typename IDC_Container::const_iterator p_data = dataContainer->begin();
-    typename IDC_Container::const_iterator p_data_end = dataContainer->end();
- 
-    for(; p_data != p_data_end; ++p_data) {
-       IdentifierHash hashId = p_data.hashId();
-       Identifier ident = p_data->identify();	
-       auto coll_data = std::make_unique<Collection>(ident, hashId);	
-      
-       typename Collection::const_iterator firstData = p_data->begin();
-       typename Collection::const_iterator lastData = p_data->end();    
-       for (; firstData != lastData; ++firstData) {		       
-          Datum* newData = new Datum (*(dynamic_cast<const Datum*>(*firstData)));
-          coll_data->push_back(newData);
-       }	
-   
-       if ( outputContainer->addCollection(coll_data.release(), p_data.hashId()).isFailure() ) {
-          parent->msg(MSG::WARNING) <<"add data Collection failed for output "<< p_data.hashId()<<endmsg; 
+  typedef typename Collection::base_value_type Datum;
+  typedef typename Collection::size_type size_type;
+
+  // Merge by copying ptrs from background and signal to output collection
+  size_type ibkg = 0, isig = 0;
+  while ((ibkg < bkgCollection->size()) || (isig < signalCollection->size())) {
+    // The Datum that goes to the output at the end of this step.
+    Datum *tmp{};
+
+    if (isig == signalCollection->size()) {
+      // just copy the remaining background digits
+      bkgCollection->swapElement(ibkg++, nullptr, tmp);
+    } else if (ibkg == bkgCollection->size()) {
+      // just copy the remaining signal digits
+      signalCollection->swapElement(isig++, nullptr, tmp);
+    } else {
+      // Need to decide which one goes first.
+      // See comments in TRTDigitization.cxx about the assumption that id1<id2
+      // <=> hash1<hash2
+      if (signalCollection->at(isig)->identify() < bkgCollection->at(ibkg)->identify()) {
+        signalCollection->swapElement(isig++, nullptr, tmp);
+      } else if (bkgCollection->at(ibkg)->identify() < signalCollection->at(isig)->identify()) {
+        bkgCollection->swapElement(ibkg++, nullptr, tmp);
+      } else {
+        // The hits are on the same channel.
+        Datum *tmpBkg{};
+        bkgCollection->swapElement(ibkg++, nullptr, tmpBkg);
+        signalCollection->swapElement(isig++, nullptr, tmp);
+        Overlay::mergeChannelData(*tmp, *tmpBkg, algorithm);
+        delete tmpBkg;
       }
-    }     
+    }
 
-    /** Add data from the ovl container to the output one */
-    typename IDC_Container::const_iterator p_ovl = mcContainer->begin(); 
-    typename IDC_Container::const_iterator p_ovl_end = mcContainer->end();
-
-    for(; p_ovl != p_ovl_end; ++p_ovl) {
-       IdentifierHash coll_id = p_ovl.hashId();//(*p_ovl)->identify();
-       Identifier elemId = p_ovl->identify();
-       auto coll_ovl = std::make_unique<Collection>(elemId, coll_id);	
-     
-       typename Collection::const_iterator firstData = p_ovl->begin();
-       typename Collection::const_iterator lastData = p_ovl->end();    
-       for (; firstData != lastData; ++firstData) {		       
-          Datum* newData = new Datum (*(dynamic_cast<const Datum*>(*firstData)));
-          coll_ovl->push_back(newData);
-    }	
-   	
-       /** The newly created stuff will go to the output EventStore SG */
-       auto coll_out = std::make_unique<Collection>(elemId, coll_id);	    
-     
-       /** Look for the same ID in the main StoreGate EventStore */ 
-       typename IDC_Container::const_iterator q = outputContainer->indexFind(coll_id);
-       if( q != outputContainer->end() ) {
-       /** Need to merge the collections
-           Retrieve q */
-
-          std::unique_ptr <Collection> coll_data ((Collection *) *q);
-          parent->mergeCollections(coll_data.get(),coll_ovl.get(),coll_out.get());
-
-          outputContainer->removeCollection(p_ovl.hashId());
-          if (outputContainer->addCollection(coll_out.release(), p_ovl.hashId()).isFailure() ) {
-	     parent->msg(MSG::WARNING) << "overlay addCollection failed " << endmsg; 
-          }
-       }
-       else {
-       /** Copy the complete collection from ovl to output, 
-           hopefully preserving the "most derived" type of its raw data */ 
-           if ( outputContainer->addCollection(coll_ovl.release(), coll_id).isFailure() ) {
-              parent->msg(MSG::WARNING) << "add mc Collection failed " << endmsg; 
-           }  
-       }   
-    }  
- }
+    outputCollection->push_back(tmp);
+  } // <= while
+}
 
 } // namespace Overlay
-
-//================================================================
diff --git a/InnerDetector/InDetRawAlgs/InDetOverlay/src/PixelOverlay.cxx b/InnerDetector/InDetRawAlgs/InDetOverlay/src/PixelOverlay.cxx
index 2e53492529d2e5f113d6a3674930a9bf08348ddc..106215eecf669aaafb6e3e7991c16b59b970fea5 100644
--- a/InnerDetector/InDetRawAlgs/InDetOverlay/src/PixelOverlay.cxx
+++ b/InnerDetector/InDetRawAlgs/InDetOverlay/src/PixelOverlay.cxx
@@ -11,21 +11,31 @@
 
 namespace Overlay
 {
+  // Specialize mergeChannelData() for the Pixel
+  template <>
+  void mergeChannelData(PixelRDORawData &/* baseDatum */,
+                        const PixelRDORawData &/* additionalDatum */,
+                        IDC_OverlayBase *algorithm)
+  {
+    algorithm->msg(MSG::WARNING) << "Overlay::mergeChannelData<PixelRDORawData>(): "
+      << "Merging of data on the same channel is not implemented for PixelRDORawData" << endmsg;
+  }
+
   // Specialize copyCollection() for the Pixel
   template<>
-  void copyCollection(const InDetRawDataCollection<PixelRDORawData> *input_coll,
-                      InDetRawDataCollection<PixelRDORawData> *copy_coll)
+  std::unique_ptr<PixelRDO_Collection> copyCollection(const IdentifierHash &hashId,
+                                                      const PixelRDO_Collection *collection)
   {
-    copy_coll->setIdentifier(input_coll->identify());
-    InDetRawDataCollection<PixelRDORawData>::const_iterator firstData = input_coll->begin();
-    InDetRawDataCollection<PixelRDORawData>::const_iterator lastData = input_coll->end();	
-    for ( ; firstData != lastData; ++firstData)
-    {	
-      const Identifier ident = (*firstData)->identify();
-      const unsigned int word = (*firstData)->getWord();
-      Pixel1RawData *newData = new Pixel1RawData(ident, word);
-      copy_coll->push_back(newData);
+    auto outputCollection = std::make_unique<PixelRDO_Collection>(hashId);
+    outputCollection->setIdentifier(collection->identify());
+
+    for (const PixelRDORawData *existingDatum : *collection) {
+      // Owned by the collection
+      auto *datumCopy = new Pixel1RawData(existingDatum->identify(), existingDatum->getWord());
+      outputCollection->push_back(datumCopy);
     }
+
+    return outputCollection;
   }
 } // namespace Overlay
 
@@ -86,13 +96,14 @@ StatusCode PixelOverlay::execute()
   // Creating output RDO container
   SG::WriteHandle<PixelRDO_Container> outputContainer(m_outputKey);
   ATH_CHECK(outputContainer.record(std::make_unique<PixelRDO_Container>(signalContainer->size())));
+  if (!outputContainer.isValid()) {
+    ATH_MSG_ERROR("Could not record output Pixel RDO container " << outputContainer.name() << " to store " << outputContainer.store());
+    return StatusCode::FAILURE;
+  }
   ATH_MSG_DEBUG("Recorded output Pixel RDO container " << outputContainer.name() << " in store " << outputContainer.store());
 
-  if (outputContainer.isValid()) {
-    overlayContainerNew(bkgContainerPtr, signalContainer.cptr(), outputContainer.ptr());
-
-    ATH_MSG_DEBUG("Pixel Result   = " << Overlay::debugPrint(outputContainer.ptr()));
-  }
+  ATH_CHECK(overlayContainer(bkgContainerPtr, signalContainer.cptr(), outputContainer.ptr()));
+  ATH_MSG_DEBUG("Pixel Result   = " << Overlay::debugPrint(outputContainer.ptr()));
 
   ATH_MSG_DEBUG("execute() end");
   return StatusCode::SUCCESS;
diff --git a/InnerDetector/InDetRawAlgs/InDetOverlay/src/SCTOverlay.cxx b/InnerDetector/InDetRawAlgs/InDetOverlay/src/SCTOverlay.cxx
index 23d205751588fcb219d2b97c3462b32d9eceaaa4..a239f2d055af0ed0093188364b85be39faa8d9bb 100644
--- a/InnerDetector/InDetRawAlgs/InDetOverlay/src/SCTOverlay.cxx
+++ b/InnerDetector/InDetRawAlgs/InDetOverlay/src/SCTOverlay.cxx
@@ -14,46 +14,35 @@ namespace Overlay
 {
   // Specialize copyCollection() for the SCT
   template<>
-  void copyCollection(const InDetRawDataCollection<SCT_RDORawData> *input_coll,
-                      InDetRawDataCollection<SCT_RDORawData> *copy_coll)
-  {  
-    copy_coll->setIdentifier(input_coll->identify());
-    InDetRawDataCollection<SCT_RDORawData>::const_iterator firstData = input_coll->begin();
-    InDetRawDataCollection<SCT_RDORawData>::const_iterator lastData = input_coll->end();	
-    for ( ; firstData != lastData; ++firstData)
-    {	
-      const Identifier ident = (*firstData)->identify();
-      const unsigned int word = (*firstData)->getWord();
-      const SCT3_RawData* oldData = dynamic_cast<const SCT3_RawData*>(*firstData);	
-      std::vector<int> errorHit=oldData->getErrorCondensedHit();
-      SCT3_RawData *newData=new SCT3_RawData(ident, word, &errorHit);
-      copy_coll->push_back(newData);
+  std::unique_ptr<SCT_RDO_Collection> copyCollection(const IdentifierHash &hashId,
+                                                     const SCT_RDO_Collection *collection)
+  {
+    auto outputCollection = std::make_unique<SCT_RDO_Collection>(hashId);
+    outputCollection->setIdentifier(collection->identify());
+
+    for (const SCT_RDORawData *existingDatum : *collection) {
+      auto *oldDatum = dynamic_cast<const SCT3_RawData *>(existingDatum);
+      // Owned by the collection
+      auto *datumCopy = new SCT3_RawData(oldDatum->identify(),
+                                         oldDatum->getWord(),
+                                         &oldDatum->getErrorCondensedHit());
+      outputCollection->push_back(datumCopy);
     }
+
+    return outputCollection;
   }
 
-  // Specialize mergeCollectionsNew() for the SCT
-  template<> void mergeCollectionsNew(InDetRawDataCollection<SCT_RDORawData> *bkgCollection,
-                                      InDetRawDataCollection<SCT_RDORawData> *signalCollection,
-                                      InDetRawDataCollection<SCT_RDORawData> *outputCollection,
-                                      IDC_OverlayBase *tmp)
+  // Specialize mergeCollections() for the SCT
+  template<>
+  void mergeCollections(SCT_RDO_Collection *bkgCollection,
+                        SCT_RDO_Collection *signalCollection,
+                        SCT_RDO_Collection *outputCollection,
+                        IDC_OverlayBase *algorithm)
   {
     // We want to use the SCT_ID helper provided by SCTOverlay, thus the constraint
-    SCTOverlay *parent = dynamic_cast<SCTOverlay*>(tmp);
+    SCTOverlay *parent = dynamic_cast<SCTOverlay *>(algorithm);
     if (!parent) {
-      std::ostringstream os;
-      os << "mergeCollectionsNew<SCT_RDORawData>() called by a wrong parent algorithm?  Must be SCTOverlay.";
-      throw std::runtime_error(os.str());
-    }
-
-    // ----------------------------------------------------------------
-    // debug
-    static bool first_time = true;
-    if (first_time) {
-      first_time = false;
-      parent->msg(MSG::INFO) << "SCTOverlay::mergeCollectionsNew(): "
-                             << " SCT specific code is called for "
-                             << typeid(*bkgCollection).name()
-                             << endmsg;
+      throw std::runtime_error("mergeCollections<SCT_RDORawData>() called by a wrong parent algorithm? Must be SCTOverlay.");
     }
 
     // ----------------------------------------------------------------
@@ -74,39 +63,25 @@ namespace Overlay
     //
     // http://alxr.usatlas.bnl.gov/lxr/source/atlas/InnerDetector/InDetRecTools/SiClusterizationTool/src/SCT_ClusteringTool.cxx
 
-
-    // ----------------------------------------------------------------
     if (bkgCollection->identify() != signalCollection->identify()) {
-      std::ostringstream os;
-      os << "mergeCollectionsNew<SCT_RDORawData>(): collection Id mismatch";
-      parent->msg(MSG::FATAL) << os.str() << endmsg;
-      throw std::runtime_error(os.str());
+      throw std::runtime_error("mergeCollections<SCT_RDO_Collection>(): collection Id mismatch");
     }
 
     const Identifier idColl = parent->get_sct_id()->wafer_id(signalCollection->identifyHash());
 
-    // Empty the input collections and move RDOs to local vectors.
-    InDetRawDataCollection<SCT_RDORawData> bkg(bkgCollection->identifyHash());
-    bkg.setIdentifier(idColl);
-    bkgCollection->swap(bkg);
-
-    InDetRawDataCollection<SCT_RDORawData> sig(signalCollection->identifyHash());
-    sig.setIdentifier(idColl);
-    signalCollection->swap(sig);
-
     // Strip hit timing information for Next, Current, Previous and Any BCs
     // Prepare one more strip to create the last one. The additional strip has no hits.
     std::bitset<SCTOverlay::NumberOfStrips+1> stripInfo[SCTOverlay::NumberOfBitSets];
     // Process background and signal in the wafer
     for (unsigned source = SCTOverlay::BkgSource; source < SCTOverlay::NumberOfSources; source++) {
-      InDetRawDataCollection<SCT_RDORawData>::const_iterator rdo;
-      InDetRawDataCollection<SCT_RDORawData>::const_iterator rdoEnd;
+      SCT_RDO_Collection::const_iterator rdo;
+      SCT_RDO_Collection::const_iterator rdoEnd;
       if (source == SCTOverlay::BkgSource) { // background
-        rdo = bkg.begin();
-        rdoEnd = bkg.end();
+        rdo = bkgCollection->begin();
+        rdoEnd = bkgCollection->end();
       } else { // signal
-        rdo = sig.begin();
-        rdoEnd = sig.end();
+        rdo = signalCollection->begin();
+        rdoEnd = signalCollection->end();
       } 
       // Loop over all RDOs in the wafer
       for (; rdo!=rdoEnd; ++rdo) {
@@ -114,7 +89,7 @@ namespace Overlay
         if (!rdo3) {
           std::ostringstream os;
           const auto& elt = **rdo;
-          os << "mergeCollectionNew<SCT_RDORawData>(): wrong datum format. Only SCT3_RawData are produced by SCT_RodDecoder and supported by overlay."
+          os << "mergeCollection<SCT_RDO_Collection>(): wrong datum format. Only SCT3_RawData are produced by SCT_RodDecoder and supported by overlay."
              << "For the supplied datum  typeid(datum).name() = " << typeid(elt).name();
           throw std::runtime_error(os.str());
         }
@@ -175,7 +150,7 @@ namespace Overlay
         }
       }
     }
-  } // mergeCollectionsNew()
+  } // mergeCollections()
 } // namespace Overlay
 
 
@@ -241,13 +216,14 @@ StatusCode SCTOverlay::execute()
   // Creating output RDO container
   SG::WriteHandle<SCT_RDO_Container> outputContainer(m_outputKey);
   ATH_CHECK(outputContainer.record(std::make_unique<SCT_RDO_Container>(signalContainer->size())));
+  if (!outputContainer.isValid()) {
+    ATH_MSG_ERROR("Could not record output SCT RDO container " << outputContainer.name() << " to store " << outputContainer.store());
+    return StatusCode::FAILURE;
+  }
   ATH_MSG_DEBUG("Recorded output SCT RDO container " << outputContainer.name() << " in store " << outputContainer.store());
 
-  if (outputContainer.isValid()) {
-    overlayContainerNew(bkgContainerPtr, signalContainer.cptr(), outputContainer.ptr());
-
-    ATH_MSG_DEBUG("SCT Result   = " << Overlay::debugPrint(outputContainer.ptr(), 50));
-  }
+  ATH_CHECK(overlayContainer(bkgContainerPtr, signalContainer.cptr(), outputContainer.ptr()));
+  ATH_MSG_DEBUG("SCT Result   = " << Overlay::debugPrint(outputContainer.ptr(), 50));
 
   ATH_MSG_DEBUG("execute() end");
   return StatusCode::SUCCESS;
diff --git a/InnerDetector/InDetRawAlgs/InDetOverlay/src/TRTOverlay.cxx b/InnerDetector/InDetRawAlgs/InDetOverlay/src/TRTOverlay.cxx
index 4e15da8f192e79371390116d15a7d85f028634e6..38d74e08d097b5f77b836f48dd90d4d453ce98f8 100644
--- a/InnerDetector/InDetRawAlgs/InDetOverlay/src/TRTOverlay.cxx
+++ b/InnerDetector/InDetRawAlgs/InDetOverlay/src/TRTOverlay.cxx
@@ -22,20 +22,10 @@
 namespace Overlay
 {
   // Specialize mergeChannelData() for the TRT
-  template<> void mergeChannelData(TRT_RDORawData &r1, const TRT_RDORawData &r2, IDC_OverlayBase *parent)
+  template<> void mergeChannelData(TRT_RDORawData &r1,
+                                   const TRT_RDORawData &r2,
+                                   TRTOverlay *)
   {
-
-    // ----------------------------------------------------------------
-    // debug
-    static bool first_time = true;
-    if (first_time) {
-      first_time = false;
-      parent->msg(MSG::INFO) << "Overlay::mergeChannelData(): "
-                             << "TRT specific code is called for "
-                             << typeid(TRT_RDORawData).name()
-                             << endmsg;
-    }
-
     // ----------------------------------------------------------------
     // FIXME: That should really be a call to r1.merge(r2);
 
@@ -49,18 +39,24 @@ namespace Overlay
   } // mergeChannelData()
 
   // Specialize copyCollection() for the TRT
-  template<> void copyCollection(const InDetRawDataCollection<TRT_RDORawData> *input_coll, InDetRawDataCollection<TRT_RDORawData> *copy_coll)
+  template<>
+  std::unique_ptr<TRT_RDO_Collection> copyCollection(const IdentifierHash &hashId,
+                                                     const TRT_RDO_Collection *collection)
   {
-    copy_coll->setIdentifier(input_coll->identify());
-    InDetRawDataCollection<TRT_RDORawData>::const_iterator firstData = input_coll->begin();
-    InDetRawDataCollection<TRT_RDORawData>::const_iterator lastData = input_coll->end();
-    for ( ; firstData != lastData; ++firstData)
-    {
-	    const Identifier ident = (*firstData)->identify();
-	    const unsigned int word = (*firstData)->getWord();
-	    TRT_LoLumRawData *newData = new TRT_LoLumRawData(ident, word);
-	    copy_coll->push_back(newData);
+    auto outputCollection = std::make_unique<TRT_RDO_Collection>(hashId);
+    if (!collection) {
+      return outputCollection;
     }
+
+    outputCollection->setIdentifier(collection->identify());
+
+    for (const TRT_RDORawData *existingDatum : *collection) {
+      // Owned by the collection
+      auto *datumCopy = new TRT_LoLumRawData(existingDatum->identify(), existingDatum->getWord());
+      outputCollection->push_back(datumCopy);
+    }
+
+    return outputCollection;
   }
 } // namespace Overlay
 
@@ -166,7 +162,7 @@ StatusCode TRTOverlay::execute() {
       //Merge containers
       overlayTRTContainers(bkgContainerPtr, signalContainer.cptr(), outputContainer.ptr(), occupancy, *signalSDOContainer);
     } else {
-      overlayContainerNew(bkgContainerPtr, signalContainer.cptr(), outputContainer.ptr());
+      ATH_CHECK(overlayContainer(bkgContainerPtr, signalContainer.cptr(), outputContainer.ptr()));
     }
 
     ATH_MSG_DEBUG("TRT Result   = " << Overlay::debugPrint(outputContainer.ptr()));
@@ -189,8 +185,7 @@ void TRTOverlay::overlayTRTContainers(const TRT_RDO_Container *bkgContainer,
 
      for(; p_bkg != p_bkg_end; ++p_bkg) {
        IdentifierHash hashId = p_bkg.hashId();
-       auto coll_bkg = std::make_unique<TRT_RDO_Collection>(hashId);
-       Overlay::copyCollection(*p_bkg, coll_bkg.get());
+       auto coll_bkg = Overlay::copyCollection(hashId, *p_bkg);
 
        if (outputContainer->addCollection(coll_bkg.release(), p_bkg.hashId() ).isFailure()) {
          ATH_MSG_WARNING("add background Collection failed for output " << p_bkg.hashId());
@@ -209,8 +204,7 @@ void TRTOverlay::overlayTRTContainers(const TRT_RDO_Container *bkgContainer,
    for (; p_signal != p_signal_end; ++p_signal) {
 
       IdentifierHash coll_id = p_signal.hashId();
-      auto coll_signal = std::make_unique<TRT_RDO_Collection>(coll_id);
-      Overlay::copyCollection( *p_signal, coll_signal.get() ) ;
+      auto coll_signal = Overlay::copyCollection( coll_id, *p_signal ) ;
 
       /** The newly created stuff will go to the output EventStore SG */
       auto coll_out = std::make_unique<TRT_RDO_Collection>(coll_id);
diff --git a/InnerDetector/InDetRawAlgs/InDetOverlay/test/PixelOverlay_test.cxx b/InnerDetector/InDetRawAlgs/InDetOverlay/test/PixelOverlay_test.cxx
index 91161d7edb11ca2d4e7af5b3b9fade0ab8f6e236..1a42456d21099378e2d8ed4bf6779ac75149ce0f 100644
--- a/InnerDetector/InDetRawAlgs/InDetOverlay/test/PixelOverlay_test.cxx
+++ b/InnerDetector/InDetRawAlgs/InDetOverlay/test/PixelOverlay_test.cxx
@@ -378,8 +378,8 @@ namespace OverlayTesting {
     ASSERT_TRUE( outputCollection->size()==1 );
     const PixelRDORawData* outputDigit1 = outputCollection->at(0);
     ASSERT_TRUE( outputDigit1!=nullptr );
-    ASSERT_TRUE( outputDigit1->getToT()==bkgToT ); // Bkg RDO taken in case of matching Identifiers
-    ASSERT_TRUE( outputDigit1->getBCID()==bkgBCID-1 ); // Bkg RDO taken in case of matching Identifiers
+    ASSERT_TRUE( outputDigit1->getToT()==sigToT ); // Signal RDO taken in case of matching Identifiers
+    ASSERT_TRUE( outputDigit1->getBCID()==sigBCID-1 ); // Signal RDO taken in case of matching Identifiers
   }
 
   TEST_F(PixelOverlay_test, two_RDOs_with_matching_id_bkg_first) {
@@ -424,8 +424,8 @@ namespace OverlayTesting {
     ASSERT_TRUE( outputCollection->size()==1 );
     const PixelRDORawData* outputDigit1 = outputCollection->at(0);
     ASSERT_TRUE( outputDigit1!=nullptr );
-    ASSERT_TRUE( outputDigit1->getToT()==bkgToT ); // Bkg RDO taken in case of matching Identifiers
-    ASSERT_TRUE( outputDigit1->getBCID()==bkgBCID-1 ); // Bkg RDO taken in case of matching Identifiers
+    ASSERT_TRUE( outputDigit1->getToT()==sigToT ); // Signal RDO taken in case of matching Identifiers
+    ASSERT_TRUE( outputDigit1->getBCID()==sigBCID-1 ); // Signal RDO taken in case of matching Identifiers
   }
 
   TEST_F(PixelOverlay_test, containers_with_matching_collections_one_different_RDO_each_v2) {
diff --git a/MuonSpectrometer/MuonOverlay/MdtOverlay/MdtOverlay/MdtOverlay.h b/MuonSpectrometer/MuonOverlay/MdtOverlay/MdtOverlay/MdtOverlay.h
index 5c9753beec3abc952282b7cd04eabfb4d7bfbbe9..b5909d1cc3214046ce75697141bd2d4e69abac5e 100644
--- a/MuonSpectrometer/MuonOverlay/MdtOverlay/MdtOverlay/MdtOverlay.h
+++ b/MuonSpectrometer/MuonOverlay/MdtOverlay/MdtOverlay/MdtOverlay.h
@@ -7,9 +7,7 @@
 // Overlaying MdtDigits from two different events for MDT subdetectors.
 //
 // Andrei Gaponenko <agaponenko@lbl.gov>, 2006, 2007
-
 // Ketevi A. Assamagan <ketevi@bnl.gov>, March 2008 
-
 // Piyali Banerjee <Piyali.Banerjee@cern.ch>, March 2011
 
 #ifndef MDTOVERLAY_H
@@ -17,35 +15,27 @@
 
 #include <string>
 
-#include "MuonOverlayBase/MuonOverlayBase.h"
-#include "MuonDigitContainer/MdtDigitContainer.h"
-
-class MdtOverlay : public MuonOverlayBase  {
+#include <MuonOverlayBase/IDC_MuonOverlayBase.h>
+#include <MuonDigitContainer/MdtDigitContainer.h>
 
+class MdtOverlay : public IDC_MuonOverlayBase
+{
 public:
-
   MdtOverlay(const std::string &name,ISvcLocator *pSvcLocator);
 
-  /** Framework implemenrtation for the event loop */
-  virtual StatusCode overlayInitialize();
-  virtual StatusCode overlayExecute();
-  virtual StatusCode overlayFinalize();
+  virtual StatusCode initialize() override final;
+  virtual StatusCode execute() override final;
 
-  float adcIntegrationWindow() const { return m_adcIntegrationWindow; }
+  float adcIntegrationWindow() const { return m_adcIntegrationWindow.value(); }
 
 private:
-  // ----------------------------------------------------------------
-
-  // jO controllable properties.
-  // "Main" containers are read, have data from "overlay" containers added,
-  // and written out with the original SG keys.
-  SG::ReadHandleKey<MdtDigitContainer> m_mainInputDigitKey{this,"MainInputDigitKey","OriginalEvent_SG+MDT_DIGITS","ReadHandleKey for Main Input MdtDigitContainer"};
-  SG::ReadHandleKey<MdtDigitContainer> m_overlayInputDigitKey{this,"OverlayInputDigitKey","BkgEvent_0_SG+MDT_DIGITS","ReadHandleKey for Overlay Input MdtDigitContainer"};
-  SG::WriteHandleKey<MdtDigitContainer> m_outputDigitKey{this,"OutputDigitKey","StoreGateSvc+MDT_DIGITS","WriteHandleKey for Output MdtDigitContainer"};
-
-  float m_adcIntegrationWindow{20.0}; // in ns
-  bool m_clean_overlay_data{false};
-  bool m_clean_overlay_signal{false};
+  SG::ReadHandleKey<MdtDigitContainer> m_bkgInputKey{this, "BkgInputKey", "OriginalEvent_SG+MDT_DIGITS", "ReadHandleKey for Background Input MdtDigitContainer"};
+  SG::ReadHandleKey<MdtDigitContainer> m_signalInputKey{this, "SignalInputKey", "BkgEvent_0_SG+MDT_DIGITS", "ReadHandleKey for Signal Input MdtDigitContainer"};
+  SG::WriteHandleKey<MdtDigitContainer> m_outputKey{this, "OutputKey", "StoreGateSvc+MDT_DIGITS", "WriteHandleKey for Output MdtDigitContainer"};
+
+  BooleanProperty m_includeBkg { this, "includeBkg", true, "Include Background RDO Container" };
+  FloatProperty m_adcIntegrationWindow { this, "IntegrationWindow", 20.0, "ADC Integration Window" };
+
 };
 
 #endif/* MDTOVERLAY_H */
diff --git a/MuonSpectrometer/MuonOverlay/MdtOverlay/python/MdtOverlayConfig.py b/MuonSpectrometer/MuonOverlay/MdtOverlay/python/MdtOverlayConfig.py
index ed8d3fd6983a7290eacaddce2e62219bfa0d5419..4a83973ea5d4b084d1da90613623836196d3d3fe 100644
--- a/MuonSpectrometer/MuonOverlay/MdtOverlay/python/MdtOverlayConfig.py
+++ b/MuonSpectrometer/MuonOverlay/MdtOverlay/python/MdtOverlayConfig.py
@@ -1,13 +1,14 @@
-# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
 
 from AthenaCommon import CfgMgr
 
 def getMdtOverlay(name="MdtOverlay", **kwargs):
     from OverlayCommonAlgs.OverlayFlags import overlayFlags
-    kwargs.setdefault("MainInputDigitKey",overlayFlags.dataStore()+"+MDT_DIGITS")
-    kwargs.setdefault("OverlayInputDigitKey",overlayFlags.evtStore()+"+MDT_DIGITS")
-    kwargs.setdefault("OutputDigitKey",overlayFlags.outputStore()+"+MDT_DIGITS")
+
+    kwargs.setdefault("BkgInputKey", overlayFlags.dataStore() + "+MDT_DIGITS")
+    kwargs.setdefault("SignalInputKey", overlayFlags.evtStore() + "+MDT_DIGITS")
+    kwargs.setdefault("OutputKey", overlayFlags.outputStore() + "+MDT_DIGITS")
+
     kwargs.setdefault("IntegrationWindow", 20) # in ns
-    kwargs.setdefault("MCStore",overlayFlags.evtStore())
-    kwargs.setdefault("DataStore", overlayFlags.dataStore())
+
     return CfgMgr.MdtOverlay(name, **kwargs)
diff --git a/MuonSpectrometer/MuonOverlay/MdtOverlay/src/MdtOverlay.cxx b/MuonSpectrometer/MuonOverlay/MdtOverlay/src/MdtOverlay.cxx
index 68d1317bac2d4045e22fcd1cf3fdb60343a76e49..44806dc8a710f314ef44570fbe3e6cd796aa3e55 100644
--- a/MuonSpectrometer/MuonOverlay/MdtOverlay/src/MdtOverlay.cxx
+++ b/MuonSpectrometer/MuonOverlay/MdtOverlay/src/MdtOverlay.cxx
@@ -3,162 +3,132 @@
 */
 
 // Andrei Gaponenko <agaponenko@lbl.gov>, 2006, 2007
-
 // Ketevi A. Assamagan <ketevi@bnl.gov>, March 2008
-
 // Piyali Banerjee <Piyali.Banerjee@cern.ch>, March 2011
 
-#include "MdtOverlay/MdtOverlay.h"
+#include <MdtOverlay/MdtOverlay.h>
 
-#include "StoreGate/StoreGateSvc.h"
-#include "StoreGate/DataHandle.h"
-#include "StoreGate/ReadHandle.h"
-#include "StoreGate/WriteHandle.h"
+#include <StoreGate/ReadHandle.h>
+#include <StoreGate/WriteHandle.h>
 
-#include "MuonDigitContainer/MdtDigitContainer.h"
+#include <IDC_OverlayBase/IDC_OverlayHelpers.h>
 
-#include <iostream>
-#include <typeinfo>
-#include <stdexcept>
 
 //================================================================
-namespace Overlay {
+namespace Overlay
+{
   /** template specialization function to add 2 MDT Digits - basically the operator+=
    * A declaration of the specialization must happen before the template is used from
    * the overlayContainer() method.  So we just put this implementation at the beginning
    * of this file.
    */
-  template<> void mergeChannelData(MdtDigit& mainDigit, const MdtDigit& ovlDigit, IDC_OverlayBase *baseParent) {
-    MdtOverlay* parent = dynamic_cast<MdtOverlay*>(baseParent);
-    if(!parent) {
-      throw std::runtime_error("Overlay::mergeChannelData<MdtDigit>(): ERROR: calling alg is not MdtOverlay.");
+  template<>
+  void mergeChannelData(MdtDigit& signalDigit,
+                        const MdtDigit& bkgDigit,
+                        IDC_MuonOverlayBase *algorithm)
+  {
+    // We want to use the integration window provided by MdtOverlay, thus the constraint
+    MdtOverlay *parent = dynamic_cast<MdtOverlay *>(algorithm);
+    if (!parent) {
+      throw std::runtime_error("mergeChannelData<MdtDigit>() called by a wrong parent algorithm? Must be MdtOverlay.");
     }
 
-    // ----------------------------------------------------------------
-    // confirm that the specialization is being used by printing out...
-    static bool first_time = true;
-    if(first_time) {
-      first_time = false;
-      parent->msg(MSG::INFO)<<"Overlay::mergeChannelData<MdtDigit>(): "
-                            <<"MDT specific code is called for "
-                            <<typeid(MdtDigit).name()
-                            <<endmsg;
-    }
+    int sig_tdc = signalDigit.tdc();
+    int bkg_tdc = bkgDigit.tdc();
 
-    // ----------------------------------------------------------------
-    // the real merging happens here
-    int main_tdc = mainDigit.tdc();
-    int ovl_tdc  = ovlDigit.tdc();
-
-    /** background masks Physics hit - no correction to the ADC
-        FIXME: Probably should return the maksed hit as well */
-    if ( abs(main_tdc-ovl_tdc) > parent->adcIntegrationWindow() && main_tdc < ovl_tdc ) {
-      // do nothing - keep mainDigit.
+    /** signal masks the background - no correction to the ADC
+        FIXME: Probably should return the masked hit as well */
+    if ( abs(sig_tdc - bkg_tdc) > parent->adcIntegrationWindow() && sig_tdc < bkg_tdc ) {
+      // do nothing - keep baseDigit.
     }
     /** Physics hit masks the background hit - no correct to the AOD
         FIXME: Probably should return the masked hit as well */
-    else if ( abs(main_tdc-ovl_tdc) > parent->adcIntegrationWindow() && main_tdc > ovl_tdc ) {
-      // Use ovlDigit as the final answer
-      mainDigit = ovlDigit;
+    else if ( abs(sig_tdc - bkg_tdc) > parent->adcIntegrationWindow() && sig_tdc > bkg_tdc ) {
+      // Use the background digit as the final answer
+      signalDigit = bkgDigit;
     }
     /** the 2 hits overlap withing the ADC integration window
         the ADC will add partially
         the TDC is from the first hit that crosses the threshold
         FIXME: how to add partially for correct - for now just add the ADD total */
-    else if ( abs(main_tdc-ovl_tdc) < parent->adcIntegrationWindow() )  {
-      int tdc = std::min( mainDigit.tdc(), ovlDigit.tdc() );
-      int adc = mainDigit.adc() + ovlDigit.adc();
-      mainDigit =  MdtDigit(mainDigit.identify(), tdc, adc );
+    else if ( abs(sig_tdc - bkg_tdc) < parent->adcIntegrationWindow() )  {
+      int tdc = std::min( signalDigit.tdc(), bkgDigit.tdc() );
+      int adc = signalDigit.adc() + bkgDigit.adc();
+      signalDigit = MdtDigit(signalDigit.identify(), tdc, adc);
     }
   }
+} // namespace Overlay
 
-}
 
 //================================================================
-MdtOverlay::MdtOverlay(const std::string &name, ISvcLocator *pSvcLocator) :
-  MuonOverlayBase(name, pSvcLocator)
+MdtOverlay::MdtOverlay(const std::string &name, ISvcLocator *pSvcLocator)
+  : IDC_MuonOverlayBase(name, pSvcLocator)
 {
-
-  /** modifiable properties in job options */
-  declareProperty("IntegrationWindow", m_adcIntegrationWindow); // in ns
-  declareProperty("CleanOverlayData", m_clean_overlay_data);//clean out the overlay data before doing overlay, so you only get MC hits in the output overlay
-  declareProperty("CleanOverlaySignal", m_clean_overlay_signal);//clean out the signal MC before doing overlay
 }
 
 //================================================================
-StatusCode MdtOverlay::overlayInitialize()
+StatusCode MdtOverlay::initialize()
 {
-  ATH_MSG_INFO("MdtOverlay initialized");
+  ATH_MSG_DEBUG("Initializing...");
 
-  ATH_CHECK(m_mainInputDigitKey.initialize());
-  ATH_MSG_VERBOSE("Initialized ReadHandleKey: " << m_mainInputDigitKey );
-  ATH_CHECK(m_overlayInputDigitKey.initialize());
-  ATH_MSG_VERBOSE("Initialized ReadHandleKey: " << m_overlayInputDigitKey );
-  ATH_CHECK(m_outputDigitKey.initialize());
-  ATH_MSG_VERBOSE("Initialized WriteHandleKey: " << m_outputDigitKey );
+  if (!m_includeBkg) {
+    ATH_MSG_DEBUG("Disabling use of background RDOs...");
+    ATH_CHECK( m_bkgInputKey.assign("") );
+  }
 
-  return StatusCode::SUCCESS;
-}
+  // Check and initialize keys
+  ATH_CHECK( m_bkgInputKey.initialize(!m_bkgInputKey.key().empty()) );
+  ATH_MSG_VERBOSE("Initialized ReadHandleKey: " << m_bkgInputKey );
+  ATH_CHECK(m_signalInputKey.initialize());
+  ATH_MSG_VERBOSE("Initialized ReadHandleKey: " << m_signalInputKey );
+  ATH_CHECK(m_outputKey.initialize());
+  ATH_MSG_VERBOSE("Initialized WriteHandleKey: " << m_outputKey );
 
-//================================================================
-StatusCode MdtOverlay::overlayFinalize()
-{
-  ATH_MSG_INFO("MdtOverlay finalized");
   return StatusCode::SUCCESS;
 }
 
 //================================================================
-StatusCode MdtOverlay::overlayExecute() {
-  ATH_MSG_DEBUG("MdtOverlay::execute() begin");
+StatusCode MdtOverlay::execute() {
+  ATH_MSG_DEBUG("execute() begin");
 
-  //----------------------------------------------------------------
-  ATH_MSG_VERBOSE("Retrieving data input MDT container");
 
-  SG::ReadHandle<MdtDigitContainer> dataContainer (m_mainInputDigitKey);
-  if (!dataContainer.isValid()) {
-    ATH_MSG_ERROR("Could not get data MDT container " << dataContainer.name() << " from store " << dataContainer.store());
-    return StatusCode::FAILURE;
+  const MdtDigitContainer *bkgContainerPtr = nullptr;
+  if (m_includeBkg) {
+    SG::ReadHandle<MdtDigitContainer> bkgContainer (m_bkgInputKey);
+    if (!bkgContainer.isValid()) {
+      ATH_MSG_ERROR("Could not get background MDT container " << bkgContainer.name() << " from store " << bkgContainer.store());
+      return StatusCode::FAILURE;
+    }
+    bkgContainerPtr = bkgContainer.cptr();
+
+    ATH_MSG_DEBUG("Found background MdtDigitContainer called " << bkgContainer.name() << " in store " << bkgContainer.store());
+    ATH_MSG_DEBUG("MDT Background = " << Overlay::debugPrint(bkgContainer.cptr()));
+    ATH_MSG_VERBOSE("MDT background has digit_size " << bkgContainer->digit_size());
   }
-  ATH_MSG_DEBUG("Found data MdtDigitContainer called " << dataContainer.name() << " in store " << dataContainer.store());
-  ATH_MSG_INFO("MDT Data     = "<<shortPrint(dataContainer.cptr()));
 
-  ATH_MSG_VERBOSE("Retrieving MC  input MDT container");
-  SG::ReadHandle<MdtDigitContainer> mcContainer(m_overlayInputDigitKey);
-  if(!mcContainer.isValid() ) {
-    ATH_MSG_ERROR("Could not get overlay MDT container " << mcContainer.name() << " from store " << mcContainer.store());
+  SG::ReadHandle<MdtDigitContainer> signalContainer(m_signalInputKey);
+  if(!signalContainer.isValid() ) {
+    ATH_MSG_ERROR("Could not get signal MDT container " << signalContainer.name() << " from store " << signalContainer.store());
+    return StatusCode::FAILURE;
+  }
+  ATH_MSG_DEBUG("Found signal MdtDigitContainer called " << signalContainer.name() << " in store " << signalContainer.store());
+  ATH_MSG_DEBUG("MDT Signal     = " << Overlay::debugPrint(signalContainer.cptr()));
+  ATH_MSG_VERBOSE("MDT signal has digit_size " << signalContainer->digit_size());
+
+  SG::WriteHandle<MdtDigitContainer> outputContainer(m_outputKey);
+  ATH_CHECK(outputContainer.record(std::make_unique<MdtDigitContainer>(signalContainer->size())));
+  if (!outputContainer.isValid()) {
+    ATH_MSG_ERROR("Could not record output MdtDigitContainer called " << outputContainer.name() << " to store " << outputContainer.store());
     return StatusCode::FAILURE;
   }
-  ATH_MSG_DEBUG("Found overlay MdtDigitContainer called " << mcContainer.name() << " in store " << mcContainer.store());
-  ATH_MSG_INFO("MDT MC       = "<<shortPrint(mcContainer.cptr()));
-
-  ATH_MSG_VERBOSE("MDT data has digit_size "<<dataContainer->digit_size());
-
-  ATH_MSG_VERBOSE("MDT signal data has digit_size "<<mcContainer->digit_size());
-
-  SG::WriteHandle<MdtDigitContainer> outputContainer(m_outputDigitKey);
-  ATH_CHECK(outputContainer.record(std::make_unique<MdtDigitContainer>(dataContainer->size())));
   ATH_MSG_DEBUG("Recorded output MdtDigitContainer called " << outputContainer.name() << " in store " << outputContainer.store());
 
-  if(dataContainer.isValid() && mcContainer.isValid() && outputContainer.isValid()) {
-    if(!m_clean_overlay_data && !m_clean_overlay_signal){
-      //Do the actual overlay
-      this->overlayContainer(dataContainer.cptr(), mcContainer.cptr(), outputContainer.ptr());
-    }
-    else if (m_clean_overlay_data) {
-      MdtDigitContainer nobkg(0);
-      this->overlayContainer(&nobkg , mcContainer.cptr() , outputContainer.ptr());
-    }
-    else if (m_clean_overlay_signal) {
-      MdtDigitContainer nomc(0);
-      this->overlayContainer(dataContainer.cptr(), &nomc , outputContainer.ptr());
-    }
-  }
-  ATH_MSG_INFO("MDT Result   = "<<shortPrint(outputContainer.cptr()));
+  // Do the actual overlay
+  ATH_CHECK(overlayContainer(bkgContainerPtr, signalContainer.cptr(), outputContainer.ptr()));
+  ATH_MSG_DEBUG("MDT Result     = " << Overlay::debugPrint(outputContainer.cptr()));
 
-  //----------------------------------------------------------------
-  ATH_MSG_DEBUG("MdtOverlay::execute() end");
+
+  ATH_MSG_DEBUG("execute() end");
 
   return StatusCode::SUCCESS;
 }
-
-//================================================================
diff --git a/MuonSpectrometer/MuonOverlay/MdtOverlay/test/MdtOverlay_test.cxx b/MuonSpectrometer/MuonOverlay/MdtOverlay/test/MdtOverlay_test.cxx
index 8f26e331ad52e2045177cee6b70eef21b4658794..60838f8adb3fceb70528b652523800c4821850be 100644
--- a/MuonSpectrometer/MuonOverlay/MdtOverlay/test/MdtOverlay_test.cxx
+++ b/MuonSpectrometer/MuonOverlay/MdtOverlay/test/MdtOverlay_test.cxx
@@ -53,11 +53,11 @@ namespace OverlayTesting {
     std::string  inputSigPropertyValue = "'StoreGateSvc+MDT_DIGITS_SIG'";
     std::string  inputBkgPropertyValue = "'StoreGateSvc+MDT_DIGITS_BKG'";
     std::string    outputPropertyValue = "'StoreGateSvc+MDT_DIGITS'";
-    ASSERT_TRUE( m_alg->setProperty( "MainInputDigitKey",   inputSigPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->setProperty( "OverlayInputDigitKey",   inputBkgPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->setProperty( "OutputDigitKey", outputPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->overlayInitialize().isSuccess() );
-    ASSERT_TRUE( m_alg->overlayExecute().isFailure() ); //inputs don't exist
+    ASSERT_TRUE( m_alg->setProperty( "BkgInputKey",    inputBkgPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->setProperty( "SignalInputKey", inputSigPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->setProperty( "OutputKey",      outputPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->initialize().isSuccess() );
+    ASSERT_TRUE( m_alg->execute().isFailure() ); //inputs don't exist
   }
 
   TEST_F(MdtOverlay_test, empty_containers_alg_execute) {
@@ -71,11 +71,11 @@ namespace OverlayTesting {
     std::string  inputSigPropertyValue = "'StoreGateSvc+MDT_DIGITS_SIG'";
     std::string  inputBkgPropertyValue = "'StoreGateSvc+MDT_DIGITS_BKG'";
     std::string    outputPropertyValue = "'StoreGateSvc+MDT_DIGITS'";
-    ASSERT_TRUE( m_alg->setProperty( "MainInputDigitKey",   inputSigPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->setProperty( "OverlayInputDigitKey",   inputBkgPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->setProperty( "OutputDigitKey", outputPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->overlayInitialize().isSuccess() );
-    ASSERT_TRUE( m_alg->overlayExecute().isSuccess() );
+    ASSERT_TRUE( m_alg->setProperty( "BkgInputKey",    inputBkgPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->setProperty( "SignalInputKey", inputSigPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->setProperty( "OutputKey",      outputPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->initialize().isSuccess() );
+    ASSERT_TRUE( m_alg->execute().isSuccess() );
   }
 
   TEST_F(MdtOverlay_test, containers_with_matching_empty_collections) {
@@ -97,11 +97,11 @@ namespace OverlayTesting {
     std::string  inputSigPropertyValue = "'StoreGateSvc+MDT_DIGITS_SIG1'";
     std::string  inputBkgPropertyValue = "'StoreGateSvc+MDT_DIGITS_BKG1'";
     std::string    outputPropertyValue = "'StoreGateSvc+MDT_DIGITS1'";
-    ASSERT_TRUE( m_alg->setProperty( "MainInputDigitKey",   inputSigPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->setProperty( "OverlayInputDigitKey",   inputBkgPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->setProperty( "OutputDigitKey", outputPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->overlayInitialize().isSuccess() );
-    ASSERT_TRUE( m_alg->overlayExecute().isSuccess() );
+    ASSERT_TRUE( m_alg->setProperty( "BkgInputKey",    inputBkgPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->setProperty( "SignalInputKey", inputSigPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->setProperty( "OutputKey",      outputPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->initialize().isSuccess() );
+    ASSERT_TRUE( m_alg->execute().isSuccess() );
     // check output makes sense
     SG::ReadHandle<MdtDigitContainer> outputDataHandle{"StoreGateSvc+MDT_DIGITS1"};
     ASSERT_TRUE( outputDataHandle.isValid() );
@@ -129,11 +129,11 @@ namespace OverlayTesting {
     std::string  inputSigPropertyValue = "'StoreGateSvc+MDT_DIGITS_SIG2'";
     std::string  inputBkgPropertyValue = "'StoreGateSvc+MDT_DIGITS_BKG2'";
     std::string    outputPropertyValue = "'StoreGateSvc+MDT_DIGITS2'";
-    ASSERT_TRUE( m_alg->setProperty( "MainInputDigitKey",   inputSigPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->setProperty( "OverlayInputDigitKey",   inputBkgPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->setProperty( "OutputDigitKey", outputPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->overlayInitialize().isSuccess() );
-    ASSERT_TRUE( m_alg->overlayExecute().isSuccess() );
+    ASSERT_TRUE( m_alg->setProperty( "BkgInputKey",    inputBkgPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->setProperty( "SignalInputKey", inputSigPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->setProperty( "OutputKey",      outputPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->initialize().isSuccess() );
+    ASSERT_TRUE( m_alg->execute().isSuccess() );
     // check output makes sense
     SG::ReadHandle<MdtDigitContainer> outputDataHandle{"StoreGateSvc+MDT_DIGITS2"};
     ASSERT_TRUE( outputDataHandle.isValid() );
@@ -169,11 +169,11 @@ namespace OverlayTesting {
     std::string  inputSigPropertyValue = "'StoreGateSvc+MDT_DIGITS_SIG3'";
     std::string  inputBkgPropertyValue = "'StoreGateSvc+MDT_DIGITS_BKG3'";
     std::string    outputPropertyValue = "'StoreGateSvc+MDT_DIGITS3'";
-    ASSERT_TRUE( m_alg->setProperty( "MainInputDigitKey",   inputSigPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->setProperty( "OverlayInputDigitKey",   inputBkgPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->setProperty( "OutputDigitKey", outputPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->overlayInitialize().isSuccess() );
-    ASSERT_TRUE( m_alg->overlayExecute().isSuccess() );
+    ASSERT_TRUE( m_alg->setProperty( "BkgInputKey",    inputBkgPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->setProperty( "SignalInputKey", inputSigPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->setProperty( "OutputKey",      outputPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->initialize().isSuccess() );
+    ASSERT_TRUE( m_alg->execute().isSuccess() );
     // check output makes sense
     SG::ReadHandle<MdtDigitContainer> outputDataHandle{"StoreGateSvc+MDT_DIGITS3"};
     ASSERT_TRUE( outputDataHandle.isValid() );
@@ -216,11 +216,11 @@ namespace OverlayTesting {
     std::string  inputSigPropertyValue = "'StoreGateSvc+MDT_DIGITS_SIG4'";
     std::string  inputBkgPropertyValue = "'StoreGateSvc+MDT_DIGITS_BKG4'";
     std::string    outputPropertyValue = "'StoreGateSvc+MDT_DIGITS4'";
-    ASSERT_TRUE( m_alg->setProperty( "MainInputDigitKey",   inputSigPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->setProperty( "OverlayInputDigitKey",   inputBkgPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->setProperty( "OutputDigitKey", outputPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->overlayInitialize().isSuccess() );
-    ASSERT_TRUE( m_alg->overlayExecute().isSuccess() );
+    ASSERT_TRUE( m_alg->setProperty( "BkgInputKey",    inputBkgPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->setProperty( "SignalInputKey", inputSigPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->setProperty( "OutputKey",      outputPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->initialize().isSuccess() );
+    ASSERT_TRUE( m_alg->execute().isSuccess() );
     // check output makes sense
     SG::ReadHandle<MdtDigitContainer> outputDataHandle{"StoreGateSvc+MDT_DIGITS4"};
     ASSERT_TRUE( outputDataHandle.isValid() );
@@ -271,11 +271,11 @@ namespace OverlayTesting {
     std::string  inputSigPropertyValue = "'StoreGateSvc+MDT_DIGITS_SIG5'";
     std::string  inputBkgPropertyValue = "'StoreGateSvc+MDT_DIGITS_BKG5'";
     std::string    outputPropertyValue = "'StoreGateSvc+MDT_DIGITS5'";
-    ASSERT_TRUE( m_alg->setProperty( "MainInputDigitKey",   inputSigPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->setProperty( "OverlayInputDigitKey",   inputBkgPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->setProperty( "OutputDigitKey", outputPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->overlayInitialize().isSuccess() );
-    ASSERT_TRUE( m_alg->overlayExecute().isSuccess() );
+    ASSERT_TRUE( m_alg->setProperty( "BkgInputKey",    inputBkgPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->setProperty( "SignalInputKey", inputSigPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->setProperty( "OutputKey",      outputPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->initialize().isSuccess() );
+    ASSERT_TRUE( m_alg->execute().isSuccess() );
     // check output makes sense
     SG::ReadHandle<MdtDigitContainer> outputDataHandle{"StoreGateSvc+MDT_DIGITS5"};
     ASSERT_TRUE( outputDataHandle.isValid() );
@@ -323,11 +323,11 @@ namespace OverlayTesting {
     std::string  inputSigPropertyValue = "'StoreGateSvc+MDT_DIGITS_SIG6'";
     std::string  inputBkgPropertyValue = "'StoreGateSvc+MDT_DIGITS_BKG6'";
     std::string    outputPropertyValue = "'StoreGateSvc+MDT_DIGITS6'";
-    ASSERT_TRUE( m_alg->setProperty( "MainInputDigitKey",   inputSigPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->setProperty( "OverlayInputDigitKey",   inputBkgPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->setProperty( "OutputDigitKey", outputPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->overlayInitialize().isSuccess() );
-    ASSERT_TRUE( m_alg->overlayExecute().isSuccess() );
+    ASSERT_TRUE( m_alg->setProperty( "BkgInputKey",    inputBkgPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->setProperty( "SignalInputKey", inputSigPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->setProperty( "OutputKey",      outputPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->initialize().isSuccess() );
+    ASSERT_TRUE( m_alg->execute().isSuccess() );
     // check output makes sense
     SG::ReadHandle<MdtDigitContainer> outputDataHandle{"StoreGateSvc+MDT_DIGITS6"};
     ASSERT_TRUE( outputDataHandle.isValid() );
@@ -370,11 +370,11 @@ namespace OverlayTesting {
     std::string  inputSigPropertyValue = "'StoreGateSvc+MDT_DIGITS_SIG7'";
     std::string  inputBkgPropertyValue = "'StoreGateSvc+MDT_DIGITS_BKG7'";
     std::string    outputPropertyValue = "'StoreGateSvc+MDT_DIGITS7'";
-    ASSERT_TRUE( m_alg->setProperty( "MainInputDigitKey",   inputSigPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->setProperty( "OverlayInputDigitKey",   inputBkgPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->setProperty( "OutputDigitKey", outputPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->overlayInitialize().isSuccess() );
-    ASSERT_TRUE( m_alg->overlayExecute().isSuccess() );
+    ASSERT_TRUE( m_alg->setProperty( "BkgInputKey",    inputBkgPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->setProperty( "SignalInputKey", inputSigPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->setProperty( "OutputKey",      outputPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->initialize().isSuccess() );
+    ASSERT_TRUE( m_alg->execute().isSuccess() );
     // check output makes sense
     SG::ReadHandle<MdtDigitContainer> outputDataHandle{"StoreGateSvc+MDT_DIGITS7"};
     ASSERT_TRUE( outputDataHandle.isValid() );
@@ -417,11 +417,11 @@ namespace OverlayTesting {
     std::string  inputSigPropertyValue = "'StoreGateSvc+MDT_DIGITS_SIG8'";
     std::string  inputBkgPropertyValue = "'StoreGateSvc+MDT_DIGITS_BKG8'";
     std::string    outputPropertyValue = "'StoreGateSvc+MDT_DIGITS8'";
-    ASSERT_TRUE( m_alg->setProperty( "MainInputDigitKey",   inputSigPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->setProperty( "OverlayInputDigitKey",   inputBkgPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->setProperty( "OutputDigitKey", outputPropertyValue).isSuccess() );
-    ASSERT_TRUE( m_alg->overlayInitialize().isSuccess() );
-    ASSERT_TRUE( m_alg->overlayExecute().isSuccess() );
+    ASSERT_TRUE( m_alg->setProperty( "BkgInputKey",    inputBkgPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->setProperty( "SignalInputKey", inputSigPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->setProperty( "OutputKey",      outputPropertyValue).isSuccess() );
+    ASSERT_TRUE( m_alg->initialize().isSuccess() );
+    ASSERT_TRUE( m_alg->execute().isSuccess() );
     // check output makes sense
     SG::ReadHandle<MdtDigitContainer> outputDataHandle{"StoreGateSvc+MDT_DIGITS8"};
     ASSERT_TRUE( outputDataHandle.isValid() );
diff --git a/MuonSpectrometer/MuonOverlay/MuonOverlayBase/CMakeLists.txt b/MuonSpectrometer/MuonOverlay/MuonOverlayBase/CMakeLists.txt
index cbcce39fb69dbd050e6985a59df53f2e63af4bcf..ad4acd746af6c4d603f6566521352b2593662350 100644
--- a/MuonSpectrometer/MuonOverlay/MuonOverlayBase/CMakeLists.txt
+++ b/MuonSpectrometer/MuonOverlay/MuonOverlayBase/CMakeLists.txt
@@ -7,16 +7,9 @@ atlas_subdir( MuonOverlayBase )
 
 # Declare the package's dependencies:
 atlas_depends_on_subdirs( PUBLIC
-                          Control/AthenaBaseComps
-                          Control/AthContainers
-                          Control/StoreGate
-                          DetectorDescription/Identifier
-                          Event/EventOverlay/IDC_OverlayBase
-                          Event/EventOverlay/OverlayAlgBase
-                          GaudiKernel )
+                          Event/EventOverlay/IDC_OverlayBase )
 
 # Component(s) in the package:
 atlas_add_library( MuonOverlayBase
                    PUBLIC_HEADERS MuonOverlayBase
-                   LINK_LIBRARIES AthenaBaseComps AthContainers Identifier IDC_OverlayBase OverlayAlgBase GaudiKernel StoreGateLib SGtests )
-
+                   LINK_LIBRARIES IDC_OverlayBase )
diff --git a/MuonSpectrometer/MuonOverlay/MuonOverlayBase/MuonOverlayBase/IDC_MuonOverlayBase.h b/MuonSpectrometer/MuonOverlay/MuonOverlayBase/MuonOverlayBase/IDC_MuonOverlayBase.h
index 27986c5a8e8e287a1485bb7fa17c46fcc090c9e0..0c8d02681eb79321de88c00398b59bacb6c47ebc 100644
--- a/MuonSpectrometer/MuonOverlay/MuonOverlayBase/MuonOverlayBase/IDC_MuonOverlayBase.h
+++ b/MuonSpectrometer/MuonOverlay/MuonOverlayBase/MuonOverlayBase/IDC_MuonOverlayBase.h
@@ -20,6 +20,7 @@
 #define IDC_MUONOVERLAYCOMMON_H
 
 #include <AthenaBaseComps/AthAlgorithm.h>
+#include <Identifier/IdentifierHash.h>
 
 
 class IDC_MuonOverlayBase : public AthAlgorithm
diff --git a/MuonSpectrometer/MuonOverlay/MuonOverlayBase/MuonOverlayBase/IDC_MuonOverlayBase.icc b/MuonSpectrometer/MuonOverlay/MuonOverlayBase/MuonOverlayBase/IDC_MuonOverlayBase.icc
index 72b9504d7943da41bd7d696cf9b838d1787276c6..dbbb840edd239e6429fb60fed26815552149def1 100644
--- a/MuonSpectrometer/MuonOverlay/MuonOverlayBase/MuonOverlayBase/IDC_MuonOverlayBase.icc
+++ b/MuonSpectrometer/MuonOverlay/MuonOverlayBase/MuonOverlayBase/IDC_MuonOverlayBase.icc
@@ -7,9 +7,9 @@
 // Andrei Gaponenko <agaponenko@lbl.gov>, 2006-2009
 
 #include <Identifier/Identifier.h>
-#include <Identifier/IdentifierHash.h>
 
-#include "IDC_MultiHitOverlayCommon.h"
+#include <IDC_OverlayBase/IDC_OverlayCommon.h>
+#include <MuonOverlayBase/IDC_MultiHitOverlayCommon.h>
 
 
 template <class Collection>
@@ -38,14 +38,33 @@ StatusCode IDC_MuonOverlayBase::overlayContainerBase(const IDC_Container *bkgCon
                                                      bool isMultiHitCollection)
 {
   typedef typename IDC_Container::base_value_type Collection;
-  typedef typename Collection::base_value_type Datum;
 
   ATH_MSG_DEBUG("overlayContainer<>() begin");
 
-  // Get all the hashes for both signal and background container
-  const std::vector<IdentifierHash> bkgHashes = bkgContainer->GetAllCurrentHashes();
+  // Get all the hashes for the signal container
   const std::vector<IdentifierHash> signalHashes = signalContainer->GetAllCurrentHashes();
 
+  // There are some use cases where background is empty
+  if (!bkgContainer) {
+    // Only loop through the signal collections and copy them over
+    for (const IdentifierHash &hashId : signalHashes) {
+      // Copy the signal collection
+      std::unique_ptr<Collection> signalCollection = copyCollection(hashId, signalContainer->indexFindPtr(hashId));
+
+      if (outputContainer->addCollection(signalCollection.get(), hashId).isFailure()) {
+        ATH_MSG_ERROR("Adding signal Collection with hashId " << hashId << " failed");
+        return StatusCode::FAILURE;
+      } else {
+        signalCollection.release();
+      }
+    }
+
+    return StatusCode::SUCCESS;
+  }
+
+  // Get all the hashes for the background container
+  const std::vector<IdentifierHash> bkgHashes = bkgContainer->GetAllCurrentHashes();
+
   // The MC signal container should typically be smaller than bkgContainer,
   // because the latter contains all the noise, minimum bias and pile up.
   // Thus we firstly iterate over signal hashes and store them in a map.
@@ -89,11 +108,9 @@ StatusCode IDC_MuonOverlayBase::overlayContainerBase(const IDC_Container *bkgCon
       if (isMultiHitCollection) {
         Overlay::mergeMultiHitCollections(bkgCollection.get(), signalCollection.get(), outputCollection.get());
       } else {
-        // TODO: single-hit case not used at the moment
-        // Overlay::mergeCollections(bkgCollection.get(), signalCollection.get(), outputCollection.get());
+        Overlay::mergeCollections(bkgCollection.get(), signalCollection.get(), outputCollection.get(), this);
       }
 
-      outputContainer->removeCollection(hashId);
       if (outputContainer->addCollection(outputCollection.get(), hashId).isFailure()) {
         ATH_MSG_ERROR("Adding overlaid Collection with hashId " << hashId << " failed");
         return StatusCode::FAILURE;
diff --git a/MuonSpectrometer/MuonOverlay/MuonOverlayBase/MuonOverlayBase/MuonOverlayBase.h b/MuonSpectrometer/MuonOverlay/MuonOverlayBase/MuonOverlayBase/MuonOverlayBase.h
deleted file mode 100644
index 697ebb5ec3279a357a6ee867ee61486ca483e230..0000000000000000000000000000000000000000
--- a/MuonSpectrometer/MuonOverlay/MuonOverlayBase/MuonOverlayBase/MuonOverlayBase.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
-*/
-
-// Dear emacs, this is -*-c++-*-
-
-// Generic overlaying code for boolean-like hits.
-// Factored out from InDetOverlay.
-//
-// Andrei Gaponenko <agaponenko@lbl.gov>, 2006-2008
-
-// Ketevi A. Assamagan <ketevi@bnl.gov>, March 2008
-
-// Piyali Banerjee <Piyali.Banerjee@cern.ch>, March 2011
-
-#ifndef MUONOVERLAYBASE_H
-#define MUONOVERLAYBASE_H
-
-#include <string>
-#include "IDC_OverlayBase/IDC_OverlayBase.h"
-
-class ISvcLocator;
-class StoreGateSvc;
-
-class MuonOverlayBase : public IDC_OverlayBase  {
-public:
-  
-  MuonOverlayBase(const std::string &name, ISvcLocator *pSvcLocator)
-    : IDC_OverlayBase(name, pSvcLocator) {}
-
-};
-
-#endif /* MUONOVERLAYBASE_H */
diff --git a/MuonSpectrometer/MuonOverlay/MuonOverlayBase/MuonOverlayBase/MuonOverlayBase.icc b/MuonSpectrometer/MuonOverlay/MuonOverlayBase/MuonOverlayBase/MuonOverlayBase.icc
deleted file mode 100644
index 79036b3d749c16108b6f70930d4770a786526ae3..0000000000000000000000000000000000000000
--- a/MuonSpectrometer/MuonOverlay/MuonOverlayBase/MuonOverlayBase/MuonOverlayBase.icc
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-// Generic overlaying code for Muon Digits 
-// Factored out from InDetOverlay.
-//
-// Andrei Gaponenko <agaponenko@lbl.gov>, 2006-2008
-
-// Ketevi A. Assamagan <ketevi@bnl.gov>, March 2008
-
-// Piyali Banerjee <Piyali.Banerjee@cern.ch>, March 2011
-
-#include "GaudiKernel/MsgStream.h"
-#include "StoreGate/StoreGateSvc.h"
-#include <memory>
-
-//================================================================
-
-template<class TypeToBeCopied, class Datum> 
-TypeToBeCopied* MuonOverlayBase::copyMuonDigitContainer(const TypeToBeCopied* oldObject)
-{
-
-  typedef typename TypeToBeCopied::base_value_type Collection;
-  const std::string templateClassName = typeid(TypeToBeCopied).name();
-
-  if (oldObject == 0) {
-    ATH_MSG_WARNING("copyMuonDigitContainer<"<<templateClassName<<">(): oldObject is a NULL pointer");
-    return 0;
-  }
-
-  TypeToBeCopied *newObject = 0;
-
-  newObject = new TypeToBeCopied (oldObject->size());
-  typename TypeToBeCopied::const_iterator iFirst = oldObject->begin();
-  typename TypeToBeCopied::const_iterator iLast = oldObject->end();
-  for (; iFirst != iLast; ++iFirst ) {
-     Collection *element = new Collection ((*iFirst)->identify(), (*iFirst)->identifierHash());
-     typename TypeToBeCopied::base_value_type::const_iterator firstData = (*iFirst)->begin();
-     typename TypeToBeCopied::base_value_type::const_iterator lastData = (*iFirst)->end();
-     for (; firstData != lastData; ++firstData) {
-        Datum * newData = new Datum (*(dynamic_cast<const Datum*>(*firstData)));
-        element->push_back(newData);
-     }
-     if ( newObject->addCollection ( element, (*iFirst)->identifierHash() ).isFailure() ) {
-        ATH_MSG_WARNING("copyMuonDigitCongtainer<"<<templateClassName<<">(): problem adding collection with "<<"hash="<<(*iFirst)->identifierHash() );
-     }
-  }
-
-  return newObject;
-
-}