Updating a TTree

Hi Rooters,

I’m trying to write a simple code to filter an ntuple based on some criteria. What I do is basically reading a TTree from a file to memory, removing some entries from it, sorting it, then writing it back to the file. I end up with a file that is double the size of the original file.

TFile f("myfile.root", "READ");
gROOT->cd(0); // Forces a memory resident tree
TTree* t = (TTree*) f.Get("myTree");
TTree* newT = t->CopyTree("selection"); // Filtering
f.cd(0); // Prepare to write tree to file
newT->Write("", TObject::kOverwrite();
f.Close();

What am I doing wrong?

N.

Sorry, I meant:

TFile f("myfile.root", "UPDATE"); 

in the first line.

[quote] I end up with a file that is double the size of the original file. [/quote]This is the expected result since the original data is still in the file.

‘newT->Write("", TObject::kOverwrite();’ only overwrites the meta data (i.e. the TTree object itself describing the content) but does not overwrite nor delete the data.

What you ought do to is create a new file (that you can later rename to have the old filename):TFile f("myfile.root", "READ"); TTree* t = (TTree*) f.Get("myTree"); TFile out("selection.root","RECREATE"); TTree* newT = t->CopyTree("selection"); // Filtering out.Write(); f.Close();

Cheers,
Philippe.

Thanks, that helped.

However, now when I try to run a sorting function, I still get a double-sized file:

TTree* sortTree(TTree* t) {
  t->BuildIndex("run", "cycle");

  Int_t table[t->GetEntries()];
  int minRun   = (int) t->GetMinimum("run");
  int maxRun   = (int) t->GetMaximum("run");
  int minCycle = (int) t->GetMinimum("cycle");
  int maxCycle = (int) t->GetMaximum("cycle");
  int i=0;
  for (int iRun = minRun; iRun <= maxRun; ++iRun) {
    for (int iCycle = minCycle; iCycle <= maxCycle; ++iCycle) {
      int entry = t->GetEntryNumberWithIndex(iRun, iCycle);
      if (entry < 0) continue;
      table[i] = entry;
      ++i;
    }
  }

  TTree* sortedTree = t->CloneTree(0);
  //loop branch by branch on the input Tree and fill the output Tree
  TIter next(t->GetListOfBranches());
  TBranch *bin, *bout;
  while ((bin = (TBranch*)next())) {
    bout = sortedTree->GetBranch(bin->GetName());
    //cout << "processing branch: " << bin->GetName() << endl;
    //load all baskets of this branch in memory (for performance)
    bin->LoadBaskets();
    //loop on entries and fill output Tree

    for (int i=0; i< t->GetEntries(); ++i) {
      int entry = table[i];
      bin->GetEntry(entry);
      bout->Fill();
    }
    bin->DropBaskets();
    //sortedTree->AutoSave();
  }
  sortedTree->SetEntries(t->GetEntries());
  return sortedTree;
}


void testTree()
{
  TFile f("myFile.root", "READ");
  TTree *t = (TTree*) f.Get("tree");
  TFile fnew("myNewFile.root", "RECREATE");
  TTree* newT = t->CloneTree();
  newT = sortTree(newT);
  newT->Write();
  fnew.Close();
  f.Close();
}

Why are you calling CloneTree twice?
see below a version of your code that should work.

Rene

[code]void sortTree(TTree* t, TTree *sortedTree) {
t->BuildIndex(“run”, “cycle”);

Int_t table[t->GetEntries()];
int minRun = (int) t->GetMinimum(“run”);
int maxRun = (int) t->GetMaximum(“run”);
int minCycle = (int) t->GetMinimum(“cycle”);
int maxCycle = (int) t->GetMaximum(“cycle”);
int i=0;
for (int iRun = minRun; iRun <= maxRun; ++iRun) {
for (int iCycle = minCycle; iCycle <= maxCycle; ++iCycle) {
int entry = t->GetEntryNumberWithIndex(iRun, iCycle);
if (entry < 0) continue;
table[i] = entry;
++i;
}
}

//loop branch by branch on the input Tree and fill the output Tree
TIter next(t->GetListOfBranches());
TBranch *bin, bout;
while ((bin = (TBranch
)next())) {
bout = sortedTree->GetBranch(bin->GetName());
//cout << "processing branch: " << bin->GetName() << endl;
//load all baskets of this branch in memory (for performance)
bin->LoadBaskets();
//loop on entries and fill output Tree

for (int i=0; i< t->GetEntries(); ++i) {
  int entry = table[i];
  bin->GetEntry(entry);
  bout->Fill();
}
bin->DropBaskets();

}
sortedTree->SetEntries(t->GetEntries());
}

void testTree()
{
TFile f(“myFile.root”, “READ”);
TTree t = (TTree) f.Get(“tree”);
TFile fnew(“myNewFile.root”, “RECREATE”);
TTree* newT = t->CloneTree(0);
newT = sortTree(t,newT);
newT->AutoSave();
fnew.Close();
f.Close();
} [/code]

Thanks Rene, it worked well.

I was trying to use the CopyTree(“selection”) function to filter my tree. In this case, whenever it is called, a new copy of the tree is created in the file.

To avoid it, I do:

  TFile fin("myfile", "READ");
  TTree* t = (TTree*) fin.Get("mytree");
  TFile fout("myoutfile", "RECREATE");

  gROOT->cd(0); // Next objects will be read to memory
  TTree* ct = t-CopyTree("selection");
  fout.cd(0); // Next objects will be read to file
  ct->Write(0,TObject::kWriteDelete);

Is this the right way around it?

In your inner loop, you should do something like

for (int i=0; i< t->GetEntries(); ++i) { int entry = table[i]; bin->GetEntry(entry); if (some_condition_is_fulfilled) bout->Fill(); }

We show examples in the tutorials/tree/copytree1,2,3,4.C tutorials

Rene