Using SetLimits() changes the histogram

In trying to compare two histograms, I notice that when I change the limits of the histogram so that I can draw them on the same canvas that it changes their distribution and maxima. I thought maybe this was a problem with histograms, so I tried a THStack but that gave me the same problems.

Is this a known problem with SetLimits()? Is there some sort of workaround? I’ve put my code below to reproduce what’s showing two different maxima after the change in limits.

#include <iostream>
#include "TFile.h"
#include "TH1.h"
using namespace std;

int main(){
    TFile *f = new TFile("temp.root");
    if (f == NULL) return 0;
    
    TH1F *hist = (TH1F*)f->Get("EBRecHits");
    if (hist == NULL) return 0;
    
    hist->BufferEmpty(-1);
    cout << hist->GetMaximum() << endl;
    
    hist->GetXaxis()->SetLimits(250, 950);
    hist->BufferEmpty(-1);
    
    cout << hist->GetMaximum() << endl;
    
    return 0;
}

temp.root (6.1 KB)

I’ve tried using SetRangeUser(), but that doesn’t change the limits and I get some incorrect histograms when drawn regularly and warnings when tried with a THStack.

(I’m mostly concerned that the distribution was changing because I was under the impression that once the histogram is filled, the histogram is unaware of the specific bin contents and cannot redistribute like this. If this is wrong, it would explain my problem.)

hist.pdf (14.2 KB) histAfterLimits.pdf (14.1 KB)


Please read tips for efficient and successful posting and posting code

ROOT Version: ROOT 6.02/05
Compiler: GCC 4.9.1


I think @moneta can help you.

Hi

If you want to change the axis range, you should use TAxis::SetRange or TAxis::SetRangeUser or TH1::SetAxisRange not SetLimits. Taxis::SetLimits (like also TH1::SetBins) should be used only when the histogram is empty. They will change the axis, but not the content and therefore will give you a wrong histogram.

I tried replacing SetLimits with each of these functions, but the resulting “histAfterLimits.pdf” that I create is identical to the first and the axis was not changed at all.

I think I understand what is happening in your case.
Your histogram contains a buffer (all the unbinned data used to fill the histogram).

In that case you have two possibility:

  • before emptying the buffer you can set the axis as you wish, setting number of bins, axis minimum and maximum. After empty the buffer, i.e. after having called hist->BufferEmpty(), you cannot change it anymore. This seems to be your case, but in the second you will have like a different histogram because the bin size is different in your two cases

  • Empty the buffer using the automatic axis limits computation and then zoom the axis using Taxis::SetRange. Note that will work only after having called TH1::BufferEmpty.
    Note that when drawing the histogram TH1::BufferEmpty is called automatically.

Lorenzo

Both of these options are still giving me unchanged histograms, sadly.

If what you’re saying about the buffer is true, would that mean that the “histAfterLimits.pdf” that is drawn after TAxis::SetLimits is called is correct, just re-binned using the buffer?

Hi,

I would need then to see your full code to understand where the mistake is.
Looking at the two pdf files, they look both correct to me, but the bin sizes are different.

Lorenzo

hist->BufferEmpty(1); // histogram is filled and buffer is deleted

This is the code I used to create the original pdf files attached to the question. I tried each of your methods to find a fix, but each time my “histAfterLimits.pdf” would print the same pdf as “hist.pdf” with no change.

#include <iostream>
#include "TFile.h"
#include "TH1.h"
using namespace std;

int main(){
    TCanvas *c = new TCanvas("c", "Canvas");
    TFile *f = new TFile("temp.root");
    if (f == NULL) return 0;
    
    TH1F *hist = (TH1F*)f->Get("EBRecHits");
    if (hist == NULL) return 0;
    
    hist->BufferEmpty(-1);
    cout << hist->GetMaximum() << endl;
    hist->Draw();
    c->SaveAs("hist.pdf");
        
    hist->GetXaxis()->SetRange(250, 950);
    hist->BufferEmpty(-1);

    cout << hist->GetMaximum() << endl;
    hist->Draw();
    c->SaveAs("histAfterLimits.pdf");
        
    return 0;
}

Ah… then I am definitely concerned as to why the distribution changes form after the limits are changed.

TH1::BufferEmpty

I just looked at that, it looks like the buffer is only deleted if I use hist->BufferEmpty(1), but I’ve been using hist->BufferEmpty(-1) to empty it instead.

Edit: Ah, I see. I misread your earlier comment. I’ll try using 1 instead.