https://github.com/root-project/root
Tip revision: 1627b96bc05467cd958bf7dc1f8161ffc61f686a authored by Unknown Author on 06 February 2002, 11:51:08 UTC
This commit was manufactured by cvs2svn to create tag 'v3-01-05'.
This commit was manufactured by cvs2svn to create tag 'v3-01-05'.
Tip revision: 1627b96
hadd.C
/*
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.
Syntax:
hist_add targetfile source1 source2 ...
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).
I have tested this macro on rootfiles with one and two dimensional
histograms, and two levels of subdirectories. Feel free to send comments
or bug reports to me.
*/
#include <TROOT.h>
#include "TFile.h"
#include "TH1.h"
#include "TTree.h"
#include "TKey.h"
#include <string.h>
#include <iostream.h>
TROOT Root( "hist_add", "Histogram Merger" );
TList *FileList;
TFile *Target;
void MergeRootfile( TDirectory *target, TList *sourcelist );
int main( int argc, char **argv ) {
FileList = new TList();
if ( argc < 4 ) {
cout << "Usage: " << argv[0] << " <target> <source1> <source2> ...\n";
cout << "supply at least two source files for this to make sense... ;-)\n";
exit( -1 );
}
cout << "Target file: " << argv[1] << endl;
Target = TFile::Open( argv[1], "RECREATE" );
for ( int i = 2; i < argc; i++ ) {
cout << "Source file " << i-1 << ": " << argv[i] << endl;
FileList->Add( TFile::Open( argv[i] ) );
}
MergeRootfile( Target, FileList );
}
// Merge all files from sourcelist into the target directory.
// The directory level (depth) is determined by the target directory's
// current level
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
TIter nextkey( current_sourcedir->GetListOfKeys() );
while ( TKey *key = (TKey*)nextkey() ) {
// 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( "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();
obj->Write( key->GetName() );
}
} // while ( ( TKey *key = (TKey*)nextkey() ) )
// save modifications to target file
target->Write();
}