Skip to content

Commit 1665cf2

Browse files
committed
Add missing images and solutions for RooFit notebook
1 parent 0d1a03b commit 1665cf2

4 files changed

Lines changed: 274 additions & 10 deletions

File tree

course/images/roofit_classes.png

81.1 KB
Loading

course/images/roofit_pdfs.png

155 KB
Loading
Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": null,
6+
"id": "b301bf8e",
7+
"metadata": {},
8+
"outputs": [],
9+
"source": [
10+
"import ROOT"
11+
]
12+
},
13+
{
14+
"cell_type": "markdown",
15+
"id": "cdc633fd",
16+
"metadata": {},
17+
"source": [
18+
"### Exercise 1"
19+
]
20+
},
21+
{
22+
"cell_type": "markdown",
23+
"id": "cf638bcf",
24+
"metadata": {},
25+
"source": [
26+
"1. **Question**: Further improve the plot with the pull distribution by visualizing also the post-fit uncertainty of the model. Figure out how to do this by reading the documentation of [RooAbsPdf::plotOn()](https://root.cern.ch/doc/master/classRooAbsPdf.html#aa0f2f98d89525302a06a1b7f1b0c2aa6)."
27+
]
28+
},
29+
{
30+
"cell_type": "markdown",
31+
"id": "bebf375c",
32+
"metadata": {},
33+
"source": [
34+
"1. **Answer**: this can be done with the `VisualizeError()` option like this:\n",
35+
"```python\n",
36+
"model.plotOn(x_frame, Name=\"model\", VisualizeError=fit_result);\n",
37+
"```\n",
38+
"Note that the uncertainty is relatively small because we have a large number of events."
39+
]
40+
},
41+
{
42+
"cell_type": "markdown",
43+
"id": "9a261718",
44+
"metadata": {},
45+
"source": [
46+
"### Exercise 2"
47+
]
48+
},
49+
{
50+
"cell_type": "markdown",
51+
"id": "ca779987",
52+
"metadata": {},
53+
"source": [
54+
"2. **Question**: Look at the [rf203_ranges.py RooFit tutorial](https://root.cern/doc/master/rf203__ranges_8py.html) to learn how to restrict the fit to a subrange. Redo the convoluted template fit to the $y$ variable, but restricted to the range from 3 to 7.\n",
55+
"\n",
56+
" Why does the uncertainty of the `resolution` parameter increase, even though we are not excluding that much signal and `resolution` doesn't affect the background?"
57+
]
58+
},
59+
{
60+
"cell_type": "markdown",
61+
"id": "45985504",
62+
"metadata": {},
63+
"source": [
64+
"2. **Answer**: Define a new subrange for $y$ with `y.setRange(\"subrange\", 3, 7)` and call `fitTo` with the `Range=\"subrange\"` keyword argument.\n",
65+
"\n",
66+
"The uncertainty on the `resolution` will increase, because also the sidebands with only background help to constrain the signal: they require that the resolution must be small enough for the signal to leak not too much in the sidebands."
67+
]
68+
},
69+
{
70+
"cell_type": "markdown",
71+
"id": "01da889e",
72+
"metadata": {},
73+
"source": [
74+
"### Exercise 3"
75+
]
76+
},
77+
{
78+
"cell_type": "markdown",
79+
"id": "bcbc7394",
80+
"metadata": {},
81+
"source": [
82+
"3. **Question**: Interpret the likelihood plot over `n_sig`. Why is the profile NLL always below the other plotted NLL?"
83+
]
84+
},
85+
{
86+
"cell_type": "markdown",
87+
"id": "5477eda4",
88+
"metadata": {},
89+
"source": [
90+
"3. **Answer**: From the likelihood plot, we can read the best fit parameter value at the minimum and the uncertainties at the points where the NLL is offset by 0.5 from the minimum (see yesterdays statistics lecture on parameter estimation).\n",
91+
"\n",
92+
"The red curve with the profile NLL is always lower than the NLL with the nuisance parameters fixed to the best-fit values, because for each value of the parameter of interest (POI), the nuisance parameters are optimized again. That's why the linklihood is always higher, or the negative log-likelihood lower.\n",
93+
"\n",
94+
"The uncertainties from the fixed likelihood can be interpreted as statistical uncertainties only, while the uncertainties from the profile liklihood include the systematic uncertainties associated to the unknown nuisance parameters."
95+
]
96+
},
97+
{
98+
"cell_type": "markdown",
99+
"id": "7b8fc976",
100+
"metadata": {},
101+
"source": [
102+
"### Exercise 4"
103+
]
104+
},
105+
{
106+
"cell_type": "markdown",
107+
"id": "eeb0dc1e",
108+
"metadata": {},
109+
"source": [
110+
"4. **Question**: In a fresh notebook, open the `RooWorkspace` we wrote to disk and create new toy data according to the 2D model. Re-fit the model to the new toy dataset."
111+
]
112+
},
113+
{
114+
"cell_type": "markdown",
115+
"id": "a44f61aa",
116+
"metadata": {},
117+
"source": [
118+
"4. **Answer**:"
119+
]
120+
},
121+
{
122+
"cell_type": "code",
123+
"execution_count": null,
124+
"id": "b3e998ba",
125+
"metadata": {},
126+
"outputs": [],
127+
"source": [
128+
"file = ROOT.TFile.Open(\"../notebooks/myworkspace.root\", \"READ\")"
129+
]
130+
},
131+
{
132+
"cell_type": "code",
133+
"execution_count": null,
134+
"id": "71f51bc8",
135+
"metadata": {},
136+
"outputs": [],
137+
"source": [
138+
"ws = file.Get(\"myworkspace\")"
139+
]
140+
},
141+
{
142+
"cell_type": "code",
143+
"execution_count": null,
144+
"id": "aef4eb3f",
145+
"metadata": {},
146+
"outputs": [],
147+
"source": [
148+
"ws.Print()"
149+
]
150+
},
151+
{
152+
"cell_type": "code",
153+
"execution_count": null,
154+
"id": "0fab2de8",
155+
"metadata": {},
156+
"outputs": [],
157+
"source": [
158+
"data_xy = ws[\"model_xy\"].generate([ws[\"x\"], ws[\"y\"]])"
159+
]
160+
},
161+
{
162+
"cell_type": "code",
163+
"execution_count": null,
164+
"id": "997dbdb8",
165+
"metadata": {},
166+
"outputs": [],
167+
"source": [
168+
"fit_result_xy = ws[\"model_xy\"].fitTo(data_xy, PrintLevel=-1, Save=True)"
169+
]
170+
},
171+
{
172+
"cell_type": "code",
173+
"execution_count": null,
174+
"id": "be075ae1",
175+
"metadata": {},
176+
"outputs": [],
177+
"source": [
178+
"fit_result_xy.Print()"
179+
]
180+
},
181+
{
182+
"cell_type": "markdown",
183+
"id": "479315e5",
184+
"metadata": {},
185+
"source": [
186+
"### Exercise 5"
187+
]
188+
},
189+
{
190+
"cell_type": "markdown",
191+
"id": "bbdf730a",
192+
"metadata": {},
193+
"source": [
194+
"5. **Question**: Which parameters are strongly (anti)correlated in the final 2D fit? Can you explain why?"
195+
]
196+
},
197+
{
198+
"cell_type": "markdown",
199+
"id": "0cd9cc20",
200+
"metadata": {},
201+
"source": [
202+
"5. **Answer**: if you print the correlation matrix of the fit result with `fit_result_xy.correlationMatrix().Print()`, you should see this:\n",
203+
"\n",
204+
"```txt\n",
205+
" | 0 | 1 | 2 | 3 | 4 | 5 \n",
206+
"-----------------------------------------------------------------------------\n",
207+
" 0 | 1 0.05982 -0.08723 -0.008045 -0.116 -0.1308\n",
208+
" 1 | 0.05982 1 -0.3631 -0.1182 -0.254 0.1301\n",
209+
" 2 | -0.08723 -0.3631 1 0.1724 0.3704 -0.1896\n",
210+
" 3 | -0.008045 -0.1182 0.1724 1 0.07469 -0.06765\n",
211+
" 4 | -0.116 -0.254 0.3704 0.07469 1 -0.1167\n",
212+
" 5 | -0.1308 0.1301 -0.1896 -0.06765 -0.1167 1\n",
213+
"```\n",
214+
"The strongest (anti-)correlations are between parameters 1 and 2, which are `n_sig` and `n_bkg`, and parameters 2 and 4, which are `n_sig` and `sigma`.\n",
215+
"\n",
216+
"These correlations make intuitive sense: the sum of `n_sig` and `n_bkg` must be constant to match the total number of observed events, which is why they are anticorrelated. If `n_sig` would be larger, `n_bkg` needs to decrease. The positive correlation between `n_sig` and the signal width for $x$ (`sigma`) is also understandable: if the width of the signal distribution would be larger, the distribution would be less peaked, and it would need to be scaled up to still match the peak in the center."
217+
]
218+
}
219+
],
220+
"metadata": {
221+
"kernelspec": {
222+
"display_name": "Python 3 (ipykernel)",
223+
"language": "python",
224+
"name": "python3"
225+
},
226+
"language_info": {
227+
"codemirror_mode": {
228+
"name": "ipython",
229+
"version": 3
230+
},
231+
"file_extension": ".py",
232+
"mimetype": "text/x-python",
233+
"name": "python",
234+
"nbconvert_exporter": "python",
235+
"pygments_lexer": "ipython3",
236+
"version": "3.13.12"
237+
}
238+
},
239+
"nbformat": 4,
240+
"nbformat_minor": 5
241+
}

course/notebooks/03-roofit.ipynb

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,18 @@
9898
}
9999
},
100100
"source": [
101-
"Mathematical concepts are represented by C++ objects:\n",
102-
"\n",
103-
"\n",
104-
"![roofit_classes.png](roofit_classes.png)"
101+
"Mathematical concepts are represented by C++ objects:"
102+
]
103+
},
104+
{
105+
"cell_type": "code",
106+
"execution_count": null,
107+
"id": "9049e569-4c05-4e41-8823-e2b96bbb604d",
108+
"metadata": {},
109+
"outputs": [],
110+
"source": [
111+
"from IPython.display import Image, display\n",
112+
"display(Image(filename=\"../images/roofit_classes.png\"))"
105113
]
106114
},
107115
{
@@ -1370,10 +1378,25 @@
13701378
"id": "d1fb099b",
13711379
"metadata": {},
13721380
"source": [
1373-
"RooFit provides a collection of standard PDF classes, e.g.:\n",
1374-
"\n",
1375-
"![roofit_pdfs.png](roofit_pdfs.png)\n",
1376-
"\n",
1381+
"RooFit provides a collection of standard PDF classes, e.g.:"
1382+
]
1383+
},
1384+
{
1385+
"cell_type": "code",
1386+
"execution_count": null,
1387+
"id": "9b0ea75d-5e74-4b82-867b-7324073a4b76",
1388+
"metadata": {},
1389+
"outputs": [],
1390+
"source": [
1391+
"from IPython.display import Image, display\n",
1392+
"display(Image(filename=\"../images/roofit_pdfs.png\"))"
1393+
]
1394+
},
1395+
{
1396+
"cell_type": "markdown",
1397+
"id": "04ab355c-650e-4700-88eb-e909c85a4e04",
1398+
"metadata": {},
1399+
"source": [
13771400
"Easy to **extend the library**: each pdf is a separate C++ class"
13781401
]
13791402
},
@@ -1962,7 +1985,7 @@
19621985
],
19631986
"metadata": {
19641987
"kernelspec": {
1965-
"display_name": "Python 3",
1988+
"display_name": "Python 3 (ipykernel)",
19661989
"language": "python",
19671990
"name": "python3"
19681991
},
@@ -1976,7 +1999,7 @@
19761999
"name": "python",
19772000
"nbconvert_exporter": "python",
19782001
"pygments_lexer": "ipython3",
1979-
"version": "3.13.11"
2002+
"version": "3.13.12"
19802003
}
19812004
},
19822005
"nbformat": 4,

0 commit comments

Comments
 (0)