Data and categories: working with RooCategory objects to describe discrete variables
Author: Wouter Verkerke
This notebook tutorial was automatically generated with ROOTBOOK-izer from the macro found in the ROOT repository on Wednesday, April 17, 2024 at 11:18 AM.
%%cpp -d
#include "RooRealVar.h"
#include "RooDataSet.h"
#include "RooPolynomial.h"
#include "RooCategory.h"
#include "Roo1DTable.h"
#include "RooGaussian.h"
#include "TCanvas.h"
#include "TAxis.h"
#include "RooPlot.h"
#include <iostream>
using namespace RooFit;
Define a category with labels only
RooCategory tagCat("tagCat", "Tagging category");
tagCat.defineType("Lepton");
tagCat.defineType("Kaon");
tagCat.defineType("NetTagger-1");
tagCat.defineType("NetTagger-2");
tagCat.Print();
RooCategory::tagCat = Lepton(idx = 0)
Define a category with explicitly numbered states
RooCategory b0flav("b0flav", "B0 flavour eigenstate");
b0flav["B0"] = -1;
b0flav["B0bar"] = 1;
Print it in "verbose" mode to see all states.
b0flav.Print("V");
--- RooAbsArg --- Value State: clean Shape State: clean Attributes: Address: 0x7ff3e015c000 Clients: Servers: Proxies: --- RooAbsCategory --- Value = -1 "B0) Possible states: B0 -1 B0bar 1
Alternatively, define many states at once. The function takes a map with std::string --> index mapping.
RooCategory largeCat("largeCat", "A category with many states");
largeCat.defineTypes({
{"A", 0}, {"b", 2}, {"c", 8}, {"dee", 4},
{"F", 133}, {"g", 15}, {"H", -20}
});
One can iterate through the {index,name} pair of category objects
std::cout << "\nThis is the for loop over states of 'largeCat':";
for (const auto& idxAndName : largeCat)
std::cout << "\n\t" << idxAndName.first << "\t" << idxAndName.second;
std::cout << '\n' << std::endl;
This is the for loop over states of 'largeCat': A 0 F 133 H -20 b 2 c 8 dee 4 g 15
To ask whether a state is valid use:
std::cout << "Has label 'A': " << largeCat.hasLabel("A");
std::cout << "\nHas index '-20': " << largeCat.hasIndex(-20);
Has label 'A': 1 Has index '-20': 1
To retrieve names or state numbers:
std::cout << "\nLabel corresponding to '2' is " << largeCat.lookupName(2);
std::cout << "\nIndex corresponding to 'A' is " << largeCat.lookupIndex("A");
Label corresponding to '2' is b Index corresponding to 'A' is 0
To get the current state:
std::cout << "\nCurrent index is " << largeCat.getCurrentIndex();
std::cout << "\nCurrent label is " << largeCat.getCurrentLabel();
std::cout << std::endl;
Current index is 0 Current label is A
To set the state, use one of the two:
largeCat.setIndex(8);
largeCat.setLabel("c");
Generate a dummy dataset
RooRealVar x("x", "x", 0, 10);
std::unique_ptr<RooDataSet> data{RooPolynomial("p", "p", x).generate({x, b0flav, tagCat}, 10000)};
input_line_57:3:1: warning: 'data' shadows a declaration with the same name in the 'std' namespace; use '::data' to reference this declaration std::unique_ptr<RooDataSet> data{RooPolynomial("p", "p", x).generate({x, b0flav, tagCat}, 10000)}; ^
Tables are equivalent of plots for categories
Roo1DTable *btable = data->table(b0flav);
btable->Print();
btable->Print("v");
input_line_58:2:23: error: reference to 'data' is ambiguous Roo1DTable *btable = data->table(b0flav); ^ input_line_57:3:29: note: candidate found by name lookup is 'data' std::unique_ptr<RooDataSet> data{RooPolynomial("p", "p", x).generate({x, b0flav, tagCat}, 10000)}; ^ /usr/include/c++/9/bits/range_access.h:318:5: note: candidate found by name lookup is 'std::data' data(initializer_list<_Tp> __il) noexcept ^ /usr/include/c++/9/bits/range_access.h:289:5: note: candidate found by name lookup is 'std::data' data(_Container& __cont) noexcept(noexcept(__cont.data())) ^ /usr/include/c++/9/bits/range_access.h:299:5: note: candidate found by name lookup is 'std::data' data(const _Container& __cont) noexcept(noexcept(__cont.data())) ^ /usr/include/c++/9/bits/range_access.h:309:5: note: candidate found by name lookup is 'std::data' data(_Tp (&__array)[_Nm]) noexcept ^
Create table for subset of events matching cut expression
Roo1DTable *ttable = data->table(tagCat, "x>8.23");
ttable->Print();
ttable->Print("v");
input_line_59:2:23: error: reference to 'data' is ambiguous Roo1DTable *ttable = data->table(tagCat, "x>8.23"); ^ input_line_57:3:29: note: candidate found by name lookup is 'data' std::unique_ptr<RooDataSet> data{RooPolynomial("p", "p", x).generate({x, b0flav, tagCat}, 10000)}; ^ /usr/include/c++/9/bits/range_access.h:318:5: note: candidate found by name lookup is 'std::data' data(initializer_list<_Tp> __il) noexcept ^ /usr/include/c++/9/bits/range_access.h:289:5: note: candidate found by name lookup is 'std::data' data(_Container& __cont) noexcept(noexcept(__cont.data())) ^ /usr/include/c++/9/bits/range_access.h:299:5: note: candidate found by name lookup is 'std::data' data(const _Container& __cont) noexcept(noexcept(__cont.data())) ^ /usr/include/c++/9/bits/range_access.h:309:5: note: candidate found by name lookup is 'std::data' data(_Tp (&__array)[_Nm]) noexcept ^
Create table for all (tagCat x b0flav) state combinations
Roo1DTable *bttable = data->table(RooArgSet(tagCat, b0flav));
bttable->Print("v");
input_line_60:2:24: error: reference to 'data' is ambiguous Roo1DTable *bttable = data->table(RooArgSet(tagCat, b0flav)); ^ input_line_57:3:29: note: candidate found by name lookup is 'data' std::unique_ptr<RooDataSet> data{RooPolynomial("p", "p", x).generate({x, b0flav, tagCat}, 10000)}; ^ /usr/include/c++/9/bits/range_access.h:318:5: note: candidate found by name lookup is 'std::data' data(initializer_list<_Tp> __il) noexcept ^ /usr/include/c++/9/bits/range_access.h:289:5: note: candidate found by name lookup is 'std::data' data(_Container& __cont) noexcept(noexcept(__cont.data())) ^ /usr/include/c++/9/bits/range_access.h:299:5: note: candidate found by name lookup is 'std::data' data(const _Container& __cont) noexcept(noexcept(__cont.data())) ^ /usr/include/c++/9/bits/range_access.h:309:5: note: candidate found by name lookup is 'std::data' data(_Tp (&__array)[_Nm]) noexcept ^
Retrieve number of events from table Number can be non-integer if source dataset has weighed events
double nb0 = btable->get("B0");
std::cout << "Number of events with B0 flavor is " << nb0 << std::endl;
input_line_62:2:3: error: use of undeclared identifier 'btable' (btable->get("B0")) ^ Error in <HandleInterpreterException>: Error evaluating expression (btable->get("B0")) Execution of your code was aborted.
Retrieve fraction of events with "Lepton" tag
double fracLep = ttable->getFrac("Lepton");
std::cout << "Fraction of events tagged with Lepton tag is " << fracLep << std::endl;
input_line_64:2:3: error: use of undeclared identifier 'ttable' (ttable->getFrac("Lepton")) ^ Error in <HandleInterpreterException>: Error evaluating expression (ttable->getFrac("Lepton")) Execution of your code was aborted.
Define named range as comma separated list of labels
tagCat.setRange("good", "Lepton,Kaon");
Or add state names one by one
tagCat.addToRange("soso", "NetTagger-1");
tagCat.addToRange("soso", "NetTagger-2");
Use category range in dataset reduction specification
std::unique_ptr<RooAbsData> goodData{data->reduce(CutRange("good"))};
static_cast<RooDataSet&>(*goodData).table(tagCat)->Print("v");
input_line_67:2:39: error: reference to 'data' is ambiguous std::unique_ptr<RooAbsData> goodData{data->reduce(CutRange("good"))}; ^ input_line_57:3:29: note: candidate found by name lookup is 'data' std::unique_ptr<RooDataSet> data{RooPolynomial("p", "p", x).generate({x, b0flav, tagCat}, 10000)}; ^ /usr/include/c++/9/bits/range_access.h:318:5: note: candidate found by name lookup is 'std::data' data(initializer_list<_Tp> __il) noexcept ^ /usr/include/c++/9/bits/range_access.h:289:5: note: candidate found by name lookup is 'std::data' data(_Container& __cont) noexcept(noexcept(__cont.data())) ^ /usr/include/c++/9/bits/range_access.h:299:5: note: candidate found by name lookup is 'std::data' data(const _Container& __cont) noexcept(noexcept(__cont.data())) ^ /usr/include/c++/9/bits/range_access.h:309:5: note: candidate found by name lookup is 'std::data' data(_Tp (&__array)[_Nm]) noexcept ^