Weird behavior of MakeSelector for a reduced tree

I am trying to use MakeSelector to reduce the size of a root file by applying several cuts to the tree variables and save the reduced tree. I found several old posts about it so I followed them easily except that the result I obtained is quite unexpected. Let’s say my original root tree has three variables inside x,y, and z.

In MySelector::Init I define the new file and I clone the original tree

newfile = new TFile("test_selector.root","RECREATE"); newtree = tree->CloneTree(0); newfile->Add(newtree);

In MySelector::Process I apply the selection criteria and I fill the new reduced tree

if (*x < 0) return kFALSE; newtree->Fill();

And, finally, in MySelector::Terminate I write the tree and delete the objects

newtree->Write(); delete newtree; newfile->Close();

Now, if I launch TBrowser and look at the variables, the number of entries is correct but for the new tree only the variable x has been filled. The other two are empty.
If I add a simple printout statement to the Process:

If (*x < 0) return kFALSE; std::cout << *x << " " << *y << " " << *z << std::endl; newtree->Fill();

the tree is filled correctly for all the three variables. What am I missing? I feel it’s something trivial that I don’t see.

Thanks a lot

Dear Giordano,

Could you post the full selector?
Which version of ROOT are you using?

G Ganis

Dear Ganis,
I’m using ROOT 6.06.02. I attached the source files and a small data file to reproduce the problem.

Thanks a lot
MySel.tar (60 KB)

Dear Giordano,

The reason is that, via the TTreeReader, the variables are only read when used.
I also suspect that the fact it works is some how by chance: TTreeReader is really done for reading trees.

In your case you are writing a new tree and you should as you were creating a new TTree, i.e. you should define the connection between the branches and the variables from where to get the values when filling.

Something like (to be tried):

  1. Add members for the variables in the class definition (MySelector.h)
     Float_t  ftxX;
     Float_t  ftxY;
     Float_t  ftxZ;
  1. In MySelector::Init

      a. Define fChain
             fChain = tree;
     b.  Connect to the branches
             // Entry values are read in ftxX, ftxY, ftxZ
             // Entry values read in ftxX, ftxY, ftxZ are transferred to the new tree
  1. In MySelector::Process
         if (*vtxZ < 0) return kFALSE;
         GetEntry(entry); // Read the full entry from original tree
         newtree->Fill(); // Write the full entry to target tree

G Ganis

Dear Ganis,
Thanks for your reply and for the explanation. I can actually do the same job with MakeClass without much efforts and with the results I want. I was looking at MakeSelector as an alternative solution that I remember using when I was a student long time ago :slight_smile:

Thanks a lot again

Hi Giordanio,

You should also be able to use MakeSelector if you request the ‘legacy’ version ( mytree->MakeSelector(selectorname, "=legacy); )