30namespace seqan3::detail
34struct view_equality_fn
37 template <std::ranges::forward_range rng1_type, std::ranges::forward_range rng2_type>
38 constexpr bool operator()(rng1_type && rng1, rng2_type && rng2)
const
40 return std::ranges::equal(rng1, rng2);
83template <
typename reference_
char_type,
typename query_
char_type>
84[[nodiscard]]
constexpr cigar::operation map_aligned_values_to_cigar_op(reference_char_type
const reference_char,
85 query_char_type
const query_char,
86 bool const extended_cigar)
88 requires seqan3::detail::weakly_equality_comparable_with<reference_char_type, gap> &&
89 seqan3::detail::weakly_equality_comparable_with<query_char_type, gap>
93 uint8_t key = (
static_cast<uint8_t
>(reference_char == gap{}) << 1) |
static_cast<uint8_t
>(query_char == gap{});
94 if (extended_cigar && (key == 0))
95 key |= ((1 << 2) |
static_cast<uint8_t
>(query_char == reference_char));
107inline void update_alignment_lengths(int32_t & ref_length,
108 int32_t & seq_length,
109 char const cigar_operation,
110 uint32_t
const cigar_count)
112 switch (cigar_operation)
114 case 'M':
case '=':
case 'X': ref_length += cigar_count, seq_length += cigar_count;
break;
115 case 'D':
case 'N': ref_length += cigar_count;
break;
116 case 'I': seq_length += cigar_count;
break;
117 case 'S':
case 'H':
case 'P':
break;
118 default:
throw format_error{
"Illegal cigar operation: " +
std::string{cigar_operation}};
136template <
typename cigar_input_type>
141 char cigar_operation{};
142 uint32_t cigar_count{};
143 int32_t ref_length{}, seq_length{};
150 while (std::ranges::begin(cigar_view) != std::ranges::end(cigar_view))
152 auto buff_end = (std::ranges::copy(cigar_view | detail::take_until_or_throw(!
is_digit), buffer.data())).out;
154 std::ranges::next(std::ranges::begin(cigar_view));
157 throw format_error{
"Corrupted cigar string encountered"};
159 update_alignment_lengths(ref_length, seq_length, cigar_operation, cigar_count);
163 return {operations, ref_length, seq_length};
203template <seqan3::detail::pairwise_alignment alignment_type>
205 uint32_t
const query_start_pos = 0,
206 uint32_t
const query_end_pos = 0,
207 bool const extended_cigar =
false)
211 auto &
ref_seq = get<0>(alignment);
212 auto & query_seq = get<1>(alignment);
214 if (
ref_seq.size() != query_seq.size())
224 result.
emplace_back(query_start_pos,
'S'_cigar_operation);
229 cigar::operation operation{map_aligned_values_to_cigar_op(ref_seq[0], query_seq[0], extended_cigar)};
233 for (
auto column :
views::zip(ref_seq, query_seq))
235 cigar::operation next_op = map_aligned_values_to_cigar_op(std::get<0>(column),
239 if (operation == next_op)
245 result.emplace_back(
count, operation);
252 result.emplace_back(
count, operation);
256 result.emplace_back(query_end_pos,
'S'_cigar_operation);
269 std::ranges::for_each(cigar_vector, [&result] (
auto & cig) { result.append(cig.to_string()); });
306template <seqan3::detail::pairwise_alignment alignment_type>
307[[nodiscard]]
inline std::string get_cigar_string(alignment_type && alignment,
308 uint32_t
const query_start_pos = 0,
309 uint32_t
const query_end_pos = 0,
310 bool const extended_cigar =
false)
312 return get_cigar_string(get_cigar_vector(alignment, query_start_pos, query_end_pos, extended_cigar));
348template <seqan3::aligned_sequence ref_seq_type, seqan3::aligned_sequence query_seq_type>
349[[nodiscard]]
inline std::string get_cigar_string(ref_seq_type && ref_seq,
350 query_seq_type && query_seq,
351 uint32_t
const query_start_pos = 0,
352 uint32_t
const query_end_pos = 0,
353 bool const extended_cigar =
false)
355 return get_cigar_string(
std::tie(ref_seq, query_seq), query_start_pos, query_end_pos, extended_cigar);
380template <seqan3::detail::writable_pairwise_alignment alignment_type>
381inline void alignment_from_cigar(alignment_type & alignment,
std::vector<cigar> const & cigar_vector)
387 for (
auto [cigar_count, cigar_operation] : cigar_vector)
390 if ((
'S'_cigar_operation == cigar_operation) || (
'H'_cigar_operation == cigar_operation))
393 assert((
'M'_cigar_operation == cigar_operation) || (
'='_cigar_operation == cigar_operation) ||
394 (
'X'_cigar_operation == cigar_operation) || (
'D'_cigar_operation == cigar_operation) ||
395 (
'N'_cigar_operation == cigar_operation) || (
'I'_cigar_operation == cigar_operation) ||
396 (
'P'_cigar_operation == cigar_operation));
398 if ((
'M'_cigar_operation == cigar_operation) || (
'='_cigar_operation == cigar_operation) ||
399 (
'X'_cigar_operation == cigar_operation))
401 std::ranges::advance(current_ref_pos , cigar_count);
402 std::ranges::advance(current_read_pos, cigar_count);
404 else if ((
'D'_cigar_operation == cigar_operation) || (
'N'_cigar_operation == cigar_operation))
408 assert(
std::distance(current_read_pos, std::ranges::end(get<1>(alignment))) >= 0);
409 current_read_pos = insert_gap(get<1>(alignment), current_read_pos, cigar_count);
411 std::ranges::advance(current_ref_pos , cigar_count);
413 else if ((
'I'_cigar_operation == cigar_operation))
415 assert(std::ranges::distance(current_ref_pos, std::ranges::end(get<0>(alignment))) >= 0);
416 current_ref_pos = insert_gap(get<0>(alignment), current_ref_pos, cigar_count);
418 std::ranges::advance(current_read_pos, cigar_count);
420 else if ((
'P'_cigar_operation == cigar_operation))
422 current_ref_pos = insert_gap(get<0>(alignment), current_ref_pos, cigar_count);
425 current_read_pos = insert_gap(get<1>(alignment), current_read_pos, cigar_count);
433struct access_restrictor_fn
436 template <
typename chr_t>
437 [[noreturn]] chr_t operator()(chr_t)
const
439 throw std::logic_error{
"Access is not allowed because there is no sequence information."};
The <algorithm> header from C++20's standard library.
Provides the seqan3::cigar alphabet.
constexpr derived_type & assign_char(char_type const chr) noexcept
Assign from a character, implicitly converts invalid characters.
Definition: alphabet_base.hpp:165
exposition_only::cigar_operation operation
The (extended) cigar operation alphabet of M,D,I,H,N,P,S,X,=.
Definition: cigar.hpp:99
The <concepts> header from C++20's standard library.
T emplace_back(T... args)
constexpr auto assign_char_to
Assign a character to an alphabet object.
Definition: concept.hpp:526
@ ref_seq
The (reference) "sequence" information, usually a range of nucleotides or amino acids.
constexpr auto is_digit
Checks whether c is a digital character.
Definition: predicate.hpp:269
constexpr ptrdiff_t count
Count the occurrences of a type in a pack.
Definition: traits.hpp:169
constexpr auto single_pass_input
A view adapter that decays most of the range properties and adds single pass behavior.
Definition: single_pass_input.hpp:361
constexpr auto zip
A zip view.
Definition: zip.hpp:29
constexpr auto const & get(configuration< configs_t... > const &config) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: configuration.hpp:429
Provides seqan3::detail::pairwise_alignment and seqan3::detail::writable_pairwise_alignment.
Provides character predicates for tokenisation.
The <ranges> header from C++20's standard library.
The <charconv> header from C++17's standard library.
Provides seqan3::views::take_until and seqan3::views::take_until_or_throw.
Auxiliary for pretty printing of exception messages.
Provides seqan3::tuple_like.
Provides seqan3::views::zip.