Dear experts,
I have two TH1F histograms with Poisson errors (obtained via hist->SetBinErrorOption(TH1::kPoisson)
). The Sumw2()
is not explicitly called for them on purpose.
Now, I would like to perform a histogram division that correctly propagates the errors. While this works on a technical level (insofar as no errors or warnings occur when calling hist_num->Divide(hist_den)
), the resulting bin errors turn out to be incorrect. Most strikingly, the lower bin errors are zero if the resulting histogram bins are smaller than one.
Please see an attached minimal example that reproduces this behavior and its pasted output below.
Could you point me towards a possible solution and tell me how to obtain the result that I need (i.e., a TH1 object with correct bin errors that is the ratio of two histograms with Poisson errors).
I haven’t been able to find a workaround that produces a suited TH1 object as the result, in particular because needed functions like TH1::SetBinErrorLow(Int_t, Double_t)
and TH1::SetBinErrorUp(Int_t, Double_t)
do not exist (in contrast to their getter functions) and there seem to be no obvious way how to set lower and upper errors manually. Further, any initial call of the Sumw2()
function does not give me the desired result as this leads to asymmetric errors being ignored altogether further downstream.
I am aware of the existing functionality of TGraphAsymmErrors
, but due to my current setup I would prefer to find a solution that allows me to work with TH1
objects, if at all possible.
Many thanks in advance, best regards,
Sebastian
Minimal example:
#include <iostream>
void printHistogram(TH1F*);
void poissonerrors() {
TH1F *num = new TH1F("num", "", 2, 0, 2);
TH1F *den = new TH1F("den", "", 2, 0, 2);
// setting the following bin error option will break error propagation later on
num->SetBinErrorOption(TH1::kPoisson);
den->SetBinErrorOption(TH1::kPoisson);
// fill some dummy data
num->SetBinContent(1, 2.0);
num->SetBinContent(2, 1.0);
den->SetBinContent(1, 1.0);
den->SetBinContent(2, 2.0);
// bin errors are reasonable (see the output)
printHistogram(num);
printHistogram(den);
// the following silently spoils the bin errors
TH1F *ratio = (TH1F*)num->Clone("ratio");
ratio->Divide(den);
// inspect the computed bin errors (see the output)
printHistogram(ratio);
}
void printHistogram(TH1F* h) {
for(Int_t i=1; i<=h->GetNbinsX(); i++) {
std::cout << "[" <<
h->GetName() << "] bin "
<< i << ": "
<< h->GetBinContent(i) << " (-"
<< h->GetBinErrorLow(i) << ", +"
<< h->GetBinErrorUp(i) << ")"
<< std::endl;
}
}
Produced output
[num] bin 1: 2 (-1.29181, +2.63786)
[num] bin 2: 1 (-0.827246, +2.29953)
[den] bin 1: 1 (-0.827246, +2.29953)
[den] bin 2: 2 (-1.29181, +2.63786)
[ratio] bin 1: 2 (-1.29181, +2.63786)
[ratio] bin 2: 0.5 (-0, +1.34102)