Replace entries in a single branch only of an existing tree with several branches based on an if condition

Hi everyone,

I have a set of ROOT files, each containing a tree named “Tree” with around 250 branches. The files follow a naming pattern like “File_001.root”, “File_002.root”, and so on. The tree “Tree” has multiple branches as said above, including a Double_t branch named "branchX" and a Double_t array branch named “branchY[11][11]”.

I want to process each file and update the entry in “branchX” based on a specific condition involving “branchY[11][11]”. Although the exact condition is not detailed here, let’s assume it’s defined by the following:

 bool pass = condition;
 if (pass) {
      branchX = -9999.;
}

I want to set the value of “branchX” to -9999. if the condition is met. I am open to modifying the existing file or creating a new file with the same or different tree name, as long as all other branches and related entries in the new tree remain the same as in the original tree.

Let me know how I should proceed to achieve this. Currently, i’m doing something like the following (which isn’t working):

void updateTreeData() {
    
    for (int i = 1; i <= 10; i++) {

        TString filename = Form("/path/to/data/File_%03d.root", i);
        TFile *inputFile = TFile::Open(filename);
        TTree *tree = (TTree*)inputFile->Get("Tree");

        TString newFilename = Form("/path/to/data/File_%03d_updated.root", i);
        TFile *newFile = new TFile(newFilename, "RECREATE");

        TTree *newTree = tree->CloneTree(0);

       
        Double_t branchX;
        Double_t branchY[11][11];
        
        tree->SetBranchAddress("branchX", &branchX);  
        tree->SetBranchAddress("branchY", branchY); 

        newTree->Branch("branchX", &branchX, "branchX/D");
        newTree->Branch("branchY", branchY, "branchY[11][11]/D");

        Long64_t nentries = tree->GetEntries();

        for (Long64_t j = 0; j < nentries; j++) {
            tree->GetEntry(j);

            // Apply conditions to modify dummyValue
            bool pass = condition;

            if (pass) {
                branchX = -9999.;  
            }
            newTree->Fill();
        }
        newFile->cd();
        newTree->Write();
        newFile->Close();
        inputFile->Close();
    }
}

Thanks!!

So, once the tree is written, the existing entries cannot be changed or replaced. Is that correct?

Correct a TTree is a write-once, read-many time structure.

As summarized here Changing the values in the branch - #2 by Wile_E_Coyote
Your 4 options are:

  1. You could apply your “fixes” when you actually analyze the data (e.g., define some alias “corrected_branch = original_branch - corerection_value” and then use the “corrected_branch” in the analysis).
    
  2. You could “copy” your tree to another file, modifying its entries on the fly.
    
  3. You could create a “friend tree” with new branches.
    
  4. You could add new branches to the existing tree.
    

Where option 3. (using a friend tree) is the most commonly used when option 1. is not possible.

Your example implements option 2. Albeit you should change the name of the branch (and/or first remove the old branches from the newTree.

Your example can implement option 4 by creating an empty 'newTreerather than cloning the existing tree (and then use the result by callingTTree::AddFriend`).

Note that you can optionally writing the newTree in the same file (open the old file with the UPDATE option) and make the friendship ‘permanent’ (by updating ‘just’ the meta-data of the old TTree).