{
"cells": [
{
"cell_type": "markdown",
"id": "9f2b8e40",
"metadata": {},
"source": [
"# rf207_comptools\n",
"Addition and convolution: tools and utilities for manipulation of composite objects\n",
"\n",
"\n",
"\n",
"\n",
"**Author:** Wouter Verkerke \n",
"This notebook tutorial was automatically generated with ROOTBOOK-izer from the macro found in the ROOT repository on Tuesday, May 19, 2026 at 08:29 PM."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "edf43a1f",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:30:01.790423Z",
"iopub.status.busy": "2026-05-19T20:30:01.790314Z",
"iopub.status.idle": "2026-05-19T20:30:01.804005Z",
"shell.execute_reply": "2026-05-19T20:30:01.803096Z"
}
},
"outputs": [],
"source": [
"%%cpp -d\n",
"#include \"RooRealVar.h\"\n",
"#include \"RooDataSet.h\"\n",
"#include \"RooGaussian.h\"\n",
"#include \"RooChebychev.h\"\n",
"#include \"RooExponential.h\"\n",
"#include \"RooAddPdf.h\"\n",
"#include \"RooPlot.h\"\n",
"#include \"RooCustomizer.h\"\n",
"#include \"TCanvas.h\"\n",
"#include \"TAxis.h\"\n",
"#include \"TH1.h\"\n",
"using namespace RooFit;"
]
},
{
"cell_type": "markdown",
"id": "72d4d38d",
"metadata": {},
"source": [
"Setup composite pdf, dataset\n",
"--------------------------------------------------------"
]
},
{
"cell_type": "markdown",
"id": "f2a4172b",
"metadata": {},
"source": [
"Declare observable x"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "1a556dec",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:30:01.805323Z",
"iopub.status.busy": "2026-05-19T20:30:01.805210Z",
"iopub.status.idle": "2026-05-19T20:30:02.013982Z",
"shell.execute_reply": "2026-05-19T20:30:02.013169Z"
}
},
"outputs": [],
"source": [
"RooRealVar x(\"x\", \"x\", 0, 10);"
]
},
{
"cell_type": "markdown",
"id": "0ffe5dea",
"metadata": {},
"source": [
"Create two Gaussian PDFs g1(x,mean1,sigma) anf g2(x,mean2,sigma) and their parameters"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "6428ab63",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:30:02.015942Z",
"iopub.status.busy": "2026-05-19T20:30:02.015822Z",
"iopub.status.idle": "2026-05-19T20:30:02.228862Z",
"shell.execute_reply": "2026-05-19T20:30:02.223305Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[#0] WARNING:InputArguments -- The parameter 'sigma' with range [-inf, inf] of the RooGaussian 'sig' exceeds the safe range of (0, inf). Advise to limit its range.\n"
]
}
],
"source": [
"RooRealVar mean(\"mean\", \"mean of gaussians\", 5);\n",
"RooRealVar sigma(\"sigma\", \"width of gaussians\", 0.5);\n",
"RooGaussian sig(\"sig\", \"Signal component 1\", x, mean, sigma);"
]
},
{
"cell_type": "markdown",
"id": "74404c7a",
"metadata": {},
"source": [
"Build Chebychev polynomial pdf"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "adb9e9e7",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:30:02.230772Z",
"iopub.status.busy": "2026-05-19T20:30:02.230651Z",
"iopub.status.idle": "2026-05-19T20:30:02.438781Z",
"shell.execute_reply": "2026-05-19T20:30:02.437668Z"
}
},
"outputs": [],
"source": [
"RooRealVar a0(\"a0\", \"a0\", 0.5, 0., 1.);\n",
"RooRealVar a1(\"a1\", \"a1\", 0.2, 0., 1.);\n",
"RooChebychev bkg1(\"bkg1\", \"Background 1\", x, RooArgSet(a0, a1));"
]
},
{
"cell_type": "markdown",
"id": "cf812e55",
"metadata": {},
"source": [
"Build exponential pdf"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "dd0782c0",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:30:02.440560Z",
"iopub.status.busy": "2026-05-19T20:30:02.440434Z",
"iopub.status.idle": "2026-05-19T20:30:02.648748Z",
"shell.execute_reply": "2026-05-19T20:30:02.647570Z"
}
},
"outputs": [],
"source": [
"RooRealVar alpha(\"alpha\", \"alpha\", -1);\n",
"RooExponential bkg2(\"bkg2\", \"Background 2\", x, alpha);"
]
},
{
"cell_type": "markdown",
"id": "4bca293f",
"metadata": {},
"source": [
"Sum the background components into a composite background pdf"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "c1807716",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:30:02.650407Z",
"iopub.status.busy": "2026-05-19T20:30:02.650290Z",
"iopub.status.idle": "2026-05-19T20:30:02.858803Z",
"shell.execute_reply": "2026-05-19T20:30:02.857472Z"
}
},
"outputs": [],
"source": [
"RooRealVar bkg1frac(\"bkg1frac\", \"fraction of component 1 in background\", 0.2, 0., 1.);\n",
"RooAddPdf bkg(\"bkg\", \"Signal\", RooArgList(bkg1, bkg2), bkg1frac);"
]
},
{
"cell_type": "markdown",
"id": "2965eef3",
"metadata": {},
"source": [
"Sum the composite signal and background"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "454cbf84",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:30:02.860676Z",
"iopub.status.busy": "2026-05-19T20:30:02.860538Z",
"iopub.status.idle": "2026-05-19T20:30:03.068799Z",
"shell.execute_reply": "2026-05-19T20:30:03.067691Z"
}
},
"outputs": [],
"source": [
"RooRealVar bkgfrac(\"bkgfrac\", \"fraction of background\", 0.5, 0., 1.);\n",
"RooAddPdf model(\"model\", \"g1+g2+a\", RooArgList(bkg, sig), bkgfrac);"
]
},
{
"cell_type": "markdown",
"id": "1443b653",
"metadata": {},
"source": [
"Create dummy dataset that has more observables than the above pdf"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "95edd1b3",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:30:03.070433Z",
"iopub.status.busy": "2026-05-19T20:30:03.070316Z",
"iopub.status.idle": "2026-05-19T20:30:03.278572Z",
"shell.execute_reply": "2026-05-19T20:30:03.277803Z"
}
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"input_line_55:3:1: warning: 'data' shadows a declaration with the same name in the 'std' namespace; use '::data' to reference this declaration\n",
"RooDataSet data(\"data\", \"data\", RooArgSet(x, y));\n",
"^\n"
]
}
],
"source": [
"RooRealVar y(\"y\", \"y\", -10, 10);\n",
"RooDataSet data(\"data\", \"data\", RooArgSet(x, y));"
]
},
{
"cell_type": "markdown",
"id": "470cc24a",
"metadata": {},
"source": [
"---------------------------------------------------\n",
"Basic information requests\n",
"==================================================="
]
},
{
"cell_type": "markdown",
"id": "3659af5e",
"metadata": {},
"source": [
"Get list of observables\n",
"---------------------------------------------"
]
},
{
"cell_type": "markdown",
"id": "5ba64624",
"metadata": {},
"source": [
"Get list of observables of pdf in context of a dataset\n",
"\n",
"Observables are define each context as the variables\n",
"shared between a model and a dataset. In this case\n",
"that is the variable 'x'"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "245f8c62",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:30:03.280212Z",
"iopub.status.busy": "2026-05-19T20:30:03.280095Z",
"iopub.status.idle": "2026-05-19T20:30:03.486678Z",
"shell.execute_reply": "2026-05-19T20:30:03.485887Z"
}
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"input_line_56:2:60: error: reference to 'data' is ambiguous\n",
" std::unique_ptr model_obs{model.getObservables(data)};\n",
" ^\n",
"input_line_55:3:12: note: candidate found by name lookup is 'data'\n",
"RooDataSet data(\"data\", \"data\", RooArgSet(x, y));\n",
" ^\n",
"/usr/lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/bits/range_access.h:344:5: note: candidate found by name lookup is 'std::data'\n",
" data(initializer_list<_Tp> __il) noexcept\n",
" ^\n",
"/usr/lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/bits/range_access.h:312:5: note: candidate found by name lookup is 'std::data'\n",
" data(_Container& __cont) noexcept(noexcept(__cont.data()))\n",
" ^\n",
"/usr/lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/bits/range_access.h:323:5: note: candidate found by name lookup is 'std::data'\n",
" data(const _Container& __cont) noexcept(noexcept(__cont.data()))\n",
" ^\n",
"/usr/lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/bits/range_access.h:334:5: note: candidate found by name lookup is 'std::data'\n",
" data(_Tp (&__array)[_Nm]) noexcept\n",
" ^\n"
]
}
],
"source": [
"std::unique_ptr model_obs{model.getObservables(data)};\n",
"model_obs->Print(\"v\");"
]
},