{
"cells": [
{
"cell_type": "markdown",
"id": "e91787cf",
"metadata": {},
"source": [
"# rf514_RooCustomizer\n",
"Using the RooCustomizer to create multiple PDFs that share a lot of properties, but have unique parameters for each category.\n",
"As an extra complication, some of the new parameters need to be functions of a mass parameter.\n",
"\n",
"\n",
"\n",
"\n",
"**Author:** Harshal Shende, Stephan Hageboeck (C++ version) \n",
"This notebook tutorial was automatically generated with ROOTBOOK-izer from the macro found in the ROOT repository on Tuesday, March 19, 2024 at 07:16 PM."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "fffd0a4a",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2024-03-19T19:16:41.711300Z",
"iopub.status.busy": "2024-03-19T19:16:41.710950Z",
"iopub.status.idle": "2024-03-19T19:16:44.725755Z",
"shell.execute_reply": "2024-03-19T19:16:44.692710Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The proto model before customisation:\n",
"\n"
]
}
],
"source": [
"import ROOT\n",
"\n",
"E = ROOT.RooRealVar(\"Energy\", \"Energy\", 0, 3000)\n",
"\n",
"meanG = ROOT.RooRealVar(\"meanG\", \"meanG\", 100.0, 0.0, 3000.0)\n",
"sigmaG = ROOT.RooRealVar(\"sigmaG\", \"sigmaG\", 3.0)\n",
"gauss = ROOT.RooGaussian(\"gauss\", \"gauss\", E, meanG, sigmaG)\n",
"\n",
"pol1 = ROOT.RooRealVar(\"pol1\", \"Constant of the polynomial\", 1, -10, 10)\n",
"linear = ROOT.RooPolynomial(\"linear\", \"linear\", E, pol1)\n",
"\n",
"yieldSig = ROOT.RooRealVar(\"yieldSig\", \"yieldSig\", 1, 0, 1.0e4)\n",
"yieldBkg = ROOT.RooRealVar(\"yieldBkg\", \"yieldBkg\", 1, 0, 1.0e4)\n",
"\n",
"model = ROOT.RooAddPdf(\"model\", \"S + B model\", [gauss, linear], [yieldSig, yieldBkg])\n",
"\n",
"print(\"The proto model before customisation:\\n\")\n",
"model.Print(\"T\") # \"T\" prints the model as a tree"
]
},
{
"cell_type": "markdown",
"id": "43874a64",
"metadata": {},
"source": [
"Build the categories"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "c02c133f",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2024-03-19T19:16:44.736905Z",
"iopub.status.busy": "2024-03-19T19:16:44.736522Z",
"iopub.status.idle": "2024-03-19T19:16:45.306789Z",
"shell.execute_reply": "2024-03-19T19:16:45.299939Z"
}
},
"outputs": [],
"source": [
"sample = ROOT.RooCategory(\"sample\", \"sample\", {\"Sample1\": 1, \"Sample2\": 2, \"Sample3\": 3})"
]
},
{
"cell_type": "markdown",
"id": "2296e133",
"metadata": {},
"source": [
"Start to customise the proto model that was defined above.\n",
"---------------------------------------------------------------------------"
]
},
{
"cell_type": "markdown",
"id": "c765d1db",
"metadata": {},
"source": [
"We need two sets for bookkeeping of PDF nodes:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "023093be",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2024-03-19T19:16:45.384886Z",
"iopub.status.busy": "2024-03-19T19:16:45.384491Z",
"iopub.status.idle": "2024-03-19T19:16:45.546533Z",
"shell.execute_reply": "2024-03-19T19:16:45.533976Z"
}
},
"outputs": [],
"source": [
"newLeafs = ROOT.RooArgSet()\n",
"allCustomiserNodes = ROOT.RooArgSet()"
]
},
{
"cell_type": "markdown",
"id": "cf4a39e3",
"metadata": {},
"source": [
"1. Each sample should have its own mean for the gaussian\n",
"The customiser will make copies of `meanG` for each category.\n",
"These will all appear in the set `newLeafs`, which will own the new nodes."
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "283962d0",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2024-03-19T19:16:45.573803Z",
"iopub.status.busy": "2024-03-19T19:16:45.573418Z",
"iopub.status.idle": "2024-03-19T19:16:45.849414Z",
"shell.execute_reply": "2024-03-19T19:16:45.825203Z"
}
},
"outputs": [],
"source": [
"cust = ROOT.RooCustomizer(model, sample, newLeafs, allCustomiserNodes)\n",
"cust.splitArg(meanG, sample)"
]
},
{
"cell_type": "markdown",
"id": "a03c6737",
"metadata": {},
"source": [
"2. Each sample should have its own signal yield, but there is an extra complication:\n",
"We need the yields 1 and 2 to be a function of the variable \"mass\".\n",
"For this, we pre-define nodes with exactly the names that the customiser would have created automatically,\n",
"that is, \"_\", and we register them in the set of customiser nodes.\n",
"The customiser will pick them up instead of creating new ones.\n",
"If we don't provide one (e.g. for \"yieldSig_Sample3\"), it will be created automatically by cloning `yieldSig`."
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "e79f08b2",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2024-03-19T19:16:45.868201Z",
"iopub.status.busy": "2024-03-19T19:16:45.867808Z",
"iopub.status.idle": "2024-03-19T19:16:46.196830Z",
"shell.execute_reply": "2024-03-19T19:16:46.195042Z"
}
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"mass = ROOT.RooRealVar(\"M\", \"M\", 1, 0, 12000)\n",
"yield1 = ROOT.RooFormulaVar(\"yieldSig_Sample1\", \"Signal yield in the first sample\", \"M/3.360779\", mass)\n",
"yield2 = ROOT.RooFormulaVar(\"yieldSig_Sample2\", \"Signal yield in the second sample\", \"M/2\", mass)\n",
"allCustomiserNodes.add(yield1)\n",
"allCustomiserNodes.add(yield2)"
]
},
{
"cell_type": "markdown",
"id": "74c2de47",
"metadata": {},
"source": [
"Instruct the customiser to replace all yieldSig nodes for each sample:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "cf3b64fb",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2024-03-19T19:16:46.204495Z",
"iopub.status.busy": "2024-03-19T19:16:46.203473Z",
"iopub.status.idle": "2024-03-19T19:16:46.335215Z",
"shell.execute_reply": "2024-03-19T19:16:46.333723Z"
}
},
"outputs": [],
"source": [
"cust.splitArg(yieldSig, sample)"
]
},
{
"cell_type": "markdown",
"id": "a7395087",
"metadata": {},
"source": [
"Now we can start building the PDFs for all categories:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "3ade7817",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2024-03-19T19:16:46.349777Z",
"iopub.status.busy": "2024-03-19T19:16:46.349407Z",
"iopub.status.idle": "2024-03-19T19:16:46.482854Z",
"shell.execute_reply": "2024-03-19T19:16:46.481729Z"
}
},
"outputs": [],
"source": [
"pdf1 = cust.build(\"Sample1\")\n",
"pdf2 = cust.build(\"Sample2\")\n",
"pdf3 = cust.build(\"Sample3\")"
]
},