Raptor 4.0.0-rc.1
A fast and space-efficient pre-filter
Loading...
Searching...
No Matches
cutoff.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2006-2026 Knut Reinert & Freie Universität Berlin
2// SPDX-FileCopyrightText: 2016-2026 Knut Reinert & MPI für molekulare Genetik
3// SPDX-License-Identifier: BSD-3-Clause
4
10#pragma once
11
12#include <seqan3/io/sequence_file/format_fasta.hpp>
13
14#include <hibf/misc/unreachable.hpp>
15
17
18namespace raptor
19{
20
21class cutoff
22{
23public:
24 cutoff() = default;
25 cutoff(cutoff const &) = default;
26 cutoff & operator=(cutoff const &) = default;
27 cutoff(cutoff &&) = default;
28 cutoff & operator=(cutoff &&) = default;
29 ~cutoff() = default;
30
31 cutoff(prepare_arguments const & arguments) : fixed_cutoff{arguments.kmer_count_cutoff}
32 {
33 if (arguments.use_filesize_dependent_cutoff)
34 {
35 cutoff_kind = cutoff_kinds::filesize_dependent;
36 }
37 else
38 {
39 cutoff_kind = cutoff_kinds::fixed;
40 }
41 }
42
43 uint8_t get(std::filesystem::path const & filename) const noexcept
44 {
45 switch (cutoff_kind)
46 {
47 case cutoff_kinds::filesize_dependent:
48 return impl(filename);
49 case cutoff_kinds::fixed:
50 return fixed_cutoff;
51 default: // GCOVR_EXCL_LINE
52 seqan::hibf::unreachable();
53 }
54 }
55
56 static inline bool file_is_compressed(std::filesystem::path const & filepath) noexcept
57 {
58 std::filesystem::path const extension = filepath.extension();
59 return extension == ".gz" || extension == ".bgzf" || extension == ".bz2";
60 }
61
62private:
63 enum class cutoff_kinds : uint8_t
64 {
65 fixed,
66 filesize_dependent
67 };
68
69 cutoff_kinds cutoff_kind{cutoff_kinds::fixed};
70
71 uint8_t fixed_cutoff{};
72 // Cutoffs and bounds from Mantis
73 // Mantis ignores k-mers which appear less than a certain cutoff. The cutoff is based on the file size of a
74 // gzipped fastq file. Small files have only a cutoff of 1 while big files have a cutoff value of 50.
75 // https://doi.org/10.1016/j.cels.2018.05.021
76 // Supplement Table S1
77 // https://www.cell.com/cms/10.1016/j.cels.2018.05.021/attachment/0a3d402b-8b90-42c0-a709-22f246fd1759/mmc1.pdf
78 static constexpr std::array<uint8_t, 4> const cutoffs{1u, 3u, 10u, 20u};
79 static constexpr std::array<uint64_t, 4> const cutoff_bounds{314'572'800ULL,
80 524'288'000ULL,
81 1'073'741'824ULL,
82 3'221'225'472ULL};
83
84 uint8_t impl(std::filesystem::path const & filename) const noexcept
85 {
86 bool const is_compressed = file_is_compressed(filename);
87 bool const is_fasta = check_for_fasta_format(filename);
88
89 // Since the curoffs are based on the filesize of a gzipped fastq file, we try account for the other cases:
90 // We multiply by two if we have fasta input.
91 // We divide by 3 if the input is not compressed.
92 size_t const filesize = std::filesystem::file_size(filename) * (is_fasta ? 2 : 1) / (is_compressed ? 1 : 3);
93
94 uint8_t cutoff{50u};
95 for (size_t i = 0; i < cutoff_bounds.size(); ++i)
96 {
97 if (filesize <= cutoff_bounds[i])
98 {
99 cutoff = cutoffs[i];
100 break;
101 }
102 }
103
104 return cutoff;
105 }
106
107 // NOLINTNEXTLINE(bugprone-exception-escape)
108 static inline bool check_for_fasta_format(
109 std::filesystem::path const & filepath,
110 std::vector<std::string> const & valid_extensions = seqan3::format_fasta::file_extensions) noexcept
111 {
112 std::string const extension = file_is_compressed(filepath) ? filepath.stem() : filepath.extension();
113
114 auto case_insensitive_string_ends_with = [&](std::string_view str, std::string_view suffix)
115 {
116 size_t const suffix_length{suffix.size()};
117 size_t const str_length{str.size()};
118 return suffix_length > str_length ? false
119 : std::ranges::equal(str.substr(str_length - suffix_length),
120 suffix,
121 [](char const chr1, char const chr2)
122 {
123 return std::tolower(chr1) == std::tolower(chr2);
124 });
125 };
126
127 auto case_insensitive_ends_with = [&](std::string const & ext)
128 {
129 return case_insensitive_string_ends_with(extension, ext);
130 };
131
132 return std::ranges::find_if(valid_extensions, case_insensitive_ends_with) != valid_extensions.end();
133 }
134};
135
136} // namespace raptor
Definition cutoff.hpp:22
T equal(T... args)
T extension(T... args)
T file_size(T... args)
T find_if(T... args)
Provides raptor::prepare_arguments.
T size(T... args)
Definition prepare_arguments.hpp:26
T substr(T... args)
Hide me