This tutorial demonstrates how to work interactively with ROOT:
Fundamentals (environment, GUIs, definitions)
Doing simple interactive analysis with trees and histograms
Build your own trees (two examples - a trivial 'ntuple' and a more advanced tree)
Put this tree into a Beta Module
Note: You may want to skip parts of this tutorial if you already have some experience with ROOT.
To execute this tutorial successfully, you will need:
a unix account properly configured for the BaBar environment (i.e., one which executes the hepix scripts at login);
10 MB free space on disk;
scratch disk space for your account on $BFROOT/work (this can be easily created if you have never used it before).
In the following,
red
text is used to indicate what you have to type in at the UNIX
prompt.
blue text is used to show
what you have to type at the ROOT prompt
red/brownish
is used to indicate exercises.
A comprehensive list of links to documentation on ROOT can be found at BaBar's webpage on ROOT Documentation
![]()
Here, we will
introduce the environment variables ROOTSYS and LD_LIBRARY_PATH, set up initialization files
make quick tour of ROOT introducing most of the concepts needed later
introduce some characteristics of the C++ interpreter (CINT)
Logon to a Unix platform. At SLAC
this is usually shire or tersk. You can
also use the Linux machines noric.
Create a directory to contain the ROOT files and macros of this tutorial:
cd ~ mkdir rootutorial cp $BFROOT/www/doc/tutorials/19Jun2000_Root_Tutorial/sample.rootrc ~/rootutorial/.rootrc cp $BFROOT/www/doc/tutorials/19Jun2000_Root_Tutorial/rootlogon.C ~/rootutorial/. cd rootutorial
ROOT needs two environment variables: ROOTSYS and LD_LIBRARY_PATH. If they are not set, nothing will work in ROOT. Nothing. ROOTSYS points to the base directory of the local ROOT installations. LD_LIBRARY_PATH is the path searched for shared libraries.
For the purpose of this tutorial (and probably also in real life), you should set ROOTSYS and LD_LIBRARY_PATH yourself:
setenv ROOTSYS /afs/slac.stanford.edu/package/cernroot/30207 setenv LD_LIBRARY_PATH $ROOTSYS/lib
and start ROOT with
$ROOTSYS/bin/root
The advantage of this method that you do not depend on BaBar software and are free to chose whatever ROOT version you like. The disadvantage is that you cannot go back to an older version of ROOT than used to make your rootfile (this is now possible with ROOT versions above 3.00.) On SunOS, a wrapper script is available as well:
cernroot
(SCS did not like the idea of having a program called 'root' in /usr/local/bin/.) On Linux, you probably want to create a symlink somewhere in your path to point to $ROOTSYS/bin/root.
|
Exercise: Start up ROOT with the wrapper script |
cernroot |
|
After you get ROOT's prompt, start the demos toolbar with |
.x demos.C |
|
Quit ROOT |
.q |
In BaBar, you can use ROOT with the wrapper script bbrroot (which works only after srtpath has been executed) or you can use ROOT on its own. Both versions have advantages and disadvantages.
Once you have done 'srtpath', ROOTSYS points to the ROOT version used in your testrelease. For all 'current' BaBar software releases this is 2.23/12. For releases analysis-14 and 12-series and later, this is root 3.02/07. In addition, LD_LIBRARY_PATH is set properly. You can start ROOT with
bbrroot
The advantage of this script is that the ROOT version used to produce your rootfile (the output of e.g. a Beta job) will be matched to your interactive ROOT version. (This is not a sine qua non, ROOT is generally backwards-compatible.) The disadvantage is that you can be tied to old versions of ROOT and thus miss many improvements which make the interactive usage much more convenient.
When you start to use ROOT seriously, you need its documentation, which is embedded in the source code. There is a hyperized version available at CERN (the most recent version of ROOT, usually) and here at SLAC you can find the source code for all installed versions from the ROOT documentation page.
During startup, ROOT reads in a few files:
.rootrc (used to set up different paths ) and
rootlogon.C (containing e.g.style definitions, etc.). Note that if you start root in a vanilla BaBar workdir, the logon file is called RooLogon.C and this overrides your ~/rootlogon.C.
In a BaBar workdir, ROOT will also read RooAlias.C with some function definitions
You can convert a normal HBOOK file to a rootfile with /usr/local/bin/h2root:
/usr/local/bin/h2root framework.hbook
Canvas: A canvas is a graphics window where e.g. your histograms wil be displayed (like the HIGZ window in PAW), You can enlarge the canvas like any window by click-and-holding e.g. a corner of the window containing the canvas.
|
Exercise: Start up ROOT |
cernroot |
|
Start the demos once again |
.x demos.C |
|
Execute an example |
Left-Click on hsimple |
|
You'll get a canvas. The canvas has a menu bar at the top |
Left-Click on Options and select Event Status |
|
Left-Click into the histogram frame |
|
|
Watch how the cross-hair cursor changes to an arrow. |
Move the pointer carefully to top of a histogram bin. |
|
Carefully watch the display at the very bottom of the canvas. |
|
|
|
|
Editor: Once you have a canvas, you can start up the editor for putting graphical components on the canvas:
|
Exercise: Start the ROOT graphics editor |
|
|
Start the editor |
Left-Click on Edit and select Editor |
|
Draw an arrow on the canvas |
Left-Click on Arrow, move the pointer
into the canvas, |
Browser: ROOT comes along with a browser that can display objects known to a ROOT session. It can be a handy tool to explore ROOT.
|
Exercise: Start the ROOT browser and display a histogram |
|
|
Start the browser |
Left-Click on Inspect and select Start Browser |
|
Open the folder ROOT files |
Double Left-Click on ROOT files in the main browser window |
|
Open the hsimple.root file |
Double Left-Click on hsimple.root |
|
You'll see a few pictograms. Display one of the histograms. |
DoubleLeft-Click on hpxpy |
Pad: A Pad is a subdivision of a canvas. (Similar to a zone in PAW.) Click on surfaces in the demos toolbar.. A canvas with two subdivisions will appear - each one is a pad. You can resize the pad by left-clicking on the corners of the pads.
Context menu: Click on hsum in the demos toolbar. Move the cursor over the box with the statistics and click with the right mouse button. A menubar (labelled 'TPaveStats::stats') will appear. It gives you access to member functions of the class TPaveStats. For example, select FillAttributes. A window will pop up. Click on a color and select Apply. All objects displayed have context menus associated with them.
Exercise: Find the context menu of the x-axis (Hint: the cross-hair cursor will change to a hand symbol when the cursor is at the right place). Add a title.
Exercise: Find the context menu of the histogram shown with the small squares. (Hint: the cross-hair cursor will change to an arrow when you hit the right place Try to aim for one of the squares. Don't despair: It's not trivial.) Change the marker symbol and its size.
Tree: A tree is (roughly) the equivalent of an ntuple though far more powerful: You can store objects (e.g. vectors ) and not only numbers.
Exercise: Open the browser if you closed it. Find the 'ntuple' (Hint: it's contained in the hsimple.root file.). Double-click on its icon. You'll see all variables (leafs) displayed. Double-click on one of them to display it.
TTreeViewer is a graphical interface to the use of trees. It is described in the Getting Started with ROOT document at FNAL.
Branches and Leafs: If you think of a tree like a directory structure, a branch is like a 'subdirectory' of the tree. The actual variable is a leaf (like a file in a subdirectory). You can have multiple leafs per branch or you can have one leaf per branch (this is the case in the 'ntuple' ntuple encountered above.)
Naming conventions: ROOT adheres to some naming conventions in its source code. Names of classes start with 'T', simple types are capitalized and have '_t' appended (e.g. Float_t). Data members start with ' f '.
Macros: The equivalent of a KUMAC. Written in (not quite standard) C++. By clicking on any of the buttons in the demos toolbar, you will execute a macro. $ROOTSYS/tutorials contains a lot of very instructive macros. There are named and unnamed macros: See below for more information.
CINT is quite sophisticated, but not perfect. You can crash it badly. You will restart ROOT more often than PAW. You need some experience to know when you can continue with CINT after having had an error. Some people (sometimes) would not bet on results obtained with CINT. Keep that in mind when your macro gets complicated. Nothing beats the security and reassurance of a trustworthy C++ compiler.
That said, CINT is just wonderful for all the interactive display stuff usually needed for getting plots into a form suited for presentation.
CINT commands always start with a dot `.'. The most important ones include
|
Command |
Action |
|---|---|
|
.q |
Quit ROOT |
|
.x bla.C |
Load and evaluate statements in the file bla.C |
|
.L bla.C |
Load macro bla.C |
|
.! shellcommand |
Execute shellcommand in shell |
|
.? |
Get list of CINT commands |
CINT's extensions to C++ are the following:
In interactive usage, the semicolon at the end of a statement is not required (but it is required in macros!)
-> can be abbreviated with . (example: hist->Draw() is equivalent to hist.Draw())
The following two lines are equivalent by definition and in order to save typing
b
= new TClass(...);
TClass *b = new TClass(...);
If an object is not declared upon first usage, CINT searches ROOT's global scope for an object with an identical name and sets up a pointer variable with the same name and initializes the variable to point to the object found.
As mentioned in the quick tour, macros come in two species:
|
|
named macro: helloWorld.C |
Unamed macro: helloWorld.cxx |
Comments |
|
Source code |
void helloWorld(int t = 3) { |
{ |
-> Note braces at beginning |
|
execution in CINT |
.x helloWorld.C(123) |
.x helloWorld.cxx |
Don't miss that initial point ' .' when copying |
|
Loading and then executing entry point |
.L helloWorld.C |
|
|
|
Scope |
scoped according to the usual C++ rules, no f visible after macro has terminated |
all statements are executed in CINT's global scope, i.e. f is visible in the ROOT session after the macro has terminated |
|
![]()
In this part you will learn how to
use the command line in ROOT
write your own macros
work with trees, histograms, and functions (including fitting)
make (presentable) plots
Here the emphasis will shift to the command line (or equivalently to macros), and the interactive GUI approach will usually be left as an exercise.
Start by copying an example rootfile from the tutorial area:
cp $BFROOT/www/doc/tutorials/19Jun2000_Root_Tutorial/Exercise3.root ~/rootutorial
Start up root:
cernroot
Open the file you just copied:
TFil<TAB>
TFile f("<TAB>
TFile f("Exercise3.root");
|
ROOT has a built-in completion. Type part of the name and ROOT will try to complete as much as unambiguously possible. |
Look what's in the file:
f.ls() |
ls() is one of the exceptions to capitalization |
TFile** Exercise3.root
TFile* Exercise3.root
KEY: TH1F h1d1;1 MicroFilter;# +trk
KEY: TH1F h1d2;1 MicroFilter;# -trk
KEY: TH1F h1d3;1 MicroFilter;# neutrals
KEY: TH2F h2d4;1 MicroFilter;;# +trk;# -trk/
KEY: TH1F h1d5;1 MicroFilter;# electron
KEY: TH1F h1d6;1 MicroFilter;# muon
KEY: TH1F h1d7;1 MicroFilter;# pion
KEY: TH1F h1d8;1 MicroFilter;# Ks
KEY: TH1F h1d9;1 MicroFilter;# JPsi
KEY: TH1F h1d10;1 MicroFilter;# B0
KEY: TTree ntp1;1 Jpsi Ks micro Analysis
KEY: TH1D h1;1
Draw a histogram:
h1d1->Draw();
h1d1->Print("all");
|
or: h1.Draw() |
Save the output:
c1->SaveAs("bla.eps");
c1->SaveAs("bla.ps");
c1->SaveAs("bla.gif");
|
this assumes that your histogram is displayed in a canvas called "c1" (which should be the case if everything went fine) |
Get more pads:
TPad *npad = new TPad("npad", "", 0.6, 0.2, 0.9, 0.5);
npad->Draw();
npad->cd();
h1d1->Draw();
c1->Clear();
c1->Divide(2,2);
c1->cd(1);
h1d1->Draw();
c1->Clear()
|
Opening a new pad allows the drawing of insets
Go back to one pad on the canvas |
Operations with histograms
TH1F *htmp = new TH1F(*h1d1);
htmp->Add(h1d1, h1d2);
htmp->Draw();
htmp->Divide(h1d1, h1d2);
htmp->Draw("e");
|
Make a copy of a histogram |
Zoom and unzoom:
htmp->SetAxisRange(4., 15., "x"); gPad->Modified(); |
Zoom - GUI: explained in part 1 |
htmp->SetAxisRange(0., -1., "x"); |
Zoom -GUI: Move to Axis context menu, select UnZoom |
Logarithmic axes:
gPad->SetLogy(1); gPad->Modified(); |
Not a histogram method! |
Gridlines
gPad->SetGridx(1); gPad->SetGridy(1); gPad->Modified(); |
|
Change the drawing style (e.g. markers, color)
h1d1->Draw("p");
h1d1->SetMarkerStyle(20);
h1d1->SetMarkerSize(1.);
h1d1->SetMarkerColor(kBlue);
gPad->Modified();
|
You'll have to look very closely to see anything |
Enlarge axis labels, add axis titles:
h1d1->SetTitleSize(0.06, "x");
h1d1->SetTitleOffset(1., "x");
h1d1->SetXTitle("Axis title text");
gPad->SetBottomMargin(0.15);
gPad->SetLeftMargin(0.15);
h1d1->Draw();
|
Title size, offset and text |
Overlay two histograms:
h1d2->SetFillColor(kYellow);
h1d2->SetFillStyle(1001);
h1d2->Draw("hist");
h1d1->Draw("psame");
|
"Same" puts onto same pad |
Make a Legend:
TLegend *pl = new TLegend(0.4,0.5,0.7,0.7); pl->SetTextSize(0.04); pl->SetFillColor(0); TLegendEntry *ple = pl->AddEntry(h1d2, "Positive tracks", "l"); TLegendEntry *ple = pl->AddEntry(h1d1, "Negative tracks", "p"); ple->SetMarkerSize(1.); pl->Draw(); |
See documentation for more details |
|
|
|
Add a text box:
TPaveText *pt = new TPaveText(0.2, 0.7, 0.4, 0.85, "NDC");
pt->SetTextSize(0.04);
pt->SetFillColor(0);
pt->SetTextAlign(12);
pte = pt->AddText("bla");
pt->Draw();
|
|
Switching off/on the statistics box:
gStyle->SetOptStat(0); h1->Draw(); gStyle->SetOptStat(1111111); h1->Draw(); gStyle->SetOptStat(1); h1->Draw(); |
Check out the documentation what the different digits mean |
|
Exercise: Write a macro that produces output similar to what is shown on the right: open
Exercise3.root Exit and restart ROOT, and execute you rmacro with .x inset.C (assuming you named it inset.C) |
There are a few built-in functions, but in addition you can define your own functions. There are one-, two-, and three-dimensional functions (TF1, TF2, and TF3)
Instantiate and draw a function defined in terms of internal functions:
TF1 *f0 = new TF1("f0", "sin(x)/x", 0., 10.);
f0->Draw();
TF1 *f1 = new TF1("f1", "0.5*f0", 0., 10.);
f1->SetLineColor(kBlue);
f1->Draw("same");
TF1 *f2 = new TF1("f2","[0]*x*sin([1]*x)",-3.,3.);
f2->SetParameters(10., 5.);
f2->Draw();
|
sin() is built-in No user-defined functions for "f0" Add parameters |
Define your own functions
TF1 *u0 = new TF1("u0", MyFunction, 0., 10., 3);
u0->SetParameters(100., 5., 1.2);
u0->Draw();
|
Put the following into a file called MyFunction.C Double_t
MyFunction(Double_t *x, Double_t *par) { and load it with .L MyFunction.C |
Fitting histograms with predefined functions, user-defined functions, and compositions of pre-defined functions. :
gStyle->SetOptFit(1111);
h1->Fit("gaus");
h1->Fit("gaus", "R", "", 0.9, 1.1);
h1->Fit("gaus", "R", "p", 0.9, 1.1);
|
Gaus is predefined and needs no further initialization. Further
predefined functions include pol0 .... pol9, landau, expo |
TF1 *myG = new TF1("myG", MyFunction, 0.6, 1.4, 3);
myG->SetParameters(h1->GetMaximum(), h1->GetMean(), h1->GetRMS());
h1->Fit("myG");
|
User-defined function |
TF1 *ff = new TF1("ff", "gaus + pol2(3)", 0.6, 1.4);
ff->SetParameters(h1->GetMaximum(), 1., 0.05, 1000., 1., -2.);
h1->Fit("ff");
|
pol2(3) means that the parameters for the polynomial of second order start at position 3 in the parameter array. |
Accessing the information from Minuit:
double parValue, parError; gMinuit->GetParameter(2, parValue, parError); cout << parValue << " " <<parError << endl; |
|
Try to do it better by taking two gaussian. Put everything into a macro to produce output in a decent format:
|
Exercise: Write a macro that opens
Exercise3.root Quit and restart ROOT adn execute this macro with .x plot.C (assuming you named it plot.C)
|
|
Exit from ROOT and start fresh. Load Exercise3.root. |
Look what's in the tree:
ntp1->Print(); |
Print the branches of the tree, how many entries per branch, etc |
ntp1->Scan(); |
Dump the variable values (for the first few variables) |
ntp1->Scan("massKs:pxKs");
|
Select the variables to be printed |
ntp1->Scan("massKs:massJpsi", "nKs ==1");
|
Dump the variable values and apply a cut |
|
|
Draw variables of a tree:
ntp1->Draw("massKs");
|
Draw a variable |
TH1D *hh = new TH1D("hh", "temporary histogram", 100, 0., 1.);
ntp1->Draw("massKs>>hh");
ntp1->Draw("massKs>>+hh");
|
Define a histogram to be filled from tree and fill it |
ntp1->Draw("pxKs:pyKs");
|
2d plot |
ntp1->Draw("sqrt(pxKs+pyKs+pzKs):sqrt(pxKs*pxKs+pyKs*pyKs)", "", "colz");
|
2d plot, no cut applied, but drawing option specified |
|
|
Make a function skeleton to analyze a tree:
ntp1->MakeCode(); |
The equivalent of uwfunc. Produces a macro ntp1.C |
Exercise: After generating the function skeleton, start up your favorite editor and open ntp1.C. At the end, you'll find the commented loop over 'nentries' entries in the tree.
|
Jump to the end of the file, |
|
|
you'll find a loop over ' i ' that is commented out: |
you are looking for // for (Int_t i=0; i<nentries;i++) { |
|
Instantiate a TH1F just before that loop: |
TH1F *hmks = new TH1F("hmks", "mass", 100, 0., 1.); |
|
|
|
|
Un-comment the loop: |
for (Int_t i=0; i<nentries;i++) { |
|
In the loop,
add another loop over the KS candidates |
for (Int_t iCand = 0; iCand < nKs; ++iCand)
{ |
|
Your macro should look now like this |
|
|
Exit from ROOT, restart it and execute the macro: |
.x ntp1.C |
|
|
|
|
Display the histogram: |
hmks->Draw() |
LIving in the times of OO, the equivalent of a COMIS function is not attractive to some. ROOT offers an alternative:
ntp1->MakeClass(); |
The OO approach to the same problem. |
Save Histograms to another rootfile: In ROOT, you are always in a directory. Before opening a file, this is Rint:. You can cd() to different directories. Saving histograms (objects in general) put them into your current directory.
|
Quit ROOT and start over again |
|
|
Print your current directory |
gDirectory->pwd() |
|
Open a file (in read-only mode, the default) |
TFile f("Exercise3.root") |
|
Print your current directory |
gDirectory->pwd() |
|
Open an output file |
TFile g("new.root", "RECREATE") |
|
Print your current directory |
gDirectory->pwd() |
|
Find the histograms in the old file and write them to the new |
(TH1*)f->Get("h1d1")->Write(); |
|
Close the new file |
g.Close() |
|
|
|
|
|
|
|
Open it with another TFile |
TFile h("new.root"); |
|
Check that the histogram actually is there |
h1d1->Draw() |
|
And don't close a file if you are still using objects of it |
h.Close() |
|
(because else you loose them ... your canvas should be empty now) |
|
This also happens when writing macros, so be warned: don't close your files too early!
c1->SaveAs("display.C");
|
Writes a macro that should reproduce your canvas. Very useful when working with the editor on a template and then wanting to convert that to a macro. |
![]()
Here you can find two examples of how to build trees - a trivial one and a more complicated one. Additional information on this topic can be found in the ROOT 102 tutorial Fermilab.
This comes in two incarnations, an interactive version and a compiled version, that also serves to introduce you to compiled ROOT programs.
Macro: Get the macro version and save it. It's documented, so have a look at it. After running this macro, you'll find a rootfile simpleTree.root in your directory:
.x simpleTree.C
TFile g("SimpleTree.root");
g.ls();
SimpleTree->Print();
SimpleTree->Draw("Pz");
Compiled stand-alone program: It is very easy to change this macro to a stand-alone program. You'll need the GNUmakefile,(you'll need to define an environment variable ARCH, it's described in the file) and the source, which has only some header files added and an instance of TROOT (the big common block of ROOT ...)
setenv ARCH `uname` gmake simpleTree ./simpleTree
This will produce a rootfile with a tree SimpleTree in it. Look at it in ROOT with
TFile g("SimpleTree.root");
g.ls();
SimpleTree->Print();
SimpleTree->Draw("Pz");
The following is a version with minimal coupling to BaBar software (mainly for historical reasons). It works, it's being used in improved versions in at least three analyses within BaBar , but is by far neither the only way nor very clever - au contraire. Enough disclaimers.
1. Define what you'll put into the tree per event. Here we'll make the definition of an event class (TMyEvent) containing several candidates (TMyCand) of the same kind. You can of course expand the example to include several lists of cands. Copy the following files:
cp /afs/slac.stanford.edu/g/babar/www/doc/tutorials/19Jun2000_Root_Tutorial/TMyEvent.hh ~/rootutorial cp /afs/slac.stanford.edu/g/babar/www/doc/tutorials/19Jun2000_Root_Tutorial/TMyEvent.cc ~/rootutorial cp /afs/slac.stanford.edu/g/babar/www/doc/tutorials/19Jun2000_Root_Tutorial/TMyEventLinkDef.h ~/rootutorial cp /afs/slac.stanford.edu/g/babar/www/doc/tutorials/19Jun2000_Root_Tutorial/TMyCand.hh ~/rootutorial cp /afs/slac.stanford.edu/g/babar/www/doc/tutorials/19Jun2000_Root_Tutorial/TMyCand.cc ~/rootutorial cp /afs/slac.stanford.edu/g/babar/www/doc/tutorials/19Jun2000_Root_Tutorial/TMyCandLinkDef.h ~/rootutorial cp /afs/slac.stanford.edu/g/babar/www/doc/tutorials/19Jun2000_Root_Tutorial/GNUmakefile ~/rootutorial
The ClassDef and ClassImp macros in the header and source files (respectively) are necessary to link your classes to the dictionary (generated by CINT) to get access to RTTI and other object I/O features of ROOT. The RTTI system allows you to, a.o. find out to which class an object belongs, its baseclasses, its datamembers and methods, the method signatures, etc. Read the full documentation for further details (you absolutely don't need to understand the details in order to use this!)
2. Change your .cshrc:
setenv ARCH `uname` setenv ROOTSYS /afs/slac.stanford.edu/package/cernroot/30207 setenv ROOTVER 3.02-07 setenv ROOTPATH $ROOTSYS addpath2 PATH $ROOTSYS/bin setenv LD_LIBRARY_PATH $ROOTSYS/lib
Note that you need to change the line with LD_LIBRARY_PATH, if you set that variable already. You need to adjust your path for the compilation, hence it is probably best to fix a version for ROOTSYS in your .chsrc. You have to be very careful about which ROOT version you use:
If you'd like to go with BaBar's standard version, then you have to take 2.23/12 for releases before analysis-14 and the 12-series. This implies that for using a non-trivial tree, you'll need to do your analysis with ROOT 2.23/12. (This is probably not what you want. ROOT has advanced a lot since those times and you probably want those features in interactive work.)
You can also adjust the ROOTSYS in the GNUmakefile, but you need to keep in mind that you
cannot read with ROOT 2.23/12 a tree written with 3.02/07 (you probably don't want to do that, but ...)
need an so-lib compiled with 3.02/07 in order to read a tree with ROOT 3.02/07
cannot use ROOT 3.02/07 in conjunction with an so-lib compiled in 2.23/12
At the moment, everything is set-up to use 3.02/07. This means, that you'll need to check out additional packages when incorporating this into a BaBar release (see below).
3. Compile the source code and link it into a shared library in a new shell:
cd ~/rootutorial/. gmake myclass
4. Now you have interactive access to this class from a ROOT session:
gSystem->Load("libPhysics.so");
gSystem->Load("~/rootutorial/libMyClass.so");
TMy<TAB>and you could e.g. instantiate objects of your event and candidate classes. An example macro filling this tree is given in writeMyEvent.C. A macro for reading the rootfile back in is provided in readMyEvent.C (with a compiled version in readMyEvent.cc)
You can write and read your custom tree with the two macros:
.x writeMyEvent.C .x readMyEvent.C
Compile and link the executable with
gmake readMyEvent
![]()
In the previous part you found an example of a possible non-trivial tree structure. In this part,you'll find templates of the necessary files to get this into a Beta job.
1. Go to a testrelease area, and check out BetaUser
2. Copy the following files into your BetaUser directory:
cp /afs/slac/g/babar/www/doc/tutorials/19Jun2000_Root_Tutorial/WorkBook* BetaUser/. cp /afs/slac/g/babar/www/doc/tutorials/19Jun2000_Root_Tutorial/bin_BetaUser.mk BetaUser/.
The additions (all marked with // -- ROOT) comprise the following:
Adding data members TTree *_Tree, and TMyEvent *_Event (with a forward declaration at the top of the header file)
Including the
relevant header files at the top of the source file.
Instantiating
objects of class TTree and TMyEvent in beginJob()
Filling the
TMyEvent object with candidate data and the tree with with the
TMyEvent.
Writing the tree out at endJob()
bin_BetaUser.mk: Add the line
override LOADLIBES += /your_home_directory/rootio/libMyClass.so
to get the dependency right for linking.
3. Set up links to your tree header files:
cd BetaUser ln -s ~/rootutorial/TMyEvent.hh ln -s ~/rootutorial/TMyCand.hh cd ..
4. Consider what ROOT version you want to use. If you go with 3.02/07 (recommended), check out all required additional packages for ROOT 3.02/07. In addition, you'll need to reset ROOTVER and ROOTPATH, BaBar-specific environment variables:
setenv ROOTVER 3.02-07
setenv ROOTPATH $ROOTSYS
If you don't care about recompiling a few additional packages, you can do everything with one modern version, e.g. 3.02/07 (a recent production version well tested within BABAR).
addpkg BtaDataR
addpkg EidDataR
addpkg StdHepDataR
addpkg TagDataR
addpkg RooCond
addpkg RooModules
addpkg RooScribes
addpkg RooSequences
addpkg RooTuple
addpkg RooTupleEnv
addpkg RooUtils
For release analysis-13 you may also need to add
addpkg RooPidCond
Update BtaDataR/BtaDataR_LinkDef.rdl:
cd BtaDataR
cvs update -A BtaDataR_LinkDef.rdl
You'll need to comment a few lines in RooTuple/RooHistogram.cc:
noric04>cvs diff RooHistogram.cc
[snip]
70c70
< histp->Fill( x, weight, 1 );
---
> // histp->Fill( x, weight, 1 );
87c87
< histp->Fill( x, y, weight );
---
> // histp->Fill( x, y, weight );
92c92
< histp->Fill( x, y, weight );
---
> // histp->Fill( x, y, weight );
This is obviously a kludge and should be necessary only if you are using analysis-13 or earlier.
setenv ....
bsub -q bldrecoq ....
6. The macro readMyEvent.C given in Part 3 should still be able to read the resulting tree, thus
.x ~/rootutorial/readMyEvent.C
[Thanks a lot to Thomas Schietinger for his help in debugging this.]