# Presentation: 658670

## ROOT

- An object oriented HEP analysis framework.
- Day 3
- http://www-pat.fnal.gov/root/
- The ROOT system website is at: http://root.cern.ch/

- ROOT Day3, Suzanne Panacek

## What we covered ...

- Day 1
- GUI
- Day 2
- More commands (CINT & ACLiC)
- Functions and Fitting
- Tree Viewer

- ROOT Day3, Suzanne Panacek

## Class Schedule Day 3:

- Building Root Trees
- Reading Root Trees
- Using Trees in Analysis
- The Draw method
- The MakeClass method
- Add your class to ROOT
- With the Interpreter
- With a compiler (Shared Library)
- With ACLiC

- ROOT Day3, Suzanne Panacek

## Building ROOT Trees

- Overview of
- ROOT Files
- Trees
- Branches
- 5 Steps to build a TTree
- Demonstration

- ROOT Day3, Suzanne Panacek

## ROOT Files (TFile)

- When a ROOT file is opened it becomes the _current directory_.
- Histograms and trees are _automatically saved_ in the file.
- When the file is closed the _histogram and tree objects _associated with the file_ are deleted_.
- _Any object_ derived from TObject can be written to a ROOT file. It has to be added explicitly.

- ROOT Day3, Suzanne Panacek

**Notes:**
Some points to remember about the TFile class:
The constructor of the TFile opens the file for reading or writing.
When a file is opened in ROOT, it becomes the current directory. The global variable gDirectory reflects this.  To change directory to a different file use the cd() method for the target file.  
New histograms and trees are automatically written to the current file. 
Any object derived from TObject can be written to the file, however they have to be added explicitly by calling file->Append(), or object->Write().
When the file is closed or the file object deleted, the histograms and trees in the file are no longer available in the ROOT session. The histogram and tree objects and  are deleted along with the file object.

## ROOT Trees (TTree)

- Storing _large number_ of entries.
- _Hierarchy_ of branches and leaves.
- Reading _selective_ branches

- ROOT Day3, Suzanne Panacek

**Notes:**
The TTree class is designed for storing large number of events. With compression, it minimizes the space overhead per entry to about 4 bytes. If each entry were added individually it would require about 60 bytes of control data. 
The TTree class consists of a hierarchy of branches and leaves which allows a flexible organization of data
 a tree may have one or many branches and  a branch may have one or many leaves
 branches are independent and  maybe written to different files
Data is written to the file one branch buffer at a time. This  results in a large compression factor especially if there are a series of the same values in a branch. 
A TTree allows selective branches to be read for optimized I/O. Each branch can be read independently of any other branch. 
When a branch buffer is written, the tree header is not saved to the file. The Write() method writes the tree header.

## Five Steps to Build a Tree

- _Steps:_
- 		1. Create a TFile
- 		2. Create a TTree
- 		3. Add TBranch to the TTree
- 		4. Fill the tree
- 		5. Write the file

- ROOT Day3, Suzanne Panacek

## Step 1: Create a TFile Object

- The TFile constructor
- file name (i.e. " AFile.root ")
- option: _NEW, CREATE, RECREATE,_ _UPDATE,_ _or READ_
- file title
- compression level 0-9, defaults to 1.

- TFile *hfile = new
-    TFile("AFile.root","RECREATE","Example");

- ROOT Day3, Suzanne Panacek

**Notes:**
Step 1: Create a macro (BuildTree.C). First load the shared library libEvent.so that contains the class definition of Event and Track. These are the objects we want to write to the tree. Then create a TFile object. 
{
// load the shared library with the class definition
// for event.
 gROOT->LoadMacro("$ROOTSYS/test/libEvent.so"); 

// create a TFile object, using RECREATE to overwrite // if it exists 	
TFile *hfile = new TFile("AFile.root", "RECREATE", 
               "An Example ROOT file");
}
If Option 
= NEW or CREATE create a new file and open it for writing, if the file already exists the file is not opened. 
= RECREATE create a new file, if the file already exists it will be overwritten. 
= UPDATE open an existing file for writing. if no file exists, it is created. 
= READ open an existing file for reading. 

## Step 2: Create a TTree Object

- The TTree Constructor:
- Tree Name (e.g. "myTree")
- Tree Title
- Maximum total size of buffers kept in memory when reading a TTree  (defaults to 64 MB)

- TTree *tree = new TTree("myTree","A ROOT tree");

- ROOT Day3, Suzanne Panacek

**Notes:**
Step 2
create a TTree object with the name T and the default buffer size of 64 MB
TTree *tree = new TTree("myTree","A ROOT tree");

Maxvirtualsize is by default 64Mbytes. It applies when reading entries from a tree and allocates the maximum space  that the sum of all branch buffers may use. For example if it is set to 64MB and there are 3 branches with 8MB buffers each it can contain 8 branch buffers.	
The method TTree::SetMaxVirtualSize() resets the MaxVirtualSize on an existing tree. This can be used for performance reasons (I.e. to keep more or less branch buffers in memory).

## Create a Tree with Folders

- TTree aliTree("aliTree", "/aliroot")

- First Parameter:	tree name
- Second Parameter:	/name of the top folder

