CopyTree (with a selection)

hi all

im using ROOT version 5.27/06b and im incurring in a problem when using the function TTree:CopyTree. i’ve wrote a simple program that reproduces the error:

// BEGIN

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


int main() {

  TFile* file = TFile::Open("TEST.root");
  TTree* originalTree = (TTree*)file->Get("reducedTree");
  TTree* selectedTree = originalTree->CopyTree("ptLept1>50.");

  return 0;

}

\\ END

you can find the test file in my afs public: /afs/cern.ch/user/p/pandolf/public/TEST.root

ive checked that “originalTree” exists and is correctly allocated. the line which invokes CopyTree gives the error:

Error in <TTree::Fill>: Failed filling branch:reducedTree.ePart, nbytes=-1, entry=2660
 This error is symptomatic of a Tree created as a memory-resident Tree
 Instead of doing:
    TTree *T = new TTree(...)
    TFile *f = new TFile(...)
 you should do:
    TFile *f = new TFile(...)
    TTree *T = new TTree(...)

(blablabla) and gives this error even if i put a dummy selection ("").

any ideas?

thanks
f

Well, if the problem persists, one thing you could do, is loop the first tree, read all the entries, and in the same loop only fill the second tree, if the entry fits the cut. Longer (not that much) but efficient.

Hi,

The problem is that you are copying the TTree into the (read-only) input file. If you intend on copying the TTree in memory you can do:

TFile* file = TFile::Open("TEST.root");
TTree* originalTree = (TTree*)file->Get("reducedTree");
gROOT->cd();
TTree* selectedTree = originalTree->CopyTree("ptLept1>50.");

You can also write into a new file:

TFile* file = TFile::Open("TEST.root");
TTree* originalTree = (TTree*)file->Get("reducedTree");
TFile* ouput = TFile::Open("TESTskim.root","RECREATE");
TTree* selectedTree = originalTree->CopyTree("ptLept1>50.");

Or you can simply use an EntryList which avoid the copy:

TFile* file = TFile::Open("TEST.root");
TTree* originalTree = (TTree*)file->Get("reducedTree");
gROOT->cd();
TEntryList *entry = new TEntryList("pt_list");
originalTree->Draw(">>pt_list","ptLept1>50.","goff");

depending on what you need to do with the copy/skim.

Cheers,
Philippe.

2 Likes

hi philippe

thanks a lot, your solution seems to work and the program i posted before indeed runs without errors.

now i’d like to do a slightly more complex thing, i.e. creating a chain out of the selected tree:

// -------------- BEGIN

#include "TTree.h"
#include "TChain.h"
#include "TFile.h"
#include "TROOT.h"


int main() {

  TFile* file = TFile::Open("TEST.root");
  TTree* originalTree = (TTree*)file->Get("reducedTree");
  gROOT->cd();
  TTree* selectedTree = originalTree->CopyTree("ptLept1>50.");

  TFile* outfile = new TFile("outfile.root", "RECREATE");
  outfile->cd();
  TChain* chain = new TChain("reducedTree");

  chain->Add((TChain*)selectedTree);
  chain->Write();
  outfile->Close();

  return 0;

}

// -------------- END

unfortunately this crashes (plain seg fault).

is what im doing simply wrong or not possible at all?

f

Why? The chain are designed to assemble after the fact a series of files together, there are very few reasons to store a chain.

This is the expected behavior of the code in your previous message.

chain->Add((TChain*)selectedTree);

‘selectedTree’ is not a TChain (TChain inherits from TTree ; not the reverse) and thus this call mis-use the object and thus segfault.

Cheers,
Philippe.