Resetting the bin content and recalling the bin content error

Imagine I created an histogram h1. Then, I set my bin contents and errors by myself by using SetBinContent(…) and SetBinError(…) functions. Then, I clone this histogram by giving a new name like h2. I changed the 2nd bin content with SetBinContent(2, 10) option as the value of 10. It was different value before. I noticed that bin error couldn’t recalculated by itself. Thus, I set it by myself again.

If I scale the h1 with 2 to create h4 , the error is recalculated by itself at this timre. Why I couldn’t get it in the 1st case. I used h2->Sumw2(); earlier in the code to make sure it recalculates the errors.

TH1F h2 = (TH1F)h1->Clone(“h2”);
h2->SetBinContent(2, 10);
h2->SetBinError(2, 10./100.);
cout << "\tContentError1: " << h2->GetBinError(1) << "\tContentError2: " << h2->GetBinError(2)<< endl;

TH1F h4 = (TH1F)h1->Clone(“h4”);
cout << "\tContentError1: " << h4->GetBinError(1) << "\tContentError2: " << h4->GetBinError(2)<< endl;

Hi @spyhunter01,
@moneta can probably help here.



I am not sure I have understood your problem, maybe posting a full working macro could help.

After calling SetBinError, errors are computed from the stored values (fSumw2 array, which keeps the square of the bin errors).
When you scale the histogram the array is also scaled in order to get the scaled errors. So if you have set the bin error to a value error , after scaling the error will be scale_factor * error.
If you have never set the bin errors in your histograms, the errors will be computed as sqrt(bin_content). If you set the bin error for only some bins, the errors will be by default zero for the other bins.



#include “TAttMarker.h”
#include “TCanvas.h”
#include “TLatex.h”
#include “TDirectory.h”
#include “TAxis.h”
#include //string
#include “TH1F.h”
#include “TH2F.h”
#include “TF1.h”
#include “TChain.h”
#include “TStyle.h” //for gStyle decleration
#include “TMath.h”
#include “TRandom.h”
#include “TAxis.h”
int testbinning()


TCanvas *c1 = new TCanvas(“c1”, “c1”,0,75,3665,2044);
float pad_x1= 0.05, pad_x2= 0.5 , pad_x3= 0.95, pad_y1= 0.5, pad_y2= 0.95, pad_y3= 0.05 ;
TPad *c1_1 = new TPad(“c1_1”, “newpad”, pad_x1, pad_y1, pad_x2, pad_y2);
TPad *c1_2 = new TPad(“c1_2”, “newpad”, pad_x2, pad_y1, pad_x3, pad_y2);
TPad *c1_3 = new TPad(“c1_3”, “newpad”, pad_x1, pad_y3, pad_x2, pad_y1);
TPad *c1_4 = new TPad(“c1_4”, “newpad”, pad_x2, pad_y3, pad_x3 ,pad_y1);

const char *name=“name”;
const char *title=“title”;
Int_t BinWidth= 1;
Double_t hist_lower_xlimit=5.;
Double_t hist_upper_xlimit=11. ;
int NbinsX = TMath::Ceil((hist_upper_xlimit-hist_lower_xlimit) / BinWidth );

