{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "8862214f",
   "metadata": {},
   "source": [
    "# rf618_mixture_models\n",
    "Use of mixture models in RooFit.\n",
    "\n",
    "This tutorial shows, how to use mixture models for Likelihood Calculation in ROOT. Instead of directly\n",
    "calculating the likelihood we use simulation based inference (SBI) as shown in tutorial 'rf615_simulation_based_inference.py'.\n",
    "We train the classifier to discriminate between samples from an background hypothesis here the zz samples and a target\n",
    "hypothesis, here the higgs samples. The data preparation is based on the tutorial 'df106_HiggsToFourLeptons.py'.\n",
    "\n",
    "An introduction to mixture models can be found here https://arxiv.org/pdf/1506.02169.\n",
    "\n",
    "A short summary:\n",
    "We assume the whole probability distribution can be written as a mixture of several components, i.e.\n",
    "$$p(x|\\theta)= \\sum_{c}w_{c}(\\theta)p_{c}(x|\\theta)$$\n",
    "We can write the likelihood ratio in terms of pairwise classification problems\n",
    " \\frac{p(x|\\mu)}{p(x|0)}&= \\frac{\\sum_{c}w_{c}(\\mu)p_{c}(x|\\mu)}{\\sum_{c'}w_{c'}(0)p_{c'}(x|0)}\\\\\n",
    " &=\\sum_{c}\\Bigg[\\sum_{c'}\\frac{w_{c'}(0)}{w_{c}(\\mu)}\\frac{p_{c'}(x|0)}{p_{c}(x|\\mu)}\\Bigg]^{-1},\n",
    "where mu is the signal strength, and a value of 0 corresponds to the background hypothesis. Using this decomposition, one is able to use the pairwise likelihood ratios.\n",
    "\n",
    "Since the only free parameter in our case is mu, the distributions are independent of this parameter and the dependence on the signal strength can be encoded into the weights.\n",
    "Thus, the subratios simplify dramatically since they are independent of theta and these ratios can be pre-computed and the classifier does\n",
    "not need to be parametrized.\n",
    "\n",
    "If you wish to see an analysis done with template histograms see 'hf001_example.py'.\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "**Author:** Robin Syring  \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:34 PM.</small></i>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "1ffb7a1a",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:34:03.133332Z",
     "iopub.status.busy": "2026-05-19T20:34:03.133212Z",
     "iopub.status.idle": "2026-05-19T20:34:04.953044Z",
     "shell.execute_reply": "2026-05-19T20:34:04.952095Z"
    }
   },
   "outputs": [],
   "source": [
    "import ROOT\n",
    "import os\n",
    "import numpy as np\n",
    "import xgboost as xgb"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "892e479a",
   "metadata": {},
   "source": [
    "Get Dataframe from tutorial df106_HiggsToFourLeptons.py\n",
    "Adjust the path if running locally"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "5014b1ee",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:34:04.955388Z",
     "iopub.status.busy": "2026-05-19T20:34:04.955153Z",
     "iopub.status.idle": "2026-05-19T20:34:05.490758Z",
     "shell.execute_reply": "2026-05-19T20:34:05.490288Z"
    }
   },
   "outputs": [],
   "source": [
    "df = ROOT.RDataFrame(\"tree\", ROOT.gROOT.GetTutorialDir().Data() + \"/analysis/dataframe/df106_HiggsToFourLeptons.root\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c1698f37",
   "metadata": {},
   "source": [
    "Initialize a dictionary to store counts and weight sums for each category"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "64846862",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:34:05.499625Z",
     "iopub.status.busy": "2026-05-19T20:34:05.499477Z",
     "iopub.status.idle": "2026-05-19T20:34:05.603013Z",
     "shell.execute_reply": "2026-05-19T20:34:05.602313Z"
    }
   },
   "outputs": [],
   "source": [
    "results = {}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "23da4439",
   "metadata": {},
   "source": [
    "Extract the relevant columns once and avoid repeated calls"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "785aa879",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:34:05.605277Z",
     "iopub.status.busy": "2026-05-19T20:34:05.605148Z",
     "iopub.status.idle": "2026-05-19T20:34:07.899484Z",
     "shell.execute_reply": "2026-05-19T20:34:07.898753Z"
    }
   },
   "outputs": [],
   "source": [
    "data_dict = df.AsNumpy(columns=[\"m4l\", \"sample_category\", \"weight\"])\n",
    "\n",
    "\n",
    "weights_dict = {\n",
    "    name: data_dict[\"weight\"][data_dict[\"sample_category\"] == [name]].sum() for name in (\"data\", \"zz\", \"other\", \"higgs\")\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e0a15209",
   "metadata": {},
   "source": [
    "Loop over each sample category"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "2a8e2dc7",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:34:07.901383Z",
     "iopub.status.busy": "2026-05-19T20:34:07.901248Z",
     "iopub.status.idle": "2026-05-19T20:34:08.037147Z",
     "shell.execute_reply": "2026-05-19T20:34:08.036487Z"
    }
   },
   "outputs": [],
   "source": [
    "for sample_category in [\"data\", \"higgs\", \"zz\", \"other\"]:\n",
    "\n",
    "    weight_sum = weights_dict[sample_category]\n",
    "\n",
    "    mask = data_dict[\"sample_category\"] == sample_category\n",
    "    # Normalize each weight\n",
    "    weights = data_dict[\"weight\"][mask]\n",
    "    # Extract the weight_modified\n",
    "    weight_modified = weights / weight_sum\n",
    "\n",
    "    count = np.sum(mask)\n",
    "\n",
    "    # Store the count and weight sum in the dictionary\n",
    "    results[sample_category] = {\n",
    "        \"weight_sum\": weight_sum,\n",
    "        \"weight_modified\": weight_modified,\n",
    "        \"count\": count,\n",
    "        \"weight\": weights,\n",
    "    }"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "54afbae5",
   "metadata": {},
   "source": [
    "Extract the mass for higgs and zz"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "acef7a45",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:34:08.039247Z",
     "iopub.status.busy": "2026-05-19T20:34:08.039116Z",
     "iopub.status.idle": "2026-05-19T20:34:08.157289Z",
     "shell.execute_reply": "2026-05-19T20:34:08.156588Z"
    }
   },
   "outputs": [],
   "source": [
    "higgs_data = data_dict[\"m4l\"][data_dict[\"sample_category\"] == [\"higgs\"]]\n",
    "zz_data = data_dict[\"m4l\"][data_dict[\"sample_category\"] == [\"zz\"]]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a37bc19b",
   "metadata": {},
   "source": [
    "Prepare sample weights"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "2fbe290b",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:34:08.159454Z",
     "iopub.status.busy": "2026-05-19T20:34:08.159326Z",
     "iopub.status.idle": "2026-05-19T20:34:08.265956Z",
     "shell.execute_reply": "2026-05-19T20:34:08.265291Z"
    }
   },
   "outputs": [],
   "source": [
    "sample_weight_higgs = np.array([results[\"higgs\"][\"weight_modified\"]]).flatten()\n",
    "sample_weight_zz = np.array([results[\"zz\"][\"weight_modified\"]]).flatten()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d8ff7945",
   "metadata": {},
   "source": [
    "Putting sample weights together in the same manner as the training data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "7ab346e3",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:34:08.268118Z",
     "iopub.status.busy": "2026-05-19T20:34:08.267988Z",
     "iopub.status.idle": "2026-05-19T20:34:08.372692Z",
     "shell.execute_reply": "2026-05-19T20:34:08.372019Z"
    }
   },
   "outputs": [],
   "source": [
    "sample_weight = np.concatenate([sample_weight_higgs, sample_weight_zz])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "af966f85",
   "metadata": {},
   "source": [
    "For Training purposes we have to get rid of the negative weights, since xgb can't handle them"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "7cecbc5b",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:34:08.374783Z",
     "iopub.status.busy": "2026-05-19T20:34:08.374650Z",
     "iopub.status.idle": "2026-05-19T20:34:08.479196Z",
     "shell.execute_reply": "2026-05-19T20:34:08.478611Z"
    }
   },
   "outputs": [],
   "source": [
    "sample_weight[sample_weight < 0] = 1e-6"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9319657e",
   "metadata": {},
   "source": [
    "Prepare the features and labels"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "c5e13121",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:34:08.481403Z",
     "iopub.status.busy": "2026-05-19T20:34:08.481271Z",
     "iopub.status.idle": "2026-05-19T20:34:08.587087Z",
     "shell.execute_reply": "2026-05-19T20:34:08.586354Z"
    }
   },
   "outputs": [],
   "source": [
    "X = np.concatenate((higgs_data, zz_data), axis=0).reshape(-1, 1)\n",
    "y = np.concatenate([np.ones(len(higgs_data)), np.zeros(len(zz_data))])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4b81053e",
   "metadata": {},
   "source": [
    "Train the Classifier to discriminate between higgs and zz"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "320726f5",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:34:08.588972Z",
     "iopub.status.busy": "2026-05-19T20:34:08.588840Z",
     "iopub.status.idle": "2026-05-19T20:34:20.067030Z",
     "shell.execute_reply": "2026-05-19T20:34:20.066185Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>#sk-container-id-1 {\n",
       "  /* Definition of color scheme common for light and dark mode */\n",
       "  --sklearn-color-text: #000;\n",
       "  --sklearn-color-text-muted: #666;\n",
       "  --sklearn-color-line: gray;\n",
       "  /* Definition of color scheme for unfitted estimators */\n",
       "  --sklearn-color-unfitted-level-0: #fff5e6;\n",
       "  --sklearn-color-unfitted-level-1: #f6e4d2;\n",
       "  --sklearn-color-unfitted-level-2: #ffe0b3;\n",
       "  --sklearn-color-unfitted-level-3: chocolate;\n",
       "  /* Definition of color scheme for fitted estimators */\n",
       "  --sklearn-color-fitted-level-0: #f0f8ff;\n",
       "  --sklearn-color-fitted-level-1: #d4ebff;\n",
       "  --sklearn-color-fitted-level-2: #b3dbfd;\n",
       "  --sklearn-color-fitted-level-3: cornflowerblue;\n",
       "}\n",
       "\n",
       "#sk-container-id-1.light {\n",
       "  /* Specific color for light theme */\n",
       "  --sklearn-color-text-on-default-background: black;\n",
       "  --sklearn-color-background: white;\n",
       "  --sklearn-color-border-box: black;\n",
       "  --sklearn-color-icon: #696969;\n",
       "}\n",
       "\n",
       "#sk-container-id-1.dark {\n",
       "  --sklearn-color-text-on-default-background: white;\n",
       "  --sklearn-color-background: #111;\n",
       "  --sklearn-color-border-box: white;\n",
       "  --sklearn-color-icon: #878787;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 {\n",
       "  color: var(--sklearn-color-text);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 pre {\n",
       "  padding: 0;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 input.sk-hidden--visually {\n",
       "  border: 0;\n",
       "  clip: rect(1px 1px 1px 1px);\n",
       "  clip: rect(1px, 1px, 1px, 1px);\n",
       "  height: 1px;\n",
       "  margin: -1px;\n",
       "  overflow: hidden;\n",
       "  padding: 0;\n",
       "  position: absolute;\n",
       "  width: 1px;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-dashed-wrapped {\n",
       "  border: 1px dashed var(--sklearn-color-line);\n",
       "  margin: 0 0.4em 0.5em 0.4em;\n",
       "  box-sizing: border-box;\n",
       "  padding-bottom: 0.4em;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-container {\n",
       "  /* jupyter's `normalize.less` sets `[hidden] { display: none; }`\n",
       "     but bootstrap.min.css set `[hidden] { display: none !important; }`\n",
       "     so we also need the `!important` here to be able to override the\n",
       "     default hidden behavior on the sphinx rendered scikit-learn.org.\n",
       "     See: https://github.com/scikit-learn/scikit-learn/issues/21755 */\n",
       "  display: inline-block !important;\n",
       "  position: relative;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-text-repr-fallback {\n",
       "  display: none;\n",
       "}\n",
       "\n",
       "div.sk-parallel-item,\n",
       "div.sk-serial,\n",
       "div.sk-item {\n",
       "  /* draw centered vertical line to link estimators */\n",
       "  background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));\n",
       "  background-size: 2px 100%;\n",
       "  background-repeat: no-repeat;\n",
       "  background-position: center center;\n",
       "}\n",
       "\n",
       "/* Parallel-specific style estimator block */\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item::after {\n",
       "  content: \"\";\n",
       "  width: 100%;\n",
       "  border-bottom: 2px solid var(--sklearn-color-text-on-default-background);\n",
       "  flex-grow: 1;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel {\n",
       "  display: flex;\n",
       "  align-items: stretch;\n",
       "  justify-content: center;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  position: relative;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item {\n",
       "  display: flex;\n",
       "  flex-direction: column;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item:first-child::after {\n",
       "  align-self: flex-end;\n",
       "  width: 50%;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item:last-child::after {\n",
       "  align-self: flex-start;\n",
       "  width: 50%;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item:only-child::after {\n",
       "  width: 0;\n",
       "}\n",
       "\n",
       "/* Serial-specific style estimator block */\n",
       "\n",
       "#sk-container-id-1 div.sk-serial {\n",
       "  display: flex;\n",
       "  flex-direction: column;\n",
       "  align-items: center;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  padding-right: 1em;\n",
       "  padding-left: 1em;\n",
       "}\n",
       "\n",
       "\n",
       "/* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is\n",
       "clickable and can be expanded/collapsed.\n",
       "- Pipeline and ColumnTransformer use this feature and define the default style\n",
       "- Estimators will overwrite some part of the style using the `sk-estimator` class\n",
       "*/\n",
       "\n",
       "/* Pipeline and ColumnTransformer style (default) */\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable {\n",
       "  /* Default theme specific background. It is overwritten whether we have a\n",
       "  specific estimator or a Pipeline/ColumnTransformer */\n",
       "  background-color: var(--sklearn-color-background);\n",
       "}\n",
       "\n",
       "/* Toggleable label */\n",
       "#sk-container-id-1 label.sk-toggleable__label {\n",
       "  cursor: pointer;\n",
       "  display: flex;\n",
       "  width: 100%;\n",
       "  margin-bottom: 0;\n",
       "  padding: 0.5em;\n",
       "  box-sizing: border-box;\n",
       "  text-align: center;\n",
       "  align-items: center;\n",
       "  justify-content: center;\n",
       "  gap: 0.5em;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 label.sk-toggleable__label .caption {\n",
       "  font-size: 0.6rem;\n",
       "  font-weight: lighter;\n",
       "  color: var(--sklearn-color-text-muted);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 label.sk-toggleable__label-arrow:before {\n",
       "  /* Arrow on the left of the label */\n",
       "  content: \"▸\";\n",
       "  float: left;\n",
       "  margin-right: 0.25em;\n",
       "  color: var(--sklearn-color-icon);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 label.sk-toggleable__label-arrow:hover:before {\n",
       "  color: var(--sklearn-color-text);\n",
       "}\n",
       "\n",
       "/* Toggleable content - dropdown */\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content {\n",
       "  display: none;\n",
       "  text-align: left;\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content.fitted {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content pre {\n",
       "  margin: 0.2em;\n",
       "  border-radius: 0.25em;\n",
       "  color: var(--sklearn-color-text);\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content.fitted pre {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 input.sk-toggleable__control:checked~div.sk-toggleable__content {\n",
       "  /* Expand drop-down */\n",
       "  display: block;\n",
       "  width: 100%;\n",
       "  overflow: visible;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {\n",
       "  content: \"▾\";\n",
       "}\n",
       "\n",
       "/* Pipeline/ColumnTransformer-specific style */\n",
       "\n",
       "#sk-container-id-1 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-label.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Estimator-specific style */\n",
       "\n",
       "/* Colorize estimator box */\n",
       "#sk-container-id-1 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-estimator.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-label label.sk-toggleable__label,\n",
       "#sk-container-id-1 div.sk-label label {\n",
       "  /* The background is the default theme color */\n",
       "  color: var(--sklearn-color-text-on-default-background);\n",
       "}\n",
       "\n",
       "/* On hover, darken the color of the background */\n",
       "#sk-container-id-1 div.sk-label:hover label.sk-toggleable__label {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "/* Label box, darken color on hover, fitted */\n",
       "#sk-container-id-1 div.sk-label.fitted:hover label.sk-toggleable__label.fitted {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Estimator label */\n",
       "\n",
       "#sk-container-id-1 div.sk-label label {\n",
       "  font-family: monospace;\n",
       "  font-weight: bold;\n",
       "  line-height: 1.2em;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-label-container {\n",
       "  text-align: center;\n",
       "}\n",
       "\n",
       "/* Estimator-specific */\n",
       "#sk-container-id-1 div.sk-estimator {\n",
       "  font-family: monospace;\n",
       "  border: 1px dotted var(--sklearn-color-border-box);\n",
       "  border-radius: 0.25em;\n",
       "  box-sizing: border-box;\n",
       "  margin-bottom: 0.5em;\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-estimator.fitted {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "/* on hover */\n",
       "#sk-container-id-1 div.sk-estimator:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-estimator.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Specification for estimator info (e.g. \"i\" and \"?\") */\n",
       "\n",
       "/* Common style for \"i\" and \"?\" */\n",
       "\n",
       ".sk-estimator-doc-link,\n",
       "a:link.sk-estimator-doc-link,\n",
       "a:visited.sk-estimator-doc-link {\n",
       "  float: right;\n",
       "  font-size: smaller;\n",
       "  line-height: 1em;\n",
       "  font-family: monospace;\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "  border-radius: 1em;\n",
       "  height: 1em;\n",
       "  width: 1em;\n",
       "  text-decoration: none !important;\n",
       "  margin-left: 0.5em;\n",
       "  text-align: center;\n",
       "  /* unfitted */\n",
       "  border: var(--sklearn-color-unfitted-level-3) 1pt solid;\n",
       "  color: var(--sklearn-color-unfitted-level-3);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link.fitted,\n",
       "a:link.sk-estimator-doc-link.fitted,\n",
       "a:visited.sk-estimator-doc-link.fitted {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "  border: var(--sklearn-color-fitted-level-3) 1pt solid;\n",
       "  color: var(--sklearn-color-fitted-level-3);\n",
       "}\n",
       "\n",
       "/* On hover */\n",
       "div.sk-estimator:hover .sk-estimator-doc-link:hover,\n",
       ".sk-estimator-doc-link:hover,\n",
       "div.sk-label-container:hover .sk-estimator-doc-link:hover,\n",
       ".sk-estimator-doc-link:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-3);\n",
       "  border: var(--sklearn-color-fitted-level-0) 1pt solid;\n",
       "  color: var(--sklearn-color-unfitted-level-0);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "div.sk-estimator.fitted:hover .sk-estimator-doc-link.fitted:hover,\n",
       ".sk-estimator-doc-link.fitted:hover,\n",
       "div.sk-label-container:hover .sk-estimator-doc-link.fitted:hover,\n",
       ".sk-estimator-doc-link.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-3);\n",
       "  border: var(--sklearn-color-fitted-level-0) 1pt solid;\n",
       "  color: var(--sklearn-color-fitted-level-0);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "/* Span, style for the box shown on hovering the info icon */\n",
       ".sk-estimator-doc-link span {\n",
       "  display: none;\n",
       "  z-index: 9999;\n",
       "  position: relative;\n",
       "  font-weight: normal;\n",
       "  right: .2ex;\n",
       "  padding: .5ex;\n",
       "  margin: .5ex;\n",
       "  width: min-content;\n",
       "  min-width: 20ex;\n",
       "  max-width: 50ex;\n",
       "  color: var(--sklearn-color-text);\n",
       "  box-shadow: 2pt 2pt 4pt #999;\n",
       "  /* unfitted */\n",
       "  background: var(--sklearn-color-unfitted-level-0);\n",
       "  border: .5pt solid var(--sklearn-color-unfitted-level-3);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link.fitted span {\n",
       "  /* fitted */\n",
       "  background: var(--sklearn-color-fitted-level-0);\n",
       "  border: var(--sklearn-color-fitted-level-3);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link:hover span {\n",
       "  display: block;\n",
       "}\n",
       "\n",
       "/* \"?\"-specific style due to the `<a>` HTML tag */\n",
       "\n",
       "#sk-container-id-1 a.estimator_doc_link {\n",
       "  float: right;\n",
       "  font-size: 1rem;\n",
       "  line-height: 1em;\n",
       "  font-family: monospace;\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "  border-radius: 1rem;\n",
       "  height: 1rem;\n",
       "  width: 1rem;\n",
       "  text-decoration: none;\n",
       "  /* unfitted */\n",
       "  color: var(--sklearn-color-unfitted-level-1);\n",
       "  border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 a.estimator_doc_link.fitted {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "  border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-fitted-level-1);\n",
       "}\n",
       "\n",
       "/* On hover */\n",
       "#sk-container-id-1 a.estimator_doc_link:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 a.estimator_doc_link.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-3);\n",
       "}\n",
       "\n",
       ".estimator-table {\n",
       "    font-family: monospace;\n",
       "}\n",
       "\n",
       ".estimator-table summary {\n",
       "    padding: .5rem;\n",
       "    cursor: pointer;\n",
       "}\n",
       "\n",
       ".estimator-table summary::marker {\n",
       "    font-size: 0.7rem;\n",
       "}\n",
       "\n",
       ".estimator-table details[open] {\n",
       "    padding-left: 0.1rem;\n",
       "    padding-right: 0.1rem;\n",
       "    padding-bottom: 0.3rem;\n",
       "}\n",
       "\n",
       ".estimator-table .parameters-table {\n",
       "    margin-left: auto !important;\n",
       "    margin-right: auto !important;\n",
       "    margin-top: 0;\n",
       "}\n",
       "\n",
       ".estimator-table .parameters-table tr:nth-child(odd) {\n",
       "    background-color: #fff;\n",
       "}\n",
       "\n",
       ".estimator-table .parameters-table tr:nth-child(even) {\n",
       "    background-color: #f6f6f6;\n",
       "}\n",
       "\n",
       ".estimator-table .parameters-table tr:hover {\n",
       "    background-color: #e0e0e0;\n",
       "}\n",
       "\n",
       ".estimator-table table td {\n",
       "    border: 1px solid rgba(106, 105, 104, 0.232);\n",
       "}\n",
       "\n",
       "/*\n",
       "    `table td`is set in notebook with right text-align.\n",
       "    We need to overwrite it.\n",
       "*/\n",
       ".estimator-table table td.param {\n",
       "    text-align: left;\n",
       "    position: relative;\n",
       "    padding: 0;\n",
       "}\n",
       "\n",
       ".user-set td {\n",
       "    color:rgb(255, 94, 0);\n",
       "    text-align: left !important;\n",
       "}\n",
       "\n",
       ".user-set td.value {\n",
       "    color:rgb(255, 94, 0);\n",
       "    background-color: transparent;\n",
       "}\n",
       "\n",
       ".default td {\n",
       "    color: black;\n",
       "    text-align: left !important;\n",
       "}\n",
       "\n",
       ".user-set td i,\n",
       ".default td i {\n",
       "    color: black;\n",
       "}\n",
       "\n",
       "/*\n",
       "    Styles for parameter documentation links\n",
       "    We need styling for visited so jupyter doesn't overwrite it\n",
       "*/\n",
       "a.param-doc-link,\n",
       "a.param-doc-link:link,\n",
       "a.param-doc-link:visited {\n",
       "    text-decoration: underline dashed;\n",
       "    text-underline-offset: .3em;\n",
       "    color: inherit;\n",
       "    display: block;\n",
       "    padding: .5em;\n",
       "}\n",
       "\n",
       "/* \"hack\" to make the entire area of the cell containing the link clickable */\n",
       "a.param-doc-link::before {\n",
       "    position: absolute;\n",
       "    content: \"\";\n",
       "    inset: 0;\n",
       "}\n",
       "\n",
       ".param-doc-description {\n",
       "    display: none;\n",
       "    position: absolute;\n",
       "    z-index: 9999;\n",
       "    left: 0;\n",
       "    padding: .5ex;\n",
       "    margin-left: 1.5em;\n",
       "    color: var(--sklearn-color-text);\n",
       "    box-shadow: .3em .3em .4em #999;\n",
       "    width: max-content;\n",
       "    text-align: left;\n",
       "    max-height: 10em;\n",
       "    overflow-y: auto;\n",
       "\n",
       "    /* unfitted */\n",
       "    background: var(--sklearn-color-unfitted-level-0);\n",
       "    border: thin solid var(--sklearn-color-unfitted-level-3);\n",
       "}\n",
       "\n",
       "/* Fitted state for parameter tooltips */\n",
       ".fitted .param-doc-description {\n",
       "    /* fitted */\n",
       "    background: var(--sklearn-color-fitted-level-0);\n",
       "    border: thin solid var(--sklearn-color-fitted-level-3);\n",
       "}\n",
       "\n",
       ".param-doc-link:hover .param-doc-description {\n",
       "    display: block;\n",
       "}\n",
       "\n",
       ".copy-paste-icon {\n",
       "    background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIj48IS0tIUZvbnQgQXdlc29tZSBGcmVlIDYuNy4yIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlL2ZyZWUgQ29weXJpZ2h0IDIwMjUgRm9udGljb25zLCBJbmMuLS0+PHBhdGggZD0iTTIwOCAwTDMzMi4xIDBjMTIuNyAwIDI0LjkgNS4xIDMzLjkgMTQuMWw2Ny45IDY3LjljOSA5IDE0LjEgMjEuMiAxNC4xIDMzLjlMNDQ4IDMzNmMwIDI2LjUtMjEuNSA0OC00OCA0OGwtMTkyIDBjLTI2LjUgMC00OC0yMS41LTQ4LTQ4bDAtMjg4YzAtMjYuNSAyMS41LTQ4IDQ4LTQ4ek00OCAxMjhsODAgMCAwIDY0LTY0IDAgMCAyNTYgMTkyIDAgMC0zMiA2NCAwIDAgNDhjMCAyNi41LTIxLjUgNDgtNDggNDhMNDggNTEyYy0yNi41IDAtNDgtMjEuNS00OC00OEwwIDE3NmMwLTI2LjUgMjEuNS00OCA0OC00OHoiLz48L3N2Zz4=);\n",
       "    background-repeat: no-repeat;\n",
       "    background-size: 14px 14px;\n",
       "    background-position: 0;\n",
       "    display: inline-block;\n",
       "    width: 14px;\n",
       "    height: 14px;\n",
       "    cursor: pointer;\n",
       "}\n",
       "</style><body><div id=\"sk-container-id-1\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>XGBClassifier(base_score=None, booster=None, callbacks=None,\n",
       "              colsample_bylevel=None, colsample_bynode=None,\n",
       "              colsample_bytree=None, device=None, early_stopping_rounds=None,\n",
       "              enable_categorical=False, eta=0.2, eval_metric=None,\n",
       "              feature_types=None, feature_weights=None, gamma=None,\n",
       "              grow_policy=None, importance_type=None,\n",
       "              interaction_constraints=None, learning_rate=None, max_bin=None,\n",
       "              max_cat_threshold=None, max_cat_to_onehot=None,\n",
       "              max_delta_step=None, max_depth=5, max_leaves=None,\n",
       "              min_child_weight=1e-06, missing=nan, monotone_constraints=None,\n",
       "              multi_strategy=None, n_estimators=1000, n_jobs=None, ...)</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-1\" type=\"checkbox\" checked><label for=\"sk-estimator-id-1\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow\"><div><div>XGBClassifier</div></div><div><a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier\">?<span>Documentation for XGBClassifier</span></a><span class=\"sk-estimator-doc-link fitted\">i<span>Fitted</span></span></div></label><div class=\"sk-toggleable__content fitted\" data-param-prefix=\"\">\n",
       "        <div class=\"estimator-table\">\n",
       "            <details>\n",
       "                <summary>Parameters</summary>\n",
       "                <table class=\"parameters-table\">\n",
       "                  <tbody>\n",
       "                    \n",
       "        <tr class=\"default\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('objective',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=objective,-typing.Union%5Bstr%2C%20xgboost.sklearn._SklObjWProto%2C%20typing.Callable%5B%5Btyping.Any%2C%20typing.Any%5D%2C%20typing.Tuple%5Bnumpy.ndarray%2C%20numpy.ndarray%5D%5D%2C%20NoneType%5D\">\n",
       "            objective\n",
       "            <span class=\"param-doc-description\">objective: typing.Union[str, xgboost.sklearn._SklObjWProto, typing.Callable[[typing.Any, typing.Any], typing.Tuple[numpy.ndarray, numpy.ndarray]], NoneType]<br><br>Specify the learning task and the corresponding learning objective or a custom<br>objective function to be used.<br><br>For custom objective, see :doc:`/tutorials/custom_metric_obj` and<br>:ref:`custom-obj-metric` for more information, along with the end note for<br>function signatures.</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">&#x27;binary:logistic&#x27;</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('base_score',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=base_score,-typing.Union%5Bfloat%2C%20typing.List%5Bfloat%5D%2C%20NoneType%5D\">\n",
       "            base_score\n",
       "            <span class=\"param-doc-description\">base_score: typing.Union[float, typing.List[float], NoneType]<br><br>The initial prediction score of all instances, global bias.</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('booster',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">booster</td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('callbacks',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=callbacks,-typing.Optional%5Btyping.List%5Bxgboost.callback.TrainingCallback%5D%5D\">\n",
       "            callbacks\n",
       "            <span class=\"param-doc-description\">callbacks: typing.Optional[typing.List[xgboost.callback.TrainingCallback]]<br><br>List of callback functions that are applied at end of each iteration.<br>It is possible to use predefined callbacks by using<br>:ref:`Callback API <callback_api>`.<br><br>.. note::<br><br>   States in callback are not preserved during training, which means callback<br>   objects can not be reused for multiple training sessions without<br>   reinitialization or deepcopy.<br><br>.. code-block:: python<br><br>    for params in parameters_grid:<br>        # be sure to (re)initialize the callbacks before each run<br>        callbacks = [xgb.callback.LearningRateScheduler(custom_rates)]<br>        reg = xgboost.XGBRegressor(**params, callbacks=callbacks)<br>        reg.fit(X, y)</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('colsample_bylevel',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=colsample_bylevel,-typing.Optional%5Bfloat%5D\">\n",
       "            colsample_bylevel\n",
       "            <span class=\"param-doc-description\">colsample_bylevel: typing.Optional[float]<br><br>Subsample ratio of columns for each level.</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('colsample_bynode',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=colsample_bynode,-typing.Optional%5Bfloat%5D\">\n",
       "            colsample_bynode\n",
       "            <span class=\"param-doc-description\">colsample_bynode: typing.Optional[float]<br><br>Subsample ratio of columns for each split.</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('colsample_bytree',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=colsample_bytree,-typing.Optional%5Bfloat%5D\">\n",
       "            colsample_bytree\n",
       "            <span class=\"param-doc-description\">colsample_bytree: typing.Optional[float]<br><br>Subsample ratio of columns when constructing each tree.</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('device',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=device,-typing.Optional%5Bstr%5D\">\n",
       "            device\n",
       "            <span class=\"param-doc-description\">device: typing.Optional[str]<br><br>.. versionadded:: 2.0.0<br><br>Device ordinal, available options are `cpu`, `cuda`, and `gpu`.</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('early_stopping_rounds',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=early_stopping_rounds,-typing.Optional%5Bint%5D\">\n",
       "            early_stopping_rounds\n",
       "            <span class=\"param-doc-description\">early_stopping_rounds: typing.Optional[int]<br><br>.. versionadded:: 1.6.0<br><br>- Activates early stopping. Validation metric needs to improve at least once in<br>  every **early_stopping_rounds** round(s) to continue training.  Requires at<br>  least one item in **eval_set** in :py:meth:`fit`.<br><br>- If early stopping occurs, the model will have two additional attributes:<br>  :py:attr:`best_score` and :py:attr:`best_iteration`. These are used by the<br>  :py:meth:`predict` and :py:meth:`apply` methods to determine the optimal<br>  number of trees during inference. If users want to access the full model<br>  (including trees built after early stopping), they can specify the<br>  `iteration_range` in these inference methods. In addition, other utilities<br>  like model plotting can also use the entire model.<br><br>- If you prefer to discard the trees after `best_iteration`, consider using the<br>  callback function :py:class:`xgboost.callback.EarlyStopping`.<br><br>- If there's more than one item in **eval_set**, the last entry will be used for<br>  early stopping.  If there's more than one metric in **eval_metric**, the last<br>  metric will be used for early stopping.</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('enable_categorical',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=enable_categorical,-bool\">\n",
       "            enable_categorical\n",
       "            <span class=\"param-doc-description\">enable_categorical: bool<br><br>See the same parameter of :py:class:`DMatrix` for details.</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">False</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('eval_metric',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=eval_metric,-typing.Union%5Bstr%2C%20typing.List%5Btyping.Union%5Bstr%2C%20typing.Callable%5D%5D%2C%20typing.Callable%2C%20NoneType%5D\">\n",
       "            eval_metric\n",
       "            <span class=\"param-doc-description\">eval_metric: typing.Union[str, typing.List[typing.Union[str, typing.Callable]], typing.Callable, NoneType]<br><br>.. versionadded:: 1.6.0<br><br>Metric used for monitoring the training result and early stopping.  It can be a<br>string or list of strings as names of predefined metric in XGBoost (See<br>:doc:`/parameter`), one of the metrics in :py:mod:`sklearn.metrics`, or any<br>other user defined metric that looks like `sklearn.metrics`.<br><br>If custom objective is also provided, then custom metric should implement the<br>corresponding reverse link function.<br><br>Unlike the `scoring` parameter commonly used in scikit-learn, when a callable<br>object is provided, it's assumed to be a cost function and by default XGBoost<br>will minimize the result during early stopping.<br><br>For advanced usage on Early stopping like directly choosing to maximize instead<br>of minimize, see :py:obj:`xgboost.callback.EarlyStopping`.<br><br>See :doc:`/tutorials/custom_metric_obj` and :ref:`custom-obj-metric` for more<br>information.<br><br>.. code-block:: python<br><br>    from sklearn.datasets import load_diabetes<br>    from sklearn.metrics import mean_absolute_error<br>    X, y = load_diabetes(return_X_y=True)<br>    reg = xgb.XGBRegressor(<br>        tree_method=\"hist\",<br>        eval_metric=mean_absolute_error,<br>    )<br>    reg.fit(X, y, eval_set=[(X, y)])</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('feature_types',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=feature_types,-typing.Optional%5Btyping.Sequence%5Bstr%5D%5D\">\n",
       "            feature_types\n",
       "            <span class=\"param-doc-description\">feature_types: typing.Optional[typing.Sequence[str]]<br><br>.. versionadded:: 1.7.0<br><br>Used for specifying feature types without constructing a dataframe. See<br>the :py:class:`DMatrix` for details.</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('feature_weights',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=feature_weights,-Optional%5BArrayLike%5D\">\n",
       "            feature_weights\n",
       "            <span class=\"param-doc-description\">feature_weights: Optional[ArrayLike]<br><br>Weight for each feature, defines the probability of each feature being selected<br>when colsample is being used.  All values must be greater than 0, otherwise a<br>`ValueError` is thrown.</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('gamma',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=gamma,-typing.Optional%5Bfloat%5D\">\n",
       "            gamma\n",
       "            <span class=\"param-doc-description\">gamma: typing.Optional[float]<br><br>(min_split_loss) Minimum loss reduction required to make a further partition on<br>a leaf node of the tree.</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('grow_policy',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=grow_policy,-typing.Optional%5Bstr%5D\">\n",
       "            grow_policy\n",
       "            <span class=\"param-doc-description\">grow_policy: typing.Optional[str]<br><br>Tree growing policy.<br><br>- depthwise: Favors splitting at nodes closest to the node,<br>- lossguide: Favors splitting at nodes with highest loss change.</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('importance_type',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">importance_type</td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('interaction_constraints',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=interaction_constraints,-typing.Union%5Bstr%2C%20typing.List%5Btyping.Tuple%5Bstr%5D%5D%2C%20NoneType%5D\">\n",
       "            interaction_constraints\n",
       "            <span class=\"param-doc-description\">interaction_constraints: typing.Union[str, typing.List[typing.Tuple[str]], NoneType]<br><br>Constraints for interaction representing permitted interactions.  The<br>constraints must be specified in the form of a nested list, e.g. ``[[0, 1], [2,<br>3, 4]]``, where each inner list is a group of indices of features that are<br>allowed to interact with each other.  See :doc:`tutorial<br></tutorials/feature_interaction_constraint>` for more information</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('learning_rate',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=learning_rate,-typing.Optional%5Bfloat%5D\">\n",
       "            learning_rate\n",
       "            <span class=\"param-doc-description\">learning_rate: typing.Optional[float]<br><br>Boosting learning rate (xgb's \"eta\")</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('max_bin',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=max_bin,-typing.Optional%5Bint%5D\">\n",
       "            max_bin\n",
       "            <span class=\"param-doc-description\">max_bin: typing.Optional[int]<br><br>If using histogram-based algorithm, maximum number of bins per feature</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('max_cat_threshold',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=max_cat_threshold,-typing.Optional%5Bint%5D\">\n",
       "            max_cat_threshold\n",
       "            <span class=\"param-doc-description\">max_cat_threshold: typing.Optional[int]<br><br>.. versionadded:: 1.7.0<br><br>.. note:: This parameter is experimental<br><br>Maximum number of categories considered for each split. Used only by<br>partition-based splits for preventing over-fitting. Also, `enable_categorical`<br>needs to be set to have categorical feature support. See :doc:`Categorical Data<br></tutorials/categorical>` and :ref:`cat-param` for details.</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('max_cat_to_onehot',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=max_cat_to_onehot,-Optional%5Bint%5D\">\n",
       "            max_cat_to_onehot\n",
       "            <span class=\"param-doc-description\">max_cat_to_onehot: Optional[int]<br><br>.. versionadded:: 1.6.0<br><br>.. note:: This parameter is experimental<br><br>A threshold for deciding whether XGBoost should use one-hot encoding based split<br>for categorical data.  When number of categories is lesser than the threshold<br>then one-hot encoding is chosen, otherwise the categories will be partitioned<br>into children nodes. Also, `enable_categorical` needs to be set to have<br>categorical feature support. See :doc:`Categorical Data<br></tutorials/categorical>` and :ref:`cat-param` for details.</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('max_delta_step',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=max_delta_step,-typing.Optional%5Bfloat%5D\">\n",
       "            max_delta_step\n",
       "            <span class=\"param-doc-description\">max_delta_step: typing.Optional[float]<br><br>Maximum delta step we allow each tree's weight estimation to be.</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('max_depth',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=max_depth,-%20typing.Optional%5Bint%5D\">\n",
       "            max_depth\n",
       "            <span class=\"param-doc-description\">max_depth:  typing.Optional[int]<br><br>Maximum tree depth for base learners.</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">5</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('max_leaves',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=max_leaves,-typing.Optional%5Bint%5D\">\n",
       "            max_leaves\n",
       "            <span class=\"param-doc-description\">max_leaves: typing.Optional[int]<br><br>Maximum number of leaves; 0 indicates no limit.</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('min_child_weight',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=min_child_weight,-typing.Optional%5Bfloat%5D\">\n",
       "            min_child_weight\n",
       "            <span class=\"param-doc-description\">min_child_weight: typing.Optional[float]<br><br>Minimum sum of instance weight(hessian) needed in a child.</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">1e-06</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('missing',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=missing,-float\">\n",
       "            missing\n",
       "            <span class=\"param-doc-description\">missing: float<br><br>Value in the data which needs to be present as a missing value. Default to<br>:py:data:`numpy.nan`.</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">nan</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('monotone_constraints',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=monotone_constraints,-typing.Union%5Btyping.Dict%5Bstr%2C%20int%5D%2C%20str%2C%20NoneType%5D\">\n",
       "            monotone_constraints\n",
       "            <span class=\"param-doc-description\">monotone_constraints: typing.Union[typing.Dict[str, int], str, NoneType]<br><br>Constraint of variable monotonicity.  See :doc:`tutorial </tutorials/monotonic>`<br>for more information.</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('multi_strategy',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=multi_strategy,-typing.Optional%5Bstr%5D\">\n",
       "            multi_strategy\n",
       "            <span class=\"param-doc-description\">multi_strategy: typing.Optional[str]<br><br>.. versionadded:: 2.0.0<br><br>.. note:: This parameter is working-in-progress.<br><br>The strategy used for training multi-target models, including multi-target<br>regression and multi-class classification. See :doc:`/tutorials/multioutput` for<br>more information.<br><br>- ``one_output_per_tree``: One model for each target.<br>- ``multi_output_tree``:  Use multi-target trees.</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('n_estimators',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=n_estimators,-Optional%5Bint%5D\">\n",
       "            n_estimators\n",
       "            <span class=\"param-doc-description\">n_estimators: Optional[int]<br><br>Number of boosting rounds.</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">1000</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('n_jobs',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=n_jobs,-typing.Optional%5Bint%5D\">\n",
       "            n_jobs\n",
       "            <span class=\"param-doc-description\">n_jobs: typing.Optional[int]<br><br>Number of parallel threads used to run xgboost.  When used with other<br>Scikit-Learn algorithms like grid search, you may choose which algorithm to<br>parallelize and balance the threads.  Creating thread contention will<br>significantly slow down both algorithms.</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('num_parallel_tree',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">num_parallel_tree</td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('random_state',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=random_state,-typing.Union%5Bnumpy.random.mtrand.RandomState%2C%20numpy.random._generator.Generator%2C%20int%2C%20NoneType%5D\">\n",
       "            random_state\n",
       "            <span class=\"param-doc-description\">random_state: typing.Union[numpy.random.mtrand.RandomState, numpy.random._generator.Generator, int, NoneType]<br><br>Random number seed.<br><br>.. note::<br><br>   Using gblinear booster with shotgun updater is nondeterministic as<br>   it uses Hogwild algorithm.</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('reg_alpha',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=reg_alpha,-typing.Optional%5Bfloat%5D\">\n",
       "            reg_alpha\n",
       "            <span class=\"param-doc-description\">reg_alpha: typing.Optional[float]<br><br>L1 regularization term on weights (xgb's alpha).</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('reg_lambda',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=reg_lambda,-typing.Optional%5Bfloat%5D\">\n",
       "            reg_lambda\n",
       "            <span class=\"param-doc-description\">reg_lambda: typing.Optional[float]<br><br>L2 regularization term on weights (xgb's lambda).</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('sampling_method',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=sampling_method,-typing.Optional%5Bstr%5D\">\n",
       "            sampling_method\n",
       "            <span class=\"param-doc-description\">sampling_method: typing.Optional[str]<br><br>Sampling method. Used only by the GPU version of ``hist`` tree method.<br><br>- ``uniform``: Select random training instances uniformly.<br>- ``gradient_based``: Select random training instances with higher probability<br>    when the gradient and hessian are larger. (cf. CatBoost)</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('scale_pos_weight',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=scale_pos_weight,-typing.Optional%5Bfloat%5D\">\n",
       "            scale_pos_weight\n",
       "            <span class=\"param-doc-description\">scale_pos_weight: typing.Optional[float]<br><br>Balancing of positive and negative weights.</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('subsample',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=subsample,-typing.Optional%5Bfloat%5D\">\n",
       "            subsample\n",
       "            <span class=\"param-doc-description\">subsample: typing.Optional[float]<br><br>Subsample ratio of the training instance.</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('tree_method',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=tree_method,-typing.Optional%5Bstr%5D\">\n",
       "            tree_method\n",
       "            <span class=\"param-doc-description\">tree_method: typing.Optional[str]<br><br>Specify which tree method to use.  Default to auto.  If this parameter is set to<br>default, XGBoost will choose the most conservative option available.  It's<br>recommended to study this option from the parameters document :doc:`tree method<br></treemethod>`</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('validate_parameters',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=validate_parameters,-typing.Optional%5Bbool%5D\">\n",
       "            validate_parameters\n",
       "            <span class=\"param-doc-description\">validate_parameters: typing.Optional[bool]<br><br>Give warnings for unknown parameter.</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('verbosity',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">\n",
       "        <a class=\"param-doc-link\"\n",
       "            rel=\"noreferrer\" target=\"_blank\" href=\"https://xgboost.readthedocs.io/en/release_3.2.0/python/python_api.html#xgboost.XGBClassifier#:~:text=verbosity,-typing.Optional%5Bint%5D\">\n",
       "            verbosity\n",
       "            <span class=\"param-doc-description\">verbosity: typing.Optional[int]<br><br>The degree of verbosity. Valid values are 0 (silent) - 3 (debug).</span>\n",
       "        </a>\n",
       "    </td>\n",
       "            <td class=\"value\">None</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('eta',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">eta</td>\n",
       "            <td class=\"value\">0.2</td>\n",
       "        </tr>\n",
       "    \n",
       "\n",
       "        <tr class=\"user-set\">\n",
       "            <td><i class=\"copy-paste-icon\"\n",
       "                 onclick=\"copyToClipboard('nthread',\n",
       "                          this.parentElement.nextElementSibling)\"\n",
       "            ></i></td>\n",
       "            <td class=\"param\">nthread</td>\n",
       "            <td class=\"value\">1</td>\n",
       "        </tr>\n",
       "    \n",
       "                  </tbody>\n",
       "                </table>\n",
       "            </details>\n",
       "        </div>\n",
       "    </div></div></div></div></div><script>function copyToClipboard(text, element) {\n",
       "    // Get the parameter prefix from the closest toggleable content\n",
       "    const toggleableContent = element.closest('.sk-toggleable__content');\n",
       "    const paramPrefix = toggleableContent ? toggleableContent.dataset.paramPrefix : '';\n",
       "    const fullParamName = paramPrefix ? `${paramPrefix}${text}` : text;\n",
       "\n",
       "    const originalStyle = element.style;\n",
       "    const computedStyle = window.getComputedStyle(element);\n",
       "    const originalWidth = computedStyle.width;\n",
       "    const originalHTML = element.innerHTML.replace('Copied!', '');\n",
       "\n",
       "    navigator.clipboard.writeText(fullParamName)\n",
       "        .then(() => {\n",
       "            element.style.width = originalWidth;\n",
       "            element.style.color = 'green';\n",
       "            element.innerHTML = \"Copied!\";\n",
       "\n",
       "            setTimeout(() => {\n",
       "                element.innerHTML = originalHTML;\n",
       "                element.style = originalStyle;\n",
       "            }, 2000);\n",
       "        })\n",
       "        .catch(err => {\n",
       "            console.error('Failed to copy:', err);\n",
       "            element.style.color = 'red';\n",
       "            element.innerHTML = \"Failed!\";\n",
       "            setTimeout(() => {\n",
       "                element.innerHTML = originalHTML;\n",
       "                element.style = originalStyle;\n",
       "            }, 2000);\n",
       "        });\n",
       "    return false;\n",
       "}\n",
       "\n",
       "document.querySelectorAll('.copy-paste-icon').forEach(function(element) {\n",
       "    const toggleableContent = element.closest('.sk-toggleable__content');\n",
       "    const paramPrefix = toggleableContent ? toggleableContent.dataset.paramPrefix : '';\n",
       "    const paramName = element.parentElement.nextElementSibling\n",
       "        .textContent.trim().split(' ')[0];\n",
       "    const fullParamName = paramPrefix ? `${paramPrefix}${paramName}` : paramName;\n",
       "\n",
       "    element.setAttribute('title', fullParamName);\n",
       "});\n",
       "\n",
       "\n",
       "/**\n",
       " * Adapted from Skrub\n",
       " * https://github.com/skrub-data/skrub/blob/403466d1d5d4dc76a7ef569b3f8228db59a31dc3/skrub/_reporting/_data/templates/report.js#L789\n",
       " * @returns \"light\" or \"dark\"\n",
       " */\n",
       "function detectTheme(element) {\n",
       "    const body = document.querySelector('body');\n",
       "\n",
       "    // Check VSCode theme\n",
       "    const themeKindAttr = body.getAttribute('data-vscode-theme-kind');\n",
       "    const themeNameAttr = body.getAttribute('data-vscode-theme-name');\n",
       "\n",
       "    if (themeKindAttr && themeNameAttr) {\n",
       "        const themeKind = themeKindAttr.toLowerCase();\n",
       "        const themeName = themeNameAttr.toLowerCase();\n",
       "\n",
       "        if (themeKind.includes(\"dark\") || themeName.includes(\"dark\")) {\n",
       "            return \"dark\";\n",
       "        }\n",
       "        if (themeKind.includes(\"light\") || themeName.includes(\"light\")) {\n",
       "            return \"light\";\n",
       "        }\n",
       "    }\n",
       "\n",
       "    // Check Jupyter theme\n",
       "    if (body.getAttribute('data-jp-theme-light') === 'false') {\n",
       "        return 'dark';\n",
       "    } else if (body.getAttribute('data-jp-theme-light') === 'true') {\n",
       "        return 'light';\n",
       "    }\n",
       "\n",
       "    // Guess based on a parent element's color\n",
       "    const color = window.getComputedStyle(element.parentNode, null).getPropertyValue('color');\n",
       "    const match = color.match(/^rgb\\s*\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*\\)\\s*$/i);\n",
       "    if (match) {\n",
       "        const [r, g, b] = [\n",
       "            parseFloat(match[1]),\n",
       "            parseFloat(match[2]),\n",
       "            parseFloat(match[3])\n",
       "        ];\n",
       "\n",
       "        // https://en.wikipedia.org/wiki/HSL_and_HSV#Lightness\n",
       "        const luma = 0.299 * r + 0.587 * g + 0.114 * b;\n",
       "\n",
       "        if (luma > 180) {\n",
       "            // If the text is very bright we have a dark theme\n",
       "            return 'dark';\n",
       "        }\n",
       "        if (luma < 75) {\n",
       "            // If the text is very dark we have a light theme\n",
       "            return 'light';\n",
       "        }\n",
       "        // Otherwise fall back to the next heuristic.\n",
       "    }\n",
       "\n",
       "    // Fallback to system preference\n",
       "    return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n",
       "}\n",
       "\n",
       "\n",
       "function forceTheme(elementId) {\n",
       "    const estimatorElement = document.querySelector(`#${elementId}`);\n",
       "    if (estimatorElement === null) {\n",
       "        console.error(`Element with id ${elementId} not found.`);\n",
       "    } else {\n",
       "        const theme = detectTheme(estimatorElement);\n",
       "        estimatorElement.classList.add(theme);\n",
       "    }\n",
       "}\n",
       "\n",
       "forceTheme('sk-container-id-1');</script></body>"
      ],
      "text/plain": [
       "XGBClassifier(base_score=None, booster=None, callbacks=None,\n",
       "              colsample_bylevel=None, colsample_bynode=None,\n",
       "              colsample_bytree=None, device=None, early_stopping_rounds=None,\n",
       "              enable_categorical=False, eta=0.2, eval_metric=None,\n",
       "              feature_types=None, feature_weights=None, gamma=None,\n",
       "              grow_policy=None, importance_type=None,\n",
       "              interaction_constraints=None, learning_rate=None, max_bin=None,\n",
       "              max_cat_threshold=None, max_cat_to_onehot=None,\n",
       "              max_delta_step=None, max_depth=5, max_leaves=None,\n",
       "              min_child_weight=1e-06, missing=nan, monotone_constraints=None,\n",
       "              multi_strategy=None, n_estimators=1000, n_jobs=None, ...)"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model_xgb = xgb.XGBClassifier(n_estimators=1000, max_depth=5, eta=0.2, min_child_weight=1e-6, nthread=1)\n",
    "model_xgb.fit(X, y, sample_weight=sample_weight)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b5174a03",
   "metadata": {},
   "source": [
    "Building a RooRealVar based on the observed data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "c4cc5783",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:34:20.068894Z",
     "iopub.status.busy": "2026-05-19T20:34:20.068759Z",
     "iopub.status.idle": "2026-05-19T20:34:20.232756Z",
     "shell.execute_reply": "2026-05-19T20:34:20.232045Z"
    }
   },
   "outputs": [],
   "source": [
    "m4l = ROOT.RooRealVar(\"m4l\", \"Four Lepton Invariant Mass\", 0.0)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c91196fc",
   "metadata": {},
   "source": [
    "Define functions to compute the learned likelihood."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "20443647",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:34:20.234982Z",
     "iopub.status.busy": "2026-05-19T20:34:20.234855Z",
     "iopub.status.idle": "2026-05-19T20:34:20.731967Z",
     "shell.execute_reply": "2026-05-19T20:34:20.731498Z"
    }
   },
   "outputs": [],
   "source": [
    "def calculate_likelihood_xgb(m4l_arr: np.ndarray) -> np.ndarray:\n",
    "    prob = model_xgb.predict_proba(m4l_arr.T)[:, 0]\n",
    "    return (1 - prob) / prob\n",
    "\n",
    "\n",
    "llh = ROOT.RooFit.bindFunction(f\"llh\", calculate_likelihood_xgb, m4l)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "430345cb",
   "metadata": {},
   "source": [
    "Number of signals and background"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "ae2ab961",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:34:20.741465Z",
     "iopub.status.busy": "2026-05-19T20:34:20.741316Z",
     "iopub.status.idle": "2026-05-19T20:34:20.845305Z",
     "shell.execute_reply": "2026-05-19T20:34:20.844710Z"
    }
   },
   "outputs": [],
   "source": [
    "n_signal = results[\"higgs\"][\"weight\"].sum()\n",
    "n_back = results[\"zz\"][\"weight\"].sum()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b50a3771",
   "metadata": {},
   "source": [
    "Define weight functions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "bfccdf9d",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:34:20.847385Z",
     "iopub.status.busy": "2026-05-19T20:34:20.847251Z",
     "iopub.status.idle": "2026-05-19T20:34:20.950799Z",
     "shell.execute_reply": "2026-05-19T20:34:20.950174Z"
    }
   },
   "outputs": [],
   "source": [
    "def weight_back(mu):\n",
    "    return n_back / (n_back + mu * n_signal)\n",
    "\n",
    "\n",
    "def weight_signal(mu):\n",
    "    return 1 - weight_back(mu)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c0814111",
   "metadata": {},
   "source": [
    "Define the likelihood ratio accordingly to mixture models"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "19e3ee59",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:34:20.952741Z",
     "iopub.status.busy": "2026-05-19T20:34:20.952589Z",
     "iopub.status.idle": "2026-05-19T20:34:21.172438Z",
     "shell.execute_reply": "2026-05-19T20:34:21.171833Z"
    }
   },
   "outputs": [],
   "source": [
    "def likelihood_ratio(llr: np.ndarray, mu: np.ndarray) -> np.ndarray:\n",
    "\n",
    "    m = 2\n",
    "\n",
    "    w_0 = np.array([weight_back(0), weight_signal(0)])\n",
    "    w_1 = np.array([weight_back(mu[0]), weight_signal(mu[0])])\n",
    "\n",
    "    w = np.outer(w_1, 1.0 / w_0)\n",
    "\n",
    "    p = np.ones((m, m, len(llr)))\n",
    "    p[1, 0] = llr\n",
    "    for i in range(m):\n",
    "        for j in range(i):\n",
    "            p[j, i] = 1.0 / p[i, j]\n",
    "\n",
    "    return 1.0 / np.sum(1.0 / np.sum(np.expand_dims(w, axis=2) * p, axis=0), axis=0)\n",
    "\n",
    "\n",
    "mu_var = ROOT.RooRealVar(\"mu\", \"mu\", 0.1, 5)\n",
    "\n",
    "nll_ratio = ROOT.RooFit.bindFunction(f\"nll\", likelihood_ratio, llh, mu_var)\n",
    "pdf_learned = ROOT.RooWrapperPdf(\"learned_pdf\", \"learned_pdf\", nll_ratio, selfNormalized=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b1c1c334",
   "metadata": {},
   "source": [
    "Plot the likelihood"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "58c538b6",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:34:21.174708Z",
     "iopub.status.busy": "2026-05-19T20:34:21.174561Z",
     "iopub.status.idle": "2026-05-19T20:34:21.305845Z",
     "shell.execute_reply": "2026-05-19T20:34:21.305196Z"
    }
   },
   "outputs": [],
   "source": [
    "frame1 = m4l.frame(Title=\"Likelihood ratio r(m_{4l}|#mu=1);m_{4l};p(#mu=1)/p(#mu=0)\", Range=(80, 170))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aa7efdc6",
   "metadata": {},
   "source": [
    "llh.plotOn(frame1, ShiftToZero=False, LineColor=\"kP6Blue\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "10f661f9",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:34:21.307571Z",
     "iopub.status.busy": "2026-05-19T20:34:21.307446Z",
     "iopub.status.idle": "2026-05-19T20:34:21.663549Z",
     "shell.execute_reply": "2026-05-19T20:34:21.662953Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_583254/3977165901.py:8: RuntimeWarning: divide by zero encountered in divide\n",
      "  w = np.outer(w_1, 1.0 / w_0)\n"
     ]
    }
   ],
   "source": [
    "nll_ratio.plotOn(frame1, ShiftToZero=False, LineColor=\"kP6Blue\")\n",
    "\n",
    "n_pred = ROOT.RooFormulaVar(\"n_pred\", f\"{n_back} + mu * {n_signal}\", [mu_var])\n",
    "pdf_learned_extended = ROOT.RooExtendPdf(\"final_pdf\", \"final_pdf\", pdf_learned, n_pred)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b2a36cee",
   "metadata": {},
   "source": [
    "Prepare the observed data set and NLL"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "fa0b3e75",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:34:21.665373Z",
     "iopub.status.busy": "2026-05-19T20:34:21.665238Z",
     "iopub.status.idle": "2026-05-19T20:34:21.956195Z",
     "shell.execute_reply": "2026-05-19T20:34:21.955625Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[#1] INFO:Fitting -- RooAbsPdf::fitTo(final_pdf) 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 1.2029 ms\n"
     ]
    }
   ],
   "source": [
    "data = ROOT.RooDataSet.from_numpy({\"m4l\": data_dict[\"m4l\"][data_dict[\"sample_category\"] == [\"data\"]]}, [m4l])\n",
    "nll = pdf_learned_extended.createNLL(data, Extended=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f73025bc",
   "metadata": {},
   "source": [
    "Plot the nll computet by the mixture model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "9d7010d9",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:34:21.958263Z",
     "iopub.status.busy": "2026-05-19T20:34:21.958115Z",
     "iopub.status.idle": "2026-05-19T20:34:22.122073Z",
     "shell.execute_reply": "2026-05-19T20:34:22.121365Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_583254/3977165901.py:8: RuntimeWarning: divide by zero encountered in divide\n",
      "  w = np.outer(w_1, 1.0 / w_0)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<cppyy.gbl.RooPlot object at 0x555d5fcb72c0>"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "frame2 = mu_var.frame(Title=\"NLL sum;#mu (signal strength);#Delta NLL\", Range=(0.5, 4))\n",
    "nll.plotOn(frame2, ShiftToZero=True, LineColor=\"kP6Blue\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cdacfc4d",
   "metadata": {},
   "source": [
    "Write the plots into one canvas to show, or into separate canvases for saving."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "37473efd",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:34:22.124576Z",
     "iopub.status.busy": "2026-05-19T20:34:22.124428Z",
     "iopub.status.idle": "2026-05-19T20:34:22.282238Z",
     "shell.execute_reply": "2026-05-19T20:34:22.281798Z"
    }
   },
   "outputs": [],
   "source": [
    "single_canvas = True\n",
    "\n",
    "c = ROOT.TCanvas(\"\", \"\", 1200 if single_canvas else 600, 600)\n",
    "if single_canvas:\n",
    "    c.Divide(2)\n",
    "    c.cd(1)\n",
    "    ROOT.gPad.SetLeftMargin(0.15)\n",
    "    frame1.GetYaxis().SetTitleOffset(1.8)\n",
    "frame1.Draw()\n",
    "\n",
    "if single_canvas:\n",
    "    c.cd(2)\n",
    "    ROOT.gPad.SetLeftMargin(0.15)\n",
    "    frame2.GetYaxis().SetTitleOffset(1.8)\n",
    "else:\n",
    "    c.SaveAs(\"rf618_plot_1.png\")\n",
    "    c = ROOT.TCanvas(\"\", \"\", 600, 600)\n",
    "\n",
    "frame2.Draw()\n",
    "\n",
    "if not single_canvas:\n",
    "    c.SaveAs(\"rf618_plot_2.png\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1fb82ec6",
   "metadata": {},
   "source": [
    "Compute the minimum via minuit and display the results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "1ce44724",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:34:22.284462Z",
     "iopub.status.busy": "2026-05-19T20:34:22.284326Z",
     "iopub.status.idle": "2026-05-19T20:34:22.547422Z",
     "shell.execute_reply": "2026-05-19T20:34:22.546810Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[#1] INFO:Fitting -- RooAddition::defaultErrorLevel(nll_final_pdf_) Summation contains a RooNLLVar, using its error level\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[#1] INFO:Minimization -- [fitFCN] No discrete parameters, performing continuous minimization only\n",
      "\n",
      "  RooFitResult: minimized FCN value: -1538.33, estimated distance to minimum: 1.0744e-09\n",
      "                covariance matrix quality: Full, accurate covariance matrix\n",
      "                Status : MINIMIZE=0 \n",
      "\n",
      "    Floating Parameter    FinalValue +/-  Error   \n",
      "  --------------------  --------------------------\n",
      "                    mu    1.7049e+00 +/-  5.93e-01\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_583254/3977165901.py:8: RuntimeWarning: divide by zero encountered in divide\n",
      "  w = np.outer(w_1, 1.0 / w_0)\n"
     ]
    }
   ],
   "source": [
    "minimizer = ROOT.RooMinimizer(nll)\n",
    "minimizer.setErrorLevel(0.5)  # Adjust the error level in the minimization to work with likelihoods\n",
    "minimizer.setPrintLevel(-1)\n",
    "minimizer.minimize(\"Minuit2\")\n",
    "result = minimizer.save()\n",
    "ROOT.SetOwnership(result, True)\n",
    "result.Print()\n",
    "\n",
    "del minimizer\n",
    "del nll\n",
    "del pdf_learned_extended\n",
    "del n_pred\n",
    "del llh\n",
    "del nll_ratio"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ea625f9a",
   "metadata": {},
   "source": [
    "Draw all canvases "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "aca3dfdb",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:34:22.549199Z",
     "iopub.status.busy": "2026-05-19T20:34:22.549074Z",
     "iopub.status.idle": "2026-05-19T20:34:22.740403Z",
     "shell.execute_reply": "2026-05-19T20:34:22.739786Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "\n",
       "<div id=\"root_plot_1779222862731\" style=\"width: 1200px; height: 600px; position: relative\">\n",
       "</div>\n",
       "\n",
       "</div>\n",
       "<script>\n",
       "   function process_root_plot_1779222862731() {\n",
       "      function execCode(Core) {\n",
       "         Core.settings.HandleKeys = false;\n",
       "         \n",
       "Core.unzipJSON(34457,'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').then(json => {\n",
       "   const obj = Core.parse(json);\n",
       "   Core.draw('root_plot_1779222862731', 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_1779222862731();\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
}
