SLAC PEP-II
BABAR
SLAC<->RAL
Babar logo
HEPIC E,S & H Databases PDG HEP preprints
Organization Detector Computing Physics Documentation
Personnel Glossary Sitemap Search Hypernews
Workbook Home Introduction Account Setup QuickTour Packages Modules Unwrap page!
Event Information Tcl Commands Editing Compile and Link Run the Job Debugging
Check this page with the
W3C Validator
(More checks...)
Parameters Tcl Files Find Data Batch Analysis ROOT Tutorial

Analysis in ROOT III

This WorkBook section is intended to extend the knowledge gained in the WorkBook sections Root1 and Root2 to the higher level needed for a real BaBar physics analysis. The tutorial in this section was written by Christopher Hearty, and provides a walkthrough of a physics analysis session in ROOT.

Contents


Preliminary

This WorkBook section will allow you to make histograms from chains or individual files, with the histograms subdivided into various MC and data types. It shows you how to add functions to the standard MakeSelector class, or to use your own functions from outside the class. It uses ntuples produced using BtaTupleMaker in the Make CM2 Ntuples tutorial, but the concepts are applicable to any ntuple structure.

This tutorial is based on ROOT 5.26 on a standalone system (i.e. one not connected to the BaBar disk system), but root versions as old as ROOT 4.04/02 should also work. You can also run it on a yakut machine using the analysis-51 (AKA 24.3.6) release using the modified instruction located at the end of some sections. In this case, you start root 5.14 by typing bbrroot in the workdir directory. Remember to srtpath first (from the release directory). In general, I find it tidier to make a new release to analyze the ntuples, instead of using the same one I used to make the ntuples in the first place.

A slight familiarity with ROOT is assumed in this tutorial. For example, you should first have completed the WorkBook sections Root1 or Root2 or the FNAL root class.

This WorkBook section does not cover fitting of histograms.


Some basics

a. Define your Macro path:

Edit the file .rootrc, located in your home directory, to specify the path that root uses to look for macros.  Root first looks for a macro in the current directory, then in a subdirectory called "macros", then in $(HOME)/Work/macros. The full set of environmental variables is set in /sw/etc/root/system.rootrc directory.
[~]: cat .rootrc
# Path used to find macros.
Unix.*.Root.MacroPath: .:./macros:$(HOME)/Work/macros:/sw/share/root/macros:
[~]:

b. Edit rootlogin.C

The macro rootlogin.C is run whenever you start root. I put mine in the macro directory defined in the previous step, but you could put it in your analysis directory if you wanted to specialize it for a particular analysis. Here is mine:
[~]: cat Work/macros/rootlogon.C
{
printf("\nWelcome to rootlogon.C \n\n"); <-- print a message
gROOT->SetStyle("Plain"); <-- plain histogram style
gStyle->SetOptStat(1111111); <-- expanded stats box
gStyle->SetPadTickX(1); <-- tic marks on all axes
gStyle->SetPadTickY(1); <--
}

c. Special for analysis-51 on yakut

.rootrc is located in the workdir directory, not in your home directory.

The macro that is run when starting ROOT is called RooLogon.C, and is also located in workdir. It contains a reasonable default set of commands, but you can edit it if you would like something different.


Make a selector for sample ROOtuples

Sample B+ --> Jpsi K+ signal MC ntuples are available as SP-989-Run1-1.root and SP-989-Run1-2.root. These were produced with BtaTupleMaker in the Make CM2 Ntuples tutorial. We are interested in the "ntp2" ntuple. 

Create a directory "data" of your analysis directory and place the two files in it. While you are at it, you can also copy these ntuples, which are made from generic B+ MC: SP-1235-Jpsitoll-Run1-R18c-1.root, SP-1235-Jpsitoll-Run1-R18c-2.root, SP-1235-Jpsitoll-Run1-R18c-3.root . We will use these later.

Now use MakeSelector to create a C++ program (histAnalysis.h and histAnalysis.C) to analyze the data:

[~/Work/tutorials/root3]: root
*******************************************
* *
* W E L C O M E to R O O T *
* *
* Version 5.26/00 14 December 2009 *
* *
* You are welcome to visit our Web site *
* http://root.cern.ch *
* *
*******************************************

