SeqAn3  3.0.1
The Modern C++ library for sequence analysis.
aligned_sequence_builder.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2020, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2020, 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 
13 #pragma once
14 
15 #include <type_traits>
16 #include <vector>
17 
30 #include <seqan3/std/concepts>
31 #include <seqan3/std/ranges>
32 
33 namespace seqan3::detail
34 {
35 
53 template <std::ranges::viewable_range range_t>
54 struct make_aligned_sequence_type
55 {
56  // The following expressions are used to check if the sequence types can be used as template arguments for the
57  // seqan3::gap_decorator. Ranges that do not model std::random_access_range for instance cannot be augmented with
58  // the gap_decorator and need to be copied instead.
59 
61  using type = lazy_conditional_t<is_class_template_declarable_with_v<gap_decorator,
62  decltype(std::declval<range_t>()
63  | views::slice(0, 1))>,
64  lazy<gap_decorator, decltype(std::declval<range_t>() | views::slice(0, 1))>,
65  lazy<std::vector, gapped<std::ranges::range_value_t<range_t>>>>;
66 };
67 
88 template <std::ranges::viewable_range fst_sequence_t, std::ranges::viewable_range sec_sequence_t>
89 class aligned_sequence_builder
90 {
91 private:
93  using fst_aligned_t = typename make_aligned_sequence_type<fst_sequence_t>::type;
95  using sec_aligned_t = typename make_aligned_sequence_type<sec_sequence_t>::type;
96 
98  "fst_aligned_t is required to model seqan3::aligned_sequence!");
100  "sec_aligned_t is required to model seqan3::aligned_sequence!");
101 
102 public:
103 
105  struct [[nodiscard]] result_type
106  {
108  std::pair<size_t, size_t> first_sequence_slice_positions{};
110  std::pair<size_t, size_t> second_sequence_slice_positions{};
114  };
115 
119  constexpr aligned_sequence_builder() = default;
120  constexpr aligned_sequence_builder(aligned_sequence_builder const &) = default;
121  constexpr aligned_sequence_builder(aligned_sequence_builder &&) = default;
122  constexpr aligned_sequence_builder & operator=(aligned_sequence_builder const &) = default;
123  constexpr aligned_sequence_builder & operator=(aligned_sequence_builder &&) = default;
124  ~aligned_sequence_builder() = default;
125 
130  constexpr aligned_sequence_builder(fst_sequence_t fst_rng, sec_sequence_t sec_rng) :
131  fst_rng{views::type_reduce(std::forward<fst_sequence_t>(fst_rng))},
132  sec_rng{views::type_reduce(std::forward<sec_sequence_t>(sec_rng))}
133  {}
135 
150  template <std::ranges::input_range trace_path_t>
151  result_type operator()(trace_path_t && trace_path)
152  {
153  static_assert(std::same_as<value_type_t<trace_path_t>, trace_directions>,
154  "The value type of the trace path must be seqan3::detail::trace_directions");
155 
156  result_type res{};
157  auto trace_it = std::ranges::begin(trace_path);
158  std::tie(res.first_sequence_slice_positions.second, res.second_sequence_slice_positions.second) =
159  std::pair<size_t, size_t>{trace_it.coordinate()};
160 
162 
163  while (trace_it != std::ranges::end(trace_path))
164  {
165  trace_directions last_dir = *trace_it;
166  size_t span = 0;
167  for (; trace_it != std::ranges::end(trace_path) && *trace_it == last_dir; ++trace_it, ++span)
168  {}
169 
170  trace_segments.emplace_back(last_dir, span);
171  }
172 
173  std::tie(res.first_sequence_slice_positions.first, res.second_sequence_slice_positions.first) =
174  std::pair<size_t, size_t>{trace_it.coordinate()};
175 
176  assign_unaligned(res.alignment.first, fst_rng | views::slice(res.first_sequence_slice_positions.first,
177  res.first_sequence_slice_positions.second));
178  assign_unaligned(res.alignment.second, sec_rng | views::slice(res.second_sequence_slice_positions.first,
179  res.second_sequence_slice_positions.second));
180 
181  // Now we need to insert the values.
182  fill_aligned_sequence(trace_segments | std::views::reverse, res.alignment.first, res.alignment.second);
183 
184  return res;
185  }
186 
187 private:
188 
195  template <typename reverse_traces_t, typename fst_aligned_t, typename sec_aligned_t>
196  void fill_aligned_sequence(reverse_traces_t && rev_traces,
197  fst_aligned_t & fst_aligned,
198  sec_aligned_t & sec_aligned) const
199  {
200  if (std::ranges::empty(rev_traces))
201  return;
202 
203  auto fst_it = std::ranges::begin(fst_aligned);
204  auto sec_it = std::ranges::begin(sec_aligned);
205 
206  for (auto const & [dir, span] : rev_traces)
207  {
208  if (dir == trace_directions::up)
209  fst_it = insert_gap(fst_aligned, fst_it, span);
210 
211  if (dir == trace_directions::left)
212  sec_it = insert_gap(sec_aligned, sec_it, span);
213 
214  fst_it += span;
215  sec_it += span;
216  }
217  }
218 
219  type_reduce_view<fst_sequence_t> fst_rng;
220  type_reduce_view<sec_sequence_t> sec_rng;
221 };
222 
227 template <std::ranges::viewable_range fst_sequence_t, std::ranges::viewable_range sec_sequence_t>
229 aligned_sequence_builder(fst_sequence_t &&, sec_sequence_t &&) ->
230  aligned_sequence_builder<fst_sequence_t, sec_sequence_t>;
232 } // namespace seqan3::detail
matrix_coordinate.hpp
Provides seqan3::detail::alignment_coordinate and associated strong types.
std::pair
seqan3::insert_gap
aligned_seq_t::iterator insert_gap(aligned_seq_t &aligned_seq, typename aligned_seq_t::const_iterator pos_it)
An implementation of seqan3::aligned_sequence::insert_gap for sequence containers.
Definition: aligned_sequence_concept.hpp:248
gap_decorator.hpp
Provides seqan3::gap_decorator.
vector
aligned_sequence
The generic concept for an aligned sequence.
convert.hpp
Provides seqan3::views::convert.
seqan3::views::type_reduce
constexpr auto type_reduce
A view adaptor that behaves like std::views::all, but type erases certain ranges.
Definition: type_reduce.hpp:158
concept.hpp
Provides the concepts seqan3::transformation_trait and seqan3::unary_type_trait.
concepts
The Concepts library.
std::tie
T tie(T... args)
trace_directions.hpp
Provides the declaration of seqan3::detail::trace_directions.
same_as
The concept std::same_as<T, U> is satisfied if and only if T and U denote the same type.
slice.hpp
Provides seqan3::views::slice.
gapped.hpp
Provides seqan3::gapped.
to.hpp
Provides seqan3::views::to.
type_reduce.hpp
Provides seqan3::views::type_reduce.
aligned_sequence_concept.hpp
Includes the aligned_sequence and the related insert_gap and erase_gap functions to enable stl contai...
seqan3::gapped
alphabet_variant< alphabet_t, gap > gapped
Extends a given alphabet with a gap character.
Definition: gapped.hpp:42
ranges
Adaptations of concepts from the Ranges TS.
std::vector::emplace_back
T emplace_back(T... args)
static_band.hpp
Provides seqan3::band_static.
std::ranges::begin
T begin(T... args)
seqan3::views::slice
constexpr auto slice
A view adaptor that returns a half-open interval on the underlying range.
Definition: slice.hpp:141
lazy.hpp
Provides lazy template instantiation traits.
seqan3::assign_unaligned
void assign_unaligned(aligned_seq_t &aligned_seq, unaligned_sequence_type &&unaligned_seq)
An implementation of seqan3::aligned_sequence::assign_unaligned_sequence for sequence containers.
Definition: aligned_sequence_concept.hpp:375
seqan3::gap_decorator
gap_decorator(urng_t &&range) -> gap_decorator< std::remove_reference_t< urng_t > const & >
Ranges (not views!) always deduce to const & range_type since they are access-only anyway.
seqan3::field::alignment
The (pairwise) alignment stored in an seqan3::alignment object.