{
"cells": [
{
"cell_type": "markdown",
"id": "659a94b1",
"metadata": {},
"source": [
"# rf702_efficiencyfit_2D\n",
"Special pdf's: unbinned maximum likelihood fit of an efficiency eff(x) function\n",
"to a dataset D(x,cut), cut is a category encoding a selection whose efficiency as function\n",
"of x should be described by eff(x)\n",
"\n",
"\n",
"\n",
"\n",
"**Author:** Clemens Lange, Wouter Verkerke (C++ version) \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": "3ff0679b",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:34:26.285131Z",
"iopub.status.busy": "2026-05-19T20:34:26.285019Z",
"iopub.status.idle": "2026-05-19T20:34:26.300503Z",
"shell.execute_reply": "2026-05-19T20:34:26.299988Z"
}
},
"outputs": [],
"source": [
"%%cpp -d\n",
"#include \"RooRealVar.h\"\n",
"#include \"RooDataSet.h\"\n",
"#include \"RooGaussian.h\"\n",
"#include \"RooConstVar.h\"\n",
"#include \"RooCategory.h\"\n",
"#include \"RooEfficiency.h\"\n",
"#include \"RooPolynomial.h\"\n",
"#include \"RooProdPdf.h\"\n",
"#include \"RooFormulaVar.h\"\n",
"#include \"TCanvas.h\"\n",
"#include \"TAxis.h\"\n",
"#include \"TH1.h\"\n",
"#include \"RooPlot.h\"\n",
"using namespace RooFit;"
]
},
{
"cell_type": "markdown",
"id": "2f4dd2ce",
"metadata": {},
"source": [
" Arguments are defined. "
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "8535b1e8",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:34:26.301771Z",
"iopub.status.busy": "2026-05-19T20:34:26.301649Z",
"iopub.status.idle": "2026-05-19T20:34:26.624898Z",
"shell.execute_reply": "2026-05-19T20:34:26.624341Z"
}
},
"outputs": [],
"source": [
"bool flat = false;"
]
},
{
"cell_type": "markdown",
"id": "b2f38f6c",
"metadata": {},
"source": [
"Construct efficiency function e(x,y)\n",
"-----------------------------------------------------------------------"
]
},
{
"cell_type": "markdown",
"id": "05222c04",
"metadata": {},
"source": [
"Declare variables x,mean,sigma with associated name, title, initial value and allowed range"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "e4e03569",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:34:26.626373Z",
"iopub.status.busy": "2026-05-19T20:34:26.626261Z",
"iopub.status.idle": "2026-05-19T20:34:26.834812Z",
"shell.execute_reply": "2026-05-19T20:34:26.834234Z"
}
},
"outputs": [],
"source": [
"RooRealVar x(\"x\", \"x\", -10, 10);\n",
"RooRealVar y(\"y\", \"y\", -10, 10);"
]
},
{
"cell_type": "markdown",
"id": "ee4a92a6",
"metadata": {},
"source": [
"Efficiency function eff(x;a,b)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "ead2d5f4",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:34:26.836192Z",
"iopub.status.busy": "2026-05-19T20:34:26.836072Z",
"iopub.status.idle": "2026-05-19T20:34:27.102150Z",
"shell.execute_reply": "2026-05-19T20:34:27.081658Z"
}
},
"outputs": [],
"source": [
"RooRealVar ax(\"ax\", \"ay\", 0.6, 0, 1);\n",
"RooRealVar bx(\"bx\", \"by\", 5);\n",
"RooRealVar cx(\"cx\", \"cy\", -1, -10, 10);\n",
"\n",
"RooRealVar ay(\"ay\", \"ay\", 0.2, 0, 1);\n",
"RooRealVar by(\"by\", \"by\", 5);\n",
"RooRealVar cy(\"cy\", \"cy\", -1, -10, 10);\n",
"\n",
"RooFormulaVar effFunc(\"effFunc\", \"((1-ax)+ax*cos((x-cx)/bx))*((1-ay)+ay*cos((y-cy)/by))\",\n",
" RooArgList(ax, bx, cx, x, ay, by, cy, y));"
]
},
{
"cell_type": "markdown",
"id": "3b1c0f6d",
"metadata": {},
"source": [
"Acceptance state cut (1 or 0)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "4a562088",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:34:27.120379Z",
"iopub.status.busy": "2026-05-19T20:34:27.120230Z",
"iopub.status.idle": "2026-05-19T20:34:27.548971Z",
"shell.execute_reply": "2026-05-19T20:34:27.531649Z"
}
},
"outputs": [],
"source": [
"RooCategory cut(\"cut\", \"cutr\", { {\"accept\", 1}, {\"reject\", 0} });"
]
},
{
"cell_type": "markdown",
"id": "b993a158",
"metadata": {},
"source": [
"Construct conditional efficiency pdf E(cut|x,y)\n",
"---------------------------------------------------------------------------------------------"
]
},
{
"cell_type": "markdown",
"id": "c30b64da",
"metadata": {},
"source": [
"Construct efficiency pdf eff(cut|x)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "7fca2bd7",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:34:27.570154Z",
"iopub.status.busy": "2026-05-19T20:34:27.569985Z",
"iopub.status.idle": "2026-05-19T20:34:27.820708Z",
"shell.execute_reply": "2026-05-19T20:34:27.804751Z"
}
},
"outputs": [],
"source": [
"RooEfficiency effPdf(\"effPdf\", \"effPdf\", effFunc, cut, \"accept\");"
]
},
{
"cell_type": "markdown",
"id": "aae9f34c",
"metadata": {},
"source": [
"Generate data (x,y,cut) from a toy model\n",
"-------------------------------------------------------------------------------"
]
},
{
"cell_type": "markdown",
"id": "34eb24e1",
"metadata": {},
"source": [
"Construct global shape pdf shape(x) and product model(x,cut) = eff(cut|x)*shape(x)\n",
"(These are _only_ needed to generate some toy MC here to be used later)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "9f042c4e",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:34:27.854170Z",
"iopub.status.busy": "2026-05-19T20:34:27.853987Z",
"iopub.status.idle": "2026-05-19T20:34:28.073322Z",
"shell.execute_reply": "2026-05-19T20:34:28.072595Z"
}
},
"outputs": [],
"source": [
"RooPolynomial shapePdfX(\"shapePdfX\", \"shapePdfX\", x, RooConst(flat ? 0 : -0.095));\n",
"RooPolynomial shapePdfY(\"shapePdfY\", \"shapePdfY\", y, RooConst(flat ? 0 : +0.095));\n",
"RooProdPdf shapePdf(\"shapePdf\", \"shapePdf\", RooArgSet(shapePdfX, shapePdfY));\n",
"RooProdPdf model(\"model\", \"model\", shapePdf, Conditional(effPdf, cut));"
]
},
{
"cell_type": "markdown",
"id": "9a737353",
"metadata": {},
"source": [
"Generate some toy data from model"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "a6bb694a",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:34:28.075442Z",
"iopub.status.busy": "2026-05-19T20:34:28.075290Z",
"iopub.status.idle": "2026-05-19T20:34:28.402635Z",
"shell.execute_reply": "2026-05-19T20:34:28.402052Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[#0] WARNING:Generation -- RooAcceptReject::ctor(effPdf_Int[]_Norm[cut]) WARNING: performing accept/reject sampling on a p.d.f in 2 dimensions without prior knowledge on maximum value of p.d.f. Determining maximum value by taking 200000 trial samples. If p.d.f contains sharp peaks smaller than average distance between trial sampling points these may be missed and p.d.f. may be sampled incorrectly.\n",
"[#0] WARNING:Generation -- RooAcceptReject::ctor(effPdf_Int[]_Norm[cut]): WARNING: 200000 trial samples requested by p.d.f for 2-dimensional accept/reject sampling, this may take some time\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"input_line_61: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, y, cut}, 10000)};\n",
" ^\n"
]
}
],
"source": [
"std::unique_ptr data{model.generate({x, y, cut}, 10000)};"
]
},
{
"cell_type": "markdown",
"id": "47c7fee8",
"metadata": {},
"source": [
"Fit conditional efficiency pdf to data\n",
"--------------------------------------------------------------------------"
]
},
{
"cell_type": "markdown",
"id": "57f8ad39",
"metadata": {},
"source": [
"Fit conditional efficiency pdf to data"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "bae96645",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:34:28.406141Z",
"iopub.status.busy": "2026-05-19T20:34:28.406021Z",
"iopub.status.idle": "2026-05-19T20:34:28.615772Z",
"shell.execute_reply": "2026-05-19T20:34:28.615149Z"
}
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"input_line_62:2:16: error: reference to 'data' is ambiguous\n",
" effPdf.fitTo(*data, ConditionalObservables(RooArgSet(x, y)), PrintLevel(-1));\n",
" ^\n",
"input_line_61:2:30: note: candidate found by name lookup is 'data'\n",
" std::unique_ptr data{model.generate({x, y, cut}, 10000)};\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": [
"effPdf.fitTo(*data, ConditionalObservables(RooArgSet(x, y)), PrintLevel(-1));"
]
},
{
"cell_type": "markdown",
"id": "30294fc9",
"metadata": {},
"source": [
"Plot fitted, data efficiency\n",
"--------------------------------------------------------"
]
},
{
"cell_type": "markdown",
"id": "587c9d24",
"metadata": {},
"source": [
"Make 2D histograms of all data, selected data and efficiency function"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "d9db7d29",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:34:28.617070Z",
"iopub.status.busy": "2026-05-19T20:34:28.616949Z",
"iopub.status.idle": "2026-05-19T20:34:28.890641Z",
"shell.execute_reply": "2026-05-19T20:34:28.867640Z"
}
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"input_line_63:2:21: error: reference to 'data' is ambiguous\n",
" TH1 *hh_data_all = data->createHistogram(\"hh_data_all\", x, Binning(8), YVar(y, Binning(8)));\n",
" ^\n",
"input_line_61:2:30: note: candidate found by name lookup is 'data'\n",
" std::unique_ptr data{model.generate({x, y, cut}, 10000)};\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_63:3:20: error: reference to 'data' is ambiguous\n",
"TH1 *hh_data_sel = data->createHistogram(\"hh_data_sel\", x, Binning(8), YVar(y, Binning(8)), Cut(\"cut==cut::accept\"));\n",
" ^\n",
"input_line_61:2:30: note: candidate found by name lookup is 'data'\n",
" std::unique_ptr data{model.generate({x, y, cut}, 10000)};\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": [
"TH1 *hh_data_all = data->createHistogram(\"hh_data_all\", x, Binning(8), YVar(y, Binning(8)));\n",
"TH1 *hh_data_sel = data->createHistogram(\"hh_data_sel\", x, Binning(8), YVar(y, Binning(8)), Cut(\"cut==cut::accept\"));\n",
"TH1 *hh_eff = effFunc.createHistogram(\"hh_eff\", x, Binning(50), YVar(y, Binning(50)));"
]
},
{
"cell_type": "markdown",
"id": "cc199371",
"metadata": {},
"source": [
"Some adjustment for good visualization"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "cb7569f1",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:34:28.916226Z",
"iopub.status.busy": "2026-05-19T20:34:28.916072Z",
"iopub.status.idle": "2026-05-19T20:34:29.125209Z",
"shell.execute_reply": "2026-05-19T20:34:29.124636Z"
}
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"input_line_64:5:22: error: cannot take the address of an rvalue of type 'EColor'\n",
"hh_eff->SetLineColor(kBlue);\n",
" ^~~~~\n",
"Error while creating dynamic expression for:\n",
" hh_eff->SetLineColor(kBlue)\n"
]
}
],
"source": [
"hh_data_all->SetMinimum(0);\n",
"hh_data_sel->SetMinimum(0);\n",
"hh_eff->SetMinimum(0);\n",
"hh_eff->SetLineColor(kBlue);"
]
},
{
"cell_type": "markdown",
"id": "bfbb38cf",
"metadata": {},
"source": [
"Draw all frames on a canvas"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "a87ed18c",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:34:29.127458Z",
"iopub.status.busy": "2026-05-19T20:34:29.127344Z",
"iopub.status.idle": "2026-05-19T20:34:29.336532Z",
"shell.execute_reply": "2026-05-19T20:34:29.335983Z"
}
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"input_line_66:2:3: error: use of undeclared identifier 'hh_data_all'\n",
" (hh_data_all->GetZaxis()->SetTitleOffset(1.8))\n",
" ^\n",
"Error in : Error evaluating expression (hh_data_all->GetZaxis()->SetTitleOffset(1.8))\n",
"Execution of your code was aborted.\n"
]
}
],
"source": [
"TCanvas *ca = new TCanvas(\"rf702_efficiency_2D\", \"rf702_efficiency_2D\", 1200, 400);\n",
"ca->Divide(3);\n",
"ca->cd(1);\n",
"gPad->SetLeftMargin(0.15);\n",
"hh_data_all->GetZaxis()->SetTitleOffset(1.8);\n",
"hh_data_all->Draw(\"lego\");\n",
"ca->cd(2);\n",
"gPad->SetLeftMargin(0.15);\n",
"hh_data_sel->GetZaxis()->SetTitleOffset(1.8);\n",
"hh_data_sel->Draw(\"lego\");\n",
"ca->cd(3);\n",
"gPad->SetLeftMargin(0.15);\n",
"hh_eff->GetZaxis()->SetTitleOffset(1.8);\n",
"hh_eff->Draw(\"surf\");\n",
"\n",
"return;"
]
},
{
"cell_type": "markdown",
"id": "2f08b260",
"metadata": {},
"source": [
"Draw all canvases "
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "0dcc7028",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:34:29.337913Z",
"iopub.status.busy": "2026-05-19T20:34:29.337792Z",
"iopub.status.idle": "2026-05-19T20:34:29.546453Z",
"shell.execute_reply": "2026-05-19T20:34:29.545883Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
"
\n",
"\n",
"\n",
"\n"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"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
}