Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:33:24

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 }