diff --git a/Control/AthenaMonitoringKernel/AthenaMonitoringKernel/HistogramFiller.h b/Control/AthenaMonitoringKernel/AthenaMonitoringKernel/HistogramFiller.h
index d9863d0e657d2b0ed5a2b4366c6e783ec8104664..ac83270ded0b5d54cf69c99dc8a1a6b4e0e506bc 100644
--- a/Control/AthenaMonitoringKernel/AthenaMonitoringKernel/HistogramFiller.h
+++ b/Control/AthenaMonitoringKernel/AthenaMonitoringKernel/HistogramFiller.h
@@ -61,7 +61,7 @@ namespace Monitored {
      * @brief Method that actually fills the ROOT object
      * @return number of fills performed
      */
-    virtual unsigned fill() = 0;
+    virtual unsigned fill() const = 0;
 
 
     /**
@@ -101,12 +101,12 @@ namespace Monitored {
     
   protected:
     template <class H>
-    H* histogram() {
+    H* histogram() const {
       return static_cast<H*>(m_histogramProvider->histogram());
     }
 
     // convenience function to provide a function that interprets the cutmask
-    std::pair<size_t, std::function<bool(size_t)>> getCutMaskFunc() {
+    std::pair<size_t, std::function<bool(size_t)>> getCutMaskFunc() const {
       std::function<bool(size_t)> cutMaskValue = [] (size_t){ return true; }; // default is true
       size_t maskSize = 1;
       if ( m_monCutMask != nullptr ) {
@@ -136,7 +136,7 @@ namespace Monitored {
      * @param  m1,m...  IMonitoredVariable list to fill from
      */
     template<class H, typename W, typename C, typename M, typename ...Ms>
-    unsigned fill(W weight, C cut, const M& m1, const Ms&... m) {
+    unsigned fill(W weight, C cut, const M& m1, const Ms&... m) const {
       // Template magic: Recursively convert all M to std::vector
       if constexpr(std::is_same_v<M, Monitored::IMonitoredVariable>) {
         if (not m1.hasStringRepresentation())
diff --git a/Control/AthenaMonitoringKernel/share/GenericMon.txt b/Control/AthenaMonitoringKernel/share/GenericMon.txt
index 87ff9cb9b393bc64224a99bd19f8fea4cfaa6464..c0d05d2cec80818f46bf7f5c7599205c7a49713d 100644
--- a/Control/AthenaMonitoringKernel/share/GenericMon.txt
+++ b/Control/AthenaMonitoringKernel/share/GenericMon.txt
@@ -19,6 +19,7 @@ ToolSvc.MonTool.Histograms =  {'{"alias": "Eta", "allvars": ["Eta"], "convention
 ToolSvc.MonTool.Histograms += {'{"alias": "Phi", "allvars": ["Phi"], "convention": "", "merge": "", "path": "EXPERT", "title": "#phi of Clusters; #phi; number of RoIs", "treeDef": "", "type": "TH1F", "weight": "", "cutMask": "", "xarray": [], "xbins": 2, "xlabels": [], "xmax": 3.15, "xmin": -3.15, "xvar": "Phi", "yarray": [], "ybins": 0.0, "ylabels": [], "ymax": 0.0, "ymin": 0.0, "yvar": "", "zbins": 0, "zlabels": [], "zmax": 0.0, "zmin": 0.0, "zvar": "", "Sumw2": false, "kLBNHistoryDepth": 0, "kAddBinsDynamically": false, "kRebinAxes": false, "kCanRebin": false, "kVec": false, "kVecUO": false, "kCumulative": false}'};
 ToolSvc.MonTool.Histograms += {'{"alias": "pt", "allvars": ["pt"], "convention": "", "merge": "", "path": "EXPERT", "title": "pt; pt; transverse momentum", "treeDef": "", "type": "TH1F", "weight": "Weight", "cutMask": "", "xarray": [], "xbins": 10, "xlabels": [], "xmax": 10, "xmin": 0, "xvar": "pt", "yarray": [], "ybins": 0.0, "ylabels": [], "ymax": 0.0, "ymin": 0.0, "yvar": "", "zbins": 0, "zlabels": [], "zmax": 0.0, "zmin": 0.0, "zvar": "", "Sumw2": false, "kLBNHistoryDepth": 0, "kAddBinsDynamically": false, "kRebinAxes": false, "kCanRebin": false, "kVec": false, "kVecUO": false, "kCumulative": false}'};
 ToolSvc.MonTool.Histograms += {'{"alias": "Eta_CutMask", "allvars": ["Eta"], "convention": "", "merge": "", "path": "EXPERT", "title": "#eta of Clusters, with cut; #eta; number of RoIs", "treeDef": "", "type": "TH1F", "weight": "", "cutMask": "CutMask", "xarray": [], "xbins": 2, "xlabels": [], "xmax": 2.50, "xmin": -2.50, "xvar": "Eta", "yarray": [], "ybins": 0.0, "ylabels": [], "ymax": 0.0, "ymin": 0.0, "yvar": "", "zbins": 0, "zlabels": [], "zmax": 0.0, "zmin": 0.0, "zvar": "", "Sumw2": false, "kLBNHistoryDepth": 0, "kAddBinsDynamically": false, "kRebinAxes": false, "kCanRebin": false, "kVec": false, "kVecUO": false, "kCumulative": false}'};
+ToolSvc.MonTool.Histograms += {'{"alias": "pt_vs_Eta", "allvars": ["Eta", "pt"], "convention": "", "merge": "", "path": "EXPERT", "title": "pt vs #eta; #eta; pt", "treeDef": "", "type": "TProfile", "weight": "", "cutMask": "", "xarray": [], "xbins": 2, "xlabels": [], "xmax": 2.5, "xmin": -2.5, "xvar": "Eta", "yarray": [], "ybins": 0, "ylabels": [], "ymax": 0.0, "ymin": 0.0, "yvar": "Pt", "zbins": 0, "zlabels": [], "zmax": 0.0, "zmin": 0.0, "zvar": "", "Sumw2": false, "kLBNHistoryDepth": 0, "kAddBinsDynamically": false, "kRebinAxes": false, "kCanRebin": false, "kVec": false, "kVecUO": false, "kCumulative": false}'};
 ToolSvc.MonTool.Histograms += {'{"alias": "Phi_vs_Eta", "allvars": ["Eta", "Phi"], "convention": "", "merge": "", "path": "EXPERT", "title": "#eta vs #phi of Clusters; #eta; #phi; number of RoIs", "treeDef": "", "type": "TH2F", "weight": "", "cutMask": "", "xarray": [], "xbins": 2, "xlabels": [], "xmax": 2.5, "xmin": -2.5, "xvar": "Eta", "yarray": [], "ybins": 2, "ylabels": [], "ymax": 3.15, "ymin": -3.15, "yvar": "Phi", "zbins": 0, "zlabels": [], "zmax": 0.0, "zmin": 0.0, "zvar": "", "Sumw2": false, "kLBNHistoryDepth": 0, "kAddBinsDynamically": false, "kRebinAxes": false, "kCanRebin": false, "kVec": false, "kVecUO": false, "kCumulative": false}'};
 ToolSvc.MonTool.Histograms += {'{"alias": "Phi_vs_Eta_Tree", "allvars": ["Eta", "Phi"], "convention": "", "merge": "", "path": "EXPERT", "title": "Test Tree", "treeDef": "Eta/F:Phi/vector<float>", "type": "TTree", "weight": "", "cutMask": "", "xarray": [], "xbins": 2, "xlabels": [], "xmax": 2.5, "xmin": -2.5, "xvar": "Eta", "yarray": [], "ybins": 2, "ylabels": [], "ymax": 3.15, "ymin": -3.15, "yvar": "Phi", "zbins": 0, "zlabels": [], "zmax": 0.0, "zmin": 0.0, "zvar": "", "Sumw2": false, "kLBNHistoryDepth": 0, "kAddBinsDynamically": false, "kRebinAxes": false, "kCanRebin": false, "kVec": false, "kVecUO": false, "kCumulative": false}'};
 ToolSvc.MonTool.Histograms += {'{"alias": "TIME_t1", "allvars": ["TIME_t1"], "convention": "", "merge": "", "path": "EXPERT", "title": "Timing of tool 1", "treeDef": "", "type": "TH1F", "weight": "", "cutMask": "", "xarray": [], "xbins": 100, "xlabels": [], "xmax": 20000.0, "xmin": 0.0, "xvar": "TIME_t1", "yarray": [], "ybins": 0.0, "ylabels": [], "ymax": 0.0, "ymin": 0.0, "yvar": "", "zbins": 0, "zlabels": [], "zmax": 0.0, "zmin": 0.0, "zvar": "", "Sumw2": false, "kLBNHistoryDepth": 0, "kAddBinsDynamically": false, "kRebinAxes": false, "kCanRebin": false, "kVec": false, "kVecUO": false, "kCumulative": false}'};
diff --git a/Control/AthenaMonitoringKernel/src/HistogramFiller/CumulativeHistogramFiller1D.h b/Control/AthenaMonitoringKernel/src/HistogramFiller/CumulativeHistogramFiller1D.h
index db6cae303d650a8296836cb5d5653143c6cfc40c..1f08de49fa689af8c498294b725925dc808935f5 100644
--- a/Control/AthenaMonitoringKernel/src/HistogramFiller/CumulativeHistogramFiller1D.h
+++ b/Control/AthenaMonitoringKernel/src/HistogramFiller/CumulativeHistogramFiller1D.h
@@ -21,7 +21,7 @@ namespace Monitored {
     }
 
     
-    virtual unsigned fill() override {
+    virtual unsigned fill() const override {
       if (m_monVariables.size() != 1) {
         return 0;
       }
diff --git a/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFiller1D.h b/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFiller1D.h
index 72dd934eb4fb8e46a53e6677c41b8c1758121812..60fd3be779eec61d2aa6bcc2691f59dffd7a0466 100644
--- a/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFiller1D.h
+++ b/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFiller1D.h
@@ -28,7 +28,7 @@ namespace Monitored {
       return new HistogramFiller1D( *this );
     }
 
-    virtual unsigned fill() override {
+    virtual unsigned fill() const override {
       if (m_monVariables.size() != 1) { return 0; }
       const IMonitoredVariable& var = m_monVariables.at(0).get();
 
diff --git a/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFiller2D.h b/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFiller2D.h
index 4fcf5d7f1fe64c225b2a1689880083187609d0f6..b9e05773c82d1e744a98cc1229cb8e6b88d4cba1 100644
--- a/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFiller2D.h
+++ b/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFiller2D.h
@@ -13,19 +13,23 @@
 #include "GaudiKernel/MsgStream.h"
 
 namespace Monitored {
+
   /**
-   * @brief Filler for plain 2D histogram
+   * @brief Generic filler for 2D histogram
+   *
+   * @tparam H  Type of 2D histogram (TH2, TProfile)
    */
-  class HistogramFiller2D : public HistogramFiller {
+  template<typename H>
+  class HistogramFiller2DGeneric : public HistogramFiller {
   public:
-    HistogramFiller2D(const HistogramDef& definition, std::shared_ptr<IHistogramProvider> provider)
+    HistogramFiller2DGeneric(const HistogramDef& definition, std::shared_ptr<IHistogramProvider> provider)
       : HistogramFiller(definition, provider) {}
 
-    virtual HistogramFiller2D* clone() const override {
-      return new HistogramFiller2D( *this ); 
+    virtual HistogramFiller2DGeneric* clone() const override {
+      return new HistogramFiller2DGeneric( *this );
     }
     
-    virtual unsigned fill() override {
+    virtual unsigned fill() const override {
       if (ATH_UNLIKELY(m_monVariables.size() != 2)) return 0;
 
       const IMonitoredVariable& var1 = m_monVariables[0].get();
@@ -72,14 +76,16 @@ namespace Monitored {
           return 0;
         }
         // Need to fill here while weightVector is still in scope
-        if (not m_monCutMask) return HistogramFiller::fill<TH2>(weightAccessor, detail::noCut, var1, var2);
-        else                  return HistogramFiller::fill<TH2>(weightAccessor, cutMaskAccessor, var1, var2);
+        if (not m_monCutMask) return HistogramFiller::fill<H>(weightAccessor, detail::noCut, var1, var2);
+        else                  return HistogramFiller::fill<H>(weightAccessor, cutMaskAccessor, var1, var2);
       }
 
-      if (not m_monCutMask) return HistogramFiller::fill<TH2>(detail::noWeight, detail::noCut, var1, var2);
-      else                  return HistogramFiller::fill<TH2>(detail::noWeight, cutMaskAccessor, var1, var2);
+      if (not m_monCutMask) return HistogramFiller::fill<H>(detail::noWeight, detail::noCut, var1, var2);
+      else                  return HistogramFiller::fill<H>(detail::noWeight, cutMaskAccessor, var1, var2);
     }
   };
+
+  typedef HistogramFiller2DGeneric<TH2> HistogramFiller2D;
 }
 
 #endif /* AthenaMonitoringKernel_HistogramFiller_HistogramFiller2D_h */
diff --git a/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFiller2DProfile.h b/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFiller2DProfile.h
index aaf480aaf1d9e860e47356a4526662c3042a1ea7..da193fedf3399c28c5349e4d96aa24bb66eeada7 100644
--- a/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFiller2DProfile.h
+++ b/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFiller2DProfile.h
@@ -6,6 +6,7 @@
 #define AthenaMonitoringKernel_HistogramFiller_HistogramFiller2DProfile_h
 
 #include "TProfile2D.h"
+#include "boost/range/combine.hpp"
 
 #include "AthenaMonitoringKernel/HistogramFiller.h"
 
@@ -23,7 +24,7 @@ namespace Monitored {
     }
 
 
-    virtual unsigned fill() override {
+    virtual unsigned fill() const override {
       if (m_monVariables.size() != 3) {
         return 0;
       }
diff --git a/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFillerEfficiency.h b/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFillerEfficiency.h
index d2880052624bd58f3d45855501d6bdc123167f27..2bb643ef46ce5f9dc20389e82399d130e1a098fd 100644
--- a/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFillerEfficiency.h
+++ b/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFillerEfficiency.h
@@ -23,7 +23,7 @@ namespace Monitored {
       return new HistogramFillerEfficiency( *this );
     }
 
-    virtual unsigned fill() override {
+    virtual unsigned fill() const override {
       size_t varVecSize = m_monVariables.at(0).get().size();
 
       auto cutMaskValuePair = getCutMaskFunc();
@@ -74,7 +74,7 @@ namespace Monitored {
       }
     }
 
-    const std::vector<double> retrieveVariable(TEfficiency* efficiency, int iVariable) {
+    const std::vector<double> retrieveVariable(TEfficiency* efficiency, int iVariable) const {
       auto valueVariable = m_monVariables[iVariable];
       std::vector<double> valuesVector;
       if ( valueVariable.get().hasStringRepresentation() ) {
@@ -91,7 +91,7 @@ namespace Monitored {
       return valuesVector;
     }
 
-    const TAxis* getAxis(TH1* hist, int iAxis) {
+    const TAxis* getAxis(TH1* hist, int iAxis) const {
       if ( iAxis==1 ) {
         return hist->GetXaxis();
       } else if ( iAxis==2 ) {
diff --git a/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFillerFactory.cxx b/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFillerFactory.cxx
index 6981582085212f3c5e730803a24de50570999221..d517d443f13cb226c097521a2dcb3e93e028334c 100644
--- a/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFillerFactory.cxx
+++ b/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFillerFactory.cxx
@@ -45,7 +45,11 @@ HistogramFiller* HistogramFillerFactory::create(const HistogramDef& def) {
       return new HistogramFiller2D(def, histogramProvider);
     }
   } else if (def.type == "TProfile") {
-    return new HistogramFillerProfile(def, histogramProvider);
+    if (def.kAddBinsDynamically || def.kRebinAxes) {
+      return new HistogramFillerProfileRebinable(def, histogramProvider);
+    } else {
+      return new HistogramFillerProfile(def, histogramProvider);
+    }
   } else if (def.type == "TProfile2D") {
     return new HistogramFiller2DProfile(def, histogramProvider);
   } else if (def.type == "TEfficiency") {
diff --git a/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFillerProfile.h b/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFillerProfile.h
index b9a3e8efc679846dea687168fa1a1a2da2c2a072..81ec49c4679c53f6a0da43e6d269475489ab58ae 100644
--- a/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFillerProfile.h
+++ b/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFillerProfile.h
@@ -7,97 +7,16 @@
 
 #include "TProfile.h"
 
-#include "AthenaMonitoringKernel/HistogramFiller.h"
+#include "HistogramFiller2D.h"
+#include "HistogramFillerRebinable.h"
 #include "HistogramFillerUtils.h"
-#include "boost/range/combine.hpp"
 
 namespace Monitored {
-  /**
-   * @brief Filler for profile 1D histogram 
-   */
-  class HistogramFillerProfile : public HistogramFiller {
-  public:
-    HistogramFillerProfile(const HistogramDef& definition, std::shared_ptr<IHistogramProvider> provider)
-      : HistogramFiller(definition, provider) {}
 
-    virtual HistogramFillerProfile* clone() const override {
-      return new HistogramFillerProfile( *this );
-    }
-
-    virtual unsigned fill() override {
-      if (m_monVariables.size() != 2) {
-        return 0;
-      }
-
-      // handling of the cutmask
-      auto cutMaskValuePair = getCutMaskFunc();
-      if (cutMaskValuePair.first == 0) { return 0; }
-      auto cutMaskAccessor = cutMaskValuePair.second;
-
-      // handling of the weight
-      std::function<double(size_t)> weightAccessor = [] (size_t ){ return 1.0; };  // default is always 1.0
-      const std::vector<double> weightVector{m_monWeight ? m_monWeight->getVectorRepresentation() : std::vector<double>{}};
-      if ( m_monWeight != nullptr ) {
-        if (weightVector.size() == 1) {
-          weightAccessor = [=](size_t){ return weightVector[0]; };
-        } else {
-        	weightAccessor = [&](size_t i){ return weightVector[i]; }; 
-        }
-      }
-
-      auto histogram = this->histogram<TProfile>();
-      const auto valuesVector1{m_monVariables[0].get().getVectorRepresentation()};
-      const auto valuesVector2{m_monVariables[1].get().getVectorRepresentation()};
-      const size_t size1 = std::size(valuesVector1);
-      const size_t size2 = std::size(valuesVector2);
-      const bool isAnyVectorEmpty = size1 == 0 || size2 == 0;
-      const bool isAnyVectorScalar = size1 == 1 || size2 == 1;
-      const bool areVectorsSameSize = size1 == size2;
-      const bool areVectorsValid = !isAnyVectorEmpty && (areVectorsSameSize || isAnyVectorScalar);
-      if (!areVectorsValid) return 0;
-      if (ATH_UNLIKELY(!isAnyVectorScalar 
-                        && ((weightVector.size() > 1 && size1 != weightVector.size())
-                            || (cutMaskValuePair.first > 1 && size1 != cutMaskValuePair.first)
-                          )
-                      )
-        ) {
-        MsgStream log(Athena::getMessageSvc(), "HistogramFillerProfile");
-        log << MSG::ERROR << "Mismatch of provided vector sizes for " << m_histDef->alias << endmsg;
-        return 0;
-      }
-
-      std::scoped_lock<std::mutex> lock(*m_mutex);
-
-      if (m_histDef->kAddBinsDynamically) {
-        const auto xmax = std::max_element(begin(valuesVector1), end(valuesVector1));
-        if (Monitored::detail::shouldRebinHistogram(histogram->GetXaxis(), *xmax)) {
-          Monitored::detail::rebinHistogram<Axis::X>(histogram, *xmax);
-        }
-      }
-
-      std::function<double(size_t)> fillFunc1, fillFunc2;
-      if (size1 == 1) {
-        fillFunc1 = [=](size_t){ return valuesVector1[0]; };
-      } else {
-        fillFunc1 = [&](size_t i){ return valuesVector1[i]; };
-      }
-
-      if (size2 == 1) {
-        fillFunc2 = [=](size_t){ return valuesVector2[0]; };
-      } else {
-        fillFunc2 = [&](size_t i){ return valuesVector2[i]; };
-      }
-                  
-      size_t itrSize = std::max(size1, size2);
-      
-      for (size_t idx = 0; idx < itrSize; ++idx) {
-        if (cutMaskAccessor(idx)) {
-          histogram->Fill(fillFunc1(idx), fillFunc2(idx), weightAccessor(idx));
-        }
-      }
-      return itrSize;
-    }
-  };
+  /// TProfile filler
+  typedef HistogramFiller2DGeneric<TProfile> HistogramFillerProfile;
+  /// TProfile filler with rebinable x-axis
+  typedef HistogramFillerRebinableAxis<HistogramFillerProfile, Axis::X> HistogramFillerProfileRebinable;
 }
 
-#endif /* AthenaMonitoringKernel_HistogramFiller_HistogramFillerProfile_h */
+#endif
diff --git a/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFillerRebinable.h b/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFillerRebinable.h
index bc4fd7b6a4d340b0f9fb2fa26f1f17abc496951b..edc383946d75332f93f6ea1fb5298cd2c7db5948 100644
--- a/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFillerRebinable.h
+++ b/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFillerRebinable.h
@@ -37,7 +37,7 @@ namespace Monitored {
       return new HistogramFillerRebinableAxis( *this );
     }
 
-    virtual unsigned fill() override {
+    virtual unsigned fill() const override {
       if (AXIS >= this->m_monVariables.size()) { return 0; }
       if (this->m_monVariables[AXIS].get().size()==0) { return 0; }
 
diff --git a/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFillerTree.h b/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFillerTree.h
index c974b7cacbb9aef6331778ca3bb2273b7bc09575..103aa92b8381b7369c246d23bb543296ff769c3f 100644
--- a/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFillerTree.h
+++ b/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFillerTree.h
@@ -30,7 +30,7 @@ namespace Monitored {
       return new HistogramFillerTree( *this );
     }
 
-    virtual unsigned fill() override {
+    virtual unsigned fill() const override {
       // handling of the cutmask
       auto cutMaskValuePair = getCutMaskFunc();
       if (cutMaskValuePair.first == 0) { return 0; }
diff --git a/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFillerUtils.h b/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFillerUtils.h
index 540b8877a2f5b390a0e3db945a9b91a3ac8de537..6c77ad828701a5eeba51dc04880e4dd389294243 100644
--- a/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFillerUtils.h
+++ b/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFillerUtils.h
@@ -12,6 +12,7 @@
 #include "CxxUtils/AthUnlikelyMacros.h"
 
 #include "TH1.h"
+#include "TProfile.h"
 #include "THashList.h"
 
 namespace Monitored {
@@ -136,6 +137,25 @@ namespace Monitored {
       else return value.c_str();
     }
 
+    /**
+     * Perform generic histogram fill with weight
+     */
+    template<typename H, typename ...Ts>
+    void doFill(H* hist, double weight, const Ts&... v) {
+      hist->Fill(toFill(v)..., weight);
+    }
+
+    /**
+     * Perform TProfile fill with weight
+     */
+    template<typename X, typename Y>
+    void doFill(TProfile* hist, [[maybe_unused]] double weight, const X& x, const Y& y) {
+      // TProfile does not support string as y-value. It would never be called that way
+      // but is required to make the pack expansion compile in HistogramFiller::fill
+      if constexpr(std::is_same_v<std::string,Y>) return;
+      else hist->Fill(toFill(x), y, weight);
+    }
+
     /**
      * Generic histogram filling helper
      *
@@ -163,9 +183,9 @@ namespace Monitored {
           if ( ATH_UNLIKELY(fillWillRebinHistogram(hist, std::index_sequence_for<Vs...>{},
                                                    toFill(get(v,i))...)) ){
             oh_scoped_lock_histogram lock;
-            hist->Fill( toFill(get(v,i))..., weight(i) );
+            doFill(hist, weight(i), get(v,i)...);
           }
-          else hist->Fill( toFill(get(v,i))..., weight(i) );
+          else doFill(hist, weight(i), get(v,i)...);
         }
       }
       return fills;
diff --git a/Control/AthenaMonitoringKernel/src/HistogramFiller/VecHistogramFiller1D.h b/Control/AthenaMonitoringKernel/src/HistogramFiller/VecHistogramFiller1D.h
index f15bb17e6dda46bdb3f8e133f74a5963aa0f3627..1a712d5205f06752547208c8257ba97034dfa957 100644
--- a/Control/AthenaMonitoringKernel/src/HistogramFiller/VecHistogramFiller1D.h
+++ b/Control/AthenaMonitoringKernel/src/HistogramFiller/VecHistogramFiller1D.h
@@ -17,7 +17,7 @@ namespace Monitored {
       return new VecHistogramFiller1D( *this );
     }
 
-    virtual unsigned fill() override {
+    virtual unsigned fill() const override {
       if (m_monVariables.size() != 1) {
         return 0;
       }
diff --git a/Control/AthenaMonitoringKernel/src/HistogramFiller/VecHistogramFiller1DWithOverflows.h b/Control/AthenaMonitoringKernel/src/HistogramFiller/VecHistogramFiller1DWithOverflows.h
index 5f61219967a91dfa7858049205d8a80f507ef148..e0524711631025369486caf10ce199fb9d2152aa 100644
--- a/Control/AthenaMonitoringKernel/src/HistogramFiller/VecHistogramFiller1DWithOverflows.h
+++ b/Control/AthenaMonitoringKernel/src/HistogramFiller/VecHistogramFiller1DWithOverflows.h
@@ -17,7 +17,7 @@ namespace Monitored {
       return new VecHistogramFiller1DWithOverflows( *this );
     }
 
-    virtual unsigned fill() override {
+    virtual unsigned fill() const override {
       if (m_monVariables.size() != 1) {
         return 0;
       }
diff --git a/Control/AthenaMonitoringKernel/test/GenericMonFilling_test.cxx b/Control/AthenaMonitoringKernel/test/GenericMonFilling_test.cxx
index 770c882e4a309a3308c6fd4fc08e3fcb21e3606a..0eac712c6dbed10e5e9c959da608dc70208fbf15 100644
--- a/Control/AthenaMonitoringKernel/test/GenericMonFilling_test.cxx
+++ b/Control/AthenaMonitoringKernel/test/GenericMonFilling_test.cxx
@@ -216,7 +216,6 @@ bool fillFromScalarIndependentScopes( ToolHandle<GenericMonitoringTool>& monTool
 
 bool fill2D( ToolHandle<GenericMonitoringTool>& monTool, ITHistSvc* histSvc ) {
 
-
   auto fill = [&]() {
     //! [fill2D_correct]
     // For 2D histogram to be filled the two histogrammed variables need to be grouped.
@@ -267,6 +266,29 @@ bool fill2D( ToolHandle<GenericMonitoringTool>& monTool, ITHistSvc* histSvc ) {
   return true;
 }
 
+
+bool fillProfile( ToolHandle<GenericMonitoringTool>& monTool, ITHistSvc* histSvc ) {
+
+  auto fill = [&]() {
+    auto pt = Monitored::Scalar<double>( "pt", 3.0 );
+    auto eta = Monitored::Scalar( "Eta", 0.2 );
+    auto group = Monitored::Group( monTool, eta, pt );
+    return 1;
+  };
+
+  auto check = [&](size_t N) {
+    VALUE( contentInBin1DHist( histSvc, "/EXPERT/TestGroup/pt_vs_Eta", 1 ) ) EXPECTED( 0 );
+    VALUE( contentInBin1DHist( histSvc, "/EXPERT/TestGroup/pt_vs_Eta", 2 ) ) EXPECTED( 3 );
+    VALUE( getHist( histSvc, "/EXPERT/TestGroup/pt_vs_Eta" )->GetEntries() ) EXPECTED( N );
+  };
+
+  resetHists( histSvc ); check(fill());
+  resetHists( histSvc ); check(fill_mt(fill));
+
+  return true;
+}
+
+
 bool fillExplicitly( ToolHandle<GenericMonitoringTool>& monTool, ITHistSvc* histSvc ) {
   resetHists( histSvc );
   //! [fillExplicitly_noop]
@@ -726,6 +748,8 @@ int main() {
   assert( fillFromScalarIndependentScopes( validMon, histSvc ) );
   log << MSG::DEBUG << "fill2D" << endmsg;
   assert( fill2D( validMon, histSvc ) );
+  log << MSG::DEBUG << "fillProfile" << endmsg;
+  assert( fillProfile( validMon, histSvc ) );
   log << MSG::DEBUG << "fillExplicitly" << endmsg;
   assert( fillExplicitly( validMon, histSvc ) );
   log << MSG::DEBUG << "fillWithCutMask" << endmsg;
diff --git a/Control/AthenaMonitoringKernel/test/HistogramFillerFactoryTestSuite.cxx b/Control/AthenaMonitoringKernel/test/HistogramFillerFactoryTestSuite.cxx
index 7581c7d5421e3d1985f7dbc8c3258e7901459488..69139ffe9807fbfbb668458720e80c97f8c0f168 100644
--- a/Control/AthenaMonitoringKernel/test/HistogramFillerFactoryTestSuite.cxx
+++ b/Control/AthenaMonitoringKernel/test/HistogramFillerFactoryTestSuite.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #undef NDEBUG
@@ -48,7 +48,7 @@ class HistogramProviderGetter : public HistogramFiller {
     HistogramProviderGetter(const HistogramFiller& hf) 
       : HistogramFiller(hf) {}
 
-    virtual unsigned fill() { return 0; }
+    virtual unsigned fill() const { return 0; }
     virtual HistogramFiller* clone() const { return nullptr; }
 
     std::shared_ptr<IHistogramProvider> histogramProvider() { return m_histogramProvider; }