Logo ROOT   6.10/09
Reference Guide
hadd.C
Go to the documentation of this file.
1 /// \file
2 /// \ingroup tutorial_io
3 /// \notebook -nodraw
4 /// Macro to add histogram files
5 /// This macro is kept for didactical purposes only: use instead the executable $ROOTSYS/bin/hadd !
6 ///
7 /// This macro will add histograms from a list of root files and write them
8 /// to a target root file. The target file is newly created and must not be
9 /// identical to one of the source files.
10 /// This code is based on the hadd.C example by Rene Brun and Dirk Geppert,
11 /// which had a problem with directories more than one level deep.
12 /// The macro from Sven has been enhanced by Anne-Sylvie Nicollerat <Anne-Sylvie.Nicollerat@cern.ch>
13 /// to automatically add Trees (via a chain of trees).
14 ///
15 /// \macro_code
16 ///
17 /// \author Sven A. Schmidt, sven.schmidt@cern.ch, 13.2.2001
18 
19 
20 #include <string.h>
21 #include "TChain.h"
22 #include "TFile.h"
23 #include "TH1.h"
24 #include "TTree.h"
25 #include "TKey.h"
26 #include "Riostream.h"
27 
28 TList *FileList;
29 TFile *Target;
30 
31 void MergeRootfile( TDirectory *target, TList *sourcelist );
32 
33 
34 void hadd() {
35  // Prepare the files to me merged
36  if(gSystem->AccessPathName("hsimple1.root")) {
37  gSystem->CopyFile("hsimple.root", "hsimple1.root");
38  gSystem->CopyFile("hsimple.root", "hsimple2.root");
39  }
40 
41  // in an interactive ROOT session, edit the file names
42  // Target and FileList, then
43  // root > .L hadd.C
44  // root > hadd()
45 
46  Target = TFile::Open( "result.root", "RECREATE" );
47 
48  FileList = new TList();
49  FileList->Add( TFile::Open("hsimple1.root") );
50  FileList->Add( TFile::Open("hsimple2.root") );
51 
52  MergeRootfile( Target, FileList );
53 
54 }
55 
56 void MergeRootfile( TDirectory *target, TList *sourcelist ) {
57 
58  // cout << "Target path: " << target->GetPath() << endl;
59  TString path( (char*)strstr( target->GetPath(), ":" ) );
60  path.Remove( 0, 2 );
61 
62  TFile *first_source = (TFile*)sourcelist->First();
63  first_source->cd( path );
64  TDirectory *current_sourcedir = gDirectory;
65  //gain time, do not add the objects in the list in memory
68 
69  // loop over all keys in this directory
70  TChain *globChain = 0;
71  TIter nextkey( current_sourcedir->GetListOfKeys() );
72  TKey *key, *oldkey=0;
73  while ( (key = (TKey*)nextkey())) {
74 
75  //keep only the highest cycle number for each key
76  if (oldkey && !strcmp(oldkey->GetName(),key->GetName())) continue;
77 
78  // read object from first source file
79  first_source->cd( path );
80  TObject *obj = key->ReadObj();
81 
82  if ( obj->IsA()->InheritsFrom( TH1::Class() ) ) {
83  // descendant of TH1 -> merge it
84 
85  // cout << "Merging histogram " << obj->GetName() << endl;
86  TH1 *h1 = (TH1*)obj;
87 
88  // loop over all source files and add the content of the
89  // correspondant histogram to the one pointed to by "h1"
90  TFile *nextsource = (TFile*)sourcelist->After( first_source );
91  while ( nextsource ) {
92 
93  // make sure we are at the correct directory level by cd'ing to path
94  nextsource->cd( path );
95  TKey *key2 = (TKey*)gDirectory->GetListOfKeys()->FindObject(h1->GetName());
96  if (key2) {
97  TH1 *h2 = (TH1*)key2->ReadObj();
98  h1->Add( h2 );
99  delete h2;
100  }
101 
102  nextsource = (TFile*)sourcelist->After( nextsource );
103  }
104  }
105  else if ( obj->IsA()->InheritsFrom( TTree::Class() ) ) {
106 
107  // loop over all source files create a chain of Trees "globChain"
108  const char* obj_name= obj->GetName();
109 
110  globChain = new TChain(obj_name);
111  globChain->Add(first_source->GetName());
112  TFile *nextsource = (TFile*)sourcelist->After( first_source );
113  // const char* file_name = nextsource->GetName();
114  // cout << "file name " << file_name << endl;
115  while ( nextsource ) {
116 
117  globChain->Add(nextsource->GetName());
118  nextsource = (TFile*)sourcelist->After( nextsource );
119  }
120 
121  } else if ( obj->IsA()->InheritsFrom( TDirectory::Class() ) ) {
122  // it's a subdirectory
123 
124  cout << "Found subdirectory " << obj->GetName() << endl;
125 
126  // create a new subdir of same name and title in the target file
127  target->cd();
128  TDirectory *newdir = target->mkdir( obj->GetName(), obj->GetTitle() );
129 
130  // newdir is now the starting point of another round of merging
131  // newdir still knows its depth within the target file via
132  // GetPath(), so we can still figure out where we are in the recursion
133  MergeRootfile( newdir, sourcelist );
134 
135  } else {
136 
137  // object is of no type that we know or can handle
138  cout << "Unknown object type, name: "
139  << obj->GetName() << " title: " << obj->GetTitle() << endl;
140  }
141 
142  // now write the merged histogram (which is "in" obj) to the target file
143  // note that this will just store obj in the current directory level,
144  // which is not persistent until the complete directory itself is stored
145  // by "target->Write()" below
146  if ( obj ) {
147  target->cd();
148 
149  //!!if the object is a tree, it is stored in globChain...
150  if(obj->IsA()->InheritsFrom( TTree::Class() ))
151  globChain->Merge(target->GetFile(),0,"keep");
152  else
153  obj->Write( key->GetName() );
154  }
155 
156  } // while ( ( TKey *key = (TKey*)nextkey() ) )
157 
158  // save modifications to target file
159  target->SaveSelf(kTRUE);
160  TH1::AddDirectory(status);
161 }
virtual Bool_t cd(const char *path=0)
Change current directory to "this" directory.
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
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:778
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:1272
virtual TList * GetListOfKeys() const
Definition: TDirectory.h:148
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format...
Definition: TFile.h:46
Basic string class.
Definition: TString.h:129
static Bool_t AddDirectoryStatus()
Static function: cannot be inlined on Windows/NT.
Definition: TH1.cxx:700
virtual TDirectory * mkdir(const char *name, const char *title="")
Create a sub-directory "a" or a hierarchy of sub-directories "a/b/c/...".
Definition: TDirectory.cxx:958
bool Bool_t
Definition: RtypesCore.h:59
static void AddDirectory(Bool_t add=kTRUE)
Sets the flag controlling the automatic add of histograms in memory.
Definition: TH1.cxx:1218
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=1, Int_t netopt=0)
Create / open a file.
Definition: TFile.cxx:3909
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:1824
void Class()
Definition: Class.C:29
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition: TKey.h:24
TH1F * h1
Definition: legend1.C:5
virtual TFile * GetFile() const
Definition: TDirectory.h:145
A doubly linked list.
Definition: TList.h:43
virtual TObject * First() const
Return the first object in the list. Returns 0 when list is empty.
Definition: TList.cxx:561
R__EXTERN TSystem * gSystem
Definition: TSystem.h:539
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:436
virtual TObject * After(const TObject *obj) const
Returns the object after object obj.
Definition: TList.cxx:293
virtual const char * GetPath() const
Returns the full path of the directory.
Definition: TDirectory.cxx:911
const Bool_t kFALSE
Definition: RtypesCore.h:92
virtual void SaveSelf(Bool_t=kFALSE)
Definition: TDirectory.h:179
Describe directory structure in memory.
Definition: TDirectory.h:34
The TH1 histogram class.
Definition: TH1.h:56
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), errors are also recalculated.
Definition: TH1.cxx:770
Mother of all ROOT objects.
Definition: TObject.h:37
virtual const char * GetTitle() const
Returns title of object.
Definition: TObject.cxx:408
virtual TObject * ReadObj()
To read a TObject* from the file.
Definition: TKey.cxx:730
virtual Bool_t cd(const char *path=0)
Change current directory to "this" directory.
Definition: TDirectory.cxx:435
virtual void Add(TObject *obj)
Definition: TList.h:77
A chain is a collection of files containing TTree objects.
Definition: TChain.h:33
virtual int CopyFile(const char *from, const char *to, Bool_t overwrite=kFALSE)
Copy a file.
Definition: TSystem.cxx:1317
#define gDirectory
Definition: TDirectory.h:211
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:364
const Bool_t kTRUE
Definition: RtypesCore.h:91
virtual Int_t Add(TChain *chain)
Add all files referenced by the passed chain to this chain.
Definition: TChain.cxx:220