Root data file conversion 5.22->5.26

Hi,

I am a newbie to ROOT and I am just discovering its usage, so please excuse if this is obvious or already answered. I wonder, if there is a generic script for conversion of ROOT files generated by 5.22 to 5.26 version to benefit from improvements in file data format. I understand that one has to load all trees stored in the source file and clone them to a new file, and I have also read the example of copytree, but I am not sure how to do it in generic way(i.e. not knowing the number of trees and type of the class it represents). Could you please shed some light on me?

Thanks
Jiri Horky

see example below

Rene

[code]void reclust() {
// this script takes an input file generated with root5.22 or older
// and rewrite it using root5.27/04. The resulting file is expected
// to be much faster when reading.
//
//load the ATLAS classes from the fake library
//to automatically generate the fake lib aod.so in subdirectory aod, do
// TFile f = TFile::Open(“InDetRecAOD_old_1.root”);
// f->MakeProject(“aod”,"
",“recreate++”);

gSystem->Load(“aod/aod”);

TFile f = TFile::Open(“InDetRecAOD_old_1.root”);
T = (TTree
)f->Get(“CollectionTree”);
T->OptimizeBaskets(40000000,1,“d”);
TFile *f2 = new TFile(“atlas2.root”,“recreate”);
TTree *T2 = T->CloneTree(0);
Long64_t nentries = T->GetEntries();
for (Int_t i=0;i<nentries;i++) {
T->GetEntry(i);
T2->Fill();
}
T2->Write();
T2->Print();
}
[/code]

Hi Rene,

thank you for the example! I was missing the “MakeProject” function call. Because I don’t know apriori name of the trees, I end up doing something like this:

[code]void reclust(TString fileName) {
// this script takes an input file generated with root5.22 or older
// and rewrite it using root5.27/04. The resulting file is expected
// to be much faster when reading.
//
//load the ATLAS classes from the fake library
//to automatically generate the fake lib aod.so in subdirectory aod, do
TFile f = TFile::Open(fileName);
f->MakeProject(“aod”,"
",“recreate++”);

    gSystem->Load("aod/aod"); 

    //TFile *f = TFile::Open("InDetRecAOD_old_1.root");
    TKey * key;
    TIter next(f->GetListOfKeys());
    TString newFileName = "NEW." + fileName;

TFile *f2 = new TFile(newFileName, “recreate”);
while ((key = (TKey ) next())) {
if ( key->ReadObj()->InheritsFrom(“TTree”)) {
cout << key->GetName() << endl;
TTree * T = (TTree
)key->ReadObj();
T->OptimizeBaskets(40000000,1,“d”);
TTree *T2 = T->CloneTree(0);
Long64_t nentries = T->GetEntries();
for (Int_t i=0;i<nentries;i++) {
T->GetEntry(i);
T2->Fill();
}
T2->Write();
T2->Print();
}
}
f2->Close();
}[/code]

Which works, but create 260MB file instead of 180MB original one, which is a bit suspicious. Should I be worried about it, or it could be just a result of a new file format?

Original file:

root [8] f->ls()
TFile**         user10.PRAFULLAKBEHERA.mc09_7TeV.105004.pythia_ddiff.recon.ESDtoD3PD.e514_s764_s767_r1182_tid122125_00_15.6.7.5vtxfix.AANT1._00001.root
 TFile*         user10.PRAFULLAKBEHERA.mc09_7TeV.105004.pythia_ddiff.recon.ESDtoD3PD.e514_s764_s767_r1182_tid122125_00_15.6.7.5vtxfix.AANT1._00001.root
  KEY: AttributeListLayout      Schema;1
  KEY: TTree    MinBiasTree;4   MinBiasTree
  KEY: TTree    MinBiasTree;3   MinBiasTree
  KEY: TTree    CollectionTree;1        CollectionTree

Thanks Jiri

The new file should be at least 5 per cent smaller. It looks like your input Tree has a ridicilous value for AutoSave.
Before the loop I suggest to call
T2->SetAutoSave(1000000000);

Rene

Hi Rene,

thank you for the suggestion, but it wasn’t the case. The value of autosave was set to the exact same value you’ve proposed. I think that the problem is in the way the file is created and then reclusted. The original file contains these object:

TFile**         user10.PRAFULLAKBEHERA.mc09_7TeV.105004.pythia_ddiff.recon.ESDtoD3PD.e514_s764_s767_r1182_tid122125_00_15.6.7.5vtxfix.AANT1._00001.root
 TFile*         user10.PRAFULLAKBEHERA.mc09_7TeV.105004.pythia_ddiff.recon.ESDtoD3PD.e514_s764_s767_r1182_tid122125_00_15.6.7.5vtxfix.AANT1._00001.root
  KEY: AttributeListLayout      Schema;1
  KEY: TTree    MinBiasTree;4   MinBiasTree
  KEY: TTree    MinBiasTree;3   MinBiasTree
  KEY: TTree    CollectionTree;1        CollectionTree

It is, it contains two version of MinBiasTree, that are, in fact, the same. See below:

root [2] TTree * T4 = f->Get("MinBiasTree;4");
root [3] TTree * T3 = f->Get("MinBiasTree;3");
root [4] T4
(class TTree*)0x8548408
root [5] T3
(class TTree*)0x8548408
root [6] T3->GetEntriesFast()
(const Long64_t)3989
root [7] T4->GetEntriesFast()
(const Long64_t)3989

When reclusted, the tree was doubled, ie. stored twice. For what I want to achieve, it is sufficient to know that only newer version of the tree should be stored. However, just for my curiosity, how could one reclust such files?

BTW: I have also seen files where there were two versions of a tree, that translated to the same value of pointer, but with different number of entries in it. I suppose that one tree was a sub-tree of the another. Does ROOT support something like that?

Thanks
Jiri

OK this explains everything. You should import only one copy of a given name (highest cycle).

Rene