I have 4 TH1D named p0, p1, p2 and z (each of them declared with Sumw2 option and with assigned errors on each of the filled bins). All histograms have the same number of bins and are needed
to compute the total histogram y according to the equation
y = exp (exponent) +p2,
where
exponent=p0+p1*x
Is there any function for TH1 that allows doing so?
Or am i forced to do this with y->SetBinContent(i, TMath::Exp(exponent->GetBinContent(i)))
for all bins i ?
If so, how would the error be propagated, considering that I should later add also the p2 histogram?
You are applying a very specific functions on the histograms, so you would need to compute it yourself , by getting the bin contents from the histogram and eventually compute the errors using for example error propagation.
You could get there half way, though. You can compute p0 + p1*x by doing:
auto exponent = p1->Clone("exponent");
exponent->Multiply(x);
exponent->Add(p0);
Then you need to manually calculate exp(exponent), including error propagation and can then do:
result->Add(p2);
These steps propagate the errors correctly (you might have to set the TH1::SetSumw2 flag before, though).
If you are using PyROOT, you could be using this class, which I threw together quickly. It allows computing a histogram where the new bin content is a function of the old bin content. It performs error propagation.
import ROOT
import math
class Func(object):
"""Function that can calculate f(h)"""
def __init__(self, f_str, pars=None):
self.f = ROOT.TF1(str(id(self)), f_str)
self.f_str = f_str
if pars is None:
if self.f.GetNpar() >= 1:
self.f.SetParameters(*[1] * self.f.GetNpar())
else:
self.f.SetParameters(*pars)
def __call__(self, h, name="temp"):
nbins = h.GetNbinsX()
self.f.SetRange(h.GetBinLowEdge(1),
h.GetBinLowEdge(nbins) + h.GetBinWidth(nbins))
h2 = h.Clone(name)
for i in range(1, nbins + 1):
y, e = h.GetBinContent(i), h.GetBinError(i)
yf = self.f(y)
if math.isinf(yf) or math.isnan(yf):
yf = 0.
h2.SetBinContent(i, yf)
df = self.f.Derivative(y)
if math.isinf(df) or math.isnan(df):
df = 0.
h2.SetBinError(i, e * abs(df))
return h2
def __str__(self):
return self.f_str
if __name__ == "__main__":
h = ROOT.TH1D("h", "h", 100, -10, 10)
h.FillRandom("gaus")
f = Func("TMath::Sqrt(x)")
h2 = f(h)
h.Draw("e")
h2.Draw("samee")
Hi Graipher,
it is basically what I did,
since I couldn’t find a way to compute the exponential of a histogram WITH automatic handle of the error propagation.
Thanks
Davide