File indexing completed on 2024-04-06 11:56:53
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Riostream.h"
0010 #include "TChain.h"
0011 #include "TFile.h"
0012 #include "TH1.h"
0013 #include "TKey.h"
0014 #include "TProfile.h"
0015 #include "TTree.h"
0016 #include <cstdlib>
0017 #include <cstring>
0018 #include <sstream>
0019 #include <utility>
0020 #include <vector>
0021
0022 using namespace std;
0023
0024 TFile *Target;
0025 typedef vector<pair<TFile *, double> > vec_pair;
0026 typedef vector<pair<TFile *, double> >::const_iterator vec_pair_it;
0027
0028 void MergeRootfile(TDirectory *target, const vector<pair<TFile *, double> > &vFileList);
0029 void loginfo(char log_type, std::string text);
0030
0031 void loginfo(char log_type = 'i', std::string text = "") {
0032
0033
0034
0035
0036
0037
0038
0039
0040 std::string source = "haddws: ";
0041 if (log_type == 'i') {
0042 std::cout << source << "[INFO] " << text << std::endl;
0043 } else if (log_type == 'w') {
0044 std::cout << source << "[WARNING] " << text << std::endl;
0045 } else if (log_type == 'e') {
0046 std::cout << source << "[ERROR] " << text << std::endl;
0047 } else if (log_type == 'f') {
0048 std::cout << source << "[FATAL] " << text << std::endl;
0049 }
0050 return;
0051 }
0052
0053
0054 int main(int argc, char *argv[]) {
0055 if (argc < 2) {
0056 cout << "\n======================== HADDWS USAGE INFO ===============================================" << endl;
0057 cout << " ./haddws file1.root file2.root w1 w2\n" << endl;
0058 cout << " w1, w2: are doubleing point numbers." << endl;
0059 cout << " Each input file should have a corresponding weight (>0)." << endl;
0060 cout << " A weight of 1 will leave those histograms/trees unchanged." << endl;
0061 cout << " Files names and weights can be given in any order." << endl;
0062 cout << " But the first weight found will be assigned to the first file listed," << endl;
0063 cout << " second weight found will be assigned to the second file listed and so on." << endl;
0064 cout << " Output file will be named results.root and will be recreated with subseqent" << endl;
0065 cout << " executions." << endl;
0066 cout << " Return value:" << endl;
0067 cout << " 0 in any error, 1 upon successful completion." << endl;
0068 cout << "======================== END USAGE INFO ==================================================\n" << endl;
0069 return 0;
0070 }
0071
0072 vec_pair inputList;
0073 vector<string> inputFileNames;
0074 vector<double> inputWeights;
0075
0076 try {
0077 for (int i = 1; i < argc; ++i) {
0078
0079 string sargi(argv[i]);
0080
0081
0082 if (sargi.find_first_not_of("1234567890.") == string::npos) {
0083 const double w = atof(argv[i]);
0084 inputWeights.push_back(w);
0085 } else {
0086 inputFileNames.push_back(sargi);
0087 }
0088 }
0089 } catch (exception &e) {
0090 cout << e.what() << endl;
0091 }
0092
0093
0094
0095 if (!inputWeights.empty()) {
0096 if (inputFileNames.size() != inputWeights.size()) {
0097 loginfo('e', "Every input root file must have a corresponding weight! please check!");
0098 return 0;
0099 }
0100 }
0101
0102 for (vector<string>::const_iterator it = inputFileNames.begin(); it != inputFileNames.end(); ++it) {
0103 TFile *f = new TFile(it->c_str());
0104 if (f->IsZombie()) {
0105 cout << "File: " << (*it) << " not found or readable!" << endl;
0106 return 0;
0107 }
0108 f->Close();
0109 delete f;
0110 }
0111
0112 vec_pair vFileList;
0113
0114 for (unsigned i = 0; i < inputFileNames.size(); ++i) {
0115 double w = 1.0;
0116 if (!inputWeights.empty())
0117 w = inputWeights.at(i);
0118 vFileList.push_back(make_pair(TFile::Open(inputFileNames.at(i).c_str()), w));
0119
0120 string msg("");
0121 msg += "File";
0122 if (!inputWeights.empty())
0123 msg += "/Weight";
0124 msg += " = ";
0125 msg += vFileList.at(i).first->GetName();
0126 if (!inputWeights.empty()) {
0127 stringstream swgt;
0128 swgt << " <- " << vFileList.at(i).second;
0129 msg += swgt.str();
0130 }
0131 loginfo('i', msg);
0132 }
0133
0134 Target = TFile::Open("result.root", "RECREATE");
0135 MergeRootfile(Target, vFileList);
0136
0137
0138 Target->Close();
0139 for (vec_pair_it it = vFileList.begin(); it != vFileList.end(); ++it) {
0140 delete (it->first);
0141 }
0142
0143 return 1;
0144 }
0145
0146 void haddws() {
0147
0148
0149
0150
0151
0152
0153 Target = TFile::Open("result.root", "RECREATE");
0154
0155 vec_pair vFileList;
0156 vFileList.push_back(make_pair(TFile::Open("simple1.root"), 1.0));
0157 vFileList.push_back(make_pair(TFile::Open("simple2.root"), 0.5));
0158
0159 for (vec_pair_it it = vFileList.begin(); it != vFileList.end(); ++it) {
0160 cout << "File/weight = " << it->first->GetName() << "/" << it->second << endl;
0161 }
0162
0163 MergeRootfile(Target, vFileList);
0164 Target->Close();
0165
0166 for (vec_pair_it it = vFileList.begin(); it != vFileList.end(); ++it) {
0167 delete (it->first);
0168 }
0169 }
0170
0171 void MergeRootfile(TDirectory *target, const vector<pair<TFile *, double> > &vFileList) {
0172
0173 TString path((char *)strstr(target->GetPath(), ":"));
0174 path.Remove(0, 2);
0175
0176 vec_pair_it it = vFileList.begin();
0177 TFile *first_source = (*it).first;
0178 const double first_weight = (*it).second;
0179 first_source->cd(path);
0180 TDirectory *current_sourcedir = gDirectory;
0181
0182 Bool_t status = TH1::AddDirectoryStatus();
0183 TH1::AddDirectory(kFALSE);
0184
0185
0186 TChain *globChain = nullptr;
0187 TIter nextkey(current_sourcedir->GetListOfKeys());
0188 TKey *key, *oldkey = nullptr;
0189 while ((key = (TKey *)nextkey())) {
0190
0191 if (oldkey && !strcmp(oldkey->GetName(), key->GetName()))
0192 continue;
0193
0194
0195 first_source->cd(path);
0196 TObject *obj = key->ReadObj();
0197
0198 if (obj->IsA()->InheritsFrom(TH1::Class())) {
0199
0200
0201
0202 TH1 *h1 = (TH1 *)obj;
0203 if (first_weight > 0) {
0204 h1->Scale(first_weight);
0205 }
0206
0207
0208
0209 for (vec_pair_it nextsrc = vFileList.begin() + 1; nextsrc != vFileList.end(); ++nextsrc) {
0210
0211 (*nextsrc).first->cd(path);
0212 const double next_weight = (*nextsrc).second;
0213 TKey *key2 = (TKey *)gDirectory->GetListOfKeys()->FindObject(h1->GetName());
0214
0215
0216 if (key2) {
0217 TH1 *h2 = (TH1 *)key2->ReadObj();
0218 if (next_weight > 0) {
0219 h2->Scale(next_weight);
0220 }
0221 if (h1->GetNbinsX() == h2->GetNbinsX()) {
0222 h1->Add(h2);
0223 } else {
0224 loginfo('w',
0225 "Inconsistent binning detected:. Merge will possibly fail for histogram: " +
0226 std::string(h2->GetName()));
0227 h1->Add(h2);
0228 }
0229 delete h2;
0230 }
0231 }
0232
0233 } else if (obj->IsA()->InheritsFrom(TTree::Class())) {
0234
0235 const char *obj_name = obj->GetName();
0236
0237 globChain = new TChain(obj_name);
0238 globChain->Add(first_source->GetName());
0239 for (vec_pair_it nextsrc = vFileList.begin() + 1; nextsrc != vFileList.end(); ++nextsrc) {
0240 globChain->Add(nextsrc->first->GetName());
0241 }
0242
0243 } else if (obj->IsA()->InheritsFrom(TDirectory::Class())) {
0244
0245 loginfo('i', "Found subdirectory " + std::string(obj->GetName()));
0246
0247
0248 target->cd();
0249 TDirectory *newdir = target->mkdir(obj->GetName(), obj->GetTitle());
0250
0251
0252
0253
0254 MergeRootfile(newdir, vFileList);
0255
0256 } else {
0257
0258 cout << "Unknown object type, name: " << obj->GetName() << " title: " << obj->GetTitle() << endl;
0259 }
0260
0261
0262
0263
0264
0265 if (obj) {
0266 target->cd();
0267
0268
0269 if (obj->IsA()->InheritsFrom(TTree::Class()))
0270 globChain->Merge(target->GetFile(), 0, "keep");
0271 else
0272 obj->Write(key->GetName());
0273 }
0274
0275 }
0276
0277
0278 target->SaveSelf(kTRUE);
0279 TH1::AddDirectory(status);
0280 }