Tags:
create new tag
view all tags

ROOT tutorial

Session I: ROOT introduction.

Slides can be retrieved here: introduction to root slides

The code needed can be downloaded from a Repository using

  • [for Roma1 students tutorial] svn co svn+ssh://<youraccount>@pcaen1.ing2.uniroma1.it/home/sarti/SvnRepos/TutorialRoot

ROOT basics.

Start an interactive session


You need to type 'root' command after having properly set the variables

ROOTSYS : should point to your root installation
LD_LIBRARY_PATH : should point to $ROOTSYS/lib + any other lib that you'll need (more on that below)
PATH : should point to $ROOTSYS/bin [use 'set path=($path $ROOTSYS/bin)' command on tcsh]

Useful files (you should know that they exist and where they are!)

  1. $home/.rootrc : can be used to override default values to customize your root session. Example is given below:
Root.Style: Plain
  1. $home/.root_hist : contains all the commands executed in the past sessions (that you can recall in your interactive session with the up and down arrows)
  2. $ROOTSYS/tutorials : this directory contains almost everything you'd like to do with ROOT. You can search it to find your favourite use case and learn about grapchis, fitting, functions, etc etc
When you're logged on your root session you can try to play with some basic interactive commands
TBrowser b; //To start the browser (GUI)
.L [nomemacro] //To load file/macro
.x [nomemacro] //To execute a macro interactively
.! [command] //To execute a system command (like 'ls')
.q //To exit

From the browser you can open any root file and display it by clicking on it.

Opening / browsing a file via command line


As a first exercise you should:

  • Open (in READ mode) the root file ACQ_all_2100_8020_Cst1_plaNew.root
  • List the content of the file and find the histogram stcMean and histogram tdc/time_t1ch_38
  • Draw the histogram
  • Open (in READ mode) the root file linked ACQ_all_2100_8020_Cst1_plaNew.root
  • Draw a variable from ntuple TbTree
Example is given below:
TFile *f = new TFile ("[nomefile.root]");
f->ls(); //List the content of a file from the current directory
gDirectory->ls(); //List the content of current directory
f->cd("[dirname]"); //Go to a given directory
TH1D * myhisto = ((TH1D)gDirectory->Get("[path_to_dir/histoname]"));
myhisto->Draw(); //Open a canvas (c1) and draw the histogram on it
TTree * myNtp = ((TTree*)gDirectory->Get("[path_to_dir/ntpname]"));
myNtp->Draw("[varname]"); //Open a canvas and plot on it the varname distribution

The second exercise is to get access to the histograms created when Drawing a variable of an ntuple.
You should:

  1. Choose and draw a variable from the "TbTree" tree
  2. Get the pointer to the histogram htemp.
  3. Draw a 2D histogram of one var vs one other
  4. Get the pointer to the TGraph created
  5. Draw a variable of the ntuple directly into an histogram
Examples are given below:
TH1F *htemp = (TH1F*)gPad->GetPrimitive("htemp"); // Get pointer to default 1D histo
TGraph *graph = (TGraph*)gPad->GetPrimitive("Graph"); // Get pointer to default 2D graph
myNtp->Draw("[varname]>>histo"); //Draws varname into the "histo" histogram
TH1F *histo = (TH1F*)gDirectory->Get("histo"); //retrievs the histo
myNtp->Draw("[varname]>>histo(500,10,20)"); //Draw varname into histo with specified binning/range. 

For a comprehensive review of the many capabilities of Draw method you can click here

Handling basics of graphics

To exercise the basics of graphics you can start with:

  • Setting the session style to "Plain"
  • Creating a TCanvas
  • Drawing an histogram on the given canvas and save the canvas as eps or png plot
  • Divide the canvas in 2 and draw 2 different ntuple variables into the canvas
  • Get access to axis/histo information, legend, stats, line color, marker. Documentation on methods you'd like to exercise is linked here for histograms, markers, lines and fill
Examples are given below:
gROOT->SetStyle("Plain");
TCanvas *c = new TCanvas("c","c",600,800);
c->Clear(); c->cd();
histo->Draw(); c->Print("tmp.eps"); c->Print("tmp.png");
TCanvas *c1 = new TCanvas("c1","c1",600,1200);
c1->Clear(); c1->Divide(1,2); 
c1->cd(1);
histo->SetMarkerColor(4);
histo->Draw("p"); 
c1->cd(2);
histo->SetLineColor(2);
histo->SetFillColor(3);
histo->Draw("h"); 
c1->Print("tmp1.eps");

