{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "a4838926",
   "metadata": {},
   "source": [
    "# rf604_constraints\n",
    "Likelihood and minimization: fitting with constraints\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "**Author:**  Clemens Lange, Wouter Verkerke (C++ version)  \n",
    "<i><small>This notebook tutorial was automatically generated with <a href= \"https://github.com/root-project/root/blob/master/documentation/doxygen/converttonotebook.py\">ROOTBOOK-izer</a> from the macro found in the ROOT repository  on Tuesday, May 19, 2026 at 08:33 PM.</small></i>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "f1f97dab",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:33:06.156053Z",
     "iopub.status.busy": "2026-05-19T20:33:06.155897Z",
     "iopub.status.idle": "2026-05-19T20:33:07.119002Z",
     "shell.execute_reply": "2026-05-19T20:33:07.118297Z"
    }
   },
   "outputs": [],
   "source": [
    "import ROOT"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8298d218",
   "metadata": {},
   "source": [
    "Create model and dataset\n",
    "----------------------------------------------"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "589c1526",
   "metadata": {},
   "source": [
    "Construct a Gaussian pdf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "4877c595",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:33:07.120932Z",
     "iopub.status.busy": "2026-05-19T20:33:07.120799Z",
     "iopub.status.idle": "2026-05-19T20:33:07.302495Z",
     "shell.execute_reply": "2026-05-19T20:33:07.301877Z"
    }
   },
   "outputs": [],
   "source": [
    "x = ROOT.RooRealVar(\"x\", \"x\", -10, 10)\n",
    "\n",
    "m = ROOT.RooRealVar(\"m\", \"m\", 0, -10, 10)\n",
    "s = ROOT.RooRealVar(\"s\", \"s\", 2, 0.1, 10)\n",
    "gauss = ROOT.RooGaussian(\"gauss\", \"gauss(x,m,s)\", x, m, s)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c899b6a2",
   "metadata": {},
   "source": [
    "Construct a flat pdf (polynomial of 0th order)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "dc68dfca",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:33:07.304411Z",
     "iopub.status.busy": "2026-05-19T20:33:07.304272Z",
     "iopub.status.idle": "2026-05-19T20:33:07.415876Z",
     "shell.execute_reply": "2026-05-19T20:33:07.415372Z"
    }
   },
   "outputs": [],
   "source": [
    "poly = ROOT.RooPolynomial(\"poly\", \"poly(x)\", x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "88d7f98b",
   "metadata": {},
   "source": [
    "model = f*gauss + (1-f)*poly"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "1bf98fdc",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:33:07.417676Z",
     "iopub.status.busy": "2026-05-19T20:33:07.417535Z",
     "iopub.status.idle": "2026-05-19T20:33:07.600095Z",
     "shell.execute_reply": "2026-05-19T20:33:07.599527Z"
    }
   },
   "outputs": [],
   "source": [
    "f = ROOT.RooRealVar(\"f\", \"f\", 0.5, 0.0, 1.0)\n",
    "model = ROOT.RooAddPdf(\"model\", \"model\", [gauss, poly], [f])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "01c3d537",
   "metadata": {},
   "source": [
    "Generate small dataset for use in fitting below"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "d8511145",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:33:07.611199Z",
     "iopub.status.busy": "2026-05-19T20:33:07.611037Z",
     "iopub.status.idle": "2026-05-19T20:33:07.756395Z",
     "shell.execute_reply": "2026-05-19T20:33:07.755922Z"
    }
   },
   "outputs": [],
   "source": [
    "d = model.generate({x}, 50)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7eecb557",
   "metadata": {},
   "source": [
    "Create constraint pdf\n",
    "-----------------------------------------"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7fe1e579",
   "metadata": {},
   "source": [
    "Construct Gaussian constraint pdf on parameter f at 0.8 with\n",
    "resolution of 0.1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "30c9c5ca",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:33:07.758230Z",
     "iopub.status.busy": "2026-05-19T20:33:07.758106Z",
     "iopub.status.idle": "2026-05-19T20:33:07.872737Z",
     "shell.execute_reply": "2026-05-19T20:33:07.872343Z"
    }
   },
   "outputs": [],
   "source": [
    "fconstraint = ROOT.RooGaussian(\"fconstraint\", \"fconstraint\", f, 0.8, 0.1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d56c8483",
   "metadata": {},
   "source": [
    "Method 1 - add internal constraint to model\n",
    "-------------------------------------------------------------------------------------"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "40b30c8a",
   "metadata": {},
   "source": [
    "Multiply constraint term with regular pdf using ROOT.RooProdPdf Specify in\n",
    "fitTo() that internal constraints on parameter f should be used"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dec799af",
   "metadata": {},
   "source": [
    "Multiply constraint with pdf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "fc38ab86",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:33:07.874934Z",
     "iopub.status.busy": "2026-05-19T20:33:07.874793Z",
     "iopub.status.idle": "2026-05-19T20:33:07.987599Z",
     "shell.execute_reply": "2026-05-19T20:33:07.987106Z"
    }
   },
   "outputs": [],
   "source": [
    "modelc = ROOT.RooProdPdf(\"modelc\", \"model with constraint\", [model, fconstraint])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "edc17abb",
   "metadata": {},
   "source": [
    "Fit model (without use of constraint term)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "2259999e",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:33:07.989154Z",
     "iopub.status.busy": "2026-05-19T20:33:07.989029Z",
     "iopub.status.idle": "2026-05-19T20:33:08.180518Z",
     "shell.execute_reply": "2026-05-19T20:33:08.179918Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[#1] INFO:Fitting -- RooAbsPdf::fitTo(model) 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 769.964 μs\n",
      "[#1] INFO:Fitting -- RooAddition::defaultErrorLevel(nll_model_modelData) Summation contains a RooNLLVar, using its error level\n",
      "[#1] INFO:Minimization -- [fitFCN] No discrete parameters, performing continuous minimization only\n"
     ]
    }
   ],
   "source": [
    "r1 = model.fitTo(d, Save=True, PrintLevel=-1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "53ff8306",
   "metadata": {},
   "source": [
    "Fit modelc with constraint term on parameter f"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "0f854c9d",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:33:08.182097Z",
     "iopub.status.busy": "2026-05-19T20:33:08.181960Z",
     "iopub.status.idle": "2026-05-19T20:33:08.292925Z",
     "shell.execute_reply": "2026-05-19T20:33:08.292289Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[#1] INFO:Minimization --  Including the following constraint terms in minimization: (fconstraint)\n",
      "[#1] INFO:Minimization -- The global observables are not defined , normalize constraints with respect to the parameters (f)\n",
      "[#1] INFO:Fitting -- RooAbsPdf::fitTo(modelc) fixing normalization set for coefficient determination to observables in data\n",
      "[#1] INFO:Fitting -- Creation of NLL object took 1.06354 ms\n",
      "[#1] INFO:Fitting -- RooAddition::defaultErrorLevel(nll_modelc_modelData) Summation contains a RooNLLVar, using its error level\n",
      "[#1] INFO:Minimization -- [fitFCN] No discrete parameters, performing continuous minimization only\n"
     ]
    }
   ],
   "source": [
    "r2 = modelc.fitTo(d, Constrain={f}, Save=True, PrintLevel=-1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0682c487",
   "metadata": {},
   "source": [
    "Method 2 - specify external constraint when fitting\n",
    "------------------------------------------------------------------------------------------"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4aa925cb",
   "metadata": {},
   "source": [
    "Construct another Gaussian constraint pdf on parameter f at 0.8 with\n",
    "resolution of 0.1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "257408bc",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:33:08.294295Z",
     "iopub.status.busy": "2026-05-19T20:33:08.294171Z",
     "iopub.status.idle": "2026-05-19T20:33:08.397610Z",
     "shell.execute_reply": "2026-05-19T20:33:08.397019Z"
    }
   },
   "outputs": [],
   "source": [
    "fconstext = ROOT.RooGaussian(\"fconstext\", \"fconstext\", f, 0.2, 0.1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b7320ead",
   "metadata": {},
   "source": [
    "Fit with external constraint"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "5e223a72",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:33:08.399095Z",
     "iopub.status.busy": "2026-05-19T20:33:08.398969Z",
     "iopub.status.idle": "2026-05-19T20:33:08.510695Z",
     "shell.execute_reply": "2026-05-19T20:33:08.510083Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[#1] INFO:Minimization --  Including the following constraint terms in minimization: (fconstext)\n",
      "[#1] INFO:Minimization -- The global observables are not defined , normalize constraints with respect to the parameters (f,m,s)\n",
      "[#1] INFO:Fitting -- RooAbsPdf::fitTo(model) fixing normalization set for coefficient determination to observables in data\n",
      "[#1] INFO:Fitting -- Creation of NLL object took 227.822 μs\n",
      "[#1] INFO:Fitting -- RooAddition::defaultErrorLevel(nll_model_modelData) Summation contains a RooNLLVar, using its error level\n",
      "[#1] INFO:Minimization -- [fitFCN] No discrete parameters, performing continuous minimization only\n"
     ]
    }
   ],
   "source": [
    "r3 = model.fitTo(d, ExternalConstraints={fconstext}, Save=True, PrintLevel=-1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "585d4674",
   "metadata": {},
   "source": [
    "Print the fit results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "5e230466",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:33:08.511976Z",
     "iopub.status.busy": "2026-05-19T20:33:08.511852Z",
     "iopub.status.idle": "2026-05-19T20:33:08.622085Z",
     "shell.execute_reply": "2026-05-19T20:33:08.621496Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "fit result without constraint (data generated at f=0.5)\n",
      "fit result with internal constraint (data generated at f=0.5, is f=0.8+/-0.2)\n",
      "fit result with (another) external constraint (data generated at f=0.5, is f=0.2+/-0.1)\n",
      "\n",
      "  RooFitResult: minimized FCN value: 134.849, estimated distance to minimum: 2.11658e-05\n",
      "                covariance matrix quality: Full, accurate covariance matrix\n",
      "                Status : MINIMIZE=0 HESSE=0 \n",
      "\n",
      "    Floating Parameter  InitialValue    FinalValue +/-  Error     GblCorr.\n",
      "  --------------------  ------------  --------------------------  --------\n",
      "                     f    5.0000e-01    6.4987e-01 +/-  1.21e-01  <none>\n",
      "                     m    0.0000e+00    7.1824e-01 +/-  4.97e-01  <none>\n",
      "                     s    2.0000e+00    2.1880e+00 +/-  4.61e-01  <none>\n",
      "\n",
      "\n",
      "  RooFitResult: minimized FCN value: 133.901, estimated distance to minimum: 5.96672e-06\n",
      "                covariance matrix quality: Full, accurate covariance matrix\n",
      "                Status : MINIMIZE=0 HESSE=0 \n",
      "\n",
      "    Floating Parameter  InitialValue    FinalValue +/-  Error     GblCorr.\n",
      "  --------------------  ------------  --------------------------  --------\n",
      "                     f    6.4987e-01    7.3784e-01 +/-  7.53e-02  <none>\n",
      "                     m    7.1824e-01    6.6350e-01 +/-  5.04e-01  <none>\n",
      "                     s    2.1880e+00    2.3885e+00 +/-  4.95e-01  <none>\n",
      "\n",
      "\n",
      "  RooFitResult: minimized FCN value: 137.195, estimated distance to minimum: 0.000153955\n",
      "                covariance matrix quality: Full, accurate covariance matrix\n",
      "                Status : MINIMIZE=0 HESSE=0 \n",
      "\n",
      "    Floating Parameter  InitialValue    FinalValue +/-  Error     GblCorr.\n",
      "  --------------------  ------------  --------------------------  --------\n",
      "                     f    7.3784e-01    3.6215e-01 +/-  8.17e-02  <none>\n",
      "                     m    6.6350e-01    7.0071e-01 +/-  5.88e-01  <none>\n",
      "                     s    2.3885e+00    1.6987e+00 +/-  4.78e-01  <none>\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print(\"fit result without constraint (data generated at f=0.5)\")\n",
    "r1.Print(\"v\")\n",
    "print(\"fit result with internal constraint (data generated at f=0.5, is f=0.8+/-0.2)\")\n",
    "r2.Print(\"v\")\n",
    "print(\"fit result with (another) external constraint (data generated at f=0.5, is f=0.2+/-0.1)\")\n",
    "r3.Print(\"v\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
