Difference: TutorialRoot (1 vs. 2)

Revision 22011-05-06 - AlessioSarti

 

ROOT tutorial

Session I: ROOT introduction.

Slides can be retrieved here: SessionI.pdf

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
Changed:
<
<

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

Opening / browsing a file via command line


As a first exercise you should:
* Open (in READ mode) the root file linked here
* List the content of the file and find the histogram 0h_zde
* Draw the histogram
* Open (in READ mode) the root file linked here
* Draw a variable from ntuple 42 inside the directory "MuDigitMoni"

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
Changed:
<
<


The second exercise is to get access to the histograms created when Drawing a variable of an ntuple.
You should:
>
>
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 "MuDigitMoni/42" 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
Changed:
<
<
Examples are given below:
<blockquote style="background-color:#f0f0f0">
<pre>
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.
</pre>
</blockquote>
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:
<blockquote style="background-color:#f0f0f0">
<pre>
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");

</pre>
</blockquote>

---++++ 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:
<blockquote style="background-color:#f0f0f0">
<pre>
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
</pre>
</blockquote>

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 an external ASCII file and displays the content: run it with -b -q option
* Write a Macro that read an external ASCII file, fill an histogram and draws it. Load it and run it interactively using .x command.

Example is given below:
<blockquote style="background-color:#f0f0f0">
<pre>
#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;
}
</pre>
</blockquote>

---++++ 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 external 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.

<blockquote style="background-color:#f0f0f0">
<pre>
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;
}
</pre>
</blockquote>

---+++ 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.

<blockquote style="background-color:#f0f0f0">
<pre>
myNtp->MakeClass("[className]");
</pre>
</blockquote>

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:

<blockquote style="background-color:#f0f0f0">
<pre>
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;
}
</pre>
</blockquote>

---++++ 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.
<blockquote style="background-color:#f0f0f0">
<pre>

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)

</pre>
</blockquote>

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:
<blockquote style="background-color:#f0f0f0">
<pre>
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;
}
</pre>
</blockquote>

Analysis:
<blockquote style="background-color:#f0f0f0">
<pre>
void ClassName::analysis()
{
cout<<"My favourite variable value"<<myVar<<endl;
my1DHisto->Fill(myvar);
my2DHisto->Fill(myvar1,myvar2);
return;
}
</pre>
</blockquote>

Finalization:
<blockquote style="background-color:#f0f0f0">
<pre>
void ClassName::finalization()
{
//Objects deletion
fOutFile->Write(); //To write objects into the file
fOutFile->Close(); //To close a file

return;
}
</pre>
</blockquote>

---++++ Load and run the macro

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

<blockquote style="background-color:#f0f0f0">
<pre>
// 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
</pre>
</blockquote>

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:
<blockquote style="background-color:#f0f0f0">
<pre>
#include <iostream>
#include <fstream>

int main (int argc, char argv[]) {
cout<<"My First Executable!"<<endl;
return 0;
}
</pre>
</blockquote>
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.
<blockquote style="background-color:#f0f0f0">
<pre>
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
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

</pre>
</blockquote>
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.
*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!=

<blockquote style="background-color:#f0f0f0">
<pre>
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
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)
#---------------------------------------------------------------
tab$$(CXX) $(SOFLAGS) $(NTUPLEB) -o libMyClass.so

MyClassDict.cc: MyClass.hh
tab$$(ROOTSYS)/bin/rootcint -f MyClassDict.cc -c -I../ MyClass.hh

# ================================================================================
Exec_tag: Exec.o lib
# -----------------------------------------------------------------------------
tab$$(LD) $(LDFLAGS) -o Exec Exec.o $(GLIBB)


clean:
tab$rm -f *.so
tab$rm -f *.o
tab$rm -f *Dict.*
tab$rm -f Exec
</pre>
</blockquote>

---++++ Compile/run/debug the executable

Instructions to compile, run, debug the executable are given below:
<blockquote style="background-color:#f0f0f0">
<pre>
gmake -f Makefile Exec_tag
./Exec -options : to run your exec.
gdb ./Exec and then run -options commands: to debug you executable
</pre>
</blockquote>

---++++ Final Exercise

Create an executable that runs on the DecayChainNtuple provided here that:
* Takes as input the number of events to process and the root file name
* Print out the Energy of lab0 candidate for each event
* Fill/save an histogram (in eps and png formats) with the momentum of lab1 and lab2 candidates
* Save an ntuple into a ROOT file that contains the: event number, invariant mass of lab1 and lab2 candidates, momentum and mass of lab0 candidate

To do so:
* First of all create a myTree class using makeclass on the DecayChainNtuple Tree.
* 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 - 18 Jun 2007

* prova.root: Ntuple for playing
>
>
Examples are given below:
Added:
>
>
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. 
 
Changed:
<
<
-- AlessioSarti - 2011-05-06
>
>
For a comprehensive review of the many capabilities of Draw method you can click here
Added:
>
>

Handling basics of graphics

 
Changed:
<
<
*
>
>
To exercise the basics of graphics you can start with:
Added:
>
>
  • 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 an external ASCII file and displays the content: run it with -b -q option
  • Write a Macro that read an external 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 external 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
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.

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
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 here that:

  • Takes as input the number of events to process and the root file name
  • Print out the Energy of lab0 candidate for each event
  • Fill/save an histogram (in eps and png formats) with the momentum of lab1 and lab2 candidates
  • Save an ntuple into a ROOT file that contains the: event number, invariant mass of lab1 and lab2 candidates, momentum and mass of lab0 candidate
