diff --git a/Calorimeter/CaloRec/python/CaloConfigFlags.py b/Calorimeter/CaloRec/python/CaloConfigFlags.py
index ad9c9d8add3e4d6c0385bbb14e3b850ce92d1a62..5e24cfc64b106103d5a65f7b0f69fe5de555d58d 100644
--- a/Calorimeter/CaloRec/python/CaloConfigFlags.py
+++ b/Calorimeter/CaloRec/python/CaloConfigFlags.py
@@ -51,6 +51,7 @@ def createCaloConfigFlags():
     ccf.addFlag("Calo.TopoCluster.addCPData",False)
     ccf.addFlag("Calo.TopoCluster.skipWriteList", lambda prevFlags:
                 ["CaloCalTopoClusters", "CaloTopoClusters"] if prevFlags.Reco.HIMode is HIMode.HI else [])
+    ccf.addFlag("Calo.TopoCluster.UseGPUCompatibleCriteria", False)
     
     ccf.addFlag("Calo.TopoCluster.xtalkInfoDumper", False) # dump raw energy, digits and some calibration for xtalk studies
     
diff --git a/Calorimeter/CaloRec/python/CaloTopoClusterConfig.py b/Calorimeter/CaloRec/python/CaloTopoClusterConfig.py
index cb6ecf8727cf6ed85d2ea10e9a20f2ceb9d79b98..d1a9cd178dbe2d751e77afd5f51128272e14d3e2 100644
--- a/Calorimeter/CaloRec/python/CaloTopoClusterConfig.py
+++ b/Calorimeter/CaloRec/python/CaloTopoClusterConfig.py
@@ -151,6 +151,9 @@ def getTopoMoments(flags):
         TopoMoments.MomentsNames += ["ENG_BAD_HV_CELLS"
                                      ,"N_BAD_HV_CELLS"
                                      ]
+    
+    TopoMoments.UseGPUCriteria = flags.Calo.TopoCluster.UseGPUCompatibleCriteria
+    
     result.setPrivateTools(TopoMoments)
     return result
 
@@ -269,13 +272,17 @@ def CaloTopoClusterToolCfg(flags, cellsname):
     
     # note E or AbsE
     #
-    # the following property must be set to TRUE in order to make double
+    # the following properties must be set to TRUE in order to make double
     # sided cuts on the seed and the cluster level
     #
     TopoMaker.SeedCutsInAbsE                 = True
+    TopoMaker.ClusterCutsInAbsEt             = True
     TopoMaker.ClusterEtorAbsEtCut            = 0.0*MeV
     # use 2-gaussian or single gaussian noise for TileCal
     TopoMaker.TwoGaussianNoise = flags.Calo.TopoCluster.doTwoGaussianNoise
+    
+    TopoMaker.UseGPUCriteria = flags.Calo.TopoCluster.UseGPUCompatibleCriteria
+    
     result.setPrivateTools(TopoMaker)
     return result
 
@@ -302,6 +309,9 @@ def CaloTopoClusterSplitterToolCfg(flags):
     TopoSplitter.ShareBorderCells = True
     TopoSplitter.RestrictHECIWandFCalNeighbors  = False
     TopoSplitter.WeightingOfNegClusters = flags.Calo.TopoCluster.doTreatEnergyCutAsAbsolute
+    
+    TopoSplitter.UseGPUCriteria = flags.Calo.TopoCluster.UseGPUCompatibleCriteria
+    
     result.setPrivateTools(TopoSplitter)
     return result
 
@@ -319,7 +329,7 @@ def CaloTopoClusterCfg(flags, cellsname="AllCalo", clustersname=None, clustersna
 
 
     if clustersname=="CaloTopoClusters" and doLCCalib is True: 
-        raise RuntimeError("Inconistent arguments: Name must not be 'CaloTopoClusters' if doLCCalib is True")
+        raise RuntimeError("Inconsistent arguments: Name must not be 'CaloTopoClusters' if doLCCalib is True")
 
     result=ComponentAccumulator()
 
@@ -364,11 +374,9 @@ def CaloTopoClusterCfg(flags, cellsname="AllCalo", clustersname=None, clustersna
     if flags.Calo.TopoCluster.doCalibHitMoments:
         calibHitsMomentsMaker=getTopoCalibMoments(flags)
         CaloTopoCluster.ClusterCorrectionTools += [calibHitsMomentsMaker]
-
-    CaloTopoCluster.ClustersOutputName=clustersname
     
     if doLCCalib:
-        theCaloClusterSnapshot=CaloClusterSnapshot(OutputName=clustersnapname,SetCrossLinks=True)        
+        theCaloClusterSnapshot=CaloClusterSnapshot(OutputName=clustersnapname,SetCrossLinks=True,FinalClusterContainerName=clustersname)        
         CaloTopoCluster.ClusterCorrectionTools += [theCaloClusterSnapshot]
         #if not clustersname:
         CaloTopoCluster.ClusterCorrectionTools += getTopoClusterLocalCalibTools(flags)
@@ -468,7 +476,7 @@ def addSnapshot(topomaker, corrName,contName):
     for t in corrTools:
         newCorrTools.append(t)
         if (t.getName()==corrName):
-            newSnapshot=CompFactory.CaloClusterSnapshot("Snapshot_"+corrName,OutputName=contName)
+            newSnapshot=CompFactory.CaloClusterSnapshot("Snapshot_"+corrName,OutputName=contName,FinalClusterContainerName=topomaker.ClustersOutputName)
             newCorrTools.append(newSnapshot)
             found=True
     if not found:
diff --git a/Calorimeter/CaloRec/src/CaloClusterSnapshot.cxx b/Calorimeter/CaloRec/src/CaloClusterSnapshot.cxx
index 4909a2fe9463c63a21b08ecca20e22523490ac5f..568c694c79d11e8a6503580c5e0a8b4790c8bd0c 100644
--- a/Calorimeter/CaloRec/src/CaloClusterSnapshot.cxx
+++ b/Calorimeter/CaloRec/src/CaloClusterSnapshot.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 
 #include "CaloUtils/CaloClusterStoreHelper.h"
@@ -15,13 +15,13 @@ CaloClusterSnapshot::CaloClusterSnapshot(const std::string& type,
 				   const std::string& name,
 				   const IInterface* parent):
   AthAlgTool(type, name, parent),
-  m_outputKey(""),
-  m_finalContName(nullptr)
+  m_outputKey("")
 { 
   declareInterface<CaloClusterCollectionProcessor> (this);
   declareProperty("OutputName",m_outputKey);
   declareProperty("CellLinkName",m_cellLinkOutputKey);
   declareProperty("SetCrossLinks",m_setCrossLinks=false);
+  declareProperty("FinalClusterContainerName", m_finalContName);
   
 }
 
@@ -32,15 +32,6 @@ CaloClusterSnapshot::~CaloClusterSnapshot()
 = default;
 
 StatusCode CaloClusterSnapshot::initialize() {
-
-  if (m_setCrossLinks) {
-    const CaloClusterMaker* parentAlgo=dynamic_cast<const CaloClusterMaker*>(parent());
-    if (!parentAlgo) {
-      ATH_MSG_ERROR( "Configuration problem. Parent is not CaloClusterMaker. Can't set ElementLink to final cluster."  );
-      return StatusCode::FAILURE;
-    }
-    m_finalContName=&(parentAlgo->getOutputContainerName());
-  }
   ATH_CHECK(m_outputKey.initialize());
   if (m_cellLinkOutputKey.key().empty()) {
     m_cellLinkOutputKey = m_outputKey.key() + "_links";
@@ -78,15 +69,18 @@ CaloClusterSnapshot::execute(const EventContext& ctx,
     }
 
     //From snapshot to final cluster
-    if (m_finalContName) {
-       ClusterLink_t finalEL (*m_finalContName, 0, ctx);
-       for (size_t i=0;i<nClusters;++i) {
-	 (*outputColl)[i]->setSisterClusterLink(ClusterLink_t(finalEL, i));
-	 //	 std::cout << "Setting link to " << *m_finalContName << ", index "<< i <<std::endl;
+    if (m_setCrossLinks) {
+       ClusterLink_t finalEL (m_finalContName, 0, ctx);
+       if (finalEL.isValid()) {
+	 for (size_t i=0;i<nClusters;++i) {
+	   (*outputColl)[i]->setSisterClusterLink(ClusterLink_t(finalEL, i));
+	   //	 std::cout << "Setting link to " << m_finalContName << ", index "<< i <<std::endl;
+	 }
+       }
+       else {
+	 ATH_MSG_DEBUG("Can't set element link from snapshot to final cluster, likely mismatch in the FinalClusterContainerName");	 
        }
     }
-    else
-      ATH_MSG_DEBUG("Can't set element link from snapshot to final cluster, see warning above");
   }
 
   
diff --git a/Calorimeter/CaloRec/src/CaloClusterSnapshot.h b/Calorimeter/CaloRec/src/CaloClusterSnapshot.h
index 97cb6b92697ab98b799c4cab80e26cf5695ab784..76f9d0cb5b093e208e9ee9dff9a1d8f98edd3467 100644
--- a/Calorimeter/CaloRec/src/CaloClusterSnapshot.h
+++ b/Calorimeter/CaloRec/src/CaloClusterSnapshot.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 
 //Dear emacs, this is -*-c++-*-
@@ -31,7 +31,7 @@ class CaloClusterSnapshot : public AthAlgTool, virtual public CaloClusterCollect
 
   bool m_setCrossLinks;
 
-  const std::string* m_finalContName;
+  std::string m_finalContName;
   
 };
 
diff --git a/Calorimeter/CaloRec/src/CaloTopoClusterMaker.cxx b/Calorimeter/CaloRec/src/CaloTopoClusterMaker.cxx
index 86ca057d2fd4e9e2eae3949f8f46d0adc6267331..aa9cc53709278cbe46892136354d26a77cf5be31 100644
--- a/Calorimeter/CaloRec/src/CaloTopoClusterMaker.cxx
+++ b/Calorimeter/CaloRec/src/CaloTopoClusterMaker.cxx
@@ -74,6 +74,7 @@ CaloTopoClusterMaker::CaloTopoClusterMaker(const std::string& type,
     m_seedCutsInAbsE                   (false),
     m_neighborCutsInAbsE               (true),
     m_cellCutsInAbsE                   (true),
+    m_clusterCutsInAbsE                (true),
     m_clusterEtorAbsEtCut              (    0.*MeV),
     m_twogaussiannoise                 (false),
     m_treatL1PredictedCellsAsGood      (true),
@@ -162,6 +163,9 @@ CaloTopoClusterMaker::CaloTopoClusterMaker(const std::string& type,
   // Restrict PS Neighbors
   declareProperty("RestrictPSNeighbors",m_restrictPSNeighbors);
 
+  //Cluster cuts are in E_t or Abs E_t 
+  declareProperty("ClusterCutsInAbsEt",m_clusterCutsInAbsE);
+  
   // Cluster E_t or Abs E_t cut
   declareProperty("ClusterEtorAbsEtCut",m_clusterEtorAbsEtCut);
 
@@ -326,7 +330,7 @@ StatusCode CaloTopoClusterMaker::initialize()
   
   ATH_CHECK(m_noiseCDOKey.initialize());
 
-  ATH_MSG_INFO( (m_seedCutsInAbsE?"ClusterAbsEtCut= ":"ClusterEtCut= ")
+  ATH_MSG_INFO( (m_clusterCutsInAbsE?"ClusterAbsEtCut= ":"ClusterEtCut= ")
                 << m_clusterEtorAbsEtCut << " MeV"  );
 
   m_hashMin = 999999;
@@ -654,7 +658,7 @@ CaloTopoClusterMaker::execute(const EventContext& ctx,
 	myCluster->addCell(iCell,1.);
       }
       const float cl_et = myCluster->et();
-      if ( (m_seedCutsInAbsE ? std::abs(cl_et) : cl_et) > m_clusterEtorAbsEtCut ) {
+      if ( (m_clusterCutsInAbsE ? std::abs(cl_et) : cl_et) > m_clusterEtorAbsEtCut ) {
 	sortClusters.push_back(std::move(myCluster));
       } 
     }
diff --git a/Calorimeter/CaloRec/src/CaloTopoClusterMaker.h b/Calorimeter/CaloRec/src/CaloTopoClusterMaker.h
index 9258feefc2484c9b38a1df81945554728b45bf8d..d87606bd6f7111736265a12271839638a8acfd62 100644
--- a/Calorimeter/CaloRec/src/CaloTopoClusterMaker.h
+++ b/Calorimeter/CaloRec/src/CaloTopoClusterMaker.h
@@ -242,6 +242,14 @@ private:
    * on energy and transverse energy instead.  */
   bool m_cellCutsInAbsE;                         
                                                  
+  /**
+   * @brief if set to true final cluster cuts are on \f$|E|_\perp\f$. 
+   *
+   * The final cluster cuts will be on absolute transverse energy
+   * if this is set to true. If set to false the cuts will be on
+   * transverse energy instead.  */
+  bool m_clusterCutsInAbsE;
+  
   /**
    * @brief \f$E_\perp\f$ cut on the final cluster. 
    *
diff --git a/Calorimeter/CaloRecGPU/CMakeLists.txt b/Calorimeter/CaloRecGPU/CMakeLists.txt
index f1ad33c05ea145223c9517a4bd45931c07ad3ea7..4f193d218b43b63fe8aa552f690f204d2a286fe7 100644
--- a/Calorimeter/CaloRecGPU/CMakeLists.txt
+++ b/Calorimeter/CaloRecGPU/CMakeLists.txt
@@ -20,7 +20,7 @@ find_package( Boost COMPONENTS chrono )
 atlas_add_library( CaloRecGPULib
    CaloRecGPU/*.h src/*.cxx src/*.cu src/*.h
    PUBLIC_HEADERS CaloRecGPU
-   LINK_LIBRARIES AthenaBaseComps CaloEvent CaloInterfaceLib CxxUtils GaudiKernel TileEvent TrigT2CaloCommonLib
+   LINK_LIBRARIES AthenaBaseComps CaloEvent CaloInterfaceLib CxxUtils GaudiKernel TileEvent TrigT2CaloCommonLib xAODTrigCalo
    PRIVATE_INCLUDE_DIRS ${Boost_INCLUDE_DIRS} )
 
 atlas_add_component( CaloRecGPU
diff --git a/Calorimeter/CaloRecGPU/CaloRecGPU/EventInfoDefinitions.h b/Calorimeter/CaloRecGPU/CaloRecGPU/EventInfoDefinitions.h
index 87792602226ed803af98acfdae6ce0c577463915..4cdc7975e1227c7206e10a88d3dfdf882d22ccf5 100644
--- a/Calorimeter/CaloRecGPU/CaloRecGPU/EventInfoDefinitions.h
+++ b/Calorimeter/CaloRecGPU/CaloRecGPU/EventInfoDefinitions.h
@@ -275,7 +275,7 @@ namespace CaloRecGPU
           if (qp.provenance() & mask)
             {
               const float this_time = time[cell];
-              if (fabsf(this_time) < threshold)
+              if (fabsf(this_time) >= threshold)
                 {
                   if (use_crosstalk)
                     {
diff --git a/Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h b/Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h
index 8a470d4a5f76fae2fcebad8b3d9fb3f8924c67b3..baa6e55a9dbedba6c89769d0913a18eb30b219f7 100644
--- a/Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h
+++ b/Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h
@@ -109,16 +109,15 @@ namespace CaloRecGPU
     {
       void * ptr = nullptr;
 
-
-      operator void * () const
+      template <class T = const void>
+      constexpr operator T * () const
       {
-        return ptr;
+        return (T *) ptr;
       }
-
-      template <class T>
-      operator T * () const
+      
+      constexpr operator bool() const
       {
-        return (T *) ptr;
+        return ptr != nullptr;
       }
 
       template <class T>
@@ -310,7 +309,7 @@ namespace CaloRecGPU
   inline constexpr T pi = std::numbers::pi_v<T>;
 
   template <class T>
-  inline constexpr T sqrt2 = std::numbers::sqrt2_v<T>
+  inline constexpr T sqrt2 = std::numbers::sqrt2_v<T>;
 #else
   template <class T>
   inline constexpr T pi = T(3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624L);
diff --git a/Calorimeter/CaloRecGPU/python/CaloRecGPUConfig.py b/Calorimeter/CaloRecGPU/python/CaloRecGPUConfig.py
index 3d663a8e07fa0af83c25ea3a72915c0a5396548f..0e47e2cc451a220318a4ef0593e266d8b3ae94e5 100755
--- a/Calorimeter/CaloRecGPU/python/CaloRecGPUConfig.py
+++ b/Calorimeter/CaloRecGPU/python/CaloRecGPUConfig.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
+# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 
 from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
 from AthenaConfiguration.ComponentFactory import CompFactory
@@ -12,508 +12,677 @@ def ComparedToolsToPlot(tool_ref, tool_test, prefix, match_in_energy = False, ma
 def MatchingOptions(min_similarity = 0.50, terminal_weight = 250., grow_weight = 500., seed_weight = 1000.):
     return (min_similarity, terminal_weight, grow_weight, seed_weight)
 
-def BasicConstantDataExporterToolCfg(flags, name = "ConstantDataExporter"):
+def BasicConstantDataExporterToolCfg(flags, name = "ConstantDataExporter", **kwargs):
     result=ComponentAccumulator()
-    ConstantDataExporter = CompFactory.BasicConstantGPUDataExporter(name)
-    ConstantDataExporter.MeasureTimes = flags.CaloRecGPU.ActiveConfig.MeasureTimes
-    ConstantDataExporter.TimeFileOutput = "ConstantDataExporterTimes.txt"
+    
+    kwargs.setdefault("MeasureTimes", flags.CaloRecGPU.ActiveConfig.MeasureTimes)
+    kwargs.setdefault("TimeFileOutput", name + "Times.txt")
+        
+    ConstantDataExporter = CompFactory.BasicConstantGPUDataExporter(name, **kwargs)
+    
     result.setPrivateTools(ConstantDataExporter)
     return result
 
-def BasicEventDataExporterToolCfg(flags, name = "EventDataExporter"):
+def BasicEventDataExporterToolCfg(flags, cellsname, name = "EventDataExporter", **kwargs):
     result=ComponentAccumulator()
-    EventDataExporter = CompFactory.BasicEventDataGPUExporter(name)
-    EventDataExporter.MeasureTimes = flags.CaloRecGPU.ActiveConfig.MeasureTimes
-    EventDataExporter.TimeFileOutput = "EventDataExporterTimes.txt"
-    EventDataExporter.CellsName = flags.CaloRecGPU.ActiveConfig.CellsName
+    
+    kwargs.setdefault("MeasureTimes", flags.CaloRecGPU.ActiveConfig.MeasureTimes)
+    kwargs.setdefault("TimeFileOutput", name + "Times.txt")
+    
+    kwargs.setdefault("CellsName", cellsname)
+      
     if flags.CaloRecGPU.ActiveConfig.FillMissingCells:
-        EventDataExporter.MissingCellsToFill = flags.CaloRecGPU.ActiveConfig.MissingCellsToFill
+        kwargs.setdefault("MissingCellsToFill", flags.CaloRecGPU.ActiveConfig.MissingCellsToFill)
+                
+    EventDataExporter = CompFactory.BasicEventDataGPUExporter(name, **kwargs)
+    
     result.setPrivateTools(EventDataExporter)
     return result
 
-def BasicAthenaClusterImporterToolCfg(flags, name = "AthenaClusterImporter"):
+def BasicAthenaClusterImporterToolCfg(flags, cellsname, name = "ClusterImporter", **kwargs):
     result=ComponentAccumulator()
-    AthenaClusterImporter = CompFactory.BasicGPUToAthenaImporter(name)
-    AthenaClusterImporter.MeasureTimes = flags.CaloRecGPU.ActiveConfig.MeasureTimes
-    AthenaClusterImporter.TimeFileOutput = "ClusterImporterTimes.txt"
-    AthenaClusterImporter.CellsName = flags.CaloRecGPU.ActiveConfig.CellsName
-    AthenaClusterImporter.ClusterSize = flags.CaloRecGPU.ActiveConfig.ClusterSize
+    kwargs.setdefault("MeasureTimes", flags.CaloRecGPU.ActiveConfig.MeasureTimes)
+    kwargs.setdefault("TimeFileOutput", name + "Times.txt")
+    kwargs.setdefault("CellsName", cellsname)
+    kwargs.setdefault("ClusterSize", flags.CaloRecGPU.ActiveConfig.ClusterSize)
     if flags.CaloRecGPU.ActiveConfig.FillMissingCells:
-        AthenaClusterImporter.MissingCellsToFill = flags.CaloRecGPU.ActiveConfig.MissingCellsToFill
+        kwargs.setdefault("MissingCellsToFill", flags.CaloRecGPU.ActiveConfig.MissingCellsToFill)
+                
+    AthenaClusterImporter = CompFactory.BasicGPUToAthenaImporter(name, **kwargs)
     result.setPrivateTools(AthenaClusterImporter)
     return result
 
-def CaloClusterDeleterToolCfg(flags, name = "ClusterDeleter"):
+def CPUOutputToolCfg(flags, cellsname, name = "CPUOutput", **kwargs):
     result=ComponentAccumulator()
-    ClusterDeleter = CompFactory.CaloClusterDeleter(name)
-    result.setPrivateTools(ClusterDeleter)
-    return result
-
-def CPUOutputToolCfg(flags, name = "CPUOutput",  folder = "output", prefix = "", suffix = ""):
-    result=ComponentAccumulator()
-    CPUOutput = CompFactory.CaloCPUOutput(name)
-    CPUOutput.SavePath = folder
-    CPUOutput.FilePrefix = prefix
-    CPUOutput.FileSuffix = suffix
-    CPUOutput.CellsName = flags.CaloRecGPU.ActiveConfig.CellsName
+    kwargs.setdefault("CellsName", cellsname)
+    kwargs.setdefault("SavePath", "output")
+    
+    CPUOutput = CompFactory.CaloCPUOutput(name, **kwargs)
     result.setPrivateTools(CPUOutput)
     return result
 
-def GPUOutputToolCfg(flags, name = "GPUOutput",  folder = "output", prefix = "", suffix = "", OnlyOutputCells = None):
+def GPUOutputToolCfg(flags, name = "GPUOutput", **kwargs):
     result=ComponentAccumulator()
-    GPUOutput = CompFactory.CaloGPUOutput(name)
-    GPUOutput.SavePath = folder
-    GPUOutput.FilePrefix = prefix
-    GPUOutput.FileSuffix = suffix
-    GPUOutput.UseSortedAndCutClusters = True
-    if OnlyOutputCells is not None:
-        GPUOutput.OnlyOutputCellInfo = OnlyOutputCells
+    kwargs.setdefault("UseSortedAndCutClusters", True)
+    kwargs.setdefault("SavePath", "output")
+        
+    GPUOutput = CompFactory.CaloGPUOutput(name, **kwargs)
     result.setPrivateTools(GPUOutput)
     return result
 
-def ClusterInfoCalcToolCfg(flags, name = "GPUClusterInfoCalculator", do_cut = True):
+def ClusterInfoCalcToolCfg(flags, name = "GPUClusterInfoCalculator", do_cut = True, **kwargs):
     result=ComponentAccumulator()
-    CalcTool = CompFactory.BasicGPUClusterInfoCalculator(name)
-    CalcTool.MeasureTimes = flags.CaloRecGPU.ActiveConfig.MeasureTimes
-    CalcTool.TimeFileOutput = name + "Times.txt"
+    kwargs.setdefault("MeasureTimes", flags.CaloRecGPU.ActiveConfig.MeasureTimes)
+    kwargs.setdefault("TimeFileOutput", name + "Times.txt")
     if do_cut:
-        if not flags.hasFlag('CaloRecGPU.ActiveConfig.CutClustersInAbsEt') :
-            CalcTool.ClusterCutsInAbsEt = flags.CaloRecGPU.ActiveConfig.TopoClusterSeedCutsInAbsE
-        else:
-            CalcTool.ClusterCutsInAbsEt = flags.CaloRecGPU.ActiveConfig.CutClustersInAbsEt
-        CalcTool.ClusterEtorAbsEtCut = flags.CaloRecGPU.ActiveConfig.ClusterEtorAbsEtCut
+        kwargs.setdefault("ClusterCutsInAbsEt", flags.CaloRecGPU.ActiveConfig.PostGrowingClusterCutClustersInAbsEt)
+        kwargs.setdefault("ClusterEtorAbsEtCut", flags.CaloRecGPU.ActiveConfig.PostGrowingClusterEnergyCut)
     else:
-        CalcTool.ClusterCutsInAbsEt = True
-        CalcTool.ClusterEtorAbsEtCut = -1
+        kwargs.setdefault("ClusterCutsInAbsEt", True)
+        kwargs.setdefault("ClusterEtorAbsEtCut", -1)
         #Cutting on absolute value with a negative value => not cutting at all.
 
+    CalcTool = CompFactory.BasicGPUClusterInfoCalculator(name, **kwargs)
     result.setPrivateTools(CalcTool)
     return result
 
-def TopoAutomatonClusteringToolCfg(flags, name = "TAClusterMaker"):
+def TopoAutomatonClusteringToolCfg(flags, name = "TopoAutomatonClustering", **kwargs):
     result=ComponentAccumulator()
-    # maker tools
-    TAClusterMaker = CompFactory.TopoAutomatonClustering(name)
 
-    TAClusterMaker.MeasureTimes = flags.CaloRecGPU.ActiveConfig.MeasureTimes
-    TAClusterMaker.TimeFileOutput = "TopoAutomatonClusteringTimes.txt"
+    kwargs.setdefault("MeasureTimes", flags.CaloRecGPU.ActiveConfig.MeasureTimes)
+    kwargs.setdefault("TimeFileOutput", name + "Times.txt")
 
-    TAClusterMaker.CalorimeterNames= flags.CaloRecGPU.ActiveConfig.CalorimeterNames
+    kwargs.setdefault("CalorimeterNames", flags.CaloRecGPU.ActiveConfig.GrowingCalorimeterNames)
 
-    TAClusterMaker.SeedSamplingNames = flags.CaloRecGPU.ActiveConfig.TopoClusterSeedSamplingNames
+    kwargs.setdefault("SeedSamplingNames", flags.CaloRecGPU.ActiveConfig.GrowingSeedSamplingNames)
 
-    TAClusterMaker.CellThresholdOnEorAbsEinSigma = flags.CaloRecGPU.ActiveConfig.TopoClusterSNRCellThreshold
-    TAClusterMaker.NeighborThresholdOnEorAbsEinSigma = flags.CaloRecGPU.ActiveConfig.TopoClusterSNRGrowThreshold
-    TAClusterMaker.SeedThresholdOnEorAbsEinSigma = flags.CaloRecGPU.ActiveConfig.TopoClusterSNRSeedThreshold
+    kwargs.setdefault("SeedThresholdOnEorAbsEinSigma", flags.CaloRecGPU.ActiveConfig.SeedThreshold)
+    kwargs.setdefault("NeighborThresholdOnEorAbsEinSigma", flags.CaloRecGPU.ActiveConfig.GrowThreshold)
+    kwargs.setdefault("CellThresholdOnEorAbsEinSigma", flags.CaloRecGPU.ActiveConfig.TermThreshold)
 
-    TAClusterMaker.SeedCutsInAbsE = flags.CaloRecGPU.ActiveConfig.TopoClusterSeedCutsInAbsE
-    TAClusterMaker.NeighborCutsInAbsE = flags.CaloRecGPU.ActiveConfig.TopoClusterNeighborCutsInAbsE
-    TAClusterMaker.CellCutsInAbsE = flags.CaloRecGPU.ActiveConfig.TopoClusterCellCutsInAbsE
+    kwargs.setdefault("SeedCutsInAbsE", flags.CaloRecGPU.ActiveConfig.UseAbsSeedThreshold)
+    kwargs.setdefault("NeighborCutsInAbsE", flags.CaloRecGPU.ActiveConfig.UseAbsGrowThreshold)
+    kwargs.setdefault("CellCutsInAbsE", flags.CaloRecGPU.ActiveConfig.UseAbsTermThreshold)
 
-    TAClusterMaker.TwoGaussianNoise = flags.CaloRecGPU.ActiveConfig.TwoGaussianNoise
+    kwargs.setdefault("TwoGaussianNoise", flags.CaloRecGPU.ActiveConfig.doTwoGaussianNoise)
 
+    kwargs.setdefault("SeedCutsInT", flags.CaloRecGPU.ActiveConfig.doTimeCut)
+    kwargs.setdefault("CutOOTseed", flags.CaloRecGPU.ActiveConfig.doTimeCut and flags.CaloRecGPU.ActiveConfig.extendTimeCut)
+    kwargs.setdefault("UseTimeCutUpperLimit", flags.CaloRecGPU.ActiveConfig.useUpperLimitForTimeCut)
+    kwargs.setdefault("TimeCutUpperLimit", flags.CaloRecGPU.ActiveConfig.timeCutUpperLimit)
+    
+    kwargs.setdefault("SeedThresholdOnTAbs", flags.CaloRecGPU.ActiveConfig.GrowingTimeCutSeedThreshold)
+    
+    kwargs.setdefault("TreatL1PredictedCellsAsGood", flags.CaloRecGPU.ActiveConfig.GrowingTreatL1PredictedCellsAsGood)
 
-    TAClusterMaker.SeedCutsInT = flags.CaloRecGPU.ActiveConfig.SeedCutsInT
-    TAClusterMaker.CutOOTseed = flags.CaloRecGPU.ActiveConfig.CutOOTseed
-    TAClusterMaker.UseTimeCutUpperLimit = flags.CaloRecGPU.ActiveConfig.UseTimeCutUpperLimit
-    TAClusterMaker.TimeCutUpperLimit = flags.CaloRecGPU.ActiveConfig.TimeCutUpperLimit
-    TAClusterMaker.SeedThresholdOnTAbs = flags.CaloRecGPU.ActiveConfig.SeedThresholdOnTAbs
-    TAClusterMaker.TreatL1PredictedCellsAsGood = flags.CaloRecGPU.ActiveConfig.TreatL1PredictedCellsAsGood
+    kwargs.setdefault("XTalkEM2", flags.CaloRecGPU.ActiveConfig.xtalkEM2)
+    kwargs.setdefault("XTalkDeltaT", flags.CaloRecGPU.ActiveConfig.xtalkDeltaT)
+    
+    #The other cross-talk options are not supported yet.
 
-    TAClusterMaker.XTalkEM2 = flags.CaloRecGPU.ActiveConfig.UseEM2CrossTalk
-    TAClusterMaker.XTalkDeltaT = flags.CaloRecGPU.ActiveConfig.CrossTalkDeltaT
-
-    TAClusterMaker.NeighborOption = flags.CaloRecGPU.ActiveConfig.NeighborOption
-    TAClusterMaker.RestrictHECIWandFCalNeighbors  = flags.CaloRecGPU.ActiveConfig.RestrictHECIWandFCalNeighbors
-    TAClusterMaker.RestrictPSNeighbors  = flags.CaloRecGPU.ActiveConfig.RestrictPSNeighbors
+    kwargs.setdefault("NeighborOption", flags.CaloRecGPU.ActiveConfig.GrowingNeighborOption)
+    
+    kwargs.setdefault("RestrictHECIWandFCalNeighbors", flags.CaloRecGPU.ActiveConfig.GrowingRestrictHECIWandFCalNeighbors)
+    
+    kwargs.setdefault("RestrictPSNeighbors", flags.CaloRecGPU.ActiveConfig.GrowingRestrictPSNeighbors)
 
+    TAClusterMaker = CompFactory.TopoAutomatonClustering(name, **kwargs)
     result.setPrivateTools(TAClusterMaker)
     return result
 
-def DefaultTopologicalClusteringToolCfg(flags, name = "TopoMaker"):
+def DefaultTopologicalClusteringToolCfg(flags, cellsname, name = "TopoClusterMaker", **kwargs):
     result=ComponentAccumulator()
-    # maker tools
-    TopoMaker = CompFactory.CaloTopoClusterMaker(name)
-
-    TopoMaker.CellsName = flags.CaloRecGPU.ActiveConfig.CellsName
-    TopoMaker.CalorimeterNames= flags.CaloRecGPU.ActiveConfig.CalorimeterNames
-    TopoMaker.SeedSamplingNames = flags.CaloRecGPU.ActiveConfig.TopoClusterSeedSamplingNames
-    TopoMaker.NeighborOption = flags.CaloRecGPU.ActiveConfig.NeighborOption
-    TopoMaker.RestrictHECIWandFCalNeighbors  = flags.CaloRecGPU.ActiveConfig.RestrictHECIWandFCalNeighbors
-    TopoMaker.RestrictPSNeighbors  = flags.CaloRecGPU.ActiveConfig.RestrictPSNeighbors
-    TopoMaker.CellThresholdOnEorAbsEinSigma = flags.CaloRecGPU.ActiveConfig.TopoClusterSNRCellThreshold
-    TopoMaker.NeighborThresholdOnEorAbsEinSigma = flags.CaloRecGPU.ActiveConfig.TopoClusterSNRGrowThreshold
-    TopoMaker.SeedThresholdOnEorAbsEinSigma = flags.CaloRecGPU.ActiveConfig.TopoClusterSNRSeedThreshold
-
-    TopoMaker.SeedCutsInT = flags.CaloRecGPU.ActiveConfig.SeedCutsInT
-    TopoMaker.CutOOTseed = flags.CaloRecGPU.ActiveConfig.CutOOTseed
-    TopoMaker.UseTimeCutUpperLimit = flags.CaloRecGPU.ActiveConfig.UseTimeCutUpperLimit
-    TopoMaker.TimeCutUpperLimit = flags.CaloRecGPU.ActiveConfig.TimeCutUpperLimit
-
-    TopoMaker.ClusterEtorAbsEtCut  = flags.CaloRecGPU.ActiveConfig.ClusterEtorAbsEtCut
-    TopoMaker.TwoGaussianNoise = flags.CaloRecGPU.ActiveConfig.TwoGaussianNoise
-    TopoMaker.SeedCutsInAbsE = flags.CaloRecGPU.ActiveConfig.TopoClusterSeedCutsInAbsE
-    TopoMaker.NeighborCutsInAbsE = flags.CaloRecGPU.ActiveConfig.TopoClusterNeighborCutsInAbsE
-    TopoMaker.CellCutsInAbsE = flags.CaloRecGPU.ActiveConfig.TopoClusterCellCutsInAbsE
-    TopoMaker.SeedThresholdOnTAbs = flags.CaloRecGPU.ActiveConfig.SeedThresholdOnTAbs
-
-    TopoMaker.TreatL1PredictedCellsAsGood = flags.CaloRecGPU.ActiveConfig.TreatL1PredictedCellsAsGood
-
-    TopoMaker.UseGPUCriteria = not flags.CaloRecGPU.ActiveConfig.UseOriginalCriteria
-
-    TopoMaker.XTalkEM2 = flags.CaloRecGPU.ActiveConfig.UseEM2CrossTalk
-    TopoMaker.XTalkDeltaT = flags.CaloRecGPU.ActiveConfig.CrossTalkDeltaT
 
+    kwargs.setdefault("CellsName", cellsname)
+    
+    kwargs.setdefault("CalorimeterNames", flags.CaloRecGPU.ActiveConfig.GrowingCalorimeterNames)
+    kwargs.setdefault("SeedSamplingNames", flags.CaloRecGPU.ActiveConfig.GrowingSeedSamplingNames)
+    
+    kwargs.setdefault("NeighborOption", flags.CaloRecGPU.ActiveConfig.GrowingNeighborOption)
+    kwargs.setdefault("RestrictHECIWandFCalNeighbors", flags.CaloRecGPU.ActiveConfig.GrowingRestrictHECIWandFCalNeighbors)
+    kwargs.setdefault("RestrictPSNeighbors", flags.CaloRecGPU.ActiveConfig.GrowingRestrictPSNeighbors)
+    
+    kwargs.setdefault("SeedThresholdOnEorAbsEinSigma", flags.CaloRecGPU.ActiveConfig.SeedThreshold)
+    kwargs.setdefault("NeighborThresholdOnEorAbsEinSigma", flags.CaloRecGPU.ActiveConfig.GrowThreshold)
+    kwargs.setdefault("CellThresholdOnEorAbsEinSigma", flags.CaloRecGPU.ActiveConfig.TermThreshold)
+    
+    kwargs.setdefault("SeedCutsInAbsE", flags.CaloRecGPU.ActiveConfig.UseAbsSeedThreshold)
+    kwargs.setdefault("NeighborCutsInAbsE", flags.CaloRecGPU.ActiveConfig.UseAbsGrowThreshold)
+    kwargs.setdefault("CellCutsInAbsE", flags.CaloRecGPU.ActiveConfig.UseAbsTermThreshold)
+
+    kwargs.setdefault("SeedCutsInT", flags.CaloRecGPU.ActiveConfig.doTimeCut)
+    kwargs.setdefault("CutOOTseed", flags.CaloRecGPU.ActiveConfig.doTimeCut and flags.CaloRecGPU.ActiveConfig.extendTimeCut)
+    kwargs.setdefault("UseTimeCutUpperLimit", flags.CaloRecGPU.ActiveConfig.useUpperLimitForTimeCut)
+    kwargs.setdefault("TimeCutUpperLimit", flags.CaloRecGPU.ActiveConfig.timeCutUpperLimit)
+    kwargs.setdefault("XTalkEM2", flags.CaloRecGPU.ActiveConfig.xtalkEM2)
+    kwargs.setdefault("XTalkEM2D", flags.CaloRecGPU.ActiveConfig.xtalkEM2D)
+    kwargs.setdefault("XTalkEM2n", flags.CaloRecGPU.ActiveConfig.xtalkEM2n)
+    kwargs.setdefault("XTalkEM3", flags.CaloRecGPU.ActiveConfig.xtalkEM3)
+    kwargs.setdefault("XTalkEMEta", flags.CaloRecGPU.ActiveConfig.xtalkEMEta)
+    kwargs.setdefault("XTalkDeltaT", flags.CaloRecGPU.ActiveConfig.xtalkDeltaT)
+    kwargs.setdefault("XTalk2Eratio1", flags.CaloRecGPU.ActiveConfig.xtalk2Eratio1)
+    kwargs.setdefault("XTalk2Eratio2", flags.CaloRecGPU.ActiveConfig.xtalk2Eratio2)
+    kwargs.setdefault("XTalk3Eratio", flags.CaloRecGPU.ActiveConfig.xtalk3Eratio)
+    kwargs.setdefault("XTalkEtaEratio", flags.CaloRecGPU.ActiveConfig.xtalkEtaEratio)
+    kwargs.setdefault("XTalk2DEratio", flags.CaloRecGPU.ActiveConfig.xtalk2DEratio)
+    
+    kwargs.setdefault("ClusterCutsInAbsEt", flags.CaloRecGPU.ActiveConfig.PostGrowingClusterCutClustersInAbsEt)
+    kwargs.setdefault("ClusterEtorAbsEtCut", flags.CaloRecGPU.ActiveConfig.PostGrowingClusterEnergyCut)
+    
+    kwargs.setdefault("TwoGaussianNoise", flags.CaloRecGPU.ActiveConfig.doTwoGaussianNoise)
+    
+    kwargs.setdefault("SeedThresholdOnTAbs", flags.CaloRecGPU.ActiveConfig.GrowingTimeCutSeedThreshold)
+
+    kwargs.setdefault("TreatL1PredictedCellsAsGood", flags.CaloRecGPU.ActiveConfig.GrowingTreatL1PredictedCellsAsGood)
+
+    kwargs.setdefault("UseGPUCriteria", not flags.CaloRecGPU.ActiveConfig.UseOriginalCriteria)
+
+    TopoMaker = CompFactory.CaloTopoClusterMaker(name, **kwargs)
     result.setPrivateTools(TopoMaker)
     return result
 
-def TopoAutomatonSplitterToolCfg(flags, name = "TopoAutomatonSplitter"):
+def TopoAutomatonSplitterToolCfg(flags, name = "ClusterSplitter", **kwargs):
     result=ComponentAccumulator()
-    # maker tools
-    Splitter = CompFactory.TopoAutomatonSplitting(name)
-
-    Splitter.MeasureTimes = flags.CaloRecGPU.ActiveConfig.MeasureTimes
-    Splitter.TimeFileOutput = "ClusterSplitterTimes.txt"
-
-    Splitter.NumberOfCellsCut = flags.CaloRecGPU.ActiveConfig.SplitterNumberOfCellsCut
-    Splitter.EnergyCut = flags.CaloRecGPU.ActiveConfig.SplitterEnergyCut
-    Splitter.SamplingNames = flags.CaloRecGPU.ActiveConfig.SplitterSamplingNames
-    Splitter.SecondarySamplingNames = flags.CaloRecGPU.ActiveConfig.SplitterSecondarySamplingNames
-    Splitter.ShareBorderCells = flags.CaloRecGPU.ActiveConfig.SplitterShareBorderCells
-    Splitter.EMShowerScale = flags.CaloRecGPU.ActiveConfig.EMShowerScale
-    Splitter.WeightingOfNegClusters = flags.CaloRecGPU.ActiveConfig.SplitterUseNegativeClusters
-
-    Splitter.TreatL1PredictedCellsAsGood = flags.CaloRecGPU.ActiveConfig.TreatL1PredictedCellsAsGood
-
-    Splitter.NeighborOption = flags.CaloRecGPU.ActiveConfig.NeighborOption
-    Splitter.RestrictHECIWandFCalNeighbors  = flags.CaloRecGPU.ActiveConfig.RestrictHECIWandFCalNeighbors
-    Splitter.RestrictPSNeighbors = flags.CaloRecGPU.ActiveConfig.RestrictPSNeighbors and flags.CaloRecGPU.ActiveConfig.AlsoRestrictPSOnGPUSplitter
+    
+    kwargs.setdefault("MeasureTimes", flags.CaloRecGPU.ActiveConfig.MeasureTimes)
+    kwargs.setdefault("TimeFileOutput", name + "Times.txt")
+
+    kwargs.setdefault("NumberOfCellsCut", flags.CaloRecGPU.ActiveConfig.SplittingNumberOfCellsCut)
+    kwargs.setdefault("EnergyCut", flags.CaloRecGPU.ActiveConfig.SplittingEnergyCut)
+    kwargs.setdefault("SamplingNames", flags.CaloRecGPU.ActiveConfig.SplittingSamplingNames)
+    kwargs.setdefault("SecondarySamplingNames", flags.CaloRecGPU.ActiveConfig.SplittingSecondarySamplingNames)
+    kwargs.setdefault("ShareBorderCells", flags.CaloRecGPU.ActiveConfig.SplittingShareBorderCells)
+    kwargs.setdefault("EMShowerScale", flags.CaloRecGPU.ActiveConfig.SplittingEMShowerScale)
+    kwargs.setdefault("WeightingOfNegClusters", flags.CaloRecGPU.ActiveConfig.SplittingUseNegativeClusters)
+
+    kwargs.setdefault("TreatL1PredictedCellsAsGood", flags.CaloRecGPU.ActiveConfig.SplittingTreatL1PredictedCellsAsGood)
+
+    kwargs.setdefault("NeighborOption", flags.CaloRecGPU.ActiveConfig.SplittingNeighborOption)
+    kwargs.setdefault("RestrictHECIWandFCalNeighbors", flags.CaloRecGPU.ActiveConfig.SplittingRestrictHECIWandFCalNeighbors)
+    kwargs.setdefault("RestrictPSNeighbors", flags.CaloRecGPU.ActiveConfig.GPUSplittingRestrictPSNeighbors)
     #Since the CPU version does not restrict this!
 
+    Splitter = CompFactory.TopoAutomatonSplitting(name, **kwargs)
     result.setPrivateTools(Splitter)
     return result
 
-def GPUClusterSplitterToolCfg(flags, name = "GPUClusterSplitter"):
+def DefaultClusterSplittingToolCfg(flags, name = "TopoSplitter", **kwargs):
     result=ComponentAccumulator()
-    # maker tools
-    Splitter = CompFactory.CaloTopoClusterSplitterGPU(name)
-
-    Splitter.MeasureTimes = flags.CaloRecGPU.ActiveConfig.MeasureTimes
-    Splitter.TimeFileOutput = "ClusterSplitterTimes.txt"
-
-    Splitter.NumberOfCellsCut = flags.CaloRecGPU.ActiveConfig.SplitterNumberOfCellsCut
-    Splitter.EnergyCut = flags.CaloRecGPU.ActiveConfig.SplitterEnergyCut
-    Splitter.SamplingNames = flags.CaloRecGPU.ActiveConfig.SplitterSamplingNames
-    Splitter.SecondarySamplingNames = flags.CaloRecGPU.ActiveConfig.SplitterSecondarySamplingNames
-    Splitter.ShareBorderCells = flags.CaloRecGPU.ActiveConfig.SplitterShareBorderCells
-    Splitter.EMShowerScale = flags.CaloRecGPU.ActiveConfig.EMShowerScale
-    Splitter.WeightingOfNegClusters = flags.CaloRecGPU.ActiveConfig.SplitterUseNegativeClusters
-
-    Splitter.TreatL1PredictedCellsAsGood = flags.CaloRecGPU.ActiveConfig.TreatL1PredictedCellsAsGood
+    
+    kwargs.setdefault("NeighborOption", flags.CaloRecGPU.ActiveConfig.SplittingNeighborOption)
+    kwargs.setdefault("RestrictHECIWandFCalNeighbors", flags.CaloRecGPU.ActiveConfig.SplittingRestrictHECIWandFCalNeighbors)
 
-    result.setPrivateTools(Splitter)
-    return result
-
-def DefaultClusterSplittingToolCfg(flags, name = "TopoSplitter"):
-    result=ComponentAccumulator()
-    # maker tools
-    TopoSplitter = CompFactory.CaloTopoClusterSplitter(name)
+    kwargs.setdefault("NumberOfCellsCut", flags.CaloRecGPU.ActiveConfig.SplittingNumberOfCellsCut)
+    kwargs.setdefault("EnergyCut", flags.CaloRecGPU.ActiveConfig.SplittingEnergyCut)
 
+    kwargs.setdefault("SamplingNames", flags.CaloRecGPU.ActiveConfig.SplittingSamplingNames)
+    kwargs.setdefault("SecondarySamplingNames", flags.CaloRecGPU.ActiveConfig.SplittingSecondarySamplingNames)
 
-    TopoSplitter.NeighborOption = flags.CaloRecGPU.ActiveConfig.NeighborOption
-    TopoSplitter.RestrictHECIWandFCalNeighbors  = flags.CaloRecGPU.ActiveConfig.RestrictHECIWandFCalNeighbors
+    kwargs.setdefault("ShareBorderCells", flags.CaloRecGPU.ActiveConfig.SplittingShareBorderCells)
+    kwargs.setdefault("EMShowerScale", flags.CaloRecGPU.ActiveConfig.SplittingEMShowerScale)
 
-    TopoSplitter.NumberOfCellsCut = flags.CaloRecGPU.ActiveConfig.SplitterNumberOfCellsCut
-    TopoSplitter.EnergyCut = flags.CaloRecGPU.ActiveConfig.SplitterEnergyCut
+    kwargs.setdefault("TreatL1PredictedCellsAsGood", flags.CaloRecGPU.ActiveConfig.SplittingTreatL1PredictedCellsAsGood)
 
-    TopoSplitter.SamplingNames = flags.CaloRecGPU.ActiveConfig.SplitterSamplingNames
-    TopoSplitter.SecondarySamplingNames = flags.CaloRecGPU.ActiveConfig.SplitterSecondarySamplingNames
+    kwargs.setdefault("WeightingOfNegClusters", flags.CaloRecGPU.ActiveConfig.SplittingUseNegativeClusters)
 
-    TopoSplitter.ShareBorderCells = flags.CaloRecGPU.ActiveConfig.SplitterShareBorderCells
-    TopoSplitter.EMShowerScale = flags.CaloRecGPU.ActiveConfig.EMShowerScale
-
-    TopoSplitter.TreatL1PredictedCellsAsGood = flags.CaloRecGPU.ActiveConfig.TreatL1PredictedCellsAsGood
-
-    TopoSplitter.WeightingOfNegClusters = flags.CaloRecGPU.ActiveConfig.SplitterUseNegativeClusters
-
-    TopoSplitter.UseGPUCriteria = not flags.CaloRecGPU.ActiveConfig.UseOriginalCriteria
+    kwargs.setdefault("UseGPUCriteria", not flags.CaloRecGPU.ActiveConfig.UseOriginalCriteria)
 
+    TopoSplitter = CompFactory.CaloTopoClusterSplitter(name, **kwargs)
     result.setPrivateTools(TopoSplitter)
     return result
 
-def GPUClusterMomentsCalculatorToolCfg(flags, name = "GPUTopoMoments"):
-
+def GPUClusterMomentsCalculatorToolCfg(flags, name = "GPUTopoMoments", **kwargs):
     result=ComponentAccumulator()
-    GPUTopoMoments = CompFactory.GPUClusterInfoAndMomentsCalculator(name)
 
-    GPUTopoMoments.MeasureTimes = flags.CaloRecGPU.ActiveConfig.MeasureTimes
+    kwargs.setdefault("MeasureTimes", flags.CaloRecGPU.ActiveConfig.MeasureTimes)
 
-    if flags.CaloRecGPU.ActiveConfig.UseAbsEnergyMoments is None:
-        GPUTopoMoments.WeightingOfNegClusters = flags.CaloRecGPU.ActiveConfig.TopoClusterSeedCutsInAbsE
-    else:
-        GPUTopoMoments.WeightingOfNegClusters = flags.CaloRecGPU.ActiveConfig.UseAbsEnergyMoments
+    kwargs.setdefault("WeightingOfNegClusters", flags.CaloRecGPU.ActiveConfig.MomentsUseAbsEnergy)
 
-    GPUTopoMoments.MaxAxisAngle = flags.CaloRecGPU.ActiveConfig.MomentsMaxAxisAngle
+    kwargs.setdefault("MaxAxisAngle", flags.CaloRecGPU.ActiveConfig.MomentsMaxAxisAngle)
 
-    GPUTopoMoments.TwoGaussianNoise = flags.CaloRecGPU.ActiveConfig.TwoGaussianNoise
+    kwargs.setdefault("TwoGaussianNoise", flags.CaloRecGPU.ActiveConfig.doTwoGaussianNoise)
 
-    GPUTopoMoments.MinBadLArQuality = flags.CaloRecGPU.ActiveConfig.MomentsMinBadLArQuality
+    kwargs.setdefault("MinBadLArQuality", flags.CaloRecGPU.ActiveConfig.MomentsMinBadLArQuality)
 
-    GPUTopoMoments.MinRLateral = flags.CaloRecGPU.ActiveConfig.MomentsMinRLateral
-    GPUTopoMoments.MinLLongitudinal = flags.CaloRecGPU.ActiveConfig.MomentsMinLLongitudinal
+    kwargs.setdefault("MinRLateral", flags.CaloRecGPU.ActiveConfig.MomentsMinRLateral)
+    kwargs.setdefault("MinLLongitudinal", flags.CaloRecGPU.ActiveConfig.MomentsMinLLongitudinal)
 
+    GPUTopoMoments = CompFactory.GPUClusterInfoAndMomentsCalculator(name, **kwargs)
     result.setPrivateTools(GPUTopoMoments)
     return result
 
-def DefaultClusterMomentsCalculatorToolCfg(flags, name = "TopoMoments"):
+def DefaultClusterMomentsCalculatorToolCfg(flags, instantiateForTrigger, name = "TopoMoments", **kwargs):
     result=ComponentAccumulator()
-    TopoMoments = CompFactory.CaloClusterMomentsMaker(name)
 
-    if flags.CaloRecGPU.ActiveConfig.UseAbsEnergyMoments is None:
-        TopoMoments.WeightingOfNegClusters = flags.CaloRecGPU.ActiveConfig.TopoClusterSeedCutsInAbsE
-    else:
-        TopoMoments.WeightingOfNegClusters = flags.CaloRecGPU.ActiveConfig.UseAbsEnergyMoments
+    kwargs.setdefault("WeightingOfNegClusters", flags.CaloRecGPU.ActiveConfig.MomentsUseAbsEnergy)
 
-    TopoMoments.MaxAxisAngle = flags.CaloRecGPU.ActiveConfig.MomentsMaxAxisAngle
+    kwargs.setdefault("MaxAxisAngle", flags.CaloRecGPU.ActiveConfig.MomentsMaxAxisAngle)
 
-    TopoMoments.TwoGaussianNoise = flags.CaloRecGPU.ActiveConfig.TwoGaussianNoise
+    kwargs.setdefault("TwoGaussianNoise", flags.CaloRecGPU.ActiveConfig.doTwoGaussianNoise)
 
-    TopoMoments.MinBadLArQuality = flags.CaloRecGPU.ActiveConfig.MomentsMinBadLArQuality
+    kwargs.setdefault("MinBadLArQuality", flags.CaloRecGPU.ActiveConfig.MomentsMinBadLArQuality)
 
-    TopoMoments.MomentsNames = flags.CaloRecGPU.ActiveConfig.MomentsToCalculate
+    kwargs.setdefault("MomentsNames", flags.CaloRecGPU.ActiveConfig.MomentsToCalculate)
 
-    TopoMoments.MinRLateral = flags.CaloRecGPU.ActiveConfig.MomentsMinRLateral
-    TopoMoments.MinLLongitudinal = flags.CaloRecGPU.ActiveConfig.MomentsMinLLongitudinal
+    kwargs.setdefault("MinRLateral", flags.CaloRecGPU.ActiveConfig.MomentsMinRLateral)
+    kwargs.setdefault("MinLLongitudinal", flags.CaloRecGPU.ActiveConfig.MomentsMinLLongitudinal)
 
-    if not flags.Common.isOnline:
+    kwargs.setdefault("UseGPUCriteria", not flags.CaloRecGPU.ActiveConfig.UseOriginalCriteria)
+        
+    TopoMoments = CompFactory.CaloClusterMomentsMaker(name, **kwargs)
+    
+    if not flags.Common.isOnline and not instantiateForTrigger and "LArHVFraction" not in kwargs:
+        #If it's already in kwargs, don't override
+        #(extra flexibility for the user, not that it's needed...)
+        from LArConfiguration.LArElecCalibDBConfig import LArElecCalibDBCfg
+        result.merge(LArElecCalibDBCfg(flags,["HVScaleCorr"]))
         if flags.Input.isMC:
             TopoMoments.LArHVFraction=CompFactory.LArHVFraction(HVScaleCorrKey="LArHVScaleCorr")
         else:
             TopoMoments.LArHVFraction=CompFactory.LArHVFraction(HVScaleCorrKey="LArHVScaleCorrRecomputed")
-
-    TopoMoments.UseGPUCriteria = not flags.CaloRecGPU.ActiveConfig.UseOriginalCriteria
-
+    
     result.setPrivateTools(TopoMoments)
     return result
 
-def AthenaClusterAndMomentsImporterToolCfg(flags, name = "AthenaClusterImporter"):
+def AthenaClusterAndMomentsImporterToolCfg(flags, cellsname, instantiateForTrigger, name = "ClusterAndMomentsImporter", **kwargs):
     result=ComponentAccumulator()
-    AthenaClusterImporter = CompFactory.GPUToAthenaImporterWithMoments(name)
-    AthenaClusterImporter.CellsName = flags.CaloRecGPU.ActiveConfig.CellsName
-    AthenaClusterImporter.ClusterSize = flags.CaloRecGPU.ActiveConfig.ClusterSize
+    kwargs.setdefault("CellsName", cellsname)
+    
+    kwargs.setdefault("ClusterSize", flags.CaloRecGPU.ActiveConfig.ClusterSize)
 
-    AthenaClusterImporter.MeasureTimes = flags.CaloRecGPU.ActiveConfig.MeasureTimes
-    AthenaClusterImporter.TimeFileOutput = "ClusterAndMomentsImporterTimes.txt"
+    kwargs.setdefault("MeasureTimes", flags.CaloRecGPU.ActiveConfig.MeasureTimes)
+    kwargs.setdefault("TimeFileOutput", name + "Times.txt")
 
-    #from LArCellRec.LArCellBuilderConfig import LArHVCellContCorrCfg
-    #theLArHVCellContCorr=LArHVCellContCorrCfg(flags)
-    #result.merge(theLArHVCellContCorr)
-    #from LArCalibUtils.LArHVScaleConfig import LArHVScaleCfg
-    #result.merge(LArHVScaleCfg(flags))
-
-
-
-    if not flags.Common.isOnline:
+    if not flags.Common.isOnline and not instantiateForTrigger:
+        kwargs.setdefault("FillHVMoments", True)
         if flags.Input.isMC:
-            AthenaClusterImporter.HVScaleCorrKey = "LArHVScaleCorr"
+            kwargs.setdefault("HVScaleCorrKey", "LArHVScaleCorr")
         else:
-            AthenaClusterImporter.HVScaleCorrKey = "LArHVScaleCorrRecomputed"
+            kwargs.setdefault("HVScaleCorrKey", "LArHVScaleCorrRecomputed")
+    else:
+        kwargs.setdefault("FillHVMoments", False)
 
-    AthenaClusterImporter.MomentsNames = flags.CaloRecGPU.ActiveConfig.MomentsToCalculate
+    kwargs.setdefault("MomentsNames", flags.CaloRecGPU.ActiveConfig.MomentsToCalculate)
 
     if flags.CaloRecGPU.ActiveConfig.FillMissingCells:
-        AthenaClusterImporter.MissingCellsToFill = flags.CaloRecGPU.ActiveConfig.MissingCellsToFill
+        kwargs.setdefault("MissingCellsToFill", flags.CaloRecGPU.ActiveConfig.MissingCellsToFill)
 
+    AthenaClusterImporter = CompFactory.GPUToAthenaImporterWithMoments(name, **kwargs)
     result.setPrivateTools(AthenaClusterImporter)
     return result
 
-def CellsCounterCPUToolCfg(flags, name = "CPUCounts", folder = "counts", prefix = "CPU", suffix = ""):
+def CellsCounterCPUToolCfg(flags, cellsname, name = "CPUCounts", **kwargs):
     result=ComponentAccumulator()
-    CPUCount = CompFactory.CaloCellsCounterCPU(name)
-    CPUCount.SavePath = folder
-    CPUCount.FilePrefix = prefix
-    CPUCount.FileSuffix = suffix
-    CPUCount.CellsName = flags.CaloRecGPU.ActiveConfig.CellsName
+    kwargs.setdefault("SavePath", "counts")
+    kwargs.setdefault("FilePrefix", "CPU")
+    kwargs.setdefault("CellsName", cellsname)
 
-    CPUCount.CellThresholdOnEorAbsEinSigma = flags.CaloRecGPU.ActiveConfig.TopoClusterSNRCellThreshold
-    CPUCount.NeighborThresholdOnEorAbsEinSigma = flags.CaloRecGPU.ActiveConfig.TopoClusterSNRGrowThreshold
-    CPUCount.SeedThresholdOnEorAbsEinSigma = flags.CaloRecGPU.ActiveConfig.TopoClusterSNRSeedThreshold
+    kwargs.setdefault("SeedThresholdOnEorAbsEinSigma", flags.CaloRecGPU.ActiveConfig.SeedThreshold)
+    kwargs.setdefault("NeighborThresholdOnEorAbsEinSigma", flags.CaloRecGPU.ActiveConfig.GrowThreshold)
+    kwargs.setdefault("CellThresholdOnEorAbsEinSigma", flags.CaloRecGPU.ActiveConfig.TermThreshold)
 
+    CPUCount = CompFactory.CaloCellsCounterCPU(name, **kwargs)
     result.setPrivateTools(CPUCount)
     return result
 
-def CellsCounterGPUToolCfg(flags, name = "GPUCounts", folder = "counts", prefix = "GPU", suffix = ""):
+def CellsCounterGPUToolCfg(flags, name = "GPUCounts", **kwargs):
     result=ComponentAccumulator()
-    GPUCount = CompFactory.CaloCellsCounterGPU(name)
-    GPUCount.SavePath = folder
-    GPUCount.FilePrefix = prefix
-    GPUCount.FileSuffix = suffix
+    kwargs.setdefault("SavePath", "counts")
+    kwargs.setdefault("FilePrefix", "GPU")
 
-    GPUCount.CellThresholdOnEorAbsEinSigma = flags.CaloRecGPU.ActiveConfig.TopoClusterSNRCellThreshold
-    GPUCount.NeighborThresholdOnEorAbsEinSigma = flags.CaloRecGPU.ActiveConfig.TopoClusterSNRGrowThreshold
-    GPUCount.SeedThresholdOnEorAbsEinSigma = flags.CaloRecGPU.ActiveConfig.TopoClusterSNRSeedThreshold
+    kwargs.setdefault("SeedThresholdOnEorAbsEinSigma", flags.CaloRecGPU.ActiveConfig.SeedThreshold)
+    kwargs.setdefault("NeighborThresholdOnEorAbsEinSigma", flags.CaloRecGPU.ActiveConfig.GrowThreshold)
+    kwargs.setdefault("CellThresholdOnEorAbsEinSigma", flags.CaloRecGPU.ActiveConfig.TermThreshold)
 
+    GPUCount = CompFactory.CaloCellsCounterGPU(name, **kwargs)
     result.setPrivateTools(GPUCount)
     return result
 
-def MomentsDumperToolCfg(flags, folder = "moments", name = "MomentsDumper", prefix = "", suffix = ""):
+def MomentsDumperToolCfg(flags, name = "MomentsDumper", **kwargs):
     result=ComponentAccumulator()
-    GPUCount = CompFactory.CaloMomentsDumper(name)
-    GPUCount.SavePath = folder
-    GPUCount.FilePrefix = prefix
-    GPUCount.FileSuffix = suffix
+    kwargs.setdefault("SavePath", "moments")
 
-    result.setPrivateTools(GPUCount)
+    MomentsDumper = CompFactory.CaloMomentsDumper(name, **kwargs)
+    result.setPrivateTools(MomentsDumper)
     return result
 
-def PlotterMonitoringToolCfg(flags, name = "PlotterMonitoring"):
+def PlotterToolCfg(flags, cellsname, name = "PlotterMonitoring", **kwargs):
     result=ComponentAccumulator()
-    PloTool = CompFactory.CaloGPUClusterAndCellDataMonitor(name)
 
-    PloTool.CellThreshold = flags.CaloRecGPU.ActiveConfig.TopoClusterSNRCellThreshold
-    PloTool.NeighborThreshold = flags.CaloRecGPU.ActiveConfig.TopoClusterSNRGrowThreshold
-    PloTool.SeedThreshold = flags.CaloRecGPU.ActiveConfig.TopoClusterSNRSeedThreshold
+    kwargs.setdefault("SeedThreshold", flags.CaloRecGPU.ActiveConfig.SeedThreshold)
+    kwargs.setdefault("NeighborThreshold", flags.CaloRecGPU.ActiveConfig.GrowThreshold)
+    kwargs.setdefault("CellThreshold", flags.CaloRecGPU.ActiveConfig.TermThreshold)
 
-    PloTool.CellsName = flags.CaloRecGPU.ActiveConfig.CellsName
+    kwargs.setdefault("CellsName", cellsname)
 
-    PloTool.ClusterMatchingParameters = MatchingOptions()
+    kwargs.setdefault("ClusterMatchingParameters", MatchingOptions())
 
     #Tools and Combinations to plot
     #should be set by the end user.
 
-    from AthenaMonitoringKernel.GenericMonitoringTool import GenericMonitoringTool
-
-    PloTool.MonitoringTool = GenericMonitoringTool(flags, "PlotterMonitoringTool")
-
+    PloTool = CompFactory.CaloGPUClusterAndCellDataMonitor(name, **kwargs)
+    
+    if "MonitoringTool" not in kwargs:
+        from AthenaMonitoringKernel.GenericMonitoringTool import GenericMonitoringTool
+        PloTool.MonitoringTool = GenericMonitoringTool(flags, "PlotterMonitoringTool")
+    
     result.setPrivateTools(PloTool)
     return result
 
-def MonitorizationTool(flags, name = "MonTool"):
-    from AthenaMonitoringKernel.GenericMonitoringTool import GenericMonitoringTool
-
-    monTool = GenericMonitoringTool(flags, name)
-
-    maxNumberOfClusters=2500.0
-
-    monTool.defineHistogram('container_size', path='EXPERT', type='TH1F',  title="Container Size; Number of Clusters; Number of Events", xbins=50, xmin=0.0, xmax=maxNumberOfClusters)
-    monTool.defineHistogram('Et', path='EXPERT', type='TH1F',  title="Cluster E_T; E_T [ MeV ] ; Number of Clusters", xbins=135, xmin=-200.0, xmax=2500.0)
-    monTool.defineHistogram('Eta', path='EXPERT', type='TH1F', title="Cluster #eta; #eta ; Number of Clusters", xbins=100, xmin=-2.5, xmax=2.5)
-    monTool.defineHistogram('Phi', path='EXPERT', type='TH1F', title="Cluster #phi; #phi ; Number of Clusters", xbins=64, xmin=-3.2, xmax=3.2)
-    monTool.defineHistogram('Eta,Phi', path='EXPERT', type='TH2F', title="Number of Clusters; #eta ; #phi ; Number of Clusters", xbins=100, xmin=-2.5, xmax=2.5, ybins=128, ymin=-3.2, ymax=3.2)
-    monTool.defineHistogram('clusterSize', path='EXPERT', type='TH1F', title="Cluster Type; Type ; Number of Clusters", xbins=13, xmin=0.5, xmax=13.5)
-    monTool.defineHistogram('signalState', path='EXPERT', type='TH1F', title="Signal State; Signal State ; Number of Clusters", xbins=4, xmin=-1.5, xmax=2.5)
-    monTool.defineHistogram('size', path='EXPERT', type='TH1F', title="Cluster Size; Size [Cells] ; Number of Clusters", xbins=125, xmin=0.0, xmax=250.0)
-    monTool.defineHistogram('N_BAD_CELLS', path='EXPERT', type='TH1F', title="N_BAD_CELLS; N_BAD_CELLS ; Number of Clusters", xbins=250, xmin=0.5, xmax=250.5)
-    monTool.defineHistogram('ENG_FRAC_MAX', path='EXPERT', type='TH1F', title="ENG_FRAC_MAX; ENG_FRAC_MAX ; Number of Clusters", xbins=50, xmin=0.0, xmax=1.1)
-    monTool.defineHistogram('mu', path='EXPERT', type='TH1F',  title="mu; mu; Number of Events", xbins=50, xmin=0.0, xmax=100)
-    monTool.defineHistogram('mu,container_size', path='EXPERT', type='TH2F',  title="Container Size versus #mu; #mu; cluster container size", xbins=50, xmin=20.0, xmax=70, ybins=50, ymin=0.0, ymax=maxNumberOfClusters)
-    return monTool
-
-#This simply uses the GPU versions.
-#For the tests, we will build our own
-#depending on what we want to compare against.
-def HybridClusterProcessorCfg(flags, name="HybridClusterProcessor"):
+def DefaultCalibMomentsToolCfg(flags, name = "TopoCalibMoments", **kwargs):
+    result=ComponentAccumulator()
+    
+    kwargs.setdefault("MomentsNames", ["ENG_CALIB_TOT"
+                                       ,"ENG_CALIB_OUT_L"
+                                       ,"ENG_CALIB_OUT_T"
+                                       ,"ENG_CALIB_EMB0"
+                                       ,"ENG_CALIB_EME0"
+                                       ,"ENG_CALIB_TILEG3"
+                                       ,"ENG_CALIB_DEAD_TOT"
+                                       ,"ENG_CALIB_DEAD_EMB0"
+                                       ,"ENG_CALIB_DEAD_TILE0"
+                                       ,"ENG_CALIB_DEAD_TILEG3"
+                                       ,"ENG_CALIB_DEAD_EME0"
+                                       ,"ENG_CALIB_DEAD_HEC0"
+                                       ,"ENG_CALIB_DEAD_FCAL"
+                                       ,"ENG_CALIB_DEAD_LEAKAGE"
+                                       ,"ENG_CALIB_DEAD_UNCLASS"
+                                       ,"ENG_CALIB_FRAC_EM"
+                                       ,"ENG_CALIB_FRAC_HAD"
+                                       ,"ENG_CALIB_FRAC_REST"])
+
+    kwargs.setdefault("CalibrationHitContainerNames", ["LArCalibrationHitInactive"
+                                                       ,"LArCalibrationHitActive"
+                                                       ,"TileCalibHitActiveCell"
+                                                       ,"TileCalibHitInactiveCell"])
+                                                       
+    kwargs.setdefault("DMCalibrationHitContainerNames", ["LArCalibrationHitDeadMaterial"
+                                                         ,"TileCalibHitDeadMaterial"])
+    
+    TopoCalibMoments = CompFactory.CaloCalibClusterMomentsMaker2(name, **kwargs)
+    result.setPrivateTools(TopoCalibMoments)
+    return result
+
+def DefaultTopoClusterLocalCalibToolsCfg(flags, instantiateForTrigger):
+    result=ComponentAccumulator()
+        
+    CaloClusterLocalCalib=CompFactory.CaloClusterLocalCalib
+    
+    # Local cell weights    
+    LCClassify   = CompFactory.CaloLCClassificationTool("TrigLCClassify" if instantiateForTrigger else "LCClassify")
+    LCClassify.ClassificationKey   = "EMFracClassify"
+    LCClassify.UseSpread = False
+    LCClassify.MaxProbability = 0.85 if flags.GeoModel.AtlasVersion.startswith("Rome") and instantiateForTrigger else 0.5
+    LCClassify.StoreClassificationProbabilityInAOD = True
+    if instantiateForTrigger:
+        LCClassify.UseNormalizedEnergyDensity = not flags.GeoModel.AtlasVersion.startswith("Rome")
+    if not instantiateForTrigger:
+        LCClassify.WeightingOfNegClusters = flags.CaloRecGPU.ActiveConfig.doTreatEnergyCutAsAbsolute
+
+    LCWeight = CompFactory.CaloLCWeightTool("TrigLCWeight" if instantiateForTrigger else "LCWeight")
+    LCWeight.CorrectionKey       = "H1ClusterCellWeights"
+    LCWeight.SignalOverNoiseCut  = 2.0
+    LCWeight.UseHadProbability   = True
+
+    LocalCalib = CaloClusterLocalCalib ("TrigLocalCalib" if instantiateForTrigger else "LocalCalib")
+    LocalCalib.ClusterClassificationTool     = [LCClassify]
+    LocalCalib.ClusterRecoStatus             = [1,2]
+    LocalCalib.LocalCalibTools               = [LCWeight]
+    if not instantiateForTrigger:
+        LocalCalib.WeightingOfNegClusters = flags.CaloRecGPU.ActiveConfig.doTreatEnergyCutAsAbsolute
+
+    # Out-of-cluster corrections
+    LCOut     = CompFactory.CaloLCOutOfClusterTool("TrigLCOut" if instantiateForTrigger else "LCOut")
+    LCOut.CorrectionKey       = "OOCCorrection"
+    LCOut.UseEmProbability    = False
+    LCOut.UseHadProbability   = True
+
+    OOCCalib   = CaloClusterLocalCalib ("TrigOOCCalib" if instantiateForTrigger else "OOCCalib")
+    OOCCalib.ClusterRecoStatus   = [1,2]
+    OOCCalib.LocalCalibTools     = [LCOut]
+    if not instantiateForTrigger:
+        OOCCalib.WeightingOfNegClusters = flags.CaloRecGPU.ActiveConfig.doTreatEnergyCutAsAbsolute
+
+    LCOutPi0  = CompFactory.CaloLCOutOfClusterTool("TrigLCOutPi0" if instantiateForTrigger else "LCOutPi0")
+    LCOutPi0.CorrectionKey    = "OOCPi0Correction"
+    LCOutPi0.UseEmProbability  = True
+    LCOutPi0.UseHadProbability = False
+
+    OOCPi0Calib   = CaloClusterLocalCalib ("TrigOOCPi0Calib" if instantiateForTrigger else "OOCPi0Calib")
+    OOCPi0Calib.ClusterRecoStatus   = [1,2]
+    OOCPi0Calib.LocalCalibTools     = [LCOutPi0]
+    if not instantiateForTrigger:
+        OOCPi0Calib.WeightingOfNegClusters = flags.CaloRecGPU.ActiveConfig.doTreatEnergyCutAsAbsolute
+
+    # Dead material corrections
+    LCDeadMaterial   = CompFactory.CaloLCDeadMaterialTool("TrigLCDeadMaterial" if instantiateForTrigger else "LCDeadMaterial")
+    LCDeadMaterial.HadDMCoeffKey       = "HadDMCoeff2"
+    LCDeadMaterial.ClusterRecoStatus   = 0
+    LCDeadMaterial.WeightModeDM        = 2
+    LCDeadMaterial.UseHadProbability   = True
+    if not instantiateForTrigger:
+        LCDeadMaterial.WeightingOfNegClusters = flags.CaloRecGPU.ActiveConfig.doTreatEnergyCutAsAbsolute
+
+    DMCalib    = CaloClusterLocalCalib ("TrigDMCalib" if instantiateForTrigger else "DMCalib")
+    DMCalib.ClusterRecoStatus   = [1,2]
+    DMCalib.LocalCalibTools      = [LCDeadMaterial]
+    if not instantiateForTrigger:
+      DMCalib.WeightingOfNegClusters = flags.CaloRecGPU.ActiveConfig.doTreatEnergyCutAsAbsolute
+
+    lccalibtools = [
+        LocalCalib,
+        OOCCalib,
+        OOCPi0Calib,
+        DMCalib]
+    
+    result.setPrivateTools(lccalibtools)
+    
+    return result
+    
+#Depending on ReallyUseGPUTools,
+#instantiates GPU or CPU tools with consistent options...
+def GPUCaloTopoClusterCfg(flags, instantiateForTrigger, cellsname,
+                          clustersname = None, clustersnapname="CaloTopoClusters", name="HybridClusterProcessor",
+                          MonitorTool = None, MonitorCells = False, PlotterTool = None,
+                          addAsPrimary = True, ReallyUseGPUTools = True):
+
+    doLCCalib = flags.CaloRecGPU.ActiveConfig.doTopoClusterLocalCalib
+
+    if clustersname is None:
+        clustersname = "CaloCalTopoClusters" if doLCCalib else "CaloTopoClusters"
+
+    if clustersname == "CaloTopoClusters" and doLCCalib:
+        raise RuntimeError("Inconsistent arguments: clustersname must not be 'CaloTopoClusters' if doTopoClusterLocalCalib is True")
+    
     result = ComponentAccumulator()
+    
+    if not instantiateForTrigger:
+    
+      from LArGeoAlgsNV.LArGMConfig import LArGMCfg
+      from TileGeoModel.TileGMConfig import TileGMCfg
+      from CaloTools.CaloNoiseCondAlgConfig import CaloNoiseCondAlgCfg
+    
+      result.merge(CaloNoiseCondAlgCfg(flags,"totalNoise"))
+      result.merge(CaloNoiseCondAlgCfg(flags,"electronicNoise"))
+    
+      result.merge(LArGMCfg(flags))
+      result.merge(TileGMCfg(flags))
+    
 
     HybridClusterProcessor = CompFactory.CaloGPUHybridClusterProcessor(name)
-    HybridClusterProcessor.ClustersOutputName = flags.CaloRecGPU.ActiveConfig.ClustersOutputName
+    HybridClusterProcessor.ClustersOutputName = clustersname
+    
+    HybridClusterProcessor.WriteTriggerSpecificInfo = instantiateForTrigger
+    
     HybridClusterProcessor.MeasureTimes = flags.CaloRecGPU.ActiveConfig.MeasureTimes
+    
     HybridClusterProcessor.TimeFileOutput = "GlobalTimes.txt"
+        
     HybridClusterProcessor.DeferConstantDataPreparationToFirstEvent = True
-    HybridClusterProcessor.DoPlots = False
-    HybridClusterProcessor.PlotterTool = None
-    HybridClusterProcessor.DoMonitoring = flags.CaloRecGPU.ActiveConfig.DoMonitoring
-
-    if flags.CaloRecGPU.ActiveConfig.DoMonitoring:
-        histSvc = CompFactory.THistSvc(Output = ["EXPERT DATAFILE='expert-monitoring.root', OPT='RECREATE'"])
-        result.addService(histSvc)
-        HybridClusterProcessor.MonitoringTool = MonitorizationTool(flags)
-
+    HybridClusterProcessor.DoPlots = PlotterTool is not None
+    HybridClusterProcessor.PlotterTool = PlotterTool
+    HybridClusterProcessor.DoMonitoring = MonitorTool is not None
+    HybridClusterProcessor.MonitoringTool = MonitorTool
+    HybridClusterProcessor.MonitorCells = MonitorCells
+    HybridClusterProcessor.CellsName = cellsname
+    
     HybridClusterProcessor.NumPreAllocatedDataHolders = flags.CaloRecGPU.ActiveConfig.NumPreAllocatedDataHolders
 
+    if ReallyUseGPUTools:
+    
+      HybridClusterProcessor.ConstantDataToGPUTool = result.popToolsAndMerge( BasicConstantDataExporterToolCfg(flags) )
+      HybridClusterProcessor.EventDataToGPUTool = result.popToolsAndMerge( BasicEventDataExporterToolCfg(flags, cellsname) )
+      HybridClusterProcessor.GPUToEventDataTool = result.popToolsAndMerge( AthenaClusterAndMomentsImporterToolCfg(flags, cellsname, instantiateForTrigger) )
+      
+      
+      HybridClusterProcessor.BeforeGPUTools = []
 
-    HybridClusterProcessor.ConstantDataToGPUTool = result.popToolsAndMerge( BasicConstantDataExporterToolCfg(flags) )
-    HybridClusterProcessor.EventDataToGPUTool = result.popToolsAndMerge( BasicEventDataExporterToolCfg(flags) )
-    HybridClusterProcessor.GPUToEventDataTool = result.popToolsAndMerge( AthenaClusterAndMomentsImporterToolCfg(flags) )
-
-    HybridClusterProcessor.BeforeGPUTools = []
+      HybridClusterProcessor.GPUTools = []
 
-    HybridClusterProcessor.GPUTools = []
+      HybridClusterProcessor.GPUTools += [result.popToolsAndMerge( TopoAutomatonClusteringToolCfg(flags,"GPUGrowing"))]
 
-    HybridClusterProcessor.GPUTools += [result.popToolsAndMerge( TopoAutomatonClusteringToolCfg(flags,"TopoAutomatonClustering"))]
+      HybridClusterProcessor.GPUTools += [result.popToolsAndMerge( ClusterInfoCalcToolCfg(flags,"PostGPUGrowingClusterPropertiesCalculator", True))]
 
-    HybridClusterProcessor.GPUTools += [result.popToolsAndMerge( ClusterInfoCalcToolCfg(flags,"PostGrowGPUClusterPropertiesCalculator", True))]
+      HybridClusterProcessor.GPUTools += [result.popToolsAndMerge( TopoAutomatonSplitterToolCfg(flags,"GPUSplitting") )]
 
-    HybridClusterProcessor.GPUTools += [result.popToolsAndMerge( TopoAutomatonSplitterToolCfg(flags,"GPUSplitter") )]
-
-    HybridClusterProcessor.GPUTools += [result.popToolsAndMerge( GPUClusterMomentsCalculatorToolCfg(flags,"GPUTopoMoments") )]
+      HybridClusterProcessor.GPUTools += [result.popToolsAndMerge( GPUClusterMomentsCalculatorToolCfg(flags,"GPUTopoMoments") )]
+      
+    else:
+      
+      HybridClusterProcessor.ConstantDataToGPUTool = None
+      HybridClusterProcessor.EventDataToGPUTool = None
+      HybridClusterProcessor.GPUToEventDataTool = None
+      HybridClusterProcessor.SkipConversions = True
+      
+      HybridClusterProcessor.GPUTools = []
+      
+      HybridClusterProcessor.BeforeGPUTools = [] 
+      
+      HybridClusterProcessor.BeforeGPUTools += [result.popToolsAndMerge( DefaultTopologicalClusteringToolCfg(flags, cellsname,"CPUGrowing"))]
+
+      HybridClusterProcessor.BeforeGPUTools += [result.popToolsAndMerge( DefaultClusterSplittingToolCfg(flags,"CPUSplitting") )]
+
+      HybridClusterProcessor.BeforeGPUTools += [result.popToolsAndMerge( DefaultClusterMomentsCalculatorToolCfg(flags, instantiateForTrigger, "CPUTopoMoments") )]
+      
+      HybridClusterProcessor.BeforeGPUTools += [ CompFactory.CaloClusterStoreRawProperties("RawPropertiesStorer") ]
+      
+      
 
     HybridClusterProcessor.AfterGPUTools = []
 
-    from CaloBadChannelTool.CaloBadChanToolConfig import CaloBadChanToolCfg
-    caloBadChanTool = result.popToolsAndMerge( CaloBadChanToolCfg(flags) )
-    HybridClusterProcessor.AfterGPUTools += [CompFactory.CaloClusterBadChannelList(badChannelTool = caloBadChanTool)]
-
-    # add the total Noise
-    from CaloTools.CaloNoiseCondAlgConfig import CaloNoiseCondAlgCfg
-    result.merge(CaloNoiseCondAlgCfg(flags))
-
-    #if self.ConfigFlags.Calo.TopoCluster.doTopoClusterLocalCalib:
-        #Took out CaloClusterSnapshot that wanted to be a part of a CaloClusterMaker.
-        #Possibly change in the future?
-    #    from CaloRec.CaloTopoClusterConfig import getTopoClusterLocalCalibTools
-    #    HybridClusterProcessor.AfterGPUTools += getTopoClusterLocalCalibTools(flags)
-
-    #    from CaloRec.CaloTopoClusterConfig import caloTopoCoolFolderCfg
-    #    result.merge(caloTopoCoolFolderCfg(self.ConfigFlags))
-
-    result.addEventAlgo(HybridClusterProcessor)
-
-    return result
-
-def DefaultCaloCellMakerCfg(flags):
-        from LArCellRec.LArCellBuilderConfig import LArCellBuilderCfg,LArCellCorrectorCfg
-        from TileRecUtils.TileCellBuilderConfig import TileCellBuilderCfg
-        from CaloCellCorrection.CaloCellCorrectionConfig import CaloCellPedestalCorrCfg, CaloCellNeighborsAverageCorrCfg, CaloCellTimeCorrCfg, CaloEnergyRescalerCfg
-        result=ComponentAccumulator()
-
-        from LArGeoAlgsNV.LArGMConfig import LArGMCfg
-        from TileGeoModel.TileGMConfig import TileGMCfg
-
-        result.merge(LArGMCfg(flags))
-        result.merge(TileGMCfg(flags))
-
-        larCellBuilder     = result.popToolsAndMerge(LArCellBuilderCfg(flags))
-        larCellCorrectors  = result.popToolsAndMerge(LArCellCorrectorCfg(flags))
-        tileCellBuilder = result.popToolsAndMerge(TileCellBuilderCfg(flags))
-        cellFinalizer  = CompFactory.CaloCellContainerFinalizerTool()
-
-        if flags.CaloRecGPU.ActiveConfig.FillMissingCells:
-            tileCellBuilder.fakeCrackCells = True
-
-        cellMakerTools=[larCellBuilder,tileCellBuilder,cellFinalizer]+larCellCorrectors
-
-        #Add corrections tools that are not LAr or Tile specific:
-        if flags.Calo.Cell.doPileupOffsetBCIDCorr or flags.Cell.doPedestalCorr:
-            theCaloCellPedestalCorr=CaloCellPedestalCorrCfg(flags)
-            cellMakerTools.append(result.popToolsAndMerge(theCaloCellPedestalCorr))
-
-        #LAr HV scale corr must come after pedestal corr
-        if flags.LAr.doHVCorr:
-            from LArCellRec.LArCellBuilderConfig import LArHVCellContCorrCfg
-            cellMakerTools.append(result.popToolsAndMerge(LArHVCellContCorrCfg(flags)))
-
-
-        if flags.Calo.Cell.doDeadCellCorr:
-            cellMakerTools.append(result.popToolsAndMerge(CaloCellNeighborsAverageCorrCfg(flags)))
-
-        if flags.Calo.Cell.doEnergyCorr:
-            cellMakerTools.append(result.popToolsAndMerge(CaloEnergyRescalerCfg(flags)))
-        if flags.Calo.Cell.doTimeCorr:
-            cellMakerTools.append(result.popToolsAndMerge(CaloCellTimeCorrCfg(flags)))
-
-        cellAlgo=CompFactory.CaloCellMaker(CaloCellMakerToolNames = cellMakerTools,
-                                           CaloCellsOutputName = flags.CaloRecGPU.ActiveConfig.CellsName)
-        result.addEventAlgo(cellAlgo)
+    if not instantiateForTrigger:
+      from CaloBadChannelTool.CaloBadChanToolConfig import CaloBadChanToolCfg
+      caloBadChanTool = result.popToolsAndMerge( CaloBadChanToolCfg(flags) )
+      HybridClusterProcessor.AfterGPUTools += [CompFactory.CaloClusterBadChannelList(badChannelTool = caloBadChanTool)]
+
+    if not instantiateForTrigger and flags.CaloRecGPU.ActiveConfig.doCalibHitMoments:
+    
+        calibHitsMomentsMaker = result.popToolsAndMerge(DefaultCalibMomentsToolCfg(flags))
+        HybridClusterProcessor.AfterGPUTools += [calibHitsMomentsMaker]
+    
+    if doLCCalib:
+        if not instantiateForTrigger:
+            HybridClusterProcessor.AfterGPUTools += [CompFactory.CaloClusterSnapshot(OutputName=clustersnapname,
+                                                                                     SetCrossLinks=True,
+                                                                                     FinalClusterContainerName=clustersname)]
+        else:
+          from CaloTools.CaloNoiseCondAlgConfig import CaloNoiseCondAlgCfg
+          from CaloRec.CaloTopoClusterConfig import caloTopoCoolFolderCfg
+          result.merge(CaloNoiseCondAlgCfg(flags, noisetype="electronicNoise"))
+          result.merge(caloTopoCoolFolderCfg(flags))
+        
+        calibTools = result.popToolsAndMerge(DefaultTopoClusterLocalCalibToolsCfg(flags, instantiateForTrigger))
+        
+        HybridClusterProcessor.AfterGPUTools += calibTools
+        #This is already a tool array.
+        
+        if not instantiateForTrigger:
+          from CaloRec.CaloTopoClusterConfig import caloTopoCoolFolderCfg
+          result.merge(caloTopoCoolFolderCfg(flags))
+    
+    if instantiateForTrigger:
+      from CaloTools.CaloNoiseCondAlgConfig import CaloNoiseCondAlgCfg
+      result.merge(CaloNoiseCondAlgCfg(flags))
+    
+    result.addEventAlgo(HybridClusterProcessor, primary=addAsPrimary)
+
+    if instantiateForTrigger or clustersname in flags.CaloRecGPU.ActiveConfig.skipWriteList:
+        # don't add these clusters to ESD and AOD
         return result
-
+    
+    #Output config:
+    AODMoments=[ "SECOND_R" 
+                 ,"SECOND_LAMBDA"
+                 ,"CENTER_MAG"
+                 ,"CENTER_LAMBDA"
+                 ,"FIRST_ENG_DENS"
+                 ,"ENG_FRAC_MAX" 
+                 ,"ISOLATION"
+                 ,"ENG_BAD_CELLS"
+                 ,"N_BAD_CELLS"
+                 ,"BADLARQ_FRAC"
+                 ,"ENG_POS"
+                 ,"SIGNIFICANCE"
+                 ,"AVG_LAR_Q"
+                 ,"AVG_TILE_Q"
+                 ,"EM_PROBABILITY"
+                 ,"BadChannelList"
+                 ,"SECOND_TIME"
+                 ,"NCELL_SAMPLING"]
+
+    if flags.CaloRecGPU.ActiveConfig.writeExtendedClusterMoments:
+        AODMoments += ["LATERAL"
+                       ,"LONGITUDINAL"
+                       ,"CELL_SIGNIFICANCE"
+                       ,"PTD"
+                       ,"MASS"]
+
+    if flags.Reco.EnableHI:
+        AODMoments += ["CELL_SIG_SAMPLING"]
+
+    if flags.CaloRecGPU.ActiveConfig.writeCalibHitClusterMoments:
+        AODMoments += ["ENG_CALIB_TOT"
+                       ,"ENG_CALIB_OUT_L"
+                       ,"ENG_CALIB_OUT_T"
+                       ,"ENG_CALIB_EMB0"
+                       ,"ENG_CALIB_EME0"
+                       ,"ENG_CALIB_TILEG3"
+                       ,"ENG_CALIB_DEAD_TOT"
+                       ,"ENG_CALIB_DEAD_EMB0"
+                       ,"ENG_CALIB_DEAD_TILE0"
+                       ,"ENG_CALIB_DEAD_TILEG3"
+                       ,"ENG_CALIB_DEAD_EME0"
+                       ,"ENG_CALIB_DEAD_HEC0"
+                       ,"ENG_CALIB_DEAD_FCAL"
+                       ,"ENG_CALIB_DEAD_LEAKAGE"
+                       ,"ENG_CALIB_DEAD_UNCLASS"
+                       ,"ENG_CALIB_FRAC_EM"
+                       ,"ENG_CALIB_FRAC_HAD"
+                       ,"ENG_CALIB_FRAC_REST"]
+
+
+    from OutputStreamAthenaPool.OutputStreamConfig import addToAOD, addToESD
+    toESD = [f"xAOD::CaloClusterContainer#{clustersname}",
+             f"xAOD::CaloClusterAuxContainer#{clustersname}Aux.",
+             f"CaloClusterCellLinkContainer#{clustersname}_links"]
+    toAOD = [f"xAOD::CaloClusterContainer#{clustersname}",
+             f"CaloClusterCellLinkContainer#{clustersname}_links"]
+
+    AODMoments.append("CellLink") #Add data-link to cell-link container
+    if flags.CaloRecGPU.ActiveConfig.addCalibrationHitDecoration: #Add calib hit deco if requried 
+        AODMoments.append(flags.CaloRecGPU.ActiveConfig.CalibrationHitDecorationName)
+
+    if flags.CaloRecGPU.ActiveConfig.addCPData:
+        AODMoments += ["ClusterWidthEta","ClusterWidthPhi"]
+
+    auxItems = f"xAOD::CaloClusterAuxContainer#{clustersname}Aux."
+    auxItems+= ".".join(AODMoments)    
+
+    toAOD.append(auxItems)
+ 
+    result.merge(addToESD(flags, toESD))
+    result.merge(addToAOD(flags, toAOD))
+    
+    
+    return result
+  
diff --git a/Calorimeter/CaloRecGPU/python/CaloRecGPUConfigurator.py b/Calorimeter/CaloRecGPU/python/CaloRecGPUConfigurator.py
deleted file mode 100644
index 9ea4a1db7f3bdbe30bf03f3e2ac19d86430e64b9..0000000000000000000000000000000000000000
--- a/Calorimeter/CaloRecGPU/python/CaloRecGPUConfigurator.py
+++ /dev/null
@@ -1,691 +0,0 @@
-# Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
-
-from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
-from AthenaConfiguration.ComponentFactory import CompFactory
-from AthenaCommon.SystemOfUnits import MeV, ns, cm, deg
-
-def MatchingOptions(min_similarity = 0.50, terminal_weight = 250., grow_weight = 500., seed_weight = 1000.):
-    return (min_similarity, terminal_weight, grow_weight, seed_weight)
-
-class CaloRecGPUConfigurator:
-    def __init__ (self, configFlags = None, cellsname ="AllCalo"):
-        self.ConfigFlags = configFlags
-        self.CellsName = cellsname
-        
-        self.TopoClusterSNRSeedThreshold = 4.0
-        self.TopoClusterSNRGrowThreshold = 2.0
-        self.TopoClusterSNRCellThreshold = 0.0
-        self.ClusterSize = "Topo_420"
-        
-        self.TopoClusterSeedCutsInAbsE = True
-        self.TopoClusterNeighborCutsInAbsE = True
-        self.TopoClusterCellCutsInAbsE = True
-        
-        self.CalorimeterNames = ["LAREM",
-                                 "LARHEC",
-                                 "LARFCAL",
-                                 "TILE"]
-        self.TopoClusterSeedSamplingNames = ["PreSamplerB", "EMB1", "EMB2", "EMB3",
-                                  "PreSamplerE", "EME1", "EME2", "EME3",
-                                  "HEC0", "HEC1","HEC2", "HEC3",
-                                  "TileBar0", "TileBar1", "TileBar2",
-                                  "TileExt0", "TileExt1", "TileExt2",
-                                  "TileGap1", "TileGap2", "TileGap3",
-                                  "FCAL0", "FCAL1", "FCAL2"]
-                                  
-        self.NeighborOption = "super3D"
-        self.RestrictHECIWandFCalNeighbors  = False
-        self.RestrictPSNeighbors  = True
-        self.AlsoRestrictPSOnGPUSplitter = False
-        #This is to override vanilla behaviour with the possibility of also
-        #restricting neighbours in out GPU splitter.
-
-        if configFlags is not None:
-            configFlags.lock()
-        
-        if configFlags is not None:
-            self.SeedCutsInT = configFlags.Calo.TopoCluster.doTimeCut
-            self.CutOOTseed = configFlags.Calo.TopoCluster.extendTimeCut and configFlags.Calo.TopoCluster.doTimeCut
-            self.UseTimeCutUpperLimit = configFlags.Calo.TopoCluster.useUpperLimitForTimeCut
-        else:
-            self.SeedCutsInT = False
-            self.CutOOTseed = False
-            self.UseTimeCutUpperLimit = False
-        
-        self.TimeCutUpperLimit = 20.0
-        self.TreatL1PredictedCellsAsGood = True
-        
-        self.UseEM2CrossTalk = False
-        self.CrossTalkDeltaT = 15 * ns
-        
-        self.SeedThresholdOnTAbs = 12.5 * ns
-        
-        self.CutClustersInAbsEt = None
-        self.ClusterEtorAbsEtCut = -1e-16*MeV
-        
-        #Since we (by default) use absolute values,
-        #a cut off of 0 MeV could mean some clusters
-        #where the cells have just the right combination
-        #of energies could sum down to 0 on one side (CPU/GPU)
-        #and not on the other. This is actually valid
-        #for any threshold, but this way we accept all clusters...
-        
-        if configFlags is not None:
-            self.TwoGaussianNoise = configFlags.Calo.TopoCluster.doTwoGaussianNoise
-        else:
-            self.TwoGaussianNoise = True
-        
-        
-        self.SplitterNumberOfCellsCut = 4
-        self.SplitterEnergyCut = 500 * MeV
-        self.SplitterSamplingNames = ["EMB2", "EMB3",
-                                      "EME2", "EME3",
-                                      "FCAL0"]
-        self.SplitterSecondarySamplingNames = ["EMB1","EME1",
-                                               "TileBar0","TileBar1","TileBar2",
-                                               "TileExt0","TileExt1","TileExt2",
-                                               "HEC0","HEC1","HEC2","HEC3",
-                                               "FCAL1","FCAL2"]
-        self.SplitterShareBorderCells = True
-        
-        self.EMShowerScale = 5.0 * cm
-        
-        if configFlags is not None:
-            self.SplitterUseNegativeClusters = configFlags.Calo.TopoCluster.doTreatEnergyCutAsAbsolute
-        else:
-            self.SplitterUseNegativeClusters = False
-         
-        if configFlags is not None:
-            self.UseAbsEnergyMoments = configFlags.Calo.TopoCluster.doTreatEnergyCutAsAbsolute
-        else:
-            self.UseAbsEnergyMoments = False
-        
-        self.MomentsMaxAxisAngle = 20 * deg
-        
-        self.MomentsMinBadLArQuality = 4000
-        
-        self.MomentsToCalculate = [ "FIRST_PHI",
-                                    "FIRST_ETA",
-                                    "SECOND_R",
-                                    "SECOND_LAMBDA",
-                                    "DELTA_PHI",
-                                    "DELTA_THETA",
-                                    "DELTA_ALPHA",
-                                    "CENTER_X",
-                                    "CENTER_Y",
-                                    "CENTER_Z",
-                                    "CENTER_MAG",
-                                    "CENTER_LAMBDA",
-                                    "LATERAL",
-                                    "LONGITUDINAL",
-                                    "ENG_FRAC_EM",
-                                    "ENG_FRAC_MAX",
-                                    "ENG_FRAC_CORE",
-                                    "FIRST_ENG_DENS",
-                                    "SECOND_ENG_DENS",
-                                    "ISOLATION",
-                                    "ENG_BAD_CELLS",
-                                    "N_BAD_CELLS",
-                                    "N_BAD_CELLS_CORR",
-                                    "BAD_CELLS_CORR_E",
-                                    "BADLARQ_FRAC",
-                                    "ENG_POS",
-                                    "SIGNIFICANCE",
-                                    "CELL_SIGNIFICANCE",
-                                    "CELL_SIG_SAMPLING",
-                                    "AVG_LAR_Q",
-                                    "AVG_TILE_Q",
-                                    "PTD",
-                                    "MASS",
-                                    "SECOND_TIME",
-                                    "NCELL_SAMPLING" ]
-        
-        self.MomentsMinRLateral = 4 * cm
-        self.MomentsMinLLongitudinal = 10 * cm
-        
-        if configFlags is not None:
-            if not configFlags.Common.isOnline:
-                self.MomentsToCalculate += ["ENG_BAD_HV_CELLS",
-                                            "N_BAD_HV_CELLS"  ]
-                
-        self.ClustersOutputName = "Clusters"
-        
-        self.MeasureTimes = False
-        self.OutputCountsToFile = False
-        self.OutputClustersToFile = False
-        
-        self.DoMonitoring = False
-                
-        self.NumPreAllocatedDataHolders = 0
-
-        self.FillMissingCells = True
-        #We want a full (and ordered) cell container
-        #to get to the fast path.
-        
-        self.MissingCellsToFill = []
-        
-        self.UseOriginalCriteria = False
-        #If True, use the original criteria
-        #(which disagree with the GPU implementation)
-                    
-    def BasicConstantDataExporterToolConf(self, name = "ConstantDataExporter"):
-        result=ComponentAccumulator()
-        ConstantDataExporter = CompFactory.BasicConstantGPUDataExporter(name)
-        ConstantDataExporter.MeasureTimes = False
-        ConstantDataExporter.TimeFileOutput = "ConstantDataExporterTimes.txt"
-        result.setPrivateTools(ConstantDataExporter)
-        return result
-
-    def BasicEventDataExporterToolConf(self, name = "EventDataExporter"):
-        result=ComponentAccumulator()
-        EventDataExporter = CompFactory.BasicEventDataGPUExporter(name)
-        EventDataExporter.MeasureTimes = self.MeasureTimes
-        EventDataExporter.TimeFileOutput = "EventDataExporterTimes.txt"
-        EventDataExporter.CellsName = self.CellsName
-        if self.FillMissingCells:
-            EventDataExporter.MissingCellsToFill = self.MissingCellsToFill
-        result.setPrivateTools(EventDataExporter)
-        return result
-
-    def BasicAthenaClusterImporterToolConf(self, name = "AthenaClusterImporter"):
-        result=ComponentAccumulator()
-        AthenaClusterImporter = CompFactory.BasicGPUToAthenaImporter(name)
-        AthenaClusterImporter.MeasureTimes = self.MeasureTimes
-        AthenaClusterImporter.TimeFileOutput = "ClusterImporterTimes.txt"
-        AthenaClusterImporter.CellsName = self.CellsName
-        AthenaClusterImporter.ClusterSize = self.ClusterSize
-        if self.FillMissingCells:
-            AthenaClusterImporter.MissingCellsToFill = self.MissingCellsToFill
-        result.setPrivateTools(AthenaClusterImporter)
-        return result
-
-    def CaloClusterDeleterToolConf(self, name = "ClusterDeleter"):
-        result=ComponentAccumulator()
-        ClusterDeleter = CompFactory.CaloClusterDeleter(name)
-        result.setPrivateTools(ClusterDeleter)
-        return result
-        
-    def CPUOutputToolConf(self, folder = "output", name = "CPUOutput", prefix = "", suffix = ""):
-        result=ComponentAccumulator()
-        CPUOutput = CompFactory.CaloCPUOutput(name)
-        CPUOutput.SavePath = folder
-        CPUOutput.FilePrefix = prefix
-        CPUOutput.FileSuffix = suffix
-        CPUOutput.CellsName = self.CellsName
-        result.setPrivateTools(CPUOutput)
-        return result
-
-    def GPUOutputToolConf(self, folder = "output", name = "GPUOutput", prefix = "", suffix = "", OnlyOutputCells = None):
-        result=ComponentAccumulator()
-        GPUOutput = CompFactory.CaloGPUOutput(name)
-        GPUOutput.SavePath = folder
-        GPUOutput.FilePrefix = prefix
-        GPUOutput.FileSuffix = suffix
-        GPUOutput.UseSortedAndCutClusters = True
-        if OnlyOutputCells is not None:
-            GPUOutput.OnlyOutputCellInfo = OnlyOutputCells
-        result.setPrivateTools(GPUOutput)
-        return result
-        
-    def ClusterInfoCalcToolConf(self, name = "GPUClusterInfoCalculator", do_cut = True):
-        result=ComponentAccumulator()
-        CalcTool = CompFactory.BasicGPUClusterInfoCalculator(name)
-        CalcTool.MeasureTimes = self.MeasureTimes
-        CalcTool.TimeFileOutput = name + "Times.txt"
-        if do_cut:
-            if self.CutClustersInAbsEt is None:
-                CalcTool.ClusterCutsInAbsEt = self.TopoClusterSeedCutsInAbsE
-            else:
-                CalcTool.ClusterCutsInAbsEt = self.CutClustersInAbsEt
-            CalcTool.ClusterEtorAbsEtCut = self.ClusterEtorAbsEtCut
-        else:
-            CalcTool.ClusterCutsInAbsEt = True
-            CalcTool.ClusterEtorAbsEtCut = -1
-            #Cutting on absolute value with a negative value => not cutting at all.
-            
-        result.setPrivateTools(CalcTool)
-        return result
-                
-    def TopoAutomatonClusteringToolConf(self, name = "TAClusterMaker"):
-        result=ComponentAccumulator()
-        # maker tools
-        TAClusterMaker = CompFactory.TopoAutomatonClustering(name)
-
-        TAClusterMaker.MeasureTimes = self.MeasureTimes
-        TAClusterMaker.TimeFileOutput = "TopoAutomatonClusteringTimes.txt"
-
-        TAClusterMaker.CalorimeterNames= self.CalorimeterNames
-        
-        TAClusterMaker.SeedSamplingNames = self.TopoClusterSeedSamplingNames
-        
-        TAClusterMaker.CellThresholdOnEorAbsEinSigma = self.TopoClusterSNRCellThreshold
-        TAClusterMaker.NeighborThresholdOnEorAbsEinSigma = self.TopoClusterSNRGrowThreshold
-        TAClusterMaker.SeedThresholdOnEorAbsEinSigma = self.TopoClusterSNRSeedThreshold
-        
-        TAClusterMaker.SeedCutsInAbsE = self.TopoClusterSeedCutsInAbsE
-        TAClusterMaker.NeighborCutsInAbsE = self.TopoClusterNeighborCutsInAbsE
-        TAClusterMaker.CellCutsInAbsE = self.TopoClusterCellCutsInAbsE
-        
-        TAClusterMaker.TwoGaussianNoise = self.TwoGaussianNoise
-                
-                
-        TAClusterMaker.SeedCutsInT = self.SeedCutsInT
-        TAClusterMaker.CutOOTseed = self.CutOOTseed
-        TAClusterMaker.UseTimeCutUpperLimit = self.UseTimeCutUpperLimit
-        TAClusterMaker.TimeCutUpperLimit = self.TimeCutUpperLimit
-        TAClusterMaker.SeedThresholdOnTAbs = self.SeedThresholdOnTAbs
-        TAClusterMaker.TreatL1PredictedCellsAsGood = self.TreatL1PredictedCellsAsGood
-        
-        TAClusterMaker.XTalkEM2 = self.UseEM2CrossTalk
-        TAClusterMaker.XTalkDeltaT = self.CrossTalkDeltaT
-        
-        TAClusterMaker.NeighborOption = self.NeighborOption
-        TAClusterMaker.RestrictHECIWandFCalNeighbors  = self.RestrictHECIWandFCalNeighbors
-        TAClusterMaker.RestrictPSNeighbors  = self.RestrictPSNeighbors
-        
-        result.setPrivateTools(TAClusterMaker)
-        return result
-        
-    def DefaultTopologicalClusteringToolConf(self, name = "TopoMaker"):
-        result=ComponentAccumulator()
-        # maker tools
-        TopoMaker = CompFactory.CaloTopoClusterMaker(name)
-
-        TopoMaker.CellsName = self.CellsName
-        TopoMaker.CalorimeterNames= self.CalorimeterNames
-        TopoMaker.SeedSamplingNames = self.TopoClusterSeedSamplingNames
-        TopoMaker.NeighborOption = self.NeighborOption
-        TopoMaker.RestrictHECIWandFCalNeighbors  = self.RestrictHECIWandFCalNeighbors
-        TopoMaker.RestrictPSNeighbors  = self.RestrictPSNeighbors
-        TopoMaker.CellThresholdOnEorAbsEinSigma = self.TopoClusterSNRCellThreshold
-        TopoMaker.NeighborThresholdOnEorAbsEinSigma = self.TopoClusterSNRGrowThreshold
-        TopoMaker.SeedThresholdOnEorAbsEinSigma = self.TopoClusterSNRSeedThreshold
-
-        TopoMaker.SeedCutsInT = self.SeedCutsInT
-        TopoMaker.CutOOTseed = self.CutOOTseed
-        TopoMaker.UseTimeCutUpperLimit = self.UseTimeCutUpperLimit
-        TopoMaker.TimeCutUpperLimit = self.TimeCutUpperLimit
-
-        TopoMaker.ClusterEtorAbsEtCut  = self.ClusterEtorAbsEtCut
-        TopoMaker.TwoGaussianNoise = self.TwoGaussianNoise
-        TopoMaker.SeedCutsInAbsE = self.TopoClusterSeedCutsInAbsE
-        TopoMaker.NeighborCutsInAbsE = self.TopoClusterNeighborCutsInAbsE
-        TopoMaker.CellCutsInAbsE = self.TopoClusterCellCutsInAbsE
-        TopoMaker.SeedThresholdOnTAbs = self.SeedThresholdOnTAbs
-        
-        TopoMaker.TreatL1PredictedCellsAsGood = self.TreatL1PredictedCellsAsGood
-        
-        TopoMaker.UseGPUCriteria = not self.UseOriginalCriteria
-        
-        TopoMaker.XTalkEM2 = self.UseEM2CrossTalk
-        TopoMaker.XTalkDeltaT = self.CrossTalkDeltaT
-        
-        result.setPrivateTools(TopoMaker)
-        return result
-        
-        
-    def TopoAutomatonSplitterToolConf(self, name = "TopoAutomatonSplitter"):
-        result=ComponentAccumulator()
-        # maker tools
-        Splitter = CompFactory.TopoAutomatonSplitting(name)
-
-        Splitter.MeasureTimes = self.MeasureTimes
-        Splitter.TimeFileOutput = "ClusterSplitterTimes.txt"
-        
-        Splitter.NumberOfCellsCut = self.SplitterNumberOfCellsCut
-        Splitter.EnergyCut = self.SplitterEnergyCut
-        Splitter.SamplingNames = self.SplitterSamplingNames
-        Splitter.SecondarySamplingNames = self.SplitterSecondarySamplingNames
-        Splitter.ShareBorderCells = self.SplitterShareBorderCells
-        Splitter.EMShowerScale = self.EMShowerScale
-        Splitter.WeightingOfNegClusters = self.SplitterUseNegativeClusters
-                
-        Splitter.TreatL1PredictedCellsAsGood = self.TreatL1PredictedCellsAsGood
-        
-        Splitter.NeighborOption = self.NeighborOption
-        Splitter.RestrictHECIWandFCalNeighbors  = self.RestrictHECIWandFCalNeighbors
-        Splitter.RestrictPSNeighbors = self.RestrictPSNeighbors and self.AlsoRestrictPSOnGPUSplitter
-        #Since the CPU version does not restrict this!
-        
-        result.setPrivateTools(Splitter)
-        return result
-        
-    def GPUClusterSplitterToolConf(self, name = "GPUClusterSplitter"):
-        result=ComponentAccumulator()
-        # maker tools
-        Splitter = CompFactory.CaloTopoClusterSplitterGPU(name)
-
-        Splitter.MeasureTimes = self.MeasureTimes
-        Splitter.TimeFileOutput = "ClusterSplitterTimes.txt"
-        
-        Splitter.NumberOfCellsCut = self.SplitterNumberOfCellsCut
-        Splitter.EnergyCut = self.SplitterEnergyCut
-        Splitter.SamplingNames = self.SplitterSamplingNames
-        Splitter.SecondarySamplingNames = self.SplitterSecondarySamplingNames
-        Splitter.ShareBorderCells = self.SplitterShareBorderCells
-        Splitter.EMShowerScale = self.EMShowerScale
-        Splitter.WeightingOfNegClusters = self.SplitterUseNegativeClusters
-                
-        Splitter.TreatL1PredictedCellsAsGood = self.TreatL1PredictedCellsAsGood
-        
-        result.setPrivateTools(Splitter)
-        return result
-        
-    def DefaultClusterSplittingToolConf(self, name = "TopoSplitter"):        
-        result=ComponentAccumulator()
-        # maker tools
-        TopoSplitter = CompFactory.CaloTopoClusterSplitter(name)
-
-        
-        TopoSplitter.NeighborOption = self.NeighborOption
-        TopoSplitter.RestrictHECIWandFCalNeighbors  = self.RestrictHECIWandFCalNeighbors
-        
-        TopoSplitter.NumberOfCellsCut = self.SplitterNumberOfCellsCut
-        TopoSplitter.EnergyCut = self.SplitterEnergyCut
-        
-        TopoSplitter.SamplingNames = self.SplitterSamplingNames
-        TopoSplitter.SecondarySamplingNames = self.SplitterSecondarySamplingNames
-        
-        TopoSplitter.ShareBorderCells = self.SplitterShareBorderCells
-        TopoSplitter.EMShowerScale = self.EMShowerScale
-        
-        TopoSplitter.TreatL1PredictedCellsAsGood = self.TreatL1PredictedCellsAsGood
-        
-        TopoSplitter.WeightingOfNegClusters = self.SplitterUseNegativeClusters
-        
-        TopoSplitter.UseGPUCriteria = not self.UseOriginalCriteria
-        
-        result.setPrivateTools(TopoSplitter)
-        return result
-      
-    def GPUClusterMomentsCalculatorToolConf(self, name = "GPUTopoMoments"):
-        
-        result=ComponentAccumulator()
-        GPUTopoMoments = CompFactory.GPUClusterInfoAndMomentsCalculator(name)
-        
-        GPUTopoMoments.MeasureTimes = self.MeasureTimes
-        
-        if self.UseAbsEnergyMoments is None:
-            GPUTopoMoments.WeightingOfNegClusters = self.TopoClusterSeedCutsInAbsE
-        else:
-            GPUTopoMoments.WeightingOfNegClusters = self.UseAbsEnergyMoments
-            
-        GPUTopoMoments.MaxAxisAngle = self.MomentsMaxAxisAngle
-        
-        GPUTopoMoments.TwoGaussianNoise = self.TwoGaussianNoise
-        
-        GPUTopoMoments.MinBadLArQuality = self.MomentsMinBadLArQuality
-        
-        GPUTopoMoments.MinRLateral = self.MomentsMinRLateral
-        GPUTopoMoments.MinLLongitudinal = self.MomentsMinLLongitudinal
-                            
-        result.setPrivateTools(GPUTopoMoments)
-        return result
-        
-        
-    def DefaultClusterMomentsCalculatorToolConf(self, name = "TopoMoments"):
-        result=ComponentAccumulator()
-        TopoMoments = CompFactory.CaloClusterMomentsMaker(name)
-        
-        if self.UseAbsEnergyMoments is None:
-            TopoMoments.WeightingOfNegClusters = self.TopoClusterSeedCutsInAbsE
-        else:
-            TopoMoments.WeightingOfNegClusters = self.UseAbsEnergyMoments
-            
-        TopoMoments.MaxAxisAngle = self.MomentsMaxAxisAngle
-        
-        TopoMoments.TwoGaussianNoise = self.TwoGaussianNoise
-        
-        TopoMoments.MinBadLArQuality = self.MomentsMinBadLArQuality
-        
-        TopoMoments.MomentsNames = self.MomentsToCalculate
-        
-        TopoMoments.MinRLateral = self.MomentsMinRLateral
-        TopoMoments.MinLLongitudinal = self.MomentsMinLLongitudinal
-
-        if not self.ConfigFlags.Common.isOnline:
-            if self.ConfigFlags.Input.isMC:
-                TopoMoments.LArHVFraction=CompFactory.LArHVFraction(HVScaleCorrKey="LArHVScaleCorr")
-            else:
-                TopoMoments.LArHVFraction=CompFactory.LArHVFraction(HVScaleCorrKey="LArHVScaleCorrRecomputed")
-        
-        TopoMoments.UseGPUCriteria = not self.UseOriginalCriteria
-        
-        result.setPrivateTools(TopoMoments)
-        return result
-        
-    def AthenaClusterAndMomentsImporterToolConf(self, name = "AthenaClusterImporter"):
-        result=ComponentAccumulator()
-        AthenaClusterImporter = CompFactory.GPUToAthenaImporterWithMoments(name)
-        AthenaClusterImporter.CellsName = self.CellsName
-        AthenaClusterImporter.ClusterSize = self.ClusterSize
-        
-        AthenaClusterImporter.MeasureTimes = self.MeasureTimes
-        AthenaClusterImporter.TimeFileOutput = "ClusterAndMomentsImporterTimes.txt"
-        
-        
-                
-        if not self.ConfigFlags.Common.isOnline:
-            if self.ConfigFlags.Input.isMC:
-                AthenaClusterImporter.HVScaleCorrKey = "LArHVScaleCorr"
-            else:
-                AthenaClusterImporter.HVScaleCorrKey = "LArHVScaleCorrRecomputed"
-        
-        AthenaClusterImporter.MomentsNames = self.MomentsToCalculate
-        
-        if self.FillMissingCells:
-            AthenaClusterImporter.MissingCellsToFill = self.MissingCellsToFill
-            
-        result.setPrivateTools(AthenaClusterImporter)
-        return result
-        
-    def CellsCounterCPUToolConf(self, folder = "counts", name = "CPUCounts", prefix = "CPU", suffix = ""):
-        result=ComponentAccumulator()
-        CPUCount = CompFactory.CaloCellsCounterCPU(name)
-        CPUCount.SavePath = folder
-        CPUCount.FilePrefix = prefix
-        CPUCount.FileSuffix = suffix
-        CPUCount.CellsName = self.CellsName
-        
-        CPUCount.CellThresholdOnEorAbsEinSigma = self.TopoClusterSNRCellThreshold
-        CPUCount.NeighborThresholdOnEorAbsEinSigma = self.TopoClusterSNRGrowThreshold
-        CPUCount.SeedThresholdOnEorAbsEinSigma = self.TopoClusterSNRSeedThreshold
-        
-        result.setPrivateTools(CPUCount)
-        return result
-        
-    def CellsCounterGPUToolConf(self, folder = "counts", name = "GPUCounts", prefix = "GPU", suffix = ""):
-        result=ComponentAccumulator()
-        GPUCount = CompFactory.CaloCellsCounterGPU(name)
-        GPUCount.SavePath = folder
-        GPUCount.FilePrefix = prefix
-        GPUCount.FileSuffix = suffix
-        
-        GPUCount.CellThresholdOnEorAbsEinSigma = self.TopoClusterSNRCellThreshold
-        GPUCount.NeighborThresholdOnEorAbsEinSigma = self.TopoClusterSNRGrowThreshold
-        GPUCount.SeedThresholdOnEorAbsEinSigma = self.TopoClusterSNRSeedThreshold
-        
-        result.setPrivateTools(GPUCount)
-        return result
-        
-    def MomentsDumperToolConf(self, folder = "moments", name = "MomentsDumper", prefix = "", suffix = ""):
-        result=ComponentAccumulator()
-        GPUCount = CompFactory.CaloMomentsDumper(name)
-        GPUCount.SavePath = folder
-        GPUCount.FilePrefix = prefix
-        GPUCount.FileSuffix = suffix
-        
-        result.setPrivateTools(GPUCount)
-        return result
-        
-    def PlotterMonitoringToolConf(self, name = "PlotterMonitoring"):
-        result=ComponentAccumulator()
-        PloTool = CompFactory.CaloGPUClusterAndCellDataMonitor(name)
-        
-        PloTool.CellThreshold = self.TopoClusterSNRCellThreshold
-        PloTool.NeighborThreshold = self.TopoClusterSNRGrowThreshold
-        PloTool.SeedThreshold = self.TopoClusterSNRSeedThreshold
-        
-        PloTool.CellsName = self.CellsName
-        
-        PloTool.ClusterMatchingParameters = MatchingOptions()
-        
-        #Tools and Combinations to plot
-        #should be set by the end user.
-        
-        from AthenaMonitoringKernel.GenericMonitoringTool import GenericMonitoringTool
-        
-        PloTool.MonitoringTool = GenericMonitoringTool(self.ConfigFlags, "PlotterMonitoringTool")
-        
-        result.setPrivateTools(PloTool)
-        return result
-    
-    def MonitorizationToolConf(self, name = "MonTool"):       
-        from AthenaMonitoringKernel.GenericMonitoringTool import GenericMonitoringTool
-        
-        monTool = GenericMonitoringTool(self.ConfigFlags, name)
-        
-        maxNumberOfClusters=2500.0
-        
-        monTool.defineHistogram('container_size', path='EXPERT', type='TH1F',  title="Container Size; Number of Clusters; Number of Events", xbins=50, xmin=0.0, xmax=maxNumberOfClusters)
-        monTool.defineHistogram('Et', path='EXPERT', type='TH1F',  title="Cluster E_T; E_T [ MeV ] ; Number of Clusters", xbins=135, xmin=-200.0, xmax=2500.0)
-        monTool.defineHistogram('Eta', path='EXPERT', type='TH1F', title="Cluster #eta; #eta ; Number of Clusters", xbins=100, xmin=-2.5, xmax=2.5)
-        monTool.defineHistogram('Phi', path='EXPERT', type='TH1F', title="Cluster #phi; #phi ; Number of Clusters", xbins=64, xmin=-3.2, xmax=3.2)
-        monTool.defineHistogram('Eta,Phi', path='EXPERT', type='TH2F', title="Number of Clusters; #eta ; #phi ; Number of Clusters", xbins=100, xmin=-2.5, xmax=2.5, ybins=128, ymin=-3.2, ymax=3.2)
-        monTool.defineHistogram('clusterSize', path='EXPERT', type='TH1F', title="Cluster Type; Type ; Number of Clusters", xbins=13, xmin=0.5, xmax=13.5)
-        monTool.defineHistogram('signalState', path='EXPERT', type='TH1F', title="Signal State; Signal State ; Number of Clusters", xbins=4, xmin=-1.5, xmax=2.5)
-        monTool.defineHistogram('size', path='EXPERT', type='TH1F', title="Cluster Size; Size [Cells] ; Number of Clusters", xbins=125, xmin=0.0, xmax=250.0)
-        monTool.defineHistogram('N_BAD_CELLS', path='EXPERT', type='TH1F', title="N_BAD_CELLS; N_BAD_CELLS ; Number of Clusters", xbins=250, xmin=0.5, xmax=250.5)
-        monTool.defineHistogram('ENG_FRAC_MAX', path='EXPERT', type='TH1F', title="ENG_FRAC_MAX; ENG_FRAC_MAX ; Number of Clusters", xbins=50, xmin=0.0, xmax=1.1)
-        monTool.defineHistogram('mu', path='EXPERT', type='TH1F',  title="mu; mu; Number of Events", xbins=50, xmin=0.0, xmax=100)
-        monTool.defineHistogram('mu,container_size', path='EXPERT', type='TH2F',  title="Container Size versus #mu; #mu; cluster container size", xbins=50, xmin=20.0, xmax=70, ybins=50, ymin=0.0, ymax=maxNumberOfClusters)
-        return monTool
-        
-    def DefaultCaloCellMakerConf(self, should_be_primary = False):
-        from LArCellRec.LArCellBuilderConfig import LArCellBuilderCfg,LArCellCorrectorCfg
-        from TileRecUtils.TileCellBuilderConfig import TileCellBuilderCfg
-        from CaloCellCorrection.CaloCellCorrectionConfig import CaloCellPedestalCorrCfg, CaloCellNeighborsAverageCorrCfg, CaloCellTimeCorrCfg, CaloEnergyRescalerCfg
-        result=ComponentAccumulator()
-       
-        from LArGeoAlgsNV.LArGMConfig import LArGMCfg
-        from TileGeoModel.TileGMConfig import TileGMCfg
-        
-        result.merge(LArGMCfg(self.ConfigFlags))
-        result.merge(TileGMCfg(self.ConfigFlags))
-
-        larCellBuilder     = result.popToolsAndMerge(LArCellBuilderCfg(self.ConfigFlags))
-        larCellCorrectors  = result.popToolsAndMerge(LArCellCorrectorCfg(self.ConfigFlags))
-        tileCellBuilder = result.popToolsAndMerge(TileCellBuilderCfg(self.ConfigFlags))
-        cellFinalizer  = CompFactory.CaloCellContainerFinalizerTool()
-        
-        if self.FillMissingCells:
-            tileCellBuilder.fakeCrackCells = True
-        
-        cellMakerTools=[larCellBuilder,tileCellBuilder,cellFinalizer]+larCellCorrectors
-        
-        #Add corrections tools that are not LAr or Tile specific:
-        if self.ConfigFlags.Calo.Cell.doPileupOffsetBCIDCorr or self.ConfigFlags.Cell.doPedestalCorr:
-            theCaloCellPedestalCorr=CaloCellPedestalCorrCfg(self.ConfigFlags)
-            cellMakerTools.append(result.popToolsAndMerge(theCaloCellPedestalCorr))
-
-        #LAr HV scale corr must come after pedestal corr
-        if self.ConfigFlags.LAr.doHVCorr:
-            from LArCellRec.LArCellBuilderConfig import LArHVCellContCorrCfg
-            theLArHVCellContCorr=LArHVCellContCorrCfg(self.ConfigFlags)
-            cellMakerTools.append(result.popToolsAndMerge(theLArHVCellContCorr))
-
-
-        if self.ConfigFlags.Calo.Cell.doDeadCellCorr:
-            theCaloCellNeighborAvg=CaloCellNeighborsAverageCorrCfg(self.ConfigFlags)
-            cellMakerTools.append(result.popToolsAndMerge(theCaloCellNeighborAvg))
-
-        if self.ConfigFlags.Calo.Cell.doEnergyCorr:
-            theCaloCellEnergyRescaler=CaloEnergyRescalerCfg(self.ConfigFlags)
-            cellMakerTools.append(result.popToolsAndMerge(theCaloCellEnergyRescaler))
-        if self.ConfigFlags.Calo.Cell.doTimeCorr:
-            theCaloTimeCorr=CaloCellTimeCorrCfg(self.ConfigFlags)
-            cellMakerTools.append(result.popToolsAndMerge(theCaloTimeCorr))
-
-        cellAlgo=CompFactory.CaloCellMaker(CaloCellMakerToolNames = cellMakerTools,
-                                           CaloCellsOutputName = self.CellsName)
-        result.addEventAlgo(cellAlgo, primary = should_be_primary)
-        return result
-        
-    #This simply uses the GPU versions.
-    #For the tests, we will build our own
-    #depending on what we want to compare against.
-    def HybridClusterProcessorConf(self, clustersname = None, should_be_primary = True):
-        result = ComponentAccumulator()
-        
-        HybridClusterProcessor = CompFactory.CaloGPUHybridClusterProcessor("HybridClusterProcessor")
-        HybridClusterProcessor.ClustersOutputName = self.ClustersOutputName
-        HybridClusterProcessor.MeasureTimes = self.MeasureTimes
-        HybridClusterProcessor.TimeFileOutput = "GlobalTimes.txt"
-        HybridClusterProcessor.DeferConstantDataPreparationToFirstEvent = True
-        HybridClusterProcessor.DoPlots = False
-        HybridClusterProcessor.PlotterTool = None
-        HybridClusterProcessor.DoMonitoring = self.DoMonitoring
-        
-        if self.DoMonitoring:
-            histSvc = CompFactory.THistSvc(Output = ["EXPERT DATAFILE='expert-monitoring.root', OPT='RECREATE'"])
-            result.addService(histSvc)
-            HybridClusterProcessor.MonitoringTool = self.MonitorizationToolConf()
-        
-        HybridClusterProcessor.NumPreAllocatedDataHolders = self.NumPreAllocatedDataHolders
-        
-        from LArGeoAlgsNV.LArGMConfig import LArGMCfg
-        from TileGeoModel.TileGMConfig import TileGMCfg
-        
-        result.merge(LArGMCfg(self.ConfigFlags))
-        result.merge(TileGMCfg(self.ConfigFlags))
-        
-        ConstantDataExporter = result.popToolsAndMerge( self.BasicConstantDataExporterToolConf() )
-        EventDataExporter = result.popToolsAndMerge( self.BasicEventDataExporterToolConf() )
-        AthenaClusterImporter = result.popToolsAndMerge( self.AthenaClusterAndMomentsImporterToolConf() )
-        
-        HybridClusterProcessor.ConstantDataToGPUTool = ConstantDataExporter
-        HybridClusterProcessor.EventDataToGPUTool = EventDataExporter
-        HybridClusterProcessor.GPUToEventDataTool = AthenaClusterImporter
-        
-        HybridClusterProcessor.BeforeGPUTools = []
-       
-        HybridClusterProcessor.GPUTools = []
-        
-        TopoAutomatonClusteringDef = result.popToolsAndMerge( self.TopoAutomatonClusteringToolConf("TopoAutomatonClustering"))
-        HybridClusterProcessor.GPUTools += [TopoAutomatonClusteringDef]
-        
-        FirstPropCalcDef = result.popToolsAndMerge( self.ClusterInfoCalcToolConf("PostGrowGPUClusterPropertiesCalculator", True))
-        HybridClusterProcessor.GPUTools += [FirstPropCalcDef]
-        
-        GPUClusterSplittingDef = result.popToolsAndMerge( self.TopoAutomatonSplitterToolConf("GPUSplitter") )
-        HybridClusterProcessor.GPUTools += [GPUClusterSplittingDef]
-        
-        GPUMomentsCalcDef = result.popToolsAndMerge( self.GPUClusterMomentsCalculatorToolConf("GPUTopoMoments") )
-        HybridClusterProcessor.GPUTools += [GPUMomentsCalcDef]
-            
-        HybridClusterProcessor.AfterGPUTools = []
-        
-        from CaloBadChannelTool.CaloBadChanToolConfig import CaloBadChanToolCfg
-        caloBadChanTool = result.popToolsAndMerge( CaloBadChanToolCfg(self.ConfigFlags) )
-        CaloClusterBadChannelList=CompFactory.CaloClusterBadChannelList
-        BadChannelListCorr = CaloClusterBadChannelList(badChannelTool = caloBadChanTool)
-        HybridClusterProcessor.AfterGPUTools += [BadChannelListCorr]
-
-            
-        if self.ConfigFlags.Calo.TopoCluster.doTopoClusterLocalCalib:    
-            #Took out CaloClusterSnapshot that wanted to be a part of a CaloClusterMaker.
-            #Possibly change in the future?
-            from CaloRec.CaloTopoClusterConfig import getTopoClusterLocalCalibTools
-            HybridClusterProcessor.AfterGPUTools += getTopoClusterLocalCalibTools(self.ConfigFlags)
-        
-            from CaloRec.CaloTopoClusterConfig import caloTopoCoolFolderCfg
-            result.merge(caloTopoCoolFolderCfg(self.ConfigFlags))
-
-        result.addEventAlgo(HybridClusterProcessor, primary = should_be_primary)
-
-        return result
-        
-
-
-
-
diff --git a/Calorimeter/CaloRecGPU/python/CaloRecGPUFlags.py b/Calorimeter/CaloRecGPU/python/CaloRecGPUFlags.py
index 2284b117fea8e99ca7435794dab892d02a88e2a8..bd29c3231e28144eefa8d1242d9ee2c29e1f66bb 100644
--- a/Calorimeter/CaloRecGPU/python/CaloRecGPUFlags.py
+++ b/Calorimeter/CaloRecGPU/python/CaloRecGPUFlags.py
@@ -17,28 +17,93 @@ def createFlagsCaloRecGPU():
     """
 
     flags = AthConfigFlags()
+    flags.addFlagsCategory('CaloRecGPU.GlobalFlags', _createGlobalFlagsCaloRecGPU, prefix=True)
     flags.addFlagsCategory('CaloRecGPU.Default', _createDefaultSubFlagsCaloRecGPU, prefix=True)
-    flags.addFlagsCategory('CaloRecGPU.LocalCalibration', _createLCSubFlagsCaloRec, prefix=True)
-    flags.addFlagsCategory('CaloRecGPU.HLT', _createHLTSubFlagsCaloRec, prefix=True)
+    flags.addFlagsCategory('Trigger.CaloRecGPU.Default', _createTriggerSubFlagsCaloRecGPU, prefix=True)
+    #flags.addFlagsCategory('Trigger.CaloRecGPU.LC', _createTriggerSubFlagsCaloRecGPUWithLC, prefix=True)
+    flags.addFlagsCategory('CaloRecGPU.ActiveConfig', _createActiveConfigFlagsCaloRecGPU, prefix=True)
+    return flags
+    
+def _createGlobalFlagsCaloRecGPU():
+    """
+    Generate top-level flags for CaloRecGPU that are meant to be global
+    and independent of the ActiveConfig.
+    """
+    flags = AthConfigFlags()
+    
+    flags.addFlag('UseCaloRecGPU', False)
+    flags.addFlag('UseCPUToolsInstead', False)
+    
+    return flags
+    
+def _createActiveConfigFlagsCaloRecGPU():
+    """
+    Generate top-level flags for CaloRecGPU that are meant to be global
+    and independent of the ActiveConfig.
+    """
+    flags = AthConfigFlags()
+    
+    flags.addFlag('MeasureTimes', False)
+    
     return flags
 
-def _createLCSubFlagsCaloRec():
+def _createTriggerSubFlagsCaloRecGPU():
     """
-    Generate CaloRecGPU flags for a particular flag subdomain
+    Generate CaloRecGPU flags for a particular flag subdomain (the trigger in this case)
  
-    Calls the function to generate a new set of default CaloRecGPU flags, and then updates the defaults as required for this specific subdomain "LocalCalibration".
-    This _createLCSubFlagsCaloRec is provided as an example of a subdomain with an updated default value for the ClustersOutputName flag. 
+    Calls the function to generate a new set of default CaloRecGPU flags, and then updates the defaults as required for this specific subdomain.
     """
     flags = _createDefaultSubFlagsCaloRecGPU()
-    flags.ClustersOutputName = "CaloTopoClusters"
-    return flags 
-
-def _createHLTSubFlagsCaloRec():
-    flags = _createDefaultSubFlagsCaloRecGPU()
-    flags.CellsName = "CaloCellsFS"
-    flags.ClustersOutputName = "HLT_TopoCaloClustersFS"
+    flags.UseOriginalCriteria = False
+    flags.GrowingRestrictPSNeighbors = False
+    flags.GPUSplittingRestrictPSNeighbors = False
+    flags.doTimeCut = lambda prevFlags: prevFlags.Trigger.Calo.TopoCluster.doTimeCut
+    flags.extendTimeCut = lambda prevFlags: prevFlags.Trigger.Calo.TopoCluster.extendTimeCut
+    flags.useUpperLimitForTimeCut = lambda prevFlags: prevFlags.Trigger.Calo.TopoCluster.useUpperLimitForTimeCut
+    flags.timeCutUpperLimit = lambda prevFlags: prevFlags.Trigger.Calo.TopoCluster.timeCutUpperLimit
+    flags.MomentsToCalculate = ['FIRST_PHI',
+                                'FIRST_ETA',
+                                'SECOND_R' ,
+                                'SECOND_LAMBDA',
+                                'DELTA_PHI',
+                                'DELTA_THETA',
+                                'DELTA_ALPHA' ,
+                                'CENTER_X',
+                                'CENTER_Y',
+                                'CENTER_Z',
+                                'CENTER_MAG',
+                                'CENTER_LAMBDA',
+                                'LATERAL',
+                                'LONGITUDINAL',
+                                'FIRST_ENG_DENS',
+                                'ENG_FRAC_EM',
+                                'ENG_FRAC_MAX',
+                                'ENG_FRAC_CORE' ,
+                                'FIRST_ENG_DENS',
+                                'SECOND_ENG_DENS',
+                                'ISOLATION',
+                                'ENG_BAD_CELLS',
+                                'N_BAD_CELLS',
+                                'N_BAD_CELLS_CORR',
+                                'BAD_CELLS_CORR_E',
+                                'BADLARQ_FRAC',
+                                'ENG_POS',
+                                'SIGNIFICANCE',
+                                'CELL_SIGNIFICANCE',
+                                'CELL_SIG_SAMPLING',
+                                'AVG_LAR_Q',
+                                'AVG_TILE_Q'
+                                ]
+    flags.MomentsUseAbsEnergy = False
+    flags.doTopoClusterLocalCalib = False
     return flags
 
+
+#def _createTriggerSubFlagsCaloRecGPUWithLC():
+#    flags = _createTriggerSubFlagsCaloRecGPU()
+#    flags.doTopoClusterLocalCalib = True
+#    return flags
+
 def _createDefaultSubFlagsCaloRecGPU():
     """
     Generate a new default CaloRecGPU flags domain
@@ -47,42 +112,75 @@ def _createDefaultSubFlagsCaloRecGPU():
     Sets the most generic default parameters or default parameter lambda function logic for each flag, this can be overridden if needed by specific subdomains. 
     """
     flags = AthConfigFlags()
-    flags.addFlag('MeasureTimes', True)
-    flags.addFlag('CellsName', "AllCalo")
-    flags.addFlag('ClustersOutputName', "CaloCalTopoClusters")
+    
+    #GPU SPECIFIC FLAGS WITH NO CPU EQUIVALENT
+    
+    flags.addFlag('MeasureTimes', False)
+    #Output timing measurements,
+    #including the breakdown
+    #within the algorithms themselves.
+    
     flags.addFlag('FillMissingCells', False)
     flags.addFlag('MissingCellsToFill', [])
+    
+    flags.addFlag('NumPreAllocatedDataHolders', 0)
+    
+    flags.addFlag('UseOriginalCriteria', lambda prevFlags: not prevFlags.Calo.TopoCluster.UseGPUCompatibleCriteria)
+    #Restore instantiated CPU tools to their original, GPU-disagreeing criteria.
+    
+    #FLAGS THAT ENCAPSULATE CPU CONFIGURATION OPTIONS THAT ARE NOT FLAGS IN CPU CONFIGURATION
+    #(Most of them aren't strictly necessary and could be hard-coded in the Cfg,
+    # but CPU vs GPU testing benefits from having all this granularity.)
+    
+    flags.addFlag('SeedThreshold',4.0)
+    flags.addFlag('GrowThreshold',2.0)
+    flags.addFlag('TermThreshold',0.0)
+    flags.addFlag('UseAbsSeedThreshold',True)
+    flags.addFlag('UseAbsGrowThreshold',True)
+    flags.addFlag('UseAbsTermThreshold',True)
     flags.addFlag('ClusterSize', 'Topo_420')
-    flags.addFlag('ClusterEtorAbsEtCut', -1e-16*MeV)
-    flags.addFlag('CalorimeterNames', ["LAREM", "LARHEC", "LARFCAL", "TILE"])
-    flags.addFlag('TopoClusterSeedSamplingNames', ["PreSamplerB", "EMB1", "EMB2", "EMB3", "PreSamplerE", "EME1", "EME2", "EME3", "HEC0", "HEC1","HEC2", "HEC3", "TileBar0", "TileBar1", "TileBar2", "TileExt0", "TileExt1", "TileExt2", "TileGap1", "TileGap2", "TileGap3", "FCAL0", "FCAL1", "FCAL2"])
-    flags.addFlag('TopoClusterSNRSeedThreshold',4.0)
-    flags.addFlag('TopoClusterSNRGrowThreshold',2.0)
-    flags.addFlag('TopoClusterSNRCellThreshold',0.0)
-    flags.addFlag('TopoClusterSeedCutsInAbsE',True)
-    flags.addFlag('TopoClusterNeighborCutsInAbsE',True)
-    flags.addFlag('TopoClusterCellCutsInAbsE',True)
-    flags.addFlag('NeighborOption',"super3D")
-    flags.addFlag('RestrictHECIWandFCalNeighbors',False)
-    flags.addFlag('RestrictPSNeighbors',True)
-    flags.addFlag('AlsoRestrictPSOnGPUSplitter',False)
-    flags.addFlag('TwoGaussianNoise', lambda prevFlags: prevFlags.Calo.TopoCluster.doTwoGaussianNoise)
-    flags.addFlag('SeedCutsInT', lambda prevFlags: prevFlags.Calo.TopoCluster.doTimeCut)
-    flags.addFlag('CutOOTseed', lambda prevFlags: prevFlags.Calo.TopoCluster.extendTimeCut and prevFlags.Calo.TopoCluster.doTimeCut)
-    flags.addFlag('UseTimeCutUpperLimit', lambda prevFlags: prevFlags.Calo.TopoCluster.useUpperLimitForTimeCut)
-    flags.addFlag('TimeCutUpperLimit',20.0)
-    flags.addFlag('TreatL1PredictedCellsAsGood',True)
-    flags.addFlag('UseEM2CrossTalk',False)
-    flags.addFlag('CrossTalkDeltaT',15*ns)
-    flags.addFlag('SeedThresholdOnTAbs',12.5*ns)
-    flags.addFlag('SplitterNumberOfCellsCut',4)
-    flags.addFlag('SplitterEnergyCut',500*MeV)
-    flags.addFlag('SplitterSamplingNames',["EMB2", "EMB3", "EME2", "EME3", "FCAL0"])
-    flags.addFlag('SplitterSecondarySamplingNames',["EMB1","EME1", "TileBar0","TileBar1","TileBar2", "TileExt0","TileExt1","TileExt2", "HEC0","HEC1","HEC2","HEC3", "FCAL1","FCAL2"])
-    flags.addFlag('SplitterShareBorderCells',True)
-    flags.addFlag('EMShowerScale',5.0*cm)
-    flags.addFlag('SplitterUseNegativeClusters', lambda prevFlags: prevFlags.Calo.TopoCluster.doTreatEnergyCutAsAbsolute)
-    flags.addFlag('UseAbsEnergyMoments', lambda prevFlags: prevFlags.Calo.TopoCluster.doTreatEnergyCutAsAbsolute)
+    #There is the "getClusterSize" function on the C++ code
+    #that tries to guess based on the thresholds,
+    #we could either rely on that or do it also in Python?
+    
+    flags.addFlag('GrowingCalorimeterNames', ["LAREM", "LARHEC", "LARFCAL", "TILE"])
+    flags.addFlag('GrowingSeedSamplingNames', ["PreSamplerB", "EMB1", "EMB2", "EMB3", "PreSamplerE", "EME1", "EME2", "EME3", "HEC0", "HEC1","HEC2", "HEC3", "TileBar0", "TileBar1", "TileBar2", "TileExt0", "TileExt1", "TileExt2", "TileGap1", "TileGap2", "TileGap3", "FCAL0", "FCAL1", "FCAL2"])
+    flags.addFlag('GrowingNeighborOption',"super3D")
+    flags.addFlag('GrowingRestrictHECIWandFCalNeighbors',False)
+    flags.addFlag('GrowingRestrictPSNeighbors',True)
+    flags.addFlag('GrowingTreatL1PredictedCellsAsGood',True)
+    
+    flags.addFlag('GrowingTimeCutSeedThreshold',12.5*ns)
+    
+    flags.addFlag('PostGrowingClusterCutClustersInAbsEt', True)
+    flags.addFlag('PostGrowingClusterEnergyCut', -1e-16*MeV)
+    #CPU has default 0, but since the comparison is not inclusive,
+    #it's better if we consider a negative value so that both CPU and GPU
+    #agree 100% when doing the comparison in absolute energy,
+    #because otherwise floating point making clusters have zero energy 
+    #in one implementation and a tiny non-zero energy on another
+    #would mean different cuts, thus different cluster numbers,
+    #thus different splitting, and so on.
+    #This problem will remain for non-zero energy cuts,
+    #like other floating point agreement issues elsewhere.
+    
+    
+    flags.addFlag('SplittingNeighborOption',"super3D")
+    flags.addFlag('SplittingRestrictHECIWandFCalNeighbors',False)
+    flags.addFlag('SplittingTreatL1PredictedCellsAsGood',True)
+    
+    flags.addFlag('SplittingNumberOfCellsCut', 4)
+    flags.addFlag('SplittingEnergyCut', 500 * MeV)
+    flags.addFlag('SplittingSamplingNames',["EMB2", "EMB3", "EME2", "EME3", "FCAL0"])
+    flags.addFlag('SplittingSecondarySamplingNames',["EMB1","EME1", "TileBar0","TileBar1","TileBar2", "TileExt0","TileExt1","TileExt2", "HEC0","HEC1","HEC2","HEC3", "FCAL1","FCAL2"])
+    flags.addFlag('SplittingShareBorderCells',True)
+    flags.addFlag('SplittingEMShowerScale',5.0*cm)
+    flags.addFlag('SplittingUseNegativeClusters', lambda prevFlags: prevFlags.Calo.TopoCluster.doTreatEnergyCutAsAbsolute)
+    
+    flags.addFlag('GPUSplittingRestrictPSNeighbors',False)
+    #The CPU code does not apply this restriction, mostly for testing purposes
+    
+    flags.addFlag('MomentsUseAbsEnergy', lambda prevFlags: prevFlags.Calo.TopoCluster.doTreatEnergyCutAsAbsolute)
     flags.addFlag('MomentsMaxAxisAngle',20*deg)
     flags.addFlag('MomentsMinBadLArQuality',4000)
     MomentsToCalculateOnline=[ "FIRST_PHI",
@@ -124,11 +222,41 @@ def _createDefaultSubFlagsCaloRecGPU():
     flags.addFlag('MomentsToCalculate', lambda prevFlags: MomentsToCalculateOnline if prevFlags.Common.isOnline else MomentsToCalculateOffline )
     flags.addFlag('MomentsMinRLateral',4*cm)
     flags.addFlag('MomentsMinLLongitudinal',10*cm)
-    flags.addFlag('OutputCountsToFile',False)
-    flags.addFlag('OutputClustersToFile',True)
-    flags.addFlag('DoMonitoring',False)
-    flags.addFlag('NumPreAllocatedDataHolders', lambda prevFlags: max(prevFlags.Concurrency.NumThreads, 1)) # Avoids 0 when running serial athena
-    #If True, use the original criteria
-    #(which disagree with the GPU implementation)
-    flags.addFlag('UseOriginalCriteria',False)
+    
+    
+    #FLAGS THAT MIRROR CPU OPTIONS
+    
+    flags.addFlag('doTwoGaussianNoise', lambda prevFlags: prevFlags.Calo.TopoCluster.doTwoGaussianNoise)
+    
+    
+    flags.addFlag('doTimeCut', lambda prevFlags: prevFlags.Calo.TopoCluster.doTimeCut)
+    flags.addFlag('extendTimeCut', lambda prevFlags: prevFlags.Calo.TopoCluster.extendTimeCut)
+    
+    flags.addFlag('useUpperLimitForTimeCut', lambda prevFlags: prevFlags.Calo.TopoCluster.useUpperLimitForTimeCut)
+    
+    flags.addFlag('timeCutUpperLimit', lambda prevFlags: prevFlags.Calo.TopoCluster.timeCutUpperLimit)
+    
+    flags.addFlag('xtalkEM2', lambda prevFlags: prevFlags.Calo.TopoCluster.xtalkEM2)
+    flags.addFlag('xtalkEM2D', lambda prevFlags: prevFlags.Calo.TopoCluster.xtalkEM2D)
+    flags.addFlag('xtalkEM2n', lambda prevFlags: prevFlags.Calo.TopoCluster.xtalkEM2n)
+    flags.addFlag('xtalkEM3', lambda prevFlags: prevFlags.Calo.TopoCluster.xtalkEM3)
+    flags.addFlag('xtalkEMEta', lambda prevFlags: prevFlags.Calo.TopoCluster.xtalkEMEta)
+    flags.addFlag('xtalkDeltaT', lambda prevFlags: prevFlags.Calo.TopoCluster.xtalkDeltaT)
+    flags.addFlag('xtalk2Eratio1', lambda prevFlags: prevFlags.Calo.TopoCluster.xtalk2Eratio1)
+    flags.addFlag('xtalk2Eratio2', lambda prevFlags: prevFlags.Calo.TopoCluster.xtalk2Eratio2)
+    flags.addFlag('xtalk3Eratio', lambda prevFlags: prevFlags.Calo.TopoCluster.xtalk3Eratio)
+    flags.addFlag('xtalkEtaEratio', lambda prevFlags: prevFlags.Calo.TopoCluster.xtalkEtaEratio)
+    flags.addFlag('xtalk2DEratio', lambda prevFlags: prevFlags.Calo.TopoCluster.xtalk2DEratio)
+    
+    flags.addFlag('doTopoClusterLocalCalib', lambda prevFlags: prevFlags.Calo.TopoCluster.doTopoClusterLocalCalib)
+    flags.addFlag('doCalibHitMoments', lambda prevFlags: prevFlags.Calo.TopoCluster.doCalibHitMoments)
+    
+    flags.addFlag('skipWriteList', lambda prevFlags: prevFlags.Calo.TopoCluster.skipWriteList)
+    flags.addFlag('writeExtendedClusterMoments', lambda prevFlags: prevFlags.Calo.TopoCluster.writeExtendedClusterMoments)
+    flags.addFlag('writeCalibHitClusterMoments', lambda prevFlags: prevFlags.Calo.TopoCluster.writeCalibHitClusterMoments)
+    
+    flags.addFlag('addCalibrationHitDecoration', lambda prevFlags: prevFlags.Calo.TopoCluster.addCalibrationHitDecoration)
+    flags.addFlag('CalibrationHitDecorationName', lambda prevFlags: prevFlags.Calo.TopoCluster.CalibrationHitDecorationName)
+    flags.addFlag('addCPData', lambda prevFlags: prevFlags.Calo.TopoCluster.addCPData)
+    
     return flags
diff --git a/Calorimeter/CaloRecGPU/src/BasicEventDataGPUExporter.cxx b/Calorimeter/CaloRecGPU/src/BasicEventDataGPUExporter.cxx
index 7c6a4ff2aba302ec41609cf6eb7cf28c1fa5e9fc..83214622cebb4711c2143ba5b1998f2c6c371ac8 100644
--- a/Calorimeter/CaloRecGPU/src/BasicEventDataGPUExporter.cxx
+++ b/Calorimeter/CaloRecGPU/src/BasicEventDataGPUExporter.cxx
@@ -32,7 +32,7 @@ StatusCode BasicEventDataGPUExporter::initialize()
   //ATH_CHECK(m_noiseCDOKey.initialize());
   //For Two Gaussian Noise comparisons.
   
-  ATH_CHECK( m_cellsKey.value().initialize() );
+  ATH_CHECK( m_cellsKey.initialize() );
 
   ATH_CHECK( detStore()->retrieve(m_calo_id, "CaloCell_ID") );
 
@@ -117,7 +117,7 @@ StatusCode BasicEventDataGPUExporter::convert(const EventContext & ctx,
           export_cell(cell, cell_index);
         }
     }
-  else if (m_missingCellsToFill.size() > 0)
+  else if (cell_collection->isOrdered() && m_missingCellsToFill.size() > 0)
     //Remediated: we know the missing cells, force them to be invalid.
     //(Tests so far, on samples both oldish and newish, had 186986 and 187352 missing...)
     {
@@ -188,11 +188,12 @@ StatusCode BasicEventDataGPUExporter::convert(const EventContext & ctx,
   //std::cout << "-------------------------------------------------------------------------- END" << std::endl;
 
   const auto post_cells = clock_type::now();
+  
+  ed.m_clusters.allocate();
+  ed.m_cell_state.allocate();
 
   if (cluster_collection->size() > 0)
     {
-      ed.m_clusters.allocate();
-      ed.m_cell_state.allocate();
 
       for (int i = 0; i < NCaloCells; ++i)
         {
diff --git a/Calorimeter/CaloRecGPU/src/BasicEventDataGPUExporter.h b/Calorimeter/CaloRecGPU/src/BasicEventDataGPUExporter.h
index ff80a869a70c275b5785284bc949c91ad36c37b7..2c1013cd85baa00008e6a519d0e2fb856ece107e 100644
--- a/Calorimeter/CaloRecGPU/src/BasicEventDataGPUExporter.h
+++ b/Calorimeter/CaloRecGPU/src/BasicEventDataGPUExporter.h
@@ -54,7 +54,7 @@ class BasicEventDataGPUExporter :
   /**
    * @brief vector of names of the cell containers to use as input.
    */
-  Gaudi::Property<SG::ReadHandleKey<CaloCellContainer>> m_cellsKey {this, "CellsName", "", "Name(s) of Cell Containers"};
+  SG::ReadHandleKey<CaloCellContainer> m_cellsKey {this, "CellsName", "", "Name(s) of Cell Containers"};
 
   /** @brief If @p true, into account the possibility of a cell being shared between clusters.
    *  Hurts performance when not needed.
diff --git a/Calorimeter/CaloRecGPU/src/BasicGPUClusterInfoCalculatorImpl.cu b/Calorimeter/CaloRecGPU/src/BasicGPUClusterInfoCalculatorImpl.cu
index 77d05cd79bcd276495d17dae49d9908ff034894b..f43184349bab2eb4ddfe73ddb963eaf59dcb79ac 100644
--- a/Calorimeter/CaloRecGPU/src/BasicGPUClusterInfoCalculatorImpl.cu
+++ b/Calorimeter/CaloRecGPU/src/BasicGPUClusterInfoCalculatorImpl.cu
@@ -83,7 +83,7 @@ void BasicClusterInfoCalculator::updateSeedCellProperties(CaloRecGPU::EventDataH
                                                           const bool synchronize,
                                                           CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream)
 {
-  const cudaStream_t & stream_to_use = (stream != nullptr ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
+  const cudaStream_t & stream_to_use = (stream ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
 
   const CUDAKernelLaunchConfiguration launch_config = optimizer.get_launch_configuration("BasicClusterInfoCalculator", 0);
 
@@ -285,7 +285,7 @@ void BasicClusterInfoCalculator::calculateClusterProperties(CaloRecGPU::EventDat
                                                             const bool cut_in_absolute_ET, const float ET_threshold,
                                                             CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream)
 {
-  const cudaStream_t & stream_to_use = (stream != nullptr ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
+  const cudaStream_t & stream_to_use = (stream ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
 
   const CUDAKernelLaunchConfiguration cfg_calculate = optimizer.get_launch_configuration("BasicClusterInfoCalculator", 1);
   const CUDAKernelLaunchConfiguration cfg_finalize  = optimizer.get_launch_configuration("BasicClusterInfoCalculator", 2);
diff --git a/Calorimeter/CaloRecGPU/src/BasicGPUToAthenaImporter.cxx b/Calorimeter/CaloRecGPU/src/BasicGPUToAthenaImporter.cxx
index 04b798264473738dfa223f997880ec01ca1e52e3..cd14c4ecf77678087548ad2becb5b30b39383327 100644
--- a/Calorimeter/CaloRecGPU/src/BasicGPUToAthenaImporter.cxx
+++ b/Calorimeter/CaloRecGPU/src/BasicGPUToAthenaImporter.cxx
@@ -34,7 +34,7 @@ BasicGPUToAthenaImporter::BasicGPUToAthenaImporter(const std::string & type, con
 
 StatusCode BasicGPUToAthenaImporter::initialize()
 {
-  ATH_CHECK( m_cellsKey.value().initialize() );
+  ATH_CHECK( m_cellsKey.initialize() );
 
   ATH_CHECK( detStore()->retrieve(m_calo_id, "CaloCell_ID") );
 
@@ -139,62 +139,75 @@ StatusCode BasicGPUToAthenaImporter::convert (const EventContext & ctx,
     }
 
   const auto after_creation = clock_type::now();
+  
+  
+  //cell_index is the actual cell index in the full set of cells (identifier hash)
+  //cell_count is the cell position in the cell collection (what we want for the weight)
+  const auto process_cell = [&](const int cell_index, const int cell_count)
+  {
+    const ClusterTag this_tag = ed.m_cell_state->clusterTag[cell_index];
+    if (this_tag.is_part_of_cluster())
+      {
+        const int this_index = this_tag.cluster_index();
+        const int32_t weight_pattern = this_tag.secondary_cluster_weight();
+
+        float tempf = 1.0f;
+
+        std::memcpy(&tempf, &weight_pattern, sizeof(float));
+        //C++20 would give us bit cast to do this more properly.
+        //Still, given how the bit pattern is created,
+        //it should be safe.
+
+        const float reverse_weight = tempf;
+
+        const float this_weight = 1.0f - reverse_weight;
+
+        if (cell_links[this_index])
+          {
+            cell_links[this_index]->addCell(cell_count, this_weight);
+
+            if (cell_index == ed.m_clusters->seedCellID[this_index] && cell_links[this_index]->size() > 1)
+              //Seed cells aren't shared,
+              //so no need to check this on the other case.
+              {
+                CaloClusterCellLink::iterator begin_it = cell_links[this_index]->begin();
+                CaloClusterCellLink::iterator back_it  = std::prev(cell_links[this_index]->end());
+
+                const unsigned int first_idx = begin_it.index();
+                const double first_wgt = begin_it.weight();
+
+                begin_it.reindex(back_it.index());
+                begin_it.reweight(back_it.weight());
+
+                back_it.reindex(first_idx);
+                back_it.reweight(first_wgt);
+
+                //Of course, this is to ensure the first cell is the seed cell,
+                //in accordance to the way some cluster properties
+                //(mostly phi-related) are calculated.
+              }
+          }
+
+        if (this_tag.is_shared_between_clusters())
+          {
+            const int other_index = this_tag.secondary_cluster_index();
+            if (cell_links[other_index])
+              {
+                cell_links[other_index]->addCell(cell_count, reverse_weight);
+              }
+          }
+      }
+  };
 
   if (cell_collection->isOrderedAndComplete())
     //Fast path: cell indices within the collection and identifierHashes match!
     {
       for (int cell_index = 0; cell_index < NCaloCells; ++cell_index)
         {
-          const ClusterTag this_tag = ed.m_cell_state->clusterTag[cell_index];
-
-          if (this_tag.is_part_of_cluster())
-            {
-              const int this_index = this_tag.cluster_index();
-              const int32_t weight_pattern = this_tag.secondary_cluster_weight();
-
-              float tempf = 1.0f;
-
-              std::memcpy(&tempf, &weight_pattern, sizeof(float));
-              //C++20 would give us bit cast to do this more properly.
-              //Still, given how the bit pattern is created,
-              //it should be safe.
-
-              const float reverse_weight = tempf;
-
-              const float this_weight = 1.0f - reverse_weight;
-
-              cell_links[this_index]->addCell(cell_index, this_weight);
-
-              if (cell_index == ed.m_clusters->seedCellID[this_index] && cell_links[this_index]->size() > 1)
-                //Seed cells aren't shared,
-                //so no need to check this on the other case.
-                {
-                  CaloClusterCellLink::iterator begin_it = cell_links[this_index]->begin();
-                  CaloClusterCellLink::iterator back_it  = (--cell_links[this_index]->end());
-
-                  const unsigned int first_idx = begin_it.index();
-                  const double first_wgt = begin_it.weight();
-
-                  begin_it.reindex(back_it.index());
-                  begin_it.reweight(back_it.weight());
-
-                  back_it.reindex(first_idx);
-                  back_it.reweight(first_wgt);
-
-                  //Of course, this is to ensure the first cell is the seed cell,
-                  //in accordance to the way some cluster properties
-                  //(mostly phi-related) are calculated.
-                }
-
-              if (this_tag.is_shared_between_clusters())
-                {
-                  const int other_index = this_tag.secondary_cluster_index();
-                  cell_links[other_index]->addCell(cell_index, reverse_weight);
-                }
-            }
+          process_cell(cell_index, cell_index);
         }
     }
-  else if (m_missingCellsToFill.size() > 0)
+  else if (cell_collection->isOrdered() && m_missingCellsToFill.size() > 0)
     {
       size_t missing_cell_count = 0;
       for (int cell_index = 0; cell_index < NCaloCells; ++cell_index)
@@ -204,53 +217,7 @@ StatusCode BasicGPUToAthenaImporter::convert (const EventContext & ctx,
               ++missing_cell_count;
               continue;
             }
-          const ClusterTag this_tag = ed.m_cell_state->clusterTag[cell_index];
-
-          if (this_tag.is_part_of_cluster())
-            {
-              const int this_index = this_tag.cluster_index();
-              const int32_t weight_pattern = this_tag.secondary_cluster_weight();
-
-              float tempf = 1.0f;
-
-              std::memcpy(&tempf, &weight_pattern, sizeof(float));
-              //C++20 would give us bit cast to do this more properly.
-              //Still, given how the bit pattern is created,
-              //it should be safe.
-
-              const float reverse_weight = tempf;
-
-              const float this_weight = 1.0f - reverse_weight;
-
-              cell_links[this_index]->addCell(cell_index - missing_cell_count, this_weight);
-
-              if (cell_index == ed.m_clusters->seedCellID[this_index] && cell_links[this_index]->size() > 1)
-                //Seed cells aren't shared,
-                //so no need to check this on the other case.
-                {
-                  CaloClusterCellLink::iterator begin_it = cell_links[this_index]->begin();
-                  CaloClusterCellLink::iterator back_it  = (--cell_links[this_index]->end());
-
-                  const unsigned int first_idx = begin_it.index();
-                  const double first_wgt = begin_it.weight();
-
-                  begin_it.reindex(back_it.index());
-                  begin_it.reweight(back_it.weight());
-
-                  back_it.reindex(first_idx);
-                  back_it.reweight(first_wgt);
-
-                  //Of course, this is to ensure the first cell is the seed cell,
-                  //in accordance to the way some cluster properties
-                  //(mostly phi-related) are calculated.
-                }
-
-              if (this_tag.is_shared_between_clusters())
-                {
-                  const int other_index = this_tag.secondary_cluster_index();
-                  cell_links[other_index]->addCell(cell_index - missing_cell_count, reverse_weight);
-                }
-            }
+          process_cell(cell_index, cell_index - missing_cell_count);
         }
     }
   else
@@ -264,55 +231,8 @@ StatusCode BasicGPUToAthenaImporter::convert (const EventContext & ctx,
 
           //const int cell_index = m_calo_id->calo_cell_hash(cell->ID());
           const int cell_index = cell->caloDDE()->calo_hash();
-
-          const ClusterTag this_tag = ed.m_cell_state->clusterTag[cell_index];
-
-          if (this_tag.is_part_of_cluster())
-            {
-              const int this_index = this_tag.cluster_index();
-              const int32_t weight_pattern = this_tag.secondary_cluster_weight();
-
-              float tempf = 1.0f;
-
-              std::memcpy(&tempf, &weight_pattern, sizeof(float));
-              //C++20 would give us bit cast to do this more properly.
-              //Still, given how the bit pattern is created,
-              //it should be safe.
-
-              const float reverse_weight = tempf;
-
-              const float this_weight = 1.0f - reverse_weight;
-
-              cell_links[this_index]->addCell(cell_count, this_weight);
-              //So we put this in the right cell link.
-
-              if (cell_index == ed.m_clusters->seedCellID[this_index] && cell_links[this_index]->size() > 1)
-                //Seed cells aren't shared,
-                //so no need to check this on the other case.
-                {
-                  CaloClusterCellLink::iterator begin_it = cell_links[this_index]->begin();
-                  CaloClusterCellLink::iterator back_it  = (--cell_links[this_index]->end());
-
-                  const unsigned int first_idx = begin_it.index();
-                  const double first_wgt = begin_it.weight();
-
-                  begin_it.reindex(back_it.index());
-                  begin_it.reweight(back_it.weight());
-
-                  back_it.reindex(first_idx);
-                  back_it.reweight(first_wgt);
-
-                  //Of course, this is to ensure the first cell is the seed cell,
-                  //in accordance to the way some cluster properties
-                  //(mostly phi-related) are calculated.
-                }
-
-              if (this_tag.is_shared_between_clusters())
-                {
-                  const int other_index = this_tag.secondary_cluster_index();
-                  cell_links[other_index]->addCell(cell_count, reverse_weight);
-                }
-            }
+                 
+          process_cell(cell_index, cell_count);
         }
     }
   const auto after_cells = clock_type::now();
@@ -377,6 +297,15 @@ StatusCode BasicGPUToAthenaImporter::convert (const EventContext & ctx,
               cluster->setEta(ed.m_clusters->clusterEta[cluster_index]);
               cluster->setPhi(ed.m_clusters->clusterPhi[cluster_index]);
             }
+
+          if (m_saveUncalibrated)
+            {
+              cluster->setRawE(cluster->calE());
+              cluster->setRawEta(cluster->calEta());
+              cluster->setRawPhi(cluster->calPhi());
+              cluster->setRawM(cluster->calM());
+            }
+
         }
 
     }
@@ -412,4 +341,4 @@ StatusCode BasicGPUToAthenaImporter::finalize()
 BasicGPUToAthenaImporter::~BasicGPUToAthenaImporter()
 {
   //Nothing!
-}
\ No newline at end of file
+}
diff --git a/Calorimeter/CaloRecGPU/src/BasicGPUToAthenaImporter.h b/Calorimeter/CaloRecGPU/src/BasicGPUToAthenaImporter.h
index 0fc1a475754584ad013eae6a393015f06cbfc6d4..2058adafc2dcbea339cf6d6005290e4669804e91 100644
--- a/Calorimeter/CaloRecGPU/src/BasicGPUToAthenaImporter.h
+++ b/Calorimeter/CaloRecGPU/src/BasicGPUToAthenaImporter.h
@@ -59,7 +59,7 @@ class BasicGPUToAthenaImporter :
   /**
    * @brief vector of names of the cell containers to use as input.
    */
-  Gaudi::Property<SG::ReadHandleKey<CaloCellContainer>> m_cellsKey {this, "CellsName", "", "Name(s) of Cell Containers"};
+  SG::ReadHandleKey<CaloCellContainer> m_cellsKey {this, "CellsName", "", "Name(s) of Cell Containers"};
 
   /// Cluster size. Should be set accordingly to the threshold.
   Gaudi::Property<std::string> m_clusterSizeString {this, "ClusterSize", "Topo_420", "The size/type of the clusters"};
@@ -75,6 +75,10 @@ class BasicGPUToAthenaImporter :
    */
   const CaloCell_ID * m_calo_id {nullptr};
 
+  /**
+  * @brief if set to true, the uncalibrated state is saved when importing the clusters. Default is @p true.
+  */
+  Gaudi::Property<bool> m_saveUncalibrated {this, "SaveUncalibratedSignalState", true, "Use CaloClusterKineHelper::calculateKine instead of GPU-calculated cluster properties"};
 
 };
 
diff --git a/Calorimeter/CaloRecGPU/src/CUDA_Helpers.cu b/Calorimeter/CaloRecGPU/src/CUDA_Helpers.cu
index 7de0f128668df1b7ecbdf32545e7dc8a07d169b7..89f7deb08e73dbf6d46e9aa388ef7bd07ba6a8ff 100644
--- a/Calorimeter/CaloRecGPU/src/CUDA_Helpers.cu
+++ b/Calorimeter/CaloRecGPU/src/CUDA_Helpers.cu
@@ -51,25 +51,25 @@ void CaloRecGPU::CUDA_Helpers::GPU_to_GPU(void * dest, const void * const source
 
 void CaloRecGPU::CUDA_Helpers::GPU_to_CPU_async(void * dest, const void * const source, const size_t num, CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream)
 {
-  const cudaStream_t & stream_to_use = (stream != nullptr ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
+  const cudaStream_t & stream_to_use = (stream ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
   CUDA_ERRCHECK(cudaMemcpyAsync(dest, source, num, cudaMemcpyDeviceToHost, cudaStreamPerThread));
 }
 
 void CaloRecGPU::CUDA_Helpers::CPU_to_GPU_async(void * dest, const void * const source, const size_t num, CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream)
 {
-  const cudaStream_t & stream_to_use = (stream != nullptr ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
+  const cudaStream_t & stream_to_use = (stream ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
   CUDA_ERRCHECK(cudaMemcpyAsync(dest, source, num, cudaMemcpyHostToDevice, stream_to_use));
 }
 
 void CaloRecGPU::CUDA_Helpers::GPU_to_GPU_async(void * dest, const void * const source, const size_t num, CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream)
 {
-  const cudaStream_t & stream_to_use = (stream != nullptr ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
+  const cudaStream_t & stream_to_use = (stream ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
   CUDA_ERRCHECK(cudaMemcpyAsync(dest, source, num, cudaMemcpyDeviceToDevice, stream_to_use));
 }
 
 void CaloRecGPU::CUDA_Helpers::GPU_synchronize(CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream)
 {
-  const cudaStream_t & stream_to_use = (stream != nullptr ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
+  const cudaStream_t & stream_to_use = (stream ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
   CUDA_ERRCHECK(cudaStreamSynchronize(stream_to_use));
 }
 
diff --git a/Calorimeter/CaloRecGPU/src/CaloCPUOutput.cxx b/Calorimeter/CaloRecGPU/src/CaloCPUOutput.cxx
index d88869d3bebda888966621548bfebfa449cd44c1..c272d1b06906b3b98232a542c4e5cc695440a620 100644
--- a/Calorimeter/CaloRecGPU/src/CaloCPUOutput.cxx
+++ b/Calorimeter/CaloRecGPU/src/CaloCPUOutput.cxx
@@ -21,7 +21,7 @@ CaloCPUOutput::CaloCPUOutput(const std::string & type, const std::string & name,
 
 StatusCode CaloCPUOutput::initialize()
 {
-  ATH_CHECK( m_cellsKey.value().initialize() );
+  ATH_CHECK( m_cellsKey.initialize() );
 
   ATH_CHECK( detStore()->retrieve(m_calo_id, "CaloCell_ID") );
 
diff --git a/Calorimeter/CaloRecGPU/src/CaloCPUOutput.h b/Calorimeter/CaloRecGPU/src/CaloCPUOutput.h
index 912f4f420a3512cffb233c5a4e09cc073b60d370..99398ad3cac43d56d9fe3596b5f1a91446a2f8a0 100644
--- a/Calorimeter/CaloRecGPU/src/CaloCPUOutput.h
+++ b/Calorimeter/CaloRecGPU/src/CaloCPUOutput.h
@@ -77,7 +77,7 @@ class CaloCPUOutput :
     /**
    * @brief vector of names of the cell containers to use as input.
    */
-  Gaudi::Property<SG::ReadHandleKey<CaloCellContainer>> m_cellsKey {this, "CellsName", "", "Name(s) of Cell Containers"};
+  SG::ReadHandleKey<CaloCellContainer> m_cellsKey {this, "CellsName", "", "Name(s) of Cell Containers"};
   
   /**
    * @brief Pointer to Calo ID Helper
diff --git a/Calorimeter/CaloRecGPU/src/CaloCellsCounterCPU.cxx b/Calorimeter/CaloRecGPU/src/CaloCellsCounterCPU.cxx
index 0a7eea2ba1e133ce8def0df435f309e18a0a9baf..2c546fcf7139c9085be55c032eb1f4c9e237ab8e 100644
--- a/Calorimeter/CaloRecGPU/src/CaloCellsCounterCPU.cxx
+++ b/Calorimeter/CaloRecGPU/src/CaloCellsCounterCPU.cxx
@@ -25,7 +25,7 @@ CaloCellsCounterCPU::CaloCellsCounterCPU(const std::string & type, const std::st
 StatusCode CaloCellsCounterCPU::initialize()
 {
   ATH_CHECK( m_noiseCDOKey.initialize() );
-  ATH_CHECK( m_cellsKey.value().initialize() );
+  ATH_CHECK( m_cellsKey.initialize() );
   ATH_CHECK( detStore()->retrieve(m_calo_id, "CaloCell_ID") );
   return StatusCode::SUCCESS;
 }
diff --git a/Calorimeter/CaloRecGPU/src/CaloCellsCounterCPU.h b/Calorimeter/CaloRecGPU/src/CaloCellsCounterCPU.h
index c19f9f453e40955ca6670fc385861ad5bd7a8ace..0839539a6438aa45a769bb9f747386a38ac95b10 100644
--- a/Calorimeter/CaloRecGPU/src/CaloCellsCounterCPU.h
+++ b/Calorimeter/CaloRecGPU/src/CaloCellsCounterCPU.h
@@ -66,7 +66,7 @@ class CaloCellsCounterCPU :
     /**
    * @brief vector of names of the cell containers to use as input.
    */
-  Gaudi::Property<SG::ReadHandleKey<CaloCellContainer>> m_cellsKey {this, "CellsName", "", "Name(s) of Cell Containers"};
+  SG::ReadHandleKey<CaloCellContainer> m_cellsKey {this, "CellsName", "", "Name(s) of Cell Containers"};
   
   /** @brief Key of the CaloNoise Conditions data object. Typical values
       are '"electronicNoise', 'pileupNoise', or '"totalNoise' (default)
diff --git a/Calorimeter/CaloRecGPU/src/CaloClusterStoreRawProperties.cxx b/Calorimeter/CaloRecGPU/src/CaloClusterStoreRawProperties.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..2ae6ac6853bb38948d78ffa5c0cc2542544f7e70
--- /dev/null
+++ b/Calorimeter/CaloRecGPU/src/CaloClusterStoreRawProperties.cxx
@@ -0,0 +1,33 @@
+//
+// Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+//
+// Dear emacs, this is -*- c++ -*-
+//
+
+#include "CaloClusterStoreRawProperties.h"
+
+CaloClusterStoreRawProperties::CaloClusterStoreRawProperties(const std::string & type, const std::string & name, const IInterface * parent):
+  AthAlgTool(type, name, parent)
+{
+  declareInterface<CaloClusterCollectionProcessor> (this);
+}
+
+StatusCode CaloClusterStoreRawProperties::execute (const EventContext &, xAOD::CaloClusterContainer * cluster_collection) const
+{
+  for (xAOD::CaloCluster* cluster : *cluster_collection)
+  {
+    cluster->setRawE(cluster->calE());
+    cluster->setRawEta(cluster->calEta());
+    cluster->setRawPhi(cluster->calPhi());
+    cluster->setRawM(cluster->calM());
+  }
+
+  return StatusCode::SUCCESS;
+
+}
+
+
+CaloClusterStoreRawProperties::~CaloClusterStoreRawProperties()
+{
+  //Nothing!
+}
diff --git a/Calorimeter/CaloRecGPU/src/CaloClusterStoreRawProperties.h b/Calorimeter/CaloRecGPU/src/CaloClusterStoreRawProperties.h
new file mode 100644
index 0000000000000000000000000000000000000000..d311bb40a178d96365cf2dd1aa6205df270a3634
--- /dev/null
+++ b/Calorimeter/CaloRecGPU/src/CaloClusterStoreRawProperties.h
@@ -0,0 +1,41 @@
+//
+// Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+//
+// Dear emacs, this is -*- c++ -*-
+//
+
+#ifndef CALORECGPU_CALOCLUSTERSTORERAWPROPERTIES_H
+#define CALORECGPU_CALOCLUSTERSTORERAWPROPERTIES_H
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "CaloUtils/CaloClusterCollectionProcessor.h"
+
+/**
+ * @class CaloClusterStoreRawProperties
+ * @author Nuno Fernandes <nuno.dos.santos.fernandes@cern.ch>
+ * @date 29 February 2024
+ * @brief Stores the current (calibrated) cluster energies and coordinates
+ *        as raw properties.
+ * 
+ * @remark The standard CPU code does this in the cluster making algorithm,
+ *         our GPU code optionally does this in the cluster importing tool,
+ *         but instantiating the CPU code in a HybridClusterProcessor
+ *         requires doing this if we want to run later stages of the reconstruction...
+ */
+
+class CaloClusterStoreRawProperties :
+  public AthAlgTool, virtual public CaloClusterCollectionProcessor
+{
+ public:
+
+  CaloClusterStoreRawProperties(const std::string & type, const std::string & name, const IInterface * parent);
+  
+  using CaloClusterCollectionProcessor::execute;
+  
+  virtual StatusCode execute (const EventContext& ctx, xAOD::CaloClusterContainer* cluster_collection) const override;
+
+  virtual ~CaloClusterStoreRawProperties();
+
+};
+
+#endif //CALORECGPU_CALOCPUOUTPUT_H
diff --git a/Calorimeter/CaloRecGPU/src/CaloGPUClusterAndCellDataMonitor.cxx b/Calorimeter/CaloRecGPU/src/CaloGPUClusterAndCellDataMonitor.cxx
index ff51924ddbb7b7b6dda8ff4d7c246ae7c488ccf3..81abbd13fd9ad445390c4702d9ebe3a02e91793c 100644
--- a/Calorimeter/CaloRecGPU/src/CaloGPUClusterAndCellDataMonitor.cxx
+++ b/Calorimeter/CaloRecGPU/src/CaloGPUClusterAndCellDataMonitor.cxx
@@ -31,7 +31,7 @@ CaloGPUClusterAndCellDataMonitor::CaloGPUClusterAndCellDataMonitor(const std::st
 
 StatusCode CaloGPUClusterAndCellDataMonitor::initialize()
 {
-  ATH_CHECK( m_cellsKey.value().initialize() );
+  ATH_CHECK( m_cellsKey.initialize() );
 
   ATH_CHECK( detStore()->retrieve(m_calo_id, "CaloCell_ID") );
 
diff --git a/Calorimeter/CaloRecGPU/src/CaloGPUClusterAndCellDataMonitor.h b/Calorimeter/CaloRecGPU/src/CaloGPUClusterAndCellDataMonitor.h
index 023113350f08d110c4bf2dd1d8d987a916971658..718278d40bab24cf4d735c6d3e32d2f7a91de99f 100644
--- a/Calorimeter/CaloRecGPU/src/CaloGPUClusterAndCellDataMonitor.h
+++ b/Calorimeter/CaloRecGPU/src/CaloGPUClusterAndCellDataMonitor.h
@@ -201,7 +201,7 @@ class CaloGPUClusterAndCellDataMonitor :
   /**
   * @brief vector of names of the cell containers to use as input.
   */
-  Gaudi::Property<SG::ReadHandleKey<CaloCellContainer>> m_cellsKey {this, "CellsName", "", "Name(s) of Cell Containers"};
+  SG::ReadHandleKey<CaloCellContainer> m_cellsKey {this, "CellsName", "", "Name(s) of Cell Containers"};
 
   /** @brief Monitoring tool.
     */
diff --git a/Calorimeter/CaloRecGPU/src/CaloGPUClusterAndCellDataMonitorOptions.h b/Calorimeter/CaloRecGPU/src/CaloGPUClusterAndCellDataMonitorOptions.h
index 2df3bc156104174ea9ee2c59eb033b0732d647f5..329d6635ed3624ef4b70a6c2f524123606a1d725 100644
--- a/Calorimeter/CaloRecGPU/src/CaloGPUClusterAndCellDataMonitorOptions.h
+++ b/Calorimeter/CaloRecGPU/src/CaloGPUClusterAndCellDataMonitorOptions.h
@@ -26,17 +26,6 @@
 
 #include <Gaudi/Parsers/Factory.h>
 
-namespace Gaudi
-{
-  namespace Parsers
-  {
-    template <typename Iterator, typename Skipper, class Enable>
-    struct Grammar_<Iterator, SG::ReadHandleKey<CaloCellContainer>, Skipper, Enable>
-    {
-      using Grammar = typename Grammar_<Iterator, std::string, Skipper, Enable>::Grammar;
-    };
-  }
-}
 //Suppress the warning that comes up from simply including Factory.h.
 
 //First, generic handling of tuples.
diff --git a/Calorimeter/CaloRecGPU/src/CaloGPUHybridClusterProcessor.cxx b/Calorimeter/CaloRecGPU/src/CaloGPUHybridClusterProcessor.cxx
index 3f7077b834868eab477507f9eac63372b5b97ed2..7653f252f4963062977950ddaac7a49927932a7c 100644
--- a/Calorimeter/CaloRecGPU/src/CaloGPUHybridClusterProcessor.cxx
+++ b/Calorimeter/CaloRecGPU/src/CaloGPUHybridClusterProcessor.cxx
@@ -16,9 +16,13 @@
 #include <new>
 
 #include "xAODCaloEvent/CaloClusterContainer.h"
+#include "xAODTrigCalo/CaloClusterTrigAuxContainer.h"
+
 #include "CaloEvent/CaloClusterCellLinkContainer.h"
 #include "CaloUtils/CaloClusterStoreHelper.h"
 
+#include "StoreGate/WriteDecorHandle.h"
+
 #include "boost/chrono/chrono.hpp"
 #include "boost/chrono/thread_clock.hpp"
 
@@ -28,9 +32,7 @@ CaloGPUHybridClusterProcessor::CaloGPUHybridClusterProcessor(const std::string &
   AthReentrantAlgorithm(name, pSvcLocator),
   CaloGPUTimed(this),
   m_temporariesSize(0),
-  m_constantDataSent(false),
-  m_preConvert(true),
-  m_postConvert(true)
+  m_constantDataSent(false)
 {
 
 }
@@ -76,26 +78,44 @@ StatusCode CaloGPUHybridClusterProcessor::initialize()
 
 
   bool checker = true;
-  retrieve_and_report(m_transformConstantData, "constant data to GPU transformer", checker);
-  if (!checker)
-    {
-      ATH_MSG_ERROR("No constant data transformer, error!");
-      any_failed = true;
-    }
+
   retrieve_and_report(m_preGPUoperations, "pre-GPU operations", checker);
-  retrieve_and_report(m_transformForGPU, "event data to GPU transformer", m_preConvert);
   retrieve_and_report(m_GPUoperations, "GPU operations", checker);
-  retrieve_and_report(m_transformBackToCPU, "GPU to Athena transformer", m_postConvert);
   retrieve_and_report(m_postGPUoperations, "post-GPU operations", checker);
 
+  if (!m_skipConversions)
+    {
+      retrieve_and_report(m_transformConstantData, "constant data to GPU transformer", checker);
+      retrieve_and_report(m_transformForGPU, "event data to GPU transformer", checker);
+      retrieve_and_report(m_transformBackToCPU, "GPU to Athena transformer", checker);
+    }
+  else
+    {
+      m_transformConstantData.disable();
+      m_transformForGPU.disable();
+      m_transformBackToCPU.disable();
+    }
+
   if (m_doPlots)
     {
+      checker = true;
       retrieve_and_report(m_plotterTool, "plotter tool", checker);
+      m_doPlots = checker;
+    }
+  else
+    {
+      m_plotterTool.disable();
     }
 
   if (m_doMonitoring)
     {
+      checker = true;
       retrieve_and_report(m_moniTool, "monitoring tool", checker);
+      m_doMonitoring = checker;
+    }
+  else
+    {
+      m_moniTool.disable();
     }
 
   if (any_failed)
@@ -103,9 +123,11 @@ StatusCode CaloGPUHybridClusterProcessor::initialize()
       return StatusCode::FAILURE;
     }
 
-  ATH_CHECK( m_avgMuKey.initialize() );
+  ATH_CHECK(m_avgMuKey.initialize(m_doMonitoring));
+  ATH_CHECK(m_noiseCDOKey.initialize(m_doMonitoring && m_monitorCells));
+  ATH_CHECK(m_cellsKey.initialize(m_doMonitoring && m_monitorCells));
 
-  if (!m_deferConstantDataToFirstEvent)
+  if (!m_deferConstantDataToFirstEvent && !m_skipConversions)
     {
       ATH_CHECK( m_transformConstantData->initialize() );
       //Not sure if this is needed or the tool will get initialized by this point.
@@ -144,20 +166,51 @@ StatusCode CaloGPUHybridClusterProcessor::initialize()
       //But the main point is really reducing the execute times...
     }
 
+  if (m_writeTriggerSpecificInfo)
+    {
+      m_mDecor_ncells = m_clusterOutput.key() + "." + m_mDecor_ncells.key();
+    }
+  
+  ATH_CHECK(m_mDecor_ncells.initialize(m_writeTriggerSpecificInfo));
+
   return StatusCode::SUCCESS;
 }
 
 
 StatusCode CaloGPUHybridClusterProcessor::execute(const EventContext & ctx) const
 {
+  auto time_tot = Monitored::Timer("TIME_execute");
+  auto time_clusMaker = Monitored::Timer("TIME_ClustMaker");
+  auto time_clusCorr = Monitored::Timer("TIME_ClustCorr");
+  //No good way to not declare this here at the outer scope
+  //since we do need the timers to be available when we do our operations.
+  //Also: contrary to what the CPU does, we don't have a clear distinction
+  //between what is cluster making and cluster corrections;
+  //for now, ClustMaker = Pre-GPU + (CPU -> GPU) + GPU Tools + (GPU -> CPU)
+  //and ClustCorr = Post-GPU...
+
+  if (m_doMonitoring)
+    {
+      time_tot.start();
+    }
+
+
   SG::WriteHandle<xAOD::CaloClusterContainer> cluster_collection (m_clusterOutput, ctx);
 
-  ATH_CHECK(CaloClusterStoreHelper::AddContainerWriteHandle(cluster_collection));
+  if (m_writeTriggerSpecificInfo)
+    {
+      ATH_CHECK( cluster_collection.record (std::make_unique<xAOD::CaloClusterContainer>(),  std::make_unique<xAOD::CaloClusterTrigAuxContainer> () ));
+    }
+  else
+    {
+      ATH_CHECK(CaloClusterStoreHelper::AddContainerWriteHandle(cluster_collection));
+    }
+
   //ATH_CHECK(CaloClusterStoreHelper::AddContainerWriteHandle(&(*evtStore()), cluster_collection, msg()));
 
   xAOD::CaloClusterContainer * cluster_collection_ptr = cluster_collection.ptr();
 
-  if (m_deferConstantDataToFirstEvent && !m_constantDataSent.load())
+  if (m_deferConstantDataToFirstEvent && !m_skipConversions && !m_constantDataSent.load())
     {
       std::lock_guard<std::mutex> lock_guard(m_mutex);
       if (!m_constantDataSent.load())
@@ -174,32 +227,35 @@ StatusCode CaloGPUHybridClusterProcessor::execute(const EventContext & ctx) cons
   //This is a RAII wrapper to access an object held by Helpers::separate_thread_holder,
   //to ensure the event data is appropriately released when we are done processing.
 
-  if (event_data_ptr == nullptr && (m_preConvert || m_postConvert || m_GPUoperations.size()))
+  if (event_data_ptr == nullptr && !m_skipConversions)
     {
       ATH_MSG_ERROR("Could not get valid Event Data Holder! Event: " << ctx.evt() );
       return StatusCode::FAILURE;
     }
-
+  
+  if (!m_skipConversions)
+    {
+      event_data_ptr->allocate(true);
+      //No-op if already allocated.
+    }
 
   simple_GPU_pointer_holder * temporaries_data_ptr_holder = nullptr;
 
   Helpers::separate_thread_accessor<simple_GPU_pointer_holder> sep_th_acc_2(m_temporariesThreadedHolder, temporaries_data_ptr_holder);
   if (!temporaries_data_ptr_holder)
-  {
-    ATH_MSG_ERROR("temporaries_data_ptr_holder is null in CaloGPUHybridClusterProcessor::execute" );
-    return StatusCode::FAILURE;
-  }
+    {
+      ATH_MSG_ERROR("temporaries_data_ptr_holder is null in CaloGPUHybridClusterProcessor::execute" );
+      return StatusCode::FAILURE;
+    }
   temporaries_data_ptr_holder->allocate(m_temporariesSize);
   //This will not perform any allocations if they've already been done.
 
-  if ( (temporaries_data_ptr_holder->get_pointer() == nullptr)   &&
-       (m_preConvert || m_postConvert || m_GPUoperations.size()) &&
-       m_temporariesSize > 0                                         )
+  if ( (temporaries_data_ptr_holder->get_pointer() == nullptr) && !m_skipConversions && m_temporariesSize > 0 )
     {
       ATH_MSG_ERROR("Could not get valid temporary buffer holder! Event: " << ctx.evt() );
       return StatusCode::FAILURE;
     }
-
+  
   const ConstantDataHolder & constant_data_holder ATLAS_THREAD_SAFE = m_constantData;
   //Just to shut up the checker. We know what we are doing...
 
@@ -215,7 +271,7 @@ StatusCode CaloGPUHybridClusterProcessor::execute(const EventContext & ctx) cons
 
   if (m_measureTimes)
     {
-      const size_t time_size = m_preGPUoperations.size() + m_GPUoperations.size() + m_postGPUoperations.size() + m_doPlots + m_preConvert + m_postConvert;
+      const size_t time_size = m_preGPUoperations.size() + m_GPUoperations.size() + m_postGPUoperations.size() + m_doPlots + 2 * !m_skipConversions;
       //+2 for the conversions
       //+1 for the plotter (only added at the end)
       times.reserve(time_size);
@@ -232,7 +288,11 @@ StatusCode CaloGPUHybridClusterProcessor::execute(const EventContext & ctx) cons
         }
     }
 
-
+  if (m_doMonitoring)
+    {
+      time_clusMaker.start();
+    }
+    
   for (const auto & pre_GPU_tool : m_preGPUoperations)
     {
       auto t1 = clock_type::now();
@@ -254,7 +314,7 @@ StatusCode CaloGPUHybridClusterProcessor::execute(const EventContext & ctx) cons
         }
     }
 
-  if (m_preConvert)
+  if (!m_skipConversions)
     {
       auto t3 = clock_type::now();
       ATH_CHECK( m_transformForGPU->convert(ctx, constant_data_holder, cluster_collection_ptr, *event_data_ptr) );
@@ -297,7 +357,7 @@ StatusCode CaloGPUHybridClusterProcessor::execute(const EventContext & ctx) cons
         }
     }
 
-  if (m_postConvert)
+  if (!m_skipConversions)
     {
       auto t7 = clock_type::now();
       ATH_CHECK( m_transformBackToCPU->convert(ctx, constant_data_holder, *event_data_ptr, cluster_collection_ptr) );
@@ -319,6 +379,12 @@ StatusCode CaloGPUHybridClusterProcessor::execute(const EventContext & ctx) cons
         }
     }
 
+  if (m_doMonitoring)
+    {
+      time_clusMaker.stop();
+      time_clusCorr.start();
+    }
+
   for (const auto & post_GPU_tool : m_postGPUoperations)
     {
       auto t9 = clock_type::now();
@@ -350,33 +416,74 @@ StatusCode CaloGPUHybridClusterProcessor::execute(const EventContext & ctx) cons
           plot_time += time_cast(t1, t2);
         }
     }
+  
+  if (m_writeTriggerSpecificInfo)
+    {
+      SG::WriteDecorHandle<xAOD::CaloClusterContainer, int> decor_handle(m_mDecor_ncells, ctx);
+      
+      for (const xAOD::CaloCluster * cl : *cluster_collection_ptr)
+        {
+          const CaloClusterCellLink* cell_links = cl->getCellLinks();
+          if (!cell_links)
+            {
+              decor_handle(*cl) = 0;
+            }
+          else
+            {
+              decor_handle(*cl) = cell_links->size();
+            }
+        }
+    }
+
+  ATH_MSG_DEBUG("Created cluster container with " << cluster_collection->size() << " clusters");
+
+  SG::WriteHandle<CaloClusterCellLinkContainer> cell_links(m_clusterCellLinkOutput, ctx);
 
+  ATH_CHECK( CaloClusterStoreHelper::finalizeClusters(cell_links, cluster_collection.ptr()) );
 
+  if (m_measureTimes)
+    {
+      if (m_doPlots)
+        {
+          times.push_back(plot_time);
+        }
+      record_times(ctx.evt(), times);
+    }
 
   if (m_doMonitoring)
     //For monitoring.
-    //Taken from TrigCaloClusterMaker from TrigCaloRec.
     {
-      auto mon_container_size = Monitored::Scalar( "container_size", 0. );
-      auto mon_clusEt = Monitored::Collection( "Et", *cluster_collection_ptr, &xAOD::CaloCluster::et );
-      auto mon_clusSignalState = Monitored::Collection( "signalState", *cluster_collection_ptr, &xAOD::CaloCluster::signalState );
-      auto mon_clusSize = Monitored::Collection( "clusterSize", *cluster_collection_ptr, &xAOD::CaloCluster::clusterSize );
+      time_clusCorr.stop();
+
+      auto mon_clusEt = Monitored::Collection("Et", *cluster_collection_ptr, &xAOD::CaloCluster::et);
+      auto mon_clusSignalState = Monitored::Collection("signalState", *cluster_collection_ptr, &xAOD::CaloCluster::signalState);
+      auto mon_clusSize = Monitored::Collection("clusterSize", *cluster_collection_ptr, &xAOD::CaloCluster::clusterSize);
       std::vector<double>       clus_phi;
       std::vector<double>       clus_eta;
       std::vector<double>       N_BAD_CELLS;
       std::vector<double>       ENG_FRAC_MAX;
       std::vector<unsigned int> sizeVec;
-      auto mon_clusPhi = Monitored::Collection( "Phi", clus_phi );
-      auto mon_clusEta = Monitored::Collection( "Eta", clus_eta );
-      auto mon_badCells = Monitored::Collection( "N_BAD_CELLS", N_BAD_CELLS );
-      auto mon_engFrac = Monitored::Collection( "ENG_FRAC_MAX", N_BAD_CELLS );
-      auto mon_size = Monitored::Collection( "size", sizeVec );
-      auto monmu = Monitored::Scalar( "mu", -999.0 );
-      auto monitorIt = Monitored::Group( m_moniTool, mon_container_size, mon_clusEt,
-                                         mon_clusPhi, mon_clusEta, mon_clusSignalState, mon_clusSize,
-                                         mon_badCells, mon_engFrac, mon_size, monmu );
+      auto mon_clusPhi = Monitored::Collection("Phi", clus_phi);
+      auto mon_clusEta = Monitored::Collection("Eta", clus_eta);
+      auto mon_badCells = Monitored::Collection("N_BAD_CELLS", N_BAD_CELLS);
+      auto mon_engFrac = Monitored::Collection("ENG_FRAC_MAX", N_BAD_CELLS);
+      auto mon_size = Monitored::Collection("size", sizeVec);
+      auto monmu = Monitored::Scalar("mu", -999.0);
+      auto mon_container_size = Monitored::Scalar("container_size", 0.);
+      auto moncount_1thrsigma = Monitored::Scalar("count_1thrsigma", -999.0);
+      auto moncount_2thrsigma = Monitored::Scalar("count_2thrsigma", -999.0);
+      auto mon_container_size_by_mu  = Monitored::Scalar("container_size_by_mu", 0.);
+      auto moncount_1thrsigma_by_mu2 = Monitored::Scalar("count_1thrsigma_by_mu2", -999.0);
+      auto moncount_2thrsigma_by_mu2 = Monitored::Scalar("count_2thrsigma_by_mu2", -999.0);
+      auto monitorIt = Monitored::Group( m_moniTool, time_tot, time_clusMaker, time_clusCorr, mon_container_size,
+                                         mon_clusEt, mon_clusPhi, mon_clusEta, mon_clusSignalState, mon_clusSize,
+                                         mon_badCells, mon_engFrac, mon_size, monmu,  moncount_1thrsigma, moncount_2thrsigma,
+                                         mon_container_size_by_mu, moncount_1thrsigma_by_mu2, moncount_2thrsigma_by_mu2 );
       // fill monitored variables
-      for (xAOD::CaloCluster * cl : *cluster_collection_ptr)
+      
+      mon_container_size = cluster_collection_ptr->size();
+      
+      for (const xAOD::CaloCluster * cl : *cluster_collection_ptr)
         {
           const CaloClusterCellLink * num_cell_links = cl->getCellLinks();
           if (! num_cell_links)
@@ -392,28 +499,63 @@ StatusCode CaloGPUHybridClusterProcessor::execute(const EventContext & ctx) cons
           N_BAD_CELLS.push_back(cl->getMomentValue(xAOD::CaloCluster::N_BAD_CELLS));
           ENG_FRAC_MAX.push_back(cl->getMomentValue(xAOD::CaloCluster::ENG_FRAC_MAX));
         }
+      
+      float read_mu = 0;
+        
       SG::ReadDecorHandle<xAOD::EventInfo, float> eventInfoDecor(m_avgMuKey, ctx);
       if (eventInfoDecor.isPresent())
         {
-          monmu = eventInfoDecor(0);
+          read_mu = eventInfoDecor(0);
+          monmu = read_mu;
         }
-      mon_container_size = cluster_collection_ptr->size();
-    }
-
-  if (m_measureTimes)
-    {
-      if (m_doPlots)
+        
+      
+      int count_1thrsigma = 0, count_2thrsigma = 0;
+      
+      if (m_monitorCells)
         {
-          times.push_back(plot_time);
+          SG::ReadHandle<CaloCellContainer> cell_collection(m_cellsKey, ctx);
+          if ( !cell_collection.isValid() )
+            {
+              ATH_MSG_ERROR( " Cannot retrieve CaloCellContainer: " << cell_collection.name()  );
+              return StatusCode::RECOVERABLE;
+            }
+          
+          SG::ReadCondHandle<CaloNoise> noiseHdl{m_noiseCDOKey, ctx};
+          const CaloNoise * noisep = *noiseHdl;
+          for (const auto & cell : *cell_collection)
+            {
+              const CaloDetDescrElement * cdde = cell->caloDDE();
+              if (cdde->is_tile())
+                {
+                  continue;
+                }
+              float thr = noisep->getNoise(cdde->identifyHash(), cell->gain());
+              if (cell->energy() > m_monitoring1thr * thr)
+                {
+                  count_1thrsigma += 1;
+                  if (cell->energy() > m_monitoring2thr * thr)
+                    {
+                      count_2thrsigma += 1;
+                    }
+                }
+            }
+        }
+      
+      moncount_1thrsigma = count_1thrsigma;
+      moncount_2thrsigma = count_2thrsigma;
+      
+      if (read_mu > 5)
+        {
+          const float rev_mu = 1.f/read_mu;
+          mon_container_size_by_mu = rev_mu * cluster_collection_ptr->size();
+          const float sqr_rev_mu = rev_mu * rev_mu;
+          moncount_1thrsigma_by_mu2 = sqr_rev_mu * count_1thrsigma;
+          moncount_2thrsigma_by_mu2 = sqr_rev_mu * count_2thrsigma;
         }
-      record_times(ctx.evt(), times);
-    }
-
-  ATH_MSG_DEBUG("Created cluster container with " << cluster_collection->size() << " clusters");
-
-  SG::WriteHandle<CaloClusterCellLinkContainer> cell_links(m_clusterCellLinkOutput, ctx);
 
-  ATH_CHECK( CaloClusterStoreHelper::finalizeClusters(cell_links, cluster_collection.ptr()) );
+      time_tot.stop();
+    }
 
   return StatusCode::SUCCESS;
 }
@@ -436,7 +578,7 @@ StatusCode CaloGPUHybridClusterProcessor::finalize()
           add_name_to_string(pre_GPU_tool);
         }
 
-      if (m_preConvert)
+      if (!m_skipConversions)
         {
           add_name_to_string(m_transformForGPU);
         }
@@ -446,7 +588,7 @@ StatusCode CaloGPUHybridClusterProcessor::finalize()
           add_name_to_string(GPU_tool);
         }
 
-      if (m_postConvert)
+      if (!m_skipConversions)
         {
           add_name_to_string(m_transformBackToCPU);
         }
@@ -461,7 +603,7 @@ StatusCode CaloGPUHybridClusterProcessor::finalize()
           add_name_to_string(m_plotterTool);
         }
 
-      print_times(header_string, m_preGPUoperations.size() + m_GPUoperations.size() + m_postGPUoperations.size() + m_preConvert + m_postConvert + m_doPlots);
+      print_times(header_string, m_preGPUoperations.size() + m_GPUoperations.size() + m_postGPUoperations.size() + 2 * !m_skipConversions + m_doPlots);
     }
 
   if (m_doPlots)
diff --git a/Calorimeter/CaloRecGPU/src/CaloGPUHybridClusterProcessor.h b/Calorimeter/CaloRecGPU/src/CaloGPUHybridClusterProcessor.h
index 993a4d4fd0cb37ece6334694047257774606d1a3..240b21cd5daeb2aa3b0ded4505e5f5cac106a26e 100644
--- a/Calorimeter/CaloRecGPU/src/CaloGPUHybridClusterProcessor.h
+++ b/Calorimeter/CaloRecGPU/src/CaloGPUHybridClusterProcessor.h
@@ -23,6 +23,9 @@
 #include "xAODCaloEvent/CaloClusterContainer.h"
 
 #include "StoreGate/ReadDecorHandle.h"
+#include "StoreGate/WriteDecorHandleKey.h"
+
+#include "CaloConditions/CaloNoise.h"
 
 #include <string>
 #include <mutex>
@@ -110,14 +113,28 @@ class CaloGPUHybridClusterProcessor : public AthReentrantAlgorithm, public CaloG
   /** @brief If @p true, uses the monitoring tool specified by @p m_monitorTool.
     */
   Gaudi::Property<bool> m_doMonitoring{this, "DoMonitoring", false, "Do monitoring."};
+  Gaudi::Property<bool> m_monitorCells{this, "MonitorCells", false, "Whether to monitor cells too."};
+  Gaudi::Property<float> m_monitoring1thr { this, "Thr1", 2, "First Threshold to pass for cell monitoring" };
+  Gaudi::Property<float> m_monitoring2thr { this, "Thr2", 4, "Second Threshold to pass for cell monitoring" };
+
+
+  // adding noise handle for monitoring purposes
+  SG::ReadCondHandleKey<CaloNoise> m_noiseCDOKey{this, "CaloNoiseKey", "totalNoise", "SG Key of CaloNoise data object"};
 
   /** @brief Monitoring tool.
     */
-  ToolHandle< GenericMonitoringTool > m_moniTool { this, "MonitoringTool", "", "Monitoring tool" };
+  ToolHandle<GenericMonitoringTool> m_moniTool { this, "MonitoringTool", "", "Monitoring tool" };
 
   ///Event input: To get <mu> from Event Info
   SG::ReadDecorHandleKey<xAOD::EventInfo> m_avgMuKey { this, "averageInteractionsPerCrossingKey", "EventInfo.averageInteractionsPerCrossing", "Decoration for Average Interaction Per Crossing" };
 
+  /** @brief If @p true, writes some trigger-specific decorations.
+    */
+  Gaudi::Property<bool> m_writeTriggerSpecificInfo{this, "WriteTriggerSpecificInfo", false, "Write some trigger-specific decorations and use the trigger auxiliary container."};
+
+  /** @brief Key to the handle for writing the number of cells as a decoration.
+    */
+  SG::WriteDecorHandleKey<xAOD::CaloClusterContainer> m_mDecor_ncells {this, "Decor_ncells", "nCells", "Decorator containing the number of cells associated to a cluster"};
 
   /**
    * @brief Number of events for which to pre-allocate space on GPU memory
@@ -125,19 +142,30 @@ class CaloGPUHybridClusterProcessor : public AthReentrantAlgorithm, public CaloG
    *
    */
   Gaudi::Property<size_t> m_numPreAllocatedGPUData{this, "NumPreAllocatedDataHolders", 0, "Number of event data holders to pre-allocate on GPU memory"};
+
+  /**
+   * @brief vector of names of the cell containers to use as input.
+   */
+  SG::ReadHandleKey<CaloCellContainer> m_cellsKey {this, "CellsName", "", "Name(s) of Cell Containers"};
+
   /** @brief The name of the key in StoreGate for the output
       CaloClusterContainer */
   SG::WriteHandleKey<xAOD::CaloClusterContainer> m_clusterOutput {this, "ClustersOutputName", "", "The name of the key in StoreGate for the output CaloClusterContainer"};
 
   /** @brief The name of the key in StoreGate for the output
       CaloClusterCellLinkContainer */
-  SG::WriteHandleKey<CaloClusterCellLinkContainer> m_clusterCellLinkOutput{this, "ClusterCellLinkOutputName", "", "The name of the key in StoreGate for the output CaloClusterCellLinkContainer"};
+  SG::WriteHandleKey<CaloClusterCellLinkContainer> m_clusterCellLinkOutput{this, "ClusterCellLinksOutputName", "", "The name of the key in StoreGate for the output CaloClusterCellLinkContainer"};
 
   /** @brief If @p true, the constant data is only converted and
       sent to the GPU on the first event, in case not all the necessary
       information is available during the @p initialize phase.
       */
-  Gaudi::Property<bool> m_deferConstantDataToFirstEvent {this, "DeferConstantDataPreparationToFirstEvent", true, "Convert and send event data on first event instead of during initialize (needed for exporting geometry and noise properly?)"};
+  Gaudi::Property<bool> m_deferConstantDataToFirstEvent {this, "DeferConstantDataPreparationToFirstEvent", true, "Convert and send event data on first event instead of during initialize (needed for exporting geometry and noise properly)?"};
+
+
+  /** @brief If @p true, both constant and event data conversion is skipped.
+      */
+  Gaudi::Property<bool> m_skipConversions {this, "SkipConversions", false, "If true, skip converting CPU to GPU data (useful if only instanting CPU tools)"};
 
   /** @brief A way to reduce allocations over multiple threads by keeping a cache
   *   of previously allocated objects that get assigned to the threads as they need them.
@@ -237,9 +265,6 @@ class CaloGPUHybridClusterProcessor : public AthReentrantAlgorithm, public CaloG
     */
   mutable std::mutex m_mutex;
 
-  ///@brief Do pre or post conversions of energy? (Used internally to ensure the conversion tools are given.)
-  bool m_preConvert, m_postConvert;
-
 };
 
 #endif //CALORECGPU_CALOGPUHYBRIDCLUSTERPROCESSOR_H
diff --git a/Calorimeter/CaloRecGPU/src/CaloTopoClusterSplitterGPU.cxx b/Calorimeter/CaloRecGPU/src/CaloTopoClusterSplitterGPU.cxx
deleted file mode 100644
index 0fd04c552ab17bdbcaa2baf3a6da0523cb5852cc..0000000000000000000000000000000000000000
--- a/Calorimeter/CaloRecGPU/src/CaloTopoClusterSplitterGPU.cxx
+++ /dev/null
@@ -1,219 +0,0 @@
-//
-// Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
-//
-// Dear emacs, this is -*- c++ -*-
-//
-
-#include "CaloTopoClusterSplitterGPU.h"
-#include "CaloTopoClusterSplitterGPUImpl.h"
-
-
-#include <string>
-#include <climits> //For CHAR_BIT... though it's a slightly inefficient way of saying 8.
-
-#include "CaloIdentifier/CaloCell_ID.h"
-
-#include "boost/chrono/chrono.hpp"
-#include "boost/chrono/thread_clock.hpp"
-
-#include "MacroHelpers.h"
-
-using namespace CaloRecGPU;
-
-CaloTopoClusterSplitterGPU::CaloTopoClusterSplitterGPU(const std::string & type, const std::string & name, const IInterface * parent):
-  AthAlgTool(type, name, parent),
-  CaloGPUTimed(this)
-{
-  declareInterface<CaloClusterGPUProcessor> (this);
-}
-
-StatusCode CaloTopoClusterSplitterGPU::initialize()
-{
-
-  m_options.allocate();
-
-
-  using PackType = decltype(m_options.m_options->m_useSampling);
-
-  static_assert(CaloCell_ID::getNumberOfSamplings() <= sizeof(PackType) * CHAR_BIT,  "We are assuming that we have fewer samplings that bits per int!");
-
-  auto get_option_from_string = [](const std::string & str, bool & failed)
-  {
-    failed = false;
-    CRGPU_RECURSIVE_MACRO(
-            CRGPU_CHEAP_STRING_TO_ENUM( str, CaloCell_ID,
-                                        PreSamplerB,
-                                        EMB1,
-                                        EMB2,
-                                        EMB3,
-                                        PreSamplerE,
-                                        EME1,
-                                        EME2,
-                                        EME3,
-                                        HEC0,
-                                        HEC1,
-                                        HEC2,
-                                        HEC3,
-                                        TileBar0,
-                                        TileBar1,
-                                        TileBar2,
-                                        TileGap1,
-                                        TileGap2,
-                                        TileGap3,
-                                        TileExt0,
-                                        TileExt1,
-                                        TileExt2,
-                                        FCAL0,
-                                        FCAL1,
-                                        FCAL2
-                                      )
-    )
-    else
-      {
-        failed = true;
-        return CaloCell_ID::Unknown;
-      }
-  };
-
-
-  auto process_sampling = [&get_option_from_string](const std::vector<std::string> & sampling_names, std::string & invalid_names, PackType & sampling_option)
-  {
-    sampling_option = 0;
-    for (const std::string & samp_name : sampling_names)
-      {
-        bool failed = false;
-        const PackType sampling = (PackType) get_option_from_string(samp_name, failed);
-
-        if (failed)
-          {
-            if (invalid_names.size() == 0)
-              {
-                invalid_names = "'" + samp_name + "'";
-              }
-            else
-              {
-                invalid_names += ", '" + samp_name + "'";
-              }
-          }
-        else
-          {
-            sampling_option |= ((PackType) 1) << sampling;
-          }
-      }
-  };
-
-  std::string invalid_names;
-
-  process_sampling(m_samplingNames, invalid_names, m_options.m_options->m_useSampling);
-
-  if (invalid_names.size() > 0)
-    {
-      ATH_MSG_ERROR( "Calorimeter samplings " << invalid_names
-                     << " are not a valid Calorimeter sampling name and will be ignored! "
-                     << "Valid names are: "
-                     << "PreSamplerB, EMB1, EMB2, EMB3, "
-                     << "PreSamplerE, EME1, EME2, EME3, "
-                     << "HEC0, HEC1, HEC2, HEC3, "
-                     << "TileBar0, TileBar1, TileBar2, "
-                     << "TileGap1, TileGap2, TileGap3, "
-                     << "TileExt0, TileExt1, TileExt2, "
-                     << "FCAL0, FCAL1, FCAL2."  );
-    }
-
-  invalid_names.clear();
-
-  process_sampling(m_secondarySamplingNames, invalid_names, m_options.m_options->m_useSecondarySampling);
-
-  if (invalid_names.size() > 0)
-    {
-      ATH_MSG_ERROR( "Calorimeter samplings " << invalid_names
-                     << " are not a valid Calorimeter sampling name and will be ignored! "
-                     << "Valid names are: "
-                     << "PreSamplerB, EMB1, EMB2, EMB3, "
-                     << "PreSamplerE, EME1, EME2, EME3, "
-                     << "HEC0, HEC1, HEC2, HEC3, "
-                     << "TileBar0, TileBar1, TileBar2, "
-                     << "TileGap1, TileGap2, TileGap3, "
-                     << "TileExt0, TileExt1, TileExt2, "
-                     << "FCAL0, FCAL1, FCAL2."  );
-    }
-
-
-  //We must repeat this printing part because ATH_MSG_ERROR
-  //is a macro that apparently calls a this->msg(...) function.
-  //Of course it won't work within a lambda...
-
-  m_options.m_options->m_nCells = m_nCells;
-  m_options.m_options->m_minEnergy = m_minEnergy;
-  m_options.m_options->m_emShowerScale = m_emShowerScale;
-  m_options.m_options->m_shareBorderCells = m_shareBorderCells;
-  m_options.m_options->m_absOpt = m_absOpt;
-  m_options.m_options->m_treatL1PredictedCellsAsGood = m_treatL1PredictedCellsAsGood;
-
-  m_options.sendToGPU();
-
-  return StatusCode::SUCCESS;
-
-}
-
-StatusCode CaloTopoClusterSplitterGPU::execute(const EventContext & ctx, const ConstantDataHolder & constant_data,
-                                               EventDataHolder & event_data, void * temporary_buffer                ) const
-{
-
-  using clock_type = boost::chrono::thread_clock;
-  auto time_cast = [](const auto & before, const auto & after)
-  {
-    return boost::chrono::duration_cast<boost::chrono::microseconds>(after - before).count();
-  };
-
-  const auto start = clock_type::now();
-
-  Helpers::CUDA_kernel_object<GPUSplitterTemporaries> temporaries((GPUSplitterTemporaries *) temporary_buffer);
-
-  preProcessingPreparation(event_data, temporaries, constant_data, m_options, m_measureTimes);
-
-  const auto before_maxima = clock_type::now();
-
-  findLocalMaxima(event_data, temporaries, constant_data, m_options, m_measureTimes);
-
-  const auto before_propagate = clock_type::now();
-
-  propagateTags(event_data, temporaries, constant_data, m_options, m_measureTimes);
-
-  const auto before_refill = clock_type::now();
-
-  refillClusters(event_data, temporaries, constant_data, m_options, m_measureTimes);
-
-  const auto end = clock_type::now();
-
-
-  if (m_measureTimes)
-    {
-      record_times(ctx.evt(),
-                   time_cast(start, before_maxima),
-                   time_cast(before_maxima, before_propagate),
-                   time_cast(before_propagate, before_refill),
-                   time_cast(before_refill, end)
-                  );
-    }
-
-  return StatusCode::SUCCESS;
-
-
-}
-
-
-StatusCode CaloTopoClusterSplitterGPU::finalize()
-{
-  if (m_measureTimes)
-    {
-      print_times("Preprocessing Find_Local_Maxima Splitter_Tag_Propagation Cluster_Refilling", 4);
-    }
-  return StatusCode::SUCCESS;
-}
-
-
-CaloTopoClusterSplitterGPU::~CaloTopoClusterSplitterGPU()
-{
-  //Nothing!
-}
diff --git a/Calorimeter/CaloRecGPU/src/CaloTopoClusterSplitterGPU.h b/Calorimeter/CaloRecGPU/src/CaloTopoClusterSplitterGPU.h
deleted file mode 100644
index 5677317b113289f7097e1c336c1b4bd4ffab0dc8..0000000000000000000000000000000000000000
--- a/Calorimeter/CaloRecGPU/src/CaloTopoClusterSplitterGPU.h
+++ /dev/null
@@ -1,147 +0,0 @@
-//
-// Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
-//
-// Dear emacs, this is -*- c++ -*-
-//
-
-
-#ifndef CALORECGPU_CALOTOPOCLUSTERSPLITTERGPU_H
-#define CALORECGPU_CALOTOPOCLUSTERSPLITTERGPU_H
-
-#include "AthenaBaseComps/AthAlgTool.h"
-
-#include "CLHEP/Units/SystemOfUnits.h"
-
-#include "CxxUtils/checker_macros.h"
-
-#include "CaloRecGPU/CaloClusterGPUProcessor.h"
-#include "CaloRecGPU/CaloGPUTimed.h"
-#include "CaloTopoClusterSplitterGPUImpl.h"
-#include <string>
-#include <mutex>
-
-/**
- * @class CaloTopoClusterSplitterGPU
- * @author Cosmin-Gabriel Samoila <cosmin.samoila@cern.ch> (Algorithm & Implementation)
- * @author Nuno Fernandes <nuno.dos.santos.fernandes@cern.ch> (Interfacing with the rest of the GPU code)
- * @date 08 August 2022
- * @brief Cluster splitter algorithm to be run on GPUs.
- */
-
-
-class CaloTopoClusterSplitterGPU :
-  public AthAlgTool, virtual public CaloClusterGPUProcessor, public CaloGPUTimed
-{
- public:
-
-  CaloTopoClusterSplitterGPU(const std::string & type, const std::string & name, const IInterface * parent);
-
-  virtual StatusCode initialize() override;
-
-  virtual StatusCode execute (const EventContext & ctx,
-                              const CaloRecGPU::ConstantDataHolder & constant_data,
-                              CaloRecGPU::EventDataHolder & event_data,
-                              void * temporary_buffer) const override;
-
-  virtual StatusCode finalize() override;
-
-  virtual ~CaloTopoClusterSplitterGPU();
-
-  virtual size_t size_of_temporaries() const
-  {
-    return sizeof(GPUSplitterTemporaries);
-  };
-
- private:
-
-
-  /**
-   * @brief vector of names of the calorimeter samplings to consider
-   * for seeds.
-   *
-   * The default is to use all calorimeter samplings. Excluding a
-   * sampling from this vector prevents the definition of a seed cell
-   * in this sampling. Cells in those samplings are still used and
-   * incorporated in the topo clusters (both on the neighbor and the
-   * cell level) they can therefore even expand a cluster but not seed
-   * one ...*/
-  Gaudi::Property<std::vector<std::string>>  m_samplingNames {this, "SamplingNames", {}, "Name(s) of Calorimeter Samplings to consider for local maxima"};
-
-  /**
-   * @brief vector of names of the secondary calorimeter samplings to
-   * consider.
-   *
-   * Samplings in this list will be considered for local maxima only
-   * if no local max in the primary list is overlapping. By default this
-   * list is empty  */
-  Gaudi::Property<std::vector<std::string>> m_secondarySamplingNames {this, "SecondarySamplingNames", {}, "Name(s) of secondary Calorimeter Samplings to consider for local maxima"};
-
-  /**
-   * @brief local maxima need at least this number of neighbors to
-   * become seeds
-   *
-   * each cell above the energy cut having at least this many
-   * neighbors in the parent cluster and only neighbors with smaller
-   * energy seed a split cluster. */
-  Gaudi::Property<int> m_nCells {this, "NumberOfCellsCut", 4, "Local maxima need at least this number of neighbors to become seeds"};
-
-  /**
-   * @brief local maxima need at least this energy content
-   *
-   * potential seed cells have to pass this cut on the energy
-   * content. */
-  Gaudi::Property<float> m_minEnergy {this, "EnergyCut", 500 * CLHEP::MeV, "Minimal energy for a local max"};
-
-
-  /**
-   * @brief share cells at the border between two local maxima
-   *
-   * this property needs to be set to true in order to treat cells
-   * which would be included in 2 clusters (for more then 2 the 2 with
-   * the largest E for the current seed cells are used) as shared
-   * cells. Shared cells are first excluded from the clustering and
-   * then clustered after all normal cells are clustered. The shared
-   * clusters are added to the 2 clusters they neighbor with the
-   * weights \f$w_1 = E_1/(E_1+r E_2)\f$ and \f$w_2 = 1-w_1\f$, where
-   * \f$E_{1,2}\f$ are the current energies of the 2 neighboring
-   * clusters without the shared cells and \f$r=\exp(d_1-d_2)\f$ is
-   * the ratio of the expected dependencies on the distances \f$d_i\f$
-   * (in units of a typical em shower scale) of each shared cell to
-   * the cluster centers. If the property is set to false the border
-   * cells are included in the normal clustering and the cluster with
-   * the largest E for the current seed cells gets the current border
-   * cell. */
-  Gaudi::Property<bool> m_shareBorderCells {this, "ShareBorderCells", false, "Whether or not to share cells at the boundary between two clusters"};
-
-
-  /**
-   * @brief typical EM shower scale to use for distance criteria in
-   * shared cells
-   *
-   * a shared cell is included in both clusters neighboring the cell
-   * with weights depending on the cluster energies and the distance
-   * of the shared cell to the cluster centroids. The distance is
-   * measured in units of this property to roughly describe the
-   * exponential slope of the energy density distribution for em
-   * showers. The exact choice of this property is not critical but
-   * should roughly match the Moliere radius in the LArEM since here
-   * the sharing of cells has the biggest use case. */
-  Gaudi::Property<float> m_emShowerScale {this, "EMShowerScale", 5 * CLHEP::cm, "Typical EM shower distance for which the energy density should drop to 1/e"};
-
-  /**
-   * @brief if set to true, splitter only looks at absolute
-   * value of Energy in order to identify potential seed cells */
-  Gaudi::Property<bool> m_absOpt {this, "WeightingOfNegClusters", false, "Should absolute value be used to identify potential seed cells"};
-
-  /**
-   * @brief if set to true treat cells with a dead OTX which can be
-   * predicted by L1 trigger info as good instead of bad cells */
-  Gaudi::Property<bool> m_treatL1PredictedCellsAsGood {this, "TreatL1PredictedCellsAsGood", true, "Treat bad cells with dead OTX if predicted from L1 as good"};
-
-  /** @brief Options for the algorithm, held in a GPU-friendly way.
-  */
-  GPUSplitterOptionsHolder m_options;
-
-};
-
-#endif //CALORECGPU_CALOTOPOCLUSTERSPLITTERGPU_H
\ No newline at end of file
diff --git a/Calorimeter/CaloRecGPU/src/CaloTopoClusterSplitterGPUImpl.cu b/Calorimeter/CaloRecGPU/src/CaloTopoClusterSplitterGPUImpl.cu
deleted file mode 100644
index 19d76252509fda80ee85d311b7a8072d84c10d69..0000000000000000000000000000000000000000
--- a/Calorimeter/CaloRecGPU/src/CaloTopoClusterSplitterGPUImpl.cu
+++ /dev/null
@@ -1,422 +0,0 @@
-//
-// Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
-//
-// Dear emacs, this is -*- c++ -*-
-//
-
-#include "CaloRecGPU/Helpers.h"
-#include "CaloRecGPU/CUDAFriendlyClasses.h"
-#include "CaloTopoClusterSplitterGPUImpl.h"
-
-
-#include <cstring>
-#include <cmath>
-#include <iostream>
-#include <stdio.h>
-
-using namespace CaloRecGPU;
-
-void GPUSplitterOptionsHolder::allocate()
-{
-  m_options.allocate();
-  m_options_dev.allocate();
-}
-
-void GPUSplitterOptionsHolder::sendToGPU(const bool clear_CPU)
-{
-  m_options_dev = m_options;
-  if (clear_CPU)
-    {
-      m_options.clear();
-    }
-}
-
-
-#define check_if_secondary(cell_id, d_meta, d_fullclusters) ((d_fullcalogeometry)->sampling((cell_id)) >= (d_meta)->m_minSecondarySampling &&\
-                                                             (d_fullcalogeometry)->sampling((cell_id)) <= (d_meta)->m_maxSecondarySampling &&\
-                                                             ((d_meta)->m_useSecondarySampling & (1 << ((d_fullcalogeometry)->sampling((cell_id)) - (d_meta)->m_minSecondarySampling))))
-
-constexpr static int DefaultBlockSize = 512;
-
-
-/************************************************************************/
-
-
-void preProcessingPreparation(EventDataHolder & holder, Helpers::CUDA_kernel_object<GPUSplitterTemporaries> temps,
-                              const ConstantDataHolder & instance_data, const GPUSplitterOptionsHolder & options, const bool synchronize)
-{
-  CUDA_ERRCHECK(cudaMemsetAsync((void *) temps->max_cells, 0, NCaloCells * sizeof(temps->max_cells[0]), cudaStreamPerThread));
-  CUDA_ERRCHECK(cudaMemsetAsync((void *) temps->secondary_max_cells, 0, NCaloCells * sizeof(temps->secondary_max_cells[0]), cudaStreamPerThread));
-  CUDA_ERRCHECK(cudaMemsetAsync((void *) temps->splitter_seeds, 0, NMaxClusters * sizeof(temps->splitter_seeds[0]), cudaStreamPerThread));
-  CUDA_ERRCHECK(cudaMemsetAsync((void *) temps->secondary_splitter_seeds, 0, NMaxClusters * sizeof(temps->secondary_splitter_seeds[0]), cudaStreamPerThread));
-
-  if (synchronize)
-    {
-      CUDA_ERRCHECK(cudaPeekAtLastError());
-      CUDA_ERRCHECK(cudaStreamSynchronize(cudaStreamPerThread));
-    }
-}
-
-
-
-/***********************************************************************/
-
-static __global__ void find_local_maximums(const Helpers::CUDA_kernel_object<CaloTopoClusterSplitterMetadata> d_meta,
-                                           const Helpers::CUDA_kernel_object<GeometryArr> d_fullcalogeometry,
-                                           const Helpers::CUDA_kernel_object<CellInfoArr> d_cellsfulldata,
-                                           const Helpers::CUDA_kernel_object<CellStateArr> d_cellstate,
-                                           Helpers::CUDA_kernel_object<GPUSplitterTemporaries> temporaries)
-{
-  unsigned cell_id = blockIdx.x * blockDim.x + threadIdx.x;
-  int num_neighbours, n_id;
-  int cell_tag;
-  int i;
-  int count_neigh = 0;
-  bool max = true;
-  float energy, n_energy, n_eta, n_phi;
-  bool is_secondary = false, is_primary = true;
-  int calo_sample, n_sample;
-
-  if (cell_id > NCaloCells)
-    {
-      return;
-    }
-
-  num_neighbours = d_fullcalogeometry->neighbours.get_total_number_of_neighbours(cell_id);
-  calo_sample = d_fullcalogeometry->sampling(cell_id);
-  energy = d_cellsfulldata->energy[cell_id];
-  cell_tag = ClusterTag::cluster_index(d_cellstate->clusterTag[cell_id]);
-
-  if (d_meta->m_absOpt)
-    {
-      energy = fabs(energy);
-    }
-
-  if (energy < d_meta->m_minEnergy)
-    {
-      return;
-    }
-
-  if (d_cellsfulldata->is_bad(*d_fullcalogeometry, cell_id, d_meta->m_treatL1PredictedCellsAsGood) && energy > 0)
-    {
-
-      /* check if cell can be used for local max */
-      if (d_meta->uses_sampling(calo_sample))
-        {
-          is_primary = true;
-        }
-      else if (d_meta->uses_secondary_sampling(calo_sample))
-        {
-          is_secondary = true;
-        }
-    }
-
-  for (i = 0; i < num_neighbours; i++)
-    {
-      n_id = d_fullcalogeometry->neighbours.get_neighbour(cell_id, i);
-      //FUTURE TODO WARNING FIX ALERT ERROR PAY ATTENTION:
-      //this is not taking into account limited neighbours!
-
-      /* skip if both cells aren't in the same cluster */
-      if (cell_tag != ClusterTag::cluster_index(d_cellstate->clusterTag[n_id]))
-        {
-          continue;
-        }
-
-      n_energy = d_meta->m_absOpt ? fabs(d_cellsfulldata->energy[n_id]) : d_cellsfulldata->energy[n_id];
-      n_phi = d_fullcalogeometry->phi[n_id];
-      n_eta = d_fullcalogeometry->eta[n_id];
-      n_sample = d_fullcalogeometry->sampling(n_id);
-
-      if (energy > n_energy)
-        {
-          count_neigh++;
-        }
-      else
-        {
-          max = false;
-        }
-
-      if (n_energy >= d_meta->m_minEnergy &&
-          is_secondary &&
-          d_meta->uses_sampling(n_sample))
-        {
-          if (fabs(n_eta - d_fullcalogeometry->eta[cell_id]) < 0.0025)
-            {
-              double diff_phi = n_phi - d_fullcalogeometry->phi[cell_id];
-              if (diff_phi > M_PI)
-                {
-                  diff_phi = diff_phi - 2 * M_PI;
-                }
-              else if (diff_phi < -M_PI)
-                {
-                  diff_phi = diff_phi + 2 * M_PI;
-                }
-
-              if (fabs(diff_phi) < 0.02)
-                {
-                  max = false;
-                }
-            }
-        }
-    }
-
-  if (count_neigh < d_meta->m_nCells)
-    {
-      max = false;
-    }
-
-  if (max)
-    {
-      if (is_primary)
-        {
-          temporaries->max_cells[cell_id] = 1;
-          atomicAdd(&temporaries->splitter_seeds[cell_tag], 1);
-        }
-      else if (is_secondary)
-        {
-          temporaries->secondary_max_cells[cell_id] = 1;
-          atomicAdd(&temporaries->secondary_splitter_seeds[cell_tag], 1);
-        }
-    }
-}
-
-
-void findLocalMaxima(EventDataHolder & holder, Helpers::CUDA_kernel_object<GPUSplitterTemporaries> temps,
-                     const ConstantDataHolder & instance_data, const GPUSplitterOptionsHolder & options, const bool synchronize)
-{
-  const int block_size = DefaultBlockSize;
-  const int num_blocks = Helpers::int_ceil_div(NCaloCells, block_size);
-
-  dim3 bsize(block_size, 1, 1);
-  dim3 gsize(num_blocks, 1, 1);
-
-  find_local_maximums <<< gsize, bsize>>>(options.m_options_dev, instance_data.m_geometry_dev,
-                                          holder.m_cell_info_dev, holder.m_cell_state_dev, temps);
-
-  if (synchronize)
-    {
-      CUDA_ERRCHECK(cudaPeekAtLastError());
-      CUDA_ERRCHECK(cudaStreamSynchronize(cudaStreamPerThread));
-    }
-}
-
-
-/***********************************************************************/
-
-__global__ void splitter_tag_propagation(const Helpers::CUDA_kernel_object<GeometryArr> d_fullcalogeometry,
-                                         const Helpers::CUDA_kernel_object<CellStateArr> d_cellstate,
-                                         Helpers::CUDA_kernel_object<ClusterInfoArr> d_fullclusters,
-                                         Helpers::CUDA_kernel_object<GPUSplitterTemporaries> temporaries)
-{
-  int tid = threadIdx.x;
-  int cell_tag, n_cell_tag;
-  int cell_id, n_cell_id;
-  int old_num;
-  /*int offset = d_fullclusters->number;*/
-  int i, k, steps = 0;
-  __shared__ int * aux, *first_q, *sec_q;
-
-
-  __shared__ int current;
-  __shared__ int Q_len, Q2_len;
-
-  if (tid == 0)
-    {
-      current = 0;
-      Q_len = 0;
-      first_q = temporaries->queue1;
-      sec_q = temporaries->queue2;
-
-      //NSF: We need this so the new clusters can be properly processed...
-      //(Obviously, since this is all on one block,
-      // it's fine to zero it here...)
-      d_fullclusters->number = 0;
-
-    }
-
-  __syncthreads();
-
-  /* Iterate through all cells and:
-   * - queue the local max and secondary maximums
-   * - assign a new cluster tag = call_id + n_clusters
-   * Compared to the CPU implementation, this doesn't start from the cells
-   * with highest energy since we don't sort the array on GPU so we might
-   * obtain slightly different results because of that.
-   */
-  for (cell_id = tid; cell_id < NCaloCells; cell_id += blockDim.x)
-    {
-      if (temporaries->max_cells[cell_id] || temporaries->secondary_max_cells[cell_id])
-        {
-
-          old_num = atomicAdd(&current, 1);
-          temporaries->tags[cell_id] = old_num /*+ offset*/;
-
-          old_num = atomicAdd(&Q_len, 1);
-          temporaries->queue1[old_num] = cell_id;
-
-
-          //NSF: We need this so the new clusters can be properly processed...
-          const int old_size = atomicAdd(&(d_fullclusters->number), 1);
-          d_fullclusters->seedCellID[old_size] = cell_id;
-
-        }
-      else
-        {
-          temporaries->tags[cell_id] = -1;
-        }
-    }
-
-  __syncthreads();
-
-  /* Start iterate through cells in queue built at previous step and:
-   * - check what cell neighbour doesn't have a tag assigned in d_tags but
-   *   has the same original cluster tag with current cell
-   * - if the tag is -1 (unused yet), change its tag with current cell
-   *   tag and add the neighbour cell in a secondary queue.
-   * This algorithm will be repeated until the secondary queue is empty.
-   */
-  do
-    {
-      if (tid == 0)
-        {
-          Q2_len = 0;
-        }
-
-      __syncthreads();
-
-      for (i = tid; i < Q_len; i += blockDim.x)
-        {
-          cell_id = first_q[i];
-          cell_tag = ClusterTag::cluster_index(d_cellstate->clusterTag[cell_id]);
-          int num_neighbours = d_fullcalogeometry->neighbours.get_total_number_of_neighbours(cell_id);
-          //FUTURE TODO WARNING FIX ALERT ERROR PAY ATTENTION:
-          //this is not taking into account limited neighbours!
-
-          for (k = 0; k < num_neighbours; k++)
-            {
-              n_cell_id = d_fullcalogeometry->neighbours.get_neighbour(cell_id, k);
-              n_cell_tag = ClusterTag::cluster_index(d_cellstate->clusterTag[n_cell_id]);
-
-              if (cell_tag == n_cell_tag)
-                {
-                  old_num = atomicCAS(&temporaries->tags[n_cell_id], -1, temporaries->tags[cell_id]);
-                  if (old_num == -1)
-                    {
-                      int j = atomicAdd(&Q2_len, 1);
-                      sec_q[j] = n_cell_id;
-                    }
-                }
-            }
-        }
-
-      __syncthreads();
-
-      if (tid == 0)
-        {
-          steps ++;
-          aux = sec_q;
-          sec_q = first_q;
-          first_q = aux;
-          Q_len = Q2_len;
-        }
-
-      __syncthreads();
-    }
-  while (Q2_len > 0);
-}
-
-
-void propagateTags(EventDataHolder & holder, Helpers::CUDA_kernel_object<GPUSplitterTemporaries> temps,
-                   const ConstantDataHolder & instance_data, const GPUSplitterOptionsHolder & options, const bool synchronize)
-{
-  splitter_tag_propagation <<< 1, 2 * DefaultBlockSize>>>(instance_data.m_geometry_dev,
-                                                          holder.m_cell_state_dev,
-                                                          holder.m_clusters_dev,
-                                                          temps);
-
-  if (synchronize)
-    {
-      CUDA_ERRCHECK(cudaPeekAtLastError());
-      CUDA_ERRCHECK(cudaStreamSynchronize(cudaStreamPerThread));
-    }
-
-}
-
-/***********************************************************************/
-
-
-static __global__ void refill_clusters(const Helpers::CUDA_kernel_object<GeometryArr> d_fullcalogeometry,
-                                       Helpers::CUDA_kernel_object<ClusterInfoArr> d_fullclusters,
-                                       Helpers::CUDA_kernel_object<CellStateArr> d_cellstate,
-                                       Helpers::CUDA_kernel_object<GPUSplitterTemporaries> temporaries)
-{
-  unsigned int i = blockIdx.x * blockDim.x + threadIdx.x;
-
-  if (i >= NCaloCells)
-    {
-      return;
-    }
-
-  /* reset all clusters to 0 */
-  /*
-  if (i < NMaxClusters) {
-      d_fullclusters->clusterSize[i] = 0;
-      d_fullclusters->clusterEnergy[i] = 0;
-      d_fullclusters->clusterEt[i] = 0;
-      d_fullclusters->clusterEta[i] = 0;
-  }
-  */
-
-  int tag = temporaries->tags[i];
-
-  /* set the seed tags accordingly to what we found in splitter algorithm */
-  if (tag >= 0)
-    {
-      d_cellstate->clusterTag[i] = ClusterTag::make_tag(tag);
-    }
-  else
-    {
-      tag = -1;
-      d_cellstate->clusterTag[i] = ClusterTag::make_invalid_tag();
-    }
-
-  //NSF: As there's no synchronization, there might be trouble between the zeroing and the calculation...
-
-  /*
-  if (tag >= 0) {
-      float energy = d_fullclusters->cellSN2[i];
-      atomicAdd(&d_fullclusters->clusterEnergy[tag], energy);
-      atomicAdd(&d_fullclusters->clusterEt[tag], abs(energy));
-      atomicAdd(&d_fullclusters->clusterEta[tag], d_fullcalogeometry->eta[i] * abs(energy));
-
-      // TODO: why?
-      float phi0 = d_fullcalogeometry->phi[i];
-      float phi = phi0;
-      if (phi > phi0 + M_PI)
-          phi = phi - 2 * M_PI;
-      if (phi < phi0 - M_PI)
-          phi = phi + 2 * M_PI;
-      atomicAdd(&d_fullclusters->clusterPhi[tag], phi * abs(energy));
-  }
-  */
-}
-
-void refillClusters(EventDataHolder & holder, Helpers::CUDA_kernel_object<GPUSplitterTemporaries> temps,
-                    const ConstantDataHolder & instance_data, const GPUSplitterOptionsHolder & options, const bool synchronize)
-{
-  const int block_size = DefaultBlockSize;
-  const int num_blocks = Helpers::int_ceil_div(NCaloCells, block_size);
-
-  dim3 bsize(block_size, 1, 1);
-  dim3 gsize(num_blocks, 1, 1);
-
-  refill_clusters <<< gsize, bsize>>>(instance_data.m_geometry_dev, holder.m_clusters_dev,
-                                      holder.m_cell_state_dev, temps);
-
-  if (synchronize)
-    {
-      CUDA_ERRCHECK(cudaPeekAtLastError());
-      CUDA_ERRCHECK(cudaStreamSynchronize(cudaStreamPerThread));
-    }
-}
diff --git a/Calorimeter/CaloRecGPU/src/CaloTopoClusterSplitterGPUImpl.h b/Calorimeter/CaloRecGPU/src/CaloTopoClusterSplitterGPUImpl.h
deleted file mode 100644
index 58cd839e1c9fb39d5530e3543ad30629267cc129..0000000000000000000000000000000000000000
--- a/Calorimeter/CaloRecGPU/src/CaloTopoClusterSplitterGPUImpl.h
+++ /dev/null
@@ -1,91 +0,0 @@
-//
-// Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
-//
-// Dear emacs, this is -*- c++ -*-
-//
-
-#ifndef CALORECGPU_CALOTOPOCLUSTERSPLITTERGPU_CUDA_H
-#define CALORECGPU_CALOTOPOCLUSTERSPLITTERGPU_CUDA_H
-
-#include "CaloRecGPU/CUDAFriendlyClasses.h"
-#include "CaloRecGPU/DataHolders.h"
-
-struct GPUSplitterTemporaries
-{
-  int max_cells[CaloRecGPU::NCaloCells];
-  int secondary_max_cells[CaloRecGPU::NCaloCells];
-  int queue1[CaloRecGPU::NCaloCells];
-  int queue2[CaloRecGPU::NCaloCells];
-  int tags[CaloRecGPU::NCaloCells];
-
-  int splitter_seeds[CaloRecGPU::NMaxClusters];
-  int secondary_splitter_seeds[CaloRecGPU::NMaxClusters];
-
-};
-
-struct CaloTopoClusterSplitterMetadata
-{
-  //int m_minSampling;
-  //int m_maxSampling;
-  //int m_minSecondarySampling;
-  //int m_maxSecondarySampling;
-
-  /* We can have up to 64 sample values stored in this bitfield.
-   * At this moment, we have enough space to accomodate all the
-   * samples but it might need to be "enlarged" in the future
-   *
-   * This is a bitfield and each bit on position pos tells if
-   * the sample with id = pos can be used.
-   */
-  unsigned long long m_useSampling;
-  unsigned long long m_useSecondarySampling;
-
-  //unsigned int m_hashMin;
-  //unsigned int m_hashMax;
-
-  int m_nCells;
-  int m_nOption;
-  float m_minEnergy;
-  float m_emShowerScale;
-  bool m_shareBorderCells;
-  bool m_absOpt;
-  bool m_treatL1PredictedCellsAsGood;
-
-
-  constexpr bool uses_sampling(const int sampling) const
-  {
-    return (m_useSampling >> sampling) & 1;
-  }
-  constexpr bool uses_secondary_sampling(const int sampling) const
-  {
-    return (m_useSecondarySampling >> sampling) & 1;
-  }
-};
-
-struct GPUSplitterOptionsHolder
-{
-  CaloRecGPU::Helpers::CPU_object<CaloTopoClusterSplitterMetadata> m_options;
-
-  CaloRecGPU::Helpers::CUDA_object<CaloTopoClusterSplitterMetadata> m_options_dev;
-
-  void allocate();
-  void sendToGPU(const bool clear_CPU = false);
-};
-
-void preProcessingPreparation(CaloRecGPU::EventDataHolder & holder,
-                              CaloRecGPU::Helpers::CUDA_kernel_object<GPUSplitterTemporaries> temps,
-                              const CaloRecGPU::ConstantDataHolder & instance_data, const GPUSplitterOptionsHolder & options, const bool synchronize = false);
-
-void findLocalMaxima(CaloRecGPU::EventDataHolder & holder,
-                     CaloRecGPU::Helpers::CUDA_kernel_object<GPUSplitterTemporaries> temps,
-                     const CaloRecGPU::ConstantDataHolder & instance_data, const GPUSplitterOptionsHolder & options, const bool synchronize = false);
-
-void propagateTags(CaloRecGPU::EventDataHolder & holder,
-                   CaloRecGPU::Helpers::CUDA_kernel_object<GPUSplitterTemporaries> temps,
-                   const CaloRecGPU::ConstantDataHolder & instance_data, const GPUSplitterOptionsHolder & options, const bool synchronize = false);
-
-void refillClusters(CaloRecGPU::EventDataHolder & holder,
-                    CaloRecGPU::Helpers::CUDA_kernel_object<GPUSplitterTemporaries> temps,
-                    const CaloRecGPU::ConstantDataHolder & instance_data, const GPUSplitterOptionsHolder & options, const bool synchronize = false);
-
-#endif //CALORECGPU_CALOTOPOCLUSTERSPLITTERGPU_CUDA_H
\ No newline at end of file
diff --git a/Calorimeter/CaloRecGPU/src/DataHolders.cu b/Calorimeter/CaloRecGPU/src/DataHolders.cu
index 9e30b2200bd059eb003accd901e4122851c1dbbf..2cde7f4da9ee9b8c8df0578e4b7f9a6421fce3c7 100644
--- a/Calorimeter/CaloRecGPU/src/DataHolders.cu
+++ b/Calorimeter/CaloRecGPU/src/DataHolders.cu
@@ -95,7 +95,7 @@ void CaloRecGPU::EventDataHolder::returnToCPU(const bool clear_GPU,
 
 void CaloRecGPU::EventDataHolder::returnCellsToCPU(CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream)
 {
-  const cudaStream_t & stream_to_use = (stream != nullptr ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
+  const cudaStream_t & stream_to_use = (stream ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
   CUDA_ERRCHECK( cudaMemcpyAsync((CaloRecGPU::CellStateArr *) m_cell_state,
                                  (CaloRecGPU::CellStateArr *) m_cell_state_dev,
                                  sizeof(CaloRecGPU::CellStateArr),
@@ -104,7 +104,7 @@ void CaloRecGPU::EventDataHolder::returnCellsToCPU(CaloRecGPU::CUDA_Helpers::CUD
 
 void CaloRecGPU::EventDataHolder::returnClustersToCPU(CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream)
 {
-  const cudaStream_t & stream_to_use = (stream != nullptr ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
+  const cudaStream_t & stream_to_use = (stream ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
   CUDA_ERRCHECK( cudaMemcpyAsync((CaloRecGPU::ClusterInfoArr *) m_clusters,
                                  (CaloRecGPU::ClusterInfoArr *) m_clusters_dev,
                                  sizeof(CaloRecGPU::ClusterInfoArr),
@@ -113,7 +113,7 @@ void CaloRecGPU::EventDataHolder::returnClustersToCPU(CaloRecGPU::CUDA_Helpers::
 
 void CaloRecGPU::EventDataHolder::returnMomentsToCPU(CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream)
 {
-  const cudaStream_t & stream_to_use = (stream != nullptr ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
+  const cudaStream_t & stream_to_use = (stream ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
   CUDA_ERRCHECK(cudaMemcpyAsync((CaloRecGPU::ClusterMomentsArr *) m_moments,
                                 (CaloRecGPU::ClusterMomentsArr *) m_moments_dev,
                                 sizeof(CaloRecGPU::ClusterMomentsArr),
@@ -122,7 +122,7 @@ void CaloRecGPU::EventDataHolder::returnMomentsToCPU(CaloRecGPU::CUDA_Helpers::C
 
 void CaloRecGPU::EventDataHolder::returnClusterNumberToCPU(CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream)
 {
-  const cudaStream_t & stream_to_use = (stream != nullptr ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
+  const cudaStream_t & stream_to_use = (stream ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
   CUDA_ERRCHECK(cudaMemcpyAsync(&(m_clusters->number),
                                 &(m_clusters_dev->number),
                                 sizeof(int),
@@ -158,7 +158,7 @@ void CaloRecGPU::EventDataHolder::returnClusterNumberToCPU(CaloRecGPU::CUDA_Help
 
 void CaloRecGPU::EventDataHolder::returnSomeClustersToCPU(const size_t num_clusters, CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream)
 {
-  const cudaStream_t & stream_to_use = (stream != nullptr ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
+  const cudaStream_t & stream_to_use = (stream ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
 
   //We assume the cluster number we take is the known number of clusters,
   //so we skip copying that.
@@ -172,7 +172,7 @@ void CaloRecGPU::EventDataHolder::returnSomeClustersToCPU(const size_t num_clust
 
 void CaloRecGPU::EventDataHolder::returnSomeMomentsToCPU(const size_t num_clusters, CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream)
 {
-  const cudaStream_t & stream_to_use = (stream != nullptr ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
+  const cudaStream_t & stream_to_use = (stream ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
 
   CALORECGPU_ASYNC_TRANSFER_PER_SAMPLE_HELPER(m_moments, energyPerSample,     float, num_clusters, stream_to_use);
   CALORECGPU_ASYNC_TRANSFER_PER_SAMPLE_HELPER(m_moments, maxEPerSample,       float, num_clusters, stream_to_use);
diff --git a/Calorimeter/CaloRecGPU/src/FPHelpers.h b/Calorimeter/CaloRecGPU/src/FPHelpers.h
index eb7b1ac722eeece45799b94564c88b28d4307a0c..ee785b94a028e4fcc02602eeb1990d391cf7f761 100644
--- a/Calorimeter/CaloRecGPU/src/FPHelpers.h
+++ b/Calorimeter/CaloRecGPU/src/FPHelpers.h
@@ -28,7 +28,7 @@
 
 #endif
 
-#if __cpp_lib_bitops
+#if __cpp_lib_bitops || __cpp_lib_bit_cast
 
   #include <bit>
 
@@ -264,7 +264,7 @@ namespace FloatingPointHelpers
     template <class To, class From>
     constexpr inline static To bitcast(const From & x)
     {
-      return bit_cast<To, From>(x);
+      return std::bit_cast<To, From>(x);
     }
 
 #else
diff --git a/Calorimeter/CaloRecGPU/src/GPUClusterInfoAndMomentsCalculatorImpl.cu b/Calorimeter/CaloRecGPU/src/GPUClusterInfoAndMomentsCalculatorImpl.cu
index 37847272e2cab95f75c30ea450a209db81fd8dec..fb9404ebdffa1c35f9ca44e531f19ab8de0e7ae1 100644
--- a/Calorimeter/CaloRecGPU/src/GPUClusterInfoAndMomentsCalculatorImpl.cu
+++ b/Calorimeter/CaloRecGPU/src/GPUClusterInfoAndMomentsCalculatorImpl.cu
@@ -2088,7 +2088,7 @@ void ClusterMomentsCalculator::calculateClusterPropertiesAndMoments(CaloRecGPU::
                                                                     CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream,
                                                                     const bool defer_instead_of_oversize)
 {
-  const cudaStream_t & stream_to_use = (stream != nullptr ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
+  const cudaStream_t & stream_to_use = (stream ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
 
   const CUDAKernelLaunchConfiguration cfg_0_clu = optimizer.get_launch_configuration("ClusterMomentsCalculator", 0);
   const CUDAKernelLaunchConfiguration cfg_1_cel = optimizer.get_launch_configuration("ClusterMomentsCalculator", 1);
diff --git a/Calorimeter/CaloRecGPU/src/GPUToAthenaImporterWithMoments.cxx b/Calorimeter/CaloRecGPU/src/GPUToAthenaImporterWithMoments.cxx
index 9041ed73ce547bf54f3378eb85396b6f51d25052..65bf9c0673d2a4be32d2f8ca98434c6ffface1f8 100644
--- a/Calorimeter/CaloRecGPU/src/GPUToAthenaImporterWithMoments.cxx
+++ b/Calorimeter/CaloRecGPU/src/GPUToAthenaImporterWithMoments.cxx
@@ -35,14 +35,14 @@ GPUToAthenaImporterWithMoments::GPUToAthenaImporterWithMoments(const std::string
 
 StatusCode GPUToAthenaImporterWithMoments::initialize()
 {
-  ATH_CHECK( m_cellsKey.value().initialize() );
+  ATH_CHECK( m_cellsKey.initialize() );
 
   ATH_CHECK( detStore()->retrieve(m_calo_id, "CaloCell_ID") );
 
   ATH_CHECK(m_caloMgrKey.initialize());
 
-  ATH_CHECK(m_HVCablingKey.initialize());
-  ATH_CHECK(m_HVScaleKey.initialize());
+  ATH_CHECK(m_HVCablingKey.initialize(m_fillHVMoments));
+  ATH_CHECK(m_HVScaleKey.initialize(m_fillHVMoments));
 
   auto get_cluster_size_from_string = [](const std::string & str, bool & failed)
   {
@@ -214,7 +214,7 @@ StatusCode GPUToAthenaImporterWithMoments::initialize()
                      << " are not valid moments and will be ignored!" );
     }
 
-  m_doHVMoments =  m_momentsToDo[xAOD::CaloCluster::ENG_BAD_HV_CELLS] || m_momentsToDo[xAOD::CaloCluster::N_BAD_HV_CELLS];
+  m_doHVMoments = (m_momentsToDo[xAOD::CaloCluster::ENG_BAD_HV_CELLS] || m_momentsToDo[xAOD::CaloCluster::N_BAD_HV_CELLS]) && m_fillHVMoments;
   return StatusCode::SUCCESS;
 }
 
@@ -284,18 +284,26 @@ StatusCode GPUToAthenaImporterWithMoments::convert (const EventContext & ctx,
   std::vector<float> HV_energy(ed.m_clusters->number * m_doHVMoments, 0.f);
   std::vector<int>   HV_number(ed.m_clusters->number * m_doHVMoments, 0  );
 
-  SG::ReadCondHandle<LArOnOffIdMapping> cablingHdl(m_HVCablingKey, ctx);
-  const LArOnOffIdMapping * cabling = *cablingHdl;
-  SG::ReadCondHandle<ILArHVScaleCorr> hvScaleHdl(m_HVScaleKey, ctx);
-  const ILArHVScaleCorr * hvcorr = *hvScaleHdl;
-
+  const LArOnOffIdMapping * cabling = nullptr;
+  const ILArHVScaleCorr * hvcorr = nullptr;
+  
+  if (m_fillHVMoments)
+    {
+      SG::ReadCondHandle<LArOnOffIdMapping> cablingHdl(m_HVCablingKey, ctx);
+      SG::ReadCondHandle<ILArHVScaleCorr> hvScaleHdl(m_HVScaleKey, ctx);
+      cabling = *cablingHdl;
+      hvcorr = *hvScaleHdl;
+    }
+  
   CaloRecGPU::CUDA_Helpers::GPU_synchronize();
 
   const auto cells = clock_type::now();
 
   ed.returnSomeMomentsToCPU(ed.m_clusters->number);
 
-  const auto process_cell = [&](const int cell_index)
+  //cell_index is the actual cell index in the full set of cells (identifier hash)
+  //cell_count is the cell position in the cell collection (what we want for the weight)
+  const auto process_cell = [&](const int cell_index, const int cell_count)
   {
     const ClusterTag this_tag = ed.m_cell_state->clusterTag[cell_index];
     if (this_tag.is_part_of_cluster())
@@ -316,7 +324,7 @@ StatusCode GPUToAthenaImporterWithMoments::convert (const EventContext & ctx,
 
         if (cell_links[this_index])
           {
-            cell_links[this_index]->addCell(cell_index, this_weight);
+            cell_links[this_index]->addCell(cell_count, this_weight);
 
             if (cell_index == ed.m_clusters->seedCellID[this_index] && cell_links[this_index]->size() > 1)
               //Seed cells aren't shared,
@@ -345,7 +353,7 @@ StatusCode GPUToAthenaImporterWithMoments::convert (const EventContext & ctx,
             const int other_index = this_tag.secondary_cluster_index();
             if (cell_links[other_index])
               {
-                cell_links[other_index]->addCell(cell_index, reverse_weight);
+                cell_links[other_index]->addCell(cell_count, reverse_weight);
               }
           }
 
@@ -374,10 +382,10 @@ StatusCode GPUToAthenaImporterWithMoments::convert (const EventContext & ctx,
     {
       for (int cell_index = 0; cell_index < NCaloCells; ++cell_index)
         {
-          process_cell(cell_index);
+          process_cell(cell_index, cell_index);
         }
     }
-  else if (m_missingCellsToFill.size() > 0)
+  else if (cell_collection->isOrdered() && m_missingCellsToFill.size() > 0)
     {
       size_t missing_cell_count = 0;
       for (int cell_index = 0; cell_index < NCaloCells; ++cell_index)
@@ -387,7 +395,7 @@ StatusCode GPUToAthenaImporterWithMoments::convert (const EventContext & ctx,
               ++missing_cell_count;
               continue;
             }
-          process_cell(cell_index);
+          process_cell(cell_index, cell_index - missing_cell_count);
         }
     }
   else
@@ -402,7 +410,7 @@ StatusCode GPUToAthenaImporterWithMoments::convert (const EventContext & ctx,
           //const int cell_index = m_calo_id->calo_cell_hash(cell->ID());
           const int cell_index = cell->caloDDE()->calo_hash();
                  
-          process_cell(cell_index);
+          process_cell(cell_index, cell_count);
         }
     }
 
@@ -467,6 +475,15 @@ StatusCode GPUToAthenaImporterWithMoments::convert (const EventContext & ctx,
 
           cluster->setE(ed.m_clusters->clusterEnergy[cluster_index]);
           cluster->setM(0.0);
+          
+          
+          if (m_saveUncalibrated)
+            {
+              cluster->setRawE(cluster->calE());
+              cluster->setRawEta(cluster->calEta());
+              cluster->setRawPhi(cluster->calPhi());
+              cluster->setRawM(cluster->calM());
+            }
 
           real_cluster_order.push_back(cluster_index);
         }
@@ -490,34 +507,34 @@ StatusCode GPUToAthenaImporterWithMoments::convert (const EventContext & ctx,
       cluster->clearSamplingData();
 
       uint32_t sampling_pattern = 0;
-      for (int i = 0; i < NumSamplings; ++i)
+      for (int sampl = 0; sampl < NumSamplings; ++sampl)
         {
-          const int cells_per_sampling = ed.m_moments->nCellSampling[i][cluster_index];
+          const int cells_per_sampling = ed.m_moments->nCellSampling[sampl][cluster_index];
 
           if (cells_per_sampling > 0)
             {
-              sampling_pattern |= (0x1U << i);
+              sampling_pattern |= (0x1U << sampl);
             }
         }
       cluster->setSamplingPattern(sampling_pattern);
 
-      for (int i = 0; i < NumSamplings; ++i)
+      for (int sampl = 0; sampl < NumSamplings; ++sampl)
         {
-          const int cells_per_sampling = ed.m_moments->nCellSampling[i][cluster_index];
+          const int cells_per_sampling = ed.m_moments->nCellSampling[sampl][cluster_index];
 
           if (cells_per_sampling > 0)
             {
-              cluster->setEnergy  ((CaloSampling::CaloSample) i, ed.m_moments->energyPerSample [i][cluster_index]);
-              cluster->setEta     ((CaloSampling::CaloSample) i, ed.m_moments->etaPerSample    [i][cluster_index]);
-              cluster->setPhi     ((CaloSampling::CaloSample) i, ed.m_moments->phiPerSample    [i][cluster_index]);
-              cluster->setEmax    ((CaloSampling::CaloSample) i, ed.m_moments->maxEPerSample   [i][cluster_index]);
-              cluster->setEtamax  ((CaloSampling::CaloSample) i, ed.m_moments->maxEtaPerSample [i][cluster_index]);
-              cluster->setPhimax  ((CaloSampling::CaloSample) i, ed.m_moments->maxPhiPerSample [i][cluster_index]);
+              cluster->setEnergy  ((CaloSampling::CaloSample) sampl, ed.m_moments->energyPerSample [sampl][cluster_index]);
+              cluster->setEta     ((CaloSampling::CaloSample) sampl, ed.m_moments->etaPerSample    [sampl][cluster_index]);
+              cluster->setPhi     ((CaloSampling::CaloSample) sampl, ed.m_moments->phiPerSample    [sampl][cluster_index]);
+              cluster->setEmax    ((CaloSampling::CaloSample) sampl, ed.m_moments->maxEPerSample   [sampl][cluster_index]);
+              cluster->setEtamax  ((CaloSampling::CaloSample) sampl, ed.m_moments->maxEtaPerSample [sampl][cluster_index]);
+              cluster->setPhimax  ((CaloSampling::CaloSample) sampl, ed.m_moments->maxPhiPerSample [sampl][cluster_index]);
             }
 
           if (m_momentsToDo[xAOD::CaloCluster::NCELL_SAMPLING])
             {
-              cluster->setNumberCellsInSampling((CaloSampling::CaloSample) i, cells_per_sampling, false);
+              cluster->setNumberCellsInSampling((CaloSampling::CaloSample) sampl, cells_per_sampling, false);
             }
         }
 
diff --git a/Calorimeter/CaloRecGPU/src/GPUToAthenaImporterWithMoments.h b/Calorimeter/CaloRecGPU/src/GPUToAthenaImporterWithMoments.h
index 99a6c6fc84e88e5387181cdb49de352d417444f8..97d0086da12c38ca4c4c716d390a101689e53fe6 100644
--- a/Calorimeter/CaloRecGPU/src/GPUToAthenaImporterWithMoments.h
+++ b/Calorimeter/CaloRecGPU/src/GPUToAthenaImporterWithMoments.h
@@ -57,7 +57,7 @@ class GPUToAthenaImporterWithMoments :
   /**
    * @brief vector of names of the cell containers to use as input.
    */
-  Gaudi::Property<SG::ReadHandleKey<CaloCellContainer>> m_cellsKey {this, "CellsName", "", "Name(s) of Cell Containers"};
+  SG::ReadHandleKey<CaloCellContainer> m_cellsKey {this, "CellsName", "", "Name(s) of Cell Containers"};
 
   /// Cluster size. Should be set accordingly to the threshold.
   Gaudi::Property<std::string> m_clusterSizeString {this, "ClusterSize", "Topo_420", "The size/type of the clusters"};
@@ -77,6 +77,11 @@ class GPUToAthenaImporterWithMoments :
 
   //Handles for things we can't (yet) do on the GPU.
 
+  /**
+  * @brief if set to true, fill the HV-related moments using the respective tools.
+  */
+  Gaudi::Property<bool> m_fillHVMoments {this, "FillHVMoments", false, "Fill the HV-related moments using the respective tools."};
+  
   ///@brief Cabling for the CPU-based HV moments calculation.
    SG::ReadCondHandleKey<LArOnOffIdMapping> m_HVCablingKey{this, "LArCablingKey","LArOnOffIdMap","SG Key of LAr Cabling object"};
  
@@ -90,6 +95,11 @@ class GPUToAthenaImporterWithMoments :
    */
   Gaudi::Property<std::vector<int>> m_missingCellsToFill {this, "MissingCellsToFill", {}, "Force fill these cells as disabled on empty containers."};
 
+  /**
+  * @brief if set to true, the uncalibrated state is saved when importing the clusters. Default is @p true.
+  */
+  Gaudi::Property<bool> m_saveUncalibrated {this, "SaveUncalibratedSignalState", true, "Use CaloClusterKineHelper::calculateKine instead of GPU-calculated cluster properties"};
+
 
   /**
    * @brief vector holding the input list of names of moments to
diff --git a/Calorimeter/CaloRecGPU/src/TopoAutomatonClusteringImpl.cu b/Calorimeter/CaloRecGPU/src/TopoAutomatonClusteringImpl.cu
index 800640fddb962b889a119987ff8e51660eeab214..5d50ad17e93c12b1de2d356d0462e74e5560381e 100644
--- a/Calorimeter/CaloRecGPU/src/TopoAutomatonClusteringImpl.cu
+++ b/Calorimeter/CaloRecGPU/src/TopoAutomatonClusteringImpl.cu
@@ -197,7 +197,7 @@ void TAGrowing::signalToNoise(EventDataHolder & holder,
                               const bool synchronize,
                               CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream)
 {
-  const cudaStream_t & stream_to_use = (stream != nullptr ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
+  const cudaStream_t & stream_to_use = (stream ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
   cudaMemsetAsync(&(holder.m_clusters_dev->number), 0, sizeof(holder.m_clusters_dev->number), stream_to_use);
 
   const CUDAKernelLaunchConfiguration config = optimizer.get_launch_configuration("TopoAutomatonGrowing", 0);
@@ -343,7 +343,7 @@ void TAGrowing::cellPairs(EventDataHolder & holder,
                           const bool synchronize,
                           CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream)
 {
-  const cudaStream_t & stream_to_use = (stream != nullptr ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
+  const cudaStream_t & stream_to_use = (stream ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
 
   TopoAutomatonGrowingTemporaries * temps = TACHacks::get_temporaries(holder);
 
@@ -370,7 +370,7 @@ void TAGrowing::cellPairs(EventDataHolder & holder,
  * Series of kernels for the growing algorithm!
  ******************************************************************************/
 
-__device__ static
+static __device__
 void propagate_through_pair_main(const int pair,
                                  Helpers::CUDA_kernel_object<CellStateArr> cell_state_arr,
                                  Helpers::CUDA_kernel_object<TopoAutomatonGrowingTemporaries> temporaries)
@@ -424,7 +424,7 @@ void propagate_through_pair_main(const int pair,
 }
 
 
-__device__ static
+static __device__
 void propagate_through_pair_terminal(const int pair,
                                      Helpers::CUDA_kernel_object<CellStateArr> cell_state_arr,
                                      Helpers::CUDA_kernel_object<TopoAutomatonGrowingTemporaries> temporaries)
@@ -438,7 +438,7 @@ void propagate_through_pair_terminal(const int pair,
 }
 
 
-__global__ static
+static __global__
 void clusterGrowingMainCooperativeKernel(Helpers::CUDA_kernel_object<CellStateArr> cell_state_arr,
                                          Helpers::CUDA_kernel_object<TopoAutomatonGrowingTemporaries> temporaries)
 {
@@ -498,7 +498,7 @@ void clusterGrowingMainCooperativeKernel(Helpers::CUDA_kernel_object<CellStateAr
 
 }
 
-__global__ static
+static __global__
 void assignSeedCellsKernel(Helpers::CUDA_kernel_object<ClusterInfoArr> clusters_arr,
                            const Helpers::CUDA_kernel_object<TopoAutomatonGrowingTemporaries> temporaries)
 {
@@ -514,7 +514,7 @@ void assignSeedCellsKernel(Helpers::CUDA_kernel_object<ClusterInfoArr> clusters_
     }
 }
 
-__global__ static
+static __global__
 void finalizeClusterAttributionKernel(Helpers::CUDA_kernel_object<CellStateArr> cell_state_arr,
                                       const Helpers::CUDA_kernel_object<TopoAutomatonGrowingTemporaries> temporaries)
 {
@@ -546,41 +546,29 @@ namespace
   };
 }
 
-__global__ static
+static __global__
 void propagateNeighboursKernel(Helpers::CUDA_kernel_object<CellStateArr> cell_state_arr,
                                Helpers::CUDA_kernel_object<TopoAutomatonGrowingTemporaries> temporaries,
-                               Helpers::CUDA_kernel_object<ClusterInfoArr> clusters_arr
-#if CUDA_CAN_USE_TAIL_LAUNCH
-  , const kernel_sizes blocks, const kernel_sizes grids
-#endif
-                              );
+                               Helpers::CUDA_kernel_object<ClusterInfoArr> clusters_arr,
+                               const kernel_sizes blocks, const kernel_sizes grids);
 
-__global__ static
+static __global__
 void propagateTerminalsKernel(Helpers::CUDA_kernel_object<CellStateArr> cell_state_arr,
                               Helpers::CUDA_kernel_object<TopoAutomatonGrowingTemporaries> temporaries,
-                              Helpers::CUDA_kernel_object<ClusterInfoArr> clusters_arr
-#if CUDA_CAN_USE_TAIL_LAUNCH
-  , const kernel_sizes blocks, const kernel_sizes grids
-#endif
-                             );
+                              Helpers::CUDA_kernel_object<ClusterInfoArr> clusters_arr,
+                              const kernel_sizes blocks, const kernel_sizes grids);
 
-__global__ static
+static __global__
 void copyTagsAndCheckTerminationKernel(Helpers::CUDA_kernel_object<CellStateArr> cell_state_arr,
                                        Helpers::CUDA_kernel_object<TopoAutomatonGrowingTemporaries> temporaries,
-                                       Helpers::CUDA_kernel_object<ClusterInfoArr> clusters_arr
-#if CUDA_CAN_USE_TAIL_LAUNCH
-  , const kernel_sizes blocks, const kernel_sizes grids
-#endif
-                                      );
+                                       Helpers::CUDA_kernel_object<ClusterInfoArr> clusters_arr,
+                                       const kernel_sizes blocks, const kernel_sizes grids);
 
-__global__ static
+static __global__
 void propagateNeighboursKernel(Helpers::CUDA_kernel_object<CellStateArr> cell_state_arr,
                                Helpers::CUDA_kernel_object<TopoAutomatonGrowingTemporaries> temporaries,
-                               Helpers::CUDA_kernel_object<ClusterInfoArr> clusters_arr
-#if CUDA_CAN_USE_TAIL_LAUNCH
-  , const kernel_sizes blocks, const kernel_sizes grids
-#endif
-                              )
+                               Helpers::CUDA_kernel_object<ClusterInfoArr> clusters_arr,
+                               const kernel_sizes blocks, const kernel_sizes grids)
 {
   const int index = blockIdx.x * blockDim.x + threadIdx.x;
   const int grid_size = gridDim.x * blockDim.x;
@@ -605,11 +593,8 @@ void propagateNeighboursKernel(Helpers::CUDA_kernel_object<CellStateArr> cell_st
 __global__ static
 void copyTagsAndCheckTerminationKernel(Helpers::CUDA_kernel_object<CellStateArr> cell_state_arr,
                                        Helpers::CUDA_kernel_object<TopoAutomatonGrowingTemporaries> temporaries,
-                                       Helpers::CUDA_kernel_object<ClusterInfoArr> clusters_arr
-#if CUDA_CAN_USE_TAIL_LAUNCH
-  , const kernel_sizes blocks, const kernel_sizes grids
-#endif
-                                      )
+                                       Helpers::CUDA_kernel_object<ClusterInfoArr> clusters_arr,
+                                       const kernel_sizes blocks, const kernel_sizes grids)
 {
   const int index = blockIdx.x * blockDim.x + threadIdx.x;
   const int grid_size = gridDim.x * blockDim.x;
@@ -625,15 +610,15 @@ void copyTagsAndCheckTerminationKernel(Helpers::CUDA_kernel_object<CellStateArr>
         {
           temporaries->continue_flag = 0;
 
-          propagateNeighboursKernel <<< grid.neigh_prop, block.neigh_prop, 0, cudaStreamTailLaunch>>>(cell_state_arr,
-                                                                                                      temporaries,
-                                                                                                      clusters_arr,
-                                                                                                      blocks, grids);
+          propagateNeighboursKernel <<< grids.neigh_prop, blocks.neigh_prop, 0, cudaStreamTailLaunch>>>(cell_state_arr,
+                                                                                                        temporaries,
+                                                                                                        clusters_arr,
+                                                                                                        blocks, grids);
         }
       else
         {
 
-          propagateTerminalsKernel <<< grid.term_prop, block.term_prop, 0, cudaStreamTailLaunch>>>(cell_state_arr,
+          propagateTerminalsKernel <<< grids.term_prop, blocks.term_prop, 0, cudaStreamTailLaunch>>>(cell_state_arr,
                                                                                                    temporaries,
                                                                                                    clusters_arr,
                                                                                                    blocks, grids);
@@ -656,11 +641,8 @@ void copyTagsAndCheckTerminationKernel(Helpers::CUDA_kernel_object<CellStateArr>
 __global__ static
 void propagateTerminalsKernel(Helpers::CUDA_kernel_object<CellStateArr> cell_state_arr,
                               Helpers::CUDA_kernel_object<TopoAutomatonGrowingTemporaries> temporaries,
-                              Helpers::CUDA_kernel_object<ClusterInfoArr> clusters_arr
-#if CUDA_CAN_USE_TAIL_LAUNCH
-  , const kernel_sizes blocks, const kernel_sizes grids
-#endif
-                             )
+                              Helpers::CUDA_kernel_object<ClusterInfoArr> clusters_arr,
+                              const kernel_sizes blocks, const kernel_sizes grids)
 {
   const int index = blockIdx.x * blockDim.x + threadIdx.x;
   const int grid_size = gridDim.x * blockDim.x;
@@ -710,11 +692,13 @@ void clusterGrowingMainDefer(Helpers::CUDA_kernel_object<CellStateArr> cell_stat
         {
           propagateNeighboursKernel <<< grids.neigh_prop, blocks.neigh_prop>>>(cell_state_arr,
                                                                                temporaries,
-                                                                               clusters_arr);
+                                                                               clusters_arr,
+                                                                               blocks, grids);
 
           copyTagsAndCheckTerminationKernel <<< grids.copy_and_check, blocks.copy_and_check>>>(cell_state_arr,
                                                                                                temporaries,
-                                                                                               clusters_arr);
+                                                                                               clusters_arr,
+                                                                                               blocks, grids);
 
           //++counter;
 
@@ -724,7 +708,8 @@ void clusterGrowingMainDefer(Helpers::CUDA_kernel_object<CellStateArr> cell_stat
 
       propagateTerminalsKernel <<< grids.term_prop, blocks.term_prop>>>(cell_state_arr,
                                                                         temporaries,
-                                                                        clusters_arr);
+                                                                        clusters_arr,
+                                                                        blocks, grids);
       assignSeedCellsKernel <<< grids.seed_assign, blocks.seed_assign>>>(clusters_arr, temporaries);
 
 #endif
@@ -739,7 +724,7 @@ void TAGrowing::clusterGrowing(EventDataHolder & holder,
                                CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream)
 {
 
-  const cudaStream_t & stream_to_use = (stream != nullptr ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
+  const cudaStream_t & stream_to_use = (stream ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
 
   TopoAutomatonGrowingTemporaries * temps = TACHacks::get_temporaries(holder);
 
diff --git a/Calorimeter/CaloRecGPU/src/TopoAutomatonSplittingImpl.cu b/Calorimeter/CaloRecGPU/src/TopoAutomatonSplittingImpl.cu
index 0d83cc1150f5fe37245bb339143147dddb19a20c..a797e66d4d53c72961fe20c1a4dac4c223c38c0c 100644
--- a/Calorimeter/CaloRecGPU/src/TopoAutomatonSplittingImpl.cu
+++ b/Calorimeter/CaloRecGPU/src/TopoAutomatonSplittingImpl.cu
@@ -319,7 +319,7 @@ void TASplitting::fillNeighbours(EventDataHolder & holder,
                                  const bool synchronize,
                                  CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream)
 {
-  const cudaStream_t & stream_to_use = (stream != nullptr ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
+  const cudaStream_t & stream_to_use = (stream ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
 
   TopoAutomatonSplittingTemporaries * temps = TASHacks::get_temporaries(holder);
 
@@ -606,7 +606,7 @@ void TASplitting::findLocalMaxima(EventDataHolder & holder,
                                   const bool synchronize,
                                   CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream)
 {
-  const cudaStream_t & stream_to_use = (stream != nullptr ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
+  const cudaStream_t & stream_to_use = (stream ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
 
   TopoAutomatonSplittingTemporaries * temps = TASHacks::get_temporaries(holder);
 
@@ -655,7 +655,7 @@ void TASplitting::findLocalMaxima(EventDataHolder & holder,
  * Delete secondary maxima according to the criteria on the CPU version.
  ******************************************************************************/
 
-__device__ static
+static __device__
 void propagate_secondary_maxima_pair(const int pair,
                                      Helpers::CUDA_kernel_object<TopoAutomatonSplittingTemporaries> temporaries)
 {
@@ -679,7 +679,7 @@ void propagate_secondary_maxima_pair(const int pair,
 }
 
 
-__global__ static
+static __global__
 void secondaryMaximaCooperativeKernel(Helpers::CUDA_kernel_object<TopoAutomatonSplittingTemporaries> temporaries)
 {
   cooperative_groups::grid_group grid = cooperative_groups::this_grid();
@@ -730,19 +730,13 @@ void secondaryMaximaCooperativeKernel(Helpers::CUDA_kernel_object<TopoAutomatonS
 
 }
 
-__global__ static
-void checkForMaximaExclusionTermination(Helpers::CUDA_kernel_object<TopoAutomatonSplittingTemporaries> temporaries
-#if CUDA_CAN_USE_TAIL_LAUNCH
-  , const int i_dimBlock, const int i_dimGrid
-#endif
-                                       );
+static __global__
+void checkForMaximaExclusionTermination(Helpers::CUDA_kernel_object<TopoAutomatonSplittingTemporaries> temporaries,
+                                        const int i_dimBlock, const int i_dimGrid);
 
-__global__ static
-void propagateForMaximaExclusionKernel( Helpers::CUDA_kernel_object<TopoAutomatonSplittingTemporaries> temporaries
-#if CUDA_CAN_USE_TAIL_LAUNCH
-  , const int i_dimBlock, const int i_dimGrid
-#endif
-                                      )
+static __global__
+void propagateForMaximaExclusionKernel(Helpers::CUDA_kernel_object<TopoAutomatonSplittingTemporaries> temporaries,
+                                       const int i_dimBlock, const int i_dimGrid)
 {
   const int index = blockIdx.x * blockDim.x + threadIdx.x;
   const int grid_size = gridDim.x * blockDim.x;
@@ -766,12 +760,9 @@ void propagateForMaximaExclusionKernel( Helpers::CUDA_kernel_object<TopoAutomato
 #endif
 }
 
-__global__ static
-void checkForMaximaExclusionTermination(Helpers::CUDA_kernel_object<TopoAutomatonSplittingTemporaries> temporaries
-#if CUDA_CAN_USE_TAIL_LAUNCH
-  , const int i_dimBlock, const int i_dimGrid
-#endif
-                                       )
+static __global__
+void checkForMaximaExclusionTermination(Helpers::CUDA_kernel_object<TopoAutomatonSplittingTemporaries> temporaries,
+                                        const int i_dimBlock, const int i_dimGrid)
 {
   const int index = blockIdx.x * blockDim.x + threadIdx.x;
   if (index == 0)
@@ -782,7 +773,7 @@ void checkForMaximaExclusionTermination(Helpers::CUDA_kernel_object<TopoAutomato
           temporaries->continue_flag = 0;
 
 #if CUDA_CAN_USE_TAIL_LAUNCH
-          secondaryMaximaPropagationKernel <<< i_dimGrid, i_dimBlock, 0, cudaStreamTailLaunch>>>(temporaries, i_dimBlock, i_dimGrid);
+          propagateForMaximaExclusionKernel <<< i_dimGrid, i_dimBlock, 0, cudaStreamTailLaunch>>>(temporaries, i_dimBlock, i_dimGrid);
 
 #endif
         }
@@ -795,7 +786,7 @@ void checkForMaximaExclusionTermination(Helpers::CUDA_kernel_object<TopoAutomato
     }
 }
 
-__global__ static
+static __global__
 void excludeSecondaryMaximaDefer(Helpers::CUDA_kernel_object<TopoAutomatonSplittingTemporaries> temporaries,
                                  const int i_dimBlock, int i_dimGrid)
 {
@@ -819,8 +810,8 @@ void excludeSecondaryMaximaDefer(Helpers::CUDA_kernel_object<TopoAutomatonSplitt
 
       while (!temporaries->stop_flag)
         {
-          propagateForMaximaExclusionKernel <<< i_dimGrid, i_dimBlock>>>(temporaries);
-          checkForMaximaExclusionTermination <<< 1, 1>>>(temporaries);
+          propagateForMaximaExclusionKernel <<< i_dimGrid, i_dimBlock>>>(temporaries, i_dimBlock, i_dimGrid);
+          checkForMaximaExclusionTermination <<< 1, 1>>>(temporaries, i_dimBlock, i_dimGrid);
 
           //++counter;
         }
@@ -830,7 +821,7 @@ void excludeSecondaryMaximaDefer(Helpers::CUDA_kernel_object<TopoAutomatonSplitt
     }
 }
 
-__global__ static
+static __global__
 void cleanUpSecondariesKernel(Helpers::CUDA_kernel_object<CellStateArr> cell_state_arr,
                               Helpers::CUDA_kernel_object<ClusterInfoArr> clusters_arr,
                               Helpers::CUDA_kernel_object<TopoAutomatonSplittingTemporaries> temporaries)
@@ -881,7 +872,7 @@ void TASplitting::excludeSecondaryMaxima(EventDataHolder & holder,
                                          const bool synchronize,
                                          CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream)
 {
-  const cudaStream_t & stream_to_use = (stream != nullptr ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
+  const cudaStream_t & stream_to_use = (stream ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
 
   TopoAutomatonSplittingTemporaries * temps = TASHacks::get_temporaries(holder);
 
@@ -941,7 +932,7 @@ void TASplitting::excludeSecondaryMaxima(EventDataHolder & holder,
  * Propagate the new tags and create the final clusters.
  ******************************************************************************************/
 
-__device__ static
+static __device__
 void propagate_main_pair(const int pair,
                          Helpers::CUDA_kernel_object<TopoAutomatonSplittingTemporaries> temporaries,
                          const Helpers::CUDA_kernel_object<CellStateArr> cell_state_arr,
@@ -1001,7 +992,7 @@ void propagate_main_pair(const int pair,
     }
 }
 
-__device__ static
+static __device__
 void update_cell_tag(const int cell,
                      Helpers::CUDA_kernel_object<CellStateArr> cell_state_arr,
                      Helpers::CUDA_kernel_object<TopoAutomatonSplittingTemporaries> temporaries,
@@ -1062,7 +1053,7 @@ void update_cell_tag(const int cell,
   temporaries->secondary_array[cell] = new_tag;
 }
 
-__global__ static
+static __global__
 void clusterSplittingMainCooperativeKernel(Helpers::CUDA_kernel_object<CellStateArr> cell_state_arr,
                                            Helpers::CUDA_kernel_object<TopoAutomatonSplittingTemporaries> temporaries,
                                            const Helpers::CUDA_kernel_object<CellInfoArr> cell_info_arr,
@@ -1133,27 +1124,23 @@ namespace
 }
 
 
-__global__ static
+static __global__
 void handleSplitterTagChangesAndTerminationKernel(Helpers::CUDA_kernel_object<CellStateArr> cell_state_arr,
                                                   Helpers::CUDA_kernel_object<TopoAutomatonSplittingTemporaries> temporaries,
                                                   const Helpers::CUDA_kernel_object<CellInfoArr> cell_info_arr,
                                                   const bool counter_select,
-                                                  const bool share_cells
-#if CUDA_CAN_USE_TAIL_LAUNCH
-  , const kernel_sizes blocks, const kernel_sizes grids
-#endif
-                                                 );
+                                                  const bool share_cells,
+                                                  const kernel_sizes blocks,
+                                                  const kernel_sizes grids);
 
-__global__ static
+static __global__
 void propagateSplitterTagsKernel(const Helpers::CUDA_kernel_object<CellStateArr> cell_state_arr,
                                  Helpers::CUDA_kernel_object<TopoAutomatonSplittingTemporaries> temporaries,
                                  const Helpers::CUDA_kernel_object<CellInfoArr> cell_info_arr,
                                  const bool counter_select,
-                                 const bool share_cells
-#if CUDA_CAN_USE_TAIL_LAUNCH
-  , const kernel_sizes blocks, const kernel_sizes grids
-#endif
-                                )
+                                 const bool share_cells ,
+                                 const kernel_sizes blocks,
+                                 const kernel_sizes grids)
 {
   const int index = blockIdx.x * blockDim.x + threadIdx.x;
   const int grid_size = gridDim.x * blockDim.x;
@@ -1168,26 +1155,24 @@ void propagateSplitterTagsKernel(const Helpers::CUDA_kernel_object<CellStateArr>
   if (index == grid_size - 1)
     {
 
-      handleSplitterTagChangesAndTerminationKernel <<< grids.tag_change, block.tag_change, 0, cudaStreamTailLaunch>>>(cell_state_arr,
-                                                                                                                      temporaries,
-                                                                                                                      cell_info_arr,
-                                                                                                                      counter_select,
-                                                                                                                      share_cells,
-                                                                                                                      blocks, grids);
+      handleSplitterTagChangesAndTerminationKernel <<< grids.tag_change, blocks.tag_change, 0, cudaStreamTailLaunch>>>(cell_state_arr,
+                                                                                                                       temporaries,
+                                                                                                                       cell_info_arr,
+                                                                                                                       counter_select,
+                                                                                                                       share_cells,
+                                                                                                                       blocks, grids);
     }
 #endif
 }
 
-__global__ static
+static __global__
 void handleSplitterTagChangesAndTerminationKernel(Helpers::CUDA_kernel_object<CellStateArr> cell_state_arr,
                                                   Helpers::CUDA_kernel_object<TopoAutomatonSplittingTemporaries> temporaries,
                                                   const Helpers::CUDA_kernel_object<CellInfoArr> cell_info_arr,
                                                   const bool counter_select,
-                                                  const bool share_cells
-#if CUDA_CAN_USE_TAIL_LAUNCH
-  , const kernel_sizes blocks, const kernel_sizes grids
-#endif
-                                                 )
+                                                  const bool share_cells,
+                                                  const kernel_sizes blocks,
+                                                  const kernel_sizes grids)
 {
   const int index = blockIdx.x * blockDim.x + threadIdx.x;
   const int grid_size = gridDim.x * blockDim.x;
@@ -1224,7 +1209,7 @@ void handleSplitterTagChangesAndTerminationKernel(Helpers::CUDA_kernel_object<Ce
 
 
 
-__global__ static
+static __global__
 void clusterSplittingMainDefer(Helpers::CUDA_kernel_object<CellStateArr> cell_state_arr,
                                Helpers::CUDA_kernel_object<TopoAutomatonSplittingTemporaries> temporaries,
                                const Helpers::CUDA_kernel_object<CellInfoArr> cell_info_arr,
@@ -1261,13 +1246,15 @@ void clusterSplittingMainDefer(Helpers::CUDA_kernel_object<CellStateArr> cell_st
                                                                                temporaries,
                                                                                cell_info_arr,
                                                                                counter_select,
-                                                                               share_cells);
+                                                                               share_cells,
+                                                                               blocks, grids);
 
           handleSplitterTagChangesAndTerminationKernel <<< grids.tag_change, blocks.tag_change>>>(cell_state_arr,
                                                                                                   temporaries,
                                                                                                   cell_info_arr,
                                                                                                   counter_select,
-                                                                                                  share_cells);
+                                                                                                  share_cells,
+                                                                                                  blocks, grids);
 
           counter_select = !counter_select;
           //++counter;
@@ -1285,7 +1272,7 @@ void TASplitting::splitClusterGrowing(EventDataHolder & holder,
                                       const bool synchronize,
                                       CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream)
 {
-  const cudaStream_t & stream_to_use = (stream != nullptr ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
+  const cudaStream_t & stream_to_use = (stream ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
 
   TopoAutomatonSplittingTemporaries * temps = TASHacks::get_temporaries(holder);
 
@@ -1365,7 +1352,7 @@ namespace
 }
 
 
-__global__ static
+static __global__
 void sumCellsForCentroidKernel( Helpers::CUDA_kernel_object<TopoAutomatonSplittingTemporaries> temporaries,
                                 const Helpers::CUDA_kernel_object<CellStateArr> cell_state_arr,
                                 const Helpers::CUDA_kernel_object<CellInfoArr> cell_info_arr,
@@ -1399,7 +1386,7 @@ void sumCellsForCentroidKernel( Helpers::CUDA_kernel_object<TopoAutomatonSplitti
 
 
 
-__global__ static
+static __global__
 void calculateCentroidsKernel(Helpers::CUDA_kernel_object<TopoAutomatonSplittingTemporaries> temporaries,
                               const Helpers::CUDA_kernel_object<ClusterInfoArr> clusters_arr)
 {
@@ -1427,7 +1414,7 @@ void calculateCentroidsKernel(Helpers::CUDA_kernel_object<TopoAutomatonSplitting
     }
 }
 
-__global__ static
+static __global__
 void calculateCentroidsKernelDeferKernel(Helpers::CUDA_kernel_object<TopoAutomatonSplittingTemporaries> temporaries,
                                          const Helpers::CUDA_kernel_object<ClusterInfoArr> clusters_arr,
                                          const int i_dimBlock)
@@ -1446,7 +1433,7 @@ void calculateCentroidsKernelDeferKernel(Helpers::CUDA_kernel_object<TopoAutomat
     }
 }
 
-__global__ static
+static __global__
 void assignFinalCellsKernel( Helpers::CUDA_kernel_object<CellStateArr> cell_state_arr,
                              Helpers::CUDA_kernel_object<ClusterInfoArr> clusters_arr,
                              const Helpers::CUDA_kernel_object<TopoAutomatonSplittingTemporaries> temporaries,
@@ -1593,7 +1580,7 @@ void TASplitting::cellWeightingAndFinalization(EventDataHolder & holder,
                                                const bool synchronize,
                                                CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream)
 {
-  const cudaStream_t & stream_to_use = (stream != nullptr ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
+  const cudaStream_t & stream_to_use = (stream ? * ((cudaStream_t *) stream) : cudaStreamPerThread);
 
   TopoAutomatonSplittingTemporaries * temps = TASHacks::get_temporaries(holder);
 
diff --git a/Calorimeter/CaloRecGPU/src/components/CaloRecGPU_entries.cxx b/Calorimeter/CaloRecGPU/src/components/CaloRecGPU_entries.cxx
index c06b85a41b44d93bbf97ed74207c55fea1438d4c..9acb381b08fafc504dbecad2406864bd46fc31f7 100644
--- a/Calorimeter/CaloRecGPU/src/components/CaloRecGPU_entries.cxx
+++ b/Calorimeter/CaloRecGPU/src/components/CaloRecGPU_entries.cxx
@@ -1,7 +1,5 @@
 //
-// Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
-//
-// Dear emacs, this is -*- c++ -*-
+// Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 //
 // Dear emacs, this is -*- c++ -*-
 //
@@ -16,7 +14,6 @@
 #include "../TopoAutomatonClustering.h"
 #include "../CaloCellsCounterCPU.h"
 #include "../CaloCellsCounterGPU.h"
-#include "../CaloTopoClusterSplitterGPU.h"
 #include "../BasicGPUClusterInfoCalculator.h"
 #include "../TopoAutomatonSplitting.h"
 #include "../CaloClusterDeleter.h"
@@ -25,6 +22,7 @@
 #include "../GPUToAthenaImporterWithMoments.h"
 #include "../CaloMomentsDumper.h"
 #include "../GPUKernelSizeOptimizerSvc.h"
+#include "../CaloClusterStoreRawProperties.h"
 
 // Declare the "components".
 DECLARE_COMPONENT( CaloGPUHybridClusterProcessor )
@@ -36,7 +34,6 @@ DECLARE_COMPONENT( CaloCPUOutput )
 DECLARE_COMPONENT( TopoAutomatonClustering )
 DECLARE_COMPONENT( CaloCellsCounterCPU )
 DECLARE_COMPONENT( CaloCellsCounterGPU )
-DECLARE_COMPONENT( CaloTopoClusterSplitterGPU )
 DECLARE_COMPONENT( BasicGPUClusterInfoCalculator )
 DECLARE_COMPONENT( CaloClusterDeleter )
 DECLARE_COMPONENT( TopoAutomatonSplitting )
@@ -45,4 +42,5 @@ DECLARE_COMPONENT( GPUClusterInfoAndMomentsCalculator )
 DECLARE_COMPONENT( GPUToAthenaImporterWithMoments )
 DECLARE_COMPONENT( CaloMomentsDumper )
 DECLARE_COMPONENT( GPUKernelSizeOptimizerSvc )
+DECLARE_COMPONENT( CaloClusterStoreRawProperties )
 
diff --git a/Calorimeter/CaloRecGPU/test/CaloRecGPUTesting.py b/Calorimeter/CaloRecGPU/test/CaloRecGPUTesting.py
deleted file mode 100644
index 4c3ce332669b4e2fb759e67f082acfbb0738f2ae..0000000000000000000000000000000000000000
--- a/Calorimeter/CaloRecGPU/test/CaloRecGPUTesting.py
+++ /dev/null
@@ -1,792 +0,0 @@
-# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
-#import CaloRecGPU.CaloRecGPUConfigurator
-
-from CaloRecGPU.CaloRecGPUConfigurator import SingleToolToPlot, ComparedToolsToPlot
-
-from AthenaConfiguration.Enums import Format
-from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
-from AthenaConfiguration.ComponentFactory import CompFactory
-
-def PrevAlgorithmsConfiguration(Configurator, clustersname = None):
-    doLCCalib = Configurator.ConfigFlags.Calo.TopoCluster.doTopoClusterLocalCalib
-    
-    if clustersname is None:
-        clustersname = "CaloCalTopoClusters" if doLCCalib else "CaloTopoClusters"
-    
-    if clustersname=="CaloTopoClusters" and doLCCalib is True: 
-        raise RuntimeError("Inconsistent arguments: Name must not be 'CaloTopoClusters' if doLCCalib is True")
-    
-    Configurator.ClustersOutputName = clustersname
-    
-    result=ComponentAccumulator()
-    
-    if Configurator.ConfigFlags.Input.Format is Format.BS:
-        #Data-case: Schedule ByteStream reading for LAr & Tile
-        from LArByteStream.LArRawDataReadingConfig import LArRawDataReadingCfg
-        result.merge(LArRawDataReadingCfg(Configurator.ConfigFlags))
-
-        from TileByteStream.TileByteStreamConfig import TileRawDataReadingCfg
-        result.merge( TileRawDataReadingCfg(Configurator.ConfigFlags) )
-
-        if Configurator.ConfigFlags.Output.doWriteESD:
-            from TileRecAlgs.TileDigitsFilterConfig import TileDigitsFilterOutputCfg
-            result.merge(TileDigitsFilterOutputCfg(Configurator.ConfigFlags))
-        else: #Mostly for wrapping in RecExCommon
-            from TileRecAlgs.TileDigitsFilterConfig import TileDigitsFilterCfg
-            result.merge(TileDigitsFilterCfg(Configurator.ConfigFlags))
-
-        from LArROD.LArRawChannelBuilderAlgConfig import LArRawChannelBuilderAlgCfg
-        result.merge(LArRawChannelBuilderAlgCfg(Configurator.ConfigFlags))
-
-        from TileRecUtils.TileRawChannelMakerConfig import TileRawChannelMakerCfg
-        result.merge(TileRawChannelMakerCfg(Configurator.ConfigFlags))
-
-    if not Configurator.ConfigFlags.Input.isMC and not Configurator.ConfigFlags.Common.isOnline:
-        from LArCellRec.LArTimeVetoAlgConfig import LArTimeVetoAlgCfg
-        result.merge(LArTimeVetoAlgCfg(Configurator.ConfigFlags))
-
-    if not Configurator.ConfigFlags.Input.isMC and not Configurator.ConfigFlags.Overlay.DataOverlay:
-        from LArROD.LArFebErrorSummaryMakerConfig import LArFebErrorSummaryMakerCfg
-        result.merge(LArFebErrorSummaryMakerCfg(Configurator.ConfigFlags))
-        
-    if Configurator.ConfigFlags.Input.Format is Format.BS or 'StreamRDO' in Configurator.ConfigFlags.Input.ProcessingTags:
-        result.merge(Configurator.DefaultCaloCellMakerConf())
-    elif Configurator.FillMissingCells:
-        from AthenaCommon.Logging import log
-        log.warning("Asked to fill missing cells but will not run cell maker! Slow path might be taken!")
-
-    from CaloTools.CaloNoiseCondAlgConfig import CaloNoiseCondAlgCfg
-    
-    # Schedule total noise cond alg
-    result.merge(CaloNoiseCondAlgCfg(Configurator.ConfigFlags,"totalNoise"))
-    # Schedule electronic noise cond alg (needed for LC weights)
-    result.merge(CaloNoiseCondAlgCfg(Configurator.ConfigFlags,"electronicNoise"))
-    
-    if not Configurator.ConfigFlags.Common.isOnline:
-        from LArConfiguration.LArElecCalibDBConfig import LArElecCalibDBCfg
-        result.merge(LArElecCalibDBCfg(Configurator.ConfigFlags,["HVScaleCorr"]))
-    
-    return result
-    
-
-
-#TestGrow, TestSplit, TestMoments are self-explanatory.
-#If `DoCrossTests` is True, outputs and/or plots
-#are done considering all possible combinations
-#of (GPU, CPU) x (Growing, Splitting)
-#PlotterConfigurator takes the CaloGPUClusterAndCellDataMonitor
-#and adds the appropriate plots to it.
-def FullTestConfiguration(Configurator, TestGrow=False, TestSplit=False, TestMoments=False, DoCrossTests=False,
-                          PlotterConfigurator=None, clustersname=None, OutputCellInfo=False, SkipSyncs=True):
-    doLCCalib = Configurator.ConfigFlags.Calo.TopoCluster.doTopoClusterLocalCalib
-    
-    if clustersname is None:
-        clustersname = "CaloCalTopoClusters" if doLCCalib else "CaloTopoClusters"
-    
-    if clustersname=="CaloTopoClusters" and doLCCalib is True: 
-        raise RuntimeError("Inconsistent arguments: Name must not be 'CaloTopoClusters' if doLCCalib is True")
-    
-    Configurator.ClustersOutputName = clustersname
-    
-    if not (TestGrow and TestSplit):
-        DoCrossTests = False
-    
-    result= PrevAlgorithmsConfiguration(Configurator, clustersname)
-        
-    GPUKernelSvc = CompFactory.GPUKernelSizeOptimizerSvc()
-    result.addService(GPUKernelSvc)
-        
-    HybridClusterProcessor = CompFactory.CaloGPUHybridClusterProcessor("HybridClusterProcessor")
-    HybridClusterProcessor.ClustersOutputName = Configurator.ClustersOutputName
-    HybridClusterProcessor.MeasureTimes = Configurator.MeasureTimes
-    HybridClusterProcessor.TimeFileOutput = "GlobalTimes.txt"
-    HybridClusterProcessor.DeferConstantDataPreparationToFirstEvent = True
-            
-    if PlotterConfigurator is None:
-        HybridClusterProcessor.DoPlots = False
-    else:
-        HybridClusterProcessor.DoPlots = True
-        Plotter = PlotterConfigurator(result.popToolsAndMerge(Configurator.PlotterMonitoringToolConf()))
-        HybridClusterProcessor.PlotterTool = Plotter
-        if TestGrow and not DoCrossTests:
-            Plotter.ToolsToPlot += [ SingleToolToPlot("DefaultGrowing", "CPU_growing") ]
-            Plotter.ToolsToPlot += [ SingleToolToPlot("PropCalcPostGrowing", "GPU_growing") ]
-            Plotter.PairsToPlot += [ ComparedToolsToPlot("DefaultGrowing", "PropCalcPostGrowing", "growing") ]
-        if TestSplit and not DoCrossTests:
-            Plotter.ToolsToPlot += [ SingleToolToPlot("DefaultSplitting", "CPU_splitting") ]
-            Plotter.ToolsToPlot += [ SingleToolToPlot("PropCalcPostSplitting", "GPU_splitting") ]
-            Plotter.PairsToPlot += [ ComparedToolsToPlot("DefaultSplitting", "PropCalcPostSplitting", "splitting", True) ]
-        if TestMoments:
-            Plotter.ToolsToPlot += [ SingleToolToPlot("CPUMoments", "CPU_moments") ]
-            Plotter.ToolsToPlot += [ SingleToolToPlot("AthenaClusterImporter", "GPU_moments") ]
-            Plotter.PairsToPlot += [ ComparedToolsToPlot("CPUMoments", "AthenaClusterImporter", "moments", True) ]
-        if DoCrossTests:
-            Plotter.ToolsToPlot += [ SingleToolToPlot("DefaultGrowing", "CPU_growing") ]
-            Plotter.ToolsToPlot += [ SingleToolToPlot("PropCalcPostGrowing", "GPU_growing") ]
-            Plotter.PairsToPlot += [ ComparedToolsToPlot("DefaultGrowing", "PropCalcPostGrowing", "growing") ]
-            
-            Plotter.ToolsToPlot += [ SingleToolToPlot("DefaultSplitting", "CPUCPU_splitting") ]
-            Plotter.ToolsToPlot += [ SingleToolToPlot("PropCalcPostSplitting", "GPUGPU_splitting") ]
-            Plotter.PairsToPlot += [ ComparedToolsToPlot("DefaultSplitting", "PropCalcPostSplitting", "CPU_to_GPUGPU_splitting", True) ]
-            
-            Plotter.ToolsToPlot += [ SingleToolToPlot("PropCalcDefaultGrowGPUSplit", "CPUGPU_splitting") ]
-            Plotter.ToolsToPlot += [ SingleToolToPlot("DefaultPostGPUSplitting", "GPUCPU_splitting") ]
-            Plotter.PairsToPlot += [ ComparedToolsToPlot("DefaultSplitting", "PropCalcDefaultGrowGPUSplit", "CPU_to_CPUGPU_splitting", True) ]
-            Plotter.PairsToPlot += [ ComparedToolsToPlot("DefaultSplitting", "DefaultPostGPUSplitting", "CPU_to_GPUCPU_splitting", True) ]
-            
-        
-    HybridClusterProcessor.DoMonitoring = Configurator.DoMonitoring
-    
-    if Configurator.DoMonitoring or PlotterConfigurator is not None:
-        histSvc = CompFactory.THistSvc(Output = ["EXPERT DATAFILE='expert-monitoring.root', OPT='RECREATE'"])
-        result.addService(histSvc)
-    
-    if Configurator.DoMonitoring:
-        HybridClusterProcessor.MonitoringTool = Configurator.MonitorizationToolConf()
-    
-    HybridClusterProcessor.NumPreAllocatedDataHolders = Configurator.NumPreAllocatedDataHolders
-    
-    from LArGeoAlgsNV.LArGMConfig import LArGMCfg
-    from TileGeoModel.TileGMConfig import TileGMCfg
-    
-    result.merge(LArGMCfg(Configurator.ConfigFlags))
-    result.merge(TileGMCfg(Configurator.ConfigFlags))
-    
-    ConstantDataExporter = result.popToolsAndMerge( Configurator.BasicConstantDataExporterToolConf() )
-    EventDataExporter = result.popToolsAndMerge( Configurator.BasicEventDataExporterToolConf() )
-        
-    AthenaClusterImporter = None
-    
-    if TestMoments:
-         AthenaClusterImporter = result.popToolsAndMerge( Configurator.AthenaClusterAndMomentsImporterToolConf("AthenaClusterImporter") )
-    else:
-         AthenaClusterImporter = result.popToolsAndMerge( Configurator.BasicAthenaClusterImporterToolConf("AthenaClusterImporter") )
-            
-    HybridClusterProcessor.ConstantDataToGPUTool = ConstantDataExporter
-    HybridClusterProcessor.EventDataToGPUTool = EventDataExporter
-    HybridClusterProcessor.GPUToEventDataTool = AthenaClusterImporter
-    
-    HybridClusterProcessor.BeforeGPUTools = []
-           
-    if TestGrow or TestSplit or TestMoments:
-        DefaultClustering = result.popToolsAndMerge( Configurator.DefaultTopologicalClusteringToolConf("DefaultGrowing") )
-        
-        HybridClusterProcessor.BeforeGPUTools += [DefaultClustering]
-                    
-        if TestGrow and (not TestSplit or DoCrossTests):
-            if Configurator.OutputCountsToFile:
-                CPUCount1 = result.popToolsAndMerge( Configurator.CellsCounterCPUToolConf("./counts", "DefaultGrowCounter", "default_grow") )
-                HybridClusterProcessor.BeforeGPUTools += [CPUCount1]
-            if Configurator.OutputClustersToFile:
-                CPUOut1 = result.popToolsAndMerge( Configurator.CPUOutputToolConf("./out_default_grow", "DefaultGrowOutput") )
-                HybridClusterProcessor.BeforeGPUTools += [CPUOut1]
-        
-            
-        if TestSplit or TestMoments:
-            FirstSplitter = result.popToolsAndMerge( Configurator.DefaultClusterSplittingToolConf("DefaultSplitting") )
-            HybridClusterProcessor.BeforeGPUTools += [FirstSplitter]
-            
-            if Configurator.OutputCountsToFile:
-                CPUCount2 = result.popToolsAndMerge( Configurator.CellsCounterCPUToolConf("./counts", "DefaultGrowAndSplitCounter", "default_grow_split") )
-                HybridClusterProcessor.BeforeGPUTools += [CPUCount2]
-            if Configurator.OutputClustersToFile:
-                CPUOut2 = result.popToolsAndMerge( Configurator.CPUOutputToolConf("./out_default_grow_split", "DefaultSplitOutput") )
-                HybridClusterProcessor.BeforeGPUTools += [CPUOut2]
-        
-        if TestMoments:
-            CPUMoments = result.popToolsAndMerge( Configurator.DefaultClusterMomentsCalculatorToolConf("CPUMoments") )
-            HybridClusterProcessor.BeforeGPUTools += [CPUMoments]
-            if Configurator.OutputCountsToFile:
-                CPUDumper = result.popToolsAndMerge( Configurator.MomentsDumperToolConf("./moments", "CPUMomentsDumper", "CPU") )
-                HybridClusterProcessor.BeforeGPUTools += [CPUDumper]
-        
-        Deleter = result.popToolsAndMerge( Configurator.CaloClusterDeleterToolConf())
-        HybridClusterProcessor.BeforeGPUTools += [Deleter]                
-        
-        if TestSplit and (not TestGrow or DoCrossTests):
-            SecondDefaultClustering = result.popToolsAndMerge( Configurator.DefaultTopologicalClusteringToolConf("SecondDefaultGrowing") )
-            HybridClusterProcessor.BeforeGPUTools += [SecondDefaultClustering]
-        
-    HybridClusterProcessor.GPUTools = []
-    
-    if OutputCellInfo:
-        CellOut = result.popToolsAndMerge( Configurator.GPUOutputToolConf("./out_cell", "CellInfoOutput", OnlyOutputCells = True) )
-        HybridClusterProcessor.GPUTools += [CellOut]
-        
-    if TestSplit:
-        if not TestGrow:
-            GPUClusterSplitting1 = result.popToolsAndMerge( Configurator.TopoAutomatonSplitterToolConf("GPUSplitter") )
-            if SkipSyncs:
-                GPUClusterSplitting1.MeasureTimes = False
-            HybridClusterProcessor.GPUTools += [GPUClusterSplitting1]
-            PropCalc1 = result.popToolsAndMerge( Configurator.ClusterInfoCalcToolConf("PropCalcPostSplitting", False) )
-            if SkipSyncs:
-                PropCalc1.MeasureTimes = False
-            HybridClusterProcessor.GPUTools += [PropCalc1]
-        elif DoCrossTests:
-            GPUClusterSplitting1 = result.popToolsAndMerge( Configurator.TopoAutomatonSplitterToolConf("FirstGPUSplitter") )
-            GPUClusterSplitting1.TimeFileOutput = "" #This means there's no output.
-            GPUClusterSplitting1.MeasureTimes = False
-            HybridClusterProcessor.GPUTools += [GPUClusterSplitting1]
-            PropCalc1 = result.popToolsAndMerge( Configurator.ClusterInfoCalcToolConf("PropCalcDefaultGrowGPUSplit", False) )
-            PropCalc1.TimeFileOutput = "" #This means there's no output.
-            PropCalc1.MeasureTimes = False
-            HybridClusterProcessor.GPUTools += [PropCalc1]
-        
-        if ((not TestGrow) or DoCrossTests):
-            if Configurator.OutputCountsToFile:
-                GPUCount1 = result.popToolsAndMerge( Configurator.CellsCounterGPUToolConf("./counts", "DefaultGrowModifiedSplitCounter", "default_grow_modified_split") )
-                HybridClusterProcessor.GPUTools += [GPUCount1]
-            if Configurator.OutputClustersToFile:
-                GPUOut1 = result.popToolsAndMerge( Configurator.GPUOutputToolConf("./out_default_grow_modified_split", "DefaultGrowModifiedSplitOutput") )
-                HybridClusterProcessor.GPUTools += [GPUOut1]
-        
-    if TestGrow:
-        TopoAutomatonClustering1 = result.popToolsAndMerge( Configurator.TopoAutomatonClusteringToolConf("GPUGrowing") )
-        if SkipSyncs:
-            TopoAutomatonClustering1.MeasureTimes = False
-        HybridClusterProcessor.GPUTools += [TopoAutomatonClustering1]
-        
-        PropCalc2 = result.popToolsAndMerge( Configurator.ClusterInfoCalcToolConf("PropCalcPostGrowing", True))
-        if SkipSyncs:
-            PropCalc2.MeasureTimes = False
-        HybridClusterProcessor.GPUTools += [PropCalc2]
-        if ((not TestSplit) or DoCrossTests):
-            if Configurator.OutputCountsToFile:
-                GPUCount2 = result.popToolsAndMerge( Configurator.CellsCounterGPUToolConf("./counts", "ModifiedGrowCounter", "modified_grow") )
-                HybridClusterProcessor.GPUTools += [GPUCount2]
-            if Configurator.OutputClustersToFile:
-                GPUOut2 = result.popToolsAndMerge( Configurator.GPUOutputToolConf("./out_modified_grow", "ModifiedGrowOutput") )
-                HybridClusterProcessor.GPUTools += [GPUOut2]
-    
-    if TestGrow and TestSplit:
-        GPUClusterSplitting2 = result.popToolsAndMerge( Configurator.TopoAutomatonSplitterToolConf("GPUSplitter") )
-        if SkipSyncs:
-            GPUClusterSplitting2.MeasureTimes = False
-        HybridClusterProcessor.GPUTools += [GPUClusterSplitting2]
-        
-        if HybridClusterProcessor.DoPlots or not TestMoments:
-          PropCalc3 = result.popToolsAndMerge( Configurator.ClusterInfoCalcToolConf("PropCalcPostSplitting", False) )
-          if SkipSyncs:
-              PropCalc3.MeasureTimes = False
-          HybridClusterProcessor.GPUTools += [PropCalc3]
-        
-        if Configurator.OutputCountsToFile:
-            GPUCount3 = result.popToolsAndMerge( Configurator.CellsCounterGPUToolConf("./counts", "ModifiedGrowSplitCounter", "modified_grow_split") )
-            HybridClusterProcessor.GPUTools += [GPUCount3]
-        if Configurator.OutputClustersToFile:
-            GPUOut3 = result.popToolsAndMerge( Configurator.GPUOutputToolConf("./out_modified_grow_split", "ModifiedGrowSplitOutput") )
-            HybridClusterProcessor.GPUTools += [GPUOut3]
-        
-        if DoCrossTests:
-            TopoAutomatonClustering2 = result.popToolsAndMerge( Configurator.TopoAutomatonClusteringToolConf("SecondGPUGrowing") )
-            TopoAutomatonClustering2.MeasureTimes = False
-            TopoAutomatonClustering2.TimeFileOutput = "" #This means there's no output.
-            HybridClusterProcessor.GPUTools += [TopoAutomatonClustering2]
-            
-            PropCalc4 = result.popToolsAndMerge( Configurator.ClusterInfoCalcToolConf("PropCalc4", True) )
-            PropCalc4.TimeFileOutput = "" #This means there's no output.
-            PropCalc4.MeasureTimes = False
-            HybridClusterProcessor.GPUTools += [PropCalc4]
-        
-    if not (TestGrow or TestSplit):
-        TopoAutomatonClusteringDef = result.popToolsAndMerge( Configurator.TopoAutomatonClusteringToolConf("TopoAutomatonClustering") )
-        if SkipSyncs:
-            TopoAutomatonClusteringDef.MeasureTimes = False
-        HybridClusterProcessor.GPUTools += [TopoAutomatonClusteringDef]
-        
-        FirstPropCalcDef = result.popToolsAndMerge( Configurator.ClusterInfoCalcToolConf("PropCalcPostGrowing", True) )
-        if SkipSyncs:
-            FirstPropCalcDef.MeasureTimes = False
-        HybridClusterProcessor.GPUTools += [FirstPropCalcDef]
-        
-        GPUClusterSplittingDef = result.popToolsAndMerge( Configurator.TopoAutomatonSplitterToolConf("GPUTopoSplitter") )
-        if SkipSyncs:
-            GPUClusterSplittingDef.MeasureTimes = False
-        HybridClusterProcessor.GPUTools += [GPUClusterSplittingDef]
-        
-        if not TestMoments:
-            SecondPropCalcDef = result.popToolsAndMerge( Configurator.ClusterInfoCalcToolConf("PropCalcPostSplitting", False) )
-            if SkipSyncs:
-                SecondPropCalcDef.MeasureTimes = False
-            HybridClusterProcessor.GPUTools += [SecondPropCalcDef]
-    
-    if TestMoments and not DoCrossTests:
-        if TestGrow and not TestSplit:
-            GPUClusterSplittingDef = result.popToolsAndMerge( Configurator.TopoAutomatonSplitterToolConf("GPUTopoSplitter") )
-            if SkipSyncs:
-                GPUClusterSplittingDef.MeasureTimes = False
-            HybridClusterProcessor.GPUTools += [GPUClusterSplittingDef]
-            
-        GPUMomentsDef = result.popToolsAndMerge( Configurator.GPUClusterMomentsCalculatorToolConf("GPUTopoMoments") )
-        if SkipSyncs:
-            GPUMomentsDef.MeasureTimes = False
-        HybridClusterProcessor.GPUTools += [GPUMomentsDef]
-        
-    HybridClusterProcessor.AfterGPUTools = []
-    
-    if TestMoments and Configurator.OutputCountsToFile:
-        GPUDumper = result.popToolsAndMerge( Configurator.MomentsDumperToolConf("./moments", "GPUMomentsDumper", "GPU") )
-        HybridClusterProcessor.AfterGPUTools += [GPUDumper]
-        
-    if TestGrow and (not TestSplit or DoCrossTests):
-    
-        TopoSplitter = result.popToolsAndMerge( Configurator.DefaultClusterSplittingToolConf("DefaultPostGPUSplitting") )
-        HybridClusterProcessor.AfterGPUTools += [TopoSplitter]
-        
-        if DoCrossTests:
-            if Configurator.OutputCountsToFile:
-                CPUCount3 = result.popToolsAndMerge( Configurator.CellsCounterCPUToolConf("./counts", "ModifiedGrowDefaultSplitCounter", "modified_grow_default_split") )
-                HybridClusterProcessor.AfterGPUTools += [CPUCount3]
-            if Configurator.OutputClustersToFile:
-                CPUOut3 = result.popToolsAndMerge( Configurator.CPUOutputToolConf("./out_modified_grow_default_split", "ModifiedGrowDefaultSplitOutput") )
-                HybridClusterProcessor.AfterGPUTools += [CPUOut3]
-            
-    result.addEventAlgo(HybridClusterProcessor,primary=True)
-
-    return result
-        
-    
-def PrepareTest(Configurator,
-                default_files = ["/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/RecExRecoTest/mc20e_13TeV/valid1.410000.PowhegPythiaEvtGen_P2012_ttbar_hdamp172p5_nonallhad.ESD.e4993_s3227_r12689/myESD.pool.root"],
-                parse_command_arguments = True,
-                allocate_as_many_as_threads = True):
-
-    import argparse
-    
-    args = None
-    rest = None
-    
-    if parse_command_arguments:
-        parser = argparse.ArgumentParser()
-        
-        parser.add_argument('-events','--numevents', type=int, default = 10)
-        parser.add_argument('-threads','--numthreads', type=int, default = 1)
-        parser.add_argument('-f','--files', action = 'extend', nargs = '*')
-        parser.add_argument('-t','--measuretimes', action = 'store_true')
-        parser.add_argument('-o','--outputclusters', action = 'store_true')
-        parser.add_argument('-c','--outputcounts', action = 'store_true')
-        parser.add_argument('-nfc','--notfillcells', action = 'store_true')
-        
-        parser.add_argument('-uoc','--useoriginalcriteria', action = 'store_true')
-        
-        parser.add_argument('-ndgn','--nodoublegaussiannoise', action = 'store_true')
-       
-        parser.add_argument('-m','--perfmon', action = 'store_true')
-        parser.add_argument('-fm','--fullmon', action = 'store_true')
-                   
-        
-        (args, pre_rest) = parser.parse_known_args()
-                    
-        if pre_rest is None or len(pre_rest) == 0:
-            rest = ['--threads', '1']
-            #Crude workaround for a condition within ConfigFlags.fillFromArgs
-            #that would make it inspect the whole command-line when provided
-            #with an empty list of arguments.
-            #(I'd personally suggest changing the "listOfArgs or sys.argv[1:]"
-            # used there since empty arrays are falsy while being non-null,
-            # to a "sys.argv[1:] if listofArgs is None else listofArgs",
-            # but I'm not about to suggest potentially code-breaking behaviour changes
-            # when I can work around them easily, even if rather inelegantly...)
-        else:
-            rest = pre_rest
-    
-    from AthenaCommon.Configurable import Configurable
-    Configurable.configurableRun3Behavior=1
-
-    from AthenaConfiguration.AllConfigFlags import initConfigFlags
-    #from AthenaConfiguration.TestDefaults import defaultTestFiles
-                    
-    Configurator.ConfigFlags = initConfigFlags() #ConfigFlags.clone()
-    
-    if parse_command_arguments:
-        Configurator.ConfigFlags.fillFromArgs(listOfArgs=rest)
-        #We could instead use our parser to overload here and so on, but...
-    
-    if args is None or args.files is None:
-        Configurator.ConfigFlags.Input.Files = default_files
-    elif len(args.files) == 0:
-        Configurator.ConfigFlags.Input.Files = default_files
-    elif len(args.files) == 1:
-        if args.files[0] == 'default':
-            Configurator.ConfigFlags.Input.Files = default_files
-        elif args.files[0] == 'ttbar':
-            Configurator.ConfigFlags.Input.Files = ["/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/TrigInDetValidation/samples/mc15_13TeV.410000.PowhegPythiaEvtGen_P2012_ttbar_hdamp172p5_nonallhad.recon.RDO.e3698_s2608_s2183_r7195/RDO.06752780._000001.pool.root.1",
-                                       "/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/TrigInDetValidation/samples/mc15_13TeV.410000.PowhegPythiaEvtGen_P2012_ttbar_hdamp172p5_nonallhad.recon.RDO.e3698_s2608_s2183_r7195/RDO.06752780._000002.pool.root.1",
-                                       "/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/TrigInDetValidation/samples/mc15_13TeV.410000.PowhegPythiaEvtGen_P2012_ttbar_hdamp172p5_nonallhad.recon.RDO.e3698_s2608_s2183_r7195/RDO.06752780._000003.pool.root.1" ]
-            
-        elif args.files[0] == 'jets':
-            Configurator.ConfigFlags.Input.Files = ["/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/TrigEgammaValidation/valid3.147917.Pythia8_AU2CT10_jetjet_JZ7W.recon.RDO.e3099_s2578_r6596_tid05293007_00/RDO.05293007._000001.pool.root.1"]
-        else:
-            Configurator.ConfigFlags.Input.Files = args.files
-    else:
-        Configurator.ConfigFlags.Input.Files = args.files
-           
-    #Configurator.ConfigFlags.Input.Files = defaultTestFiles.RDO_RUN2
-            
-    if parse_command_arguments:
-        Configurator.ConfigFlags.Concurrency.NumThreads = int(args.numthreads)
-        Configurator.ConfigFlags.Concurrency.NumConcurrentEvents = int(args.numthreads)
-        #This is to ensure the measurments are multi-threaded in the way we expect, I guess?
-        Configurator.ConfigFlags.PerfMon.doFastMonMT = args.perfmon
-        Configurator.ConfigFlags.PerfMon.doFullMonMT = args.fullmon
-            
-    
-    Configurator.ConfigFlags.lock()
-    
-    from AthenaConfiguration.MainServicesConfig import MainServicesCfg
-    from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg
-
-    cfg=MainServicesCfg(Configurator.ConfigFlags)
-    cfg.merge(PoolReadCfg(Configurator.ConfigFlags))
-    
-    if parse_command_arguments:
-        if args.perfmon or args.fullmon:
-             from PerfMonComps.PerfMonCompsConfig import PerfMonMTSvcCfg
-             cfg.merge(PerfMonMTSvcCfg(Configurator.ConfigFlags))
-            
-    if parse_command_arguments:
-        Configurator.MeasureTimes = args.measuretimes
-        Configurator.OutputClustersToFile = args.outputclusters
-        Configurator.OutputCountsToFile = args.outputcounts
-        Configurator.FillMissingCells = not args.notfillcells
-        Configurator.UseOriginalCriteria = args.useoriginalcriteria
-        Configurator.TwoGaussianNoise = not args.nodoublegaussiannoise
-        if allocate_as_many_as_threads:
-            Configurator.NumPreAllocatedDataHolders = int(args.numthreads)
-    
-    if 'StreamRDO' in Configurator.ConfigFlags.Input.ProcessingTags:
-        cfg.addEventAlgo(CompFactory.xAODMaker.EventInfoCnvAlg(),sequenceName="AthAlgSeq")
-    
-    Configurator.MissingCellsToFill = [186986, 187352]
-    
-    if parse_command_arguments:
-        return (cfg, int(args.numevents))
-    else:
-        return (cfg, -1)
-
-#For pretty printing things in axes when it comes to moments:
-#<MOMENT_NAME>: <PLOT TITLE> <AXIS TITLE> <UNITS>
-name_to_moment_map =  {
-   #"time"                        :  (("time",                "time",               "[#mu s]"),[]),
-    "FIRST_PHI"                   :  (("firstPhi",            "firstPhi",            ""),[(-3.2, 3.2)]),
-    "FIRST_ETA"                   :  (("firstEta",            "firstEta",            ""),[(-10.1, 10.1)]),
-    "SECOND_R"                    :  (("secondR",             "secondR",             ""),[(0, 1.25e6)]),
-    "SECOND_LAMBDA"               :  (("secondLambda",        "secondLambda",        ""),[(0, 2.5e6)]),
-    "DELTA_PHI"                   :  (("deltaPhi",            "deltaPhi",            ""),[(-3.2, 3.2)]),
-    "DELTA_THETA"                 :  (("deltaTheta",          "deltaTheta",          ""),[(-1.6, 1.6)]),
-    "DELTA_ALPHA"                 :  (("deltaAlpha",          "deltaAlpha",          ""),[(-0.1, 1.6)]),
-    "CENTER_X"                    :  (("centerX",             "centerX",             ""),[(-4000, 4000)]),
-    "CENTER_Y"                    :  (("centerY",             "centerY",             ""),[(-4000, 4000)]),
-    "CENTER_Z"                    :  (("centerZ",             "centerZ",             ""),[(-7000, 7000)]),
-    "CENTER_MAG"                  :  (("centerMag",           "centerMag",           ""),[(1000, 7500)]),
-    "CENTER_LAMBDA"               :  (("centerLambda",        "centerLambda",        ""),[(0., 25000.),(0., 5000.)]),
-    "LATERAL"                     :  (("lateral",             "lateral",             ""),[(-0.05, 1.05)]),
-    "LONGITUDINAL"                :  (("longitudinal",        "longitudinal",        ""),[(-0.05, 1.05)]),
-    "ENG_FRAC_EM"                 :  (("engFracEM",           "engFracEM",           ""),[(-0.1, 1.1)]),
-    "ENG_FRAC_MAX"                :  (("engFracMax",          "engFracMax",          ""),[(-0.1, 1.1)]),
-    "ENG_FRAC_CORE"               :  (("engFracCore",         "engFracCore",         ""),[(-0.1, 1.1)]),
-    "FIRST_ENG_DENS"              :  (("firstEngDens",        "firstEngDens",        ""),[(-0.1, 5.1)]),
-    "SECOND_ENG_DENS"             :  (("secondEngDens",       "secondEngDens",       ""),[(-0.5, 50.5)]),
-    "ISOLATION"                   :  (("isolation",           "isolation",           ""),[(-0.05, 2.05)]),
-    "ENG_BAD_CELLS"               :  (("engBadCells",         "engBadCells",         ""),[(0., 100000.)]),
-    "N_BAD_CELLS"                 :  (("nBadCells",           "nBadCells",           ""),[(-0.5, 25.5)]),
-    "N_BAD_CELLS_CORR"            :  (("nBadCellsCorr",       "nBadCellsCorr",       ""),[(-0.5, 25.5)]),
-    "BAD_CELLS_CORR_E"            :  (("badCellsCorrE",       "badCellsCorrE",       ""),[(-0.1, 25000.)]),
-    "BADLARQ_FRAC"                :  (("badLArQFrac",         "badLArQFrac",         ""),[(-2500., 2500.)]),
-    "ENG_POS"                     :  (("engPos",              "engPos",              ""),[(-0.1, 250000.)]),
-    "SIGNIFICANCE"                :  (("significance",        "significance",        ""),[(-500., 500.)]),
-    "CELL_SIGNIFICANCE"           :  (("cellSignificance",    "cellSignificance",    ""),[(-0.1, 100.)]),
-    "CELL_SIG_SAMPLING"           :  (("cellSigSampling",     "cellSigSampling",     ""),[(-0.1, 30.)]),
-    "AVG_LAR_Q"                   :  (("avgLArQ",             "avgLArQ",             ""),[(-0.1, 70000.)]),
-    "AVG_TILE_Q"                  :  (("avgTileQ",            "avgTileQ",            ""),[(-0.1, 300.)]),
-   #"ENG_BAD_HV_CELLS"            :  (("engBadHVCells",       "engBadHVCells",       ""),[]),
-   #"N_BAD_HV_CELLS"              :  (("nBadHVCells",         "nBadHVCells",         ""),[]),
-    "PTD"                         :  (("PTD",                 "PTD",                 ""),[(-0.05, 1.05)]),
-    "MASS"                        :  (("mass",                "mass",                ""),[(0., 200000.), (0., 100.)]),
-   #"EM_PROBABILITY"              :  (("EMProbability",       "EMProbability",       ""),[]),
-   #"HAD_WEIGHT"                  :  (("hadWeight",           "hadWeight",           ""),[]),
-   #"OOC_WEIGHT"                  :  (("OOCweight",           "OOCweight",           ""),[]),
-   #"DM_WEIGHT"                   :  (("DMweight",            "DMweight",            ""),[]),
-   #"TILE_CONFIDENCE_LEVEL"       :  (("tileConfidenceLevel", "tileConfidenceLevel", ""),[]),
-    "SECOND_TIME"                 :  (("secondTime",          "secondTime",          ""),[(0., 1e7)])
-   #"number_of_cells"             :  (("numCells",            "numCells",            ""),[]),
-   #"VERTEX_FRACTION"             :  (("vertexFraction",      "vertexFraction",      ""),[]),
-   #"NVERTEX_FRACTION"            :  (("nVertexFraction",     "nVertexFraction",     ""),[]),
-   #"ETACALOFRAME"                :  (("etaCaloFrame",        "etaCaloFrame",        ""),[]),
-   #"PHICALOFRAME"                :  (("phiCaloFrame",        "phiCaloFrame",        ""),[]),
-   #"ETA1CALOFRAME"               :  (("eta1CaloFrame",       "eta1CaloFrame",       ""),[]),
-   #"PHI1CALOFRAME"               :  (("phi1CaloFrame",       "phi1CaloFrame",       ""),[]),
-   #"ETA2CALOFRAME"               :  (("eta2CaloFrame",       "eta2CaloFrame",       ""),[]),
-   #"PHI2CALOFRAME"               :  (("phi2CaloFrame",       "phi2CaloFrame",       ""),[]),
-   #"ENG_CALIB_TOT"               :  (("engCalibTot",         "engCalibTot",         ""),[]),
-   #"ENG_CALIB_OUT_L"             :  (("engCalibOutL",        "engCalibOutL",        ""),[]),
-   #"ENG_CALIB_OUT_M"             :  (("engCalibOutM",        "engCalibOutM",        ""),[]),
-   #"ENG_CALIB_OUT_T"             :  (("engCalibOutT",        "engCalibOutT",        ""),[]),
-   #"ENG_CALIB_DEAD_L"            :  (("engCalibDeadL",       "engCalibDeadL",       ""),[]),
-   #"ENG_CALIB_DEAD_M"            :  (("engCalibDeadM",       "engCalibDeadM",       ""),[]),
-   #"ENG_CALIB_DEAD_T"            :  (("engCalibDeadT",       "engCalibDeadT",       ""),[]),
-   #"ENG_CALIB_EMB0"              :  (("engCalibEMB0",        "engCalibEMB0",        ""),[]),
-   #"ENG_CALIB_EME0"              :  (("engCalibEME0",        "engCalibEME0",        ""),[]),
-   #"ENG_CALIB_TILEG3"            :  (("engCalibTileG3",      "engCalibTileG3",      ""),[]),
-   #"ENG_CALIB_DEAD_TOT"          :  (("engCalibDeadTot",     "engCalibDeadTot",     ""),[]),
-   #"ENG_CALIB_DEAD_EMB0"         :  (("engCalibDeadEMB0",    "engCalibDeadEMB0",    ""),[]),
-   #"ENG_CALIB_DEAD_TILE0"        :  (("engCalibDeadTile0",   "engCalibDeadTile0",   ""),[]),
-   #"ENG_CALIB_DEAD_TILEG3"       :  (("engCalibDeadTileG3",  "engCalibDeadTileG3",  ""),[]),
-   #"ENG_CALIB_DEAD_EME0"         :  (("engCalibDeadEME0",    "engCalibDeadEME0",    ""),[]),
-   #"ENG_CALIB_DEAD_HEC0"         :  (("engCalibDeadHEC0",    "engCalibDeadHEC0",    ""),[]),
-   #"ENG_CALIB_DEAD_FCAL"         :  (("engCalibDeadFCAL",    "engCalibDeadFCAL",    ""),[]),
-   #"ENG_CALIB_DEAD_LEAKAGE"      :  (("engCalibDeadLeakage", "engCalibDeadLeakage", ""),[]),
-   #"ENG_CALIB_DEAD_UNCLASS"      :  (("engCalibDeadUnclass", "engCalibDeadUnclass", ""),[]),
-   #"ENG_CALIB_FRAC_EM"           :  (("engCalibFracEM",      "engCalibFracEM",      ""),[]),
-   #"ENG_CALIB_FRAC_HAD"          :  (("engCalibFracHad",     "engCalibFracHad",     ""),[]),
-   #"ENG_CALIB_FRAC_REST"         :  (("engCalibFracRest"     "engCalibFracRest"     ""),[])
-}
-
-class PlotterConfigurator:
-    #DoCells currently changes nothing
-    #(originally was intended to show
-    #that we had cells with the same energy),
-    #keeping it here to remain part of the interface
-    #if/when we port the cell maker as well.
-    def __init__ (self, StepsToPlot = [], PairsToPlot = [], DoStandard = True, DoMoments = False, DoCells = False):
-        self.PlotsToDo = []
-        if DoStandard:
-            for step in StepsToPlot:
-                self.PlotsToDo += [
-                                    ( (step + "_cluster_E",),
-                                      {'type': 'TH1F', 
-                                       'title': "Cluster Energy; E [MeV]; Number of Events",
-                                       'xbins':  63,
-                                       'xmin':  -5020,
-                                       'xmax':   5020,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (step + "_cluster_Et",),
-                                      {'type': 'TH1F', 
-                                       'title': "Cluster Transverse Energy; E_T [MeV]; Number of Events",
-                                       'xbins':  63,
-                                       'xmin':  -5020,
-                                       'xmax':   5020,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (step + "_cluster_eta",),
-                                      {'type': 'TH1F', 
-                                       'title': "Cluster #eta; #eta; Number of Events",
-                                       'xbins':  84,
-                                       'xmin':  -10.5,
-                                       'xmax':   10.5,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (step + "_cluster_phi",),
-                                      {'type': 'TH1F', 
-                                       'title': "Cluster #phi; #phi; Number of Events",
-                                       'xbins':  61,
-                                       'xmin':  -3.25,
-                                       'xmax':   3.25,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (step + "_cluster_eta," + step + "_cluster_phi",),
-                                      {'type': 'TH2F', 
-                                       'title': "Cluster #eta versus #phi; #eta; #phi",
-                                       'xbins':  84,
-                                       'xmin':  -10.5,
-                                       'xmax':   10.5,
-                                       'ybins':  61,
-                                       'ymin':  -3.25,
-                                       'ymax':   3.25,
-                                       'path': "EXPERT"}
-                                    )
-                                  ]
-            for pair in PairsToPlot:
-                self.PlotsToDo += [
-                                    ( (pair + "_num_unmatched_clusters",),
-                                      {'type': 'TH1F', 
-                                       'title': "Number of Unmatched Clusters; # of Unmatched Clusters; Number of Events",
-                                       'xbins':  21,
-                                       'xmin':  -0.5,
-                                       'xmax':   20.5,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (pair + "_cluster_diff_cells;" + pair + "_cluster_diff_cells_zoom_0",),
-                                      {'type': 'TH1F',
-                                       'title': "Different Cell Assignments; # of Differently Assigned Cells; Number of Clusters",
-                                       'xbins':  21,
-                                       'xmin':  -25,
-                                       'xmax':   1025,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (pair + "_cluster_diff_cells;" + pair + "_cluster_diff_cells_zoom_1",),
-                                      {'type': 'TH1F',
-                                       'title': "Different Cell Assignments; # of Differently Assigned Cells; Number of Clusters",
-                                       'xbins':  21,
-                                       'xmin':  -12.5,
-                                       'xmax':   512.5,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (pair + "_cluster_diff_cells;" + pair + "_cluster_diff_cells_zoom_2",),
-                                      {'type': 'TH1F',
-                                       'title': "Different Cell Assignments; # of Differently Assigned Cells; Number of Clusters",
-                                       'xbins':  21,
-                                       'xmin':  -2.5,
-                                       'xmax':   102.5,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (pair + "_cluster_diff_cells;" + pair + "_cluster_diff_cells_zoom_3",),
-                                      {'type': 'TH1F',
-                                       'title': "Different Cell Assignments; # of Differently Assigned Cells; Number of Clusters",
-                                       'xbins':  21,
-                                       'xmin':  -0.5,
-                                       'xmax':   20.5,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (pair + "_cluster_E_ref," + pair + "_cluster_E_test",),
-                                      {'type': 'TH2F', 
-                                       'title': "Cluster Energy Comparison; E^{(CPU)} [MeV]; E^{(GPU)} [MeV]",
-                                       'xbins':  63,
-                                       'xmin':  -50.5,
-                                       'xmax':   50.5,
-                                       'ybins':  63,
-                                       'ymin':  -50.5,
-                                       'ymax':   50.5,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (pair + "_cluster_E_ref," + pair + "_cluster_delta_E_rel_ref",),
-                                      {'type': 'TH2F', 
-                                       'title': "Cluster Energy Resolution; E^{(CPU)} [MeV]; #Delta E / #(){E^{(CPU)}}",
-                                       'xbins':  63,
-                                       'xmin':  -50.5,
-                                       'xmax':   50.5,
-                                       'ybins':  63,
-                                       'ymin':  -0.025,
-                                       'ymax':   0.025,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (pair + "_cluster_Et_ref," + pair + "_cluster_Et_test",),
-                                      {'type': 'TH2F', 
-                                       'title': "Cluster Transverse Energy Comparison; E_T^{(CPU)} [MeV]; E_T^{(GPU)} [MeV]",
-                                       'xbins':  63,
-                                       'xmin':  -50.5,
-                                       'xmax':   50.5,
-                                       'ybins':  63,
-                                       'ymin':  -50.5,
-                                       'ymax':   50.5,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (pair + "_cluster_Et_ref," + pair + "_cluster_delta_Et_rel_ref",),
-                                      {'type': 'TH2F', 
-                                       'title': "Cluster Transverse Energy Resolution; E_T^{(CPU)} [MeV]; #Delta E_T / #(){E_T^{(CPU)}}",
-                                       'xbins':  63,
-                                       'xmin':  -50.5,
-                                       'xmax':   50.5,
-                                       'ybins':  63,
-                                       'ymin':  -0.025,
-                                       'ymax':   0.025,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (pair + "_cluster_eta_ref," + pair + "_cluster_eta_test",),
-                                      {'type': 'TH2F', 
-                                       'title': "Cluster #eta Comparison; #eta^{(CPU)}; #eta^{(GPU)}",
-                                       'xbins':  63,
-                                       'xmin':  -10.5,
-                                       'xmax':   10.5,
-                                       'ybins':  63,
-                                       'ymin':  -10.5,
-                                       'ymax':   10.5,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (pair + "_cluster_eta_ref," + pair + "_cluster_delta_eta_rel_ref",),
-                                      {'type': 'TH2F', 
-                                       'title': "Cluster #eta Resolution; #eta^{(CPU)}; #Delta #eta / #(){#eta^{(CPU)}}",
-                                       'xbins':  63,
-                                       'xmin':  -10.5,
-                                       'xmax':   10.5,
-                                       'ybins':  63,
-                                       'ymin':  -0.025,
-                                       'ymax':   0.025,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (pair + "_cluster_phi_ref," + pair + "_cluster_phi_test",),
-                                      {'type': 'TH2F', 
-                                       'title': "Cluster #phi Comparison; #phi^{(CPU)}; #phi^{(GPU)}",
-                                       'xbins':  63,
-                                       'xmin':  -3.3,
-                                       'xmax':   3.3,
-                                       'ybins':  63,
-                                       'ymin':  -3.3,
-                                       'ymax':   3.3,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (pair + "_cluster_phi_ref," + pair + "_cluster_delta_phi_in_range",),
-                                      {'type': 'TH2F', 
-                                       'title': "Cluster #phi Resolution; #phi^{(CPU)}; #Delta #phi",
-                                       'xbins':  63,
-                                       'xmin':  -10.5,
-                                       'xmax':   10.5,
-                                       'ybins':  63,
-                                       'ymin':  -0.025,
-                                       'ymax':   0.025,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (pair + "_cluster_delta_phi_in_range",),
-                                      {'type': 'TH1F', 
-                                       'title': "Cluster #phi; #phi; Number of Clusters",
-                                       'xbins':  61,
-                                       'xmin':  -3.25,
-                                       'xmax':   3.25,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (pair + "_cell_secondary_weight_ref," + pair + "_cell_secondary_weight_test",),
-                                      {'type': 'TH2F', 
-                                       'title': "Shared Cell Secondary Weight Comparison; w_2^{(CPU)}; w_2^{(GPU)}",
-                                       'xbins': 51,
-                                       'xmin':  -0.05,
-                                       'xmax':  0.505,
-                                       'ybins': 51,
-                                       'ymin':  -0.05,
-                                       'ymax':  0.505,
-                                       'path': "EXPERT"}
-                                    )
-                                  ]
-        if DoMoments:
-            for pair in PairsToPlot:
-                for mom, (prettynames, limits) in name_to_moment_map.items():
-                    for i in range(0, len(limits)):
-                      self.PlotsToDo += [ ( (pair + "_cluster_moments_" + mom + "_ref," + pair + "_cluster_moments_" + mom + "_test;" + pair + "_" + mom + "_versus_zoom_" + str(i + 1),),
-                                            {'type':  'TH2F', 
-                                             'title': prettynames[0] + " (" + str(i+1) + "); CPU " + prettynames[1] + "; GPU " + prettynames[1],
-                                             'xbins': 63,
-                                             'xmin':  limits[i][0],
-                                             'xmax':  limits[i][1],
-                                             'ybins': 63,
-                                             'ymin':  limits[i][0],
-                                             'ymax':  limits[i][1],
-                                             'path':  "EXPERT"},
-                                          ),
-                                        ]
-                      self.PlotsToDo += [ ( (pair + "_cluster_moments_" + mom + "_ref," + pair + "_cluster_delta_moments_" + mom + "_rel_ref;" + pair + "_" + mom + "_error_zoom_" + str(i + 1),),
-                                            {'type':   'TH2F', 
-                                             'title': prettynames[0] + " (" + str(i+1) + "); CPU " + prettynames[1] + "; #Delta " + prettynames[1] + " / #(){CPU " + prettynames[1] + "}",
-                                             'xbins':  63,
-                                             'xmin':   limits[i][0],
-                                             'xmax':   limits[i][1],
-                                             'ybins':  63,
-                                             'ymin':  -0.025,
-                                             'ymax':   0.025,
-                                             'path':   "EXPERT"}
-                                          ),
-                                        ]
-                      self.PlotsToDo += [ ( (pair + "_cluster_delta_moments_" + mom + "_rel_ref;" + pair + "_cluster_delta_moments_" + mom + "_rel_ref_zoom_0",),
-                                            {'type': 'TH1F', 
-                                             'title': prettynames[0] + "; #Delta " + prettynames[1] + "; Number of Clusters",
-                                             'xbins': 51,
-                                             'xmin':  -1,
-                                             'xmax':  1,
-                                             'path': "EXPERT"}
-                                           ),
-                                        ]
-    def __call__(self, Plotter):
-        for plotdef in self.PlotsToDo:
-            Plotter.MonitoringTool.defineHistogram(*plotdef[0], **plotdef[1])
-        return Plotter
-        
diff --git a/Calorimeter/CaloRecGPU/test/CaloRecGPUTestingConfig.py b/Calorimeter/CaloRecGPU/test/CaloRecGPUTestingConfig.py
index 98e733facdf49b1aab0fd5d43817e2a2a0e91485..092087e21f922dd34dd59f87e33d5b9b3e9493c2 100644
--- a/Calorimeter/CaloRecGPU/test/CaloRecGPUTestingConfig.py
+++ b/Calorimeter/CaloRecGPU/test/CaloRecGPUTestingConfig.py
@@ -1,12 +1,394 @@
 # Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+class PlotterConfigurator:
+    #DoCells currently changes nothing
+    #(originally was intended to show
+    #that we had cells with the same energy),
+    #keeping it here to remain part of the interface
+    #if/when we port the cell maker as well.
+    def __init__ (self, StepsToPlot = [], PairsToPlot = [], DoStandard = True, DoMoments = False, DoCells = False):
+        self.PlotsToDo = []
+        if DoStandard:
+            for step in StepsToPlot:
+                self.PlotsToDo += [
+                                    ( (step + "_cluster_E",),
+                                      {'type': 'TH1F',
+                                       'title': "Cluster Energy; E [MeV]; Number of Events",
+                                       'xbins':  63,
+                                       'xmin':  -5020,
+                                       'xmax':   5020,
+                                       'path': "EXPERT"}
+                                    ),
+                                    ( (step + "_cluster_Et",),
+                                      {'type': 'TH1F',
+                                       'title': "Cluster Transverse Energy; E_T [MeV]; Number of Events",
+                                       'xbins':  63,
+                                       'xmin':  -5020,
+                                       'xmax':   5020,
+                                       'path': "EXPERT"}
+                                    ),
+                                    ( (step + "_cluster_eta",),
+                                      {'type': 'TH1F',
+                                       'title': "Cluster #eta; #eta; Number of Events",
+                                       'xbins':  84,
+                                       'xmin':  -10.5,
+                                       'xmax':   10.5,
+                                       'path': "EXPERT"}
+                                    ),
+                                    ( (step + "_cluster_phi",),
+                                      {'type': 'TH1F',
+                                       'title': "Cluster #phi; #phi; Number of Events",
+                                       'xbins':  61,
+                                       'xmin':  -3.25,
+                                       'xmax':   3.25,
+                                       'path': "EXPERT"}
+                                    ),
+                                    ( (step + "_cluster_eta," + step + "_cluster_phi",),
+                                      {'type': 'TH2F',
+                                       'title': "Cluster #eta versus #phi; #eta; #phi",
+                                       'xbins':  84,
+                                       'xmin':  -10.5,
+                                       'xmax':   10.5,
+                                       'ybins':  61,
+                                       'ymin':  -3.25,
+                                       'ymax':   3.25,
+                                       'path': "EXPERT"}
+                                    )
+                                  ]
+            for pair in PairsToPlot:
+                self.PlotsToDo += [
+                                    ( (pair + "_num_unmatched_clusters",),
+                                      {'type': 'TH1F',
+                                       'title': "Number of Unmatched Clusters; # of Unmatched Clusters; Number of Events",
+                                       'xbins':  21,
+                                       'xmin':  -0.5,
+                                       'xmax':   20.5,
+                                       'path': "EXPERT"}
+                                    ),
+                                    ( (pair + "_cluster_diff_cells;" + pair + "_cluster_diff_cells_zoom_0",),
+                                      {'type': 'TH1F',
+                                       'title': "Different Cell Assignments; # of Differently Assigned Cells; Number of Clusters",
+                                       'xbins':  21,
+                                       'xmin':  -25,
+                                       'xmax':   1025,
+                                       'path': "EXPERT"}
+                                    ),
+                                    ( (pair + "_cluster_diff_cells;" + pair + "_cluster_diff_cells_zoom_1",),
+                                      {'type': 'TH1F',
+                                       'title': "Different Cell Assignments; # of Differently Assigned Cells; Number of Clusters",
+                                       'xbins':  21,
+                                       'xmin':  -12.5,
+                                       'xmax':   512.5,
+                                       'path': "EXPERT"}
+                                    ),
+                                    ( (pair + "_cluster_diff_cells;" + pair + "_cluster_diff_cells_zoom_2",),
+                                      {'type': 'TH1F',
+                                       'title': "Different Cell Assignments; # of Differently Assigned Cells; Number of Clusters",
+                                       'xbins':  21,
+                                       'xmin':  -2.5,
+                                       'xmax':   102.5,
+                                       'path': "EXPERT"}
+                                    ),
+                                    ( (pair + "_cluster_diff_cells;" + pair + "_cluster_diff_cells_zoom_3",),
+                                      {'type': 'TH1F',
+                                       'title': "Different Cell Assignments; # of Differently Assigned Cells; Number of Clusters",
+                                       'xbins':  21,
+                                       'xmin':  -0.5,
+                                       'xmax':   20.5,
+                                       'path': "EXPERT"}
+                                    ),
+                                    ( (pair + "_cluster_E_ref," + pair + "_cluster_E_test",),
+                                      {'type': 'TH2F',
+                                       'title': "Cluster Energy Comparison; E^{(CPU)} [MeV]; E^{(GPU)} [MeV]",
+                                       'xbins':  63,
+                                       'xmin':  -50.5,
+                                       'xmax':   50.5,
+                                       'ybins':  63,
+                                       'ymin':  -50.5,
+                                       'ymax':   50.5,
+                                       'path': "EXPERT"}
+                                    ),
+                                    ( (pair + "_cluster_E_ref," + pair + "_cluster_delta_E_rel_ref",),
+                                      {'type': 'TH2F',
+                                       'title': "Cluster Energy Resolution; E^{(CPU)} [MeV]; #Delta E / #(){E^{(CPU)}}",
+                                       'xbins':  63,
+                                       'xmin':  -50.5,
+                                       'xmax':   50.5,
+                                       'ybins':  63,
+                                       'ymin':  -0.025,
+                                       'ymax':   0.025,
+                                       'path': "EXPERT"}
+                                    ),
+                                    ( (pair + "_cluster_Et_ref," + pair + "_cluster_Et_test",),
+                                      {'type': 'TH2F',
+                                       'title': "Cluster Transverse Energy Comparison; E_T^{(CPU)} [MeV]; E_T^{(GPU)} [MeV]",
+                                       'xbins':  63,
+                                       'xmin':  -50.5,
+                                       'xmax':   50.5,
+                                       'ybins':  63,
+                                       'ymin':  -50.5,
+                                       'ymax':   50.5,
+                                       'path': "EXPERT"}
+                                    ),
+                                    ( (pair + "_cluster_Et_ref," + pair + "_cluster_delta_Et_rel_ref",),
+                                      {'type': 'TH2F',
+                                       'title': "Cluster Transverse Energy Resolution; E_T^{(CPU)} [MeV]; #Delta E_T / #(){E_T^{(CPU)}}",
+                                       'xbins':  63,
+                                       'xmin':  -50.5,
+                                       'xmax':   50.5,
+                                       'ybins':  63,
+                                       'ymin':  -0.025,
+                                       'ymax':   0.025,
+                                       'path': "EXPERT"}
+                                    ),
+                                    ( (pair + "_cluster_eta_ref," + pair + "_cluster_eta_test",),
+                                      {'type': 'TH2F',
+                                       'title': "Cluster #eta Comparison; #eta^{(CPU)}; #eta^{(GPU)}",
+                                       'xbins':  63,
+                                       'xmin':  -10.5,
+                                       'xmax':   10.5,
+                                       'ybins':  63,
+                                       'ymin':  -10.5,
+                                       'ymax':   10.5,
+                                       'path': "EXPERT"}
+                                    ),
+                                    ( (pair + "_cluster_eta_ref," + pair + "_cluster_delta_eta_rel_ref",),
+                                      {'type': 'TH2F',
+                                       'title': "Cluster #eta Resolution; #eta^{(CPU)}; #Delta #eta / #(){#eta^{(CPU)}}",
+                                       'xbins':  63,
+                                       'xmin':  -10.5,
+                                       'xmax':   10.5,
+                                       'ybins':  63,
+                                       'ymin':  -0.025,
+                                       'ymax':   0.025,
+                                       'path': "EXPERT"}
+                                    ),
+                                    ( (pair + "_cluster_phi_ref," + pair + "_cluster_phi_test",),
+                                      {'type': 'TH2F',
+                                       'title': "Cluster #phi Comparison; #phi^{(CPU)}; #phi^{(GPU)}",
+                                       'xbins':  63,
+                                       'xmin':  -3.3,
+                                       'xmax':   3.3,
+                                       'ybins':  63,
+                                       'ymin':  -3.3,
+                                       'ymax':   3.3,
+                                       'path': "EXPERT"}
+                                    ),
+                                    ( (pair + "_cluster_phi_ref," + pair + "_cluster_delta_phi_in_range",),
+                                      {'type': 'TH2F',
+                                       'title': "Cluster #phi Resolution; #phi^{(CPU)}; #Delta #phi",
+                                       'xbins':  63,
+                                       'xmin':  -10.5,
+                                       'xmax':   10.5,
+                                       'ybins':  63,
+                                       'ymin':  -0.025,
+                                       'ymax':   0.025,
+                                       'path': "EXPERT"}
+                                    ),
+                                    ( (pair + "_cluster_delta_phi_in_range",),
+                                      {'type': 'TH1F',
+                                       'title': "Cluster #phi; #phi; Number of Clusters",
+                                       'xbins':  61,
+                                       'xmin':  -3.25,
+                                       'xmax':   3.25,
+                                       'path': "EXPERT"}
+                                    ),
+                                    ( (pair + "_cell_secondary_weight_ref," + pair + "_cell_secondary_weight_test",),
+                                      {'type': 'TH2F',
+                                       'title': "Shared Cell Secondary Weight Comparison; w_2^{(CPU)}; w_2^{(GPU)}",
+                                       'xbins': 51,
+                                       'xmin':  -0.05,
+                                       'xmax':  0.505,
+                                       'ybins': 51,
+                                       'ymin':  -0.05,
+                                       'ymax':  0.505,
+                                       'path': "EXPERT"}
+                                    )
+                                  ]
+        if DoMoments:
+            for pair in PairsToPlot:
+                for mom, (prettynames, limits) in name_to_moment_map.items():
+                    for i in range(0, len(limits)):
+                      self.PlotsToDo += [ ( (pair + "_cluster_moments_" + mom + "_ref," + pair + "_cluster_moments_" + mom + "_test;" + pair + "_" + mom + "_versus_zoom_" + str(i + 1),),
+                                            {'type':  'TH2F',
+                                             'title': prettynames[0] + " (" + str(i+1) + "); CPU " + prettynames[1] + "; GPU " + prettynames[1],
+                                             'xbins': 63,
+                                             'xmin':  limits[i][0],
+                                             'xmax':  limits[i][1],
+                                             'ybins': 63,
+                                             'ymin':  limits[i][0],
+                                             'ymax':  limits[i][1],
+                                             'path':  "EXPERT"},
+                                          ),
+                                        ]
+                      self.PlotsToDo += [ ( (pair + "_cluster_moments_" + mom + "_ref," + pair + "_cluster_delta_moments_" + mom + "_rel_ref;" + pair + "_" + mom + "_error_zoom_" + str(i + 1),),
+                                            {'type':   'TH2F',
+                                             'title': prettynames[0] + " (" + str(i+1) + "); CPU " + prettynames[1] + "; #Delta " + prettynames[1] + " / #(){CPU " + prettynames[1] + "}",
+                                             'xbins':  63,
+                                             'xmin':   limits[i][0],
+                                             'xmax':   limits[i][1],
+                                             'ybins':  63,
+                                             'ymin':  -0.025,
+                                             'ymax':   0.025,
+                                             'path':   "EXPERT"}
+                                          ),
+                                        ]
+                      self.PlotsToDo += [ ( (pair + "_cluster_delta_moments_" + mom + "_rel_ref;" + pair + "_cluster_delta_moments_" + mom + "_rel_ref_zoom_0",),
+                                            {'type': 'TH1F',
+                                             'title': prettynames[0] + "; #Delta " + prettynames[1] + "; Number of Clusters",
+                                             'xbins': 51,
+                                             'xmin':  -1,
+                                             'xmax':  1,
+                                             'path': "EXPERT"}
+                                           ),
+                                        ]
+    def __call__(self, Plotter):
+        for plotdef in self.PlotsToDo:
+            Plotter.MonitoringTool.defineHistogram(*plotdef[0], **plotdef[1])
+        return Plotter
+
+#For pretty printing things in axes when it comes to moments:
+#<MOMENT_NAME>: <PLOT TITLE> <AXIS TITLE> <UNITS>
+name_to_moment_map =  {
+   #"time"                        :  (("time",                "time",               "[#mu s]"),[]),
+    "FIRST_PHI"                   :  (("firstPhi",            "firstPhi",            ""),[(-3.2, 3.2)]),
+    "FIRST_ETA"                   :  (("firstEta",            "firstEta",            ""),[(-10.1, 10.1)]),
+    "SECOND_R"                    :  (("secondR",             "secondR",             ""),[(0, 1.25e6)]),
+    "SECOND_LAMBDA"               :  (("secondLambda",        "secondLambda",        ""),[(0, 2.5e6)]),
+    "DELTA_PHI"                   :  (("deltaPhi",            "deltaPhi",            ""),[(-3.2, 3.2)]),
+    "DELTA_THETA"                 :  (("deltaTheta",          "deltaTheta",          ""),[(-1.6, 1.6)]),
+    "DELTA_ALPHA"                 :  (("deltaAlpha",          "deltaAlpha",          ""),[(-0.1, 1.6)]),
+    "CENTER_X"                    :  (("centerX",             "centerX",             ""),[(-4000, 4000)]),
+    "CENTER_Y"                    :  (("centerY",             "centerY",             ""),[(-4000, 4000)]),
+    "CENTER_Z"                    :  (("centerZ",             "centerZ",             ""),[(-7000, 7000)]),
+    "CENTER_MAG"                  :  (("centerMag",           "centerMag",           ""),[(1000, 7500)]),
+    "CENTER_LAMBDA"               :  (("centerLambda",        "centerLambda",        ""),[(0., 25000.),(0., 5000.)]),
+    "LATERAL"                     :  (("lateral",             "lateral",             ""),[(-0.05, 1.05)]),
+    "LONGITUDINAL"                :  (("longitudinal",        "longitudinal",        ""),[(-0.05, 1.05)]),
+    "ENG_FRAC_EM"                 :  (("engFracEM",           "engFracEM",           ""),[(-0.1, 1.1)]),
+    "ENG_FRAC_MAX"                :  (("engFracMax",          "engFracMax",          ""),[(-0.1, 1.1)]),
+    "ENG_FRAC_CORE"               :  (("engFracCore",         "engFracCore",         ""),[(-0.1, 1.1)]),
+    "FIRST_ENG_DENS"              :  (("firstEngDens",        "firstEngDens",        ""),[(-0.1, 5.1)]),
+    "SECOND_ENG_DENS"             :  (("secondEngDens",       "secondEngDens",       ""),[(-0.5, 50.5)]),
+    "ISOLATION"                   :  (("isolation",           "isolation",           ""),[(-0.05, 2.05)]),
+    "ENG_BAD_CELLS"               :  (("engBadCells",         "engBadCells",         ""),[(0., 100000.)]),
+    "N_BAD_CELLS"                 :  (("nBadCells",           "nBadCells",           ""),[(-0.5, 25.5)]),
+    "N_BAD_CELLS_CORR"            :  (("nBadCellsCorr",       "nBadCellsCorr",       ""),[(-0.5, 25.5)]),
+    "BAD_CELLS_CORR_E"            :  (("badCellsCorrE",       "badCellsCorrE",       ""),[(-0.1, 25000.)]),
+    "BADLARQ_FRAC"                :  (("badLArQFrac",         "badLArQFrac",         ""),[(-2500., 2500.)]),
+    "ENG_POS"                     :  (("engPos",              "engPos",              ""),[(-0.1, 250000.)]),
+    "SIGNIFICANCE"                :  (("significance",        "significance",        ""),[(-500., 500.)]),
+    "CELL_SIGNIFICANCE"           :  (("cellSignificance",    "cellSignificance",    ""),[(-0.1, 100.)]),
+    "CELL_SIG_SAMPLING"           :  (("cellSigSampling",     "cellSigSampling",     ""),[(-0.1, 30.)]),
+    "AVG_LAR_Q"                   :  (("avgLArQ",             "avgLArQ",             ""),[(-0.1, 70000.)]),
+    "AVG_TILE_Q"                  :  (("avgTileQ",            "avgTileQ",            ""),[(-0.1, 300.)]),
+   #"ENG_BAD_HV_CELLS"            :  (("engBadHVCells",       "engBadHVCells",       ""),[]),
+   #"N_BAD_HV_CELLS"              :  (("nBadHVCells",         "nBadHVCells",         ""),[]),
+    "PTD"                         :  (("PTD",                 "PTD",                 ""),[(-0.05, 1.05)]),
+    "MASS"                        :  (("mass",                "mass",                ""),[(0., 200000.), (0., 100.)]),
+   #"EM_PROBABILITY"              :  (("EMProbability",       "EMProbability",       ""),[]),
+   #"HAD_WEIGHT"                  :  (("hadWeight",           "hadWeight",           ""),[]),
+   #"OOC_WEIGHT"                  :  (("OOCweight",           "OOCweight",           ""),[]),
+   #"DM_WEIGHT"                   :  (("DMweight",            "DMweight",            ""),[]),
+   #"TILE_CONFIDENCE_LEVEL"       :  (("tileConfidenceLevel", "tileConfidenceLevel", ""),[]),
+    "SECOND_TIME"                 :  (("secondTime",          "secondTime",          ""),[(0., 1e7)])
+   #"number_of_cells"             :  (("numCells",            "numCells",            ""),[]),
+   #"VERTEX_FRACTION"             :  (("vertexFraction",      "vertexFraction",      ""),[]),
+   #"NVERTEX_FRACTION"            :  (("nVertexFraction",     "nVertexFraction",     ""),[]),
+   #"ETACALOFRAME"                :  (("etaCaloFrame",        "etaCaloFrame",        ""),[]),
+   #"PHICALOFRAME"                :  (("phiCaloFrame",        "phiCaloFrame",        ""),[]),
+   #"ETA1CALOFRAME"               :  (("eta1CaloFrame",       "eta1CaloFrame",       ""),[]),
+   #"PHI1CALOFRAME"               :  (("phi1CaloFrame",       "phi1CaloFrame",       ""),[]),
+   #"ETA2CALOFRAME"               :  (("eta2CaloFrame",       "eta2CaloFrame",       ""),[]),
+   #"PHI2CALOFRAME"               :  (("phi2CaloFrame",       "phi2CaloFrame",       ""),[]),
+   #"ENG_CALIB_TOT"               :  (("engCalibTot",         "engCalibTot",         ""),[]),
+   #"ENG_CALIB_OUT_L"             :  (("engCalibOutL",        "engCalibOutL",        ""),[]),
+   #"ENG_CALIB_OUT_M"             :  (("engCalibOutM",        "engCalibOutM",        ""),[]),
+   #"ENG_CALIB_OUT_T"             :  (("engCalibOutT",        "engCalibOutT",        ""),[]),
+   #"ENG_CALIB_DEAD_L"            :  (("engCalibDeadL",       "engCalibDeadL",       ""),[]),
+   #"ENG_CALIB_DEAD_M"            :  (("engCalibDeadM",       "engCalibDeadM",       ""),[]),
+   #"ENG_CALIB_DEAD_T"            :  (("engCalibDeadT",       "engCalibDeadT",       ""),[]),
+   #"ENG_CALIB_EMB0"              :  (("engCalibEMB0",        "engCalibEMB0",        ""),[]),
+   #"ENG_CALIB_EME0"              :  (("engCalibEME0",        "engCalibEME0",        ""),[]),
+   #"ENG_CALIB_TILEG3"            :  (("engCalibTileG3",      "engCalibTileG3",      ""),[]),
+   #"ENG_CALIB_DEAD_TOT"          :  (("engCalibDeadTot",     "engCalibDeadTot",     ""),[]),
+   #"ENG_CALIB_DEAD_EMB0"         :  (("engCalibDeadEMB0",    "engCalibDeadEMB0",    ""),[]),
+   #"ENG_CALIB_DEAD_TILE0"        :  (("engCalibDeadTile0",   "engCalibDeadTile0",   ""),[]),
+   #"ENG_CALIB_DEAD_TILEG3"       :  (("engCalibDeadTileG3",  "engCalibDeadTileG3",  ""),[]),
+   #"ENG_CALIB_DEAD_EME0"         :  (("engCalibDeadEME0",    "engCalibDeadEME0",    ""),[]),
+   #"ENG_CALIB_DEAD_HEC0"         :  (("engCalibDeadHEC0",    "engCalibDeadHEC0",    ""),[]),
+   #"ENG_CALIB_DEAD_FCAL"         :  (("engCalibDeadFCAL",    "engCalibDeadFCAL",    ""),[]),
+   #"ENG_CALIB_DEAD_LEAKAGE"      :  (("engCalibDeadLeakage", "engCalibDeadLeakage", ""),[]),
+   #"ENG_CALIB_DEAD_UNCLASS"      :  (("engCalibDeadUnclass", "engCalibDeadUnclass", ""),[]),
+   #"ENG_CALIB_FRAC_EM"           :  (("engCalibFracEM",      "engCalibFracEM",      ""),[]),
+   #"ENG_CALIB_FRAC_HAD"          :  (("engCalibFracHad",     "engCalibFracHad",     ""),[]),
+   #"ENG_CALIB_FRAC_REST"         :  (("engCalibFracRest"     "engCalibFracRest"     ""),[])
+}
 
 from AthenaConfiguration.Enums import Format
 from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
 from AthenaConfiguration.ComponentFactory import CompFactory
-from PlotterConfigurator import SingleToolToPlot, ComparedToolsToPlot
-from CaloRecGPU.CaloRecGPUConfig import PlotterMonitoringToolCfg, DefaultCaloCellMakerCfg, AthenaClusterAndMomentsImporterToolCfg, BasicAthenaClusterImporterToolCfg, DefaultTopologicalClusteringToolCfg, CellsCounterCPUToolCfg, CPUOutputToolCfg, DefaultClusterSplittingToolCfg, DefaultClusterMomentsCalculatorToolCfg, MomentsDumperToolCfg, CaloClusterDeleterToolCfg, GPUOutputToolCfg, TopoAutomatonSplitterToolCfg, ClusterInfoCalcToolCfg, CellsCounterGPUToolCfg, TopoAutomatonClusteringToolCfg, GPUClusterMomentsCalculatorToolCfg
 
-def PrevAlgorithmsConfigurationCfg(flags):
+def DefaultCaloCellMakerCfg(flags, testoptions, cellname):
+    from LArCellRec.LArCellBuilderConfig import LArCellBuilderCfg,LArCellCorrectorCfg
+    from TileRecUtils.TileCellBuilderConfig import TileCellBuilderCfg
+    from CaloCellCorrection.CaloCellCorrectionConfig import CaloCellPedestalCorrCfg, CaloCellNeighborsAverageCorrCfg, CaloCellTimeCorrCfg, CaloEnergyRescalerCfg
+    result=ComponentAccumulator()
+
+    from LArGeoAlgsNV.LArGMConfig import LArGMCfg
+    from TileGeoModel.TileGMConfig import TileGMCfg
+
+    result.merge(LArGMCfg(flags))
+    result.merge(TileGMCfg(flags))
+
+    larCellBuilder     = result.popToolsAndMerge(LArCellBuilderCfg(flags))
+    larCellCorrectors  = result.popToolsAndMerge(LArCellCorrectorCfg(flags))
+    tileCellBuilder = result.popToolsAndMerge(TileCellBuilderCfg(flags))
+    cellFinalizer  = CompFactory.CaloCellContainerFinalizerTool()
+
+    if flags.CaloRecGPU.ActiveConfig.FillMissingCells:
+        tileCellBuilder.fakeCrackCells = True
+
+    cellMakerTools=[larCellBuilder,tileCellBuilder,cellFinalizer]+larCellCorrectors
+
+    #Add corrections tools that are not LAr or Tile specific:
+    if flags.Calo.Cell.doPileupOffsetBCIDCorr or flags.Cell.doPedestalCorr:
+        theCaloCellPedestalCorr=CaloCellPedestalCorrCfg(flags)
+        cellMakerTools.append(result.popToolsAndMerge(theCaloCellPedestalCorr))
+
+    #LAr HV scale corr must come after pedestal corr
+    if flags.LAr.doHVCorr:
+        from LArCellRec.LArCellBuilderConfig import LArHVCellContCorrCfg
+        cellMakerTools.append(result.popToolsAndMerge(LArHVCellContCorrCfg(flags)))
+
+
+    if flags.Calo.Cell.doDeadCellCorr:
+        cellMakerTools.append(result.popToolsAndMerge(CaloCellNeighborsAverageCorrCfg(flags)))
+
+    if flags.Calo.Cell.doEnergyCorr:
+        cellMakerTools.append(result.popToolsAndMerge(CaloEnergyRescalerCfg(flags)))
+    if flags.Calo.Cell.doTimeCorr:
+        cellMakerTools.append(result.popToolsAndMerge(CaloCellTimeCorrCfg(flags)))
+
+    cellAlgo=CompFactory.CaloCellMaker(CaloCellMakerToolNames = cellMakerTools,
+                                       CaloCellsOutputName = cellname)
+    result.addEventAlgo(cellAlgo)
+    return result
+
+
+class TestOptions:
+    def __init__(self):
+        self.OutputClusters = False
+        self.OutputCounts = False
+        self.TestGrow = False
+        self.TestSplit = False
+        self.TestMoments = False
+        self.DoCrossTests = False
+        self.OutputCellInfo = False
+        self.SkipSyncs = True
+        self.UsePerfMon = False
+        self.NumEvents = -1
+
+def PrevAlgorithmsConfigurationCfg(flags, testoptions, cellsname):
     result=ComponentAccumulator()
     
     if flags.Input.Format is Format.BS:
@@ -39,7 +421,7 @@ def PrevAlgorithmsConfigurationCfg(flags):
         result.merge(LArFebErrorSummaryMakerCfg(flags))
         
     if flags.Input.Format is Format.BS or 'StreamRDO' in flags.Input.ProcessingTags:
-        result.merge(DefaultCaloCellMakerCfg(flags))
+        result.merge(DefaultCaloCellMakerCfg(flags, testoptions, cellsname))
     elif flags.CaloRecGPU.ActiveConfig.FillMissingCells:
         from AthenaCommon.Logging import log
         log.warning("Asked to fill missing cells but will not run cell maker! Slow path might be taken!")
@@ -57,49 +439,61 @@ def PrevAlgorithmsConfigurationCfg(flags):
     
     return result
     
-
-
-#TestGrow, TestSplit, TestMoments are self-explanatory.
-#If `DoCrossTests` is True, outputs and/or plots
-#are done considering all possible combinations
-#of (GPU, CPU) x (Growing, Splitting)
-#PlotterConfigurator takes the CaloGPUClusterAndCellDataMonitor
-#and adds the appropriate plots to it.
-def FullTestConfiguration(flags, TestGrow=False, TestSplit=False, TestMoments=False, DoCrossTests=False,
-                          PlotterConfigurator=None, OutputCellInfo=False, SkipSyncs=True):
-    
     
-    if not (TestGrow and TestSplit):
-        DoCrossTests = False
+def MainTestConfiguration(flags, testoptions, PlotterConfigurator, cellsname, clustersname):    
+    if not (testoptions.TestGrow and testoptions.TestSplit):
+        testoptions.DoCrossTests = False
     
-    result= PrevAlgorithmsConfigurationCfg(flags)
+    result = PrevAlgorithmsConfigurationCfg(flags, testoptions, cellsname)
         
     GPUKernelSvc = CompFactory.GPUKernelSizeOptimizerSvc()
     result.addService(GPUKernelSvc)
+    
+    from LArGeoAlgsNV.LArGMConfig import LArGMCfg
+    from TileGeoModel.TileGMConfig import TileGMCfg
+    from CaloTools.CaloNoiseCondAlgConfig import CaloNoiseCondAlgCfg
+    
+    result.merge(CaloNoiseCondAlgCfg(flags,"totalNoise"))
+    result.merge(CaloNoiseCondAlgCfg(flags,"electronicNoise"))
+        
+    result.merge(LArGMCfg(flags))
+    result.merge(TileGMCfg(flags))
+    
 
-    from CaloRecGPU.CaloRecGPUConfig import HybridClusterProcessorCfg
-    result.merge(HybridClusterProcessorCfg(flags))
-    hybridClusterProcessor = result.getEventAlgo("HybridClusterProcessor")
-
+    HybridClusterProcessor = CompFactory.CaloGPUHybridClusterProcessor("HybridClusterProcessor")
+    HybridClusterProcessor.ClustersOutputName = clustersname
+    
+    HybridClusterProcessor.WriteTriggerSpecificInfo = False
+    
+    HybridClusterProcessor.MeasureTimes = flags.CaloRecGPU.ActiveConfig.MeasureTimes
+    
+    HybridClusterProcessor.TimeFileOutput = "GlobalTimes.txt"
+    
+    HybridClusterProcessor.DeferConstantDataPreparationToFirstEvent = True
+    
     if PlotterConfigurator is None:
-        hybridClusterProcessor.DoPlots = False
+        HybridClusterProcessor.DoPlots = False
     else:
-        hybridClusterProcessor.DoPlots = True
-        Plotter = PlotterConfigurator(result.popToolsAndMerge(PlotterMonitoringToolCfg(flags)))
-        hybridClusterProcessor.PlotterTool = Plotter
-        if TestGrow and not DoCrossTests:
+        HybridClusterProcessor.DoPlots = True
+        
+        from CaloRecGPU.CaloRecGPUConfig import PlotterToolCfg, SingleToolToPlot, ComparedToolsToPlot
+        
+        Plotter = PlotterConfigurator(result.popToolsAndMerge(PlotterToolCfg(flags, cellsname)))
+        HybridClusterProcessor.PlotterTool = Plotter
+        
+        if testoptions.TestGrow and not testoptions.DoCrossTests:
             Plotter.ToolsToPlot += [ SingleToolToPlot("DefaultGrowing", "CPU_growing") ]
             Plotter.ToolsToPlot += [ SingleToolToPlot("PropCalcPostGrowing", "GPU_growing") ]
             Plotter.PairsToPlot += [ ComparedToolsToPlot("DefaultGrowing", "PropCalcPostGrowing", "growing") ]
-        if TestSplit and not DoCrossTests:
+        if testoptions.TestSplit and not testoptions.DoCrossTests:
             Plotter.ToolsToPlot += [ SingleToolToPlot("DefaultSplitting", "CPU_splitting") ]
             Plotter.ToolsToPlot += [ SingleToolToPlot("PropCalcPostSplitting", "GPU_splitting") ]
             Plotter.PairsToPlot += [ ComparedToolsToPlot("DefaultSplitting", "PropCalcPostSplitting", "splitting", True) ]
-        if TestMoments:
+        if testoptions.TestMoments:
             Plotter.ToolsToPlot += [ SingleToolToPlot("CPUMoments", "CPU_moments") ]
             Plotter.ToolsToPlot += [ SingleToolToPlot("AthenaClusterImporter", "GPU_moments") ]
             Plotter.PairsToPlot += [ ComparedToolsToPlot("CPUMoments", "AthenaClusterImporter", "moments", True) ]
-        if DoCrossTests:
+        if testoptions.DoCrossTests:
             Plotter.ToolsToPlot += [ SingleToolToPlot("DefaultGrowing", "CPU_growing") ]
             Plotter.ToolsToPlot += [ SingleToolToPlot("PropCalcPostGrowing", "GPU_growing") ]
             Plotter.PairsToPlot += [ ComparedToolsToPlot("DefaultGrowing", "PropCalcPostGrowing", "growing") ]
@@ -113,208 +507,244 @@ def FullTestConfiguration(flags, TestGrow=False, TestSplit=False, TestMoments=Fa
             Plotter.PairsToPlot += [ ComparedToolsToPlot("DefaultSplitting", "PropCalcDefaultGrowGPUSplit", "CPU_to_CPUGPU_splitting", True) ]
             Plotter.PairsToPlot += [ ComparedToolsToPlot("DefaultSplitting", "DefaultPostGPUSplitting", "CPU_to_GPUCPU_splitting", True) ]
             
+    HybridClusterProcessor.DoMonitoring = False
+    
+    HybridClusterProcessor.NumPreAllocatedDataHolders = flags.CaloRecGPU.ActiveConfig.NumPreAllocatedDataHolders
         
-    if flags.CaloRecGPU.DoMonitoring or PlotterConfigurator is not None:
+    if PlotterConfigurator is not None:
         histSvc = CompFactory.THistSvc(Output = ["EXPERT DATAFILE='expert-monitoring.root', OPT='RECREATE'"])
         result.addService(histSvc)
     
-    from LArGeoAlgsNV.LArGMConfig import LArGMCfg
-    from TileGeoModel.TileGMConfig import TileGMCfg
-    
-    result.merge(LArGMCfg(flags))
-    result.merge(TileGMCfg(flags))
-    
     AthenaClusterImporter = None
-    
-    if TestMoments:
-         AthenaClusterImporter = result.popToolsAndMerge( AthenaClusterAndMomentsImporterToolCfg(flags,"AthenaClusterImporter") )
+
+    from CaloRecGPU.CaloRecGPUConfig import ( BasicConstantDataExporterToolCfg,
+                                              BasicEventDataExporterToolCfg,
+                                              BasicAthenaClusterImporterToolCfg,
+                                              AthenaClusterAndMomentsImporterToolCfg,
+                                              DefaultTopologicalClusteringToolCfg, 
+                                              DefaultClusterSplittingToolCfg,
+                                              DefaultClusterMomentsCalculatorToolCfg,
+                                              MomentsDumperToolCfg,
+                                              CellsCounterCPUToolCfg,
+                                              CPUOutputToolCfg,
+                                              TopoAutomatonClusteringToolCfg,
+                                              ClusterInfoCalcToolCfg,
+                                              GPUClusterMomentsCalculatorToolCfg,
+                                              TopoAutomatonSplitterToolCfg,
+                                              CellsCounterGPUToolCfg,
+                                              GPUOutputToolCfg )
+                                            
+        
+    if testoptions.TestMoments:
+        AthenaClusterImporter = result.popToolsAndMerge( AthenaClusterAndMomentsImporterToolCfg(flags, cellsname,"AthenaClusterImporter") )
     else:
-         AthenaClusterImporter = result.popToolsAndMerge( BasicAthenaClusterImporterToolCfg(flags,"AthenaClusterImporter") )
+        AthenaClusterImporter = result.popToolsAndMerge( BasicAthenaClusterImporterToolCfg(flags, cellsname,"AthenaClusterImporter") )
             
-    hybridClusterProcessor.GPUToEventDataTool = AthenaClusterImporter
+    HybridClusterProcessor.ConstantDataToGPUTool = result.popToolsAndMerge(BasicConstantDataExporterToolCfg(flags, cellsname))
+    HybridClusterProcessor.EventDataToGPUTool = result.popToolsAndMerge(BasicEventDataExporterToolCfg(flags, cellsname))
+    HybridClusterProcessor.GPUToEventDataTool = AthenaClusterImporter
     
-    hybridClusterProcessor.BeforeGPUTools = []
+    HybridClusterProcessor.BeforeGPUTools = []
            
-    if TestGrow or TestSplit or TestMoments:
-        DefaultClustering = result.popToolsAndMerge( DefaultTopologicalClusteringToolCfg(flags,"DefaultGrowing") )
+    if testoptions.TestGrow or testoptions.TestSplit or testoptions.TestMoments:
+        DefaultClustering = result.popToolsAndMerge( DefaultTopologicalClusteringToolCfg(flags, cellsname,"DefaultGrowing") )
         
-        hybridClusterProcessor.BeforeGPUTools += [DefaultClustering]
+        HybridClusterProcessor.BeforeGPUTools += [DefaultClustering]
                     
-        if TestGrow and (not TestSplit or DoCrossTests):
-            if flags.CaloRecGPU.OutputCountsToFile:
-                CPUCount1 = result.popToolsAndMerge( CellsCounterCPUToolCfg(flags,"DefaultGrowCounter","./counts", "default_grow") )
-                hybridClusterProcessor.BeforeGPUTools += [CPUCount1]
-            if flags.CaloRecGPU.OutputClustersToFile:
-                CPUOut1 = result.popToolsAndMerge( CPUOutputToolCfg(flags,"DefaultGrowOutput","./out_default_grow") )
-                hybridClusterProcessor.BeforeGPUTools += [CPUOut1]
+        if testoptions.TestGrow and (not testoptions.TestSplit or testoptions.DoCrossTests):
+            if testoptions.OutputCounts:
+                CPUCount1 = result.popToolsAndMerge( CellsCounterCPUToolCfg(flags,cellsname,"DefaultGrowCounter", SavePath = "./counts", FilePrefix = "default_grow") )
+                HybridClusterProcessor.BeforeGPUTools += [CPUCount1]
+            if testoptions.OutputClusters:
+                CPUOut1 = result.popToolsAndMerge( CPUOutputToolCfg(flags,cellsname,"DefaultGrowOutput", SavePath = "./out_default_grow") )
+                HybridClusterProcessor.BeforeGPUTools += [CPUOut1]
         
             
-        if TestSplit or TestMoments:
+        if testoptions.TestSplit or testoptions.TestMoments:
             FirstSplitter = result.popToolsAndMerge( DefaultClusterSplittingToolCfg(flags,"DefaultSplitting") )
-            hybridClusterProcessor.BeforeGPUTools += [FirstSplitter]
+            HybridClusterProcessor.BeforeGPUTools += [FirstSplitter]
             
-            if flags.CaloRecGPU.OutputCountsToFile:
-                CPUCount2 = result.popToolsAndMerge( CellsCounterCPUToolCfg(flags,"DefaultGrowAndSplitCounter","./counts", "default_grow_split") )
-                hybridClusterProcessor.BeforeGPUTools += [CPUCount2]
-            if flags.CaloRecGPU.OutputClustersToFile:
-                CPUOut2 = result.popToolsAndMerge( CPUOutputToolCfg(flags,"DefaultSplitOutput", "./out_default_grow_split") )
-                hybridClusterProcessor.BeforeGPUTools += [CPUOut2]
-        
-        if TestMoments:
+            if testoptions.OutputCounts:
+                CPUCount2 = result.popToolsAndMerge( CellsCounterCPUToolCfg(flags,cellsname,"DefaultGrowAndSplitCounter", SavePath = "./counts", FilePrefix = "default_grow_split") )
+                HybridClusterProcessor.BeforeGPUTools += [CPUCount2]
+            if testoptions.OutputClusters:
+                CPUOut2 = result.popToolsAndMerge( CPUOutputToolCfg(flags, cellsname,"DefaultSplitOutput", SavePath = "./out_default_grow_split") )
+                HybridClusterProcessor.BeforeGPUTools += [CPUOut2]
+        
+        if testoptions.TestMoments:
             CPUMoments = result.popToolsAndMerge( DefaultClusterMomentsCalculatorToolCfg(flags,"CPUMoments") )
-            hybridClusterProcessor.BeforeGPUTools += [CPUMoments]
-            if flags.CaloRecGPU.OutputCountsToFile:
-                CPUDumper = result.popToolsAndMerge( MomentsDumperToolCfg(flags,"./moments", "CPUMomentsDumper", "CPU") )
-                hybridClusterProcessor.BeforeGPUTools += [CPUDumper]
+            HybridClusterProcessor.BeforeGPUTools += [CPUMoments]
+            if testoptions.OutputCounts:
+                CPUDumper = result.popToolsAndMerge( MomentsDumperToolCfg(flags,"CPUMomentsDumper", SavePath = "./moments", FilePrefix = "CPU") )
+                HybridClusterProcessor.BeforeGPUTools += [CPUDumper]
         
-        Deleter = result.popToolsAndMerge( CaloClusterDeleterToolCfg(flags))
-        hybridClusterProcessor.BeforeGPUTools += [Deleter]                
+        HybridClusterProcessor.BeforeGPUTools += [CompFactory.CaloClusterDeleter("ClusterDeleter")]                
         
-        if TestSplit and (not TestGrow or DoCrossTests):
-            SecondDefaultClustering = result.popToolsAndMerge( DefaultTopologicalClusteringToolCfg(flags,"SecondDefaultGrowing") )
-            hybridClusterProcessor.BeforeGPUTools += [SecondDefaultClustering]
+        if testoptions.TestSplit and (not testoptions.TestGrow or testoptions.DoCrossTests):
+            SecondDefaultClustering = result.popToolsAndMerge( DefaultTopologicalClusteringToolCfg(flags,cellsname,"SecondDefaultGrowing") )
+            HybridClusterProcessor.BeforeGPUTools += [SecondDefaultClustering]
         
-    hybridClusterProcessor.GPUTools = []
+    HybridClusterProcessor.GPUTools = []
     
-    if OutputCellInfo:
-        CellOut = result.popToolsAndMerge( GPUOutputToolCfg(flags,"CellInfoOutput","./out_cell", OnlyOutputCells = True) )
-        hybridClusterProcessor.GPUTools += [CellOut]
+    if testoptions.OutputCellInfo:
+        CellOut = result.popToolsAndMerge( GPUOutputToolCfg(flags,"CellInfoOutput", SavePath = "./out_cell", OnlyOutputCellInfo = True) )
+        HybridClusterProcessor.GPUTools += [CellOut]
         
-    if TestSplit:
-        if not TestGrow:
+    if testoptions.TestSplit:
+        if not testoptions.TestGrow:
             GPUClusterSplitting1 = result.popToolsAndMerge( TopoAutomatonSplitterToolCfg(flags,"GPUSplitter") )
-            if SkipSyncs:
+            if testoptions.SkipSyncs:
                 GPUClusterSplitting1.MeasureTimes = False
-            hybridClusterProcessor.GPUTools += [GPUClusterSplitting1]
+            HybridClusterProcessor.GPUTools += [GPUClusterSplitting1]
             PropCalc1 = result.popToolsAndMerge( ClusterInfoCalcToolCfg(flags,"PropCalcPostSplitting", False) )
-            if SkipSyncs:
+            if testoptions.SkipSyncs:
                 PropCalc1.MeasureTimes = False
-            hybridClusterProcessor.GPUTools += [PropCalc1]
-        elif DoCrossTests:
+            HybridClusterProcessor.GPUTools += [PropCalc1]
+        elif testoptions.DoCrossTests:
             GPUClusterSplitting1 = result.popToolsAndMerge( TopoAutomatonSplitterToolCfg(flags,"FirstGPUSplitter") )
             GPUClusterSplitting1.TimeFileOutput = "" #This means there's no output.
             GPUClusterSplitting1.MeasureTimes = False
-            hybridClusterProcessor.GPUTools += [GPUClusterSplitting1]
+            HybridClusterProcessor.GPUTools += [GPUClusterSplitting1]
             PropCalc1 = result.popToolsAndMerge( ClusterInfoCalcToolCfg(flags,"PropCalcDefaultGrowGPUSplit", False) )
             PropCalc1.TimeFileOutput = "" #This means there's no output.
             PropCalc1.MeasureTimes = False
-            hybridClusterProcessor.GPUTools += [PropCalc1]
+            HybridClusterProcessor.GPUTools += [PropCalc1]
         
-        if ((not TestGrow) or DoCrossTests):
-            if flags.CaloRecGPU.OutputCountsToFile:
-                GPUCount1 = result.popToolsAndMerge( CellsCounterGPUToolCfg(flags,"DefaultGrowModifiedSplitCounter","./counts", "default_grow_modified_split") )
-                hybridClusterProcessor.GPUTools += [GPUCount1]
-            if flags.CaloRecGPU.OutputClustersToFile:
-                GPUOut1 = result.popToolsAndMerge( GPUOutputToolCfg(flags,"DefaultGrowModifiedSplitOutput","./out_default_grow_modified_split") )
-                hybridClusterProcessor.GPUTools += [GPUOut1]
+        if ((not testoptions.TestGrow) or testoptions.DoCrossTests):
+            if testoptions.OutputCounts:
+                GPUCount1 = result.popToolsAndMerge( CellsCounterGPUToolCfg(flags,"DefaultGrowModifiedSplitCounter", SavePath = "./counts", FilePrefix = "default_grow_modified_split") )
+                HybridClusterProcessor.GPUTools += [GPUCount1]
+            if testoptions.OutputClusters:
+                GPUOut1 = result.popToolsAndMerge( GPUOutputToolCfg(flags,"DefaultGrowModifiedSplitOutput", SavePath = "./out_default_grow_modified_split") )
+                HybridClusterProcessor.GPUTools += [GPUOut1]
         
-    if TestGrow:
+    if testoptions.TestGrow:
         TopoAutomatonClustering1 = result.popToolsAndMerge( TopoAutomatonClusteringToolCfg(flags,"GPUGrowing") )
-        if SkipSyncs:
+        if testoptions.SkipSyncs:
             TopoAutomatonClustering1.MeasureTimes = False
-        hybridClusterProcessor.GPUTools += [TopoAutomatonClustering1]
+        HybridClusterProcessor.GPUTools += [TopoAutomatonClustering1]
         
         PropCalc2 = result.popToolsAndMerge( ClusterInfoCalcToolCfg(flags,"PropCalcPostGrowing", True))
-        if SkipSyncs:
+        if testoptions.SkipSyncs:
             PropCalc2.MeasureTimes = False
-        hybridClusterProcessor.GPUTools += [PropCalc2]
-        if ((not TestSplit) or DoCrossTests):
-            if flags.CaloRecGPU.OutputCountsToFile:
-                GPUCount2 = result.popToolsAndMerge( CellsCounterGPUToolCfg(flags,"ModifiedGrowCounter","./counts", "modified_grow") )
-                hybridClusterProcessor.GPUTools += [GPUCount2]
-            if flags.CaloRecGPU.OutputClustersToFile:
-                GPUOut2 = result.popToolsAndMerge( GPUOutputToolCfg(flags,"ModifiedGrowOutput","./out_modified_grow") )
-                hybridClusterProcessor.GPUTools += [GPUOut2]
-    
-    if TestGrow and TestSplit:
+        HybridClusterProcessor.GPUTools += [PropCalc2]
+        if ((not testoptions.TestSplit) or testoptions.DoCrossTests):
+            if testoptions.OutputCounts:
+                GPUCount2 = result.popToolsAndMerge( CellsCounterGPUToolCfg(flags,"ModifiedGrowCounter", SavePath = "./counts", FilePrefix = "modified_grow") )
+                HybridClusterProcessor.GPUTools += [GPUCount2]
+            if testoptions.OutputClusters:
+                GPUOut2 = result.popToolsAndMerge( GPUOutputToolCfg(flags,"ModifiedGrowOutput", SavePath = "./out_modified_grow") )
+                HybridClusterProcessor.GPUTools += [GPUOut2]
+    
+    if testoptions.TestGrow and testoptions.TestSplit:
         GPUClusterSplitting2 = result.popToolsAndMerge( TopoAutomatonSplitterToolCfg(flags,"GPUSplitter") )
-        if SkipSyncs:
+        if testoptions.SkipSyncs:
             GPUClusterSplitting2.MeasureTimes = False
-        hybridClusterProcessor.GPUTools += [GPUClusterSplitting2]
+        HybridClusterProcessor.GPUTools += [GPUClusterSplitting2]
         
-        if hybridClusterProcessor.DoPlots or not TestMoments:
+        if HybridClusterProcessor.DoPlots or not testoptions.TestMoments:
           PropCalc3 = result.popToolsAndMerge( ClusterInfoCalcToolCfg(flags,"PropCalcPostSplitting", False) )
-          if SkipSyncs:
+          if testoptions.SkipSyncs:
               PropCalc3.MeasureTimes = False
-          hybridClusterProcessor.GPUTools += [PropCalc3]
+          HybridClusterProcessor.GPUTools += [PropCalc3]
         
-        if flags.CaloRecGPU.OutputCountsToFile:
-            GPUCount3 = result.popToolsAndMerge( CellsCounterGPUToolCfg(flags,"ModifiedGrowSplitCounter","./counts", "modified_grow_split") )
-            hybridClusterProcessor.GPUTools += [GPUCount3]
-        if flags.CaloRecGPU.OutputClustersToFile:
-            GPUOut3 = result.popToolsAndMerge( GPUOutputToolCfg(flags,"ModifiedGrowSplitOutput","./out_modified_grow_split") )
-            hybridClusterProcessor.GPUTools += [GPUOut3]
+        if testoptions.OutputCounts:
+            GPUCount3 = result.popToolsAndMerge( CellsCounterGPUToolCfg(flags,"ModifiedGrowSplitCounter", SavePath = "./counts", FilePrefix = "modified_grow_split") )
+            HybridClusterProcessor.GPUTools += [GPUCount3]
+        if testoptions.OutputClusters:
+            GPUOut3 = result.popToolsAndMerge( GPUOutputToolCfg(flags,"ModifiedGrowSplitOutput", SavePath = "./out_modified_grow_split") )
+            HybridClusterProcessor.GPUTools += [GPUOut3]
         
-        if DoCrossTests:
+        if testoptions.DoCrossTests:
             TopoAutomatonClustering2 = result.popToolsAndMerge( TopoAutomatonClusteringToolCfg(flags,"SecondGPUGrowing") )
             TopoAutomatonClustering2.MeasureTimes = False
             TopoAutomatonClustering2.TimeFileOutput = "" #This means there's no output.
-            hybridClusterProcessor.GPUTools += [TopoAutomatonClustering2]
+            HybridClusterProcessor.GPUTools += [TopoAutomatonClustering2]
             
             PropCalc4 = result.popToolsAndMerge( ClusterInfoCalcToolCfg(flags,"PropCalc4", True) )
             PropCalc4.TimeFileOutput = "" #This means there's no output.
             PropCalc4.MeasureTimes = False
-            hybridClusterProcessor.GPUTools += [PropCalc4]
+            HybridClusterProcessor.GPUTools += [PropCalc4]
         
-    if not (TestGrow or TestSplit):
+    if not (testoptions.TestGrow or testoptions.TestSplit):
         TopoAutomatonClusteringDef = result.popToolsAndMerge( TopoAutomatonClusteringToolCfg(flags,"TopoAutomatonClustering") )
-        if SkipSyncs:
+        if testoptions.SkipSyncs:
             TopoAutomatonClusteringDef.MeasureTimes = False
-        hybridClusterProcessor.GPUTools += [TopoAutomatonClusteringDef]
+        HybridClusterProcessor.GPUTools += [TopoAutomatonClusteringDef]
         
         FirstPropCalcDef = result.popToolsAndMerge( ClusterInfoCalcToolCfg(flags,"PropCalcPostGrowing", True) )
-        if SkipSyncs:
+        if testoptions.SkipSyncs:
             FirstPropCalcDef.MeasureTimes = False
-        hybridClusterProcessor.GPUTools += [FirstPropCalcDef]
+        HybridClusterProcessor.GPUTools += [FirstPropCalcDef]
         
         GPUClusterSplittingDef = result.popToolsAndMerge( TopoAutomatonSplitterToolCfg(flags,"GPUTopoSplitter") )
-        if SkipSyncs:
+        if testoptions.SkipSyncs:
             GPUClusterSplittingDef.MeasureTimes = False
-        hybridClusterProcessor.GPUTools += [GPUClusterSplittingDef]
+        HybridClusterProcessor.GPUTools += [GPUClusterSplittingDef]
         
-        if not TestMoments:
+        if not testoptions.TestMoments:
             SecondPropCalcDef = result.popToolsAndMerge( ClusterInfoCalcToolCfg(flags,"PropCalcPostSplitting", False) )
-            if SkipSyncs:
+            if testoptions.SkipSyncs:
                 SecondPropCalcDef.MeasureTimes = False
-            hybridClusterProcessor.GPUTools += [SecondPropCalcDef]
+            HybridClusterProcessor.GPUTools += [SecondPropCalcDef]
     
-    if TestMoments and not DoCrossTests:
-        if TestGrow and not TestSplit:
+    if testoptions.TestMoments and not testoptions.DoCrossTests:
+        if testoptions.TestGrow and not testoptions.TestSplit:
             GPUClusterSplittingDef = result.popToolsAndMerge( TopoAutomatonSplitterToolCfg(flags,"GPUTopoSplitter") )
-            if SkipSyncs:
+            if testoptions.SkipSyncs:
                 GPUClusterSplittingDef.MeasureTimes = False
-            hybridClusterProcessor.GPUTools += [GPUClusterSplittingDef]
+            HybridClusterProcessor.GPUTools += [GPUClusterSplittingDef]
             
         GPUMomentsDef = result.popToolsAndMerge( GPUClusterMomentsCalculatorToolCfg(flags,"GPUTopoMoments") )
-        if SkipSyncs:
+        if testoptions.SkipSyncs:
             GPUMomentsDef.MeasureTimes = False
-        hybridClusterProcessor.GPUTools += [GPUMomentsDef]
+        HybridClusterProcessor.GPUTools += [GPUMomentsDef]
         
-    hybridClusterProcessor.AfterGPUTools = []
+    HybridClusterProcessor.AfterGPUTools = []
     
-    if TestMoments and flags.CaloRecGPU.OutputCountsToFile:
-        GPUDumper = result.popToolsAndMerge( MomentsDumperToolCfg(flags,"./moments", "GPUMomentsDumper", "GPU") )
-        hybridClusterProcessor.AfterGPUTools += [GPUDumper]
+    if testoptions.TestMoments and testoptions.OutputCounts:
+        GPUDumper = result.popToolsAndMerge( MomentsDumperToolCfg(flags,"GPUMomentsDumper", SavePath = "./moments", FilePrefix = "GPU") )
+        HybridClusterProcessor.AfterGPUTools += [GPUDumper]
         
-    if TestGrow and (not TestSplit or DoCrossTests):
+    if testoptions.TestGrow and (not testoptions.TestSplit or testoptions.DoCrossTests):
     
         TopoSplitter = result.popToolsAndMerge( DefaultClusterSplittingToolCfg(flags,"DefaultPostGPUSplitting") )
-        hybridClusterProcessor.AfterGPUTools += [TopoSplitter]
-        
-        if DoCrossTests:
-            if flags.CaloRecGPU.OutputCountsToFile:
-                CPUCount3 = result.popToolsAndMerge( CellsCounterCPUToolCfg(flags,"ModifiedGrowDefaultSplitCounter","./counts", "modified_grow_default_split") )
-                hybridClusterProcessor.AfterGPUTools += [CPUCount3]
-            if flags.CaloRecGPU.OutputClustersToFile:
-                CPUOut3 = result.popToolsAndMerge( CPUOutputToolCfg(flags,"ModifiedGrowDefaultSplitOutput","./out_modified_grow_default_split") )
-                hybridClusterProcessor.AfterGPUTools += [CPUOut3]
+        HybridClusterProcessor.AfterGPUTools += [TopoSplitter]
+        
+        if testoptions.DoCrossTests:
+            if testoptions.OutputCounts:
+                CPUCount3 = result.popToolsAndMerge( CellsCounterCPUToolCfg(flags,cellsname,"ModifiedGrowDefaultSplitCounter", SavePath = "./counts", FilePrefix = "modified_grow_default_split") )
+                HybridClusterProcessor.AfterGPUTools += [CPUCount3]
+            if testoptions.OutputClusters:
+                CPUOut3 = result.popToolsAndMerge( CPUOutputToolCfg(flags,cellsname,"ModifiedGrowDefaultSplitOutput", SavePath = "./out_modified_grow_default_split") )
+                HybridClusterProcessor.AfterGPUTools += [CPUOut3]
             
-    result.addEventAlgo(hybridClusterProcessor,primary=True)
+    result.addEventAlgo(HybridClusterProcessor,primary=True)
 
     return result
+
+def RunFullTestConfiguration(flags, testoptions, PlotterConfigurator = None, cellsname = "AllCalo", clustersname = "CaloCalTopoClustersNew"):
+    from AthenaConfiguration.MainServicesConfig import MainServicesCfg
+    from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg
+
+    cfg=MainServicesCfg(flags)
+    cfg.merge(PoolReadCfg(flags))
+    
+    if testoptions.UsePerfMon:
+       from PerfMonComps.PerfMonCompsConfig import PerfMonMTSvcCfg
+       cfg.merge(PerfMonMTSvcCfg(flags))
+            
+    if 'StreamRDO' in flags.Input.ProcessingTags:
+        cfg.addEventAlgo(CompFactory.xAODMaker.EventInfoCnvAlg(),sequenceName="AthAlgSeq")
         
+    cfg.merge(MainTestConfiguration(flags, testoptions, PlotterConfigurator, cellsname, clustersname))
+    
+    cfg.getService("MessageSvc").infoLimit = 100000000
+    
+    cfg.run(testoptions.NumEvents)
+    
     
-def PrepareTest(clustersname=None,default_files = ["/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/RecExRecoTest/mc20e_13TeV/valid1.410000.PowhegPythiaEvtGen_P2012_ttbar_hdamp172p5_nonallhad.ESD.e4993_s3227_r12689/myESD.pool.root"],
+def PrepareTest(default_files = ["/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/RecExRecoTest/mc20e_13TeV/valid1.410000.PowhegPythiaEvtGen_P2012_ttbar_hdamp172p5_nonallhad.ESD.e4993_s3227_r12689/myESD.pool.root"],
                 parse_command_arguments = True,
                 allocate_as_many_as_threads = True):
 
@@ -361,9 +791,13 @@ def PrepareTest(clustersname=None,default_files = ["/cvmfs/atlas-nightlies.cern.
     Configurable.configurableRun3Behavior=1
 
     from AthenaConfiguration.AllConfigFlags import initConfigFlags
-    #from AthenaConfiguration.TestDefaults import defaultTestFiles
                     
-    flags = initConfigFlags()
+    initflags = initConfigFlags()
+    testoptions = TestOptions()
+    
+    flags = initflags.cloneAndReplace("CaloRecGPU.ActiveConfig", "CaloRecGPU.Default", True)
+    
+    flags.CaloRecGPU.GlobalFlags.UseCaloRecGPU = True 
     
     if parse_command_arguments:
         flags.fillFromArgs(listOfArgs=rest)
@@ -383,16 +817,14 @@ def PrepareTest(clustersname=None,default_files = ["/cvmfs/atlas-nightlies.cern.
             
         elif args.files[0] == 'jets':
             flags.Input.Files = ["/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/TrigEgammaValidation/valid3.147917.Pythia8_AU2CT10_jetjet_JZ7W.recon.RDO.e3099_s2578_r6596_tid05293007_00/RDO.05293007._000001.pool.root.1"]
+        elif args.files[0] == 'trigEB':
+            flags.Input.Files = ["/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/TrigP1Test/data22_13p6TeV.00440499.physics_EnhancedBias.merge.RAW._lb0470._SFO-11._0001.1",
+                                 "/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/TrigP1Test/data22_13p6TeV.00440499.physics_EnhancedBias.merge.RAW._lb0470._SFO-12._0001.1"]
         else:
             flags.Input.Files = args.files
     else:
         flags.Input.Files = args.files
 
-    perfmon=False
-    if parse_command_arguments:
-        if args.perfmon or args.fullmon:
-           perfmon=True
-
     if parse_command_arguments:
         flags.Concurrency.NumThreads = int(args.numthreads)
         flags.Concurrency.NumConcurrentEvents = int(args.numthreads)
@@ -400,41 +832,18 @@ def PrepareTest(clustersname=None,default_files = ["/cvmfs/atlas-nightlies.cern.
         flags.PerfMon.doFastMonMT = args.perfmon
         flags.PerfMon.doFullMonMT = args.fullmon
         # configure GPU
-        flags.CaloRecGPU.Default.MeasureTimes = args.measuretimes
-        flags.CaloRecGPU.Default.OutputClustersToFile = args.outputclusters
-        flags.CaloRecGPU.Default.OutputCountsToFile = args.outputcounts
-        flags.CaloRecGPU.Default.FillMissingCells = not args.notfillcells
-        flags.CaloRecGPU.Default.UseOriginalCriteria = args.useoriginalcriteria
-        flags.CaloRecGPU.Default.TwoGaussianNoise = not args.nodoublegaussiannoise
+        flags.CaloRecGPU.ActiveConfig.MeasureTimes = args.measuretimes
+        testoptions.OutputClusters = args.outputclusters
+        testoptions.OutputCounts = args.outputcounts
+        flags.CaloRecGPU.ActiveConfig.FillMissingCells = not args.notfillcells
+        flags.CaloRecGPU.ActiveConfig.UseOriginalCriteria = args.useoriginalcriteria
+        flags.CaloRecGPU.ActiveConfig.doTwoGaussianNoise = not args.nodoublegaussiannoise
         if allocate_as_many_as_threads:
-            flags.CaloRecGPU.Default.NumPreAllocatedDataHolders = int(args.numthreads)
-
-    flags.CaloRecGPU.Default.MissingCellsToFill = [186986, 187352]
-
-    if clustersname is not None:
-        flags.CaloRecGPU.Default.ClustersOutputName = clustersname
-    
-    if parse_command_arguments:
-        return (flags, perfmon,int(args.numevents))
-    else:
-        return (flags, perfmon, -1)
-
-def MinimalSetup(flags,perfmon):
-    from AthenaConfiguration.MainServicesConfig import MainServicesCfg
-    from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg
-
-    cfg=MainServicesCfg(flags)
-    cfg.merge(PoolReadCfg(flags))
-    
-    if perfmon:
-       from PerfMonComps.PerfMonCompsConfig import PerfMonMTSvcCfg
-       cfg.merge(PerfMonMTSvcCfg(flags))
-            
-    
-    if 'StreamRDO' in flags.Input.ProcessingTags:
-        cfg.addEventAlgo(CompFactory.xAODMaker.EventInfoCnvAlg(),sequenceName="AthAlgSeq")
-
-    return cfg
+            flags.CaloRecGPU.ActiveConfig.NumPreAllocatedDataHolders = int(args.numthreads)
+        testoptions.UsePerfMon = args.perfmon or args.fullmon
+        testoptions.NumEvents = int(args.numevents)
     
+    flags.CaloRecGPU.GlobalFlags.UseCaloRecGPU = True
+    flags.CaloRecGPU.ActiveConfig.MissingCellsToFill = [186986, 187352]
     
-
+    return (flags, testoptions)
\ No newline at end of file
diff --git a/Calorimeter/CaloRecGPU/test/CaloRecGPU_count_cells_to_file.py b/Calorimeter/CaloRecGPU/test/CaloRecGPU_count_cells_to_file.py
index 70b1e43e49dc82a433d88b2907e099c813b5075a..61a128cb2070d9ff46e18414f427ca76fd48ea35 100644
--- a/Calorimeter/CaloRecGPU/test/CaloRecGPU_count_cells_to_file.py
+++ b/Calorimeter/CaloRecGPU/test/CaloRecGPU_count_cells_to_file.py
@@ -9,15 +9,14 @@ import CaloRecGPUTestingConfig
     
 if __name__=="__main__":
 
-    flags, perfmon, numevents = CaloRecGPUTestingConfig.PrepareTest()
-
-    flags.CaloRecGPU.Default.OutputCountsToFile = True
-    flags.CaloRecGPU.Default.ClustersOutputName="CaloCalTopoClustersNew"
+    flags, testopts = CaloRecGPUTestingConfig.PrepareTest()
+    
     flags.lock()
-    flagsActive = flags.cloneAndReplace("CaloRecGPU.ActiveConfig", "CaloRecGPU.Default")
     
-    topoAcc = CaloRecGPUTestingConfig.MinimalSetup(flagsActive,perfmon)
-    topoAcc.merge(CaloRecGPUTestingConfig.FullTestConfiguration(flagsActive, TestGrow = True, TestSplit = True, DoCrossTests = True))
-
-    topoAcc.run(numevents)
+    testopts.TestGrow = True
+    testopts.TestSplit = True
+    testopts.DoCrossTests = True
+    testopts.OutputCounts = True
+    
+    CaloRecGPUTestingConfig.RunFullTestConfiguration(flags, testopts)
 
diff --git a/Calorimeter/CaloRecGPU/test/CaloRecGPU_measure_times.py b/Calorimeter/CaloRecGPU/test/CaloRecGPU_measure_times.py
index 4cd5b8f50cd25aadd9234dc8a3d06ca86d37d046..bc4c70ca0091a3ee53c33d952e3c1b270c14ec6a 100644
--- a/Calorimeter/CaloRecGPU/test/CaloRecGPU_measure_times.py
+++ b/Calorimeter/CaloRecGPU/test/CaloRecGPU_measure_times.py
@@ -8,16 +8,17 @@ import CaloRecGPUTestingConfig
     
 if __name__=="__main__":
 
-    flags, perfmon, numevents = CaloRecGPUTestingConfig.PrepareTest()
-    flags.CaloRecGPU.Default.MeasureTimes = True
-    flags.CaloRecGPU.Default.ClustersOutputName="CaloCalTopoClustersNew"
+    flags, testopts = CaloRecGPUTestingConfig.PrepareTest()
+        
+    flags.CaloRecGPU.ActiveConfig.MeasureTimes = True
+    
     flags.lock()
-    flagsActive = flags.cloneAndReplace("CaloRecGPU.ActiveConfig", "CaloRecGPU.Default")
-
-    topoAcc = CaloRecGPUTestingConfig.MinimalSetup(flagsActive,perfmon)
-
-    topoAcc.merge(CaloRecGPUTestingConfig.FullTestConfiguration(flagsActive,TestGrow=True, TestSplit=True, SkipSyncs=True))
-
-    topoAcc.run(numevents)
+    
+    testopts.TestGrow = True
+    testopts.TestSplit = True
+    testopts.TestMoments = True
+    testopts.SkipSyncs = True
+    
+    CaloRecGPUTestingConfig.RunFullTestConfiguration(flags, testopts)
 
     
diff --git a/Calorimeter/CaloRecGPU/test/CaloRecGPU_measure_times_sync.py b/Calorimeter/CaloRecGPU/test/CaloRecGPU_measure_times_sync.py
index 5ca5a658d3a4ccc674698b1e789abfc9e92969b2..9315da26d0955053c54acc8e0e09895f866ef4ca 100644
--- a/Calorimeter/CaloRecGPU/test/CaloRecGPU_measure_times_sync.py
+++ b/Calorimeter/CaloRecGPU/test/CaloRecGPU_measure_times_sync.py
@@ -10,15 +10,16 @@ import CaloRecGPUTestingConfig
     
 if __name__=="__main__":
 
-    flags, perfmon, numevents = CaloRecGPUTestingConfig.PrepareTest()
-    flags.CaloRecGPU.Default.MeasureTimes = True
-    flags.CaloRecGPU.Default.ClustersOutputName="CaloCalTopoClustersNew"
+    flags, testopts = CaloRecGPUTestingConfig.PrepareTest()
+        
+    flags.CaloRecGPU.ActiveConfig.MeasureTimes = True
+    
     flags.lock()
-    flagsActive = flags.cloneAndReplace("CaloRecGPU.ActiveConfig", "CaloRecGPU.Default")
-
-    topoAcc = CaloRecGPUTestingConfig.MinimalSetup(flagsActive,perfmon)
-
-    topoAcc.merge(CaloRecGPUTestingConfig.FullTestConfiguration(flagsActive, TestGrow=True, TestSplit=True, SkipSyncs = False))
-
-    topoAcc.run(numevents)
+    
+    testopts.TestGrow = True
+    testopts.TestSplit = True
+    testopts.TestMoments = True
+    testopts.SkipSyncs = False
+    
+    CaloRecGPUTestingConfig.RunFullTestConfiguration(flags, testopts)
 
diff --git a/Calorimeter/CaloRecGPU/test/CaloRecGPU_simple_grow_test.py b/Calorimeter/CaloRecGPU/test/CaloRecGPU_simple_grow_test.py
index d39195af69442d9fc8c242960d9450ed628b4889..d2df17d9f0254c18e5d9f76211734e8585428835 100644
--- a/Calorimeter/CaloRecGPU/test/CaloRecGPU_simple_grow_test.py
+++ b/Calorimeter/CaloRecGPU/test/CaloRecGPU_simple_grow_test.py
@@ -3,23 +3,16 @@
 #Outputs plots for comparing CPU and GPU growing.
 
 import CaloRecGPUTestingConfig
-from PlotterConfigurator import PlotterConfigurator
 
 if __name__=="__main__":
 
+    flags, testopts = CaloRecGPUTestingConfig.PrepareTest()
     
-    PlotterConfig = PlotterConfigurator(["CPU_growing", "GPU_growing"], ["growing"])
-    
-    flags, perfmon, numevents = CaloRecGPUTestingConfig.PrepareTest()
-    flags.CaloRecGPU.Default.DoMonitoring = True
-    flags.CaloRecGPU.Default.ClustersOutputName="CaloCalTopoClustersNew"
     flags.lock()
-    flagsActive = flags.cloneAndReplace("CaloRecGPU.ActiveConfig", "CaloRecGPU.Default")
-
-    topoAcc = CaloRecGPUTestingConfig.MinimalSetup(flagsActive,perfmon)
-
-    topoAcc.merge(CaloRecGPUTestingConfig.FullTestConfiguration(flagsActive, TestGrow = True, PlotterConfigurator = PlotterConfig))
-
-
-    topoAcc.run(numevents)
+    
+    testopts.TestGrow = True
+    
+    PlotterConfig = CaloRecGPUTestingConfig.PlotterConfigurator(["CPU_growing", "GPU_growing"], ["growing"])
+    
+    CaloRecGPUTestingConfig.RunFullTestConfiguration(flags, testopts, PlotterConfigurator = PlotterConfig)
 
diff --git a/Calorimeter/CaloRecGPU/test/CaloRecGPU_simple_growsplit_cross_test.py b/Calorimeter/CaloRecGPU/test/CaloRecGPU_simple_growsplit_cross_test.py
index d08e8b50c9d283aa802d8b6b68e2abc9a7e34467..5b8c946b83858e05b104aac19b244c120c446fb1 100644
--- a/Calorimeter/CaloRecGPU/test/CaloRecGPU_simple_growsplit_cross_test.py
+++ b/Calorimeter/CaloRecGPU/test/CaloRecGPU_simple_growsplit_cross_test.py
@@ -9,25 +9,20 @@
 #and GPU growing with CPU splitting.
 
 import CaloRecGPUTestingConfig
-from PlotterConfigurator import PlotterConfigurator
 
     
 if __name__=="__main__":
 
-    
-    PlotterConfig = PlotterConfigurator(["CPU_growing", "GPU_growing", "CPUCPU_splitting", "GPUGPU_splitting", "CPUGPU_splitting", "GPUCPU_splitting"],
-                                                          ["growing", "CPU_to_GPUGPU_splitting", "CPU_to_CPUGPU_splitting", "CPU_to_GPUCPU_splitting"])   
-
-    flags, perfmon, numevents = CaloRecGPUTestingConfig.PrepareTest()
-    flags.CaloRecGPU.Default.DoMonitoring = True
-    flags.CaloRecGPU.Default.ClustersOutputName="CaloCalTopoClustersNew"
+    flags, testopts = CaloRecGPUTestingConfig.PrepareTest()
+        
     flags.lock()
-    flagsActive = flags.cloneAndReplace("CaloRecGPU.ActiveConfig", "CaloRecGPU.Default")
     
-    topoAcc = CaloRecGPUTestingConfig.MinimalSetup(flagsActive,perfmon)
-
-    topoAcc.merge(CaloRecGPUTestingConfig.FullTestConfiguration(flagsActive, TestGrow = True, TestSplit = True, DoCrossTests = True, PlotterConfigurator = PlotterConfig))
-
+    testopts.TestGrow = True
+    testopts.TestSplit = True
+    testopts.DoCrossTests = True
     
-    topoAcc.run(numevents)
-
+    PlotterConfig = CaloRecGPUTestingConfig.PlotterConfigurator(["CPU_growing", "GPU_growing", "CPUCPU_splitting", "GPUGPU_splitting", "CPUGPU_splitting", "GPUCPU_splitting"],
+                                                          ["growing", "CPU_to_GPUGPU_splitting", "CPU_to_CPUGPU_splitting", "CPU_to_GPUCPU_splitting"])   
+    
+    CaloRecGPUTestingConfig.RunFullTestConfiguration(flags, testopts, PlotterConfigurator = PlotterConfig)
+    
\ No newline at end of file
diff --git a/Calorimeter/CaloRecGPU/test/CaloRecGPU_simple_growsplit_test.py b/Calorimeter/CaloRecGPU/test/CaloRecGPU_simple_growsplit_test.py
index bc99419c5a569e75641fca379970ac7750376c55..e5114e7fd33613163f475522d13dcef307b7d413 100644
--- a/Calorimeter/CaloRecGPU/test/CaloRecGPU_simple_growsplit_test.py
+++ b/Calorimeter/CaloRecGPU/test/CaloRecGPU_simple_growsplit_test.py
@@ -5,21 +5,18 @@
 #and CPU growing + splitting with GPU growing + splitting
 
 import CaloRecGPUTestingConfig
-from PlotterConfigurator import PlotterConfigurator
     
 if __name__=="__main__":
 
-    PlotterConfig = PlotterConfigurator(["CPU_growing", "GPU_growing", "CPU_splitting", "GPU_splitting"], ["growing", "splitting"])
-
-    flags, perfmon, numevents = CaloRecGPUTestingConfig.PrepareTest()
-    flags.CaloRecGPU.Default.DoMonitoring = True
-    flags.CaloRecGPU.Default.ClustersOutputName="CaloCalTopoClustersNew"
+    flags, testopts = CaloRecGPUTestingConfig.PrepareTest()
+    
     flags.lock()
-    flagsActive = flags.cloneAndReplace("CaloRecGPU.ActiveConfig", "CaloRecGPU.Default")
-
-    topoAcc = CaloRecGPUTestingConfig.MinimalSetup(flagsActive,perfmon)
-
-    topoAcc.merge(CaloRecGPUTestingConfig.FullTestConfiguration(flagsActive, TestGrow = True, TestSplit = True, PlotterConfigurator = PlotterConfig))
+    
+    testopts.TestGrow = True
+    testopts.TestSplit = True
+    
+    PlotterConfig = CaloRecGPUTestingConfig.PlotterConfigurator(["CPU_growing", "GPU_growing", "CPU_splitting", "GPU_splitting"], ["growing", "splitting"])  
+    
+    CaloRecGPUTestingConfig.RunFullTestConfiguration(flags, testopts, PlotterConfigurator = PlotterConfig)
 
-    topoAcc.run(numevents)
 
diff --git a/Calorimeter/CaloRecGPU/test/CaloRecGPU_simple_moments_test.py b/Calorimeter/CaloRecGPU/test/CaloRecGPU_simple_moments_test.py
index 349c051b2143e1409a612e4ca337a4132daae4a3..1c893986e7a96cb20c0a2563dc289957ea6cb18e 100644
--- a/Calorimeter/CaloRecGPU/test/CaloRecGPU_simple_moments_test.py
+++ b/Calorimeter/CaloRecGPU/test/CaloRecGPU_simple_moments_test.py
@@ -4,20 +4,17 @@
 #to compare CPU with GPU moments calculation.
 
 import CaloRecGPUTestingConfig
-from PlotterConfigurator import PlotterConfigurator
     
 if __name__=="__main__":
 
-    PlotterConfig = PlotterConfigurator(["CPU_moments", "GPU_moments"], ["moments"], DoMoments = True)
-    
-    flags, perfmon, numevents = CaloRecGPUTestingConfig.PrepareTest()
-    flags.CaloRecGPU.Default.UseAbsEnergyMoments = True
-    flags.CaloRecGPU.Default.ClustersOutputName="CaloCalTopoClustersNew"
+    flags, testopts = CaloRecGPUTestingConfig.PrepareTest()
+            
     flags.lock()
-    flagsActive = flags.cloneAndReplace("CaloRecGPU.ActiveConfig", "CaloRecGPU.Default")
-
-    topoAcc = CaloRecGPUTestingConfig.MinimalSetup(flagsActive,perfmon)
-
-    topoAcc.merge(CaloRecGPUTestingConfig.FullTestConfiguration(flagsActive, TestMoments = True, PlotterConfigurator = PlotterConfig))
-
-    topoAcc.run(numevents)
+    
+    testopts.TestGrow = True
+    testopts.TestSplit = True
+    
+    PlotterConfig = CaloRecGPUTestingConfig.PlotterConfigurator(["CPU_moments", "GPU_moments"], ["moments"], DoMoments = True)
+    
+    CaloRecGPUTestingConfig.RunFullTestConfiguration(flags, testopts, PlotterConfigurator = PlotterConfig)
+    
\ No newline at end of file
diff --git a/Calorimeter/CaloRecGPU/test/CaloRecGPU_simple_run.py b/Calorimeter/CaloRecGPU/test/CaloRecGPU_simple_run.py
index 7c20fa14fc49e37824812159b054da2f83a010b7..9c82ff27d29d5013f542b6f90c46c97b89a85417 100644
--- a/Calorimeter/CaloRecGPU/test/CaloRecGPU_simple_run.py
+++ b/Calorimeter/CaloRecGPU/test/CaloRecGPU_simple_run.py
@@ -6,15 +6,11 @@ import CaloRecGPUTestingConfig
     
 if __name__=="__main__":
 
-    flags, perfmon, numevents = CaloRecGPUTestingConfig.PrepareTest()
-
-    flags.CaloRecGPU.Default.ClustersOutputName="CaloCalTopoClustersNew"
+    flags, testopts = CaloRecGPUTestingConfig.PrepareTest()
+            
     flags.lock()
-    flagsActive = flags.cloneAndReplace("CaloRecGPU.ActiveConfig", "CaloRecGPU.Default")
-
-    topoAcc = CaloRecGPUTestingConfig.MinimalSetup(flagsActive,perfmon)
     
-    topoAcc.merge(CaloRecGPUTestingConfig.FullTestConfiguration(flagsActive))
+    CaloRecGPUTestingConfig.RunFullTestConfiguration(flags, testopts)
+
 
-    topoAcc.run(numevents)
 
diff --git a/Calorimeter/CaloRecGPU/test/CaloRecGPU_simple_run_monitoring.py b/Calorimeter/CaloRecGPU/test/CaloRecGPU_simple_run_monitoring.py
deleted file mode 100644
index 14d89c590e24215bbf60519aa15d33d1866c3eeb..0000000000000000000000000000000000000000
--- a/Calorimeter/CaloRecGPU/test/CaloRecGPU_simple_run_monitoring.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
-
-#Just runs the GPU algorithms, with basic monitoring enabled.
-
-import CaloRecGPUTestingConfig
-    
-if __name__=="__main__":
-
-    
-    flags, perfmon, numevents = CaloRecGPUTestingConfig.PrepareTest()
-    flags.CaloRecGPU.Default.DoMonitoring = True
-    flags.CaloRecGPU.Default.ClustersOutputName="CaloCalTopoClustersNew"
-    flags.lock()
-    flagsActive = flags.cloneAndReplace("CaloRecGPU.ActiveConfig", "CaloRecGPU.Default")
-
-    topoAcc = CaloRecGPUTestingConfig.MinimalSetup(flagsActive,perfmon)
-
-    topoAcc.merge(CaloRecGPUTestingConfig.FullTestConfiguration(flagsActive))
-
-
-    topoAcc.run(numevents)
-
diff --git a/Calorimeter/CaloRecGPU/test/CaloRecGPU_simple_split_test.py b/Calorimeter/CaloRecGPU/test/CaloRecGPU_simple_split_test.py
index e264a9d7360a3e6d9badba6e063195224632dcde..ec06b8f8eb0b76184b709a0e773afb1695bf4a93 100644
--- a/Calorimeter/CaloRecGPU/test/CaloRecGPU_simple_split_test.py
+++ b/Calorimeter/CaloRecGPU/test/CaloRecGPU_simple_split_test.py
@@ -3,21 +3,16 @@
 #Outputs plots for comparing CPU and GPU splitting.
 
 import CaloRecGPUTestingConfig
-from PlotterConfigurator import PlotterConfigurator
     
 if __name__=="__main__":
 
-    PlotterConfig = PlotterConfigurator(["CPU_splitting", "GPU_splitting"], ["splitting"])
-
-    flags, perfmon, numevents = CaloRecGPUTestingConfig.PrepareTest()
-    flags.CaloRecGPU.Default.DoMonitoring = True
-
-    flags.CaloRecGPU.Default.ClustersOutputName="CaloCalTopoClustersNew"
+    flags, testopts = CaloRecGPUTestingConfig.PrepareTest()
+        
     flags.lock()
-    flagsActive = flags.cloneAndReplace("CaloRecGPU.ActiveConfig", "CaloRecGPU.Default")
-
-    topoAcc = CaloRecGPUTestingConfig.MinimalSetup(flagsActive,perfmon)
-
-    topoAcc.merge(CaloRecGPUTestingConfig.FullTestConfiguration(flagsActive, TestSplit = True, PlotterConfigurator = PlotterConfig))
-
-    topoAcc.run(numevents)
+    
+    testopts.TestGrow = True
+    
+    PlotterConfig = CaloRecGPUTestingConfig.PlotterConfigurator(["CPU_splitting", "GPU_splitting"], ["splitting"])
+    
+    CaloRecGPUTestingConfig.RunFullTestConfiguration(flags, testopts, PlotterConfigurator = PlotterConfig)
+    
diff --git a/Calorimeter/CaloRecGPU/test/CaloRecGPU_time_CPU_and_overheads.py b/Calorimeter/CaloRecGPU/test/CaloRecGPU_time_CPU_and_overheads.py
deleted file mode 100644
index 6bbe450f9bff27d0a43c670a9ddc8c64cf5115e7..0000000000000000000000000000000000000000
--- a/Calorimeter/CaloRecGPU/test/CaloRecGPU_time_CPU_and_overheads.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
-
-from CaloRecGPU.CaloRecGPUConfigurator import CaloRecGPUConfigurator
-import CaloRecGPUTesting
-
-#Run the CPU implementation plus any overheads,
-#for multithreading studies.
-
-def Configure(Configurator, clustersname = None):
-        from AthenaConfiguration.ComponentFactory import CompFactory
-        
-        result = CaloRecGPUTesting.PrevAlgorithmsConfiguration(Configurator, clustersname)
-        
-        HybridClusterProcessor = CompFactory.CaloGPUHybridClusterProcessor("HybridClusterProcessor")
-        HybridClusterProcessor.ClustersOutputName = Configurator.ClustersOutputName
-        HybridClusterProcessor.MeasureTimes = Configurator.MeasureTimes
-        HybridClusterProcessor.TimeFileOutput = "GlobalTimes.txt"
-        HybridClusterProcessor.DeferConstantDataPreparationToFirstEvent = True
-        HybridClusterProcessor.DoPlots = False
-        HybridClusterProcessor.PlotterTool = None
-        HybridClusterProcessor.DoMonitoring = False
-        HybridClusterProcessor.NumPreAllocatedDataHolders = Configurator.NumPreAllocatedDataHolders
-        
-        from LArGeoAlgsNV.LArGMConfig import LArGMCfg
-        from TileGeoModel.TileGMConfig import TileGMCfg
-        
-        result.merge(LArGMCfg(Configurator.ConfigFlags))
-        result.merge(TileGMCfg(Configurator.ConfigFlags))
-        
-        ConstantDataExporter = result.popToolsAndMerge( Configurator.BasicConstantDataExporterToolConf() )
-        
-        HybridClusterProcessor.ConstantDataToGPUTool = ConstantDataExporter
-        
-        HybridClusterProcessor.EventDataToGPUTool = None
-        HybridClusterProcessor.GPUToEventDataTool = None
-        
-        HybridClusterProcessor.BeforeGPUTools = []
-        
-        DefaultClustering = result.popToolsAndMerge( Configurator.DefaultTopologicalClusteringToolConf("DefaultGrowing") )
-        HybridClusterProcessor.BeforeGPUTools += [DefaultClustering]
-        
-        DefaultSplitting = result.popToolsAndMerge( Configurator.DefaultClusterSplittingToolConf("DefaultSplitting") )
-        HybridClusterProcessor.BeforeGPUTools += [DefaultSplitting]
-        
-        CPUMoments = result.popToolsAndMerge( Configurator.DefaultClusterMomentsCalculatorToolConf("CPUMoments") )
-        HybridClusterProcessor.BeforeGPUTools += [CPUMoments]
-        
-        HybridClusterProcessor.GPUTools = []
-        
-        HybridClusterProcessor.AfterGPUTools = []
-        
-        result.addEventAlgo(HybridClusterProcessor,primary=True)
-
-        return result
-
-
-if __name__=="__main__":
-
-    Configurator = CaloRecGPUConfigurator()
-    
-    cfg, numevents = CaloRecGPUTesting.PrepareTest(Configurator)
-
-    theKey="CaloCalTopoClustersNew"
-    
-    topoAcc = Configure(Configurator)
-
-    topoAlg = topoAcc.getPrimary()
-    topoAlg.ClustersOutputName=theKey
-    
-    cfg.merge(topoAcc)
-    
-    cfg.run(numevents)
-
diff --git a/Calorimeter/CaloRecGPU/test/CaloRecGPU_time_GPU_and_overheads.py b/Calorimeter/CaloRecGPU/test/CaloRecGPU_time_GPU_and_overheads.py
deleted file mode 100644
index 0541969528cb7a31fb4470d46b40bf42d9c7598b..0000000000000000000000000000000000000000
--- a/Calorimeter/CaloRecGPU/test/CaloRecGPU_time_GPU_and_overheads.py
+++ /dev/null
@@ -1,77 +0,0 @@
-# Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
-
-from CaloRecGPU.CaloRecGPUConfigurator import CaloRecGPUConfigurator
-import CaloRecGPUTesting
-
-#Run the GPU implementation plus any overheads,
-#for multithreading studies.
-
-def Configure(Configurator, clustersname = None):
-        from AthenaConfiguration.ComponentFactory import CompFactory
-        
-        result = CaloRecGPUTesting.PrevAlgorithmsConfiguration(Configurator, clustersname)
-        
-        HybridClusterProcessor = CompFactory.CaloGPUHybridClusterProcessor("HybridClusterProcessor")
-        HybridClusterProcessor.ClustersOutputName = Configurator.ClustersOutputName
-        HybridClusterProcessor.MeasureTimes = Configurator.MeasureTimes
-        HybridClusterProcessor.TimeFileOutput = "GlobalTimes.txt"
-        HybridClusterProcessor.DeferConstantDataPreparationToFirstEvent = True
-        HybridClusterProcessor.DoPlots = False
-        HybridClusterProcessor.PlotterTool = None
-        HybridClusterProcessor.DoMonitoring = False
-        HybridClusterProcessor.NumPreAllocatedDataHolders = Configurator.NumPreAllocatedDataHolders
-        
-        from LArGeoAlgsNV.LArGMConfig import LArGMCfg
-        from TileGeoModel.TileGMConfig import TileGMCfg
-        
-        result.merge(LArGMCfg(Configurator.ConfigFlags))
-        result.merge(TileGMCfg(Configurator.ConfigFlags))
-        
-        ConstantDataExporter = result.popToolsAndMerge( Configurator.BasicConstantDataExporterToolConf() )
-        EventDataExporter = result.popToolsAndMerge( Configurator.BasicEventDataExporterToolConf() )
-        AthenaClusterImporter = result.popToolsAndMerge( Configurator.AthenaClusterAndMomentsImporterToolConf() )
-        
-        HybridClusterProcessor.ConstantDataToGPUTool = ConstantDataExporter
-        HybridClusterProcessor.EventDataToGPUTool = EventDataExporter
-        HybridClusterProcessor.GPUToEventDataTool = AthenaClusterImporter
-        
-        HybridClusterProcessor.BeforeGPUTools = []
-       
-        HybridClusterProcessor.GPUTools = []
-        
-        TopoAutomatonClusteringDef = result.popToolsAndMerge( Configurator.TopoAutomatonClusteringToolConf("TopoAutomatonClustering"))
-        HybridClusterProcessor.GPUTools += [TopoAutomatonClusteringDef]
-        
-        FirstPropCalcDef = result.popToolsAndMerge( Configurator.ClusterInfoCalcToolConf("PostGrowGPUClusterPropertiesCalculator", True))
-        HybridClusterProcessor.GPUTools += [FirstPropCalcDef]
-        
-        GPUClusterSplittingDef = result.popToolsAndMerge( Configurator.TopoAutomatonSplitterToolConf("GPUSplitter") )
-        HybridClusterProcessor.GPUTools += [GPUClusterSplittingDef]
-        
-        GPUMomentsDef = result.popToolsAndMerge( Configurator.GPUClusterMomentsCalculatorToolConf("GPUTopoMoments") )
-        HybridClusterProcessor.GPUTools += [GPUMomentsDef]
-            
-        HybridClusterProcessor.AfterGPUTools = []
-        
-        result.addEventAlgo(HybridClusterProcessor,primary=True)
-
-        return result
-
-
-if __name__=="__main__":
-
-    Configurator = CaloRecGPUConfigurator()
-    
-    cfg, numevents = CaloRecGPUTesting.PrepareTest(Configurator)
-
-    theKey="CaloCalTopoClustersNew"
-    
-    topoAcc = Configure(Configurator)
-
-    topoAlg = topoAcc.getPrimary()
-    topoAlg.ClustersOutputName=theKey
-    
-    cfg.merge(topoAcc)
-    
-    cfg.run(numevents)
-
diff --git a/Calorimeter/CaloRecGPU/test/CaloRecGPU_time_overheads.py b/Calorimeter/CaloRecGPU/test/CaloRecGPU_time_overheads.py
deleted file mode 100644
index b3a0ef488fc9f5676bb695726ae81d31ae4622c3..0000000000000000000000000000000000000000
--- a/Calorimeter/CaloRecGPU/test/CaloRecGPU_time_overheads.py
+++ /dev/null
@@ -1,64 +0,0 @@
-# Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
-
-from CaloRecGPU.CaloRecGPUConfigurator import CaloRecGPUConfigurator
-import CaloRecGPUTesting
-
-#Run with just the potential overheads and no clustering,
-#for multithreading studies.
-
-def Configure(Configurator, clustersname = None):
-        from AthenaConfiguration.ComponentFactory import CompFactory
-    
-        result = CaloRecGPUTesting.PrevAlgorithmsConfiguration(Configurator, clustersname)
-        
-        HybridClusterProcessor = CompFactory.CaloGPUHybridClusterProcessor("HybridClusterProcessor")
-        HybridClusterProcessor.ClustersOutputName = Configurator.ClustersOutputName
-        HybridClusterProcessor.MeasureTimes = Configurator.MeasureTimes
-        HybridClusterProcessor.TimeFileOutput = "GlobalTimes.txt"
-        HybridClusterProcessor.DeferConstantDataPreparationToFirstEvent = True
-        HybridClusterProcessor.DoPlots = False
-        HybridClusterProcessor.PlotterTool = None
-        HybridClusterProcessor.DoMonitoring = False
-        HybridClusterProcessor.NumPreAllocatedDataHolders = Configurator.NumPreAllocatedDataHolders
-        
-        from LArGeoAlgsNV.LArGMConfig import LArGMCfg
-        from TileGeoModel.TileGMConfig import TileGMCfg
-        
-        result.merge(LArGMCfg(Configurator.ConfigFlags))
-        result.merge(TileGMCfg(Configurator.ConfigFlags))
-        
-        ConstantDataExporter = result.popToolsAndMerge( Configurator.BasicConstantDataExporterToolConf() )
-        
-        HybridClusterProcessor.ConstantDataToGPUTool = ConstantDataExporter
-        
-        HybridClusterProcessor.EventDataToGPUTool = None
-        HybridClusterProcessor.GPUToEventDataTool = None
-        
-        HybridClusterProcessor.BeforeGPUTools = []
-       
-        HybridClusterProcessor.GPUTools = []
-        
-        HybridClusterProcessor.AfterGPUTools = []
-        
-        result.addEventAlgo(HybridClusterProcessor,primary=True)
-
-        return result
-
-
-if __name__=="__main__":
-
-    Configurator = CaloRecGPUConfigurator()
-    
-    cfg, numevents = CaloRecGPUTesting.PrepareTest(Configurator)
-
-    theKey="CaloCalTopoClustersNew"
-    
-    topoAcc = Configure(Configurator)
-
-    topoAlg = topoAcc.getPrimary()
-    topoAlg.ClustersOutputName=theKey
-    
-    cfg.merge(topoAcc)
-    
-    cfg.run(numevents)
-
diff --git a/Calorimeter/CaloRecGPU/test/PlotterConfigurator.py b/Calorimeter/CaloRecGPU/test/PlotterConfigurator.py
deleted file mode 100644
index a27d7e21adeba68c5defaeb17fc091bcd6ae2513..0000000000000000000000000000000000000000
--- a/Calorimeter/CaloRecGPU/test/PlotterConfigurator.py
+++ /dev/null
@@ -1,332 +0,0 @@
-# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
-
-def SingleToolToPlot(tool_name, prefix):
-    return (tool_name, prefix)
-
-def ComparedToolsToPlot(tool_ref, tool_test, prefix, match_in_energy = False, match_without_shared = False, match_perfectly = False):
-    return (tool_ref, tool_test, prefix, match_in_energy, match_without_shared, match_perfectly)
-
-class PlotterConfigurator:
-    #DoCells currently changes nothing
-    #(originally was intended to show
-    #that we had cells with the same energy),
-    #keeping it here to remain part of the interface
-    #if/when we port the cell maker as well.
-    def __init__ (self, StepsToPlot = [], PairsToPlot = [], DoStandard = True, DoMoments = False, DoCells = False):
-        self.PlotsToDo = []
-        if DoStandard:
-            for step in StepsToPlot:
-                self.PlotsToDo += [
-                                    ( (step + "_cluster_E",),
-                                      {'type': 'TH1F',
-                                       'title': "Cluster Energy; E [MeV]; Number of Events",
-                                       'xbins':  63,
-                                       'xmin':  -5020,
-                                       'xmax':   5020,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (step + "_cluster_Et",),
-                                      {'type': 'TH1F',
-                                       'title': "Cluster Transverse Energy; E_T [MeV]; Number of Events",
-                                       'xbins':  63,
-                                       'xmin':  -5020,
-                                       'xmax':   5020,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (step + "_cluster_eta",),
-                                      {'type': 'TH1F',
-                                       'title': "Cluster #eta; #eta; Number of Events",
-                                       'xbins':  84,
-                                       'xmin':  -10.5,
-                                       'xmax':   10.5,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (step + "_cluster_phi",),
-                                      {'type': 'TH1F',
-                                       'title': "Cluster #phi; #phi; Number of Events",
-                                       'xbins':  61,
-                                       'xmin':  -3.25,
-                                       'xmax':   3.25,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (step + "_cluster_eta," + step + "_cluster_phi",),
-                                      {'type': 'TH2F',
-                                       'title': "Cluster #eta versus #phi; #eta; #phi",
-                                       'xbins':  84,
-                                       'xmin':  -10.5,
-                                       'xmax':   10.5,
-                                       'ybins':  61,
-                                       'ymin':  -3.25,
-                                       'ymax':   3.25,
-                                       'path': "EXPERT"}
-                                    )
-                                  ]
-            for pair in PairsToPlot:
-                self.PlotsToDo += [
-                                    ( (pair + "_num_unmatched_clusters",),
-                                      {'type': 'TH1F',
-                                       'title': "Number of Unmatched Clusters; # of Unmatched Clusters; Number of Events",
-                                       'xbins':  21,
-                                       'xmin':  -0.5,
-                                       'xmax':   20.5,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (pair + "_cluster_diff_cells;" + pair + "_cluster_diff_cells_zoom_0",),
-                                      {'type': 'TH1F',
-                                       'title': "Different Cell Assignments; # of Differently Assigned Cells; Number of Clusters",
-                                       'xbins':  21,
-                                       'xmin':  -25,
-                                       'xmax':   1025,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (pair + "_cluster_diff_cells;" + pair + "_cluster_diff_cells_zoom_1",),
-                                      {'type': 'TH1F',
-                                       'title': "Different Cell Assignments; # of Differently Assigned Cells; Number of Clusters",
-                                       'xbins':  21,
-                                       'xmin':  -12.5,
-                                       'xmax':   512.5,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (pair + "_cluster_diff_cells;" + pair + "_cluster_diff_cells_zoom_2",),
-                                      {'type': 'TH1F',
-                                       'title': "Different Cell Assignments; # of Differently Assigned Cells; Number of Clusters",
-                                       'xbins':  21,
-                                       'xmin':  -2.5,
-                                       'xmax':   102.5,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (pair + "_cluster_diff_cells;" + pair + "_cluster_diff_cells_zoom_3",),
-                                      {'type': 'TH1F',
-                                       'title': "Different Cell Assignments; # of Differently Assigned Cells; Number of Clusters",
-                                       'xbins':  21,
-                                       'xmin':  -0.5,
-                                       'xmax':   20.5,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (pair + "_cluster_E_ref," + pair + "_cluster_E_test",),
-                                      {'type': 'TH2F',
-                                       'title': "Cluster Energy Comparison; E^{(CPU)} [MeV]; E^{(GPU)} [MeV]",
-                                       'xbins':  63,
-                                       'xmin':  -50.5,
-                                       'xmax':   50.5,
-                                       'ybins':  63,
-                                       'ymin':  -50.5,
-                                       'ymax':   50.5,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (pair + "_cluster_E_ref," + pair + "_cluster_delta_E_rel_ref",),
-                                      {'type': 'TH2F',
-                                       'title': "Cluster Energy Resolution; E^{(CPU)} [MeV]; #Delta E / #(){E^{(CPU)}}",
-                                       'xbins':  63,
-                                       'xmin':  -50.5,
-                                       'xmax':   50.5,
-                                       'ybins':  63,
-                                       'ymin':  -0.025,
-                                       'ymax':   0.025,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (pair + "_cluster_Et_ref," + pair + "_cluster_Et_test",),
-                                      {'type': 'TH2F',
-                                       'title': "Cluster Transverse Energy Comparison; E_T^{(CPU)} [MeV]; E_T^{(GPU)} [MeV]",
-                                       'xbins':  63,
-                                       'xmin':  -50.5,
-                                       'xmax':   50.5,
-                                       'ybins':  63,
-                                       'ymin':  -50.5,
-                                       'ymax':   50.5,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (pair + "_cluster_Et_ref," + pair + "_cluster_delta_Et_rel_ref",),
-                                      {'type': 'TH2F',
-                                       'title': "Cluster Transverse Energy Resolution; E_T^{(CPU)} [MeV]; #Delta E_T / #(){E_T^{(CPU)}}",
-                                       'xbins':  63,
-                                       'xmin':  -50.5,
-                                       'xmax':   50.5,
-                                       'ybins':  63,
-                                       'ymin':  -0.025,
-                                       'ymax':   0.025,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (pair + "_cluster_eta_ref," + pair + "_cluster_eta_test",),
-                                      {'type': 'TH2F',
-                                       'title': "Cluster #eta Comparison; #eta^{(CPU)}; #eta^{(GPU)}",
-                                       'xbins':  63,
-                                       'xmin':  -10.5,
-                                       'xmax':   10.5,
-                                       'ybins':  63,
-                                       'ymin':  -10.5,
-                                       'ymax':   10.5,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (pair + "_cluster_eta_ref," + pair + "_cluster_delta_eta_rel_ref",),
-                                      {'type': 'TH2F',
-                                       'title': "Cluster #eta Resolution; #eta^{(CPU)}; #Delta #eta / #(){#eta^{(CPU)}}",
-                                       'xbins':  63,
-                                       'xmin':  -10.5,
-                                       'xmax':   10.5,
-                                       'ybins':  63,
-                                       'ymin':  -0.025,
-                                       'ymax':   0.025,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (pair + "_cluster_phi_ref," + pair + "_cluster_phi_test",),
-                                      {'type': 'TH2F',
-                                       'title': "Cluster #phi Comparison; #phi^{(CPU)}; #phi^{(GPU)}",
-                                       'xbins':  63,
-                                       'xmin':  -3.3,
-                                       'xmax':   3.3,
-                                       'ybins':  63,
-                                       'ymin':  -3.3,
-                                       'ymax':   3.3,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (pair + "_cluster_phi_ref," + pair + "_cluster_delta_phi_in_range",),
-                                      {'type': 'TH2F',
-                                       'title': "Cluster #phi Resolution; #phi^{(CPU)}; #Delta #phi",
-                                       'xbins':  63,
-                                       'xmin':  -10.5,
-                                       'xmax':   10.5,
-                                       'ybins':  63,
-                                       'ymin':  -0.025,
-                                       'ymax':   0.025,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (pair + "_cluster_delta_phi_in_range",),
-                                      {'type': 'TH1F',
-                                       'title': "Cluster #phi; #phi; Number of Clusters",
-                                       'xbins':  61,
-                                       'xmin':  -3.25,
-                                       'xmax':   3.25,
-                                       'path': "EXPERT"}
-                                    ),
-                                    ( (pair + "_cell_secondary_weight_ref," + pair + "_cell_secondary_weight_test",),
-                                      {'type': 'TH2F',
-                                       'title': "Shared Cell Secondary Weight Comparison; w_2^{(CPU)}; w_2^{(GPU)}",
-                                       'xbins': 51,
-                                       'xmin':  -0.05,
-                                       'xmax':  0.505,
-                                       'ybins': 51,
-                                       'ymin':  -0.05,
-                                       'ymax':  0.505,
-                                       'path': "EXPERT"}
-                                    )
-                                  ]
-        if DoMoments:
-            for pair in PairsToPlot:
-                for mom, (prettynames, limits) in name_to_moment_map.items():
-                    for i in range(0, len(limits)):
-                      self.PlotsToDo += [ ( (pair + "_cluster_moments_" + mom + "_ref," + pair + "_cluster_moments_" + mom + "_test;" + pair + "_" + mom + "_versus_zoom_" + str(i + 1),),
-                                            {'type':  'TH2F',
-                                             'title': prettynames[0] + " (" + str(i+1) + "); CPU " + prettynames[1] + "; GPU " + prettynames[1],
-                                             'xbins': 63,
-                                             'xmin':  limits[i][0],
-                                             'xmax':  limits[i][1],
-                                             'ybins': 63,
-                                             'ymin':  limits[i][0],
-                                             'ymax':  limits[i][1],
-                                             'path':  "EXPERT"},
-                                          ),
-                                        ]
-                      self.PlotsToDo += [ ( (pair + "_cluster_moments_" + mom + "_ref," + pair + "_cluster_delta_moments_" + mom + "_rel_ref;" + pair + "_" + mom + "_error_zoom_" + str(i + 1),),
-                                            {'type':   'TH2F',
-                                             'title': prettynames[0] + " (" + str(i+1) + "); CPU " + prettynames[1] + "; #Delta " + prettynames[1] + " / #(){CPU " + prettynames[1] + "}",
-                                             'xbins':  63,
-                                             'xmin':   limits[i][0],
-                                             'xmax':   limits[i][1],
-                                             'ybins':  63,
-                                             'ymin':  -0.025,
-                                             'ymax':   0.025,
-                                             'path':   "EXPERT"}
-                                          ),
-                                        ]
-                      self.PlotsToDo += [ ( (pair + "_cluster_delta_moments_" + mom + "_rel_ref;" + pair + "_cluster_delta_moments_" + mom + "_rel_ref_zoom_0",),
-                                            {'type': 'TH1F',
-                                             'title': prettynames[0] + "; #Delta " + prettynames[1] + "; Number of Clusters",
-                                             'xbins': 51,
-                                             'xmin':  -1,
-                                             'xmax':  1,
-                                             'path': "EXPERT"}
-                                           ),
-                                        ]
-    def __call__(self, Plotter):
-        for plotdef in self.PlotsToDo:
-            Plotter.MonitoringTool.defineHistogram(*plotdef[0], **plotdef[1])
-        return Plotter
-
-#For pretty printing things in axes when it comes to moments:
-#<MOMENT_NAME>: <PLOT TITLE> <AXIS TITLE> <UNITS>
-name_to_moment_map =  {
-   #"time"                        :  (("time",                "time",               "[#mu s]"),[]),
-    "FIRST_PHI"                   :  (("firstPhi",            "firstPhi",            ""),[(-3.2, 3.2)]),
-    "FIRST_ETA"                   :  (("firstEta",            "firstEta",            ""),[(-10.1, 10.1)]),
-    "SECOND_R"                    :  (("secondR",             "secondR",             ""),[(0, 1.25e6)]),
-    "SECOND_LAMBDA"               :  (("secondLambda",        "secondLambda",        ""),[(0, 2.5e6)]),
-    "DELTA_PHI"                   :  (("deltaPhi",            "deltaPhi",            ""),[(-3.2, 3.2)]),
-    "DELTA_THETA"                 :  (("deltaTheta",          "deltaTheta",          ""),[(-1.6, 1.6)]),
-    "DELTA_ALPHA"                 :  (("deltaAlpha",          "deltaAlpha",          ""),[(-0.1, 1.6)]),
-    "CENTER_X"                    :  (("centerX",             "centerX",             ""),[(-4000, 4000)]),
-    "CENTER_Y"                    :  (("centerY",             "centerY",             ""),[(-4000, 4000)]),
-    "CENTER_Z"                    :  (("centerZ",             "centerZ",             ""),[(-7000, 7000)]),
-    "CENTER_MAG"                  :  (("centerMag",           "centerMag",           ""),[(1000, 7500)]),
-    "CENTER_LAMBDA"               :  (("centerLambda",        "centerLambda",        ""),[(0., 25000.),(0., 5000.)]),
-    "LATERAL"                     :  (("lateral",             "lateral",             ""),[(-0.05, 1.05)]),
-    "LONGITUDINAL"                :  (("longitudinal",        "longitudinal",        ""),[(-0.05, 1.05)]),
-    "ENG_FRAC_EM"                 :  (("engFracEM",           "engFracEM",           ""),[(-0.1, 1.1)]),
-    "ENG_FRAC_MAX"                :  (("engFracMax",          "engFracMax",          ""),[(-0.1, 1.1)]),
-    "ENG_FRAC_CORE"               :  (("engFracCore",         "engFracCore",         ""),[(-0.1, 1.1)]),
-    "FIRST_ENG_DENS"              :  (("firstEngDens",        "firstEngDens",        ""),[(-0.1, 5.1)]),
-    "SECOND_ENG_DENS"             :  (("secondEngDens",       "secondEngDens",       ""),[(-0.5, 50.5)]),
-    "ISOLATION"                   :  (("isolation",           "isolation",           ""),[(-0.05, 2.05)]),
-    "ENG_BAD_CELLS"               :  (("engBadCells",         "engBadCells",         ""),[(0., 100000.)]),
-    "N_BAD_CELLS"                 :  (("nBadCells",           "nBadCells",           ""),[(-0.5, 25.5)]),
-    "N_BAD_CELLS_CORR"            :  (("nBadCellsCorr",       "nBadCellsCorr",       ""),[(-0.5, 25.5)]),
-    "BAD_CELLS_CORR_E"            :  (("badCellsCorrE",       "badCellsCorrE",       ""),[(-0.1, 25000.)]),
-    "BADLARQ_FRAC"                :  (("badLArQFrac",         "badLArQFrac",         ""),[(-2500., 2500.)]),
-    "ENG_POS"                     :  (("engPos",              "engPos",              ""),[(-0.1, 250000.)]),
-    "SIGNIFICANCE"                :  (("significance",        "significance",        ""),[(-500., 500.)]),
-    "CELL_SIGNIFICANCE"           :  (("cellSignificance",    "cellSignificance",    ""),[(-0.1, 100.)]),
-    "CELL_SIG_SAMPLING"           :  (("cellSigSampling",     "cellSigSampling",     ""),[(-0.1, 30.)]),
-    "AVG_LAR_Q"                   :  (("avgLArQ",             "avgLArQ",             ""),[(-0.1, 70000.)]),
-    "AVG_TILE_Q"                  :  (("avgTileQ",            "avgTileQ",            ""),[(-0.1, 300.)]),
-   #"ENG_BAD_HV_CELLS"            :  (("engBadHVCells",       "engBadHVCells",       ""),[]),
-   #"N_BAD_HV_CELLS"              :  (("nBadHVCells",         "nBadHVCells",         ""),[]),
-    "PTD"                         :  (("PTD",                 "PTD",                 ""),[(-0.05, 1.05)]),
-    "MASS"                        :  (("mass",                "mass",                ""),[(0., 200000.), (0., 100.)]),
-   #"EM_PROBABILITY"              :  (("EMProbability",       "EMProbability",       ""),[]),
-   #"HAD_WEIGHT"                  :  (("hadWeight",           "hadWeight",           ""),[]),
-   #"OOC_WEIGHT"                  :  (("OOCweight",           "OOCweight",           ""),[]),
-   #"DM_WEIGHT"                   :  (("DMweight",            "DMweight",            ""),[]),
-   #"TILE_CONFIDENCE_LEVEL"       :  (("tileConfidenceLevel", "tileConfidenceLevel", ""),[]),
-    "SECOND_TIME"                 :  (("secondTime",          "secondTime",          ""),[(0., 1e7)])
-   #"number_of_cells"             :  (("numCells",            "numCells",            ""),[]),
-   #"VERTEX_FRACTION"             :  (("vertexFraction",      "vertexFraction",      ""),[]),
-   #"NVERTEX_FRACTION"            :  (("nVertexFraction",     "nVertexFraction",     ""),[]),
-   #"ETACALOFRAME"                :  (("etaCaloFrame",        "etaCaloFrame",        ""),[]),
-   #"PHICALOFRAME"                :  (("phiCaloFrame",        "phiCaloFrame",        ""),[]),
-   #"ETA1CALOFRAME"               :  (("eta1CaloFrame",       "eta1CaloFrame",       ""),[]),
-   #"PHI1CALOFRAME"               :  (("phi1CaloFrame",       "phi1CaloFrame",       ""),[]),
-   #"ETA2CALOFRAME"               :  (("eta2CaloFrame",       "eta2CaloFrame",       ""),[]),
-   #"PHI2CALOFRAME"               :  (("phi2CaloFrame",       "phi2CaloFrame",       ""),[]),
-   #"ENG_CALIB_TOT"               :  (("engCalibTot",         "engCalibTot",         ""),[]),
-   #"ENG_CALIB_OUT_L"             :  (("engCalibOutL",        "engCalibOutL",        ""),[]),
-   #"ENG_CALIB_OUT_M"             :  (("engCalibOutM",        "engCalibOutM",        ""),[]),
-   #"ENG_CALIB_OUT_T"             :  (("engCalibOutT",        "engCalibOutT",        ""),[]),
-   #"ENG_CALIB_DEAD_L"            :  (("engCalibDeadL",       "engCalibDeadL",       ""),[]),
-   #"ENG_CALIB_DEAD_M"            :  (("engCalibDeadM",       "engCalibDeadM",       ""),[]),
-   #"ENG_CALIB_DEAD_T"            :  (("engCalibDeadT",       "engCalibDeadT",       ""),[]),
-   #"ENG_CALIB_EMB0"              :  (("engCalibEMB0",        "engCalibEMB0",        ""),[]),
-   #"ENG_CALIB_EME0"              :  (("engCalibEME0",        "engCalibEME0",        ""),[]),
-   #"ENG_CALIB_TILEG3"            :  (("engCalibTileG3",      "engCalibTileG3",      ""),[]),
-   #"ENG_CALIB_DEAD_TOT"          :  (("engCalibDeadTot",     "engCalibDeadTot",     ""),[]),
-   #"ENG_CALIB_DEAD_EMB0"         :  (("engCalibDeadEMB0",    "engCalibDeadEMB0",    ""),[]),
-   #"ENG_CALIB_DEAD_TILE0"        :  (("engCalibDeadTile0",   "engCalibDeadTile0",   ""),[]),
-   #"ENG_CALIB_DEAD_TILEG3"       :  (("engCalibDeadTileG3",  "engCalibDeadTileG3",  ""),[]),
-   #"ENG_CALIB_DEAD_EME0"         :  (("engCalibDeadEME0",    "engCalibDeadEME0",    ""),[]),
-   #"ENG_CALIB_DEAD_HEC0"         :  (("engCalibDeadHEC0",    "engCalibDeadHEC0",    ""),[]),
-   #"ENG_CALIB_DEAD_FCAL"         :  (("engCalibDeadFCAL",    "engCalibDeadFCAL",    ""),[]),
-   #"ENG_CALIB_DEAD_LEAKAGE"      :  (("engCalibDeadLeakage", "engCalibDeadLeakage", ""),[]),
-   #"ENG_CALIB_DEAD_UNCLASS"      :  (("engCalibDeadUnclass", "engCalibDeadUnclass", ""),[]),
-   #"ENG_CALIB_FRAC_EM"           :  (("engCalibFracEM",      "engCalibFracEM",      ""),[]),
-   #"ENG_CALIB_FRAC_HAD"          :  (("engCalibFracHad",     "engCalibFracHad",     ""),[]),
-   #"ENG_CALIB_FRAC_REST"         :  (("engCalibFracRest"     "engCalibFracRest"     ""),[])
-}
diff --git a/Calorimeter/CaloRecGPU/test/test_CaloRecGPU_4_2_0.py b/Calorimeter/CaloRecGPU/test/test_CaloRecGPU_4_2_0.py
index ee0724071c81f61c5c2a0eaff08ecda924bc97ba..a4954686bccbcad2bea5e1a740c98f517edf8625 100755
--- a/Calorimeter/CaloRecGPU/test/test_CaloRecGPU_4_2_0.py
+++ b/Calorimeter/CaloRecGPU/test/test_CaloRecGPU_4_2_0.py
@@ -8,46 +8,40 @@
 # Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
 
 import CaloRecGPUTestingConfig
-from PlotterConfigurator import PlotterConfigurator
 from CaloRecGPUTestingChecker import check
 import sys
 
 def do_test(files):
+    #files does nothing for now, to be improved in the future to maybe allow multiple tests?
     
-    PlotterConfig = PlotterConfigurator(["CPU_growing", "GPU_growing", "CPU_splitting", "GPU_splitting"], ["growing", "splitting"])
     
-
-    flags, perfmon, numevents = CaloRecGPUTestingConfig.PrepareTest()
-    flags.CaloRecGPU.DoMonitoring = True
-    flags.CaloRecGPU.TopoClusterSeedCutsInAbsE = False
-    flags.CaloRecGPU.TopoClusterCellCutsInAbsE = False
-    flags.CaloRecGPU.TopoClusterNeighborCutsInAbsE = False
-    flags.CaloRecGPU.SplitterUseNegativeClusters = False
-
-    flags.CaloRecGPU.TwoGaussianNoise = False
-
-    flags.CaloRecGPU.TopoClusterSNRSeedThreshold = 4.0
-    flags.CaloRecGPU.TopoClusterSNRGrowThreshold = 2.0
-    flags.CaloRecGPU.TopoClusterSNRCellThreshold = 0.0
-
-    flags.CaloRecGPU.ClusterSize = "Topo_420"
+    flags, testopts = CaloRecGPUTestingConfig.PrepareTest()
+    
+    flags.CaloRecGPU.ActiveConfig.SeedThreshold = 4.0
+    flags.CaloRecGPU.ActiveConfig.GrowThreshold = 2.0
+    flags.CaloRecGPU.ActiveConfig.TermThreshold = 0.0
+        
+    flags.CaloRecGPU.ActiveConfig.UseAbsSeedThreshold = False
+    flags.CaloRecGPU.ActiveConfig.UseAbsGrowThreshold = False
+    flags.CaloRecGPU.ActiveConfig.UseAbsTermThreshold = False
+    
+    flags.CaloRecGPU.ActiveConfig.SplittingUseNegativeClusters = False
+    
+    flags.CaloRecGPU.ActiveConfig.UseOriginalCriteria = False
+    flags.CaloRecGPU.ActiveConfig.doTwoGaussianNoise = False
     
-    flags.CaloRecGPU.ClustersOutputName="CaloCalTopoClustersNew"
     flags.lock()
-
-    topoAcc = CaloRecGPUTestingConfig.MinimalSetup(flags,perfmon)
-
-    topoAcc.merge(CaloRecGPUTestingConfig.FullTestConfiguration(flags, TestGrow = True, TestSplit = True, PlotterConfigurator = PlotterConfig))
-
-
-    topoAcc.run(100)
     
-
+    testopts.TestGrow = True
+    testopts.TestSplit = True
+    testopts.NumEvents = 100
+    
+    PlotterConfig = CaloRecGPUTestingConfig.PlotterConfigurator(["CPU_growing", "GPU_growing", "CPU_splitting", "GPU_splitting"], ["growing", "splitting"])
+        
+    CaloRecGPUTestingConfig.RunFullTestConfiguration(flags, testopts, PlotterConfigurator = PlotterConfig)
+    
 if __name__=="__main__":
     do_test(["/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/TrigInDetValidation/samples/mc15_13TeV.410000.PowhegPythiaEvtGen_P2012_ttbar_hdamp172p5_nonallhad.recon.RDO.e3698_s2608_s2183_r7195/RDO.06752780._000001.pool.root.1",
              "/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/TrigInDetValidation/samples/mc15_13TeV.410000.PowhegPythiaEvtGen_P2012_ttbar_hdamp172p5_nonallhad.recon.RDO.e3698_s2608_s2183_r7195/RDO.06752780._000002.pool.root.1",
              "/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/TrigInDetValidation/samples/mc15_13TeV.410000.PowhegPythiaEvtGen_P2012_ttbar_hdamp172p5_nonallhad.recon.RDO.e3698_s2608_s2183_r7195/RDO.06752780._000003.pool.root.1" ])
-#    do_test(["/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/TrigEgammaValidation/valid3.147917.Pythia8_AU2CT10_jetjet_JZ7W.recon.RDO.e3099_s2578_r6596_tid05293007_00/RDO.05293007._000001.pool.root.1"],
-#             "jets")
     sys.exit(check())
-
diff --git a/Calorimeter/CaloRecGPU/test/test_CaloRecGPU_4_2_0_abs.py b/Calorimeter/CaloRecGPU/test/test_CaloRecGPU_4_2_0_abs.py
index 04ca3e704dbfb3be9f88bb3e439ce5368a0ae1be..9c2b1fd2cc61767ba82271f99d3dd81057043193 100755
--- a/Calorimeter/CaloRecGPU/test/test_CaloRecGPU_4_2_0_abs.py
+++ b/Calorimeter/CaloRecGPU/test/test_CaloRecGPU_4_2_0_abs.py
@@ -8,46 +8,41 @@
 # Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
 
 import CaloRecGPUTestingConfig
-from PlotterConfigurator import PlotterConfigurator
 from CaloRecGPUTestingChecker import check
 import sys
 
-
 def do_test(files):
+    #files does nothing for now, to be improved in the future to maybe allow multiple tests?
+    
+    
+    flags, testopts = CaloRecGPUTestingConfig.PrepareTest()
+    
+    flags.CaloRecGPU.ActiveConfig.SeedThreshold = 4.0
+    flags.CaloRecGPU.ActiveConfig.GrowThreshold = 2.0
+    flags.CaloRecGPU.ActiveConfig.TermThreshold = 0.0
+        
+    flags.CaloRecGPU.ActiveConfig.UseAbsSeedThreshold = True
+    flags.CaloRecGPU.ActiveConfig.UseAbsGrowThreshold = True
+    flags.CaloRecGPU.ActiveConfig.UseAbsTermThreshold = True
+    
+    flags.CaloRecGPU.ActiveConfig.SplittingUseNegativeClusters = True
+    
+    flags.CaloRecGPU.ActiveConfig.UseOriginalCriteria = False
+    flags.CaloRecGPU.ActiveConfig.doTwoGaussianNoise = False
     
-    PlotterConfig = PlotterConfigurator(["CPU_growing", "GPU_growing", "CPU_splitting", "GPU_splitting"], ["growing", "splitting"])
-
-    flags, perfmon, numevents = CaloRecGPUTestingConfig.PrepareTest()
-    flags.CaloRecGPU.DoMonitoring = True
-    flags.CaloRecGPU.TopoClusterSeedCutsInAbsE = True
-    flags.CaloRecGPU.TopoClusterCellCutsInAbsE = True
-    flags.CaloRecGPU.TopoClusterNeighborCutsInAbsE = True
-    flags.CaloRecGPU.SplitterUseNegativeClusters = True
-
-    flags.CaloRecGPU.TwoGaussianNoise = False
-
-    flags.CaloRecGPU.TopoClusterSNRSeedThreshold = 4.0
-    flags.CaloRecGPU.TopoClusterSNRGrowThreshold = 2.0
-    flags.CaloRecGPU.TopoClusterSNRCellThreshold = 0.0
-
-    flags.CaloRecGPU.ClusterSize = "Topo_420"
-
-    flags.CaloRecGPU.ClustersOutputName="CaloCalTopoClustersNew"
     flags.lock()
-
-    topoAcc = CaloRecGPUTestingConfig.MinimalSetup(flags,perfmon)
-
-    topoAcc.merge(CaloRecGPUTestingConfig.FullTestConfiguration(flags, TestGrow = True, TestSplit = True, PlotterConfigurator = PlotterConfig))
-
-
-    topoAcc.run(100)
     
-
+    testopts.TestGrow = True
+    testopts.TestSplit = True
+    testopts.NumEvents = 100
+    
+    PlotterConfig = CaloRecGPUTestingConfig.PlotterConfigurator(["CPU_growing", "GPU_growing", "CPU_splitting", "GPU_splitting"], ["growing", "splitting"])
+        
+    CaloRecGPUTestingConfig.RunFullTestConfiguration(flags, testopts, PlotterConfigurator = PlotterConfig)
+    
 if __name__=="__main__":
     do_test(["/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/TrigInDetValidation/samples/mc15_13TeV.410000.PowhegPythiaEvtGen_P2012_ttbar_hdamp172p5_nonallhad.recon.RDO.e3698_s2608_s2183_r7195/RDO.06752780._000001.pool.root.1",
              "/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/TrigInDetValidation/samples/mc15_13TeV.410000.PowhegPythiaEvtGen_P2012_ttbar_hdamp172p5_nonallhad.recon.RDO.e3698_s2608_s2183_r7195/RDO.06752780._000002.pool.root.1",
              "/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/TrigInDetValidation/samples/mc15_13TeV.410000.PowhegPythiaEvtGen_P2012_ttbar_hdamp172p5_nonallhad.recon.RDO.e3698_s2608_s2183_r7195/RDO.06752780._000003.pool.root.1" ])
-#    do_test(["/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/TrigEgammaValidation/valid3.147917.Pythia8_AU2CT10_jetjet_JZ7W.recon.RDO.e3099_s2578_r6596_tid05293007_00/RDO.05293007._000001.pool.root.1"],
-#             "jets")
     sys.exit(check())
 
diff --git a/Calorimeter/CaloRecGPU/test/test_CaloRecGPU_4_2_2.py b/Calorimeter/CaloRecGPU/test/test_CaloRecGPU_4_2_2.py
index ad040263a472625d42209c9d6f9a7d062b9b7d80..aad62deea4d195b0df658e37566ca1617eb819a6 100755
--- a/Calorimeter/CaloRecGPU/test/test_CaloRecGPU_4_2_2.py
+++ b/Calorimeter/CaloRecGPU/test/test_CaloRecGPU_4_2_2.py
@@ -9,45 +9,40 @@
 
 import CaloRecGPUTestingConfig
 from CaloRecGPUTestingChecker import check
-from PlotterConfigurator import PlotterConfigurator
 import sys
 
 def do_test(files):
-
-    PlotterConfig = PlotterConfigurator(["CPU_growing", "GPU_growing", "CPU_splitting", "GPU_splitting"], ["growing", "splitting"])
-
-
-    flags, perfmon, numevents = CaloRecGPUTestingConfig.PrepareTest()
-    flags.CaloRecGPU.DoMonitoring = True
-    flags.CaloRecGPU.TopoClusterSeedCutsInAbsE = False
-    flags.CaloRecGPU.TopoClusterCellCutsInAbsE = False
-    flags.CaloRecGPU.TopoClusterNeighborCutsInAbsE = False
-    flags.CaloRecGPU.SplitterUseNegativeClusters = False
-
-    flags.CaloRecGPU.TwoGaussianNoise = False
-
-    flags.CaloRecGPU.TopoClusterSNRSeedThreshold = 4.0
-    flags.CaloRecGPU.TopoClusterSNRGrowThreshold = 2.0
-    flags.CaloRecGPU.TopoClusterSNRCellThreshold = 2.0
-
-    flags.CaloRecGPU.ClusterSize = "Topo_420" #no 4 2 2 yet?
-
-    flags.CaloRecGPU.ClustersOutputName="CaloCalTopoClustersNew"
+    #files does nothing for now, to be improved in the future to maybe allow multiple tests?
+    
+    
+    flags, testopts = CaloRecGPUTestingConfig.PrepareTest()
+    
+    flags.CaloRecGPU.ActiveConfig.SeedThreshold = 4.0
+    flags.CaloRecGPU.ActiveConfig.GrowThreshold = 2.0
+    flags.CaloRecGPU.ActiveConfig.TermThreshold = 2.0
+        
+    flags.CaloRecGPU.ActiveConfig.UseAbsSeedThreshold = False
+    flags.CaloRecGPU.ActiveConfig.UseAbsGrowThreshold = False
+    flags.CaloRecGPU.ActiveConfig.UseAbsTermThreshold = False
+    
+    flags.CaloRecGPU.ActiveConfig.SplittingUseNegativeClusters = False
+    
+    flags.CaloRecGPU.ActiveConfig.UseOriginalCriteria = False
+    flags.CaloRecGPU.ActiveConfig.doTwoGaussianNoise = False
+    
     flags.lock()
-
-    topoAcc = CaloRecGPUTestingConfig.MinimalSetup(flags,perfmon)
-
-    topoAcc.merge(CaloRecGPUTestingConfig.FullTestConfiguration(flags, TestGrow = True, TestSplit = True, PlotterConfigurator = PlotterConfig))
-
-
-    topoAcc.run(100)
-
-
+    
+    testopts.TestGrow = True
+    testopts.TestSplit = True
+    testopts.NumEvents = 100
+    
+    PlotterConfig = CaloRecGPUTestingConfig.PlotterConfigurator(["CPU_growing", "GPU_growing", "CPU_splitting", "GPU_splitting"], ["growing", "splitting"])
+        
+    CaloRecGPUTestingConfig.RunFullTestConfiguration(flags, testopts, PlotterConfigurator = PlotterConfig)
+    
 if __name__=="__main__":
     do_test(["/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/TrigInDetValidation/samples/mc15_13TeV.410000.PowhegPythiaEvtGen_P2012_ttbar_hdamp172p5_nonallhad.recon.RDO.e3698_s2608_s2183_r7195/RDO.06752780._000001.pool.root.1",
              "/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/TrigInDetValidation/samples/mc15_13TeV.410000.PowhegPythiaEvtGen_P2012_ttbar_hdamp172p5_nonallhad.recon.RDO.e3698_s2608_s2183_r7195/RDO.06752780._000002.pool.root.1",
              "/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/TrigInDetValidation/samples/mc15_13TeV.410000.PowhegPythiaEvtGen_P2012_ttbar_hdamp172p5_nonallhad.recon.RDO.e3698_s2608_s2183_r7195/RDO.06752780._000003.pool.root.1" ])
-#    do_test(["/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/TrigEgammaValidation/valid3.147917.Pythia8_AU2CT10_jetjet_JZ7W.recon.RDO.e3099_s2578_r6596_tid05293007_00/RDO.05293007._000001.pool.root.1"],
-#             "jets")
     sys.exit(check())
 
diff --git a/Calorimeter/CaloRecGPU/test/test_CaloRecGPU_6_3_3.py b/Calorimeter/CaloRecGPU/test/test_CaloRecGPU_6_3_3.py
index 205e3aa1b87458c4c1de817d02df56719cec831e..0a289171d7e6d00d04d1fdee4c1a5582009c56c2 100755
--- a/Calorimeter/CaloRecGPU/test/test_CaloRecGPU_6_3_3.py
+++ b/Calorimeter/CaloRecGPU/test/test_CaloRecGPU_6_3_3.py
@@ -9,44 +9,40 @@
 
 import CaloRecGPUTestingConfig
 from CaloRecGPUTestingChecker import check
-from PlotterConfigurator import PlotterConfigurator
 import sys
 
 def do_test(files):
+    #files does nothing for now, to be improved in the future to maybe allow multiple tests?
     
-    PlotterConfig = PlotterConfigurator(["CPU_growing", "GPU_growing", "CPU_splitting", "GPU_splitting"], ["growing", "splitting"])
     
-
-    flags, perfmon, numevents = CaloRecGPUTestingConfig.PrepareTest()
-    flags.CaloRecGPU.DoMonitoring = True
-    flags.CaloRecGPU.TopoClusterSeedCutsInAbsE = False
-    flags.CaloRecGPU.TopoClusterCellCutsInAbsE = False
-    flags.CaloRecGPU.TopoClusterNeighborCutsInAbsE = False
-    flags.CaloRecGPU.SplitterUseNegativeClusters = False
-
-    flags.CaloRecGPU.TwoGaussianNoise = False
-
-    flags.CaloRecGPU.TopoClusterSNRSeedThreshold = 6.0
-    flags.CaloRecGPU.TopoClusterSNRGrowThreshold = 3.0
-    flags.CaloRecGPU.TopoClusterSNRCellThreshold = 3.0
-
-    flags.CaloRecGPU.ClusterSize = "Topo_633"
-
-    flags.CaloRecGPU.ClustersOutputName="CaloCalTopoClustersNew"
+    flags, testopts = CaloRecGPUTestingConfig.PrepareTest()
+    
+    flags.CaloRecGPU.ActiveConfig.SeedThreshold = 6.0
+    flags.CaloRecGPU.ActiveConfig.GrowThreshold = 3.0
+    flags.CaloRecGPU.ActiveConfig.TermThreshold = 3.0
+        
+    flags.CaloRecGPU.ActiveConfig.UseAbsSeedThreshold = False
+    flags.CaloRecGPU.ActiveConfig.UseAbsGrowThreshold = False
+    flags.CaloRecGPU.ActiveConfig.UseAbsTermThreshold = False
+    
+    flags.CaloRecGPU.ActiveConfig.SplittingUseNegativeClusters = False
+    
+    flags.CaloRecGPU.ActiveConfig.UseOriginalCriteria = False
+    flags.CaloRecGPU.ActiveConfig.doTwoGaussianNoise = False
+    
     flags.lock()
-
-    topoAcc = CaloRecGPUTestingConfig.MinimalSetup(flags,perfmon)
-
-    topoAcc.merge(CaloRecGPUTestingConfig.FullTestConfiguration(flags, TestGrow = True, TestSplit = True, PlotterConfigurator = PlotterConfig))
-
-
-    topoAcc.run(100)
+    
+    testopts.TestGrow = True
+    testopts.TestSplit = True
+    testopts.NumEvents = 100
+    
+    PlotterConfig = CaloRecGPUTestingConfig.PlotterConfigurator(["CPU_growing", "GPU_growing", "CPU_splitting", "GPU_splitting"], ["growing", "splitting"])
+        
+    CaloRecGPUTestingConfig.RunFullTestConfiguration(flags, testopts, PlotterConfigurator = PlotterConfig)
     
 if __name__=="__main__":
     do_test(["/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/TrigInDetValidation/samples/mc15_13TeV.410000.PowhegPythiaEvtGen_P2012_ttbar_hdamp172p5_nonallhad.recon.RDO.e3698_s2608_s2183_r7195/RDO.06752780._000001.pool.root.1",
              "/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/TrigInDetValidation/samples/mc15_13TeV.410000.PowhegPythiaEvtGen_P2012_ttbar_hdamp172p5_nonallhad.recon.RDO.e3698_s2608_s2183_r7195/RDO.06752780._000002.pool.root.1",
              "/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/TrigInDetValidation/samples/mc15_13TeV.410000.PowhegPythiaEvtGen_P2012_ttbar_hdamp172p5_nonallhad.recon.RDO.e3698_s2608_s2183_r7195/RDO.06752780._000003.pool.root.1" ])
-#    do_test(["/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/TrigEgammaValidation/valid3.147917.Pythia8_AU2CT10_jetjet_JZ7W.recon.RDO.e3099_s2578_r6596_tid05293007_00/RDO.05293007._000001.pool.root.1"],
-#             "jets")
     sys.exit(check())
 
diff --git a/Reconstruction/tauRec/python/TauToolHolder.py b/Reconstruction/tauRec/python/TauToolHolder.py
index a714ce162027721ca298c95bd010a8470c7977bd..63cd7be38f4b497795df60f00a67b2bdae3eee09 100644
--- a/Reconstruction/tauRec/python/TauToolHolder.py
+++ b/Reconstruction/tauRec/python/TauToolHolder.py
@@ -524,6 +524,7 @@ def TauCaloTopoClusterMakerCfg(flags):
     TopoClusterForTaus.NeighborThresholdOnEorAbsEinSigma = 2.0
     TopoClusterForTaus.SeedThresholdOnEorAbsEinSigma     = 4.0
     TopoClusterForTaus.SeedCutsInAbsE                    = True
+    TopoClusterForTaus.ClusterCutsInAbsEt                = True
     TopoClusterForTaus.ClusterEtorAbsEtCut               = 0.5*GeV # 0.0*MeV in standard CaloCalTopoCluster JobOptions!
     TopoClusterForTaus.TwoGaussianNoise                  = flags.Calo.TopoCluster.doTwoGaussianNoise
     # timing cut on seed cell to suppress out-of-time pileup
diff --git a/TileCalorimeter/TileMonitoring/python/TileTopoClusterConfig.py b/TileCalorimeter/TileMonitoring/python/TileTopoClusterConfig.py
index 1d33f91e59bf0550db618177f9c86b2c4257a996..6d2cb998f97a7e2ed5b35993c5cfd223b6ce294a 100644
--- a/TileCalorimeter/TileMonitoring/python/TileTopoClusterConfig.py
+++ b/TileCalorimeter/TileMonitoring/python/TileTopoClusterConfig.py
@@ -43,6 +43,7 @@ def TileTopoClusterCfg(flags, **kwargs):
     topoClusterMaker.SeedThresholdOnEorAbsEinSigma = 4.0
 
     topoClusterMaker.SeedCutsInAbsE = True
+    topoClusterMaker.ClusterCutsInAbsEt = True
     topoClusterMaker.ClusterEtorAbsEtCut = 0.0 * MeV
     topoClusterMaker.TwoGaussianNoise = flags.Calo.TopoCluster.doTwoGaussianNoise
 
diff --git a/Trigger/TrigAlgorithms/TrigCaloRec/python/TrigCaloRecConfig.py b/Trigger/TrigAlgorithms/TrigCaloRec/python/TrigCaloRecConfig.py
index 3070a0307e2b01cc8ae20f025853257334b5eb22..0008ee4c329dbb641e270ca7a2c1e7b5b4de4e8f 100755
--- a/Trigger/TrigAlgorithms/TrigCaloRec/python/TrigCaloRecConfig.py
+++ b/Trigger/TrigAlgorithms/TrigCaloRec/python/TrigCaloRecConfig.py
@@ -228,9 +228,6 @@ def hltTopoClusterMakerCfg(flags, name, clustersKey="HLT_TopoCaloClustersFS",
 
     topoMaker = acc.popToolsAndMerge(CaloTopoClusterToolCfg(flags, cellsname=cells))
     topoMaker.RestrictPSNeighbors = False
-    # TODO - Don't use hasFlag here, use another concrete flag instead
-    if flags.hasFlag("CaloRecGPU.ActiveConfig"):
-       topoMaker.UseGPUCriteria=flags.CaloRecGPU.ActiveConfig.UseOriginalCriteria
     listClusterCorrectionTools = []
     if doLC :
        from CaloTools.CaloNoiseCondAlgConfig import CaloNoiseCondAlgCfg
@@ -351,11 +348,6 @@ TrigEgammaKeys = getTrigEgammaKeys()
 TrigEgammaKeys_LRT = getTrigEgammaKeys(name = '_LRT')
 TrigEgammaKeys_HI = getTrigEgammaKeys(ion = True)
 
-def prepareFlagsGPUHLT(flags):
-    flags.LAr.doHVCorr=True
-    # NOTE: "HLT" flag subdomain defaults moved to CaloRecGPUFlags
-    return
-
 @AccumulatorCache
 def hltCaloTopoClusteringCfg(
     flags, namePrefix=None,nameSuffix=None, CellsName=None, monitorCells=False, roisKey="UNSPECIFIED",clustersKey=None, doLCFS=False, doTau = False):
@@ -371,13 +363,32 @@ def hltCaloTopoClusteringCfg(
     acc.merge(
         hltCaloCellMakerCfg(flags, namePrefix + "HLTCaloCellMaker"+nameSuffix, roisKey=roisKey, CellsName=CellsName, monitorCells=monitorCells, doTau = doTau)
     )
+    
+    clustermakername = namePrefix + "HLTCaloClusterMaker"+nameSuffix
+    
     # TODO - Don't use hasFlag here, use another concrete flag instead
-    if flags.hasFlag("CaloRecGPU.ActiveConfig") and (nameSuffix == "FS") and (not doTau):
-       from CaloRecGPU.CaloRecGPUConfig import HybridClusterProcessorCfg
-       hyb = HybridClusterProcessorCfg(flags, namePrefix + "HLTCaloClusterMaker"+nameSuffix)
-       acc.merge(hyb)
+    if flags.hasFlag("CaloRecGPU.GlobalFlags.UseCaloRecGPU") and flags.CaloRecGPU.GlobalFlags.UseCaloRecGPU and not doTau and "FS" in clustermakername:
+      flags = flags.cloneAndReplace("CaloRecGPU.ActiveConfig", "Trigger.CaloRecGPU.Default", True)
+      from CaloRecGPU.CaloRecGPUConfig import GPUCaloTopoClusterCfg
+      
+      
+      GPUKernelSvc = CompFactory.GPUKernelSizeOptimizerSvc()
+      acc.addService(GPUKernelSvc)
+      
+      monitorCells = "FS" in clustermakername
+      
+      gpuhyb = GPUCaloTopoClusterCfg(flags,
+                                     True,
+                                     CellsName,
+                                     clustersname = recordable(clusters),
+                                     name = clustermakername,
+                                     MonitorTool = trigCaloClusterMakerMonTool(flags, monitorCells),
+                                     MonitorCells = monitorCells,
+                                     ReallyUseGPUTools = not flags.CaloRecGPU.GlobalFlags.UseCPUToolsInstead)
+                                     
+      acc.merge(gpuhyb)
     else : 
-       calt=hltTopoClusterMakerCfg(flags, namePrefix + "HLTCaloClusterMaker"+nameSuffix,cellsKey=CellsName, clustersKey=clusters, doLC=doTau)
+       calt=hltTopoClusterMakerCfg(flags, clustermakername, cellsKey=CellsName, clustersKey=clusters, doLC=doTau)
        acc.merge(calt)
     if doLCFS:
         acc.merge( hltCaloTopoClusterCalibratorCfg(