In [ ]:
%load_ext ROOTmagic

Introduction to ROOT

Andrew Kubera

ROOT

  • C++ Framework developed by CERN in the '90s to replace old FORTRAN code
  • Uses its own compiler/interpreter: CINT (C INTerpreter)
  • Can ALSO be compiled like a 'normal' C++ program
  • All classes start with letter 'T'
    • 1D histogram of doubles: TH1D
    • Random number generator: TRandom
    • Standard Output File: TFile
  • Does a lot of 'magic' in the background for you, so you don't have to worry about certain things
    • Can cause confusion for beginners
    • 'Automatic' memory management (create everything with new)
    • Stored type information (TClass)
    • Interpreter mode : No need for #include
  • Does NOT use templates, instead everything inherits from class TObject

Standards

  • ROOT Standards differ from the standard C++ library

  • Functions Start with capital letter, use capitals to separate words

    • file->FindObject("hist");
    • Good: obj->Write()
    • Bad : obj->write()
  • Standard function names start with a verb
    • Good: array->GetSize();
    • Bad : array->Size();
  • Exception to capitalization rule : Abbreviation or a single letter word:
    • Good: hist->GetXaxis()
    • Bad : hist->GetXAxis()

TObject

Mother of most ROOT classes.

Adds methods common to ROOT objects, such as Draw(), FindObject(), GetUniqueID(), IsA(), Write().

NOT an abstract class - you don't have to implement anything to use TObject as your parent class.

TObject Documentation

TBrowser

Interface for looking at objects (often histograms) and inspecting files.

Create with 'new TBrowser()'

TFile

Standard ROOT output file (.root extension). Will automatically grab objects created AFTER the file is opened.

TFile *file = new TFile("filename.root", "RECREATE");
TH1D *hist = new TH1D("hist", "My Histogram", 100, 0, 10);

... fill hist ...

file->Write(); // Saves hist in filename.root

TFile Documentation


In [11]:
%%ROOT

#include <TFile.h>
#include <TTree.h>
#include <TRandom.h>
#include <TH1D.h>
#include <iostream>

int main()
{
  TFile *file = new TFile("rangen.root", "RECREATE");
  TRandom *rnd = new TRandom();
  TH1D *hist = new TH1D("gaus", "Gaussian Distribution", 1000, -5, 5);

  for (int i = 0; i < 70000; i++) {
    double value = rnd->Gaus();
    hist->Fill(value);
  }

  file->Write();
  std::cout << "Done. Hurray!!";
  return 0;
}


Done. Hurray!!

TObjArray

ROOT's container of TObject pointers. Kind of like std::vector<TObject*>

TObjArray arr;

arr->Add(new TH1D("h0", "Histogram 0", 100, 0, 10));
arr->Add(new TH1D("h1", "Histogram 1", 100, 10, 100));
arr->Add(new TH1D("h2", "Histogram 2", 100, 100, 1000));

arr->FindObject("h1")->Fill(25);

TObjArray Documentation

TString

