26 namespace seqan3::detail
60 template <matrix matrix_t,
typename first_sequence_t = std::nullopt_t,
typename second_sequence_t = std::nullopt_t>
65 static constexpr
bool has_first_sequence = !std::is_same_v<std::decay_t<first_sequence_t>,
std::nullopt_t>;
67 static constexpr
bool has_second_sequence = !std::is_same_v<std::decay_t<second_sequence_t>,
std::nullopt_t>;
71 static constexpr
bool is_traceback_matrix = std::is_same_v<std::decay_t<entry_t>, trace_directions>;
74 static constexpr
bool is_optional_score = is_type_specialisation_of_v<entry_t, std::optional>;
85 using reference = value_type;
87 using const_reference = reference;
95 debug_matrix() =
default;
96 debug_matrix(debug_matrix
const &) =
default;
97 debug_matrix(debug_matrix &&) =
default;
98 debug_matrix & operator=(debug_matrix
const &) =
default;
99 debug_matrix & operator=(debug_matrix &&) =
default;
100 ~debug_matrix() =
default;
105 debug_matrix(matrix_t matrix)
114 debug_matrix(matrix_t matrix, first_sequence_t first_sequence, second_sequence_t second_sequence)
115 : _matrix{std::forward<matrix_t>(matrix)},
116 _first_sequence{std::forward<first_sequence_t>(first_sequence)},
117 _second_sequence{std::forward<second_sequence_t>(second_sequence)}
119 if constexpr(has_first_sequence)
121 assert(_matrix.cols() <= _first_sequence.size() + 1u);
124 if constexpr(has_second_sequence)
126 assert(_matrix.rows() <= _second_sequence.size() + 1u);
132 size_t rows() const noexcept
135 return _rows.value_or(_matrix.rows());
137 return _cols.value_or(_matrix.cols());
141 size_t cols() const noexcept
144 return _cols.value_or(_matrix.cols());
146 return _rows.value_or(_matrix.rows());
150 first_sequence_t
const & first_sequence() const noexcept
153 return _first_sequence;
155 return _second_sequence;
159 second_sequence_t
const & second_sequence() const noexcept
162 return _second_sequence;
164 return _first_sequence;
168 const_reference
at(matrix_coordinate
const & coordinate)
const noexcept
170 size_t row = coordinate.row;
171 size_t col = coordinate.col;
173 assert(row < rows() && col < cols());
175 row_index_type
const _row{!_transpose ? row : col};
176 column_index_type
const _col{!_transpose ? col : row};
177 row_index_type
const _mask_row{_transpose == _transpose_mask ? row : col};
178 column_index_type
const _mask_col{_transpose == _transpose_mask ? col : row};
180 if (!_masking_matrix.has_value() || _masking_matrix.value().at({_mask_row, _mask_col}))
182 entry_t
const & entry = _matrix.at({_row, _col});
184 if (!is_traceback_matrix || !_transpose)
187 if constexpr(is_traceback_matrix)
190 if ((entry & trace_directions::left) == trace_directions::left)
191 reverse |= trace_directions::up;
192 if ((entry & trace_directions::up) == trace_directions::up)
193 reverse |= trace_directions::left;
194 if ((entry & trace_directions::diagonal) == trace_directions::diagonal)
195 reverse |= trace_directions::diagonal;
200 if constexpr(is_traceback_matrix)
201 return trace_directions::none;
212 debug_matrix & mask_matrix(row_wise_matrix<bool> masking_matrix) noexcept
214 assert(masking_matrix.rows() == rows());
215 assert(masking_matrix.cols() == cols());
216 _transpose_mask = _transpose;
217 _masking_matrix =
std::move(masking_matrix);
227 return mask_matrix(row_wise_matrix<bool>{number_rows{rows()},
237 debug_matrix & sub_matrix(
size_t const new_rows,
size_t const new_cols) noexcept
239 assert(new_rows <= rows());
240 assert(new_cols <= cols());
257 debug_matrix & transpose_matrix() noexcept
259 _transpose = !_transpose;
278 template <
typename ostream_t>
279 void stream_matrix(ostream_t & cout,
fmtflags2 const flags)
const noexcept
282 size_t const column_width = this->column_width.has_value() ?
283 this->column_width.value() : auto_column_width(flags);
285 auto char_first_sequence = [&]([[maybe_unused]]
size_t const i) ->
std::string
287 if constexpr(!has_first_sequence)
290 return as_string(first_sequence()[i], flags);
293 auto char_second_sequence = [&]([[maybe_unused]]
size_t const i) ->
std::string
295 if constexpr(!has_second_sequence)
298 return as_string(second_sequence()[i], flags);
304 size_t const length_bytes = symbol.size();
305 size_t const length = unicode_str_length(symbol);
306 size_t const offset = length_bytes - length;
314 auto print_first_cell = [&](
std::string const & symbol)
316 cout << symbol << symbols.col_sep;
320 auto print_first_row = [&]
322 print_first_cell(
" ");
323 print_cell(symbols.epsilon);
325 for (
size_t col = 0; col < cols() - 1; ++col)
326 print_cell(char_first_sequence(col));
332 auto print_divider = [&]
334 cout <<
" " << symbols.row_col_sep;
335 for (
size_t col = 0; col < cols(); ++col)
337 for (
size_t i = 0; i < column_width; ++i)
338 cout << symbols.row_sep;
340 cout << symbols.row_col_sep;
346 for (
size_t row = 0; row < rows(); ++row)
348 if (symbols.row_sep[0] !=
'\0')
353 print_first_cell(symbols.epsilon);
355 print_first_cell(char_second_sequence(row - 1));
357 for (
size_t col = 0; col < cols(); ++col)
358 print_cell(entry_at({row_index_type{row}, column_index_type{col}}, flags));
365 size_t auto_column_width(
fmtflags2 const flags)
const noexcept
367 size_t col_width = 1;
368 for (
size_t row = 0; row < rows(); ++row)
369 for (
size_t col = 0; col < cols(); ++col)
371 unicode_str_length(entry_at({row_index_type{row}, column_index_type{col}}, flags)));
382 value_type
const & entry =
at(coordinate);
383 if (!is_traceback_matrix && entry == matrix_inf<value_type>)
386 return as_string(entry, flags);
390 template <
typename value_type>
394 debug_stream_type stream{strstream};
395 stream << flags << entry;
396 return strstream.
str();
401 static size_t unicode_str_length(
std::string const & str) noexcept
404 for (
auto it = str.cbegin(); it < str.cend(); ++it, ++length)
407 if ((v & 0b11100000) == 0b11000000)
409 else if ((v & 0b11110000) == 0b11100000)
411 else if ((v & 0b11111000) == 0b11110000)
421 char const * epsilon{};
423 char const * col_sep{};
425 char const * row_sep{};
427 char const * row_col_sep{};
433 static constexpr format_type csv{
" ",
";",
"",
"",
""};
435 static constexpr format_type unicode{
"ε",
"║",
"═",
"╬",
"∞"};
445 first_sequence_t _first_sequence;
447 second_sequence_t _second_sequence;
457 bool _transpose_mask{};
464 template <matrix matrix_t>
466 debug_matrix(matrix_t &&)
467 -> debug_matrix<matrix_t>;
471 template <matrix matrix_t,
typename first_sequence_t,
typename second_sequence_t>
472 debug_matrix(matrix_t &&, first_sequence_t &&, second_sequence_t &&)
473 -> debug_matrix<matrix_t, first_sequence_t, second_sequence_t>;
490 template <
typename char_t, detail::matrix alignment_matrix_t>
491 inline debug_stream_type<char_t> &
operator<<(debug_stream_type<char_t> & s, alignment_matrix_t && matrix)
493 detail::debug_matrix debug{std::forward<alignment_matrix_t>(matrix)};
496 debug.stream_matrix(sstream, s.flags2());
502 template <
typename char_t, std::ranges::input_range alignment_matrix_t>
504 requires detail::debug_stream_range_guard<alignment_matrix_t> && detail::matrix<alignment_matrix_t>
506 inline debug_stream_type<char_t> &
operator<<(debug_stream_type<char_t> & s, alignment_matrix_t && matrix)
508 return s << detail::debug_matrix{std::forward<alignment_matrix_t>(matrix)};