Copy TBranch from one to another directory

Hi

In one file, I have two dirs and each one has a branch named the same. What I want, is to get the TBranch from dir1 and replace it over the dir2. I ve tried something similar to the copytree example but without much success. So in the code below, the “genweight” is the commonly existing branch, which I want to copy from the “initroottree” to the makerootree dir… How can I do this ?

[code]
//Get old file, old tree and set top branch address
TFile oldfile = new TFile(“output.root”);
TTree oldtree = (TTree)oldfile->Get(“makeroottree/AC1B”);
TTree oldtree2 = (TTree)oldfile->Get(“initroottree/AC1B”);
oldtree->SetBranchStatus("
",1);
oldtree->SetBranchStatus(“genweight”,0);

//Create a new file + a clone of old tree in new file
TFile *newfile = new TFile(“small.root”,“recreate”);
newfile->mkdir(“makeroottree”);
newfile->cd(“makeroottree”);
//oldtree2->AddFriend(oldtree);
TTree *newtree = oldtree->CloneTree();
//TTree *newtree2 = oldtree2->CloneTree();
newtree= oldtree2->CloneTree();
//newtree->Print();
newfile->Write();
delete oldfile;
delete newfile;[/code]

Hi,

could you share the macro you tried as well as the files?
Which version of ROOT are you using?

Danilo

Hi Danilo

The code is the one I pasted in my first post (slightly different from the copytree.C example). I also attach a small .root file to be used as input
output.root (79.4 KB)

Hi,

The usual way to handle this is to use a Friend tree rather than rewrite the TTree. Nonetheless the way to strickly do want you want (assume genweight is a double) is:[code]//Get old file, old tree and set top branch address
TFile *oldfile = new TFile(“output.root”);
TTree oldtree = (TTree)oldfile->Get(“makeroottree/AC1B”);
TTree oldtree2 = (TTree)oldfile->Get(“initroottree/AC1B”);
//Create a new file + a clone of old tree in new file
TFile *newfile = new TFile(“small.root”,“recreate”);
newfile->mkdir(“makeroottree”);
newfile->cd(“makeroottree”);
//oldtree2->AddFriend(oldtree);
TTree *newtree = oldtree->CloneTree(-1);

double genweight;
oldtree2->SetBranchAddress(“genweight”,&genweight);
newtree->SetBranchAddress(“genweight”,&genweight);

for(Long64_t entry = 0; entry < oldtree->GetEntry(entry); ++entry) {
oldtree->GetEntry(entry);
oldtree2->GetEntry(entry); // This assume the entries in oldtree and oldtree2 are aligned
newtree->Fill();
}
newfile->Write();
delete oldfile;
delete newfile;
[/code]

Cheers,
Philippe.

Thanks - Another approach I found is to simply fill a histogram from the initroottree and just save it in the new.root. Could you please point me to how to read the tree with the highest cycle in a given TKEY ? I have two branches with “;1” “;2” or “;2” “;3” and I want to take the one with the highest key - I am trying something like this [*] but I still always get the branch with the lower cycle.

Thanks in advance

[code] oldfile->cd();
TDirectory *current_sourcedir = gDirectory;
//gain time, do not add the objects in the list in memory
Bool_t status = TH1::AddDirectoryStatus ();
TH1::AddDirectory (kFALSE);
// loop over all keys in this directory
TChain *globChain = 0;
//TIter nextkey (current_sourcedir->GetListOfKeys ());
TIter nextkey (((TDirectory *) current_sourcedir->Get (“makeroottree”))->GetListOfKeys ());
TKey *key, *oldkey = 0;
while ((key = (TKey *) nextkey ())) {

    if (oldkey && !strcmp (oldkey->GetName (), key->GetName ()))

    continue;
oldtree = (TTree*)oldfile->Get("makeroottree/AC1B");

    TObject *obj = key->ReadObj ();
    cout<<" obj "<<key->GetName ()<<"  "<<endl;


    }

[/code]

Hi,

This is the default behavior of GetObject:dir = ((TDirectory *) current_sourcedir->Get ("makeroottree"); TTree *tree; dir->GetObject("treename",tree"); TH1F *hist; dir->GetObject("histoname",hist);

Cheers,
Philippe.

Hi Philippe

Sure, but still I want to read the “treename” with the latest cycle number ie

if

"makeroottree/treename;2" "makeroottree/treename;1"

I want to get the “;2” one - and in advance if it is “2” the highest or maybe “3” … so, the default behaviour that you are giving me takes the very first one ie the “1”…

Hi,

[quote] so, the default behaviour that you are giving me takes the very first one ie the “1”…[/quote]This should not be the behavior, GetObject should return the highest cycle. If this is the case for your use case, please let us know how to reproduce it.

Cheers,
Philippe.

Hi Philippe

Thanks for your help; Please use this file as input

desy.de/~alkaloge/output.root

and this is the full code I use

[code]#include <TH2.h>
#include <TH1.h>
#include <TFile.h>
#include <TStyle.h>
#include <TCanvas.h>
#include <TKey.h>
#include <TDirectory.h>

using namespace std;
void mine2()
{

TString fin = “output.root”;
TFile *oldfile = new TFile(fin,“read”);

oldfile->cd();

TDirectory *current_sourcedir = gDirectory;
TDirectory *dir = ( (TDirectory *) current_sourcedir->Get ("makeroottree"));
TTree *tree; dir->GetObject("AC1B",tree);

TFile *newfile = new TFile("small.root","recreate");
tree ->CloneTree();

}[/code]

It seems to me that you need to search for “cycle” and/or “namecycle”, for example, in the “ROOT User’s Guide” -> “Input/Output” chapter.
BTW. If you write an object with a specific “name” to a file, and no object with such a “name” exists in this file yet, then it’s newly assigned “cycle” will be “1” (so that you will see “name;1”, when listing the new contents of this file).

Hi,

The file has only one cycle for each keys:root [1] gFile->ls() TFile** /Users/pcanal/Downloads/cycles.root TFile* /Users/pcanal/Downloads/cycles.root KEY: TDirectoryFile initroottree;1 initroottree KEY: TDirectoryFile makeroottree;1 makeroottreeIn order for us to provide you the best help possible, please provide exactly why you try, the result you see and how it differs from your expectation.

Cheers,
Philippe.

Hi Philippe

I use as input the output.root If you open it, you will see that it has two AC1B branches under makeroottree dir.

   TDirectoryFile*		makeroottree	makeroottree
   OBJ: TTree	AC1B	AC1B : 0 at: 0x383b450
   OBJ: TTree	AC1B	AC1B : 0 at: 0x4245360
   KEY: TTree	AC1B;3	AC1B
   KEY: TTree	AC1B;2	AC1B

if I run the code I pasted in my message at 14:46 , you will see that the small.root file has indeed a makeroottree/AC1B but if you open any leaf, you will see that has it has ~35k entries like the “AC1B;2” and not 50k like the “AC1B;3”. So, what I asked is how to get the branch with the “latest” branch AC1B (probably I confused the “cycle” with namecycle"

Looking here as you suggested

root.cern.ch/root/html534/guide … ree-blocks

but I cannot find how to do this…

Thanks for your patience

root [0] TFile *_file0 = TFile::Open("output.root"); root [1] gFile->ls() TFile** /Users/pcanal/Downloads/output.root TFile* /Users/pcanal/Downloads/output.root KEY: TDirectoryFile initroottree;1 initroottree KEY: TDirectoryFile makeroottree;1 makeroottree root [2] gFile->cd("makeroottree") (Bool_t) true root [3] gFile->ls() TFile** /Users/pcanal/Downloads/output.root TFile* /Users/pcanal/Downloads/output.root TDirectoryFile* makeroottree makeroottree KEY: TTree AC1B;3 AC1B KEY: TTree AC1B;2 AC1B KEY: TH1D nEvents;1 nEvents KEY: TTree AC1Blumi;1 AC1Blumi KEY: TTree AC1Brun;1 AC1Brun KEY: TTree CircJetID_puv2;1 Circlar Tree for categorization KEY: TDirectoryFile initroottree;1 initroottree KEY: TDirectoryFile makeroottree;1 makeroottree root [4] TTree *tree; gDirectory->GetObject("AC1B",tree) root [5] tree->GetEntries() (Long64_t) 50000

Hi,

Your script is missing a file line:newfile->Write();i.e. the file set of data is not written to the file (yet).

Cheers,
Philippe.

Hi Philippe

so, doing

tree ->CloneTree(); cout<<tree->GetEntries()<<endl;
gives indeed “50000” in the cout, but in the root file the tree with the 35k events is saved.

doing

cout<<tree->GetEntries()<<endl; newfile->Write();

does not save any tree

and doing

tree ->CloneTree(); cout<<tree->GetEntries()<<endl; newfile->Write();

saves BOTH trees in the new .root file…I guess this is not the expected behaviour - Forgot to mention that this is in 6.02

Hi,

You of course need both the CloneTree (to ask for the cloning of the tree) and the newfile->Write (to finalize the writing of the file) [Please re-read the I/O and TTree chapter in the User’s guide for more details).

And yes, this will (in your case) result in 2 cycles on the file. The data is not duplicated, just the meta-data (the number of entries), the cycle is backup information in case something goes wrong in the middle of the process.

Cheers,
Philippe.

[code]include <TH2.h>
#include <TH1.h>
#include <TFile.h>
#include <TStyle.h>
#include <TCanvas.h>
#include <TKey.h>
#include <TDirectory.h>

using namespace std;
void mine2()
{

TString fin = “output.root”;
TFile *oldfile = new TFile(fin,“read”);

oldfile->cd();

TDirectory *current_sourcedir = gDirectory;
TDirectory *dir = ( (TDirectory *) current_sourcedir->Get ("makeroottree"));
TTree *tree; dir->GetObject("AC1B",tree);

TFile *newfile = new TFile("small.root","recreate");
tree ->CloneTree();
newfile->Write();

}[/code]