hadd.C

Go to the documentation of this file.
00001 //macro to add histogram files
00002 //NOTE: This macro is kept for back compatibility only.
00003 //Use instead the executable $ROOTSYS/bin/hadd
00004 //
00005 //This macro will add histograms from a list of root files and write them
00006 //to a target root file. The target file is newly created and must not be
00007 //identical to one of the source files.
00008 //
00009 //Author: Sven A. Schmidt, sven.schmidt@cern.ch
00010 //Date:   13.2.2001
00011 
00012 //This code is based on the hadd.C example by Rene Brun and Dirk Geppert,
00013 //which had a problem with directories more than one level deep.
00014 //(see macro hadd_old.C for this previous implementation).
00015 //
00016 //The macro from Sven has been enhanced by
00017 //   Anne-Sylvie Nicollerat <Anne-Sylvie.Nicollerat@cern.ch>
00018 // to automatically add Trees (via a chain of trees).
00019 //
00020 //To use this macro, modify the file names in function hadd.
00021 //
00022 //NB: This macro is provided as a tutorial.
00023 //    Use $ROOTSYS/bin/hadd to merge many histogram files
00024 
00025 
00026 
00027 #include <string.h>
00028 #include "TChain.h"
00029 #include "TFile.h"
00030 #include "TH1.h"
00031 #include "TTree.h"
00032 #include "TKey.h"
00033 #include "Riostream.h"
00034 
00035 TList *FileList;
00036 TFile *Target;
00037 
00038 void MergeRootfile( TDirectory *target, TList *sourcelist );
00039 
00040 
00041 void hadd() {
00042    // in an interactive ROOT session, edit the file names
00043    // Target and FileList, then
00044    // root > .L hadd.C
00045    // root > hadd()
00046 
00047    Target = TFile::Open( "result.root", "RECREATE" );
00048 
00049    FileList = new TList();
00050    FileList->Add( TFile::Open("hsimple1.root") );
00051    FileList->Add( TFile::Open("hsimple2.root") );
00052 
00053    MergeRootfile( Target, FileList );
00054 
00055 }
00056 
00057 void MergeRootfile( TDirectory *target, TList *sourcelist ) {
00058 
00059    //  cout << "Target path: " << target->GetPath() << endl;
00060    TString path( (char*)strstr( target->GetPath(), ":" ) );
00061    path.Remove( 0, 2 );
00062 
00063    TFile *first_source = (TFile*)sourcelist->First();
00064    first_source->cd( path );
00065    TDirectory *current_sourcedir = gDirectory;
00066    //gain time, do not add the objects in the list in memory
00067    Bool_t status = TH1::AddDirectoryStatus();
00068    TH1::AddDirectory(kFALSE);
00069 
00070    // loop over all keys in this directory
00071    TChain *globChain = 0;
00072    TIter nextkey( current_sourcedir->GetListOfKeys() );
00073    TKey *key, *oldkey=0;
00074    while ( (key = (TKey*)nextkey())) {
00075 
00076       //keep only the highest cycle number for each key
00077       if (oldkey && !strcmp(oldkey->GetName(),key->GetName())) continue;
00078 
00079       // read object from first source file
00080       first_source->cd( path );
00081       TObject *obj = key->ReadObj();
00082 
00083       if ( obj->IsA()->InheritsFrom( TH1::Class() ) ) {
00084          // descendant of TH1 -> merge it
00085 
00086          //      cout << "Merging histogram " << obj->GetName() << endl;
00087          TH1 *h1 = (TH1*)obj;
00088 
00089          // loop over all source files and add the content of the
00090          // correspondant histogram to the one pointed to by "h1"
00091          TFile *nextsource = (TFile*)sourcelist->After( first_source );
00092          while ( nextsource ) {
00093 
00094             // make sure we are at the correct directory level by cd'ing to path
00095             nextsource->cd( path );
00096             TKey *key2 = (TKey*)gDirectory->GetListOfKeys()->FindObject(h1->GetName());
00097             if (key2) {
00098                TH1 *h2 = (TH1*)key2->ReadObj();
00099                h1->Add( h2 );
00100                delete h2;
00101             }
00102 
00103             nextsource = (TFile*)sourcelist->After( nextsource );
00104          }
00105       }
00106       else if ( obj->IsA()->InheritsFrom( TTree::Class() ) ) {
00107 
00108          // loop over all source files create a chain of Trees "globChain"
00109          const char* obj_name= obj->GetName();
00110 
00111          globChain = new TChain(obj_name);
00112          globChain->Add(first_source->GetName());
00113          TFile *nextsource = (TFile*)sourcelist->After( first_source );
00114          //      const char* file_name = nextsource->GetName();
00115          // cout << "file name  " << file_name << endl;
00116          while ( nextsource ) {
00117 
00118             globChain->Add(nextsource->GetName());
00119             nextsource = (TFile*)sourcelist->After( nextsource );
00120          }
00121 
00122       } else if ( obj->IsA()->InheritsFrom( TDirectory::Class() ) ) {
00123          // it's a subdirectory
00124 
00125          cout << "Found subdirectory " << obj->GetName() << endl;
00126 
00127          // create a new subdir of same name and title in the target file
00128          target->cd();
00129          TDirectory *newdir = target->mkdir( obj->GetName(), obj->GetTitle() );
00130 
00131          // newdir is now the starting point of another round of merging
00132          // newdir still knows its depth within the target file via
00133          // GetPath(), so we can still figure out where we are in the recursion
00134          MergeRootfile( newdir, sourcelist );
00135 
00136       } else {
00137 
00138          // object is of no type that we know or can handle
00139          cout << "Unknown object type, name: "
00140          << obj->GetName() << " title: " << obj->GetTitle() << endl;
00141       }
00142 
00143       // now write the merged histogram (which is "in" obj) to the target file
00144       // note that this will just store obj in the current directory level,
00145       // which is not persistent until the complete directory itself is stored
00146       // by "target->Write()" below
00147       if ( obj ) {
00148          target->cd();
00149 
00150          //!!if the object is a tree, it is stored in globChain...
00151          if(obj->IsA()->InheritsFrom( TTree::Class() ))
00152             globChain->Merge(target->GetFile(),0,"keep");
00153          else
00154             obj->Write( key->GetName() );
00155       }
00156 
00157    } // while ( ( TKey *key = (TKey*)nextkey() ) )
00158 
00159    // save modifications to target file
00160    target->SaveSelf(kTRUE);
00161    TH1::AddDirectory(status);
00162 }

Generated on Tue Jul 5 15:44:49 2011 for ROOT_528-00b_version by  doxygen 1.5.1