Loading...
Searching...
No Matches
policy_max_error.hpp
Go to the documentation of this file.
// SPDX-FileCopyrightText: 2006-2025 Knut Reinert & Freie Universität Berlin
// SPDX-FileCopyrightText: 2016-2025 Knut Reinert & MPI für molekulare Genetik
// SPDX-License-Identifier: BSD-3-Clause
#pragma once
#include <ranges>
#include <seqan3/search/detail/search_common.hpp>
#include <seqan3/search/detail/search_traits.hpp>
namespace seqan3::detail
{
struct policy_max_error
{
protected:
search_cfg::max_error_total total{};
search_cfg::max_error_substitution substitution{};
search_cfg::max_error_insertion insertion{};
search_cfg::max_error_deletion deletion{};
bool only_max_error_total{false};
bool has_max_error_total{false};
policy_max_error() = default;
policy_max_error(policy_max_error const &) = default;
policy_max_error(policy_max_error &&) = default;
policy_max_error & operator=(policy_max_error const &) = default;
policy_max_error & operator=(policy_max_error &&) = default;
~policy_max_error() = default;
template <typename configuration_t>
requires is_type_specialisation_of_v<configuration_t, seqan3::configuration>
explicit policy_max_error(configuration_t const & config)
{
using search_traits_t = search_traits<configuration_t>;
only_max_error_total = search_traits_t::only_max_error_total;
has_max_error_total = search_traits_t::has_max_error_total;
total = config.get_or(search_cfg::max_error_total{search_cfg::error_count{0}});
substitution = config.get_or(search_cfg::max_error_substitution{search_cfg::error_count{0}});
insertion = config.get_or(search_cfg::max_error_insertion{search_cfg::error_count{0}});
deletion = config.get_or(search_cfg::max_error_deletion{search_cfg::error_count{0}});
}
template <std::ranges::forward_range query_t>
auto max_error_counts(query_t && query)
{
detail::search_param errors{0, 0, 0, 0}; // total, substitution, insertion, deletion
[[maybe_unused]] auto query_size = std::ranges::size(query);
errors.total = to_error_count(total.error, query_size);
errors.substitution = to_error_count(substitution.error, query_size);
errors.insertion = to_error_count(insertion.error, query_size);
errors.deletion = to_error_count(deletion.error, query_size);
// If only total is set, we set all other errors to the total limit.
if (only_max_error_total)
errors.substitution = errors.insertion = errors.deletion = errors.total;
// If total is not set but any other field is set than use total as the sum of all set errors.
else if (!has_max_error_total)
errors.total = std::min<uint32_t>(255, errors.substitution + errors.insertion + errors.deletion);
// Validate the error configuration.
// Checks if the given thresholds for the configured errors are valid. Otherwise throws std::invalid_argument.
if (errors.substitution > errors.total)
throw std::invalid_argument{"The substitution error threshold is higher than the total error threshold."};
if (errors.insertion > errors.total)
throw std::invalid_argument{"The insertion error threshold is higher than the total error threshold."};
if (errors.deletion > errors.total)
throw std::invalid_argument{"The deletion error threshold is higher than the total error threshold."};
return errors;
}
private:
uint8_t to_error_count(std::variant<search_cfg::error_count, search_cfg::error_rate> const & error_variant,
[[maybe_unused]] size_t const query_size)
{
return std::visit(
[&query_size](auto error)
{
if constexpr (std::same_as<decltype(error), search_cfg::error_count>)
return error.get();
else
{
// check correct error rate values.
if (0.0 > error.get() || error.get() > 1.0)
throw std::invalid_argument{"Error rates must be between 0 and 1."};
// make sure that error rate can be saved as uint8_t, so it is not too big in terms of query size
uint8_t const calculated_error_count = std::clamp(error.get() * query_size, 0.0, 255.0);
return calculated_error_count;
}
},
error_variant);
}
};
} // namespace seqan3::detail
std::clamp
T clamp(T... args)
std::min
T min(T... args)
search_common.hpp
Provides data structures used by different search algorithms.
search_traits.hpp
Provides seqan3::detail::search_traits.
std::visit
T visit(T... args)
Hide me