Walkthrough: Making a histogram with Analyze
Edit the file Analyze.C. In the Definitions section, insert the following code:
TH1* chi2Hist = NULL;
This means “define a new histogram pointer and call it
Why define this as a pointer when plain ol’ variables are easier to use?
The short answer is that ROOT uses pointers all the time; for example,
if you want to read something from a file, you must always use pointers.
The sooner you get used to pointers, the better.1
Don’t forget the semi-colons “;” at the ends of the lines! You can omit them in interactive commands, but not in macros.
In the Initialization section, insert the following code:
chi2Hist = new TH1D("chi2","Histogram of Chi2",100,0,20);
This means “set this pointer to a new histogram object.” We’re doing this here, instead of the Definitions section, because sometimes you want quantities like histogram limits to be variable rather than fixed; e.g., they depend on user input.
In the Loop section, put this in:
The first of these two lines means “get the ‘(entry+1)-th’ row
TTree”; e.g., if
entry is 100, get the 101st row from the
n-tuple.2 Note that the variable
entry comes from an argument to the
Process method, so you don’t have to set it. This line will assign
values to variables defined in the n-tuple:
and so on.3 In code prepared by
MakeSelector, the variables
extracted from an n-tuple are pointers; they have to be prefixed with
“*” to access their values.
The second line means “in the histogram
chi2Hist add 1 to a bin that
corresponds to the value of
This goes in the Wrap-up section:
You already know what this does; you’ve used it before!
Save the file, quit and restart ROOT, then enter the same commands as before:
 TFile myFile("experiment.root")  tree1->Process("Analyze.C")
Finally, we’ve made our first histogram with a C++ analysis macro. In the Initialization section, we defined a histogram; in the Loop section, we filled the histogram with values; in the Wrap-up section, we drew the histogram.
“What histogram? I don’t see anything!” Don’t forget: if you have the TBrowser open, you may need to click on the Canvas 1 tab.
How did I know which bin limits to use on
chi2Hist? Before I wrote
the code, I drew a test histogram with the command:
Hmm, the histogram’s axes aren’t labeled. How do I put the labels in the macro? Here’s how I figured it out: I labeled the axes on the test histogram by right-clicking on them and selecting. I saved the canvas by selecting . I looked at c1.C and saw these commands in the file:
chi2->GetXaxis()->SetTitle("chi2"); chi2->GetYaxis()->SetTitle("number of events");
I scrolled up and saw that ROOT had used the variable
chi2 for the
name of the histogram pointer. I copied the lines into Analyze.C, but
used the name of my histogram instead:
chi2Hist->GetXaxis()->SetTitle("chi2"); chi2Hist->GetYaxis()->SetTitle("number of events");
Try this yourself: add the two lines above to the Initialization section, right after the line that defines the histogram. Test the revised Analyze class.
Why are we defining a pointer then setting it equal to
NULL? I’m teaching you to avoid a common problem in programming: uninitialized variables. If we didn’t set
NULL, what would its value be? I don’t know. It would likely be set to zero, which is also the typical value of
NULL. But this behavior varies between different C++ compilers. It’s better to be sure.
This is not an issue in the code we’re writing now, but in the future you’ll discover that uninitialized variables cause lots of crashes. Let’s get into good programming habits and avoid them from the start.
Some compilers offer another name for
nullptr. They both have the same value, but for you one may be clearer than the other.
Actually, in the context of
MakeSelectorit means “get the data from the
TTreepointed to by
Note that when
GetEntrywill fetch the first row in the n-tuple; that’s why when
GetEntrywill fetch the 101st row in the n-tuple.
It’s mildly annoying that whenever you use
MakeSelectorto create an analysis skeleton, you must remember to put a
MakeSelectoris doing everything else for us, why can’t it put in that one line too so we don’t have to remember?
The answer is that there’s more that can be done with the
TSelectorskeleton than we’re doing in this course; do a web search on “TSelector example” for some ideas. Since there are times when a simple line like
GetEntry(entry)is not what you want, or you might create an analysis skeleton for one tree and use it on another,
MakeSelectormakes you put in the