CopyTree & SetBranchAddress

From: Vassili Maroussov <vmarusov_at_fnal.gov>
Date: Wed, 07 Jun 2006 19:03:59 +0200


Dear ROOTers,

I'm wondering why CopyTree(Cuts) is affected by SetBranchAddress(...). Consider a fragment like



template <class T>
void func(TTree *tree, const char *bname, ...) {

   T b_val;
   TBranch *b_ref;
   tree->SetBranchAddress(bname, &b_val);

//Here is a code, that doesn't reset the branch address...

int main()
{

   TFile inp_file("inpfile.root", "READ");    TTree *tree = (TTree*)inp_file.Get("tree");

   func(tree, "branchname", ...);

   TFile out_file("outfile.root", "RECREATE");    TString Cuts = "..."; //some cuts, maybe "", then all tree should be copied

   TTree *newtree = tree->CopyTree(Cuts);    newtree->SetName("newtree");
   newtree->Write();

One may discover the branch "branchname" in "newtree" will be filled with 0's. Is it a bug or a feature?

More unexpected things appear if to try a similar program structure (SetBranchAddress to a local variable in a function) with TChain. In that case even ResetBranchAddresses() doesn't help. Please consider the sample program (test_CopyTree.cxx) attached. It is expected to do the following:

  1. produce 2 files with a simple tree with one branch with floats, another with integers; integers are the sequence 0,1,2,3,...,9999;
  2. add files produced to a TChain;
  3. find 95% intervals for branches by means of getting each branch in an STL vector, sorting, etc.;
  4. copy TChain into a TTree with Cuts that correspond to 95% intervals;
  5. save the TTree in a new file.

What I observed in reality (test_out.txt) is the following:

What is wrong with the sample code? I used ROOT 5.06 and gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-54), SLC3. The code was compiled with:

g++ -o test_CopyTree test_CopyTree.cxx `root-config --cflags --libs`

With the best regards,

Vassili.

#include <iostream>
#include <vector>
#include <algorithm>

#include "TChain.h"
#include "TFile.h"

#include "TRandom.h"
#include "TString.h"

using namespace std;

const char *fname  = "testCopyTree";
const char *fbname = "fbranch";
const char *ibname = "ibranch";

void make_datafile(const char *f_name)
{

//Create a ROOT file with a tree "T" with 2 simple branches, one with
//float's, another with int's. Integers incremented from 0 to 9999, floats
//normally distributed around 10 with sigma=1.

   Float_t fbranch;
   Int_t ibranch;

   TFile *f = new TFile(f_name,"recreate");    TTree *T = new TTree("T","test CopyTree");    T->Branch(fbname,&fbranch,"fbranch/F");    T->Branch(ibname,&ibranch,"ibranch/I");

   TRandom r;
   for (Int_t ii=0; ii<10000; ii++) {

      fbranch = r.Gaus(10,1);
      ibranch = ii;
      T->Fill();

   }
   T->Write();
   delete f;
}

template <class T>
void FindInterval(TChain *tree, const char *b_name,

                  T& left, T& right,
                  Float_t frac = 0.95)

{
//Scans a branch <b_name> of a tree <tree> that contain a simple 
//variable (no objects) and returns interval [left, right] that 
//contains required fraction <frac> of entries.

   Int_t n_ent = tree->GetEntries();
   std::vector<T> val;
   val.reserve(n_ent);    

   T b_val;
   TBranch *b_ref;    

   tree->SetBranchAddress(b_name, &b_val);    

   b_ref = tree->GetBranch(b_name);    

   for (int ii = 0; ii < n_ent; ii++) {

      b_ref->GetEntry(ii);
      val.push_back(b_val);

   }

   sort(val.begin(), val.end());    

   frac = 1.0 - frac;
   if (frac <= 0.0) {

      left  = val.front();
      right = val.back();
      return;

   }    

   Int_t n_skip = (Int_t)(0.5 * frac * n_ent);    

cout << "Skipping " << n_skip << " entries..." << endl; cout << "End index: " << n_ent - n_skip - 1 << endl;

   left = val[n_skip];
   right = val[n_ent - n_skip - 1];    

cout << "\nArray \"head\" :" << endl;
for (int ii = 0; ii < 20; ii++) {

   b_ref->GetEntry(ii);
   cout << "val[" << ii << "] = " << val[ii] << " ; GetEntry(" << ii << ") = " << b_val << endl;
}
   

cout << "\nArray \"tail\" :" << endl;
int jj = n_ent - n_skip - 1;
for (int ii = 0; ii < 20; ii++) {

   b_ref->GetEntry(jj);
   cout << "val[" << jj << "] = " << val[jj] << " ; GetEntry(" << jj << ") = " << b_val << endl;    jj--;
}

   tree->ResetBranchAddresses();    

   return;
}

int main()
{

   Float_t fleft, fright;
   Int_t ileft, iright;    

   TString fullfname;

   for (Int_t ii = 0; ii < 2; ii++) {

      fullfname = fname;
      fullfname += "_";   //"straight" fullfname = fname+"_"+ii+".root"; doesn't work
      fullfname += ii;
      fullfname += ".root";
      cout << "...making datafile " << fullfname << endl;
      make_datafile(fullfname);

   }    

   TChain *chain = new TChain("T");
   chain->Add((fullfname = fname) + "*.root");    

   FindInterval(chain, fbname, fleft, fright);    FindInterval(chain, ibname, ileft, iright);    

cout << "\nThe interval for \"" << fbname << "\": [" << fleft << "," << fright << "]"

     << "\nThe interval for \"" << ibname << "\": [" << ileft << "," << iright << "]\n" << endl;    

   char sLeft[30];
   char sRight[30];

   sprintf(sLeft, "%g", fleft);
   sprintf(sRight, "%g", fright);    

   TString Cuts;
   Cuts = "(" + (TString)fbname + ">=" + sLeft + ")&&(" + (TString)fbname + "<=" + sRight + ")";

   sprintf(sLeft, "%d", ileft);
   sprintf(sRight, "%d", iright);    

   Cuts += "&&(" + (TString)ibname + ">=" + sLeft + ")&&(" + (TString)ibname + "<=" + sRight + ")";    

cout << "Cuts string: " << Cuts.Data() << endl;

   TFile out_file("test_out_file.root", "RECREATE");    

cout << "New file recreated. Trying to CopyTree with cuts..."<< endl;

   TTree *newtree = chain->CopyTree(Cuts);

   newtree->SetName("NewTree_WingCuts");

cout << "Writing the new tree..." << endl;

   newtree->Write();
   out_file.Close();
}

[pcmspur5] ~/TreePlay > test_CopyTree
...making datafile testCopyTree_0.root
...making datafile testCopyTree_1.root
Skipping 500 entries...
End index: 19499

Array "head" :

val[0] = 6.56342 ; GetEntry(0) = 8.89772
val[1] = 6.60677 ; GetEntry(1) = 11.2028
val[2] = 6.73436 ; GetEntry(2) = 10.3929
val[3] = 6.74979 ; GetEntry(3) = 9.47582
val[4] = 6.80376 ; GetEntry(4) = 9.40583
val[5] = 6.81106 ; GetEntry(5) = 10.3499
val[6] = 6.82342 ; GetEntry(6) = 10.5525
val[7] = 6.83903 ; GetEntry(7) = 10.1094
val[8] = 6.85538 ; GetEntry(8) = 10.223
val[9] = 6.87955 ; GetEntry(9) = 10.2056
val[10] = 6.95277 ; GetEntry(10) = 9.66529
val[11] = 6.96276 ; GetEntry(11) = 9.64864
val[12] = 6.97322 ; GetEntry(12) = 9.72508
val[13] = 6.97927 ; GetEntry(13) = 10.9662
val[14] = 6.99377 ; GetEntry(14) = 8.93446
val[15] = 7.03579 ; GetEntry(15) = 9.54132
val[16] = 7.03654 ; GetEntry(16) = 8.49909
val[17] = 7.0802 ; GetEntry(17) = 8.79561
val[18] = 7.08616 ; GetEntry(18) = 9.28766
val[19] = 7.08897 ; GetEntry(19) = 10.2172

Array "tail" :

val[19499] = 11.5811 ; GetEntry(19499) = 10.2172
val[19498] = 11.5806 ; GetEntry(19498) = 10.2172
val[19497] = 11.5803 ; GetEntry(19497) = 10.2172
val[19496] = 11.5799 ; GetEntry(19496) = 10.2172
val[19495] = 11.5783 ; GetEntry(19495) = 10.2172
val[19494] = 11.578 ; GetEntry(19494) = 10.2172
val[19493] = 11.5778 ; GetEntry(19493) = 10.2172
val[19492] = 11.5755 ; GetEntry(19492) = 10.2172
val[19491] = 11.5747 ; GetEntry(19491) = 10.2172
val[19490] = 11.5735 ; GetEntry(19490) = 10.2172
val[19489] = 11.5733 ; GetEntry(19489) = 10.2172
val[19488] = 11.5731 ; GetEntry(19488) = 10.2172
val[19487] = 11.5724 ; GetEntry(19487) = 10.2172
val[19486] = 11.5721 ; GetEntry(19486) = 10.2172
val[19485] = 11.572 ; GetEntry(19485) = 10.2172
val[19484] = 11.5716 ; GetEntry(19484) = 10.2172
val[19483] = 11.5697 ; GetEntry(19483) = 10.2172
val[19482] = 11.5697 ; GetEntry(19482) = 10.2172
val[19481] = 11.5695 ; GetEntry(19481) = 10.2172
val[19480] = 11.5683 ; GetEntry(19480) = 10.2172
Skipping 500 entries...
End index: 19499

Array "head" :

val[0] = 0 ; GetEntry(0) = 0
val[1] = 1 ; GetEntry(1) = 1
val[2] = 2 ; GetEntry(2) = 2
val[3] = 3 ; GetEntry(3) = 3
val[4] = 4 ; GetEntry(4) = 4
val[5] = 5 ; GetEntry(5) = 5
val[6] = 6 ; GetEntry(6) = 6
val[7] = 7 ; GetEntry(7) = 7
val[8] = 8 ; GetEntry(8) = 8
val[9] = 9 ; GetEntry(9) = 9
val[10] = 10 ; GetEntry(10) = 10
val[11] = 11 ; GetEntry(11) = 11
val[12] = 12 ; GetEntry(12) = 12
val[13] = 13 ; GetEntry(13) = 13
val[14] = 14 ; GetEntry(14) = 14
val[15] = 15 ; GetEntry(15) = 15
val[16] = 16 ; GetEntry(16) = 16
val[17] = 17 ; GetEntry(17) = 17
val[18] = 18 ; GetEntry(18) = 18
val[19] = 19 ; GetEntry(19) = 19

Array "tail" :

val[19499] = 9999 ; GetEntry(19499) = 19
val[19498] = 9999 ; GetEntry(19498) = 19
val[19497] = 9999 ; GetEntry(19497) = 19
val[19496] = 9999 ; GetEntry(19496) = 19
val[19495] = 9999 ; GetEntry(19495) = 19
val[19494] = 9999 ; GetEntry(19494) = 19
val[19493] = 9999 ; GetEntry(19493) = 19
val[19492] = 9999 ; GetEntry(19492) = 19
val[19491] = 9999 ; GetEntry(19491) = 19
val[19490] = 9999 ; GetEntry(19490) = 19
val[19489] = 9999 ; GetEntry(19489) = 19
val[19488] = 9999 ; GetEntry(19488) = 19
val[19487] = 9999 ; GetEntry(19487) = 19
val[19486] = 9999 ; GetEntry(19486) = 19
val[19485] = 9999 ; GetEntry(19485) = 19
val[19484] = 9999 ; GetEntry(19484) = 19
val[19483] = 9999 ; GetEntry(19483) = 19
val[19482] = 9999 ; GetEntry(19482) = 19
val[19481] = 9999 ; GetEntry(19481) = 19
val[19480] = 9999 ; GetEntry(19480) = 19

The interval for "fbranch": [8.37443,11.5811] The interval for "ibranch": [500,9999]

Cuts string: (fbranch>=8.37443)&&(fbranch<=11.5811)&&(ibranch>=500)&&(ibranch<=9999) New file recreated. Trying to CopyTree with cuts...

Received on Wed Jun 07 2006 - 19:04:21 MEST

This archive was generated by hypermail 2.2.0 : Mon Jan 01 2007 - 16:31:58 MET