ROOT 5.26/00 (trunk@31882, Dec 14 2009, 20:18:36 on macosx64)

CINT/ROOT C/C++ Interpreter version 5.17.00, Dec 21, 2008
Type ? for help. Commands must be C++ statements.
Enclose multiple statements between { }.

Welcome to rootlogon.C <-- note the message from rootlogin.C
For approved plots use: gROOT->SetStyle("BABAR");

root [0] TFile f("data/SP-989-Run1-1.root") <-- either file will do
root [1] .ls
TFile** data/SP-989-Run1-1.root Created for you by RooTupleManager
TFile* data/SP-989-Run1-1.root Created for you by RooTupleManager
KEY: TTree ntp1;1 Analysis Ntuple
KEY: TTree ntp2;1 myNtuple
root [2] ntp2->MakeSelector("histAnalysis")
Info in <TTreePlayer::MakeClass>: Files: histAnalysis.h and histAnalysis.C generated from TTree: ntp2
(Int_t)0
root [3] .q

This is what the original files look like:

By default, the block sizes are set to the largest value needed for the particular file used with MakeSelector. For example, although we allowed for up to 50 Jpsi candidates when we made the ntuples (see Analysis.tcl in the root3 tutorial), only 1 is allowed for in histAnalysis.h: Float_t JpsiChi2[1]; //[nJpsi]. You will need to go through and edit all of these to the correct values. The resulting file is histAnalysis-blocksize.h

Special for analysis-51 on yakut

Start root by typing bbrroot. Here is what you should see

Fill some basic histograms

There are a lot of comments in the histAnalysis.C as generated. If you want, you can delete them all to tidy up the file; you can always check the histAnalysis-orig.C link above.

There are three steps to creating a histogram. First, it must be declared prior to the  Begin function.

TH1F *hnJpsi, *hmassJpsi;

Next, define the histograms in the Begin function:

  //..Histogram definitions
hnJpsi = new TH1F("hnJpsi", "Number of Jpsi", 20, -0.5, 19.5);
hmassJpsi = new TH1F("hmassJpsi", "Raw Jpsi Mass", 60, 2.9, 3.3);

Fill the histograms in Process

If you are using only a few variables, it can be faster to read only the data you need from the ntuple. In practice, I generally just read the whole thing.
  //..Just read the full event
fChain->GetTree()->GetEntry(entry);

//..Fill some simple histograms
hnJpsi->Fill(nJpsi);
for(Int_t i=0; i<nJpsi; i++) {
hmassJpsi->Fill(JpsiUncMass[i]);
}

Run the job

Start root, define the data file, then compile the code and run on ntuple ntp2. I always compile the code, as opposed to running in interpreted mode. I have found bugs in the interpreter when processing the sample data used in this tutorial.
root [0] TFile f("data/SP-989-Run1-1.root");
root [1] ntp2->Process("histAnalysis.C+");

To run only 100 events, you would say

   ntp2->Process("histAnalysis.C+","",100,0);

The following commands create a canvas and display the two histograms on it. You can save the canvas using the File menu if you wish. I normally use eps output format, since it is more convenient for inserting into documents, but gif is useful for web pages.

root [2] TCanvas MyC("MyC");
root [3] MyC.Divide(2,1);
root [4] MyC.cd(1);
root [5] hnJpsi->Draw()
root [6] MyC.cd(2);
root [7] hmassJpsi->Draw()

Here is a screen capture of the root session:

And the resulting histograms: This version of the code is

Chains

You will generally want to chain many files together.
TChain chain("ntp2");
chain.Add("data/SP-989-Run1-1.root");
chain.Add("data/SP-989-Run1-2.root");

chain.Process("histAnalysis.C+");
We will use this later.

If your ntuple is in a root subdirectory, the syntax is (for example) TChain chain("TauMicroFilter/ntpl"); The remaining commands are the same.


Write the histograms to a file

By writing the histograms to a file, you can separate their generation from their presentation or subsequent fitting. I find this a convenient way to work, particularly when combined with running root in batch mode (below).

a. After filling the histograms, write them to a file:

