Get Ttree entries without knowing type

Hi all,

I am looking for a solution to generically access information from branches in a root tree.

The tree could have a variety of branches with different datatypes and I would like to access them all basically in a loop without knowing beforehand which branch contains which type.

Is there an easy way to achieve this?

Cheers,

Erik

I am not sure to understand your question. What do you want to do in your loop if you do not know what the data types are?
Via the TBranch/TBranchElement/TLeafElement you can find out the data type in each branch/leaf.
You can retrieve the value in a leaf by leaf->GetValue(0) if a scalar, GetValue(i) if vector.
You can get the pointer (better outside the loop) to a leaf with
TLeaf *leaf = tree.GetLeaf(leaf_name);

Rene

Hi Rene,

I am thinking of something which could make use of e.g. the boost::any container or something like this, such that I can set the branchaddress to such an object and retrieve the value without having to care about the actual type.

So something like (not to be taken as the 100% actual code)

std::vector<boost::any> vector;
TObjArray* array = tree->GetListOfBranches();
Int_t nBranches = array->GetEntriesFast();
vector.resize(nBranches);
for(int i  = 0;i < entries; ++i) {
   char* branchName = array->At(i)->GetName();
   static_cast<TBranch*>(array->At(i))->SetBranchAddress(branchName,&vector[i]);
}

for(int n = 0; n < tree->GetEntriesFast(); ++n) {
    tree->GetEntry(n);
   // then do something with various vector[i]'s

}

Erik

I am still puzzled why you want to make the things complex.
If you provide a top branch as a class, ROOT will automatically create the branches corresponding to your object model. Then tree.GetEntry will correctly fill back your top level object and descendants.

Also note that in case you do not set the branch addresses to your own objects/types, ROOt will automatically map them in dynamically allocated data structures faking your objects.
You can retrieve the values from these internal structures.

Rene

Hi Rene,

ok, I see, what you said in your first reply actually does what I want.

Is this documented anywhere?! Because I did not find this in either the TTree, TBranch, or TLeaf class documentation or the users’ guide, or …

Maybe I just overlooked it, but at least looking for TLeaf in the documentation of TBranch and TTree did not return any hints on this and the documentation in TLeaf is also not very much hinting at this usecase.

I think this method is VERY useful, especially is saves the user the work of having to keep track of the type of a branch, e.g in the case where he is just reading somebody elses tree which could change without prior notice. By using this, these things can be handled very transparent.

I can also post this as a question in the documentation forum, as the technical aspect of this is solved.

Cheers,

Erik

Erik,

Well, I agree that this could be better documented. However we do that a bit on purpose because we believe that this is not the best solution. Use your object model, whatever it is and tree.GetEntry will be able to fill your object automatically.

Rene

[quote]I am thinking of something which could make use of e.g. the boost::any container or something like this, such that I can set the branchaddress to such an object and retrieve the value without having to care about the actual type. [/quote]This is technically very hard. The major issue is that each boost::any must know the type of the content at compile time (This is because internally boost::any use templates to generate the proper ‘tuple’ pointer, constructor, destructor. (So the ‘hard’ part would be ‘how to construct’ a ‘proper’ boost::any given a TClass object).

For complete parsing the content of TTree, see TTreeFormula, TTree::MakeSelector or TTree::MakeProxy (and yes it is not ‘simple’).

The following code is essentially equivalent to yours if the content of the TTree are objects (if not, then Rene’s recommendation is the best and easiest !!! )

[code]std::vector<std::pair<TClassRef,void > > values;
TObjArray
array = tree->GetListOfBranches();
Int_t nBranches = array->GetEntriesFast();
vector.resize(nBranches);
for(int i = 0;i < entries; ++i) {
TBranchElement be = dynamic_cast<TBranchElement>(array->At(i));
if (be) {
char* branchName = be->GetName();
tree->SetBranchAddress(branchName, & ( vector[i].second ) );
}
}
for(int n = 0; n < tree->GetEntriesFast(); ++n) {
tree->GetEntry(n);
// then do something with various vector[i]'s

} [/code]

Cheers,
Philippe.

Hi,

just to clarify a bit more the original scope. I have an API, which gets a TTree and should then enable the user to work with the contents of the tree. However I do not have control about the contents of the tree, since they come from various sources. So I need to be able to process the data no matter if they have been booked as Int, float, double, … .

Neither the number of branches, nor the structure of the tree does have to stay the same for the future. The only thing which is (somewhat) guaranteed is the fact that the branch contains an elementary datatype and no objects or arrays

This is why the suggestion to use leaf->GetValue(0) was exactly what I needed, since I can work with the “double” which is returned without problem, but the tree won’t complain that I try to set a wrong type variable to the branchaddress.

I also realized that my boost::any was not all that simply to use, since I only get the information about the tree at runtime.

Sorry if I was a bit harsh in my previous posts.

Cheers,

Erik