Copy branch with cuts

I want to take an existing branch in an existing tree, perform cuts, then save the now reduced branch to a new tree in a new file, and I’d prefer to do it without setting branch addresses. (I have existing code that uses TCut and I’d rather not move everything over into if statements.)

TTree::CopyTree() seems the best way to do this as it lets you specify a selection. However, the examples the documentation suggests (1) do not actually use CopyTree, (2) involve setting branch addresses, and (3) do not actually work if I just try to run them. I tried following [url]Copy tree from one file to another (no changes in between) but this results in an empty tree. I have also tried[code] TCut cmid = “[some cuts]”;
TFile *oldfile = new TFile("[path to old file]",“READ”);
cout<<“oldfile opened”<<endl;
TTree oldtree = (TTree)oldfile->Get(“Lb2JpsiLTree/mytree”);
cout<<“oldtree gotten”<<endl;
TFile *newfile = new TFile("[path]/test.root",“recreate”);
cout<<“newfile recreated”<<endl;
TTree *newtree = oldtree->CopyTree(cmid);
cout<<“newtree declared as copy of oldtree”<<endl;
newtree->GetBranch(“Bs_LOKI_MASS_JpsiConstr”)->SetFile("[path]/test_small.root");
cout<<“separate file declared for Bs_LOKI_MASS_JpsiConstr”<<endl;
newtree->CopyEntries(oldtree);
cout<<“entries copied”<<endl;

newtree->Print();
cout<<“newtree printed”<<endl;
newfile->Write();
cout<<“newfile written”<<endl;
delete oldfile;
delete newfile;
cout<<“files deleted”<<endl<<“done”<<endl;
[/code]

but test_small.root doesn’t have any trees inside, and when I trymytree->Draw("Bs_LOKI_MASS_JpsiConstr")with test.root, I end up with an enormous error output. The beginning is included below. Advice?

libGL error: No matching fbConfigs or visuals found
libGL error: failed to load driver: swrast
Info in TCanvas::MakeDefCanvas: created default TCanvas with name c1
Warning in TFile::Init: no StreamerInfo found in /afs/cern.ch/work/m/mwilkins/Lb2JpsiLtr/data/test_small.root therefore preventing schema evolution when reading this file.
Error in TBasket::Streamer: The value of fKeylen is incorrect (-30713) ; trying to recover by setting it to zero
Error in TBasket::Streamer: The value of fNbytes is incorrect (-481200332) ; trying to recover by setting it to zero
Error in TBranch::GetBasket: File: /afs/cern.ch/work/m/mwilkins/Lb2JpsiLtr/data/test_small.root at byte:-1070189243, branch:Bs_LOKI_MASS_JpsiConstr, entry:0, badread=1, nerrors=1, basketnumber=0
Error in TBasket::Streamer: The value of fKeylen is incorrect (-30713) ; trying to recover by setting it to zero
Error in TBasket::Streamer: The value of fNbytes is incorrect (-481200332) ; trying to recover by setting it to zero
Error in TBranch::GetBasket: File: /afs/cern.ch/work/m/mwilkins/Lb2JpsiLtr/data/test_small.root at byte:-1070189243, branch:Bs_LOKI_MASS_JpsiConstr, entry:1, badread=1, nerrors=2, basketnumber=0
Error in TBasket::Streamer: The value of fKeylen is incorrect (-30713) ; trying to recover by setting it to zero
Error in TBasket::Streamer: The value of fNbytes is incorrect (-481200332) ; trying to recover by setting it to zero
Error in TBranch::GetBasket: File: /afs/cern.ch/work/m/mwilkins/Lb2JpsiLtr/data/test_small.root at byte:-1070189243, branch:Bs_LOKI_MASS_JpsiConstr, entry:2, badread=1, nerrors=3, basketnumber=0
Error in TBasket::Streamer: The value of fKeylen is incorrect (-30713) ; trying to recover by setting it to zero
Error in TBasket::Streamer: The value of fNbytes is incorrect (-481200332) ; trying to recover by setting it to zero
Error in TBranch::GetBasket: File: /afs/cern.ch/work/m/mwilkins/Lb2JpsiLtr/data/test_small.root at byte:-1070189243, branch:Bs_LOKI_MASS_JpsiConstr, entry:3, badread=1, nerrors=4, basketnumber=0
Error in TBasket::Streamer: The value of fKeylen is incorrect (-30713) ; trying to recover by setting it to zero
Error in TBasket::Streamer: The value of fNbytes is incorrect (-481200332) ; trying to recover by setting it to zero
Error in TBranch::GetBasket: File: /afs/cern.ch/work/m/mwilkins/Lb2JpsiLtr/data/test_small.root at byte:-1070189243, branch:Bs_LOKI_MASS_JpsiConstr, entry:4, badread=1, nerrors=5, basketnumber=0
Error in TBasket::Streamer: The value of fKeylen is incorrect (-30713) ; trying to recover by setting it to zero
Error in TBasket::Streamer: The value of fNbytes is incorrect (-481200332) ; trying to recover by setting it to zero
Error in TBranch::GetBasket: File: /afs/cern.ch/work/m/mwilkins/Lb2JpsiLtr/data/test_small.root at byte:-1070189243, branch:Bs_LOKI_MASS_JpsiConstr, entry:5, badread=1, nerrors=6, basketnumber=0
Error in TBasket::Streamer: The value of fKeylen is incorrect (-30713) ; trying to recover by setting it to zero
Error in TBasket::Streamer: The value of fNbytes is incorrect (-481200332) ; trying to recover by setting it to zero
Error in TBranch::GetBasket: File: /afs/cern.ch/work/m/mwilkins/Lb2JpsiLtr/data/test_small.root at byte:-1070189243, branch:Bs_LOKI_MASS_JpsiConstr, entry:6, badread=1, nerrors=7, basketnumber=0
Error in TBasket::Streamer: The value of fKeylen is incorrect (-30713) ; trying to recover by setting it to zero
Error in TBasket::Streamer: The value of fNbytes is incorrect (-481200332) ; trying to recover by setting it to zero
Error in TBranch::GetBasket: File: /afs/cern.ch/work/m/mwilkins/Lb2JpsiLtr/data/test_small.root at byte:-1070189243, branch:Bs_LOKI_MASS_JpsiConstr, entry:7, badread=1, nerrors=8, basketnumber=0
Error in TBasket::Streamer: The value of fKeylen is incorrect (-30713) ; trying to recover by setting it to zero
Error in TBasket::Streamer: The value of fNbytes is incorrect (-481200332) ; trying to recover by setting it to zero
Error in TBranch::GetBasket: File: /afs/cern.ch/work/m/mwilkins/Lb2JpsiLtr/data/test_small.root at byte:-1070189243, branch:Bs_LOKI_MASS_JpsiConstr, entry:8, badread=1, nerrors=9, basketnumber=0
Error in TBasket::Streamer: The value of fKeylen is incorrect (-30713) ; trying to recover by setting it to zero
Error in TBasket::Streamer: The value of fNbytes is incorrect (-481200332) ; trying to recover by setting it to zero
file probably overwritten: stopping reporting error messages
Error in TBranch::GetBasket: File: /afs/cern.ch/work/m/mwilkins/Lb2JpsiLtr/data/test_small.root at byte:-1070189243, branch:Bs_LOKI_MASS_JpsiConstr, entry:9, badread=1, nerrors=10, basketnumber=0
Error in TBasket::Streamer: The value of fKeylen is incorrect (-30713) ; trying to recover by setting it to zero

Hi,

The file is broken. You can try with TFile::Recover() - but your mileage might vary…

Cheers, Axel.

Yeah, recover did not work. Is this just a random error or is something about my code causing this?

After a little more investigating, it seems the issue is the line newtree->GetBranch("Bs_LOKI_MASS_JpsiConstr")->SetFile("[path to file]/test_small.root");The other branches appear to work just fine, so I could take out this line, then copy the newly cut branch into another file by its lonesome. However, none of my cuts seem to have actually been applied.

I don’t understand this at all. It seems like CloneTree (https://root.cern.ch/doc/master/TTree_8cxx_source.html#l02992) includes the CopyEntries command, and CopyTree (https://root.cern.ch/doc/master/TTreePlayer_8cxx_source.html#l00181) includes CloneTree, so I don’t get why I end up with an empty tree unless I include the CopyEntries command. I also don’t understand what the selection input for CopyTree is doing if I’m not actually ending up with any cuts; is the call to CopyEntries overwriting the entries with cuts?

Please advise.

I believe I’ve found a solution that works. First, TFile *oldfile = new TFile("[path to file]/subLimDVNtuples.root","READ"); TTree *oldtree = (TTree*)oldfile->Get("Lb2JpsiLTree/mytree"); TFile *newfile = new TFile("[path to file]/test_temp.root","recreate"); TTree *newtree = oldtree->CopyTree("cut"); newtree->Print(); newfile->Write(); delete oldfile; delete newfile; This creates a copy of the entire old tree with cuts applied in a new file. Then, TFile *cutfile = new TFile("[path to file]/test_temp.root","read"); TTree *cuttree = (TTree*)cutfile->Get("mytree"); cuttree->SetBranchStatus("*",0); cuttree->SetBranchStatus("Bs_LOKI_MASS_JpsiConstr",1); TFile *newfile = new TFile("[path to file]/test.root","recreate"); TTree *newtree = cuttree->CopyTree(""); newtree->Print(); newfile->Write(); cuttree->SetBranchStatus("*",1); delete cutfile; delete newfile; This opens the copied tree and copies only the selected branch into another new file.

I don’t like this solution since it involves an intermediate file and copying a lot of unnecessary branches, making it pretty slow, plus it’s in 2 parts right now, but it does give me the result I want. I’ll probably make some attempts at streamlining it, but if anyone has suggestions, I’d love to hear them.

1 Like

newtree->GetBranch("Bs_LOKI_MASS_JpsiConstr")->SetFile("[path]/test_small.root");The resulting file (test_small.root) can not be used on its own and still need the main file (test.root).

TTree *newtree = oldtree->CopyTree(cmid); .... newtree->CopyEntries(oldtree);This should lead to all entries being written (by the 2nd call) and all the entries passing the cut being written twice (an additional time by the 1st call).

Cheers,
Philippe.

Hi,

Unfortunately, there is no pre-canned routine (like CopyTree) that let you clone a tree, trimming and using trimmer branch for a selection.

To speed things up (possibly close to the max since you have no overlap between the two set of branches), you can try:

[code]TFile *oldfile = new TFile("[path to file]/subLimDVNtuples.root",“READ”);
TTree oldtree = (TTree)oldfile->Get(“Lb2JpsiLTree/mytree”);
TEntryList *elist = new TEntryList(“sel_list”);
oldtree->Draw(">>sel_list",“cut”,“entrylist”); // Will read only the branch listed in the cut.
oldtree->SetEntryList(elist);

oldtree->SetBranchStatus("*",0);
oldtree->SetBranchStatus(“Bs_LOKI_MASS_JpsiConstr”,1);
TFile *newfile = new TFile("[path to file]/test.root",“recreate”);
TTree newtree = cuttree->CopyTree("");
newtree->Print();
newfile->Write();
cuttree->SetBranchStatus("
",1);
delete oldtree;
delete newfile;[/code]

Cheers,
Philippe.