Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
StandardBayesianNumericalDemo.py
Go to the documentation of this file.
1# \file
2# \ingroup tutorial_roostats
3# \notebook -js
4# Standard demo of the numerical Bayesian calculator
5#
6# This is a standard demo that can be used with any ROOT file
7# prepared in the standard way. You specify:
8# - name for input ROOT file
9# - name of workspace inside ROOT file that holds model and data
10# - name of ModelConfig that specifies details for calculator tools
11# - name of dataset
12#
13# With default parameters the macro will attempt to run the
14# standard hist2workspace example and read the ROOT file
15# that it produces.
16#
17# The actual heart of the demo is only about 10 lines long.
18#
19# The BayesianCalculator is based on Bayes's theorem
20# and performs the integration using ROOT's numeric integration utilities
21#
22# \macro_image
23# \macro_output
24# \macro_code
25#
26# \author Kyle Cranmer (C++ version), and P. P. (Python translation)
27
28import ROOT
29import time
30
31
32class Struct:
33 def __init__(self, **kargs):
34 self.__dict__.update(kargs)
35
36
37BayesianNumericalOptions = Struct( # interval CL
38 confLevel=0.95, # integration Type (default is adaptive (numerical integration)
39 # possible values are "TOYMC" (toy MC integration, work when nuisances have a constraints pdf)
40 # "VEGAS" , "MISER", or "PLAIN" (these are all possible MC integration)
41 integrationType="", # number of toys used for the MC integrations - for Vegas should be probably set to an higher value
42 nToys=10000, # flag to compute interval by scanning posterior (it is more robust but maybe less precise)
43 scanPosterior=False, # plot posterior function after having computed the interval
44 plotPosterior=True, # number of points for scanning the posterior (if scanPosterior = False it is used only for
45 # plotting). Use by default a low value to speed-up tutorial
46 nScanPoints=50, # type of interval (0 is shortest, 1 central, 2 upper limit)
47 intervalType=1, # force a different value of POI for doing the scan (default is given value)
48 maxPOI=-999, # force integration of nuisance parameters to be within nSigma of their error (do first
49 # a model fit to find nuisance error)
50 nSigmaNuisance=-1,
51)
52
53optBayes = BayesianNumericalOptions
54
55
57 infile="", workspaceName="combined", modelConfigName="ModelConfig", dataName="obsData"
58):
59
60 # Setting timer
61 t0 = time.time()
62
63 # option definitions
64 confLevel = optBayes.confLevel
65 integrationType = ROOT.TString(optBayes.integrationType)
66 nToys = optBayes.nToys
67 scanPosterior = optBayes.scanPosterior
68 plotPosterior = optBayes.plotPosterior
69 nScanPoints = optBayes.nScanPoints
70 intervalType = optBayes.intervalType
71 maxPOI = optBayes.maxPOI
72 nSigmaNuisance = optBayes.nSigmaNuisance
73
74 # -------------------------------------------------------
75 # First part is just to access a user-defined file
76 # or create the standard example file if it doesn't exist
77
78 filename = ""
79 if infile == "":
80 filename = "results/example_combined_GaussExample_model.root"
81 fileExist = not ROOT.gSystem.AccessPathName(filename) # note opposite return code
82 # if file does not exists generate with histfactory
83 if not fileExist:
84 # Normally this would be run on the command line
85 # print(f"will run standard hist2workspace example")
86 ROOT.gROOT.ProcessLine(".! prepareHistFactory .")
87 ROOT.gROOT.ProcessLine(".! hist2workspace config/example.xml")
88 print(f"\n\n---------------------")
89 print(f"Done creating example input")
90 print(f"---------------------\n\n")
91
92 else:
93 filename = infile
94
95 # Try to open the file
96 file = ROOT.TFile.Open(filename)
97
98 # if input file was specified but not found, quit
99 if not file:
100 print(f"StandardRooStatsDemoMacro: Input file {filename} is not found")
101 return
102
103 # -------------------------------------------------------
104 # Tutorial starts here
105 # -------------------------------------------------------
106
107 # get the workspace out of the file
108 w = file.Get(workspaceName)
109 if not w:
110 print(f"workspace not found")
111 return
112
113 # get the modelConfig out of the file
114 mc = w.obj(modelConfigName)
115
116 # get the modelConfig out of the file
117 data = w.data(dataName)
118
119 # make sure ingredients are found
120 if not data or not mc:
121 w.Print()
122 print(f"data or ModelConfig was not found")
123 return
124
125 # ------------------------------------------
126 # create and use the BayesianCalculator
127 # to find and plot the 95% credible interval
128 # on the parameter of interest as specified
129 # in the model config
130
131 # before we do that, we must specify our prior
132 # it belongs in the model config, but it may not have
133 # been specified
134 prior = ROOT.RooUniform("prior", "", mc.GetParametersOfInterest())
135 w.Import(prior)
136 mc.SetPriorPdf(w.pdf("prior"))
137
138 # do without systematics
139 # mc->SetNuisanceParameters(RooArgSet() );
140 if nSigmaNuisance > 0:
141 pdf = mc.GetPdf()
142 assert pdf
143 res(
144 pdf.fitTo(
145 data,
146 Save=True,
147 Minimizer=MinimizerOptions.DefaultMinimizerType(),
148 Hesse=True,
149 PrintLevel=MinimizerOptions.DefaultPrintLevel() - 1,
150 )
151 )
152
153 res.Print()
154 nuisPar = RooArgList(mc.GetNuisanceParameters())
155 for i in range(nuisPar.getSize()):
156 v = nuisPar[i]
157 assert v
158 v.setMin(TMath.Max(v.getMin(), v.getVal() - nSigmaNuisance * v.getError()))
159 v.setMax(TMath.Min(v.getMax(), v.getVal() + nSigmaNuisance * v.getError()))
160 print(f"setting interval for nuisance {v.GetName()} : [ {v.getMin()} , {v.getMax()} ] \n")
161
162 bayesianCalc = ROOT.RooStats.BayesianCalculator(data, mc)
163 bayesianCalc.SetConfidenceLevel(confLevel) # 95% interval
164
165 # default of the calculator is central interval. here use shortest , central or upper limit depending on input
166 # doing a shortest interval might require a longer time since it requires a scan of the posterior function
167 if intervalType == 0:
168 bayesianCalc.SetShortestInterval() # for shortest interval
169 if intervalType == 1:
170 bayesianCalc.SetLeftSideTailFraction(0.5) # for central interval
171 if intervalType == 2:
172 bayesianCalc.SetLeftSideTailFraction(0.0) # for upper limit
173
174 if not integrationType.IsNull():
175 bayesianCalc.SetIntegrationType(integrationType) # set integrationType
176 bayesianCalc.SetNumIters(nToys) # set number of iterations (i.e. number of toys for MC integrations)
177
178 # in case of toyMC make a nuisance pdf
179 if integrationType.Contains("TOYMC"):
180 nuisPdf = RooStats.MakeNuisancePdf(mc, "nuisance_pdf")
181 print(f"using TOYMC integration: make nuisance pdf from the model ")
182 nuisPdf.Print()
183 bayesianCalc.ForceNuisancePdf(nuisPdf)
184 scanPosterior = True # for ToyMC the posterior is scanned anyway so used given points
185
186 # compute interval by scanning the posterior function
187 if scanPosterior:
188 bayesianCalc.SetScanOfPosterior(nScanPoints)
189
190 poi = mc.GetParametersOfInterest().first()
191 if maxPOI != -999 and maxPOI > poi.getMin():
192 poi.setMax(maxPOI)
193
194 interval = bayesianCalc.GetInterval()
195
196 # print out the interval on the first Parameter of Interest
197 print(
198 f"\n>>>> RESULT : {confLevel*100}% interval on {poi.GetName()} is : ["
199 + f"{interval.LowerLimit():f}, {interval.UpperLimit():f} ] "
200 )
201
202 # end in case plotting is not requested
203 if not plotPosterior:
204 return
205
206 # make a plot
207 # since plotting may take a long time (it requires evaluating
208 # the posterior in many points) this command will speed up
209 # by reducing the number of points to plot - do 50
210
211 # ignore errors of PDF if is zero
212 ROOT.RooAbsReal.setEvalErrorLoggingMode("Ignore")
213
214 # Stop timer
215 t1 = time.time()
216 print("Standard Bayesian Numerical Algorithm was performed in :")
217 print("{:2f} seconds. ".format(t1 - t0))
218 print(f"\nDrawing plot of posterior function.....")
219 c1 = ROOT.TCanvas()
220 # always plot using number of scan points
221 bayesianCalc.SetScanOfPosterior(nScanPoints)
222
223 plot = bayesianCalc.GetPosteriorPlot()
224 plot.Draw()
225 c1.Update()
226 c1.Draw()
227 c1.SaveAs("StandardBayesianNumericalDemo.png")
228 global gbayesianCalc, gplot
229 gbayesianCalc = bayesianCalc
230 gplot = plot
231
232
233StandardBayesianNumericalDemo(infile="", workspaceName="combined", modelConfigName="ModelConfig", dataName="obsData")
static void update(gsl_integration_workspace *workspace, double a1, double b1, double area1, double error1, double a2, double b2, double area2, double error2)
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
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition RooArgList.h:22
RooAbsPdf * MakeNuisancePdf(RooAbsPdf &pdf, const RooArgSet &observables, const char *name)
extract constraint terms from pdf
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:250
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:198