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?