{
"cells": [
{
"cell_type": "markdown",
"id": "9783775c",
"metadata": {},
"source": [
"# rf201_composite\n",
"Addition and convolution: composite pdf with signal and background component\n",
"\n",
"```\n",
" pdf = f_bkg * bkg(x,a0,a1) + (1-fbkg) * (f_sig1 * sig1(x,m,s1 + (1-f_sig1) * sig2(x,m,s2)))\n",
"```\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": "46b6cdf3",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:29:33.142486Z",
"iopub.status.busy": "2026-05-19T20:29:33.142373Z",
"iopub.status.idle": "2026-05-19T20:29:33.155252Z",
"shell.execute_reply": "2026-05-19T20:29:33.154692Z"
}
},
"outputs": [],
"source": [
"%%cpp -d\n",
"#include \"RooRealVar.h\"\n",
"#include \"RooDataSet.h\"\n",
"#include \"RooGaussian.h\"\n",
"#include \"RooChebychev.h\"\n",
"#include \"RooAddPdf.h\"\n",
"#include \"TCanvas.h\"\n",
"#include \"TAxis.h\"\n",
"#include \"RooPlot.h\"\n",
"using namespace RooFit;"
]
},
{
"cell_type": "markdown",
"id": "7a01da5b",
"metadata": {},
"source": [
"Setup component pdfs\n",
"---------------------------------------"
]
},
{
"cell_type": "markdown",
"id": "919c45ba",
"metadata": {},
"source": [
"Declare observable x"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "1528a8c9",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:29:33.156928Z",
"iopub.status.busy": "2026-05-19T20:29:33.156807Z",
"iopub.status.idle": "2026-05-19T20:29:33.368650Z",
"shell.execute_reply": "2026-05-19T20:29:33.367923Z"
}
},
"outputs": [],
"source": [
"RooRealVar x(\"x\", \"x\", 0, 10);"
]
},
{
"cell_type": "markdown",
"id": "8b025dca",
"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": "ac42de69",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:29:33.370516Z",
"iopub.status.busy": "2026-05-19T20:29:33.370398Z",
"iopub.status.idle": "2026-05-19T20:29:33.578100Z",
"shell.execute_reply": "2026-05-19T20:29:33.577637Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[#0] WARNING:InputArguments -- The parameter 'sigma1' with range [-inf, inf] of the RooGaussian 'sig1' exceeds the safe range of (0, inf). Advise to limit its range.\n",
"[#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 mean(\"mean\", \"mean of gaussians\", 5);\n",
"RooRealVar sigma1(\"sigma1\", \"width of gaussians\", 0.5);\n",
"RooRealVar sigma2(\"sigma2\", \"width of gaussians\", 1);\n",
"\n",
"RooGaussian sig1(\"sig1\", \"Signal component 1\", x, mean, sigma1);\n",
"RooGaussian sig2(\"sig2\", \"Signal component 2\", x, mean, sigma2);"
]
},
{
"cell_type": "markdown",
"id": "7fb21de1",
"metadata": {},
"source": [
"Build Chebychev polynomial pdf"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "239a11dc",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:29:33.579880Z",
"iopub.status.busy": "2026-05-19T20:29:33.579767Z",
"iopub.status.idle": "2026-05-19T20:29:33.787095Z",
"shell.execute_reply": "2026-05-19T20:29:33.786438Z"
}
},
"outputs": [],
"source": [
"RooRealVar a0(\"a0\", \"a0\", 0.5, 0., 1.);\n",
"RooRealVar a1(\"a1\", \"a1\", 0.2, 0., 1.);\n",
"RooChebychev bkg(\"bkg\", \"Background\", x, RooArgSet(a0, a1));"
]
},
{
"cell_type": "markdown",
"id": "48e213e7",
"metadata": {},
"source": [
"---------------------------------------------\n",
"METHOD 1-Two RooAddPdfs\n",
"============================================="
]
},
{
"cell_type": "markdown",
"id": "869358fc",
"metadata": {},
"source": [
"Add signal components\n",
"------------------------------------------"
]
},