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?
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();
}
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.
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?
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:
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?
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;
}