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