Draw overflow bin

Hi,

I was wondering if there’s a way to get ROOT to show the contents of the overflow bin when drawing the histogram? I know that I can go through all my histograms and set the last bin by hand (using SetBinContent), but I was wondering whether there’s a general flag that I could set somewhere without changing the contents of the histogram itself?

Thanks a lot!
Heather

[root.cern.ch/root/htmldoc/TStyle ... SetOptStat](http://root.cern.ch/root/htmldoc/TStyle.html#TStyle:SetOptStat)

Jan

root.cern.ch/root/htmldoc/TStyle … SetOptStat

Jan

Hello All,

Is there a way to show overflow as an additional bin?

Thanks,
Raz

void overflow()
{
  c1 = new TCanvas("c1","Overflow",200,10,700,700);
//c1->Divide(1,2);

  hpx    = new TH1F("hpx","This is the px distribution",50,-4,4);

  gRandom->SetSeed();
  Float_t px,py;
  for (Int_t i = 0; i < 25000; i++) {
     gRandom->Rannor(px,py);
     Float_t random = gRandom->Rndm(1);
     hpx->Fill(px);
     hpx->Fill(px+10,0.01);
     hpx->Fill(px-10,0.01);
  }
  gStyle->SetOptStat(111111);

//c1->cd(1);
//hpx->Draw();

//c1->cd(2);
  PaintOverflow(hpx);
}

void PaintOverflow(TH1 *h)
{
   // This function paint the histogram h with an extra bin for overflows

   char* name  = h->GetName();
   char* title = h->GetTitle();
   Int_t nx    = h->GetNbinsX()+1;
   Double_t x1 = h->GetBinLowEdge(1);
   Double_t bw = h->GetBinWidth(nx);
   Double_t x2 = h->GetBinLowEdge(nx)+bw;

   // Book a temporary histogram having ab extra bin for overflows
   TH1F *htmp = new TH1F(name, title, nx, x1, x2);

   // Fill the new hitogram including the extra bin for overflows
   for (Int_t i=1; i<=nx; i++) {
      htmp->Fill(htmp->GetBinCenter(i), h->GetBinContent(i));
   }

   // Fill the underflows
   htmp->Fill(x1-1, h->GetBinContent(0));

   // Restore the number of entries
   htmp->SetEntries(h->GetEntries());

   // Draw the temporary histogram
   htmp->Draw();
   TText *t = new TText(x2-bw/2,h->GetBinContent(nx),"Overflow");
   t->SetTextAngle(90);
   t->SetTextAlign(12);
   t->SetTextSize(0.03);;
   t->Draw();
}

Thanks,

I was hoping there would be a more native way to do this.

Raz

No, nothing native.

I wrote down a better function. It can deal with non-uniform bins, make axises’ labels correctly, and reset the handle of the histogram to avoid further problems.

TH1F * DrawOverflow(TH1F *h)
{
   // This function paint the histogram h with an extra bin for overflows
   UInt_t nx    = h->GetNbinsX()+1;
   Double_t *xbins= new Double_t[nx+1];
   for (UInt_t i=0;i<nx;i++)
     xbins[i]=*(h->GetXaxis()->GetXbins()->GetArray()+i);
   xbins[nx]=xbins[nx-1]+h->GetBinWidth(nx);
   char *tempName= new char[strlen(h->GetName())+10];
   sprintf(tempName,"%swtOverFlow",h->GetName());
   // Book a temporary histogram having ab extra bin for overflows
   TH1F *htmp = new TH1F(tempName, h->GetTitle(), nx, xbins);
   // Reset the axis labels
   htmp->SetXTitle(h->GetXaxis()->GetTitle());
   htmp->SetYTitle(h->GetYaxis()->GetTitle());
   // Fill the new hitogram including the extra bin for overflows
   for (UInt_t i=1; i<=nx; i++) 
     htmp->Fill(htmp->GetBinCenter(i), h->GetBinContent(i));
   // Fill the underflows
   htmp->Fill(h->GetBinLowEdge(1)-1, h->GetBinContent(0));
   // Restore the number of entries
   htmp->SetEntries(h->GetEntries());
   // Draw the temporary histogram
   return htmp;
}

Ok, if it works for you it is good. I quickly tried your function in my initial macro and I get a segmentation violation. I have not investigate further. As I said if it is fine for you that’s ok. May be you use it in a different context.

This should fix the segment violation:

TH1F * DrawOverflow(TH1F *h)
{
      // This function paint the histogram h with an extra bin for overflows
   UInt_t nx    = h->GetNbinsX()+1;
   Double_t *xbins= new Double_t[nx+1];
   for (UInt_t i=0;i<nx;i++)
     xbins[i]=h->GetBinLowEdge(i+1);
   xbins[nx]=xbins[nx-1]+h->GetBinWidth(nx);
   char *tempName= new char[strlen(h->GetName())+10];
   sprintf(tempName,"%swtOverFlow",h->GetName());
   // Book a temporary histogram having ab extra bin for overflows
   TH1F *htmp = new TH1F(tempName, h->GetTitle(), nx, xbins);
   // Reset the axis labels
   htmp->SetXTitle(h->GetXaxis()->GetTitle());
   htmp->SetYTitle(h->GetYaxis()->GetTitle());
   // Fill the new hitogram including the extra bin for overflows
   for (UInt_t i=1; i<=nx; i++)
     htmp->Fill(htmp->GetBinCenter(i), h->GetBinContent(i));
   // Fill the underflows
   htmp->Fill(h->GetBinLowEdge(1)-1, h->GetBinContent(0));
   // Restore the number of entries
   htmp->SetEntries(h->GetEntries());
   // FillStyle and color
   htmp->SetFillStyle(h->GetFillStyle());
   htmp->SetFillColor(h->GetFillColor());
   return htmp;
}

This line is not safe in some root versions, but why not make it native in the draw option?

I want to support this question/request. It would be nice to have an option in Draw()

Because the macro is really simple. Moreover there is surely many ways to represent the overflows and we will end up with a huge collection of options. With a simple macro like that, users can customize as they wish the way it is drawn. You can had this macro in your basic tools. The typing you have to do is the same:

.x DrawOverflow(h)

instead of:

h1->Draw("…");

Ok, that make sense, I’ll have my own macro.
Thanks

Hi,

In the above example if histogram *h is already filled with some weights then how the new histogram *htmp should set the error on new bin content after doing division/addition of ovr flow bin?

thanks
sushil

Hello all,

I found this thread as I was looking for a way to draw overflow bin.
I tried the macros you proposed and I found some problems regarding the reset of the number of entries of the new histogram and the way in which the errors are propagated by using the Fill method.
Concerning the number of entries, the previous macro posted here says htmp->SetEntries(h->GetEntries()). This is ok just in case the original histogram is filled with weight=1. In the case in which weights!=1, it is correct using GetEffectiveEntries() which returns the square of sum of the weights divided by the sum of the weights square (as Lorenzo Moneta explains in this thread [url]TH1D: integral + underflow + overflow != entries Regarding the Fill(), I substituted that part of the code with SetBinContent() and SetBinError() methods. This is the only way I found to restore the uncertainties properly.
I put here an updated version of the macro, in case it might be useful for anyone.

   TH1F *DrawOverflow(TH1F* h){
    //function to paint the histogram h with an extra bin for overflows
    UInt_t nx    = h->GetNbinsX()+1;
    Double_t *xbins= new Double_t[nx+1];
    for (UInt_t i=0;i<nx;i++)
        xbins[i]=h->GetBinLowEdge(i+1);
    xbins[nx]=xbins[nx-1]+h->GetBinWidth(nx);
    //book a temporary histogram having extra bins for overflows
    TH1F *htmp = new TH1F(h->GetName(), h->GetTitle(), nx, xbins);
    htmp->Sumw2();
    //fill the new histogram including the overflows
    for (UInt_t i=1; i<=nx; i++) {
        htmp->SetBinContent(htmp->FindBin(htmp->GetBinCenter(i)),h->GetBinContent(i));
        htmp->SetBinError(htmp->FindBin(htmp->GetBinCenter(i)),h->GetBinError(i));
    }
    htmp->SetBinContent(htmp->FindBin(h->GetBinLowEdge(1)-1), h->GetBinContent(0));
    htmp->SetBinError(htmp->FindBin(h->GetBinLowEdge(1)-1), h->GetBinError(0));
    // Restore the number of entries
    htmp->SetEntries(h->GetEffectiveEntries());
    return htmp;
}

Cheers,
Lucia

1 Like

Thanks :slight_smile:

h->GetXaxis()->SetRange(1, h->GetNbinsX() + 1);
h->Draw(); // will draw with the overflow bin
1 Like

Hi,

It’s hard to believe that this took so many years to get a reasonable answer.

import ROOT
import numpy

h=ROOT.TH1F('h', '', 10, 0, 1)
for val in numpy.random.normal(0, 0.5, 10000):
    h.Fill(val)

c=ROOT.TCanvas('c', '', 600, 600)

h.GetXaxis().SetRangeUser(-1, 11) 
h.Draw()

c.SaveAs('plot.png')

The code above shows how to get the overflow and underflow bins drawn easily.

How could it be that such a trivial task gave rise to a long thread and a bunch of bad/long/complicated code?

Cheers.