-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmergeMu.C
208 lines (155 loc) · 6.37 KB
/
mergeMu.C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
/*
This macro will add histograms multiplied by their cross-section
from a list of root files and write them
to a target root file. The target file is newly created and must not be
identical to one of the source files.
Author: Sven A. Schmidt, [email protected]
Date: 13.2.2001
Editing Author: Michael B. Anderson, [email protected]
Date: July 12, 2007
This code is based on the hadd.C example by Rene Brun and Dirk Geppert,
which had a problem with directories more than one level deep.
(see macro hadd_old.C for this previous implementation).
The macro from Sven has been enhanced by
Anne-Sylvie Nicollerat <[email protected]>
to automatically add Trees (via a chain of trees).
To use this macro, modify the file names in function hadd.
NB: This macro is provided as a tutorial.
Use $ROOTSYS/bin/hadd to merge many histogram files
*/
#include <string.h>
#include "TChain.h"
#include "TFile.h"
#include "TH1.h"
#include "TTree.h"
#include "TKey.h"
#include "Riostream.h"
TString histoType;
TString histoType2;
TList *FileList;
TFile *Target;
void MergeRootfile( TDirectory *target, TList *sourcelist, double crossArray[] );
void mergeMu() {
// in an interactive ROOT session, edit the file names
// Target and FileList, then
// root > .L hadd.C
// root > hadd()
Target = TFile::Open( "MuAllval.root", "RECREATE" );
FileList = new TList();
// ************************************************************
// List of Files
FileList->Add( TFile::Open("Mu00val.root"));
FileList->Add( TFile::Open("Mu01val.root"));
FileList->Add( TFile::Open("Mu02val.root"));
FileList->Add( TFile::Open("Mu03val.root"));
FileList->Add( TFile::Open("Mu04val.root"));
FileList->Add( TFile::Open("Mu05val.root"));
// // List of Cross-sections divided by num of events produced
// --------------------------------------------------------
// double crossSections[8] = { 0.74,1,1,1,0.5,0.37,0.37,0.37};
double crossSections[6] = { 1,1,1,1,1,1};
// ************************************************************
cout << "going to call merging routine..." << endl;
MergeRootfile( Target, FileList, crossSections );
cout << "done." << endl;
}
void MergeRootfile( TDirectory *target, TList *sourcelist, double crossArray[] ) {
cout << "Target path: " << target->GetPath() << endl;
TString path( (char*)strstr( target->GetPath(), ":" ) );
path.Remove( 0, 2 );
TFile *first_source = (TFile*)sourcelist->First();
first_source->cd( path );
TDirectory *current_sourcedir = gDirectory;
//gain time, do not add the objects in the list in memory
Bool_t status = TH1::AddDirectoryStatus();
TH1::AddDirectory(kFALSE);
// loop over all keys in this directory
TChain *globChain = 0;
TIter nextkey( current_sourcedir->GetListOfKeys() );
TKey *key, *oldkey=0;
while ( (key = (TKey*)nextkey())) {
//keep only the highest cycle number for each key
if (oldkey && !strcmp(oldkey->GetName(),key->GetName())) continue;
// read object from first source file
first_source->cd( path );
TObject *obj = key->ReadObj();
histoType = obj ->ClassName();
if ( obj->IsA()->InheritsFrom( "TH1" ) ) {
// descendant of TH1 -> merge it
cout << "Merging histogram " << obj->GetName() << endl;
TH1 *h1 = (TH1*)obj;
// Scale by the cross-section factor
if ( histoType.Contains("TH1") ) {
h1->Scale(crossArray[0]);
}
h1->Sumw2();
// loop over all source files and add the content of the
// correspondant histogram to the one pointed to by "h1"
TFile *nextsource = (TFile*)sourcelist->After( first_source );
int q = 1; // This keeps track of which
// cross section factor to use
while ( nextsource ) {
// make sure we are at the correct directory level by cd'ing to path
nextsource->cd( path );
TKey *key2 = (TKey*)gDirectory->GetListOfKeys()->FindObject(h1->GetName());
if (key2) {
TObject *obj2 = key2->ReadObj();
// if ( histoType.Contains("TH1") ) {
TH1 *h2 = (TH1*)key2->ReadObj();
histoType2 = obj2 ->ClassName();
// Scale by the cross section factor
// before adding.
if ( histoType2.Contains("TH1") ) {
h2->Scale(crossArray[q]);
}
h1->Add( h2 );
q++;
delete h2;
}
nextsource = (TFile*)sourcelist->After( nextsource );
}
}
else if ( obj->IsA()->InheritsFrom( "TTree" ) ) {
// loop over all source files create a chain of Trees "globChain"
const char* obj_name= obj->GetName();
globChain = new TChain(obj_name);
globChain->Add(first_source->GetName());
TFile *nextsource = (TFile*)sourcelist->After( first_source );
// const char* file_name = nextsource->GetName();
// cout << "file name " << file_name << endl;
while ( nextsource ) {
globChain->Add(nextsource->GetName());
nextsource = (TFile*)sourcelist->After( nextsource );
}
} else if ( obj->IsA()->InheritsFrom( "TDirectory" ) ) {
// it's a subdirectory
cout << "Found subdirectory " << obj->GetName() << endl;
// create a new subdir of same name and title in the target file
target->cd();
TDirectory *newdir = target->mkdir( obj->GetName(), obj->GetTitle() );
// newdir is now the starting point of another round of merging
// newdir still knows its depth within the target file via
// GetPath(), so we can still figure out where we are in the recursion
MergeRootfile( newdir, sourcelist,crossArray );
} else {
// object is of no type that we know or can handle
cout << "Unknown object type, name: "
<< obj->GetName() << " title: " << obj->GetTitle() << endl;
}
// now write the merged histogram (which is "in" obj) to the target file
// note that this will just store obj in the current directory level,
// which is not persistent until the complete directory itself is stored
// by "target->Write()" below
if ( obj ) {
target->cd();
//!!if the object is a tree, it is stored in globChain...
if(obj->IsA()->InheritsFrom( "TTree" ))
globChain->Merge(target->GetFile(),0,"keep");
else
obj->Write( key->GetName() );
}
} // while ( ( TKey *key = (TKey*)nextkey() ) )
// save modifications to target file
target->SaveSelf(kTRUE);
TH1::AddDirectory(status);
}