{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "c9c9b53f",
   "metadata": {},
   "source": [
    "# rf409_NumPyPandasToRooFit\n",
    "Convert between NumPy arrays or Pandas DataFrames and RooDataSets.\n",
    "\n",
    "This tutorials first how to export a RooDataSet to NumPy arrays or a Pandas\n",
    "DataFrame, and then it shows you how to create a RooDataSet from a Pandas\n",
    "DataFrame.\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "**Author:** Jonas Rembser  \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:32 PM.</small></i>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "108357e2",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:03.494013Z",
     "iopub.status.busy": "2026-05-19T20:32:03.493895Z",
     "iopub.status.idle": "2026-05-19T20:32:04.546192Z",
     "shell.execute_reply": "2026-05-19T20:32:04.545470Z"
    }
   },
   "outputs": [],
   "source": [
    "import ROOT\n",
    "\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b44016dd",
   "metadata": {},
   "source": [
    "The number of events that we use for the datasets created in this tutorial."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "3d2ce94d",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:04.548182Z",
     "iopub.status.busy": "2026-05-19T20:32:04.547988Z",
     "iopub.status.idle": "2026-05-19T20:32:04.662430Z",
     "shell.execute_reply": "2026-05-19T20:32:04.661652Z"
    }
   },
   "outputs": [],
   "source": [
    "n_events = 10000"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4ea814f4",
   "metadata": {},
   "source": [
    "Creating a RooDataSet and exporting it to the Python ecosystem\n",
    "--------------------------------------------------------------"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6fb9a04c",
   "metadata": {},
   "source": [
    "Define the observable."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "c66aeb03",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:04.664539Z",
     "iopub.status.busy": "2026-05-19T20:32:04.664406Z",
     "iopub.status.idle": "2026-05-19T20:32:04.818561Z",
     "shell.execute_reply": "2026-05-19T20:32:04.817485Z"
    }
   },
   "outputs": [],
   "source": [
    "x = ROOT.RooRealVar(\"x\", \"x\", -10, 10)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "afa5fe4a",
   "metadata": {},
   "source": [
    "Define a Gaussian model with its parameters."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "21a9a5c5",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:04.820229Z",
     "iopub.status.busy": "2026-05-19T20:32:04.820094Z",
     "iopub.status.idle": "2026-05-19T20:32:04.952372Z",
     "shell.execute_reply": "2026-05-19T20:32:04.951780Z"
    }
   },
   "outputs": [],
   "source": [
    "mean = ROOT.RooRealVar(\"mean\", \"mean of gaussian\", 1, -10, 10)\n",
    "sigma = ROOT.RooRealVar(\"sigma\", \"width of gaussian\", 1, 0.1, 10)\n",
    "gauss = ROOT.RooGaussian(\"gauss\", \"gaussian PDF\", x, mean, sigma)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d58ecdae",
   "metadata": {},
   "source": [
    "Create a RooDataSet."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "dc29a51f",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:04.954483Z",
     "iopub.status.busy": "2026-05-19T20:32:04.954356Z",
     "iopub.status.idle": "2026-05-19T20:32:05.123472Z",
     "shell.execute_reply": "2026-05-19T20:32:05.122342Z"
    }
   },
   "outputs": [],
   "source": [
    "data = gauss.generate(ROOT.RooArgSet(x), 10000)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b7631402",
   "metadata": {},
   "source": [
    "Use RooDataSet.to_numpy() to export dataset to a dictionary of NumPy arrays.\n",
    "Real values will be of type `double`, categorical values of type `int`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "b8a60812",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:05.125157Z",
     "iopub.status.busy": "2026-05-19T20:32:05.125030Z",
     "iopub.status.idle": "2026-05-19T20:32:05.323596Z",
     "shell.execute_reply": "2026-05-19T20:32:05.322330Z"
    }
   },
   "outputs": [],
   "source": [
    "arrays = data.to_numpy()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0410cc3e",
   "metadata": {},
   "source": [
    "We can verify that the mean and standard deviation matches our model specification."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "08566951",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:05.325260Z",
     "iopub.status.busy": "2026-05-19T20:32:05.325134Z",
     "iopub.status.idle": "2026-05-19T20:32:05.429804Z",
     "shell.execute_reply": "2026-05-19T20:32:05.428888Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Mean of numpy array: 1.0066466535473986\n",
      "Standard deviation of numpy array: 0.997349967781135\n"
     ]
    }
   ],
   "source": [
    "print(\"Mean of numpy array:\", np.mean(arrays[\"x\"]))\n",
    "print(\"Standard deviation of numpy array:\", np.std(arrays[\"x\"]))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2bf5edcc",
   "metadata": {},
   "source": [
    "It is also possible to create a Pandas DataFrame directly from the numpy arrays:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "2ed064dd",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:05.431319Z",
     "iopub.status.busy": "2026-05-19T20:32:05.431192Z",
     "iopub.status.idle": "2026-05-19T20:32:05.672970Z",
     "shell.execute_reply": "2026-05-19T20:32:05.671864Z"
    }
   },
   "outputs": [],
   "source": [
    "df = data.to_pandas()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "971d138b",
   "metadata": {},
   "source": [
    "Now you can use the DataFrame e.g. for plotting. You can even combine this\n",
    "with the RooAbsReal.bins PyROOT function, which returns the binning from\n",
    "RooFit as a numpy array!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "a7061c05",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:05.674709Z",
     "iopub.status.busy": "2026-05-19T20:32:05.674496Z",
     "iopub.status.idle": "2026-05-19T20:32:06.202566Z",
     "shell.execute_reply": "2026-05-19T20:32:06.201612Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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EdHkMZ1l7dq1SkpK0o033thsv0cffVSxsbGKiYnRRx99pKefflonTpzQH/7whw6ba0v967/+q77zne8oIiJCe/bsUWZmps6fP6/ly5c32r+kpERBQUEN7kGKiooybr2udurUKa1evVrLli1rtp+p6/f3v/9dtbW1jb7GPv7440aPaeo1afpa6asvQZ01a5buuusuDR06tMl+AwcO1CuvvKLhw4eroqJCy5Yt09ixY1VUVHTN12pHi4+P17p16zRw4ECdP39e2dnZ+n//7//p6NGj6t27d4P+vrx+mzZtUnl5uX784x832ceX1q4x9evgzRq15nXcGn4RUObOnavnn3++2T7Hjx+/5o1cvqQ1NZ89e1bbtm3TG2+8cc3xv37/zLBhw9S3b1+NHz9en3zyiW6++eZvOPtr86a+jIwMd9vw4cMVFBSkn/3sZ1q8eLGx35XRmvX77LPPdO+99+qhhx7StGnTmj22s9cP/yc9PV1Hjx5t9h4NSXI4HB7f5D527FgNHjxYL730khYtWtQBM225iRMnun8/fPhwxcfHKzY2Vm+88YamTp3aqXNra2vXrtXEiRMVExPTZB9fWjtf4xcB5cknn2w24UrSTTfd1KKxoqOjG9yJXP/ujujo6CaPufrGoJqaGl24cKHJY76p1tScl5enPn366J/+6Z+8frz4+Hjpq//Bd8Q/cN9kTePj41VTU6NPP/1UAwcObLA/Ojpa1dXVKi8v9ziLUlpa2m7rdTVv6zt37py+//3va+zYsXr55Ze9fryOXr+mXH/99erWrVuDd0w192cfHR3tVX9TzJw5033DvLf/k7bZbBo5cqROnTrVbvNrK+Hh4br11lubnKuvrt+ZM2e0Y8cOr886+tLa6Wv/rpWWlqpv377u9tLSUo0YMaLRY1rzOm6VNrubxcdc6ybZ0tJSd9tLL71k2e1268qVK42OVX+T7MGDB91t27ZtM+om2bq6OisuLs568sknW3X8Bx98YEmy/vKXv7T53Nraq6++agUGBloXLlxodH/9TbK///3v3W0ff/yxsTfJnj171rrlllusKVOmWDU1Na0aw6T1u/POO62ZM2e6t2tra61vfetbzd4k+4Mf/MCjzeFwGHuTZV1dnZWenm7FxMRYf/3rX1s1Rk1NjTVw4EBr9uzZbT6/tnbx4kXruuuus371q181ut/X1q/ewoULrejoaMvlcnl1nOlr19RNssuWLXO3VVRUtOgmWW9ex62aa5uN5CPOnDljHTp0yMrOzrZ69eplHTp0yDp06JB18eJFy/rqyTV06FArMTHROnz4sLV161brhhtusDIzM91j7Nu3zxo4cKB19uxZd9u9995rjRw50tq3b5/1wQcfWLfccov1yCOPdEqNjdmxY4clyTp+/HiDfWfPnrUGDhxo7du3z7Isyzp16pSVk5NjHTx40Dp9+rT1xz/+0brpppus7373u50w8+bt2bPHWrFihXX48GHrk08+sV599VXrhhtusH70ox+5+1xdn2VZ1s9//nOrf//+1rvvvmsdPHjQcjgclsPh6KQqmnb27Fnr29/+tjV+/Hjr7Nmz1vnz590/X+/jS+v3+uuvW8HBwda6deusY8eOWdOnT7fCw8Pd75x77LHHrLlz57r7//nPf7a6d+9uLVu2zDp+/Li1cOFCy2azWUeOHOnEKpo2Y8YMKywszHr//fc91quqqsrd5+oas7OzrW3btlmffPKJVVhYaE2ZMsUKCQmxioqKOqmKpj355JPW+++/b50+fdr685//bCUkJFjXX3+9VVZWZll+sH7WV//Y9u/f33r66acb7PPFtbt48aL73zpJ1vLly61Dhw5ZZ86csSzLspYsWWKFh4dbf/zjH62PPvrImjRpkhUXF2d9+eWX7jHGjRtnrV692r19rddxW+hyASUtLc2S1ODnvffec/f59NNPrYkTJ1o9evSwrr/+euvJJ5/0SNHvvfeeJck6ffq0u+3zzz+3HnnkEatXr16W3W63fvKTn7hDjwkeeeQRa+zYsY3uO336tMefQXFxsfXd737XioiIsIKDg61vf/vb1pw5c6yKiooOnvW1FRYWWvHx8VZYWJgVEhJiDR482Hruuec8znZdXZ9lWdaXX35p/eIXv7Cuu+46KzQ01HrggQc8/tE3RV5eXqPP16+f/PTF9Vu9erXVv39/KygoyLrzzjutvXv3uvfdc889Vlpamkf/N954w7r11lutoKAg67bbbrPefvvtTph1yzS1Xnl5ee4+V9c4a9Ys959HVFSUdd9991kffvhhJ1XQvIcfftjq27evFRQUZH3rW9+yHn74YevUqVPu/b6+ftZXZ8AlWSdOnGiwzxfXrv7frKt/6uuoq6uz5s+fb0VFRVnBwcHW+PHjG9QeGxtrLVy40KOtuddxWwiw/u8FBQAAYAw+BwUAABiHgAIAAIxDQAEAAMYhoAAAAOMQUAAAgHEIKAAAwDgEFAAAYBwCCgAAMA4BBQAAGIeAAgAAjENAAQAAxvn/osrTMEblRPUAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "try:\n",
    "    import matplotlib.pyplot as plt\n",
    "\n",
    "    df.hist(column=\"x\", bins=x.bins())\n",
    "except Exception:\n",
    "    print(\n",
    "        'Skipping `df.hist(column=\"x\", bins=x.bins())` because matplotlib could not be imported or was not able to display the plot.'\n",
    "    )\n",
    "\n",
    "del data\n",
    "del arrays\n",
    "del df"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fc21a665",
   "metadata": {},
   "source": [
    "Creating a dataset with NumPy and importing it to a RooDataSet\n",
    "--------------------------------------------------------------"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f9a8396d",
   "metadata": {},
   "source": [
    "Now we create some Gaussian toy data with numpy, this time with a different\n",
    "mean."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "f39f6572",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:06.204250Z",
     "iopub.status.busy": "2026-05-19T20:32:06.204067Z",
     "iopub.status.idle": "2026-05-19T20:32:06.307925Z",
     "shell.execute_reply": "2026-05-19T20:32:06.307364Z"
    }
   },
   "outputs": [],
   "source": [
    "x_arr = np.random.normal(-1.0, 1.0, (n_events,))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9ed52a57",
   "metadata": {},
   "source": [
    "Import the data to a RooDataSet, passing a dictionary of arrays and the\n",
    "corresponding RooRealVars just like you would pass to the RooDataSet\n",
    "constructor."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "8eba4a0b",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:06.310166Z",
     "iopub.status.busy": "2026-05-19T20:32:06.310031Z",
     "iopub.status.idle": "2026-05-19T20:32:06.588242Z",
     "shell.execute_reply": "2026-05-19T20:32:06.587082Z"
    }
   },
   "outputs": [],
   "source": [
    "data = ROOT.RooDataSet.from_numpy({\"x\": x_arr}, [x])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9d1dc6c3",
   "metadata": {},
   "source": [
    "Let's fit the Gaussian to the data. The mean is updated accordingly."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "7ce055d3",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:06.589952Z",
     "iopub.status.busy": "2026-05-19T20:32:06.589806Z",
     "iopub.status.idle": "2026-05-19T20:32:06.814850Z",
     "shell.execute_reply": "2026-05-19T20:32:06.813953Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[#1] INFO:Fitting -- RooAbsPdf::fitTo(gauss_over_gauss_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 9.23545 ms\n",
      "[#1] INFO:Fitting -- RooAddition::defaultErrorLevel(nll_gauss_over_gauss_Int[x]_) Summation contains a RooNLLVar, using its error level\n",
      "[#1] INFO:Minimization -- [fitFCN] No discrete parameters, performing continuous minimization only\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "  RooFitResult: minimized FCN value: 14152.2, estimated distance to minimum: 6.36827e-09\n",
      "                covariance matrix quality: Full, accurate covariance matrix\n",
      "                Status : MINIMIZE=0 HESSE=0 \n",
      "\n",
      "    Floating Parameter    FinalValue +/-  Error   \n",
      "  --------------------  --------------------------\n",
      "                  mean   -9.9420e-01 +/-  9.96e-03\n",
      "                 sigma    9.9629e-01 +/-  7.04e-03\n",
      "\n"
     ]
    }
   ],
   "source": [
    "fit_result = gauss.fitTo(data, PrintLevel=-1, Save=True)\n",
    "fit_result.Print()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d0c54a54",
   "metadata": {},
   "source": [
    "We can now plot the model and the dataset with RooFit."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "2e854545",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:06.816397Z",
     "iopub.status.busy": "2026-05-19T20:32:06.816268Z",
     "iopub.status.idle": "2026-05-19T20:32:06.993996Z",
     "shell.execute_reply": "2026-05-19T20:32:06.992915Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<cppyy.gbl.RooPlot object at 0x55dce7a41d30>"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "xframe = x.frame(Title=\"Gaussian pdf\")\n",
    "data.plotOn(xframe)\n",
    "gauss.plotOn(xframe)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dc42add4",
   "metadata": {},
   "source": [
    "Draw RooFit plot on a canvas."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "065f4e09",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:06.995654Z",
     "iopub.status.busy": "2026-05-19T20:32:06.995504Z",
     "iopub.status.idle": "2026-05-19T20:32:07.199113Z",
     "shell.execute_reply": "2026-05-19T20:32:07.198413Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Info in <TCanvas::Print>: png file rf409_NumPyPandasToRooFit.png has been created\n"
     ]
    }
   ],
   "source": [
    "c = ROOT.TCanvas(\"rf409_NumPyPandasToRooFit\", \"rf409_NumPyPandasToRooFit\", 800, 400)\n",
    "xframe.Draw()\n",
    "c.SaveAs(\"rf409_NumPyPandasToRooFit.png\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6cd2cb83",
   "metadata": {},
   "source": [
    "Exporting a RooDataHist to NumPy arrays for histogram counts and bin edges\n",
    "--------------------------------------------------------------------------"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "2b4cb99d",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:07.201078Z",
     "iopub.status.busy": "2026-05-19T20:32:07.200950Z",
     "iopub.status.idle": "2026-05-19T20:32:07.304593Z",
     "shell.execute_reply": "2026-05-19T20:32:07.304018Z"
    }
   },
   "outputs": [],
   "source": [
    "def print_histogram_output(histogram_output):\n",
    "    counts, bin_edges = histogram_output\n",
    "    print(np.array(counts, dtype=int))\n",
    "    print(bin_edges[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a99b86e3",
   "metadata": {},
   "source": [
    "Create a binned clone of the dataset to show RooDataHist to NumPy export."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "54bb28ce",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:07.306538Z",
     "iopub.status.busy": "2026-05-19T20:32:07.306414Z",
     "iopub.status.idle": "2026-05-19T20:32:07.420041Z",
     "shell.execute_reply": "2026-05-19T20:32:07.419479Z"
    }
   },
   "outputs": [],
   "source": [
    "datahist = data.binnedClone()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0ed8fb93",
   "metadata": {},
   "source": [
    "You can also export a RooDataHist to numpy arrays with\n",
    "RooDataHist.to_numpy(). As output, you will get a multidimensional array with\n",
    "the histogram counts and a list of arrays with bin edges. This is comparable\n",
    "to the output of numpy.histogram (or numpy.histogramdd for the\n",
    "multidimensional case)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "dd0483fb",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:07.422102Z",
     "iopub.status.busy": "2026-05-19T20:32:07.421967Z",
     "iopub.status.idle": "2026-05-19T20:32:07.602415Z",
     "shell.execute_reply": "2026-05-19T20:32:07.601801Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Counts and bin edges from RooDataHist.to_numpy:\n",
      "[  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0\n",
      "   0   0   0   0   0   0   0   0   0   2   1   8  13  19  39  60  83 131\n",
      " 187 248 331 453 506 633 668 789 791 785 797 710 637 532 458 362 229 180\n",
      " 115  84  49  46  19  12  10   7   4   1   0   0   0   1   0   0   0   0\n",
      "   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0\n",
      "   0   0   0   0   0   0   0   0   0   0]\n",
      "[-1.00000000e+01 -9.80000000e+00 -9.60000000e+00 -9.40000000e+00\n",
      " -9.20000000e+00 -9.00000000e+00 -8.80000000e+00 -8.60000000e+00\n",
      " -8.40000000e+00 -8.20000000e+00 -8.00000000e+00 -7.80000000e+00\n",
      " -7.60000000e+00 -7.40000000e+00 -7.20000000e+00 -7.00000000e+00\n",
      " -6.80000000e+00 -6.60000000e+00 -6.40000000e+00 -6.20000000e+00\n",
      " -6.00000000e+00 -5.80000000e+00 -5.60000000e+00 -5.40000000e+00\n",
      " -5.20000000e+00 -5.00000000e+00 -4.80000000e+00 -4.60000000e+00\n",
      " -4.40000000e+00 -4.20000000e+00 -4.00000000e+00 -3.80000000e+00\n",
      " -3.60000000e+00 -3.40000000e+00 -3.20000000e+00 -3.00000000e+00\n",
      " -2.80000000e+00 -2.60000000e+00 -2.40000000e+00 -2.20000000e+00\n",
      " -2.00000000e+00 -1.80000000e+00 -1.60000000e+00 -1.40000000e+00\n",
      " -1.20000000e+00 -1.00000000e+00 -8.00000000e-01 -6.00000000e-01\n",
      " -4.00000000e-01 -2.00000000e-01  5.55111512e-16  2.00000000e-01\n",
      "  4.00000000e-01  6.00000000e-01  8.00000000e-01  1.00000000e+00\n",
      "  1.20000000e+00  1.40000000e+00  1.60000000e+00  1.80000000e+00\n",
      "  2.00000000e+00  2.20000000e+00  2.40000000e+00  2.60000000e+00\n",
      "  2.80000000e+00  3.00000000e+00  3.20000000e+00  3.40000000e+00\n",
      "  3.60000000e+00  3.80000000e+00  4.00000000e+00  4.20000000e+00\n",
      "  4.40000000e+00  4.60000000e+00  4.80000000e+00  5.00000000e+00\n",
      "  5.20000000e+00  5.40000000e+00  5.60000000e+00  5.80000000e+00\n",
      "  6.00000000e+00  6.20000000e+00  6.40000000e+00  6.60000000e+00\n",
      "  6.80000000e+00  7.00000000e+00  7.20000000e+00  7.40000000e+00\n",
      "  7.60000000e+00  7.80000000e+00  8.00000000e+00  8.20000000e+00\n",
      "  8.40000000e+00  8.60000000e+00  8.80000000e+00  9.00000000e+00\n",
      "  9.20000000e+00  9.40000000e+00  9.60000000e+00  9.80000000e+00\n",
      "  1.00000000e+01]\n"
     ]
    }
   ],
   "source": [
    "counts, bin_edges = datahist.to_numpy()\n",
    "\n",
    "print(\"Counts and bin edges from RooDataHist.to_numpy:\")\n",
    "print_histogram_output((counts, bin_edges))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "369509b7",
   "metadata": {},
   "source": [
    "Let's compare the output to the counts and bin edges we get with\n",
    "numpy.histogramdd when we pass it the original samples:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "4f588165",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:07.603978Z",
     "iopub.status.busy": "2026-05-19T20:32:07.603851Z",
     "iopub.status.idle": "2026-05-19T20:32:07.709040Z",
     "shell.execute_reply": "2026-05-19T20:32:07.708448Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Counts and bin edges from np.histogram:\n",
      "[  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0\n",
      "   0   0   0   0   0   0   0   0   0   2   1   8  13  19  39  60  83 131\n",
      " 187 248 331 453 506 633 668 789 791 785 797 710 637 532 458 362 229 180\n",
      " 115  84  49  46  19  12  10   7   4   1   0   0   0   1   0   0   0   0\n",
      "   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0\n",
      "   0   0   0   0   0   0   0   0   0   0]\n",
      "[-1.00000000e+01 -9.80000000e+00 -9.60000000e+00 -9.40000000e+00\n",
      " -9.20000000e+00 -9.00000000e+00 -8.80000000e+00 -8.60000000e+00\n",
      " -8.40000000e+00 -8.20000000e+00 -8.00000000e+00 -7.80000000e+00\n",
      " -7.60000000e+00 -7.40000000e+00 -7.20000000e+00 -7.00000000e+00\n",
      " -6.80000000e+00 -6.60000000e+00 -6.40000000e+00 -6.20000000e+00\n",
      " -6.00000000e+00 -5.80000000e+00 -5.60000000e+00 -5.40000000e+00\n",
      " -5.20000000e+00 -5.00000000e+00 -4.80000000e+00 -4.60000000e+00\n",
      " -4.40000000e+00 -4.20000000e+00 -4.00000000e+00 -3.80000000e+00\n",
      " -3.60000000e+00 -3.40000000e+00 -3.20000000e+00 -3.00000000e+00\n",
      " -2.80000000e+00 -2.60000000e+00 -2.40000000e+00 -2.20000000e+00\n",
      " -2.00000000e+00 -1.80000000e+00 -1.60000000e+00 -1.40000000e+00\n",
      " -1.20000000e+00 -1.00000000e+00 -8.00000000e-01 -6.00000000e-01\n",
      " -4.00000000e-01 -2.00000000e-01  5.55111512e-16  2.00000000e-01\n",
      "  4.00000000e-01  6.00000000e-01  8.00000000e-01  1.00000000e+00\n",
      "  1.20000000e+00  1.40000000e+00  1.60000000e+00  1.80000000e+00\n",
      "  2.00000000e+00  2.20000000e+00  2.40000000e+00  2.60000000e+00\n",
      "  2.80000000e+00  3.00000000e+00  3.20000000e+00  3.40000000e+00\n",
      "  3.60000000e+00  3.80000000e+00  4.00000000e+00  4.20000000e+00\n",
      "  4.40000000e+00  4.60000000e+00  4.80000000e+00  5.00000000e+00\n",
      "  5.20000000e+00  5.40000000e+00  5.60000000e+00  5.80000000e+00\n",
      "  6.00000000e+00  6.20000000e+00  6.40000000e+00  6.60000000e+00\n",
      "  6.80000000e+00  7.00000000e+00  7.20000000e+00  7.40000000e+00\n",
      "  7.60000000e+00  7.80000000e+00  8.00000000e+00  8.20000000e+00\n",
      "  8.40000000e+00  8.60000000e+00  8.80000000e+00  9.00000000e+00\n",
      "  9.20000000e+00  9.40000000e+00  9.60000000e+00  9.80000000e+00\n",
      "  1.00000000e+01]\n"
     ]
    }
   ],
   "source": [
    "print(\"Counts and bin edges from np.histogram:\")\n",
    "print_histogram_output(np.histogramdd([x_arr], bins=[x.bins()]))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f135ad79",
   "metadata": {},
   "source": [
    "The array values should be the same!"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ebad92f9",
   "metadata": {},
   "source": [
    "Importing a RooDataHist from NumPy arrays with histogram counts and bin edges\n",
    "-----------------------------------------------------------------------------"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c8b0590a",
   "metadata": {},
   "source": [
    "There is also a `RooDataHist.from_numpy` function, again with an interface\n",
    "inspired by `numpy.histogramdd`. You need to pass at least the histogram\n",
    "counts and the list of variables. The binning is optional: the default\n",
    "binning of the RooRealVars is used if not explicitly specified."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "d8e533e6",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:07.710845Z",
     "iopub.status.busy": "2026-05-19T20:32:07.710719Z",
     "iopub.status.idle": "2026-05-19T20:32:07.842690Z",
     "shell.execute_reply": "2026-05-19T20:32:07.842091Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "RooDataHist imported with default binning and exported back to numpy:\n",
      "[  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0\n",
      "   0   0   0   0   0   0   0   0   0   2   1   8  13  19  39  60  83 131\n",
      " 187 248 331 453 506 633 668 789 791 785 797 710 637 532 458 362 229 180\n",
      " 115  84  49  46  19  12  10   7   4   1   0   0   0   1   0   0   0   0\n",
      "   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0\n",
      "   0   0   0   0   0   0   0   0   0   0]\n",
      "[-1.00000000e+01 -9.80000000e+00 -9.60000000e+00 -9.40000000e+00\n",
      " -9.20000000e+00 -9.00000000e+00 -8.80000000e+00 -8.60000000e+00\n",
      " -8.40000000e+00 -8.20000000e+00 -8.00000000e+00 -7.80000000e+00\n",
      " -7.60000000e+00 -7.40000000e+00 -7.20000000e+00 -7.00000000e+00\n",
      " -6.80000000e+00 -6.60000000e+00 -6.40000000e+00 -6.20000000e+00\n",
      " -6.00000000e+00 -5.80000000e+00 -5.60000000e+00 -5.40000000e+00\n",
      " -5.20000000e+00 -5.00000000e+00 -4.80000000e+00 -4.60000000e+00\n",
      " -4.40000000e+00 -4.20000000e+00 -4.00000000e+00 -3.80000000e+00\n",
      " -3.60000000e+00 -3.40000000e+00 -3.20000000e+00 -3.00000000e+00\n",
      " -2.80000000e+00 -2.60000000e+00 -2.40000000e+00 -2.20000000e+00\n",
      " -2.00000000e+00 -1.80000000e+00 -1.60000000e+00 -1.40000000e+00\n",
      " -1.20000000e+00 -1.00000000e+00 -8.00000000e-01 -6.00000000e-01\n",
      " -4.00000000e-01 -2.00000000e-01  5.55111512e-16  2.00000000e-01\n",
      "  4.00000000e-01  6.00000000e-01  8.00000000e-01  1.00000000e+00\n",
      "  1.20000000e+00  1.40000000e+00  1.60000000e+00  1.80000000e+00\n",
      "  2.00000000e+00  2.20000000e+00  2.40000000e+00  2.60000000e+00\n",
      "  2.80000000e+00  3.00000000e+00  3.20000000e+00  3.40000000e+00\n",
      "  3.60000000e+00  3.80000000e+00  4.00000000e+00  4.20000000e+00\n",
      "  4.40000000e+00  4.60000000e+00  4.80000000e+00  5.00000000e+00\n",
      "  5.20000000e+00  5.40000000e+00  5.60000000e+00  5.80000000e+00\n",
      "  6.00000000e+00  6.20000000e+00  6.40000000e+00  6.60000000e+00\n",
      "  6.80000000e+00  7.00000000e+00  7.20000000e+00  7.40000000e+00\n",
      "  7.60000000e+00  7.80000000e+00  8.00000000e+00  8.20000000e+00\n",
      "  8.40000000e+00  8.60000000e+00  8.80000000e+00  9.00000000e+00\n",
      "  9.20000000e+00  9.40000000e+00  9.60000000e+00  9.80000000e+00\n",
      "  1.00000000e+01]\n"
     ]
    }
   ],
   "source": [
    "datahist_new_1 = ROOT.RooDataHist.from_numpy(counts, [x])\n",
    "\n",
    "print(\"RooDataHist imported with default binning and exported back to numpy:\")\n",
    "print_histogram_output(datahist_new_1.to_numpy())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c403edf4",
   "metadata": {},
   "source": [
    "It's also possible to pass custom bin edges to `RooDataHist.from_numpy`, just\n",
    "like you pass them to `numpy.histogramdd` when you get the counts to fill the\n",
    "RooDataHist with:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "cea4277d",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:07.844550Z",
     "iopub.status.busy": "2026-05-19T20:32:07.844422Z",
     "iopub.status.idle": "2026-05-19T20:32:07.956290Z",
     "shell.execute_reply": "2026-05-19T20:32:07.955709Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "RooDataHist imported with linspace binning and exported back to numpy:\n",
      "[   0    0    0    0    0   11  214 1350 3387 3461 1344  210   22    1\n",
      "    0    0    0    0    0    0]\n",
      "[-10.  -9.  -8.  -7.  -6.  -5.  -4.  -3.  -2.  -1.   0.   1.   2.   3.\n",
      "   4.   5.   6.   7.   8.   9.  10.]\n"
     ]
    }
   ],
   "source": [
    "bins = [np.linspace(-10, 10, 21)]\n",
    "counts, _ = np.histogramdd([x_arr], bins=bins)\n",
    "datahist_new_2 = ROOT.RooDataHist.from_numpy(counts, [x], bins=bins)\n",
    "\n",
    "print(\"RooDataHist imported with linspace binning and exported back to numpy:\")\n",
    "print_histogram_output(datahist_new_2.to_numpy())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0fad7c94",
   "metadata": {},
   "source": [
    "Alternatively, you can specify only the number of bins and the range if your\n",
    "binning is uniform. This is preferred over passing the full list of bin\n",
    "edges, because RooFit will know that the binning is uniform and do some\n",
    "optimizations."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "02185a8a",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:07.958276Z",
     "iopub.status.busy": "2026-05-19T20:32:07.958104Z",
     "iopub.status.idle": "2026-05-19T20:32:08.069179Z",
     "shell.execute_reply": "2026-05-19T20:32:08.068622Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "RooDataHist imported with uniform binning and exported back to numpy:\n",
      "[   0    0    0    0    0   11  214 1350 3387 3461 1344  210   22    1\n",
      "    0    0    0    0    0    0]\n",
      "[-10.  -9.  -8.  -7.  -6.  -5.  -4.  -3.  -2.  -1.   0.   1.   2.   3.\n",
      "   4.   5.   6.   7.   8.   9.  10.]\n"
     ]
    }
   ],
   "source": [
    "bins = [20]\n",
    "ranges = [(-10, 10)]\n",
    "counts, _ = np.histogramdd([x_arr], bins=bins, range=ranges)\n",
    "datahist_new_3 = ROOT.RooDataHist.from_numpy(counts, [x], bins=bins, ranges=ranges)\n",
    "\n",
    "print(\"RooDataHist imported with uniform binning and exported back to numpy:\")\n",
    "print_histogram_output(datahist_new_3.to_numpy())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4ee224a2",
   "metadata": {},
   "source": [
    "Draw all canvases "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "fea71dbd",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:08.071017Z",
     "iopub.status.busy": "2026-05-19T20:32:08.070889Z",
     "iopub.status.idle": "2026-05-19T20:32:08.264004Z",
     "shell.execute_reply": "2026-05-19T20:32:08.263418Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "\n",
       "<div id=\"root_plot_1779222728254\" style=\"width: 800px; height: 400px; position: relative\">\n",
       "</div>\n",
       "\n",
       "</div>\n",
       "<script>\n",
       "   function process_root_plot_1779222728254() {\n",
       "      function execCode(Core) {\n",
       "         Core.settings.HandleKeys = false;\n",
       "         \n",
       "Core.unzipJSON(27255,'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').then(json => {\n",
       "   const obj = Core.parse(json);\n",
       "   Core.draw('root_plot_1779222728254', 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_1779222728254();\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
}
