Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
rs_bernsteinCorrection.py
Go to the documentation of this file.
1## \file
2## \ingroup tutorial_roostats
3## \notebook -js
4## Example of the BernsteinCorrection utility in RooStats.
5##
6## The idea is that one has a distribution coming either from data or Monte Carlo
7## (called "reality" in the macro) and a nominal model that is not sufficiently
8## flexible to take into account the real distribution. One wants to take into
9## account the systematic associated with this imperfect modeling by augmenting
10## the nominal model with some correction term (in this case a polynomial).
11## The BernsteinCorrection utility will import into your workspace a corrected model
12## given by nominal(x) * poly_N(x), where poly_N is an n-th order polynomial in
13## the Bernstein basis. The degree N of the polynomial is chosen by specifying the tolerance
14## one has in adding an extra term to the polynomial.
15## The Bernstein basis is nice because it only has positive-definite terms
16## and works well with PDFs.
17## Finally, the macro makes a plot of:
18## - the data (drawn from 'reality'),
19## - the best fit of the nominal model (blue)
20## - and the best fit corrected model.
21##
22## \macro_image
23## \macro_output
24## \macro_code
25##
26## \date June 2022
27## \authors Artem Busorgin, Kyle Cranmer (C++ version)
28
29import sys
30import ROOT
31
32# set range of observable
33lowRange = -1
34highRange = 5
35
36# make a RooRealVar for the observable
37x = ROOT.RooRealVar("x", "x", lowRange, highRange)
38
39# true model
40narrow = ROOT.RooGaussian("narrow", "", x, ROOT.RooFit.RooConst(0.0), ROOT.RooFit.RooConst(0.8))
41wide = ROOT.RooGaussian("wide", "", x, ROOT.RooFit.RooConst(0.0), ROOT.RooFit.RooConst(2.0))
42reality = ROOT.RooAddPdf("reality", "", [narrow, wide], ROOT.RooFit.RooConst(0.8))
43
44data = reality.generate(x, 1000)
45
46# nominal model
47sigma = ROOT.RooRealVar("sigma", "", 1.0, 0, 10)
48nominal = ROOT.RooGaussian("nominal", "", x, ROOT.RooFit.RooConst(0.0), sigma)
49
50wks = ROOT.RooWorkspace("myWorksspace")
51
52wks.Import(data, Rename="data")
53wks.Import(nominal)
54
55if ROOT.TClass.GetClass("ROOT::Minuit2::Minuit2Minimizer"):
56 # use Minuit2 if ROOT was built with support for it:
58
59# The tolerance sets the probability to add an unnecessary term.
60# lower tolerance will add fewer terms, while higher tolerance
61# will add more terms and provide a more flexible function.
62tolerance = 0.05
63bernsteinCorrection = ROOT.RooStats.BernsteinCorrection(tolerance)
64degree = bernsteinCorrection.ImportCorrectedPdf(wks, "nominal", "x", "data")
65
66if degree < 0:
67 ROOT.Error("rs_bernsteinCorrection", "Bernstein correction failed !")
68 sys.exit()
69
70print("Correction based on Bernstein Poly of degree ", degree)
71
72frame = x.frame()
73data.plotOn(frame)
74# plot the best fit nominal model in blue
75nominal.fitTo(data, PrintLevel=0)
76nominal.plotOn(frame)
77
78# plot the best fit corrected model in red
79corrected = wks["corrected"]
80if not corrected:
81 sys.exit()
82
83# fit corrected model
84corrected.fitTo(data, PrintLevel=0)
85corrected.plotOn(frame, LineColor="r")
86
87# plot the correction term (* norm constant) in dashed green
88# should make norm constant just be 1, not depend on binning of data
89poly = wks["poly"]
90if poly:
91 poly.plotOn(frame, LineColor="g", LineStyle="--")
92
93# this is a switch to check the sampling distribution
94# of -2 log LR for two comparisons:
95# the first is for n-1 vs. n degree polynomial corrections
96# the second is for n vs. n+1 degree polynomial corrections
97# Here we choose n to be the one chosen by the tolerance
98# criterion above, eg. n = "degree" in the code.
99# Setting this to true is takes about 10 min.
100checkSamplingDist = True
101numToyMC = 20 # increase this value for sensible results
102
103c1 = ROOT.TCanvas()
104if checkSamplingDist:
105 c1.Divide(1, 2)
106 c1.cd(1)
107
108frame.Draw()
109ROOT.gPad.Update()
110
111if checkSamplingDist:
112 # check sampling dist
114 samplingDist = ROOT.TH1F("samplingDist", "", 20, 0, 10)
115 samplingDistExtra = ROOT.TH1F("samplingDistExtra", "", 20, 0, 10)
116 bernsteinCorrection.CreateQSamplingDist(
117 wks, "nominal", "x", "data", samplingDist, samplingDistExtra, degree, numToyMC
118 )
119
120 c1.cd(2)
121 samplingDistExtra.SetLineColor(ROOT.kRed)
122 samplingDistExtra.Draw()
123 samplingDist.Draw("same")
124
125c1.SaveAs("rs_bernsteinCorrection.png")
static void SetDefaultMinimizer(const char *type, const char *algo=nullptr)
Set the default Minimizer type and corresponding algorithms.
static void SetDefaultPrintLevel(int level)
Set the default Print Level.