Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
rs301_splot.C
Go to the documentation of this file.
1/// \file
2/// \ingroup tutorial_roostats
3/// \notebook -js
4/// SPlot tutorial
5///
6/// This tutorial shows an example of using SPlot to unfold two distributions.
7/// The physics context for the example is that we want to know
8/// the isolation distribution for real electrons from Z events
9/// and fake electrons from QCD. Isolation is our 'control' variable.
10/// To unfold them, we need a model for an uncorrelated variable that
11/// discriminates between Z and QCD. To do this, we use the invariant
12/// mass of two electrons. We model the Z with a Gaussian and the QCD
13/// with a falling exponential.
14///
15/// Note, since we don't have real data in this tutorial, we need to generate
16/// toy data. To do that we need a model for the isolation variable for
17/// both Z and QCD. This is only used to generate the toy data, and would
18/// not be needed if we had real data.
19///
20/// \macro_image
21/// \macro_code
22/// \macro_output
23///
24/// \author Kyle Cranmer
25
26#include "RooRealVar.h"
27#include "RooStats/SPlot.h"
28#include "RooDataSet.h"
29#include "RooRealVar.h"
30#include "RooGaussian.h"
31#include "RooExponential.h"
32#include "RooChebychev.h"
33#include "RooAddPdf.h"
34#include "RooProdPdf.h"
35#include "RooAddition.h"
36#include "RooProduct.h"
37#include "RooAbsPdf.h"
38#include "RooFitResult.h"
39#include "RooWorkspace.h"
40#include "RooConstVar.h"
41
42#include "TCanvas.h"
43#include "TLegend.h"
44
45#include <iomanip>
46
47// use this order for safety on library loading
48using namespace RooFit;
49using namespace RooStats;
50
51// see below for implementation
52void AddModel(RooWorkspace &);
53void AddData(RooWorkspace &);
54void DoSPlot(RooWorkspace &);
55void MakePlots(RooWorkspace &);
56
57void rs301_splot()
58{
59
60 // Create a workspace to manage the project.
61 RooWorkspace wspace{"myWS"};
62
63 // add the signal and background models to the workspace.
64 // Inside this function you will find a description of our model.
65 AddModel(wspace);
66
67 // add some toy data to the workspace
68 AddData(wspace);
69
70 // inspect the workspace if you wish
71 // wspace->Print();
72
73 // do sPlot.
74 // This will make a new dataset with sWeights added for every event.
75 DoSPlot(wspace);
76
77 // Make some plots showing the discriminating variable and
78 // the control variable after unfolding.
79 MakePlots(wspace);
80}
81
82//____________________________________
83void AddModel(RooWorkspace &ws)
84{
85
86 // Make models for signal (Higgs) and background (Z+jets and QCD)
87 // In real life, this part requires an intelligent modeling
88 // of signal and background -- this is only an example.
89
90 // set range of observable
91 Double_t lowRange = 0., highRange = 200.;
92
93 // make a RooRealVar for the observables
94 RooRealVar invMass("invMass", "M_{inv}", lowRange, highRange, "GeV");
95 RooRealVar isolation("isolation", "isolation", 0., 20., "GeV");
96
97 // --------------------------------------
98 // make 2-d model for Z including the invariant mass
99 // distribution and an isolation distribution which we want to
100 // unfold from QCD.
101 std::cout << "make z model" << std::endl;
102 // mass model for Z
103 RooRealVar mZ("mZ", "Z Mass", 91.2, lowRange, highRange);
104 RooRealVar sigmaZ("sigmaZ", "Width of Gaussian", 2, 0, 10, "GeV");
105 RooGaussian mZModel("mZModel", "Z+jets Model", invMass, mZ, sigmaZ);
106 // we know Z mass
107 mZ.setConstant();
108 // we leave the width of the Z free during the fit in this example.
109
110 // isolation model for Z. Only used to generate toy MC.
111 // the exponential is of the form exp(c*x). If we want
112 // the isolation to decay an e-fold every R GeV, we use
113 // c = -1/R.
114 RooConstVar zIsolDecayConst("zIsolDecayConst", "z isolation decay constant", -1);
115 RooExponential zIsolationModel("zIsolationModel", "z isolation model", isolation, zIsolDecayConst);
116
117 // make the combined Z model
118 RooProdPdf zModel("zModel", "2-d model for Z", RooArgSet(mZModel, zIsolationModel));
119
120 // --------------------------------------
121 // make QCD model
122
123 std::cout << "make qcd model" << std::endl;
124 // mass model for QCD.
125 // the exponential is of the form exp(c*x). If we want
126 // the mass to decay an e-fold every R GeV, we use
127 // c = -1/R.
128 // We can leave this parameter free during the fit.
129 RooRealVar qcdMassDecayConst("qcdMassDecayConst", "Decay const for QCD mass spectrum", -0.01, -100, 100, "1/GeV");
130 RooExponential qcdMassModel("qcdMassModel", "qcd Mass Model", invMass, qcdMassDecayConst);
131
132 // isolation model for QCD. Only used to generate toy MC
133 // the exponential is of the form exp(c*x). If we want
134 // the isolation to decay an e-fold every R GeV, we use
135 // c = -1/R.
136 RooConstVar qcdIsolDecayConst("qcdIsolDecayConst", "Et resolution constant", -.1);
137 RooExponential qcdIsolationModel("qcdIsolationModel", "QCD isolation model", isolation, qcdIsolDecayConst);
138
139 // make the 2-d model
140 RooProdPdf qcdModel("qcdModel", "2-d model for QCD", RooArgSet(qcdMassModel, qcdIsolationModel));
141
142 // --------------------------------------
143 // combined model
144
145 // These variables represent the number of Z or QCD events
146 // They will be fitted.
147 RooRealVar zYield("zYield", "fitted yield for Z", 500, 0., 5000);
148 RooRealVar qcdYield("qcdYield", "fitted yield for QCD", 1000, 0., 10000);
149
150 // now make the combined models
151 std::cout << "make full model" << std::endl;
152 RooAddPdf model("model", "z+qcd background models", {zModel, qcdModel}, {zYield, qcdYield});
153 RooAddPdf massModel("massModel", "z+qcd invariant mass model", {mZModel, qcdMassModel}, {zYield, qcdYield});
154
155 // interesting for debugging and visualizing the model
156 model.graphVizTree("fullModel.dot");
157
158 std::cout << "import model" << std::endl;
159
160 ws.import(model);
161 ws.import(massModel, RecycleConflictNodes());
162}
163
164//____________________________________
165void AddData(RooWorkspace &ws)
166{
167 // Add a toy dataset
168
169 // get what we need out of the workspace to make toy data
170 RooAbsPdf *model = ws.pdf("model");
171 RooRealVar *invMass = ws.var("invMass");
172 RooRealVar *isolation = ws.var("isolation");
173
174 // make the toy data
175 std::cout << "make data set and import to workspace" << std::endl;
176 std::unique_ptr<RooDataSet> data{model->generate({*invMass, *isolation})};
177
178 // import data into workspace
179 ws.import(*data, Rename("data"));
180}
181
182//____________________________________
183void DoSPlot(RooWorkspace &ws)
184{
185 std::cout << "Calculate sWeights" << std::endl;
186
187 // get what we need out of the workspace to do the fit
188 RooAbsPdf *model = ws.pdf("model");
189 RooAbsPdf *massModel = ws.pdf("massModel");
190 RooRealVar *zYield = ws.var("zYield");
191 RooRealVar *qcdYield = ws.var("qcdYield");
192 RooDataSet& data = static_cast<RooDataSet&>(*ws.data("data"));
193
194 // The sPlot technique requires that we fix the parameters
195 // of the model that are not yields after doing the fit.
196 //
197 // This *could* be done with the lines below, however this is taken care of
198 // by the RooStats::SPlot constructor (or more precisely the AddSWeight
199 // method).
200 //
201 // RooRealVar* sigmaZ = ws.var("sigmaZ");
202 // RooRealVar* qcdMassDecayConst = ws.var("qcdMassDecayConst");
203 // sigmaZ->setConstant();
204 // qcdMassDecayConst->setConstant();
205
207
208 std::cout << "\n\n------------------------------------------\nThe dataset before creating sWeights:\n";
209 data.Print();
210
212
213 // Now we use the SPlot class to add SWeights for the isolation variable to
214 // our data set based on fitting the yields to the invariant mass variable
215 RooStats::SPlot sData{"sData", "An SPlot", data, massModel, RooArgList(*zYield, *qcdYield)};
216
217 std::cout << "\n\nThe dataset after creating sWeights:\n";
218 data.Print();
219
220 // Check that our weights have the desired properties
221
222 std::cout << "\n\n------------------------------------------\n\nCheck SWeights:" << std::endl;
223
224 std::cout << std::endl
225 << "Yield of Z is\t" << zYield->getVal() << ". From sWeights it is "
226 << sData.GetYieldFromSWeight("zYield") << std::endl;
227
228 std::cout << "Yield of QCD is\t" << qcdYield->getVal() << ". From sWeights it is "
229 << sData.GetYieldFromSWeight("qcdYield") << std::endl
230 << std::endl;
231
232 for (Int_t i = 0; i < 10; i++) {
233 std::cout << "z Weight for event " << i << std::right << std::setw(12) << sData.GetSWeight(i, "zYield") << " qcd Weight"
234 << std::setw(12) << sData.GetSWeight(i, "qcdYield") << " Total Weight" << std::setw(12) << sData.GetSumOfEventSWeight(i)
235 << std::endl;
236 }
237
238 std::cout << std::endl;
239
240 // import this new dataset with sWeights
241 std::cout << "import new dataset with sWeights" << std::endl;
242 ws.import(data, Rename("dataWithSWeights"));
243
245}
246
247void MakePlots(RooWorkspace &ws)
248{
249
250 // Here we make plots of the discriminating variable (invMass) after the fit
251 // and of the control variable (isolation) after unfolding with sPlot.
252 std::cout << "make plots" << std::endl;
253
254 // make our canvas
255 TCanvas *cdata = new TCanvas("sPlot", "sPlot demo", 400, 600);
256 cdata->Divide(1, 3);
257
258 // get what we need out of the workspace
259 RooAbsPdf *model = ws.pdf("model");
260 RooAbsPdf *zModel = ws.pdf("zModel");
261 RooAbsPdf *qcdModel = ws.pdf("qcdModel");
262
263 RooRealVar *isolation = ws.var("isolation");
264 RooRealVar *invMass = ws.var("invMass");
265
266 // note, we get the dataset with sWeights
267 auto& data = static_cast<RooDataSet&>(*ws.data("dataWithSWeights"));
268
269 // create weighted data sets
270 RooDataSet dataw_z{data.GetName(), data.GetTitle(), *data.get(), Import(data), WeightVar("zYield_sw")};
271 RooDataSet dataw_qcd{data.GetName(), data.GetTitle(), *data.get(), Import(data), WeightVar("qcdYield_sw")};
272
273
274 // this shouldn't be necessary, need to fix something with workspace
275 // do this to set parameters back to their fitted values.
276// model->fitTo(*data, Extended());
277
278 // plot invMass for data with full model and individual components overlaid
279 // TCanvas* cdata = new TCanvas();
280 cdata->cd(1);
281 RooPlot *frame = invMass->frame(Title("Fit of model to discriminating variable"));
282 data.plotOn(frame);
283 model->plotOn(frame, Name("FullModel"));
284 model->plotOn(frame, Components(*zModel), LineStyle(kDashed), LineColor(kRed), Name("ZModel"));
285 model->plotOn(frame, Components(*qcdModel), LineStyle(kDashed), LineColor(kGreen), Name("QCDModel"));
286
287 TLegend leg(0.11, 0.5, 0.5, 0.8);
288 leg.AddEntry(frame->findObject("FullModel"), "Full model", "L");
289 leg.AddEntry(frame->findObject("ZModel"), "Z model", "L");
290 leg.AddEntry(frame->findObject("QCDModel"), "QCD model", "L");
291 leg.SetBorderSize(0);
292 leg.SetFillStyle(0);
293
294 frame->Draw();
295 leg.DrawClone();
296
297 // Now use the sWeights to show isolation distribution for Z and QCD.
298 // The SPlot class can make this easier, but here we demonstrate in more
299 // detail how the sWeights are used. The SPlot class should make this
300 // very easy and needs some more development.
301
302 // Plot isolation for Z component.
303 // Do this by plotting all events weighted by the sWeight for the Z component.
304 // The SPlot class adds a new variable that has the name of the corresponding
305 // yield + "_sw".
306 cdata->cd(2);
307
308 RooPlot *frame2 = isolation->frame(Title("Isolation distribution with s weights to project out Z"));
309 // Since the data are weighted, we use SumW2 to compute the errors.
310 dataw_z.plotOn(frame2, DataError(RooAbsData::SumW2));
311 zModel->plotOn(frame2, LineStyle(kDashed), LineColor(kRed));
312
313 frame2->Draw();
314
315 // Plot isolation for QCD component.
316 // Eg. plot all events weighted by the sWeight for the QCD component.
317 // The SPlot class adds a new variable that has the name of the corresponding
318 // yield + "_sw".
319 cdata->cd(3);
320 RooPlot *frame3 = isolation->frame(Title("Isolation distribution with s weights to project out QCD"));
321 dataw_qcd.plotOn(frame3, DataError(RooAbsData::SumW2));
322 qcdModel->plotOn(frame3, LineStyle(kDashed), LineColor(kGreen));
323
324 frame3->Draw();
325
326 // cdata->SaveAs("SPlot.gif");
327}
int Int_t
Definition RtypesCore.h:45
double Double_t
Definition RtypesCore.h:59
@ kRed
Definition Rtypes.h:66
@ kGreen
Definition Rtypes.h:66
@ kDashed
Definition TAttLine.h:48
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
void graphVizTree(const char *fileName, const char *delimiter="\n", bool useTitle=false, bool useLatex=false)
Create a GraphViz .dot file visualizing the expression tree headed by this RooAbsArg object.
Abstract interface for all probability density functions.
Definition RooAbsPdf.h:40
RooPlot * plotOn(RooPlot *frame, const RooCmdArg &arg1={}, const RooCmdArg &arg2={}, const RooCmdArg &arg3={}, const RooCmdArg &arg4={}, const RooCmdArg &arg5={}, const RooCmdArg &arg6={}, const RooCmdArg &arg7={}, const RooCmdArg &arg8={}, const RooCmdArg &arg9={}, const RooCmdArg &arg10={}) const override
Helper calling plotOn(RooPlot*, RooLinkedList&) const.
Definition RooAbsPdf.h:124
RooFit::OwningPtr< RooDataSet > generate(const RooArgSet &whatVars, Int_t nEvents, const RooCmdArg &arg1, const RooCmdArg &arg2={}, const RooCmdArg &arg3={}, const RooCmdArg &arg4={}, const RooCmdArg &arg5={})
See RooAbsPdf::generate(const RooArgSet&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,...
Definition RooAbsPdf.h:57
RooPlot * frame(const RooCmdArg &arg1, const RooCmdArg &arg2={}, const RooCmdArg &arg3={}, const RooCmdArg &arg4={}, const RooCmdArg &arg5={}, const RooCmdArg &arg6={}, const RooCmdArg &arg7={}, const RooCmdArg &arg8={}) const
Create a new RooPlot on the heap with a drawing frame initialized for this object,...
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:103
Efficient implementation of a sum of PDFs of the form.
Definition RooAddPdf.h:33
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition RooArgList.h:22
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:24
Represents a constant real-valued object.
Definition RooConstVar.h:23
Container class to hold unbinned data.
Definition RooDataSet.h:34
Exponential PDF.
Plain Gaussian p.d.f.
Definition RooGaussian.h:24
static RooMsgService & instance()
Return reference to singleton instance.
void setGlobalKillBelow(RooFit::MsgLevel level)
void setSilentMode(bool flag)
Plot frame and a container for graphics objects within that frame.
Definition RooPlot.h:43
TObject * findObject(const char *name, const TClass *tClass=nullptr) const
Find the named object in our list of items and return a pointer to it.
Definition RooPlot.cxx:902
void Draw(Option_t *options=nullptr) override
Draw this plot and all of the elements it contains.
Definition RooPlot.cxx:597
Efficient implementation of a product of PDFs of the form.
Definition RooProdPdf.h:39
Variable that can be changed from the outside.
Definition RooRealVar.h:37
A class to calculate "sWeights" used to create an "sPlot".
Definition SPlot.h:32
Persistable container for RooFit projects.
RooAbsPdf * pdf(RooStringView name) const
Retrieve p.d.f (RooAbsPdf) with given name. A null pointer is returned if not found.
RooRealVar * var(RooStringView name) const
Retrieve real-valued variable (RooRealVar) with given name. A null pointer is returned if not found.
RooAbsData * data(RooStringView name) const
Retrieve dataset (binned or unbinned) with given name. A null pointer is returned if not found.
bool import(const RooAbsArg &arg, const RooCmdArg &arg1={}, const RooCmdArg &arg2={}, const RooCmdArg &arg3={}, const RooCmdArg &arg4={}, const RooCmdArg &arg5={}, const RooCmdArg &arg6={}, const RooCmdArg &arg7={}, const RooCmdArg &arg8={}, const RooCmdArg &arg9={})
Import a RooAbsArg object, e.g.
The Canvas class.
Definition TCanvas.h:23
TVirtualPad * cd(Int_t subpadnumber=0) override
Set current canvas & pad.
Definition TCanvas.cxx:719
This class displays a legend box (TPaveText) containing several legend entries.
Definition TLegend.h:23
void Divide(Int_t nx=1, Int_t ny=1, Float_t xmargin=0.01, Float_t ymargin=0.01, Int_t color=0) override
Automatic pad generation by division.
Definition TPad.cxx:1249
RooCmdArg RecycleConflictNodes(bool flag=true)
RooCmdArg Rename(const char *suffix)
RooCmdArg WeightVar(const char *name="weight", bool reinterpretAsWeight=false)
RooCmdArg Import(const char *state, TH1 &histo)
RooCmdArg DataError(Int_t)
RooCmdArg Components(Args_t &&... argsOrArgSet)
RooCmdArg LineColor(Color_t color)
RooCmdArg LineStyle(Style_t style)
leg
Definition legend1.C:34
The namespace RooFit contains mostly switches that change the behaviour of functions of PDFs (or othe...
Definition CodegenImpl.h:64
Namespace for the RooStats classes.
Definition CodegenImpl.h:58
const char * Name
Definition TXMLSetup.cxx:67
const char * Title
Definition TXMLSetup.cxx:68