/** >HEADER Copyright (c) 2013 -- 2017 Rob Patro rob.patro@cs.stonybrook.edu This file is part of salmon. salmon is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. salmon is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with salmon. If not, see .
#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // C++ string formatting library #include "spdlog/fmt/fmt.h" #include "GenomicFeature.hpp" #include "SalmonConfig.hpp" #include "VersionChecker.hpp" int help(const std::vector& opts) { //}int argc, char* argv[]) { fmt::MemoryWriter helpMsg; helpMsg.write("salmon v{}\n\n", salmon::version); helpMsg.write( "Usage: salmon -h|--help or \n" " salmon -v|--version or \n" " salmon -c|--cite or \n" " salmon [--no-version-check] [-h | options]\n\n"); helpMsg.write("Commands:\n"); helpMsg.write(" index Create a salmon index\n"); helpMsg.write(" quant Quantify a sample\n"); helpMsg.write(" alevin single cell analysis\n"); helpMsg.write(" swim Perform super-secret operation\n"); helpMsg.write( " quantmerge Merge multiple quantifications into a single file\n"); std::cout << helpMsg.str(); return 0; } int dualModeMessage() { auto helpmsg = R"( =============== salmon quant has two modes --- one quantifies expression using raw reads and the other makes use of already-aligned reads (in BAM/SAM format). Which algorithm is used depends on the arguments passed to salmon quant. If you provide salmon with alignments '-a [ --alignments ]' then the alignment-based algorithm will be used, otherwise the algorithm for quantifying from raw reads will be used. to view the help for salmon's quasi-mapping-based mode, use the command salmon quant --help-reads To view the help for salmon's alignment-based mode, use the command salmon quant --help-alignment )"; std::cout << " salmon v" << salmon::version << helpmsg << "\n"; return 0; } /** * Bonus! */ int salmonSwim(int argc, const char* argv[]) { std::cout << R"( _____ __ / ___/____ _/ /___ ___ ____ ____ \__ \/ __ `/ / __ `__ \/ __ \/ __ \ ___/ / /_/ / / / / / / / /_/ / / / / /____/\__,_/_/_/ /_/ /_/\____/_/ /_/ )"; return 0; } /** * Citation */ void printCite() { std::cout << R"( If you use salmon in your research, please cite the publication in any papers, pre-prints or reports. The proper citation information for salmon appears below. Reference: ========== Rob Patro, Geet Duggal, Michael I. Love, Rafael A. Irizarry, Carl Kingsford. Salmon provides fast and bias-aware quantification of transcript expression. Nature Methods. 2017;14(4):417-419. doi: 10.1038/nmeth.4197 bibtex: ======= @article{Patro2017Salmon, doi = {10.1038/nmeth.4197}, url = {https://doi.org/10.1038%2Fnmeth.4197}, year = {2017}, month = {mar}, publisher = {{Springer Nature}}, volume = {14}, number = {4}, pages = {417--419}, author = {Rob Patro and Geet Duggal and Michael I Love and Rafael A Irizarry and Carl Kingsford}, title = {Salmon provides fast and bias-aware quantification of transcript expression}, journal = {{Nature Methods}} } )"; } int salmonIndex(int argc, const char* argv[]); int salmonQuantify(int argc, const char* argv[]); int salmonAlignmentQuantify(int argc, const char* argv[]); int salmonBarcoding(int argc, const char* argv[]); int salmonQuantMerge(int argc, const char* argv[]); bool verbose = false; int main(int argc, char* argv[]) { using std::string; namespace po = boost::program_options; std::setlocale(LC_ALL, "en_US.UTF-8"); // With no arguments, print help if (argc == 1) { std::vector o; help(o); // argc, argv); std::exit(1); } try { // subcommand parsing code inspired by : // https://gist.github.com/randomphrase/10801888 po::options_description sfopts("Allowed Options"); sfopts.add_options()("version,v", "print version string")( "no-version-check", "don't check with the server to see if this is the latest version")( "cite,c", "show citation information")( "help,h", "produce help message")("command", po::value(), "command to run {index, quant, sf}")( "subargs", po::value>(), "Arguments for command"); po::options_description all("Allowed Options"); all.add(sfopts); po::positional_options_description pd; pd.add("command", 1).add("subargs", -1); po::variables_map vm; po::parsed_options parsed = po::command_line_parser(argc, argv) .options(all) .positional(pd) .allow_unregistered() .run(); po::store(parsed, vm); if (vm.count("version")) { std::cout << "salmon " << salmon::version << "\n"; std::exit(0); } if (vm.count("help") and !vm.count("command")) { std::vector o; help(o); std::exit(0); } if (vm.count("cite") and !vm.count("command")) { printCite(); std::exit(0); } if (!vm.count("no-version-check")) { std::string versionMessage = getVersionMessage(); std::cout << versionMessage; } // po::notify(vm); std::string cmd = vm["command"].as(); std::vector opts = po::collect_unrecognized(parsed.options, po::include_positional); opts.erase(opts.begin()); // if there was a help and a command, then add the help back since it was // parsed if (vm.count("help")) { opts.insert(opts.begin(), "--help"); } std::unordered_map> cmds( {{"index", salmonIndex}, {"quant", salmonQuantify}, {"quantmerge", salmonQuantMerge}, {"alevin", salmonBarcoding}, {"swim", salmonSwim}}); /* //string cmd = vm["command"].as(); int subCommandArgc = argc - topLevelArgc + 1; char** argv2 = new char*[subCommandArgc]; argv2[0] = argv[0]; std::copy_n( &argv[topLevelArgc], argc-topLevelArgc, &argv2[1] ); */ int32_t subCommandArgc = opts.size() + 1; std::unique_ptr argv2(new const char*[subCommandArgc]); argv2[0] = argv[0]; for (int32_t i = 0; i < subCommandArgc - 1; ++i) { argv2[i + 1] = opts[i].c_str(); } auto cmdMain = cmds.find(cmd); if (cmdMain == cmds.end()) { // help(subCommandArgc, argv2); return help(opts); } else { // If the command is quant; determine whether // we're quantifying with raw sequences or alignemnts if (cmdMain->first == "quant") { if (subCommandArgc < 2) { return dualModeMessage(); } // detect mode-specific help request if (strncmp(argv2[1], "--help-alignment", 16) == 0) { std::vector helpStr{'-', '-', 'h', 'e', 'l', 'p', '\0'}; const char* helpArgv[] = {argv[0], &helpStr[0]}; return salmonAlignmentQuantify(2, helpArgv); } else if (strncmp(argv2[1], "--help-reads", 12) == 0) { std::vector helpStr{'-', '-', 'h', 'e', 'l', 'p', '\0'}; const char* helpArgv[] = {argv[0], &helpStr[0]}; return salmonQuantify(2, helpArgv); } // detect general help request if (strncmp(argv2[1], "--help", 6) == 0 or strncmp(argv2[1], "-h", 2) == 0) { return dualModeMessage(); } // otherwise, detect and dispatch the correct mode bool useSalmonAlign{false}; for (int32_t i = 0; i < subCommandArgc; ++i) { if (strncmp(argv2[i], "-a", 2) == 0 or strncmp(argv2[i], "--alignments", 12) == 0) { useSalmonAlign = true; break; } } if (useSalmonAlign) { return salmonAlignmentQuantify(subCommandArgc, argv2.get()); } else { return salmonQuantify(subCommandArgc, argv2.get()); } } else { return cmdMain->second(subCommandArgc, argv2.get()); } } } catch (po::error& e) { std::cerr << "Program Option Error (main) : [" << e.what() << "].\n Exiting.\n"; std::exit(1); } catch (...) { std::cerr << argv[0] << " was invoked improperly.\n"; std::cerr << "For usage information, try " << argv[0] << " --help\nExiting.\n"; } return 0; }