SeqAn3 3.4.0-rc.1
The Modern C++ library for sequence analysis.
Loading...
Searching...
No Matches
pairwise_alignment_algorithm.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
21
22namespace seqan3::detail
23{
24
41template <typename alignment_configuration_t, typename... policies_t>
42 requires is_type_specialisation_of_v<alignment_configuration_t, configuration>
43class pairwise_alignment_algorithm : protected policies_t...
44{
45protected:
52
53 static_assert(!std::same_as<alignment_result_type, empty_type>, "Alignment result type was not configured.");
54
55public:
65
73 pairwise_alignment_algorithm(alignment_configuration_t const & config) : policies_t(config)...
74 {}
76
122 template <indexed_sequence_pair_range indexed_sequence_pairs_t, typename callback_t>
123 requires std::invocable<callback_t, alignment_result_type>
124 void operator()(indexed_sequence_pairs_t && indexed_sequence_pairs, callback_t && callback)
125 {
126 using std::get;
127
128 for (auto && [sequence_pair, idx] : indexed_sequence_pairs)
129 {
130 size_t const sequence1_size = std::ranges::distance(get<0>(sequence_pair));
131 size_t const sequence2_size = std::ranges::distance(get<1>(sequence_pair));
132
133 auto && [alignment_matrix, index_matrix] = this->acquire_matrices(sequence1_size, sequence2_size);
134
135 compute_matrix(get<0>(sequence_pair), get<1>(sequence_pair), alignment_matrix, index_matrix);
136 this->make_result_and_invoke(std::forward<decltype(sequence_pair)>(sequence_pair),
137 std::move(idx),
138 this->optimal_score,
139 this->optimal_coordinate,
140 alignment_matrix,
141 callback);
142 }
143 }
145
147 template <indexed_sequence_pair_range indexed_sequence_pairs_t, typename callback_t>
148 requires traits_type::is_vectorised && std::invocable<callback_t, alignment_result_type>
149 auto operator()(indexed_sequence_pairs_t && indexed_sequence_pairs, callback_t && callback)
150 {
151 using simd_collection_t = std::vector<score_type, aligned_allocator<score_type, alignof(score_type)>>;
152 using original_score_t = typename traits_type::original_score_type;
153
154 // Extract the batch of sequences for the first and the second sequence.
155 auto seq1_collection = indexed_sequence_pairs | views::elements<0> | views::elements<0>;
156 auto seq2_collection = indexed_sequence_pairs | views::elements<0> | views::elements<1>;
157
158 this->initialise_tracker(seq1_collection, seq2_collection);
159
160 // Convert batch of sequences to sequence of simd vectors.
161 thread_local simd_collection_t simd_seq1_collection{};
162 thread_local simd_collection_t simd_seq2_collection{};
163
165 seq1_collection,
166 this->scoring_scheme.padding_symbol);
168 seq2_collection,
169 this->scoring_scheme.padding_symbol);
170
171 size_t const sequence1_size = std::ranges::distance(simd_seq1_collection);
172 size_t const sequence2_size = std::ranges::distance(simd_seq2_collection);
173
174 auto && [alignment_matrix, index_matrix] = this->acquire_matrices(sequence1_size, sequence2_size);
175
176 compute_matrix(simd_seq1_collection, simd_seq2_collection, alignment_matrix, index_matrix);
177
178 size_t index = 0;
179 for (auto && [sequence_pair, idx] : indexed_sequence_pairs)
180 {
181 original_score_t score = this->optimal_score[index]
182 - (this->padding_offsets[index] * this->scoring_scheme.padding_match_score());
183 matrix_coordinate coordinate{row_index_type{size_t{this->optimal_coordinate.row[index]}},
184 column_index_type{size_t{this->optimal_coordinate.col[index]}}};
185 this->make_result_and_invoke(std::forward<decltype(sequence_pair)>(sequence_pair),
186 std::move(idx),
187 std::move(score),
188 std::move(coordinate),
189 alignment_matrix,
190 callback);
191 ++index;
192 }
193 }
194
195protected:
215 template <typename simd_sequence_t, std::ranges::forward_range sequence_collection_t, arithmetic padding_symbol_t>
216 requires std::ranges::output_range<simd_sequence_t, score_type>
217 void convert_batch_of_sequences_to_simd_vector(simd_sequence_t & simd_sequence,
218 sequence_collection_t & sequences,
219 padding_symbol_t const & padding_symbol)
220 {
221 assert(static_cast<size_t>(std::ranges::distance(sequences)) <= traits_type::alignments_per_vector);
222
223 simd_sequence.clear();
224 for (auto && simd_vector_chunk : sequences | views::to_simd<score_type>(padding_symbol))
225 std::ranges::move(simd_vector_chunk, std::back_inserter(simd_sequence));
226 }
227
241 template <std::ranges::forward_range sequence1_t,
242 std::ranges::forward_range sequence2_t,
243 std::ranges::input_range alignment_matrix_t,
244 std::ranges::input_range index_matrix_t>
245 requires std::ranges::forward_range<std::ranges::range_reference_t<alignment_matrix_t>>
246 && std::ranges::forward_range<std::ranges::range_reference_t<index_matrix_t>>
247 void compute_matrix(sequence1_t && sequence1,
248 sequence2_t && sequence2,
249 alignment_matrix_t && alignment_matrix,
250 index_matrix_t && index_matrix)
251 {
252 // ---------------------------------------------------------------------
253 // Initialisation phase: allocate memory and initialise first column.
254 // ---------------------------------------------------------------------
255
256 this->reset_optimum(); // Reset the tracker for the new alignment computation.
257
258 auto alignment_matrix_it = alignment_matrix.begin();
259 auto indexed_matrix_it = index_matrix.begin();
260
261 initialise_column(*alignment_matrix_it, *indexed_matrix_it, sequence2);
262
263 // ---------------------------------------------------------------------
264 // Iteration phase: compute column-wise the alignment matrix.
265 // ---------------------------------------------------------------------
266
267 for (auto alphabet1 : sequence1)
268 compute_column(*++alignment_matrix_it,
269 *++indexed_matrix_it,
270 this->scoring_scheme_profile_column(alphabet1),
271 sequence2);
272
273 // ---------------------------------------------------------------------
274 // Final phase: track score of last column
275 // ---------------------------------------------------------------------
276
277 auto && alignment_column = *alignment_matrix_it;
278 auto && cell_index_column = *indexed_matrix_it;
279
280 auto alignment_column_it = alignment_column.begin();
281 auto cell_index_column_it = cell_index_column.begin();
282
283 this->track_last_column_cell(*alignment_column_it, *cell_index_column_it);
284
285 for ([[maybe_unused]] auto && unused : sequence2)
286 this->track_last_column_cell(*++alignment_column_it, *++cell_index_column_it);
287
288 this->track_final_cell(*alignment_column_it, *cell_index_column_it);
289 }
290
309 template <std::ranges::input_range alignment_column_t,
310 std::ranges::input_range cell_index_column_t,
311 std::ranges::input_range sequence2_t>
312 void initialise_column(alignment_column_t && alignment_column,
313 cell_index_column_t && cell_index_column,
314 sequence2_t && sequence2)
315 {
316 // ---------------------------------------------------------------------
317 // Initial phase: prepare column and initialise first cell
318 // ---------------------------------------------------------------------
319
320 auto first_column_it = alignment_column.begin();
321 auto cell_index_column_it = cell_index_column.begin();
322 *first_column_it = this->track_cell(this->initialise_origin_cell(), *cell_index_column_it);
323
324 // ---------------------------------------------------------------------
325 // Iteration phase: iterate over column and compute each cell
326 // ---------------------------------------------------------------------
327
328 for ([[maybe_unused]] auto const & unused : sequence2)
329 {
330 ++first_column_it;
331 *first_column_it =
332 this->track_cell(this->initialise_first_column_cell(*first_column_it), *++cell_index_column_it);
333 }
334
335 // ---------------------------------------------------------------------
336 // Final phase: track last cell of initial column
337 // ---------------------------------------------------------------------
338
339 this->track_last_row_cell(*first_column_it, *cell_index_column_it);
340 }
341
360 template <std::ranges::input_range alignment_column_t,
361 std::ranges::input_range cell_index_column_t,
362 typename alphabet1_t,
363 std::ranges::input_range sequence2_t>
365 void compute_column(alignment_column_t && alignment_column,
366 cell_index_column_t && cell_index_column,
367 alphabet1_t const & alphabet1,
368 sequence2_t && sequence2)
369 {
370 using score_type = typename traits_type::score_type;
371
372 // ---------------------------------------------------------------------
373 // Initial phase: prepare column and initialise first cell
374 // ---------------------------------------------------------------------
375
376 auto alignment_column_it = alignment_column.begin();
377 auto cell_index_column_it = cell_index_column.begin();
378
379 auto cell = *alignment_column_it;
380 score_type diagonal = cell.best_score();
381 *alignment_column_it = this->track_cell(this->initialise_first_row_cell(cell), *cell_index_column_it);
382
383 // ---------------------------------------------------------------------
384 // Iteration phase: iterate over column and compute each cell
385 // ---------------------------------------------------------------------
386
387 for (auto const & alphabet2 : sequence2)
388 {
389 auto cell = *++alignment_column_it;
390 score_type next_diagonal = cell.best_score();
391 *alignment_column_it = this->track_cell(
392 this->compute_inner_cell(diagonal, cell, this->scoring_scheme.score(alphabet1, alphabet2)),
393 *++cell_index_column_it);
394 diagonal = next_diagonal;
395 }
396
397 // ---------------------------------------------------------------------
398 // Final phase: track last cell
399 // ---------------------------------------------------------------------
400
401 this->track_last_row_cell(*alignment_column_it, *cell_index_column_it);
402 }
403};
404
405} // namespace seqan3::detail
Provides seqan3::aligned_allocator.
Provides helper type traits for the configuration and execution of the alignment algorithm.
T back_inserter(T... args)
Allocates uninitialized storage whose memory-alignment is specified by alignment.
Definition aligned_allocator.hpp:74
The alignment algorithm type to compute standard pairwise alignment using dynamic programming.
Definition pairwise_alignment_algorithm.hpp:44
pairwise_alignment_algorithm(alignment_configuration_t const &config)
Constructs and initialises the algorithm using the alignment configuration.
Definition pairwise_alignment_algorithm.hpp:73
void compute_matrix(sequence1_t &&sequence1, sequence2_t &&sequence2, alignment_matrix_t &&alignment_matrix, index_matrix_t &&index_matrix)
Compute the actual alignment.
Definition pairwise_alignment_algorithm.hpp:247
pairwise_alignment_algorithm & operator=(pairwise_alignment_algorithm const &)=default
Defaulted.
pairwise_alignment_algorithm(pairwise_alignment_algorithm &&)=default
Defaulted.
pairwise_alignment_algorithm & operator=(pairwise_alignment_algorithm &&)=default
Defaulted.
pairwise_alignment_algorithm(pairwise_alignment_algorithm const &)=default
Defaulted.
typename traits_type::score_type score_type
The configured score type.
Definition pairwise_alignment_algorithm.hpp:49
::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.hpp:149
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
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
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.hpp:124
Provides seqan3::views::elements.
Provides seqan3::detail::empty_type.
T forward(T... args)
@ diagonal
Trace comes from the diagonal entry.
A helper concept to check if a type is a sequence pair.
The basis for seqan3::alphabet, but requires only rank interface (not char).
The generic simd concept.
T move(T... args)
The internal SeqAn3 namespace.
Definition aligned_sequence_concept.hpp:26
A traits type for the alignment algorithm that exposes static information stored within the alignment...
Definition alignment/pairwise/detail/type_traits.hpp:80
static constexpr bool is_vectorised
Flag to indicate vectorised mode.
Definition alignment/pairwise/detail/type_traits.hpp:112
std::conditional_t< is_vectorised, simd_type_t< original_score_type >, original_score_type > score_type
The score type for the alignment algorithm.
Definition alignment/pairwise/detail/type_traits.hpp:133
static constexpr size_t alignments_per_vector
The number of alignments that can be computed in one simd vector.
Definition alignment/pairwise/detail/type_traits.hpp:146
decltype(determine_alignment_result_type()) alignment_result_type
The alignment result type if present. Otherwise seqan3::detail::empty_type.
Definition alignment/pairwise/detail/type_traits.hpp:137
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
Provides seqan3::detail::to_simd view.
Provides traits to inspect some information of a type, for example its name.
Hide me