{ "cells": [ { "cell_type": "markdown", "id": "e5fe3f96", "metadata": {}, "source": [ "# rf705_linearmorph\n", "Special pdf's: linear interpolation between pdf shapes using the 'Alex Read' algorithm\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:34 PM." ] }, { "cell_type": "code", "execution_count": 1, "id": "d13d2741", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:34:38.648431Z", "iopub.status.busy": "2026-05-19T20:34:38.648323Z", "iopub.status.idle": "2026-05-19T20:34:38.663807Z", "shell.execute_reply": "2026-05-19T20:34:38.663273Z" } }, "outputs": [], "source": [ "%%cpp -d\n", "#include \"RooRealVar.h\"\n", "#include \"RooDataSet.h\"\n", "#include \"RooGaussian.h\"\n", "#include \"RooPolynomial.h\"\n", "#include \"RooIntegralMorph.h\"\n", "#include \"TCanvas.h\"\n", "#include \"TAxis.h\"\n", "#include \"RooPlot.h\"\n", "#include \"TH1.h\"\n", "using namespace RooFit;" ] }, { "cell_type": "markdown", "id": "1093e351", "metadata": {}, "source": [ "Create end point pdf shapes\n", "------------------------------------------------------" ] }, { "cell_type": "markdown", "id": "33bf9495", "metadata": {}, "source": [ "Observable" ] }, { "cell_type": "code", "execution_count": 2, "id": "a922beb1", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:34:38.665326Z", "iopub.status.busy": "2026-05-19T20:34:38.665214Z", "iopub.status.idle": "2026-05-19T20:34:38.888855Z", "shell.execute_reply": "2026-05-19T20:34:38.888462Z" } }, "outputs": [], "source": [ "RooRealVar x(\"x\", \"x\", -20, 20);" ] }, { "cell_type": "markdown", "id": "2edd089d", "metadata": {}, "source": [ "Lower end point shape: a Gaussian" ] }, { "cell_type": "code", "execution_count": 3, "id": "39f50d0b", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:34:38.898221Z", "iopub.status.busy": "2026-05-19T20:34:38.898093Z", "iopub.status.idle": "2026-05-19T20:34:39.106933Z", "shell.execute_reply": "2026-05-19T20:34:39.106237Z" } }, "outputs": [], "source": [ "RooRealVar g1mean(\"g1mean\", \"g1mean\", -10);\n", "RooGaussian g1(\"g1\", \"g1\", x, g1mean, 2.0);" ] }, { "cell_type": "markdown", "id": "7a8c8c3a", "metadata": {}, "source": [ "Upper end point shape: a Polynomial" ] }, { "cell_type": "code", "execution_count": 4, "id": "9cefdaf1", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:34:39.108658Z", "iopub.status.busy": "2026-05-19T20:34:39.108527Z", "iopub.status.idle": "2026-05-19T20:34:39.317037Z", "shell.execute_reply": "2026-05-19T20:34:39.316474Z" } }, "outputs": [], "source": [ "RooPolynomial g2(\"g2\", \"g2\", x, RooArgSet(-0.03, -0.001));" ] }, { "cell_type": "markdown", "id": "d2045478", "metadata": {}, "source": [ "Create interpolating pdf\n", "-----------------------------------------------" ] }, { "cell_type": "markdown", "id": "a4df392f", "metadata": {}, "source": [ "Create interpolation variable" ] }, { "cell_type": "code", "execution_count": 5, "id": "ee9207d5", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:34:39.319428Z", "iopub.status.busy": "2026-05-19T20:34:39.319310Z", "iopub.status.idle": "2026-05-19T20:34:39.527949Z", "shell.execute_reply": "2026-05-19T20:34:39.527305Z" } }, "outputs": [], "source": [ "RooRealVar alpha(\"alpha\", \"alpha\", 0, 1.0);" ] }, { "cell_type": "markdown", "id": "cf857216", "metadata": {}, "source": [ "Specify sampling density on observable and interpolation variable" ] }, { "cell_type": "code", "execution_count": 6, "id": "9a450689", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:34:39.529878Z", "iopub.status.busy": "2026-05-19T20:34:39.529752Z", "iopub.status.idle": "2026-05-19T20:34:39.735320Z", "shell.execute_reply": "2026-05-19T20:34:39.734723Z" } }, "outputs": [], "source": [ "x.setBins(1000, \"cache\");\n", "alpha.setBins(50, \"cache\");" ] }, { "cell_type": "markdown", "id": "07e43ed7", "metadata": {}, "source": [ "Construct interpolating pdf in (x,a) represent g1(x) at a=a_min\n", "and g2(x) at a=a_max" ] }, { "cell_type": "code", "execution_count": 7, "id": "84b1f21d", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:34:39.737254Z", "iopub.status.busy": "2026-05-19T20:34:39.737135Z", "iopub.status.idle": "2026-05-19T20:34:39.946240Z", "shell.execute_reply": "2026-05-19T20:34:39.945574Z" } }, "outputs": [], "source": [ "RooIntegralMorph lmorph(\"lmorph\", \"lmorph\", g1, g2, x, alpha);" ] }, { "cell_type": "markdown", "id": "fa84b92e", "metadata": {}, "source": [ "Plot interpolating pdf at various alpha\n", "-----------------------------------------------------------------------------" ] }, { "cell_type": "markdown", "id": "780d366e", "metadata": {}, "source": [ "Show end points as blue curves" ] }, { "cell_type": "code", "execution_count": 8, "id": "542f7f39", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:34:39.948261Z", "iopub.status.busy": "2026-05-19T20:34:39.948146Z", "iopub.status.idle": "2026-05-19T20:34:40.156973Z", "shell.execute_reply": "2026-05-19T20:34:40.156180Z" } }, "outputs": [], "source": [ "RooPlot *frame1 = x.frame();\n", "g1.plotOn(frame1);\n", "g2.plotOn(frame1);" ] }, { "cell_type": "markdown", "id": "e7f0f67d", "metadata": {}, "source": [ "Show interpolated shapes in red" ] }, { "cell_type": "code", "execution_count": 9, "id": "24046d15", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:34:40.158800Z", "iopub.status.busy": "2026-05-19T20:34:40.158667Z", "iopub.status.idle": "2026-05-19T20:34:40.377009Z", "shell.execute_reply": "2026-05-19T20:34:40.369723Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[#1] INFO:Caching -- RooAbsCachedPdf::getCache(lmorph) creating new cache 0x7faeb1569fe0 with pdf g1_MORPH_g2_CACHE_Obs[x]_NORM_x for nset (x) with code 0\n", "[#1] INFO:Caching -- RooAbsCachedPdf::getCache(lmorph) creating new cache 0x7faeb1796650 with pdf g1_MORPH_g2_CACHE_Obs[x]_NORM_x for nset (x) with code 0\n", "[#1] INFO:Caching -- RooAbsCachedPdf::getCache(lmorph) creating new cache 0x7faeb1796650 with pdf g1_MORPH_g2_CACHE_Obs[x]_NORM_x for nset (x) with code 0\n", "[#1] INFO:Caching -- RooAbsCachedPdf::getCache(lmorph) creating new cache 0x7faeb1796650 with pdf g1_MORPH_g2_CACHE_Obs[x]_NORM_x for nset (x) with code 0\n", "[#1] INFO:Caching -- RooAbsCachedPdf::getCache(lmorph) creating new cache 0x7faeb1796650 with pdf g1_MORPH_g2_CACHE_Obs[x]_NORM_x for nset (x) with code 0\n", "[#1] INFO:Caching -- RooAbsCachedPdf::getCache(lmorph) creating new cache 0x7faeb1796650 with pdf g1_MORPH_g2_CACHE_Obs[x]_NORM_x for nset (x) with code 0\n", "[#1] INFO:Caching -- RooAbsCachedPdf::getCache(lmorph) creating new cache 0x7faeb1796650 with pdf g1_MORPH_g2_CACHE_Obs[x]_NORM_x for nset (x) with code 0\n", "[#1] INFO:Caching -- RooAbsCachedPdf::getCache(lmorph) creating new cache 0x7faeb1796650 with pdf g1_MORPH_g2_CACHE_Obs[x]_NORM_x for nset (x) with code 0\n" ] } ], "source": [ "alpha.setVal(0.125);\n", "lmorph.plotOn(frame1, LineColor(kRed));\n", "alpha.setVal(0.25);\n", "lmorph.plotOn(frame1, LineColor(kRed));\n", "alpha.setVal(0.375);\n", "lmorph.plotOn(frame1, LineColor(kRed));\n", "alpha.setVal(0.50);\n", "lmorph.plotOn(frame1, LineColor(kRed));\n", "alpha.setVal(0.625);\n", "lmorph.plotOn(frame1, LineColor(kRed));\n", "alpha.setVal(0.75);\n", "lmorph.plotOn(frame1, LineColor(kRed));\n", "alpha.setVal(0.875);\n", "lmorph.plotOn(frame1, LineColor(kRed));\n", "alpha.setVal(0.95);\n", "lmorph.plotOn(frame1, LineColor(kRed));" ] }, { "cell_type": "markdown", "id": "8173f67a", "metadata": {}, "source": [ "Show 2D distribution of pdf(x,alpha)\n", "-----------------------------------------------------------------------" ] }, { "cell_type": "markdown", "id": "002e54d2", "metadata": {}, "source": [ "Create 2D histogram" ] }, { "cell_type": "code", "execution_count": 10, "id": "24194f7c", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:34:40.378751Z", "iopub.status.busy": "2026-05-19T20:34:40.378580Z", "iopub.status.idle": "2026-05-19T20:34:40.778387Z", "shell.execute_reply": "2026-05-19T20:34:40.777877Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[#1] INFO:Caching -- RooAbsCachedPdf::getCache(lmorph) creating new cache 0x7faeb16fdee0 with pdf g1_MORPH_g2_CACHE_Obs[x]_NORM_x_alpha for nset (x,alpha) with code 0\n" ] } ], "source": [ "TH1 *hh = lmorph.createHistogram(\"hh\", x, Binning(40), YVar(alpha, Binning(40)));\n", "hh->SetLineColor(kBlue);" ] }, { "cell_type": "markdown", "id": "58827898", "metadata": {}, "source": [ "Fit pdf to dataset with alpha=0.8\n", "-----------------------------------------------------------------" ] }, { "cell_type": "markdown", "id": "c3f81b01", "metadata": {}, "source": [ "Generate a toy dataset at alpha = 0.8" ] }, { "cell_type": "code", "execution_count": 11, "id": "2abfb745", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:34:40.780255Z", "iopub.status.busy": "2026-05-19T20:34:40.780134Z", "iopub.status.idle": "2026-05-19T20:34:40.990678Z", "shell.execute_reply": "2026-05-19T20:34:40.990148Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[#1] INFO:Caching -- RooAbsCachedPdf::getCache(lmorph) creating new cache 0x7faeb1796650 with pdf g1_MORPH_g2_CACHE_Obs[x]_NORM_x for nset (x) with code 0\n", "[#1] INFO:Caching -- RooAbsCachedPdf::getCache(lmorph) creating new cache 0x7faeb16fdee0 with pdf g1_MORPH_g2_CACHE_Obs[x]_NORM_x for nset (x) with code 0\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "input_line_58:3:1: warning: 'data' shadows a declaration with the same name in the 'std' namespace; use '::data' to reference this declaration\n", "std::unique_ptr data{lmorph.generate(x, 1000)};\n", "^\n" ] } ], "source": [ "alpha = 0.8;\n", "std::unique_ptr data{lmorph.generate(x, 1000)};" ] }, { "cell_type": "markdown", "id": "eabbdfba", "metadata": {}, "source": [ "Fit pdf to toy data" ] }, { "cell_type": "code", "execution_count": 12, "id": "c0ddaea9", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:34:40.992553Z", "iopub.status.busy": "2026-05-19T20:34:40.992433Z", "iopub.status.idle": "2026-05-19T20:34:41.203171Z", "shell.execute_reply": "2026-05-19T20:34:41.202231Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "input_line_59:3:15: error: reference to 'data' is ambiguous\n", "lmorph.fitTo(*data, Verbose(true), PrintLevel(-1));\n", " ^\n", "input_line_58:3:29: note: candidate found by name lookup is 'data'\n", "std::unique_ptr data{lmorph.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": [ "lmorph.setCacheAlpha(true);\n", "lmorph.fitTo(*data, Verbose(true), PrintLevel(-1));" ] }, { "cell_type": "markdown", "id": "17649918", "metadata": {}, "source": [ "Plot fitted pdf and data overlaid" ] }, { "cell_type": "code", "execution_count": 13, "id": "d85e98d1", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:34:41.204743Z", "iopub.status.busy": "2026-05-19T20:34:41.204596Z", "iopub.status.idle": "2026-05-19T20:34:41.415159Z", "shell.execute_reply": "2026-05-19T20:34:41.414545Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "input_line_60:3:1: error: reference to 'data' is ambiguous\n", "data->plotOn(frame2);\n", "^\n", "input_line_58:3:29: note: candidate found by name lookup is 'data'\n", "std::unique_ptr data{lmorph.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 *frame2 = x.frame(Bins(100));\n", "data->plotOn(frame2);\n", "lmorph.plotOn(frame2);" ] }, { "cell_type": "markdown", "id": "c9d2b4d9", "metadata": {}, "source": [ "Scan -log(L) vs alpha\n", "-----------------------------------------" ] }, { "cell_type": "markdown", "id": "679f4ef0", "metadata": {}, "source": [ "Show scan -log(L) of dataset w.r.t alpha" ] }, { "cell_type": "code", "execution_count": 14, "id": "55b0ddd9", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:34:41.417008Z", "iopub.status.busy": "2026-05-19T20:34:41.416883Z", "iopub.status.idle": "2026-05-19T20:34:41.625878Z", "shell.execute_reply": "2026-05-19T20:34:41.625309Z" } }, "outputs": [], "source": [ "RooPlot *frame3 = alpha.frame(Bins(100), Range(0.1, 0.9));" ] }, { "cell_type": "markdown", "id": "95a5d3d2", "metadata": {}, "source": [ "Make 2D pdf of histogram" ] }, { "cell_type": "code", "execution_count": 15, "id": "7357382f", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:34:41.635583Z", "iopub.status.busy": "2026-05-19T20:34:41.635456Z", "iopub.status.idle": "2026-05-19T20:34:41.846233Z", "shell.execute_reply": "2026-05-19T20:34:41.845582Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "input_line_62:2:52: error: reference to 'data' is ambiguous\n", " std::unique_ptr nll{lmorph.createNLL(*data)};\n", " ^\n", "input_line_58:3:29: note: candidate found by name lookup is 'data'\n", "std::unique_ptr data{lmorph.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", "input_line_62:23:1: error: use of undeclared identifier 'frame2'\n", "frame2->GetYaxis()->SetTitleOffset(1.4);\n", "^\n", "input_line_62:24:1: error: use of undeclared identifier 'frame2'\n", "frame2->Draw();\n", "^\n" ] } ], "source": [ "std::unique_ptr nll{lmorph.createNLL(*data)};\n", "nll->plotOn(frame3, ShiftToZero());\n", "\n", "lmorph.setCacheAlpha(false);\n", "\n", "TCanvas *c = new TCanvas(\"rf705_linearmorph\", \"rf705_linearmorph\", 800, 800);\n", "c->Divide(2, 2);\n", "c->cd(1);\n", "gPad->SetLeftMargin(0.15);\n", "frame1->GetYaxis()->SetTitleOffset(1.6);\n", "frame1->Draw();\n", "c->cd(2);\n", "gPad->SetLeftMargin(0.20);\n", "hh->GetZaxis()->SetTitleOffset(2.5);\n", "hh->Draw(\"surf\");\n", "c->cd(3);\n", "gPad->SetLeftMargin(0.15);\n", "frame3->GetYaxis()->SetTitleOffset(1.4);\n", "frame3->Draw();\n", "c->cd(4);\n", "gPad->SetLeftMargin(0.15);\n", "frame2->GetYaxis()->SetTitleOffset(1.4);\n", "frame2->Draw();\n", "\n", "return;" ] }, { "cell_type": "markdown", "id": "6e844187", "metadata": {}, "source": [ "Draw all canvases " ] }, { "cell_type": "code", "execution_count": 16, "id": "e1e157e2", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:34:41.848070Z", "iopub.status.busy": "2026-05-19T20:34:41.847955Z", "iopub.status.idle": "2026-05-19T20:34:42.057375Z", "shell.execute_reply": "2026-05-19T20:34:42.056213Z" } }, "outputs": [], "source": [ "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 }