hadd.C
// example of macro to add two histogram files containing the same histograms
// (in a directory structure) or ntuples/trees.
// Histograms are added in memory as well as profile histograms.
// ntuples and trees are merged.
// The resulting histograms are saved into a new file.
// original implementation : Rene Brun
// extensions by Dirk Geppert to support files with sub-directories
//______________________________________________________________________
// give the list of files below. Last file must be a NULL string
const char *cfiles[] = {
"file1.root",
"file2.root",
""};
const char *outfile="file.root";
//______________________________________________________________________
TFile *fnew;
TList *flist;
TFile *afile, *file1;
TH1 *h1, *h2;
TTree *t1, *t2;
TObject *obj;
TKey *key;
void AddRecursive(TDirectory *root,TDirectory* node);
//______________________________________________________________________
//
//
//
//______________________________________________________________________
void hadd() {
// create the result file
fnew = new TFile(outfile,"RECREATE");
//create a support list for the input files
flist = new TList();
//open all input files and insert them in the list of files
Int_t nfiles = 0;
while (strlen(cfiles[nfiles])) {
afile = new TFile(cfiles[nfiles]);
flist->Add(afile);
nfiles++;
}
//Get a pointer to the first file
afile = file1 = (TFile*)flist->First();
AddRecursive(fnew,file1);
//fnew->ls();
fnew->Write();
fnew->Close();
delete fnew;
flist->Delete();
delete flist;
}
//______________________________________________________________________
//
//
//
//______________________________________________________________________
void AddRecursive(TDirectory *root,TDirectory* node) {
static TDirectory *dact;
TDirectory *dirsav;
//We create an iterator to loop on all objects(keys) of first file
TIter nextkey(node->GetListOfKeys());
while (key = (TKey*)nextkey()) {
node->cd();
obj = key->ReadObj();
if (obj->IsA()->InheritsFrom("TTree")) { //case of a TTree or TNtuple
t1 = (TTree*)obj;
// this part still to be implemented
// use TChain::Merge instead
} elseif(obj->IsA()->InheritsFrom("TH1")) { //case of TH1 or TProfile
h1 = (TH1*)obj;
afile = (TFile*)flist->After(file1);
while (afile) { //loop on all files starting at second file
char* base=strstr(root->GetPath(),":"); base+=2;
//printf("base=%s\n",base);
dirsav=gDirectory;
afile->cd(base);
h2 = (TH1*)gDirectory->Get(h1->GetName());
dirsav->cd();
if (h2) { // here we should check that we can add
//printf("adding histo %s to %s\n",h2->GetName(),h1->GetName());
h1->Add(h2);
delete h2;
}
afile = (TFile*)flist->After(afile);
}
} elseif(obj->IsA()->InheritsFrom("TDirectory")) { //case of TDirectory
// recursion
// printf("Found TDirectory name=%s title=%s\n",
// obj->GetName(),obj->GetTitle());
root->cd();
dact=root->mkdir(obj->GetName(),obj->GetTitle());
dact->cd();
TObject *objsave = obj;
TKey *keysave = key;
AddRecursive(dact,(TDirectory*)obj);
obj = objsave;
key = keysave;
} else { //another object
printf("anotherobjname=%s, title=%s\n",obj->GetName(),obj->GetTitle());
}
// write node object, modified or not into fnew
if (obj) {
root->cd();
obj->Write(key->GetName());
delete obj;
obj=NULL;
}
}
root->cd();
}