- ROOT Day3, Suzanne Panacek

## Step 3: Adding a Branch(case 1)

- Branch name
- Class name
- _Address of the pointer_ to the Object (descendant of TObject)
- Buffer size (default = 32,000)
- Split level (default = 99)

- Event *event = new  Event();
- myTree->Branch
-   ("EventBranch","Event",&event);

- ROOT Day3, Suzanne Panacek

**Notes:**
Step 3
create a branch object for the event object:
Event *event = new  Event(); tree->Branch       ("EventBranch","Event",&event,,1);

The Buffer size default is 32k. This means a read and write operation on a branch is done in a 32k byte chunks. While writing a tree, each branch buffer is written when it is filled. When reading a tree, ROOT keeps the old branch buffers as long as the TTree MaxVirtualSize is large enough to hold an additional buffer.

If the sum of the buffers is larger than MaxVirtualSize, and we are reading the tree, only one branch buffer is kept.  

## Splitting a Branch

- Setting the split level (default = 99)

- Split level = 0

- Split level = 99

- Example:
- tree->Branch("EvBr","Event",&ev,64000,0);

- ROOT Day3, Suzanne Panacek

**Notes:**
Setting the split level
If the split level = 0, the branch is not split and the entire object is written on one branch. 
If split level=1 (default), this branch will automatically be split into sub-branches, with one sub-branch for each data member of the object itself. The parent object is also split.
If split level = 2 The data members will be split so that there is a branch for each of the data members of the objects contained in the top object. 
Making one single branch and one single buffer can be the right choice when one wants to process only a subset of all entries in the tree.
Making several branches is particularly interesting in the data analysis phase, when one wants to histogram some attributes of an object (entry) without reading all the attributes.

## Adding Branches with a List of Variables 

- Branch name
- Address: the address of the first item of a structure.
- Leaflist: all variable names and types
- Order the variables according to their size

- Example
- TBranch *b = tree->Branch ("Ev_Branch",&event,
- 	"ntrack/I:nseg:nvtex:flag/i:temp/F");

- ROOT Day3, Suzanne Panacek

**Notes:**
The variable name and the variable type are separated by a slash (/). If no type is given, the type of the variable is assumed to be the same as the previous variable. If the first variable does not have a type, it is assumed of type F by default. 
The list of currently supported types is given below: 
- C : a character string terminated by the 0 character- B : an 8 bit signed integer - b : an 8 bit unsigned integer - S : a 16 bit signed integer - s : a 16 bit unsigned integer - I : a 32 bit signed integer - i : a 32 bit unsigned integer - F : a 32 bit floating point - D : a 64 bit floating point
The leaflist with names of variables is NOT used to pick variables out of the structure, but is only used later by root as names for the elements that were saved on the branch. The type info is used for a byte count to decide how much to save. The variables actually written out are simply the block of bytes starting at the starting address, and they may or may not match up with the leaflist depending on whether or not the programmer is being careful. 
A branch created with a structure is probably the closest to a branch that represents a block in an ntuple.

## Adding Branches with a TClonesArray

- Branch name
- Address of a pointer to a TClonesArray
- Buffer size
- Split level

- Example:
- tree->Branch( "Track_B",&Track,64000);

- ROOT Day3, Suzanne Panacek

**Notes:**
This Branch method takes as input an array of objects of the same class (I.e. tracks, hits). When the split level is set to 1 (and by default) it creates one branch for each of the members of the class.
Using a ClonesArray in the Branch method will optimize the I/O for the root file. Since ROOT knows a clones array contains objects of the same class, it will reuse the memory space to read and write the object from the tree. This optimization uses much fewer calls to "new" and can make a large difference in execution time. 
TClonesArray
The TClonesArray is a direct access list of objects of the same class. For example, if the TClonesArray is an array of TTrack objects, this function will create one sub-branch for each data member of the object TTrack.

## List and Folder Branches

- Branch(TList *list, buffer, split)
- Creates one branch for each list element
- TObject
- TClonesArray
- Will add a split level parameter
- Branch("folder-name", buffer, split)
- Creates one branch per folder

- ROOT Day3, Suzanne Panacek

**Notes:**
Int_t Branch(TList *list, Int_t bufsize) This new function creates one branch for each element in the list. Two cases are supported: 
list[i] is a TObject*: a TBranchObject is created with a branch name being the name of the object. 
list[i] is a TClonesArray*: A TBranchClones is created. 

if list[i]->TestBit(TClonesArray::kNoSplit) is 1, the TClonesArray is not split. 
if list[i]->TestBit(TClonesArray::kForgetBits) is 1 and the TClonesArray is split, then no branches are created for the fBits and fUniqueID of the TObject part of the class referenced by the TClonesArray. The function returns the total number of branches created. 

Int_t Branch(const char *foldername, Int_t bufsize, Int_t splitlevel) This new function creates one branch for each element in the folder. The function returns the total number of branches created. 

## Step 4: Fill the Tree 

- Create a for loop
- Assign values to the event object
- Call the Fill method for the tree
- 		myTree->Fill()

- ROOT Day3, Suzanne Panacek

