Skip to main content
  • Home
  • Development
  • Documentation
  • Donate
  • Operational login
  • Browse the archive

swh logo
SoftwareHeritage
Software
Heritage
Archive
Features
  • Search

  • Downloads

  • Save code now

  • Add forge now

  • Help

Revision d1bb46dfe8bc7efe6257b5ce222c04bfe8aedaab authored by Ryan Wick on 10 May 2018, 23:16:07 UTC, committed by Ryan Wick on 10 May 2018, 23:16:07 UTC
Fix typo
1 parent 260bb4d
  • Files
  • Changes
  • c0d2609
  • /
  • src
  • /
  • arguments.cpp
Raw File Download

To reference or cite the objects present in the Software Heritage archive, permalinks based on SoftWare Hash IDentifiers (SWHIDs) must be used.
Select below a type of object currently browsed in order to display its associated SWHID and permalink.

  • revision
  • directory
  • content
revision badge
swh:1:rev:d1bb46dfe8bc7efe6257b5ce222c04bfe8aedaab
directory badge
swh:1:dir:3a1cefd215cbb8c5c686cc840a95178f90953d5e
content badge
swh:1:cnt:f58fbcab17b4e818b46472f3fd88eb3ef79fd780

This interface enables to generate software citations, provided that the root directory of browsed objects contains a citation.cff or codemeta.json file.
Select below a type of object currently browsed in order to generate citations for them.

  • revision
  • directory
  • content
(requires biblatex-software package)
Generating citation ...
(requires biblatex-software package)
Generating citation ...
(requires biblatex-software package)
Generating citation ...
arguments.cpp
// Copyright 2017 Ryan Wick

// This file is part of Filtlong

// Filtlong 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.

// Filtlong 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 Filtlong.  If not, see
// <http://www.gnu.org/licenses/>.


#include "arguments.h"

#include <iostream>
#include <sys/ioctl.h>
#include <stdio.h>
#include <unistd.h>
#include <fstream>

#include "args.h"


struct DoublesReader
{
    void operator()(const std::string &name, const std::string &value, double &destination) {
        try {
            if (value.find_first_not_of("0123456789.") != std::string::npos)
                throw std::invalid_argument("");
            destination = std::stod(value);
        }
        catch ( ... ) {
            std::ostringstream problem;
            problem << "Error: argument '" << name << "' received invalid value type '" << value << "'";
            throw args::ParseError(problem.str());
        }
    }
};


typedef args::ValueFlag<double, DoublesReader> d_arg;
typedef args::ValueFlag<long long> i_arg;
typedef args::ValueFlag<std::string> s_arg;
typedef args::Flag f_arg;


Arguments::Arguments(int argc, char **argv) {

    args::ArgumentParser parser("Filtlong: a quality filtering tool for Nanopore and PacBio reads",
                                "For more information, go to: https://github.com/rrwick/Filtlong");
    parser.LongSeparator(" ");

    struct winsize w;
    ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
    int terminal_width = w.ws_col;

    int indent_size;
    if (terminal_width > 120)
        indent_size = 4;
    else if (terminal_width > 80)
        indent_size = 3;
    else if (terminal_width > 60)
        indent_size = 2;
    else
        indent_size = 1;

    parser.helpParams.showTerminator = false;
    parser.helpParams.progindent = 0;
    parser.helpParams.descriptionindent = 0;
    parser.helpParams.width = terminal_width;
    parser.helpParams.flagindent = indent_size;
    parser.helpParams.eachgroupindent = indent_size;

    args::Positional<std::string> input_reads_arg(parser, "input_reads",
                                      "input long reads to be filtered");

    args::Group thresholds_group(parser, "output thresholds:");
    i_arg target_bases_arg(thresholds_group, "int",
                           "keep only the best reads up to this many total bases",
                           {'t', "target_bases"});
    d_arg keep_percent_arg(thresholds_group, "float",
                           "keep only this percentage of the best reads (measured by bases)",
                           {'p', "keep_percent"});
    i_arg min_length_arg(thresholds_group, "int",
                         "minimum length threshold",
                         {"min_length"});
    d_arg min_mean_q_arg(thresholds_group, "float",
                         "minimum mean quality threshold",
                         {"min_mean_q"});
    d_arg min_window_q_arg(thresholds_group, "float",
                           "minimum window quality threshold",
                           {"min_window_q"});

    args::Group references_group(parser, "NLexternal references "   // The NL at the start results in a newline
            "(if provided, read quality will be determined using these instead of from the Phred scores):");
    s_arg assembly_arg(references_group, "file",
                       "reference assembly in FASTA format",
                        {'a', "assembly"});
    s_arg illumina_1_arg(references_group, "file",
                         "reference Illumina reads in FASTQ format",
                         {'1', "illumina_1"});
    s_arg illumina_2_arg(references_group, "file",
                         "reference Illumina reads in FASTQ format",
                         {'2', "illumina_2"});

    args::Group score_weights_group(parser, "NLscore weights "    // The NL at the start results in a newline
                                            "(control the relative contribution of each score to the final read score):");
    d_arg length_weight_arg(score_weights_group, "float",
                            "weight given to the length score (default: 1)",
                            {"length_weight"}, 1.0);
    d_arg mean_q_weight_arg(score_weights_group, "float",
                            "weight given to the mean quality score (default: 1)",
                            {"mean_q_weight"}, 1.0);
    d_arg window_q_weight_arg(score_weights_group, "float",
                              "weight given to the window quality score (default: 1)",
                              {"window_q_weight"}, 1.0);

    // TO DO: half_length_score: reads of this length get a 50% score (currently hard-coded at 5000)

    args::Group manipulation_group(parser, "NLread manipulation:");    // The NL at the start results in a newline
    f_arg trim_arg(manipulation_group, "trim",
                   "trim non-k-mer-matching bases from start/end of reads",
                   {"trim"});
    i_arg split_arg(manipulation_group, "split",
                    "split reads at this many (or more) consecutive non-k-mer-matching bases",
                    {"split"});

    args::Group other_group(parser, "NLother:");    // The NL at the start results in a newline
    i_arg window_size_arg(other_group, "int",
                          "size of sliding window used when measuring window quality (default: 250)",
                          {"window_size"}, 250);
    f_arg verbose_arg(other_group, "verbose",
                      "verbose output to stderr with info for each read",
                      {"verbose"});
    f_arg version_arg(other_group, "version",
                      "display the program version and quit",
                      {"version"});

    args::HelpFlag help(parser, "help",
                        "display this help menu",
                        {'h', "help"});


    parsing_result = GOOD;
    try {
        parser.ParseCLI(argc, argv);
    }
    catch (args::Help) {
        std::cerr << parser;
        parsing_result = HELP;
        return;
    }
    catch (args::ParseError e) {
        std::cerr << e.what() << "\n";
        parsing_result = BAD;
        return;
    }
    catch (args::ValidationError e) {
        std::cerr << e.what() << "\n";
        parsing_result = BAD;
        return;
    }
    if (argc == 1) {
        std::cerr << parser;
        parsing_result = HELP;
        return;
    }
    if (args::get(version_arg)) {
        parsing_result = VERSION;
        return;
    }

    input_reads = args::get(input_reads_arg);
    if (input_reads.empty()) {
        std::cerr << "Error: input reads are required" << "\n";
        parsing_result = BAD;
        return;
    }

    target_bases_set = bool(target_bases_arg);
    target_bases = args::get(target_bases_arg);

    keep_percent_set = bool(keep_percent_arg);
    keep_percent = args::get(keep_percent_arg);

    assembly_set = bool(assembly_arg);
    assembly = args::get(assembly_arg);

    if (bool(illumina_1_arg))
        illumina_reads.push_back(args::get(illumina_1_arg));
    if (bool(illumina_2_arg))
        illumina_reads.push_back(args::get(illumina_2_arg));

    min_length_set = bool(min_length_arg);
    min_length = args::get(min_length_arg);

    min_mean_q_set = bool(min_mean_q_arg);
    min_mean_q = args::get(min_mean_q_arg);

    min_window_q_set = bool(min_window_q_arg);
    min_window_q = args::get(min_window_q_arg);

    length_weight = args::get(length_weight_arg);
    mean_q_weight = args::get(mean_q_weight_arg);
    window_q_weight = args::get(window_q_weight_arg);

    trim = args::get(trim_arg);

    split_set = bool(split_arg);
    split = args::get(split_arg);

    window_size = args::get(window_size_arg);
    verbose = args::get(verbose_arg);

    bool some_reference = (illumina_reads.size() > 0 || assembly_set);
    if (trim && !some_reference) {
        std::cerr << "Error: assembly or read reference is required to use --trim" << "\n";
        parsing_result = BAD;
        return;
    }
    if (split_set && !some_reference) {
        std::cerr << "Error: assembly or read reference is required to use --split" << "\n";
        parsing_result = BAD;
        return;
    }

    // Check to make sure files exist.
    std::vector<std::string> files;
    files.push_back(input_reads);
    for (auto f : illumina_reads)
        files.push_back(f);
    if (assembly_set)
        files.push_back(assembly);
    for (auto f : files) {
        if (!does_file_exist(f)) {
            std::cerr << "Error: cannot find file: " << f << "\n";
            parsing_result = BAD;
            return;
        }
    }

    // If nothing is set, then Filtlong won't do anything. Give an error message and quit.
    if (!trim && !split_set && !target_bases_set && !keep_percent_set &&
            !min_length_set && !min_mean_q_set && !min_window_q_set) {
        std::cerr << "Error: no thresholds set, you must use one of the following options:\n";
        std::cerr << "target_bases, keep_percent, min_length, min_mean_q, min_window_q, trim, split\n";
        parsing_result = BAD;
        return;
    }

    // Non-positive target_bases doesn't make sense.
    if (target_bases_set && target_bases <= 0) {
        std::cerr << "Error: the value for --target_bases must be a positive integer\n";
        parsing_result = BAD;
        return;
    }

    // Non-positive min_length doesn't make sense.
    if (min_length_set && min_length <= 0) {
        std::cerr << "Error: the value for --min_length must be a positive integer\n";
        parsing_result = BAD;
        return;
    }

    // keep_percent must be between 0 and 100 (exclusive).
    if (keep_percent_set && (keep_percent <= 0.0 || keep_percent >= 100.0)) {
        std::cerr << "Error: the value for --keep_percent must be greater than 0 and less than 100\n";
        parsing_result = BAD;
        return;
    }

    // min_mean_q and min_window_q must be positive.
    if (min_mean_q_set && min_mean_q <= 0.0) {
        std::cerr << "Error: the value for --min_mean_q must be greater than 0\n";
        parsing_result = BAD;
        return;
    }
    if (min_window_q_set && min_window_q <= 0.0) {
        std::cerr << "Error: the value for --min_window_q must be greater than 0\n";
        parsing_result = BAD;
        return;
    }

    // Negative weights don't make sense.
    if (length_weight < 0.0 || mean_q_weight < 0.0 || window_q_weight < 0.0) {
        std::cerr << "Error: weight values cannot be negative\n";
        parsing_result = BAD;
        return;
    }

    // Non-positive split doesn't make sense.
    if (split_set && split <= 0) {
        std::cerr << "Error: the value for --split must be a positive integer\n";
        parsing_result = BAD;
        return;
    }

    // Non-positive window_size doesn't make sense.
    if (window_size <= 0) {
        std::cerr << "Error: the value for --window_size must be a positive integer\n";
        parsing_result = BAD;
        return;
    }
}


bool Arguments::does_file_exist(std::string filename){
    std::ifstream infile(filename);
    return infile.good();
}
The diff you're trying to view is too large. Only the first 1000 changed files have been loaded.
Showing with 0 additions and 0 deletions (0 / 0 diffs computed)
swh spinner

Computing file changes ...

back to top

Software Heritage — Copyright (C) 2015–2026, The Software Heritage developers. License: GNU AGPLv3+.
The source code of Software Heritage itself is available on our development forge.
The source code files archived by Software Heritage are available under their own copyright and licenses.
Terms of use: Archive access, API— Content policy— Contact— JavaScript license information— Web API