SeqAn3 3.4.1-rc.1
The Modern C++ library for sequence analysis.
Loading...
Searching...
No Matches
debug_matrix.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2006-2025 Knut Reinert & Freie Universität Berlin
2// SPDX-FileCopyrightText: 2016-2025 Knut Reinert & MPI für molekulare Genetik
3// SPDX-License-Identifier: BSD-3-Clause
4
10#pragma once
11
12#include <iomanip>
13#include <sstream>
14
23
24namespace seqan3::detail
25{
26
58template <matrix matrix_t, typename first_sequence_t = std::nullopt_t, typename second_sequence_t = std::nullopt_t>
60{
61protected:
63 static constexpr bool has_first_sequence = !std::is_same_v<std::decay_t<first_sequence_t>, std::nullopt_t>;
65 static constexpr bool has_second_sequence = !std::is_same_v<std::decay_t<second_sequence_t>, std::nullopt_t>;
69 static constexpr bool is_traceback_matrix = std::is_same_v<std::decay_t<entry_t>, trace_directions>;
72 static constexpr bool is_optional_score = is_type_specialisation_of_v<entry_t, std::optional>;
73
74public:
87
91 debug_matrix() = default;
92 debug_matrix(debug_matrix const &) = default;
93 debug_matrix(debug_matrix &&) = default;
94 debug_matrix & operator=(debug_matrix const &) = default;
96 ~debug_matrix() = default;
97
101 debug_matrix(matrix_t matrix) : debug_matrix(std::forward<matrix_t>(matrix), std::nullopt, std::nullopt)
102 {}
103
109 debug_matrix(matrix_t matrix, first_sequence_t first_sequence, second_sequence_t second_sequence) :
110 _matrix{std::forward<matrix_t>(matrix)},
111 _first_sequence{std::forward<first_sequence_t>(first_sequence)},
112 _second_sequence{std::forward<second_sequence_t>(second_sequence)}
113 {
114 if constexpr (has_first_sequence)
115 {
116 assert(_matrix.cols() <= _first_sequence.size() + 1u);
117 }
118
119 if constexpr (has_second_sequence)
120 {
121 assert(_matrix.rows() <= _second_sequence.size() + 1u);
122 }
123 }
125
127 size_t rows() const noexcept
128 {
129 if (!_transpose)
130 return _rows.value_or(_matrix.rows());
131 else
132 return _cols.value_or(_matrix.cols());
133 }
134
136 size_t cols() const noexcept
137 {
138 if (!_transpose)
139 return _cols.value_or(_matrix.cols());
140 else
141 return _rows.value_or(_matrix.rows());
142 }
143
145 first_sequence_t const & first_sequence() const noexcept
146 {
147 if (!_transpose)
148 return _first_sequence;
149 else
150 return _second_sequence;
151 }
152
154 second_sequence_t const & second_sequence() const noexcept
155 {
156 if (!_transpose)
157 return _second_sequence;
158 else
159 return _first_sequence;
160 }
161
163 const_reference at(matrix_coordinate const & coordinate) const noexcept
164 {
165 size_t row = coordinate.row;
166 size_t col = coordinate.col;
167
168 assert(row < rows() && col < cols());
169
170 row_index_type const _row{!_transpose ? row : col};
171 column_index_type const _col{!_transpose ? col : row};
172 row_index_type const _mask_row{_transpose == _transpose_mask ? row : col};
173 column_index_type const _mask_col{_transpose == _transpose_mask ? col : row};
174
175 if (!_masking_matrix.has_value() || _masking_matrix.value().at({_mask_row, _mask_col}))
176 {
177 entry_t const & entry = _matrix.at({_row, _col});
178
180 return entry;
181
182 if constexpr (is_traceback_matrix)
183 {
184 trace_directions reverse{};
186 reverse |= trace_directions::up;
188 reverse |= trace_directions::left;
191 return reverse;
192 }
193 }
194
195 if constexpr (is_traceback_matrix)
197 else
198 return std::nullopt;
199 }
200
208 {
209 assert(masking_matrix.rows() == rows());
210 assert(masking_matrix.cols() == cols());
212 _masking_matrix = std::move(masking_matrix);
213 return *this;
214 }
215
220 debug_matrix & mask_matrix(std::vector<bool> masking_vector) noexcept
221 {
222 return mask_matrix(row_wise_matrix<bool>{number_rows{rows()}, number_cols{cols()}, std::move(masking_vector)});
223 }
224
230 debug_matrix & sub_matrix(size_t const new_rows, size_t const new_cols) noexcept
231 {
232 assert(new_rows <= rows());
233 assert(new_cols <= cols());
234 if (!_transpose)
235 {
236 _rows = new_rows;
237 _cols = new_cols;
238 }
239 else
240 {
241 _rows = new_cols;
242 _cols = new_rows;
243 }
244 return *this;
245 }
246
251 {
253 return *this;
254 }
255
256protected:
258 struct format_type; // forward declaration
260
261public:
271 template <typename ostream_t>
272 void stream_matrix(ostream_t & cout, fmtflags2 const flags) const noexcept
273 {
274 format_type const & symbols = (flags & fmtflags2::utf8) == fmtflags2::utf8 ? unicode : csv;
275 size_t const column_width =
276 this->column_width.has_value() ? this->column_width.value() : auto_column_width(flags);
277
278 auto char_first_sequence = [&]([[maybe_unused]] size_t const i) -> std::string
279 {
280 if constexpr (!has_first_sequence)
281 return " ";
282 else
283 return as_string(first_sequence()[i], flags);
284 };
285
286 auto char_second_sequence = [&]([[maybe_unused]] size_t const i) -> std::string
287 {
288 if constexpr (!has_second_sequence)
289 return " ";
290 else
291 return as_string(second_sequence()[i], flags);
292 };
293
294 auto print_cell = [&](std::string const & symbol)
295 {
296 // deal with unicode chars that mess up std::setw
297 size_t const length_bytes = symbol.size();
298 size_t const length = unicode_str_length(symbol);
299 size_t const offset = length_bytes - length;
300
301 cout << std::left << std::setw(column_width + offset) << symbol << symbols.col_sep;
302 };
303
304 auto print_first_cell = [&](std::string const & symbol)
305 {
306 cout << symbol << symbols.col_sep;
307 };
308
309 // |_|d|a|t|a|b|a|s|e|
310 auto print_first_row = [&]
311 {
312 print_first_cell(" ");
313 print_cell(symbols.epsilon);
314
315 for (size_t col = 0; col < cols() - 1; ++col)
316 print_cell(char_first_sequence(col));
317
318 cout << "\n";
319 };
320
321 // |-|-|-|-|-|-|-|-|-|
322 auto print_divider = [&]
323 {
324 cout << " " << symbols.row_col_sep;
325 for (size_t col = 0; col < cols(); ++col)
326 {
327 for (size_t i = 0; i < column_width; ++i)
328 cout << symbols.row_sep;
329
330 cout << symbols.row_col_sep;
331 }
332 cout << "\n";
333 };
334
335 print_first_row();
336 for (size_t row = 0; row < rows(); ++row)
337 {
338 if (symbols.row_sep[0] != '\0')
339 print_divider();
340
341 // one query letter + one row of scores / traces
342 if (row == 0)
343 print_first_cell(symbols.epsilon);
344 else
345 print_first_cell(char_second_sequence(row - 1));
346
347 for (size_t col = 0; col < cols(); ++col)
348 print_cell(entry_at({row_index_type{row}, column_index_type{col}}, flags));
349
350 cout << "\n";
351 }
352 }
353
355 size_t auto_column_width(fmtflags2 const flags) const noexcept
356 {
357 size_t col_width = 1;
358 for (size_t row = 0; row < rows(); ++row)
359 for (size_t col = 0; col < cols(); ++col)
360 col_width =
361 std::max(col_width,
363
364 return col_width;
365 }
366
367protected:
369 std::string entry_at(matrix_coordinate const coordinate, fmtflags2 flags) const noexcept
370 {
371 format_type const & symbols = (flags & fmtflags2::utf8) == fmtflags2::utf8 ? unicode : csv;
372
373 value_type const & entry = at(coordinate);
374 if (!is_traceback_matrix && entry == matrix_inf<value_type>)
375 return symbols.inf;
376
377 return as_string(entry, flags);
378 }
379
381 template <typename value_type>
382 static std::string as_string(value_type && entry, fmtflags2 const flags) noexcept
383 {
384 std::stringstream strstream;
385 debug_stream_type stream{strstream};
386 stream << flags << entry;
387 return strstream.str();
388 }
389
392 static size_t unicode_str_length(std::string const & str) noexcept
393 {
394 size_t length = 0u;
395 for (auto it = str.cbegin(); it < str.cend(); ++it, ++length)
396 {
397 uint8_t v = *it;
398 if ((v & 0b1110'0000) == 0b1100'0000)
399 ++it;
400 else if ((v & 0b1111'0000) == 0b1110'0000)
401 it += 2;
402 else if ((v & 0b1111'1000) == 0b1111'0000)
403 it += 3;
404 }
405 return length;
406 }
407
410 {
412 char const * epsilon{};
414 char const * col_sep{};
416 char const * row_sep{};
418 char const * row_col_sep{};
420 char const * inf{};
421 };
422
424 static constexpr format_type csv{" ", ";", "", "", ""};
426 static constexpr format_type unicode{"ε", "║", "═", "╬", "∞"};
427
428public:
431
432protected:
434 matrix_t _matrix;
436 first_sequence_t _first_sequence;
438 second_sequence_t _second_sequence;
449};
450
456template <matrix matrix_t>
458
461template <matrix matrix_t, typename first_sequence_t, typename second_sequence_t>
462debug_matrix(matrix_t &&,
463 first_sequence_t &&,
466
467} // namespace seqan3::detail
468
469namespace seqan3
470{
471
479template <detail::matrix alignment_matrix_t>
480struct alignment_matrix_printer<alignment_matrix_t>
481{
494 template <typename stream_t, typename arg_t>
495 requires detail::is_type_specialisation_of_v<stream_t, debug_stream_type>
496 constexpr void operator()(stream_t & stream, arg_t && arg) const
497 {
498 print_impl(stream.get_underlying_stream(), stream.flags2(), std::forward<arg_t>(arg));
499 }
500
511 template <typename stream_t, typename arg_t>
512 constexpr void operator()(stream_t & stream, arg_t && arg) const
513 {
514 print_impl(stream, fmtflags2::none, std::forward<arg_t>(arg));
515 }
516
517private:
525 template <typename stream_t, typename arg_t>
526 void print_impl(stream_t & stream, fmtflags2 const flags, arg_t && arg) const
527 {
528 detail::debug_matrix debug{std::forward<arg_t>(arg)};
529
530 debug.stream_matrix(stream, flags);
531 }
532};
533
534} // namespace seqan3
A "pretty printer" for most SeqAn data structures and related types.
Definition debug_stream_type.hpp:79
A debug matrix to wrap alignment matrices and sequences and make them printable together.
Definition debug_matrix.hpp:60
std::optional< size_t > _cols
The number of columns the debug matrix should have. Must be at most the size of the original matrix.
Definition debug_matrix.hpp:442
debug_matrix & mask_matrix(row_wise_matrix< bool > masking_matrix) noexcept
Masks entries out of the current matrix. This operations changes the way this.at(i,...
Definition debug_matrix.hpp:207
first_sequence_t const & first_sequence() const noexcept
The first sequence of the sequence alignment.
Definition debug_matrix.hpp:145
debug_matrix(matrix_t &&, first_sequence_t &&, second_sequence_t &&) -> debug_matrix< matrix_t, first_sequence_t, second_sequence_t >
The type deduction guide for the constructor seqan3::detail::debug_matrix(matrix_t,...
static constexpr format_type unicode
The format when printing to a unicode stream.
Definition debug_matrix.hpp:426
static std::string as_string(value_type &&entry, fmtflags2 const flags) noexcept
Convert a value into a std::string.
Definition debug_matrix.hpp:382
size_t rows() const noexcept
The number of rows in the matrix.
Definition debug_matrix.hpp:127
size_t cols() const noexcept
The number of columns in the matrix.
Definition debug_matrix.hpp:136
bool _transpose
Whether the current matrix should be transposed.
Definition debug_matrix.hpp:446
debug_matrix & operator=(debug_matrix &&)=default
Defaulted.
debug_matrix()=default
Defaulted.
debug_matrix(debug_matrix &&)=default
Defaulted.
bool _transpose_mask
Whether the masking matrix should be transposed.
Definition debug_matrix.hpp:448
size_t auto_column_width(fmtflags2 const flags) const noexcept
Determines the largest width of all entries in the matrix, e.g. -152 has width 4.
Definition debug_matrix.hpp:355
debug_matrix(debug_matrix const &)=default
Defaulted.
debug_matrix & sub_matrix(size_t const new_rows, size_t const new_cols) noexcept
Limits the view port of the current matrix.
Definition debug_matrix.hpp:230
static constexpr bool is_traceback_matrix
Whether the value_type is trace_directions.
Definition debug_matrix.hpp:69
debug_matrix & mask_matrix(std::vector< bool > masking_vector) noexcept
Creates the masking_matrix out of the given masking_vector and calls mask_matrix(row_wise_matrix<bool...
Definition debug_matrix.hpp:220
std::conditional_t< is_traceback_matrix||is_optional_score, entry_t, std::optional< entry_t > > value_type
The type of an entry in the matrix.
Definition debug_matrix.hpp:79
second_sequence_t const & second_sequence() const noexcept
The second sequence of the sequence alignment.
Definition debug_matrix.hpp:154
static constexpr bool is_optional_score
Whether a score matrix already returns std::optional scores. (Where std::nullopt means unset/invalid/...
Definition debug_matrix.hpp:72
~debug_matrix()=default
Defaulted.
static constexpr format_type csv
The format when printing to a ascii stream.
Definition debug_matrix.hpp:424
std::optional< row_wise_matrix< bool > > _masking_matrix
The masking matrix.
Definition debug_matrix.hpp:444
value_type reference
The type of a reference to an entry in the matrix.
Definition debug_matrix.hpp:81
static constexpr bool has_second_sequence
Whether the current debug_matrix was given a second_sequence.
Definition debug_matrix.hpp:65
std::optional< size_t > _rows
The number of rows the debug matrix should have. Must be at most the size of the original matrix.
Definition debug_matrix.hpp:440
matrix_t _matrix
The matrix.
Definition debug_matrix.hpp:434
first_sequence_t _first_sequence
The first sequence of the sequence alignment.
Definition debug_matrix.hpp:436
debug_matrix & transpose_matrix() noexcept
Transposes the current matrix.
Definition debug_matrix.hpp:250
debug_matrix(matrix_t matrix)
Construct the matrix out of an existing matrix.
Definition debug_matrix.hpp:101
second_sequence_t _second_sequence
The second sequence of the sequence alignment.
Definition debug_matrix.hpp:438
typename std::remove_reference_t< matrix_t >::value_type entry_t
The entry type.
Definition debug_matrix.hpp:67
void stream_matrix(ostream_t &cout, fmtflags2 const flags) const noexcept
Prints this matrix into the given stream.
Definition debug_matrix.hpp:272
debug_matrix & operator=(debug_matrix const &)=default
Defaulted.
debug_matrix(matrix_t &&) -> debug_matrix< matrix_t >
The type deduction guide for the constructor seqan3::detail::debug_matrix(matrix_t)
const_reference at(matrix_coordinate const &coordinate) const noexcept
A reference to the entry of the matrix at the given coordinate.
Definition debug_matrix.hpp:163
typename std::remove_reference_t< matrix_t >::size_type size_type
The size type.
Definition debug_matrix.hpp:85
std::string entry_at(matrix_coordinate const coordinate, fmtflags2 flags) const noexcept
Same as at(coordinate), but as string.
Definition debug_matrix.hpp:369
debug_matrix(matrix_t matrix, first_sequence_t first_sequence, second_sequence_t second_sequence)
Construct the matrix out of an existing matrix and two sequences.
Definition debug_matrix.hpp:109
static size_t unicode_str_length(std::string const &str) noexcept
The length of the str (traceback symbols are unicode aware).
Definition debug_matrix.hpp:392
std::optional< size_t > column_width
What is the width (number of chars) of an entry. Defaults to auto_column_width.
Definition debug_matrix.hpp:430
static constexpr bool has_first_sequence
Whether the current debug_matrix was given a first_sequence.
Definition debug_matrix.hpp:63
Defines the requirements of a matrix (e.g. score matrices, trace matrices).
Definition matrix_concept.hpp:52
A two dimensional matrix used inside of alignment algorithms.
Definition two_dimensional_matrix.hpp:62
Provides seqan3::debug_stream and related types.
Provides seqan3::debug_stream and related types.
trace_directions
The possible directions a trace can have. The values can be combined by the logical |-operator.
Definition trace_directions.hpp:30
@ row
The corresponding alignment coordinate will be incrementable/decrementable in the row index.
@ up
Trace comes from the above entry.
@ left
Trace comes from the left entry.
@ diagonal
Trace comes from the diagonal entry.
fmtflags2
Flags that change the behaviour of the seqan3::debug_stream.
Definition debug_stream_type.hpp:32
@ utf8
Enables use of non-ASCII UTF8 characters in formatted output.
@ none
No flag is set.
@ offset
Sequence (seqan3::field::seq) relative start position (0-based), unsigned value.
T left(T... args)
Provides seqan3::detail::matrix.
T max(T... args)
The internal SeqAn3 namespace.
Definition aligned_sequence_concept.hpp:26
The main SeqAn3 namespace.
Definition aligned_sequence_concept.hpp:26
SeqAn specific customisations in the standard namespace.
T has_value(T... args)
Provides seqan3::debug_stream and related types.
Provides seqan3::debug_stream and related types.
Provides seqan3::detail::row_wise_matrix.
T setw(T... args)
T str(T... args)
constexpr void operator()(stream_t &stream, arg_t &&arg) const
Prints the alignment matrix into the given stream using ascii formatting.
Definition debug_matrix.hpp:512
void print_impl(stream_t &stream, fmtflags2 const flags, arg_t &&arg) const
Prints the alignment matrix into the given formatted output stream.
Definition debug_matrix.hpp:526
constexpr void operator()(stream_t &stream, arg_t &&arg) const
Prints the alignment matrix into the given stream using formatting specified by seqan3::fmtflags2.
Definition debug_matrix.hpp:496
Definition default_printer.hpp:28
A strong type for designated initialisation of the column index of a matrix.
Definition matrix_coordinate.hpp:29
Format used by seqan3::detail::debug_matrix.
Definition debug_matrix.hpp:410
char const * inf
Infinity symbol (a single symbol)
Definition debug_matrix.hpp:420
char const * row_col_sep
Row separator symbol (a single symbol)
Definition debug_matrix.hpp:418
char const * col_sep
Column separator symbol (a single symbol)
Definition debug_matrix.hpp:414
char const * row_sep
Row separator symbol (a single symbol)
Definition debug_matrix.hpp:416
char const * epsilon
Epsilon symbol (a single symbol)
Definition debug_matrix.hpp:412
Strong type for setting the column dimension of a matrix.
Definition two_dimensional_matrix.hpp:29
Strong type for setting the row dimension of a matrix.
Definition two_dimensional_matrix.hpp:37
A strong type for designated initialisation of the row index of a matrix.
Definition matrix_coordinate.hpp:58
Provides type traits for working with templates.
Provides the declaration of seqan3::detail::trace_directions.
T value_or(T... args)
Hide me