
{
"cell_type": "markdown",
"id": "5f517eb8",
"metadata": {},
"source": [
"Sum the signal components into a composite signal pdf"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "2c36086b",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:29:33.789177Z",
"iopub.status.busy": "2026-05-19T20:29:33.789059Z",
"iopub.status.idle": "2026-05-19T20:29:33.996414Z",
"shell.execute_reply": "2026-05-19T20:29:33.995775Z"
}
},
"outputs": [],
"source": [
"RooRealVar sig1frac(\"sig1frac\", \"fraction of component 1 in signal\", 0.8, 0., 1.);\n",
"RooAddPdf sig(\"sig\", \"Signal\", RooArgList(sig1, sig2), sig1frac);"
]
},
{
"cell_type": "markdown",
"id": "3727cb19",
"metadata": {},
"source": [
"Add signal and background\n",
"------------------------------------------------"
]
},
{
"cell_type": "markdown",
"id": "2bd048da",
"metadata": {},
"source": [
"Sum the composite signal and background"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "acaa0873",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:29:33.998108Z",
"iopub.status.busy": "2026-05-19T20:29:33.997994Z",
"iopub.status.idle": "2026-05-19T20:29:34.205373Z",
"shell.execute_reply": "2026-05-19T20:29:34.204665Z"
}
},
"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": "ba5e0f20",
"metadata": {},
"source": [
"Sample, fit and plot model\n",
"---------------------------------------------------"
]
},
{
"cell_type": "markdown",
"id": "fc5d841b",
"metadata": {},
"source": [
"Generate a data sample of 1000 events in x from model"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "3d345b09",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:29:34.207430Z",
"iopub.status.busy": "2026-05-19T20:29:34.207313Z",
"iopub.status.idle": "2026-05-19T20:29:34.414764Z",
"shell.execute_reply": "2026-05-19T20:29:34.414379Z"
}
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"input_line_54:2:2: warning: 'data' shadows a declaration with the same name in the 'std' namespace; use '::data' to reference this declaration\n",
" std::unique_ptr data{model.generate(x, 1000)};\n",
" ^\n"
]
}
],
"source": [
"std::unique_ptr data{model.generate(x, 1000)};"
]
},
{
"cell_type": "markdown",
"id": "b04b9ecd",
"metadata": {},
"source": [
"Fit model to data"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "0633e9df",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:29:34.416583Z",
"iopub.status.busy": "2026-05-19T20:29:34.416465Z",
"iopub.status.idle": "2026-05-19T20:29:34.624596Z",
"shell.execute_reply": "2026-05-19T20:29:34.624056Z"
}
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"input_line_55:2:15: error: reference to 'data' is ambiguous\n",
" model.fitTo(*data, PrintLevel(-1));\n",
" ^\n",
"input_line_54:2:30: note: candidate found by name lookup is 'data'\n",
" std::unique_ptr data{model.generate(x, 1000)};\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": [
"model.fitTo(*data, PrintLevel(-1));"
]
},
{
"cell_type": "markdown",
"id": "dd7dfd37",
"metadata": {},
"source": [
"Plot data and PDF overlaid"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "e65e348a",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:29:34.626272Z",
"iopub.status.busy": "2026-05-19T20:29:34.626158Z",
"iopub.status.idle": "2026-05-19T20:29:34.834301Z",
"shell.execute_reply": "2026-05-19T20:29:34.833749Z"
}
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"input_line_56:3:1: error: reference to 'data' is ambiguous\n",
"data->plotOn(xframe);\n",
"^\n",
"input_line_54:2:30: note: candidate found by name lookup is 'data'\n",
" std::unique_ptr data{model.generate(x, 1000)};\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": [
"RooPlot *xframe = x.frame(Title(\"Example of composite pdf=(sig1+sig2)+bkg\"));\n",
"data->plotOn(xframe);\n",
"model.plotOn(xframe);"
]
},
{
"cell_type": "markdown",
"id": "968f3f20",
"metadata": {},
"source": [
"Overlay the background component of model with a dashed line"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "0a3499e4",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:29:34.836059Z",
"iopub.status.busy": "2026-05-19T20:29:34.835943Z",
"iopub.status.idle": "2026-05-19T20:29:35.043631Z",
"shell.execute_reply": "2026-05-19T20:29:35.043155Z"
}
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"input_line_57:2:50: error: cannot take the address of an rvalue of type 'ELineStyle'\n",
" model.plotOn(xframe, Components(bkg), LineStyle(kDashed));\n",
" ^~~~~~~\n",
"Error while creating dynamic expression for:\n",
" model.plotOn(xframe, Components(bkg), LineStyle(kDashed))\n"
]
}
],
"source": [
"model.plotOn(xframe, Components(bkg), LineStyle(kDashed));"
]
},
{
"cell_type": "markdown",
"id": "72331c62",
"metadata": {},
"source": [
"Overlay the background+sig2 components of model with a dotted line"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "29118100",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:29:35.045402Z",
"iopub.status.busy": "2026-05-19T20:29:35.045250Z",
"iopub.status.idle": "2026-05-19T20:29:35.253767Z",
"shell.execute_reply": "2026-05-19T20:29:35.253245Z"
}
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"input_line_58:2:67: error: cannot take the address of an rvalue of type 'ELineStyle'\n",
" model.plotOn(xframe, Components(RooArgSet(bkg, sig2)), LineStyle(kDotted));\n",
" ^~~~~~~\n",
"Error while creating dynamic expression for:\n",
" model.plotOn(xframe, Components(RooArgSet(bkg, sig2)), LineStyle(kDotted))\n"
]
}
],
"source": [
"model.plotOn(xframe, Components(RooArgSet(bkg, sig2)), LineStyle(kDotted));"
]
},
{
"cell_type": "markdown",
"id": "4c050c95",
"metadata": {},
"source": [
"Print structure of composite pdf"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "b55ae134",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:29:35.255356Z",
"iopub.status.busy": "2026-05-19T20:29:35.255241Z",
"iopub.status.idle": "2026-05-19T20:29:35.460710Z",
"shell.execute_reply": "2026-05-19T20:29:35.460145Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0x7f520e6ce3e8 RooAddPdf::model = 0.9/1 [Auto,Clean] \n",
" 0x7f520e6d97d0/V- RooChebychev::bkg = 0.8 [Auto,Dirty] \n",
" 0x7f520e7a9000/V- RooRealVar::x = 5\n",
" 0x7f520e6d9000/V- RooRealVar::a0 = 0.5\n",
" 0x7f520e6d93e8/V- RooRealVar::a1 = 0.2\n",
" 0x7f520e6ce000/V- RooRealVar::bkgfrac = 0.5\n",
" 0x7f520e6d13e8/V- RooAddPdf::sig = 1/1 [Auto,Clean] \n",
" 0x7f520e6dcbb8/V- RooGaussian::sig1 = 1 [Auto,Dirty] \n",
" 0x7f520e7a9000/V- RooRealVar::x = 5\n",
" 0x7f520e6dc000/V- RooRealVar::mean = 5\n",
" 0x7f520e6dc3e8/V- RooRealVar::sigma1 = 0.5\n",
" 0x7f520e6d1000/V- RooRealVar::sig1frac = 0.8\n",
" 0x7f520e6dd110/V- RooGaussian::sig2 = 1 [Auto,Dirty] \n",
" 0x7f520e7a9000/V- RooRealVar::x = 5\n",
" 0x7f520e6dc000/V- RooRealVar::mean = 5\n",
" 0x7f520e6dc7d0/V- RooRealVar::sigma2 = 1\n"
]
}
],
"source": [
"model.Print(\"t\");"
]
},
{
"cell_type": "markdown",
"id": "7e822cb1",
"metadata": {},
"source": [
"---------------------------------------------------------------------------------------------\n",
"METHOD 2-One RooAddPdf with recursive fractions\n",
"============================================================================================="
]
},