FairRoot/PandaRoot
hadd.C
Go to the documentation of this file.
1 /*
2 
3  This macro will add histograms from a list of root files and write them
4  to a target root file. The target file is newly created and must not be
5  identical to one of the source files.
6 
7  Author: Sven A. Schmidt, sven.schmidt@cern.ch
8  Date: 13.2.2001
9 
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  (see macro hadd_old.C for this previous implementation).
13 
14  The macro from Sven has been enhanced by
15  Anne-Sylvie Nicollerat <Anne-Sylvie.Nicollerat@cern.ch>
16  to automatically add Trees (via a chain of trees).
17 
18  To use this macro, modify the file names in function hadd.
19 
20  NB: This macro is provided as a tutorial.
21  Use $ROOTSYS/bin/hadd to merge many histogram files
22 
23 */
24 
25 
26 #include <string.h>
27 #include "TChain.h"
28 #include "TFile.h"
29 #include "TH1.h"
30 #include "TTree.h"
31 #include "TKey.h"
32 #include "Riostream.h"
33 
34 TList *FileList;
35 TFile *Target;
36 
37 void MergeRootfile( TDirectory *target, TList *sourcelist );
38 
39 
40 void hadd(Char_t list[]="inputlist", Char_t outputfile[]="results.root") {
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( outputfile, "RECREATE" );
47 
48  Int_t val;
49  Char_t filename[256];
50 
51  FileList = new TList();
52 
53  char line[1024], filename[1024];
54  FILE *fp=fopen((char*) list,"r");
55  if (NULL==fp)
56  {
57  printf("<E> File %s could not be opened\n",list);
58  return;
59  }
60  Int_t cnt=0, maxfiles=986;
61  while ((fgets(line,sizeof(line),fp)) && cnt<maxfiles)
62  {
63  cnt++;
64  sscanf(line,"%s\n",filename);
65  printf("Opening file %s\n",filename);
66  FileList->Add( TFile::Open(filename) );
67  }
69  fclose(fp);
70 }
71 
72 void MergeRootfile( TDirectory *target, TList *sourcelist ) {
73 
74  // cout << "Target path: " << target->GetPath() << endl;
75  TString path( (char*)strstr( target->GetPath(), ":" ) );
76  path.Remove( 0, 2 );
77 
78  TFile *first_source = (TFile*)sourcelist->First();
79  first_source->cd( path );
80  TDirectory *current_sourcedir = gDirectory;
81 
82  // loop over all keys in this directory
83  TChain *globChain = 0;
84  TIter nextkey( current_sourcedir->GetListOfKeys() );
85  TKey *key;
86  while ( (key = (TKey*)nextkey())) {
87 
88  // read object from first source file
89  first_source->cd( path );
90  TObject *obj = key->ReadObj();
91 
92  if ( obj->IsA()->InheritsFrom( "TH1" ) ) {
93  // descendant of TH1 -> merge it
94 
95  // cout << "Merging histogram " << obj->GetName() << endl;
96  TH1 *h1 = (TH1*)obj;
97 
98  // loop over all source files and add the content of the
99  // correspondant histogram to the one pointed to by "h1"
100  TFile *nextsource = (TFile*)sourcelist->After( first_source );
101  while ( nextsource ) {
102 
103  // make sure we are at the correct directory level by cd'ing to path
104  nextsource->cd( path );
105  TH1 *h2 = (TH1*)gDirectory->Get( h1->GetName() );
106  if ( h2 ) {
107  h1->Add( h2 );
108  delete h2; // don't know if this is necessary, i.e. if
109  // h2 is created by the call to gDirectory above.
110  }
111 
112  nextsource = (TFile*)sourcelist->After( nextsource );
113  }
114  }
115  else if ( obj->IsA()->InheritsFrom( "TTree" ) ) {
116 
117  // loop over all source files create a chain of Trees "globChain"
118  const char* obj_name= obj->GetName();
119 
120  globChain = new TChain(obj_name);
121  globChain->Add(first_source->GetName());
122  TFile *nextsource = (TFile*)sourcelist->After( first_source );
123  // const char* file_name = nextsource->GetName();
124  // cout << "file name " << file_name << endl;
125  while ( nextsource ) {
126 
127  globChain->Add(nextsource->GetName());
128  nextsource = (TFile*)sourcelist->After( nextsource );
129  }
130 
131  } else if ( obj->IsA()->InheritsFrom( "TDirectory" ) ) {
132  // it's a subdirectory
133 
134  cout << "Found subdirectory " << obj->GetName() << endl;
135 
136  // create a new subdir of same name and title in the target file
137  target->cd();
138  TDirectory *newdir = target->mkdir( obj->GetName(), obj->GetTitle() );
139 
140  // newdir is now the starting point of another round of merging
141  // newdir still knows its depth within the target file via
142  // GetPath(), so we can still figure out where we are in the recursion
143  MergeRootfile( newdir, sourcelist );
144 
145  } else {
146 
147  // object is of no type that we know or can handle
148  cout << "Unknown object type, name: "
149  << obj->GetName() << " title: " << obj->GetTitle() << endl;
150  }
151 
152  // now write the merged histogram (which is "in" obj) to the target file
153  // note that this will just store obj in the current directory level,
154  // which is not persistent until the complete directory itself is stored
155  // by "target->Write()" below
156  if ( obj ) {
157  target->cd();
158 
160  if(obj->IsA()->InheritsFrom( "TTree" ))
161  globChain->Write( key->GetName() );
162  else
163  obj->Write( key->GetName() );
164  }
165 
166  } // while ( ( TKey *key = (TKey*)nextkey() ) )
167 
168  // save modifications to target file
169  target->Write();
170 
171 }
void hadd(Char_t list[]="inputlist", Char_t outputfile[]="results.root")
Definition: hadd.C:40
printf("RealTime=%f seconds, CpuTime=%f seconds\n", rtime, ctime)
Double_t val[nBoxes][nFEBox]
Definition: createCalib.C:11
TFile * Target
Definition: hadd.C:35
TList * FileList
Definition: hadd.C:34
void MergeRootfile(TDirectory *target, TList *sourcelist)
Definition: hadd.C:72
Int_t cnt
Definition: hist-t7.C:106
const string filename