Now start up a new ROOT session with bbrroot and load
the root file with
TFile *f = new TFile("example.root"); //load the file
This ROOT file has a more complicated
directory structure than the simple file used in the first Workbook
section on ROOT. To have a look
around the directories and files in example.root use
f->ls(); (list the directories, histograms and ntuples)In this example file there are lots of histograms, but they are all contained in directories. The output from the previous command should look like:
root [1] f->ls(); TFile** example.root TFile* example.root KEY: TDirectory event_dir;1 Event Property Histograms KEY: TDirectory pipi_dir;1 pi pi Histograms KEY: TDirectory bkg_dir;1 Background events KEY: TDirectory track_dir;1 Track Histograms KEY: TDirectory gamma_dir;1 gamma Histograms KEY: TDirectory pi0_dir;1 pi0 HistogramsTo change into a directory, say, event_dir:
gDirectory->cd("event_dir"); //or, possibly best
f->cd("event_dir"); //where f is the name of the currently
//open file
(Note that anything that follows "//" is a comment and is
ignored by the ROOT interpreter.)
You can now list the contents of that directory with
gDirectory->ls(); //or f->ls()The output this time lists the available directories, but also the histograms in the open directory (event_dir):
root [5] f->ls() TFile** example.root TFile* example.root TDirectory* event_dir Event Property Histograms KEY: TH1F eTag_p_CM;1 eTag_p_CM KEY: TDirectory event_dir;1 Event Property Histograms KEY: TDirectory pipi_dir;1 pi pi Histograms KEY: TDirectory bkg_dir;1 Background events KEY: TDirectory track_dir;1 Track Histograms KEY: TDirectory gamma_dir;1 gamma Histograms KEY: TDirectory pi0_dir;1 pi0 Histograms
To change into the base directory of the ROOT file:
f->cd();If you don't use a semi-colon at the end of the line, you'll get a message like:
(Bool_t)1This is a return value indicating if the operation (changing directory) has been successfully executed. If the value is 0, it will be accompanied by an error message - usually a message saying you haven't entered a valid directory name). Now change into the "gamma_dir" directory:
gamma_dir->cd();list its contents:
root [12] f->ls() TDirectory* gamma_dir gamma Histograms OBJ: TH2F gammaEvsMassM gammaEvsMassM : 0 KEY: TH1F num_good_neutM;1 num_good_neutM KEY: TH1F num_good_neutD;1 num_good_neutD KEY: TH1F lateralMomentM38;1 Cluster Lateral Moment KEY: TH1F lateralMomentD38;1 Cluster Lateral Moment KEY: TH1F lateralMomentSig38;1 Cluster Lateral Moment KEY: TH1F gammaEM38;1 gammaEM KEY: TH1F gammaED38;1 gammaED KEY: TH1F gammaESig38;1 gammaESig KEY: TH1F nCrysM38;1 nCrysM KEY: TH1F nCrysD38;1 nCrysD KEY: TH1F nCrysSig38;1 nCrysSig KEY: TH1F gammaCosThM38;1 gammaCosThM KEY: TH1F gammaCosThD38;1 gammaCosThD KEY: TH1F gammaCosThSig38;1 gammaCosThSig KEY: TH1F lateralMomentM;1 Cluster Lateral Moment KEY: TH1F lateralMomentD;1 Cluster Lateral Moment KEY: TH1F lateralMomentSig;1 Cluster Lateral Moment KEY: TH1F gammaEM;1 gammaEM KEY: TH1F gammaED;1 gammaED KEY: TH1F gammaESig;1 gammaESig KEY: TH1F gammaEMFine;1 gammaEMFine KEY: TH1F gammaEDFine;1 gammaEDFine KEY: TH1F gammaESigFine;1 gammaESigFine KEY: TH2F gammaEvsMassD;1 gammaEvsMassD KEY: TH2F gammaEvsMassM;1 gammaEvsMassM KEY: TH2F gammaEvsMassSig;1 gammaEvsMassSig KEY: TH1F nCrysM;1 nCrysM KEY: TH1F nCrysD;1 nCrysD KEY: TH1F nCrysSig;1 nCrysSig KEY: TH1F gammaThetaM;1 gammaThetaM KEY: TH1F gammaThetaD;1 gammaThetaD KEY: TH1F gammaThetaSig;1 gammaThetaSig KEY: TH1F gammaCosThM;1 gammaCosThM KEY: TH1F gammaCosThD;1 gammaCosThD KEY: TH1F gammaCosThSig;1 gammaCosThSigand display a couple of histograms:
gammaEvsMassM.Draw("surf4"); //display 2-d histogram (surf4 is a
//display command specifying a surface style)
nCrysM.Draw(); //display 1-d histogram called nCrysD
Note that you can always check which directory you are in by typing
gDirectory->pwd();Where, when you have file "f" open, and are in its root directory, you should see:
root [42] gDirectory->pwd() example.root:/
gPad->Modified();
To zoom and unzoom:
nCrysM->SetAxisRange(10, 30.5, "x"); gPad->Modified(); // Needs a refresh from the command lineTo change to logarithmic axes (note that this is a display command, not a histogram method, so won't affect any fits):
gPad->SetLogy(1); gPad->Modified();To set up gridlines:
gPad->SetGridx(1); gPad->SetGridy(1); gPad->Modified();These options are controlled by boolean variables, and can be switched off using a "0" option, e.g.:
gPad->SetLogy(0); gPad->Modified();To change the drawing style (e.g.markers, color)
nCrysM->Draw("p"); //draw with points - not joined up
nCrysM->SetMarkerStyle(20); //round dots
nCrysM->SetMarkerSize(1.); //fat, round dots
nCrysM->SetMarkerColor(kBlue); //fat, blue, round dots
gPad->Modified();
To enlarge axis labels and add axis titles:
nCrysM->SetTitleSize(0.06, "x"); // Title size, offset and text
nCrysM->SetTitleOffset(1., "x");
nCrysM->SetXTitle("Axis title text");
gPad->SetBottomMargin(0.15);
gPad->SetLeftMargin(0.15);
nCrysM->Draw();
You can also set axis titles with
nCrysM->GetXaxis()->SetTitle("X-axis");
nCrysM->GetXaxis()->CenterTitle(1); // center the name of the x-axis
This command structure should start to become familiar pretty quickly:
you access the object you are interested in (in this case, the x-axis
object), then you set one of its attributes (SetTitle, CenterTitle,...)
(Note: (e)ps output can be missing if you cut off too much, so be sure
that you have sufficient margins.)
You can also change the y-axis range of your histogram either before or
after drawing the histogra using the functions
TH1F::SetMinimum(minValue) and
TH1F::SetMaximum(maxValue), e.g.
nCrysM->SetMaximum(1000);
You can also do it with the GUI (see below), moving the cursor over
the axis and left-clicking. A pair of lines will appear, one staying
where you started, the other following your mouse movements.
You can modify the binning of your histo with the command:
nCrysM->GetXaxis()->Set(nbins,xmin,xmax);
where you need to input actual numbers here.
TF1, TF2 and TF3).
To define a function with predefined components:
TF1 *f1a = new TF1("f1a","sin(x)", -5., 5.);
// built-in, this defines the function over the range -5<x<+5
TF1 *f1b = new TF1("f1b","x*sin(x)", -2., 2.); // combined
TF1 *f1c = new TF1("f1c", "[0]*x + [1] + gaus(2)",0.,15.);
gaus() is a 3-parameter Gaussian function used for
fitting. The combination here is a Gaussian plus a linear
function. gaus(2) means that the parameter numbering on
the Gaussian starts at 2. Here f1c is defined with 5
parameters, which by default are set to zero, but which you can set
before drawing the function. You can also use functions defined with
parameters for fitting, and use the fitting to determine the best
values for the parameters. For the 5-parameter function above, this is
done with, e.g.
f1c->SetParameters(0.1, 10., 50., 0.5, 0.01);Now define a 2-dimensional function:
TF2 *f2 = new TF2("f2", "sin(x)*sin(y)", -10., 10., -10., 10.);
To draw a 1D function, say f1c, enter:
f1c->Draw();The above command calls the default drawing option for functions. Other drawing options for functions include:
f1c->Draw("p"); // use markers
f1c->Draw("h"); // histogram
Note that you may have to set the markers to something sensible before
getting output. See above for instructions on how to do this.
2D functions are handled in a very similar manner
f2.Draw(); //2-d projection - not very impressive
f2.Draw("surf4"); // surface plot - much nicer
surf1-5 are different surface plot options.
To change the colours, you can do, e.g.
gStyle->SetPalette(1) //and plot again
TF1 *f1=new TF1("f1","sin(x)",0,10);
f1.Draw(); // need to draw the function first!
(f1->GetHistogram())->Draw();
To generate a 2D histogram from a 2D function and plot it:
f2->Draw(); (f2->GetHistogram())->Draw();For the 1D function the smooth function line will be jagged in a histo, and for the 2D function, the only clear difference is possibly the appearance of a statistics box for the histogrammed function (depending on your stats settings).
f2.Delete();This function now no longer exists and cannot be called, plotted, etc. You can then define
f2 afresh, or using something
else, e.g.
TF2 *f2 = new TF2("fun2","sin(x)*sin(y)",0.,3.14,0.,3.14);
f->cd("pi0_dir");
gg_massD_>Draw();
gg_massD->SetXTitle("f[#circ]");
gg_massD_>Draw();
Apart from the newest versions of ROOT, it is not possible to include
primes in axis or graph titles. Later versions have this facility with
the command #prime. Otherwise, the best workaround found
so far is to put a comma as a superscript.
The macro basic.C can be used to
read in data from an ascii file containing numbers laid out in
columns. The file basic.C is a simple macro which expects the input to
come from a simple ascii file, called basic.dat containing, in this example,
three columns of numbers.
To run this macro, from within ROOT execute the following command:
.x basic.C
The file reads in the numbers from basic.dat, histograms
the values from the first column, and writes all the entries into an
ntuple. This output, the histogram and ntuple, are saved to a file
called basic.root. This output
file can then be studied, ntuple entries printed, and cuts performed
on the three histogrammed quantities just like any other ROOT file.
How to fit histograms with predefined functions (these commands assume you are running ROOT from the same directory as you have saved the example file myrootfile.root):
TFile f("myrootfile.root");
h1->Draw();
h1->Fit("gaus");
h1->Fit("landau","R", "", 1., 5.);
// where "R" indicates to fit only in
// a range, given in the last two arguments
h1->Fit("landau","R", "P", 1., 5.);
// where "P" is an option indicating
// to plot markers instead of histograms
In a file myfunc.C define
double myfunc(double *x, double *par) {
double arg = 0;
if (par[2]) arg = (x[0] - par[1])/par[2];
return par[0]*TMath::Exp(-0.5*arg*arg);
}
Load this macro into ROOT and perform a fit with this function
.L myfunc.C
TF1 *f1 = new TF1("f1",myfunc, -1., 1., 3); // where 3 is the number of
// parameters for the function
f1->SetParameters(10.,h1->GetMean(), h1->GetRMS());
h1->Fit("f1");
A further example (from the ROOT site) of generating histograms with
random numbers from a function and then fitting those histograms is
provided here. There are some
more examples of fits and functions reproduced here.
Move the pointer over the histogram line (the cursor should change from cross to arrow) and click on the right mouse button. A context menu on TH1 should appear, from which you can choose FitPanel.
|
|
The FitPanel "slider" can be used to graphically restrict the fit range. The slider is the grey bar near the bottom of the fit panel, directly above the words "Fit", "Default", and "Close". If you move the mouse pointer over this slider, at the ends of its ranges the pointer changes from a cross to "|<-" at the left-hand edge and "->|" at the right-hand edge. When the pointer is displayed in this way, you can change the fit ranges by holding down the left mouse button and dragging the left- or right-hand edge of the slider to a new position. The changing fit range is shown graphically on your canvas as a vertical line that moves along as you move the slider.
Related Documents
The ROOT file in this example contains two separate ntuples, or trees. Trees are discussed later in this workbook chapter, but for now, is it sufficienct to follow the instructions below to access one of the trees in this file.
First open the file and access the tree called h2013:
TFile* myfile = new TFile("taufile.root");
TTree* mytree = (TTree*)gDirectory->Get("h2013");
A cut is defined in ROOT by way of a TCut object. For example,
TCut *cut1= new TCut("nPi0s>2");
where here the fully correct C++ syntax is provided to allow this command to be used in a macro. "nPi0s" is a property of the objects about which information is to be plotted. This could be used, for example, to plot thrust vs the minimum angle between particles in each hemisphere of an event for events, but only selecting those events in which there were more than two pi0s detected. The object would then be drawn with, e.g.
mytree->Draw("thrustMag:MinAngBtwHemis",*cut1);
c1->Update(); //update canvas called c1
In this case it is assumed that there is one entry in the ntuple
(compare: one row in a spreadsheet, where the columns represent
different information about that entry). Note also that in the
Draw(...) function call, the actual TCut object (*cut1)
is passed, rather than just the pointer (cut1).
Also, to plot only a section of the data:
mytree->Draw("ch_px_cms","ch_px_cms>0");
The above command displays "ch_px_cms", where
"ch_px_cms" is greater than zero. (Compare with the result
when plotting without the cut). In this case, the cut wasn't defined
as a TCut object, instead it was simply included in the
Draw(...) function call, in quotes.
You can use more than one cut, using logical operators to choose the inter-relation of the cuts, for example
mytree->Draw("ch_px_cms","(ch_py_cms<.5)&&(ch_pz_cms>1)");
While you can clearly use cuts without having to define a TCut object, it does become cumbersome, particularly if several cuts are to be used, or if the cut is to be used repeatedly and the value of it might be changed. In which case it is much better to define several TCut objects at the start of your code and only have to edit them in one well-defined place.
Related Documents
A ROOT Object Browser is instantiated with a command like
TBrowser* tb = new TBrowser();or, simply
TBrowser tbA new Object Browser window should appear which looks like this
Now start a TBrowser with:
root[0] TBrowser tbOpen the file by selecting
File->Open in the menu bar
and choosing "SimpleTree.root".
You can now look at the contents of this file by double-clicking on
ROOT files (in the right-hand pane of the TBrowser) and
then double-clicking on the filename. This file contains a single tree
(see the Trees section later in this WorkBook
chapter) called SimpleTree. To look at the contents of the tree,
double-click on that. The display will now list the contents of the
tree - namely E, Px, Py, Pz, n.
You can display the data in any of these leaves of the tree by
double-clicking on the name of the leaf. Try this by double-clicking
on the Px label. You should see a histogram which
looks like this file.
Now click on Options in the menu bar of the canvas and
select Event Status. Click on the Canvas again and point
to the histogram line with the mouse pointer. You should see a display
of the bin contents (and other things) in the lowest row of the
canvas - this is particularly useful when looking at a log plot to
determine the x and y coordinates of a particular point on a line.
Now get the Editor by clicking on Edit->Editor in
the menu bar of the canvas containing the histogram:
Get a DrawPanel by moving the mouse pointer to the histogram line in any bin (the pointer should change from a cross to a pointer), clicking the right mouse button and choosing DrawPanel:
Have a play with some of the options (lego1 is nice) by clicking on the option and then clicking on "Draw".
Get a FitPanel by moving the mouse pointer to the histogram line in any bin (the pointer should change from a cross to a pointer), clicking the right mouse button and choosing FitPanel:
Again, have a go by clicking some options and then clicking "Fit" (we'll do a bit more with this later in this Workbook Chapter.
Back in the ROOT Browser: Show the variables contained in the tree by double clicking on the tree icon (SimpleTree):
Display the variable by double-clicking on its name:
Try clicking the right mouse button on the SimpleTree icon, you'll
get a context menu. To start the GUI for working with Trees, choose
StartViewer from this context menu. (If a pop-up window
appears prompting you for width (ww) and height (wh) settings, select
OK in that window.
c1.
In this section we will see some of the power of the ROOT canvas
First load in a root file as above, e.g. myrootfile.root, and display the
histogram:
h1.Draw();You can enlarge the canvas like any window by click-and-dragging e.g. a corner of the window containing the canvas.
By right-clicking on different areas of the canvas, you are presented with a drop-down menu with different options for displaying your picture. For example (assuming the graph is displayed with a legend and a stats box):
| Click on | Options |
|---|---|
| x-axis | attributes of x-axis |
| y-axis | attributes of y-axis |
| graph title | title display |
| area inside histogram | histogram attributes such as fill style |
| area outside histogram | canvas display options such as log scales |
| legend box | legend display |
| stats box | stats box display |
zone 2 2 in PAW)Assuming you have a canvas c1, the CINT way is
c1->Clear(); c1->Divide(2,2); // divisions in x and yTo select the subdivision of the canvas to change the focus to, the command-line entry required is, for example,
c1->cd(3); //where c1 is the canvas name, and 3 is one of
//the subdivisions of the 2x2 canvas
(You can test this by plotting your histogram again,
h1->Draw(); and seeing that it appears in the 3rd place.)
The GUI-way is to right-button click on the canvas, choose "Properties", then select "Divide" and fill in the nx and ny attributes. You can then move the mouse pointer over the pad you want to access and click the middle button.
c1->Clear(); //clear the contents of the current canvas
TFile f("example.root");
f.ls(); //just to check what's there
f.cd("pi0_dir"); //to change into a subdirectory of the file
TPad *npad = new TPad("npad", "", 0.6, 0.2, 0.9, 0.5);
npad->Draw();
npad->cd();
gg_massM->Draw();
c1->Clear();
c1->Divide(2,2);
c1->cd(1);
pi0CosThM->Draw();
c1->cd(2);
mass_v_energyM.Draw("surf");
c1->cd(3);
gg_massD.Draw();
c1->cd(4);
mass_v_energyD.Draw();
The last set of commands creates a 2x2 pad and steps through each
element of the pad drawing a different histogram. The output should
look like this:
The following command clears the canvas and returns it to having just one pad on the canvas:
c1->Clear()
That said, CINT is great for all the interactive display stuff usually needed for getting plots into a form suited for presentation.
CINT completes partially typed commands, provides you with a list of arguments a given function expects and completes filenames you have to enter. Try
root[0] TFi<TAB>
root[1] TFile f(<TAB>
root[2] TFile f("fr<TAB>
where <TAB> indicates you have to hit
the TAB key.
Further, if you type in a variable followed by an arrow, for example:
gStyle-> and then enter a tabThis will print out a listing of all the methods and members of gStyle, and lists all the things that you can dowith gStyle. You can continue it by typing in
gStyle->SetOptS<tab>etc. If you enter the name of a function, say
gStyle->SetOptStat( and then a taba list of the parameters that are expected for this function will appear. If the method has multiple definitions, called with different parameter lists, then all of them are displayed.
CINT allows you to scroll through your history of commands with the arrow keys (just like PAW). It keeps this history between sessions and you can scroll through previous sessions (unlike PAW). This is a very useful feature.
CINT also provides you with a search facility in its history,
accessible with <Ctrl-r>. Try
root[3] <CTRL-r> TF
rootlogon.C
The equivalent of pawlogon.kumac. It is good to keep it as short as possible.
.root_hist
This text file stores a history of the commands you entered during a ROOT session. These commands can be copied out of this text file and into a macro (see below) to be used later.
In the section about fitting you created a
macro called myfunc.C to define a new function,
myfunc();. A macro is a C++ function defined with the
syntax:
return_type function_name(arg1_type arg1_name, arg2_type,
arg2_name, ...) {
commands with ";%quot; at the end of each line;
}
Macros can be loaded with the command
.L mymacro.CAnd the macro is then called with the command
function_name(parm1, parm2...);You can also load and execute statements saved in a file using
.x myfile.CFor example, load the macro
myfunc.C you created earlier
with
.L myfunc.Cand define a function with it:
TF1 *f1 = new TF1("f1", myfunc, -1.,1., 3);
// here 3 is the number of parameters for the function
You can now use this function for fitting, plot it, etc.
You can also write unnamed macros as a bunch of commands, enclosed in
braces, and with each line ending in a semi-colon, and put them in a
file (e.g. macro1.C)
// macro.C
{
cout << "hello world" <<
endl;
}
and execute them in a ROOT session with
.x macro1.CYou can put functions into a file e.g.
macro2.C
//macro2.C
void helloWorld() {
cout << "Hello World" << endl;
}
and load and execute any function in that file in two steps:
root[2] .L macro2.C root[3] helloWorld()By the way, after you loaded the file, ROOT knows about your function, so instead of the above, try to hit <TAB>:
root[3] helloWo<TAB>Further example macros are here. These files are copies of the ROOT distribution examples.
TChain,
provided those files have the same internal structure. In that way,
you can treat them as one contiguous ROOT file. For example, if you
have two ROOT files, fil1.root and fil2.root, you can link them using
the command:
void
input_data( TChain* dataChain )
{
dataChain->Add("fil1.root");
dataChain->Add("fil2.root");
}
A single ROOT file can hold several trees, as in the example file taufile.root first introduced in the Cuts section in this workbook chapter. Each tree is independent, like an individual file, and it is not possible to plot quantities in one tree subject to cuts on quantities in another tree.
Opening the example file:
root [0] TFile *myfile=new TFile("taufile.root");
We can list the objects (trees and histograms) contained in the file:
root [1] myfile.ls() TFile** taufile.root HBOOK file: .../tau-1571.hbook converted to ROOT TFile* taufile.root HBOOK file: .../tau-1571.hbook converted to ROOT KEY: TTree h2013;1 1-3 KEY: TTree h2033;1 3-3
This tells you the irrelevant information that this file was actually
made by converting a PAW file to ROOT format. It also shows that there
are two trees in the file, h2013 and h2033,
and no histograms.
To access the contents of a tree, you can make a tree object which holds the contents of one of the trees in the file:
myfile.cd() //make sure ROOT's focus is on myfile
TTree* mytree = (TTree*)gDirectory->Get("h2013");
By calling TTree functions of the mytree object, you
can now access the contents of the tree h2013 from taufile.root. For
example, to get a list of branch or leaf names, enter:
mytree->GetListOfBranches()->Print(); mytree->GetListOfLeaves()->Print();You can also inspect the contents of a tree with the TBrowser described here.
Executing the example with
.x roottest.Ccreates a tree with up to 200,000 variables per event. It creates a tree called "SimpleTree" which contains 5 branches, n, E, Px, Py, Pz. The last 4 entries are array-valued entries, containing n elements for each entry, which could be the energy and 3 momenta of tracks for BaBar events containing n tracks per event. The energy and momentum components have Gaussian distributions, as defined in the macro.
The resulting tree is written into a file called SimpleTree.root. This root file, and the tree in it can be inspected in the manner described in this Workbook chapter, and in Introduction to ROOT.
.x someMacro.cc > outFile.txt
ofstream fout;
int count;
fout.open("outputFile.dat");
for (count=0; count<total; ++count) {
fout << sig[count].name << " "
<< sig[count].slope << " "
<< sig[count].coeff << endl;
}
Finally, you can dump the output of an ntuple directly to a text file
with the commands
ntp->Print(); > output.log
ntp1->Scan("momentum"); > output.log
to get the output (of a tree ntp1) into a file. Don't forget the ';'.
.! commandfor example,
.! lswill list the contents of the current shell directory, i.e. the directory from which you started the present ROOT session. To display a message:
printf("Welcome\n");
Follow the link above for instructions for setting up and using RooFit for BaBar analyses. During BaBar Collaboration meetings, there are often RooFit tutorials conducted by experts.