Logo ROOT  
Reference Guide
hadd.C File Reference

Detailed Description

View in nbviewer Open in SWAN Macro to add histogram files This macro is kept for didactical purposes 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. 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. The macro from Sven has been enhanced by Anne-Sylvie Nicollerat Anne-.nosp@m.Sylv.nosp@m.ie.Ni.nosp@m.coll.nosp@m.erat@.nosp@m.cern.nosp@m..ch to automatically add Trees (via a chain of trees).

#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() {
// Prepare the files to me merged
if(gSystem->AccessPathName("hsimple1.root")) {
gSystem->CopyFile("hsimple.root", "hsimple1.root");
gSystem->CopyFile("hsimple.root", "hsimple2.root");
}
// 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;
//gain time, do not add the objects in the list in memory
// 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::Class() ) ) {
// 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 );
TKey *key2 = (TKey*)gDirectory->GetListOfKeys()->FindObject(h1->GetName());
if (key2) {
TH1 *h2 = (TH1*)key2->ReadObj();
h1->Add( h2 );
delete h2;
}
nextsource = (TFile*)sourcelist->After( nextsource );
}
}
else if ( obj->IsA()->InheritsFrom( TTree::Class() ) ) {
// 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::Class() ) ) {
// 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::Class() ))
globChain->Merge(target->GetFile(),0,"keep");
else
obj->Write( key->GetName() );
}
} // while ( ( TKey *key = (TKey*)nextkey() ) )
// save modifications to target file
target->SaveSelf(kTRUE);
}
Author
Sven A. Schmidt, sven..nosp@m.schm.nosp@m.idt@c.nosp@m.ern..nosp@m.ch, 13.2.2001

Definition in file hadd.C.

kTRUE
const Bool_t kTRUE
Definition: RtypesCore.h:100
TDirectory::mkdir
virtual TDirectory * mkdir(const char *name, const char *title="", Bool_t returnExistingDirectory=kFALSE)
Create a sub-directory "a" or a hierarchy of sub-directories "a/b/c/...".
Definition: TDirectory.cxx:1050
TDirectory::GetListOfKeys
virtual TList * GetListOfKeys() const
Definition: TDirectory.h:214
TChain::Merge
virtual Long64_t Merge(const char *name, Option_t *option="")
Merge all the entries in the chain into a new tree in a new file.
Definition: TChain.cxx:1866
TChain::Add
virtual Int_t Add(TChain *chain)
Add all files referenced by the passed chain to this chain.
Definition: TChain.cxx:229
TFile::Open
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
Definition: TFile.cxx:3998
TDirectoryFile::cd
Bool_t cd(const char *path=nullptr) override
Change current directory to "this" directory.
Definition: TDirectoryFile.cxx:340
TDirectory::cd
virtual Bool_t cd(const char *path=nullptr)
Change current directory to "this" directory.
Definition: TDirectory.cxx:504
TH1::Add
virtual Bool_t Add(TF1 *h1, Double_t c1=1, Option_t *option="")
Performs the operation: this = this + c1*f1 if errors are defined (see TH1::Sumw2),...
Definition: TH1.cxx:822
TObject::GetTitle
virtual const char * GetTitle() const
Returns title of object.
Definition: TObject.cxx:403
TTree.h
TString
Basic string class.
Definition: TString.h:136
TSystem::AccessPathName
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition: TSystem.cxx:1295
Bool_t
bool Bool_t
Definition: RtypesCore.h:63
TObject::InheritsFrom
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:445
TFile.h
h1
TH1F * h1
Definition: legend1.C:5
TSystem::CopyFile
virtual int CopyFile(const char *from, const char *to, Bool_t overwrite=kFALSE)
Copy a file.
Definition: TSystem.cxx:1340
TList::First
virtual TObject * First() const
Return the first object in the list. Returns 0 when list is empty.
Definition: TList.cxx:659
TObject::GetName
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:359
TList::After
virtual TObject * After(const TObject *obj) const
Returns the object after object obj.
Definition: TList.cxx:330
TChain.h
kFALSE
const Bool_t kFALSE
Definition: RtypesCore.h:101
TH1::AddDirectory
static void AddDirectory(Bool_t add=kTRUE)
Sets the flag controlling the automatic add of histograms in memory.
Definition: TH1.cxx:1282
gDirectory
#define gDirectory
Definition: TDirectory.h:327
TDirectory::SaveSelf
virtual void SaveSelf(Bool_t=kFALSE)
Definition: TDirectory.h:245
TFile
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format.
Definition: TFile.h:54
TDirectory::GetPath
virtual const char * GetPath() const
Returns the full path of the directory.
Definition: TDirectory.cxx:996
gSystem
R__EXTERN TSystem * gSystem
Definition: TSystem.h:559
TKey
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition: TKey.h:28
TKey::ReadObj
virtual TObject * ReadObj()
To read a TObject* from the file.
Definition: TKey.cxx:750
TObject::Write
virtual Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0)
Write this object to the current directory.
Definition: TObject.cxx:798
TList::Add
virtual void Add(TObject *obj)
Definition: TList.h:87
TObject
Mother of all ROOT objects.
Definition: TObject.h:37
TH1
TH1 is the base class of all histogram classes in ROOT.
Definition: TH1.h:58
TDirectory::GetFile
virtual TFile * GetFile() const
Definition: TDirectory.h:211
TDirectory
Describe directory structure in memory.
Definition: TDirectory.h:45
TIter
Definition: TCollection.h:233
TChain
A chain is a collection of files containing TTree objects.
Definition: TChain.h:33
TNamed::GetName
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
TH1::AddDirectoryStatus
static Bool_t AddDirectoryStatus()
Static function: cannot be inlined on Windows/NT.
Definition: TH1.cxx:750
TKey.h
Class
void Class()
Definition: Class.C:29
Riostream.h
TH1.h
TList
A doubly linked list.
Definition: TList.h:44