From a1f830c0ad7dcc30bd5c82a52e940a0f9aeb7932 Mon Sep 17 00:00:00 2001
From: Peter Onyisi <ponyisi@utexas.edu>
Date: Mon, 14 Oct 2019 14:09:42 +0000
Subject: [PATCH] Tuning of PixelAthClusterMonTool (ATLASRECTS-5154)

---
 .../PixelMonitoring/PixelAthMonitoringBase.h  |  19 ++-
 .../python/PixelAthClusterMonToolCfg.py       |  83 +++++------
 .../python/PixelAthErrorMonToolCfg.py         |   2 +-
 .../python/PixelAthHitMonToolCfg.py           |   2 +-
 .../python/PixelAthMonitoringBase.py          |  48 ++++---
 .../src/PixelAthClusterMonTool.cxx            | 131 +++++++++++-------
 .../src/PixelAthMonitoringBase.cxx            |  72 ++++++++--
 7 files changed, 233 insertions(+), 124 deletions(-)

diff --git a/InnerDetector/InDetMonitoring/PixelMonitoring/PixelMonitoring/PixelAthMonitoringBase.h b/InnerDetector/InDetMonitoring/PixelMonitoring/PixelMonitoring/PixelAthMonitoringBase.h
index 355aaa23d48..24188edf9b4 100644
--- a/InnerDetector/InDetMonitoring/PixelMonitoring/PixelMonitoring/PixelAthMonitoringBase.h
+++ b/InnerDetector/InDetMonitoring/PixelMonitoring/PixelMonitoring/PixelAthMonitoringBase.h
@@ -42,7 +42,7 @@ class PixelAthMonitoringBase : public virtual AthMonitorAlgorithm {
 
  public:
 
-  StatusCode fill2DProfLayer( std::string prof2Dname, Identifier& id, const PixelID* pid, float weight=1.0, bool copy2DFEval=false ) const;
+  StatusCode fill2DProfLayer( const std::string& prof2Dname, const std::string& layer, Identifier& id, const PixelID* pid, float weight=1.0, bool copy2DFEval=false ) const;
   StatusCode fill1DProfLumiLayers( std::string prof1Dname, int lb, float* weights ) const;
   StatusCode fill1DProfLayers( std::string name, float* values ) const;
   StatusCode fillPP0Histos( std::string name, int(&D_A)[PixMon::kNumModulesDisk][PixMon::kNumLayersDisk], int(&D_C)[PixMon::kNumModulesDisk][PixMon::kNumLayersDisk], int(&B0)[PixMon::kNumStavesL0][PixMon::kNumModulesBarrel], int(&B1)[PixMon::kNumStavesL1][PixMon::kNumModulesBarrel], int(&B2)[PixMon::kNumStavesL2][PixMon::kNumModulesBarrel], int(&IBL)[PixMon::kNumStavesIBL][PixMon::kNumFEsIBL] ) const;
@@ -55,6 +55,23 @@ class PixelAthMonitoringBase : public virtual AthMonitorAlgorithm {
   bool isClusterOnTrack(Identifier id, std::vector<std::pair<Identifier, double> > const &ClusterIDs) const;
   bool isClusterOnTrack(Identifier id, std::vector<std::pair<Identifier, double> > const &ClusterIDs, double& cosalpha) const;
 
+  /// helper class to accumulate points to fill a 2D plot with
+  struct VecAccumulator2DMap {
+    std::unordered_map<int, std::vector<int>> m_pm;
+    std::unordered_map<int, std::vector<int>> m_em;
+    std::unordered_map<int, std::vector<float>> m_val;
+    bool m_copy2DFEval;
+    std::string m_prof2Dname;
+
+    VecAccumulator2DMap( const std::string& prof2Dname, bool copy2DFEval = false ) 
+      : m_copy2DFEval(copy2DFEval)
+      , m_prof2Dname(prof2Dname) {}
+    
+    void add( const int layer, const Identifier& id,
+	      const PixelID* pid, float value=1.0 );
+  };
+  void fill2DProfLayerAccum( const VecAccumulator2DMap& accumulator ) const;
+  
 };
 
 #endif
diff --git a/InnerDetector/InDetMonitoring/PixelMonitoring/python/PixelAthClusterMonToolCfg.py b/InnerDetector/InDetMonitoring/PixelMonitoring/python/PixelAthClusterMonToolCfg.py
index d79c5647b60..b3d6b141fdb 100644
--- a/InnerDetector/InDetMonitoring/PixelMonitoring/python/PixelAthClusterMonToolCfg.py
+++ b/InnerDetector/InDetMonitoring/PixelMonitoring/python/PixelAthClusterMonToolCfg.py
@@ -7,7 +7,7 @@
 @brief Configuration of Pixel Monitoring Clusters, Tracks and Status Histograms for Run 3
 '''
 
-from PixelMonitoring.PixelAthMonitoringBase import define2DProfLayers, definePP0Histos
+from PixelMonitoring.PixelAthMonitoringBase import define2DProfHist, definePP0Histos
 from PixelMonitoring.PixelAthMonitoringBase import define1DLayers
 from PixelMonitoring.PixelAthMonitoringBase import define1DProfLumiLayers
 from PixelMonitoring.PixelAthMonitoringBase import layers, totcuts, xbinsem, xminsem, lumibinsx
@@ -20,6 +20,7 @@ runtext = ' (Run ' + str(runNumber) + ')'
 def PixelAthClusterMonToolCfg(helper, alg, **kwargs):
 
     doOnline  = kwargs.get('doOnline',  False)
+    doLumiBlock = kwargs.get('doLumiBlock', False)
 
 ### begin status histograms
 
@@ -28,15 +29,14 @@ def PixelAthClusterMonToolCfg(helper, alg, **kwargs):
 
     histoGroupName = 'Map_Of_Modules_Status' 
     title = 'Modules Status (0=Active+Good 1=Active+Bad 2=Inactive)'
-    define2DProfLayers(helper, alg, histoGroupName, title, path, type='TProfile2D')
+    define2DProfHist(helper, alg, histoGroupName, title, path, type='TProfile2D')
 
-    histoGroupName = 'Map_Of_Modules_Status_Mon'
     title = 'Modules Status Reset (0=Active+Good 1=Active+Bad 2=Inactive)'
-    define2DProfLayers(helper, alg, histoGroupName, title, path, type='TProfile2D', zmin=0, zmax=2, opt='kLBNHistoryDepth=2')
+    define2DProfHist(helper, alg, histoGroupName, title, path, type='TProfile2D', zmin=0, zmax=2, opt='kLBNHistoryDepth=2', histname='Map_Of_Modules_Status_Mon')
 
-    histoGroupName = 'Map_Of_Modules_Status_LB' 
-    title = 'Modules Status (0=Active+Good 1=Active+Bad 2=Inactive)'
-    define2DProfLayers(helper, alg, histoGroupName, title, pathLowStat, type='TProfile2D', lifecycle='lowStat')
+    if doLumiBlock:
+        title = 'Modules Status (0=Active+Good 1=Active+Bad 2=Inactive)'
+        define2DProfHist(helper, alg, histoGroupName, title, pathLowStat, type='TProfile2D', lifecycle='lowStat', histname='Map_Of_Modules_Status_LB')
 
     histoGroupName = 'BadModules_per_lumi'
     title          = 'Number of bad modules (bad+active) per event per LB'
@@ -55,15 +55,15 @@ def PixelAthClusterMonToolCfg(helper, alg, **kwargs):
 
     histoGroupName = 'TSOS_Measurement' 
     title = 'TSOS of type Measurement'
-    define2DProfLayers(helper, alg, histoGroupName, title, path, type='TH2F')
+    define2DProfHist(helper, alg, histoGroupName, title, path, type='TH2F')
 
     histoGroupName = 'TSOS_Hole' 
     title = 'TSOS of type Hole'
-    define2DProfLayers(helper, alg, histoGroupName, title, path, type='TH2F')
+    define2DProfHist(helper, alg, histoGroupName, title, path, type='TH2F')
 
     histoGroupName = 'TSOS_Outlier' 
     title = 'TSOS of type Outlier'
-    define2DProfLayers(helper, alg, histoGroupName, title, path, type='TH2F')
+    define2DProfHist(helper, alg, histoGroupName, title, path, type='TH2F')
 
     histoGroupName = 'HitEff_all'
     title          = 'hit efficiency'
@@ -72,44 +72,39 @@ def PixelAthClusterMonToolCfg(helper, alg, **kwargs):
 
     histoGroupName = 'HolesRatio' 
     title = 'Holes per track'
-    define2DProfLayers(helper, alg, histoGroupName, title, path, type='TProfile2D')
+    define2DProfHist(helper, alg, histoGroupName, title, path, type='TProfile2D')
 
     histoGroupName = 'MissHitsRatio' 
     title = 'Hole+Outlier per track'
-    define2DProfLayers(helper, alg, histoGroupName, title, path, type='TProfile2D')
-
+    define2DProfHist(helper, alg, histoGroupName, title, path, type='TProfile2D')
 
+    trackGroup = helper.addGroup(alg, 'Track')
     varName = 'res_phi'
     title = fullDressTitle('Pixel Residual LocX(phi)', False, ';Residual LocX(phi)',';# measurements on track')
-    trackGroup = helper.addGroup(alg, 'Track_res_phi')
     varName += ';Track_res_phi'
     trackGroup.defineHistogram(varName,
                                 type='TH1F', path=path, title=title,
                                 xbins=100, xmin=-0.1, xmax=0.1)
     varName = 'res_eta'
     title = fullDressTitle('Pixel Residual LocY(eta)', False, ';Residual LocY(eta)',';# measurements on track')
-    trackGroup = helper.addGroup(alg, 'Track_res_eta')
     varName += ';Track_res_eta'
     trackGroup.defineHistogram(varName,
                                 type='TH1F', path=path, title=title,
                                 xbins=100, xmin=-0.3, xmax=0.3)
     varName = 'pull_phi'
     title = fullDressTitle('Pixel Pull LocX(phi)', False, ';Pull LocX(phi)',';# measurements on track')
-    trackGroup = helper.addGroup(alg, 'Track_pulls_phi')
     varName += ';Track_pulls_phi'
     trackGroup.defineHistogram(varName,
                                 type='TH1F', path=path, title=title,
                                 xbins=100, xmin=-1.2, xmax=1.2)
     varName = 'pull_eta'
     title = fullDressTitle('Pixel Pull LocY(eta)', False, ';Pull LocY(eta)',';# measurements on track')
-    trackGroup = helper.addGroup(alg, 'Track_pulls_eta')
     varName += ';Track_pulls_eta'
     trackGroup.defineHistogram(varName,
                                 type='TH1F', path=path, title=title,
                                 xbins=100, xmin=-2.0, xmax=2.0)
     varName = 'fit_chi2byndf'
     title = fullDressTitle('chi2/ndf of track', False, ';#chi^{2}/DoF',';# of tracks')
-    trackGroup = helper.addGroup(alg, 'Track_chi2byndf')
     varName += ';Track_chi2byndf'
     trackGroup.defineHistogram(varName,
                                 type='TH1F', path=path, title=title,
@@ -117,7 +112,6 @@ def PixelAthClusterMonToolCfg(helper, alg, **kwargs):
 
     varName = 'pixclusmontool_lb,ntrks_per_event'
     title = fullDressTitle('Number of tracks per event per LB', False, ';lumi block', ';tracks/event')
-    trackGroup = helper.addGroup(alg, 'tracksPerEvt_per_lumi')
     varName += ';tracksPerEvt_per_lumi'
     trackGroup.defineHistogram(varName,
                                 type='TProfile', path=path, title=title,
@@ -125,7 +119,6 @@ def PixelAthClusterMonToolCfg(helper, alg, **kwargs):
 
     varName = 'pixclusmontool_lb,npixhits_per_track'
     title   = fullDressTitle('Number of pixhits per track per LB', False, ';lumi block', ';number of hits')
-    trackGroup = helper.addGroup(alg, 'NPixhits_per_track_lumi')
     varName += ';NPixhits_per_track_lumi'
     trackGroup.defineHistogram(varName,
                                 type='TH2F', path=path, title=title, weight='npixhits_per_track_wgt',
@@ -135,11 +128,11 @@ def PixelAthClusterMonToolCfg(helper, alg, **kwargs):
     if doOnline:
         histoGroupName = 'HolesRatio_5min' 
         title = 'Holes per track reset every 5 min'
-        define2DProfLayers(helper, alg, histoGroupName, title, path, type='TProfile2D', zmin=0, zmax=1.1, opt='kLBNHistoryDepth=5')
+        define2DProfHist(helper, alg, 'HolesRatio', title, path, type='TProfile2D', zmin=0, zmax=1.1, opt='kLBNHistoryDepth=5', histname=histoGroupName)
 
         histoGroupName = 'MissHitsRatio_5min' 
         title = 'Hole+Outlier per track reset every 5 min'
-        define2DProfLayers(helper, alg, histoGroupName, title, path, type='TProfile2D', zmin=0, zmax=1.1, opt='kLBNHistoryDepth=5')
+        define2DProfHist(helper, alg, 'MissHitsRatio', title, path, type='TProfile2D', zmin=0, zmax=1.1, opt='kLBNHistoryDepth=5', histname=histoGroupName)
 
 ### end track histograms
 ### begin cluster histograms
@@ -149,25 +142,26 @@ def PixelAthClusterMonToolCfg(helper, alg, **kwargs):
 
 ### begin cluster timing
 ###
+    clusterGroup = { True: helper.addGroup(alg, "Cluster_OnTrack" ),
+                     False: helper.addGroup(alg, "Cluster") }
     for ontrack in True,False:
         pathGroup = addOnTrackToPath(pathTiming, ontrack)
         varName = 'Cluster_LVL1A_lvl1a'
         title = fullDressTitle('Cluster Level 1 Accept', ontrack, ';LVL1A',';# clusters/event')
-        clusterGroup = helper.addGroup(alg, addOnTrackTxt('Cluster_LVL1A', ontrack) )
         varName += ';'+ addOnTrackTxt('Cluster_LVL1A', ontrack)
-        clusterGroup.defineHistogram(varName, 
-                                     type='TH1F', path=pathGroup, title=title,
-                                     xbins=14, xmin=-1.5, xmax=12.5)
+        clusterGroup[ontrack].defineHistogram(varName, 
+                                              type='TH1F', path=pathGroup, title=title,
+                                              xbins=14, xmin=-1.5, xmax=12.5)
 
         histoGroupName = addOnTrackTxt('Cluster_LVL1A_Mod', ontrack)
         title = addOnTrackTxt('Average cluster Level 1 Accept', ontrack, True)
-        define2DProfLayers(helper, alg, histoGroupName, title, pathGroup, type='TProfile2D')
+        define2DProfHist(helper, alg, histoGroupName, title, pathGroup, type='TProfile2D')
 
         histoGroupName = addOnTrackTxt('Cluster_LVL1A_SizeCut', ontrack)
         title = addOnTrackTxt('Average Size>1 Cluster Level 1 Accept', ontrack, True)
-        define2DProfLayers(helper, alg, histoGroupName, title, pathGroup, type='TProfile2D')
+        define2DProfHist(helper, alg, histoGroupName, title, pathGroup, type='TProfile2D')
 
-        varName = 'Cluster_LVL1A_lvl1a' # re-using sam e variable
+        varName = 'Cluster_LVL1A_lvl1a' # re-using same variable
         histoGroupName = addOnTrackTxt('Cluster_LVL1A_ToTCut', ontrack)
         xaxistext      = ';LVL1A'
         yaxistext      = ';# clusters/event'
@@ -203,7 +197,7 @@ def PixelAthClusterMonToolCfg(helper, alg, **kwargs):
 
             histoGroupName = addOnTrackTxt('Cluster_Size_Map', ontrack)
             title = addOnTrackTxt('Average cluster size map', ontrack, True)
-            define2DProfLayers(helper, alg, histoGroupName, title, pathGroup, type='TProfile2D')
+            define2DProfHist(helper, alg, histoGroupName, title, pathGroup, type='TProfile2D')
 
 ### 
 ### end cluster sizes
@@ -213,11 +207,10 @@ def PixelAthClusterMonToolCfg(helper, alg, **kwargs):
 
         varName = 'pixclusmontool_lb,ncls_per_event'
         title = fullDressTitle('Average number of pixel clusters per event per LB', ontrack, ';lumi block', ';clusters/event')
-        trackGroup = helper.addGroup(alg, addOnTrackTxt('Clusters_per_lumi', ontrack) )
         varName += ';'+ addOnTrackTxt('Clusters_per_lumi', ontrack)
-        trackGroup.defineHistogram(varName,
-                                   type='TProfile', path=pathGroup, title=title,
-                                   xbins=lumibinsx, xmin=-0.5, xmax=-0.5+lumibinsx)
+        clusterGroup[ontrack].defineHistogram(varName,
+                                              type='TProfile', path=pathGroup, title=title,
+                                              xbins=lumibinsx, xmin=-0.5, xmax=-0.5+lumibinsx)
 
         histoGroupName = addOnTrackTxt('Clusters_per_lumi', ontrack)
         title          = addOnTrackTxt('Average number of pixel clusters per event per LB', ontrack, True)
@@ -227,11 +220,10 @@ def PixelAthClusterMonToolCfg(helper, alg, **kwargs):
         if ontrack:
             varName = 'pixclusmontool_lb,cls_frac_ontrack'
             title = fullDressTitle('Fraction pixel clusters on track per event per LB', False, ';lumi block', ';fraction clusters/event')
-            trackGroup = helper.addGroup(alg, 'ClustersOnOffTrack_per_lumi' )
             varName += ';ClustersOnOffTrack_per_lumi'
-            trackGroup.defineHistogram(varName,
-                                   type='TProfile', path=pathGroup, title=title,
-                                   xbins=lumibinsx, xmin=-0.5, xmax=-0.5+lumibinsx)
+            clusterGroup[ontrack].defineHistogram(varName,
+                                                  type='TProfile', path=pathGroup, title=title,
+                                                  xbins=lumibinsx, xmin=-0.5, xmax=-0.5+lumibinsx)
 
 
             histoGroupName = 'num_clusters_per_track_per_lumi'
@@ -242,7 +234,7 @@ def PixelAthClusterMonToolCfg(helper, alg, **kwargs):
         if doOnline:
             histoGroupName = addOnTrackTxt('ClusterMap_Mon', ontrack)
             title = addOnTrackTxt('Cluster map for monitoring', ontrack, True)
-            define2DProfLayers(helper, alg, histoGroupName, title, pathGroup, type='TH2D', zmin=0, zmax=1e4, opt='kLBNHistoryDepth=2') #FIXME zmax value w/ high stat
+            define2DProfHist(helper, alg, histoGroupName, title, pathGroup, type='TH2D', zmin=0, zmax=1e4, opt='kLBNHistoryDepth=2') #FIXME zmax value w/ high stat
 
 ### 
 ### end cluster rates
@@ -252,21 +244,22 @@ def PixelAthClusterMonToolCfg(helper, alg, **kwargs):
 
         histoGroupName = addOnTrackTxt('Cluster_Occupancy', ontrack)
         title = addOnTrackTxt('Cluster occupancy', ontrack, True)
-        define2DProfLayers(helper, alg, histoGroupName, title, pathGroup, type='TH2D')
+        define2DProfHist(helper, alg, histoGroupName, title, pathGroup, type='TH2D')
 
         histoGroupName = addOnTrackTxt('Clus_Occ_SizeCut', ontrack)
         title = addOnTrackTxt('Size>1 Cluster occupancy', ontrack, True)
-        define2DProfLayers(helper, alg, histoGroupName, title, pathGroup, type='TH2D')
+        define2DProfHist(helper, alg, histoGroupName, title, pathGroup, type='TH2D')
         if ontrack:
             histoGroupName = addOnTrackTxt('Cluster_Occupancy_PP0', ontrack)
             title = addOnTrackTxt('Average per module(FE) cluster occupancy reset every 5 min', ontrack, True)
             definePP0Histos(helper, alg, histoGroupName, title, pathGroup, opt='kLBNHistoryDepth=5')
 
 
-        pathGroup = addOnTrackToPath(pathLowStat, ontrack)
-        histoGroupName = addOnTrackTxt('Cluster_Occupancy_LB', ontrack)
-        title = addOnTrackTxt('Cluster occupancy lowStat', ontrack, True)
-        define2DProfLayers(helper, alg, histoGroupName, title, pathGroup, type='TH2D', lifecycle='lowStat')
+        if doLumiBlock:
+            pathGroup = addOnTrackToPath(pathLowStat, ontrack)
+            histoGroupName = addOnTrackTxt('Cluster_Occupancy_LB', ontrack)
+            title = addOnTrackTxt('Cluster occupancy lowStat', ontrack, True)
+            define2DProfHist(helper, alg, addOnTrackTxt('Cluster_Occupancy', ontrack), title, pathGroup, type='TH2D', lifecycle='lowStat', histname=histoGroupName)
 
 
 ### 
diff --git a/InnerDetector/InDetMonitoring/PixelMonitoring/python/PixelAthErrorMonToolCfg.py b/InnerDetector/InDetMonitoring/PixelMonitoring/python/PixelAthErrorMonToolCfg.py
index 922ceb623d1..f8583a04555 100644
--- a/InnerDetector/InDetMonitoring/PixelMonitoring/python/PixelAthErrorMonToolCfg.py
+++ b/InnerDetector/InDetMonitoring/PixelMonitoring/python/PixelAthErrorMonToolCfg.py
@@ -6,7 +6,7 @@
 @file PixelAthErrorMonToolCfg.py
 @brief Configuration of Pixel Error Monitoring Histograms for Run 3
 '''
-from PixelMonitoring.PixelAthMonitoringBase import define2DProfLayers
+from PixelMonitoring.PixelAthMonitoringBase import define2DProfHist
 from PixelMonitoring.PixelAthMonitoringBase import define1DLayers
 from PixelMonitoring.PixelAthMonitoringBase import define1DProfLumiLayers
 from PixelMonitoring.PixelAthMonitoringBase import layers, totcuts, xbinsem, xminsem, lumibinsx
diff --git a/InnerDetector/InDetMonitoring/PixelMonitoring/python/PixelAthHitMonToolCfg.py b/InnerDetector/InDetMonitoring/PixelMonitoring/python/PixelAthHitMonToolCfg.py
index 1969cbaa577..0ac6c699c4f 100644
--- a/InnerDetector/InDetMonitoring/PixelMonitoring/python/PixelAthHitMonToolCfg.py
+++ b/InnerDetector/InDetMonitoring/PixelMonitoring/python/PixelAthHitMonToolCfg.py
@@ -7,7 +7,7 @@
 @brief Configuration of Pixel Hit Monitoring Histograms for Run 3
 '''
 
-from PixelMonitoring.PixelAthMonitoringBase import define2DProfLayers
+from PixelMonitoring.PixelAthMonitoringBase import define2DProfHist
 from PixelMonitoring.PixelAthMonitoringBase import define1DLayers
 from PixelMonitoring.PixelAthMonitoringBase import define1DProfLumiLayers
 from PixelMonitoring.PixelAthMonitoringBase import layers, totcuts, xbinsem, xminsem, lumibinsx
diff --git a/InnerDetector/InDetMonitoring/PixelMonitoring/python/PixelAthMonitoringBase.py b/InnerDetector/InDetMonitoring/PixelMonitoring/python/PixelAthMonitoringBase.py
index 6f7f046cf7f..8ab416b8df8 100644
--- a/InnerDetector/InDetMonitoring/PixelMonitoring/python/PixelAthMonitoringBase.py
+++ b/InnerDetector/InDetMonitoring/PixelMonitoring/python/PixelAthMonitoringBase.py
@@ -129,10 +129,16 @@ PP0sEC = [
 
 PP0LabelX = [PP0sEC, PP0sEC, StavesL0, StavesL1, StavesL2, StavesIBL, StavesIBL]
 
+layergroups = {}
+def getLayerGroup(helper, alg, layer):
+    if alg not in layergroups:
+        layergroups[alg] = {}
+    if layer not in layergroups[alg]:
+        layergroups[alg][layer] = helper.addGroup(alg, layer)
+    return layergroups[alg][layer]
 
 
-
-def define2DProfLayers(helper, alg, name, title, path, type='TProfile2D', doWeight=False, lifecycle='run', zmin=None, zmax=None, opt='', subDir=False):
+def define2DProfHist(helper, alg, name, title, path, type='TProfile2D', doWeight=False, lifecycle='run', zmin=None, zmax=None, opt='', subDir=False, histname=None):
     '''
     This function configures 2D (Profile) histograms (or maps) for Pixel layers.
 
@@ -148,13 +154,11 @@ def define2DProfLayers(helper, alg, name, title, path, type='TProfile2D', doWeig
          opt     -- history depth of a histogram e.g. 'kLBNHistoryDepth=10'
          subDir  -- Put the configured histograms into sub directory named like partion (True, False)
     '''
+    if histname is None:
+        histname = name
     for i, layer in enumerate(layers):
-        groupname   = name  + '_{0}'.format(layer)
         fulltitle   = title + ' {0}'.format(layer) + runtext + etatxt[i] + phitext
-        if lifecycle != 'run':
-            layerGroup = helper.addGroup(alg, groupname, defaultDuration=str(lifecycle) )
-        else :
-            layerGroup = helper.addGroup(alg, groupname)
+        layerGroup = getLayerGroup(helper, alg, layer)
 
         # sequential list of x- and y-axis bin labels (see defineHistogram)
         labels = []
@@ -162,18 +166,19 @@ def define2DProfLayers(helper, alg, name, title, path, type='TProfile2D', doWeig
             labels.append(label)
         for label in LabelY[i]:
             labels.append(label)
-        fullvarstring = '{0}_{1},{0}_{2}'.format(groupname, 'em', 'pm')
-        if 'Profile' in type: fullvarstring += ',{0}_{1}'.format(groupname, 'val')
+        fullvarstring = '{0}_{1},{0}_{2}'.format(name, 'em', 'pm')
+        if 'Profile' in type: fullvarstring += ',{0}_{1}'.format(name, 'val')
         if doWeight:
-            weightvar = '{0}_{1}'.format(groupname, 'wgt')
+            weightvar = '{0}_{1}'.format(name, 'wgt')
         else :
             weightvar = ''
-        fullvarstring += ';' + groupname
+        fullvarstring += ';' + histname + '_{0}'.format(layer)
         layerGroup.defineHistogram(fullvarstring, 
                                     type=type, path=path, title=fulltitle, weight=weightvar,
                                     xbins=xbinsl[i], xmin=xminsl[i], xmax=xminsl[i]+xbinsl[i], 
                                     ybins=ybinsl[i], ymin=-0.5, ymax=-0.5+ybinsl[i],
-                                    zmin=zmin, zmax=zmax, 
+                                    zmin=zmin, zmax=zmax,
+                                    duration=lifecycle,
                                     opt=opt, labels=labels)
 
 def definePP0Histos(helper, alg, name, title, path, opt=''):
@@ -215,7 +220,8 @@ def definePP0Histos(helper, alg, name, title, path, opt=''):
 
 
 
-def define1DProfLumiLayers(helper, alg, name, title, path, yaxistext, type='TProfile'):
+def define1DProfLumiLayers(helper, alg, name, title, path, yaxistext, type='TProfile',
+                           histname=None):
     '''
     This function configures 1D (Profile) vs lumi histograms for Pixel layers.
 
@@ -229,13 +235,14 @@ def define1DProfLumiLayers(helper, alg, name, title, path, yaxistext, type='TPro
          zmin(zmax) -- fix the displayed range
     '''
 
+    if histname is None:
+        histname = name
     for layer in layers:
-        groupname   = name  + '_{0}'.format(layer)
         fulltitle   = title + ' {0}'.format(layer) + runtext + lumitext + yaxistext
-        layerGroup = helper.addGroup(alg, groupname)
+        layerGroup = getLayerGroup(helper, alg, layer)
         fullvarstring = '{0}_{1}'.format(name,'lb')
         if 'Profile' in type: fullvarstring += ',{0}_{1}'.format(name, 'val')
-        fullvarstring += ';' + groupname
+        fullvarstring += ';' + histname + '_{0}'.format(layer)
         layerGroup.defineHistogram(fullvarstring, 
                                     type=type, path=path, title=fulltitle,
                                     xbins=lumibinsx, xmin=-0.5, xmax=-0.5+lumibinsx)
@@ -268,7 +275,7 @@ def defineMapVsLumiLayers(helper, alg, name, title, path, ybins, ymin, ymax, yax
 
 
 
-def define1DLayers(helper, alg, name, title, path, xaxistext, yaxistext, xbins, xmins, binsizes=[1.0], type='TH1F'):
+def define1DLayers(helper, alg, name, title, path, xaxistext, yaxistext, xbins, xmins, binsizes=[1.0], type='TH1F', histname=None):
     '''
     This function configures 1D (Profile) histograms for Pixel layers.
 
@@ -284,12 +291,13 @@ def define1DLayers(helper, alg, name, title, path, xaxistext, yaxistext, xbins,
          *name*     -- name of the variable to fill (_common_ to all layers)  
     '''
 
+    if histname is None:
+        histname = name
     for idx,layer in enumerate(layers):
-        groupname   = name  + '_{0}'.format(layer)
         fulltitle   = title + ' {0}'.format(layer) + runtext + xaxistext + yaxistext
-        layerGroup = helper.addGroup(alg, groupname)
+        layerGroup = getLayerGroup(helper, alg, layer)
         fullvarstring = '{0}_{1}'.format(name,'val')
-        fullvarstring += ';' + groupname
+        fullvarstring += ';' + histname  + '_{0}'.format(layer)
         if ( len(xbins)==1 and len(xmins)==1 and len(binsizes)==1):
             layerGroup.defineHistogram(fullvarstring, 
                                         type=type, path=path, title=fulltitle,
diff --git a/InnerDetector/InDetMonitoring/PixelMonitoring/src/PixelAthClusterMonTool.cxx b/InnerDetector/InDetMonitoring/PixelMonitoring/src/PixelAthClusterMonTool.cxx
index 72011da339a..7ca8af5f75b 100644
--- a/InnerDetector/InDetMonitoring/PixelMonitoring/src/PixelAthClusterMonTool.cxx
+++ b/InnerDetector/InDetMonitoring/PixelMonitoring/src/PixelAthClusterMonTool.cxx
@@ -65,6 +65,8 @@ StatusCode PixelAthClusterMonTool::fillHistograms( const EventContext& ctx ) con
   int clusPerEventArray_l2[PixMon::kNumStavesL2][PixMon::kNumModulesBarrel] = { {0} };
   int clusPerEventArray_lI[PixMon::kNumStavesIBL][PixMon::kNumFEsIBL] = { {0} };  
 
+  VecAccumulator2DMap Map_Of_Modules_Status("Map_Of_Modules_Status", true);
+  
   for (auto idIt = m_pixelid->wafer_begin(); idIt!=m_pixelid->wafer_end(); ++idIt) {
     Identifier     waferID = *idIt;
     IdentifierHash id_hash = m_pixelid->wafer_hash(waferID);
@@ -105,11 +107,10 @@ StatusCode PixelAthClusterMonTool::fillHistograms( const EventContext& ctx ) con
       nBadMod[pixlayer]+= inv_nmod_per_layer[pixlayer];
     }
     
-    CHECK( fill2DProfLayer("Map_Of_Modules_Status_"+pixLayersLabel[pixlayer], waferID, m_pixelid, index, true) );
-    CHECK( fill2DProfLayer("Map_Of_Modules_Status_Mon_"+pixLayersLabel[pixlayer], waferID, m_pixelid, index, true) );
-    if (m_doLumiBlock) CHECK( fill2DProfLayer("Map_Of_Modules_Status_LB_"+pixLayersLabel[pixlayer], waferID, m_pixelid, index, true) );
+    Map_Of_Modules_Status.add(pixlayer, waferID, m_pixelid, index);
   }  // end of pixelid wafer loop
 
+  fill2DProfLayerAccum( Map_Of_Modules_Status );
   CHECK( fill1DProfLumiLayers("BadModules_per_lumi", lb, nBadMod) );
   CHECK( fill1DProfLumiLayers("DisabledModules_per_lumi", lb, nDisabledMod) );
 
@@ -125,6 +126,13 @@ StatusCode PixelAthClusterMonTool::fillHistograms( const EventContext& ctx ) con
 
   ATH_MSG_DEBUG("Filling Track Monitoring Histograms");
 
+  VecAccumulator2DMap TSOS_Outlier("TSOS_Outlier", true);
+  VecAccumulator2DMap TSOS_Hole("TSOS_Hole", true);
+  VecAccumulator2DMap TSOS_Measurement("TSOS_Measurement", true);
+  VecAccumulator2DMap HolesRatio("HolesRatio", true);
+  VecAccumulator2DMap MissHitsRatio("MissHitsRatio", true);
+  auto trackGroup = getGroup("Track");
+  
   auto tracks = SG::makeHandle(m_tracksKey, ctx);
 
   if ( !(tracks.isValid()) ) {
@@ -189,19 +197,19 @@ StatusCode PixelAthClusterMonTool::fillHistograms( const EventContext& ctx ) con
       auto efflb   = Monitored::Scalar<float>( "HitEff_all_lb", lb );
       if ((*trackStateOnSurfaceIterator)->type(Trk::TrackStateOnSurface::Outlier)) {
         nOutlier = 1.0;
-	if (!m_doOnline) CHECK( fill2DProfLayer("TSOS_Outlier_"+pixLayersLabel[pixlayer], surfaceID, m_pixelid, 1.0, true) );
-        if (pass1hole5GeVptTightCut) fill("HitEff_all_" + pixLayersLabel[pixlayer], efflb, effval);
+	if (!m_doOnline) TSOS_Outlier.add(pixlayer, surfaceID, m_pixelid, 1.0);
+        if (pass1hole5GeVptTightCut) fill(pixLayersLabel[pixlayer], efflb, effval);
 
       } else if ((*trackStateOnSurfaceIterator)->type(Trk::TrackStateOnSurface::Hole)) {
         nHole = 1.0;
-	if (!m_doOnline) CHECK( fill2DProfLayer("TSOS_Hole_"+pixLayersLabel[pixlayer], surfaceID, m_pixelid, 1.0, true) );
-        if (pass1hole5GeVptTightCut) fill("HitEff_all_" + pixLayersLabel[pixlayer], efflb, effval);
+	if (!m_doOnline) TSOS_Hole.add(pixlayer, surfaceID, m_pixelid, 1.0);
+        if (pass1hole5GeVptTightCut) fill(pixLayersLabel[pixlayer], efflb, effval);
 
       } else if ((*trackStateOnSurfaceIterator)->type(Trk::TrackStateOnSurface::Measurement)) {
 
-	if (!m_doOnline) CHECK( fill2DProfLayer("TSOS_Measurement_"+pixLayersLabel[pixlayer], surfaceID, m_pixelid, 1.0, true) );
+	if (!m_doOnline) TSOS_Measurement.add(pixlayer, surfaceID, m_pixelid, 1.0);
 	effval = 1.;
-	if (pass1hole5GeVptTightCut) fill("HitEff_all_" + pixLayersLabel[pixlayer], efflb, effval);
+	if (pass1hole5GeVptTightCut) fill(pixLayersLabel[pixlayer], efflb, effval);
 
 	if (not mesBase) continue;
 	const InDetDD::SiDetectorElement *side = dynamic_cast<const InDetDD::SiDetectorElement *>(mesBase->associatedSurface().associatedDetectorElement());
@@ -222,18 +230,18 @@ StatusCode PixelAthClusterMonTool::fillHistograms( const EventContext& ctx ) con
 	  
 	  double error_sum = sqrt(pow(Amg::error(trackErrMat, Trk::locX), 2) + pow(Amg::error(clusErrMat, Trk::locX), 2));
 	  auto  resPhi = Monitored::Scalar<float>( "res_phi", clus->localParameters()[Trk::locX] - localpos[0]);	  
-	  fill("Track_res_phi", resPhi);
+	  fill(trackGroup, resPhi);
 	  if (error_sum != 0) {
 	    auto pullPhi = Monitored::Scalar<float>( "pull_phi", resPhi / error_sum);
-	    fill("Track_pulls_phi", pullPhi);
+	    fill(trackGroup, pullPhi);
 	  }
 
 	  error_sum = sqrt(pow(Amg::error(trackErrMat, Trk::locY), 2) + pow(Amg::error(clusErrMat, Trk::locY), 2));
 	  auto  resEta = Monitored::Scalar<float>( "res_eta", clus->localParameters()[Trk::locY] - localpos[1]);
-	  fill("Track_res_eta", resEta);
+	  fill(trackGroup, resEta);
 	  if (error_sum != 0) {
 	    auto pullEta = Monitored::Scalar<float>( "pull_eta", resEta / error_sum);
-	    fill("Track_pulls_eta", pullEta);
+	    fill(trackGroup, pullEta);
 	  }
 	  // Filling containers, which hold id's of hits and clusters on track 
 	  // _and_ incident angle information for later normalization
@@ -252,12 +260,8 @@ StatusCode PixelAthClusterMonTool::fillHistograms( const EventContext& ctx ) con
       } // end of measurement case
     
       if (pass1hole1GeVptTightCut) {
-	CHECK( fill2DProfLayer("HolesRatio_"+pixLayersLabel[pixlayer], surfaceID, m_pixelid, nHole, true) );
-	CHECK( fill2DProfLayer("MissHitsRatio_"+pixLayersLabel[pixlayer], surfaceID, m_pixelid, nOutlier + nHole, true) ); 
-        if (m_doOnline) {
-	  CHECK( fill2DProfLayer("HolesRatio_5min_"+pixLayersLabel[pixlayer], surfaceID, m_pixelid, nHole, true) );
-	  CHECK( fill2DProfLayer("MissHitsRatio_5min_"+pixLayersLabel[pixlayer], surfaceID, m_pixelid, nOutlier + nHole, true) );
-        }
+	HolesRatio.add(pixlayer, surfaceID, m_pixelid, nHole);
+	MissHitsRatio.add(pixlayer, surfaceID, m_pixelid, nOutlier + nHole); 
       }
  
     } // end of TSOS loop
@@ -265,15 +269,21 @@ StatusCode PixelAthClusterMonTool::fillHistograms( const EventContext& ctx ) con
     ntracksPerEvent++;
     auto nph    = Monitored::Scalar<int>( "npixhits_per_track", nPixelHits);
     auto nphwgt = Monitored::Scalar<float>( "npixhits_per_track_wgt", 1.0 );
-    fill("NPixhits_per_track_lumi", lbval, nph, nphwgt);
+    fill(trackGroup, lbval, nph, nphwgt);
 
     int     trkfitndf = (*itrack)->fitQuality()->numberDoF();
     double trkfitchi2 = (*itrack)->fitQuality()->chiSquared();
     if (trkfitndf != 0) {
       auto trkChiN = Monitored::Scalar<float>( "fit_chi2byndf", trkfitchi2 / trkfitndf);
-      fill("Track_chi2byndf", trkChiN);
+      fill(trackGroup, trkChiN);
     }
   } // end of track loop
+  
+  fill2DProfLayerAccum( TSOS_Outlier );
+  fill2DProfLayerAccum( TSOS_Hole );
+  fill2DProfLayerAccum( TSOS_Measurement );
+  fill2DProfLayerAccum( HolesRatio );
+  fill2DProfLayerAccum( MissHitsRatio );
 
   sort(ClusterIDs.begin(), ClusterIDs.end(), [](const std::pair<Identifier, double> &left, const std::pair<Identifier, double> &right) {
       return left.first < right.first;
@@ -283,7 +293,7 @@ StatusCode PixelAthClusterMonTool::fillHistograms( const EventContext& ctx ) con
   // Filling per-event histograms
   //
   auto nTrks   = Monitored::Scalar<int>( "ntrks_per_event", ntracksPerEvent);
-  fill("tracksPerEvt_per_lumi", lbval, nTrks);
+  fill(trackGroup, lbval, nTrks);
 
   //m_npixhits_per_track_lastXlb-> // m_npixhits_per_track_lumi TH2F vs lumi
   //*******************************************************************************
@@ -296,6 +306,20 @@ StatusCode PixelAthClusterMonTool::fillHistograms( const EventContext& ctx ) con
 
   ATH_MSG_DEBUG("Filling Cluster Monitoring Histograms");
 
+  VecAccumulator2DMap Cluster_LVL1A_Mod("Cluster_LVL1A_Mod");
+  VecAccumulator2DMap Cluster_LVL1A_SizeCut("Cluster_LVL1A_SizeCut");
+  VecAccumulator2DMap Cluster_LVL1A_Mod_OnTrack("Cluster_LVL1A_Mod_OnTrack");
+  VecAccumulator2DMap Cluster_LVL1A_SizeCut_OnTrack("Cluster_LVL1A_SizeCut_OnTrack");
+  VecAccumulator2DMap ClusterMap_Mon("ClusterMap_Mon");
+  VecAccumulator2DMap ClusterMap_Mon_OnTrack("ClusterMap_Mon_OnTrack");
+  VecAccumulator2DMap Cluster_Size_Map_OnTrack("Cluster_Size_Map_OnTrack");
+  VecAccumulator2DMap Cluster_Occupancy("Cluster_Occupancy");
+  VecAccumulator2DMap Cluster_Occupancy_OnTrack("Cluster_Occupancy_OnTrack");
+  VecAccumulator2DMap Clus_Occ_SizeCut("Clus_Occ_SizeCut");
+  VecAccumulator2DMap Clus_Occ_SizeCut_OnTrack("Clus_Occ_SizeCut_OnTrack");
+  auto clusterGroup = getGroup("Cluster");
+  auto clusterGroup_OnTrack = getGroup("Cluster_OnTrack");
+
   auto pixel_clcontainer = SG::makeHandle(m_clustersKey, ctx);
 
   if ( !(pixel_clcontainer.isValid()) ) {
@@ -336,26 +360,24 @@ StatusCode PixelAthClusterMonTool::fillHistograms( const EventContext& ctx ) con
       // begin timing histos
       //
       auto clLVL1A   = Monitored::Scalar<float>( "Cluster_LVL1A_lvl1a", cluster.LVL1A() );
-      fill( addTxt("Cluster_LVL1A", false), clLVL1A);
-      CHECK( fill2DProfLayer( addTxt("Cluster_LVL1A_Mod", false)+"_"+pixLayersLabel[pixlayer], clusID, m_pixelid, cluster.LVL1A() + 0.00001) );
-      if (cluster.rdoList().size() > 1) CHECK( fill2DProfLayer( addTxt("Cluster_LVL1A_SizeCut", false)+"_"+pixLayersLabel[pixlayer], clusID, m_pixelid, cluster.LVL1A() + 0.00001) );
+      fill( clusterGroup, clLVL1A);
+      Cluster_LVL1A_Mod.add(pixlayer, clusID, m_pixelid, cluster.LVL1A() + 0.00001);
+      if (cluster.rdoList().size() > 1) Cluster_LVL1A_SizeCut.add(pixlayer, clusID, m_pixelid, cluster.LVL1A() + 0.00001);
       if (cluster.totalToT() > clusterToTMinCut[pixlayer]) fill( addTxt("Cluster_LVL1A_ToTCut", false) + "_" + pixLayersLabel[pixlayer], clLVL1A);
 
-
       // 
       // end timing histos
       // begin cluster rate
       //
-      if (m_doOnline) CHECK( fill2DProfLayer( addTxt("ClusterMap_Mon", false)+"_"+pixLayersLabel[pixlayer], clusID, m_pixelid) );
+      if (m_doOnline) ClusterMap_Mon.add(pixlayer, clusID, m_pixelid);
       // 
       // end cluster rate
       // begin cluster occupancy
       //
-      CHECK( fill2DProfLayer( addTxt("Cluster_Occupancy", false)+"_"+pixLayersLabel[pixlayer], clusID, m_pixelid) );
-      if (cluster.rdoList().size() > 1) CHECK( fill2DProfLayer( addTxt("Clus_Occ_SizeCut", false)+"_"+pixLayersLabel[pixlayer], clusID, m_pixelid) );
-      if (m_doLumiBlock) CHECK( fill2DProfLayer( addTxt("Cluster_Occupancy_LB", false)+"_"+pixLayersLabel[pixlayer], clusID, m_pixelid) );
-      // 
+      Cluster_Occupancy.add(pixlayer, clusID, m_pixelid);
+      if (cluster.rdoList().size() > 1) Clus_Occ_SizeCut.add(pixlayer, clusID, m_pixelid);
       // end cluster occupancy
+
       double cosalpha(0.); 
       if ( isClusterOnTrack(clusID, ClusterIDs, cosalpha) ) {
 	nclusters_ontrack++;
@@ -384,40 +406,39 @@ StatusCode PixelAthClusterMonTool::fillHistograms( const EventContext& ctx ) con
 	// begin timing histos
 	//
 	clLVL1A = cluster.LVL1A(); 
-	fill( addTxt("Cluster_LVL1A", true), clLVL1A);
-	CHECK( fill2DProfLayer( addTxt("Cluster_LVL1A_Mod", true)+"_"+pixLayersLabel[pixlayer], clusID, m_pixelid, cluster.LVL1A() + 0.00001) );
-	if (cluster.rdoList().size() > 1) CHECK( fill2DProfLayer( addTxt("Cluster_LVL1A_SizeCut", true)+"_"+pixLayersLabel[pixlayer], clusID, m_pixelid, cluster.LVL1A() + 0.00001) );
+	fill( clusterGroup_OnTrack, clLVL1A);
+	Cluster_LVL1A_Mod_OnTrack.add(pixlayer, clusID, m_pixelid, cluster.LVL1A() + 0.00001);
+	if (cluster.rdoList().size() > 1) Cluster_LVL1A_SizeCut_OnTrack.add(pixlayer, clusID, m_pixelid, cluster.LVL1A() + 0.00001);
 	if (cluster.totalToT() > clusterToTMinCut[pixlayer]) fill( addTxt("Cluster_LVL1A_ToTCut", true) + "_" + pixLayersLabel[pixlayer], clLVL1A);
 	// 
 	// end timing histos
 	// begin cluster sizes
 	//
-	auto clSize    = Monitored::Scalar<float>( Form("%s_%s", addTxt("Cluster_Size", true).c_str(), "clsize"), cluster.rdoList().size());
-	auto etaModule = Monitored::Scalar<float>( Form("%s_%s", addTxt("Cluster_Size", true).c_str(), "em"), m_pixelid->eta_module(clusID) );
+	auto clSize    = Monitored::Scalar<float>( "Cluster_Size_OnTrack_clsize", cluster.rdoList().size());
+	auto etaModule = Monitored::Scalar<float>( "Cluster_Size_OnTrack_em", m_pixelid->eta_module(clusID) );
 	if ( abs(m_pixelid->barrel_ec(clusID))!=0 ) etaModule = m_pixelid->layer_disk(clusID) + 1;
 	fill( addTxt("Cluster_groupsize_vs_eta", true) + "_" + pixLayersLabel[pixlayer], etaModule, clSize );
-	CHECK( fill2DProfLayer( addTxt("Cluster_Size_Map", true)+"_"+pixLayersLabel[pixlayer], clusID, m_pixelid, cluster.rdoList().size()) );
+	Cluster_Size_Map_OnTrack.add(pixlayer, clusID, m_pixelid, cluster.rdoList().size());
 	// 
 	// end cluster sizes
 	// begin cluster rate
 	//
-	if (m_doOnline) CHECK( fill2DProfLayer( addTxt("ClusterMap_Mon", true)+"_"+pixLayersLabel[pixlayer], clusID, m_pixelid) );
+	if (m_doOnline) ClusterMap_Mon_OnTrack.add(pixlayer, clusID, m_pixelid);
 	// 
 	// end cluster rate
 	// begin cluster occupancy
 	//
-	CHECK( fill2DProfLayer( addTxt("Cluster_Occupancy", true)+"_"+pixLayersLabel[pixlayer], clusID, m_pixelid) );
-	if (cluster.rdoList().size() > 1) CHECK( fill2DProfLayer( addTxt("Clus_Occ_SizeCut", true)+"_"+pixLayersLabel[pixlayer], clusID, m_pixelid) );
-	if (m_doLumiBlock) CHECK( fill2DProfLayer( addTxt("Cluster_Occupancy_LB", true)+"_"+pixLayersLabel[pixlayer], clusID, m_pixelid) );
+	Cluster_Occupancy_OnTrack.add(pixlayer, clusID, m_pixelid);
+	if (cluster.rdoList().size() > 1) Clus_Occ_SizeCut_OnTrack.add(pixlayer, clusID, m_pixelid);
 	// 
 	// end cluster occupancy
 	// begin cluster ToT and charge
 	//
-	auto clToTcosAlpha = Monitored::Scalar<float>( Form("%s_%s", addTxt("Cluster_ToTxCosAlpha", true).c_str(), "val"), cluster.totalToT() * cosalpha );
-	fill( addTxt("Cluster_ToTxCosAlpha", true) + "_" + pixLayersLabel[pixlayer], clToTcosAlpha);
+	auto clToTcosAlpha = Monitored::Scalar<float>( "Cluster_ToTxCosAlpha_OnTrack_val", cluster.totalToT() * cosalpha );
+	fill( pixLayersLabel[pixlayer], clToTcosAlpha);
 	if (!m_doOnline) {
-	  auto clQcosAlpha   = Monitored::Scalar<float>( Form("%s_%s", addTxt("Cluster_QxCosAlpha", true).c_str(), "val"), cluster.totalCharge() * cosalpha);
-	  fill( addTxt("Cluster_QxCosAlpha", true) + "_" + pixLayersLabel[pixlayer], clQcosAlpha);
+	  auto clQcosAlpha   = Monitored::Scalar<float>( "Cluster_QxCosAlpha_OnTrack_val", cluster.totalCharge() * cosalpha);
+	  fill( pixLayersLabel[pixlayer], clQcosAlpha);
 	}
 	// 
 	// end cluster ToT and charge   
@@ -425,16 +446,30 @@ StatusCode PixelAthClusterMonTool::fillHistograms( const EventContext& ctx ) con
     }
 
   }
+  fill2DProfLayerAccum(Cluster_LVL1A_Mod);
+  fill2DProfLayerAccum(Cluster_LVL1A_SizeCut);
+  fill2DProfLayerAccum(Cluster_LVL1A_Mod_OnTrack);
+  fill2DProfLayerAccum(Cluster_LVL1A_SizeCut_OnTrack);
+  if (m_doOnline) {
+    fill2DProfLayerAccum(ClusterMap_Mon);
+    fill2DProfLayerAccum(ClusterMap_Mon_OnTrack);
+  }
+  fill2DProfLayerAccum(Cluster_Size_Map_OnTrack);
+  fill2DProfLayerAccum(Cluster_Occupancy);
+  fill2DProfLayerAccum(Cluster_Occupancy_OnTrack);
+  fill2DProfLayerAccum(Clus_Occ_SizeCut);
+  fill2DProfLayerAccum(Clus_Occ_SizeCut_OnTrack);
+  
   // begin cluster rates
   //
   auto nCls   = Monitored::Scalar<int>( "ncls_per_event", nclusters );
-  fill( addTxt("Clusters_per_lumi", false), lbval, nCls);
+  fill( clusterGroup, lbval, nCls);
   nCls = nclusters_ontrack;
-  fill( addTxt("Clusters_per_lumi", true), lbval, nCls);
+  fill( clusterGroup_OnTrack, lbval, nCls);
 
   if (nclusters>0) {
     auto clsFracOnTrack = Monitored::Scalar<float>( "cls_frac_ontrack", (float)nclusters_ontrack / nclusters );
-    fill( "ClustersOnOffTrack_per_lumi", lbval, clsFracOnTrack);
+    fill( clusterGroup_OnTrack, lbval, clsFracOnTrack);
   }
 
   CHECK( fill1DProfLumiLayers( addTxt("Clusters_per_lumi", false), lb, nclusters_mod) );
diff --git a/InnerDetector/InDetMonitoring/PixelMonitoring/src/PixelAthMonitoringBase.cxx b/InnerDetector/InDetMonitoring/PixelMonitoring/src/PixelAthMonitoringBase.cxx
index f179b08c318..f8fee792691 100644
--- a/InnerDetector/InDetMonitoring/PixelMonitoring/src/PixelAthMonitoringBase.cxx
+++ b/InnerDetector/InDetMonitoring/PixelMonitoring/src/PixelAthMonitoringBase.cxx
@@ -4,19 +4,75 @@
 
 #include "PixelMonitoring/PixelAthMonitoringBase.h"
 
+
+//////////////////////////////////////////////
+///
+/// helper class to accumulate points to fill a 2D plot with
+///
+void PixelAthMonitoringBase::VecAccumulator2DMap::add( const int layer, const Identifier& id,
+						  const PixelID* pid, float value ) {
+  m_pm[layer].push_back(pid->phi_module(id));
+  int ld = pid->layer_disk(id);
+  int em = ld;
+  m_val[layer].push_back(value);
+
+  bool copy = false;
+  if (pid->barrel_ec(id) == 0) {
+    em = pid->eta_module(id);
+    if (ld == 0) {
+      int feid = 0;
+      int emf = 0;
+      if (em < -6) {
+	emf = em - 6;
+      } else if (em > -7 && em < 6) {
+	if (pid->eta_index(id) >= 80) feid = 1;
+	emf = 2 * em + feid;
+	copy = true;
+      } else {
+	emf = em + 6;
+      }
+      em = emf;
+    }
+  }
+  m_em[layer].push_back(em);
+  
+  if (m_copy2DFEval && copy) {
+    ++em;
+    m_pm[layer].push_back(pid->phi_module(id));
+    m_em[layer].push_back(em);
+    m_val[layer].push_back(value);
+  }   
+}
+
+//////////////////////////////////////////////
+///
+/// take VecAccumulator2DMap and fill the corresponding group
+///
+void PixelAthMonitoringBase::fill2DProfLayerAccum( const VecAccumulator2DMap& accumulator ) const {
+  // iterate over all actually filled layers
+  for ( const auto& itr : accumulator.m_pm ) {
+    // Define the monitored variables
+    int layer = itr.first;
+    auto pm  = Monitored::Collection(accumulator.m_prof2Dname + "_pm", accumulator.m_pm.at(layer));
+    auto val = Monitored::Collection(accumulator.m_prof2Dname + "_val", accumulator.m_val.at(layer));
+    auto em  = Monitored::Collection(accumulator.m_prof2Dname + "_em", accumulator.m_em.at(layer));
+    fill(pixLayersLabel[layer], pm, em, val);
+  }
+}
+  
 //////////////////////////////////////////////
 ///
 /// filling 2D(Prof) per-layer histogram, one of ["ECA","ECC","B0","B1","B2","IBL","DBMA","DBMC"]
 ///
-StatusCode PixelAthMonitoringBase::fill2DProfLayer( std::string prof2Dname, Identifier& id, const PixelID* pid, float value, bool copy2DFEval) const {
+StatusCode PixelAthMonitoringBase::fill2DProfLayer( const std::string& prof2Dname, const std::string& layer, Identifier& id, const PixelID* pid, float value, bool copy2DFEval) const {
   ATH_MSG_VERBOSE( "in fill2DProfLayer()" );
 
   // Define the monitored variables
-  auto pm  = Monitored::Scalar<int>(   Form("%s_%s", prof2Dname.c_str(), "pm"), pid->phi_module(id));
-  auto val = Monitored::Scalar<float>( Form("%s_%s", prof2Dname.c_str(), "val"), value);
+  auto pm  = Monitored::Scalar<int>(   prof2Dname + "_pm", pid->phi_module(id));
+  auto val = Monitored::Scalar<float>( prof2Dname + "_val", value);
 
   int ld  = pid->layer_disk(id);
-  auto em  = Monitored::Scalar<int>(   Form("%s_%s", prof2Dname.c_str(), "em"), ld);
+  auto em  = Monitored::Scalar<int>(   prof2Dname + "_em", ld);
   bool copy = false;
   if (pid->barrel_ec(id) == 0) {
     em = pid->eta_module(id);
@@ -35,12 +91,12 @@ StatusCode PixelAthMonitoringBase::fill2DProfLayer( std::string prof2Dname, Iden
       em = emf;
     }
   }
-  fill(prof2Dname, em, pm, val);
+  fill(layer, em, pm, val);
   // next line is only for IBL: fill the (per-FE) histogram again to avoid holes in the histogram in case 
   // the filled information is available per module (and not per FE)
   if ( copy2DFEval && copy ) {
     em++;
-    fill(prof2Dname, em, pm, val);
+    fill(layer, em, pm, val);
   }
   return StatusCode::SUCCESS;
 }
@@ -58,7 +114,7 @@ StatusCode PixelAthMonitoringBase::fill1DProfLumiLayers( std::string prof1Dname,
 
   for (int i = 0; i < PixLayers::COUNT; i++) {
     val = values[i];
-    fill( prof1Dname + "_" + pixLayersLabel[i], lb, val);
+    fill( pixLayersLabel[i], lb, val);
   }
 
   return StatusCode::SUCCESS;
@@ -75,7 +131,7 @@ StatusCode PixelAthMonitoringBase::fill1DProfLayers( std::string name, float* va
   auto val = Monitored::Scalar<float>( Form("%s_%s", name.c_str(), "val"), -999. );
   for (int i = 0; i < PixLayers::COUNT; i++) {
     val = values[i];
-    fill(name + "_" + pixLayersLabel[i], val);
+    fill(pixLayersLabel[i], val);
   }
   return StatusCode::SUCCESS;
 }
-- 
GitLab