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 array
31
32import ROOT
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
44def rs_numberCountingCombination(flag=1):
45
46 if flag == 1:
48 if flag == 2:
50 if flag == 3:
52
53
54# -------------------------------
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 = array.array("d", [20.0, 10.0]) # expected signal
72 b = array.array("d", [100.0, 100.0]) # expected background
73 db = array.array("d", [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.
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")
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
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("-------------------------------------------------")
123 print("The p-value for the null is ", htr.NullPValue())
124 print("Corresponding to a significance of ", htr.Significance())
125 print("-------------------------------------------------\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()
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")
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("-------------------------------------------------")
168 print("Consider this parameter point:")
170 if lrint.IsInInterval(paramsOfInterest):
171 print("It IS in the interval.")
172 else:
173 print("It is NOT in the interval.")
174 print("-------------------------------------------------\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("-------------------------------------------------")
179 print("Consider this parameter point:")
181 if lrint.IsInInterval(paramsOfInterest):
182 print("It IS in the interval.")
183 else:
184 print("It is NOT in the interval.")
185 print("-------------------------------------------------\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
230 import ctypes
231
232 ##############
233 # The same example with observed data in a main
234 # measurement and an background-only auxiliary
235 # measurement with a factor tau more background
236 # than in the main measurement.
237
238 ##############
239 # The Model building stage
240 ##############
241
242 # Step 1, define arrays with signal & bkg expectations and background uncertainties
243 # We still need the expectation to relate signal in different channels with the master signal
244 s = [20.0, 10.0] # expected signal
245 s_c = (ctypes.c_double * len(s))(*s)
246
247 # Step 2, use a RooStats factory to build a PDF for a
248 # number counting combination and add it to the workspace.
249 # We need to give the signal expectation to relate the masterSignal
250 # to the signal contribution in the individual channels.
251 # The model neglects correlations in background uncertainty,
252 # but they could be added without much change to the example.
254 wspace = ROOT.RooWorkspace()
255 f.AddModel(s_c, 2, wspace, "TopLevelPdf", "masterSignal")
256
257 # Step 3, use a RooStats factory to add datasets to the workspace.
258 # Add the observed data to the workspace
259 mainMeas = [123.0, 117.0] # observed main measurement
260 mainMeas_c = (ctypes.c_double * len(mainMeas))(*mainMeas)
261 bkgMeas = [111.23, 98.76] # observed background
262 bkgMeas_c = (ctypes.c_double * len(bkgMeas))(*bkgMeas)
263 dbMeas = [0.011, 0.0095] # observed fractional background uncertainty
264 dbMeas_c = (ctypes.c_double * len(bkgMeas))(*dbMeas)
265 f.AddData(mainMeas_c, bkgMeas_c, dbMeas_c, 2, wspace, "ObservedNumberCountingData")
266
267 # see below for a printout of the workspace
268 # wspace->Print(); #uncomment to see structure of workspace
269
270 ##############
271 # The Hypothesis testing stage:
272 ##############
273 # Step 4, Define the null hypothesis for the calculator
274 # Here you need to know the name of the variables corresponding to hypothesis.
275 mu = wspace.var("masterSignal")
276 poi = ROOT.RooArgSet(mu)
277 nullParams = ROOT.RooArgSet("nullParams")
279 # here we explicitly set the value of the parameters for the null
280 nullParams.setRealValue("masterSignal", 0)
281
282 # Step 5, Create a calculator for doing the hypothesis test.
283 # because this is a
285 wspace.data("ObservedNumberCountingData"), wspace.pdf("TopLevelPdf"), poi, 0.05, nullParams
286 )
287
288 wspace.var("tau_0").Print()
289 wspace.var("tau_1").Print()
290
291 # Step 7, Use the Calculator to get a HypoTestResult
292 htr = plc.GetHypoTest()
293 print("-------------------------------------------------")
294 print("The p-value for the null is ", htr.NullPValue())
295 print("Corresponding to a significance of ", htr.Significance())
296 print("-------------------------------------------------\n\n")
297
298 """
299 # observed case should return:
300 -------------------------------------------------
301 The p-value for the null is 0.0351669
302 Corresponding to a significance of 1.80975
303 -------------------------------------------------
304 """
305
306 ##############
307 # Confidence Interval Stage
308
309 # Step 8, Here we re-use the ProfileLikelihoodCalculator to return a confidence interval.
310 # We need to specify what are our parameters of interest
311 paramsOfInterest = nullParams # they are the same as before in this case
312 plc.SetParameters(paramsOfInterest)
313 lrint = plc.GetInterval()
315
316 # Step 9c. Get upper and lower limits
317 print("signal = ", lrint.LowerLimit(mu))
318 print("signal = ", lrint.UpperLimit(mu))
319
320 del lrint
321 del htr
322 del wspace
323 del nullParams
324 del poi
325
326
328 import ctypes
329
330 ##############
331 # The same example with observed data in a main
332 # measurement and an background-only auxiliary
333 # measurement with a factor tau more background
334 # than in the main measurement.
335
336 ##############
337 # The Model building stage
338 ##############
339
340 # Step 1, define arrays with signal & bkg expectations and background uncertainties
341 # We still need the expectation to relate signal in different channels with the master signal
342 s = [20.0, 10.0] # expected signal
343 s_c = (ctypes.c_double * 2)(*s)
344
345 # Step 2, use a RooStats factory to build a PDF for a
346 # number counting combination and add it to the workspace.
347 # We need to give the signal expectation to relate the masterSignal
348 # to the signal contribution in the individual channels.
349 # The model neglects correlations in background uncertainty,
350 # but they could be added without much change to the example.
352 wspace = ROOT.RooWorkspace()
353 f.AddModel(s_c, 2, wspace, "TopLevelPdf", "masterSignal")
354
355 # Step 3, use a RooStats factory to add datasets to the workspace.
356 # Add the observed data to the workspace in the on-off problem.
357 mainMeas = [123.0, 117.0] # observed main measurement
358 sideband = [11123.0, 9876.0] # observed sideband
359 tau = [100.0, 100.0] # ratio of bkg in sideband to bkg in main measurement, from experimental design.
360 mainMeas_c = (ctypes.c_double * 2)(*mainMeas)
361 sideband_c = (ctypes.c_double * 2)(*sideband)
362 tau_c = (ctypes.c_double * 2)(*tau)
363 f.AddDataWithSideband(mainMeas_c, sideband_c, tau_c, 2, wspace, "ObservedNumberCountingDataWithSideband")
364
365 # see below for a printout of the workspace
366 # wspace.Print(); #uncomment to see structure of workspace
367
368 ##############
369 # The Hypothesis testing stage:
370 ##############
371 # Step 4, Define the null hypothesis for the calculator
372 # Here you need to know the name of the variables corresponding to hypothesis.
373 mu = wspace.var("masterSignal")
374 poi = ROOT.RooArgSet(mu)
375 nullParams = ROOT.RooArgSet("nullParams")
377 # here we explicitly set the value of the parameters for the null
378 nullParams.setRealValue("masterSignal", 0)
379
380 # Step 5, Create a calculator for doing the hypothesis test.
381 # because this is a
383 wspace.data("ObservedNumberCountingDataWithSideband"), wspace.pdf("TopLevelPdf"), poi, 0.05, nullParams
384 )
385
386 # Step 7, Use the Calculator to get a HypoTestResult
387 htr = plc.GetHypoTest()
388 print("-------------------------------------------------")
389 print("The p-value for the null is ", htr.NullPValue())
390 print("Corresponding to a significance of ", htr.Significance())
391 print("-------------------------------------------------\n\n")
392
393 """
394 # observed case should return:
395 -------------------------------------------------
396 The p-value for the null is 0.0352035
397 Corresponding to a significance of 1.80928
398 -------------------------------------------------
399 """
400
401 ##############
402 # Confidence Interval Stage
403
404 # Step 8, Here we re-use the ProfileLikelihoodCalculator to return a confidence interval.
405 # We need to specify what are our parameters of interest
406 paramsOfInterest = nullParams # they are the same as before in this case
407 plc.SetParameters(paramsOfInterest)
408 lrint = plc.GetInterval()
410
411 # Step 9c. Get upper and lower limits
412 print("signal = ", lrint.LowerLimit(mu))
413 print("signal = ", lrint.UpperLimit(mu))
414
415 del lrint
416 del htr
417 del wspace
418 del nullParams
419 del poi
420
421
422rs_numberCountingCombination(flag=1)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
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(Option_t *option="") const override