(analyze-tree-c-reader)= # Walkthrough: Using a C++ TTreeReader to analyze a Tree **(10 minutes)** :::{admonition} Why TTreeReader? :class: note If you look through the [ROOT TTree examples](https://root.cern/doc/master/group__tutorial__tree.html), you'll see that using [`TTreeReader`](https://root.cern/doc/master/classTTreeReader.html) is the preferred method for reading n-tuples and TTrees. ::: I've prepared an example to get you started. In your UNIX window, copy {file}`AnalyzeReader.C` from my home directory:[^remote] > cp ~seligman/root-class/AnalyzeReader.C [^remote]: If you're not at Nevis, you can [download it](https://www.nevis.columbia.edu/~seligman/root-class/files/). Take a look: > less AnalyzeReader.C Here's an abbreviated version of that file, without some of the comments: [^reader] [^reader]: If you're working through all the sections in this tutorial, Your first reaction on looking at this code is that it doesn't look much like {file}`Analyze.C`, the code that we saw in {numref}`Listing %s `. It's actually the same code, but it's arranged differently. In that {ref}`walkthrough `, I have you use `MakeSelector` to create an "code skeleton" for you. The `TTreeReader` and `TTReaderValue` declarations were "hidden" in {file}`Analyze.h`, so you could focus on the event loop. {numref}`Listing %s ` is simpler, but I chose not to introduce a newcomer C+\+\-based analysis with this code because: - It uses a template (as in `TTreeReaderValue`). For students who are relatively new to C++, this can be confusing. - `TTreeReader` and `TTReaderValue` are not normally used in Python/pyroot. I want the C++ code and the Python code (in {numref}`Listing %s `) to resemble each other. :::{code-block} c++ :name: analyze-c-code-reader :caption: Example C++ TTreeReader macro void AnalyzeReader() { //******** Definition section ********* //******** Initialization section ********* // Open the file containing the tree. TFile* myFile = TFile::Open("experiment.root"); // Create a TTreeReader for the TTree "tree1" in 'myFile'. TTreeReader myReader("tree1", myFile); // Tell the TTreeReader which branches (or columns) we'll read. TTreeReaderValue ebeam(myReader, "ebeam"); // Loop over all the entries of the TTree. while (myReader.Next()) { //******** Loop section ********* } //******** Wrap-up section ********* } ::: Compare this with the Python code in {numref}`Listing %s `. While you look through the code, it helps to understand the typical steps needed for an analysis task: - **Definition** -- define the variables we're going to use. - **Initialization** - open files, create histograms, etc. - **Loop** - for each event in the n-tuple or Tree, perform some tasks: calculate values, apply cuts, fill histograms, etc. - **Wrap-up** - display results, save histograms, etc. For this macro, the Definition and Initialization parts aren't really distinct, the way they are in a {ref}`TSelector macro `. :::::{admonition} A closer look (optional) :class: note Let's take a more abstract view of the key statements in {numref}`Listing %s `: ``` TFile* file = TFile::Open(NameOfFile); ``` This opens a ROOT file (in read-only mode by default). - **`file`** = A variable that contains the pointer to a ROOT file. - **`NameOfFile`** = A C-style string constant containing the name of the ROOT file. ``` TTreeReader myReader(NtupleName, file); ``` - **`myReader`** = The name of the `TTreeReader` variable. This will be used to fetch the contents of an n-tuple from the file. - **`NtupleName`** = A C-style text string with the name of the n-tuple within the file. ``` TTreeReaderValue branchVariable(myReader, BranchName); ``` - **`TYPE`** = This is the C++ type of the variable stored in the branch (or column) in the n-tuple; e.g., `int`, `float`, `double`, etc. - **`branchVariable`** = A variable that acts like a pointer to the value of the given branch. - **`BranchName`** = A C-style text string that contains the name of the branch in the n-tuple. In a typical analysis task, you'll have one `TTreeReaderValue` definition for every branch you want to access. How do you know the names and types of the branches? What I usually do is load the file in interactive ROOT and use the `TTree::Print()` method:[^prompts] > root experiment.root [] tree1->Print() [^prompts]: Don't forget that I use the different prompts to indicate whether you're running in {ref}`UNIX or ROOT `. Don't actually type the `>` or `[]`! When I type those commands, what I see is this: ``` ****************************************************************************** *Tree :tree1 : Reconstruction ntuple * *Entries : 100000 : Total = 2810761 bytes File Size = 2171135 * * : : Tree compression factor = 1.30 * ****************************************************************************** *Br 0 :event : event/I * *Entries : 100000 : Total Size= 401519 bytes File Size = 134514 * *Baskets : 12 : Basket Size= 32000 bytes Compression= 2.85 * *............................................................................* *Br 1 :ebeam : ebeam/F * *Entries : 100000 : Total Size= 401519 bytes File Size = 260330 * *Baskets : 12 : Basket Size= 32000 bytes Compression= 1.47 * *............................................................................* *Br 2 :px : px/F * *Entries : 100000 : Total Size= 401465 bytes File Size = 359238 * *Baskets : 12 : Basket Size= 32000 bytes Compression= 1.07 * *............................................................................* *Br 3 :py : py/F * *Entries : 100000 : Total Size= 401465 bytes File Size = 359138 * *Baskets : 12 : Basket Size= 32000 bytes Compression= 1.07 * *............................................................................* *Br 4 :pz : pz/F * *Entries : 100000 : Total Size= 401465 bytes File Size = 292046 * *Baskets : 12 : Basket Size= 32000 bytes Compression= 1.31 * *............................................................................* *Br 5 :zv : zv/F * *Entries : 100000 : Total Size= 401465 bytes File Size = 349087 * *Baskets : 12 : Basket Size= 32000 bytes Compression= 1.10 * *............................................................................* *Br 6 :chi2 : chi2/F * *Entries : 100000 : Total Size= 401501 bytes File Size = 321049 * *Baskets : 12 : Basket Size= 32000 bytes Compression= 1.20 * *............................................................................* ``` Most of what you see is not relevant to this tutorial; for example, you're not going to care about "Baskets" unless you want to optimize ROOT I/O for gigabyte-size files. What's important here are the names of the branches; e.g.; ``` *Br 6 :chi2 : chi2/F ``` tells you that the sixth branch's name is `chi2`. More important, it also tells you the type of the variable: `chi2/F` means that type of `chi2` is `float`. So if you wanted to access the value of `chi2`, you'd include a statement like: TTreeReaderValue chi2(myReader, "chi2"); You can find the correspondence between the C++ types and those one-letter abbreviations on the [TTree documentation page](https://root.cern/doc/master/classTTree.html). :::::