SeqAn3  3.2.0-rc.1
The Modern C++ library for sequence analysis.
policy_max_error.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2022, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2022, 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 <ranges>
17 
20 
21 namespace seqan3::detail
22 {
23 
26 struct policy_max_error
27 {
28 protected:
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>
63  requires is_type_specialisation_of_v<configuration_t, seqan3::configuration>
64  explicit policy_max_error(configuration_t const & config)
65  {
66  using search_traits_t = search_traits<configuration_t>;
67  only_max_error_total = search_traits_t::only_max_error_total;
68  has_max_error_total = search_traits_t::has_max_error_total;
69 
70  total = config.get_or(search_cfg::max_error_total{search_cfg::error_count{0}});
71  substitution = config.get_or(search_cfg::max_error_substitution{search_cfg::error_count{0}});
72  insertion = config.get_or(search_cfg::max_error_insertion{search_cfg::error_count{0}});
73  deletion = config.get_or(search_cfg::max_error_deletion{search_cfg::error_count{0}});
74  }
76 
85  template <std::ranges::forward_range query_t>
86  auto max_error_counts(query_t && query)
87  {
88  detail::search_param errors{0, 0, 0, 0}; // total, substitution, insertion, deletion
89 
90  [[maybe_unused]] auto query_size = std::ranges::size(query);
91 
92  errors.total = to_error_count(total.error, query_size);
93  errors.substitution = to_error_count(substitution.error, query_size);
94  errors.insertion = to_error_count(insertion.error, query_size);
95  errors.deletion = to_error_count(deletion.error, query_size);
96 
97  // If only total is set, we set all other errors to the total limit.
98  if (only_max_error_total)
99  errors.substitution = errors.insertion = errors.deletion = errors.total;
100  // If total is not set but any other field is set than use total as the sum of all set errors.
101  else if (!has_max_error_total)
102  errors.total = std::min<uint32_t>(255, errors.substitution + errors.insertion + errors.deletion);
103 
104  // Validate the error configuration.
105  // Checks if the given thresholds for the configured errors are valid. Otherwise throws std::invalid_argument.
106  if (errors.substitution > errors.total)
107  throw std::invalid_argument{"The substitution error threshold is higher than the total error threshold."};
108  if (errors.insertion > errors.total)
109  throw std::invalid_argument{"The insertion error threshold is higher than the total error threshold."};
110  if (errors.deletion > errors.total)
111  throw std::invalid_argument{"The deletion error threshold is higher than the total error threshold."};
112 
113  return errors;
114  }
115 
116 private:
132  uint8_t to_error_count(std::variant<search_cfg::error_count, search_cfg::error_rate> const & error_variant,
133  [[maybe_unused]] size_t const query_size)
134  {
135  return std::visit(
136  [&query_size](auto error)
137  {
138  if constexpr (std::same_as<decltype(error), search_cfg::error_count>)
139  return error.get();
140  else
141  {
142  // check correct error rate values.
143  if (0.0 > error.get() || error.get() > 1.0)
144  throw std::invalid_argument{"Error rates must be between 0 and 1."};
145 
146  // make sure that error rate can be saved as uint8_t, so it is not too big in terms of query size
147  uint8_t const calculated_error_count = std::clamp(error.get() * query_size, 0.0, 255.0);
148  return calculated_error_count;
149  }
150  },
151  error_variant);
152  }
153 };
154 
155 } // namespace seqan3::detail
T clamp(T... args)
requires requires
The rank_type of the semi-alphabet; defined as the return type of seqan3::to_rank....
Definition: alphabet/concept.hpp:164
constexpr size_t size
The size of a type pack.
Definition: type_pack/traits.hpp:146
constexpr auto const & get(configuration< configs_t... > const &config) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: configuration.hpp:415
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)