Loading [MathJax]/extensions/tex2jax.js
Logo ROOT  
Reference Guide
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
ntpl003_lhcbOpenData.C
Go to the documentation of this file.
1/// \file
2/// \ingroup tutorial_ntuple
3/// \notebook
4/// Convert LHCb run 1 open data from a TTree to RNTuple.
5/// This tutorial illustrates data conversion for a simple, tabular data model.
6/// For reading, the tutorial shows the use of an ntuple View, which selectively accesses specific fields.
7/// If a view is used for reading, there is no need to define the data model as an RNTupleModel first.
8/// The advantage of a view is that it directly accesses RNTuple's data buffers without making an additional
9/// memory copy.
10///
11/// \macro_image
12/// \macro_code
13///
14/// \date April 2019
15/// \author The ROOT Team
16
17// NOTE: The RNTuple classes are experimental at this point.
18// Functionality, interface, and data format is still subject to changes.
19// Do not use for real data!
20
21#include <ROOT/RField.hxx>
22#include <ROOT/RNTuple.hxx>
23#include <ROOT/RNTupleModel.hxx>
24
25#include <TBranch.h>
26#include <TCanvas.h>
27#include <TFile.h>
28#include <TH1F.h>
29#include <TLeaf.h>
30#include <TTree.h>
31
32#include <cassert>
33#include <memory>
34#include <vector>
35
36// Import classes from experimental namespace for the time being
37using RNTupleModel = ROOT::Experimental::RNTupleModel;
39using RNTupleReader = ROOT::Experimental::RNTupleReader;
40using RNTupleWriter = ROOT::Experimental::RNTupleWriter;
41
42constexpr char const* kTreeFileName = "http://root.cern.ch/files/LHCb/lhcb_B2HHH_MagnetUp.root";
43constexpr char const* kNTupleFileName = "ntpl003_lhcbOpenData.root";
44
45
46void Convert() {
47 std::unique_ptr<TFile> f(TFile::Open(kTreeFileName));
48 assert(f && ! f->IsZombie());
49
50 // Get a unique pointer to an empty RNTuple model
51 auto model = RNTupleModel::Create();
52
53 // We create RNTuple fields based on the types found in the TTree
54 // This simple approach only works for trees with simple branches and only one leaf per branch
55 auto tree = f->Get<TTree>("DecayTree");
56 for (auto b : TRangeDynCast<TBranch>(*tree->GetListOfBranches())) {
57 // The dynamic cast to TBranch should never fail for GetListOfBranches()
58 assert(b);
59
60 // We assume every branch has a single leaf
61 TLeaf *l = static_cast<TLeaf*>(b->GetListOfLeaves()->First());
62
63 // Create an ntuple field with the same name and type than the tree branch
64 auto field = RFieldBase::Create(l->GetName(), l->GetTypeName());
65 std::cout << "Convert leaf " << l->GetName() << " [" << l->GetTypeName() << "]"
66 << " --> " << "field " << field->GetName() << " [" << field->GetType() << "]" << std::endl;
67
68 // Hand over ownership of the field to the ntuple model. This will also create a memory location attached
69 // to the model's default entry, that will be used to place the data supposed to be written
70 model->AddField(std::unique_ptr<RFieldBase>(field));
71
72 // We connect the model's default entry's memory location for the new field to the branch, so that we can
73 // fill the ntuple with the data read from the TTree
74 void *fieldDataPtr = model->GetDefaultEntry()->GetValue(l->GetName()).GetRawPtr();
75 tree->SetBranchAddress(b->GetName(), fieldDataPtr);
76 }
77
78 // The new ntuple takes ownership of the model
79 auto ntuple = RNTupleWriter::Recreate(std::move(model), "DecayTree", kNTupleFileName);
80
81 auto nEntries = tree->GetEntries();
82 for (decltype(nEntries) i = 0; i < nEntries; ++i) {
83 tree->GetEntry(i);
84 ntuple->Fill();
85
86 if (i && i % 100000 == 0)
87 std::cout << "Wrote " << i << " entries" << std::endl;
88 }
89}
90
91
92void ntpl003_lhcbOpenData()
93{
94 Convert();
95
96 // Create histogram of the flight distance
97
98 // We open the ntuple without specifiying an explicit model first, but instead use a view on the field we are
99 // interested in
100 auto ntuple = RNTupleReader::Open("DecayTree", kNTupleFileName);
101
102 // The view wraps a read-only double value and accesses directly the ntuple's data buffers
103 auto viewFlightDistance = ntuple->GetView<double>("B_FlightDistance");
104
105 auto c = new TCanvas("c", "B Flight Distance", 200, 10, 700, 500);
106 TH1F h("h", "B Flight Distance", 200, 0, 140);
107 h.SetFillColor(48);
108
109 for (auto i : ntuple->GetEntryRange()) {
110 // Note that we do not load an entry in this loop, i.e. we avoid the memory copy of loading the data into
111 // the memory location given by the entry
112 h.Fill(viewFlightDistance(i));
113 }
114
115 h.DrawCopy();
116}
#define b(i)
Definition: RSha256.hxx:100
#define f(i)
Definition: RSha256.hxx:104
#define c(i)
Definition: RSha256.hxx:101
#define h(i)
Definition: RSha256.hxx:106
A field translates read and write calls from/to underlying columns to/from tree values.
Definition: RField.hxx:60
The RNTupleModel encapulates the schema of an ntuple.
An RNTuple that is used to read data from storage.
Definition: RNTuple.hxx:73
An RNTuple that gets filled with entries (data) and writes them to storage.
Definition: RNTuple.hxx:169
The Canvas class.
Definition: TCanvas.h:27
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
Definition: TFile.cxx:3942
1-D histogram with a float per channel (see TH1 documentation)}
Definition: TH1.h:571
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition: TLeaf.h:49
TRangeDynCast is an adaptater class that allows the typed iteration through a TCollection.
Definition: TCollection.h:411
A TTree represents a columnar dataset.
Definition: TTree.h:78
Definition: tree.py:1
auto * l
Definition: textangle.C:4