SeqAn3  3.0.2
The Modern C++ library for sequence analysis.
alignment_trace_algorithms.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2020, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2020, 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 
13 #pragma once
14 
15 #include <deque>
16 #include <vector>
17 
26 
27 namespace seqan3::detail
28 {
29 
37  template <typename trace_matrix_t>
39  requires matrix<std::remove_cvref_t<trace_matrix_t>> &&
40  std::same_as<typename std::remove_cvref_t<trace_matrix_t>::value_type, trace_directions>
42 inline alignment_coordinate alignment_begin_positions(trace_matrix_t && matrix,
43  alignment_coordinate const end_positions)
44 {
45  constexpr auto D = trace_directions::diagonal;
46  constexpr auto L = trace_directions::left;
47  constexpr auto U = trace_directions::up;
48 
49  matrix_coordinate coordinate{row_index_type{end_positions.second}, column_index_type{end_positions.first}};
50 
51  assert(coordinate.row < matrix.rows());
52  assert(coordinate.col < matrix.cols());
53 
54  while (true)
55  {
56  trace_directions dir = matrix.at(coordinate);
57  if ((dir & L) == L)
58  {
59  coordinate.col = std::max<size_t>(coordinate.col, 1) - 1;
60  }
61  else if ((dir & U) == U)
62  {
63  coordinate.row = std::max<size_t>(coordinate.row, 1) - 1;
64  }
65  else if ((dir & D) == D)
66  {
67  coordinate.row = std::max<size_t>(coordinate.row, 1) - 1;
68  coordinate.col = std::max<size_t>(coordinate.col, 1) - 1;
69  }
70  else
71  {
72 #ifndef NDEBUG
73  if (!(coordinate.row == 0 || coordinate.col == 0))
74  throw std::logic_error{"Unknown seqan3::trace_direction in an inner cell of the trace matrix."};
75 #endif
76  break;
77  }
78  }
79 
80  return {column_index_type{coordinate.col}, row_index_type{coordinate.row}};
81 }
82 
96 template <
97  tuple_like alignment_t,
98  typename database_t,
99  typename query_t,
100  typename trace_matrix_t>
102  requires matrix<std::remove_cvref_t<trace_matrix_t>> &&
103  std::same_as<typename std::remove_cvref_t<trace_matrix_t>::value_type, trace_directions> &&
104  detail::all_model_writable_aligned_seq<detail::tuple_type_list_t<alignment_t>>
106 inline alignment_t alignment_trace(database_t && database,
107  query_t && query,
108  trace_matrix_t && matrix,
109  alignment_coordinate const end_positions,
110  alignment_coordinate const begin_positions)
111 {
112  constexpr auto N = trace_directions::none;
113  constexpr auto D = trace_directions::diagonal;
114  constexpr auto L = trace_directions::left;
115  constexpr auto U = trace_directions::up;
116 
117  matrix_coordinate coordinate{row_index_type{end_positions.second}, column_index_type{end_positions.first}};
118 
119  assert(coordinate.row <= query.size());
120  assert(coordinate.col <= database.size());
121  assert(coordinate.row < matrix.rows());
122  assert(coordinate.col < matrix.cols());
123 
124  alignment_t aligned_seq{};
125  assign_unaligned(std::get<0>(aligned_seq), database | views::type_reduce
126  | views::slice(begin_positions.first, coordinate.col));
127  assign_unaligned(std::get<1>(aligned_seq), query | views::type_reduce
128  | views::slice(begin_positions.second, coordinate.row));
129  auto end_aligned_db = std::ranges::cend(std::get<0>(aligned_seq));
130  auto end_aligned_qy = std::ranges::cend(std::get<1>(aligned_seq));
131 
132  if (matrix.at({row_index_type{0u}, column_index_type{0u}}) != N)
133  throw std::logic_error{"End trace must be NONE"};
134 
135  while (true)
136  {
137  trace_directions dir = matrix.at(coordinate);
138  if ((dir & L) == L)
139  {
140  coordinate.col = std::max<size_t>(coordinate.col, 1) - 1;
141  --end_aligned_db;
142  end_aligned_qy = insert_gap(std::get<1>(aligned_seq), end_aligned_qy);
143  }
144  else if ((dir & U) == U)
145  {
146  coordinate.row = std::max<size_t>(coordinate.row, 1) - 1;
147  end_aligned_db = insert_gap(std::get<0>(aligned_seq), end_aligned_db);
148  --end_aligned_qy;
149  }
150  else if ((dir & D) == D)
151  {
152  coordinate.row = std::max<size_t>(coordinate.row, 1) - 1;
153  coordinate.col = std::max<size_t>(coordinate.col, 1) - 1;
154  --end_aligned_db;
155  --end_aligned_qy;
156  }
157  else
158  {
159 #ifndef NDEBUG
160  if (!(coordinate.row == 0 || coordinate.col == 0))
161  throw std::logic_error{"Unknown seqan3::trace_direction in an inner cell of the trace matrix."};
162 #endif
163  break;
164  }
165  }
166 
167  return aligned_seq;
168 }
169 
170 } // namespace seqan3::detail
matrix_concept.hpp
Provides seqan3::detail::matrix.
vector
seqan3::views::type_reduce
constexpr auto type_reduce
A view adaptor that behaves like std::views::all, but type erases certain ranges.
Definition: type_reduce.hpp:158
trace_directions.hpp
Provides the declaration of seqan3::detail::trace_directions.
slice.hpp
Provides seqan3::views::slice.
gapped.hpp
Provides seqan3::gapped.
type_reduce.hpp
Provides seqan3::views::type_reduce.
range.hpp
Provides various transformation traits used by the range module.
deque
std::logic_error
tuple_like
Whether a type behaves like a tuple.
aligned_sequence_concept.hpp
Includes the aligned_sequence and the related insert_gap and erase_gap functions to enable stl contai...
seqan3::alignment_coordinate::second
size_t second
The begin/end position of the alignment in the second sequence.
Definition: alignment_coordinate.hpp:379
seqan3::views::slice
constexpr auto slice
A view adaptor that returns a half-open interval on the underlying range.
Definition: slice.hpp:141
alignment_coordinate.hpp
Provides seqan3::detail::alignment_coordinate.