Basic ROOT Tutorial Collaboration Meeting Jun2019: Difference between revisions

From Mu2eWiki
Jump to navigation Jump to search
No edit summary
Line 267: Line 267:


===Exercise 9: Basic event loop===
===Exercise 9: Basic event loop===
Most analyses will require more processing than can be done with a simple Draw command. In these cases we will use an event loop, where we iterate over every entry in our TTree and can do arbitrary operations on all the branches for that entry. We will create a simple ROOT macro to try this.
* Note that there are several ways to do this! In this exercise we will go over the old way, you can look up TTreeReader if you want to see a newer method. The end result is practically the same.
<ol style="list-style-type:lower-alpha">
<li>First we will generate a very simple TTree. Run scripts/treeBuild.C</li>
  >.x scripts/treeBuild.C
<li>This should create a file treeBuild.root in your directory. First lets quickly look at the script you ran. You will see that this script creates a tree with two branches: a single float num1, and an array of 10 floats num2. You can also check the root file created in the TBrowser to see if it looks like you expect.</li>
<li>Lets create a script to check how many events in the TTree have num1 != any of the values in num2. We could try writing a Draw command and cut on "num1 != num2[0] && num1 != num2[1] &&..." but this way we can use a normal "for" loop in our script.</li>
* We will start our script by creating a TFile to read in our existing root file:
  TFile *fin = new TFile("treeBuild.root","READ");
* Next we will create a variable pointing at the TTree, which from treeBuild.C we can see is named "T":
  TTree *t = (TTree*) fin->Get("T");
* We next have to create variables to hold the values of each branch, in this case a float and an array of 10 floats
* Finally, we point the tree at these variables for each branch using the command:
  t->SetBranchAddress("<name of branch>",&<name of variable>);
* We can now loop over the entries in our tree. We can get the total number of entries with the function
  t->GetEntries()
and for each entry, in order to load the values of num1 and num2 into our float variables we must call
  t->GetEntry(<entry number>)
<li>Try writing a script to print out the index of the entries where num1 != any num2. If you need help, you can look at solutions/treeRead.C</li>
<ol>


===Exercise 10: MakeClass===
===Exercise 10: MakeClass===

Revision as of 18:54, 13 June 2019

Tutorial Session Goal

In this Tutorial you will learn the basics of ROOT. The final aim being to learn how to analyze TTree data produced by the Mu2e Offline software.

Session Prerequisites and Advance Preparation

As this is a basic introduction, few prerequisites are necessary, however, it would be beneficial if attendees:

  • Take a look at [1].
  • Download and install from this page to your machine.
  • It will be very useful to have a Fermilab account and have a working version of Mu2e Offline code.

ROOT: An introduction

ROOT is a modular scientific software toolkit used extensive in High Energy and Particle Physics. ROOT provides a platform for data processing, statistical analyses, visualisation and data storage.

ROOT is an object-orientated framework predominately written in c++.

For more information: https://root.cern.ch/

The Basics

ROOT uses a C++ interpreter, you can use it on command line, no need to use ";" at the end of every line.

Some basic commands:

  • -".q" - quits ROOT
  • - ".?" - displays special commands
  • - ".x Example.C" - executes the macro in Example
  • -".L Example.C" - Loads Example and the associated classes within

What is a TTree?

TTrees are used through out particle physics as data containers. They can be form both input and output files in a ROOT macro.

Exercises

The majority of the session time should be spent performing exercises, which you link or embed in the session page.

For these exericses please download the .root file located here "/mu2e/app/users/sophie/tutorial" if you do not have Fermilab access let me know before the session.

Exercise 1: Open the and look at content with a TBrowser

  • Once you have downloaded and installed root, open a new terminal.
  • Type "root" - this will open up root in interactive mode (you should see the root logo flash up and you are then in the root environment)
  • Open up the file by typing:
TFile::Open("$FullPathToFile/FileName.root")


This file will contain the TTree, this is a data container used by root and by the Mu2e Offline software.

  • View the contents of the File by typing:
.ls

You should see a list of the contents of the file.

  • You can create a TBrowser called "a" using the following in the command line:
 TBrowser a 

A GUI browser should appear which lists files in your current directory. You should see the .root file. You can select the file. You will see the TTree and various associated TBranches. Select one - a histogram should appear.

You can project a histogram in the TBrowser.

Exercise 2: Reading a TTree

You can find all the methods which can be applied to a TTree Class object here: https://root.cern.ch/doc/master/classTTree.html

There are a few ways to Read a TTree, for example:

TFile f("ExampleFile.root")
myTree->Print()

An alternative approach is to use the TTree::Scan function to loop over the TTree entries and print entries passing given selection:

TTree::Scan("leaf":"leaf":….)

Exercise 3: Plotting from command line

You can use root to plot functions for example:

TF1 f1("f1","sin(x)/x",-10,10)
f1.Draw()

This command displays the function in a window which should pop up after you typed the above two lines.

You can also build histograms on the command line:

TF1 func("efunc","exp([0]+[1]*x)",0.,5.)
func.SetParameter(0,1)
func.SetParameter(1,-1)
TH1F h("h","example histogram",100,0.,5.)
for (int i=0;i<1000;i++) {h.Fill(efunc.GetRandom())}
h.Draw()

Exercise 3: Write a macro to produce histograms

This example is a standalone exercise to illustrate use of macros. We will go back to existing root files later.

If you have a number of lines which you were able to execute at the ROOT prompt, they can be turned into a ROOT macro by giving them a name which corresponds to the file name without extension, for example, if you create a file ExampleMacro.C which contains:

void ExampleMacro() {
       ....YOUR FUNCTION....
}

You can execute the macro by typing:

.x ExampleMacro.C

You can load the macro into the root session by typing:

.L ExampleMacro.C

Now we shall create a simple macro to analyse some of the data from the .root file provided.

Here is an example macro, this is a basic plotting function which plots a function then builds a histogram based on that function:

First you will need to include the relevant ROOT libraries. Here we state explicitly which we use:

// 1-D histogram drawing options
#include "TCanvas.h"
#include "TPad.h"
#include "TFormula.h"
#include "TPaveLabel.h"
#include "TFile.h"
#include "TBenchmark.h"

This is the macro body:

void ExampleMacro()
{
  //create a TCanvass
  TCanvas *c1 = new TCanvas("c1","Histogram Example",200,10,700,900);
  //Set up 2 TPads:
  auto pad1 = new TPad("pad1","The pad with the function",0.05,0.50,0.95,0.95);
  auto pad2 = new TPad("pad2","The pad with the histogram",0.05,0.05,0.95,0.45);
  pad1->Draw();
  pad2->Draw();
  pad1->cd();
  gBenchmark->Start("fillrandom");
  
  //Any function can be used here but we have chosen this one
  auto form1 = new TFormula("form1","abs(sin(x)/x)");
  auto sqroot = new TF1("sqroot","x*gaus(0) + [3]*form1",0,10);
  sqroot->SetParameters(10,4,1,20);
  //Some Styling:
  pad1->SetGridx();
  pad1->SetGridy();
  pad1->GetFrame()->SetBorderMode(-1);
  pad1->GetFrame()->SetBorderSize(5);
  sqroot->SetLineColor(4);
  sqroot->SetLineWidth(6);
  //Draw the function in pad1
  sqroot->Draw();
  auto lfunction = new TPaveLabel(5,39,9.8,46,"The sqroot function");
  lfunction->Draw();
  //Update the TCanvas to add this plot to that canvas.
  c1->Update();
  
  // Create a one dimensional histogram (one float per bin) and fill it following the distribution in function sqroot.
  //This will take place in the second TPad:
  pad2->cd();
  pad2->GetFrame()->SetBorderMode(-1);
  pad2->GetFrame()->SetBorderSize(5);
  auto h1f = new TH1F("h1f","Test random numbers",200,0,10);
  h1f->SetFillColor(45);
  h1f->FillRandom("sqroot",10000);
  h1f->Draw();
  c1->Update();
  //Save to a root file:
  TFile myfile("fillrandom.root","RECREATE");
  form1->Write();
  sqroot->Write();
  h1f->Write();
  gBenchmark->Show("fillrandom");
}

Exercise 4: Styling

Root has a diverse range of histogram and graph styles. Many options are discussed here: https://root.cern.ch/doc/master/classTAttMarker.html

You can fill histograms with various colours via

 h1f->SetFillColor(...)

Similarly, you can change the line color using

  h1f->SetLineColor(...)

Have a play with the various options.

Exercise 5: Axes, Legends and Labels

