{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "6dad1fc8",
   "metadata": {},
   "source": [
    "# rf513_wsfactory_tools\n",
    "Organization and simultaneous fits: illustration use of ROOT.RooCustomizer and\n",
    "ROOT.RooSimWSTool interface in factory workspace tool in a complex standalone B physics example\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "**Author:**  Clemens Lange, Wouter Verkerke (C++ version)  \n",
    "<i><small>This notebook tutorial was automatically generated with <a href= \"https://github.com/root-project/root/blob/master/documentation/doxygen/converttonotebook.py\">ROOTBOOK-izer</a> from the macro found in the ROOT repository  on Tuesday, May 19, 2026 at 08:32 PM.</small></i>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "8a7ebfb6",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:42.765450Z",
     "iopub.status.busy": "2026-05-19T20:32:42.765320Z",
     "iopub.status.idle": "2026-05-19T20:32:43.788533Z",
     "shell.execute_reply": "2026-05-19T20:32:43.787932Z"
    }
   },
   "outputs": [],
   "source": [
    "import ROOT\n",
    "\n",
    "\n",
    "w = ROOT.RooWorkspace(\"w\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "87421d0b",
   "metadata": {},
   "source": [
    "Build a complex example pdf\n",
    "-----------------------------------------------------------"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "846da623",
   "metadata": {},
   "source": [
    "Make signal model for CPV: A bmixing decay function in t (convoluted with a triple Gaussian resolution model)\n",
    "times a Gaussian function the reconstructed mass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "3b3ca9d6",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:43.790624Z",
     "iopub.status.busy": "2026-05-19T20:32:43.790478Z",
     "iopub.status.idle": "2026-05-19T20:32:44.037183Z",
     "shell.execute_reply": "2026-05-19T20:32:44.036124Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<cppyy.gbl.RooProdPdf object at 0x55b493e141f0>"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "w.factory(\n",
    "    \"PROD::sig(  BMixDecay::sig_t( dt[-20,20], mixState[mixed=1,unmix=-1], tagFlav[B0=1,B0bar=-1], \"\n",
    "    \"tau[1.54], dm[0.472], w[0.05], dw[0], \"\n",
    "    \"AddModel::gm({GaussModel(dt,biasC[-10,10],sigmaC[0.1,3],dterr[0.01,0.2]), \"\n",
    "    \"GaussModel(dt,0,sigmaT[3,10]), \"\n",
    "    \"GaussModel(dt,0,20)},{fracC[0,1],fracT[0,1]}), \"\n",
    "    \"DoubleSided ), \"\n",
    "    \"Gaussian::sig_m( mes[5.20,5.30], mB0[5.20,5.30], sigmB0[0.01,0.05] ))\"\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "20c217a8",
   "metadata": {},
   "source": [
    "Make background component: A plain decay function in t times an Argus\n",
    "function in the reconstructed mass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "4f8a5674",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:44.038808Z",
     "iopub.status.busy": "2026-05-19T20:32:44.038678Z",
     "iopub.status.idle": "2026-05-19T20:32:44.155784Z",
     "shell.execute_reply": "2026-05-19T20:32:44.154741Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<cppyy.gbl.RooProdPdf object at 0x55b494094240>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "w.factory(\"PROD::bkg(  Decay::bkg_t( dt, tau, gm, DoubleSided), \" \"ArgusBG::bkg_m( mes, 5.291, k[-100,-10]))\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e35f7d72",
   "metadata": {},
   "source": [
    "Make composite model from the signal and background component"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "e10c78cf",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:44.157379Z",
     "iopub.status.busy": "2026-05-19T20:32:44.157253Z",
     "iopub.status.idle": "2026-05-19T20:32:44.266317Z",
     "shell.execute_reply": "2026-05-19T20:32:44.265285Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<cppyy.gbl.RooAddPdf object at 0x55b494112830>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "w.factory(\"SUM::model( Nsig[5000,0,10000]*sig, NBkg[500,0,10000]*bkg )\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8de98815",
   "metadata": {},
   "source": [
    "Example of RooSimWSTool interface\n",
    "------------------------------------------------------------------"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "793d32aa",
   "metadata": {},
   "source": [
    "Introduce a flavour tagging category tagCat as observable with 4 states corresponding\n",
    "to 4 flavour tagging techniques with different performance that require different\n",
    "parameterizations of the fit model\n",
    "\n",
    "ROOT.RooSimWSTool operation:\n",
    "    - Make 4 clones of model (for each tagCat) state, will gain an individual\n",
    "      copy of parameters w, and biasC. The other parameters remain common\n",
    "    - Make a simultaneous pdf of the 4 clones assigning each to the appropriate\n",
    "      state of the tagCat index category"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "247c6044",
   "metadata": {},
   "source": [
    "ROOT.RooSimWSTool is interfaced as meta-type SIMCLONE in the factory. The $SplitParam()\n",
    "argument maps to the SplitParam() named argument in the\n",
    "ROOT.RooSimWSTool constructor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "9d4a64c1",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:44.268007Z",
     "iopub.status.busy": "2026-05-19T20:32:44.267878Z",
     "iopub.status.idle": "2026-05-19T20:32:44.381462Z",
     "shell.execute_reply": "2026-05-19T20:32:44.380392Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<cppyy.gbl.RooSimultaneous object at 0x55b4943da250>"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "w.factory(\"SIMCLONE::model_sim( model, $SplitParam({w,dw,biasC},tagCat[Lep,Kao,NT1,NT2]))\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8552c63c",
   "metadata": {},
   "source": [
    "Example of RooCustomizer interface\n",
    "-------------------------------------------------------------------\n",
    "\n",
    "Class ROOT.RooCustomizer makes clones of existing pdfs with certain prescribed\n",
    "modifications (branch of leaf node replacements)\n",
    "\n",
    "Here we take our model (the original before ROOT.RooSimWSTool modifications)\n",
    "and request that the parameter w (the mistag rate) is replaced with\n",
    "an expression-based function that calculates w in terms of the Dilution\n",
    "parameter D that is defined D = 1-2*w"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6862e53f",
   "metadata": {},
   "source": [
    "Make a clone model_D of original 'model' replacing 'w' with\n",
    "'expr('0.5-D/2',D[0,1])'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "f2318825",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:44.383120Z",
     "iopub.status.busy": "2026-05-19T20:32:44.382995Z",
     "iopub.status.idle": "2026-05-19T20:32:44.503119Z",
     "shell.execute_reply": "2026-05-19T20:32:44.502070Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<cppyy.gbl.RooAddPdf object at 0x55b49416fde0>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "w.factory(\"EDIT::model_D(model, w=expr('0.5-D/2',D[0,1]) )\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c6905428",
   "metadata": {},
   "source": [
    "Print workspace contents"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "fc8bd11e",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:44.504765Z",
     "iopub.status.busy": "2026-05-19T20:32:44.504630Z",
     "iopub.status.idle": "2026-05-19T20:32:44.632484Z",
     "shell.execute_reply": "2026-05-19T20:32:44.631611Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "RooWorkspace(w) w contents\n",
      "\n",
      "variables\n",
      "---------\n",
      "(D,NBkg,Nsig,biasC,biasC_Kao,biasC_Lep,biasC_NT1,biasC_NT2,dm,dt,dterr,dw,dw_Kao,dw_Lep,dw_NT1,dw_NT2,fracC,fracT,k,mB0,mes,mixState,sigmB0,sigmaC,sigmaT,tagCat,tagFlav,tau,w,w_Kao,w_Lep,w_NT1,w_NT2)\n",
      "\n",
      "p.d.f.s\n",
      "-------\n",
      "RooProdPdf::bkg[ bkg_t * bkg_m ] = 0.307193\n",
      "RooProdPdf::bkg_Kao[ bkg_t_Kao * bkg_m ] = 0.307193\n",
      "RooProdPdf::bkg_Lep[ bkg_t_Lep * bkg_m ] = 0.307193\n",
      "RooProdPdf::bkg_NT1[ bkg_t_NT1 * bkg_m ] = 0.307193\n",
      "RooProdPdf::bkg_NT2[ bkg_t_NT2 * bkg_m ] = 0.307193\n",
      "RooArgusBG::bkg_m[ m=mes m0=5.291 c=k p=0.5 ] = 0.279062\n",
      "RooDecay::bkg_t[ t=dt tau=tau ] = 1.10081\n",
      "RooDecay::bkg_t_Kao[ t=dt tau=tau ] = 1.10081\n",
      "RooDecay::bkg_t_Lep[ t=dt tau=tau ] = 1.10081\n",
      "RooDecay::bkg_t_NT1[ t=dt tau=tau ] = 1.10081\n",
      "RooDecay::bkg_t_NT2[ t=dt tau=tau ] = 1.10081\n",
      "RooAddPdf::model[ Nsig * sig + NBkg * bkg ] = 1.88229/1\n",
      "RooAddPdf::model_D[ Nsig * sig_model_D + NBkg * bkg ] = 1.5029/1\n",
      "RooAddPdf::model_Kao[ Nsig * sig_Kao + NBkg * bkg_Kao ] = 1.88229/1\n",
      "RooAddPdf::model_Lep[ Nsig * sig_Lep + NBkg * bkg_Lep ] = 1.88229/1\n",
      "RooAddPdf::model_NT1[ Nsig * sig_NT1 + NBkg * bkg_NT1 ] = 1.88229/1\n",
      "RooAddPdf::model_NT2[ Nsig * sig_NT2 + NBkg * bkg_NT2 ] = 1.88229/1\n",
      "RooSimultaneous::model_sim[ indexCat=tagCat Kao=model_Kao Lep=model_Lep NT1=model_NT1 NT2=model_NT2 ] = 0.470573\n",
      "RooProdPdf::sig[ sig_t * sig_m ] = 2.0398\n",
      "RooProdPdf::sig_Kao[ sig_t_Kao * sig_m ] = 2.0398\n",
      "RooProdPdf::sig_Lep[ sig_t_Lep * sig_m ] = 2.0398\n",
      "RooProdPdf::sig_NT1[ sig_t_NT1 * sig_m ] = 2.0398\n",
      "RooProdPdf::sig_NT2[ sig_t_NT2 * sig_m ] = 2.0398\n",
      "RooGaussian::sig_m[ x=mes mean=mB0 sigma=sigmB0 ] = 1\n",
      "RooProdPdf::sig_model_D[ sig_t_model_D * sig_m ] = 1.62247\n",
      "RooBMixDecay::sig_t[ mistag=w delMistag=dw mixState=mixState tagFlav=tagFlav tau=tau dm=dm t=dt ] = 2.0398\n",
      "RooBMixDecay::sig_t_Kao[ mistag=w_Kao delMistag=dw_Kao mixState=mixState tagFlav=tagFlav tau=tau dm=dm t=dt ] = 2.0398\n",
      "RooBMixDecay::sig_t_Lep[ mistag=w_Lep delMistag=dw_Lep mixState=mixState tagFlav=tagFlav tau=tau dm=dm t=dt ] = 2.0398\n",
      "RooBMixDecay::sig_t_NT1[ mistag=w_NT1 delMistag=dw_NT1 mixState=mixState tagFlav=tagFlav tau=tau dm=dm t=dt ] = 2.0398\n",
      "RooBMixDecay::sig_t_NT2[ mistag=w_NT2 delMistag=dw_NT2 mixState=mixState tagFlav=tagFlav tau=tau dm=dm t=dt ] = 2.0398\n",
      "RooBMixDecay::sig_t_model_D[ mistag=model_D_2 delMistag=dw mixState=mixState tagFlav=tagFlav tau=tau dm=dm t=dt ] = 1.62247\n",
      "\n",
      "analytical resolution models\n",
      "----------------------------\n",
      "RooAddModel::gm[ x=dt (fracC * gm_11 + fracT * gm_12 + [%] * gm_13) ] = 1.25632\n",
      "RooGaussModel::gm_11[ x=dt mean=biasC sigma=sigmaC msf=dterr ssf=dterr ] = 2.45126\n",
      "RooGaussModel::gm_11_Kao[ x=dt mean=biasC_Kao sigma=sigmaC msf=dterr ssf=dterr ] = 2.45126\n",
      "RooGaussModel::gm_11_Lep[ x=dt mean=biasC_Lep sigma=sigmaC msf=dterr ssf=dterr ] = 2.45126\n",
      "RooGaussModel::gm_11_NT1[ x=dt mean=biasC_NT1 sigma=sigmaC msf=dterr ssf=dterr ] = 2.45126\n",
      "RooGaussModel::gm_11_NT2[ x=dt mean=biasC_NT2 sigma=sigmaC msf=dterr ssf=dterr ] = 2.45126\n",
      "RooGaussModel::gm_12[ x=dt mean=0 sigma=sigmaT msf=1 ssf=1 ] = 0.0613757\n",
      "RooGaussModel::gm_13[ x=dt mean=0 sigma=20 msf=1 ssf=1 ] = 0.0199471\n",
      "RooAddModel::gm_Kao[ x=dt (fracC * gm_11_Kao + fracT * gm_12 + [%] * gm_13) ] = 1.25632\n",
      "RooAddModel::gm_Lep[ x=dt (fracC * gm_11_Lep + fracT * gm_12 + [%] * gm_13) ] = 1.25632\n",
      "RooAddModel::gm_NT1[ x=dt (fracC * gm_11_NT1 + fracT * gm_12 + [%] * gm_13) ] = 1.25632\n",
      "RooAddModel::gm_NT2[ x=dt (fracC * gm_11_NT2 + fracT * gm_12 + [%] * gm_13) ] = 1.25632\n",
      "\n",
      "functions\n",
      "--------\n",
      "RooFormulaVar::model_D_2[ actualVars=(D) formula=\"0.5-D/2\" ] = 0.25\n",
      "\n"
     ]
    }
   ],
   "source": [
    "w.Print()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "38c220ef",
   "metadata": {},
   "source": [
    "Make workspace visible on command line"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "d5213f7a",
   "metadata": {
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2026-05-19T20:32:44.634064Z",
     "iopub.status.busy": "2026-05-19T20:32:44.633932Z",
     "iopub.status.idle": "2026-05-19T20:32:44.751877Z",
     "shell.execute_reply": "2026-05-19T20:32:44.751243Z"
    }
   },
   "outputs": [],
   "source": [
    "ROOT.gDirectory.Add(w)"
   ]
  }
 ],
 "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
}