To do so:
  • First of all create a myTree class using makeclass on the ntuple Tree.
  • 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
 
META FILEATTACHMENT attachment="SessionI.pdf" attr="h" comment="" date="1304695777" name="SessionI.pdf" path="SessionI.pdf" size="355061" user="AlessioSarti" version="1"

Revision 12011-05-06 - AlessioSarti

 

ROOT tutorial

Session I: ROOT introduction.

Slides can be retrieved here: SessionI.pdf

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 linked here
* List the content of the file and find the histogram 0h_zde
* Draw the histogram
* Open (in READ mode) the root file linked here
* Draw a variable from ntuple 42 inside the directory "MuDigitMoni"

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 "MuDigitMoni/42" 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:
<blockquote style="background-color:#f0f0f0">
<pre>
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.
</pre>
</blockquote>
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:
<blockquote style="background-color:#f0f0f0">
<pre>
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");

</pre>
</blockquote>

---++++ 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:
<blockquote style="background-color:#f0f0f0">
<pre>
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
</pre>
</blockquote>

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 an external ASCII file and displays the content: run it with -b -q option
* Write a Macro that read an external ASCII file, fill an histogram and draws it. Load it and run it interactively using .x command.

Example is given below:
<blockquote style="background-color:#f0f0f0">
<pre>
#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;
}
</pre>
</blockquote>

---++++ 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 external 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.

<blockquote style="background-color:#f0f0f0">
<pre>
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;
}
</pre>
</blockquote>

---+++ 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.

<blockquote style="background-color:#f0f0f0">
<pre>
myNtp->MakeClass("[className]");
</pre>
</blockquote>

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:

<blockquote style="background-color:#f0f0f0">
<pre>
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;
}
</pre>
</blockquote>

---++++ 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.
<blockquote style="background-color:#f0f0f0">
<pre>

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)

</pre>
</blockquote>

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:
<blockquote style="background-color:#f0f0f0">
<pre>
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;
}
</pre>
</blockquote>

Analysis:
<blockquote style="background-color:#f0f0f0">
<pre>
void ClassName::analysis()
{
cout<<"My favourite variable value"<<myVar<<endl;
my1DHisto->Fill(myvar);
my2DHisto->Fill(myvar1,myvar2);
return;
}
</pre>
</blockquote>

Finalization:
<blockquote style="background-color:#f0f0f0">
<pre>
void ClassName::finalization()
{
//Objects deletion
fOutFile->Write(); //To write objects into the file
fOutFile->Close(); //To close a file

return;
}
</pre>
</blockquote>

---++++ Load and run the macro

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

<blockquote style="background-color:#f0f0f0">
<pre>
// 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
</pre>
</blockquote>

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:
<blockquote style="background-color:#f0f0f0">
<pre>
#include <iostream>
#include <fstream>

int main (int argc, char argv[]) {
cout<<"My First Executable!"<<endl;
return 0;
}
</pre>
</blockquote>
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.
<blockquote style="background-color:#f0f0f0">
<pre>
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
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

</pre>
</blockquote>
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.
*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!=

<blockquote style="background-color:#f0f0f0">
<pre>
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
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)
#---------------------------------------------------------------
tab$$(CXX) $(SOFLAGS) $(NTUPLEB) -o libMyClass.so

MyClassDict.cc: MyClass.hh
tab$$(ROOTSYS)/bin/rootcint -f MyClassDict.cc -c -I../ MyClass.hh

# ================================================================================
Exec_tag: Exec.o lib
# -----------------------------------------------------------------------------
tab$$(LD) $(LDFLAGS) -o Exec Exec.o $(GLIBB)


clean:
tab$rm -f *.so
tab$rm -f *.o
tab$rm -f *Dict.*
tab$rm -f Exec
</pre>
</blockquote>

---++++ Compile/run/debug the executable

Instructions to compile, run, debug the executable are given below:
<blockquote style="background-color:#f0f0f0">
<pre>
gmake -f Makefile Exec_tag
./Exec -options : to run your exec.
gdb ./Exec and then run -options commands: to debug you executable
</pre>
</blockquote>

---++++ Final Exercise

Create an executable that runs on the DecayChainNtuple provided here that:
* Takes as input the number of events to process and the root file name
* Print out the Energy of lab0 candidate for each event
* Fill/save an histogram (in eps and png formats) with the momentum of lab1 and lab2 candidates
* Save an ntuple into a ROOT file that contains the: event number, invariant mass of lab1 and lab2 candidates, momentum and mass of lab0 candidate

To do so:
* First of all create a myTree class using makeclass on the DecayChainNtuple Tree.
* 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 - 18 Jun 2007

* prova.root: Ntuple for playing

-- AlessioSarti - 2011-05-06

*

META FILEATTACHMENT attachment="SessionI.pdf" attr="h" comment="" date="1304695777" name="SessionI.pdf" path="SessionI.pdf" size="355061" user="AlessioSarti" version="1"
 
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