Trying to read TTree subbranch

Hi all,

I am trying to read a sub-branch from a TTree (called MGTree).

When I do a print of the TTree, like so:

MGTree->Print()

I see the following:

fWaveforms.fData : std::vector<double> fData[fWaveforms_]

This seems to indicate to me that the sub-branch fData should be read into an array of vectors.
Here are some of the things I have tried. I discovered on my own that the structure of the tree requires that I type MGTree->SetMakeClass(1) in order to read in any of the branches/sub-branches due to something called event splitting, so this is always a part of the code. I include the first line to be safe, but it actually seems to work without it, so the newest version of ROOT must include vectors.

gRoot->ProcessLine("#include <vector>"); TFile f("OR_run150.root"); MGTree->SetMakeClass(1); vector<double> fDataArr[9000]; TBranch *fDataBranch = MGTree->GetBranch("fWaveforms.fData"); fDataBranch->SetAddress(fDataArr); MGTree->GetEntry(0);

This unfortunately segfaults.

I am basing my code off of this discussion thread and the example that it references in the TTree tutorial, which seemed to address a similar problem.

I also tried making 'fDataArr" into a pointer rather than an array. It seems one common reason for the segfault is to not initialize the pointer to zero, so I have tried the following.

gRoot->ProcessLine("#include <vector>"); TFile f("OR_run150.root"); MGTree->SetMakeClass(1); vector<double>* fDataArr=0; TBranch *fDataBranch = MGTree->GetBranch("fWaveforms.fData"); fDataBranch->SetAddress(fDataArr); MGTree->GetEntry(0);

Nevertheless, this also segfaults.
In addition to the above, I have tried not initializing fDataArr to zero. I have also tried setting it using the new operator. None of these seemed to work.

I then noticed that if I typed ‘MGTree->Show(0)’, I see the following:

fWaveforms.fData = (vector<double>*)0x7ffa4db1f168

This to me seems to indicate that perhaps fWaveforms.fData should be read into an array of pointers to vectors. I then tried to modify my code to try that:

First I tried this:

gRoot->ProcessLine("#include <vector>"); TFile f("OR_run150.root"); MGTree->SetMakeClass(1); vector<double>** fDataArr=0; TBranch *fDataBranch = MGTree->GetBranch("fWaveforms.fData"); fDataBranch->SetAddress(fDataArr); MGTree->GetEntry(0);

Then I tried:

gRoot->ProcessLine("#include <vector>"); TFile f("OR_run150.root"); MGTree->SetMakeClass(1); vector<double>* fDataArr[9000]; TBranch *fDataBranch = MGTree->GetBranch("fWaveforms.fData"); fDataBranch->SetAddress(fDataArr); MGTree->GetEntry(0);

Reading through the documentation, it seems that the biggest causes for segfaults if you aren’t careful are 1) not initializing a vector 2) Not using SetMakeClass when appropriate. I feel that I’ve been fairly thorough with this and I still cannot see what the issue is. Perhaps my understanding of the data type which is stored in the TTree is incorrect. I should mention that I also tried

fDataBranch->SetAddresss(&fDataArr) 

for all of the examples above as well.

If anyone has any suggestions, it would be much appreciated. I am using ROOT version 6, but have also tried all of the above using ROOT version 5-34 with the same results.

Thank you,
Chelsea Bartram

Hi Chelsea,

fWaveforms.fData : std::vector<double> fData[fWaveforms_]indicates that fData is a datamember of class and that instances of that class are held in a collection that has been split in the TTree.

So, for example, fWaveforms might be a vector. fData is thus is nested collections. It is non-trivial to access those playing directly with addresses.

MGTree->SetMakeClass(1);only allows to read the object as decomposed in ints and floats and those not support nested collection which can only read as an object.

One way to access the data is to use TTreeFormula:TTreeFormula formula("formula","fWaveforms.fData",t); for (int entry=0;entry< t->GetEntries();++entry){ t->LoadTree(entry); const auto size = formula.GetNdata(); cout << " o Size is " << size << endl; for(int i = 0; i < size; ++i) { auto charge = formula.EvalInstance(i); cout << " * " << charge << endl; } }

Other alternative include using TTree::MakeProxy or TTree::MakeSelector from v6.06 (based on the TTreeReader), loading the original shared library and using the real object or using TFile::MakeProject to generate a POD version of those objects.

Cheers,
Philippe.