SeqAn3 3.1.0
The Modern C++ library for sequence analysis.
policy_max_error.hpp
Go to the documentation of this file.
1// -----------------------------------------------------------------------------------------------------
2// Copyright (c) 2006-2021, Knut Reinert & Freie Universität Berlin
3// Copyright (c) 2016-2021, Knut Reinert & MPI für molekulare Genetik
4// This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
5// shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
6// -----------------------------------------------------------------------------------------------------
7
14#pragma once
15
16#include <seqan3/std/ranges>
17
20
21namespace seqan3::detail
22{
23
26struct policy_max_error
27{
28protected:
30 search_cfg::max_error_total total{};
32 search_cfg::max_error_substitution substitution{};
34 search_cfg::max_error_insertion insertion{};
36 search_cfg::max_error_deletion deletion{};
37
39 bool only_max_error_total{false};
41 bool has_max_error_total{false};
42
46 policy_max_error() = default;
47 policy_max_error(policy_max_error const &) = default;
48 policy_max_error(policy_max_error &&) = default;
49 policy_max_error & operator=(policy_max_error const &) = default;
50 policy_max_error & operator=(policy_max_error &&) = default;
51 ~policy_max_error() = default;
52
62 template <typename configuration_t>
64 requires is_type_specialisation_of_v<configuration_t, seqan3::configuration>
66 explicit policy_max_error(configuration_t const & config)
67 {
68 using search_traits_t = search_traits<configuration_t>;
69 only_max_error_total = search_traits_t::only_max_error_total;
70 has_max_error_total = search_traits_t::has_max_error_total;
71
72 total = config.get_or(search_cfg::max_error_total{search_cfg::error_count{0}});
73 substitution = config.get_or(search_cfg::max_error_substitution{search_cfg::error_count{0}});
74 insertion = config.get_or(search_cfg::max_error_insertion{search_cfg::error_count{0}});
75 deletion = config.get_or(search_cfg::max_error_deletion{search_cfg::error_count{0}});
76 }
78
87 template <std::ranges::forward_range query_t>
88 auto max_error_counts(query_t && query)
89 {
90 detail::search_param errors{0, 0, 0, 0}; // total, substitution, insertion, deletion
91
92 [[maybe_unused]] auto query_size = std::ranges::size(query);
93
94 errors.total = to_error_count(total.error, query_size);
95 errors.substitution = to_error_count(substitution.error, query_size);
96 errors.insertion = to_error_count(insertion.error, query_size);
97 errors.deletion = to_error_count(deletion.error, query_size);
98
99 // If only total is set, we set all other errors to the total limit.
100 if (only_max_error_total)
101 errors.substitution = errors.insertion = errors.deletion = errors.total;
102 // If total is not set but any other field is set than use total as the sum of all set errors.
103 else if (!has_max_error_total)
104 errors.total = std::min<uint32_t>(255, errors.substitution + errors.insertion + errors.deletion);
105
106 // Validate the error configuration.
107 // Checks if the given thresholds for the configured errors are valid. Otherwise throws std::invalid_argument.
108 if (errors.substitution > errors.total)
109 throw std::invalid_argument{"The substitution error threshold is higher than the total error threshold."};
110 if (errors.insertion > errors.total)
111 throw std::invalid_argument{"The insertion error threshold is higher than the total error threshold."};
112 if (errors.deletion > errors.total)
113 throw std::invalid_argument{"The deletion error threshold is higher than the total error threshold."};
114
115 return errors;
116 }
117
118private:
134 uint8_t to_error_count(std::variant<search_cfg::error_count, search_cfg::error_rate> const & error_variant,
135 [[maybe_unused]] size_t const query_size)
136 {
137 return std::visit([&query_size] (auto error)
138 {
139 if constexpr (std::same_as<decltype(error), search_cfg::error_count>)
140 return error.get();
141 else
142 {
143 // check correct error rate values.
144 if (0.0 > error.get() || error.get() > 1.0)
145 throw std::invalid_argument{"Error rates must be between 0 and 1."};
146
147 // make sure that error rate can be saved as uint8_t, so it is not too big in terms of query size
148 uint8_t const calculated_error_count = std::clamp(error.get() * query_size, 0.0, 255.0);
149 return calculated_error_count;
150 }
151 }, error_variant);
152 }
153};
154
155} // namespace seqan3::detail
T clamp(T... args)
constexpr size_t size
The size of a type pack.
Definition: traits.hpp:151
The <ranges> header from C++20's standard library.
Provides data structures used by different search algorithms.
Provides seqan3::detail::search_traits.
T visit(T... args)