Copy tree entry-by-entry in PyROOT

Dear experts,

I have problem copying a tree entry-by-entry in PyROOT. I think the task itself is rather simple:

  • Load a tree w/ several branches from file
  • Go through all entries and put some of them in a similar tree in an output file
  • In the same tree, add another branch that is filled in the loop above

It’s somewhat like
https://root.cern.ch/root/html/tutorials/tree/copytree3.C.html
but I cannot manage to set all branch addresses correctly. This is what I would do in C++.

Is there an easier way, e.g. can I tell PyROOT to write all branches w/o setting each branch?
If not, how can I generally use SetBranchAddress() for all branches in the tree without knowing the branches before?

Many thanks
Rudiger

PS: Underlying root is root5

When using CloneTree, you need to set the branch address of only the branch you need to use the data from (for example to make a selection).

Cheers,
Philippe.

1 Like

Hi,

thanks, that works for one tree. What do I have to do when I want to copy entries from several trees & files?

What I would like to do is the following (it is not working the way it is):

    firstTree = True
    for fileName in files:
        fileH  = ROOT.TFile.Open(fileName)
        inTree = fileH.Get('myTree')

        if firstTree:
          ofile   = ROOT.TFile('./test.root', 'update')
          outTree = inTree.CloneTree(0)
          firstTree = False

        # Add events to tree
        for iSample in listSamples:
          inTree.GetEntry(iSample)
          outTree.Fill()

    outTree.AutoSave()
    ofile.Close()

So I would like to take several trees from different files and add some of their events to an output tree in the same format. I also want to add a new branch, but this should be independent of my problem here.

The above code is working for the first tree. Then I guess the associated branches addresses get invalid as I load a new input file. This makes sense, but how to solve my problem? In principle, I would have to reassociate all the branches of the inTree to the outTree. Maybe there is a better solution?

Thanks
Rudiger

Instead of manipulating each TTree individually, use a TChain :slight_smile:

OK, thanks!
Actually, using a chain is simplifying a lot in my code :slight_smile:
One thing is still open for me: I can only use CloneTree(0) if I create the outTree from scratch.
What do I have to do if outTree already exists and I want to update the tree in the same way as before from the input chain?

Thanks!
Rudiger

Hi Rudiger,

For this use something along the line of:

  // Make sure the first TTree is loaded and the address are set.
  inputChain->LoadTree(0);

   // Note: For a tree we get the this pointer, for
   //       a chain we get the chain's current tree.
   TTree* thistree = inputChain->GetTree();

   // The clone should not delete any objects allocated by SetAddress().
   TObjArray* branches = newtree->GetListOfBranches();
   Int_t nb = branches->GetEntriesFast();
   for (Int_t i = 0; i < nb; ++i) {
      TBranch* br = (TBranch*) branches->UncheckedAt(i);
      if (br->InheritsFrom(TBranchElement::Class())) {
         ((TBranchElement*) br)->ResetDeleteObject();
      }
   }

   // Add the new tree to the list of clones so that
   // we can later inform it of changes to branch addresses.
   thistree->AddClone(newtree);
   if (thistree != this) {
      // In case this object is a TChain, add the clone
      // also to the TChain's list of clones.
      inputChain->AddClone(newtree);
   }
      
   // Copy branch addresses.
   inputChain->CopyAddresses(newtree);

Cheers,
Philippe.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.