ROOT's implementation of string (NOT compatible with std::string!).

  • Not inherited from TObject. You cannot store in a TObjArray. :-(
    • Must use another class: TObjString
TString str("This is my string. It's just a bunch of chars");

// NO! std::cout << str << '\n'
std:cout << str.Data() << '\n'; // str.Data() returns
                                // char* to internal 
                                // character array

TObjArray *words = str.Tokenize(" "); // Break string into
                                   // tokens (around spaces)

for (int i = 0; i < words->GetEntries(); i++) {
  TString *word = words[i]->At(i);
  cout << "Next word is '" << word->Data() << "'\n"; 
}

TString Documentation


In [43]:
%%ROOT

#include <TString.h>
#include <TObjArray.h>
#include <TObjString.h>
#include <iostream>

using namespace std;

int main(){
TString str("This is my string. It's just a bunch of chars");

// NO! std::cout << str << '\n'
std:cout << str.Data() << '\n';
 
TObjArray *words = str.Tokenize(" "); // Break string into tokens (around spaces)

std::cout << "\nFound : "  << words->GetEntries() << " words \n\n";

for (int i = 0; i < words->GetEntries(); i++) {
  TString word = ((TObjString*)words->At(i))->GetString();
  cout << "Word " << i << " is '" << word.Data() << "'\n"; 
}
return 0;
}


This is my string. It's just a bunch of chars

Found : 10 words 

Word 0 is 'This'
Word 1 is 'is'
Word 2 is 'my'
Word 3 is 'string.'
Word 4 is 'It's'
Word 5 is 'just'
Word 6 is 'a'
Word 7 is 'bunch'
Word 8 is 'of'
Word 9 is 'chars'

Example :: Monte Carlo π

Idea: Find π using random numbers

  • Generate random points in an RxR square.
  • Find the ratio of number of points within the square to the number in the inscriped circle
  • Number of points is proportional to area
  • Ratio yields a number proportional to π
    • circle_area = $πr^2$
    • square_area = $(2r)^2$
    • circle_area/square_area = $π/4$
TRandom3 rng(); // Create Random Number Generator

int inside_circle = 0, total = 100; // total number and
                                    // number inside circle

for (int i = 0; i < total; i++) {
  double x = rng.Uniform(-1., 1.), // Get random x,y pair
         y = rng.Uniform(-1., 1.); // from uniform
                                   // distribution between 
                                   // -1,1
  if (x*x + y*y < 1.0) {
    inside_circle++; // If x and y are within circle,
                     // increment 'inside_circle'
  }
}

double calc_pi = inside_circle/total * 4; // calculate pi

cout << "Calculated π to be : " << calc_pi << "\n";

In [ ]:
%%ROOT

#include <iostream>
#include <TRandom3.h>

using namespace std;

int main()
{
TRandom3 rng; // Create Random Number Generator
rng.SetSeed(); // Set a random seed
    
int inside_circle = 0, total = 100; // total number and number inside circle
for (int i = 0; i < total; i++) {
  double x = rng.Uniform(-1., 1.), // Get random x,y pair from uniform
         y = rng.Uniform(-1., 1);  // distribution between -1,1
  if (x*x + y*y < 1) {
    inside_circle++;
  }
}

float calc_pi = 4.0 * inside_circle/total;
w
cout << "Calculated π to be : " << std::fixed << calc_pi << "\n";
cout << "M_PI " << M_PI << "\n";
}

Well... that was boring

So that worked, but we didn't use Object Oriented Programming!

Let's figure out a different question, what does the distribution of π look like with different 'total' values? Solve with classes.

class PiCalculator {
public:
  PiCalculator ():_rnd(new TRandom3()) {_rnd->SetSeed();};
  PiCalculator (TRandom3* generator):_rnd(generator){};

  double GetPi(int repeats) {
      int numerator = 0, denominator = repeats;
      while (repeats--) {
        double x = rng.Uniform(-1., 1.),
               y = rng.Uniform(-1., 1);
        if (x*x + y*y < 1.0) {
          numerator++;
        }
      }
      return 4.0 * numerator / denominator;
  }

protected:
  TRandom3* _rnd;
};

int main()
{
  PiCalculator calc;
  std::cout << "pi " << calc.GetPi(100) << "\n";
  return 0;
}

In [72]:
%%ROOT

#include <iostream>
#include <TRandom3.h>

class PiCalculator {
public:
  PiCalculator ():_rnd(new TRandom3()) {_rnd->SetSeed();};
  PiCalculator (TRandom3* generator):_rnd(generator){};
  
  double GetPi(int repeats) {
      int numerator = 0, denominator = repeats;
      while (repeats--) {
        double x = _rnd->Uniform(-1., 1.),
               y = _rnd->Uniform(-1., 1);
        if (x*x + y*y < 1.0) {
          numerator++;
        }
      }
      return 4.0 * numerator / denominator;
  }

protected:
  TRandom3* _rnd;
};

int main()
{
  PiCalculator calc;
  std::cout << "pi " << calc.GetPi(1000) << "\n";
  return 0;
}


pi 3.172


In [ ]:
%%ROOT

#include <iostream>
#include <TRandom3.h>
#include <TFile.h>
#include <TH2D.h>

class PiCalculator {
public:
  PiCalculator ():_rnd(new TRandom3()) {_rnd->SetSeed();};
  PiCalculator (TRandom3* generator):_rnd(generator){};
  
  double GetPi(int repeats) {
      int numerator = 0, denominator = repeats;
      while (repeats--) {
        double x = _rnd->Uniform(-1., 1.),
               y = _rnd->Uniform(-1., 1);
        if (x*x + y*y < 1.0) {
          numerator++;
        }
      }
      return 4.0 * numerator / denominator;
  }

protected:
  TRandom3* _rnd;
};

int main()
{
  const int REPETITIONS = 500,
            MIN = 100,
            MAX = 50000;

  TFile *file = new TFile("MCPi.root", "RECREATE");

  TH2D *pihist = new TH2D("PiHist", "Repeats vs Pi Value", 
                          100, MIN, MAX, // Number of repetitions
                          100, 3, 3.3);    // Pi values
    
  PiCalculator calc;

  for (int num = MIN; num < MAX; num += 10000) {
    double avg_pi = 0.0;
    int rep = REPETITIONS;
    while (rep--) {
      double pi = calc.GetPi(num);
      pihist->Fill(num, pi);
      avg_pi += pi;
    }
    std::cout << num << " : " << avg_pi/REPETITIONS << "\n";
  }
  file->Write();
  std::cout << "Done.\n";  
  return 0;
}