{ "cells": [ { "cell_type": "markdown", "id": "93e90920", "metadata": {}, "source": [ "# df020_helpers\n", "Show usage of RDataFrame's helper tools, contained in ROOT/RDFHelpers.hxx.\n", "\n", "\n", "\n", "\n", "**Author:** Enrico Guiraud (CERN) \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:09 PM." ] }, { "cell_type": "markdown", "id": "5bd41e08", "metadata": {}, "source": [ "First of all, we create a dataframe with 3 entries and define two simple columns" ] }, { "cell_type": "code", "execution_count": 1, "id": "e6f3e3a9", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:09:53.391929Z", "iopub.status.busy": "2026-05-19T20:09:53.391809Z", "iopub.status.idle": "2026-05-19T20:09:54.091199Z", "shell.execute_reply": "2026-05-19T20:09:54.090704Z" } }, "outputs": [], "source": [ "const auto nEntries = 3;\n", "ROOT::RDataFrame _df(nEntries);\n", "auto df = _df.Define(\"one\", [] { return 1; }).Define(\"two\", [] { return 2; });" ] }, { "cell_type": "markdown", "id": "b1a28bb4", "metadata": {}, "source": [ "*** Not ***\n", "This helper takes a callable `f` (which must return a `bool`) and produces a new callable which takes the same\n", "arguments as `f` but returns its negated result. `Not` is useful to invert the check performed by a given Filter.\n", "Here we define a simple lambda that checks whether a value is equal to 1, and invert it with Not:" ] }, { "cell_type": "code", "execution_count": 2, "id": "e6641860", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:09:54.094209Z", "iopub.status.busy": "2026-05-19T20:09:54.094094Z", "iopub.status.idle": "2026-05-19T20:09:54.307053Z", "shell.execute_reply": "2026-05-19T20:09:54.305694Z" } }, "outputs": [], "source": [ "auto isOne = [] (int a) { return a == 1; };\n", "auto isNotOne = ROOT::RDF::Not(isOne);" ] }, { "cell_type": "markdown", "id": "2fad3426", "metadata": {}, "source": [ "Both `isOne` and `isNotOne` are callables that we can use in `Filters`:" ] }, { "cell_type": "code", "execution_count": 3, "id": "4add284f", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:09:54.326443Z", "iopub.status.busy": "2026-05-19T20:09:54.326302Z", "iopub.status.idle": "2026-05-19T20:09:55.678210Z", "shell.execute_reply": "2026-05-19T20:09:55.677668Z" } }, "outputs": [], "source": [ "auto c1 = df.Filter(isOne, {\"one\"}).Count();\n", "auto c2 = df.Filter(isNotOne, {\"two\"}).Count();" ] }, { "cell_type": "markdown", "id": "db6b5714", "metadata": {}, "source": [ "Both counts are equal to the total number of entries, as both Filters always pass." ] }, { "cell_type": "code", "execution_count": 4, "id": "68613f8c", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:09:55.694260Z", "iopub.status.busy": "2026-05-19T20:09:55.694107Z", "iopub.status.idle": "2026-05-19T20:09:55.897367Z", "shell.execute_reply": "2026-05-19T20:09:55.896840Z" } }, "outputs": [], "source": [ "R__ASSERT(*c1 == nEntries);\n", "R__ASSERT(*c2 == nEntries);" ] }, { "cell_type": "markdown", "id": "4e8eabc4", "metadata": {}, "source": [ "*** PassAsVec ***\n", "Consider the following function, which checks if a vector consists of two elements equal to 1 and 2:" ] }, { "cell_type": "code", "execution_count": 5, "id": "61f00e52", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:09:55.907697Z", "iopub.status.busy": "2026-05-19T20:09:55.907540Z", "iopub.status.idle": "2026-05-19T20:09:56.124797Z", "shell.execute_reply": "2026-05-19T20:09:56.114635Z" } }, "outputs": [], "source": [ "auto checkOneTwo = [] (const std::vector &v) { return v.size() == 2 && v[0] == 1 && v[1] == 2; };" ] }, { "cell_type": "markdown", "id": "4ea3adc4", "metadata": {}, "source": [ "The following line, although it looks reasonable, would _not_ run correctly:\n", "df.Filter(checkOneTwo, {\"one\", \"two\"});\n", "The reason is that `Filter(..., {\"one\", \"two\"})` expects a callable that takes exactly two integers, while\n", "`checkOneTwo` actually takes a vector of integers (i.e. it does not have the right signature).\n", "PassAsVec helps passing down the single values \"one\", \"two\" to `checkOneTwo` as a collection: it takes a callable\n", "`f` that expects a collection as argument and returns a new callable that takes single arguments instead, passes\n", "them down to `f` and returns what `f` returns.\n", "PassAsVec requires that number of arguments and their type is specified as template argument.\n", "Here's an example usage (remember, PassAsVec(f) returns a new callable!):" ] }, { "cell_type": "code", "execution_count": 6, "id": "69318e7b", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:09:56.142485Z", "iopub.status.busy": "2026-05-19T20:09:56.142343Z", "iopub.status.idle": "2026-05-19T20:09:56.840918Z", "shell.execute_reply": "2026-05-19T20:09:56.829655Z" } }, "outputs": [], "source": [ "auto c3 = df.Filter(ROOT::RDF::PassAsVec<2, int>(checkOneTwo), {\"one\", \"two\"}).Count();\n", "R__ASSERT(*c3 == nEntries);" ] }, { "cell_type": "markdown", "id": "cba16b90", "metadata": {}, "source": [ "Draw all canvases " ] }, { "cell_type": "code", "execution_count": 7, "id": "846d6237", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:09:56.852057Z", "iopub.status.busy": "2026-05-19T20:09:56.851907Z", "iopub.status.idle": "2026-05-19T20:09:57.055406Z", "shell.execute_reply": "2026-05-19T20:09:57.054811Z" } }, "outputs": [], "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 }