{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "4572ab74",
   "metadata": {},
   "source": [
    "# rf403_weightedevts\n",
    "'DATA AND CATEGORIES' RooFit tutorial macro #403\n",
    "\n",
    "Using weights in unbinned datasets\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:31 PM.</small></i>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "2995278b",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:31:40.023031Z",
     "iopub.status.busy": "2026-05-19T20:31:40.022900Z",
     "iopub.status.idle": "2026-05-19T20:31:41.014220Z",
     "shell.execute_reply": "2026-05-19T20:31:41.013490Z"
    }
   },
   "outputs": [],
   "source": [
    "import ROOT"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "874a1c37",
   "metadata": {},
   "source": [
    "Create observable and unweighted dataset\n",
    "-------------------------------------------"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2e166c50",
   "metadata": {},
   "source": [
    "Declare observable"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "1e4dadff",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:31:41.026481Z",
     "iopub.status.busy": "2026-05-19T20:31:41.026334Z",
     "iopub.status.idle": "2026-05-19T20:31:41.189973Z",
     "shell.execute_reply": "2026-05-19T20:31:41.189186Z"
    }
   },
   "outputs": [],
   "source": [
    "x = ROOT.RooRealVar(\"x\", \"x\", -10, 10)\n",
    "x.setBins(40)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "19592469",
   "metadata": {},
   "source": [
    "Construction a uniform pdf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "834ce35e",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:31:41.192389Z",
     "iopub.status.busy": "2026-05-19T20:31:41.192255Z",
     "iopub.status.idle": "2026-05-19T20:31:41.316364Z",
     "shell.execute_reply": "2026-05-19T20:31:41.315718Z"
    }
   },
   "outputs": [],
   "source": [
    "p0 = ROOT.RooPolynomial(\"px\", \"px\", x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aa9c090b",
   "metadata": {},
   "source": [
    "Sample 1000 events from pdf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "d3666764",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:31:41.318505Z",
     "iopub.status.busy": "2026-05-19T20:31:41.318376Z",
     "iopub.status.idle": "2026-05-19T20:31:41.504515Z",
     "shell.execute_reply": "2026-05-19T20:31:41.503712Z"
    }
   },
   "outputs": [],
   "source": [
    "data = p0.generate(x, 1000)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c0a9d95d",
   "metadata": {},
   "source": [
    "Calculate weight and make dataset weighted\n",
    "--------------------------------------------------"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "68a069ca",
   "metadata": {},
   "source": [
    "Construct formula to calculate (fake) weight for events"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "4f2e6964",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:31:41.506350Z",
     "iopub.status.busy": "2026-05-19T20:31:41.506224Z",
     "iopub.status.idle": "2026-05-19T20:31:41.686920Z",
     "shell.execute_reply": "2026-05-19T20:31:41.686209Z"
    }
   },
   "outputs": [],
   "source": [
    "wFunc = ROOT.RooFormulaVar(\"w\", \"event weight\", \"(x*x+10)\", [x])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0a04ac3e",
   "metadata": {},
   "source": [
    "Add column with variable w to previously generated dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "722bd641",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:31:41.688730Z",
     "iopub.status.busy": "2026-05-19T20:31:41.688592Z",
     "iopub.status.idle": "2026-05-19T20:31:41.820809Z",
     "shell.execute_reply": "2026-05-19T20:31:41.812845Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<cppyy.gbl.RooRealVar object at 0x55df2cbdab90>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data.addColumn(wFunc)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a88d0297",
   "metadata": {},
   "source": [
    "Dataset d is now a dataset with two observable (x,w) with 1000 entries"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "a659aa8d",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:31:41.833079Z",
     "iopub.status.busy": "2026-05-19T20:31:41.832942Z",
     "iopub.status.idle": "2026-05-19T20:31:41.941285Z",
     "shell.execute_reply": "2026-05-19T20:31:41.940643Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "RooDataSet::pxData[x,w] = 1000 entries\n"
     ]
    }
   ],
   "source": [
    "data.Print()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "707ff348",
   "metadata": {},
   "source": [
    "Create a new dataset wdata where w is interpreted as event weight rather than\n",
    "as observable"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "d8f7b35b",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:31:41.942897Z",
     "iopub.status.busy": "2026-05-19T20:31:41.942775Z",
     "iopub.status.idle": "2026-05-19T20:31:42.129664Z",
     "shell.execute_reply": "2026-05-19T20:31:42.129063Z"
    }
   },
   "outputs": [],
   "source": [
    "wdata = ROOT.RooDataSet(data.GetName(), data.GetTitle(), data.get(), Import=data, WeightVar=\"w\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8f20612a",
   "metadata": {},
   "source": [
    "Dataset d is now a dataset with one observable (x) with 1000 entries and\n",
    "a sum of weights of ~430K"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "9b7ad2b7",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:31:42.135530Z",
     "iopub.status.busy": "2026-05-19T20:31:42.135403Z",
     "iopub.status.idle": "2026-05-19T20:31:42.239890Z",
     "shell.execute_reply": "2026-05-19T20:31:42.239261Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "RooDataSet::pxData[x,weight:w] = 1000 entries (43238.9 weighted)\n"
     ]
    }
   ],
   "source": [
    "wdata.Print()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ed87d27c",
   "metadata": {},
   "source": [
    "Unbinned ML fit to weighted data\n",
    "---------------------------------------------------------------"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e150ec4f",
   "metadata": {},
   "source": [
    "Construction quadratic polynomial pdf for fitting"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "aa4670e0",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:31:42.241511Z",
     "iopub.status.busy": "2026-05-19T20:31:42.241388Z",
     "iopub.status.idle": "2026-05-19T20:31:42.358754Z",
     "shell.execute_reply": "2026-05-19T20:31:42.358157Z"
    }
   },
   "outputs": [],
   "source": [
    "a0 = ROOT.RooRealVar(\"a0\", \"a0\", 1)\n",
    "a1 = ROOT.RooRealVar(\"a1\", \"a1\", 0, -1, 1)\n",
    "a2 = ROOT.RooRealVar(\"a2\", \"a2\", 1, 0, 10)\n",
    "p2 = ROOT.RooPolynomial(\"p2\", \"p2\", x, [a0, a1, a2], 0)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fcb8fcd2",
   "metadata": {},
   "source": [
    "Fit quadratic polynomial to weighted data"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "812f999f",
   "metadata": {},
   "source": [
    "NOTE: A plain Maximum likelihood fit to weighted data does in general\n",
    "      NOT result in correct error estimates, individual\n",
    "      event weights represent Poisson statistics themselves.\n",
    "\n",
    "Fit with 'wrong' errors"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "ad197445",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:31:42.360757Z",
     "iopub.status.busy": "2026-05-19T20:31:42.360635Z",
     "iopub.status.idle": "2026-05-19T20:31:42.562354Z",
     "shell.execute_reply": "2026-05-19T20:31:42.561674Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[#1] INFO:Fitting -- RooAbsPdf::fitTo(p2_over_p2_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 755.084 μs\n",
      "[#0] WARNING:InputArguments -- RooAbsPdf::fitTo(p2): WARNING: a likelihood fit is requested of what appears to be weighted data.\n",
      "       While the estimated values of the parameters will always be calculated taking the weights into account,\n",
      "       there are multiple ways to estimate the errors of the parameters. You are advised to make an\n",
      "       explicit choice for the error calculation:\n",
      "           - Either provide SumW2Error(true), to calculate a sum-of-weights-corrected HESSE error matrix\n",
      "             (error will be proportional to the number of events in MC).\n",
      "           - Or provide SumW2Error(false), to return errors from original HESSE error matrix\n",
      "             (which will be proportional to the sum of the weights, i.e., a dataset with <sum of weights> events).\n",
      "           - Or provide AsymptoticError(true), to use the asymptotically correct expression\n",
      "             (for details see https://arxiv.org/abs/1911.01303).\"\n",
      "[#1] INFO:Fitting -- RooAddition::defaultErrorLevel(nll_p2_over_p2_Int[x]_pxData) Summation contains a RooNLLVar, using its error level\n",
      "[#1] INFO:Minimization -- [fitFCN] No discrete parameters, performing continuous minimization only\n"
     ]
    }
   ],
   "source": [
    "r_ml_wgt = p2.fitTo(wdata, Save=True, PrintLevel=-1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cd7926f3",
   "metadata": {},
   "source": [
    "A first order correction to estimated parameter errors in an\n",
    "(unbinned) ML fit can be obtained by calculating the\n",
    "covariance matrix as\n",
    "\n",
    "   V' = V C-1 V\n",
    "\n",
    "where V is the covariance matrix calculated from a fit\n",
    "to -logL = - sum [ w_i log f(x_i) ] and C is the covariance\n",
    "matrix calculated from -logL' = -sum [ w_i^2 log f(x_i) ]\n",
    "(i.e. the weights are applied squared)\n",
    "\n",
    "A fit in self mode can be performed as follows:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "1cee1fde",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:31:42.564428Z",
     "iopub.status.busy": "2026-05-19T20:31:42.564300Z",
     "iopub.status.idle": "2026-05-19T20:31:42.682039Z",
     "shell.execute_reply": "2026-05-19T20:31:42.681461Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[#1] INFO:Fitting -- RooAbsPdf::fitTo(p2_over_p2_Int[x]) fixing normalization set for coefficient determination to observables in data\n",
      "[#1] INFO:Fitting -- Creation of NLL object took 152.79 μs\n",
      "[#1] INFO:Fitting -- RooAddition::defaultErrorLevel(nll_p2_over_p2_Int[x]_pxData) Summation contains a RooNLLVar, using its error level\n",
      "[#1] INFO:Minimization -- [fitFCN] No discrete parameters, performing continuous minimization only\n",
      "[#1] INFO:Fitting -- RooAbsPdf::fitTo(p2) Calculating sum-of-weights-squared correction matrix for covariance matrix\n"
     ]
    }
   ],
   "source": [
    "r_ml_wgt_corr = p2.fitTo(wdata, Save=True, SumW2Error=True, PrintLevel=-1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "952a9b71",
   "metadata": {},
   "source": [
    "Plot weighted data and fit result\n",
    "---------------------------------------------------------------"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "25e973cd",
   "metadata": {},
   "source": [
    "Construct plot frame"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "58c41ca1",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:31:42.683899Z",
     "iopub.status.busy": "2026-05-19T20:31:42.683768Z",
     "iopub.status.idle": "2026-05-19T20:31:42.811932Z",
     "shell.execute_reply": "2026-05-19T20:31:42.811289Z"
    }
   },
   "outputs": [],
   "source": [
    "frame = x.frame(Title=\"Unbinned ML fit, chi^2 fit to weighted data\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eda917d9",
   "metadata": {},
   "source": [
    "Plot data using sum-of-weights-squared error rather than Poisson errors"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "26fb9d60",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:31:42.814042Z",
     "iopub.status.busy": "2026-05-19T20:31:42.813915Z",
     "iopub.status.idle": "2026-05-19T20:31:42.943425Z",
     "shell.execute_reply": "2026-05-19T20:31:42.942324Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<cppyy.gbl.RooPlot object at 0x55df2d687320>"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "wdata.plotOn(frame, DataError=\"SumW2\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aed273dc",
   "metadata": {},
   "source": [
    "Overlay result of 2nd order polynomial fit to weighted data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "f7b4a22c",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:31:42.945021Z",
     "iopub.status.busy": "2026-05-19T20:31:42.944895Z",
     "iopub.status.idle": "2026-05-19T20:31:43.080393Z",
     "shell.execute_reply": "2026-05-19T20:31:43.078859Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<cppyy.gbl.RooPlot object at 0x55df2d687320>"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p2.plotOn(frame)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dfd62731",
   "metadata": {},
   "source": [
    "ML fit of pdf to equivalent unweighted dataset\n",
    "---------------------------------------------------------------------"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e371dbf9",
   "metadata": {},
   "source": [
    "Construct a pdf with the same shape as p0 after weighting"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "bc2a9aae",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:31:43.082057Z",
     "iopub.status.busy": "2026-05-19T20:31:43.081932Z",
     "iopub.status.idle": "2026-05-19T20:31:43.199136Z",
     "shell.execute_reply": "2026-05-19T20:31:43.198481Z"
    }
   },
   "outputs": [],
   "source": [
    "genPdf = ROOT.RooGenericPdf(\"genPdf\", \"x*x+10\", [x])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0d392c7c",
   "metadata": {},
   "source": [
    "Sample a dataset with the same number of events as data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "f4d07696",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:31:43.201155Z",
     "iopub.status.busy": "2026-05-19T20:31:43.201027Z",
     "iopub.status.idle": "2026-05-19T20:31:43.309747Z",
     "shell.execute_reply": "2026-05-19T20:31:43.308798Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[#1] INFO:NumericIntegration -- RooRealIntegral::init(genPdf_Int[x]) using numeric integrator RooIntegrator1D to calculate Int(x)\n",
      "[#1] INFO:NumericIntegration -- RooRealIntegral::init(genPdf_Int[x]) using numeric integrator RooIntegrator1D to calculate Int(x)\n"
     ]
    }
   ],
   "source": [
    "data2 = genPdf.generate(x, 1000)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "77c79345",
   "metadata": {},
   "source": [
    "Sample a dataset with the same number of weights as data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "3b7f4c6c",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:31:43.311235Z",
     "iopub.status.busy": "2026-05-19T20:31:43.311112Z",
     "iopub.status.idle": "2026-05-19T20:31:43.434037Z",
     "shell.execute_reply": "2026-05-19T20:31:43.433642Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[#1] INFO:NumericIntegration -- RooRealIntegral::init(genPdf_Int[x]) using numeric integrator RooIntegrator1D to calculate Int(x)\n",
      "[#1] INFO:NumericIntegration -- RooRealIntegral::init(genPdf_Int[x]) using numeric integrator RooIntegrator1D to calculate Int(x)\n"
     ]
    }
   ],
   "source": [
    "data3 = genPdf.generate(x, 43000)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6ceeb527",
   "metadata": {},
   "source": [
    "Fit the 2nd order polynomial to both unweighted datasets and save the\n",
    "results for comparison"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "7f7c94a6",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:31:43.439296Z",
     "iopub.status.busy": "2026-05-19T20:31:43.439163Z",
     "iopub.status.idle": "2026-05-19T20:31:43.565712Z",
     "shell.execute_reply": "2026-05-19T20:31:43.564725Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[#1] INFO:Fitting -- RooAbsPdf::fitTo(p2_over_p2_Int[x]) fixing normalization set for coefficient determination to observables in data\n",
      "[#1] INFO:Fitting -- Creation of NLL object took 155.05 μs\n",
      "[#1] INFO:Fitting -- RooAddition::defaultErrorLevel(nll_p2_over_p2_Int[x]_genPdfData) Summation contains a RooNLLVar, using its error level\n",
      "[#1] INFO:Minimization -- [fitFCN] No discrete parameters, performing continuous minimization only\n",
      "[#1] INFO:Fitting -- RooAbsPdf::fitTo(p2_over_p2_Int[x]) fixing normalization set for coefficient determination to observables in data\n",
      "[#1] INFO:Fitting -- Creation of NLL object took 190.13 μs\n",
      "[#1] INFO:Fitting -- RooAddition::defaultErrorLevel(nll_p2_over_p2_Int[x]_genPdfData) Summation contains a RooNLLVar, using its error level\n",
      "[#1] INFO:Minimization -- [fitFCN] No discrete parameters, performing continuous minimization only\n"
     ]
    }
   ],
   "source": [
    "r_ml_unw10 = p2.fitTo(data2, Save=True, PrintLevel=-1)\n",
    "r_ml_unw43 = p2.fitTo(data3, Save=True, PrintLevel=-1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "805bcabc",
   "metadata": {},
   "source": [
    "Chis2 fit of pdf to binned weighted dataset\n",
    "---------------------------------------------------------------------------"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "86ed769b",
   "metadata": {},
   "source": [
    "Construct binned clone of unbinned weighted dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "1a18b88b",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:31:43.567352Z",
     "iopub.status.busy": "2026-05-19T20:31:43.567221Z",
     "iopub.status.idle": "2026-05-19T20:31:43.681746Z",
     "shell.execute_reply": "2026-05-19T20:31:43.680791Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "DataStore pxData_binned (Generated From px_binned)\n",
      "  Contains 40 entries\n",
      "  Observables: \n",
      "    1)  x = 9.75  L(-10 - 10) B(40)  \"x\"\n",
      "Binned Dataset pxData_binned (Generated From px_binned)\n",
      "  Contains 40 bins with a total weight of 43238.9\n",
      "  Observables:     1)  x = 9.75  L(-10 - 10) B(40)  \"x\"\n"
     ]
    }
   ],
   "source": [
    "binnedData = wdata.binnedClone()\n",
    "binnedData.Print(\"v\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "24ad7f9a",
   "metadata": {},
   "source": [
    "Perform chi2 fit to binned weighted dataset using sum-of-weights errors\n",
    "\n",
    "NB: Within the usual approximations of a chi2 fit, chi2 fit to weighted\n",
    "data using sum-of-weights-squared errors does give correct error\n",
    "estimates"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "cf69bcd0",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:31:43.683309Z",
     "iopub.status.busy": "2026-05-19T20:31:43.683179Z",
     "iopub.status.idle": "2026-05-19T20:31:43.824131Z",
     "shell.execute_reply": "2026-05-19T20:31:43.823454Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[#1] INFO:Fitting -- createChi2(p2) fixing normalization set for coefficient determination to observables in data\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[#1] INFO:Minimization -- [fitFCN] No discrete parameters, performing continuous minimization only\n",
      "Minuit2Minimizer: Minimize with max-calls 1000 convergence for edm < 1 strategy 1\n",
      "Minuit2Minimizer : Valid minimum - status = 0\n",
      "FVAL  = 31.3747451817532266\n",
      "Edm   = 4.13511590231855403e-08\n",
      "Nfcn  = 29\n",
      "a1\t  = -0.009989\t +/-  0.0262975\t(limited)\n",
      "a2\t  = 0.106373\t +/-  0.0101849\t(limited)\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Info in <Minuit2>: MnSeedGenerator Computing seed using NumericalGradient calculator\n",
      "Info in <Minuit2>: MnSeedGenerator Evaluated function and gradient in 44.259 μs\n",
      "Info in <Minuit2>: MnSeedGenerator Initial state: FCN =       32.33995323 Edm =      0.8968537856 NCalls =      7\n",
      "Info in <Minuit2>: MnSeedGenerator Initial state  \n",
      "  Minimum value : 32.33995323\n",
      "  Edm           : 0.8968537856\n",
      "  Internal parameters:\t[   -0.00121057482     -1.372915994]\t\n",
      "  Internal gradient  :\t[      27.17902731     -203.7916428]\t\n",
      "  Internal covariance matrix:\n",
      "[[  0.00060495515              0]\n",
      " [              0  7.5618996e-05]]]\n",
      "Info in <Minuit2>: VariableMetricBuilder Start iterating until Edm is < 0.002 with call limit = 1000\n",
      "Info in <Minuit2>: VariableMetricBuilder    0 - FCN =       32.33995323 Edm =      0.8968537856 NCalls =      7\n",
      "Info in <Minuit2>: VariableMetricBuilder    1 - FCN =       31.37772394 Edm =    0.002313012129 NCalls =     13\n",
      "Info in <Minuit2>: VariableMetricBuilder    2 - FCN =       31.37474518 Edm =   3.566880604e-08 NCalls =     19\n",
      "Info in <Minuit2>: MnHesse Done after 15.629 μs\n",
      "Info in <Minuit2>: VariableMetricBuilder After Hessian\n",
      "Info in <Minuit2>: VariableMetricBuilder    3 - FCN =       31.37474518 Edm =   4.135115902e-08 NCalls =     29\n",
      "Info in <Minuit2>: VariableMetricBuilder Stop iterating after 63.432 μs\n",
      "Info in <Minuit2>: Minuit2Minimizer::Hesse Using max-calls 1000\n",
      "Info in <Minuit2>: MnHesse Done after 20.349 μs\n",
      "Info in <Minuit2>: Minuit2Minimizer::Hesse Hesse is valid - matrix is accurate\n"
     ]
    }
   ],
   "source": [
    "chi2 = p2.createChi2(binnedData, ROOT.RooFit.DataError(\"SumW2\"))\n",
    "m = ROOT.RooMinimizer(chi2)\n",
    "m.migrad()\n",
    "m.hesse()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "377b5d93",
   "metadata": {},
   "source": [
    "Plot chi^2 fit result on frame as well"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "9c72f576",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:31:43.826044Z",
     "iopub.status.busy": "2026-05-19T20:31:43.825911Z",
     "iopub.status.idle": "2026-05-19T20:31:43.945172Z",
     "shell.execute_reply": "2026-05-19T20:31:43.944510Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<cppyy.gbl.RooPlot object at 0x55df2d687320>"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r_chi2_wgt = m.save()\n",
    "p2.plotOn(frame, LineStyle=\"--\", LineColor=\"r\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "17f7e8a9",
   "metadata": {},
   "source": [
    "Compare fit results of chi2, L fits to (un)weighted data\n",
    "------------------------------------------------------------"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "97408f8e",
   "metadata": {},
   "source": [
    "Note that ML fit on 1Kevt of weighted data is closer to result of ML fit on 43Kevt of unweighted data\n",
    "than to 1Kevt of unweighted data, the reference chi^2 fit with SumW2 error gives a result closer to\n",
    "that of an unbinned ML fit to 1Kevt of unweighted data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "e45f2a54",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:31:43.947403Z",
     "iopub.status.busy": "2026-05-19T20:31:43.947270Z",
     "iopub.status.idle": "2026-05-19T20:31:44.161615Z",
     "shell.execute_reply": "2026-05-19T20:31:44.160917Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "==> ML Fit results on 1K unweighted events\n",
      "==> ML Fit results on 43K unweighted events\n",
      "==> ML Fit results on 1K weighted events with a summed weight of 43K\n",
      "==> Corrected ML Fit results on 1K weighted events with a summed weight of 43K\n",
      "==> Chi2 Fit results on 1K weighted events with a summed weight of 43K\n",
      "\n",
      "  RooFitResult: minimized FCN value: 2766.49, estimated distance to minimum: 0.000399952\n",
      "                covariance matrix quality: Full, accurate covariance matrix\n",
      "                Status : MINIMIZE=0 HESSE=0 \n",
      "\n",
      "    Floating Parameter    FinalValue +/-  Error   \n",
      "  --------------------  --------------------------\n",
      "                    a1    8.9483e-03 +/-  2.70e-02\n",
      "                    a2    1.0177e-01 +/-  1.69e-02\n",
      "\n",
      "\n",
      "  RooFitResult: minimized FCN value: 118892, estimated distance to minimum: 0.000206627\n",
      "                covariance matrix quality: Full, accurate covariance matrix\n",
      "                Status : MINIMIZE=0 HESSE=0 \n",
      "\n",
      "    Floating Parameter    FinalValue +/-  Error   \n",
      "  --------------------  --------------------------\n",
      "                    a1   -1.2106e-03 +/-  4.02e-03\n",
      "                    a2    9.7573e-02 +/-  2.37e-03\n",
      "\n",
      "\n",
      "  RooFitResult: minimized FCN value: 119682, estimated distance to minimum: 1.25398e-05\n",
      "                covariance matrix quality: Full, accurate covariance matrix\n",
      "                Status : MINIMIZE=0 HESSE=0 \n",
      "\n",
      "    Floating Parameter    FinalValue +/-  Error   \n",
      "  --------------------  --------------------------\n",
      "                    a1   -4.8713e-03 +/-  4.03e-03\n",
      "                    a2    9.8645e-02 +/-  2.41e-03\n",
      "\n",
      "\n",
      "  RooFitResult: minimized FCN value: 119682, estimated distance to minimum: 79498.5\n",
      "                covariance matrix quality: Full, accurate covariance matrix\n",
      "                Status : MINIMIZE=0 HESSE=0 HESSE=0 \n",
      "\n",
      "    Floating Parameter    FinalValue +/-  Error   \n",
      "  --------------------  --------------------------\n",
      "                    a1   -4.8565e-03 +/-  3.00e-02\n",
      "                    a2    9.8652e-02 +/-  2.99e-02\n",
      "\n",
      "\n",
      "  RooFitResult: minimized FCN value: 31.3747, estimated distance to minimum: 4.135e-08\n",
      "                covariance matrix quality: Full, accurate covariance matrix\n",
      "                Status : MIGRAD=0 HESSE=0 \n",
      "\n",
      "    Floating Parameter    FinalValue +/-  Error   \n",
      "  --------------------  --------------------------\n",
      "                    a1   -9.9890e-03 +/-  2.63e-02\n",
      "                    a2    1.0637e-01 +/-  1.02e-02\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Info in <TCanvas::Print>: png file rf403_weightedevts.png has been created\n"
     ]
    }
   ],
   "source": [
    "print(\"==> ML Fit results on 1K unweighted events\")\n",
    "r_ml_unw10.Print()\n",
    "print(\"==> ML Fit results on 43K unweighted events\")\n",
    "r_ml_unw43.Print()\n",
    "print(\"==> ML Fit results on 1K weighted events with a summed weight of 43K\")\n",
    "r_ml_wgt.Print()\n",
    "print(\"==> Corrected ML Fit results on 1K weighted events with a summed weight of 43K\")\n",
    "r_ml_wgt_corr.Print()\n",
    "print(\"==> Chi2 Fit results on 1K weighted events with a summed weight of 43K\")\n",
    "r_chi2_wgt.Print()\n",
    "\n",
    "c = ROOT.TCanvas(\"rf403_weightedevts\", \"rf403_weightedevts\", 600, 600)\n",
    "ROOT.gPad.SetLeftMargin(0.15)\n",
    "frame.GetYaxis().SetTitleOffset(1.8)\n",
    "frame.Draw()\n",
    "\n",
    "c.SaveAs(\"rf403_weightedevts.png\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d00a2ff1",
   "metadata": {},
   "source": [
    "Draw all canvases "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "39084edb",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:31:44.163724Z",
     "iopub.status.busy": "2026-05-19T20:31:44.163565Z",
     "iopub.status.idle": "2026-05-19T20:31:44.346642Z",
     "shell.execute_reply": "2026-05-19T20:31:44.345906Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "\n",
       "<div id=\"root_plot_1779222704336\" style=\"width: 600px; height: 600px; position: relative\">\n",
       "</div>\n",
       "\n",
       "</div>\n",
       "<script>\n",
       "   function process_root_plot_1779222704336() {\n",
       "      function execCode(Core) {\n",
       "         Core.settings.HandleKeys = false;\n",
       "         \n",
       "Core.unzipJSON(27093,'WkwIHiYA1WkAeAHtfWmTHDeS5V+hpfWHXTMw1t3hODziE0WKI+2SIk2UWuRoe2lJVhaZy6rMmqykRPWY/vvacyAys3jo2FGPdY+1TFUMxxFwAI7nB4Cof1883/90tdosL1eLcfHN3eXmh+X1d6sXTzbLq+vX2/0iLM6/3az/7e3qy3uLkcLi/LP1/ro9PXrxf1cv90hfoNijq/16u+nE/1pvzhZjDIvzw5vGf/9YW59qIEaVqBoW5w/Wm9Xd7cV2txi5k0/2P12sjuR367P960beX19c9MJgFuRcmMirr873D5e7V+vNYqSBU1icf71+9fo0DZ3c7vfby5NyYXH+zfbqZsLT8zW4kLA4f3Z8vNMeUePp9X65RzNmKHODutMoVL6/W16u3mccae/1/FDuZo8ORefk+ZWofjo0eOVn293Zavdk/dc+fCeJD7dnqzaxT3kx3mYdyP/jVE1TQQ+QrmpDtESiZsLq/ZTFyDJk/69QVopIfiaLUUl1SEktFcrV8Jan++2dF9eP1+9WF28WY2QZDO2wCPt0PN1vfz1zMYoMUc3MaoxaDBP57MabE+tQUCAno8wQpWfHV/9C7mK8TQNLkSoSU2IxgSB/e+PtkK5vj687JRdjshwW53++USEVzPWfj1VuJizG2y1hHpv99umbj0+Dj86vZ0PwSLWoFLEcrSpG//j6Z28+Oj397cj92FzP2YvxdhlqyiklY8mmghl4erH98at7d5sYPTslnn575RkuGCfP3x1Svzg83XlxfeNFd15c33jXnRfXx2p3Xlwfa3777hIL+zb7fPzkhD++u1y+W4xzMp5jsjRwMotCJVfM8DevV/vlYoyo8fj1uj/dub5avdx/vdyvt61fX729fLHatedv1i/fvDs+/tQeH2xf9cQH21fHtL+23MfLs8fL9QbIEBbnd3fb6+vXy3V/4YF8vO0we7pkIUKNPq7Wh9uz9fl6dbYYz5cX16uwOP+X3frs3U3ypyN558X13e12d1L+87P1fvkCWLbfvcUL7q/frc5u9Ht+9ePd+nK9X/+wuv4Azx+sr6EuZlXSyeVutxi//0tYbK/2ePg5LM4/f7d6eb0YN28vLsLi/Kume3bnSvH5jyuA8eps9cPeVcM36z34+kTuV28vHy8vVvv9rCAwoF+t3u0/TL335ZPHD+48W4yLP82PYXF+b/v2xcXqs7fn5/OEfr3aL9cbjGYfi6fX67+uvr2e85/dJD3369USgITGPfuE/m69Odv++M32CssxLI70s1O6o/SxwBc+DF1AfpwB5e7rRUeNu8v9/oMJuLPfN/2Nnj39bLX/cbXadP10g/JBvb/bXn6zvVqMPECqnp4t94B/J57NBFbFnUbwz2Hx5uH2h9Wjq+W/vT3IypuvVxiRm4nnX6xfvX6Amey62OV2uX/5eh7WN09eb3/8/IfVZv9kv9y/vT6I55s7b/dbCMih5MPV5u1ny12jIT53XkIADzXOv14tzx5tLn6aa5x/t96/3r7dn8rqLL9fLK+79M0pp6W+f89E+cMMISifTxpC361eOB6sN68+ZQ1BMu5eLK+v+2JBuWZ+nSZcQUgXNEpKof9MPFKgQJN4Kp7iSJ5Lk3qepDSlQx2aci+J9NLL4rmO1YIwh6qT4blqEM4To0EN/WdiHtkkcJXARSaWseTg/08cRyYJ/WdiHVlK6D8Tp5FTDP1n4jxyqaH/TFxGIQ39Z+I6iljoPxPbKCqh/0xCXpgN9WkSvknKyBYDGwfOdZI4cs2BK8g4ibZ2cwqcaJI0co3ICZzSJOCqM6k0SRk5pcAqgSNNUkeOyTtY8yQ2cklBKIOTKdLIUYI3neMUeeRYwEHgTFOUkSMFTjXgxTG2dmptdTFU0tpJcYppZC7B62uaYh6ZFBw4y7GMTBa8QpQp1pFFfVyFbIp2HPWUJqWRCwXvrvGkPGKKneeYJpVRhIOPD0gMVW1MRppURx9izJropGn0MQUbbJPmEa8xDZYnLa0ZDJSWSevoLbKzOamNrCV4J1imRM6Ei9iUeGTNwWV2SuLj0Ik4Wp2fdSw6P6cx8fycRynzcxnj/Fgh2P01NlJQCHCaMo0Ucm3PWDrG7VlGdMqX1ZSxgjhay8EignR49QSilkZktMGtkewrKfZWvHVfpDxlNO+ElKmgfSdIpwIGQHClqYADJ1KeyryGMb8FHHgO1amAAxA1TcUZSClknsq8kmOZytw8x6kYjCIUoqnS2BjEM4/Ju4FnGasPA56xhBu60FQhlT4MINry7a/CMskzgaV7aAQL14cBdbBsfbQDTdaBK1YQ3BCJFUQDLzbAl0XP4ZxBaCNUQDQUg1DRZA3GzN9cvFRhpFd/1oJn82eJgSYmGpk5aHJQYGKXUJWgMjFJAwXD9PLEFMdaArvUIFu9H5xyiCDTKFJDLCHpxJRHThQKFqhNTICM7GU541VYnhJiDCIgMSQhY1R5YsfWhDUkEzNgjEPkIKDERxVglG1iYCue8SNpYoArZhMDj/dyahw3eWagK3EwC0w0MZcRAIf+cJ0Y6Aq5yxYYiG4jV0PDPLHQyArM0sAZ+A4ca+NWQcro1aiEahNLHCV6OzQxoLUmqIWAZc7AVo7BoUxQOPtSF66NZ6DriQoQ4tEYS9J4EkwJILH9TELAphj6zySYE0Z//GcSSg1vAeuTYFJqdAigSaiMWJuFQ8Gb6yjRGltcJiEbUQtgnSbBlEAKUHkS5rFwaJUnYXFc7rUnwaSgPVSehBU1W+VJOKFmqzwJ5gOIzgW1J+HSuJ0brYfOeavm/M7NQt0BjhrTk/iUgNvWLqak9ZVrnMSnxDsrUScRPfTWW8ak9N6CaQGKH0dVytzfVrkeOozKcV7DwDbSKc7LGMIEvYWV3LV4o9ti9nySKWI9z/lOn9gETrdVjfKJp4iF3Ys7WQ8WhJPAtmZuJJ6UjoYRTUrNJkB1UHKoCepop4BSqBNolEkJo9HQC/1TX8yO/d4fxWIGDW2c4qQQHZJD/5Sp0cgnmRTGEliEBnVa0FbvnnJ0itT5Z+cDRdEbdiWHyk7NUE+TskN96xcD6lEF6VA0qECTCvRM65L0KWk246Qwh3qXoNIUi7Z3ybsM+ehdavlAEvEut3xYH71LGAKpc5dacZv75KUjgUQDXjiyk23WJo2z0vOq0bVem+9JoyveQ0XXvId6GA6ftClBJLuM4C3J+DDVjT5OPThKdpz8lq+tP62PU4JItnac5WQZLLdZm5KVmfJ3ed9bB6dk3nVQJFMmTIFrxSlTs9JRJxP67JM2ZUKPfdKmTM1ah8UAKWwrzFnMgK+2wjpdvct92qYMnYL8Nm1TdghzCWxNQgqbBHqXMlSLr7D2Oo7+OnQRDEKzuBD2wm085m7xqfuQu9UO1EPNtjp656BVII1tOMQFAbM2ZYjk3D/UA2L1/kFKMiCrrbBOd8Xfpz87ZrX++VC7le4rrNNNvTUByWJz99A2rPTWO6fa+uwl49GJyrENCiySDOsca8yf23C0ZxcNPJYZCBvbU+lA2Id9KpC6zmLiqUDoOonK6dBfzzxOP7pXunnjLEylGzhoyQu33rXMOmOgo0MFBvZxTTxVakjgkzLVDoIOEpUOc46czk7DntqlsfM71VkaHWkqZLHLnrdxGGzYmA2RWxNdCFEYBaFKO6ygpCNhf+URCJHT4ah1t0KPzoBMMlXo0Sb2XrgeKG/jgEUwcl0A0TyIrh3a6EwVKnTGdbwWIAlpa2BcgZGdROVuCXeWujT2UZhql8a5pbZWQYEl+Iy9IRjbHbsaUxDG3jcsiwqXsQ8RlkWNbZCa3Ez1CJDgOLq+AE+tbEftrqhrnP2DVviI2d6QuyhzVT31Uao6YuM9/l51xG6Lb6rqnlKXE50BG/3UIzvgTo/stNcc2EHH9MBOKzyzgxelmRsn+gg1FT1VuIt9Xrwj6SBG/t4Ejjo61+Y19gGdamoc9QGfagJHnotQSHKOjiQ46vhY3Yfs+qDmptDatE21+ZFt0qbqjmQHztocycbtVHNT700UpppPlCzad3fy+NY2PnOv3aM8VG0u5ZxXeihkZqh07TezVJpgz4NSmmA3xK6lCfbc0dKMocMoFHg2s4ddSxPseSDgaLZMSFRtgt3UX61t2uaitc1aUxq1+pw1LVGr20CdHXicLlttcuFzdsz0Mapt6c9ttKV/aMOXfm/Cuu7xah2p5xHoQN3b78aBq6naQboTDRTn2ewYfZjPjtHzaw4KyAW6Y7S/yDpEd+KI0Bg3O4FoSLABpLsuJpmsw3RrxTpO957YjNN9qq3jdBtM6zbDTDWLoc+0daDumT265jIFpuBuYODbz2QAS8hx+5lMfAabDjXRMUW41RxR1cVc4RqXySSPidwDVzj9ZVSDo86Kl9ZRa4DjqXkysVFzSBRY62SRRgV8Bk48WeRRNTgzOlmUUWNweCqTxTiqBLjfGZEEHZUCIm5ZJotpjBaSIRY2WcxjrCG3EKHFMsYS4CIXtFDHmAIc4IIWDGGTnAOXPJnSGGPIJXCxyZTHKPDm4Rubyhjd5eOaJtM4igX4wrVMpjpK9SCBIayRELYqCdHCyRBJy6GUwIYWCiIExQIbWoCzGiokmSdTG0VCbXadeRwtuOtXJgM4WqgJManJAI011ByE42QJ0YNQaxBOkyUdOQdD9KpOltwhRCBMeDLgYgomncKS9/CE4J2w7xByaZS7zZYblWFXBSudgsgEg5+PUA1iBohFCNtkOYJiBC6cdGZcap1MLTf23NzIFriwXBqJTtbJckW3mNBLkAjIBoQmnCwIfQaESoXLZIWdRDjMSYR8AkJCjfQRYpZOIkocEL1ACNyAjDWwxxpAIrrQ4oVOlkaiXeTCmQ+MKAdGG8gIEmykySo5iUiBk9xIsIFcxK496NHI2EiwoZMhIIdcdB8kArKBBd0HmRsJNkCWRoKNOBkAEoXBBkhzMoKNOJk1rhB7YpkMTlRF9LGTbawQb2KeDCiJ6DTYANlmMIINkG0GI9hADM4FiiPYAOkS5dFVJ12kWCHfNhlceg04dQCSCUE70BD4ChrBKADGTCOqHlgRjvD8ODIi0DkIFZRHBBMR6ZlOja4zjbBMYDVExFG+OJ3AjtPQKoCdIJSQ7+FUTuAHNNNoXRU7yU76NgZyZUQwvcVKmDg6CV48V50EKxG5aURIB5w4mUFmMIKIIwJ4iCfOZHUSbHiujYjmYVQQYhTyuh4dBMloCHBmGFMRMIntD8OQuanr4VY2DBlsXek0+gRrFzFIoBPY9iBep8Gom7ttm8PAC0JG4Bz45cw08XeMRPNwwAzbNoEr2o+wWDqN9uGEYWvJdyVAI8LYYooV/ETEYjsNfiKcwxYXRXySou8IeJy0RXILgJcRnq0YjVgBy9i4AYIzAd7RPmjwA4BH+w3vmQDxaB802gfIo31oALSvEcqixTExHqpQJY0GP5qgaBh4XtC+ZqghrhhztK8FSqrR3n6FCmu7VRgPNSi4RmM8EkH9+fZbBj+JoRw9LJrRfhIo0kaj/W4T+x4X5iPpmFAfCh3twy4ugSscB7Sf8ggd6bS3V8YMfpDv7dURsuM0+p9sxBYX4r4eKs+ECGKj0V7mETFr5Cvay75h2Gi0l+OIscEOnaK9rCO2Fp1GezmNaMtptJezB7qdRv9yGT1qDzvC26sjNv9Aezg+22jY/QON9gphV6nRGF+oBQLDwDs0CMUAB8cT0KLbzBgiR0Qk6Ag10hLQJtQDFk013yZkgoJAlBUJ4q0CWNAsErxZbAugWSR4s9i3wxol32xjgqIQbC0iATMLVQHR9QQ0C2XhO44oAdmCuoAwYucTcX6CwoA0ogSjWagMiN8xATF57FqiBMYfagMC5glgDIpDOx/YLSCoDoiYlwBjUB6wzjwBAzTH4DwBnHoQro8Hg1OPh/TxcKR3JYIxxY4FWHc10sfUsRyKxCUPJcApVAlgyRPAKZRJwxlsNSIBBkGfWyT4JpAjQQ0MmPVtICxtT8Cuy7wT5Am+Q4N9h/kd2EqBTvGNiBqAp9gNcmkGjb0V33pA12oAoPqGEAaiFmyUsm8I+QZ6CQBY7AixQd5KAMBiT4gN3SoBAIttIcY+DmjfJUIYBwzNdItUOQ2GfRsCXYKJBxqeC/jJvmODrSHsWqI8ABh7Q9gSdhr8YXPIhblik5GxO4RNFvQHgIsNInHZrqGCP8RSgPjYzkX7iO51UQfg+hYREN4oAHCxS+R7zqDRPqJ7QHzjUDBeiKf4QuAAwMUukQDhQXv72GGETEsA4DLie0B40BgfBFV8mcQAwGUoGGxtWQxtI01G8VWjAYDLrmAg8BoAuAwF44sIRj/oNEqE/MMlAJ1H7GE6jfahYHxJ5QDAZSgYRXsZG7PMsZ1dwJwCcFlpFF9gJQBwGVvyQHDQaB978r7eagAAM/wIX241AIAZnoS6dxAS2ocv4avPAgCY4U24geIuJjP8CY8zUEgYD3gUTksAIDN8CqdjULQPr8LpFADInOCjwrTIAYDMCVFSN8ACAJkTorewRCwo+EnYs4XhyL61ygn8gY4BAM3YsndaAwCaE/hDfg4AaE7gD3TBZjZzAn+gLUTwk8EfvBUKwGvO4A+0BMA1Z/AHWkMEPxn8gU4BYM0Z/IEuIWI8chs/yBA2KTmDPwoC0xj8ZPAHmgOQmzP4Ax2DOD/gDzS2zbHVCv5A5wDYZoRknIY3BBr8IR+WOGjMrwXIDECcS5tfnHVh8FNSz8caBJ07DYsENPxF1IfVBRryBxqbuzhI9Nnbc5wl+5Mf1Vvcv9gu91EWYXHhp8dSCosfFuP3JhpM4PrlYAJsqcHEgkUKhi3eKMFiDBY1WEzBYg4WgVE1WLRgSsGUg6kE0xhMNZjCecQZEWBbDaYWLFGwxMGSBEsxWNJg2ANPOVgCJtZgyYJlCpY5WJZgOQbLOGiSguUcLANLa7BswQoFKxysSLASgxUNVuCK5mClBCvAYQtWKVjlYFWC1RisarAKJzUHA5Y6flswo2DYgzYJZjEYDrhYCmZwYUswA+77vjriMEBi8kgIYQfCI6OEvRhAMMFsIIAv4cAOAXYJWEsAWIJdTYBWAp6Se8VAUgJ8EqxkAnAS7AQCRBIsYQI4EhCRYB4QsJAAgATUIxizOJ8NSxq/UAPwRn5wCUBGsAgIEEbALYL5SUAsgsgRrE2CsBFQiSBm1A7voAakihCYIWAOJdTwqByMSoKOJ4RfCDYlQcMTrEmCaidEWwg6nRBpIXgkBI1OCK4QVDnBlCTocIKDQFDehBAKwYYkqG6CpU7Q2QQbnHCAgGBBEkxqgqomGJAEHU0wHQm2J8FgJFiB5KrdjQaoZYKxRFDIBLuRoIrJUANmI0ETEwxGwpwjagGjAb9wyAFz3k41Yc4RiIC+xy94/JhzNxQRZWC3ENt5CMy524eMOW8HAzDnfl4KoQFoVfzygxRoA3MOvx/qEb/QBubcDcJ2Igtz7uYgY87hrEN34RdqYM7hhEMfIZCBNjDnbvzBoYZiwS/UwJz7gS238+AeQy3gF2pgzj0YyJhzPx/nJ14Yc+4H3ODGAqjxCzUw537Czr3QdjIMc+7mm5+Qc7vNnUI32NoREsy5m2vunbmd5n4Xl/qXn3/+OfytTnPipPsnT3O2Wxi/cG2mn9jEAe7dBgXnM84t5dbhBe9d/wB5csXj/dsdx4svjNsmH958ebjcvVntTm7StISTV/aEw+WQb1bv9nc2r3AAGwdQQbZMGghj4PkX61ebBaIijT55P7Lvb3HOPfsJ4+W79Yenxu/s93eQjoPbZ+sf1tfr7eZ6MSY/qo+ckxc+WL5Yzbd70J7TrQVFC04/Oj+/XvmtG+BsTzywHZ3v9cs3D1abV7g0RAP50X+cM5+rel+Q8H61/cV80PxQZG4eB5Of/cP00Kfz/6OH//oP08PDBP3OOfxsuTu5M/XZcjcLhR/BxjU0LNOLx0/amri3W/7YLmQ0+tHV/nj5oxH9/kcj+hWQR1f7e+28fbs4h0PwWES+jB5d7TskoBOPrvb3/Z5ZL3p/3e8FfHCCHgU88Wy9x225mf5mu73wA/RIaJdX7m43++3b3XW/tXBn39l5DzHv7PdYxA5Sv4AFfvXnd4AB1gq6364ooZOgcCNicOrzzdnnu922X1PDynbSi2P93n+7edlhAZkgT1AMZJ9C5OIyTC+M/oPshbHuQZ7M94PVq9Xm7PTGDbhrqScIixcdE+e25wuGeMUMC4eCGJ4uimFx/gXuQqyu38PwnvrkavkSdwG87cOlv5M+HG789TTweCh3k5tD0Tl5Lvpe017u/X6fJB6vG32xvoZAnvKDJLyvs5MJ3Z7LzQ230ZmLzqm94HvcoNTD9WZ9+fbyX1e77fGqBzJu3MN0iG+3Xh7vVuer3b88OJZu6ScD1xJOuwlOT1OP/Wyp91bnXyzGRJi0Q8p3i7HcTHna75YdijzrCY+Xp8L3eHlDttD4IenYsid9eP/08fLsRtcxdo+XZ+9daG2JH7nS+nh5BmF/ehyenvLsRgp0Y7+rhAbXL9/0m0qPl1ft4ujTDhqHhGcLbE8uzp+83K1Wm/vLl44+4ASwdjL8ILEOTsQWSafzMdc6WT8oAvK4epAyC1ATq1ZmdwkUXeRB/SINEh0zrHZeHGLgnDbWvpvvO6HkFyDY+7Hfra/urV6uL5cX14dLRQ7J3drx+6CecNI7p9/rnqed9g9y5IknHTzQB1XVjBQYIO2i86HWAQK9TuuOX311Gv2Z34/uNPDZfrnZrHZfo3t4L5aav/Z6MX6Pi0S3buEXyy2G039Lb9WZzrf0FmdQQiigvciR8qTTdKGbxQ95lXpepVtKt/SWeklv+2/06y8Al9XybLWDtvY7Uz5MB+r+en9/FprUhcZvYmEWDzkuSz5qL5cXXhmK439u1xskzobA3eXVKfnN+vJgTpZajas6Ynx5uXy1wosOAH93uTm7WH33en39ZrX7erl51W9mt/TPtu96Wpu9luqcnFzg/PN6e7HezKn94mIrene9e3nxPtr3LNw8BdMnCvApTO7P3109PTV75sRnp4nPPlZyTrxREgUfLt/dW7/yTwdACB/t9q+3d5eXq92yo8/f0F1zTJm/Z/C+ieM67lPuGnADA3QCWCBn7Om5J8P3nmL80AlrV+uxMnGZHv/65XlPkI9eSj5FD7TY6K4t/vBRu//tV3cxGu37Db84cl/wvU+NW/K7sN3RPcd3B56/e57S2bmc5Vqig0Rbi4tx8e3mxXqzWZ3devjg1vl6H269fL3+P4LHW/vtrflC8K2z5X6J9k7moxka/8EZ+f1u8VcvVxdQDO5zfsKr7S7tpz6d0YfmnbtTM2QvxsU7EP/QfjD4f7GGC68u3Sf38Z8e7+A/bUVwL/z8/np33V2aB8v5CV8ZkVmdXa7ura+vLpYnl9iBrweEdrFAbOB4qfzh9uzB8kWnf8E3/23z9NP78+Q3l69v/e//ceu/3aIh3frvf1/zNgC4XNcdTIoe+PiFCMZx5rDs28S1KfRPJyDtP33WPhFv+G2z9tf3Z+3va5L+i0zReyGSk/gJucXz+Wa/W8PY9A5fv738sS9rPM5LHM/zZzT8uWc8XL6DE/hRxdgdRHzto8VNvtruLmfvA4Lbgxzt8xPnT1pzDjk3PlWEeAG+XPRhbPK3f9GifUHi6KHMX5Tw1j5bb+BgfL7bPcI3MMAa6Ec/rHbnF9sfEYTBVw12OwDczX24jA0634eDssHHGnwz7v1vl/zxwe4rrJVfNwK+3m7hkqPwx1Sd7zEdvvDx+vnVu3tdizs4LcYFam9f7ZaXt7bnt1r286uL7f75c1eFJ8oe4vMfUPUY9V9W9cDM9yPgX11t1xt876ops1+YHmq7pLdtKCnctkFSuF39ufpz8efiz9mfsz8nf07+rP6s/hz9Ofqz+LP4M/sz+zP5M+G5/8LeF0gv5RW8rr/G3+gv93a8SW/dGXGenD3n1Jl2/r0r6JV/uuXZrw+BZKlDtSQ55oJTIVLxpZ1qQtWq+ja3xqFUKpkL13bSLg7VjLTU5HtF0dKQWYqJ5VZCyyCUk84JUWkoLElUWX1jLZUhlmjEaNePTcUhldLY8F1B4oE4WSQuqeC0tQ3KUZOwOmMlpqEIq+VUBZukqQq+EaQSq1Tsr2nUIQuZYtMKG3iqdSCLqlpF/QyC0VAsHTmVmAcxKYViTUVx1TsOFf8ltYqtUyk6lMiFzQoVHG3OPBQRSdZY84RcrHDtrAvRkHOpJpoytlVjoSEm40g1WcRnJyp2aUolEgyiBRUZtHcMZx1qGlQpmnE2Ewkp2sAlKSeKhm3YyDpYKcmpFErNQ7IiRj2/Fh5yKSxKEjGvHM0GmVvENqqKDbUIOuW7k5TjkFRzKaXVSJQGNcmYDy8RaxmyFs3kveAqeeDINbZecS02lFoksmryYzuWhmqxS5cfYo1DjSkVlmo4+q1sQ46cjIvlWl2O/wjQP2DX4VNGH6ikg/6addQNzfM5vnL1qwvKl/ZiAwyCIfv509frV69/dy18QOtXK32fJA0mpKxJDXv+SepQiuSIbfFiMajSIFpjUkmKffBYdBDRmGKMsRjEBsBTCylEJ5UQIw2RLLNxjYpjxyUOlTDhSlZwPD3mIRZitqwZ+7gSZbCElVsoZeyxmwyVRYxqMRzP4ZQHpVgKPnCGsx+s6gmakhQ/csB1aJ+oq8oJJ0J0MDZOotlirByqDbnGTDFmbMbHUPJQiBO+PEg51xxSGgpXYEqNnDJOcA1YT6VUjlVKDglr2SzWUqNqxDWUIQrWVEoUo+Bq8BCF2CKTVl+IecDYcMmFc8hp0FpyrhIpZ9wy4YHVSgKqoYVig4lpsoKJYFzvGKSUlJIW4dpOWAwVKOVDg4scZdBoKWHZAGZwTWYoqcaIkweK8wm5DMainKxGwXn5SIOQFYtaOQKD1AaOJZVUJBUcGJI81CyGwxXedak21Kycs1lWnGq3PJCUyIL1KxZiqkPUKJwIM8khVuA8Y8Qs4kSbch5ijJWExU8xaEyDlCgpa9WKK5Tk4GhWVPHBwfYFsWe/aRH8U57/Kc//CPL8/Ce4tB7CWIwfDS48P3zL8PlP7fOFKnGw7HFl2A5h8Xyz3V3+eXmBb7ORk5frzfLis/WmByg9gvx882T96nLpnsTz1eybaZRYByzMFEvCfsnz3fLHg+t2m8Pi+Xa3foUXfuffpnNv6fTI4Imr0m3hfxqC/zQE3X7/uzUE//Dw+cVvdpvvvt398Ml9hyQpnobQr+Q5ghvfv/sL3j/7zo93W3yAeb3duPOM3btThzm7z/tplxm7WL+4X/HrLjN88k+7zNhL/SWXOXeXmWlIOKvlD/gN/xlONDxouNHhdsG/JdzO+DeH2wn/pnBb8a+G2xH/xnBb8K+E24x/OdwG5FHAbw5Ik4ASMaC8BtROAe/KAW8uAe3UgFYtgAc/kBvAoP8i+nUvOJ/Eab6XknggkSpK8FrChwmJipu6FEUrznhLKUOUGDVSygk3FZMNLNE0Jop+cyLFIaaKA7i1wtvPmQaSVGGn+00yLahScKq1RJyAjQx/kS1xLuqHRZMOOVJMKXJsx4t5oCiRLRmO7cLRqrlU1UQ5phIKDNOYLRJlyolDTjpUWPhZUlRKIWUaDJ5cpKqZcXnbhqQpJUpw3HHAn4aktZaasyhO2Kc4WE0lFyXDQeZINtSUhXMxxVleKXXgTCK5ckkIJySEF0qxgs8+445jkgEfl5Za8L1nfHauDLnELIT4g2HQh8KMnSfLMHYj5YFrzDUnFhxFjmoDwVukmHPE58xIB9jTphVfj9agRQYhWPBmGOqQkgyKgEQqyYwlZE0DaUZcIFeciSqJBmaLEWZrMgs1lyFLhv1slnFe3sqQYPQnkdhO7kYbzP1prgmHhMV0KFpyigXxAlyC48FqzVFJFKd2s/KQc+Si5qfDa4wDvPKSFWm4L1qHyGIIP/gHKSWlQWrlzDEr7sJq1SFbNvURjUGK5CFFk1ozF9w9/rWEvxun+qYp9RGI/MCS+mBJ3rSk/mvriIjQ84mOmMluMv5TR/xn6AjjgUqJWa0KvpDwQULSOEimWiWKUoWzjqijUKSkGZefqKYhFapkOfllj1rSkK0IW44JJ/xzqYMWlkwJMUTctoUvLhZFFBdwOAoPlkWi1oIrEZwFQUfONdbq1yMYkYtYopSKCEutMlBKJqASEC8jJptKUqFS8f0MQLNEd+2jlpBSGqxUQdCRVMRhFZqMi6WaTYMSDzUihJsRc00hIlYs7saZ4VKdWB2kqCXLyvjsvCCEkitiLFlxvUc0IeBEJXG2io8DxDIUaCaTlD22IYPFWFjxhX9EpJ3xopWoSMxoBFGYWotDOXOIEWGuYqTKEfeGYrXBkqYsRmA2KIIdUmsSqdC7HlCNiUqRFLOYhBzjQAIlmwtUbyjRhhhLQozLL5BUvIMkMrSO+m0kG4y1ZInQYO3ixgBOY0F4CQqCB6qCeFzJuF+jmYYcSy2GP6qAUI/KUBUqOZIHxmssQzZWVTV1DaEeoM8lpuyfF81piDANYuKIb2uo1YHFoHEUwaKiCK0Ta6qE0fnVhH9o/fDe+vwb64c7T7988uTOw88/7Ur8abc6X4yc/nDV9OICf4PhN+38ffN4+YOfdkTxj+394RLKH7R9B0ekH5ya/yaJGGv0P+nBizEWrdiJoCpVUoHSwqmq2v8iSS45Ey6DzX+SRGQgX6apwkDCy/1vT/S/B/NspiwqZ6oaTQzXVfHaXrDiFNuzmTJL/qdSFH9Iwv/Ox+mpLbD/5QbH9vGKJ6+XZ9sfT06U3d3ucD5zebbGZ/BR+LBJcJiPfl5oj/MbGHAcUPz4zZw5s13LEejz98+kHq7lHC/N9OORD7abVyscwVGM4fGv3bSLNOvN7/yrD+/dJniw3K98V/dj4gLGey+9g97T33047LeOyzxMp8d3D8OCzH4Eup99/s1y3Myny/W+nUNoBwIwlo88eHY8jVNFNXIVLhSNfz78fQz8TQzcXcPBqCcvd+srBNp8RPAnFS7an1TYbFYv98dT2/7XOtqr/Y8a/Pz/AEZPLrg=').then(json => {\n",
       "   const obj = Core.parse(json);\n",
       "   Core.draw('root_plot_1779222704336', obj, '');\n",
       "});\n",
       "\n",
       "      }\n",
       "      const servers = ['/static/', 'https://root.cern/js/7.11.0/', 'https://jsroot.gsi.de/7.11.0/'],\n",
       "            path = 'build/jsroot';\n",
       "      if (typeof JSROOT !== 'undefined')\n",
       "         execCode(JSROOT);\n",
       "      else if (typeof requirejs !== 'undefined') {\n",
       "         servers.forEach((s,i) => { servers[i] = s + path; });\n",
       "         requirejs.config({ paths: { 'jsroot' : servers } })(['jsroot'],  execCode);\n",
       "      } else {\n",
       "         const config = document.getElementById('jupyter-config-data');\n",
       "         if (config)\n",
       "            servers[0] = (JSON.parse(config.innerHTML || '{}')?.baseUrl || '/') + 'static/';\n",
       "         else\n",
       "            servers.shift();\n",
       "         function loadJsroot() {\n",
       "            return !servers.length ? 0 : import(servers.shift() + path + '.js').catch(loadJsroot).then(() => execCode(JSROOT));\n",
       "         }\n",
       "         loadJsroot();\n",
       "      }\n",
       "   }\n",
       "   process_root_plot_1779222704336();\n",
       "</script>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from ROOT import gROOT \n",
    "gROOT.GetListOfCanvases().Draw()"
   ]
  }
 ],
 "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
}
