The ROOT trees are meant to:
- Store large number of entries.
- Manage hierarchy of branches and leaves.
- Read selective branches
The TTree class is designed for storing large number of same-class objects. The TTree class is optimized to reduce disk space and enhance access speed. 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. Each branch can be read independently from any other branch. For example, assume that Px and Py are data members of the event, and we would like to compute Px^2 + Py^2 for every event and histogram the result. If we had saved the million events without a TTree we would have to:
- Read each event in its entirety into memory
- Extract the value of Px and Py from the event
- Compute the sum of the squares
- Fill a histogram
We would have to do that a million times! This is very time consuming, and we really do not need to read the entire event, every time. All we need are two little data members (Px and Py). On the other hand, if we use a tree with one branch containing Px and another branch containing Py, we can read all values of Px and Py by only reading the Px and Py branches. This makes the use of the TTree very attractive.
Let's review the 5 steps to build a Tree:
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");
The creation options are:
- 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");
One can also create a Tree with Folders:
TTree aliTree("aliTree", "/aliroot")
- First Parameter: tree name
- Second Parameter: /name of the top folder
Step 3: Adding a Branch
Adding branches is done with the TTree::Branch():
- 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);
Adding branches with a list of variables is done with the Branch() method which has the following parameters:
TBranch *b = tree->Branch ("Ev_Branch",&event, "ntrack/I:nseg:nvtex:flag/i:temp/F");
Adding branches with a TClonesArray:
tree->Branch( "Track_B", &Track, 64000);
Step 4: Fill the Tree
Now, let's just:
- Create a for loop
- Assign values to the event object
- Call the Fill method for the tree
Step 5: Write the File
Write the fileThe TFile::Write()
- Writes Histograms and Trees
- Write is needed to write file header
Reading a TTree
Didn't we say 5 steps? To look at a tree one can do:
- TTree::Print() Shows the branches
TFile f("AFile.root"); myTree->Print();
For more details refer to this how to.