{ "cells": [ { "cell_type": "markdown", "id": "31655b67", "metadata": {}, "source": [ "# rf210_angularconv\n", "Addition and convolution: convolution in cyclical angular observables theta\n", "\n", "and construction of pdf in terms of transformed angular coordinates, e.g. cos(theta),\n", "where the convolution is performed in theta rather than cos(theta)\n", "\n", "```\n", " pdf(theta) = T(theta) (x) gauss(theta)\n", " pdf(cosTheta) = T(acos(cosTheta)) (x) gauss(acos(cosTheta))\n", "```\n", "\n", "This tutorial requires FFT3 to be enabled.\n", "\n", "\n", "\n", "\n", "**Author:** Wouter Verkerke \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:30 PM." ] }, { "cell_type": "code", "execution_count": 1, "id": "20d010fc", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:14.758837Z", "iopub.status.busy": "2026-05-19T20:30:14.758728Z", "iopub.status.idle": "2026-05-19T20:30:14.771871Z", "shell.execute_reply": "2026-05-19T20:30:14.771394Z" } }, "outputs": [], "source": [ "%%cpp -d\n", "#include \"RooRealVar.h\"\n", "#include \"RooDataSet.h\"\n", "#include \"RooGaussian.h\"\n", "#include \"RooGenericPdf.h\"\n", "#include \"RooFormulaVar.h\"\n", "#include \"RooFFTConvPdf.h\"\n", "#include \"RooPlot.h\"\n", "#include \"TCanvas.h\"\n", "#include \"TAxis.h\"\n", "#include \"TH1.h\"\n", "using namespace RooFit;" ] }, { "cell_type": "markdown", "id": "1c0ade3c", "metadata": {}, "source": [ "Setup component pdfs\n", "---------------------------------------" ] }, { "cell_type": "markdown", "id": "47951193", "metadata": {}, "source": [ "Define angle psi" ] }, { "cell_type": "code", "execution_count": 2, "id": "c70f1e23", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:14.773533Z", "iopub.status.busy": "2026-05-19T20:30:14.773420Z", "iopub.status.idle": "2026-05-19T20:30:15.087534Z", "shell.execute_reply": "2026-05-19T20:30:15.086892Z" } }, "outputs": [], "source": [ "RooRealVar psi(\"psi\", \"psi\", 0, 3.14159268);" ] }, { "cell_type": "markdown", "id": "2f6785a7", "metadata": {}, "source": [ "Define physics pdf T(psi)" ] }, { "cell_type": "code", "execution_count": 3, "id": "9d7624d6", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:15.089585Z", "iopub.status.busy": "2026-05-19T20:30:15.089467Z", "iopub.status.idle": "2026-05-19T20:30:15.297546Z", "shell.execute_reply": "2026-05-19T20:30:15.296763Z" } }, "outputs": [], "source": [ "RooGenericPdf Tpsi(\"Tpsi\", \"1+sin(2*@0)\", psi);" ] }, { "cell_type": "markdown", "id": "1466a59e", "metadata": {}, "source": [ "Define resolution R(psi)" ] }, { "cell_type": "code", "execution_count": 4, "id": "c99457bf", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:15.299457Z", "iopub.status.busy": "2026-05-19T20:30:15.299340Z", "iopub.status.idle": "2026-05-19T20:30:15.507636Z", "shell.execute_reply": "2026-05-19T20:30:15.506406Z" } }, "outputs": [], "source": [ "RooRealVar gbias(\"gbias\", \"gbias\", 0.2, 0., 1);\n", "RooRealVar greso(\"greso\", \"greso\", 0.3, 0.1, 1.0);\n", "RooGaussian Rpsi(\"Rpsi\", \"Rpsi\", psi, gbias, greso);" ] }, { "cell_type": "markdown", "id": "132e1343", "metadata": {}, "source": [ "Define cos(psi) and function psif that calculates psi from cos(psi)" ] }, { "cell_type": "code", "execution_count": 5, "id": "cbcefce6", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:15.509216Z", "iopub.status.busy": "2026-05-19T20:30:15.509100Z", "iopub.status.idle": "2026-05-19T20:30:15.716726Z", "shell.execute_reply": "2026-05-19T20:30:15.716276Z" } }, "outputs": [], "source": [ "RooRealVar cpsi(\"cpsi\", \"cos(psi)\", -1, 1);\n", "RooFormulaVar psif(\"psif\", \"acos(cpsi)\", cpsi);" ] }, { "cell_type": "markdown", "id": "477c9640", "metadata": {}, "source": [ "Define physics pdf also as function of cos(psi): T(psif(cpsi)) = T(cpsi) ;" ] }, { "cell_type": "code", "execution_count": 6, "id": "5abdfc62", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:15.730421Z", "iopub.status.busy": "2026-05-19T20:30:15.730280Z", "iopub.status.idle": "2026-05-19T20:30:15.938285Z", "shell.execute_reply": "2026-05-19T20:30:15.937297Z" } }, "outputs": [], "source": [ "RooGenericPdf Tcpsi(\"T\", \"1+sin(2*@0)\", psif);" ] }, { "cell_type": "markdown", "id": "78a88ad1", "metadata": {}, "source": [ "Construct convolution pdf in psi\n", "--------------------------------------------------------------" ] }, { "cell_type": "markdown", "id": "250479ce", "metadata": {}, "source": [ "Define convoluted pdf as function of psi: M=[T(x)R](psi) = M(psi)" ] }, { "cell_type": "code", "execution_count": 7, "id": "3ba84f83", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:15.939914Z", "iopub.status.busy": "2026-05-19T20:30:15.939797Z", "iopub.status.idle": "2026-05-19T20:30:16.148752Z", "shell.execute_reply": "2026-05-19T20:30:16.147993Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[#1] INFO:Caching -- Changing internal binning of variable 'psi' in FFT 'Mf' from 100 to 930 to improve the precision of the numerical FFT. This can be done manually by setting an additional binning named 'cache'.\n" ] } ], "source": [ "RooFFTConvPdf Mpsi(\"Mf\", \"Mf\", psi, Tpsi, Rpsi);" ] }, { "cell_type": "markdown", "id": "bb82cd5e", "metadata": {}, "source": [ "Set the buffer fraction to zero to obtain a true cyclical convolution" ] }, { "cell_type": "code", "execution_count": 8, "id": "e47a4731", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:16.150289Z", "iopub.status.busy": "2026-05-19T20:30:16.150175Z", "iopub.status.idle": "2026-05-19T20:30:16.357820Z", "shell.execute_reply": "2026-05-19T20:30:16.357304Z" } }, "outputs": [], "source": [ "Mpsi.setBufferFraction(0);" ] }, { "cell_type": "markdown", "id": "1a623e3b", "metadata": {}, "source": [ "Sample, fit and plot convoluted pdf (psi)\n", "--------------------------------------------------------------------------------" ] }, { "cell_type": "markdown", "id": "5d525562", "metadata": {}, "source": [ "Generate some events in observable psi" ] }, { "cell_type": "code", "execution_count": 9, "id": "8606f7d4", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:16.359719Z", "iopub.status.busy": "2026-05-19T20:30:16.359581Z", "iopub.status.idle": "2026-05-19T20:30:16.568824Z", "shell.execute_reply": "2026-05-19T20:30:16.568081Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[#1] INFO:Eval -- RooRealVar::setRange(psi) new range named 'refrange_fft_Mf' created with bounds [0,3.14159]\n", "[#1] INFO:NumericIntegration -- RooRealIntegral::init(Tpsi_Int[psi]) using numeric integrator RooIntegrator1D to calculate Int(psi)\n", "[#1] INFO:Caching -- RooAbsCachedPdf::getCache(Mf) creating new cache 0x7fb25959d4d0 with pdf Tpsi_CONV_Rpsi_CACHE_Obs[psi]_NORM_psi for nset (psi) with code 0\n", "[#1] INFO:NumericIntegration -- RooRealIntegral::init(Tpsi_Int[psi]) using numeric integrator RooIntegrator1D to calculate Int(psi)\n", "[#1] INFO:Caching -- RooAbsCachedPdf::getCache(Mf) creating new cache 0x7fb259940b10 with pdf Tpsi_CONV_Rpsi_CACHE_Obs[psi]_NORM_psi for nset (psi) with code 0\n" ] } ], "source": [ "std::unique_ptr data_psi{Mpsi.generate(psi, 10000)};" ] }, { "cell_type": "markdown", "id": "2d8014a0", "metadata": {}, "source": [ "Fit convoluted model as function of angle psi" ] }, { "cell_type": "code", "execution_count": 10, "id": "aa154ce0", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:16.570349Z", "iopub.status.busy": "2026-05-19T20:30:16.570233Z", "iopub.status.idle": "2026-05-19T20:30:16.779737Z", "shell.execute_reply": "2026-05-19T20:30:16.778804Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[#1] INFO:NumericIntegration -- RooRealIntegral::init(Tpsi_Int[psi]) using numeric integrator RooIntegrator1D to calculate Int(psi)\n", "[#1] INFO:Caching -- RooAbsCachedPdf::getCache(Mf) creating new cache 0x7fb25999fbd0 with pdf Tpsi_CONV_Rpsi_CACHE_Obs[psi]_NORM_psi for nset (psi) with code 0\n", "[#1] INFO:Fitting -- RooAbsPdf::fitTo(Mf_over_Mf_Int[psi]) 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.42739 ms\n", "[#1] INFO:Fitting -- RooAddition::defaultErrorLevel(nll_Mf_over_Mf_Int[psi]_MfData) Summation contains a RooNLLVar, using its error level\n", "[#1] INFO:Minimization -- [fitFCN] No discrete parameters, performing continuous minimization only\n" ] } ], "source": [ "Mpsi.fitTo(*data_psi, PrintLevel(-1));" ] }, { "cell_type": "markdown", "id": "9aafd65e", "metadata": {}, "source": [ "Plot cos(psi) frame with Mf(cpsi)" ] }, { "cell_type": "code", "execution_count": 11, "id": "f5a1bbe1", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:16.781226Z", "iopub.status.busy": "2026-05-19T20:30:16.781106Z", "iopub.status.idle": "2026-05-19T20:30:16.989657Z", "shell.execute_reply": "2026-05-19T20:30:16.988872Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[#1] INFO:NumericIntegration -- RooRealIntegral::init(Tpsi_Int[psi]) using numeric integrator RooIntegrator1D to calculate Int(psi)\n", "[#1] INFO:Caching -- RooAbsCachedPdf::getCache(Mf) creating new cache 0x7fb259e09950 with pdf Tpsi_CONV_Rpsi_CACHE_Obs[psi]_NORM_psi for nset (psi) with code 0\n" ] } ], "source": [ "RooPlot *frame1 = psi.frame(Title(\"Cyclical convolution in angle psi\"));\n", "data_psi->plotOn(frame1);\n", "Mpsi.plotOn(frame1);" ] }, { "cell_type": "markdown", "id": "9b992a6b", "metadata": {}, "source": [ "Overlay comparison to unsmeared physics pdf T(psi)" ] }, { "cell_type": "code", "execution_count": 12, "id": "f4278e5f", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:17.000248Z", "iopub.status.busy": "2026-05-19T20:30:17.000129Z", "iopub.status.idle": "2026-05-19T20:30:17.208460Z", "shell.execute_reply": "2026-05-19T20:30:17.208049Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[#1] INFO:NumericIntegration -- RooRealIntegral::init(Tpsi_Int[psi]) using numeric integrator RooIntegrator1D to calculate Int(psi)\n" ] } ], "source": [ "Tpsi.plotOn(frame1, LineColor(kRed));" ] }, { "cell_type": "markdown", "id": "4bfc00b3", "metadata": {}, "source": [ "Construct convolution pdf in cos(psi)\n", "--------------------------------------------------------------------------" ] }, { "cell_type": "markdown", "id": "8f4c34d1", "metadata": {}, "source": [ "Define convoluted pdf as function of cos(psi): M=[T(x)R](psif(cpsi)) = M(cpsi)\n", "\n", "Need to give both observable psi here (for definition of convolution)\n", "and function psif here (for definition of observables, ultimately in cpsi)" ] }, { "cell_type": "code", "execution_count": 13, "id": "85b098fa", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:17.209978Z", "iopub.status.busy": "2026-05-19T20:30:17.209868Z", "iopub.status.idle": "2026-05-19T20:30:17.417883Z", "shell.execute_reply": "2026-05-19T20:30:17.416948Z" } }, "outputs": [], "source": [ "RooFFTConvPdf Mcpsi(\"Mf\", \"Mf\", psif, psi, Tpsi, Rpsi);" ] }, { "cell_type": "markdown", "id": "2c31c5a1", "metadata": {}, "source": [ "Set the buffer fraction to zero to obtain a true cyclical convolution" ] }, { "cell_type": "code", "execution_count": 14, "id": "a0ed70a7", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:17.419259Z", "iopub.status.busy": "2026-05-19T20:30:17.419149Z", "iopub.status.idle": "2026-05-19T20:30:17.626735Z", "shell.execute_reply": "2026-05-19T20:30:17.626238Z" } }, "outputs": [], "source": [ "Mcpsi.setBufferFraction(0);" ] }, { "cell_type": "markdown", "id": "f0ecc2db", "metadata": {}, "source": [ "Sample, fit and plot convoluted pdf (cospsi)\n", "--------------------------------------------------------------------------------" ] }, { "cell_type": "markdown", "id": "f0c37722", "metadata": {}, "source": [ "Generate some events" ] }, { "cell_type": "code", "execution_count": 15, "id": "276c9b40", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:17.628464Z", "iopub.status.busy": "2026-05-19T20:30:17.628357Z", "iopub.status.idle": "2026-05-19T20:30:17.837272Z", "shell.execute_reply": "2026-05-19T20:30:17.836852Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[#1] INFO:NumericIntegration -- RooRealIntegral::init(Tpsi_Int[psi]) using numeric integrator RooIntegrator1D to calculate Int(psi)\n", "[#1] INFO:Caching -- RooAbsCachedPdf::getCache(Mf) creating new cache 0x7fb259e2fb70 with pdf Tpsi_CONV_Rpsi_CACHE_Obs[cpsi]_NORM_cpsi for nset (cpsi) with code 0\n", "[#1] INFO:NumericIntegration -- RooRealIntegral::init(Tpsi_CONV_Rpsi_CACHE_Obs[cpsi]_NORM_cpsi_Int[cpsi]) using numeric integrator RooIntegrator1D to calculate Int(cpsi)\n", "[#1] INFO:NumericIntegration -- RooRealIntegral::init(Tpsi_Int[psi]) using numeric integrator RooIntegrator1D to calculate Int(psi)\n", "[#1] INFO:Caching -- RooAbsCachedPdf::getCache(Mf) creating new cache 0x7fb259e52f50 with pdf Tpsi_CONV_Rpsi_CACHE_Obs[cpsi]_NORM_cpsi for nset (cpsi) with code 0\n", "[#1] INFO:NumericIntegration -- RooRealIntegral::init(Tpsi_CONV_Rpsi_CACHE_Obs[cpsi]_NORM_cpsi_Int[cpsi]) using numeric integrator RooIntegrator1D to calculate Int(cpsi)\n" ] } ], "source": [ "std::unique_ptr data_cpsi{Mcpsi.generate(cpsi, 10000)};" ] }, { "cell_type": "markdown", "id": "9172a797", "metadata": {}, "source": [ "set psi constant to exclude to be a parameter of the fit" ] }, { "cell_type": "code", "execution_count": 16, "id": "3fa868fc", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:17.838740Z", "iopub.status.busy": "2026-05-19T20:30:17.838619Z", "iopub.status.idle": "2026-05-19T20:30:18.045967Z", "shell.execute_reply": "2026-05-19T20:30:18.045506Z" } }, "outputs": [], "source": [ "psi.setConstant(true);" ] }, { "cell_type": "markdown", "id": "8b95a24c", "metadata": {}, "source": [ "Fit convoluted model as function of cos(psi)" ] }, { "cell_type": "code", "execution_count": 17, "id": "02b1aa3b", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:18.055294Z", "iopub.status.busy": "2026-05-19T20:30:18.055170Z", "iopub.status.idle": "2026-05-19T20:30:18.263976Z", "shell.execute_reply": "2026-05-19T20:30:18.263218Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[#1] INFO:NumericIntegration -- RooRealIntegral::init(Tpsi_Int[psi]) using numeric integrator RooIntegrator1D to calculate Int(psi)\n", "[#1] INFO:Caching -- RooAbsCachedPdf::getCache(Mf) creating new cache 0x7fb259ca8bf0 with pdf Tpsi_CONV_Rpsi_CACHE_Obs[cpsi]_NORM_cpsi for nset (cpsi) with code 0\n", "[#1] INFO:Fitting -- RooAbsPdf::fitTo(Mf_over_Mf_Int[cpsi]) fixing normalization set for coefficient determination to observables in data\n", "[#1] INFO:Fitting -- Creation of NLL object took 924.425 μs\n", "[#1] INFO:Fitting -- RooAddition::defaultErrorLevel(nll_Mf_over_Mf_Int[cpsi]_MfData) Summation contains a RooNLLVar, using its error level\n", "[#1] INFO:Minimization -- [fitFCN] No discrete parameters, performing continuous minimization only\n", "[#1] INFO:NumericIntegration -- RooRealIntegral::init(Mf_Int[cpsi]) using numeric integrator RooIntegrator1D to calculate Int(cpsi)\n", "[#1] INFO:NumericIntegration -- RooRealIntegral::init(Tpsi_Int[psi]) using numeric integrator RooIntegrator1D to calculate Int(psi)\n", "[#1] INFO:Caching -- RooAbsCachedPdf::getCache(Mf) creating new cache 0x7fb259e107a0 with pdf Tpsi_CONV_Rpsi_CACHE_Obs[cpsi] for nset () with code 1\n" ] } ], "source": [ "Mcpsi.fitTo(*data_cpsi, PrintLevel(-1));" ] }, { "cell_type": "markdown", "id": "550d442d", "metadata": {}, "source": [ "Plot cos(psi) frame with Mf(cpsi)" ] }, { "cell_type": "code", "execution_count": 18, "id": "05d5b505", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:18.265385Z", "iopub.status.busy": "2026-05-19T20:30:18.265260Z", "iopub.status.idle": "2026-05-19T20:30:18.473755Z", "shell.execute_reply": "2026-05-19T20:30:18.472978Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[#1] INFO:NumericIntegration -- RooRealIntegral::init(Tpsi_Int[psi]) using numeric integrator RooIntegrator1D to calculate Int(psi)\n", "[#1] INFO:Caching -- RooAbsCachedPdf::getCache(Mf) creating new cache 0x7fb259e80650 with pdf Tpsi_CONV_Rpsi_CACHE_Obs[cpsi]_NORM_cpsi for nset (cpsi) with code 0\n", "[#1] INFO:NumericIntegration -- RooRealIntegral::init(Tpsi_CONV_Rpsi_CACHE_Obs[cpsi]_NORM_cpsi_Int[cpsi]) using numeric integrator RooIntegrator1D to calculate Int(cpsi)\n" ] } ], "source": [ "RooPlot *frame2 = cpsi.frame(Title(\"Same convolution in psi, expressed in cos(psi)\"));\n", "data_cpsi->plotOn(frame2);\n", "Mcpsi.plotOn(frame2);" ] }, { "cell_type": "markdown", "id": "f90dad9a", "metadata": {}, "source": [ "Overlay comparison to unsmeared physics pdf Tf(cpsi)" ] }, { "cell_type": "code", "execution_count": 19, "id": "fa8803c3", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:18.475099Z", "iopub.status.busy": "2026-05-19T20:30:18.474992Z", "iopub.status.idle": "2026-05-19T20:30:18.683689Z", "shell.execute_reply": "2026-05-19T20:30:18.682975Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[#1] INFO:NumericIntegration -- RooRealIntegral::init(T_Int[cpsi]) using numeric integrator RooIntegrator1D to calculate Int(cpsi)\n" ] } ], "source": [ "Tcpsi.plotOn(frame2, LineColor(kRed));" ] }, { "cell_type": "markdown", "id": "ab823fe6", "metadata": {}, "source": [ "Draw frame on canvas" ] }, { "cell_type": "code", "execution_count": 20, "id": "30897ba7", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:18.685057Z", "iopub.status.busy": "2026-05-19T20:30:18.684946Z", "iopub.status.idle": "2026-05-19T20:30:18.893140Z", "shell.execute_reply": "2026-05-19T20:30:18.892599Z" } }, "outputs": [], "source": [ "TCanvas *c = new TCanvas(\"rf210_angularconv\", \"rf210_angularconv\", 800, 400);\n", "c->Divide(2);\n", "c->cd(1);\n", "gPad->SetLeftMargin(0.15);\n", "frame1->GetYaxis()->SetTitleOffset(1.4);\n", "frame1->Draw();\n", "c->cd(2);\n", "gPad->SetLeftMargin(0.15);\n", "frame2->GetYaxis()->SetTitleOffset(1.4);\n", "frame2->Draw();" ] }, { "cell_type": "markdown", "id": "b4f2ebdc", "metadata": {}, "source": [ "Draw all canvases " ] }, { "cell_type": "code", "execution_count": 21, "id": "5fe6ce5a", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:30:18.894890Z", "iopub.status.busy": "2026-05-19T20:30:18.894778Z", "iopub.status.idle": "2026-05-19T20:30:19.122754Z", "shell.execute_reply": "2026-05-19T20:30:19.121884Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "
\n", "
\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%jsroot on\n", "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 }