Start Using ROOT

Welcome to the first hands-on session. We will focus on introductory exercises for getting started working with the ROOT environment and writing our first ROOT macro. Two levels of help will be provided: a hint and a full solution. Try not to jump to the solution even if you experience some frustration. The help is organised as follow:

Here the hint is shown.

Here the solution is shown.

Some points linked to the exercises are optional and marked with a Pointing hand icon: they are useful to scrutinise in more detail some aspects. Try to solve them if you have the time.

Before starting the exercise 1, follow what is written in the lecture

Start using the ROOT prompt

First of all open a Visual Studio Command window on your computer and type

If this does not work, then it means ROOT is not properly installed in your system. Stop here and ask for help to fix the installation. If it works then start playing with the prompt. Use as a calculator and type:
root [0] 2+2
or whatever you like (see for example the lecture slide) or page 5 of the booklet ("A ROOT Guide for Beginners"). Note that after having issue a statement from the ROOT prompt, you can omit the ; required by C++. This will make ROOT printing the returned value, if there is one. For example:
root [0] TMath::Pi();
will not print anything, while
root [0] TMath::Pi()

Afterwards start writing your first ROOT macro. A ROOT macro is a file containing some C++ code which can be run from the ROOT prompt. You need to define a function and in the function scope you write the code. For example, you create a file, which you will call mymacro.C. Inside the file you define a function mymacro(int value) and you write the code of slide 8 of the lecture (or something else, if you prefer). The you can run the macro from the ROOT prompt by typing:

root [0] .x mymacro.C(42)
Note that if the function name is different than the macro (file) name, you need two steps to run. First you load the macro:
root [0] .L mymacro.C
Then you run the function in the macro. Let's assume the function name is test(int value):
root [1] test(42)

After having followed this introduction, you can try to solve the first exercise.

Exercise 1: Computing PI

The aim of this exercise is to write a ROOT macro which can compute the number PI. You can deduce the number PI from the area of a circle with unitary radius. You can compute the area of the first quadrant of the circle by generating random points (x,y) , which are uniform distributed in the interval [0,1]. The function to generate uniform random number in the interval [0,1] is

root [0] gRandom->Rndm()
If you throw for example one million random points, which value of PI do you obtain ? How is it different from the real value of PI, which you can get in ROOT by using TMath::Pi() ?

To solve the exercise you would need:
  • make a loop on the n number of points you want to generate
  • inside the loop you throw two random numbers, uniformly distributed between [0,1], that we can call x and y
  • compute the radius of the point (x,y) : r = x^2 + y^2
  • if r < 1= accept the point and increase a counter
  • if r > 1 do nothing and continue
  • the ratio of the number of accepted points to n, will then be equal to the area of the first quadrant, which is PI/4

This we can do in C++ by making a for loop and we call the function to generate the random x and y numbers:

