I reported a bug with "class TChain" a few days ago in which the analysis skeleton generated by "TTree::MakeClass" didn't work when instantiated with a TChain* (see http://root.cern.ch/root/roottalk/roottalk99/1944.html). I have a fix and a workaround for this bug, which I thought I would share with the list. The problem is in `TREE_Chain.cxx'. Please note that this bug can affect *all* uses of a "TChain" in your analysis code, and is *not* limited to the code generated by "TTree::MakeClass". I have a patch to the source code which fixes this bug which I would be happy to share with whomever may need it. However, using my patch would require you to patch your sources and rebuild ROOT. You can do this if you wish, but there is an easier workaround that doesn't require you to rebuild ROOT, which is the subject of the rest of this e-mail. Besides, the ROOT Team will probably come up with a more elegant solution than mine in the next release of ROOT. The executive summary for the workaround is that you must use the method "TChain::SetBranchAddress" instead of the methods "TTree::GetBranch" followed by "TTree::SetAddress". For example, consider the following example, in which we write to stdout an element from a branch named "foo" (consisting of a float) which comes from a "TTree" named "T" (which consists of a "TChain" of files): >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> begin example >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> TChain* tree = new TChain( "T" ); tree->Add( "foo-1.root" ); tree->Add( "foo-2.root" ); tree->Add( "foo-3.root" ); tree->Add( "foo-4.root" ); float foo; // The next two lines are broken. TBranch* b_foo = tree->GetBranch( "foo" ); b_foo->SetAddress( &foo ); size_t nevent = static_cast< size_t >( tree->GetEntries() ); for ( size_t i = 0; i < nevent; ++i ) { tree->GetEntry( i ); cout << "foo = " << foo << endl; } <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< end example <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Notice the comment, above, indicating which of the two lines are broken for "class TChain". The workaround is to use the single method "TChain::SetBranchAddress" instead, as follows: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> begin example >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> TChain* tree = new TChain( "T" ); tree->Add( "foo-1.root" ); tree->Add( "foo-2.root" ); tree->Add( "foo-3.root" ); tree->Add( "foo-4.root" ); float foo; tree->SetBranchAddress( "foo" , &foo ); size_t nevent = static_cast< size_t >( tree->GetEntries() ); for ( size_t i = 0; i < nevent; ++i ) { tree->GetEntry( i ); cout << "foo = " << foo << endl; } <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< end example <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Unfortunately, although this is a trivial way to workaround the bug, the code generated by "TTree::MakeClass" uses the first (broken) method. So, you will have to edit the automatically generated code by hand. Interestingly enough, the code generated by "TTree::MakeCode" does generate correct code (it uses "TChain::SetBranchAddress"). There was another proposed fix for this bug (see http://root.cern.ch/root/roottalk/roottalk99/1810.html), but I have confirmed that this does not work for ROOT 2.22.10. -- Matthew D. Langston SLD, Stanford Linear Accelerator Center langston@SLAC.Stanford.EDU
This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:43:38 MET