{ "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 }