Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
MultivariateGaussianTest.py
Go to the documentation of this file.
1## \file
2## \ingroup tutorial_roostats
3## \notebook
4## Comparison of MCMC and PLC in a multi-variate gaussian problem
5##
6## This tutorial produces an N-dimensional multivariate Gaussian
7## with a non-trivial covariance matrix. By default N=4 (called "dim").
8##
9## A subset of these are considered parameters of interest.
10## This problem is tractable analytically.
11##
12## We use this mainly as a test of Markov Chain Monte Carlo
13## and we compare the result to the profile likelihood ratio.
14##
15## We use the proposal helper to create a customized
16## proposal function for this problem.
17##
18## For N=4 and 2 parameters of interest it takes about 10-20 seconds
19## and the acceptance rate is 37%
20##
21## \macro_image
22## \macro_output
23## \macro_code
24##
25## \date July 2022
26## \authors Artem Busorgin, Kevin Belasco and Kyle Cranmer (C++ version)
27
28import ROOT
29
30dim = 4
31nPOI = 2
32
33# let's time this challenging example
34t = ROOT.TStopwatch()
35t.Start()
36
37xVec = []
38muVec = []
39poi = set()
40
41# make the observable and means
42for i in range(dim):
43 name = "x{}".format(i)
44 x = ROOT.RooRealVar(name, name, 0, -3, 3)
45 xVec.append(x)
46
47 mu_name = "mu_x{}".format(i)
48 mu_x = ROOT.RooRealVar(mu_name, mu_name, 0, -2, 2)
49 muVec.append(mu_x)
50
51# put them into the list of parameters of interest
52for i in range(nPOI):
53 poi.add(muVec[i])
54
55# make a covariance matrix that is all 1's
56cov = ROOT.TMatrixDSym(dim)
57for i in range(dim):
58 for j in range(dim):
59 if i == j:
60 cov[i, j] = 3.0
61 else:
62 cov[i, j] = 1.0
63
64# now make the multivariate Gaussian
65mvg = ROOT.RooMultiVarGaussian("mvg", "mvg", xVec, muVec, cov)
66
67# --------------------
68# make a toy dataset
69data = mvg.generate(xVec, 100)
70
71# now create the model config for this problem
72w = ROOT.RooWorkspace("MVG")
73modelConfig = ROOT.RooStats.ModelConfig(w)
74modelConfig.SetPdf(mvg)
75modelConfig.SetParametersOfInterest(poi)
76
77# -------------------------------------------------------
78# Setup calculators
79
80# MCMC
81# we want to setup an efficient proposal function
82# using the covariance matrix from a fit to the data
83fit = mvg.fitTo(data, Save=True)
84ph = ROOT.RooStats.ProposalHelper()
85ph.SetVariables(fit.floatParsFinal())
86ph.SetCovMatrix(fit.covarianceMatrix())
87ph.SetUpdateProposalParameters(True)
88ph.SetCacheSize(100)
89pdfProp = ph.GetProposalFunction()
90
91# now create the calculator
92mc = ROOT.RooStats.MCMCCalculator(data, modelConfig)
93mc.SetConfidenceLevel(0.95)
94mc.SetNumBurnInSteps(100)
95mc.SetNumIters(10000)
96mc.SetNumBins(50)
97mc.SetProposalFunction(pdfProp)
98
99mcInt = mc.GetInterval()
100poiList = mcInt.GetAxes()
101
102# now setup the profile likelihood calculator
103plc = ROOT.RooStats.ProfileLikelihoodCalculator(data, modelConfig)
104plc.SetConfidenceLevel(0.95)
105plInt = plc.GetInterval()
106
107# make some plots
108mcPlot = ROOT.RooStats.MCMCIntervalPlot(mcInt)
109
110c1 = ROOT.TCanvas()
111mcPlot.SetLineColor(ROOT.kGreen)
112mcPlot.SetLineWidth(2)
113mcPlot.Draw()
114
115plPlot = ROOT.RooStats.LikelihoodIntervalPlot(plInt)
116plPlot.Draw("same")
117
118if len(poiList) == 1:
119 p = poiList.at(0)
120 print("MCMC interval: [{}, {}]".format(mcInt.LowerLimit(p), mcInt.UpperLimit(p)))
121
122if len(poiList) == 2:
123 p0 = poiList.at(0)
124 p1 = poiList.at(1)
125 scatter = ROOT.TCanvas()
126 print("MCMC interval on p0: [{}, {}]".format(mcInt.LowerLimit(p0), mcInt.UpperLimit(p0)))
127 print("MCMC interval on p1: [{}, {}]".format(mcInt.LowerLimit(p1), mcInt.UpperLimit(p1)))
128
129 # MCMC interval on p0: [-0.2, 0.6]
130 # MCMC interval on p1: [-0.2, 0.6]
131
132 mcPlot.DrawChainScatter(p0, p1)
133 scatter.Update()
134 scatter.SaveAs("MultivariateGaussianTest_scatter.png")
135
136t.Stop()
137t.Print()
138
139c1.SaveAs("MultivariateGaussianTest_plot.png")
140
141# TODO: The MCMCCalculator has to be destructed first. Otherwise, we can get
142# segmentation faults depending on the destruction order, which is random in
143# Python. Probably the issue is that some object has a non-owning pointer to
144# another object, which it uses in its destructor. This should be fixed either
145# in the design of RooStats in C++, or with phythonizations.
146del mc
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t format