예제 #1
0
seqan::ArgumentParser::ParseResult
parseArgs(FxSamCoverageOptions & options,
          int argc,
          char const ** argv)
{
    seqan::ArgumentParser parser("fx_sam_coverage");
    setShortDescription(parser, "Read Coverage Computation.");
    setVersion(parser, "0.1");
    setDate(parser, "August 2012");
    
    addUsageLine(parser, "[\\fIOPTIONS\\fP] \\fB-o\\fP \\fIOUT.tsv\\fP \\fIGENOME.fa\\fP \\fIMAPPING.sam\\fP");
    addDescription(parser, "Compute read coverage and C+G content for a genome.");

    // Two input files: Genome, and mapping.
    addArgument(parser, seqan::ArgParseArgument(seqan::ArgParseArgument::INPUTFILE));
    setValidValues(parser, 0, "fasta fa");
    addArgument(parser, seqan::ArgParseArgument(seqan::ArgParseArgument::INPUTFILE));
    setValidValues(parser, 1, "sam");

    // TODO(holtgrew): I want a custom help text!
    // addOption(parser, seqan::ArgParseOption("h", "help", "This helpful screen."));
    addOption(parser, seqan::ArgParseOption("v", "verbose", "Verbose, log to STDERR."));
    hideOption(parser, "verbose");
    addOption(parser, seqan::ArgParseOption("vv", "very-verbose", "Very verbose, log to STDERR."));
    hideOption(parser, "very-verbose");

    addSection(parser, "Main Options");
    addOption(parser, seqan::ArgParseOption("w", "window-size", "Set the size of the non-overlapping windows in base pairs.", seqan::ArgParseArgument::INTEGER, "NUM"));
    setDefaultValue(parser, "window-size", "10000");

    addSection(parser, "Output Options");
    addOption(parser, seqan::ArgParseOption("o", "out-path", "Path to the resulting file.  If omitted, result is printed to stdout.", seqan::ArgParseArgument::OUTPUTFILE, "TSV"));
    setRequired(parser, "out-path");
    setValidValues(parser, "out-path", "sam.coverage.tsv");

    seqan::ArgumentParser::ParseResult res = parse(parser, argc, argv);

    if (res == seqan::ArgumentParser::PARSE_OK)
    {
        getArgumentValue(options.inGenomePath, parser, 0);
        getArgumentValue(options.inSamPath, parser, 1);
        getOptionValue(options.outPath, parser, "out-path");

        if (isSet(parser, "verbose"))
            options.verbosity = 2;
        if (isSet(parser, "very-verbose"))
            options.verbosity = 3;
    }

    return res;
}
예제 #2
0
seqan::ArgumentParser buildParser(void)
{
    seqan::ArgumentParser parser;

    setCategory(parser, "5-prime end counter");
    setShortDescription(parser, "Preprocessing Pipeline for Chip-Nexus and Chip-Exo data");
    addUsageLine(parser, " \\fI<READ_FILE1> \\fP \\fI[OPTIONS]\\fP");
    addDescription(parser,
        "");

    addDescription(parser, "");

    seqan::setVersion(parser, SEQAN_APP_VERSION " [" SEQAN_REVISION "]");
    setDate(parser, SEQAN_DATE);

    seqan::ArgParseArgument fileArg(seqan::ArgParseArgument::INPUT_FILE, "positions in bed-format", true);
    setValidValues(fileArg, ".bed");
    addArgument(parser, fileArg);
    setHelpText(parser, 0, "bed file");

    seqan::ArgParseOption readsOpt = seqan::ArgParseOption(
        "i", "input", "Name of the reads file.",
        seqan::ArgParseOption::INPUT_FILE, "INPUT");
    setValidValues(readsOpt, seqan::BamFileIn::getFileExtensions());
    addOption(parser, readsOpt);

    seqan::ArgParseOption outputOpt = seqan::ArgParseOption(
        "o", "output", "Name of output file.",
        seqan::ArgParseOption::INPUT_FILE, "INPUT");
    addOption(parser, outputOpt);

    seqan::ArgParseOption radiusOpt = seqan::ArgParseOption(
        "r", "radius", "radius around peaks to scan ",
        seqan::ArgParseOption::INTEGER, "VALUE");
    setDefaultValue(radiusOpt, 1000);
    setMinValue(radiusOpt, "1");
    addOption(parser, radiusOpt);

    seqan::ArgParseOption filterChromosomesOpt = seqan::ArgParseOption(
        "fc", "filterChromosomes", "Regular expression to remove chromosomes",
        seqan::ArgParseOption::STRING, "REGEX");
    addOption(parser, filterChromosomesOpt);

    return parser;
}
예제 #3
0
파일: sak.cpp 프로젝트: abadd0n/seqan
seqan::ArgumentParser::ParseResult
parseArgs(SakOptions & options,
          int argc,
          char ** argv)
{
    seqan::ArgumentParser parser("sak");
    setShortDescription(parser, "Slicing and dicing of FASTA/FASTQ files..");
    setVersion(parser, SEQAN_APP_VERSION " [" SEQAN_REVISION "]");
    setDate(parser, SEQAN_DATE);
    setCategory(parser, "Utilities");

    addUsageLine(parser, "[\\fIOPTIONS\\fP] [\\fB-o\\fP \\fIOUT.{fa,fq}\\fP] \\fIIN.{fa,fq}\\fP");
    addDescription(parser, "\"It slices, it dices and it makes the laundry!\"");
    addDescription(parser, "Original SAK tool by David Weese. Rewrite by Manuel Holtgrewe.");

    // The only argument is the input file.
    addArgument(parser, seqan::ArgParseArgument(seqan::ArgParseArgument::INPUT_FILE, "IN"));

    // Only FASTA and FASTQ files are allowed as input.
    setValidValues(parser, 0, seqan::SeqFileIn::getFileExtensions());

    // TODO(holtgrew): I want a custom help text!
    // addOption(parser, seqan::ArgParseOption("h", "help", "This helpful screen."));
    addOption(parser, seqan::ArgParseOption("v", "verbose", "Verbose, log to STDERR."));
    hideOption(parser, "verbose");
    addOption(parser, seqan::ArgParseOption("vv", "very-verbose", "Very verbose, log to STDERR."));
    hideOption(parser, "very-verbose");

    addSection(parser, "Output Options");
    addOption(parser, seqan::ArgParseOption("o", "out-path",
                                            "Path to the resulting file.  If omitted, result is printed to stdout in FastQ format.",
                                            seqan::ArgParseOption::OUTPUT_FILE, "FASTX"));
    setValidValues(parser, "out-path", seqan::SeqFileOut::getFileExtensions());
    addOption(parser, seqan::ArgParseOption("rc", "revcomp", "Reverse-complement output."));
    addOption(parser, seqan::ArgParseOption("l", "max-length", "Maximal number of sequence characters to write out.",
                                            seqan::ArgParseOption::INTEGER, "LEN"));

    addSection(parser, "Filter Options");
    addOption(parser, seqan::ArgParseOption("s", "sequence", "Select the given sequence for extraction by 0-based index.",
                                            seqan::ArgParseOption::INTEGER, "NUM", true));
    addOption(parser, seqan::ArgParseOption("sn", "sequence-name", "Select sequence with name prefix being \\fINAME\\fP.",
                                            seqan::ArgParseOption::STRING, "NAME", true));
    addOption(parser, seqan::ArgParseOption("ss", "sequences",
                                            "Select sequences \\fIfrom\\fP-\\fIto\\fP where \\fIfrom\\fP and \\fIto\\fP "
                                            "are 0-based indices.",
                                            seqan::ArgParseArgument::STRING, "RANGE", true));
    addOption(parser, seqan::ArgParseOption("i", "infix",
                                            "Select characters \\fIfrom\\fP-\\fIto\\fP where \\fIfrom\\fP and \\fIto\\fP "
                                            "are 0-based indices.",
                                            seqan::ArgParseArgument::STRING, "RANGE", true));

    addOption(parser, seqan::ArgParseOption("ll", "line-length",
                                            "Set line length in output file.  See section \\fILine Length\\fP for details.",
                                            seqan::ArgParseArgument::INTEGER, "LEN", false));
    setMinValue(parser, "line-length", "-1");

    addTextSection(parser, "Line Length");
    addText(parser,
            "You can use the setting \\fB--line-length\\fP for setting the resulting line length.  By default, "
            "sequences in FASTA files are written with at most 70 characters per line and sequences in FASTQ files are "
            "written without any line breaks.  The quality sequence in FASTQ file is written in the same way as the "
            "residue sequence.");
    addText(parser,
            "The default is selected with a \\fB--line-length\\fP value of \\fI-1\\fP and line breaks can be disabled "
            "with a value of \\fI0\\fP.");

    addTextSection(parser, "Usage Examples");
    addListItem(parser, "\\fBsak\\fP \\fB-s\\fP \\fI10\\fP \\fIIN.fa\\fP",
                "Cut out 11th sequence from \\fIIN.fa\\fP and write to stdout as FASTA.");
    addListItem(parser, "\\fBsak\\fP \\fB-ss\\fP \\fI10-12\\fP \\fB-ss\\fP \\fI100-200\\fP \\fIIN.fq\\fP",
                "Cut out 11th up to and including 12th and 101th up to and including 199th sequence from \\fIIN.fq\\fP "
                "and write to stdout as FASTA.");

    seqan::ArgumentParser::ParseResult res = parse(parser, argc, argv);

    if (res != seqan::ArgumentParser::PARSE_OK)
        return res;

    getArgumentValue(options.inFastxPath, parser, 0);

    seqan::CharString tmp;
    getOptionValue(tmp, parser, "out-path");

    if (isSet(parser, "out-path"))
        getOptionValue(options.outPath, parser, "out-path");

    if (isSet(parser, "verbose"))
        options.verbosity = 2;
    if (isSet(parser, "very-verbose"))
        options.verbosity = 3;

    if (isSet(parser, "sequence"))
    {
        std::vector<std::string> sequenceIds = getOptionValues(parser, "sequence");
        for (unsigned i = 0; i < seqan::length(sequenceIds); ++i)
        {
            unsigned idx = 0;
            if (!seqan::lexicalCast(idx, sequenceIds[i]))
            {
                std::cerr << "ERROR: Invalid sequence index " << sequenceIds[i] << "\n";
                return seqan::ArgumentParser::PARSE_ERROR;
            }
            appendValue(options.seqIndices, idx);
        }
    }

    if (isSet(parser, "sequences"))
    {
        std::vector<std::string> sequenceRanges = getOptionValues(parser, "sequences");
        seqan::CharString buffer;
        for (unsigned i = 0; i < seqan::length(sequenceRanges); ++i)
        {
            seqan::Pair<uint64_t> range;
            if (!parseRange(range.i1, range.i2, sequenceRanges[i]))
            {
                std::cerr << "ERROR: Invalid range " << sequenceRanges[i] << "\n";
                return seqan::ArgumentParser::PARSE_ERROR;
            }
            appendValue(options.seqIndexRanges, range);
        }
    }

    if (isSet(parser, "infix"))
    {
        seqan::CharString buffer;
        getOptionValue(buffer, parser, "infix");
        if (!parseRange(options.seqInfixBegin, options.seqInfixEnd, buffer))
        {
            std::cerr << "ERROR: Invalid range " << buffer << "\n";
            return seqan::ArgumentParser::PARSE_ERROR;
        }
    }

    options.reverseComplement = isSet(parser, "revcomp");

    if (isSet(parser, "max-length"))
        getOptionValue(options.maxLength, parser, "max-length");

    if (isSet(parser, "sequence-name"))
        getOptionValue(options.readPattern, parser, "sequence-name");

    getOptionValue(options.seqOutOptions.lineLength, parser, "line-length");

    return res;
}
예제 #4
0
seqan::ArgumentParser::ParseResult
parseCommandLine(Options & options, int argc, char const ** argv)
{
    // Setup ArgumentParser.
    seqan::ArgumentParser parser("roiGFF");

    // Set short description, version, and date.
    setShortDescription(parser, "get ROIs based on GFF annotation");
    setVersion(parser, VERSION);
    setDate(parser, "March 2013");

    // Define usage line and long description.
    addUsageLine(parser,
                 "[\\fIOPTIONS\\fP] \\fB-if\\fP \\fIIN.roi\\fP"
				 "\\fB-ig\\fP \\fIIN.gff\fP"
                 "\\fB-of\\fP \\fIOUT.roi\\fP"
				 "[\\fB-ss\\fP] [\\fB-t\\fP \\fItype\\fP] "
				 "[\\fB-p\\fP \\fIparent attribute\\fP]]");
	addDescription(parser,
       "Takes regions from GFF file, calculates the overlap with the ROI file"
       "and creates a new ROI file based on the GFF regions.");
	
	// General Options

    addOption(parser, seqan::ArgParseOption("v", "verbose", "Verbose mode."));
    addOption(parser, seqan::ArgParseOption("vv", "vverbose", "Very verbose mode."));

    // Input / Output Options

    addSection(parser, "Input / Output Parameters");

	addOption(parser, seqan::ArgParseOption("if", "roi-file", "roi file", seqan::ArgParseOption::INPUTFILE));
    setValidValues(parser, "roi-file", "roi");
    setRequired(parser, "roi-file");

	addOption(parser, seqan::ArgParseOption("ig", "gff-file", "gff file", seqan::ArgParseOption::INPUTFILE));
    setValidValues(parser, "gff-file", "gff");
    setRequired(parser, "gff-file");

    addOption(parser, seqan::ArgParseOption("of", "output-file", "Output file", seqan::ArgParseOption::OUTPUTFILE));
    setValidValues(parser, "output-file", "roi");
    setRequired(parser, "output-file");

    // Optional Parameter
	addOption(parser,
		seqan::ArgParseOption("ss", "strandspecific",
			"calculate strandspecific stats (only position sorted)"));

	addOption(parser,
		seqan::ArgParseOption("t", "type",
		"Type to used (3. column in GFF file). If not set all types will be used."
		"There can only be one or none set.", seqan::ArgParseOption::STRING));
	setDefaultValue(parser, "type", "");

	addOption(parser,
		seqan::ArgParseOption("p", "parent",
			"tag to used to identify regions that should be concatednated."
			"They are sorted by start position and then concatenated. If empty/not set"
			"there will be no concatenation performed", 
			seqan::ArgParseOption::STRING));
	setDefaultValue(parser, "parent", "");


    // Parse command line.
    seqan::ArgumentParser::ParseResult res = seqan::parse(parser, argc, argv);

    // Extract option values.
	if (isSet(parser, "verbose"))
        options.verbosity = 1;
    if (isSet(parser, "vverbose"))
        options.verbosity = 2;

    getOptionValue(options.roiFileName, parser, "roi-file");
    getOptionValue(options.gffFileName, parser, "gff-file");
    getOptionValue(options.outputFileName, parser, "output-file");
    getOptionValue(options.strandSpecific, parser, "strandspecific");
    getOptionValue(options.type, parser, "type");
    getOptionValue(options.parent, parser, "parent");
	
    return seqan::ArgumentParser::PARSE_OK;

}
예제 #5
0
seqan::ArgumentParser::ParseResult
parseCommandLine(SeqConsOptions & options, int argc, char const ** argv)
{
    // Setup ArgumentParser.
    seqan::ArgumentParser parser("seqcons2");
    // Set short description, version, and date.
    setShortDescription(parser, "Compute consensus from sequences.");
    setVersion(parser, SEQAN_APP_VERSION " [" SEQAN_REVISION "]");
    setDate(parser, SEQAN_DATE);

    // Define usage line and long description.
    addUsageLine(parser,
                 "\\fB-i\\fP \\fIINPUT.{fa,sam}\\fP [\\fB-oa\\fP \\fIOUT_ALIGN.{fa,sam}\\fP] "
                 "[\\fB-oc\\fP \\fIOUT_CONSENSUS.fa\\fP]");
    addDescription(parser,
                   "Compute consensus from sequences with and without approximate alignment information.");

    // Overall Program Options
    addOption(parser, seqan::ArgParseOption("q", "quiet", "Set verbosity to a minimum."));
    addOption(parser, seqan::ArgParseOption("v", "verbose", "Enable verbose output."));
    addOption(parser, seqan::ArgParseOption("vv", "very-verbose", "Enable very verbose output."));

    addOption(parser, seqan::ArgParseOption("m", "method", "Method to perform.  See section \\fIMethods\\fP "
                                            "below for details.", seqan::ArgParseOption::STRING, "METHOD"));
    setValidValues(parser, "method", "nop realign align_consensus overlap_consensus contig_consensus pos_consensus");
    setDefaultValue(parser, "method", "pos_consensus");

    // I/O Options
    addSection(parser, "I/O Options");

    addOption(parser, seqan::ArgParseOption("i", "input-file", "Input file.", seqan::ArgParseOption::INPUT_FILE,
                                            "INPUT"));
    setRequired(parser, "input-file", true);
    setValidValues(parser, "input-file", "sam fa fasta");

    addOption(parser, seqan::ArgParseOption("oa", "output-alignment-file", "Output file with alignment.",
                                            seqan::ArgParseOption::OUTPUT_FILE, "OUT_ALIGNMENT"));
    setRequired(parser, "output-alignment-file", false);
    setValidValues(parser, "output-alignment-file", "sam txt");

    addOption(parser, seqan::ArgParseOption("oc", "output-consensus-file", "Output file with consensus sequence.",
                                            seqan::ArgParseOption::OUTPUT_FILE, "OUT_CONSENSUS"));
    setRequired(parser, "output-consensus-file", false);
    setValidValues(parser, "output-consensus-file", "fa fasta");

    // Alignment Quality Filter Options
    addSection(parser, "Alignment Quality Filter Options");

    addOption(parser, seqan::ArgParseOption("", "overlap-min-length", "Minimal overlap length.",
                                            seqan::ArgParseOption::INTEGER, "LENGTH"));
    setMinValue(parser, "overlap-min-length", "0");
    setDefaultValue(parser, "overlap-min-length", "20");

    addOption(parser, seqan::ArgParseOption("", "overlap-max-error", "Maximal error rate in overlap as percentage.",
                                            seqan::ArgParseOption::DOUBLE, "RATE"));
    setMinValue(parser, "overlap-max-error", "0.0");
    setDefaultValue(parser, "overlap-max-error", "5.0");

    addOption(parser, seqan::ArgParseOption("", "overlap-min-count", "Minimal overlap count.",
                                            seqan::ArgParseOption::INTEGER, "COUNT"));
    setMinValue(parser, "overlap-min-count", "0");
    setDefaultValue(parser, "overlap-min-count", "3");

    addOption(parser, seqan::ArgParseOption("", "overlap-window-size", "Window size to look for alignments.",
                                            seqan::ArgParseOption::INTEGER, "SIZE"));
    setMinValue(parser, "overlap-window-size", "0");
    setDefaultValue(parser, "overlap-window-size", "20");

    // K-mer Filter Options
    addSection(parser, "K-Mer Filter Options");

    addOption(parser, seqan::ArgParseOption("", "k-mer-size", "The k-mer size to use.",
                                            seqan::ArgParseOption::INTEGER, "LENGTH"));
    setMinValue(parser, "k-mer-size", "5");
    setDefaultValue(parser, "k-mer-size", "20");

    addOption(parser, seqan::ArgParseOption("", "k-mer-max-occ", "Ignore k-mer with higher occurence count, 0 to disable.",
                                            seqan::ArgParseOption::INTEGER, "COUNT"));
    setMinValue(parser, "k-mer-max-occ", "0");
    setDefaultValue(parser, "k-mer-max-occ", "200");

    // Realignment Options
    addSection(parser, "Realignment Options");

    addOption(parser, seqan::ArgParseOption("", "realign-bandwidth",
                                            "Bandwidth to use for pairwise alignments in realignment.",
                                            seqan::ArgParseOption::INTEGER, "LENGTH"));
    setMinValue(parser, "realign-bandwidth", "5");
    setDefaultValue(parser, "realign-bandwidth", "10");

    addOption(parser, seqan::ArgParseOption("", "realign-environment",
                                            "Environment for extraction in realignment.",
                                            seqan::ArgParseOption::INTEGER, "COUNT"));
    setMinValue(parser, "realign-environment", "5");
    setDefaultValue(parser, "realign-environment", "20");

    // Add Methods Section
    addTextSection(parser, "Methods");
    addListItem(parser, "\\fBnop\\fP",
                "Perform no action, just perform file conversion if possible.");
    addListItem(parser, "\\fBrealign\\fP",
                "Perform realignment, requires input to be a SAM file to provide approximate position "
                "information, creates consensus sequence after realignment.");
    addListItem(parser, "\\fBoverlap_consensus\\fP",
                "Perform MSA with overlap alignments of the input ignoring any given coordinates, then realign. "
                "This is most suited when computing the consensus of reads where the underlying sequence is very "
                "similar and most differences stem from sequencing errors and not genomic variation. All "
                "pairwise alignments computed here are banded.");
    addListItem(parser, "\\fBalign_consensus\\fP",
                "Perform MSA with global alignments of the input ignoring any given coordinates, then realign. "
                "This will computed unbanded global ends-gap free pairwise alignments.  This is also suitable "
                "when aligning different sequences, e.g. clustered transcripts.  Using this method, seqcons "
                "will be similar to calling SeqAn::T-Coffee, followed by realignment and consensus computation.");
    addListItem(parser, "\\fBcontig_consensus\\fP",
                "Perform MSA of the input, contig by contig, requires contig information, then realign. Input "
                "must be SAM.");
    addListItem(parser, "\\fBpos_consensus\\fP",
                "Perform consensus of the input, then realign. Requires approximate coordinate information in "
                "SAM file.");

    // Add Output Section
    addTextSection(parser, "Output Formats");
    addText(parser,
            "The program can write out the consensus sequence in FASTA format and optionally the alignment of the "
            "input sequences against the consensus in SAM/BAM format.  When using the extension \\fI.txt\\fP, seqcons "
            "will write out the MSA as a plain text visualization.");

    // Add Examples Section
    addTextSection(parser, "Examples");
    addListItem(parser,
                "\\fBseqcons\\fP \\fB-m\\fP \\fIovl_consensus\\fP \\fB-i\\fP \\fIreads.fa\\fP \\fB-oa\\fP "
                "\\fIout.sam\\fP \\fB-oc\\fP \\fIcons.fa\\fP",
                "Compute MSA of the sequences in \\fIreads.fa\\fP.  The consensus sequence is written to "
                "\\fIcons.fa\\fP and the alignment of the sequences in \\fIreads.fa\\fP is written to "
                "\\fIout.sam\\fP.");
    addListItem(parser,
                "\\fBseqcons\\fP \\fB-m\\fP \\fIrealign\\fP \\fB-i\\fP \\fIin.sam\\fP \\fB-oa\\fP \\fIout.sam\\fP",
                "Read in multi-read alignment from \\fIin.sam\\fP, refine it using Anson-Myers realignment and "
                "write out the refined alignment to \\fIout.sam\\fP");

    // Parse command line.
    seqan::ArgumentParser::ParseResult res = seqan::parse(parser, argc, argv);

    // Only extract  options if the program will continue after parseCommandLine()
    if (res != seqan::ArgumentParser::PARSE_OK)
        return res;

    // Extract option values.

    if (isSet(parser, "quiet"))
        options.verbosity = 0;
    if (isSet(parser, "verbose"))
        options.verbosity = 2;
    if (isSet(parser, "very-verbose"))
        options.verbosity = 3;

    std::string opStr;
    getOptionValue(opStr, parser, "method");
    options.operation = strToMethod(opStr.c_str());

    getOptionValue(options.inputFile, parser, "input-file");
    getOptionValue(options.outputFileAlignment, parser, "output-alignment-file");
    getOptionValue(options.outputFileConsensus, parser, "output-consensus-file");

    getOptionValue(options.overlapMinLength, parser, "overlap-min-length");
    getOptionValue(options.overlapMaxErrorRate, parser, "overlap-max-error");
    getOptionValue(options.overlapWindowSize, parser, "overlap-window-size");

    getOptionValue(options.kMerSize, parser, "k-mer-size");
    getOptionValue(options.kMerMaxOcc, parser, "k-mer-max-occ");

    getOptionValue(options.reAlignmentBandwidth, parser, "realign-bandwidth");
    getOptionValue(options.reAlignmentEnvironment, parser, "realign-environment");

    return seqan::ArgumentParser::PARSE_OK;
}
예제 #6
0
seqan::ArgumentParser::ParseResult
parseCommandLine(MasonGenomeOptions & options, int argc, char const ** argv)
{
    // Setup ArgumentParser.
    seqan::ArgumentParser parser("mason_genome");
    // Set short description, version, and date.
    setShortDescription(parser, "Random Genome Simulation");
    setVersion(parser, "2.1");
    setDate(parser, "March 2013");
    setCategory(parser, "Simulators");

    // Define usage line and long description.
    addUsageLine(parser, "[\\fIOPTIONS\\fP] [\\fB-l\\fP \\fILEN\\fP]+ \\fB-o\\fP \\fIOUT.fa\\fP");
    addDescription(parser,
                   "Simulate a random genome to the output file.  For each \\fB-l\\fP/\\fB--contig-length\\fP "
                   "entry, a contig with the given length will be simulated.");

    // We require one argument.
    addOption(parser, seqan::ArgParseOption("q", "quiet", "Set verbosity to a minimum."));
    addOption(parser, seqan::ArgParseOption("v", "verbose", "Enable verbose output."));
    addOption(parser, seqan::ArgParseOption("vv", "very-verbose", "Enable very verbose output."));

    addSection(parser, "Simulation Configuration");
    addOption(parser, seqan::ArgParseOption("l", "contig-length",
                                            "Length of the contig to simulate. Give one \\fB-l\\fP "
                                            "value for each contig to simulate.",
                                            seqan::ArgParseOption::INTEGER, "LENGTH", true));
    setMinValue(parser, "contig-length", "1");
    setRequired(parser, "contig-length");

    addOption(parser, seqan::ArgParseOption("s", "seed", "The seed to use for the random number generator.",
                                            seqan::ArgParseOption::INTEGER, "INT"));
    setDefaultValue(parser, "seed", 0);

    addSection(parser, "Output Options");
    addOption(parser, seqan::ArgParseOption("o", "out-file", "Output file.",
                                            seqan::ArgParseOption::OUTPUTFILE, "FILE"));
    setValidValues(parser, "out-file", "fa fasta");
    setRequired(parser, "out-file");

    // Add Examples Section.
    addTextSection(parser, "Examples");
    addListItem(parser, "\\fBmason_genome\\fP \\fB-l\\fP 1000 \\fB-l\\fP 4000 \\fB-o\\fP \\fIgenome.fa\\fP",
                "Simulate a genome with two contigs of lengths 1000 and 4000 and write it to genome.fa.");

    // Parse command line.
    seqan::ArgumentParser::ParseResult res = seqan::parse(parser, argc, argv);

    // Only extract  options if the program will continue after parseCommandLine()
    if (res != seqan::ArgumentParser::PARSE_OK)
        return res;

    // Extract option values.
    if (isSet(parser, "quiet"))
        options.verbosity = 0;
    if (isSet(parser, "verbose"))
        options.verbosity = 2;
    if (isSet(parser, "very-verbose"))
        options.verbosity = 3;

    getOptionValue(options.outputFilename, parser, "out-file");
    getOptionValue(options.seed, parser, "seed");

    for (unsigned i = 0; i < getOptionValueCount(parser, "contig-length"); ++i)
    {
        int len = 0;
        getOptionValue(len, parser, "contig-length", i);
        appendValue(options.contigLengths, len);
    }

    return seqan::ArgumentParser::PARSE_OK;
}