
{
"cell_type": "markdown",
"id": "b19ca8e8",
"metadata": {},
"source": [
"Get list of parameters\n",
"-------------------------------------------"
]
},
{
"cell_type": "markdown",
"id": "bf063c96",
"metadata": {},
"source": [
"Get list of parameters, given list of observables"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "ebf690c8",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:30:03.488272Z",
"iopub.status.busy": "2026-05-19T20:30:03.488155Z",
"iopub.status.idle": "2026-05-19T20:30:03.694273Z",
"shell.execute_reply": "2026-05-19T20:30:03.693424Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" 1) 0x7f69d9247000 RooRealVar:: a0 = 0.5 L(0 - 1) \"a0\"\n",
" 2) 0x7f69d92473e8 RooRealVar:: a1 = 0.2 L(0 - 1) \"a1\"\n",
" 3) 0x7f69d923f000 RooRealVar:: alpha = -1 C L(-INF - +INF) \"alpha\"\n",
" 4) 0x7f69d923c000 RooRealVar:: bkg1frac = 0.2 L(0 - 1) \"fraction of component 1 in background\"\n",
" 5) 0x7f69d9239000 RooRealVar:: bkgfrac = 0.5 L(0 - 1) \"fraction of background\"\n",
" 6) 0x7f69d924a000 RooRealVar:: mean = 5 C L(-INF - +INF) \"mean of gaussians\"\n",
" 7) 0x7f69d924a3e8 RooRealVar:: sigma = 0.5 C L(-INF - +INF) \"width of gaussians\"\n"
]
}
],
"source": [
"std::unique_ptr model_params{model.getParameters(x)};\n",
"model_params->Print(\"v\");"
]
},
{
"cell_type": "markdown",
"id": "0064dbc8",
"metadata": {},
"source": [
"Get list of parameters, given a dataset\n",
"(Gives identical results to operation above)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "1fb26bc2",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:30:03.695800Z",
"iopub.status.busy": "2026-05-19T20:30:03.695681Z",
"iopub.status.idle": "2026-05-19T20:30:03.916102Z",
"shell.execute_reply": "2026-05-19T20:30:03.904678Z"
}
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"input_line_58:2:63: error: reference to 'data' is ambiguous\n",
" std::unique_ptr model_params2{model.getParameters(data)};\n",
" ^\n",
"input_line_55:3:12: note: candidate found by name lookup is 'data'\n",
"RooDataSet data(\"data\", \"data\", RooArgSet(x, y));\n",
" ^\n",
"/usr/lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/bits/range_access.h:344:5: note: candidate found by name lookup is 'std::data'\n",
" data(initializer_list<_Tp> __il) noexcept\n",
" ^\n",
"/usr/lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/bits/range_access.h:312:5: note: candidate found by name lookup is 'std::data'\n",
" data(_Container& __cont) noexcept(noexcept(__cont.data()))\n",
" ^\n",
"/usr/lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/bits/range_access.h:323:5: note: candidate found by name lookup is 'std::data'\n",
" data(const _Container& __cont) noexcept(noexcept(__cont.data()))\n",
" ^\n",
"/usr/lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/bits/range_access.h:334:5: note: candidate found by name lookup is 'std::data'\n",
" data(_Tp (&__array)[_Nm]) noexcept\n",
" ^\n"
]
}
],
"source": [
"std::unique_ptr model_params2{model.getParameters(data)};\n",
"model_params2->Print();"
]
},
{
"cell_type": "markdown",
"id": "d11cd6ac",
"metadata": {},
"source": [
"Get list of components\n",
"-------------------------------------------"
]
},
{
"cell_type": "markdown",
"id": "e5b315bb",
"metadata": {},
"source": [
"Get list of component objects, including top-level node"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "9d6f97d1",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:30:03.927355Z",
"iopub.status.busy": "2026-05-19T20:30:03.927216Z",
"iopub.status.idle": "2026-05-19T20:30:04.133256Z",
"shell.execute_reply": "2026-05-19T20:30:04.132562Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" 1) 0x7f69d92393e8 RooAddPdf:: model[ bkgfrac * bkg + [%] * sig ] = 0.582695/1 \"g1+g2+a\"\n",
" 2) 0x7f69d923c3e8 RooAddPdf:: bkg[ bkg1frac * bkg1 + [%] * bkg2 ] = 0.16539/1 \"Signal\"\n",
" 3) 0x7f69d92477d0 RooChebychev:: bkg1[ x=x coefList=(a0,a1) ] = 0.8 \"Background 1\"\n",
" 4) 0x7f69d923f3e8 RooExponential:: bkg2[ x=x c=alpha ] = 0.00673795 \"Background 2\"\n",
" 5) 0x7f69d924a7d0 RooGaussian:: sig[ x=x mean=mean sigma=sigma ] = 1 \"Signal component 1\"\n"
]
}
],
"source": [
"std::unique_ptr model_comps{model.getComponents()};\n",
"model_comps->Print(\"v\");"
]
},
{
"cell_type": "markdown",
"id": "5abec110",
"metadata": {},
"source": [
"-------------------------------------------------------------------------------\n",
"Modifications to structure of composites\n",
"==============================================================================="
]
},
{
"cell_type": "markdown",
"id": "5a0ee0eb",
"metadata": {},
"source": [
"Create a second Gaussian"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "8f31be20",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:30:04.135100Z",
"iopub.status.busy": "2026-05-19T20:30:04.134982Z",
"iopub.status.idle": "2026-05-19T20:30:04.343513Z",
"shell.execute_reply": "2026-05-19T20:30:04.343137Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[#0] WARNING:InputArguments -- The parameter 'sigma2' with range [-inf, inf] of the RooGaussian 'sig2' exceeds the safe range of (0, inf). Advise to limit its range.\n"
]
}
],
"source": [
"RooRealVar sigma2(\"sigma2\", \"width of gaussians\", 1);\n",
"RooGaussian sig2(\"sig2\", \"Signal component 1\", x, mean, sigma2);"
]
},
{
"cell_type": "markdown",
"id": "6af84c7d",
"metadata": {},
"source": [
"Create a sum of the original Gaussian plus the new second Gaussian"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "b2b2f509",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:30:04.348237Z",
"iopub.status.busy": "2026-05-19T20:30:04.348115Z",
"iopub.status.idle": "2026-05-19T20:30:04.556612Z",
"shell.execute_reply": "2026-05-19T20:30:04.555414Z"
}
},
"outputs": [],
"source": [
"RooRealVar sig1frac(\"sig1frac\", \"fraction of component 1 in signal\", 0.8, 0., 1.);\n",
"RooAddPdf sigsum(\"sigsum\", \"sig+sig2\", RooArgList(sig, sig2), sig1frac);"
]
},
{
"cell_type": "markdown",
"id": "b130e5e3",
"metadata": {},
"source": [
"Construct a customizer utility to customize model"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "94ae7b1b",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:30:04.558221Z",
"iopub.status.busy": "2026-05-19T20:30:04.558105Z",
"iopub.status.idle": "2026-05-19T20:30:04.763424Z",
"shell.execute_reply": "2026-05-19T20:30:04.762709Z"
}
},
"outputs": [],
"source": [
"RooCustomizer cust(model, \"cust\");"
]
},
{
"cell_type": "markdown",
"id": "09e6a939",
"metadata": {},
"source": [
"Instruct the customizer to replace node 'sig' with node 'sigsum'"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "0cebc340",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:30:04.765313Z",
"iopub.status.busy": "2026-05-19T20:30:04.765202Z",
"iopub.status.idle": "2026-05-19T20:30:04.972859Z",
"shell.execute_reply": "2026-05-19T20:30:04.972149Z"
}
},
"outputs": [],
"source": [
"cust.replaceArg(sig, sigsum);"
]
},
{
"cell_type": "markdown",
"id": "bf7d75a1",
"metadata": {},
"source": [
"Build a clone of the input pdf according to the above customization\n",
"instructions. Each node that requires modified is clone so that the\n",
"original pdf remained untouched. The name of each cloned node is that\n",
"of the original node suffixed by the name of the customizer object\n",
"\n",
"The returned head node own all nodes that were cloned as part of\n",
"the build process so when cust_clone is deleted so will all other\n",
"nodes that were created in the process."
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "12dbd8aa",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:30:04.974851Z",
"iopub.status.busy": "2026-05-19T20:30:04.974730Z",
"iopub.status.idle": "2026-05-19T20:30:05.183130Z",
"shell.execute_reply": "2026-05-19T20:30:05.182849Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[#1] INFO:ObjectHandling -- RooCustomizer::build(model): tree node sig will be replaced by sigsum\n",
"[#1] INFO:ObjectHandling -- RooCustomizer::build(model) Branch node RooAddPdf::model cloned: depends on a replaced parameter\n",
"[#1] INFO:ObjectHandling -- RooCustomizer::build(model) Branch node sig is already replaced\n"
]
}
],
"source": [
"RooAbsPdf *cust_clone = (RooAbsPdf *)cust.build(true);"
]
},
{
"cell_type": "markdown",
"id": "7a9f29d6",
"metadata": {},
"source": [
"Print structure of clone of model with sig->sigsum replacement."
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "01fcdebb",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:30:05.190105Z",
"iopub.status.busy": "2026-05-19T20:30:05.189987Z",
"iopub.status.idle": "2026-05-19T20:30:05.398487Z",
"shell.execute_reply": "2026-05-19T20:30:05.397885Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0x7f69898c2060 RooAddPdf::model_cust = 0.582695/1 [Auto,Clean] \n",
" 0x7f69d923c3e8/V- RooAddPdf::bkg = 0.16539/1 [Auto,Clean] \n",
" 0x7f69d92477d0/V- RooChebychev::bkg1 = 0.8 [Auto,Dirty] \n",
" 0x7f69d9316000/V- RooRealVar::x = 5\n",
" 0x7f69d9247000/V- RooRealVar::a0 = 0.5\n",
" 0x7f69d92473e8/V- RooRealVar::a1 = 0.2\n",
" 0x7f69d923c000/V- RooRealVar::bkg1frac = 0.2\n",
" 0x7f69d923f3e8/V- RooExponential::bkg2 = 0.00673795 [Auto,Dirty] \n",
" 0x7f69d9316000/V- RooRealVar::x = 5\n",
" 0x7f69d923f000/V- RooRealVar::alpha = -1\n",
" 0x7f69d9239000/V- RooRealVar::bkgfrac = 0.5\n",
" 0x7f69b400f3e8/V- RooAddPdf::sigsum = 1/1 [Auto,Clean] \n",
" 0x7f69d924a7d0/V- RooGaussian::sig = 1 [Auto,Dirty] \n",
" 0x7f69d9316000/V- RooRealVar::x = 5\n",
" 0x7f69d924a000/V- RooRealVar::mean = 5\n",
" 0x7f69d924a3e8/V- RooRealVar::sigma = 0.5\n",
" 0x7f69b400f000/V- RooRealVar::sig1frac = 0.8\n",
" 0x7f69b40123e8/V- RooGaussian::sig2 = 1 [Auto,Dirty] \n",
" 0x7f69d9316000/V- RooRealVar::x = 5\n",
" 0x7f69d924a000/V- RooRealVar::mean = 5\n",
" 0x7f69b4012000/V- RooRealVar::sigma2 = 1\n"
]
}
],
"source": [
"cust_clone->Print(\"t\");\n",
"\n",
"delete cust_clone;"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "ROOT C++",
"language": "c++",
"name": "root"
},
"language_info": {
"codemirror_mode": "text/x-c++src",
"file_extension": ".C",
"mimetype": " text/x-c++src",
"name": "c++"
}
},
"nbformat": 4,
"nbformat_minor": 5
}