30 namespace seqan3::detail
33 struct view_equality_fn
36 template <std::ranges::forward_range rng1_type, std::ranges::forward_range rng2_type>
37 constexpr
bool operator()(rng1_type && rng1, rng2_type && rng2)
const
39 return std::ranges::equal(rng1, rng2);
82 template <
typename reference_
char_type,
typename query_
char_type>
83 [[nodiscard]] constexpr
cigar::operation map_aligned_values_to_cigar_op(reference_char_type
const reference_char,
84 query_char_type
const query_char,
85 bool const extended_cigar)
87 requires seqan3::detail::weakly_equality_comparable_with<reference_char_type, gap> &&
88 seqan3::detail::weakly_equality_comparable_with<query_char_type, gap>
92 uint8_t key = (
static_cast<uint8_t
>(reference_char == gap{}) << 1) |
static_cast<uint8_t
>(query_char == gap{});
93 if (extended_cigar && (key == 0))
94 key |= ((1 << 2) |
static_cast<uint8_t
>(query_char == reference_char));
105 inline void update_alignment_lengths(int32_t & ref_length,
106 int32_t & seq_length,
107 char const cigar_operation,
108 uint32_t
const cigar_count)
110 switch (cigar_operation)
112 case 'M':
case '=':
case 'X': ref_length += cigar_count, seq_length += cigar_count;
break;
113 case 'D':
case 'N': ref_length += cigar_count;
break;
114 case 'I' : seq_length += cigar_count;
break;
115 case 'S':
case 'H':
case 'P':
break;
116 default:
throw format_error{
"Illegal cigar operation: " +
std::string{cigar_operation}};
133 template <
typename cigar_input_type>
138 char cigar_operation{};
139 uint32_t cigar_count{};
140 int32_t ref_length{}, seq_length{};
147 while (std::ranges::begin(cigar_view) != std::ranges::end(cigar_view))
149 auto buff_end = (std::ranges::copy(cigar_view | detail::take_until_or_throw(!
is_digit), buffer.data())).out;
151 std::ranges::next(std::ranges::begin(cigar_view));
154 throw format_error{
"Corrupted cigar string encountered"};
156 update_alignment_lengths(ref_length, seq_length, cigar_operation, cigar_count);
160 return {operations, ref_length, seq_length};
200 template <seqan3::detail::pairwise_alignment alignment_type>
202 uint32_t
const query_start_pos = 0,
203 uint32_t
const query_end_pos = 0,
204 bool const extended_cigar =
false)
208 auto &
ref_seq = get<0>(alignment);
209 auto & query_seq = get<1>(alignment);
211 if (
ref_seq.size() != query_seq.size())
221 result.
emplace_back(query_start_pos,
'S'_cigar_operation);
226 cigar::operation operation{map_aligned_values_to_cigar_op(ref_seq[0], query_seq[0], extended_cigar)};
230 for (
auto column :
views::zip(ref_seq, query_seq))
232 cigar::operation next_op = map_aligned_values_to_cigar_op(std::get<0>(column),
236 if (operation == next_op)
242 result.emplace_back(
count, operation);
249 result.emplace_back(
count, operation);
253 result.emplace_back(query_end_pos,
'S'_cigar_operation);
266 std::ranges::for_each(cigar_vector, [&result] (
auto & cig) { result.append(cig.to_string()); });
303 template <seqan3::detail::pairwise_alignment alignment_type>
304 [[nodiscard]]
inline std::string get_cigar_string(alignment_type && alignment,
305 uint32_t
const query_start_pos = 0,
306 uint32_t
const query_end_pos = 0,
307 bool const extended_cigar =
false)
309 return get_cigar_string(get_cigar_vector(alignment, query_start_pos, query_end_pos, extended_cigar));
345 template <seqan3::aligned_sequence ref_seq_type, seqan3::aligned_sequence query_seq_type>
346 [[nodiscard]]
inline std::string get_cigar_string(ref_seq_type && ref_seq,
347 query_seq_type && query_seq,
348 uint32_t
const query_start_pos = 0,
349 uint32_t
const query_end_pos = 0,
350 bool const extended_cigar =
false)
352 return get_cigar_string(
std::tie(ref_seq, query_seq), query_start_pos, query_end_pos, extended_cigar);
377 template <seqan3::detail::writable_pairwise_alignment alignment_type>
378 inline void alignment_from_cigar(alignment_type & alignment,
std::vector<cigar> const & cigar_vector)
384 for (
auto [cigar_count, cigar_operation] : cigar_vector)
387 if ((
'S'_cigar_operation == cigar_operation) || (
'H'_cigar_operation == cigar_operation))
390 assert((
'M'_cigar_operation == cigar_operation) || (
'='_cigar_operation == cigar_operation) ||
391 (
'X'_cigar_operation == cigar_operation) || (
'D'_cigar_operation == cigar_operation) ||
392 (
'N'_cigar_operation == cigar_operation) || (
'I'_cigar_operation == cigar_operation) ||
393 (
'P'_cigar_operation == cigar_operation));
395 if ((
'M'_cigar_operation == cigar_operation) || (
'='_cigar_operation == cigar_operation) ||
396 (
'X'_cigar_operation == cigar_operation))
398 std::ranges::advance(current_ref_pos , cigar_count);
399 std::ranges::advance(current_read_pos, cigar_count);
401 else if ((
'D'_cigar_operation == cigar_operation) || (
'N'_cigar_operation == cigar_operation))
405 assert(
std::distance(current_read_pos, std::ranges::end(get<1>(alignment))) >= 0);
406 current_read_pos = insert_gap(get<1>(alignment), current_read_pos, cigar_count);
408 std::ranges::advance(current_ref_pos , cigar_count);
410 else if ((
'I'_cigar_operation == cigar_operation))
412 assert(std::ranges::distance(current_ref_pos, std::ranges::end(get<0>(alignment))) >= 0);
413 current_ref_pos = insert_gap(get<0>(alignment), current_ref_pos, cigar_count);
415 std::ranges::advance(current_read_pos, cigar_count);
417 else if ((
'P'_cigar_operation == cigar_operation))
419 current_ref_pos = insert_gap(get<0>(alignment), current_ref_pos, cigar_count);
422 current_read_pos = insert_gap(get<1>(alignment), current_read_pos, cigar_count);
429 struct access_restrictor_fn
432 template <
typename chr_t>
433 [[noreturn]] chr_t operator()(chr_t)
const
435 throw std::logic_error{
"Access is not allowed because there is no sequence information."};
Adaptations of algorithms from the Ranges TS.
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:211
exposition_only::cigar_operation operation
The (extended) cigar operation alphabet of M,D,I,H,N,P,S,X,=.
Definition: cigar.hpp:99
Auxiliary for pretty printing of exception messages.
T emplace_back(T... args)
constexpr auto assign_char_to
Assign a character to an alphabet object.
Definition: concept.hpp:523
constexpr auto is_digit
Checks whether c is a digital character.
Definition: predicate.hpp:287
@ ref_seq
The (reference) "sequence" information, usually a range of nucleotides or amino acids.
constexpr ptrdiff_t count
Count the occurrences of a type in a pack.
Definition: traits.hpp:169
constexpr auto get
A view calling get on each element in a range.
Definition: elements.hpp:114
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:365
constexpr auto zip
A zip view.
Definition: zip.hpp:29
Provides seqan3::detail::pairwise_alignment and seqan3::detail::writable_pairwise_alignment.
Adaptations of concepts from the Ranges TS.
Provides std::from_chars and std::to_chars if not defined in the stdlib <charconv> header.
Provides seqan3::views::take_until and seqan3::views::take_until_or_throw.
Provides character predicates for tokenisation.
Provides seqan3::tuple_like.
Provides seqan3::views::zip.