diff --git a/Simulation/G4Utilities/MCTruthSimAlgs/CMakeLists.txt b/Simulation/G4Utilities/MCTruthSimAlgs/CMakeLists.txt
index d6f3d8278e57b0c7d2c42b2d0b6e03ea3f0ee5bc..31f6cc252a2c3264f04b8d8a5a1d36d4d7f5904e 100644
--- a/Simulation/G4Utilities/MCTruthSimAlgs/CMakeLists.txt
+++ b/Simulation/G4Utilities/MCTruthSimAlgs/CMakeLists.txt
@@ -8,9 +8,9 @@ atlas_subdir( MCTruthSimAlgs )
 # Declare the package's dependencies:
 atlas_depends_on_subdirs( PRIVATE
                           Calorimeter/CaloSimEvent
-                          Control/AthToolSupport/AsgTools
                           Control/AthenaBaseComps
                           Control/AthenaKernel
+                          Control/CxxUtils
                           Control/PileUpTools
                           Control/StoreGate
                           Event/xAOD/xAODJet
@@ -18,7 +18,6 @@ atlas_depends_on_subdirs( PRIVATE
                           Generators/GeneratorObjects
                           Generators/TruthUtils
                           MuonSpectrometer/MuonSimEvent
-                          Reconstruction/Jet/JetInterface
                           Reconstruction/RecEvent
                           Simulation/G4Sim/TrackRecord )
 
@@ -27,7 +26,7 @@ atlas_add_component( MCTruthSimAlgs
                      src/*.cxx
                      src/components/MCTruthSimAlgs_entries.cxx
                      src/components/MCTruthSimAlgs_load.cxx
-                     LINK_LIBRARIES CaloSimEvent AsgTools AthenaBaseComps AthenaKernel PileUpToolsLib StoreGateLib SGtests xAODJet GaudiKernel GeneratorObjects TruthUtils MuonSimEvent JetInterface RecEvent )
+                     LINK_LIBRARIES CaloSimEvent AthenaBaseComps AthenaKernel CxxUtils PileUpToolsLib StoreGateLib SGtests xAODJet GaudiKernel GeneratorObjects TruthUtils MuonSimEvent RecEvent )
 
 # Install files from the package:
 atlas_install_python_modules( python/*.py )
diff --git a/Simulation/G4Utilities/MCTruthSimAlgs/cmt/requirements b/Simulation/G4Utilities/MCTruthSimAlgs/cmt/requirements
index ee14106037e1867b3b5eca383f650bdd1861dfb0..ec5a0d479197ada63f662ab27dbe1c0c4c6a5dde 100644
--- a/Simulation/G4Utilities/MCTruthSimAlgs/cmt/requirements
+++ b/Simulation/G4Utilities/MCTruthSimAlgs/cmt/requirements
@@ -4,13 +4,12 @@ author Davide Costanzo
 use AtlasPolicy         AtlasPolicy-*
 
 private
-use AsgTools            AsgTools-*          Control/AthToolSupport
 use AthenaBaseComps     AthenaBaseComps-*   Control
 use AthenaKernel        AthenaKernel-*      Control
 use CaloSimEvent        CaloSimEvent-*      Calorimeter
+use CxxUtils            CxxUtils-*          Control
 use GaudiInterface      GaudiInterface-*    External
 use GeneratorObjects    GeneratorObjects-*  Generators
-use JetInterface        JetInterface-*      Reconstruction/Jet
 use MuonSimEvent        MuonSimEvent-*      MuonSpectrometer
 use PileUpTools         PileUpTools-*       Control
 use RecEvent            RecEvent-*          Reconstruction
diff --git a/Simulation/G4Utilities/MCTruthSimAlgs/python/MCTruthSimAlgsConfig.py b/Simulation/G4Utilities/MCTruthSimAlgs/python/MCTruthSimAlgsConfig.py
index 938bd1f7e3451b90308253089962f7b5c9b0332e..5925e2f81de734ebf5ee8330aa08bd2e22f00678 100644
--- a/Simulation/G4Utilities/MCTruthSimAlgs/python/MCTruthSimAlgsConfig.py
+++ b/Simulation/G4Utilities/MCTruthSimAlgs/python/MCTruthSimAlgsConfig.py
@@ -69,14 +69,16 @@ def getTruthJetRange(name="TruthJetRange", **kwargs):
     return CfgMgr.PileUpXingFolder(name, **kwargs)
 
 
-def MergeTruthJetsTool(name="MergeTruthJetsTool", **kwargs):
+def getMergeTruthJetsTool(name="MergeTruthJetsTool", **kwargs):
     if digitizationFlags.doXingByXingPileUp(): # PileUpTool approach
         kwargs.setdefault("FirstXing", TruthJet_FirstXing() )
         kwargs.setdefault("LastXing",  TruthJet_LastXing() )
-    #kwargs.setdefault("OutputLevel",  1 )
-
     return CfgMgr.MergeTruthJetsTool(name, **kwargs)
 
+def getMergeTruthJetsFilterTool(name="MergeTruthJetsFilterTool", **kwargs):
+    kwargs.setdefault("ActivateFilter", True )
+    return getMergeTruthJetsTool(name, **kwargs)
+
 
 ############################################################################
 
diff --git a/Simulation/G4Utilities/MCTruthSimAlgs/python/MCTruthSimAlgsConfigDb.py b/Simulation/G4Utilities/MCTruthSimAlgs/python/MCTruthSimAlgsConfigDb.py
index 428a0762e2a311349d33785cebde3fd6ac669605..300342cd2c2ceb6c3ba29fceb90c2976d78cf5e2 100644
--- a/Simulation/G4Utilities/MCTruthSimAlgs/python/MCTruthSimAlgsConfigDb.py
+++ b/Simulation/G4Utilities/MCTruthSimAlgs/python/MCTruthSimAlgsConfigDb.py
@@ -10,7 +10,8 @@ addTool("MCTruthSimAlgs.MCTruthSimAlgsConfig.getCalibRange"                  , "
 addTool("MCTruthSimAlgs.MCTruthSimAlgsConfig.MergeCalibHitsTool"             , "MergeCalibHitsTool")
 
 addTool("MCTruthSimAlgs.MCTruthSimAlgsConfig.getTruthJetRange"               , "TruthJetRange")
-addTool("MCTruthSimAlgs.MCTruthSimAlgsConfig.MergeTruthJetsTool"             , "MergeTruthJetsTool")
+addTool("MCTruthSimAlgs.MCTruthSimAlgsConfig.getMergeTruthJetsTool"          , "MergeTruthJetsTool")
+addTool("MCTruthSimAlgs.MCTruthSimAlgsConfig.getMergeTruthJetsFilterTool"    , "MergeTruthJetsFilterTool")
 
 addTool("MCTruthSimAlgs.MCTruthSimAlgsConfig.getTimingObjRange"              , "TimingObjRange")
 addTool("MCTruthSimAlgs.MCTruthSimAlgsConfig.MergeRecoTimingObjTool"         , "MergeRecoTimingObjTool")
diff --git a/Simulation/G4Utilities/MCTruthSimAlgs/src/MergeHijingParsTool.cxx b/Simulation/G4Utilities/MCTruthSimAlgs/src/MergeHijingParsTool.cxx
index 8f64383208d241c386d7dbbf1eccc721d5087d57..908ef04adb997f8fd33e1d60c97faca25daf96c2 100644
--- a/Simulation/G4Utilities/MCTruthSimAlgs/src/MergeHijingParsTool.cxx
+++ b/Simulation/G4Utilities/MCTruthSimAlgs/src/MergeHijingParsTool.cxx
@@ -4,76 +4,92 @@
 
 #include "MergeHijingParsTool.h"
 
-#include "AthenaKernel/errorcheck.h"
-#include "GeneratorObjects/HijingEventParams.h"
 #include "PileUpTools/PileUpMergeSvc.h"
 #include "StoreGate/StoreGateSvc.h"
+#include "CxxUtils/make_unique.h"
 
 MergeHijingParsTool::MergeHijingParsTool(const std::string& type,
                                          const std::string& name,
                                          const IInterface* parent) :
   PileUpToolBase(type, name, parent),
   m_pMergeSvc("PileUpMergeSvc", name),
-  m_key("Hijing_event_params"),
+  m_outputObject("Hijing_event_params"),
   m_firstSubEvent(true)
 {
   declareInterface<IPileUpTool>(this);
-  declareProperty("HijingParamsKey", m_key=std::string("Hijing_event_params"));
+  declareProperty("HijingParamsKey", m_outputObject, "");
 }
 
 StatusCode MergeHijingParsTool::prepareEvent(unsigned int nInputEvents) {
-  ATH_MSG_DEBUG ( "Calling prepareEvent(): " << name() << " - package version " << PACKAGE_VERSION );
+  ATH_MSG_VERBOSE ( "Calling prepareEvent(): " << name() << " - package version " << PACKAGE_VERSION );
   ATH_MSG_DEBUG( "prepareEvent: there are " << nInputEvents << " subevents in this event.");
   m_firstSubEvent=true;
   return StatusCode::SUCCESS;
 }
 
-StatusCode MergeHijingParsTool::processBunchXing(int bunchXing,
-                                                SubEventIterator bSubEvents,
-                                                SubEventIterator eSubEvents)
+StatusCode MergeHijingParsTool::processBunchXing(int,
+                                                 SubEventIterator bSubEvents,
+                                                 SubEventIterator eSubEvents)
 {
   ATH_MSG_VERBOSE ( "processBunchXing()" );
-  //We are only interested in the HijingEventParams for the original event
-  if(m_firstSubEvent && bunchXing==0) {
-    if (bSubEvents != eSubEvents) {
+  if(m_outputObject.isValid())
+    {
+      ATH_MSG_VERBOSE("Already written out a HijingEventParams for the current signal event.");
+      return StatusCode::SUCCESS;
+    }
+  SubEventIterator iEvt = bSubEvents;
+  for (; iEvt!=eSubEvents; iEvt++)
+    {
       StoreGateSvc& seStore(*bSubEvents->ptr()->evtStore());
-      const HijingEventParams *hijing_pars(0);
-      if (seStore.retrieve(hijing_pars, m_key.value()).isSuccess()) {
+      if (seStore.contains<HijingEventParams>(m_outputObject.name()))
+        {
+          const HijingEventParams *hijing_pars(nullptr);
+          ATH_CHECK(seStore.retrieve(hijing_pars, m_outputObject.name()));
+          // create new container for overlayed event
+          m_outputObject = CxxUtils::make_unique<HijingEventParams>(hijing_pars->get_np(),
+                                                                    hijing_pars->get_nt(),
+                                                                    hijing_pars->get_n0(),
+                                                                    hijing_pars->get_n01(),
+                                                                    hijing_pars->get_n10(),
+                                                                    hijing_pars->get_n11(),
+                                                                    hijing_pars->get_natt(),
+                                                                    hijing_pars->get_jatt(),
+                                                                    hijing_pars->get_b(),
+                                                                    hijing_pars->get_bphi());
+          // FIXME Why is there no copy constructor for this class?!
+          // add in setting Psi angles manually.
+          for(int n=1;n<7;++n)
+            {
+              m_outputObject->set_psi(n,hijing_pars->get_psi(n));
+            }
 
-        // create new container for overlayed event
-        HijingEventParams* newContainer = new HijingEventParams(hijing_pars->get_np(),
-                                                                hijing_pars->get_nt(),
-                                                                hijing_pars->get_n0(),
-                                                                hijing_pars->get_n01(),
-                                                                hijing_pars->get_n10(),
-                                                                hijing_pars->get_n11(),
-                                                                hijing_pars->get_natt(),
-                                                                hijing_pars->get_jatt(),
-                                                                hijing_pars->get_b(),
-                                                                hijing_pars->get_bphi());
-
-        // record new container in overlayed event
-        if (!(evtStore()->record(newContainer,m_key.value()).isSuccess())) {
-          ATH_MSG_ERROR ( " Cannot record new HijingEventParams in overlayed event " );
-          return StatusCode::FAILURE;
+          if(m_firstSubEvent)
+            {
+              ATH_MSG_DEBUG( "processBunchXing: copied original event HijingEventParams" );
+            }
+          else
+            {
+              ATH_MSG_DEBUG( "processBunchXing: copied background event HijingEventParams" );
+            }
+          return StatusCode::SUCCESS;
+        }
+      if(m_firstSubEvent)
+        {
+          ATH_MSG_VERBOSE("processBunchXing: No HijingEventParams found in the signal eventStore." );
+          m_firstSubEvent=false;
         }
-
-        ATH_MSG_DEBUG( "processBunchXing: copied original event HijingEventParams" );
-        m_firstSubEvent=false;
-      }
-      else {
-        ATH_MSG_ERROR ( "processBunchXing: No HijingEventParams found in the signal eventStore." );
-      }
-    }
-    else {
-      ATH_MSG_ERROR ( "processBunchXing: No events found." );
     }
-  }
-
   return StatusCode::SUCCESS;
 }
-StatusCode MergeHijingParsTool::mergeEvent() {
-  //Nothing to do here;
+
+StatusCode MergeHijingParsTool::mergeEvent()
+{
+  //Double check that something was found.
+  if(!m_outputObject.isValid())
+    {
+      ATH_MSG_ERROR ( "mergeEvent: No HijingEventParams found in the signal or background eventStores." );
+      return StatusCode::FAILURE;
+    }
   return StatusCode::SUCCESS;
 }
 
@@ -85,45 +101,46 @@ bool MergeHijingParsTool::toProcess(int bunchXing) const {
 
 StatusCode MergeHijingParsTool::processAllSubEvents() {
   ATH_MSG_VERBOSE ( "processAllSubEvents()" );
-  if(!m_pMergeSvc) {
-    if (!(m_pMergeSvc.retrieve()).isSuccess()) {
-      ATH_MSG_FATAL ( "processAllSubEvents: Could not find PileUpMergeSvc" );
-      return StatusCode::FAILURE;
+  if(!m_pMergeSvc)
+    {
+      ATH_CHECK(m_pMergeSvc.retrieve());
     }
-  }
-
   typedef PileUpMergeSvc::TimedList<HijingEventParams>::type TimedHijingParamsList;
   TimedHijingParamsList HijingList;
   const HijingEventParams *hijing_pars(0);
-  if (!(m_pMergeSvc->retrieveSubEvtsData(m_key.value(), HijingList).isSuccess())
+  if (!(m_pMergeSvc->retrieveSubEvtsData(m_outputObject.name(), HijingList).isSuccess())
       || HijingList.size()==0) {
     ATH_MSG_INFO ( " Cannot find HijingEventParams from PileUp service " );
     return StatusCode::SUCCESS;
   }
-  else {
-    ATH_MSG_INFO ( " HijingEventParams found from PileUp service " );
-    TimedHijingParamsList::iterator firstHijing(HijingList.begin());
-    // assume only 1 Hijing event in pileup
-    hijing_pars = firstHijing->second;
-  }
-
-  // create new container for overlayed event
-  HijingEventParams* newContainer = new HijingEventParams(hijing_pars->get_np(),
-                                                          hijing_pars->get_nt(),
-                                                          hijing_pars->get_n0(),
-                                                          hijing_pars->get_n01(),
-                                                          hijing_pars->get_n10(),
-                                                          hijing_pars->get_n11(),
-                                                          hijing_pars->get_natt(),
-                                                          hijing_pars->get_jatt(),
-                                                          hijing_pars->get_b(),
-                                                          hijing_pars->get_bphi());
-
-  // record new container in overlayed event
-  if (!(evtStore()->record(newContainer,m_key.value()).isSuccess())) {
-    ATH_MSG_ERROR ( " Cannot record new HijingEventParams in overlayed event " );
-    return StatusCode::FAILURE;
-  }
-
+  ATH_MSG_DEBUG ( " HijingEventParams found from PileUp service " );
+  for (const auto& hijingParams: HijingList)
+    {
+      hijing_pars = hijingParams.second;
+      // create new container for overlayed event
+      m_outputObject = CxxUtils::make_unique<HijingEventParams>(hijing_pars->get_np(),
+                                                                hijing_pars->get_nt(),
+                                                                hijing_pars->get_n0(),
+                                                                hijing_pars->get_n01(),
+                                                                hijing_pars->get_n10(),
+                                                                hijing_pars->get_n11(),
+                                                                hijing_pars->get_natt(),
+                                                                hijing_pars->get_jatt(),
+                                                                hijing_pars->get_b(),
+                                                                hijing_pars->get_bphi());
+      // FIXME Why is there no copy constructor for this class?!
+      // add in setting Psi angles manually.
+      for(int n=1;n<7;++n)
+        {
+          m_outputObject->set_psi(n,hijing_pars->get_psi(n));
+        }
+      break;
+    }
+  //Double check that something was found.
+  if(!m_outputObject.isValid())
+    {
+      ATH_MSG_ERROR( "processAllSubEvents: No HijingEventParams found in the signal or background eventStores." );
+      return StatusCode::FAILURE;
+    }
   return StatusCode::SUCCESS;
 }
diff --git a/Simulation/G4Utilities/MCTruthSimAlgs/src/MergeHijingParsTool.h b/Simulation/G4Utilities/MCTruthSimAlgs/src/MergeHijingParsTool.h
index 9cc5658d6b11f345d12fde6093c106c9d1a323c2..b1c526c8ee4922afe68dae9612d45c23aed49a9c 100644
--- a/Simulation/G4Utilities/MCTruthSimAlgs/src/MergeHijingParsTool.h
+++ b/Simulation/G4Utilities/MCTruthSimAlgs/src/MergeHijingParsTool.h
@@ -7,7 +7,9 @@
 
 #include "PileUpTools/PileUpToolBase.h"
 
-#include "GaudiKernel/Property.h"
+#include "GeneratorObjects/HijingEventParams.h"
+#include "StoreGate/WriteHandle.h"
+
 #include "GaudiKernel/ServiceHandle.h"
 
 #include <string>
@@ -46,7 +48,7 @@ public:
   virtual StatusCode processAllSubEvents() override final;
 private:
   ServiceHandle<PileUpMergeSvc> m_pMergeSvc;
-  StringProperty m_key;
+  SG::WriteHandle<HijingEventParams> m_outputObject;
   bool m_firstSubEvent;
 };
 #endif //MCTRUTHSIMALGS_MERGEHIJINGPARSTOOL_H
diff --git a/Simulation/G4Utilities/MCTruthSimAlgs/src/MergeMcEventCollTool.cxx b/Simulation/G4Utilities/MCTruthSimAlgs/src/MergeMcEventCollTool.cxx
index 2dc584cbe8fde14c2b6e46997da4a7acf97d0cf4..cff6982cf28c37085982048a0747e24436264c92 100644
--- a/Simulation/G4Utilities/MCTruthSimAlgs/src/MergeMcEventCollTool.cxx
+++ b/Simulation/G4Utilities/MCTruthSimAlgs/src/MergeMcEventCollTool.cxx
@@ -190,7 +190,7 @@ StatusCode MergeMcEventCollTool::prepareEvent(unsigned int nInputEvents) {
     msg(MSG::ERROR)
       << "prepareEvent: TimedTruthList with key "
       << m_truthCollKey.value()
-      << " is empty" << endreq;
+      << " is empty" << endmsg;
     return StatusCode::RECOVERABLE;
   }
   ATH_MSG_DEBUG( "prepareEvent: there are " << m_nInputMcEventColls << " subevents in this event.");
@@ -214,7 +214,7 @@ StatusCode MergeMcEventCollTool::processAllSubEvents() {
   if (!m_pMergeSvc->retrieveSubEvtsData(m_truthCollKey.value(), truthList).isSuccess() ) {
     msg(MSG::ERROR)
       << "execute: Can not find TimedTruthList with key "
-      << m_truthCollKey.value() << endreq;
+      << m_truthCollKey.value() << endmsg;
     return StatusCode::RECOVERABLE;;
   }
 
@@ -227,7 +227,7 @@ StatusCode MergeMcEventCollTool::processAllSubEvents() {
     msg(MSG::ERROR)
       << "execute: TimedTruthList with key "
       << m_truthCollKey.value()
-      << " is empty" << endreq;
+      << " is empty" << endmsg;
     return StatusCode::RECOVERABLE;
   }
   ATH_MSG_DEBUG( "execute: there are " << m_nInputMcEventColls << " subevents in this event.");
@@ -452,9 +452,20 @@ StatusCode MergeMcEventCollTool::processEvent(const McEventCollection *pMcEvtCol
   return StatusCode::FAILURE;
 }
 
+StatusCode MergeMcEventCollTool::saveHeavyIonInfo(const McEventCollection *pMcEvtColl)
+{
+  if (m_pOvrlMcEvColl->at(0)->heavy_ion()) return StatusCode::SUCCESS;
+  if (pMcEvtColl->at(0)->heavy_ion())
+    {
+      m_pOvrlMcEvColl->at(0)->set_heavy_ion(*(pMcEvtColl->at(0)->heavy_ion()));
+    }
+  return StatusCode::SUCCESS;
+}
+
 StatusCode MergeMcEventCollTool::processTruthFilteredEvent(const McEventCollection *pMcEvtColl, const double currentEventTime, const int currentBkgEventIndex) {
   //insert the GenEvent into the overlay McEventCollection.
   ATH_MSG_VERBOSE ( "processTruthFilteredEvent()" );
+  ATH_CHECK(this->saveHeavyIonInfo(pMcEvtColl));
   m_pOvrlMcEvColl->at(m_startingIndexForBackground+m_nBkgEventsReadSoFar)=new HepMC::GenEvent(**(pMcEvtColl->begin()));
   HepMC::GenEvent& currentBackgroundEvent(*(m_pOvrlMcEvColl->at(m_startingIndexForBackground+m_nBkgEventsReadSoFar)));
   currentBackgroundEvent.set_event_number(currentBkgEventIndex);
@@ -470,7 +481,8 @@ StatusCode MergeMcEventCollTool::processTruthFilteredEvent(const McEventCollecti
 
 StatusCode MergeMcEventCollTool::processUnfilteredEvent(const McEventCollection *pMcEvtColl, const double currentEventTime, const int currentBkgEventIndex) {
   ATH_MSG_VERBOSE ( "processUnfilteredEvent()" );
-  HepMC::GenEvent& currentBackgroundEvent(**(pMcEvtColl->begin()));         //background event
+  ATH_CHECK(this->saveHeavyIonInfo(pMcEvtColl));
+  const HepMC::GenEvent& currentBackgroundEvent(**(pMcEvtColl->begin()));         //background event
   //handle the slimming case
   //ATH_MSG_VERBOSE( "The MB Event Number is " << currentBkgEventIndex << ". m_nBkgEventsReadSoFar = " << m_nBkgEventsReadSoFar );
   HepMC::GenVertex *pCopyOfGenVertex(NULL);
@@ -481,8 +493,8 @@ StatusCode MergeMcEventCollTool::processUnfilteredEvent(const McEventCollection
 
   unsigned int nCollisionVerticesFound(0);
   //loop over vertices in Background GenEvent
-  HepMC::GenEvent::vertex_iterator currentVertexIter(currentBackgroundEvent.vertices_begin());
-  const HepMC::GenEvent::vertex_iterator endOfCurrentListOfVertices(currentBackgroundEvent.vertices_end());
+  HepMC::GenEvent::vertex_const_iterator currentVertexIter(currentBackgroundEvent.vertices_begin());
+  const HepMC::GenEvent::vertex_const_iterator endOfCurrentListOfVertices(currentBackgroundEvent.vertices_end());
   ATH_MSG_VERBOSE( "Starting a vertex loop ... " );
   //cout << "Starting a vertex loop ... " <<endl;
   for (; currentVertexIter != endOfCurrentListOfVertices; ++currentVertexIter) {
diff --git a/Simulation/G4Utilities/MCTruthSimAlgs/src/MergeMcEventCollTool.h b/Simulation/G4Utilities/MCTruthSimAlgs/src/MergeMcEventCollTool.h
index 4b2ea4697d404d97ea68e1ad59fa0da1c5a89684..c919cb63046eb8d85343c65d7afdb267ea4858e4 100755
--- a/Simulation/G4Utilities/MCTruthSimAlgs/src/MergeMcEventCollTool.h
+++ b/Simulation/G4Utilities/MCTruthSimAlgs/src/MergeMcEventCollTool.h
@@ -64,6 +64,8 @@ private:
   StatusCode compressOutputMcEventCollection();
   //** Print out detailed debug info if required.
   void printDetailsOfMergedMcEventCollection() const;
+  //** Ensure that any GenEvent::HeavyIon info is stored in the signal GenEvent.
+  StatusCode saveHeavyIonInfo(const McEventCollection *pMcEvtColl);
 
   //** Handle for the PileUpMergeSvc (provides input McEventCollections)
   ServiceHandle<PileUpMergeSvc> m_pMergeSvc;
diff --git a/Simulation/G4Utilities/MCTruthSimAlgs/src/MergeTruthJetsTool.cxx b/Simulation/G4Utilities/MCTruthSimAlgs/src/MergeTruthJetsTool.cxx
index 13d58425900ed4cf2c70c1013b5729ac0067a14f..f95689a1a4229d22e0b38cf79a377c245b7e73da 100644
--- a/Simulation/G4Utilities/MCTruthSimAlgs/src/MergeTruthJetsTool.cxx
+++ b/Simulation/G4Utilities/MCTruthSimAlgs/src/MergeTruthJetsTool.cxx
@@ -13,24 +13,29 @@
 
 MergeTruthJetsTool::MergeTruthJetsTool(const std::string& type,
                                        const std::string& name,
-                                       const IInterface* parent) :
-  PileUpToolBase(type, name, parent),m_intool(""),
-  m_pMergeSvc("PileUpMergeSvc", name),
-  m_inTimeOutputJetContainer(NULL),
-  m_outOfTimeOutputJetContainer(NULL),
-  m_first_event(true),
-  m_signal_max_pT(-1.),
-  m_pileup_max_pT(-1.)
+                                       const IInterface* parent)
+  : PileUpToolBase(type, name, parent)
+  , m_pMergeSvc("PileUpMergeSvc", name)
+  , m_inTimeOutputJetContainer(nullptr)
+  , m_outOfTimeOutputJetContainer(nullptr)
+  , m_inputJetCollKey("AntiKt4TruthJets")
+  , m_inTimeOutputJetCollKey("InTimeAntiKt4TruthJets")
+  , m_outOfTimeOutputJetCollKey("OutOfTimeAntiKt4TruthJets")
+  , m_inTimePtCut(10.0*Gaudi::Units::GeV)
+  , m_outOfTimePtCut(15.0*Gaudi::Units::GeV)
+  , m_activateFilter(false)
+  , m_includeSignalJets(false)
+  , m_signal_max_pT(-1.)
+  , m_pileup_max_pT(-1.)
 {
   declareInterface<IPileUpTool>(this);
-  declareProperty("InputTool", m_intool);
-  declareProperty("InputTruthJetCollKey", m_inputJetCollKey="AntiKt4TruthJets");
-  declareProperty("InTimeOutputTruthJetCollKey", m_inTimeOutputJetCollKey="InTimeAntiKt4TruthJets");
-  declareProperty("OutOfTimeTruthJetCollKey", m_outOfTimeOutputJetCollKey="OutOfTimeAntiKt4TruthJets");
-  declareProperty("InTimePtCut", m_inTimePtCut=10.0*Gaudi::Units::GeV);
-  declareProperty("OutOfTimePtCut", m_outOfTimePtCut=15.0*Gaudi::Units::GeV);
-  declareProperty("VetoOnInTime", m_vetoOnInTime=false);
-  declareProperty("IncludeSignalJets", m_includeSignalJets=false, "Include signal jets in the pileup truth jet collections, if they exist");
+  declareProperty("InputTruthJetCollKey", m_inputJetCollKey);
+  declareProperty("InTimeOutputTruthJetCollKey", m_inTimeOutputJetCollKey);
+  declareProperty("OutOfTimeTruthJetCollKey", m_outOfTimeOutputJetCollKey);
+  declareProperty("InTimePtCut", m_inTimePtCut);
+  declareProperty("OutOfTimePtCut", m_outOfTimePtCut);
+  declareProperty("ActivateFilter", m_activateFilter);
+  declareProperty("IncludeSignalJets", m_includeSignalJets, "Include signal jets in the pileup truth jet collections, if they exist");
 }
 
 StatusCode MergeTruthJetsTool::initialize()
@@ -67,45 +72,38 @@ StatusCode MergeTruthJetsTool::processBunchXing(int bunchXing,
           //Back-compatibility with inputs which contain old JetCollections
           if ( inputJetContainer==0 )
             {
-              if (!m_intool.empty() )
-                {
-                  ATH_MSG_VERBOSE("Excuting input tool.");
-                  if ( m_intool->execute() ) //NEED TO BE ABLE TO SET THE STOREGATE FOR m_intool AT THIS POINT.
-                    {
-                      ATH_MSG_WARNING("Input tool execution failed.");
-                    }
-                  inputJetContainer = seStore.retrieve<const xAOD::JetContainer>(m_inputJetCollKey);
-                }
-              if(inputJetContainer == 0)
-                {
-                  ATH_MSG_ERROR("Unable to retrieve input jet container: " << m_inputJetCollKey);
-                  return StatusCode::FAILURE;
-                }
+              ATH_MSG_ERROR("Unable to retrieve input jet container: " << m_inputJetCollKey);
+              return StatusCode::FAILURE;
             }
           ATH_MSG_DEBUG ( "processBunchXing: bunch Crossing = " << bunchXing << " JetContainer size = " << inputJetContainer->size());
-          double pileup_this_pT=-1.;
           if (bunchXing==0)
             {
-              if (m_first_event)//FIXME this may not be robust in the case that there is no TruthJet container from the signal event.
-                {
-                  m_signal_max_pT = processJetContainer(&(*inputJetContainer), 0, 0.0, 0.0);
+              if (m_first_event)
+                {//FIXME this may not be robust in the case that there is no TruthJet container from the signal event.
+                  m_signal_max_pT = this->processJetContainer(&(*inputJetContainer), 0, 0.0, 0.0);
                   ATH_MSG_DEBUG ( "Setting m_signal_max_pT = " << m_signal_max_pT);
-                  m_first_event=false;
-                  if (!m_includeSignalJets)
+                  if(m_includeSignalJets)
+                    {
+                      (void)this->processJetContainer(&(*inputJetContainer), m_inTimeOutputJetContainer, m_inTimePtCut, 0.0);
+                    }
+                  else
                     {
                       ATH_MSG_VERBOSE ( "Don't include signal events in output Truth Jet Containers.");
-                      ++iEvt;
-                      continue;
                     }
+                  m_first_event=false;
+                  ++iEvt;
+                  continue;
                 }
-              pileup_this_pT=processJetContainer(&(*inputJetContainer), m_inTimeOutputJetContainer, m_inTimePtCut, 0.0);
+              const double pileup_this_pT=this->processJetContainer(&(*inputJetContainer), m_inTimeOutputJetContainer, m_inTimePtCut, 0.0);
+              ATH_MSG_VERBOSE ( "highest jet pT in the current background event = " << pileup_this_pT);
+              if (pileup_this_pT>m_pileup_max_pT) m_pileup_max_pT=pileup_this_pT;
+              ATH_MSG_DEBUG ( "highest in-time background jet pT so far = " << m_pileup_max_pT);
             }
           else
             {
               const float timeOfBCID(static_cast<float>(iEvt->time()));
-              pileup_this_pT=processJetContainer(&(*inputJetContainer), m_outOfTimeOutputJetContainer, m_outOfTimePtCut, timeOfBCID);
+              (void)this->processJetContainer(&(*inputJetContainer), m_outOfTimeOutputJetContainer, m_outOfTimePtCut, timeOfBCID);
             }
-          if (pileup_this_pT>m_pileup_max_pT) m_pileup_max_pT=pileup_this_pT;
         }
       else
         {
@@ -113,13 +111,25 @@ StatusCode MergeTruthJetsTool::processBunchXing(int bunchXing,
         }
       ++iEvt;
     }
-  if(m_first_event) {m_first_event=false;}//signal is always the first event, so even if we didn't see anything should set this to false here.
+  //signal is always the first event, so even if we didn't see
+  //anything should set this to false here.
+  if(m_first_event) {m_first_event=false;}
   return StatusCode::SUCCESS;
 }
 
 StatusCode MergeTruthJetsTool::mergeEvent()
 {
   ATH_MSG_VERBOSE ( "mergeEvent" );
+
+  // Veto event when m_pileup_max_pT>m_signal_max_pT
+  if (m_activateFilter && m_pileup_max_pT>m_signal_max_pT)
+    {
+      ATH_MSG_INFO ( "Highest pT Jet in Hard-scatter event = " << m_signal_max_pT
+                     << ", highest pT jet in a background event = " << m_pileup_max_pT
+                     << ". Therefore filtering this hard-scatter event." );
+      m_filterPassed = false;
+    }
+
   if(this->record(m_inTimeOutputJetContainer, m_inTimeOutputJetCollKey).isFailure())
     { //This call also records the xAOD::JetAuxContainer.
       ATH_MSG_ERROR("mergeEvent: Failed to record InTimeOutputJetContainer");
@@ -181,7 +191,7 @@ StatusCode MergeTruthJetsTool::processAllSubEvents()
           return StatusCode::FAILURE;
         }
     }
-  
+
   m_inTimeOutputJetContainer = new xAOD::JetContainer();
   m_inTimeOutputJetContainer->setStore(new xAOD::JetAuxContainer);
   m_outOfTimeOutputJetContainer = new xAOD::JetContainer();
@@ -189,7 +199,6 @@ StatusCode MergeTruthJetsTool::processAllSubEvents()
 
   typedef PileUpMergeSvc::TimedList<xAOD::JetContainer>::type TruthJetList;
   TruthJetList truthList;
-  double pileup_this_pT=-1.;
   if ( (m_pMergeSvc->retrieveSubEvtsData(m_inputJetCollKey, truthList)).isSuccess() )
     {
       if (!truthList.empty())
@@ -206,29 +215,35 @@ StatusCode MergeTruthJetsTool::processAllSubEvents()
                   if (m_first_event)
                     {//FIXME this may not be robust in the case that there is no TruthJet container from the signal event.
                       m_signal_max_pT = this->processJetContainer(&(*((jetColl_iter)->second)), 0, 0.0, 0.0);
-                      m_first_event=false;
-                      if (!m_includeSignalJets)
+                      if(m_includeSignalJets)
+                        {
+                          (void)this->processJetContainer(&(*((jetColl_iter)->second)), m_inTimeOutputJetContainer, m_inTimePtCut, 0.0);
+                        }
+                      else
                         {
                           ATH_MSG_VERBOSE ( "Don't include signal events in output Truth Jet Containers.");
-                          ++jetColl_iter;
-                          continue;
                         }
+                      m_first_event=false;
+                      ++jetColl_iter;
+                      continue;
                     }
-                  pileup_this_pT=this->processJetContainer(&(*((jetColl_iter)->second)), m_inTimeOutputJetContainer, m_inTimePtCut, 0.0);
+                  const double pileup_this_pT=this->processJetContainer(&(*((jetColl_iter)->second)), m_inTimeOutputJetContainer, m_inTimePtCut, 0.0);
+                  ATH_MSG_VERBOSE ( "highest jet pT in the current background event = " << pileup_this_pT);
+                  if (pileup_this_pT>m_pileup_max_pT) m_pileup_max_pT=pileup_this_pT;
+                  ATH_MSG_DEBUG ( "highest in-time background jet pT so far = " << m_pileup_max_pT);
                 }
               else
                 {
                   const float timeOfBCID(static_cast<float>((jetColl_iter)->first.time()));
-                  pileup_this_pT=this->processJetContainer(&(*((jetColl_iter)->second)), m_outOfTimeOutputJetContainer, m_outOfTimePtCut, timeOfBCID);
+                  (void)this->processJetContainer(&(*((jetColl_iter)->second)), m_outOfTimeOutputJetContainer, m_outOfTimePtCut, timeOfBCID);
                 }
-              if (pileup_this_pT>m_pileup_max_pT) m_pileup_max_pT=pileup_this_pT;
               //signal is always the first event, so if the first event
               //wasn't in-time, then the signal collection was missing and
               //we should skip further checks.
               if(m_first_event) {m_first_event=false;}
               ++jetColl_iter;
             }
-      
+
         }
       else
         {
@@ -240,8 +255,13 @@ StatusCode MergeTruthJetsTool::processAllSubEvents()
       ATH_MSG_ERROR ( "processAllSubEvents: Can not find TruthJetList" );
     }
   // Veto event when m_pileup_max_pT>m_signal_max_pT
-  if (m_pileup_max_pT>m_signal_max_pT) m_filterPassed = false;
-
+  if (m_activateFilter && m_pileup_max_pT>m_signal_max_pT)
+    {
+      ATH_MSG_INFO ( "Highest pT Jet in Hard-scatter event = " << m_signal_max_pT
+                     << ", highest pT jet in a background event = " << m_pileup_max_pT
+                     << ". Therefore filtering this hard-scatter event." );
+      m_filterPassed = false;
+    }
   if(this->record(m_inTimeOutputJetContainer, m_inTimeOutputJetCollKey).isFailure())
     { //This call also records the JetMomentMap.
       ATH_MSG_ERROR ( "processAllSubEvents: Failed to record InTimeOutputJetContainer" );
@@ -263,7 +283,7 @@ StatusCode MergeTruthJetsTool::processAllSubEvents()
       ATH_MSG_DEBUG ( "processAllSubEvents: Recorded " << m_outOfTimeOutputJetCollKey << " JetContainer with "
                       << m_outOfTimeOutputJetContainer->size() <<" entries." );
     }
-  
+
   return StatusCode::SUCCESS;
 }
 
diff --git a/Simulation/G4Utilities/MCTruthSimAlgs/src/MergeTruthJetsTool.h b/Simulation/G4Utilities/MCTruthSimAlgs/src/MergeTruthJetsTool.h
index 8e031bb9b0f5b9d45bc4e2bb007942e3bec93a47..3e8957a684f99514f378bc17b2b3f6ff7e34548d 100644
--- a/Simulation/G4Utilities/MCTruthSimAlgs/src/MergeTruthJetsTool.h
+++ b/Simulation/G4Utilities/MCTruthSimAlgs/src/MergeTruthJetsTool.h
@@ -7,8 +7,6 @@
 
 #include "PileUpTools/PileUpToolBase.h"
 
-#include "AsgTools/AsgTool.h"
-#include "JetInterface/IJetExecuteTool.h"
 #include "xAODJet/JetContainer.h"
 
 #include "GaudiKernel/Property.h"
@@ -42,8 +40,8 @@ public:
   ///Merge the Truth JetContainers using the PileUpMergeSvc
   virtual StatusCode processAllSubEvents() override final;
 
-  ///implementation of passing filter
-  virtual bool filterPassed() const override final { return (!m_vetoOnInTime || m_filterPassed); }
+  // ///implementation of passing filter
+  // virtual bool filterPassed() const override final { return (!m_vetoOnInTime || m_filterPassed); }
 
   ///implementation of filter reset
   virtual void resetFilter() override final { m_first_event=true; m_signal_max_pT=-1.;  m_pileup_max_pT=-1.; m_filterPassed=true; }
@@ -52,7 +50,6 @@ private:
   /// JetContainer Loop
   virtual double processJetContainer(const xAOD::JetContainer* inputJetContainer, xAOD::JetContainer *outputJetContainer, const double& ptCut, const float& timeOfBCID);
   StatusCode record(const xAOD::JetContainer* pjets, std::string jetcontainername) const;
-  ToolHandle<IJetExecuteTool> m_intool;
   ServiceHandle<PileUpMergeSvc> m_pMergeSvc;
   xAOD::JetContainer *m_inTimeOutputJetContainer;
   xAOD::JetContainer *m_outOfTimeOutputJetContainer;
@@ -61,7 +58,7 @@ private:
   std::string m_outOfTimeOutputJetCollKey;
   double m_inTimePtCut;
   double m_outOfTimePtCut;
-  bool m_vetoOnInTime;
+  bool m_activateFilter;
   bool m_includeSignalJets;
   bool m_first_event;
   double m_signal_max_pT;