
{
"cell_type": "markdown",
"id": "35bad7e2",
"metadata": {},
"source": [
"And we inspect the two PDFs"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "9fff4bae",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2024-03-19T19:16:46.508124Z",
"iopub.status.busy": "2024-03-19T19:16:46.507529Z",
"iopub.status.idle": "2024-03-19T19:16:46.632445Z",
"shell.execute_reply": "2024-03-19T19:16:46.630810Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"PDF 1 with a yield depending on M:\n",
"\n",
"\n",
"PDF 2 with a yield depending on M:\n",
"\n",
"\n",
"PDF 3 with a free yield:\n",
"\n",
"\n",
"The following leafs have been created automatically while customising:\n",
"\n",
"0xa2cdff0 RooAddPdf::model_Sample1 = 1156.8/1 [Auto,Clean] \n",
" 0xa2c38f0/V- RooGaussian::gauss_Sample1 = 0 [Auto,Dirty] \n",
" 0x8b21f60/V- RooRealVar::Energy = 1500\n",
" 0xa277c60/V- RooRealVar::meanG_Sample1 = 100\n",
" 0x870fc00/V- RooRealVar::sigmaG = 3\n",
" 0x7beb690/V- RooFormulaVar::yieldSig_Sample1 = 0.29755 [Auto,Clean] \n",
" 0x9d59c70/V- RooRealVar::M = 1\n",
" 0x8f65710/V- RooPolynomial::linear = 1501 [Auto,Dirty] \n",
" 0x8b21f60/V- RooRealVar::Energy = 1500\n",
" 0x8659910/V- RooRealVar::pol1 = 1\n",
" 0x5ed5430/V- RooRealVar::yieldBkg = 1\n",
"0xa2d6d40 RooAddPdf::model_Sample2 = 1000.67/1 [Auto,Clean] \n",
" 0xa289e00/V- RooGaussian::gauss_Sample2 = 0 [Auto,Dirty] \n",
" 0x8b21f60/V- RooRealVar::Energy = 1500\n",
" 0xa2a6630/V- RooRealVar::meanG_Sample2 = 100\n",
" 0x870fc00/V- RooRealVar::sigmaG = 3\n",
" 0xa214470/V- RooFormulaVar::yieldSig_Sample2 = 0.5 [Auto,Clean] \n",
" 0x9d59c70/V- RooRealVar::M = 1\n",
" 0x8f65710/V- RooPolynomial::linear = 1501 [Auto,Dirty] \n",
" 0x8b21f60/V- RooRealVar::Energy = 1500\n",
" 0x8659910/V- RooRealVar::pol1 = 1\n",
" 0x5ed5430/V- RooRealVar::yieldBkg = 1\n",
"0xa1a0140 RooAddPdf::model_Sample3 = 750.5/1 [Auto,Clean] \n",
" 0xa250e80/V- RooGaussian::gauss_Sample3 = 0 [Auto,Dirty] \n",
" 0x8b21f60/V- RooRealVar::Energy = 1500\n",
" 0xa1bc130/V- RooRealVar::meanG_Sample3 = 100\n",
" 0x870fc00/V- RooRealVar::sigmaG = 3\n",
" 0xa286780/V- RooRealVar::yieldSig_Sample3 = 1\n",
" 0x8f65710/V- RooPolynomial::linear = 1501 [Auto,Dirty] \n",
" 0x8b21f60/V- RooRealVar::Energy = 1500\n",
" 0x8659910/V- RooRealVar::pol1 = 1\n",
" 0x5ed5430/V- RooRealVar::yieldBkg = 1\n",
" 1) RooRealVar:: meanG_Sample1 = 100\n",
" 2) RooRealVar:: meanG_Sample2 = 100\n",
" 3) RooRealVar:: meanG_Sample3 = 100\n",
" 4) RooRealVar:: yieldSig_Sample3 = 1\n"
]
}
],
"source": [
"print(\"\\nPDF 1 with a yield depending on M:\\n\")\n",
"pdf1.Print(\"T\")\n",
"print(\"\\nPDF 2 with a yield depending on M:\\n\")\n",
"pdf2.Print(\"T\")\n",
"print(\"\\nPDF 3 with a free yield:\\n\")\n",
"pdf3.Print(\"T\")\n",
"\n",
"print(\"\\nThe following leafs have been created automatically while customising:\\n\")\n",
"newLeafs.Print(\"V\")"
]
},
{
"cell_type": "markdown",
"id": "186a4ff5",
"metadata": {},
"source": [
" If we needed to set reasonable values for the means of the gaussians, this could be done as follows:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "ffe1bc1a",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2024-03-19T19:16:46.641513Z",
"iopub.status.busy": "2024-03-19T19:16:46.640892Z",
"iopub.status.idle": "2024-03-19T19:16:46.927981Z",
"shell.execute_reply": "2024-03-19T19:16:46.921001Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"The following leafs have been used while customising\n",
"\t(partial overlap with the set of automatically created leaves.\n",
"\ta new customiser for a different PDF could reuse them if necessary.):\n",
" 1) RooFormulaVar:: yieldSig_Sample1 = 0.29755\n",
" 2) RooFormulaVar:: yieldSig_Sample2 = 0.5\n",
" 3) RooRealVar:: meanG_Sample1 = 200\n",
" 4) RooRealVar:: meanG_Sample2 = 300\n",
" 5) RooRealVar:: meanG_Sample3 = 100\n",
" 6) RooRealVar:: yieldSig_Sample3 = 1\n"
]
}
],
"source": [
"meanG1 = allCustomiserNodes[\"meanG_Sample1\"]\n",
"meanG1.setVal(200)\n",
"meanG2 = allCustomiserNodes[\"meanG_Sample2\"]\n",
"meanG2.setVal(300)\n",
"\n",
"print(\n",
" \"\\nThe following leafs have been used while customising\\n\\t(partial overlap with the set of automatically created leaves.\\n\\ta new customiser for a different PDF could reuse them if necessary.):\"\n",
")\n",
"allCustomiserNodes.Print(\"V\")\n",
"\n",
"del cust"
]
}
],
"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.8.10"
}
},
"nbformat": 4,
"nbformat_minor": 5
}