**Notes:**
The Fill method will loop on all defined branches and fetch the information from the variables associated with the branch and copy it to the branch.
Step 4
write a for loop to assigns values to create events and fill the tree with them.
for (ev = 0; ev < 200; ev++) {
   Float_t  sigmat, sigmas;
   gRandom->Rannor(sigmat,sigmas);
   Int_t ntrack = Int_t (600 +600*sigmat/120.);
   Float_t random = gRandom->Rndm(1); 
   event -> SetHeader(ev, 200, 960312, random);
   event -> SetNseg(Int_t (10*600+20*sigmas));
   event -> SetNvertex(1); 
   event -> SetFlag(UInt_t (random+0.5));
   event -> SetTemperature(random+20.);
   for (Int_t t = 0; t < ntrack; t++)
      event->AddTrack(random); 
   myTree->Fill();   //fill the tree
   event->GetTracks()->Clear();
}

## Step 5: Write the File

- The TFile::Write()
- Writes Histograms and Trees
- Write is needed to write file header
- hfile->Write();

- ROOT Day3, Suzanne Panacek

**Notes:**

Step 5
write the file.
	hfile->Write();

When is what written to disk?
File Header: when calling the file->Write() or file->Close() method.File Content: when calling the file->Write() or file->Close() method.Objects on file (like Histograms): with File Content or when calling theobj->Write() method.Trees: same as other objects or when the number of bytes that have been generated since the previous AutoSave is greater than fAutoSave (use SetAutoSave) (this includes, tree, branch and leaf meta data).Leaf data: every time the buffer is full (size given in the TTree::Branch call)or the tree is written.

## Demo: 5 steps to build a Tree

- BuildTreeDemo.C
- create "AFile.root"
- 2nd Type of Branch, crated with a class name and split.
- .X BuildTreeDemo.C
- One tree called "T"
- One branch for eachdata member of Event.
- recursive split (see Track)

- ROOT Day3, Suzanne Panacek

**Notes:**
As an example, look at BuildTreeDemo.C. This is a macro containing the 5 steps discussed earlier. 

Now execute the BuildTreeDemo.C

root [0] .X BuildTree.C
root [1] TBrowser B

You can see there is a tree called "myTree", and one branch for each data member of the object we used to create the branch. You can also see the recursive nature of the split. Each data member of Track is also in a branch.

## Summary (Building ROOT Trees)

- Overview of
- ROOT Files
- Trees
- Branches
- 5 Steps to build a TTree
- Demo

- ROOT Day3, Suzanne Panacek

## Reading a TTree

- How to Read a Tree
- Reading Simple variables
- Example: reading Selected Branches
- Example: reading an Object Branch
- Trees and Friends

- ROOT Day3, Suzanne Panacek

## Looking at the Tree

- TTree::Print()  Shows the branchesTFile f("AFile.root")myTree->Print(); > print.txt
- TTree::Scan("leaf":"leaf":....)myTree->Scan("fNseg:fNtrack"); > scan.txt
-   myTree->Scan("fEventHdr.fDate:fNtrack");

- ROOT Day3, Suzanne Panacek

## How To Read TTree

- $ROOTSYS/tutorials/tree1.C
- Reading a simple tree
- 1. Open the TFile
-   TFile f("tree1.root")
- 2. Get the TTree
-   TTree * t1 =
-     (TTree*)f.FindObject("t1")

- ROOT Day3, Suzanne Panacek

## How to Read A TTree ++

- 3. Create a variable to hold the data
-   Float_t px, py, pz;
- 4. Associate a branch with a variable:
**SetBranchAddress("name", address)**
- t1->SetBranchAddress("px", &px)
- t1->SetBranchAddress("py", &py)
- t1->SetBranchAddress("pz", &pz)

- ROOT Day3, Suzanne Panacek

## GetEntry

- 5. Read one Entry in the TTree
**t1->GetEntry(0) // first entry**
- root [20] px
- (Float_t)(-1.10227906703948970e+00)
- root [21] py
- (Float_t)(-1.79938960075378420e+00)
- root [22] pz
- (Float_t)4.45282220840454100e+00

- ROOT Day3, Suzanne Panacek

## Demo: Reading Branches

- Demo:readTree1.C
- Read selected branches
- Fill two histograms

- ROOT Day3, Suzanne Panacek

## Reading an Object Branch

- Print the first entry with less than 587 tracks
- Find the entry using the fNtrack sub-branch
- Once found, read the entire entry

- $ROOTSYS/tutorials/tree4.C

- ROOT Day3, Suzanne Panacek

## Friends of Trees

- Adding Branches
- Often the tree is read only
- Risk of Damaging existing tree
- Add a Friend
- Unrestricted Access to the Friend's data

- ROOT Day3, Suzanne Panacek

## Adding a Friend to a TTree

- AddFriend("treeName", "fileName")
- tree.AddFriend("ft1", "ff.root")
- Friends with Trees of the same name:
- tree.AddFriend("tree1 = tree","ff.root")

- ROOT Day3, Suzanne Panacek

## Accessing Friends

- Access:
-   treeName.branchName.leafname
**Example:**
-    Int_t px;
-   t->SetBranchAddress("t2.px")
**Or**
-     t->Scan("t2.px.px") //unique
-   t->Scan("px")
**Also:**t->Print("all")

- ROOT Day3, Suzanne Panacek

## The Friends List

- Number of Entries of a Friend must be greater or equal

- To access the list of Friends:
- TTree::GetListOfFriends()
- Persistent
- tree->Write()

- ROOT Day3, Suzanne Panacek

## Summary: Reading Trees

- How to Read a Tree
- Reading Simple variables
- Example: reading Selected Branches
- Example: reading an Object Branch
- Trees and their Friends

- ROOT Day3, Suzanne Panacek

## Trees in Analysis

- Using TTree::Draw()
- Using MakeClass
- TChains

- ROOT Day3, Suzanne Panacek

## Using Trees in Analysis

- The TTree::Draw()
- _Parameters:_
- 1. expressions for x,y,z

- myTree->Draw("**ntrack**");
- myTree->Draw("**sqrt(ntrack): ntrack**");

- ROOT Day3, Suzanne Panacek

**Notes:**
Steps by Step:
To draw views of a tree from the command line:
1. Open the root file if it is not already open :
TFile *p = new TFile("AFile.root","READ");
2. Create a canvas with 4 divisions and activate the first sub-pad
TCanvas *myCanvas = new TCanvas
	("myCanvas","My Canvas", 0,0,600,400);
myCanvas->Divide(2,2);
myCanvas->cd(1);
3. Draw the first histogram using the TTree::Draw method with just the name of a variable.
myTree->Draw("ntrack");
4. Change the active pad and use the TTree::Draw method to plot two variables.
myCanvas->cd(2);
myTree->Draw("sqrt(ntrack): ntrack");

## Using Trees in Analysis (cont.)

- The TTree::Draw()
-  _Parameters:_
- 2. selection
- 3. draw option
- 4. number of entries

- myTree->Draw("sqrt(ntrack): ntrack",	"**temp > 20.8**");myTree ->Draw("sqrt(ntrack): ntrack",
- 	"temp >20.8","**surf2**");

- ROOT Day3, Suzanne Panacek

**Notes:**
Steps by Step continued:
5. Change the active pad and add a selection parameter to TTree::Draw 
myCanvas->cd(3); 
myTree->Draw("sqrt(ntrack): ntrack", "temp > 20.8");
6. Change the active pad and add a draw option
myCanvas->cd(4); 
myTree ->Draw("sqrt(ntrack): ntrack", "temp >20.8","surf2");

## Using Trees in Analysis (cont.)

- If the Branch was created with an object and was not split we can still use the Draw() method.
- myTree->Draw("**event.GetNtrack()**");
- 			event 	  = branch name
- 			GetNtrack()  = a method of the 					   	   object on the branch.

- ROOT Day3, Suzanne Panacek

## Histograms and Lists 

- The TTree::Draw() parameters continued:
- - creating a histogram
- 		myTree ->Draw(" ntrack **>> myHisto**");	myHisto->Draw();
- 	 - saving an event list 	myTree ->Draw("**>> myList**","ntrack>0");	myList->Print("all")
- - using an event list	myTree ->**SetEventList**(myList);	myTree ->Draw("ntrack");

- ROOT Day3, Suzanne Panacek

**Notes:**
Saving the histogram:
- By default ROOT creates a histogram called htemp.
- By default the histogram is reset. Use a "+"  to append the data to the histogram:
	T->Draw("ntrack >>+ myHisto") 
Saving an event list:
T->Draw(">> myList", " ntrack");
myList->Print("all")
When the first argument is preceded by ">>" ROOT knows that this command is not intended to draw anything, but to save the entries in a list with the name given in the first argument.

Using the event list:
TEventList *elist = (TEventList*)gDirectory->Get("myList");
T->SetEventList(elist);
T->Draw("ntrack");

## TTree Contents

- After executing the Draw command, we can get information about the TTree:
- GetSelectedRows()
- Returns the number of entries accepted by the selection expression.
- GetV1(), GetV2(), GetV3()
- returns a pointer to the float array of the first, second, or third variable (x,y,z)
- GetW()

- ROOT Day3, Suzanne Panacek

**Notes:**
After executing the Draw command, we can get information about the TTree:
- GetSelectedRows ()    returns the number of entries accepted by the selection expression. In case where no selection was specified, it returns the number of entries processed. 
- GetV1()   returns a pointer to the float array of the first variable
- GetV2()   returns a pointer to the float array of second variable 
- GetV3()   returns a pointer to the float array of third variable
- GetW()  returns a pointer to the float array of Weights where weight equal the result of the selection expression.
To get the fPx array from the tree and loop through the entries from the command line:
T->Draw("ntrack","temp>20.8")
Double_t *a
a = T->GetV1()
{
 for (Int_t i =0; i < T->GetSelectedRows() ; i+10)
      cout << a[i] << endl;
}

## Introducing MakeClass

- Draw() is powerful and quick.
- What if  you would like to plot the masses of all oppositely charged pairs of tracks?  You need a loop over all events, find all pairs of tracks, and calculate the required quantities.
- ROOT provides MakeClass to do this

- ROOT Day3, Suzanne Panacek

**Notes:**
The Draw method is convenient and easy to use, however it falls short if you need to do some programming with the variable. 

