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 /*
2 > hadd.C(TString detector)
3 - Used to combine the evaluated root files while running jobs in batches
4 - Arguments
5  # detector - CEMC, EEMC, FEMC, FHCAL, HCALIN, HCALOUT
6 - Output file - merged_Eval_<detector>.root
7 */
8 
9 /*
10 Authors - Sagar Joshi (ee190002054@iiti.ac.in)
11  Siddhant Rathi (me190003061@iiti.ac.in)
12 
13 v2.0
14 */
15 
16 #include <string.h>
17 #include "TChain.h"
18 #include "TFile.h"
19 #include "TH1.h"
20 #include "TTree.h"
21 #include "TKey.h"
22 #include "Riostream.h"
23 #include <iostream>
24 #include <dirent.h>
25 #include <errno.h>
26 
27 TList *FileList;
28 TFile *Target;
29 
30 void MergeRootfile( TDirectory *target, TList *sourcelist );
31 
32 
33 void hadd(TString detector) {
34  // Prepare the files to me merged
35 
36  //std::cout<<"Please enter the name of the detector (all caps): ";
37  //std::cin>>detector;
38 
39  int nCopies = successfulJobs;
40 
41  if(gSystem->AccessPathName("EvalFiles/Eval_" + detector + "_0.root")) {
42  for(int i = 1; i < nCopies; i++){
43  gSystem->CopyFile("hsimple.root", "EvalFiles/Eval_" + detector + "_" + TString::Itoa(i,10) + ".root");
44  }
45  }
46 
47  // in an interactive ROOT session, edit the file names
48  // Target and FileList, then
49  // root > .L hadd.C
50  // root > hadd()
51 
52  Target = TFile::Open("merged_Eval_" + detector + ".root", "RECREATE" );
53  FileList = new TList();
54 
55  for(int i = 0; i < nCopies; i++){
56  FileList->Add( TFile::Open("EvalFiles/Eval_" + detector + "_" + TString::Itoa(i,10) + ".root"));
57  }
58 
59 
61 
62 }
63 
64 void MergeRootfile( TDirectory *target, TList *sourcelist ) {
65 
66  // cout << "Target path: " << target->GetPath() << endl;
67  TString path( (char*)strstr( target->GetPath(), ":" ) );
68  path.Remove( 0, 2 );
69 
70  TFile *first_source = (TFile*)sourcelist->First();
71  first_source->cd( path );
72  TDirectory *current_sourcedir = gDirectory;
73  //gain time, do not add the objects in the list in memory
74  Bool_t status = TH1::AddDirectoryStatus();
75  TH1::AddDirectory(kFALSE);
76 
77  // loop over all keys in this directory
78  TChain *globChain = 0;
79  TIter nextkey( current_sourcedir->GetListOfKeys() );
80  TKey *key, *oldkey=0;
81  while ( (key = (TKey*)nextkey())) {
82 
83  //keep only the highest cycle number for each key
84  if (oldkey && !strcmp(oldkey->GetName(),key->GetName())) continue;
85 
86  // read object from first source file
87  first_source->cd( path );
88  TObject *obj = key->ReadObj();
89 
90  if ( obj->IsA()->InheritsFrom( TH1::Class() ) ) {
91  // descendant of TH1 -> merge it
92 
93  // cout << "Merging histogram " << obj->GetName() << endl;
94  TH1 *h1 = (TH1*)obj;
95 
96  // loop over all source files and add the content of the
97  // correspondant histogram to the one pointed to by "h1"
98  TFile *nextsource = (TFile*)sourcelist->After( first_source );
99  while ( nextsource ) {
100 
101  // make sure we are at the correct directory level by cd'ing to path
102  nextsource->cd( path );
103  TKey *key2 = (TKey*)gDirectory->GetListOfKeys()->FindObject(h1->GetName());
104  if (key2) {
105  TH1 *h2 = (TH1*)key2->ReadObj();
106  h1->Add( h2 );
107  delete h2;
108  }
109 
110  nextsource = (TFile*)sourcelist->After( nextsource );
111  }
112  }
113  else if ( obj->IsA()->InheritsFrom( TTree::Class() ) ) {
114 
115  // loop over all source files create a chain of Trees "globChain"
116  const char* obj_name= obj->GetName();
117 
118  globChain = new TChain(obj_name);
119  globChain->SetMaxTreeSize(200000000000LL); // set size to ~100 GB
120  globChain->Add(first_source->GetName());
121  TFile *nextsource = (TFile*)sourcelist->After( first_source );
122  // const char* file_name = nextsource->GetName();
123  // cout << "file name " << file_name << endl;
124  while ( nextsource ) {
125 
126  globChain->Add(nextsource->GetName());
127  nextsource = (TFile*)sourcelist->After( nextsource );
128  }
129 
130  } else if ( obj->IsA()->InheritsFrom( TDirectory::Class() ) ) {
131  // it's a subdirectory
132 
133  cout << "Found subdirectory " << obj->GetName() << endl;
134 
135  // create a new subdir of same name and title in the target file
136  target->cd();
137  TDirectory *newdir = target->mkdir( obj->GetName(), obj->GetTitle() );
138 
139  // newdir is now the starting point of another round of merging
140  // newdir still knows its depth within the target file via
141  // GetPath(), so we can still figure out where we are in the recursion
142  MergeRootfile( newdir, sourcelist );
143 
144  } else {
145 
146  // object is of no type that we know or can handle
147  cout << "Unknown object type, name: "
148  << obj->GetName() << " title: " << obj->GetTitle() << endl;
149  }
150 
151  // now write the merged histogram (which is "in" obj) to the target file
152  // note that this will just store obj in the current directory level,
153  // which is not persistent until the complete directory itself is stored
154  // by "target->Write()" below
155  if ( obj ) {
156  target->cd();
157 
159  if(obj->IsA()->InheritsFrom( TTree::Class() ))
160  globChain->Merge(target->GetFile(),0,"keep");
161  else
162  obj->Write( key->GetName() );
163  }
164 
165  } // while ( ( TKey *key = (TKey*)nextkey() ) )
166 
167  // save modifications to target file
168  target->SaveSelf(kTRUE);
169  TH1::AddDirectory(status);
170 }