Ntuple analysis From command line

To exercise the ntuple analysis via command line you should:

  • Get access to the ntuple pointer (e.g. using gDirectory):
  • Print the ntuple information
  • Scan the desired variable
  • Plot the variable as a function of a second variable
  • Plot the variable applying some cuts
  • Plot the variable specifying graphic options (like 'same' one to superimpose 2 plots)
Examples are given below:
myNtp->Print();
myNtp->Draw("[varname]");
myNtp->Draw("[var1]:[var2]"); //Plots var1 as a function of var2
myNtp->Draw("[varname]","[cuts]");
myNtp->Draw("[varname]","[cuts]","[graph options]");
myNtp->Scan(); //Scans all variables
myNtp->Scan("[varname]"); //Scan the specified variable

For more informations on how to use cuts see TCut class.
For more informations on graphics options see the TTree::Draw page.

Using macros

You have two possible ways to use macros inside root:

  • Interactively using the .x command to load the macro
  • running the macro in batch using the -b (-q) options.
  • -q option exits root after having executed the macro
  • -b run in batch mode (no graphics)
As exercise:
  • Write a Macro that display an Hello World message: run it with the -b option
  • Write a Macro that read the FinalCorrDatRightErr.dat ASCII file and displays the content: run it with -b -q option
  • Write a Macro that read the FinalCorrDatRightErr.dat ASCII file, fill an histogram and draws it. Load it and run it interactively using .x command.
Example is given below:
#include <iostream.h>
void test() {
 cout<<"Hello World!!!"<<endl;
 //Histo inizialization
 TH1D * h_fa = new TH1D("h_fa","Factor histogram",100,0,1);
 //File reading
 double fact,top,err; int flag; char buffertC[200];
 ifstream tsC("FinalCorrDatRightErrRms.dat");

 while (tsC.getline(buffertC, 200, '\n')) {
 sscanf(buffertC, "%lf %lf %lf %d",&fact,&err,&top,&flag);
 cout<<"My factor: "<<fact<<endl;
 //Histo filling
 h_fa->Fill(fact);
 }

 TCanvas *c = new TCanvas("c","mycanvas",600,600);
 c->cd() h_fa->Draw(); c->Print("test.eps");
 return;
}

Ntuple/file creation

To exercise the creation and filling of an ntuple you should:

  • Add the creation of the ntuple at the top of your macro
  • Properly initialize the variables
  • Read the FinalCorrDatRightErr.dat ASCII file.
  • Set up some int, double, string variables to be written.
  • Add the filling of the variables and writing of ntuple
  • Add the writing of the ntuple into a file.
  • Exit and browse the created file.
Examples are given below.
void MacroRead() {
 //Create a new file
 TFile *fNewOutFile = new TFile("root_file.root", "RECREATE"); //Existing file will be overwritten.
 fNewOutFile->cd(); //To go into the main directory of the file 
 int f_myInt; double f_myDou; 
 vector<string> *f_strVct; 
 vector<double> *f_douVct;
 TTree *dataTree = new TTree("data","data"); //Creates ntuple 
 dataTree->Branch("myInt", &f_myInt , "myInt/I"); //Int 
 dataTree->Branch("myDou", &f_myDou , "myDou/D"); //Double
 dataTree->Branch("myStrVct", "vector<string>" , &f_strVct,32000,0);
 dataTree->Branch("myDouVct" ,"vector<double>" , &f_douVct,32000,0);
 //Inside the reading loop
 double fact,top,err; int flag; char buffertC[200]; string str;
 ifstream tsC("FinalCorrDatRightErr.dat");
 while (tsC.getline(buffertC, 200, '\n')) {
 sscanf(buffertC, "%lf %lf %lf %d",&fact,&err,&top,&flag);
 f_myInt = f_myDou = 0; f_strVct->clear(); f_douVct->clear();
 f_myInt = fact+1;
 f_myDou = err;
 str = "Time over Press: ";
 f_douVct->push_back(flag);
 f_strVct->push_back(str);
 dataTree->Fill();
 } 
 fNewOutFile->Write(); //To write objects into the file
 fNewOutFile->Close(); //To close a file
 return;
}

Using a macro to Loop over the events

Creating the macro

To create a macro to loop over the events in a given ntuple you should use the MakeClass method.

myNtp->MakeClass("[className]");

This creates [className].C and [className].h in your working directory.
You can then edit [className].C to include your analysis code that needs to
run on each event.

Modifications should go into the Loop() method (contained in the [className].C) that looks like:

Long64_t nentries = fChain->GetEntriesFast();
 Long64_t nbytes = 0, nb = 0;
 for (Long64_t jentry=0; jentry<nentries;jentry++) {
 Long64_t ientry = LoadTree(jentry);
 if (ientry < 0) break;
 nb = fChain->GetEntry(jentry); nbytes += nb;
 // if (Cut(ientry) < 0) continue;
 }

Modifying the Loop() method.

In order to add your particular analysis to the macro you should modify the Loop method adding three different phases:

  • Initialization. Should run only once and take care of object creation and initialization.
  • Analysis. Should run on each event and fill the histograms, ntuples, or analyze the events in other ways....
  • Finalization. Should run only once at the end of the job and take care of clean up and file/plots writing..
Example is given below.
initialization(); //Perform objects initialization
 Long64_t nentries = fChain->GetEntriesFast();
 Long64_t nbytes = 0, nb = 0;
 for (Long64_t jentry=0; jentry<nentries;jentry++) {
 Long64_t ientry = LoadTree(jentry);
 if (ientry < 0) break;
 nb = fChain->GetEntry(jentry); nbytes += nb;
 // if (Cut(ientry) < 0) continue;
analysis(); //Perform analysis of each event, fill s output objects
 }
finalization(); //Finalize the jobs (write/delete objects/file)

To exercise the Loop method and the analysis using macros you should:

  • Customize the initialization() method in order to include the object definition that you'll need for your analysis.
  • Customize the analysis() method, that should contain the code that you want to run on each event.
  • Customize the finalization() method, that should contain the writing of analysis objects and their deletion.
Examples on how to write those methods are given below.
Remeber that:
  • Global variables should be declared in the .h file
  • Ntuple variables ARE already defined in the .h file: you should not REDECLARE them
Initialization:
void ClassName::initialization()
{
 fOutFile = new TFile("root_file.root", "RECREATE");
 fOutFile->cd();
 //Histogram definition.
 my1DHisto = new TH1D("name","title",xbins,xmin,xmax);
 my2DHisto = new TH2D("name","title",xbins,xmin,xmax,ybins,ymin,ymax);
 return;
}

Analysis:

void ClassName::analysis()
{
 cout<<"My favourite variable value"<<myVar<<endl; 
 my1DHisto->Fill(myvar);
 my2DHisto->Fill(myvar1,myvar2);
 return;
}

Finalization:

void ClassName::finalization()
{
 //Objects deletion
 fOutFile->Write(); //To write objects into the file
 fOutFile->Close(); //To close a file
return;
}

Load and run the macro

Instructions are given in the macro [className].C file itself.

// In a ROOT session, you can do:
// Root > .L [className].C // Load of [className] macro
// Root > [className] t // Class obejct creation
// Root > t.GetEntry(12); // Fill t data members with entry number 12
// Root > t.Show(); // Show values of entry 12
// Root > t.Show(16); // Read and show values of entry 16
// Root > t.Loop(); // Loop on all entries

Keep in mind that if you're using the macro to dump an ntuple into a file the ntuple will not be dumped into the file until you EXIT from root (or force the writing and closing of the file!)

Creating standalone executables

If you arrived here in less than 1 hour you can be proud of yourself.
The most important part starts here. To create an executable you should:

  • Create a main()
  • Include/use/call in your main your favourite classes.
  • Create a makefile and know where to pick up libraries
  • Have gcc installed
  • Compile the main and run it
The following subsection will remind you the basics to set up your executable. The exercise is contained in the very last subsection of this paragraph!

Create a main() executable

First of all you should create the main that you're going to compile. The main should look like:

#include <iostream>
#include <fstream>

int main (int argc, char *argv[]) {
 cout<<"My First Executable!"<<endl;
 return 0;
} 

Remeber to properly include the includes for the classes you're going to use!

Create a makefile

Makefiles are typically needed in case of complex executables. If you have just one main and you don't need to include special classes or libraries you can just compile your main using gcc syntax. But in more complex cases the Makefile really helps to take care of the executable creation.
Example of such makefile is given below: you should change the Simple tag replacing the rag name and code name with the values you've used for your executable.

ROOTCFLAGS = $(shell $(ROOTSYS)/bin/root-config --cflags)
ROOTLIBS = $(shell $(ROOTSYS)/bin/root-config --libs)
ROOTGLIBS = $(shell $(ROOTSYS)/bin/root-config --glibs)
 
CXX = g++
CXXFLAGS = -g -Wall -fPIC
LD = g++
LDFLAGS = -g
SOFLAGS = -shared
NGLIBB = $(ROOTGLIBS) 
NGLIBB += -lMinuit
GLIBB = $(filter-out -lNew, $(NGLIBB))
CXXFLAGS += $(ROOTCFLAGS)
LIBS = $(ROOTLIBS) 
Exec_tag: Simple.cc
# -----------------------------------------------------------------------------
 $(CXX) $(CXXFLAGS) -c $<
 $(LD) $(LDFLAGS) -o Simple Simple.o $(GLIBB)
# ==============================================================================
clean:
 rm -f *.o Simple 

The example above can be used to compile executables that need ROOT libraries but that are not depending on external classes. If you wanto to use external classes you might want to use a more complicated template. Changes [minor] are needed for Mac osx compilers to work....

Attention: after the tag the command should start with a 'tab' separator. If you copy paste the makefile from this page you loose the tab and the making won't work. Replace the spaces with a 'tab' when indicated!

ROOTCFLAGS = $(shell $(ROOTSYS)/bin/root-config --cflags)
ROOTLIBS = $(shell $(ROOTSYS)/bin/root-config --libs)
ROOTGLIBS = $(shell $(ROOTSYS)/bin/root-config --glibs)
CXX = g++
CXXFLAGS = -g -Wall -fPIC
LD = g++
LDFLAGS = -g
SOFLAGS = -shared
NGLIBB = $(ROOTGLIBS) 
NGLIBB + -lMinuit
NGLIBB + /home/asarti/macro/source/libMyClass.so
GLIBB = $(filter-out -lNew, $(NGLIBB))
CXXFLAGS + $(ROOTCFLAGS)
LIBS = $(ROOTLIBS) 
NTUPLEB = MyClass.o MyClassDict.o

.SUFFIXES: .cc,.C
.cc.o:
tab$(CXX) $(CXXFLAGS) -c $<

# ================================================================================
lib: $(NTUPLEB)
#-----------------------------------------------------------
$(CXX) $(SOFLAGS) $(NTUPLEB) -o libMyClass.so

MyClassDict.cc: MyClass.hh
$(ROOTSYS)/bin/rootcint -f MyClassDict.cc -c -I../ MyClass.hh
# ================================================================================
Exec_tag: Exec.o lib
# -----------------------------------------------------------------------------
$(LD) $(LDFLAGS) -o Exec Exec.o $(GLIBB) 
clean:

rm -f *.so
rm -f *.o
rm -f *Dict.*
rm -f Exec

Compile/run/debug the executable

Instructions to compile, run, debug the executable are given below:

gmake -f Makefile Exec_tag
./Exec -options : to run your exec.
gdb ./Exec and then run -options commands: to debug you executable 

Final Exercise

Create an executable that runs on the Ntuple provided (ACQ_all_2100_8020_Cst1_plaNew.root) that:

  • Takes as input the number of events to process and the root file name
  • Print out the time of time sel of the tdc channel 1 candidate for each event (placing a cut > -100 on the time)
  • Fill/save an histogram (in eps and png formats) with the qdc 1 and qdc 2 variables.
  • Save an ntuple into a ROOT file that contains the: event number, time of channel 0,1,2 and qdc 0, 1 and 2
To do so:
  • First of all create a myTree class using makeclass on the ntuple TbTree.
  • Create the main, include the myTree.h file and create the myTree ntp onject.
  • Use the ntp.Loop() method to loop on candidates
  • create the proper initialize and finalize methods to create and save histograms and ntuples.
  • compile it and run it!
-- AlessioSarti - 2011-05-06
Edit | Attach | Watch | Print version | History: r5 < r4 < r3 < r2 < r1 | Backlinks | Raw View | Raw edit | More topic actions
Topic revision: r5 - 2012-12-14 - AlessioSarti
 
This site is powered by the TWiki collaboration platform Powered by PerlCopyright © 2008-2024 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback