Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated PR for the printer design proposal #3259

Merged
merged 1 commit into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -91,27 +91,31 @@ void stream_alignment(debug_stream_type<char_t> & stream,

namespace seqan3
{
/*!\brief Stream operator for alignments, which are represented as tuples of aligned sequences.

/*!\brief The printer for alignment.
* \tparam alignment_t The type of the alignment; must model seqan3::tuple_like and all sequences must be
* seqan3::aligned_sequence.
* \ingroup alignment_aligned_sequence
*
* \tparam alignment_t The alignment type, must satisfy tuple_like and its size must be at least 2.
*
* \param[in,out] stream The target stream for the formatted output.
* \param[in] alignment The alignment that shall be formatted. All sequences must be equally long.
*
* \return The given stream to which the alignment representation is appended.
*/
template <typename char_t, typename alignment_t>
requires (detail::debug_streamable_tuple<alignment_t>
&& detail::all_model_aligned_seq<detail::tuple_type_list_t<std::remove_cvref_t<alignment_t>>>)
inline debug_stream_type<char_t> & operator<<(debug_stream_type<char_t> & stream, alignment_t && alignment)
template <typename alignment_t>
requires tuple_like<alignment_t> && detail::all_model_aligned_seq<detail::tuple_type_list_t<alignment_t>>
struct alignment_printer<alignment_t>
{
constexpr size_t sequence_count = std::tuple_size_v<std::remove_cvref_t<alignment_t>>;
/*!\brief The function call operator that pretty prints the alignment to the stream.
* \tparam stream_t The type of the stream.
* \tparam arg_t The type of the argument.
* \param[in,out] stream The target stream for the formatted output.
* \param[in] arg The alignment that shall be formatted. All sequences must be equally long.
*/
template <typename stream_t, typename arg_t>
constexpr void operator()(stream_t & stream, arg_t && arg) const
{
constexpr size_t sequence_count = std::tuple_size_v<std::remove_cvref_t<arg_t>>;

static_assert(sequence_count >= 2, "An alignment requires at least two sequences.");
static_assert(sequence_count >= 2, "An alignment requires at least two sequences.");

detail::stream_alignment(stream, alignment, std::make_index_sequence<sequence_count - 1>{});
return stream;
}
detail::stream_alignment(stream, std::forward<arg_t>(arg), std::make_index_sequence<sequence_count - 1>{});
}
};

} // namespace seqan3
Original file line number Diff line number Diff line change
Expand Up @@ -294,23 +294,26 @@ class advanceable_alignment_coordinate
namespace seqan3
{

/*!\brief A seqan3::detail::advanceable_alignment_coordinate can be printed to the seqan3::debug_stream.
* \tparam coordinate_type The alignment coordinate type.
* \param[in] s The seqan3::debug_stream.
* \param[in] c The alignment coordinate to print.
* \relates seqan3::debug_stream_type
/*!\brief The printer for seqan3::detail::advanceable_alignment_coordinate.
*
* \details
* Prints the alignment coordinate as a tuple of the column and row index.
*
* Prints the alignment coordinate as a tuple.
* \tparam state_t The state of the detail::advanceable_alignment_coordinate.
* \ingroup alignment_matrix
*/
template <typename char_t, typename coordinate_type>
requires detail::is_value_specialisation_of_v<std::remove_cvref_t<coordinate_type>,
detail::advanceable_alignment_coordinate>
inline debug_stream_type<char_t> & operator<<(debug_stream_type<char_t> & s, coordinate_type && c)
template <auto state_t>
struct advanceable_alignment_coordinate_printer<detail::advanceable_alignment_coordinate<state_t>>
{
s << std::tie(c.first, c.second);
return s;
}
/*!\brief The function call operator that prints the coordinate to the given stream.
* \tparam stream_t The type of the stream.
* \param[in,out] stream The stream to print to.
* \param[in] arg The alignment coordinate to print.
*/
template <typename stream_t>
constexpr void operator()(stream_t & stream, detail::advanceable_alignment_coordinate<state_t> const arg) const
{
stream << std::tie(arg.first, arg.second);
}
};

} // namespace seqan3
82 changes: 58 additions & 24 deletions include/seqan3/alignment/matrix/detail/debug_matrix.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -467,33 +467,67 @@ debug_matrix(matrix_t &&,

namespace seqan3
{
/*!\brief An alignment matrix can be printed to the seqan3::debug_stream.
* \tparam alignment_matrix_t Type of the alignment matrix to be printed; must model seqan3::detail::matrix.
* \param s The seqan3::debug_stream.
* \param matrix The alignment matrix.
* \relates seqan3::debug_stream_type

/*!\brief The printer for alignment scoring and trace matrices.
*
* \details
* Prints the alignment matrix to the given formatted ouput stream.
*
* This prints out an alignment matrix which can be a score matrix or a trace matrix.
* \tparam alignment_matrix_t The type of the alignment matrix; must model seqan3::detail::matrix.
* \ingroup alignment_matrix
*/
template <typename char_t, detail::matrix alignment_matrix_t>
inline debug_stream_type<char_t> & operator<<(debug_stream_type<char_t> & s, alignment_matrix_t && matrix)
template <detail::matrix alignment_matrix_t>
struct alignment_matrix_printer<alignment_matrix_t>
{
detail::debug_matrix debug{std::forward<alignment_matrix_t>(matrix)};

std::stringstream sstream{};
debug.stream_matrix(sstream, s.flags2());
s << sstream.str();
return s;
}

//!\overload
template <typename char_t, std::ranges::input_range alignment_matrix_t>
requires detail::debug_stream_range_guard<alignment_matrix_t> && detail::matrix<alignment_matrix_t>
inline debug_stream_type<char_t> & operator<<(debug_stream_type<char_t> & s, alignment_matrix_t && matrix)
{
return s << detail::debug_matrix{std::forward<alignment_matrix_t>(matrix)};
}
/*!\brief Prints the alignment matrix into the given stream using formatting specified by seqan3::fmtflags2.
*
* This overload is selected if the stream is a seqan3::debug_stream_type and has a `flags2()` member function that
* returns a seqan3::fmtflags2 object.
* Using the flags2() member function allows to print the matrix with unicode characters if seqan3::fmtflags2::utf8
* is set to the seqan3::debug_stream.
*
* \tparam stream_t The type of the stream.
* \tparam arg_t The type of the argument.
* \param stream The stream to print to.
* \param arg The alignment matrix to print
*/
template <typename stream_t, typename arg_t>
requires detail::is_type_specialisation_of_v<stream_t, debug_stream_type>
constexpr void operator()(stream_t & stream, arg_t && arg) const
{
print_impl(stream.get_underlying_stream(), stream.flags2(), std::forward<arg_t>(arg));
}

/*!\brief Prints the alignment matrix into the given stream using ascii formatting.
*
* This overload is selected if the stream is \b not a seqan3::debug_stream_type and always prints
* with seqan3::fmtflags2::none.
*
* \tparam stream_t The type of the stream.
* \tparam arg_t The type of the argument.
* \param stream The stream to print to.
* \param arg The alignment matrix to print.
*/
template <typename stream_t, typename arg_t>
constexpr void operator()(stream_t & stream, arg_t && arg) const
{
print_impl(stream, fmtflags2::none, std::forward<arg_t>(arg));
}

private:
/*!\brief Prints the alignment matrix into the given formatted output stream.
* \tparam stream_t The type of the stream.
* \tparam arg_t The type of the argument.
* \param stream The stream to print to.
* \param flags The flags to modify the way the matrix is printed.
* \param arg The alignment matrix to print.
*/
template <typename stream_t, typename arg_t>
void print_impl(stream_t & stream, fmtflags2 const flags, arg_t && arg) const
{
detail::debug_matrix debug{std::forward<arg_t>(arg)};

debug.stream_matrix(stream, flags);
}
};

} // namespace seqan3
85 changes: 66 additions & 19 deletions include/seqan3/alignment/matrix/detail/trace_directions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@

#pragma once

#include <array>
#include <string_view>

#include <seqan3/core/add_enum_bitwise_operators.hpp>
#include <seqan3/core/debug_stream/debug_stream_type.hpp>
#include <seqan3/core/detail/template_inspection.hpp>

namespace seqan3::detail
{
Expand Down Expand Up @@ -54,12 +58,7 @@ template <>
inline constexpr bool add_enum_bitwise_operators<seqan3::detail::trace_directions> = true;
//!\endcond

/*!\brief All trace_directions can be printed as ascii or as utf8 to the seqan3::debug_stream.
* \param s The seqan3::debug_stream.
* \param trace The trace direction.
* \relates seqan3::debug_stream_type
*
* \details
/*!\brief Prints `trace_directions` as ascii or as utf8 to output stream.
*
* The following table shows the printed symbol of a particular seqan3::detail::trace_directions:
*
Expand All @@ -71,23 +70,71 @@ inline constexpr bool add_enum_bitwise_operators<seqan3::detail::trace_direction
* | seqan3::detail::trace_directions::up | ⇡ | u |
* | seqan3::detail::trace_directions::left_open | ← | L |
* | seqan3::detail::trace_directions::left | ⇠ | l |
*
* \ingroup alignment_matrix
*/
template <typename char_t>
inline debug_stream_type<char_t> & operator<<(debug_stream_type<char_t> & s, detail::trace_directions const trace)
template <>
struct trace_directions_printer<detail::trace_directions>
{
static char const * unicode[32]{"↺", "↖", "↑", "↖↑", "⇡", "↖⇡", "↑⇡", "↖↑⇡", "←", "↖←", "↑←",
"↖↑←", "⇡←", "↖⇡←", "↑⇡←", "↖↑⇡←", "⇠", "↖⇠", "↑⇠", "↖↑⇠", "⇡⇠", "↖⇡⇠",
"↑⇡⇠", "↖↑⇡⇠", "←⇠", "↖←⇠", "↑←⇠", "↖↑←⇠", "⇡←⇠", "↖⇡←⇠", "↑⇡←⇠", "↖↑⇡←⇠"};
private:
//!\brief The unicode representation of the trace directions.
static constexpr std::array<std::string_view, 32> unicode{
"↺", "↖", "↑", "↖↑", "⇡", "↖⇡", "↑⇡", "↖↑⇡", "←", "↖←", "↑←", "↖↑←", "⇡←", "↖⇡←", "↑⇡←", "↖↑⇡←",
"⇠", "↖⇠", "↑⇠", "↖↑⇠", "⇡⇠", "↖⇡⇠", "↑⇡⇠", "↖↑⇡⇠", "←⇠", "↖←⇠", "↑←⇠", "↖↑←⇠", "⇡←⇠", "↖⇡←⇠", "↑⇡←⇠", "↖↑⇡←⇠"};

//!\brief The ascii representation of the trace directions.
static constexpr std::array<std::string_view, 32> csv{
"N", "D", "U", "DU", "u", "Du", "Uu", "DUu", "L", "DL", "UL", "DUL", "uL", "DuL", "UuL", "DUuL",
"l", "Dl", "Ul", "DUl", "ul", "Dul", "Uul", "DUul", "Ll", "DLl", "ULl", "DULl", "uLl", "DuLl", "UuLl", "DUuLl"};

static char const * csv[32]{"N", "D", "U", "DU", "u", "Du", "Uu", "DUu", "L", "DL", "UL",
"DUL", "uL", "DuL", "UuL", "DUuL", "l", "Dl", "Ul", "DUl", "ul", "Dul",
"Uul", "DUul", "Ll", "DLl", "ULl", "DULl", "uLl", "DuLl", "UuLl", "DUuLl"};
public:
/*!\brief Prints the trace directions into the given stream.
*
* This overload is only available if the stream has a member function `flags2` that returns a `fmtflags2`.
* Using the flags2() member function allows to print the trace with unicode characters if seqan3::fmtflags2::utf8
* is set to the seqan3::debug_stream.
*
* \tparam stream_t The type of the stream.
* \param stream The stream to print to.
* \param trace The trace directions to print.
*/
template <typename stream_t>
requires detail::is_type_specialisation_of_v<stream_t, debug_stream_type>
constexpr void operator()(stream_t & stream, detail::trace_directions const trace) const
{
print_impl(stream, stream.flags2(), trace);
}

bool is_unicode = (s.flags2() & fmtflags2::utf8) == fmtflags2::utf8;
auto const & trace_dir = is_unicode ? unicode : csv;
/*!\brief Prints the trace directions into the given stream.
*
* This overload is only available if the stream has no member function `flags2`. In this case it will use
* ascii characters to print the trace.
*
* \tparam stream_t The type of the stream.
* \param stream The stream to print to.
* \param trace The trace directions to print.
*/
template <typename stream_t>
constexpr void operator()(stream_t & stream, detail::trace_directions const trace) const
{
print_impl(stream, fmtflags2::none, trace);
}

s << trace_dir[static_cast<size_t>(trace)];
return s;
}
private:
/*!\brief Prints the trace directions
* \tparam stream_t The type of the stream.
* \param stream The stream to print to.
* \param flag The flags of the stream.
* \param trace The trace directions to print.
*/
template <typename stream_t>
constexpr void print_impl(stream_t & stream, fmtflags2 const flag, detail::trace_directions const trace) const
{
bool const is_unicode = (flag & fmtflags2::utf8) == fmtflags2::utf8;
auto const & trace_dir = is_unicode ? unicode : csv;

stream << trace_dir[static_cast<size_t>(trace)];
}
};

} // namespace seqan3
Loading
Loading