Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
rs_numberCountingCombination.py
Go to the documentation of this file.
1# \file
2# \ingroup tutorial_roostats
3# \notebook -js
4# 'Number Counting Example' RooStats tutorial macro #100
5#
6# This tutorial shows an example of a combination of
7# two searches using number counting with background uncertainty.
8#
9# The macro uses a RooStats "factory" to construct a PDF
10# that represents the two number counting analyses with background
11# uncertainties. The uncertainties are taken into account by
12# considering a sideband measurement of a size that corresponds to the
13# background uncertainty. The problem has been studied in these references:
14# - http:#arxiv.org/abs/physics/0511028
15# - http:#arxiv.org/abs/physics/0702156
16# - http:#cdsweb.cern.ch/record/1099969?ln=en
17#
18# After using the factory to make the model, we use a RooStats
19# ProfileLikelihoodCalculator for a Hypothesis test and a confidence interval.
20# The calculator takes into account systematics by eliminating nuisance parameters
21# with the profile likelihood. This is equivalent to the method of MINOS.
22#
23#
24# \macro_image
25# \macro_output
26# \macro_code
27#
28# \author Kyle Cranmer (C++ version), and P. P. (Python translation)
29
30import numpy as np
31import ROOT
32
33
34# use this order for safety on library loading
35
36# declare three variations on the same tutorial
37# rs_numberCountingCombination_expected()
38# rs_numberCountingCombination_observed()
39# rs_numberCountingCombination_observedWithTau()
40
41
42# -------------------------------
43# main driver to choose one
45
46 if flag == 1:
47 rs_numberCountingCombination_expected()
48 if flag == 2:
49 rs_numberCountingCombination_observed()
50 if flag == 3:
51 rs_numberCountingCombination_observedWithTau()
52
53
54# -------------------------------
55def rs_numberCountingCombination_expected():
56
57 ##############
58 # An example of a number counting combination with two channels.
59 # We consider both hypothesis testing and the equivalent confidence interval.
60 ##############
61
62 ##############
63 # The Model building stage
64 ##############
65
66 # Step 1, define arrays with signal & bkg expectations and background uncertainties
67 # note: _c means is a ctype. Used for double*[2]
68 # alternatively you can use cppyy:
69 # cppyy.cppdef("double s[2]";")
70 # s_c = cppyy.gbl.s
71 s = np.array([20.0, 10.0]) # expected signal
72 b = np.array([100.0, 100.0]) # expected background
73 db = np.array([0.0100, 0.0100]) # fractional background uncertainty
74
75 # Step 2, use a RooStats factory to build a PDF for a
76 # number counting combination and add it to the workspace.
77 # We need to give the signal expectation to relate the masterSignal
78 # to the signal contribution in the individual channels.
79 # The model neglects correlations in background uncertainty,
80 # but they could be added without much change to the example.
81 f = ROOT.RooStats.NumberCountingPdfFactory()
82 wspace = ROOT.RooWorkspace()
83 # debugging
84 global gf, gwspace
85 gf = f
86 gwspace = wspace
87 global gs # list
88 gs = s
89 # return
90
91 f.AddModel(s, 2, wspace, "TopLevelPdf", "masterSignal")
92
93 # Step 3, use a RooStats factory to add datasets to the workspace.
94 # Step 3a.
95 # Add the expected data to the workspace
96 f.AddExpData(s, b, db, 2, wspace, "ExpectedNumberCountingData")
97
98 # see below for a printout of the workspace
99 # wspace->Print(); #uncomment to see structure of workspace
100
101 ##############
102 # The Hypothesis testing stage:
103 ##############
104 # Step 4, Define the null hypothesis for the calculator
105 # Here you need to know the name of the variables corresponding to hypothesis.
106 mu = wspace.var("masterSignal")
107 poi = ROOT.RooArgSet(mu)
108 nullParams = ROOT.RooArgSet("nullParams")
109 nullParams.addClone(mu)
110 # here we explicitly set the value of the parameters for the null
111 nullParams.setRealValue("masterSignal", 0)
112
113 # Step 5, Create a calculator for doing the hypothesis test.
114 # because this is a
115 plc = ROOT.RooStats.ProfileLikelihoodCalculator(
116 wspace["ExpectedNumberCountingData"], wspace["TopLevelPdf"], poi, 0.05, nullParams
117 )
118
119 # Step 6, Use the Calculator to get a HypoTestResult
120 htr = plc.GetHypoTest()
121 assert htr != 0
122 print(f"-------------------------------------------------")
123 print(f"The p-value for the null is ", htr.NullPValue())
124 print(f"Corresponding to a significance of ", htr.Significance())
125 print(f"-------------------------------------------------\n\n")
126
127 # expected case should return:
128 # -------------------------------------------------
129 # The p-value for the null is 0.015294
130 # Corresponding to a significance of 2.16239
131 # -------------------------------------------------
132
133 ##############
134 # #Confidence Interval Stage
135
136 # Step 8, Here we re-use the ProfileLikelihoodCalculator to return a confidence interval.
137 # We need to specify what are our parameters of interest
138 paramsOfInterest = nullParams # they are the same as before in this case
139 plc.SetParameters(paramsOfInterest)
140 lrint = plc.GetInterval()
141 lrint.SetConfidenceLevel(0.95)
142
143 # Step 9, make a plot of the likelihood ratio and the interval obtained
144 # paramsOfInterest->setRealValue("masterSignal",1.);
145 # find limits
146 lower = lrint.LowerLimit(mu)
147 upper = lrint.UpperLimit(mu)
148
149 c1 = ROOT.TCanvas("myc1", "myc1")
150 lrPlot = ROOT.RooStats.LikelihoodIntervalPlot(lrint)
151 lrPlot.SetMaximum(3.0)
152 lrPlot.Draw()
153 c1.Update()
154 c1.Draw()
155 c1.SaveAs("rs_numberCountingCombination.png")
156
157 # Step 10a. Get upper and lower limits
158 print("signal = ", lower)
159 print("signal = ", upper)
160
161 # Step 10b, Ask if masterSignal=0 is in the interval.
162 # Note, this is equivalent to the question of a 2-sigma hypothesis test:
163 # "is the parameter point masterSignal=0 inside the 95% confidence interval?"
164 # Since the significance of the Hypothesis test was > 2-sigma it should not be:
165 # eg. we exclude masterSignal=0 at 95% confidence.
166 paramsOfInterest.setRealValue("masterSignal", 0.0)
167 print(f"-------------------------------------------------")
168 print(f"Consider this parameter point:")
169 paramsOfInterest.first().Print()
170 if lrint.IsInInterval(paramsOfInterest):
171 print(f"It IS in the interval.")
172 else:
173 print(f"It is NOT in the interval.")
174 print(f"-------------------------------------------------\n\n")
175
176 # Step 10c, We also ask about the parameter point masterSignal=2, which is inside the interval.
177 paramsOfInterest.setRealValue("masterSignal", 2.0)
178 print(f"-------------------------------------------------")
179 print(f"Consider this parameter point:")
180 paramsOfInterest.first().Print()
181 if lrint.IsInInterval(paramsOfInterest):
182 print(f"It IS in the interval.")
183 else:
184 print(f"It is NOT in the interval.")
185 print(f"-------------------------------------------------\n\n")
186
187 del lrint
188 del htr
189 del wspace
190 del poi
191 del nullParams
192
193 """
194 #
195 # Here's an example of what is in the workspace
196 # wspace.Print();
197 RooWorkspace(NumberCountingWS) Number Counting WS contents
198
199 variables
200 ---------
201 (x_0,masterSignal,expected_s_0,b_0,y_0,tau_0,x_1,expected_s_1,b_1,y_1,tau_1)
202
203 p.d.f.s
204 -------
205 RooProdPdf.joint[ pdfs=(sigRegion_0,sideband_0,sigRegion_1,sideband_1) ] = 2.20148e-08
206 RooPoisson.sigRegion_0[ x=x_0 mean=splusb_0 ] = 0.036393
207 RooPoisson.sideband_0[ x=y_0 mean=bTau_0 ] = 0.00398939
208 RooPoisson.sigRegion_1[ x=x_1 mean=splusb_1 ] = 0.0380088
209 RooPoisson.sideband_1[ x=y_1 mean=bTau_1 ] = 0.00398939
210
211 functions
212 --------
213 RooAddition.splusb_0[ set1=(s_0,b_0) set2=() ] = 120
214 RooProduct.s_0[ compRSet=(masterSignal,expected_s_0) compCSet=() ] = 20
215 RooProduct.bTau_0[ compRSet=(b_0,tau_0) compCSet=() ] = 10000
216 RooAddition.splusb_1[ set1=(s_1,b_1) set2=() ] = 110
217 RooProduct.s_1[ compRSet=(masterSignal,expected_s_1) compCSet=() ] = 10
218 RooProduct.bTau_1[ compRSet=(b_1,tau_1) compCSet=() ] = 10000
219
220 datasets
221 --------
222 RooDataSet.ExpectedNumberCountingData(x_0,y_0,x_1,y_1)
223
224 embedded pre-calculated expensive components
225 -------------------------------------------
226 """
227
228
229def rs_numberCountingCombination_observed():
230
231 ##############
232 # The same example with observed data in a main
233 # measurement and an background-only auxiliary
234 # measurement with a factor tau more background
235 # than in the main measurement.
236
237 ##############
238 # The Model building stage
239 ##############
240
241 # Step 1, define arrays with signal & bkg expectations and background uncertainties
242 # We still need the expectation to relate signal in different channels with the master signal
243 s = [20.0, 10.0] # expected signal
244 s_c = (ctypes.c_double * len(s))(*s)
245
246 # Step 2, use a RooStats factory to build a PDF for a
247 # number counting combination and add it to the workspace.
248 # We need to give the signal expectation to relate the masterSignal
249 # to the signal contribution in the individual channels.
250 # The model neglects correlations in background uncertainty,
251 # but they could be added without much change to the example.
252 f = NumberCountingPdfFactory()
253 wspace = RooWorkspace()
254 f.AddModel(s_c, 2, wspace, "TopLevelPdf", "masterSignal")
255
256 # Step 3, use a RooStats factory to add datasets to the workspace.
257 # Add the observed data to the workspace
258 mainMeas = [123.0, 117.0] # observed main measurement
259 mainMeas_c = (ctypes.c_double * len(mainMeas))(*mainMeas)
260 bkgMeas = [111.23, 98.76] # observed background
261 bkgMeas_c = (ctypes.c_double * len(bkgMeas))(*bkgMeas)
262 dbMeas = [0.011, 0.0095] # observed fractional background uncertainty
263 dbMeas_c = (ctypes.c_double * len(bkgMeas))(*dbMeas)
264 f.AddData(mainMeas_c, bkgMeas_c, dbMeas_c, 2, wspace, "ObservedNumberCountingData")
265
266 # see below for a printout of the workspace
267 # wspace->Print(); #uncomment to see structure of workspace
268
269 ##############
270 # The Hypothesis testing stage:
271 ##############
272 # Step 4, Define the null hypothesis for the calculator
273 # Here you need to know the name of the variables corresponding to hypothesis.
274 mu = wspace.var("masterSignal")
275 poi = RooArgSet(mu)
276 nullParams = RooArgSet("nullParams")
277 nullParams.addClone(mu)
278 # here we explicitly set the value of the parameters for the null
279 nullParams.setRealValue("masterSignal", 0)
280
281 # Step 5, Create a calculator for doing the hypothesis test.
282 # because this is a
283 plc = ProfileLikelihoodCalculator(
284 wspace.data("ObservedNumberCountingData"), wspace.pdf("TopLevelPdf"), poi, 0.05, nullParams
285 )
286
287 wspace.var("tau_0").Print()
288 wspace.var("tau_1").Print()
289
290 # Step 7, Use the Calculator to get a HypoTestResult
291 htr = plc.GetHypoTest()
292 print(f"-------------------------------------------------")
293 print(f"The p-value for the null is ", htr.NullPValue())
294 print(f"Corresponding to a significance of ", htr.Significance())
295 print(f"-------------------------------------------------\n\n")
296
297 """
298 # observed case should return:
299 -------------------------------------------------
300 The p-value for the null is 0.0351669
301 Corresponding to a significance of 1.80975
302 -------------------------------------------------
303 """
304
305 ##############
306 # Confidence Interval Stage
307
308 # Step 8, Here we re-use the ProfileLikelihoodCalculator to return a confidence interval.
309 # We need to specify what are our parameters of interest
310 paramsOfInterest = nullParams # they are the same as before in this case
311 plc.SetParameters(paramsOfInterest)
312 lrint = plc.GetInterval()
313 lrint.SetConfidenceLevel(0.95)
314
315 # Step 9c. Get upper and lower limits
316 print("signal = ", lrint.LowerLimit(mu))
317 print("signal = ", lrint.UpperLimit(mu))
318
319 del lrint
320 del htr
321 del wspace
322 del nullParams
323 del poi
324
325
326def rs_numberCountingCombination_observedWithTau():
327
328 ##############
329 # The same example with observed data in a main
330 # measurement and an background-only auxiliary
331 # measurement with a factor tau more background
332 # than in the main measurement.
333
334 ##############
335 # The Model building stage
336 ##############
337
338 # Step 1, define arrays with signal & bkg expectations and background uncertainties
339 # We still need the expectation to relate signal in different channels with the master signal
340 s = [20.0, 10.0] # expected signal
341 s_c = (ctypes.c_double * 2)(*s)
342
343 # Step 2, use a RooStats factory to build a PDF for a
344 # number counting combination and add it to the workspace.
345 # We need to give the signal expectation to relate the masterSignal
346 # to the signal contribution in the individual channels.
347 # The model neglects correlations in background uncertainty,
348 # but they could be added without much change to the example.
349 f = NumberCountingPdfFactory()
350 wspace = RooWorkspace()
351 f.AddModel(s_c, 2, wspace, "TopLevelPdf", "masterSignal")
352
353 # Step 3, use a RooStats factory to add datasets to the workspace.
354 # Add the observed data to the workspace in the on-off problem.
355 mainMeas = [123.0, 117.0] # observed main measurement
356 sideband = [11123.0, 9876.0] # observed sideband
357 tau = [100.0, 100.0] # ratio of bkg in sideband to bkg in main measurement, from experimental design.
358 mainMeas_c = (ctypes.c_double * 2)(*mainMeas)
359 sideband_c = (ctypes.c_double * 2)(*sideband)
360 tau_c = (ctypes.c_double * 2)(*tau)
361 f.AddDataWithSideband(mainMeas_c, sideband_c, tau_c, 2, wspace, "ObservedNumberCountingDataWithSideband")
362
363 # see below for a printout of the workspace
364 # wspace.Print(); #uncomment to see structure of workspace
365
366 ##############
367 # The Hypothesis testing stage:
368 ##############
369 # Step 4, Define the null hypothesis for the calculator
370 # Here you need to know the name of the variables corresponding to hypothesis.
371 mu = wspace.var("masterSignal")
372 poi = RooArgSet(mu)
373 nullParams = RooArgSet("nullParams")
374 nullParams.addClone(mu)
375 # here we explicitly set the value of the parameters for the null
376 nullParams.setRealValue("masterSignal", 0)
377
378 # Step 5, Create a calculator for doing the hypothesis test.
379 # because this is a
380 plc = ProfileLikelihoodCalculator(
381 wspace.data("ObservedNumberCountingDataWithSideband"), wspace.pdf("TopLevelPdf"), poi, 0.05, nullParams
382 )
383
384 # Step 7, Use the Calculator to get a HypoTestResult
385 htr = plc.GetHypoTest()
386 print(f"-------------------------------------------------")
387 print(f"The p-value for the null is ", htr.NullPValue())
388 print(f"Corresponding to a significance of ", htr.Significance())
389 print(f"-------------------------------------------------\n\n")
390
391 """
392 # observed case should return:
393 -------------------------------------------------
394 The p-value for the null is 0.0352035
395 Corresponding to a significance of 1.80928
396 -------------------------------------------------
397 """
398
399 ##############
400 # Confidence Interval Stage
401
402 # Step 8, Here we re-use the ProfileLikelihoodCalculator to return a confidence interval.
403 # We need to specify what are our parameters of interest
404 paramsOfInterest = nullParams # they are the same as before in this case
405 plc.SetParameters(paramsOfInterest)
406 lrint = plc.GetInterval()
407 lrint.SetConfidenceLevel(0.95)
408
409 # Step 9c. Get upper and lower limits
410 print("signal = ", lrint.LowerLimit(mu))
411 print("signal = ", lrint.UpperLimit(mu))
412
413 del lrint
414 del htr
415 del wspace
416 del nullParams
417 del poi
418
419
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
void Print(GNN_Data &d, std::string txt="")
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:24
Persistable container for RooFit projects.