ROOT is a C++ based framework for data analysis that is widely used in High Energy Physics. This tutorial aims to help getting started with ROOT and will introduce ROOT's basic features (histograms, functions, graphs) as well as more complex objects (files, trees). A number of further references and online tutorials are compiled to guide the user during the first steps throughout the rest of the school.
Further references, additional material and a collection of tutorials can be found here.
Introductory slides for this tutorial can be found here.
Some basic knowledge of C++ is required for the successful completion of the tutorial and the work with ROOT. A short overview and reminder on the basics of C++ can be found in the references.
The tutorial is split into several exercises:
Steps marked with * are advanced exercises and can be solved if the time allows. A proposal for homework is also given.
In the first exercise you open an interactive ROOT session and try some useful objects and methods.
You will need the following classes and methods for the exercise which we have already seen:
> root ******************************************* * * * W E L C O M E to R O O T * * * * Version 5.32/00 2 December 2011 * * * * You are welcome to visit our Web site * * http://root.cern.ch * * * ******************************************* ROOT 5.32/00 (tags/v5-32-00@42375, Dec 02 2011, 12:42:25 on linuxx8664gcc) CINT/ROOT C/C++ Interpreter version 5.18.00, July 2, 2010 Type ? for help. Commands must be C++ statements. Enclose multiple statements between { }. root [0] double x = TMath::Pi()/2. root [1] double sinx = TMath::Sin(x) root [2] sinx*sinx (double)1.00000000000000000e+00 root [3] TLorentzVector vec1(-29.4,-26.2,119.6,125.9) root [4] TLorentzVector vec2 root [5] vec2.SetPtEtaPhiE(53.,1.82,0.91,167.8) root [6] TLorentzVector vec3=vec1+vec2 root [7] vec3.M() (const Double_t)9.07852492341699104e+01 root [8] vec3.Boost(-vec3.Px()/vec3.E(),-vec3.Py()/vec3.E(),-vec3.Pz()/vec3.E()) root [9] vec3.E() (const Double_t)9.07852492341698252e+01 root [10] .q
This exercise shows you how to create a histogram and how to work with it. Write a small ROOT macro for the following purposes:
You will need the following classes and methods for the exercise:
#include "TH1.h" #include "TAxis.h" #include <iostream> void ex2() { TH1F* hist = new TH1F("histogram1", ";x", 10, 0., 100.); hist->Fill(11.3); hist->Fill(25.4); hist->Fill(18.1); for (unsigned int i=0; i<10; i++) { hist->Fill(i*i); } hist->Draw(); std::cout << "mean=" << hist->GetMean() << " sigma=" << hist->GetRMS() << std::endl; std::cout << "integral=" << hist->Integral() << std::endl; std::cout << "bin with maximum value=" << hist->GetMaximumBin() << std::endl; std::cout << "maximum value=" << hist->GetBinContent(hist->GetMaximumBin()) << std::endl; hist->GetYaxis()->SetTitle("entries"); hist->SetLineColor(kRed); }Output:
> root -l ex2.C root [0] Processing ex2.C... <TCanvas::MakeDefCanvas>: created default TCanvas with name c1 mean=26.1385 sigma=24.1017 integral=13 bin with maximum value=1 maximum value=4
The histogram should look like this:
This exercise shows you how to use different canvases and draw histograms into them. Additionally you will add a legend to a canvas.
hist1->FillRandom("gaus", 500);
hist2->FillRandom("pol2", 500);
You will need the following classes and methods for the exercise:
TH1F *hist1b = (TH1F*)hist1->Clone("gaus2");
#include "TH1.h" #include "TCanvas.h" #include "TLegend.h" #include <iostream> void ex3() { // create two histograms with identical binning TH1F* hist1 = new TH1F("gausshisto", "", 10, -5., 5.); TH1F* hist2 = new TH1F("polyhisto", "", 10, -5., 5.); // fill each randomly with 500 entries hist1->FillRandom("gaus", 500); hist2->FillRandom("pol2", 500); // create canvases and draw the histograms TCanvas* c1 = new TCanvas("c1", "gauss"); hist1->Draw(); TCanvas* c2 = new TCanvas("c2", "polynomial"); hist2->Draw(); // set line colors hist1->SetLineColor(kRed); hist2->SetLineColor(kBlue); // clone the histograms with new names TH1F *hist1b = (TH1F*)hist1->Clone("gaus2"); TH1F *hist2b = (TH1F*)hist2->Clone("pol2"); // Sumw2 is needed for correct error scaling hist1b->Sumw2(); hist2b->Sumw2(); // hint: it would be better here to check // first whether hist1b->Integral() is larger 0 ! hist1b->Scale(1./hist1b->Integral()); hist2b->Scale(1./hist2b->Integral()); // create new canvas and draw both histogram in same plot TCanvas* c3 = new TCanvas("c3", "both"); hist1b->Draw(); hist2b->Draw("same"); // add legend TLegend* legend = new TLegend(0.16, 0.63, 0.45, 0.91); legend->AddEntry(hist1b, "Gaussian", "l"); legend->AddEntry(hist2b, "Polynomial", "l"); legend->Draw(); // save canvas as PDF file c3->Print("gaussian-polynomial.pdf"); // save canvas as ROOT file c3->Print("gaussian-polynomial.root"); }Output:
> root -l ex3.C root [0] Processing ex3.C... Info in <TCanvas::Print>: pdf file gaussian-polynomial.pdf has been created Info in <TCanvas::SaveAs>: ROOT file gaussian-polynomial.root has been created root [1]
The canvases should look like this:
A simple example on how to use the TBrowser object and how to handle files. Do the following interactively, i.e. without a ROOT script:
You will need the following classes and methods for the exercise:
> root -l gaussian-polynomial.root root [0] Attaching file gaussian-polynomial.root as _file0... root [1] new TBrowser() (class TBrowser*)0x1117c00 root [2] TFile* histfile = new TFile("hist.root", "read") root [3] histfile->ls() TFile** hist.root TFile* hist.root KEY: TH1F pol2;1 KEY: TH1F gaus2;1 root [6] TH1F* hist = (TH1F*) histfile->Get("pol2") root [7] hist->Draw() root [8] TFile* myfile = new TFile("myhist.root", "RECREATE") root [9] hist->Write(); root [10] myfile->Close();
The editor looks like this:
A first example on how to use trees. Again do this exercise interactively at the ROOT prompt.
You will need the following classes and methods for the exercise:
> root -l ntu_8843.root Setting default style root [0] Attaching file ntu_8843.root as _file0... root [1] ntu1->Draw("ene") <TCanvas::MakeDefCanvas>: created default TCanvas with name c1 root [2] ntu1->Draw("ene:kpx") root [3] ntu1->Draw("ene:kpx", "y>0") (Long64_t)30221 root [4] ntu1->Draw("sqrt(kpx*kpx+kpy*kpy)") root [5] gStyle->SetPalette(1)root [6] ntu1->Draw("ene:kpz", "", "colz")
This exercise shows how to use a one dimensional function.
You will need the following classes and methods for the exercise:
> root -l Setting default style root [0] TF1 f1("f1", "sin(x)/x+[0]", 0., 10.) root [1] f1.SetParameter(0, 5.) root [2] f1.Draw() <TCanvas::MakeDefCanvas>: created default TCanvas with name c1 root [3] f1.Eval(5.) (const Double_t)4.80821514506737202e+00 root [4] f1.Integral(0., 3.) (Double_t)1.68486525279994694e+01 root [5] f1.Derivative(7.) (const Double_t)9.42924322788899899e-02 root [6] f1.SetNpx(1000) root [7] f1.Draw()
The function should look like this:
This exercise shows how to use graphs and errors on graphs.
You will need the following classes and methods for the exercise:
#include "TCanvas.h" #include "TGraphErrors.h" #include "TF1.h" #include <iostream> void ex7() { TGraphErrors* graph = new TGraphErrors(5); graph->SetPoint(0, 1., 2.1); graph->SetPoint(1, 2., 2.9); graph->SetPoint(2, 3., 4.05); graph->SetPoint(3, 4., 5.2); graph->SetPoint(4, 5., 5.95); graph->SetPointError(0, 0., 0.1); graph->SetPointError(1, 0., 0.1); graph->SetPointError(2, 0., 0.1); graph->SetPointError(3, 0., 0.1); graph->SetPointError(4, 0., 0.1); TCanvas* c1 = new TCanvas("c1", "fitting graphs"); graph->Draw("APE"); TF1* f = new TF1("f", "[0]*x+[1]", 0., 6.); graph->Fit("f"); double m = f->GetParameter(0); double merr = f->GetParError(0); double b = f->GetParameter(1); double berr = f->GetParError(1); std::cout << "m = " << m << " +- " << merr << std::endl; std::cout << "b = " << b << " +- " << berr << std::endl; }Output:
root -l ex7.C Setting default style root [0] Processing ex7.C... FCN=5.7 FROM MIGRAD STATUS=CONVERGED 33 CALLS 34 TOTAL EDM=2.71359e-21 STRATEGY= 1 ERROR MATRIX ACCURATE EXT PARAMETER STEP FIRST NO. NAME VALUE ERROR SIZE DERIVATIVE 1 p0 1.00000e+00 3.16228e-02 1.70422e-05 -2.08465e-09 2 p1 1.04000e+00 1.04881e-01 5.65226e-05 -1.21781e-09 m = 1 +- 0.0316228 b = 1.04 +- 0.104881 root [1]
The graph and the fit function should look like this:
Documentation on ROOT can be found here:
Other tutorials can be found here:
Other useful links and material: