StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
hadd.C
1 #include <string.h>
2 #include "TChain.h"
3 #include "TFile.h"
4 #include "TH1.h"
5 #include "TTree.h"
6 #include "TKey.h"
7 #include "Riostream.h"
8 
9 TList *FileList;
10 TFile *Target;
11 
12 void MergeRootfile( TDirectory *target, TList *sourcelist );
13 
14 void hadd(int flag=0) {
15  TString iPath="out1/";
16  TString out=iPath;
17  out+="/sumP";
18 
19  Target = TFile::Open( out+".hist.root", "RECREATE" );
20 
21  //... pp minB events ....
22  // char *runL="R7114062 R7115091 R7116006 R7119053";
23 
24  //... ppTrans events ....
25  char *runL="R7098001 R7098024 R7098038 R7098065 R7098082 R7099025 R7099047 R7100072 R7098002 R7098025 R7098039 R7098066 R7098083 R7099026 R7100052 R7100075 ";
26 
27  FileList = new TList();
28 
29  char *run=strtok(runL," "); // init 'strtok'
30  int i=0;
31  do {
32  printf("add run %d '%s' \n",i++,run);
33  TString fullName=iPath+run+".hist.root";
34  FileList->Add( TFile::Open(fullName));
35  } while(run=strtok(0," ")); // advance by one nam
36 
37  MergeRootfile( Target, FileList );
38 
39 }
40 
41 void MergeRootfile( TDirectory *target, TList *sourcelist ) {
42 
43  // cout << "Target path: " << target->GetPath() << endl;
44  TString path( (char*)strstr( target->GetPath(), ":" ) );
45  path.Remove( 0, 2 );
46 
47  TFile *first_source = (TFile*)sourcelist->First();
48  first_source->cd( path );
49  TDirectory *current_sourcedir = gDirectory;
50 
51  int nh=0;
52  // loop over all keys in this directory
53  TChain *globChain = 0;
54  TIter nextkey( current_sourcedir->GetListOfKeys() );
55  TKey *key;
56  while ( (key = (TKey*)nextkey())) {
57  const char *name=key->GetName();
58  nh++;
59  if(nh%10==0) printf("nh=%d addingX %s\n",nh,name);
60 
61  // read object from first source file
62  first_source->cd( path );
63  TObject *obj = key->ReadObj();
64 
65  if ( obj->IsA()->InheritsFrom( "TH1" ) ) {
66  // descendant of TH1 -> merge it
67 
68  // cout << "Merging histogram " << obj->GetName() << endl;
69  TH1 *h1 = (TH1*)obj;
70 
71  // loop over all source files and add the content of the
72  // correspondant histogram to the one pointed to by "h1"
73  TFile *nextsource = (TFile*)sourcelist->After( first_source );
74  while ( nextsource ) {
75 
76  // make sure we are at the correct directory level by cd'ing to path
77  nextsource->cd( path );
78  TH1 *h2 = (TH1*)gDirectory->Get( h1->GetName() );
79  if ( h2 ) {
80  h1->Add( h2 );
81  delete h2; // don't know if this is necessary, i.e. if
82  // h2 is created by the call to gDirectory above.
83  }
84 
85  nextsource = (TFile*)sourcelist->After( nextsource );
86  }
87  }
88  else if ( obj->IsA()->InheritsFrom( "TTree" ) ) {
89 
90  // loop over all source files create a chain of Trees "globChain"
91  const char* obj_name= obj->GetName();
92 
93  globChain = new TChain(obj_name);
94  globChain->Add(first_source->GetName());
95  TFile *nextsource = (TFile*)sourcelist->After( first_source );
96  // const char* file_name = nextsource->GetName();
97  // cout << "file name " << file_name << endl;
98  while ( nextsource ) {
99 
100  globChain->Add(nextsource->GetName());
101  nextsource = (TFile*)sourcelist->After( nextsource );
102  }
103 
104  } else if ( obj->IsA()->InheritsFrom( "TDirectory" ) ) {
105  // it's a subdirectory
106 
107  cout << "Found subdirectory " << obj->GetName() << endl;
108 
109  // create a new subdir of same name and title in the target file
110  target->cd();
111  TDirectory *newdir = target->mkdir( obj->GetName(), obj->GetTitle() );
112 
113  // newdir is now the starting point of another round of merging
114  // newdir still knows its depth within the target file via
115  // GetPath(), so we can still figure out where we are in the recursion
116  MergeRootfile( core,newdir, sourcelist );
117 
118  } else {
119 
120  // object is of no type that we know or can handle
121  cout << "Unknown object type, name: "
122  << obj->GetName() << " title: " << obj->GetTitle() << endl;
123  }
124 
125  // now write the merged histogram (which is "in" obj) to the target file
126  // note that this will just store obj in the current directory level,
127  // which is not persistent until the complete directory itself is stored
128  // by "target->Write()" below
129  if ( obj ) {
130  target->cd();
131 
133  if(obj->IsA()->InheritsFrom( "TTree" ))
134  globChain->Write( key->GetName() );
135  else
136  obj->Write( key->GetName() );
137  }
138 
139  } // while ( ( TKey *key = (TKey*)nextkey() ) )
140 
141  // save modifications to target file
142  target->Write();
143 
144 }
145 
146 
147 /*
148 
149  This macro will add histograms from a list of root files and write them
150  to a target root file. The target file is newly created and must not be
151  identical to one of the source files.
152 
153  Author: Sven A. Schmidt, sven.schmidt@cern.ch
154  Date: 13.2.2001
155 
156  This code is based on the hadd.C example by Rene Brun and Dirk Geppert,
157  which had a problem with directories more than one level deep.
158  (see macro hadd_old.C for this previous implementation).
159 
160  The macro from Sven has been enhanced by
161  Anne-Sylvie Nicollerat <Anne-Sylvie.Nicollerat@cern.ch>
162  to automatically add Trees (via a chain of trees).
163 
164  To use this macro, modify the file names in function hadd.
165 
166  NB: This macro is provided as a tutorial.
167  Use $ROOTSYS/bin/hadd to merge many histogram files
168 
169  */
170