
{
"cell_type": "markdown",
"id": "23a58751",
"metadata": {},
"source": [
"Construct sum of models on one go using recursive fraction interpretations\n",
"\n",
"model2 = bkg + (sig1 + sig2)"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "6f3748a9",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:29:35.462179Z",
"iopub.status.busy": "2026-05-19T20:29:35.462067Z",
"iopub.status.idle": "2026-05-19T20:29:35.669317Z",
"shell.execute_reply": "2026-05-19T20:29:35.668775Z"
}
},
"outputs": [],
"source": [
"RooAddPdf model2(\"model\", \"g1+g2+a\", RooArgList(bkg, sig1, sig2), RooArgList(bkgfrac, sig1frac), true);"
]
},
{
"cell_type": "markdown",
"id": "6a6a44d4",
"metadata": {},
"source": [
"NB: Each coefficient is interpreted as the fraction of the\n",
"left-hand component of the i-th recursive sum, i.e.\n",
"\n",
"sum4 = A + ( B + ( C + D) with fraction fA, fB and fC expands to\n",
"\n",
"sum4 = fA*A + (1-fA)*(fB*B + (1-fB)*(fC*C + (1-fC)*D))"
]
},
{
"cell_type": "markdown",
"id": "fb7342d4",
"metadata": {},
"source": [
"Plot recursive addition model\n",
"---------------------------------------------------------"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "be62dbf6",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:29:35.671400Z",
"iopub.status.busy": "2026-05-19T20:29:35.671287Z",
"iopub.status.idle": "2026-05-19T20:29:35.876868Z",
"shell.execute_reply": "2026-05-19T20:29:35.876211Z"
}
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"input_line_61:2:34: error: cannot take the address of an rvalue of type 'EColor'\n",
" model2.plotOn(xframe, LineColor(kRed), LineStyle(kDashed));\n",
" ^~~~\n",
"Error while creating dynamic expression for:\n",
" model2.plotOn(xframe, LineColor(kRed), LineStyle(kDashed))\n",
"input_line_61:3:67: error: cannot take the address of an rvalue of type 'EColor'\n",
"model2.plotOn(xframe, Components(RooArgSet(bkg, sig2)), LineColor(kRed), LineStyle(kDashed));\n",
" ^~~~\n",
"Error while creating dynamic expression for:\n",
" model2.plotOn(xframe, Components(RooArgSet(bkg, sig2)), LineColor(kRed), LineStyle(kDashed))\n"
]
}
],
"source": [
"model2.plotOn(xframe, LineColor(kRed), LineStyle(kDashed));\n",
"model2.plotOn(xframe, Components(RooArgSet(bkg, sig2)), LineColor(kRed), LineStyle(kDashed));\n",
"model2.Print(\"t\");"
]
},
{
"cell_type": "markdown",
"id": "cd06610f",
"metadata": {},
"source": [
"Draw the frame on the canvas"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "5628e16c",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:29:35.878274Z",
"iopub.status.busy": "2026-05-19T20:29:35.878162Z",
"iopub.status.idle": "2026-05-19T20:29:36.212671Z",
"shell.execute_reply": "2026-05-19T20:29:36.212083Z"
}
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"IncrementalExecutor::executeFunction: symbol '_ZN5cling7runtime8internal9EvaluateTIvEET_PNS1_15DynamicExprInfoEPN5clang11DeclContextE' unresolved while linking [cling interface function]!\n",
"You are probably missing the definition of void cling::runtime::internal::EvaluateT(cling::runtime::internal::DynamicExprInfo*, clang::DeclContext*)\n",
"Maybe you need to load the corresponding shared library?\n"
]
}
],
"source": [
"new TCanvas(\"rf201_composite\", \"rf201_composite\", 600, 600);\n",
"gPad->SetLeftMargin(0.15);\n",
"xframe->GetYaxis()->SetTitleOffset(1.4);\n",
"xframe->Draw();"
]
},
{
"cell_type": "markdown",
"id": "6de3ac51",
"metadata": {},
"source": [
"Draw all canvases "
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "a6f6e414",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:29:36.214134Z",
"iopub.status.busy": "2026-05-19T20:29:36.214016Z",
"iopub.status.idle": "2026-05-19T20:29:36.441482Z",
"shell.execute_reply": "2026-05-19T20:29:36.440878Z"
}
},
"outputs": [],
"source": [
"%jsroot on\n",
"gROOT->GetListOfCanvases()->Draw()"
]
}
],
"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
}