EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
hadd.C
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file 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 
15 void hadd() {
16  // in an interactive ROOT session, edit the file names
17  // Target and FileList, then
18  // root > .L hadd.C
19  // root > hadd()
20 
21  Target = TFile::Open( "result.root", "RECREATE" );
22 
23  FileList = new TList();
24  FileList->Add( TFile::Open("hsimple1.root") );
25  FileList->Add( TFile::Open("hsimple2.root") );
26 
28 
29 }
30 
31 void MergeRootfile( TDirectory *target, TList *sourcelist ) {
32 
33  // cout << "Target path: " << target->GetPath() << endl;
34  TString path( (char*)strstr( target->GetPath(), ":" ) );
35  path.Remove( 0, 2 );
36 
37  TFile *first_source = (TFile*)sourcelist->First();
38  first_source->cd( path );
39  TDirectory *current_sourcedir = gDirectory;
40  //gain time, do not add the objects in the list in memory
41  Bool_t status = TH1::AddDirectoryStatus();
42  TH1::AddDirectory(kFALSE);
43 
44  // loop over all keys in this directory
45  TChain *globChain = 0;
46  TIter nextkey( current_sourcedir->GetListOfKeys() );
47  TKey *key, *oldkey=0;
48  while ( (key = (TKey*)nextkey())) {
49 
50  //keep only the highest cycle number for each key
51  if (oldkey && !strcmp(oldkey->GetName(),key->GetName())) continue;
52 
53  // read object from first source file
54  first_source->cd( path );
55  TObject *obj = key->ReadObj();
56 
57  if ( obj->IsA()->InheritsFrom( TH1::Class() ) ) {
58  // descendant of TH1 -> merge it
59 
60  // cout << "Merging histogram " << obj->GetName() << endl;
61  TH1 *h1 = (TH1*)obj;
62 
63  // loop over all source files and add the content of the
64  // correspondant histogram to the one pointed to by "h1"
65  TFile *nextsource = (TFile*)sourcelist->After( first_source );
66  while ( nextsource ) {
67 
68  // make sure we are at the correct directory level by cd'ing to path
69  nextsource->cd( path );
70  TKey *key2 = (TKey*)gDirectory->GetListOfKeys()->FindObject(h1->GetName());
71  if (key2) {
72  TH1 *h2 = (TH1*)key2->ReadObj();
73  h1->Add( h2 );
74  delete h2;
75  }
76 
77  nextsource = (TFile*)sourcelist->After( nextsource );
78  }
79  }
80  else if ( obj->IsA()->InheritsFrom( TTree::Class() ) ) {
81 
82  // loop over all source files create a chain of Trees "globChain"
83  const char* obj_name= obj->GetName();
84 
85  globChain = new TChain(obj_name);
86  globChain->Add(first_source->GetName());
87  TFile *nextsource = (TFile*)sourcelist->After( first_source );
88  // const char* file_name = nextsource->GetName();
89  // cout << "file name " << file_name << endl;
90  while ( nextsource ) {
91 
92  globChain->Add(nextsource->GetName());
93  nextsource = (TFile*)sourcelist->After( nextsource );
94  }
95 
96  } else if ( obj->IsA()->InheritsFrom( TDirectory::Class() ) ) {
97  // it's a subdirectory
98 
99  cout << "Found subdirectory " << obj->GetName() << endl;
100 
101  // create a new subdir of same name and title in the target file
102  target->cd();
103  TDirectory *newdir = target->mkdir( obj->GetName(), obj->GetTitle() );
104 
105  // newdir is now the starting point of another round of merging
106  // newdir still knows its depth within the target file via
107  // GetPath(), so we can still figure out where we are in the recursion
108  MergeRootfile( newdir, sourcelist );
109 
110  } else {
111 
112  // object is of no type that we know or can handle
113  cout << "Unknown object type, name: "
114  << obj->GetName() << " title: " << obj->GetTitle() << endl;
115  }
116 
117  // now write the merged histogram (which is "in" obj) to the target file
118  // note that this will just store obj in the current directory level,
119  // which is not persistent until the complete directory itself is stored
120  // by "target->Write()" below
121  if ( obj ) {
122  target->cd();
123 
125  if(obj->IsA()->InheritsFrom( TTree::Class() ))
126  globChain->Merge(target->GetFile(),0,"keep");
127  else
128  obj->Write( key->GetName() );
129  }
130 
131  } // while ( ( TKey *key = (TKey*)nextkey() ) )
132 
133  // save modifications to target file
134  target->SaveSelf(kTRUE);
135  TH1::AddDirectory(status);
136 }