Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
rf212_plottingInRanges_blinding.py
Go to the documentation of this file.
1## \file
2## \ingroup tutorial_roofit
3## \notebook
4## Plot a PDF in disjunct ranges, and get normalisation right.
5##
6## Usually, when comparing a fit to data, one should first plot the data, and then the PDF.
7## In this case, the PDF is automatically normalised to match the number of data events in the plot.
8## However, when plotting only a sub-range, when e.g. a signal region has to be blinded,
9## one has to exclude the blinded region from the computation of the normalisation.
10##
11## In this tutorial, we show how to explicitly choose the normalisation when plotting using `NormRange()`.
12##
13## \macro_image
14## \macro_code
15## \macro_output
16##
17## \date June 2021
18## \author Harshal Shende, Stephan Hageboeck (C++ version)
19
20import ROOT
21
22# Make a fit model
23x = ROOT.RooRealVar("x", "The observable", 1, 30)
24tau = ROOT.RooRealVar("tau", "The exponent", -0.1337, -10.0, -0.1)
25expo = ROOT.RooExponential("expo", "A falling exponential function", x, tau)
26
27# Define the sidebands (e.g. background regions)
28x.setRange("full", 1, 30)
29x.setRange("left", 1, 10)
30x.setRange("right", 20, 30)
31
32# Generate toy data, and cut out the blinded region.
33data = expo.generate(x, 1000)
34blindedData = data.reduce(CutRange="left,right")
35
36# Kick tau a bit, and run an unbinned fit where the blinded data are missing.
37# ----------------------------------------------------------------------------------------------------------
38# The fit should be done only in the unblinded regions, otherwise it would try
39# to make the model adapt to the empty bins in the blinded region.
40tau.setVal(-2.0)
41expo.fitTo(blindedData, Range="left,right", PrintLevel=-1)
42
43# Clear the "fitrange" attribute of the PDF. Otherwise, the fitrange would be
44# automatically taken as the NormRange() for plotting. We want to avoid this,
45# because the point of this tutorial is to show what can go wrong when the
46# NormRange() is not specified.
47expo.removeStringAttribute("fitrange")
48
49
50# Here we will plot the results
51canvas = ROOT.TCanvas("canvas", "canvas", 800, 600)
52canvas.Divide(2, 1)
53
54
55# Wrong:
56# ----------------------------------------------------------------------------------------------------------
57# Plotting each slice on its own normalises the PDF over its plotting range. For the full curve, that means
58# that the blinded region where data is missing is included in the normalisation calculation. The PDF therefore
59# comes out too low, and doesn't match up with the slices in the side bands, which are normalised to "their" data.
60
61print("Now plotting with unique normalisation for each slice.\n")
62canvas.cd(1)
63plotFrame = x.frame(Title="Wrong: Each slice normalised over its plotting range")
64
65# Plot only the blinded data, and then plot the PDF over the full range as well as both sidebands
66blindedData.plotOn(plotFrame)
67expo.plotOn(plotFrame, LineColor="r", Range="full")
68expo.plotOn(plotFrame, LineColor="b", Range="left")
69expo.plotOn(plotFrame, LineColor="g", Range="right")
70
71plotFrame.Draw()
72
73# Right:
74# ----------------------------------------------------------------------------------------------------------
75# Make the same plot, but normalise each piece with respect to the regions "left" AND "right". This requires setting
76# a "NormRange", which tells RooFit over which range the PDF has to be integrated to normalise.
77# This means that the normalisation of the blue and green curves is slightly different from the left plot,
78# because they get a common scale factor.
79
80print("\n\nNow plotting with correct norm ranges:\n")
81canvas.cd(2)
82plotFrameWithNormRange = x.frame(Title="Right: All slices have common normalisation")
83
84# Plot only the blinded data, and then plot the PDF over the full range as well as both sidebands
85blindedData.plotOn(plotFrameWithNormRange)
86expo.plotOn(plotFrameWithNormRange, LineColor="b", Range="left", NormRange="left,right")
87expo.plotOn(plotFrameWithNormRange, LineColor="g", Range="right", NormRange="left,right")
88expo.plotOn(plotFrameWithNormRange, LineColor="r", Range="full", NormRange="left,right", LineStyle=10)
89
90plotFrameWithNormRange.Draw()
91
92canvas.Draw()
93
94canvas.SaveAs("rf212_plottingInRanges_blinding.png")