For example, for plotting the masses of all oppositely changed pairs of tracks, you would need to write a program that loops over all events, finds all pairs of tracks, and calculate the required quantities. We have shown how to retrieve the data arrays from the branches of the tree in the previous section, and you could just write that program from scratch.

This is a very common task, and ROOT provides a powerful facility to do most of the book keeping for you in creating a class that has methods to loop through the tree entries. This class makes all this much easier and is automatically generated when calling the TTree::MakeClass method. 

We will now go through the steps of using MakeClass with a simplified example. We will show how to plot just the first 100 tracks. The methods used here obviously work for much more complex event loop calculations. 

## Using MakeClass

*Scenario:  We would like to do selective plotting. For simplicity we choose to plot only the first 100 tracks of each entry*.
*We have a ROOT file with a tree with one branch  which has leaves of type "Event". The designer has made the class definition* *available in the shared library libEvent.so and given you the header file Event.h.*

- ROOT Day3, Suzanne Panacek

**Notes:**
The data designer makes a shared library available to you, which defines the classes needed. In this case the classes are Event, EventHeader, and Track. The designer also gives you the Event.h file for you to be able to see the definition of the classes.

To work along with these slides you will need to create several Event.root files. Use the $ROOTSYS/test/Event program to create multiple root files. The output is written in Event.root, so you need to rename the file before running the program again.

> $ROOTSYS/test/Event 100 1 0 1      // a root file with=0 and 100 events
> mv Event.root EventOB.root
> $ROOTSYS/test/Event 40 1 0 1       // a root file with=0 and 40 events
> mv Event.root EventOB40.root 
> $ROOTSYS/test/Event 50 1 0 1       // a root file with=0 and 50 events
> mv Event.root EventOB50.root
> $ROOTSYS/test/Event 100		// a root file with split = 1 (default) 

Open the root file:             EventOB.root
View it in the ROOT Object Browser. You can see that there is only one leaf in the tree (T) and that leaf is called event. If you double click on it nothing happens.

## Event.h

- Event has
- a TClonesArray of Tracks
- GetNtrack() method
- much more ...
- Track has
- a GetPx() method
- much more ...

- ROOT Day3, Suzanne Panacek

## Using MakeClass()

- 1. Load the shared library
- 		root [0].L libEvent.so
- 2. Load the root file
- 		root [1] TFile *f = new TFile
- 						("EventOB.root");
- 3. Call MakeClass	root [2] T->MakeClass("MyClass");
- 	- creates MyClass.C and MyClass.h- where does T come from?

- ROOT Day3, Suzanne Panacek

**Notes:**
To plot only selective entries, we need to loop over all entries in the tree and be able to select the ones we want. ROOT provides a utility that creates a skeleton class to do this: MakeClass() 

Step 1: Load the shared library to define the Event and Track classes
    root [0] .L libEvent.so

Step 2: Load the root file
   root [1] TFile *f = new TFile("EventOB.root");

Step 3: Call MakeClass
   root [2] T->MakeClass("MyClass");
This creates 2 files MyClass.h and MyClass.C.

Where does "T" come from? This is the CINT naming feature in action. CINT looks for an object that was created with the name "T" and creates a variable with the same name and class (more on this is session 4). In this example, the root file EventOB.root has a tree in it that is called T. Do a f->ls() and you will see T.  This does not work in a compiled program.

## Using MakeClass()

- _MyClass.h and MyClass.C_
- MyClass.h
- contains the class definition of "MyClass"
- MyTree.C
- contains the class implementation of "MyClass"

- ROOT Day3, Suzanne Panacek

**Notes:**

Look at MyClass.h and MyClass.C
Note that it declared the leave type Event *event.

## Loading and Using MyClass.C

- Load the macro and create a MyClass object:
- root [0].L libEvent.so
- root [1].L MyClass.C
- root [2] MyClass *m = new MyClass ();

- ROOT Day3, Suzanne Panacek

**Notes:**
To load the macro and create an instance of MyClass:
Step 1  Load the shared library that contains the class definition for Event.
root [0].L libEvent.so
Step 2  Load the macro MyClass.C. This will automatically open the file.
root [1].L MyClass.C
Step 3  Create an instance of MyClass
root [2] MyClass *m = new MyClass();

## GetEntry()

- MyClass::GetEntry()
- root [3] **m->GetEntry(1);**
- root [4] m->event->GetNtrack()
- (Int_t)**597**
- root [5] **m->GetEntry(2);**
- root [6] m->event->GetNtrack()
- (Int_t)**606**

- ROOT Day3, Suzanne Panacek

**Notes:**
Load the MyClass.C and execute GetEntry
root [0] .L libEvent.so
root [1] .L MyClass.C
root [2] MyClass *m = new MyClass()
root [3] m->GetEntry(1)    
(Int_t)48018
root [4] m->event->GetNtrack()
(Int_t)597
     root [5] m->GetEntry(2);      
     root [6] m->event->GetNtrack()
     (Int_t)606
Note: the reason you see a response after m->GetEntry(1) and you see nothing after m->GetEntry(2); is the use of the semicolon. If the semicolon is omitted, CINT will print the output of the method. In this case it is the bytes read. To convince your self try:
root [0] 3+4
(int)7
root [1] 3+4;
root [2]

## Loop()

- MyClass::Loop()
- root [6] **m->Loop();**
- Bytes read: 48492
- Bytes read: 48413
- Bytes read: 48255
- Bytes read: 48413
- Bytes read: 48255
- Bytes read: 48176
- ...

- ROOT Day3, Suzanne Panacek

**Notes:**
Add this line to the Loop() to have some output:
cout << " Bytes read: " << nb << endl;
Load the MyClass.C and execute Loop()
     root [0] .L libEvent.so
root [1] .L MyClass.C
root [2] MyClass *m = new MyClass();
root [3] m->Loop(); 
...   
            Bytes read: 48492
     Bytes read: 48413
     Bytes read: 48255
     Bytes read: 48413
     Bytes read: 48255
     Bytes read: 48176

## Demo - Expanding Loop()

- _Modifying MyClass::Loop() _
- 	 1. Create a Track object
**	****	**Track *track     = 0;
- 2. Create two histograms
- TH1F *myHisto = new TH1F(
- 		"myHisto","fPx",100,-5,5);
- TH1F *smallHisto = new TH1F(
- 		"small","fPx 100",100,-5,5);

- ROOT Day3, Suzanne Panacek

## Expanding Loop() (cont.)

- 3. In Event loop, get the event branch
- fChain->GetEntry(i);
- 4. And get the number of tracks
- n_Tracks = event->GetNtrack();
- 6. Add track loop
- for (Int_t j = 0; j < n_Tracks; j++){
- 	track = (Track*) event->GetTracks()->At(j);

- ROOT Day3, Suzanne Panacek

## Expanding Loop() (cont.)

- Fill the first histogram with Px
- myHisto->Fill(track->GetPx());
- Add an if statement for the first 100 tracks
- if (j < 100){
- smallHisto->Fill(track->GetPx());
- }
- Outside of the Event loop, draw the histograms
- myHisto->Draw();
- smallHisto->Draw("Same");

- ROOT Day3, Suzanne Panacek

## Expanding Loop() (cont.)

- .L libEvent.so
- .L MyClass.C
- MyClass *m = new MyClass();
- m->Loop()

- ROOT Day3, Suzanne Panacek

## Chains

- Scenario:
*Perform an analysis using multiple ROOT files. All files are of the same structure and have the same tree.*

- ROOT Day3, Suzanne Panacek

**Notes:**
When the input is to be found in several files containing the same tree, we can use TChain to access the data on the tree in all the files.  

## Chains (cont.)

- TChain::Add()
- root [3] TChain chain("T");
- root [4] chain.Add("Event.root")
- root [5] chain.Draw("fTracks.fPx")
- root [6] myCanvas->cd(2);
- root [7] chain.Add("Event50.root")
- root [8] chain.Draw("fTracks.fPx")

- ROOT Day3, Suzanne Panacek

**Notes:**
This example builds a chain with 2 root files that contain the tree "T".
A TChain is a collection of TFile objects. the first parameter "name" is the name of the TTree object in the files added with Add. Use TChain::Add to add a new element to this chain.

Add a new element to this chain. An element can be the name of another chain or the name of a file containing a tree. name may have the following format: //machine/file_name.root/subdir/tree_name machine, subdir and tree_name are optional. If tree_name is missing, the chain name will be assumed. 

Step 1:  Create a chain and call the Add method:
root [0] TCanvas *myCanvas = new TCanvas (
	"myCanvas","My Canvas", 0,0,600,400);
root [1] myCanvas->Divide(2,1);
root [2] myCanvas->cd(1);
root [3] TChain chain("T");
root [4] chain.Add("Event.root")
root [5] chain.Draw("fTracks.fPx")
root [6] myCanvas->cd(2);
root [7] chain.Add("Event50.root")
root [8] chain.Draw("fTracks.fPx")

## Chains (cont.)

- TChain::GetListOf...
- To see the files that are chained
- 		chain.GetListOfFiles()->Print()
- List the branches and leaves of the chain.
- 		chain.GetListOfBranches()->Print()
- 		chain.GetListOfLeaves()->Print()
- TChain::Merge()
- To merge the files in a chain and write them to a new file :
- 		chain.Merge("all.root")

- ROOT Day3, Suzanne Panacek

**Notes:**
Step 2:  To see the files that are chained:
root [9] chain.GetListOfFiles()->Print()
Step 3:  List the branches and leaves of the chain.
root [10] chain.GetListOfBranches()->Print() root [11] chain.GetListOfLeaves()->Print()
Step 4:  To merge the files in a chain and write them to a new file :
root [12] chain.Merge("all.root")

## Demo: Building Chains

- {
-  	gROOT->LoadMacro("$ROOTSYS/test/libEvent.so");
- 	TChain chain("T") ;
- 	chain->Add("EventOB.root")  ;
- 	chain->Add("EventOB40.root");
- 	chain->Add("EventOB50.root");
- 	chain->GetListOfFiles()->Print();
- 	chain->MakeClass("ChainClass");
- }

- ROOT Day3, Suzanne Panacek

## Summary: Trees in Analysis

- From the command line using TTree::Draw()
- Using MakeClass and Loop()
- Using Chains

- ROOT Day3, Suzanne Panacek

## Adding Your Own Class

- From the Interpreter
- No I/O
- As a Shared Library
- Full Functionality
- With ACLiC
- Full Functionality

- ROOT Day3, Suzanne Panacek

**Notes:**
There are several ways to add your own class to ROOT and make it available from the command line. 
From the InterpreterThis is easy, however it is also limiting. Your will not be able to save it to a root file, and you will not be able to use the methods most objects inherit from TObject. For example Inspect(), or Print().
As a Shared LibraryThis option involved building a shared library that contains your class and a class dictionary for CINT. This will allow you to save your class to a root file (it must inherit from TObject), and you will have ROOT's RTTI available for your class.
With ACLiCACLiC allows you to add your class without a makefile. It is the best of both worlds. A dictionary will be generated, and you do not have worry about building and linking.

## A Class From the Interpreter*

- Define the Class in a Macro  IClass.Csee  notes below
- Load the Class by Loading the Macroroot [0] .L IClass.C
- Instantiate an IClassroot [1] IClass *ic = new IClass()

- ROOT Day3, Suzanne Panacek

**Notes:**
To add your own class to root from the interpreter you write a macro containing your class. Below is the code that we save in a macro called IClass.C:

#include <iostream.h>
class IClass {
private:
   float   fX;     //x position in centimeters
   float   fY;     //y position in centimeters

public:
   IClass() { fX = fY = -1; }
   void Print()       {cout << "fX = " << fX << ", fY = " << fY << endl;}
   void SetX(float x) { fX = x; }
   void SetY(float y) { fY = y; }
};

## A Class From the Interpreter

- Use the IClass
- root [2] ic->SetX(3)
- root [3] ic->SetY(500)
- root [4] ic->Print()
- fX = 3, fY = 500
- Cool, but can't save it. We need the Write() method from TObject.
- root [5] ic->Write()
- Error: Can't call IClass::Write() ...

- ROOT Day3, Suzanne Panacek

**Notes:**
Now we can load the macro and instantiate an IClass:
root [0] .L IClass.C              
root [1] IClass *ic = new IClass()

And we can use it.
root [2] ic->Print()
fX = -1, fY = -1
root [3] ic->SetX(3)
root [4] ic->SetY(500)
root [5] ic->Print()  
fX = 3, fY = 500

But we can't save it – ouch!
root [6] ic->Write()
Error: Can't call IClass::Write() in current scope FILE:/var/tmp/daaa08MrC_cint LINE:1
Possible candidates are...

## A Class From a Shared Library

- _Step 1:_
- define your class as a descendent of TObject and write the implementation.
- SClass.h
- #include <iostream.h>
- #include "TObject.h"
- class SClass : public TObject {
- ...

- ROOT Day3, Suzanne Panacek

## A Class From a Shared Library

- _Step 2:_
**ClassDef**(*ClassName,ClassVersionID*)
- At the end of the class definition
**ClassImp**(*ClassName*)
- 	At the beginning of the implementation file

- ROOT Day3, Suzanne Panacek

**Notes:**
Step 2:Add a call to the ClassDef macro to at the end of the class definition (i.e. in the SClass.h file).ClassDef(SClass,1). In case you don't need object I/O you could set ClassVersionID to 0.
Add a call to the ClassImp macro in the implementation file (SClass .cxx). ClassImp(SClass) 
SClass.cxx:
#include "SClass.h"
ClassImp (SClass)
void SClass::Print() const {
   cout << "fX = " << fX << ", fY = " << fY << endl;
}

## ClassDef and ClassImp*

- ClassDef and ClassImp needed for Object I/O :
- These macros can automatically create:
- Streamer method needed for writing to ROOT files and Trees.
- ShowMembers()
- >> operator overload

- ROOT Day3, Suzanne Panacek

## The LinkDef file

- _Step 3:_
- create a LinkDef.h file
- #ifdef __CINT__
- #pragma link off all globals;
- #pragma link off all classes;
- #pragma link off all functions;
**#pragma link C++ class SClass;**
- #endif

- ROOT Day3, Suzanne Panacek

## The LinkDef Options:

- "-" do not generate a streamer.
**#pragma link C++ class SClass-;**
- Use for objects with customized streamers
- "!" do not generate the operator >>
**#pragma link C++ class SClass-!;**
- Use for classes not inheriting from TObject.
- "+" use the byte count check
**#pragma link C++ class SClass+;**
- !! In ROOT 3 the "+" turns on the new ROOT IO.

- ROOT Day3, Suzanne Panacek

## Makefile and rootcint

- _Step 4:_
- Write a Makefile and call rootcint to add your class to the dictionary:
- SClassDict.cxx SClass.h LinkDef.h
- $(ROOTSYS)/bin/**rootcint** -f SClassDict.cxx -c SClass.h LinkDef.h

- ROOT Day3, Suzanne Panacek

## rootcint ...

- LinkDef.h must be the **last** argument on the rootcint command line.
- The LinkDef file name **MUST** contain the string:
- LinkDef.h or linkdef.h, i.e. NA49_LinkDef.h is fine just like, mylinkdef.h.

- ROOT Day3, Suzanne Panacek

## Compile and Load

- Compile the class using the Makefile
- 	gmake –f Makefile.sgikcc
- Load the shared library
- 	 root [0] .L SClass.so
- 	 root [1] SClass *sc = new SClass()
- 	 root [2] TFile *f = new TFile("Afile.root", "UPDATE");
- 	 root [3] sc->Write();

- ROOT Day3, Suzanne Panacek

**Notes:**
Now we can compile the shared library
Then load it on the command line, and instantiate an object of our class. And after opening a file to have a place to save it to, we can write the class to a root file.

## Adding Your Class With ACLiC

- _Step 1: _define your class
**#include "TObject.h"**
- class ABC : public TObject {
-   public:
-     Float_t a,b,c,p;
-     ABC():a(0),b(0),c(0),p(0){};
-   **ClassDef(ABC,1)**
- };
**#if !defined(__CINT__) // conditional**
-   **ClassImp(ABC);**
- #endif

- ROOT Day3, Suzanne Panacek

**Notes:**
You need to include the header files of the classes you intend to use.

#include "TObject.h"
  // define the ABC class and make it inherit from TObject so that we can write ABC to a root file
  class ABC : public TObject {
  public:
    Float_t a,b,c,p;
    ABC():a(0),b(0),c(0),p(0){};
    // Define the class for the cint dictionary
   ClassDef(ABC,1)  
  };

  // Call the ClassImp macro to give the ABC class RTTI and full I/O capabilities.
  #if !defined(__CINT__) 
    ClassImp(ABC);
  #endif

To be able to run this macro with ACLiC and the interpreter make the call to ClassImp conditional.

#if !defined(__CINT__) 
  ClassImp(ABC);

## Adding Your Class With ACLiC*

- _Step 2:_ Load the ABC class in the script.
- Check if ABC is already loaded
- 	if (!TClassTable::GetDict("ABC")) {
- 		gSystem->CompileMacro("ABCClass.C");
- 	}
- Use the Class
- ABC *v = new ABC;
-       v->p = (sqrt((v->a * v->a)+
-          (v->b * v->b)+(v->c * v->c)));

- ROOT Day3, Suzanne Panacek

**Notes:**
{  // check to see if the class ABC is in the dictionary
   // if it is not in the dictionary compile it with ACLiC.
  if (!TClassTable::GetDict("ABC")) {
    gSystem->CompileMacro("ABCClass.C", "k");
  }
  // Open the ASCII file for reading
 ifstream asciiFile("ABC.txt");

  // create a TFile object, using RECREATE to overwrite if it exists 	
  TFile *hfile = new TFile("ABCwithClass.root","RECREATE","Exercise 1");

  // create a TTree object with the name T, title : A ROOT tree, 
  // and the default buffer size of 64 MB
  TTree *tree = new TTree("T","A ROOT tree");
  // create an ABC object. This must be on the heap to be added to the tree correctly.
  ABC *v = new ABC;	
... SEE NEXT PAGE

## Adding Your Class With ACLiC

- _Step 3:_ Run ABCWriteClass.C
-      root[0] .X ABCWriteClass.C

- ROOT Day3, Suzanne Panacek

**Notes:**
CONTINUED ...
  // add a branch called abcBranch, it contains ABCSTURCTURE , and the
  // leaves are: a,b,c. add another branch for the lenght of this vectorv
  TBranch *abcBranch = tree->Branch("abcBranch","ABC",&v);	
  while (asciiFile >> v->a >> v->b >> v->c) {
    v->p = (sqrt((v->a * v->a)+(v->b * v->b)+(v->c * v->c)));
    tree->Fill();
  }
  hfile->Write();
  // Draw the tree
  TCanvas *myCanvas = new TCanvas ("myCanvas","My Canvas", 0,0,600,400);
  myCanvas->Divide(2,2);
  myCanvas->cd(1); tree->Draw("a");
  myCanvas->cd(2); tree->Draw("b");
  myCanvas->cd(3); tree->Draw("c");
  myCanvas->cd(4); tree->Draw("p");
}

## Summary: How Add your own Class

- From the Interpreter
- As a Shared Library
- With ACLiC

- ROOT Day3, Suzanne Panacek

## Wrap Up

- Questions ?
- Feedback Forms
**Vote** on importance of subject (no recounts)
- _[http://](http://patwww/root/class/survey/vote.html)__[www-pat.fnal.gov/root](http://www-pat.fnal.gov/root)_/_[class/survey/vote.html](http://root.cern.ch/root/htmldoc/ListOfTypes.html#Int_t)_
- More information:
- _[http://www-pat.fnal.gov/root](http://www-pat.fnal.gov/root)_/
- http://root.cern.ch
- roottalk@root.cern.ch
- about-root@fnal.gov
- http://ods.fnal.gov/ods/root-eval

- ROOT Day3, Suzanne Panacek

## ROOT User's Workshop

- Fermilab
- June 13-15, 2001
- http://patwww/root/root2001/

- ROOT Day3, Suzanne Panacek

## Solutions to the Exercises

- http://patwww.fnal.gov/root/class/solutions.htm

- ROOT Day3, Suzanne Panacek