{ "cells": [ { "cell_type": "markdown", "id": "02b84bd9", "metadata": {}, "source": [ "# combinedFit\n", "Combined (simultaneous) fit of two histogram with separate functions\n", "and some common parameters\n", "\n", "See http://root.cern/phpBB3//viewtopic.php?f=3&t=11740#p50908\n", "for a modified version working with Fumili or GSLMultiFit\n", "\n", "N.B. this macro must be compiled with ACliC\n", "\n", "\n", "\n", "\n", "**Author:** Lorenzo Moneta \n", "This notebook tutorial was automatically generated with ROOTBOOK-izer from the macro found in the ROOT repository on Tuesday, May 19, 2026 at 08:24 PM." ] }, { "cell_type": "code", "execution_count": 1, "id": "0d6bdb93", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:24:31.517940Z", "iopub.status.busy": "2026-05-19T20:24:31.517834Z", "iopub.status.idle": "2026-05-19T20:24:31.524620Z", "shell.execute_reply": "2026-05-19T20:24:31.524134Z" } }, "outputs": [], "source": [ "%%cpp -d\n", "\n", "#include \n", "#include \n", "#include \n", "#include \n", "#include \n", "#include \n", "#include \n", "#include " ] }, { "cell_type": "markdown", "id": "f4857cc1", "metadata": {}, "source": [ "definition of shared parameter\n", "background function" ] }, { "cell_type": "code", "execution_count": 2, "id": "76740068", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:24:31.526094Z", "iopub.status.busy": "2026-05-19T20:24:31.525983Z", "iopub.status.idle": "2026-05-19T20:24:31.843233Z", "shell.execute_reply": "2026-05-19T20:24:31.842679Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "input_line_45:6:1: error: expected expression\n", "%%cpp -d\n", "^\n", "input_line_45:6:2: error: expected expression\n", "%%cpp -d\n", " ^\n", "input_line_45:6:3: error: use of undeclared identifier 'cpp'\n", "%%cpp -d\n", " ^\n", "input_line_45:6:8: error: use of undeclared identifier 'd'\n", "%%cpp -d\n", " ^\n" ] } ], "source": [ "int iparB[2] = {\n", " 0, // exp amplitude in B histo\n", " 2 // exp common parameter\n", "};\n", "%%cpp -d" ] }, { "cell_type": "markdown", "id": "3f8952c8", "metadata": {}, "source": [ "signal + background function" ] }, { "cell_type": "code", "execution_count": 3, "id": "84f36854", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:24:31.844918Z", "iopub.status.busy": "2026-05-19T20:24:31.844798Z", "iopub.status.idle": "2026-05-19T20:24:32.049442Z", "shell.execute_reply": "2026-05-19T20:24:32.048961Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "input_line_54:9:1: error: expected expression\n", "%%cpp -d\n", "^\n", "input_line_54:9:2: error: expected expression\n", "%%cpp -d\n", " ^\n", "input_line_54:9:3: error: use of undeclared identifier 'cpp'\n", "%%cpp -d\n", " ^\n", "input_line_54:9:8: error: use of undeclared identifier 'd'\n", "%%cpp -d\n", " ^\n" ] } ], "source": [ "int iparSB[5] = {\n", " 1, // exp amplitude in S+B histo\n", " 2, // exp common parameter\n", " 3, // Gaussian amplitude\n", " 4, // Gaussian mean\n", " 5 // Gaussian sigma\n", "};\n", "%%cpp -d" ] }, { "cell_type": "markdown", "id": "90fc828c", "metadata": {}, "source": [ "Create the GlobalCHi2 structure" ] }, { "cell_type": "code", "execution_count": 4, "id": "c0adc2ed", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:24:32.051219Z", "iopub.status.busy": "2026-05-19T20:24:32.051104Z", "iopub.status.idle": "2026-05-19T20:24:32.253614Z", "shell.execute_reply": "2026-05-19T20:24:32.252997Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "input_line_55:10:22: error: use of undeclared identifier 'iparB'\n", " p1[i] = par[iparB[i]];\n", " ^\n", "input_line_55:14:22: error: use of undeclared identifier 'iparSB'\n", " p2[i] = par[iparSB[i]];\n", " ^\n" ] } ], "source": [ "struct GlobalChi2 {\n", " GlobalChi2(ROOT::Math::IMultiGenFunction &f1, ROOT::Math::IMultiGenFunction &f2) : fChi2_1(&f1), fChi2_2(&f2) {}\n", "\n", " // parameter vector is first background (in common 1 and 2)\n", " // and then is signal (only in 2)\n", " double operator()(const double *par) const\n", " {\n", " double p1[2];\n", " for (int i = 0; i < 2; ++i)\n", " p1[i] = par[iparB[i]];\n", "\n", " double p2[5];\n", " for (int i = 0; i < 5; ++i)\n", " p2[i] = par[iparSB[i]];\n", "\n", " return (*fChi2_1)(p1) + (*fChi2_2)(p2);\n", " }\n", "\n", " const ROOT::Math::IMultiGenFunction *fChi2_1;\n", " const ROOT::Math::IMultiGenFunction *fChi2_2;\n", "};" ] }, { "cell_type": "code", "execution_count": 5, "id": "9d89c4c1", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:24:32.255353Z", "iopub.status.busy": "2026-05-19T20:24:32.255196Z", "iopub.status.idle": "2026-05-19T20:24:32.462324Z", "shell.execute_reply": "2026-05-19T20:24:32.461704Z" } }, "outputs": [], "source": [ "TH1D *hB = new TH1D(\"hB\", \"histo B\", 100, 0, 100);\n", "TH1D *hSB = new TH1D(\"hSB\", \"histo S+B\", 100, 0, 100);" ] }, { "cell_type": "markdown", "id": "b7c6c20e", "metadata": {}, "source": [ "Create functions (not adding them to ROOT's global list,\n", "because we want to add them to the histograms later)" ] }, { "cell_type": "code", "execution_count": 6, "id": "59004207", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:24:32.464347Z", "iopub.status.busy": "2026-05-19T20:24:32.464226Z", "iopub.status.idle": "2026-05-19T20:24:32.670379Z", "shell.execute_reply": "2026-05-19T20:24:32.669706Z" } }, "outputs": [], "source": [ "TF1 *fB = new TF1(\"fB\", \"expo\", 0, 100, TF1::EAddToList::kNo);\n", "fB->SetParameters(1, -0.05);\n", "hB->FillRandom(fB);\n", "\n", "TF1 *fS = new TF1(\"fS\", \"gaus\", 0, 100, TF1::EAddToList::kNo);\n", "fS->SetParameters(1, 30, 5);\n", "\n", "hSB->FillRandom(fB, 2000);\n", "hSB->FillRandom(fS, 1000);" ] }, { "cell_type": "markdown", "id": "7ca89331", "metadata": {}, "source": [ "perform now global fit" ] }, { "cell_type": "code", "execution_count": 7, "id": "a24d12d0", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:24:32.672259Z", "iopub.status.busy": "2026-05-19T20:24:32.672146Z", "iopub.status.idle": "2026-05-19T20:24:32.878276Z", "shell.execute_reply": "2026-05-19T20:24:32.877723Z" } }, "outputs": [], "source": [ "TF1 *fSB = new TF1(\"fSB\", \"expo + gaus(2)\", 0, 100, TF1::EAddToList::kNo);\n", "\n", "ROOT::Math::WrappedMultiTF1 wfB(*fB, 1);\n", "ROOT::Math::WrappedMultiTF1 wfSB(*fSB, 1);\n", "\n", "ROOT::Fit::DataOptions opt;\n", "ROOT::Fit::DataRange rangeB;" ] }, { "cell_type": "markdown", "id": "988056c8", "metadata": {}, "source": [ "set the data range" ] }, { "cell_type": "code", "execution_count": 8, "id": "8d372b11", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:24:32.880538Z", "iopub.status.busy": "2026-05-19T20:24:32.880409Z", "iopub.status.idle": "2026-05-19T20:24:33.088736Z", "shell.execute_reply": "2026-05-19T20:24:33.088249Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "input_line_68:14:1: error: unknown type name 'GlobalChi2'\n", "GlobalChi2 globalChi2(chi2_B, chi2_SB);\n", "^\n" ] } ], "source": [ "rangeB.SetRange(10, 90);\n", "ROOT::Fit::BinData dataB(opt, rangeB);\n", "ROOT::Fit::FillData(dataB, hB);\n", "\n", "ROOT::Fit::DataRange rangeSB;\n", "rangeSB.SetRange(10, 50);\n", "ROOT::Fit::BinData dataSB(opt, rangeSB);\n", "ROOT::Fit::FillData(dataSB, hSB);\n", "\n", "ROOT::Fit::Chi2Function chi2_B(dataB, wfB);\n", "ROOT::Fit::Chi2Function chi2_SB(dataSB, wfSB);\n", "\n", "GlobalChi2 globalChi2(chi2_B, chi2_SB);\n", "\n", "ROOT::Fit::Fitter fitter;\n", "\n", "const int Npar = 6;\n", "double par0[Npar] = {5, 5, -0.1, 100, 30, 10};" ] }, { "cell_type": "markdown", "id": "9215e04d", "metadata": {}, "source": [ "create before the parameter settings in order to fix or set range on them" ] }, { "cell_type": "code", "execution_count": 9, "id": "c3595b37", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:24:33.090513Z", "iopub.status.busy": "2026-05-19T20:24:33.090396Z", "iopub.status.idle": "2026-05-19T20:24:33.297539Z", "shell.execute_reply": "2026-05-19T20:24:33.296999Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "In module 'MathCore':\n", "/github/home/ROOT-CI/build/include/Fit/Chi2FCN.h:73:4: warning: inline function 'ROOT::Fit::Chi2FCN, ROOT::Math::IParametricFunctionMultiDimTempl >::Chi2FCN' is not defined [-Wundefined-inline]\n", " Chi2FCN ( const BinData & data, const IModelFunction & func, const ::ROOT::EExecutionPolicy &executionPolicy = ::ROOT::EExecutionPolicy::kSequential) :\n", " ^\n", "input_line_68: note: used here\n", "In module 'MathCore':\n", "/github/home/ROOT-CI/build/include/Fit/Chi2FCN.h:83:12: warning: inline function 'ROOT::Fit::Chi2FCN, ROOT::Math::IParametricFunctionMultiDimTempl >::~Chi2FCN' is not defined [-Wundefined-inline]\n", " virtual ~Chi2FCN () {}\n", " ^\n", "input_line_68: note: used here\n", "input_line_70:2:3: error: use of undeclared identifier 'fitter'\n", " (fitter.Config().SetParamsSettings(6, par0))\n", " ^\n", "input_line_70:2:40: error: use of undeclared identifier 'par0'\n", " (fitter.Config().SetParamsSettings(6, par0))\n", " ^\n", "Error in : Error evaluating expression (fitter.Config().SetParamsSettings(6, par0))\n", "Execution of your code was aborted.\n" ] } ], "source": [ "fitter.Config().SetParamsSettings(6, par0);" ] }, { "cell_type": "markdown", "id": "c4310977", "metadata": {}, "source": [ "fix 5-th parameter" ] }, { "cell_type": "code", "execution_count": 10, "id": "af22f266", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:24:33.299207Z", "iopub.status.busy": "2026-05-19T20:24:33.299085Z", "iopub.status.idle": "2026-05-19T20:24:33.505509Z", "shell.execute_reply": "2026-05-19T20:24:33.504932Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "input_line_72:2:3: error: use of undeclared identifier 'fitter'\n", " (fitter.Config().ParSettings(4).Fix())\n", " ^\n", "Error in : Error evaluating expression (fitter.Config().ParSettings(4).Fix())\n", "Execution of your code was aborted.\n" ] } ], "source": [ "fitter.Config().ParSettings(4).Fix();" ] }, { "cell_type": "markdown", "id": "f5ad5395", "metadata": {}, "source": [ "set limits on the third and 4-th parameter" ] }, { "cell_type": "code", "execution_count": 11, "id": "4576eb92", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:24:33.507203Z", "iopub.status.busy": "2026-05-19T20:24:33.507075Z", "iopub.status.idle": "2026-05-19T20:24:33.711781Z", "shell.execute_reply": "2026-05-19T20:24:33.711188Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "input_line_74:2:3: error: use of undeclared identifier 'fitter'\n", " (fitter.Config().ParSettings(2).SetLimits(-10, -1.0E-4))\n", " ^\n", "Error in : Error evaluating expression (fitter.Config().ParSettings(2).SetLimits(-10, -1.0E-4))\n", "Execution of your code was aborted.\n" ] } ], "source": [ "fitter.Config().ParSettings(2).SetLimits(-10, -1.E-4);\n", "fitter.Config().ParSettings(3).SetLimits(0, 10000);\n", "fitter.Config().ParSettings(3).SetStepSize(5);\n", "\n", "fitter.Config().MinimizerOptions().SetPrintLevel(0);\n", "fitter.Config().SetMinimizer(\"Minuit2\", \"Migrad\");" ] }, { "cell_type": "markdown", "id": "653eba49", "metadata": {}, "source": [ "fit FCN function directly\n", "(specify optionally data size and flag to indicate that is a chi2 fit)" ] }, { "cell_type": "code", "execution_count": 12, "id": "e347fd7c", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:24:33.713448Z", "iopub.status.busy": "2026-05-19T20:24:33.713333Z", "iopub.status.idle": "2026-05-19T20:24:34.095627Z", "shell.execute_reply": "2026-05-19T20:24:34.095007Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "[runStaticInitializersOnce]: Failed to materialize symbols: { (main, { _Z31__fd_init_order__cling_Un1Qu310v, cling_module_306_.27, __vd_init_order__cling_Un1Qu313, $.cling-module-306.__inits.0, _ZN12__cling_N52924__dynamic__cling_Un1Qu30E, _GLOBAL__sub_I_cling_module_306, _ZN12__cling_N5296resultE, _ZNK4ROOT3Fit9FitResult4Chi2Ev, __vd_init_order__cling_Un1Qu311, _ZN12__cling_N5292c1E, _ZNK5cling7runtime8internal15LifetimeHandler9getMemoryEv, cling_module_306_, cling_module_306_.25, _Z31__fd_init_order__cling_Un1Qu312v, cling_module_306_.24, _ZN12__cling_N52916__cling_Un1Qu330EPv, __orc_init_func.cling-module-306, _ZNK3TH118GetListOfFunctionsEv, cling_module_306_.26 }) }\n", "IncrementalExecutor::executeFunction: symbol '_ZN5cling7runtime8internal15LifetimeHandlerC1EPNS1_15DynamicExprInfoEPN5clang11DeclContextEPKcPNS_11InterpreterE' unresolved while linking [cling interface function]!\n", "You are probably missing the definition of cling::runtime::internal::LifetimeHandler::LifetimeHandler(cling::runtime::internal::DynamicExprInfo*, clang::DeclContext*, char const*, cling::Interpreter*)\n", "Maybe you need to load the corresponding shared library?\n", "IncrementalExecutor::executeFunction: symbol '_ZN5cling7runtime8internal15LifetimeHandlerD1Ev' unresolved while linking [cling interface function]!\n", "You are probably missing the definition of cling::runtime::internal::LifetimeHandler::~LifetimeHandler()\n", "Maybe you need to load the corresponding shared library?\n" ] } ], "source": [ "fitter.FitFCN(6, globalChi2, nullptr, dataB.Size() + dataSB.Size(), true);\n", "ROOT::Fit::FitResult result = fitter.Result();\n", "result.Print(std::cout);\n", "\n", "std::cout << \"Combined fit Chi2 = \" << result.Chi2() << std::endl;\n", "\n", "TCanvas *c1 = new TCanvas(\"Simfit\", \"Simultaneous fit of two histograms\", 10, 10, 700, 700);\n", "c1->Divide(1, 2);\n", "c1->cd(1);\n", "gStyle->SetOptFit(1111);\n", "\n", "fB->SetFitResult(result, iparB);\n", "fB->SetRange(rangeB().first, rangeB().second);\n", "fB->SetLineColor(kBlue);\n", "hB->GetListOfFunctions()->Add(fB);\n", "hB->Draw();\n", "\n", "c1->cd(2);\n", "fSB->SetFitResult(result, iparSB);\n", "fSB->SetRange(rangeSB().first, rangeSB().second);\n", "fSB->SetLineColor(kRed);\n", "hSB->GetListOfFunctions()->Add(fSB);\n", "hSB->Draw();" ] }, { "cell_type": "markdown", "id": "2bbddab0", "metadata": {}, "source": [ "Draw all canvases " ] }, { "cell_type": "code", "execution_count": 13, "id": "5804e69b", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:24:34.097042Z", "iopub.status.busy": "2026-05-19T20:24:34.096912Z", "iopub.status.idle": "2026-05-19T20:24:34.303540Z", "shell.execute_reply": "2026-05-19T20:24:34.302973Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "[runStaticInitializersOnce]: Failed to materialize symbols: { (main, { __orc_init_func.cling-module-306 }) }\n" ] } ], "source": [ "gROOT->GetListOfCanvases()->Draw()" ] } ], "metadata": { "kernelspec": { "display_name": "ROOT C++", "language": "c++", "name": "root" }, "language_info": { "codemirror_mode": "text/x-c++src", "file_extension": ".C", "mimetype": " text/x-c++src", "name": "c++" } }, "nbformat": 4, "nbformat_minor": 5 }