Create a new index for a TTree

Hi,

After filling a TTree, I’d like to re-index the tree based on a given branch. ThenI want to save the tree in a file with this new index. From the TTreeIndex class documentation it looks like it is possible but it is not clear how.

I want to do something like this but this is obviously wrong:

[...] TTreeIndex *index = new TTreeIndex(myTree, "myBranchname", "0"); myTree->Write(); [...]

Any idea how to do this properly ? Thank you

I tried the following:

myTree->BuildIndex("myBranchname","0"); myTree->Write();

I thought that the new index would be saved with the tree but it didn’t. What am I missing?

Thank you.

Just a crazy thought … you do know that you should use actual “LeafNames” (NOT “BranchNames”) of your TTree when defining “major” and “minor” names for the index table, don’t you?
See, for example, TTreeIndex::TTreeIndex, TTree::BuildIndex and TTree::SetTreeIndex

Right!

Let me be more explicit:

[code]TTree *myTree = new TTree(“myTree”, “myTree”);
double Ttime;
myTree->Branch(“time”, &Ttime, “time/D”);

here, I skip some code lines where I fill my tree with time values which are not sorted

myTree->BuildIndex(“time”,“0”);
myTree->Write();[/code]

Now, with this piece of code, I end up with a TTree where the the entries are not time-sorted. How could I achieve this?

The entries themselves will NOT be “reorganised” in the ROOT file according to your “index”.
If you use “MyTree->GetEntry(i)” (where int i = 0 … MyTree->GetEntries() - 1), you will still read them in the order in which you filled them (i.e. in the order in which they were written to the ROOT file).
You need to use “MyTree->GetEntryWithIndex(SomeTime)”, then you will read them according to the “index” (note that “SomeTime” should be an integer value equal to “int(time)”).
Note that, if your “SomeTime” does not correspond to any “index value”, the TTree::GetEntryWithIndex method will return -1 (otherwise it returns the total number of bytes read).

That’s too bad that what I want is impossible.

The solution you propose is what I was using until now. The problem is that it is quite slow, especially in case of big trees. I imagine that with the new index you need to go back and forth in the memory to retrieve the entries in the right order and it takes time.

I was hoping that I could save the tree with the entry in the right order so that, later, I could read the tree entries chronologically which is much faster.

I guess I have to find a way to fill the tree in the right order from the start :cry:

Yes, you need to sort your data yourself before you fill your tree.

There is also the possibility to do it in two steps.
First create an “unsorted tree” (no need for any “index” at this step) and write it into a ROOT file (or keep it simply in RAM, if it’s not too big).
Then, in the second step, open the “unsorted tree” and copy its contents into another “sorted tree”, into another ROOT file, filling the new “sorted tree” with the entries from the old “unsorted tree” in the order defined by your “sorting index” (note: you do not need to store your “sorting index” at all, you just need to compute it on the fly, so that you retrieve “old” entries in the proper order).
See TTree::CloneTree and the “copytree*.C” files in the ROOT Tutorials: Trees I/O, Queries, Graphics

Thanks a lot Wile,

This sounds good. Can I skip the intermediate ROOT file step? I’m working with 2 trees but I only saved the sorted one at the very end. Would that trigger a conflict of some kind?
Thanks.

As I’ve already written … if you have enough RAM, you can simply keep the whole “unsorted tree” in it (no need to “Write()” it anywhere at all).