SeqAn3 3.2.0
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
28namespace seqan3::detail
29{
30
32template <template <typename...> typename container_type, typename seq_alph_t, typename... rest_t>
34constexpr auto remove_gap_from_value_type(container_type<gapped<seq_alph_t>, rest_t...>)
35 -> container_type<seq_alph_t, rest_t...>;
36
38template <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...>>
44constexpr 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
49template <typename t>
50struct unaligned_seq
51{};
52
54template <typename t>
55 requires (!requires { typename std::remove_reference_t<t>::unaligned_sequence_type; })
56 && requires { remove_gap_from_value_type(std::declval<t>()); }
57struct 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.
65template <typename t>
66 requires requires { typename std::remove_reference_t<t>::unaligned_sequence_type; }
67struct unaligned_seq<t>
68{
70};
71
73template <typename t>
74using unaligned_seq_t = typename unaligned_seq<t>::type;
75
76} // namespace seqan3::detail
77
78// ---------------------------------------------------------------------------------------------------------------------
79// aligned_sequence
80// ---------------------------------------------------------------------------------------------------------------------
81
82namespace seqan3
83{
84
106template <typename t>
107concept aligned_sequence = sequence<t> && std::equality_comparable_with<std::ranges::range_reference_t<t>, gap>;
109
216template <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
263template <sequence_container aligned_seq_t>
264 requires detail::is_gapped_alphabet<std::iter_value_t<aligned_seq_t>>
265inline 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
287template <sequence_container aligned_seq_t>
288 requires detail::is_gapped_alphabet<std::iter_value_t<aligned_seq_t>>
289inline 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
315template <sequence_container aligned_seq_t>
316 requires detail::is_gapped_alphabet<std::iter_value_t<aligned_seq_t>>
317inline 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
346template <sequence_container aligned_seq_t>
347 requires detail::is_gapped_alphabet<std::iter_value_t<aligned_seq_t>>
348inline 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
381template <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>>
385inline 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
422template <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 }
427std::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
450template <typename range_type>
451 requires requires (range_type v) { v.erase_gap(std::ranges::iterator_t<range_type>{}); }
452std::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
475template <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 }
479std::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
488namespace seqan3::detail
489{
490
494template <typename... elems>
495inline constexpr bool all_model_aligned_seq = (aligned_sequence<elems> && ...);
496
500template <typename... elems>
501inline 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 .
T begin(T... args)
A combined alphabet that can hold values of either of its alternatives..
Definition: alphabet_variant.hpp:120
T copy(T... args)
Provides seqan3::gapped.
aligned_seq_t::iterator insert_gap(aligned_seq_t &aligned_seq, typename aligned_seq_t::const_iterator pos_it, typename aligned_seq_t::size_type size)
An implementation of seqan3::writable_aligned_sequence::insert_gap for sequence containers.
Definition: aligned_sequence_concept.hpp:289
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::erase_gap for ranges with the corresponding m...
Definition: aligned_sequence_concept.hpp:479
aligned_seq_t::iterator erase_gap(aligned_seq_t &aligned_seq, typename aligned_seq_t::const_iterator pos_it)
An implementation of seqan3::writable_aligned_sequence::erase_gap for sequence containers.
Definition: aligned_sequence_concept.hpp:317
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::erase_gap for ranges with the corresponding m...
Definition: aligned_sequence_concept.hpp:452
aligned_seq_t::iterator erase_gap(aligned_seq_t &aligned_seq, typename aligned_seq_t::const_iterator first, typename aligned_seq_t::const_iterator last)
An implementation of seqan3::writable_aligned_sequence::erase_gap for sequence containers.
Definition: aligned_sequence_concept.hpp:348
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
aligned_seq_t::iterator insert_gap(aligned_seq_t &aligned_seq, typename aligned_seq_t::const_iterator pos_it)
An implementation of seqan3::writable_aligned_sequence::insert_gap for sequence containers.
Definition: aligned_sequence_concept.hpp:265
constexpr size_t size
The size of a type pack.
Definition: 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
Additional non-standard concepts for ranges.
T swap(T... args)
Adaptations of concepts from the standard library.