File indexing completed on 2024-09-07 04:37:17
0001
0002 #include <iostream>
0003 #include <fstream>
0004 #include <iomanip>
0005 #include <cstdlib>
0006 #include <cassert>
0007
0008 #include "TString.h"
0009
0010 #include "PhysicsTools/FWLite/interface/CommandLineParser.h"
0011 #include "PhysicsTools/FWLite/interface/dout.h"
0012 #include "PhysicsTools/FWLite/interface/dumpSTL.icc"
0013
0014 using namespace std;
0015 using namespace optutl;
0016
0017 const std::string CommandLineParser::kSpaces = " \t";
0018
0019 CommandLineParser::CommandLineParser(const string &usage, unsigned int optionsType)
0020 : m_argv0(""), m_usageString(usage), m_printOptions(true), m_optionsType(optionsType) {
0021 if (m_optionsType & kEventContOpt) {
0022
0023 addOption("totalSections", kInteger, "Total number of sections", 0);
0024 addOption("section", kInteger, "This section (from 1..totalSections inclusive)", 0);
0025 addOption("maxEvents", kInteger, "Maximum number of events to run over (0 for whole file)", 0);
0026 addOption("jobID", kInteger, "jobID given by CRAB,etc. (-1 means append nothing)", -1);
0027 addOption("outputEvery", kInteger, "Output something once every N events (0 for never)", 0);
0028
0029 addOption("outputFile", kString, "Output filename", "output.root");
0030 addOption("storePrepend", kString, "Prepend location on files starting with '/store/'");
0031 addOption("tag", kString, "A 'tag' to append to output file (e.g., 'v2', etc.)");
0032
0033 addOption("logName", kBool, "Print log name and exit");
0034
0035 addOption("inputFiles", kStringVector, "List of input files");
0036 addOption("secondaryInputFiles", kStringVector, "List of secondary input files (a.k.a. two-file-solution");
0037 addOption("orderedSecondaryFiles", kBool, "Are the secondary files ordered?", false);
0038 return;
0039 }
0040
0041 cerr << "CommandLineParser() Error: type '" << optionsType << "' is not understood. Aborting." << endl;
0042 assert(0);
0043 }
0044
0045 void CommandLineParser::parseArguments(int argc, char **argv, bool returnArgs) {
0046 bool callHelp = false;
0047 SVec argsVec;
0048 m_argv0 = argv[0];
0049 m_fullArgVec.push_back(argv[0]);
0050 for (int loop = 1; loop < argc; ++loop) {
0051 string arg = argv[loop];
0052 m_fullArgVec.push_back(arg);
0053 string::size_type where = arg.find_first_of('=');
0054 if (string::npos != where) {
0055 if (_setVariableFromString(arg)) {
0056 continue;
0057 }
0058 if (_runVariableCommandFromString(arg)) {
0059 continue;
0060 }
0061 cerr << "Don't understand: " << arg << endl;
0062 exit(0);
0063 }
0064 else if (arg.at(0) == '-') {
0065 string::size_type where = arg.find_first_not_of('-');
0066 if (string::npos == where) {
0067
0068 cerr << "Don't understand: " << arg << endl;
0069 exit(0);
0070 continue;
0071 }
0072 lowercaseString(arg);
0073 char first = arg.at(where);
0074
0075 if ('p' == first) {
0076 m_printOptions = true;
0077 continue;
0078 }
0079 if ('n' == first) {
0080 m_printOptions = false;
0081 continue;
0082 }
0083
0084 if ('h' == first) {
0085 callHelp = true;
0086 continue;
0087 }
0088
0089 cerr << "Don't understand: " << arg << endl;
0090 exit(0);
0091 }
0092 if (returnArgs) {
0093 argsVec.push_back(arg);
0094 } else {
0095 cerr << "Don't understand: " << arg << endl;
0096 exit(0);
0097 }
0098 }
0099 if (callHelp) {
0100 help();
0101 }
0102 }
0103
0104 void CommandLineParser::help() {
0105 if (m_usageString.length()) {
0106 cout << m_argv0 << " - " << m_usageString << endl;
0107 }
0108 cout << "--help - This screen" << endl
0109 << "--noPrint - Do not print out all settings" << endl
0110 << "--print - Print out all settings" << endl;
0111 printOptionValues();
0112 exit(0);
0113 }
0114
0115 void CommandLineParser::split(SVec &retval, string line, string match, bool ignoreComments) {
0116 if (ignoreComments) {
0117 removeComment(line);
0118 }
0119 retval.clear();
0120
0121 string::size_type start1 = line.find_first_not_of(kSpaces);
0122
0123 char firstCh = line[start1];
0124 if ('#' == firstCh) {
0125
0126 return;
0127 }
0128
0129 line += match;
0130 string::size_type last = string::npos;
0131 string::size_type current = line.find_first_of(match);
0132 while (string::npos != current) {
0133 string::size_type pos;
0134 if (string::npos != last) {
0135 pos = last + 1;
0136 } else {
0137 pos = 0;
0138 }
0139 string part = line.substr(pos, current - last - 1);
0140
0141 if (part.length()) {
0142 retval.push_back(part);
0143 }
0144 last = current;
0145 current = line.find_first_of(match, current + 1);
0146 }
0147 }
0148
0149 void CommandLineParser::removeComment(string &line) {
0150 string::size_type location = line.find('#');
0151 if (string::npos != location) {
0152
0153 line = line.substr(0, location - 1);
0154 }
0155 }
0156
0157 void CommandLineParser::removeLeadingAndTrailingSpaces(std::string &line) {
0158 string::size_type pos = line.find_first_not_of(kSpaces);
0159 if (string::npos == pos) {
0160
0161 return;
0162 }
0163 if (pos) {
0164
0165 line = line.substr(pos);
0166 }
0167 pos = line.find_last_not_of(kSpaces);
0168 if (pos + 1 != line.length()) {
0169
0170 line = line.substr(0, pos + 1);
0171 }
0172 }
0173
0174 string CommandLineParser::removeEnding(const string &input, const string &ending) {
0175 string::size_type position = input.rfind(ending);
0176 if (input.length() - ending.length() == position) {
0177
0178 return input.substr(0, position);
0179 }
0180
0181 return input;
0182 }
0183
0184 void CommandLineParser::findCommand(const string &line, string &command, string &rest) {
0185 command = rest = "";
0186 string::size_type nonspace = line.find_first_not_of(kSpaces);
0187 if (string::npos == nonspace) {
0188
0189 return;
0190 }
0191 string::size_type space = line.find_first_of(kSpaces, nonspace);
0192 if (string::npos == space) {
0193
0194 command = line.substr(nonspace);
0195 return;
0196 }
0197 command = line.substr(nonspace, space - nonspace);
0198 rest = line.substr(space + 1);
0199 removeLeadingAndTrailingSpaces(rest);
0200 }
0201
0202 void CommandLineParser::printOptionValues() {
0203 cout << "------------------------------------------------------------------" << left << endl;
0204
0205 if (!m_integerMap.empty()) {
0206 cout << endl << "Integer options:" << endl;
0207 }
0208 for (SIMapConstIter iter = m_integerMap.begin(); m_integerMap.end() != iter; ++iter) {
0209 const string &description = m_variableDescriptionMap[iter->first];
0210 cout << " " << setw(14) << iter->first << " = " << setw(14) << iter->second;
0211 if (description.length()) {
0212 cout << " - " << description;
0213 }
0214 cout << endl;
0215 }
0216
0217
0218 if (!m_doubleMap.empty()) {
0219 cout << endl << "Double options:" << endl;
0220 }
0221 for (SDMapConstIter iter = m_doubleMap.begin(); m_doubleMap.end() != iter; ++iter) {
0222 const string &description = m_variableDescriptionMap[iter->first];
0223 cout << " " << setw(14) << iter->first << " = " << setw(14) << iter->second;
0224 if (description.length()) {
0225 cout << " - " << description;
0226 }
0227 cout << endl;
0228 }
0229
0230
0231 if (!m_boolMap.empty()) {
0232 cout << endl << "Bool options:" << endl;
0233 }
0234 for (SBMapConstIter iter = m_boolMap.begin(); m_boolMap.end() != iter; ++iter) {
0235 const string &description = m_variableDescriptionMap[iter->first];
0236 cout << " " << setw(14) << iter->first << " = " << setw(14);
0237 if (iter->second) {
0238 cout << "true";
0239 } else {
0240 cout << "false";
0241 }
0242 if (description.length()) {
0243 cout << " - " << description;
0244 }
0245 cout << endl;
0246 }
0247
0248
0249 if (!m_stringMap.empty()) {
0250 cout << endl << "String options:" << endl;
0251 }
0252 for (SSMapConstIter iter = m_stringMap.begin(); m_stringMap.end() != iter; ++iter) {
0253 const string &description = m_variableDescriptionMap[iter->first];
0254 cout << " " << setw(14) << iter->first << " = ";
0255 const string value = "'" + iter->second + "'";
0256 cout << setw(14) << "";
0257 if (description.length()) {
0258 cout << " - " << description;
0259 }
0260 cout << endl << " " << value << endl;
0261 }
0262
0263
0264 if (!m_integerVecMap.empty()) {
0265 cout << endl << "Integer Vector options:" << endl;
0266 }
0267 for (SIVecMapConstIter iter = m_integerVecMap.begin(); m_integerVecMap.end() != iter; ++iter) {
0268 const string &description = m_variableDescriptionMap[iter->first];
0269 cout << " " << setw(14) << iter->first << " = ";
0270 dumpSTL(iter->second);
0271 cout << endl;
0272 if (description.length()) {
0273 cout << " - " << description;
0274 }
0275 cout << endl;
0276 }
0277
0278
0279 if (!m_doubleVecMap.empty()) {
0280 cout << endl << "Double Vector options:" << endl;
0281 }
0282 for (SDVecMapConstIter iter = m_doubleVecMap.begin(); m_doubleVecMap.end() != iter; ++iter) {
0283 const string &description = m_variableDescriptionMap[iter->first];
0284 cout << " " << setw(14) << iter->first << " = ";
0285 dumpSTL(iter->second);
0286 cout << endl;
0287 if (description.length()) {
0288 cout << " - " << description;
0289 }
0290 cout << endl;
0291 }
0292
0293
0294 if (!m_stringVecMap.empty()) {
0295 cout << endl << "String Vector options:" << endl;
0296 } else {
0297 cout << endl;
0298 }
0299 for (SSVecMapConstIter iter = m_stringVecMap.begin(); m_stringVecMap.end() != iter; ++iter) {
0300 const string &description = m_variableDescriptionMap[iter->first];
0301 cout << " " << setw(14) << iter->first << " = ";
0302 if (description.length()) {
0303 cout << setw(14) << ""
0304 << " - " << description;
0305 }
0306 cout << endl;
0307 dumpSTLeachEndl(iter->second, 8);
0308 }
0309
0310 cout << "------------------------------------------------------------------" << right << endl;
0311 }
0312
0313 bool CommandLineParser::_setVariableFromString(const string &arg, bool dontOverrideChange, int offset) {
0314 string::size_type where = arg.find_first_of('=', offset + 1);
0315 string varname = arg.substr(offset, where - offset);
0316 string value = arg.substr(where + 1);
0317 lowercaseString(varname);
0318
0319 SBMapConstIter sbiter = m_variableModifiedMap.find(varname);
0320 if (m_variableModifiedMap.end() == sbiter) {
0321
0322 return false;
0323 }
0324
0325
0326 if (dontOverrideChange && _valueHasBeenModified(varname)) {
0327
0328 return true;
0329 }
0330
0331 SIMapIter integerIter = m_integerMap.find(varname);
0332 if (m_integerMap.end() != integerIter) {
0333
0334
0335 integerIter->second = (int)atof(value.c_str());
0336 m_variableModifiedMap[varname] = true;
0337 return true;
0338 }
0339
0340 SDMapIter doubleIter = m_doubleMap.find(varname);
0341 if (m_doubleMap.end() != doubleIter) {
0342
0343 doubleIter->second = atof(value.c_str());
0344 m_variableModifiedMap[varname] = true;
0345 return true;
0346 }
0347
0348 SSMapIter stringIter = m_stringMap.find(varname);
0349 if (m_stringMap.end() != stringIter) {
0350
0351 stringIter->second = value;
0352 m_variableModifiedMap[varname] = true;
0353 return true;
0354 }
0355
0356 SBMapIter boolIter = m_boolMap.find(varname);
0357 if (m_boolMap.end() != boolIter) {
0358
0359 boolIter->second = 0 != atoi(value.c_str());
0360 m_variableModifiedMap[varname] = true;
0361 return true;
0362 }
0363
0364 SIVecMapIter integerVecIter = m_integerVecMap.find(varname);
0365 if (m_integerVecMap.end() != integerVecIter) {
0366
0367 SVec words;
0368 split(words, value, ",");
0369 for (SVecConstIter wordIter = words.begin(); words.end() != wordIter; ++wordIter) {
0370 integerVecIter->second.push_back((int)atof(wordIter->c_str()));
0371 }
0372
0373
0374
0375 return true;
0376 }
0377
0378 SDVecMapIter doubleVecIter = m_doubleVecMap.find(varname);
0379 if (m_doubleVecMap.end() != doubleVecIter) {
0380
0381 SVec words;
0382 split(words, value, ",");
0383 for (SVecConstIter wordIter = words.begin(); words.end() != wordIter; ++wordIter) {
0384 doubleVecIter->second.push_back(atof(wordIter->c_str()));
0385 }
0386
0387
0388
0389 return true;
0390 }
0391
0392 SSVecMapIter stringVecIter = m_stringVecMap.find(varname);
0393 if (m_stringVecMap.end() != stringVecIter) {
0394
0395 SVec words;
0396 split(words, value, ",");
0397 for (SVecConstIter wordIter = words.begin(); words.end() != wordIter; ++wordIter) {
0398 stringVecIter->second.push_back(*wordIter);
0399 }
0400
0401
0402
0403 return true;
0404 }
0405
0406
0407 cerr << "CommandLineParser::SetVeriableFromString() Error: "
0408 << "Unknown variable and internal fault. Aborting." << endl;
0409 assert(0);
0410 return false;
0411 }
0412
0413 bool CommandLineParser::_setVariablesFromFile(const string &filename) {
0414 ifstream source(filename.c_str(), ios::in);
0415 if (!source) {
0416 cerr << "file " << filename << "could not be opened" << endl;
0417 return false;
0418 }
0419 string line;
0420 while (getline(source, line)) {
0421
0422 string::size_type where = line.find_first_not_of(kSpaces);
0423 if (string::npos == where) {
0424
0425 continue;
0426 }
0427 char first = line.at(where);
0428 if ('-' != first) {
0429 continue;
0430 }
0431 where = line.find_first_not_of(kSpaces, where + 1);
0432 if (string::npos == where) {
0433
0434 continue;
0435 }
0436
0437
0438
0439 string withspaces = line.substr(where);
0440 string nospaces;
0441 for (int position = 0; position < (int)withspaces.length(); ++position) {
0442 char ch = withspaces[position];
0443 if ('#' == ch) {
0444
0445 break;
0446 } else if (' ' == ch || '\t' == ch) {
0447 continue;
0448 }
0449 nospaces += ch;
0450 }
0451 if (!_setVariableFromString(nospaces, true)) {
0452 cerr << "Don't understand line" << endl
0453 << line << endl
0454 << "in options file '" << filename << "'. Aborting." << endl;
0455 exit(0);
0456 }
0457 }
0458 return true;
0459 }
0460
0461 bool CommandLineParser::_runVariableCommandFromString(const string &arg) {
0462 SVec equalWords;
0463 split(equalWords, arg, "=");
0464 if (2 != equalWords.size()) {
0465 return false;
0466 }
0467 SVec commandWords;
0468 split(commandWords, equalWords.at(0), "_");
0469 if (2 != commandWords.size()) {
0470 return false;
0471 }
0472 string &command = commandWords.at(1);
0473 lowercaseString(command);
0474 if (command != "load" && command != "clear") {
0475 return false;
0476 }
0477 const string &key = commandWords.at(0);
0478 OptionType type = hasOption(key);
0479 if (type < kIntegerVector || type > kStringVector) {
0480 cerr << "Command '" << command << "' only works on vectors." << endl;
0481 return false;
0482 }
0483
0484
0485
0486
0487 if ("clear" == command) {
0488 if (kIntegerVector == type) {
0489 integerVector(key).clear();
0490 } else if (kDoubleVector == type) {
0491 doubleVector(key).clear();
0492 } else if (kStringVector == type) {
0493 stringVector(key).clear();
0494 } else {
0495
0496
0497 assert(0);
0498 }
0499 return true;
0500 }
0501
0502
0503
0504
0505 const string &filename = equalWords.at(1);
0506 ifstream source(filename.c_str(), ios::in);
0507 if (!source) {
0508 cerr << "file " << filename << "could not be opened" << endl;
0509 return false;
0510 }
0511 string line;
0512 while (getline(source, line)) {
0513
0514 string::size_type where = line.find_first_not_of(kSpaces);
0515 if (string::npos == where) {
0516
0517 continue;
0518 }
0519
0520 line = line.substr(where);
0521
0522 where = line.find_last_not_of(kSpaces);
0523 if (line.length() - 1 != where) {
0524 line = line.substr(0, where + 1);
0525 }
0526 if ('#' == line.at(0)) {
0527
0528 continue;
0529 }
0530 if (kIntegerVector == type) {
0531 integerVector(key).push_back((int)atof(line.c_str()));
0532 } else if (kDoubleVector == type) {
0533 doubleVector(key).push_back(atof(line.c_str()));
0534 } else if (kStringVector == type) {
0535 stringVector(key).push_back(line);
0536 } else {
0537
0538
0539 assert(0);
0540 }
0541 }
0542 return true;
0543 }
0544
0545 void CommandLineParser::_getSectionFiles(const SVec &inputList, SVec &outputList, int section, int totalSections) {
0546
0547 assert(section > 0 && section <= totalSections);
0548
0549
0550
0551
0552
0553
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563 int entries = (int)inputList.size();
0564 int perSection = entries / totalSections;
0565 int extra = entries % totalSections;
0566 --section;
0567 int current = perSection * section;
0568 int num = perSection - 1;
0569 if (section < extra) {
0570 current += section;
0571 ++num;
0572 } else {
0573 current += extra;
0574 }
0575 outputList.clear();
0576
0577
0578 for (int loop = current; loop <= current + num; ++loop) {
0579 outputList.push_back(inputList.at(loop));
0580 }
0581 }
0582
0583 void CommandLineParser::_finishDefaultOptions(std::string tag) {
0584 if (!(m_optionsType & kEventContOpt)) {
0585
0586 return;
0587 }
0588
0589
0590
0591 if (integerValue("totalSections")) {
0592
0593
0594 tag += Form("_sec%03d", integerValue("section"));
0595 SVec tempVec;
0596 _getSectionFiles(stringVector("inputFiles"), tempVec, integerValue("section"), integerValue("totalSections"));
0597 stringVector("inputFiles") = tempVec;
0598 }
0599
0600
0601
0602
0603 const string &kStorePrepend = stringValue("storePrepend");
0604 if (kStorePrepend.length()) {
0605 string match = "/store/";
0606 int matchLen = match.length();
0607 SVec tempVec;
0608 SVec ¤tFiles = stringVector("inputFiles");
0609 for (SVecConstIter iter = currentFiles.begin(); currentFiles.end() != iter; ++iter) {
0610 const string &filename = *iter;
0611 if ((int)filename.length() > matchLen && filename.substr(0, matchLen) == match) {
0612 tempVec.push_back(kStorePrepend + filename);
0613 } else {
0614 tempVec.push_back(filename);
0615 }
0616 }
0617 currentFiles = tempVec;
0618 }
0619
0620
0621
0622
0623
0624
0625 string outputFile = stringValue("outputFile");
0626 bool modifyOutputFile = (outputFile.length());
0627 outputFile = removeEnding(outputFile, ".root");
0628 outputFile += tag;
0629 if (integerValue("maxEvents")) {
0630 outputFile += Form("_maxevt%03d", integerValue("maxEvents"));
0631 }
0632 if (integerValue("jobID") >= 0) {
0633 outputFile += Form("_jobID%03d", integerValue("jobID"));
0634 }
0635 if (stringValue("tag").length()) {
0636 outputFile += "_" + stringValue("tag");
0637 }
0638
0639
0640
0641
0642 if (boolValue("logName")) {
0643 cout << outputFile << ".log" << endl;
0644 exit(0);
0645 }
0646 outputFile += ".root";
0647 if (modifyOutputFile) {
0648 stringValue("outputFile") = outputFile;
0649 }
0650
0651
0652
0653 if (m_printOptions) {
0654 printOptionValues();
0655 }
0656 }
0657
0658
0659 ostream &operator<<(ostream &o_stream, const CommandLineParser &rhs) { return o_stream; }