TChains, friends, and loops

Hey everyone. I’m a having a problem and am in need of a sanity check to make sure that what I’m doing should indeed work. I have a bunch of files with TTree’s in them. In each file, there’s a master tree that has an EventID and RunID for every single event. Other trees have EventID’s and RunID’s and other quantities, but there is not necessarily an entry in each of these trees for each entry in the master tree. These trees are friends of the master tree. I’m trying to do the following in order to loop over the chains:

TChain* masterTree = new TChain(“tree”);
TChain* subTree1 = new TChain(“tree1”);
TChain* subTree2 = new TChain(“tree2”);

masterTree->Add(“blah”);
subTree1->Add(“blah”);
subTree2->Add(“blah”);

masterTree->AddFriend(subTree1, “”);
masterTree->AddFriend(subTree2,"");

Double_t value1;
Double_t value2;

subTree1->SetBranchAddress(“value1”, &value1);
subTree2->SetBranchAddress(“value2”, &value2);

Long64_t entries = masterTree->GetEntries();

for(Long64_t i=0; i<entries; i++){

masterTree->GetEntry(i);

}

This appears to work fine, and the data members of the friend trees seem to be filled in properly, at least for awhile. However, things eventually segmentation fault, and they always segmentation fault at the boundary between one file in the chain and the next. (core dump below…) I’ve tried this with a bunch of different chains with the same result.

My question: Is there something fundamentally wrong here? Is the fact that the subsidiary trees don’t have entries for all the entries of the master tree a problem? It seems to me that this should work, but the seg faults are persistent. Any help you all could provide would be much appreciated. Thanks!

Michelangelo

core dump:

*** Break *** segmentation violation
(no debugging symbols found)
Using host libthread_db library “/lib64/tls/libthread_db.so.1”.
Attaching to program: /proc/26139/exe, process 26139
(no debugging symbols found)…done.
(no debugging symbols found)…done.
(no debugging symbols found)…done.
(no debugging symbols found)…done.
[Thread debugging using libthread_db enabled]
[New Thread 182943199456 (LWP 26139)]
(no debugging symbols found)…done.
(no debugging symbols found)…done.
(no debugging symbols found)…done.
(no debugging symbols found)…done.
(no debugging symbols found)…done.
0x0000002a9816eca6 in waitpid () from /lib64/tls/libc.so.6
Thread 1 (Thread 182943199456 (LWP 26139)):
#0 0x0000002a9816eca6 in waitpid () from /lib64/tls/libc.so.6
#1 0x0000002a98105ea1 in do_system () from /lib64/tls/libc.so.6
#2 0x0000002a97fb9e19 in system () from /lib64/tls/libpthread.so.0
#3 0x0000002a9598069c in TUnixSystem::Exec () from /opt/cern/root_v5.14.00_x86-64/lib/libCore.so
#4 0x0000002a95980a56 in TUnixSystem::StackTrace () from /opt/cern/root_v5.14.00_x86-64/lib/libCore.so
#5 0x0000002a9597ee08 in TUnixSystem::DispatchSignals () from /opt/cern/root_v5.14.00_x86-64/lib/libCore.so
#6 0x0000002a9597d061 in SigHandler () from /opt/cern/root_v5.14.00_x86-64/lib/libCore.so
#7 0x0000002a9598325c in sighandler () from /opt/cern/root_v5.14.00_x86-64/lib/libCore.so
#8
#9 0x00000000017a3bd7 in ?? ()
#10 0x0000002a9a7b37c4 in TTreeFormula::EvalInstance () from /opt/cern/root_v5.14.00_x86-64/lib/libTreePlayer.so
#11 0x0000002a9a7b86b8 in TTreeIndex::GetEntryNumberFriend () from /opt/cern/root_v5.14.00_x86-64/lib/libTreePlayer.so
#12 0x0000002a9736a0cc in TTree::LoadTreeFriend () from /opt/cern/root_v5.14.00_x86-64/lib/libTree.so
#13 0x0000002a97368ddb in TTree::GetEntry () from /opt/cern/root_v5.14.00_x86-64/lib/libTree.so
#14 0x0000002a97345e64 in TChain::GetEntry () from /opt/cern/root_v5.14.00_x86-64/lib/libTree.so
#15 0x0000002a99a88a5c in drawBasics (LFcutVal=

Friend Trees must have the same entries than the parent tree.
If this is not the case you should build an Index. see class TTreeIndex
root.cern.ch/root/html/TTreeInde … TTreeIndex

Rene

Hey Rene. Thanks for the response. I tried running BuildIndex on my trees and got the following error:

Error in TChainIndex::TChainIndex: The indices in files of this chain aren’t sorted.
Error in TTreePlayer::BuildIndex: Creating a TChainIndex unsuccessfull - switching to TTreeIndex

After looking into the source code a bit, I discovered that this is because the trees in my chain already had indices built before they were written to the file. However, the index value of the last entry in one file was larger than the index value of the first entry in the next file of the chain. Does this mean that it won’t be possible for me to use TChain to chain these files together? Is it required that the index monotonically increase throughout the chain? Thanks!

Michelangelo

