diff --git a/LArCalorimeter/LArG4/LArG4Code/CMakeLists.txt b/LArCalorimeter/LArG4/LArG4Code/CMakeLists.txt
index 983c95848543042fe0c3eec69be0c64a8c888ca6..e57ac4f4d852cdd6a2f92ce08c8294428e82123a 100644
--- a/LArCalorimeter/LArG4/LArG4Code/CMakeLists.txt
+++ b/LArCalorimeter/LArG4/LArG4Code/CMakeLists.txt
@@ -9,6 +9,7 @@ atlas_subdir( LArG4Code )
 atlas_depends_on_subdirs( PUBLIC
                           Calorimeter/CaloG4Sim
                           Calorimeter/CaloSimEvent
+                          DetectorDescription/AtlasDetDescr
                           LArCalorimeter/LArGeoModel/LArGeoCode
                           LArCalorimeter/LArSimEvent
                           Simulation/G4Atlas/G4AtlasTools
@@ -34,11 +35,11 @@ atlas_add_library( LArG4Code
                    PUBLIC_HEADERS LArG4Code
                    INCLUDE_DIRS ${GEANT4_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS}
                    DEFINITIONS ${CLHEP_DEFINITIONS}
-                   LINK_LIBRARIES ${GEANT4_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} CaloSimEvent LArGeoCode LArSimEvent CaloG4SimLib G4AtlasToolsLib StoreGateLib SGtests GaudiKernel
+                   LINK_LIBRARIES ${GEANT4_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} AtlasDetDescr CaloSimEvent LArGeoCode LArSimEvent CaloG4SimLib G4AtlasToolsLib StoreGateLib SGtests GaudiKernel
                    PRIVATE_LINK_LIBRARIES CaloIdentifier AthenaKernel CxxUtils MCTruth )
 
 atlas_add_dictionary( LArG4CodeEnums
                       LArG4Code/LArG4EnumDefs.h
                       LArG4Code/selectionEnums.xml
                       INCLUDE_DIRS  ${GEANT4_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS}
-                      LINK_LIBRARIES ${GEANT4_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} CaloSimEvent LArGeoCode LArSimEvent CaloG4SimLib G4AtlasToolsLib StoreGateLib SGtests GaudiKernel LArG4Code )
+                      LINK_LIBRARIES ${GEANT4_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} AtlasDetDescr CaloSimEvent LArGeoCode LArSimEvent CaloG4SimLib G4AtlasToolsLib StoreGateLib SGtests GaudiKernel LArG4Code )
diff --git a/LArCalorimeter/LArG4/LArG4Code/LArG4Code/CalibSDTool.h b/LArCalorimeter/LArG4/LArG4Code/LArG4Code/CalibSDTool.h
index 7a9c19ee345b31fb250aeef300bdf7e48b44ed58..fe85068457cc0948a61eec9f54a53d9a96324c63 100644
--- a/LArCalorimeter/LArG4/LArG4Code/LArG4Code/CalibSDTool.h
+++ b/LArCalorimeter/LArG4/LArG4Code/LArG4Code/CalibSDTool.h
@@ -81,6 +81,7 @@ namespace LArG4
       const LArHEC_ID*      m_larHecID;
       const LArMiniFCAL_ID* m_larMiniFcalID;
       const CaloDM_ID*      m_caloDmID;
+      const AtlasDetectorID* m_id_helper;
       /// @}
 
   }; // class CalibSDTool
diff --git a/LArCalorimeter/LArG4/LArG4Code/LArG4Code/LArG4CalibSD.h b/LArCalorimeter/LArG4/LArG4Code/LArG4Code/LArG4CalibSD.h
index c3a5effa7b897f37121afe69828cf113056d62e0..1e61b68ec700099c000341a8edd5353b525eb1ca 100644
--- a/LArCalorimeter/LArG4/LArG4Code/LArG4Code/LArG4CalibSD.h
+++ b/LArCalorimeter/LArG4/LArG4Code/LArG4Code/LArG4CalibSD.h
@@ -21,6 +21,7 @@ class LArFCAL_ID;
 class LArHEC_ID;
 class LArMiniFCAL_ID;
 class CaloDM_ID;
+class AtlasDetectorID;
 
 class ILArCalibCalculatorSvc; 
 
@@ -47,7 +48,7 @@ public:
   G4bool ProcessHits(G4Step* a_step,G4TouchableHistory*) override;
 
   /// End of athena event processing
-  void EndOfAthenaEvent( CaloCalibrationHitContainer* hitContainer );
+  void EndOfAthenaEvent( CaloCalibrationHitContainer* hitContainer, CaloCalibrationHitContainer* deadHitContainer=nullptr );
 
   /// Sets the ID helper pointers
   void setupHelpers( const LArEM_ID* EM ,
@@ -62,25 +63,13 @@ public:
     m_caloDmID = caloDm;
   }
 