Some people have reported that they need to write each histogram individually, such as
hnJpsi->Write();

b. running the job now creates the output file:

[~/Work/tutorials/root3]: ls -l histAnalysis.root
-rw-r--r-- 1 hearty staff 4111 Jun 19 20:26 histAnalysis.root

c. Read the file into root to access it. Here is a sample session.

root [0] TFile f("histAnalysis.root");
root [1] .ls
TFile** histAnalysis.root
TFile* histAnalysis.root
KEY: TH1F hnJpsi;1 Number of Jpsi
KEY: TH1F hmassJpsi;1 Raw Jpsi Mass
root [2] TCanvas MyC("MyC");
root [3] MyC.Divide(2,1);
root [4] MyC.cd(1)
(class TVirtualPad*)0x3cea400
root [5] hnJpsi->Draw()
root [6] MyC.cd(2)
(class TVirtualPad*)0x3a04a00
root [7] hmassJpsi->Draw()

d. This version of the code is

The resulting histogram file is histAnalysis-2.root.

Use a macro to run the code

a. It is convenient to write a short macro, runAnalysis.C, to run the code and generate the output histogram file. We will also run the code on the chained files, instead of the single input file.
[~/Work/tutorials/root3]: cat runAnalysis.C
#include "TChain.h"

void runAnalysis () {
TChain chain("ntp2");
#include "SP-989-Run1-Chain.C"
chain.Process("histAnalysis.C+");
}

Note that I include the files to be chained in an include file:

[~/Work/tutorials/root3]: cat SP-989-Run1-Chain.C
chain.Add("data/SP-989-Run1-1.root");
chain.Add("data/SP-989-Run1-2.root");

This is a convenient way to deal with multiple data types - just create a similar include file for each (on-peak data, off-peak data, BB MC, continuum MC and so on). List them all in your macro and comment out the ones to skip by starting the line with "//". Now we can compile and execute the macro to run our analysis code on the full chain.  (Actually, since we haven't changed histAnalysis.C, root doesn't recompile it).

root [0] .x runAnalysis.C+
Info in <TUnixSystem::ACLiC>: creating shared library /Users/hearty/Work/tutorials/root3/./runAnalysis_C.so
histograms written to histAnalysis.root

Here is the resulting histogram file: histAnalysis-3.root.

Note that the include file only works when compiling. Here are versions that work in interpreted mode, which you run by typing .x runAnalysis-i.C. They lack the flexibility of modifying datasets by adding or subtracting include files. Note that the analysis code itself is still compiled in this example. This macro can also be used in batch mode (next step):


Run in batch/background mode

a. If you execute the macro in background/batch mode, you can be sure that there are no problems with memory leaks or stale temporary items.
[~/Work/tutorials/root3]: root -b -q runAnalysis.C+ >& runAnalysis.log &
[1] 7544
[~/Work/tutorials/root3]:
[1] Done root -b -q runAnalysis.C+ >& runAnalysis.log
The "-b" runs in batch mode, "-q" exits root after running the macro. Here is the log: runAnalysis-3.log.

You can skip the log file if you like: root -b -q runAnalysis-i.C+

b. You can now view the histograms by reading histAnalysis.root. It is convenient to leave an interactive root session running for this purpose. Just close and reopen the file when you remake it:

root [0] TFile f("histAnalysis.root");
root [1] hnJpsi->Draw();
<TCanvas::MakeDefCanvas>: created default TCanvas with name c1
root [2] f.Close();
root [3] hnJpsi->Draw();
Error: Symbol hnJpsi is not defined in current scope FILE:(tmpfile) LINE:1
Error: Failed to evaluate hnJpsi->Draw()Possible candidates are...
filename line:size busy function type and name
*** Interpreter error recovered ***
root [4] TFile f("histAnalysis.root");
root [5] hnJpsi->Draw();

Running root at a remote Tier A site

It is likely that your data, and perhaps the ntuples you produce from your data, are located at a remote computing center.  A convenient way to operate under these circumstances is to run root in batch mode at the remote site, and to run it interactively on your local machine. You then need to copy only the small histogram file histAnalysis.root over the network. This is very much faster than runnng an X window over the network. If you use AFS, the copying happens seamlessly.  

