{ "cells": [ { "cell_type": "markdown", "id": "4ca66aca", "metadata": {}, "source": [ "# rf303_conditional\n", "Multidimensional models: use of tailored pdf as conditional pdfs.s\n", "\n", "`pdf = gauss(x,f(y),sx | y )` with `f(y) = a0 + a1*y`\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:30 PM." ] }, { "cell_type": "code", "execution_count": 1, "id": "92762d11", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:35.525676Z", "iopub.status.busy": "2026-05-19T20:30:35.525546Z", "iopub.status.idle": "2026-05-19T20:30:35.539301Z", "shell.execute_reply": "2026-05-19T20:30:35.538722Z" } }, "outputs": [], "source": [ "%%cpp -d\n", "#include \"RooRealVar.h\"\n", "#include \"RooDataSet.h\"\n", "#include \"RooDataHist.h\"\n", "#include \"RooGaussian.h\"\n", "#include \"RooPolyVar.h\"\n", "#include \"RooProdPdf.h\"\n", "#include \"RooPlot.h\"\n", "#include \"TRandom.h\"\n", "#include \"TCanvas.h\"\n", "#include \"TAxis.h\"\n", "#include \"TH1.h\"\n", "\n", "using namespace RooFit;\n", "\n", "RooDataSet *makeFakeDataXY();" ] }, { "cell_type": "markdown", "id": "ca5ec743", "metadata": {}, "source": [ " Definition of a helper function: " ] }, { "cell_type": "code", "execution_count": 2, "id": "62ade1ec", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:35.540852Z", "iopub.status.busy": "2026-05-19T20:30:35.540735Z", "iopub.status.idle": "2026-05-19T20:30:35.564457Z", "shell.execute_reply": "2026-05-19T20:30:35.563908Z" } }, "outputs": [], "source": [ "%%cpp -d\n", "RooDataSet *makeFakeDataXY()\n", "{\n", " TRandom3 trnd{};\n", "\n", " RooRealVar x(\"x\", \"x\", -10, 10);\n", " RooRealVar y(\"y\", \"y\", -10, 10);\n", " RooArgSet coord(x, y);\n", "\n", " RooDataSet *d = new RooDataSet(\"d\", \"d\", RooArgSet(x, y));\n", "\n", " for (int i = 0; i < 10000; i++) {\n", " double tmpy = trnd.Gaus(0, 10);\n", " double tmpx = trnd.Gaus(0.5 * tmpy, 1);\n", " if (fabs(tmpy) < 10 && fabs(tmpx) < 10) {\n", " x.setVal(tmpx);\n", " y.setVal(tmpy);\n", " d->add(coord);\n", " }\n", " }\n", "\n", " return d;\n", "}" ] }, { "cell_type": "markdown", "id": "43353c2f", "metadata": {}, "source": [ "Setup composed model gauss(x,m(y),s)\n", "-----------------------------------------------------------------------" ] }, { "cell_type": "markdown", "id": "1beb39d2", "metadata": {}, "source": [ "Create observables" ] }, { "cell_type": "code", "execution_count": 3, "id": "c784f733", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:35.566033Z", "iopub.status.busy": "2026-05-19T20:30:35.565912Z", "iopub.status.idle": "2026-05-19T20:30:35.774109Z", "shell.execute_reply": "2026-05-19T20:30:35.773511Z" } }, "outputs": [], "source": [ "RooRealVar x(\"x\", \"x\", -10, 10);\n", "RooRealVar y(\"y\", \"y\", -10, 10);" ] }, { "cell_type": "markdown", "id": "6d647e33", "metadata": {}, "source": [ "Create function f(y) = a0 + a1*y" ] }, { "cell_type": "code", "execution_count": 4, "id": "eb2a6023", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:35.776136Z", "iopub.status.busy": "2026-05-19T20:30:35.776013Z", "iopub.status.idle": "2026-05-19T20:30:35.983878Z", "shell.execute_reply": "2026-05-19T20:30:35.983247Z" } }, "outputs": [], "source": [ "RooRealVar a0(\"a0\", \"a0\", -0.5, -5, 5);\n", "RooRealVar a1(\"a1\", \"a1\", -0.5, -1, 1);\n", "RooPolyVar fy(\"fy\", \"fy\", y, RooArgSet(a0, a1));" ] }, { "cell_type": "markdown", "id": "a2f1faf6", "metadata": {}, "source": [ "Create gauss(x,f(y),s)" ] }, { "cell_type": "code", "execution_count": 5, "id": "1e253392", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:35.985984Z", "iopub.status.busy": "2026-05-19T20:30:35.985858Z", "iopub.status.idle": "2026-05-19T20:30:36.193785Z", "shell.execute_reply": "2026-05-19T20:30:36.193102Z" } }, "outputs": [], "source": [ "RooRealVar sigma(\"sigma\", \"width of gaussian\", 0.5, 0.1, 2.0);\n", "RooGaussian model(\"model\", \"Gaussian with shifting mean\", x, fy, sigma);" ] }, { "cell_type": "markdown", "id": "88135db1", "metadata": {}, "source": [ "Obtain fake external experimental dataset with values for x and y" ] }, { "cell_type": "code", "execution_count": 6, "id": "b8708367", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:36.195591Z", "iopub.status.busy": "2026-05-19T20:30:36.195471Z", "iopub.status.idle": "2026-05-19T20:30:36.403348Z", "shell.execute_reply": "2026-05-19T20:30:36.402681Z" } }, "outputs": [], "source": [ "RooDataSet *expDataXY = makeFakeDataXY();" ] }, { "cell_type": "markdown", "id": "25eac4e7", "metadata": {}, "source": [ "Generate data from conditional p.d.f model(x|y)\n", "---------------------------------------------------------------------------------------------" ] }, { "cell_type": "markdown", "id": "4c8a32d3", "metadata": {}, "source": [ "Make subset of experimental data with only y values" ] }, { "cell_type": "code", "execution_count": 7, "id": "0daf2f0b", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:36.405386Z", "iopub.status.busy": "2026-05-19T20:30:36.405260Z", "iopub.status.idle": "2026-05-19T20:30:36.613331Z", "shell.execute_reply": "2026-05-19T20:30:36.612676Z" } }, "outputs": [], "source": [ "std::unique_ptr expAbsDataY{expDataXY->reduce(y)};\n", "RooDataSet *expDataY = static_cast(expAbsDataY.get());" ] }, { "cell_type": "markdown", "id": "30b42164", "metadata": {}, "source": [ "Generate 10000 events in x obtained from _conditional_ model(x|y) with y values taken from experimental data" ] }, { "cell_type": "code", "execution_count": 8, "id": "98277fe8", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:36.615383Z", "iopub.status.busy": "2026-05-19T20:30:36.615255Z", "iopub.status.idle": "2026-05-19T20:30:36.825069Z", "shell.execute_reply": "2026-05-19T20:30:36.824319Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "RooDataSet::modelData[x,y] = 6850 entries\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "input_line_55: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, ProtoData(*expDataY))};\n", " ^\n" ] } ], "source": [ "std::unique_ptr data{model.generate(x, ProtoData(*expDataY))};\n", "data->Print();" ] }, { "cell_type": "markdown", "id": "1627abf8", "metadata": {}, "source": [ "Fit conditional p.d.f model(x|y) to data\n", "---------------------------------------------------------------------------------------------" ] }, { "cell_type": "code", "execution_count": 9, "id": "c3b48811", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:36.826817Z", "iopub.status.busy": "2026-05-19T20:30:36.826690Z", "iopub.status.idle": "2026-05-19T20:30:37.156271Z", "shell.execute_reply": "2026-05-19T20:30:37.155735Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[#1] INFO:Fitting -- RooAbsPdf::fitTo(model_over_model_Int[x]) fixing normalization set for coefficient determination to observables in data\n", "[#1] INFO:Fitting -- using generic CPU library compiled with no vectorizations\n", "[#1] INFO:Fitting -- Creation of NLL object took 826.903 μs\n", "[#1] INFO:Fitting -- RooAddition::defaultErrorLevel(nll_model_over_model_Int[x]_d) Summation contains a RooNLLVar, using its error level\n", "[#1] INFO:Minimization -- [fitFCN] No discrete parameters, performing continuous minimization only\n" ] } ], "source": [ "model.fitTo(*expDataXY, ConditionalObservables(y), PrintLevel(-1));" ] }, { "cell_type": "markdown", "id": "b35facd3", "metadata": {}, "source": [ "Project conditional p.d.f on x and y dimensions\n", "---------------------------------------------------------------------------------------------" ] }, { "cell_type": "markdown", "id": "0375fc69", "metadata": {}, "source": [ "Plot x distribution of data and projection of model on x = 1/Ndata sum(data(y_i)) model(x;y_i)" ] }, { "cell_type": "code", "execution_count": 10, "id": "64385daf", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:37.158042Z", "iopub.status.busy": "2026-05-19T20:30:37.157923Z", "iopub.status.idle": "2026-05-19T20:30:37.366252Z", "shell.execute_reply": "2026-05-19T20:30:37.365300Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[#1] INFO:Plotting -- RooAbsReal::plotOn(model) plot on x averages using data variables (y)\n" ] } ], "source": [ "RooPlot *xframe = x.frame();\n", "expDataXY->plotOn(xframe);\n", "model.plotOn(xframe, ProjWData(*expDataY));" ] }, { "cell_type": "markdown", "id": "0be1820f", "metadata": {}, "source": [ "Speed up (and approximate) projection by using binned clone of data for projection" ] }, { "cell_type": "code", "execution_count": 11, "id": "a35f51e5", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:37.367712Z", "iopub.status.busy": "2026-05-19T20:30:37.367574Z", "iopub.status.idle": "2026-05-19T20:30:37.575722Z", "shell.execute_reply": "2026-05-19T20:30:37.574917Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[#1] INFO:Plotting -- RooAbsReal::plotOn(model) plot on x averages using data variables (y)\n" ] } ], "source": [ "std::unique_ptr binnedDataY{expDataY->binnedClone()};\n", "model.plotOn(xframe, ProjWData(*binnedDataY), LineColor(kCyan), LineStyle(kDotted));" ] }, { "cell_type": "markdown", "id": "3ba74eac", "metadata": {}, "source": [ "Show effect of projection with too coarse binning" ] }, { "cell_type": "code", "execution_count": 12, "id": "0e3de4cd", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:37.577482Z", "iopub.status.busy": "2026-05-19T20:30:37.577358Z", "iopub.status.idle": "2026-05-19T20:30:37.786101Z", "shell.execute_reply": "2026-05-19T20:30:37.785412Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[#1] INFO:Plotting -- RooAbsReal::plotOn(model) plot on x averages using data variables (y)\n" ] } ], "source": [ "((RooRealVar *)expDataY->get()->find(\"y\"))->setBins(5);\n", "std::unique_ptr binnedDataY2{expDataY->binnedClone()};\n", "model.plotOn(xframe, ProjWData(*binnedDataY2), LineColor(kRed));" ] }, { "cell_type": "markdown", "id": "0e8e7d1a", "metadata": {}, "source": [ "Make canvas and draw RooPlots" ] }, { "cell_type": "code", "execution_count": 13, "id": "a6ec4dc5", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:37.788333Z", "iopub.status.busy": "2026-05-19T20:30:37.788204Z", "iopub.status.idle": "2026-05-19T20:30:37.996446Z", "shell.execute_reply": "2026-05-19T20:30:37.995711Z" } }, "outputs": [], "source": [ "new TCanvas(\"rf303_conditional\", \"rf303_conditional\", 600, 460);\n", "gPad->SetLeftMargin(0.15);\n", "xframe->GetYaxis()->SetTitleOffset(1.2);\n", "xframe->Draw();" ] }, { "cell_type": "markdown", "id": "0d49e208", "metadata": {}, "source": [ "Draw all canvases " ] }, { "cell_type": "code", "execution_count": 14, "id": "c4eccf4c", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:37.998295Z", "iopub.status.busy": "2026-05-19T20:30:37.998167Z", "iopub.status.idle": "2026-05-19T20:30:38.228472Z", "shell.execute_reply": "2026-05-19T20:30:38.227858Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "
\n", "
\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "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 }