+  void addDetectorHelper( const AtlasDetectorID* id_helper) { m_id_helper=id_helper; }
+
   /// For other classes that need to call into us...
   G4bool SpecialHit(G4Step* a_step, const std::vector<G4double>& a_energies);
 
 protected:
 
-  /// Constructs the calibration hit and saves it to the set
-  G4bool SimpleHit( const LArG4Identifier& a_ident, const std::vector<double>& energies );
-
-protected:
-
-  /// Member variable - the calculator we'll use
-  ILArCalibCalculatorSvc * m_calculator;
-
-  /// Count the number of invalid hits.
-  G4int m_numberInvalidHits;
-
-  /// Are we set up to run with PID hits?
-  G4bool m_doPID;
-
   // We need two types containers for hits:
 
   // The set defined below is used to tell us if we've already had a
@@ -97,10 +86,24 @@ protected:
   };
 
   typedef std::set< CaloCalibrationHit*, LessHit >  m_calibrationHits_t;
+  /// Constructs the calibration hit and saves it to the set
+  G4bool SimpleHit( const LArG4Identifier& a_ident, const std::vector<double>& energies, m_calibrationHits_t& calibrationHits );
+
+  /// Member variable - the calculator we'll use
+  ILArCalibCalculatorSvc * m_calculator;
+
+  /// Count the number of invalid hits.
+  G4int m_numberInvalidHits;
+
+  /// Are we set up to run with PID hits?
+  G4bool m_doPID;
 
   /// The actual set of calibration hits
   m_calibrationHits_t m_calibrationHits;
 
+  /// The actual set of dead material calibration hits
+  m_calibrationHits_t m_deadCalibrationHits;
+
   /// Helper function for making "real" identifiers from LArG4Identifiers
   Identifier ConvertID(const LArG4Identifier& a_ident) const;
 
@@ -110,6 +113,7 @@ protected:
   const LArHEC_ID*      m_larHecID;
   const LArMiniFCAL_ID* m_larMiniFcalID;
   const CaloDM_ID*      m_caloDmID;
+  const AtlasDetectorID* m_id_helper;
 };
 
 #endif
diff --git a/LArCalorimeter/LArG4/LArG4Code/LArG4Code/SDWrapper.h b/LArCalorimeter/LArG4/LArG4Code/LArG4Code/SDWrapper.h
index aab623292337fb896963de1b967747ff4454194c..24d20c28fe93f479d568161e5395a77527f4f698 100644
--- a/LArCalorimeter/LArG4/LArG4Code/LArG4Code/SDWrapper.h
+++ b/LArCalorimeter/LArG4/LArG4Code/LArG4Code/SDWrapper.h
@@ -58,7 +58,7 @@ namespace LArG4
         using SDList_t = std::vector< std::unique_ptr<SDType> >;
 
         /// Construct the wrapper from the output collection name
-        SDWrapper(const std::string& name, const std::string& hitCollectionName);
+        SDWrapper(const std::string& name, const std::string& hitCollectionName, std::string deadHitCollectionName="");
 
         /// Add an SD to this wrapper
         void addSD(std::unique_ptr<SDType> sd);
@@ -83,6 +83,12 @@ namespace LArG4
         /// The hit container handle
         SG::WriteHandle<HitContainerType> m_hitColl;
 
+        /// The hit container name
+        std::string m_deadHitCollName;
+
+        /// The hit container handle
+        SG::WriteHandle<HitContainerType> m_deadHitColl;
+
         /// The list of sensitive detectors that I own and manage
         SDList_t m_sdList;
 
@@ -92,6 +98,9 @@ namespace LArG4
 
     }; // class SDWrapper
 
+    template<>
+    void SDWrapper<LArG4CalibSD, CaloCalibrationHitContainer>::EndOfAthenaEvent();
+
   } // namespace detail
 
 
diff --git a/LArCalorimeter/LArG4/LArG4Code/src/CalibSDTool.cc b/LArCalorimeter/LArG4/LArG4Code/src/CalibSDTool.cc
index e47f1ca85952443102acc46155b90cbf87fbf6df..ca06c9878a769161897252cb95f8fc2e7983144d 100644
--- a/LArCalorimeter/LArG4/LArG4Code/src/CalibSDTool.cc
+++ b/LArCalorimeter/LArG4/LArG4Code/src/CalibSDTool.cc
@@ -66,6 +66,8 @@ namespace LArG4
       return StatusCode::FAILURE;
     }
 
+    ATH_CHECK(detStore()->retrieve(m_id_helper));
+
     // No general volume list for SensitiveDetectorBase
     m_noVolumes = true;
 
@@ -104,6 +106,11 @@ namespace LArG4
     auto sd = std::make_unique<LArG4CalibSD>(sdName, calc, m_doPID);
     sd->setupHelpers(m_larEmID, m_larFcalID, m_larHecID, m_larMiniFcalID, m_caloDmID);
 
+    const std::string dead("Dead");
+    if(sdName.find(dead)==std::string::npos) {
+      sd->addDetectorHelper(m_id_helper);
+    }
+
     // Assign the volumes to the SD
     if( assignSD( sd.get(), parsedVolumes ).isFailure() ) {
       // TODO: can I just return NULL here?
diff --git a/LArCalorimeter/LArG4/LArG4Code/src/LArG4CalibSD.cc b/LArCalorimeter/LArG4/LArG4Code/src/LArG4CalibSD.cc
index b27e455aecbb2468038da8d794c0d63877723dc5..f9a7b3a35da70d98a7ea2f69ac8a993836870ed5 100644
--- a/LArCalorimeter/LArG4/LArG4Code/src/LArG4CalibSD.cc
+++ b/LArCalorimeter/LArG4/LArG4Code/src/LArG4CalibSD.cc
@@ -15,7 +15,7 @@
 
 #include "G4RunManager.hh"
 #include "MCTruth/EventInformation.h"
-
+#include "AtlasDetDescr/AtlasDetectorID.h"
 #include "G4Step.hh"
 
 LArG4CalibSD::LArG4CalibSD(G4String a_name, ILArCalibCalculatorSvc* calc, bool doPID)
@@ -28,6 +28,7 @@ LArG4CalibSD::LArG4CalibSD(G4String a_name, ILArCalibCalculatorSvc* calc, bool d
   , m_larHecID (nullptr)
   , m_larMiniFcalID (nullptr)
   , m_caloDmID (nullptr)
+  , m_id_helper (nullptr)
 {}
 
 LArG4CalibSD::~LArG4CalibSD()
@@ -61,10 +62,16 @@ G4bool LArG4CalibSD::ProcessHits(G4Step* a_step,G4TouchableHistory*)
     return false;
   }
 
-  return SimpleHit( identifier , energies );
+  if(m_id_helper) {
+    Identifier id = this->ConvertID( identifier );
+    if(id.is_valid() && m_id_helper->is_lar_dm(id)) {
+      return SimpleHit( identifier, energies, m_deadCalibrationHits );
+    }
+  }
+  return SimpleHit( identifier, energies, m_calibrationHits );
 }
 
