Walkthrough: Using a C++ selector to analyze a Tree

(10 minutes)

Note

The first step is to have ROOT write the skeleton of an analysis class for your n-tuple. This is done with the MakeSelector command.

Let’s start with a clean slate: quit ROOT if it’s running and start it up again. Open the ROOT tree again:

[] TFile myFile("experiment.root")

Now create an analysis macro for tree1 with MakeSelector. I’m going to use the name “Analyze” for this macro, but you can use any name you want; just remember to use your name instead of “Analyze” in all the examples below.

[] tree1->MakeSelector("Analyze")

Switch to the UNIX window and examine the files that were created:

> less Analyze.h
> less Analyze.C

A mass of code

Unless you’re familiar with C++, this probably looks like gobbledy-gook to you. (I know C++, and it looked like gobbledy-gook to me… at first.) We can simplify this by understanding the approach of most analysis tasks:

  • 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.

You’ve probably already guessed that the lines beginning with // are comments. They describe more than we’re going to use, so I’ll narrow things down below.1

Here’s a simplified version of the C++ code from Analyze.C. I’ve removed the automatically generated comments created by ROOT, and minimized the routines SlaveBegin and SlaveTerminate which we won’t use for this tutorial. I also marked the places in the code where you’d place your own commands for Definition, Initialization, Loop, and Wrap-up. Compare the code you see in Analyze.C with what I’ve put below. If you wish, you can edit the contents of your Analyze.C to match what I’ve done; it will give you practice using emacs or whatever text editor you choose.2

Listing 41: Example C++ TSelector macro
#define Analyze_cxx
#include "Analyze.h"
#include <TH2.h>
#include <TStyle.h>

//******** Definition section *********

void Analyze::Begin(TTree * /*tree*/)
{
    TString option = GetOption();

    //******** Initialization section *********
}

void Analyze::SlaveBegin(TTree* tree) {}

Bool_t Analyze::Process(Long64_t entry)
{
    // Don't delete this line! Without it the program will crash.
    fReader.SetEntry(entry);

    //******** Loop section *********
    // You probably want GetEntry(entry) here.

    return kTRUE;
}

void Analyze::SlaveTerminate() {}

void Analyze::Terminate()
{
    //******** Wrap-up section *********
}

Compare this with the Python code in Listing 39.


1

Many of the comments, as well as the routines SlaveBegin and SlaveTerminate refer to something called PROOF. This is a method of breaking up your n-tuple into sections and analyzing each section on a separate CPU core of your computer.

PROOF is now deprecated by the ROOT developers. If, by some rare chance, you do use PROOF, note that SlaveBegin and SlaveTerminate are where you put your initialization and wrap-up code, respectively, and Begin and Terminate should be “stubs.”

By the way, PROOF has nothing directly to do with batch processing, which I describe in one of the optional appendices of this course.

There’s another ROOT class that can speed up n-tuple analysis on machines with multiple cores; see The RDataframe Path.

2

You can copy the “reduced” file from my area if (A) you’re pressed for time, or (B) just feeling lazy today.

> cp ~seligman/root-class/Analyze.C $PWD