diff --git a/hist/hist/src/TAxis.cxx b/hist/hist/src/TAxis.cxx index 5b6c0ae65dff9..9ac1d453857bf 100644 --- a/hist/hist/src/TAxis.cxx +++ b/hist/hist/src/TAxis.cxx @@ -27,6 +27,7 @@ #include "snprintf.h" #include +#include #include #include @@ -779,10 +780,20 @@ void TAxis::SaveAttributes(std::ostream &out, const char *name, const char *subn //////////////////////////////////////////////////////////////////////////////// /// Initialize axis with fix bins +/// +/// An error is printed if xup or xlow are infinite/nan +/// (due to resulting undefined fixed bin width) +/// +/// Set xup <= xlow to force the axis range and number of bins to be automatically +/// deduced after buffer is full or BufferEmpty is called void TAxis::Set(Int_t nbins, Double_t xlow, Double_t xup) { fNbins = nbins; + if (std::isinf(xlow) || std::isinf(xup)) + Error("TAxis::Set", "fixed binwidth not compatible with infinite lower/upper edges"); + if (std::isnan(xlow) || std::isnan(xup)) + Error("TAxis::Set", "lower/upper edges should not be NaN"); fXmin = xlow; fXmax = xup; if (!fParent) SetDefaults(); @@ -791,17 +802,26 @@ void TAxis::Set(Int_t nbins, Double_t xlow, Double_t xup) //////////////////////////////////////////////////////////////////////////////// /// Initialize axis with variable bins +/// +/// An error is printed if bin edges are not in strictly increasing order +/// or if any of them is infinite or nan void TAxis::Set(Int_t nbins, const Float_t *xbins) { Int_t bin; fNbins = nbins; fXbins.Set(fNbins+1); - for (bin=0; bin<= fNbins; bin++) + for (bin = 0; bin <= fNbins; bin++) { + if (std::isinf(xbins[bin])) { + Error("TAxis::Set", "infinite bin edges are not supported. Use a large number instead."); + } else if (std::isnan(xbins[bin])) { + Error("TAxis::Set", "bin edges should not be NaN"); + } fXbins.fArray[bin] = xbins[bin]; + } for (bin=1; bin<= fNbins; bin++) if (fXbins.fArray[bin] <= fXbins.fArray[bin - 1]) - Error("TAxis::Set", "bins must be in increasing order"); + Error("TAxis::Set", "bin edges must be in increasing order"); fXmin = fXbins.fArray[0]; fXmax = fXbins.fArray[fNbins]; if (!fParent) SetDefaults(); @@ -819,7 +839,7 @@ void TAxis::Set(Int_t nbins, const Double_t *xbins) fXbins.fArray[bin] = xbins[bin]; for (bin=1; bin<= fNbins; bin++) if (fXbins.fArray[bin] <= fXbins.fArray[bin - 1]) - Error("TAxis::Set", "bins must be in increasing order"); + Error("TAxis::Set", "bin edges must be in increasing order"); fXmin = fXbins.fArray[0]; fXmax = fXbins.fArray[fNbins]; if (!fParent) SetDefaults(); diff --git a/hist/hist/src/TH2Poly.cxx b/hist/hist/src/TH2Poly.cxx index 0ee3531957bf8..c5f93aec99da0 100644 --- a/hist/hist/src/TH2Poly.cxx +++ b/hist/hist/src/TH2Poly.cxx @@ -146,7 +146,7 @@ times, it is better to divide into a small number of cells. TH2Poly::TH2Poly() { - Initialize(0., 0., 0., 0., 25, 25); + Initialize(0., 0., 0., 0., 25, 25); // automatic axis range calculation SetName("NoName"); SetTitle("NoTitle"); SetFloat(); diff --git a/hist/hist/test/test_TH1.cxx b/hist/hist/test/test_TH1.cxx index 73d4ba9f5cef1..f7a180894f5ff 100644 --- a/hist/hist/test/test_TH1.cxx +++ b/hist/hist/test/test_TH1.cxx @@ -318,5 +318,9 @@ TEST(TH1, SetBufferedSumw2) // https://github.com/root-project/root/issues/20185 TEST(TAxis, EqualBinEdges) { - ROOT_EXPECT_ERROR(TAxis _({1, 1}), "TAxis::Set", "bins must be in increasing order"); + ROOT_EXPECT_ERROR(TAxis _({1, 1}), "TAxis::Set", "bin edges must be in increasing order"); + ROOT_EXPECT_ERROR(TAxis _(1, -std::numeric_limits::infinity(), 0), "TAxis::Set", "fixed binwidth not compatible with infinite lower/upper edges"); + ROOT_EXPECT_ERROR(TAxis _(1, 0., std::numeric_limits::infinity()), "TAxis::Set", "fixed binwidth not compatible with infinite lower/upper edges"); + ROOT_EXPECT_ERROR(TAxis _(1, std::numeric_limits::quiet_NaN(), 0), "TAxis::Set", "lower/upper edges should not be NaN"); + ROOT_EXPECT_ERROR(TAxis _(1, 0, std::numeric_limits::quiet_NaN()), "TAxis::Set", "lower/upper edges should not be NaN"); } diff --git a/test/stressHistogram.cxx b/test/stressHistogram.cxx index bfb7361a83806..93c5d7e366d4d 100644 --- a/test/stressHistogram.cxx +++ b/test/stressHistogram.cxx @@ -6269,7 +6269,7 @@ bool testMerge1DWithBuffer(bool allNoLimits) // where different axis are used, BUT the largest bin width must be // a multiple of the smallest bin width - double x1 = 1; double x2 = 0; + double x1 = 1; double x2 = 0; // i.e. automatic axis range calculation if (!allNoLimits) { // case when one of the histogram has limits (mix mode) x1 = minRange; x2 = maxRange; @@ -6277,18 +6277,18 @@ bool testMerge1DWithBuffer(bool allNoLimits) TH1D* h0 = new TH1D("h0", "h0-Title", numberOfBins, 1, 0); TH1D* h1 = new TH1D("h1", "h1-Title", numberOfBins, x1, x2); - TH1D* h2 = new TH1D("h2", "h2-Title", 1,1,0); - TH1D* h3 = new TH1D("h3", "h3-Title", 1,1,0); - TH1D* h4 = new TH1D("h4", "h4-Title", numberOfBins, x1,x2); + TH1D* h2 = new TH1D("h2", "h2-Title", 1, 1, 0); + TH1D* h3 = new TH1D("h3", "h3-Title", 1, 1, 0); + TH1D* h4 = new TH1D("h4", "h4-Title", numberOfBins, x1, x2); h0->Sumw2(); h1->Sumw2();h2->Sumw2();h4->Sumw2(); // The below histograms will be merged into h0, so they all need to fit into the buffer. // Otherwise, the axis ranges will be computed already during the partial merge. h0->SetBuffer(nEvents * 10); - h1->SetBuffer(nEvents*10); - h2->SetBuffer(nEvents*10); - h3->SetBuffer(nEvents*10); - h4->SetBuffer(nEvents*10); + h1->SetBuffer(nEvents * 10); + h2->SetBuffer(nEvents * 10); + h3->SetBuffer(nEvents * 10); + h4->SetBuffer(nEvents * 10); for ( Int_t e = 0; e < nEvents; ++e ) {