In principle what you do should work. To understand what happens in your case we will need the shortest possible set of files to reproduce the problem togeteher with a simple script.

Rene

Hey Rene. Thanks for taking a look at this. I’ve tried to condense the problem down as much as possible. You can grab a tarball from

icecube.berkeley.edu/~mdagost/root_forum.tgz

Make everything and there’s a library, analysisPackage.so, with a function testTreeCrashes(). I add 6 files to the chain and then loop through. As it is now, it seg faults somewhere in the loop. The strange thing is that, if I only add a single file to the chain, nothing crashes, no matter which of the 6 files it is…

Oh, and I’m using v5.10.00 on a 64 bit RHEL 3 machine…

Thanks!

Michelangelo

I’ve been beating my head against the wall on this one for so long I think I’m going to draw blood soon. Anyway, maybe someone can help. Here’s what I’ve found so far:

My masterTree and subTrees were already made friends in the file where they’re written (for instance, I can loop through the friend list to see this). Making the chains friends again in my analysis script seems to mess things up–certain trees seem to get loaded more than once (once because the chains are friends and then again because the trees were already friends). I’m guessing that’s what’s causing my problem.

So I’ve changed strategies slightly. I’m trying to do something else which seems like it should obviously just work. masterTree and subTree1 are already friends in the file they’re written in, so I don’t need to make them friends again in my analysis script. Also, a TreeIndex has been built for both. So I’d like to do

TChain* masterTreeChain = new TChain(“tree”);
masterTree->Add(“blah”);

//this is a leaf of the friend tree
Double_t subTreeValue1;

masterTreeChain->SetMakeClass(1);
masterTree->SetBranchAddress(“subTreeValue1”, &subTreeValue1);

for(Long64_t i=0; iGetEntries(); i++){

masterTree->GetEntry(i);

}

When I run this code interactively with CINT, it works and the subTreeValue1 gets filled in properly each time through the loop. When I compile the exact same come, however, I get the following error:

Error in TTree::SetBranchStatus: unknown branch

It’s like the masterTree doesn’t know about the branches of its friends when I compile, but it does when it’s interactive. This really seems like it should work. Any thoughts?

Also, while I’m at it, what does SetMakeClass do? I can’t seem to find documentation on it, but with SetMakeClass(0) thing don’t work, even interactively.

Save me from insanity :slight_smile:

Michelangelo

Hi,

I can reproduce your original problem and will have a fix shortly.

SetMakeClass allows to read ‘partial’ object using simple float and ints.

masterTreeChain->SetMakeClass(1); masterTreeChain->SetBranchAddress("EventID", &event); masterTreeChain->SetBranchAddress("RunID", &run);Your EventID and RunID are not part of an object so, here, SetMakeClass is a no-op. double LFVel; subTreeChain->SetMakeClass(1); subTreeChain->SetBranchAddress("LFVel", &LFVel);LFVel is part of an object (of type I3LineFitParams) and without the SetMakeClass(1), you SetBranchAddress would be incorrect (because the system would generate the object and add the offset to the address and other details).

[quote]but with SetMakeClass(0) thing don’t work, even interactively.[/quote]I am not sure what you mean (but indeed is you do SetMakeClass(0) and the SetBranchAddress(“LFVel”) you are unlikely to get any good result for LFVEL).

[quote]When I run this code interactively with CINT, it works and the subTreeValue1 gets filled in properly each time through the loop. When I compile the exact same come, however, I get the following error:
[/quote]I’ll need a real example to reproduce this problem.

Cheers,
Philippe

Your original problem has been solved in the CVS head.

Cheers,
Philippe

One difficulty in your second approach is that you have to (if you still want to access the data without an object) call the SetMakeClass on each of the friend tree in the chain. The following code works for me (with your files):

[code] //declare some variables and set the branch addresses
int event, run;
double LFVel;

masterTreeChain->SetMakeClass(1);
masterTreeChain->SetBranchAddress(“EventID”, &event);
masterTreeChain->SetBranchAddress(“RunID”, &run);

//subTreeChain->SetMakeClass(1);
masterTreeChain->SetBranchAddress(“LineFitParams.LFVel”, &LFVel);

//loop over events
long treenumber = -1;
for(Long64_t i=0; iGetEntriesFast(); i++){

 masterTreeChain->LoadTree(i);
 if (masterTreeChain->GetTreeNumber() != treenumber) {
    treenumber = masterTreeChain->GetTreeNumber();
    masterTreeChain->GetTree()->GetFriend("LineFitParams")->SetMakeClass(1);
    cout << "Tree#: " << treenumber << endl;
 }

 masterTreeChain->GetEntry(i);

 if (i%1000==0) cout << "EventID: " << event << " RunID: " << run << " LFVel: " << LFVel << endl;

}[/code]

Hey Philippe. Thanks for taking a look at this. I’m glad you were able to reproduce the problem and think you have a fix. That’s great news!

Michelangelo

Hey Philippe. Things work perfectly. Thanks! Just in time to generate my plots for a talk :slight_smile:

I think ultimately the way to go is to just load things with the original classes rather than doing things branch by branch with chain friends…

Michelangelo