SeqAn3 3.4.0-rc.1
The Modern C++ library for sequence analysis.
Loading...
Searching...
No Matches
pairwise_alignment_algorithm_banded.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2006-2024 Knut Reinert & Freie Universität Berlin
2// SPDX-FileCopyrightText: 2016-2024 Knut Reinert & MPI für molekulare Genetik
3// SPDX-License-Identifier: BSD-3-Clause
4
10#pragma once
11
12#include <concepts>
13#include <ranges>
14
17
18namespace seqan3::detail
19{
20
26template <typename alignment_configuration_t, typename... policies_t>
27 requires is_type_specialisation_of_v<alignment_configuration_t, configuration>
29 protected pairwise_alignment_algorithm<alignment_configuration_t, policies_t...>
30{
31protected:
33 using base_algorithm_t = pairwise_alignment_algorithm<alignment_configuration_t, policies_t...>;
34
35 // Import types from base class.
37 using typename base_algorithm_t::score_type;
38 using typename base_algorithm_t::traits_type;
39
40 static_assert(!std::same_as<alignment_result_type, empty_type>, "Alignment result type was not configured.");
41 static_assert(traits_type::is_banded, "Alignment configuration must have band configured.");
42
43public:
54
64 pairwise_alignment_algorithm_banded(alignment_configuration_t const & config) : base_algorithm_t(config)
65 {}
67
72 template <indexed_sequence_pair_range indexed_sequence_pairs_t, typename callback_t>
73 requires std::invocable<callback_t, alignment_result_type>
74 void operator()(indexed_sequence_pairs_t && indexed_sequence_pairs, callback_t && callback)
75 {
76 using std::get;
77
78 for (auto && [sequence_pair, idx] : indexed_sequence_pairs)
79 {
80 size_t sequence1_size = std::ranges::distance(get<0>(sequence_pair));
81 size_t const sequence2_size = std::ranges::distance(get<1>(sequence_pair));
82
83 auto && [alignment_matrix, index_matrix] =
84 this->acquire_matrices(sequence1_size, sequence2_size, this->lowest_viable_score());
85
86 // Initialise the cell updater with the dimensions of the regular matrix.
87 this->compare_and_set_optimum.set_target_indices(row_index_type{sequence2_size},
88 column_index_type{sequence1_size});
89
90 // Shrink the first sequence if the band ends before its actual end.
91 sequence1_size = std::min(sequence1_size, this->upper_diagonal + sequence2_size);
92
93 using sequence1_difference_t = std::ranges::range_difference_t<decltype(get<0>(sequence_pair))>;
94
95 compute_matrix(std::views::take(get<0>(sequence_pair), static_cast<sequence1_difference_t>(sequence1_size)),
96 get<1>(sequence_pair),
97 alignment_matrix,
98 index_matrix);
99 this->make_result_and_invoke(std::forward<decltype(sequence_pair)>(sequence_pair),
100 std::move(idx),
101 this->optimal_score,
102 this->optimal_coordinate,
103 alignment_matrix,
104 callback);
105 }
106 }
107
109 template <indexed_sequence_pair_range indexed_sequence_pairs_t, typename callback_t>
110 requires traits_type::is_vectorised && std::invocable<callback_t, alignment_result_type>
111 auto operator()(indexed_sequence_pairs_t && indexed_sequence_pairs, callback_t && callback)
112 {
113 using simd_collection_t = std::vector<score_type, aligned_allocator<score_type, alignof(score_type)>>;
114 using original_score_t = typename traits_type::original_score_type;
115
116 // Extract the batch of sequences for the first and the second sequence.
117 auto seq1_collection = indexed_sequence_pairs | views::elements<0> | views::elements<0>;
118 auto seq2_collection = indexed_sequence_pairs | views::elements<0> | views::elements<1>;
119
120 this->initialise_tracker(seq1_collection, seq2_collection);
121
122 // Convert batch of sequences to sequence of simd vectors.
123 thread_local simd_collection_t simd_seq1_collection{};
124 thread_local simd_collection_t simd_seq2_collection{};
125
126 this->convert_batch_of_sequences_to_simd_vector(simd_seq1_collection,
127 seq1_collection,
128 this->scoring_scheme.padding_symbol);
129 this->convert_batch_of_sequences_to_simd_vector(simd_seq2_collection,
130 seq2_collection,
131 this->scoring_scheme.padding_symbol);
132
133 size_t const sequence1_size = std::ranges::distance(simd_seq1_collection);
134 size_t const sequence2_size = std::ranges::distance(simd_seq2_collection);
135
136 auto && [alignment_matrix, index_matrix] =
137 this->acquire_matrices(sequence1_size, sequence2_size, this->lowest_viable_score());
138
139 compute_matrix(simd_seq1_collection, simd_seq2_collection, alignment_matrix, index_matrix);
140
141 size_t index = 0;
142 for (auto && [sequence_pair, idx] : indexed_sequence_pairs)
143 {
144 original_score_t score = this->optimal_score[index]
145 - (this->padding_offsets[index] * this->scoring_scheme.padding_match_score());
146 matrix_coordinate coordinate{row_index_type{size_t{this->optimal_coordinate.row[index]}},
147 column_index_type{size_t{this->optimal_coordinate.col[index]}}};
148 this->make_result_and_invoke(std::forward<decltype(sequence_pair)>(sequence_pair),
149 std::move(idx),
150 std::move(score),
151 std::move(coordinate),
152 alignment_matrix,
153 callback);
154 ++index;
155 }
156 }
158
159protected:
212 template <std::ranges::forward_range sequence1_t,
213 std::ranges::forward_range sequence2_t,
214 std::ranges::input_range alignment_matrix_t,
215 std::ranges::input_range index_matrix_t>
216 requires std::ranges::forward_range<std::ranges::range_reference_t<alignment_matrix_t>>
217 && std::ranges::forward_range<std::ranges::range_reference_t<index_matrix_t>>
218 void compute_matrix(sequence1_t && sequence1,
219 sequence2_t && sequence2,
220 alignment_matrix_t && alignment_matrix,
221 index_matrix_t && index_matrix)
222 {
223 // ---------------------------------------------------------------------
224 // Initialisation phase: allocate memory and initialise first column.
225 // ---------------------------------------------------------------------
226
227 this->reset_optimum(); // Reset the tracker for the new alignment computation.
228
229 auto alignment_matrix_it = alignment_matrix.begin();
230 auto indexed_matrix_it = index_matrix.begin();
231
232 using row_index_t = std::ranges::range_difference_t<sequence2_t>; // row_size = |sequence2| + 1
233 using column_index_t = std::ranges::range_difference_t<sequence1_t>; // column_size = |sequence1| + 1
234
235 row_index_t row_size = std::max<int32_t>(0, -this->lower_diagonal);
236 column_index_t const column_size = std::max<int32_t>(0, this->upper_diagonal);
237 this->initialise_column(*alignment_matrix_it, *indexed_matrix_it, std::views::take(sequence2, row_size));
238
239 // ---------------------------------------------------------------------
240 // 1st recursion phase: band intersects with the first row.
241 // ---------------------------------------------------------------------
242
243 for (auto alphabet1 : std::views::take(sequence1, column_size))
244 {
245 this->compute_column(*++alignment_matrix_it,
246 *++indexed_matrix_it,
247 alphabet1,
248 std::views::take(sequence2, ++row_size));
249 }
250
251 // ---------------------------------------------------------------------
252 // 2nd recursion phase: iterate until the end of the matrix.
253 // ---------------------------------------------------------------------
254
255 row_index_t first_row_index = 0u;
256 for (auto alphabet1 : std::views::drop(sequence1, column_size))
257 {
258 compute_band_column(*++alignment_matrix_it,
259 std::views::drop(*++indexed_matrix_it, first_row_index + 1),
260 alphabet1,
261 views::slice(sequence2, first_row_index, ++row_size));
262 ++first_row_index;
263 }
264
265 // ---------------------------------------------------------------------
266 // Final phase: track score of last column
267 // ---------------------------------------------------------------------
268
269 auto alignment_column = *alignment_matrix_it;
270 auto cell_index_column = std::views::drop(*indexed_matrix_it, first_row_index);
271
272 auto alignment_column_it = alignment_column.begin();
273 auto cell_index_column_it = cell_index_column.begin();
274
275 this->track_last_column_cell(*alignment_column_it, *cell_index_column_it);
276
277 for (row_index_t last_row = std::min<row_index_t>(std::ranges::distance(sequence2), row_size);
278 first_row_index < last_row;
279 ++first_row_index)
280 this->track_last_column_cell(*++alignment_column_it, *++cell_index_column_it);
281
282 this->track_final_cell(*alignment_column_it, *cell_index_column_it);
283 }
284
336 template <std::ranges::forward_range alignment_column_t,
337 std::ranges::input_range cell_index_column_t,
338 typename alphabet1_t,
339 std::ranges::input_range sequence2_t>
340 void compute_band_column(alignment_column_t && alignment_column,
341 cell_index_column_t && cell_index_column,
342 alphabet1_t const & alphabet1,
343 sequence2_t && sequence2)
344 {
345 // ---------------------------------------------------------------------
346 // Initial phase: prepare column and initialise first cell
347 // ---------------------------------------------------------------------
348
349 auto current_alignment_column_it = alignment_column.begin();
350 auto cell_index_column_it = cell_index_column.begin();
351
352 // Points to the last valid cell in the column.
353 decltype(current_alignment_column_it) next_alignment_column_it{current_alignment_column_it};
354 auto cell = *current_alignment_column_it;
355 cell = this->track_cell(
356 this->initialise_band_first_cell(cell.best_score(),
357 *++next_alignment_column_it,
358 this->scoring_scheme.score(alphabet1, *std::ranges::begin(sequence2))),
359 *cell_index_column_it);
360
361 // ---------------------------------------------------------------------
362 // Iteration phase: iterate over column and compute each cell
363 // ---------------------------------------------------------------------
364
365 for (auto && alphabet2 : std::views::drop(sequence2, 1))
366 {
367 current_alignment_column_it = next_alignment_column_it;
368 auto cell = *current_alignment_column_it;
369 cell = this->track_cell(this->compute_inner_cell(cell.best_score(),
370 *++next_alignment_column_it,
371 this->scoring_scheme.score(alphabet1, alphabet2)),
372 *++cell_index_column_it);
373 }
374
375 // ---------------------------------------------------------------------
376 // Final phase: track last cell
377 // ---------------------------------------------------------------------
378
379 this->track_last_row_cell(*current_alignment_column_it, *cell_index_column_it);
380 }
381};
382
383} // namespace seqan3::detail
T begin(T... args)
Allocates uninitialized storage whose memory-alignment is specified by alignment.
Definition aligned_allocator.hpp:74
The alignment algorithm type to compute the banded standard pairwise alignment using dynamic programm...
Definition pairwise_alignment_algorithm_banded.hpp:30
pairwise_alignment_algorithm_banded & operator=(pairwise_alignment_algorithm_banded const &)=default
Defaulted.
void compute_matrix(sequence1_t &&sequence1, sequence2_t &&sequence2, alignment_matrix_t &&alignment_matrix, index_matrix_t &&index_matrix)
Compute the actual banded alignment.
Definition pairwise_alignment_algorithm_banded.hpp:218
pairwise_alignment_algorithm_banded(pairwise_alignment_algorithm_banded &&)=default
Defaulted.
pairwise_alignment_algorithm_banded(pairwise_alignment_algorithm_banded const &)=default
Defaulted.
::is_vectorised &&std::invocable< callback_t, alignment_result_type > auto operator()(indexed_sequence_pairs_t &&indexed_sequence_pairs, callback_t &&callback)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition pairwise_alignment_algorithm_banded.hpp:111
pairwise_alignment_algorithm_banded(alignment_configuration_t const &config)
Constructs and initialises the algorithm using the alignment configuration.
Definition pairwise_alignment_algorithm_banded.hpp:64
pairwise_alignment_algorithm_banded & operator=(pairwise_alignment_algorithm_banded &&)=default
Defaulted.
void operator()(indexed_sequence_pairs_t &&indexed_sequence_pairs, callback_t &&callback)
Computes the pairwise sequence alignment for the given range over indexed sequence pairs.
Definition pairwise_alignment_algorithm_banded.hpp:74
void compute_band_column(alignment_column_t &&alignment_column, cell_index_column_t &&cell_index_column, alphabet1_t const &alphabet1, sequence2_t &&sequence2)
Computes a column of the band that does not start in the first row of the alignment matrix.
Definition pairwise_alignment_algorithm_banded.hpp:340
The alignment algorithm type to compute standard pairwise alignment using dynamic programming.
Definition pairwise_alignment_algorithm.hpp:44
typename traits_type::score_type score_type
The configured score type.
Definition pairwise_alignment_algorithm.hpp:49
void compute_column(alignment_column_t &&alignment_column, cell_index_column_t &&cell_index_column, alphabet1_t const &alphabet1, sequence2_t &&sequence2)
Initialise any column of the alignment matrix except the first one.
Definition pairwise_alignment_algorithm.hpp:365
alignment_configuration_traits< alignment_configuration_t > traits_type
The alignment configuration traits type with auxiliary information extracted from the configuration t...
Definition pairwise_alignment_algorithm.hpp:47
void initialise_column(alignment_column_t &&alignment_column, cell_index_column_t &&cell_index_column, sequence2_t &&sequence2)
Initialise the first column of the alignment matrix.
Definition pairwise_alignment_algorithm.hpp:312
void convert_batch_of_sequences_to_simd_vector(simd_sequence_t &simd_sequence, sequence_collection_t &sequences, padding_symbol_t const &padding_symbol)
Converts a batch of sequences to a sequence of simd vectors.
Definition pairwise_alignment_algorithm.hpp:217
typename traits_type::alignment_result_type alignment_result_type
The configured alignment result type.
Definition pairwise_alignment_algorithm.hpp:51
T forward(T... args)
constexpr auto slice
A view adaptor that returns a half-open interval on the underlying range.
Definition slice.hpp:175
A helper concept to check if a type is a sequence pair.
T min(T... args)
The internal SeqAn3 namespace.
Definition aligned_sequence_concept.hpp:26
Provides seqan3::detail::pairwise_alignment_algorithm.
Provides seqan3::views::slice.
static constexpr bool is_banded
Flag indicating whether banded alignment mode is enabled.
Definition alignment/pairwise/detail/type_traits.hpp:120
static constexpr bool is_vectorised
Flag to indicate vectorised mode.
Definition alignment/pairwise/detail/type_traits.hpp:112
typename std::remove_reference_t< decltype(std::declval< configuration_t >().get_or(align_cfg::score_type< int32_t >{}))>::type original_score_type
The original score type selected by the user.
Definition alignment/pairwise/detail/type_traits.hpp:131
A strong type for designated initialisation of the column index of a matrix.
Definition matrix_coordinate.hpp:29
A strong type for designated initialisation of the row index of a matrix.
Definition matrix_coordinate.hpp:58
Hide me