Getting events from one tree to add to another

Hey guys,
I’d like to iterate over the events of a tree and randomly add them to two other trees: tree1 and tree2. I am quite new to this so excuse me if some things are wrong. I iterate over some root files, get their respective trees. I then create two new trees and two root files. I am now confused as to how I would go about getting an event from the original tree and then adding them to either tree1 or tree2. It’s not so much the process of randomly sorting them, rather I am not sure of the syntax used to getting an event and adding it to a tree. this is what I have so far:

def test():
    
    bins = ["ybins","ptbins","y_ptbins"]

    for i in os.listdir(TUPLE_PATH):
        
        for bin_type in bins:
            ##DATASET1
            if not os.path.exists(TUPLE_PATH+i+"/random_data/dataset1/"+bin_type+"/"): 
                os.makedirs(TUPLE_PATH+i+"/random_data/dataset1/"+bin_type+"/")

            ##DATASET2
            if not os.path.exists(TUPLE_PATH+i+"/random_data/dataset1/"+bin_type+"/"): 
                os.makedirs(TUPLE_PATH+i+"/random_data/dataset1/"+bin_type+"/")

        
            for root_file in os.listdir(TUPLE_PATH+i+"/bins/"+bin_type+"/"):
                name = root_file

                read_file = ROOT.TFile(TUPLE_PATH+i+"/bins/"+bin_type+"/"+name, "READ")
                dataTree = read_file.Get("DecayTree")

                file1 = ROOT.TFile(TUPLE_PATH+i+"/random_data/dataset1/"+bin_type+"/"+name,"RECREATE")
                file2 = ROOT.TFile(TUPLE_PATH+i+"/random_data/dataset2/"+bin_type+"/"+name,"RECREATE")

                tree1 = ROOT.TTree("DecayTree","DecayTree")
                tree2 = ROOT.TTree("DecayTree","DecayTree")

Any help is appreciated

Hi @Diyon335,
and welcome to the ROOT forum!

You could either use TTree::AddClone or take advantage of RDataFrame with a Filter that selects random events and a Snapshot that writes out the output file.

Here is the AddClone versoin:

import ROOT

ROOT.RDataFrame(2).Define("x", "42").Snapshot("t", "f.root")

f = ROOT.TFile("f.root")
t = f.Get("t")

f2 = ROOT.TFile("f2.root", "recreate")
t2 = ROOT.TTree("t2", "t2")
t.AddClone(t2)

n = t.GetEntries()
for i in range(n):
    t.GetEntry(0)
    t2.Fill()
f2.Write()

Cheers,
Enrico

Hey @eguiraud

Thanks for your suggestion. I used a bit of what you’ve told me. Here’s my code:

name = root_file

                read_file = ROOT.TFile(TUPLE_PATH+i+"/bins/"+bin_type+"/"+name, "READ")
                dataTree = read_file.Get("DecayTree")

                file1 = ROOT.TFile.Open(TUPLE_PATH+i+"/random_data/dataset1/"+bin_type+"/"+name,"RECREATE")
                file2 = ROOT.TFile.Open(TUPLE_PATH+i+"/random_data/dataset2/"+bin_type+"/"+name,"RECREATE")

                tree1 = ROOT.TTree("DecayTree","DecayTree")
                tree2 = ROOT.TTree("DecayTree","DecayTree")

                tree1 = dataTree.CloneTree(0)
                tree2 = dataTree.CloneTree(0)

                n = dataTree.GetEntries()
                x = 0

                
                for entry in range(dataTree.GetEntries()):
                    #Progress 
                    if(x%1000==0):
                        j = (x / n)*100
                        sys.stdout.write('\r')
                        sys.stdout.write("{0}%".format(str(int(j))))
                        sys.stdout.flush()

                    if(x==n):
                        sys.stdout.write("\r")
                        sys.stdout.write("100%")
                        sys.stdout.flush()
                
                    #50% probability of being added to dataset1 or dataset2
                    if(random.rand()>0.5):
                        dataTree.GetEntry(entry)
                        tree1.Fill()
                        
                    else:
                        dataTree.GetEntry(entry)
                        tree2.Fill()


                    x+=1
                        

                file1.cd()
                tree1.Write()
                print("\nEvents in tree1: "+str(tree1.GetEntries()))
                file1.Close()
                
                file2.cd()
                tree2.Write()
                print("\nEvents in tree2: "+str(tree2.GetEntries()))
                file2.Close()

                read_file.Close()

                print("\nRandomisation finished for: "+name)

basically I iterate over the events of a tree (dataTree) from a root file (read_file). and then I add events from this tree to two other trees (tree1 and tree2). ignore the file paths and etc. It successfully writes the trees and splits the events. However, when I open one of these files with the new trees, I have the events, but they have no distribution, rather they are all centered at 0. And I do get this error:

Error in <TFile::ReadBuffer>: error reading all requested bytes from file Xic_ybin_2.0-2.5.root, got 0 of 8141

Any ideas why?

Regards,
Diyon

Hi,
I can’t tell what’s wrong, I think we need @pcanal to lend a hand.

Cheers,
Enrico

Trye

                file1 = ROOT.TFile.Open(TUPLE_PATH+i+"/random_data/dataset1/"+bin_type+"/"+name,"RECREATE")
                file2 = ROOT.TFile.Open(TUPLE_PATH+i+"/random_data/dataset2/"+bin_type+"/"+name,"RECREATE")

                tree1 = dataTree.CloneTree(0)
                tree1.SetDirectory(file1)
                tree2 = dataTree.CloneTree(0)
                tree2.SetDirectory(file2)

@pcanal, this worked perfectly! However, do you have any idea why each file has two decay trees?

The original root files do have two decay trees, however I ran the program to clone the tree and write it to a new file and then immediately stop the script. When I looked at it in a TBrowser, there was only one decay tree as needed. However, when I let the script run its full course and actually add entries to this new tree, it creates two decay trees in the new file. Any idea why?

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