From 44a7b478dfd014d3c4da8717898187a204708baf Mon Sep 17 00:00:00 2001
From: moneta <lorenzo.moneta@cern.ch>
Date: Wed, 30 May 2018 11:11:21 +0200
Subject: [PATCH] Fix the protected function Th1::IsEmpty used in TH1Merger for
 the case when both fTSumw=0 and fEntries=0, but in reality the bin contents
 are not zero. Add in this case a check to all bin contents, including
 underflow/overflows Fix also TH1::GetStats() for the case of labels
 histograms.  In this case when you have   fTSumw=0  and fEntries !=0 (for
 example after calling SetBinContent) you want to compute the correct fTsumw
 and fTsumw2 values

---
 hist/hist/inc/TH1.h   |  2 +-
 hist/hist/src/TH1.cxx | 43 ++++++++++++++++++++++++++++++-------------
 2 files changed, 31 insertions(+), 14 deletions(-)

diff --git a/hist/hist/inc/TH1.h b/hist/hist/inc/TH1.h
index 68bdc6d33c6..8acf0c3663f 100644
--- a/hist/hist/inc/TH1.h
+++ b/hist/hist/inc/TH1.h
@@ -135,7 +135,7 @@ protected:
    virtual void     SavePrimitiveHelp(std::ostream &out, const char *hname, Option_t *option = "");
    static Bool_t    RecomputeAxisLimits(TAxis& destAxis, const TAxis& anAxis);
    static Bool_t    SameLimitsAndNBins(const TAxis& axis1, const TAxis& axis2);
-   Bool_t   IsEmpty() const { return fTsumw == 0 && GetEntries() == 0; } //need to use GetEntries() in case of buffer histograms
+   Bool_t   IsEmpty() const;
 
    inline static Double_t AutoP2GetPower2(Double_t x, Bool_t next = kTRUE);
    inline static Int_t AutoP2GetBins(Int_t n);
diff --git a/hist/hist/src/TH1.cxx b/hist/hist/src/TH1.cxx
index aa2477b4d77..2d15e07d6ab 100644
--- a/hist/hist/src/TH1.cxx
+++ b/hist/hist/src/TH1.cxx
@@ -1646,8 +1646,7 @@ bool TH1::CheckConsistency(const TH1* h1, const TH1* h2)
    if (dim > 2) ret &= CheckBinLimits(h1->GetZaxis(), h2->GetZaxis());
 
    // check labels if histograms are both not empty
-   if ( (h1->fTsumw != 0 || h1->GetEntries() != 0) &&
-        (h2->fTsumw != 0 || h2->GetEntries() != 0) ) {
+   if ( !h1->IsEmpty() && !h2->IsEmpty() ) {
       ret &= CheckBinLabels(h1->GetXaxis(), h2->GetXaxis());
       if (dim > 1) ret &= CheckBinLabels(h1->GetYaxis(), h2->GetYaxis());
       if (dim > 2) ret &= CheckBinLabels(h1->GetZaxis(), h2->GetZaxis());
@@ -4889,6 +4888,25 @@ Double_t TH1::Interpolate(Double_t, Double_t, Double_t)
    return 0;
 }
 
+///////////////////////////////////////////////////////////////////////////////
+/// Check if an histogram is empty
+///  (this a protected method used mainly by TH1Merger )
+
+Bool_t TH1::IsEmpty() const
+{
+   // if fTsumw or fentries are not zero histogram is not empty
+   // need to use GetEntries() instead of fEntries in case of bugger histograms
+   // so we will flash the buffer
+   if (fTsumw != 0) return kFALSE;
+   if (GetEntries() != 0) return kFALSE;
+   // case fTSumw == 0 amd entries are also zero
+   // this should not really happening, but if one sets content by hand
+   // it can happen. a call to ResetStats() should be done in such cases
+   double sumw = 0; 
+   for (int i = 0; i< GetNcells(); ++i) sumw += RetrieveBinContent(i);
+   return (sumw != 0) ? kFALSE : kTRUE;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 /// Return true if the bin is overflow.
 
@@ -7202,15 +7220,11 @@ void TH1::GetStats(Double_t *stats) const
    Int_t bin, binx;
    Double_t w,err;
    Double_t x;
-   // case of labels with extension of axis range
-   // statistics in x does not make any sense - set to zero
-   if ((const_cast<TAxis&>(fXaxis)).GetLabels() && CanExtendAllAxes() ) {
-      stats[0] = fTsumw;
-      stats[1] = fTsumw2;
-      stats[2] = 0;
-      stats[3] = 0;
-   }
-   else if ((fTsumw == 0 && fEntries > 0) || fXaxis.TestBit(TAxis::kAxisRange)) {
+   // identify the case of labels with extension of axis range
+   // in this case the statistics in x does not make any sense
+   Bool_t labelHist =  ((const_cast<TAxis&>(fXaxis)).GetLabels() && CanExtendAllAxes() );
+   // fTsumw == 0 && fEntries > 0 is a special case when uses SetBinContent or calls ResetStats before
+   if ((fTsumw == 0 && fEntries > 0) || ( fXaxis.TestBit(TAxis::kAxisRange) && !labelHist) ) {
       for (bin=0;bin<4;bin++) stats[bin] = 0;
 
       Int_t firstBinX = fXaxis.GetFirst();
@@ -7228,8 +7242,11 @@ void TH1::GetStats(Double_t *stats) const
          err = TMath::Abs(GetBinError(binx));
          stats[0] += w;
          stats[1] += err*err;
-         stats[2] += w*x;
-         stats[3] += w*x*x;
+         // statistics in x makes sense only for not labels histograms
+         if (!labelHist)  { 
+            stats[2] += w*x;
+            stats[3] += w*x*x;
+         }
       }
       // if (stats[0] < 0) {
       //    // in case total is negative do something ??
-- 
GitLab