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