File indexing completed on 2024-04-06 12:24:16
0001 #include <TFile.h>
0002 #include <TROOT.h>
0003 #include <TKey.h>
0004 #include <TH1.h>
0005 #include <TH2.h>
0006 #include <TDirectory.h>
0007 #include <boost/tokenizer.hpp>
0008 #include <boost/program_options.hpp>
0009 #include <string>
0010 #include <vector>
0011 #include <iostream>
0012 #include <algorithm>
0013 #include <cassert>
0014 #include <sstream>
0015 #include <cstdlib>
0016
0017 using namespace boost::program_options;
0018 using namespace boost;
0019 using namespace std;
0020
0021 void make(TDirectory &out, TObject *o);
0022 void fill(TDirectory &out, TObject *o, double);
0023
0024 static const char *const kHelpOpt = "help";
0025 static const char *const kHelpCommandOpt = "help,h";
0026 static const char *const kOutputFileOpt = "output-file";
0027 static const char *const kOutputFileCommandOpt = "output-file,o";
0028 static const char *const kInputFilesOpt = "input-files";
0029 static const char *const kInputFilesCommandOpt = "input-files,i";
0030 static const char *const kWeightsOpt = "weights";
0031 static const char *const kWeightsCommandOpt = "weights,w";
0032
0033 vector<double> weights;
0034
0035 int main(int argc, char *argv[]) {
0036 string programName(argv[0]);
0037 string descString(programName);
0038 descString += " [options] ";
0039 descString += "data_file \nAllowed options";
0040 options_description desc(descString);
0041
0042 desc.add_options()(kHelpCommandOpt, "produce help message")(
0043 kOutputFileCommandOpt, value<string>()->default_value("out.root"), "output root file")(
0044 kWeightsCommandOpt, value<string>(), "list of weights (comma separates).\ndefault: weights are assumed to be 1")(
0045 kInputFilesCommandOpt, value<vector<string> >()->multitoken(), "input root files");
0046
0047 positional_options_description p;
0048
0049 variables_map vm;
0050 try {
0051 store(command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
0052 notify(vm);
0053 } catch (const error &) {
0054 cerr << "invalid arguments. usage:" << endl;
0055 cerr << desc << std::endl;
0056 return -1;
0057 }
0058
0059 if (vm.count(kHelpOpt)) {
0060 cout << desc << std::endl;
0061 return 0;
0062 }
0063
0064 vector<string> fileNames;
0065 if (vm.count(kInputFilesOpt)) {
0066 fileNames = vm[kInputFilesOpt].as<vector<string> >();
0067 } else {
0068 cerr << "option -i must be specifyed" << endl;
0069 return -1;
0070 }
0071
0072 if (fileNames.empty()) {
0073 cerr << "at least one file name must be specified with option -i" << endl;
0074 return -1;
0075 }
0076
0077 string outputFile;
0078 if (vm.count(kOutputFileOpt)) {
0079 outputFile = vm[kOutputFileOpt].as<string>();
0080 } else {
0081 cerr << "option -o must be specifyed" << endl;
0082 return -1;
0083 }
0084
0085 if (vm.count(kWeightsOpt)) {
0086 string w = vm[kWeightsOpt].as<string>();
0087 char_separator<char> sep(",");
0088 tokenizer<char_separator<char> > tokens(w, sep);
0089 for (tokenizer<char_separator<char> >::iterator t = tokens.begin(); t != tokens.end(); ++t) {
0090 const char *begin = t->c_str();
0091 char *end;
0092 double w = strtod(begin, &end);
0093 size_t s = end - begin;
0094 if (s < t->size()) {
0095 cerr << "invalid weight: " << begin << endl;
0096 exit(1);
0097 }
0098 weights.push_back(w);
0099 }
0100 } else {
0101 weights = vector<double>(fileNames.size(), 1.0);
0102 }
0103 if (weights.size() != fileNames.size()) {
0104 cerr << "the number of weights and the number of files must be the same" << endl;
0105 exit(-1);
0106 }
0107
0108 gROOT->SetBatch();
0109
0110 TFile out(outputFile.c_str(), "RECREATE");
0111 if (!out.IsOpen()) {
0112 cerr << "can't open output file: " << outputFile << endl;
0113 return -1;
0114 }
0115
0116 bool empty = true;
0117 for (size_t i = 0; i < fileNames.size(); ++i) {
0118 string fileName = fileNames[i];
0119 TFile file(fileName.c_str(), "read");
0120 if (!file.IsOpen()) {
0121 cerr << "can't open input file: " << fileName << endl;
0122 return -1;
0123 }
0124
0125 TIter next(file.GetListOfKeys());
0126 TKey *key;
0127 while ((key = dynamic_cast<TKey *>(next()))) {
0128 string className(key->GetClassName());
0129 string name(key->GetName());
0130 TObject *obj = file.Get(name.c_str());
0131 if (obj == nullptr) {
0132 cerr << "error: key " << name << " not found in file " << fileName << endl;
0133 return -1;
0134 }
0135 if (empty)
0136 make(out, obj);
0137 fill(out, obj, weights[i]);
0138 }
0139 file.Close();
0140 empty = false;
0141 }
0142
0143 out.Write();
0144 out.Close();
0145
0146 return 0;
0147 }
0148
0149 void make(TDirectory &out, TObject *o) {
0150 TDirectory *dir;
0151 TH1F *th1f;
0152 TH1D *th1d;
0153 TH2F *th2f;
0154 TH2D *th2d;
0155 out.cd();
0156 if ((dir = dynamic_cast<TDirectory *>(o)) != nullptr) {
0157 TDirectory *outDir = out.mkdir(dir->GetName(), dir->GetTitle());
0158 TIter next(dir->GetListOfKeys());
0159 TKey *key;
0160 while ((key = dynamic_cast<TKey *>(next()))) {
0161 string className(key->GetClassName());
0162 string name(key->GetName());
0163 TObject *obj = dir->Get(name.c_str());
0164 if (obj == nullptr) {
0165 cerr << "error: key " << name << " not found in directory " << dir->GetName() << endl;
0166 exit(-1);
0167 }
0168 make(*outDir, obj);
0169 }
0170 } else if ((th1f = dynamic_cast<TH1F *>(o)) != nullptr) {
0171 TH1F *h = (TH1F *)th1f->Clone();
0172 h->Reset();
0173 h->Sumw2();
0174 h->SetDirectory(&out);
0175 } else if ((th1d = dynamic_cast<TH1D *>(o)) != nullptr) {
0176 TH1D *h = (TH1D *)th1d->Clone();
0177 h->Reset();
0178 h->Sumw2();
0179 h->SetDirectory(&out);
0180 } else if ((th2f = dynamic_cast<TH2F *>(o)) != nullptr) {
0181 TH2F *h = (TH2F *)th2f->Clone();
0182 h->Reset();
0183 h->Sumw2();
0184 h->SetDirectory(&out);
0185 } else if ((th2d = dynamic_cast<TH2D *>(o)) != nullptr) {
0186 TH2D *h = (TH2D *)th2d->Clone();
0187 h->Reset();
0188 h->Sumw2();
0189 h->SetDirectory(&out);
0190 }
0191 }
0192
0193 void fill(TDirectory &out, TObject *o, double w) {
0194 TDirectory *dir;
0195 TH1F *th1f;
0196 TH1D *th1d;
0197 TH2F *th2f;
0198 TH2D *th2d;
0199 if ((dir = dynamic_cast<TDirectory *>(o)) != nullptr) {
0200 const char *name = dir->GetName();
0201 TDirectory *outDir = dynamic_cast<TDirectory *>(out.Get(name));
0202 if (outDir == nullptr) {
0203 cerr << "can't find directory " << name << " in output file" << endl;
0204 exit(-1);
0205 }
0206 TIter next(dir->GetListOfKeys());
0207 TKey *key;
0208 while ((key = dynamic_cast<TKey *>(next()))) {
0209 string className(key->GetClassName());
0210 string name(key->GetName());
0211 TObject *obj = dir->Get(name.c_str());
0212 if (obj == nullptr) {
0213 cerr << "error: key " << name << " not found in directory " << dir->GetName() << endl;
0214 exit(-1);
0215 }
0216 fill(*outDir, obj, w);
0217 }
0218 } else if ((th1f = dynamic_cast<TH1F *>(o)) != nullptr) {
0219 const char *name = th1f->GetName();
0220 TH1F *outTh1f = dynamic_cast<TH1F *>(out.Get(name));
0221 if (outTh1f == nullptr) {
0222 cerr << "error: histogram TH1F" << name << " not found in directory " << out.GetName() << endl;
0223 exit(-1);
0224 }
0225 outTh1f->Add(th1f, w);
0226 } else if ((th1d = dynamic_cast<TH1D *>(o)) != nullptr) {
0227 const char *name = th1d->GetName();
0228 TH1D *outTh1d = dynamic_cast<TH1D *>(out.Get(name));
0229 if (outTh1d == nullptr) {
0230 cerr << "error: histogram TH1D" << name << " not found in directory " << out.GetName() << endl;
0231 exit(-1);
0232 }
0233 outTh1d->Add(th1d, w);
0234 } else if ((th2f = dynamic_cast<TH2F *>(o)) != nullptr) {
0235 const char *name = th2f->GetName();
0236 TH2F *outTh2f = dynamic_cast<TH2F *>(out.Get(name));
0237 if (outTh2f == nullptr) {
0238 cerr << "error: histogram TH2F" << name << " not found in directory " << out.GetName() << endl;
0239 exit(-1);
0240 }
0241 outTh2f->Add(th2f, w);
0242 } else if ((th2d = dynamic_cast<TH2D *>(o)) != nullptr) {
0243 const char *name = th2d->GetName();
0244 TH2D *outTh2d = dynamic_cast<TH2D *>(out.Get(name));
0245 if (outTh2d == nullptr) {
0246 cerr << "error: histogram TH2D" << name << " not found in directory " << out.GetName() << endl;
0247 exit(-1);
0248 }
0249 outTh2d->Add(th2d, w);
0250 }
0251 }