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