Special for analysis-51 on yakut

Use bbrroot instead of root when running in background mode:
  bbrroot -b -q runAnalysis.C+ >& runAnalysis.log &
or
  bbrroot -b -q runAnalysis.C+

Add some CLHEP to your analysis

You will probably want to use TLorentzVectors and other CLHEP-type classes. To do so, you need to load the libPhysics library in runAnalysis.C. Note the TSystem.h header as well, which allows gSystem-
[~/Work/tutorials/root3]: cat runAnalysis.C 
#include "TChain.h"
#include "TSystem.h"

void runAnalysis () {
gSystem->Load("libPhysics.so");
TChain chain("ntp2");
#include "SP-989-Run1Chain.C"
chain.Process("histAnalysis.C+");
}
We can use TLorentzVector to create a 4-vector of the center of mass, from which we can get the center of mass energy. First, #include "TLorentzVector.h" in histAnalysis.C. Then, in Process:
  TLorentzVector mom4Ups(eePx, eePy, eePz, eeE);
Float_t sqrts = mom4Ups.M();
See the "Physics Vectors" chapter of the root users manual for more details on this class.  Here is this version of the file: runAnalysis-CheckMC.C.

Add a function to your analysis class

It may be convenient to add other functions to your histAnalysis class. Here we create a function called CheckMC that uses the MC truth block and the center of mass energy to categorize the event as on-peak data, off-peak data, signal MC, inclusive Jpsi MC, other BB MC, or continuum MC. (You could further subdivide the continuum and BB MC if desired). Note that this sort of code can actually be quite tricky, because our simulation includes Photos, a package that adds low-energy radiative photons to the final state. So our B+ --> Jpsi K+ signal MC may actually show up as a three body decay B+ --> Jpsi K+ gamma.

a. declare the function in histAnalysis.h, right after the Terminate declaration:

   virtual void    Terminate();
Int_t CheckMC(Int_t mclund[200], Int_t mothidx[200], Int_t daulen[200],
Int_t dauidx[200], Int_t mclen, Float_t sqrts);

ClassDef(histAnalysis,0);

(Note that the second line above is broken only for formatting purposes.) Here is the full file: histAnalysis-CheckMC.h

b. Write the function. I prefer to put it in a separate file, CheckMC.C, but some people like to have all of their code in one file. Here are the first few lines:

// Value of CheckMC tells what type of events this is:
// 0 = on peak data, 1 = off peak, 2 = Jpsi K+, 3 = Other B-->Jpsi
// 4 = Other BB, 5 = continuum