-G4bool LArG4CalibSD::SimpleHit( const LArG4Identifier& a_ident , const std::vector<double>& energies ){
+G4bool LArG4CalibSD::SimpleHit( const LArG4Identifier& a_ident , const std::vector<double>& energies, m_calibrationHits_t& calibrationHits ){
 
   // retreive particle ID
   unsigned int particleID = 0;
@@ -100,7 +107,7 @@ G4bool LArG4CalibSD::SimpleHit( const LArG4Identifier& a_ident , const std::vect
   // the existing hit.
       
   // Look for the key in the hitCollection (this is a binary search).
-  auto bookmark = m_calibrationHits.lower_bound(hit);
+  auto bookmark = calibrationHits.lower_bound(hit);
  
   // The lower_bound method of a map finds the first element
   // whose key is not less than the identifier.  If this element
@@ -113,14 +120,14 @@ G4bool LArG4CalibSD::SimpleHit( const LArG4Identifier& a_ident , const std::vect
   // Equals() is a function defined in LArG4Hit.h; it has the value of
   // "true" when a LArG4Hit* points to the same identifier.
     
-  if (bookmark == m_calibrationHits.end() ||
+  if (bookmark == calibrationHits.end() ||
       !(*bookmark)->Equals(hit)) {
     // We haven't had a hit in this readout cell before.  Add it
     // to our set.
-    if (m_calibrationHits.empty() ||
-        bookmark == m_calibrationHits.begin()) {
+    if (calibrationHits.empty() ||
+        bookmark == calibrationHits.begin()) {
       // Insert the hit before the first entry in the map.
-      m_calibrationHits.insert(hit);
+      calibrationHits.insert(hit);
     } else {
       // We'just done a binary search of hitCollection, so we should use
       // the results of that search to speed up the insertion of a new
@@ -130,7 +137,7 @@ G4bool LArG4CalibSD::SimpleHit( const LArG4Identifier& a_ident , const std::vect
       // bookmark.  We therefore want to decrement the bookmark from
       // the lower_bound search.
             
-      m_calibrationHits.insert(--bookmark, hit);
+      calibrationHits.insert(--bookmark, hit);
     }
   } else {
     // Update the existing hit.
@@ -159,24 +166,35 @@ G4bool LArG4CalibSD::SpecialHit(G4Step* a_step,
   // If we can't calculate the identifier, something is wrong.
   if (!(m_calculator->Process( a_step, identifier, vtmp, LArG4::kOnlyID))) return false;
 
-  return SimpleHit( identifier , a_energies );
+  return SimpleHit( identifier , a_energies, m_calibrationHits );
 } 
  
 
-void LArG4CalibSD::EndOfAthenaEvent( CaloCalibrationHitContainer * hitContainer )
+void LArG4CalibSD::EndOfAthenaEvent( CaloCalibrationHitContainer * hitContainer, CaloCalibrationHitContainer * deadHitContainer )
 {
-  // Loop through the hits...
-  for(auto hit : m_calibrationHits)
-  {
-
-    // Because of the design, we are sure this is going into the right hit container
-    // Can we actually do this with move?
-    hitContainer->push_back(hit);
-
-  } // End of loop over hits
-
-  // Clean up    
+  if(verboseLevel>4) {
+    G4cout << "EndOfAthenaEvent: " << SensitiveDetectorName << " m_deadCalibrationHits.size() = " << m_deadCalibrationHits.size() << G4endl;
+  }
+  if(hitContainer) {
+    // Loop through the hits...
+    for(auto hit : m_calibrationHits) {
+      // Because of the design, we are sure this is going into the right hit container
+      // Can we actually do this with move?
+      hitContainer->push_back(hit);
+    } // End of loop over hits
+  }
+  // Clean up
   m_calibrationHits.clear();
+  if(deadHitContainer) {
+    // Loop through the hits...
+    for(auto hit : m_deadCalibrationHits) {
+      // Because of the design, we are sure this is going into the right hit container
+      // Can we actually do this with move?
+      deadHitContainer->push_back(hit);
+    } // End of loop over hits
+  }
+  // Clean up
+  m_deadCalibrationHits.clear();
 }
 
 
diff --git a/LArCalorimeter/LArG4/LArG4Code/src/SDWrapper.cc b/LArCalorimeter/LArG4/LArG4Code/src/SDWrapper.cc
index 0182d8d6325b2e4be1c60efda72048492855fd36..853338cf20ce5ae7bc6ed37fd68b304dd0e5cbe7 100644
--- a/LArCalorimeter/LArG4/LArG4Code/src/SDWrapper.cc
+++ b/LArCalorimeter/LArG4/LArG4Code/src/SDWrapper.cc
@@ -29,10 +29,12 @@ namespace LArG4
     //-------------------------------------------------------------------------
     template<class SDType, class HitContainerType>
     SDWrapper<SDType, HitContainerType>::
-    SDWrapper(const std::string& name, const std::string& hitCollectionName)
+    SDWrapper(const std::string& name, const std::string& hitCollectionName, std::string deadHitCollectionName)
       : G4VSensitiveDetector(name),
         m_hitCollName(hitCollectionName),
-        m_hitColl(hitCollectionName)
+        m_hitColl(hitCollectionName),
+        m_deadHitCollName(deadHitCollectionName),
+        m_deadHitColl(deadHitCollectionName)
     {}
 
     //-------------------------------------------------------------------------
@@ -75,6 +77,13 @@ namespace LArG4
         }
         m_hitColl = CxxUtils::make_unique<HitContainerType>(m_hitCollName);
       }
+      if(!m_deadHitCollName.empty() && !m_deadHitColl.isValid()) {
+        if(verboseLevel >= 5) {
+          G4cout << GetName() << " \tDEBUG\t" << "Initializing hit container: "
+                 << m_deadHitCollName << G4endl;
+        }
+        m_deadHitColl = CxxUtils::make_unique<HitContainerType>(m_deadHitCollName);
+      }
     }
 
     //-------------------------------------------------------------------------
@@ -122,6 +131,45 @@ namespace LArG4
       }
     }
 
+    template<>
+    void SDWrapper<LArG4CalibSD, CaloCalibrationHitContainer>::
+    EndOfAthenaEvent()
+    {
+      if(!m_hitColl.isValid()) {
+        G4cerr << GetName() << " \tERROR\t" << "Hit collection WriteHandle is "
+               << "invalid!" << G4endl;
+        throw std::runtime_error("Invalid hit container WriteHandle: " +
+                                 m_hitColl.name());
+      }
+      CaloCalibrationHitContainer* deadHitCollPtr(nullptr);
+      if(!m_deadHitCollName.empty()) {
+        if(!m_deadHitColl.isValid()) {
+          G4cerr << GetName() << " \tERROR\t" << "Dead Hit collection WriteHandle is "
+               << "invalid!" << G4endl;
+          throw std::runtime_error("Invalid hit container WriteHandle: " +
+                                   m_deadHitColl.name());
+        }
+        deadHitCollPtr = &*m_deadHitColl;
+      }
+      // Loop over each SD and fill the container
+      for(auto& sd : m_sdList) {
+        sd->EndOfAthenaEvent( &*m_hitColl, deadHitCollPtr );
+      }
+      // Gather frozen shower hits
+      if(!m_fastSimSDName.empty()) {
+        auto fastSD = dynamic_cast<LArG4CalibSD*>
+          ( G4SDManager::GetSDMpointer()->FindSensitiveDetector(m_fastSimSDName) );
+        if(fastSD) {
+          fastSD->EndOfAthenaEvent( &*m_hitColl, deadHitCollPtr );
+        }
+        else {
+          G4cerr << GetName() << " \tERROR\t" << "Failed to retrieve/cast "
+                 << m_fastSimSDName << G4endl;
+          throw std::runtime_error("Failed to retrieve/cast " + m_fastSimSDName);
+        }
+      }
+    }
+
     //-------------------------------------------------------------------------
     // Explit template instantiations
     //-------------------------------------------------------------------------
diff --git a/LArCalorimeter/LArG4/LArG4H6SD/src/LArG4H62004CalibSD.cc b/LArCalorimeter/LArG4/LArG4H6SD/src/LArG4H62004CalibSD.cc
index d7aac6723f199849dbc8535c24d8a73f5e47a615..9234cb37862b58104d25b527215058191317ea91 100644
--- a/LArCalorimeter/LArG4/LArG4H6SD/src/LArG4H62004CalibSD.cc
+++ b/LArCalorimeter/LArG4/LArG4H6SD/src/LArG4H62004CalibSD.cc
@@ -51,7 +51,7 @@ G4bool LArG4H62004CalibSD::ProcessHits(G4Step* a_step,G4TouchableHistory* /*ROhi
     }
   }
 
-  bool processed = SimpleHit( ident, energies );
+  bool processed = SimpleHit( ident, energies, m_calibrationHits );
   if(!processed) G4cout<<"LArG4H62004CalibSD name: "<<GetName()<<" failure !!"<<G4endl;
   return true;
 }
@@ -84,6 +84,6 @@ G4bool LArG4H62004CalibSD::SpecialHit(G4Step* a_step,
     }
   }
 
-  bool processed = SimpleHit( ident, a_energies );
+  bool processed = SimpleHit( ident, a_energies, m_calibrationHits );
   return processed;
 }
diff --git a/LArCalorimeter/LArG4/LArG4SD/CMakeLists.txt b/LArCalorimeter/LArG4/LArG4SD/CMakeLists.txt
index a0e41afc27a9c1590e21df202770b4c5b78863f6..6862c144102b12f92bf97298ed764c8dcaa1bf29 100644
--- a/LArCalorimeter/LArG4/LArG4SD/CMakeLists.txt
+++ b/LArCalorimeter/LArG4/LArG4SD/CMakeLists.txt
@@ -19,6 +19,7 @@ find_package( XercesC )
 # Component(s) in the package:
 atlas_add_component( LArG4SD
                      src/*.cc
+                     src/*.cxx
                      src/components/*.cxx
                      INCLUDE_DIRS ${GEANT4_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS}
                      LINK_LIBRARIES ${GEANT4_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} CaloG4SimLib GaudiKernel LArG4Code )
diff --git a/LArCalorimeter/LArG4/LArG4SD/python/LArG4SDConfig.py b/LArCalorimeter/LArG4/LArG4SD/python/LArG4SDConfig.py
index dfcae0fb3abcf5f0259344f399b4204daf4bece0..61260cfb216e0e9f5619fbba8b940775fd86667c 100644
--- a/LArCalorimeter/LArG4/LArG4SD/python/LArG4SDConfig.py
+++ b/LArCalorimeter/LArG4/LArG4SD/python/LArG4SDConfig.py
@@ -115,7 +115,11 @@ def getLArDeadSensitiveDetector(name="LArDeadSensitiveDetector", **kwargs):
     kwargs.setdefault("ParticleID",simFlags.ParticleID())
     kwargs.setdefault("doEscapedEnergy",simFlags.CalibrationRun.get_Value()!='DeadLAr')
     # No effect currently
-    kwargs.setdefault("OutputCollectionNames", ["LArCalibrationHitDeadMaterial"])
+    outputCollectionName = "LArCalibrationHitDeadMaterial"
+    from G4AtlasApps.SimFlags import simFlags
+    if simFlags.CalibrationRun.get_Value() in ['LAr', 'LAr+Tile']:
+        outputCollectionName = "LArCalibrationHitDeadMaterial_DEAD"
+    kwargs.setdefault("HitCollectionName", outputCollectionName)
     return CfgMgr.LArG4__DeadSDTool(name, **kwargs)
 
 def getLArEMBSensitiveDetector(name="LArEMBSensitiveDetector", **kwargs):
@@ -258,3 +262,8 @@ def getLArMiniFCALSensitiveDetector(name="LArMiniFCALSensitiveDetector", **kwarg
 
 def getCalibrationDefaultCalculator(name="CalibrationDefaultCalculator", **kwargs):
     return CfgMgr.LArG4__CalibrationDefaultCalculator(name, **kwargs)
+
+def getDeadMaterialCalibrationHitMerger(name="DeadMaterialCalibrationHitMerger", **kwargs):
+    kwargs.setdefault("InputHits",["LArCalibrationHitDeadMaterial_DEAD","LArCalibrationHitActive_DEAD","LArCalibrationHitInactive_DEAD"])
+    kwargs.setdefault("OutputHits","LArCalibrationHitDeadMaterial")
+    return CfgMgr.LArG4__CalibrationHitMerger(name, **kwargs)
diff --git a/LArCalorimeter/LArG4/LArG4SD/python/LArG4SDConfigDb.py b/LArCalorimeter/LArG4/LArG4SD/python/LArG4SDConfigDb.py
index 952acf3bec8d3118ddb9ac0cf1f807791b55ce57..202821798a4383e08a7abd4189f3517dae9d19c6 100644
--- a/LArCalorimeter/LArG4/LArG4SD/python/LArG4SDConfigDb.py
+++ b/LArCalorimeter/LArG4/LArG4SD/python/LArG4SDConfigDb.py
@@ -1,6 +1,6 @@
 # Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 
-from AthenaCommon.CfgGetter import addTool, addService
+from AthenaCommon.CfgGetter import addTool, addService, addAlgorithm
 addTool("LArG4SD.LArG4SDConfig.getLArActiveSensitiveDetector","LArActiveSensitiveDetector")
 addTool("LArG4SD.LArG4SDConfig.getLArDeadSensitiveDetector","LArDeadSensitiveDetector")
 addTool("LArG4SD.LArG4SDConfig.getLArEMBSensitiveDetector","LArEMBSensitiveDetector")
@@ -11,3 +11,4 @@ addTool("LArG4SD.LArG4SDConfig.getLArInactiveSensitiveDetector","LArInactiveSens
 addTool("LArG4SD.LArG4SDConfig.getLArMiniFCALSensitiveDetector","LArMiniFCALSensitiveDetector")
 
 addService("LArG4SD.LArG4SDConfig.getCalibrationDefaultCalculator","CalibrationDefaultCalculator")
+addAlgorithm("LArG4SD.LArG4SDConfig.getDeadMaterialCalibrationHitMerger","DeadMaterialCalibrationHitMerger")
diff --git a/LArCalorimeter/LArG4/LArG4SD/src/ActiveSDTool.cc b/LArCalorimeter/LArG4/LArG4SD/src/ActiveSDTool.cc
index 0f6372e12c64ac9791a605f80c59dac02ab29f9a..64bb15da0d2307621890e6ce067ab1e5d148c446 100644
--- a/LArCalorimeter/LArG4/LArG4SD/src/ActiveSDTool.cc
+++ b/LArCalorimeter/LArG4/LArG4SD/src/ActiveSDTool.cc
@@ -89,8 +89,9 @@ namespace LArG4
   //---------------------------------------------------------------------------
   G4VSensitiveDetector* ActiveSDTool::makeSD()
   {
+    const std::string deadHitCollName=m_hitCollName+"_DEAD";
     // Create the wrapper
-    auto sdWrapper = new CalibSDWrapper("LArActiveSDWrapper", m_hitCollName);
+    auto sdWrapper = new CalibSDWrapper("LArActiveSDWrapper", m_hitCollName, deadHitCollName);
 
     // Create the SDs.
     sdWrapper->addSD( makeOneSD( "Barrel::Presampler::Module::Calibration", &*m_bpsmodcalc, m_presBarVolumes ) );
diff --git a/LArCalorimeter/LArG4/LArG4SD/src/CalibrationHitMerger.cxx b/LArCalorimeter/LArG4/LArG4SD/src/CalibrationHitMerger.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..720a902a42e1aa0a77f32b84c836ca1ba6017335
--- /dev/null
+++ b/LArCalorimeter/LArG4/LArG4SD/src/CalibrationHitMerger.cxx
@@ -0,0 +1,147 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "CalibrationHitMerger.h"
+
+/** Constructor */
+LArG4::CalibrationHitMerger::CalibrationHitMerger( const std::string& name, ISvcLocator* pSvcLocator ) :
+  ::AthAlgorithm( name, pSvcLocator ),
+  m_inputHitsSGKeys(),
+  m_inputHits(),
+  m_outputHits()
+{
+  // Input collections StoreGate keys
+  declareProperty( "InputHits",    m_inputHitsSGKeys   );
+
+  // Output collections
+  declareProperty( "OutputHits",   m_outputHits        );
+}
+
+
+/** Destructor */
+LArG4::CalibrationHitMerger::~CalibrationHitMerger()
+{}
+
+
+/** Athena Algorithm initialize */
+StatusCode LArG4::CalibrationHitMerger::initialize()
+{
+  ATH_CHECK(setupReadHandleKeyVector(m_inputHitsSGKeys,   m_inputHits  ));
+
+  ATH_CHECK(initializeVarHandleKey(m_outputHits  ));
+
+  return StatusCode::SUCCESS;
+}
+
+
+/** Athena Algorithm execute */
+StatusCode LArG4::CalibrationHitMerger::execute()
+{
+  // skip if not input collection
+  if ( m_inputHits.empty() ) {
+    return StatusCode::SUCCESS;
+  }
+  // TODO: is there a way to conveniently get the total number of hits in all m_inputHits
+  //       and reserve the corresponding size in the outputHandle
+  SG::WriteHandle<CaloCalibrationHitContainer> outputHandle{m_outputHits};
+  ATH_CHECK( outputHandle.record(std::make_unique<CaloCalibrationHitContainer>()) );
+  m_calibrationHits_t calibrationHits;
+  unsigned int nHitsMerged(0);
+  for ( const auto& collKey: m_inputHits ) {
+    SG::ReadHandle<CaloCalibrationHitContainer> inputHandle{collKey};
+    ATH_MSG_DEBUG(inputHandle.name() << " has " << inputHandle->size() << " hits.");
+    for ( const auto& hit: *inputHandle ) {
+      // If we haven't had a hit in this cell before, create one and add
+      // it to the hit collection.
+
+      // If we've had a hit in this cell before, then add the energy to
+      // the existing hit.
+
+      // Look for the key in the hitCollection (this is a binary search).
+      auto bookmark = calibrationHits.lower_bound(hit);
+
+      // The lower_bound method of a map finds the first element
+      // whose key is not less than the identifier.  If this element
+      // == our hit, we've found a match.
+
+      // Reminders:
+      // bookmark = iterator (pointer) into the hitCollection set.
+      // (*bookmark) = a member of the set, which is a LArG4Hit*.
+
+      // Equals() is a function defined in LArG4Hit.h; it has the value of
+      // "true" when a LArG4Hit* points to the same identifier.
+
+      if (bookmark == calibrationHits.end() ||
+          !(*bookmark)->Equals(hit)) {
+        auto&& hitCopy = std::make_unique<CaloCalibrationHit>(*hit);
+        // We haven't had a hit in this readout cell before.  Add it
+        // to our set.
+        if (calibrationHits.empty() ||
+            bookmark == calibrationHits.begin()) {
+          // Insert the hit before the first entry in the map.
+          calibrationHits.insert(hitCopy.release());
+        } else {
+          // We'just done a binary search of hitCollection, so we should use
+          // the results of that search to speed up the insertion of a new
+          // hit into the map.  The "insert" method is faster if the new
+          // entry is right _after_ the bookmark.  If we left bookmark
+          // unchanged, the new entry would go right _before_ the
+          // bookmark.  We therefore want to decrement the bookmark from
+          // the lower_bound search.
+          calibrationHits.insert(--bookmark, hitCopy.release());
+        }
+      } else {
+        ++nHitsMerged;
+        // Update the existing hit.
+        (*bookmark)->Add(hit);
+      }
+    }
+  }
+
+  // Loop through the hits...
+  for(auto hit : calibrationHits)
+  {
+    // Can we actually do this with move?
+    outputHandle->push_back(hit);
+  } // End of loop over hits
+  // Clean up
+  calibrationHits.clear();
+  ATH_MSG_DEBUG(outputHandle.name() << " has " << outputHandle->size() << " hits. Merged " << nHitsMerged << " hits.");
+  return StatusCode::SUCCESS;
+}
+
+
+/** Athena Algorithm finalize */
+StatusCode LArG4::CalibrationHitMerger::finalize()
+{
+  return StatusCode::SUCCESS;
+}
+
+/** Initialize the given VarHandleKey */
+StatusCode LArG4::CalibrationHitMerger::initializeVarHandleKey( SG::VarHandleKey& varHandleKey ) const {
+  if ( varHandleKey.key().empty() )
+    return StatusCode::SUCCESS;
+
+  return varHandleKey.initialize();
+}
+/** Setup a vector of ReadHandleKeys for the given vector of string StoreGate Keys */
+StatusCode LArG4::CalibrationHitMerger::setupReadHandleKeyVector( const SGKeyVector_t&      sgKeyVec,
+                                                                ReadHandleKeyVector_t& readHandleVec ) const {
+  readHandleVec.reserve( sgKeyVec.size() );
+
+  // convert string StoreGate key to ReadHandleKey
+  for ( const auto& sgKey: sgKeyVec ) {
+    readHandleVec.emplace_back( sgKey );
+  }
+
+  // initialize all ReadHandleKeys
+  for ( auto& readHandleKey: readHandleVec ) {
+    if ( readHandleKey.initialize().isFailure() ) {
+      return StatusCode::FAILURE;
+    }
+  }
+
+  return StatusCode::SUCCESS;
+}
+
diff --git a/LArCalorimeter/LArG4/LArG4SD/src/CalibrationHitMerger.h b/LArCalorimeter/LArG4/LArG4SD/src/CalibrationHitMerger.h
new file mode 100644
index 0000000000000000000000000000000000000000..1b0feea4a5a44607f38599f3e1511d30071a3809
--- /dev/null
+++ b/LArCalorimeter/LArG4/LArG4SD/src/CalibrationHitMerger.h
@@ -0,0 +1,73 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef LARG4SD_CALIBRATIONHITMERGER_H
+#define LARG4SD_CALIBRATIONHITMERGER_H 1
+
+// STL includes
+#include <set>
+#include <string>
+#include <vector>
+
+// Framework includes
+#include "AthenaBaseComps/AthAlgorithm.h"
+#include "StoreGate/WriteHandleKey.h"
+#include "CaloSimEvent/CaloCalibrationHitContainer.h"
+
+namespace LArG4 {
+
+  /** @class CalibrationHitMerger
+
+      @brief Athena Algorithm that merges a given set of CaloCalibrationHitContainers into a single CaloCalibrationHitContainers - based on CollectionMerger by Elmar Ritsch.
+
+     */
+  class CalibrationHitMerger final : public AthAlgorithm {
+
+  public:
+    /** Constructor */
+    CalibrationHitMerger( const std::string& name, ISvcLocator* pSvcLocator );
+
+    /** Destructor */
+    virtual ~CalibrationHitMerger();
+
+    /** Athena algorithm's interface methods */
+    virtual StatusCode  initialize() override final;
+    virtual StatusCode  execute()    override final;
+    virtual StatusCode  finalize()   override final;
+
+  private:
+    class LessHit {
+    public:
+      bool operator() ( CaloCalibrationHit* const& p, CaloCalibrationHit* const& q ) const
+      {
+        return p->Less(q);
+      }
+    };
+    typedef std::set< CaloCalibrationHit*, LessHit >  m_calibrationHits_t;
+
+    /** Initialize the given VarHandleKey */
+    StatusCode initializeVarHandleKey( SG::VarHandleKey& varHandleKey ) const;
+
+    /** Commonly used member and function parameter types */
+    typedef std::vector<std::string>  SGKeyVector_t;
+    typedef std::vector<SG::ReadHandleKey<CaloCalibrationHitContainer>> ReadHandleKeyVector_t;
+
+
+    /** Setup a vector of ReadHandleKeys for the given vector of string StoreGate Keys */
+    StatusCode setupReadHandleKeyVector( const SGKeyVector_t&      sgKeyVec,
+                                         ReadHandleKeyVector_t& readHandleVec ) const;
+
+    /** Input collection StoreGate keys */
+    SGKeyVector_t m_inputHitsSGKeys;
+
+    /** Input collection ReadHandleKeys */
+    ReadHandleKeyVector_t m_inputHits;
+
+    /** Output collection WriteHandleKeys */
+    SG::WriteHandleKey<CaloCalibrationHitContainer> m_outputHits;
+  };
+
+}
+
+#endif //> !LARG4SD_CALIBRATIONHITMERGER_H
diff --git a/LArCalorimeter/LArG4/LArG4SD/src/InactiveSDTool.cc b/LArCalorimeter/LArG4/LArG4SD/src/InactiveSDTool.cc
index f874ed97b7a99a1ef01286e25084058e177202c4..24b1c53ea9fd833a6be2ffdcb38f6a358aeeebdf 100644
--- a/LArCalorimeter/LArG4/LArG4SD/src/InactiveSDTool.cc
+++ b/LArCalorimeter/LArG4/LArG4SD/src/InactiveSDTool.cc
@@ -84,8 +84,9 @@ namespace LArG4
   //---------------------------------------------------------------------------
   G4VSensitiveDetector* InactiveSDTool::makeSD()
   {
+    const std::string deadHitCollName=m_hitCollName+"_DEAD";
     // Create the wrapper
-    auto sdWrapper = new CalibSDWrapper("LArInactiveSDWrapper", m_hitCollName);
+    auto sdWrapper = new CalibSDWrapper("LArInactiveSDWrapper", m_hitCollName, deadHitCollName);
 
     sdWrapper->addSD(
       makeOneSD("LAr::Barrel::Presampler::Inactive", &*m_embpscalc, m_barPreVolumes)
diff --git a/LArCalorimeter/LArG4/LArG4SD/src/components/LArG4SD_entries.cxx b/LArCalorimeter/LArG4/LArG4SD/src/components/LArG4SD_entries.cxx
index f139ae9711804631f270c3ee71155cc5da4e9c11..5b3d73eb9c35d39bde2be2b0bba90259a58c8b12 100644
--- a/LArCalorimeter/LArG4/LArG4SD/src/components/LArG4SD_entries.cxx
+++ b/LArCalorimeter/LArG4/LArG4SD/src/components/LArG4SD_entries.cxx
@@ -9,6 +9,7 @@
 #include "../DeadSDTool.h"
 
 #include "../CalibrationDefaultCalculator.h"
+#include "../CalibrationHitMerger.h"
 
 DECLARE_COMPONENT( LArG4::EMBSDTool )
 DECLARE_COMPONENT( LArG4::EMECSDTool )
@@ -20,4 +21,4 @@ DECLARE_COMPONENT( LArG4::InactiveSDTool )
 DECLARE_COMPONENT( LArG4::DeadSDTool )
 
 DECLARE_COMPONENT( LArG4::CalibrationDefaultCalculator )
-
+DECLARE_COMPONENT( LArG4::CalibrationHitMerger )