Loading [MathJax]/extensions/tex2jax.js
Logo ROOT  
Reference Guide
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
Loading...
Searching...
No Matches
rf501_simultaneouspdf.py
Go to the documentation of this file.
1## \file
2## \ingroup tutorial_roofit
3## \notebook
4## Organization and simultaneous fits: using simultaneous pdfs to describe simultaneous
5## fits to multiple datasets
6##
7## \macro_code
8##
9## \date February 2018
10## \authors Clemens Lange, Wouter Verkerke (C++ version)
11
12import ROOT
13
14
15# Create model for physics sample
16# -------------------------------------------------------------
17
18# Create observables
19x = ROOT.RooRealVar("x", "x", -8, 8)
20
21# Construct signal pdf
22mean = ROOT.RooRealVar("mean", "mean", 0, -8, 8)
23sigma = ROOT.RooRealVar("sigma", "sigma", 0.3, 0.1, 10)
24gx = ROOT.RooGaussian("gx", "gx", x, mean, sigma)
25
26# Construct background pdf
27a0 = ROOT.RooRealVar("a0", "a0", -0.1, -1, 1)
28a1 = ROOT.RooRealVar("a1", "a1", 0.004, -1, 1)
29px = ROOT.RooChebychev("px", "px", x, [a0, a1])
30
31# Construct composite pdf
32f = ROOT.RooRealVar("f", "f", 0.2, 0.0, 1.0)
33model = ROOT.RooAddPdf("model", "model", [gx, px], [f])
34
35# Create model for control sample
36# --------------------------------------------------------------
37
38# Construct signal pdf.
39# NOTE that sigma is shared with the signal sample model
40mean_ctl = ROOT.RooRealVar("mean_ctl", "mean_ctl", -3, -8, 8)
41gx_ctl = ROOT.RooGaussian("gx_ctl", "gx_ctl", x, mean_ctl, sigma)
42
43# Construct the background pdf
44a0_ctl = ROOT.RooRealVar("a0_ctl", "a0_ctl", -0.1, -1, 1)
45a1_ctl = ROOT.RooRealVar("a1_ctl", "a1_ctl", 0.5, -0.1, 1)
46px_ctl = ROOT.RooChebychev("px_ctl", "px_ctl", x, [a0_ctl, a1_ctl])
47
48# Construct the composite model
49f_ctl = ROOT.RooRealVar("f_ctl", "f_ctl", 0.5, 0.0, 1.0)
50model_ctl = ROOT.RooAddPdf("model_ctl", "model_ctl", [gx_ctl, px_ctl], [f_ctl])
51
52# Generate events for both samples
53# ---------------------------------------------------------------
54
55# Generate 1000 events in x and y from model
56data = model.generate({x}, 100)
57data_ctl = model_ctl.generate({x}, 2000)
58
59# Create index category and join samples
60# ---------------------------------------------------------------------------
61
62# Define category to distinguish physics and control samples events
63sample = ROOT.RooCategory("sample", "sample")
64sample.defineType("physics")
65sample.defineType("control")
66
67# Construct combined dataset in (x,sample)
68combData = ROOT.RooDataSet(
69 "combData",
70 "combined data",
71 {x},
72 ROOT.RooFit.Index(sample),
73 ROOT.RooFit.Import("physics", data),
74 ROOT.RooFit.Import("control", data_ctl),
75)
76
77# Construct a simultaneous pdf in (x, sample)
78# -----------------------------------------------------------------------------------
79
80# Construct a simultaneous pdf using category sample as index
81simPdf = ROOT.RooSimultaneous("simPdf", "simultaneous pdf", sample)
82
83# Associate model with the physics state and model_ctl with the control
84# state
85simPdf.addPdf(model, "physics")
86simPdf.addPdf(model_ctl, "control")
87
88# Perform a simultaneous fit
89# ---------------------------------------------------
90
91# Perform simultaneous fit of model to data and model_ctl to data_ctl
92simPdf.fitTo(combData)
93
94# Plot model slices on data slices
95# ----------------------------------------------------------------
96
97# Make a frame for the physics sample
98frame1 = x.frame(Bins=30, Title="Physics sample")
99
100# Plot all data tagged as physics sample
101combData.plotOn(frame1, Cut="sample==sample::physics")
102
103# Plot "physics" slice of simultaneous pdf.
104# NB: You *must* project the sample index category with data using ProjWData
105# as a RooSimultaneous makes no prediction on the shape in the index category
106# and can thus not be integrated
107# NB2: The sampleSet *must* be named. It will not work to pass this as a temporary
108# because python will delete it. The same holds for fitTo() and plotOn() below.
109sampleSet = {sample}
110simPdf.plotOn(frame1, Slice=(sample, "physics"), Components="px", ProjWData=(sampleSet, combData), LineStyle="--")
111
112# The same plot for the control sample slice
113frame2 = x.frame(Bins=30, Title="Control sample")
114combData.plotOn(frame2, Cut="sample==sample::control")
115simPdf.plotOn(frame2, Slice=(sample, "control"), ProjWData=(sampleSet, combData))
116simPdf.plotOn(frame2, Slice=(sample, "control"), Components="px_ctl", ProjWData=(sampleSet, combData), LineStyle="--")
117
118c = ROOT.TCanvas("rf501_simultaneouspdf", "rf501_simultaneouspdf", 800, 400)
119c.Divide(2)
120c.cd(1)
121ROOT.gPad.SetLeftMargin(0.15)
122frame1.GetYaxis().SetTitleOffset(1.4)
123frame1.Draw()
124c.cd(2)
125ROOT.gPad.SetLeftMargin(0.15)
126frame2.GetYaxis().SetTitleOffset(1.4)
127frame2.Draw()
128
129c.SaveAs("rf501_simultaneouspdf.png")