SeqAn3  3.2.0-rc.1
The Modern C++ library for sequence analysis.
aligned_sequence_concept.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2022, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2022, Knut Reinert & MPI für molekulare Genetik
4 // This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
5 // shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
6 // -----------------------------------------------------------------------------------------------------
7 
14 #pragma once
15 
16 #include <algorithm>
17 #include <ranges>
18 
23 
24 // ---------------------------------------------------------------------------------------------------------------------
25 // unaligned_seq transformation trait
26 // ---------------------------------------------------------------------------------------------------------------------
27 
28 namespace seqan3::detail
29 {
30 
32 template <template <typename...> typename container_type, typename seq_alph_t, typename... rest_t>
34 constexpr auto remove_gap_from_value_type(container_type<gapped<seq_alph_t>, rest_t...>)
35  -> container_type<seq_alph_t, rest_t...>;
36 
38 template <template <typename...> typename container_type,
39  template <typename...>
40  typename allocator_type,
41  typename seq_alph_t,
42  typename... rest_t>
43  requires container<container_type<gapped<seq_alph_t>, allocator_type<gapped<seq_alph_t>>, rest_t...>>
44 constexpr auto
45  remove_gap_from_value_type(container_type<gapped<seq_alph_t>, allocator_type<gapped<seq_alph_t>>, rest_t...>)
46  -> container_type<seq_alph_t, allocator_type<seq_alph_t>, rest_t...>;
47 
49 template <typename t>
50 struct unaligned_seq
51 {};
52 
54 template <typename t>
56  && requires { remove_gap_from_value_type(std::declval<t>()); }
57 struct unaligned_seq<t>
58 {
60  using type = decltype(remove_gap_from_value_type(std::declval<t>()));
61 };
62 
63 // customisation point for our gap decorators.
65 template <typename t>
67 struct unaligned_seq<t>
68 {
70 };
71 
73 template <typename t>
74 using unaligned_seq_t = typename unaligned_seq<t>::type;
75 
76 } // namespace seqan3::detail
77 
78 // ---------------------------------------------------------------------------------------------------------------------
79 // aligned_sequence
80 // ---------------------------------------------------------------------------------------------------------------------
81 
82 namespace seqan3
83 {
84 
106 template <typename t>
107 concept aligned_sequence = sequence<t> && std::equality_comparable_with<std::ranges::range_reference_t<t>, gap>;
109 
216 template <typename t>
218  aligned_sequence<t> && std::ranges::forward_range<t> && requires { typename detail::unaligned_seq_t<t>; }
219  && requires (t v, detail::unaligned_seq_t<t> unaligned) {
220  // global functions for generic usability
221  {
222  insert_gap(v, std::ranges::begin(v))
223  } -> std::same_as<std::ranges::iterator_t<t>>;
224  {
225  insert_gap(v, std::ranges::begin(v), 2)
226  } -> std::same_as<std::ranges::iterator_t<t>>;
227  {
228  erase_gap(v, std::ranges::begin(v))
229  } -> std::same_as<std::ranges::iterator_t<t>>;
230  {
231  erase_gap(v, std::ranges::begin(v), std::ranges::end(v))
232  } -> std::same_as<std::ranges::iterator_t<t>>;
233  {
234  assign_unaligned(v, unaligned)
235  } -> std::same_as<void>;
236  };
238 
239 // ---------------------------------------------------------------------------------------------------------------------
240 // Aligned sequence interface for containers over the seqan3::gapped alphabet
241 // ---------------------------------------------------------------------------------------------------------------------
242 
263 template <sequence_container aligned_seq_t>
264  requires detail::is_gapped_alphabet<std::iter_value_t<aligned_seq_t>>
265 inline typename aligned_seq_t::iterator insert_gap(aligned_seq_t & aligned_seq,
266  typename aligned_seq_t::const_iterator pos_it)
267 {
268  return aligned_seq.insert(pos_it, std::iter_value_t<aligned_seq_t>{gap{}});
269 }
270 
287 template <sequence_container aligned_seq_t>
288  requires detail::is_gapped_alphabet<std::iter_value_t<aligned_seq_t>>
289 inline typename aligned_seq_t::iterator insert_gap(aligned_seq_t & aligned_seq,
290  typename aligned_seq_t::const_iterator pos_it,
291  typename aligned_seq_t::size_type size)
292 {
293  return aligned_seq.insert(pos_it, size, std::iter_value_t<aligned_seq_t>{gap{}});
294 }
295 
315 template <sequence_container aligned_seq_t>
316  requires detail::is_gapped_alphabet<std::iter_value_t<aligned_seq_t>>
317 inline typename aligned_seq_t::iterator erase_gap(aligned_seq_t & aligned_seq,
318  typename aligned_seq_t::const_iterator pos_it)
319 {
320  if (*pos_it != gap{}) // [[unlikely]]
321  throw gap_erase_failure("The position to be erased does not contain a gap.");
322 
323  return aligned_seq.erase(pos_it);
324 }
325 
346 template <sequence_container aligned_seq_t>
347  requires detail::is_gapped_alphabet<std::iter_value_t<aligned_seq_t>>
348 inline typename aligned_seq_t::iterator erase_gap(aligned_seq_t & aligned_seq,
349  typename aligned_seq_t::const_iterator first,
350  typename aligned_seq_t::const_iterator last)
351 {
352  for (auto it = first; it != last; ++it)
353  if (*it != gap{}) // [[unlikely]]
354  throw gap_erase_failure("The range to be erased contains at least one non-gap character.");
355 
356  return aligned_seq.erase(first, last);
357 }
358 
381 template <sequence_container aligned_seq_t, std::ranges::forward_range unaligned_sequence_type>
382  requires detail::is_gapped_alphabet<std::iter_value_t<aligned_seq_t>>
384  std::ranges::range_reference_t<unaligned_sequence_type>>
385 inline void assign_unaligned(aligned_seq_t & aligned_seq, unaligned_sequence_type && unaligned_seq)
386 {
387  using std::swap;
388  aligned_seq_t tmp;
389  tmp.resize(std::ranges::distance(unaligned_seq));
390 #if SEQAN3_WORKAROUND_GCC_BOGUS_MEMCPY
391 # pragma GCC diagnostic push
392 # pragma GCC diagnostic ignored "-Wstringop-overflow"
393 #endif // SEQAN3_WORKAROUND_GCC_BOGUS_MEMCPY
394  std::ranges::copy(unaligned_seq, std::ranges::begin(tmp));
395 #if SEQAN3_WORKAROUND_GCC_BOGUS_MEMCPY
396 # pragma GCC diagnostic pop
397 #endif // SEQAN3_WORKAROUND_GCC_BOGUS_MEMCPY
398  swap(aligned_seq, tmp);
399 }
401 
422 template <typename range_type>
423  requires requires (range_type v) {
424  v.insert_gap(std::ranges::iterator_t<range_type>{});
425  v.insert_gap(std::ranges::iterator_t<range_type>{}, typename range_type::size_type{});
426  }
427 std::ranges::iterator_t<range_type> insert_gap(range_type & rng,
428  std::ranges::iterator_t<range_type> const pos_it,
429  typename range_type::size_type const size = 1)
430 {
431  return rng.insert_gap(pos_it, size);
432 }
433 
450 template <typename range_type>
451  requires requires (range_type v) { v.erase_gap(std::ranges::iterator_t<range_type>{}); }
452 std::ranges::iterator_t<range_type> erase_gap(range_type & rng, std::ranges::iterator_t<range_type> const pos_it)
453 {
454  return rng.erase_gap(pos_it);
455 }
456 
475 template <typename range_type>
476  requires requires (range_type v) {
477  v.erase_gap(std::ranges::iterator_t<range_type>{}, std::ranges::iterator_t<range_type>{});
478  }
479 std::ranges::iterator_t<range_type> erase_gap(range_type & rng,
480  std::ranges::iterator_t<range_type> const first,
481  std::ranges::iterator_t<range_type> const last)
482 {
483  return rng.erase_gap(first, last);
484 }
486 } // namespace seqan3
487 
488 namespace seqan3::detail
489 {
490 
494 template <typename... elems>
495 inline constexpr bool all_model_aligned_seq = (aligned_sequence<elems> && ...);
496 
500 template <typename... elems>
501 inline constexpr bool all_model_aligned_seq<type_list<elems...>> = all_model_aligned_seq<elems...>;
502 } // namespace seqan3::detail
Includes customized exception types for the alignment module .
Provides seqan3::gapped.
requires requires(range_type v)
An implementation of seqan3::writable_aligned_sequence::insert_gap for ranges with the corresponding ...
Definition: aligned_sequence_concept.hpp:423
std::ranges::iterator_t< range_type > erase_gap(range_type &rng, std::ranges::iterator_t< range_type > const pos_it)
An implementation of seqan3::writable_aligned_sequence::insert_gap for ranges with the corresponding ...
Definition: aligned_sequence_concept.hpp:452
std::ranges::iterator_t< range_type > insert_gap(range_type &rng, std::ranges::iterator_t< range_type > const pos_it, typename range_type::size_type const size=1)
An implementation of seqan3::writable_aligned_sequence::insert_gap for ranges with the corresponding ...
Definition: aligned_sequence_concept.hpp:427
requires detail::is_gapped_alphabet< std::iter_value_t< aligned_seq_t > > &&weakly_assignable_from< std::ranges::range_reference_t< aligned_seq_t >, std::ranges::range_reference_t< unaligned_sequence_type > > void assign_unaligned(aligned_seq_t &aligned_seq, unaligned_sequence_type &&unaligned_seq)
An implementation of seqan3::writable_aligned_sequence::assign_unaligned_sequence for sequence contai...
Definition: aligned_sequence_concept.hpp:385
std::ranges::iterator_t< range_type > erase_gap(range_type &rng, std::ranges::iterator_t< range_type > const first, std::ranges::iterator_t< range_type > const last)
An implementation of seqan3::writable_aligned_sequence::insert_gap for ranges with the corresponding ...
Definition: aligned_sequence_concept.hpp:479
alphabet_variant< alphabet_t, gap > gapped
Extends a given alphabet with a gap character.
Definition: gapped.hpp:41
requires requires
The rank_type of the semi-alphabet; defined as the return type of seqan3::to_rank....
Definition: alphabet/concept.hpp:164
constexpr size_t size
The size of a type pack.
Definition: type_pack/traits.hpp:146
The generic concept for an aligned sequence.
The (most general) container concept as defined by the standard library.
The generic concept for a (biological) sequence.
Resolves to std::is_assignable_v<t>.
The generic concept for an aligned sequence that is writable.
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29
The <ranges> header from C++20's standard library.
Additional non-standard concepts for ranges.
T swap(T... args)
Adaptations of concepts from the standard library.