Int_t histAnalysis::CheckMC(Int_t mcLund[200], Int_t mothIdx[200], Int_t dauLen[200],
Int_t dauIdx[200], Int_t mcLen, Float_t sqrts) {

(Note that the line above is broken only for formatting purposes.) Note the "histAnalysis::CheckMC". Here is the full file: CheckMC.C

c. Include the new file into your code with #include "CheckMC.C":

//-----------------------------------------------------------------------------
#include "CheckMC.C"

d. Lets add a new histogram, hdtype, and fill it with the value returned by CheckMC.

  //..Categorize the event
TLorentzVector mom4Ups(eePx, eePy, eePz, eeE);
Float_t sqrts = mom4Ups.M();
Int_t dtype = histAnalysis::CheckMC(mcLund, mothIdx, dauLen, dauIdx, mcLen,
sqrts);
hdtype->Fill(dtype);

Note that you include the class histAnalysis when using the function. If you check the histogram, note that every entry is 2, as expected. For something different, try the generic B+B- ntuples (SP-1235) instead. (You will need to create a chain out of them, and modify your runAnalysis.C). In fact, most of these are also signal events - it is often the case that when you run on generic BB MC, you will need to identify the signal events mixed among the other BB events using code similar to CheckMC.C.

Here is the full code: histAnalysis-CheckMC.C and the new chain file: SP-1235-Jpsitoll-Run1-Chain.C


Add some functions outside your analysis class

You may want to write functions that are not part of the histAnalysis class. Perhaps they are more general than this particular analysis. There is also the advantage that such functions are not recompiled when you modify your analysis code.

In this example, we will use a single class, MyF. Other classes can be similarly created as needed.

a. Create the header file MyF.h. This should be put in your Macros directory defined in .rootrc.

[~/Work/tutorials/root3]: cat ~/Work/macros/MyF.h
#include "TLorentzVector.h"

class MyF {

public:

//--------------------------------------------------------------------------
//..FourMomentum returns four vector from p, theta, phi and mass

static TLorentzVector FourMomentum(Float_t mom, Float_t theta, Float_t phi,
Float_t mass);

};

This first function makes a TLorentzVector from the p,theta, phi and mass of the particle. (There is no such standard constructor). The key features:

b. Write the function in MyF.C in the same directory:
[~/Work/tutorials/root3]: cat ~/Work/macros/MyF.C
#include "MyF.h"

//--------------------------------------------------------------------------
//..FourMomentum returns four vector from p, Cos(theta), phi and mass

TLorentzVector MyF::FourMomentum(Float_t mom, Float_t costheta, Float_t phi, Float_t mass)
{
TLorentzVector temp(1.0,1.0,1.0,1.0);
Float_t energy = sqrt(mom*mom + mass*mass);
temp.SetRho(mom);
temp.SetTheta(acos(costheta));
temp.SetPhi(phi);
temp.SetE(energy);

return temp;
}

You could also put the code into a file FourMomentum.C and just include it in MyF.C using #include "FourMomentum.C"

c. Compile the code and load the library to make the code accessible.

To use the code, we need to compile and load it before running histAnalysis. We do this in runAnalysis.C, right after loading libPhysics.so:

  gSystem->Load("libPhysics.so");
gROOT->LoadMacro("MyF.C+");
Recall that the ".C+" extension means that MyF.C is compiled if changed; otherwise the existing library is loaded. You will also need to include the corresponding header file for gROOT:
  #include "TROOT.h"

d. Create a soft link to your Macros directory:

[~/Work/tutorials/root3]: ln -s ~/Work/macros Macros

e. Use the function in your analysis.

First, you need to include the header: #include "Macros/MyF.h"

Here is a snippet of code to calculate the four vector and corresponding missing mass for every B candidate. Actually, a proper calculation of this quantity using a kinematic fit is available in the ntuple as BpostFitMmiss[ib]. You might find it interesting to compare this quantity to Mmiss:

  //..Missing mass
for(Int_t ib=0; ib<nb; ib++) {
TLorentzVector mom4B =
MyF::FourMomentum(Bp3[ib], Bcosth[ib], Bphi[ib], BMass[ib]);
Float_t Mmiss = (mom4Ups - mom4B).M();
hmyBmiss->Fill(Mmiss);
hntpBmiss->Fill(BpostFitMmiss[ib]);
hCompMiss->Fill(BpostFitMmiss[ib],Mmiss);
}

Remember to declare and create the histograms.  Here are the complete files.

and the resulting plot:

Dump some MC truth events

a. It is often convenient to write out the MC truth block for an event in a graphical format.  Unfortunately, this section of the workbook is currently broken. 

Handle multiple data types

Many analyses compare on peak, off peak and various MC data types. One method of dealing with these different data starts with the CheckMC function defined earlier. We use the resulting index dtype with arrays of histograms, and weight each data type by its relative luminosity so that all resulting plots are normalized to the on-peak luminosity. 

In general, whenever you are filling histograms with events of different weights, you need to use the Sumw2() option to get the correct error bars.

a. Declare the relevant histograms to be arrays of length 6:

TH1F *hnJpsi[6], *hmassJpsi[6], *hdtype, *hmyBmiss[6], *hntpBmiss[6];
TH2F *hCompMiss[6];
TFile *fHistFile;

Note that hdtype is still only a single histogram.

b. Before defining the histograms in the Begin method of histAnalysis, create a vector of names and use them to customize each histogram:

 //..Some quantities to handle multiple data types
TString htit[6] = {"_on","_off","_sig","_Jpsi","_BB","_cont"};

//..Define histograms
hdtype = new TH1F("hdtype", "Event Type", 10, -1.5, 8.5);
for( Int_t ih=0; ih<6; ih++ ) {
hnJpsi[ih] = new TH1F("hnJpsi"+htit[ih], "Number of Jpsi"+htit[ih],
20, -0.5, 19.5);
hnJpsi[ih]->Sumw2();

hmassJpsi[ih] = new TH1F("hmassJpsi"+htit[ih], "Raw Jpsi Mass"+htit[ih],
60, 2.9, 3.3);
hmassJpsi[ih]->Sumw2();

hmyBmiss[ih] = new TH1F("hmyBmiss"+htit[ih], "My Missing Mass"+htit[ih],
50, 5.20, 5.30);
hmyBmiss[ih]->Sumw2();

hntpBmiss[ih] = new TH1F("hntpBmiss"+htit[ih],
"Ntp Missing Mass"+htit[ih], 50, 5.20, 5.30);
hntpBmiss[ih]->Sumw2();

hCompMiss[ih] = new TH2F("hCompMiss"+htit[ih],
"My Mmiss vs Ntp Mmiss"+htit[ih],50, 5.20,
5.30, 50, 5.20, 5.30);
hCompMiss[ih]->Sumw2();
}

c. Now create an array of weights corresponding to each data type. The weight = on-peak-luminosity/sample-luminosity. Put this before the Begin function since it will probably be needed in more than one function of histAnalysis.  (Of course, you will need to calculate these for your own analysis!)

Float_t hwt[6] = {1., 8.55, 1., 0.241, 0.283, 1.098};

d. Now fill the histograms according to the event type and with the appropriate weight.  Note that dtype enters both in the histogram identifier and in the weight. 

  hnJpsi[dtype]->Fill(nJpsi,hwt[dtype]);

and so forth for hmassJpsi and the others.

e. To test this out, use the B+B- MC (SP mode  1235). Run the job using root -q -b runAnalysis.C+ as normal.

f. Take a look at the resulting histograms in your interactive root, starting with the histogram of the event type, hdtype->Draw(). Note that most of the events are actually B+ --> Jpsi K+ signal events. This is not surprising, since we are requiring a reconstructed Jpsi K+ to write the ntuple.  Here is a gif version of the plot (or eps).   Take a look at the Jpsi masses for each data type as well: 

root [4] TCanvas MyC("MyC");
root [5] MyC.Divide(3,2)
root [6] MyC.cd(1)
root [7] hmassJpsi_on->Draw()
root [8] MyC.cd(2)
root [9] hmassJpsi_off->Draw()
root [10] MyC.cd(3)
root [11] hmassJpsi_sig->Draw()
root [12] MyC.cd(4)
root [13] hmassJpsi_Jpsi->Draw()
root [14] MyC.cd(5)
root [15] hmassJpsi_BB->Draw()
root [16] MyC.cd(6)
root [17] hmassJpsi_cont->Draw()
root [18] Info in <TCanvas::Print>: GIF file /Users/hearty/Work/tutorials/root26/Jpsi-mass-SP1235.gif
has been created
Here is resulting plot.  Note that the on-peak, off-peak and continuum plots are empty, since we didn't run on those data, and that the Signal sample gives a nice Jpsi peaks, while the "Other BB" sample does not. 

Also note that for the signal plot "Entries" (which is the number of times that Fill was called for this histogram) is equal to "underflow" + "overflow" + "integral", which are the sum of weights below, above and in the plot respectively. This is in contrast to the BB plot, where the two values differ by the ratio of 0.283 - the BB luminosity weight.

When doing an analysis, you often find yourself making the same set of plots over and over. In this case, it is worth writing a macro to make it.  To execute it, type .x plotMass.C in an interactive root session.  This is a much easier way to produce the same plot!

Here are the final versions of various files:


Producing a publication-quality plot

At some point you may want to produce a nice version of a plot for a talk or publication. As discussed in the previous section, it is often convenient to use a macro when manipulating histograms. In this section, we will use a macro to produce a nice version of a Jpsi mass distribution. This is based on a style package developed by David Kirkby, which is available in RooLogon.C, located in the workdir package.

a. Add the BABAR style to your rootlogon.C

Insert this code into your rootlogon.C (see "Some basics"), which defines a style called BABAR.  Put it before your normal commands, to be sure that you end up in your normal style. Here is my resulting rootlogon.C.

You then invoke this style by the command

     gROOT->SetStyle("BABAR");

b. Pick up code to write BaBar on plots

For conference use, you will generally want to write BaBar in an official-looking way on your plots. Sasha Telnov wrote a macro to do this, which I have copied from workdir/RooAlias.C. Add this to your macros directory: BABARSmartLabel.C

Note that there is no header file; it is assumed that this macro will not be used in compiled macros. You will need to load the macro either using .L BABARSmartLabel.C interactively, or gROOT->LoadMacro("BABARSmartLabel.C"); in the histogramming macro. (You don't need to specify the path to BABARSmartLabel.C if it's in your macros directory as defined in Some Basics). After loading the macro, the command

BABARSmartLabel(-1,-1,-1,"-1",-1);
will put "BaBar" in the upper right-hand corner;
BABARSmartLabel(-1,-1,-1,"~1",-1,-1);
will add "Preliminary" underneath. Check the comments in the code for the full usage.

c. A macro to produce a nice plot

It is often easier to manipulate histograms in a macro than interactively, unless you are confident that you will only have to do it once, and will do it right the first time. When making publication-quality plots, it is easiest to have one macro per plot.

In this macro, we will make a nice version of the Jpsi mass plot produced above. Here is the root file containing the produced histograms, in case you don't have your own: histAnalysis-final.root.

Here is the macro: DrawsighmassJpsi.C

This macro also includes a couple of lines with commands for drawing lines on figures in ROOT.

A key point for manipulating histograms in a macro is that under many circumstances (in particular, if you want to work with more than one in the macro), you need to explicitly create a pointer to each histogram:

TFile f("histAnalysis.root");
TH1* sighmassJpsi = (TH1*) f.Get("sighmassJpsi");
In addition to invoking the BABAR style, this macro does some typical modifications, like adjusting the marker size and moving the axis labels. Note that the BABAR style turns off the default titles, so you will need to add titles yourself. It then writes the plot to an eps file.

d. Run the macro

[~/Work/tutorials/root3]: root
*******************************************
* *
* W E L C O M E to R O O T *
* *
* Version 5.26/00 14 December 2009 *
* *
* You are welcome to visit our Web site *
* http://root.cern.ch *
* *
*******************************************

ROOT 5.26/00 (trunk@31882, Dec 14 2009, 20:18:36 on macosx64)

CINT/ROOT C/C++ Interpreter version 5.17.00, Dec 21, 2008
Type ? for help. Commands must be C++ statements.
Enclose multiple statements between { }.

Welcome to rootlogon.C
For approved plots use: gROOT->SetStyle("BABAR");

root [0] .x DrawsighmassJpsi.C
Info in <TCanvas::Print>: eps file JpsiMass.eps has been created
root [1] .q
[~/Work/tutorials/root3]:

If you make changes to DrawsighmassJpsi.C, you don't need to quit and restart root; just rerun the macro. Here is the resulting plot: JpsiMass.eps

e. Special for analysis-51 on yakut

RooLogon.C already contains the BABAR style and loads the command BABARSmartLabel, so you do not need to add anything to your RooLogon.C or to your Macros directory. However, you do need to delete the following command in DrawsighJpsi.C, which loads BABARSmartLabel:
gROOT->LoadMacro("BABARSmartLabel.C");
Here is the resulting macro: DrawsighmassJpsi-yakut.C 

Conclusion

In completing this tutorial, you have covered the features needed to perform an analysis on a set of ntuples. You have generated the code structure using MakeSelector, added histograms, code to deal with multiple MC types, and external functions, and developed a macro to load the required libraries and execute the code. These tools are adequate for a cut-and-count type analysis.

The next step in sophistication would be fitting. Basic fits are discussed in the ROOT II tutorial. The package RooFit provides many convenient and advanced tools for this purpose.


Back to Workbook Front Page

Author: Christopher Hearty

Last modified: 29-Jun-2006
Last significant update: 27-Jun-2006
Updated to analysis-31: 27-Jun-2006
Updated to analysis-51 and root 5.26: 29-Jan-2010

Send comments to Workbook Team.