for (int i = 0; i < n; ++i) { 
    double  x = gRandom->Rndm();
    double y = gRandom->Rndm(); 

    // count the number of accepted points (x^2 + y^2 <= 1)

After having written and run the macro, try to compile it using ACLIC. For compiling the macro, you need to add to include the required header files, thus you need to add at the beginning of the code:

#include "TRandom.h"       // for using  gRandom
#include "TMath.h"            // for using TMath
Then, you can compile with ACLIC, by adding a + at the end
root[0] .x computePI.C+
Note the difference in time by using ACLIC, by generating for example more points (e.g. 10E8).

#include "TRandom.h"
#include "TStopwatch.h"
#include "TMath.h"
#include <iostream>

void computePI(int n = 1000000) {

   int nin = 0;

   TStopwatch w;   // for measuring the time                                                                                                    

   for (int i = 0; i < n; ++i) {

      double x = gRandom->Rndm();
      double y = gRandom->Rndm();

      if ( (x*x + y*y) < 1.)  nin++;


   double pi4 = nin/double(n);

   std::cout << "Computed  PI is " << pi4*4 << std::endl;
   std::cout << "Real PI  is  " << TMath::Pi() << " difference = " << TMath::Pi()-pi4*4 << std::endl;


Pointing hand Can you measure the time of generating 10E8 points using CINT or ACLIC. How much faster is ACLIC ? You can use the ROOT class TStopwatch for measuring the elapsed time. Add at the begining of the macro (before the loop)

TStopwatch w; 
and after the end of the macro

Exercise 2: Plotting a Function in ROOT

Following slide 13 of the lecture or page 6 of the Introductory Guide, create a TF1 class using the sin(x)/x function and draw it.

Create then a function with parameters, p0 * sin ( p1 * x) /x and also draw it for different parameter values. You can try to change the parameter values using TF1::SetParameters or by using the ROOT GUI. Try also to change the style of the line and its color. You can either use the ROOT GUI and/or use the methods of the class TAttLine (see TAttLine reference documentation). Since TF1 derives from TAttLine, it inherits all its functions. Try for example to set the colour of the parametric function to blue.

After having drawn the function, compute for the parameter values (p0=1, p1=2):

  • function value for x = 1.
  • function derivative for x = 1
  • integral of the function between 0 and 3.

To solve the exercise you need to :
  • create a TF1 object using a formula expression. In the case of a parametric functions, the two parameters are defined as [0] and [1]
  • call TF1::Draw()

You can also find the available function of the class TF1, by using the Tab key on the ROOT prompt, for example

root [0] TF1 * f1 = ....
root [1] f1-><TAB>
And you can get the full signature of a method by doing for example:
root [1] f1->Derivative(<TAB>

#include "TF1.h"

void plotFunction() {

   TF1 * f1 = new TF1("f1","sin(x)/x",0,10);

   TF1 * fp = new TF1("fp","[0]*sin([1]*x)/x",0,10);

   // to change axis y margins                                                                                                                  
   // (or invert the order of plotting the functions)                                                                                           

   std::cout << "Value of f(x) at x = 1 is       " << fp->Eval(1.) << std::endl; 
   std::cout << "Derivative of f(x) at x = 1 is  " << fp->Derivative(1.) << std::endl; 
   std::cout << "Integral of f(x) in [0,3] is    " << fp->Integral(0,4)  << std::endl;

Pointing hand You can try to use a different function, for example the Gamma distribution, defined in ROOT::Math::gamma_pdf. Try to make a plot as the one in Wikipedia, see here, where the function is plot for different parameter values. See the here the reference documentation of the gamma distribution in ROOT.

#include "TF1.h"
#include "Math/DistFunc.h"

void plotGamma() {

   // Note that parameter [0] is called alpha in definition of gamma_pdf or kappa in Wikipedia                                                  
   // Note that parameter [1] is  theta                                                                                                         

   // use range [0,20] as in Wikipedia plot                                                                                                     
   TF1 * f1 = new TF1("f","ROOT::Math::gamma_pdf(x,[0],[1])",0,20);


   // use DrawClone because we will plot many different copies of same object but with different                                                
   // parameter values                                                                                                                          

   // now change parameters and draw at different parameter values                                                                              





Exercise 3: Plotting Measurement Points in ROOT

We will learn in this exercise how to plot a set of points in ROOT using the TGraph class.

Suppose you have this set of points:

  • x = 1; y = 0.4
  • x = 2; y = 0.3
  • x = 3; y = 0.5
  • x = 4; y = 0.7
  • x = 5; y = 1.3

Plot these points using the TGraph class. Use as a marker point a black box. Looking at the possible options for drawing the TGraph in TGraphPainter, plot a line connecting the points.

To solve the exercise you need to :
  • create an array for the X points: double x[] = {1,2...
  • create an array for the y points
  • create the TGraph from the X and Y arrays

Alternatively you can create first an empty TGraph object and set the point one by one by calling TGraph::SetPoint

void plotGraph() {

   double x[] = {1.,2.,3.,4.,5.};
   double y[] = {0.4,0.3,0.5.,0.7,1.3};

   TGraph * g = new TGraph(5,x,y);



Pointing hand Make a TGraphError by adding an error of 0.3 in X and 0.2 in Y for every point.

Exercise 4: Making an histogram in ROOT

We will learn in this exercise how to create a one-dimensional histogram in ROOT, how to fill it with data and how to plot it.

Create a one-dimensional histogram with 50 bins between 0 10 and fill it with 10000 gaussian distributed random numbers with mean 5 and sigma 2. Plot the histogram and, looking at the documentation in the THistPainter, show in the statistic box the number of entries, the mean, the RMS, the integral of the histogram, the number of underflows, the number of overflows, the skewness and the kurtosis.

For generating gaussian random numbers use gRandom->Gaus(mean, sigma)

#include "TH1.h"
#include "TRandom.h"
#include "TStyle.h"

void plotHistogram() { 

   TH1D * h1 = new TH1D("h1","h1",50,0,10);

   for (int i = 0; i < 10000; ++i) {
      double x = gRandom->Gaus(5,2);




Pointing hand After calling the function TH1::ResetStats() , you will see that the statistics (mean, RMS,..) of the histogram is slightly different. Try to understand the reason for this, by trying for example to compute the mean of the histogram yourself.

The initial statistics is computed using the original (un-binned) data, while after calling ResetStats(), the statistics is computed using the bin contents and centres (binned data).

Pointing hand The following macro, creating, filling and plotting histogram contains an error, which one ?

#include "TH1.h"

void testPlotHistogram() { 

   TH1D h1("h1","h1",50,-5,5);


The histogram objected is deleted at the end of the macro, therefore it is not shown in the plot after exiting the macro. To fix it, either call TH1::DrawClone or create the histogram using operator new as in the previous example.
Edit | Attach | Watch | Print version | History: r8 < r7 < r6 < r5 < r4 | Backlinks | Raw View | WYSIWYG | More topic actions
Topic revision: r8 - 2013-02-28 - LorenzoMoneta
    • Cern Search Icon Cern Search
    • TWiki Search Icon TWiki Search
    • Google Search Icon Google Search

    Main All webs login

This site is powered by the TWiki collaboration platform Powered by PerlCopyright & 2008-2021 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
or Ideas, requests, problems regarding TWiki? use Discourse or Send feedback