Revision 61b7f921373838caf90ad5753899b86058ed3762 authored by Unknown Author on 13 September 2004, 22:36:46 UTC, committed by Unknown Author on 13 September 2004, 22:36:46 UTC
git-svn-id: http://root.cern.ch/svn/root/tags/v4-00-08d@10025 27541ba8-7e3a-0410-8455-c3a389f83636
1 parent d0349f6
hadd.C
/*
NOTE: This macro is kept for back compatibility only.
Use instead the executable $ROOTSYS/bin/hadd
This macro will add histograms from a list of root files and write them
to a target root file. The target file is newly created and must not be
identical to one of the source files.
Author: Sven A. Schmidt, sven.schmidt@cern.ch
Date: 13.2.2001
This code is based on the hadd.C example by Rene Brun and Dirk Geppert,
which had a problem with directories more than one level deep.
(see macro hadd_old.C for this previous implementation).
The macro from Sven has been enhanced by
Anne-Sylvie Nicollerat <Anne-Sylvie.Nicollerat@cern.ch>
to automatically add Trees (via a chain of trees).
To use this macro, modify the file names in function hadd.
NB: This macro is provided as a tutorial.
Use $ROOTSYS/bin/hadd to merge many histogram files
*/
#include <string.h>
#include "TChain.h"
#include "TFile.h"
#include "TH1.h"
#include "TTree.h"
#include "TKey.h"
#include "Riostream.h"
TList *FileList;
TFile *Target;
void MergeRootfile( TDirectory *target, TList *sourcelist );
void hadd() {
// in an interactive ROOT session, edit the file names
// Target and FileList, then
// root > .L hadd.C
// root > hadd()
Target = TFile::Open( "result.root", "RECREATE" );
FileList = new TList();
FileList->Add( TFile::Open("hsimple1.root") );
FileList->Add( TFile::Open("hsimple2.root") );
MergeRootfile( Target, FileList );
}
void MergeRootfile( TDirectory *target, TList *sourcelist ) {
// cout << "Target path: " << target->GetPath() << endl;
TString path( (char*)strstr( target->GetPath(), ":" ) );
path.Remove( 0, 2 );
TFile *first_source = (TFile*)sourcelist->First();
first_source->cd( path );
TDirectory *current_sourcedir = gDirectory;
// loop over all keys in this directory
TChain *globChain = 0;
TIter nextkey( current_sourcedir->GetListOfKeys() );
TKey *key, *oldkey=0;
while ( (key = (TKey*)nextkey())) {
//keep only the highest cycle number for each key
if (oldkey && !strcmp(oldkey->GetName(),key->GetName())) continue;
// read object from first source file
first_source->cd( path );
TObject *obj = key->ReadObj();
if ( obj->IsA()->InheritsFrom( "TH1" ) ) {
// descendant of TH1 -> merge it
// cout << "Merging histogram " << obj->GetName() << endl;
TH1 *h1 = (TH1*)obj;
// loop over all source files and add the content of the
// correspondant histogram to the one pointed to by "h1"
TFile *nextsource = (TFile*)sourcelist->After( first_source );
while ( nextsource ) {
// make sure we are at the correct directory level by cd'ing to path
nextsource->cd( path );
TH1 *h2 = (TH1*)gDirectory->Get( h1->GetName() );
if ( h2 ) {
h1->Add( h2 );
delete h2; // don't know if this is necessary, i.e. if
// h2 is created by the call to gDirectory above.
}
nextsource = (TFile*)sourcelist->After( nextsource );
}
}
else if ( obj->IsA()->InheritsFrom( "TTree" ) ) {
// loop over all source files create a chain of Trees "globChain"
const char* obj_name= obj->GetName();
globChain = new TChain(obj_name);
globChain->Add(first_source->GetName());
TFile *nextsource = (TFile*)sourcelist->After( first_source );
// const char* file_name = nextsource->GetName();
// cout << "file name " << file_name << endl;
while ( nextsource ) {
globChain->Add(nextsource->GetName());
nextsource = (TFile*)sourcelist->After( nextsource );
}
} else if ( obj->IsA()->InheritsFrom( "TDirectory" ) ) {
// it's a subdirectory
cout << "Found subdirectory " << obj->GetName() << endl;
// create a new subdir of same name and title in the target file
target->cd();
TDirectory *newdir = target->mkdir( obj->GetName(), obj->GetTitle() );
// newdir is now the starting point of another round of merging
// newdir still knows its depth within the target file via
// GetPath(), so we can still figure out where we are in the recursion
MergeRootfile( newdir, sourcelist );
} else {
// object is of no type that we know or can handle
cout << "Unknown object type, name: "
<< obj->GetName() << " title: " << obj->GetTitle() << endl;
}
// now write the merged histogram (which is "in" obj) to the target file
// note that this will just store obj in the current directory level,
// which is not persistent until the complete directory itself is stored
// by "target->Write()" below
if ( obj ) {
target->cd();
//!!if the object is a tree, it is stored in globChain...
if(obj->IsA()->InheritsFrom( "TTree" ))
globChain->Merge(target->GetFile(),0,"keep");
else
obj->Write( key->GetName() );
}
} // while ( ( TKey *key = (TKey*)nextkey() ) )
// save modifications to target file
target->SaveSelf(kTRUE);
}
![swh spinner](/static/img/swh-spinner.gif)
Computing file changes ...