Loading...
Searching...
No Matches
align_pairwise.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 <concepts>
#include <functional>
#include <iostream>
#include <ranges>
#include <tuple>
#include <type_traits>
#include <seqan3/alignment/pairwise/alignment_configurator.hpp>
#include <seqan3/alignment/pairwise/alignment_result.hpp>
#include <seqan3/alignment/pairwise/detail/concept.hpp>
#include <seqan3/alignment/pairwise/detail/type_traits.hpp>
#include <seqan3/core/algorithm/algorithm_result_generator_range.hpp>
#include <seqan3/core/algorithm/detail/algorithm_executor_blocking.hpp>
#include <seqan3/utility/simd/simd.hpp>
#include <seqan3/utility/simd/simd_traits.hpp>
#include <seqan3/utility/type_traits/basic.hpp>
namespace seqan3
{
template <typename sequence_t, typename alignment_config_t>
requires detail::align_pairwise_single_input<sequence_t>
&& std::copy_constructible<std::remove_reference_t<sequence_t>>
&& detail::is_type_specialisation_of_v<alignment_config_t, configuration>
constexpr auto align_pairwise(sequence_t && seq, alignment_config_t const & config)
{
using std::get;
if constexpr (std::is_lvalue_reference_v<sequence_t>) // Forward tuple elements as references.
{
return align_pairwise(std::tie(get<0>(seq), get<1>(seq)), config);
}
else
{
static_assert(std::tuple_size_v<std::remove_reference_t<sequence_t>> == 2,
"Alignment configuration error: Expects exactly two sequences for pairwise alignments.");
static_assert(std::ranges::viewable_range<std::tuple_element_t<0, std::remove_reference_t<sequence_t>>>
&& std::ranges::viewable_range<std::tuple_element_t<1, std::remove_reference_t<sequence_t>>>,
"Alignment configuration error: The tuple elements must model std::ranges::viewable_range.");
return align_pairwise(std::views::single(std::forward<sequence_t>(seq)), config);
}
}
template <typename sequence_t, typename alignment_config_t>
requires detail::align_pairwise_range_input<sequence_t>
&& detail::is_type_specialisation_of_v<alignment_config_t, configuration>
constexpr auto align_pairwise(sequence_t && sequences, alignment_config_t const & config)
{
using first_seq_t = std::tuple_element_t<0, std::ranges::range_value_t<sequence_t>>;
using second_seq_t = std::tuple_element_t<1, std::ranges::range_value_t<sequence_t>>;
static_assert(std::ranges::random_access_range<first_seq_t> && std::ranges::sized_range<first_seq_t>,
"Alignment configuration error: The sequence must model random_access_range and sized_range.");
static_assert(std::ranges::random_access_range<second_seq_t> && std::ranges::sized_range<second_seq_t>,
"Alignment configuration error: The sequence must model random_access_range and sized_range.");
// Pipe with std::views::all to allow rvalue non-view ranges.
auto seq_view = std::forward<sequence_t>(sequences) | std::views::all;
// Configure the alignment algorithm.
auto && [algorithm, complete_config] = detail::alignment_configurator::configure<decltype(seq_view)>(config);
using complete_config_t = std::remove_cvref_t<decltype(complete_config)>;
using traits_t = detail::alignment_configuration_traits<complete_config_t>;
auto indexed_sequence_chunk_view =
views::zip(seq_view, std::views::iota(0)) | views::chunk(traits_t::alignments_per_vector);
using indexed_sequences_t = decltype(indexed_sequence_chunk_view);
using alignment_result_t = typename traits_t::alignment_result_type;
using execution_handler_t = std::conditional_t<complete_config_t::template exists<align_cfg::parallel>(),
detail::execution_handler_parallel,
detail::execution_handler_sequential>;
using executor_t = detail::
algorithm_executor_blocking<indexed_sequences_t, decltype(algorithm), alignment_result_t, execution_handler_t>;
// Select the execution handler for the alignment configuration.
auto select_execution_handler = [parallel = complete_config.get_or(align_cfg::parallel{})]()
{
if constexpr (std::same_as<execution_handler_t, detail::execution_handler_parallel>)
{
auto thread_count = parallel.thread_count;
if (!thread_count)
throw std::runtime_error{"You must configure the number of threads in seqan3::align_cfg::parallel."};
return execution_handler_t{*thread_count};
}
else
{
return execution_handler_t{};
}
};
if constexpr (traits_t::is_one_way_execution) // Just compute alignment and wait until all alignments are computed.
select_execution_handler().bulk_execute(algorithm,
indexed_sequence_chunk_view,
get<align_cfg::on_result>(complete_config).callback);
else // Require two way execution: return the range over the alignments.
return algorithm_result_generator_range{executor_t{std::move(indexed_sequence_chunk_view),
std::move(algorithm),
alignment_result_t{},
select_execution_handler()}};
}
} // namespace seqan3
algorithm_executor_blocking.hpp
Provides seqan3::detail::algorithm_executor_blocking.
algorithm_result_generator_range.hpp
Provides seqan3::detail::algorithm_result_generator_range.
concept.hpp
Provides concepts needed internally for the alignment algorithms.
type_traits.hpp
Provides helper type traits for the configuration and execution of the alignment algorithm.
alignment_configurator.hpp
Provides seqan3::detail::alignment_selector.
alignment_result.hpp
Provides seqan3::alignment_result.
basic.hpp
Provides various type traits on generic types.
seqan3::algorithm_result_generator_range
An input range over the algorithm results generated by the underlying algorithm executor.
Definition algorithm_result_generator_range.hpp:45
std::conditional_t
std::forward
T forward(T... args)
functional
seqan3::align_cfg::parallel
seqan3::detail::parallel_mode< std::integral_constant< seqan3::detail::align_config_id, seqan3::detail::align_config_id::parallel > > parallel
Enables the parallel execution of the alignment algorithm if possible for the given configuration.
Definition align_config_parallel.hpp:34
seqan3::align_pairwise
constexpr auto align_pairwise(sequence_t &&seq, alignment_config_t const &config)
Computes the pairwise alignment for a pair of sequences or a range over sequence pairs.
Definition align_pairwise.hpp:130
seqan3::field::seq
@ seq
The "sequence", usually a range of nucleotides or amino acids.
Definition record.hpp:62
seqan3::views::zip
seqan::stl::views::zip zip
A view adaptor that takes several views and returns tuple-like values from every i-th element of each...
Definition zip.hpp:24
seqan3::views::chunk
seqan::stl::views::chunk chunk
A view adaptor that divides a range into chunks. <dl class="no-api">This entity is not part of the Se...
Definition chunk.hpp:23
iostream
std::is_lvalue_reference_v
T is_lvalue_reference_v
seqan3
The main SeqAn3 namespace.
Definition aligned_sequence_concept.hpp:26
seqan3::get
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:412
std::tie
T tie(T... args)
tuple
std::tuple_size_v
T tuple_size_v
type_traits
Hide me