Hello @jonas and @mdessole, Thanks for the answering.
Root Version:
The ROOT version used is 6.32.02.
Normalization and Bin Width:
I’ve checked both the normalization and bin width, and there don’t appear to be any issues with them. You can review the relevant code snippet below for more details.
Model Details:
The model is a non-extended RooAbsPdf aimed at fitting a histogram with weighted data. Currently, I’m focusing on the shape of the distribution rather than yields, which is why I’m using a probability density function.
The bin width is set to 0.1 ps, but I adjust it iteratively to achieve better fitting results.
import ROOT
from ROOT import RooRealVar, RooArgList, RooFormulaVar, RooAddPdf, RooFit
fileP = ROOT.TFile.Open("tbar/histograms.root")
folderP = fileP.Get("/NOSYS/reco")
histograms = folderP.Get("lifetime")
#
var = ROOT.RooRealVar("tau", "Lifetime ", -0.9, 0.9, "ps")
def pdf_to_th(name, model, variable, binning):
"""Converts RooFit pdf into a histogram
Main purpose of this function is to correctly normalize
by bin width, RooFit divides by bin width.
"""
root_hist = model.createHistogram(name, variable, Extended=False, Scaling=False, Binning=binning)
root_hist.SetDirectory(0)
ROOT.SetOwnership(root_hist, True)
# For some reason the histogram is off by bin width.
# In theory that is what `Scaling` option was for,
# but it is disable when calling `Extended` (which
# is responsible for norm to expected events)
for i in range(root_hist.GetNbinsX()):
val = root_hist.GetBinContent(i) * total_events * bin_width
root_hist.SetBinContent(i, val)
return root_hist
def roofit_draw(plotName, var, data, model, npar, extra_labels, components = {}):
"""Plots result of RooFit fit with possibility to plot specific model components.
Arguments:
var (``RooRealVar``): Variable used in the fit.
data (``RooDataHist``): Hist to which model wasfitted to.
model (``RooAddPdf``): Model which was fitted.
result (``RooFitResult``): Result of the fit.
extra_labels (``list`` of `` strings``): Extra labels to be
added to the plot
components (``string``): Components of the model to be plotted
in addition to the complete model
"""
ROOT.gROOT.SetStyle('ATLAS')
ROOT.gROOT.SetBatch(True)
c = ROOT.TCanvas(plotName)
ROOT.SetOwnership(c, True)
c.SetCanvasSize(1000, 1000)
c.cd()
main_pad = ROOT.TPad('mainpad', 'mainpad', 0, 0.3, 1, 1 )
ROOT.SetOwnership(main_pad, True)
main_pad.SetBottomMargin(0)
main_pad.Draw()
main_pad.cd()
frame = var.frame()
ROOT.SetOwnership(frame, True)
data.plotOn(frame, ROOT.RooFit.Name("data"))
model.plotOn(frame, ROOT.RooFit.Name("model"), ROOT.RooFit.LineColor(ROOT.kRed))
chi2_var = ROOT.RooChi2Var("chi2", "chi2", model, data, False, ROOT.RooDataHist.SumW2)
chi2_value = chi2_var.getVal()
ndof = dataHist.numEntries() - npar
chi2= chi2_value/ndof
col = 0
cols = [ROOT.kGreen+2, ROOT.kBlue, ROOT.kOrange+1, ROOT.kCyan]
# for name, comp in components.items():
# model.plotOn(frame, ROOT.RooFit.Name(name), ROOT.RooFit.Components(comp),
# ROOT.RooFit.LineColor(cols[col]),
# ROOT.RooFit.LineStyle(ROOT.kDotted))
#col+=1
frame.Draw()
frame.GetYaxis().SetRangeUser(0, frame.GetMaximum()*1.5)
leg = ROOT.TLegend(0.7, 0.63, 0.91, 0.85)
ROOT.SetOwnership(leg, True)
leg.SetBorderSize(0)
leg.SetFillStyle(0)
leg.AddEntry("data", "Data", "LP")
leg.AddEntry("model", "model", "L")
for name, comp in components.items():
leg.AddEntry(name, name, "L")
leg.Draw()
ltx = ROOT.TLatex()
ROOT.SetOwnership(ltx, True)
ltx.SetNDC()
ltx.SetTextColor(ROOT.kBlack)
pos_y = 0.85
ltx.DrawLatex(0.2, pos_y, "#chi^{{2}}/dof={chi2:.3f}".format(chi2=chi2))
for lbl in extra_labels:
pos_y-=0.05
ltx.DrawLatex(0.2, pos_y, lbl)
c.cd()
ratio_pad = ROOT.TPad('ratiopad', 'ratiopad', 0, 0, 1, 0.3)
ROOT.SetOwnership(ratio_pad, True)
ratio_pad.SetBottomMargin(0.35)
ratio_pad.SetTopMargin(0)
ratio_pad.Draw()
ratio_pad.cd()
ratio = data.createHistogram('data_hist', var)
ROOT.SetOwnership(ratio, True)
ratio.SetDirectory(0)
tmp = pdf_to_th('mc_hist', model, var, data.getBinnings()[0])
for i in range(ratio.GetNbinsX()):
val = ratio.GetBinContent(i)
err = ratio.GetBinError(i)
valmc = tmp.GetBinContent(i)
if valmc != 0:
ratio.SetBinContent(i, val/valmc)
ratio.SetBinError(i, err/valmc)
else:
ratio.SetBinContent(i, 0)
ratio.SetBinError(i, 0)
tmp.GetYaxis().SetRangeUser(-1, 2)
tmp.GetYaxis().SetTitle("data/model")
tmp.GetYaxis().SetTitleOffset(0.56)
tmp.GetXaxis().SetTitleSize(0.12)
tmp.GetXaxis().SetLabelSize(0.12)
tmp.GetYaxis().SetTitleSize(0.12)
tmp.GetYaxis().SetLabelSize(0.12)
tmp.SetNdivisions(505, 'Y')
tmp.Divide(tmp)
tmp.SetLineColor(ROOT.kRed)
tmp.Draw("hist")
ratio.Draw("same")
if "/" in plotName:
dirName = plotName[:plotName.rindex("/")]
if not os.path.exists(dirName):
os.makedirs(dirName)
# Supress info messages about creating plots
ignoreLevel = ROOT.gErrorIgnoreLevel
ROOT.gErrorIgnoreLevel = ROOT.kWarning
c.SaveAs(plotName+".png")
ROOT.gErrorIgnoreLevel = ignoreLevel
histograms.Rebin(2)
dataHist = ROOT.RooDataHist("dataHist", "Data Histogram", ROOT.RooArgList(var), histograms)
frac1 = ROOT.RooRealVar("frac1", "fraction", 0.675, 0.55, 0.72)
frac2 = ROOT.RooRealVar("frac2", "fraction", 0.27, 0.22, 0.35)
mean1 = ROOT.RooRealVar("mean1", "mean1", -0.0019, -0.01, 0.01)
mean2 = ROOT.RooRealVar("mean2", "mean2", 0.0155, 0.008, 0.027)
mean3 = ROOT.RooRealVar("mean3", "mean3", -0.0101, -0.02, -0.0045)
sigma1 = ROOT.RooRealVar("sigma1", "sigma1", 0.07, 0.048, 0.088)
sigma2 = ROOT.RooRealVar("sigma2", "sigma2", 0.69, 0.5, 0.88)
sigma3 = ROOT.RooRealVar("sigma3", "sigma3", 0.205, 0.14, 0.29)
gauss1 = ROOT.RooGaussian("gauss1", "Gaussian 1", var, mean1, sigma1)
gauss2 = ROOT.RooGaussian("gauss2", "Gaussian 2", var, mean2, sigma2)
gauss3 = ROOT.RooGaussian("gauss3", "Gaussian 3", var, mean3, sigma3)
model = ROOT.RooAddPdf("model", "Triple Gaussian Model", ROOT.RooArgList(gauss1, gauss2, gauss3), ROOT.RooArgList(frac1, frac2), True)
total_events = dataHist.sumEntries()
bin_width = 0.1
result = model.chi2FitTo(dataHist, ROOT.RooFit.Save(), ROOT.RooFit.SumW2Error(True))
ratio=roofit_draw( "tripleGaussian" ,var, dataHist, model, 8, ["MC prompt", "Triple Gaussian"], { "Gaussian1" : "gauss1", "Gaussian2": "gauss2", "Gaussian3":"gauss3" } )
fileP.Close()
best regards,
Abdessamad baoud