Axes of histograms have there own class "TAxis". You will want to label you axes. This can be done via:

 h1f->GetXaxis()->SetTitle("......")

and likewise for the y-axis. If you want to add a special character (like a symbol/greek letter) you can add using the "#" e.g.type "#theta."

You can switch to a log y-axis via:

TCanvas c1; 
c1.Setlogy();

In the case when you have multiple plots or fit lines on you histogram you may wish to add a legend. To do this use the TLegend class. You can add code like this to produce a legend and add it to your canvas:

  auto legend = new TLegend(0.1,0.7,0.48,0.9);//places the histogram
  legend->SetHeader("The Legend Title","C"); // option "C" allows to center the header
  legend->AddEntry(h1f,"Histogram filled with random numbers","f");
  legend->Draw();

Exercise 5: Compiling Code

Code can be compiled a number of ways.

1) Generate an object library from the macro code, inside the interpreter type:

.L ExampleMacro.C+

Note the use of the "+" here. Once this operation is accomplished, the macro functions are in memory and you will be able to execute them by calling from inside the interpreter:

ExampleMacro()

We will not got through this part but it is useful to know:

2)Compile with a c++ compiler e.g. gcc. In order to make the code executable stand-alone, you must have a main function defined, for example:

int main() {
 ExampleMacro();
 return 0;
}

Can be added to the end of your macro. Now compile using:

g++ -o ExampleMacro ExampleMacro.C `root-config --cflags --libs`

or similar if you use another platform.

You can now execute the macro by typing:

./ExampleMacro

Exercise 6: Saving the histograms to a file (.root)

You will have seen in the example macro the final few lines:

  TFile myfile("fillrandom.root","RECREATE");
  form1->Write();
  sqroot->Write();
  h1f->Write();
  

This wrote the various functions and histograms to a .root file named "fill random.root". To save the histogram as a .root file. This will allow you to use it in other analyses in root, type:

MyHist->Write()

Any root object can be written to a .root file in this manner.

Exercise 7: Saving the histogram as .png, pdf ....

Exercise 8: Chaining multiple input files together

A TChain is a collection of files containing TTree objects. Use TChain::Add to add a new element to this chain, for example, if three files each contain a TTree called "Position" then you could write:

TChain chain("Position")
chain.Add("particle1.root");
chain.Add("particle2.root");
chain.Add("particle3.root");
chain.Draw("x"); 

the last line processes variable "x" from the "Position" TTree.

You can see an example of a file chain in the file /mu2e/app/users/sophie/AnalysisExample.C

Exercise 9: Basic event loop

Most analyses will require more processing than can be done with a simple Draw command. In these cases we will use an event loop, where we iterate over every entry in our TTree and can do arbitrary operations on all the branches for that entry. We will create a simple ROOT macro to try this.

  • Note that there are several ways to do this! In this exercise we will go over the old way, you can look up TTreeReader if you want to see a newer method. The end result is practically the same.
  1. First we will generate a very simple TTree. Run scripts/treeBuild.C
  2. >.x scripts/treeBuild.C
  3. This should create a file treeBuild.root in your directory. First lets quickly look at the script you ran. You will see that this script creates a tree with two branches: a single float num1, and an array of 10 floats num2. You can also check the root file created in the TBrowser to see if it looks like you expect.
  4. Lets create a script to check how many events in the TTree have num1 != any of the values in num2. We could try writing a Draw command and cut on "num1 != num2[0] && num1 != num2[1] &&..." but this way we can use a normal "for" loop in our script.
    • We will start our script by creating a TFile to read in our existing root file:
    TFile *fin = new TFile("treeBuild.root","READ");
    • Next we will create a variable pointing at the TTree, which from treeBuild.C we can see is named "T":
    TTree *t = (TTree*) fin->Get("T");
    • We next have to create variables to hold the values of each branch, in this case a float and an array of 10 floats
    • Finally, we point the tree at these variables for each branch using the command:
    t->SetBranchAddress("<name of branch>",&<name of variable>);
    • We can now loop over the entries in our tree. We can get the total number of entries with the function
    t->GetEntries() and for each entry, in order to load the values of num1 and num2 into our float variables we must call t->GetEntry(<entry number>)
  5. Try writing a script to print out the index of the entries where num1 != any num2. If you need help, you can look at solutions/treeRead.C
    1. Exercise 10: MakeClass

      Exercise 11: Pyroot

      Reference Materials