import ROOT
%jsroot on
ROOT.RooMsgService.instance().setGlobalKillBelow(5)
from matplotlib import pyplot
%matplotlib inline
First we retrieve the workspace created in ExploringData
infile = ROOT.TFile.Open("output/Preselection.root")
w = infile.Get("w")
mc = w.obj("ModelConfig")
data = w.data("data")
x = w.var("x")
mc.LoadSnapshot()
We create a model. From the distributions that we looked at before creating this workspace we know that the background follows a Breit Wigner distribution so let us fit a function to this.
This function is built into RooFit and can be defined as:
mean = ROOT.RooRealVar("mean","Mean of Gaussian",91,0,200)
sigma = ROOT.RooRealVar("sigma","Width of Gaussian",40,0,200)
ztautau = ROOT.RooBreitWigner("ztautau","Breit-Wigner(x,mean,sigma)",x,mean,sigma)
However is a pdf. We want to use the extended likelihood formalism (adding the normlisation).
First we retrieve the number of background events from the workspace.
nbkg = w.var("n_bkg")
n_bkg_true = nbkg.getVal()
And now we extend the pdf.
background = ROOT.RooExtendPdf("background","background distribution",ztautau,nbkg)
now we can fit to the data!
background.fitTo(data,ROOT.RooFit.Range(0,200),ROOT.RooFit.PrintLevel(-1))
c = ROOT.TCanvas()
plot = x.frame(ROOT.RooFit.Title("Reconstructed Mass"))
plot.SetTitle("")
plot.GetYaxis().SetTitleOffset(1.)
plot.GetYaxis().SetTitleSize(0.05)
plot.GetXaxis().SetTitleSize(0.05)
plot.SetXTitle("MMC mass (GeV)")
data.plotOn(plot,ROOT.RooFit.Name("data"))
background.plotOn(plot,ROOT.RooFit.Name("ztautau"))
l = ROOT.TLegend( 0.1, 0.6, 0.4, 0.9)
dataobj = plot.findObject("data")
zobj = plot.findObject("ztautau")
l.AddEntry( dataobj , "Data", "pl" )
l.AddEntry( zobj , "{0:0.0f}GeV Z mass ".format(mean.getVal()), "l" )
l.SetTextSizePixels(400)
plot.Draw()
l.Draw()
c.Draw()
This process can be repeated (almost) identically to before.
infile = ROOT.TFile.Open("output/VBFselection.root")
w = infile.Get("w")
mc = w.obj("ModelConfig")
data = w.data("data")
mc.LoadSnapshot()
x = w.var("x")
This time we don't assume that the Z peak is the only background contributing. A poloynomial is added to approximate the fake multijet background.
mean = ROOT.RooRealVar("mean","Mean of Gaussian",0,200)
sigma = ROOT.RooRealVar("sigma","Width of Gaussian",40,0,200)
ztautau = ROOT.RooBreitWigner("ztautau","Breit-Wigner(x,mean,sigma)",x,mean,sigma)
coef0 = ROOT.RooRealVar("c0","coefficient #0",1.0,-1.,1)
coef1 = ROOT.RooRealVar("c1","coefficient #1",0.1,-1.,1)
coef2 = ROOT.RooRealVar("c2","coefficient #2",-0.1,-1.,1)
fake = ROOT.RooChebychev("fake","background p.d.f.",x,ROOT.RooArgList(coef0,coef1,coef2))
fbkg = ROOT.RooRealVar("fbkg","background fraction",0.9,0.,1.)
model = ROOT.RooAddPdf('prod','prod',ROOT.RooArgList(ztautau,fake),ROOT.RooArgList(fbkg))
mean.setVal(91.1876)
nbkg = w.var("n_bkg")
background = ROOT.RooExtendPdf("background","background distribution",model,nbkg)
background.fitTo(data,ROOT.RooFit.Range(0,200),ROOT.RooFit.PrintLevel(-1))
c = ROOT.TCanvas()
plot = x.frame(ROOT.RooFit.Title("Reconstructed Mass"))
plot.SetTitle("")
plot.GetYaxis().SetTitleOffset(1.)
plot.GetYaxis().SetTitleSize(0.05)
plot.GetXaxis().SetTitleSize(0.05)
plot.SetXTitle("MMC mass (GeV)")
data.plotOn(plot,ROOT.RooFit.Name("data"))
background.plotOn(plot,ROOT.RooFit.Name("ztautau"))
background.plotOn(plot,ROOT.RooFit.Components("fake"),ROOT.RooFit.Name("fake"), ROOT.RooFit.LineStyle(2) )
l = ROOT.TLegend( 0.6, 0.6, 0.9, 0.9)
dataobj = plot.findObject("data")
zobj = plot.findObject("background")
fobj = plot.findObject("fake")
l.AddEntry( dataobj , "VBF Data", "pl" )
l.AddEntry( zobj , "{0:0.0f} GeV Z mass".format(mean.getVal()), "l" )
l.AddEntry( fobj , "fake component", "l" )
l.SetTextSizePixels(400)
plot.Draw()
l.Draw()
c.Draw()
As can be seen the Z mass peak is much better approximated in the VBF region.