TH1Fh1= new TH1F( name,title,NbinsX,hist_lower_xlimit,hist_upper_xlimit); //TH1F : histograms with one float per channel. Maximum precision 7 digits
xAxis = h1->GetXaxis();
for(double i= hist_lower_xlimit ; i < hist_upper_xlimit ; i++){
h1->Fill(i, i+20);
for(int i=0 ; i <= h1->GetNbinsX() ; i++){

h1->SetBinContent(i, i+20);
h1->SetBinError(i, (i+20)/100.);


c1_1->Modified(); //retain


int binx1= xAxis->FindBin(hist_lower_xlimit); //FindBin (Double_t x, Double_t y=0, Double_t z=0) Return Global bin number corresponding to x,y,z
cout << "\n\nTotal bin number ROOT finds: " << h1->GetNbinsX()<<endl;
cout << “To compare with my calculation of bin number:” << NbinsX << endl;
cout << "Bin width ROOT calculates: "<< h1->GetBinWidth(1) << endl; //GetBinWidth(bin no)
cout << "To compare with my bin width: " << BinWidth << endl;
cout << “hist_lower_xlimit= “<<hist_lower_xlimit<<” related bin number:”<< binx1<<endl;
cout << “To find the X value details from the bin INFO:”<< endl;
cout << "X Lower edge: " << xAxis->GetBinLowEdge(binx1) << endl;
cout << "X Center: " << xAxis->GetBinCenter(binx1) << endl;
cout << "X Upper edge: " << xAxis->GetBinUpEdge(binx1) << endl;
cout << "Bin content from bin no: " << h1->GetBinContent(binx1) << endl;
cout << "Bin content error from bin no: “<<binx1 <<” : " << h1->GetBinError(binx1) << endl;
cout << "Bin content error from bin no: “<< 2 <<” : " << h1->GetBinError(2) << endl;
cout << "Bin content from integral of binx1-binx1 range: "<< h1->Integral(binx1,binx1) << endl;

//GetBinContent (Int_t bin) const ,Return content of bin number whatever bin is.


TH1F h2 = (TH1F)h1->Clone(“h2”);
//c1->Update(); // or create a pad and clear before drawing the 2nd one
cout<<"\nLet’s merge 2 bins into one bin."<<endl;
h2->Rebin(2.); //merge 2 bins into one bin. //
cout<< "\n\n\nTotal bin number: " << h2->GetNbinsX()<< endl;
//cout<<“Only 1st bin content is changed.”<<endl;
cout << "\tContent1: " << h2->GetBinContent(1) << "\tContent2: " << h2->GetBinContent(2)<< endl;
cout << "\tContentError1: " << h2->GetBinError(1) << "\tContentError2: " << h2->GetBinError(2)<< endl;
//c1->Modified(); //not working
cout<< "integral of 1-2 bins: "<< h2->Integral(1,2) << endl;
c1_2->Modified(); // koru , kaybetme , retain


TH1F h3 = (TH1F)h1->Clone(“h3”);
h3->SetBinContent(2, 10);
h3->SetBinError(2, 10./100.);
cout<<"\n\nOnly 2nd bin content is changed."<<endl;
cout << "\tContent1: " << h3->GetBinContent(1) << "\tContent2: " << h3->GetBinContent(2)<<endl;
cout << "\tContentError1: " << h3->GetBinError(1) << "\tContentError2: " << h3->GetBinError(2)<< endl;
cout<< "integral of 1-2 bins: "<< h3->Integral(1,2) << " integral of 2-3 bins: "<< h3->Integral(2,3) << " integral of 3-4 bins: "<< h3->Integral(3,4) << endl;
c1_3->Modified(); // koru , kaybetme , retain

TH1F h4 = (TH1F)h1->Clone(“h4”);
cout << "\n\nNew Scaled Content1: " << h4->GetBinContent(1) << "\tContent2: " << h4->GetBinContent(2)<< endl;
cout << "\tContentError1: " << h4->GetBinError(1) << "\tContentError2: " << h4->GetBinError(2)<< endl;
cout<< "integral of 1-2 bins: "<< h4->Integral(1,2) << endl;
c1_4->Modified(); // retain
c1->Modified(); // retain

return 0;

I posted the code that I was testing some options. I clone the 1st histogram for h3, then I only set up the 2nd bin’s error and content. The errors of the other bins didn’t become 0 as you said. They kept the original histogram h1’s information.

Another think I want to ask is about Sumw2(). When I got warning saying that I have created it already even if I typed it only one tiöe in the whole code.



Thank you for posting your code, but do not paste as text as it becomes unreadable and one cannot execute. Use code tags (```) or add the code as a file attachment.
See Tips for Efficient and Successful Posting

Concerning your questions:

  • when you call SetBinError(…), Sumw2() is called internally, since the array needs to be created to store the errors so you don’t need to call it again.
  • In my previous quote:

it is true I did not explain correctly. The errors by default are computed as sqrt(bin_content). If you have an already filled histograms (i.e. with content not equal to zero) and you call SetBinError on some bins, the error will be computed as default as sqrt(bin_content) for all bins where you have not called SetBinError. However, if you have an empty bin and then you call SetBinContent to fill that bin, and you have called before SetBinError for some another bins, the error will be zero for the bin where you have called just SetBinContent.


This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.