19using FourVector = ROOT::Math::XYZTVector;
20using FourVectorVec = std::vector<FourVector>;
21using CylFourVector = ROOT::Math::RhoEtaPhiVector;
23// A simple helper function to fill a test tree: this makes the example
25void fill_tree(const char *filename, const char *treeName)
27 const double M = 0.13957; // set pi+ mass
30 auto genTracks = [&](){
32 const auto nPart = R.Poisson(15);
33 tracks.reserve(nPart);
34 for (int j = 0; j < nPart; ++j) {
35 const auto px = R.Gaus(0, 10);
36 const auto py = R.Gaus(0, 10);
37 const auto pt =
sqrt(px * px + py * py);
38 const auto eta = R.Uniform(-3, 3);
39 const auto phi = R.Uniform(0.0, 2 * TMath::
Pi());
40 CylFourVector vcyl(pt, eta, phi);
42 auto E =
sqrt(vcyl.R() * vcyl.R() + M * M);
44 tracks.emplace_back(vcyl.X(), vcyl.Y(), vcyl.Z(), E);
49 ROOT::RDataFrame
d(64);
50 d.Define(
"tracks", genTracks).Snapshot<FourVectorVec>(treeName, filename, {
"tracks"});
54# We prepare an input tree to run on
55fileName = "df002_dataModel_py.root"
57ROOT.gInterpreter.Declare(fill_tree_code)
58ROOT.fill_tree(fileName, treeName)
60# We read the tree from the file and create a RDataFrame, a class that
61# allows us to interact with the data contained in the tree.
62d = ROOT.RDataFrame(treeName, fileName)
64# Operating on branches which are collection of objects
65# Here we deal with the simplest of the cuts: we decide to accept the event
66# only if the number of tracks is greater than 8.
67n_cut = 'tracks.size() > 8'
68nentries = d.Filter(n_cut).Count();
70print("%s events passed all filters" % nentries.GetValue())
72# Another possibility consists in creating a new column containing the
73# quantity we are interested in.
74# In this example, we will cut on the number of tracks and plot their
78using namespace ROOT::VecOps;
79RVec<double> getPt(const RVec<FourVector> &tracks)
81 auto pt = [](const FourVector &v) {
return v.pt(); };
82 return Map(tracks, pt);
85ROOT.gInterpreter.Declare(getPt_code)
88using namespace ROOT::VecOps;
89RVec<double> getPtWeights(const RVec<FourVector> &tracks)
91 auto ptWeight = [](const FourVector &v) {
return 1. / v.Pt(); };
92 return Map(tracks, ptWeight);
95ROOT.gInterpreter.Declare(getPtWeights_code)
97augmented_d = d.Define('tracks_n', '(int)tracks.size()') \
99 .Define(
'tracks_pts',
'getPt( tracks )') \
100 .Define(
"tracks_pts_weights",
'getPtWeights( tracks )' )
104trN = augmented_d.Histo1D((
"",
"", 40, -.5, 39.5),
"tracks_n")
105trPts = augmented_d.Histo1D(
"tracks_pts")
106trWPts = augmented_d.Histo1D(
"tracks_pts",
"tracks_pts_weights")
110c1.SaveAs(
"df002_trN.png")
114c2.SaveAs(
"df002_trPts.png")
118c2.SaveAs(
"df002_trWPts.png")
120print(
"Saved figures to df002_*.png")
double Pi()
Mathematical constants.
auto Map(Args &&... args) -> decltype(ROOT::Detail::VecOps::MapFromTuple(std::forward_as_tuple(args...), std::make_index_sequence< sizeof...(args) - 1 >()))
Create new collection applying a callable to the elements of the input collection.
RVec< T > Filter(const RVec< T > &v, F &&f)
Create a new collection with the elements passing the filter expressed by the predicate.