Logo ROOT   6.12/07
Reference Guide
tdf002_dataModel.py
Go to the documentation of this file.
1 ## \file
2 ## \ingroup tutorial_tdataframe
3 ## \notebook -draw
4 ## This tutorial shows the possibility to use data models which are more
5 ## complex than flat ntuples with TDataFrame
6 ##
7 ## \macro_code
8 ##
9 ## \date May 2017
10 ## \author Danilo Piparo
11 
12 import ROOT
13 
14 # A simple helper function to fill a test tree: this makes the example stand-alone.
15 fill_tree_code = '''
16 
17 using FourVector = ROOT::Math::XYZTVector;
18 using FourVectors = std::vector<FourVector>;
19 using CylFourVector = ROOT::Math::RhoEtaPhiVector;
20 
21 void fill_tree(const char *filename, const char *treeName)
22 {
23  TFile f(filename, "RECREATE");
24  TTree t(treeName, treeName);
25  FourVectors tracks;
26  t.Branch("tracks", &tracks);
27 
28  const double M = 0.13957; // set pi+ mass
29  TRandom3 R(1);
30 
31  for (int i = 0; i < 50; ++i) {
32  auto nPart = R.Poisson(15);
33  tracks.clear();
34  tracks.reserve(nPart);
35  for (int j = 0; j < nPart; ++j) {
36  double px = R.Gaus(0, 10);
37  double py = R.Gaus(0, 10);
38  double pt = sqrt(px * px + py * py);
39  double eta = R.Uniform(-3, 3);
40  double phi = R.Uniform(0.0, 2 * TMath::Pi());
41  CylFourVector vcyl(pt, eta, phi);
42  // set energy
43  double E = sqrt(vcyl.R() * vcyl.R() + M * M);
44  FourVector q(vcyl.X(), vcyl.Y(), vcyl.Z(), E);
45  // fill track vector
46  tracks.emplace_back(q);
47  }
48  t.Fill();
49  }
50 
51  t.Write();
52  f.Close();
53  return;
54 }
55 '''
56 
57 # We prepare an input tree to run on
58 fileName = "tdf002_dataModel_py.root"
59 treeName = "myTree"
60 ROOT.gInterpreter.Declare(fill_tree_code)
61 ROOT.fill_tree(fileName, treeName)
62 
63 # We read the tree from the file and create a TDataFrame, a class that
64 # allows us to interact with the data contained in the tree.
65 TDF = ROOT.ROOT.Experimental.TDataFrame
66 d = TDF(treeName, fileName)
67 
68 # Operating on branches which are collection of objects
69 # Here we deal with the simplest of the cuts: we decide to accept the event
70 # only if the number of tracks is greater than 5.
71 n_cut = 'tracks.size() > 8'
72 nentries = d.Filter(n_cut).Count();
73 
74 print("%s passed all filters" %nentries.GetValue())
75 
76 # Another possibility consists in creating a new column containing the
77 # quantity we are interested in.
78 # In this example, we will cut on the number of tracks and plot their
79 # transverse momentum.
80 
81 getPt_code ='''
82 std::vector<double> getPt (const FourVectors &tracks)
83 {
84  std::vector<double> pts;
85  pts.reserve(tracks.size());
86  for (auto &t : tracks) pts.emplace_back(t.Pt());
87  return pts;
88 }
89 '''
90 ROOT.gInterpreter.Declare(getPt_code)
91 
92 getPtWeights_code ='''
93 std::vector<double> getPtWeights (const FourVectors &tracks) {
94  std::vector<double> ptsw;
95  ptsw.reserve(tracks.size());
96  for (auto &t : tracks) ptsw.emplace_back(1. / t.Pt());
97  return ptsw;
98 };
99 '''
100 ROOT.gInterpreter.Declare(getPtWeights_code)
101 
102 augmented_d = d.Define('tracks_n', '(int)tracks.size()') \
103  .Filter('tracks_n > 2') \
104  .Define('tracks_pts', 'getPt( tracks )') \
105  .Define("tracks_pts_weights", 'getPtWeights( tracks )' )
106 
107 # The histogram is initialised with a tuple containing the parameters of the
108 # histogram
109 trN = augmented_d.Histo1D(("", "", 40, -.5, 39.5), "tracks_n")
110 trPts = augmented_d.Histo1D("tracks_pts")
111 trWPts = augmented_d.Histo1D("tracks_pts", "tracks_pts_weights")
112 
113 c1 = ROOT.TCanvas()
114 trN.Draw()
115 c1.Print("tracks_n.png")
116 
117 c2 = ROOT.TCanvas()
118 trPts.Draw()
119 c2.Print("tracks_pt.png")
120 
121 c3 = ROOT.TCanvas()
122 trWPts.Draw()
123 c3.Print("tracks_Wpt.png")