18.2 Loading Data
Table of Contents
Reading TTrees
In modern ROOT analysis, RDataFrame is the recommended way to work with TTrees. Instead of writing explicit event loops, you create an RDataFrame that is logically connected to one or more TTrees, then express your analysis as a sequence of transformations.
The most common constructor in C++ takes a TTree name and one or more input files:
#include "ROOT/RDataFrame.hxx"
void example() {
ROOT::RDataFrame df("Events", "data.root");
}
Here, "Events" is the name of the TTree, and "data.root" is the ROOT file that contains it. After this line, df represents all entries of the TTree Events from data.root. No data are loaded yet. The actual reading happens only when you trigger an action such as creating a histogram or counting entries.
You can also give a list of input files. RDataFrame then internally creates a TChain and processes all entries as if they were one long tree:
std::vector<std::string> files = {
"data_run1.root",
"data_run2.root",
"data_run3.root"
};
ROOT::RDataFrame df("Events", files);If all files contain a TTree with the same name, branch structure, and compatible types, RDataFrame will iterate over the combined dataset transparently.
It is often convenient to use wildcards for file names. In that case you pass a pattern string that matches multiple files, for example:
ROOT::RDataFrame df("Events", "data_run*.root");
RDataFrame expands the pattern, opens all matching files, and processes their Events TTrees.
If you already have a TTree pointer, for example after opening a TFile and retrieving the tree manually, you can also build an RDataFrame directly from that pointer:
TFile *f = TFile::Open("data.root");
TTree *tree = nullptr;
f->GetObject("Events", tree);
ROOT::RDataFrame df(*tree);This form is useful when the TTree is not in the top-level directory, or when it comes from more complex setups such as friends or custom TChains that you prepared yourself.
Whenever you create an RDataFrame from a TTree, the available columns correspond to the branches of that TTree. Scalar branches become scalar columns, and array-like or std::vector branches become columns that you can use with operations that understand container types.
Important rule: When constructing ROOT::RDataFrame, the first argument is always the TTree name (or an existing TTree reference), and the second argument is the input file or files. All input TTrees must have compatible structures.
There is also a convenience factory ROOT::RDF::MakeCsvDataFrame and other helpers, but for TTrees inside ROOT files the standard constructors are sufficient and are the usual starting point for analysis with RDataFrame.
Reading ROOT files
RDataFrame can open ROOT files on its own when you give it a file name. You do not have to manage TFile objects manually. For simple cases, you only need the TTree name and the file or files:
ROOT::RDataFrame df("Events", "data.root");
Internally, RDataFrame opens data.root, looks for a TTree named Events, and uses it as the data source. The TFile is kept open as long as the RDataFrame and its result objects exist. You should not close the file by hand when you let RDataFrame manage it.
If needed, you can still open a file first, inspect its content, and then construct an RDataFrame. This is useful when you are not sure about the TTree name or want to explore the file interactively:
TFile f("data.root");
f.ls(); // inspect file contents in the ROOT shell
TTree *tree = nullptr;
f.GetObject("Events", tree);
ROOT::RDataFrame df(*tree);In this pattern, you control the TFile lifetime. The file must remain open for as long as you use the RDataFrame that reads from the TTree inside it. If the TFile goes out of scope or is closed, the underlying TTree becomes invalid and RDataFrame can no longer read data.
When your dataset is split across multiple ROOT files, you can let RDataFrame open them directly:
ROOT::RDataFrame df("Events", {
"data_part1.root",
"data_part2.root",
"data_part3.root"
});or, using a pattern string:
ROOT::RDataFrame df("Events", "data_part*.root");RDataFrame then handles all file opening, chaining, and iteration for you. This is particularly convenient for large experimental datasets that are stored as many smaller ROOT files.
If you are working in PyROOT, the syntax is very similar. For example:
import ROOT
df = ROOT.RDataFrame("Events", "data.root")and for multiple files:
files = ["data_run1.root", "data_run2.root"]
df = ROOT.RDataFrame("Events", files)Here too, ROOT manages the underlying TFiles automatically.
Important rule: When RDataFrame is constructed from file names, do not close the underlying TFiles manually. Let RDataFrame manage them. If you open TFiles yourself and pass TTrees to RDataFrame, ensure the files stay open for the entire lifetime of any actions that read from the TTrees.
In summary, loading data for RDataFrame usually requires only the TTree name and one or more ROOT files. Whether you let RDataFrame open the files or you open them yourself, the result is the same: a high level interface that lets you define your analysis declaratively, without writing explicit loops over events.
Views: 8
KAHIBARO