SeqAn3  3.1.0-rc.1
The Modern C++ library for sequence analysis.
translate.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2021, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2021, 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 <seqan3/std/concepts>
16 #include <seqan3/std/ranges>
17 #include <vector>
18 #include <stdexcept>
19 
28 
29 // ============================================================================
30 // forwards
31 // ============================================================================
32 
33 namespace seqan3::detail
34 {
35 
36 template <std::ranges::view urng_t>
38  requires std::ranges::sized_range<urng_t> &&
39  std::ranges::random_access_range<urng_t> &&
42 class view_translate;
43 
44 template <std::ranges::view urng_t>
46  requires std::ranges::sized_range<urng_t> &&
47  std::ranges::random_access_range<urng_t> &&
51 
52 } // namespace seqan3::detail
53 
54 // ============================================================================
55 // translation_frames
56 // ============================================================================
57 
58 namespace seqan3
59 {
60 
67 enum class translation_frames : uint8_t
68 {
69  forward_frame0 = 1,
70  forward_frame1 = 1 << 1,
71  forward_frame2 = 1 << 2,
72  reverse_frame0 = 1 << 3,
73  reverse_frame1 = 1 << 4,
74  reverse_frame2 = 1 << 5,
81 };
82 
86 template <>
89 
90 }
91 
92 namespace seqan3::detail
93 {
94 
95 // ============================================================================
96 // translate_fn (adaptor definition for both views)
97 // ============================================================================
98 
102 template <bool single>
104 {
109 
111  constexpr auto operator()(translation_frames const tf = default_frames) const
112  {
113  return detail::adaptor_from_functor{*this, tf};
114  }
115 
121  template <std::ranges::range urng_t>
122  constexpr auto operator()(urng_t && urange, translation_frames const tf = default_frames) const
123  {
124  static_assert(std::ranges::viewable_range<urng_t>,
125  "The range parameter to views::translate[_single] cannot be a temporary of a non-view range.");
126  static_assert(std::ranges::sized_range<urng_t>,
127  "The range parameter to views::translate[_single] must model std::ranges::sized_range.");
128  static_assert(std::ranges::random_access_range<urng_t>,
129  "The range parameter to views::translate[_single] must model std::ranges::random_access_range.");
130  static_assert(nucleotide_alphabet<std::ranges::range_reference_t<urng_t>>,
131  "The range parameter to views::translate[_single] must be over elements of seqan3::nucleotide_alphabet.");
132 
133  if constexpr (single)
134  return detail::view_translate_single{std::forward<urng_t>(urange), tf};
135  else
136  return detail::view_translate{std::forward<urng_t>(urange), tf};
137  }
138 
140  template <std::ranges::range urng_t>
141  constexpr friend auto operator|(urng_t && urange, translate_fn const & me)
142  {
143  return me(std::forward<urng_t>(urange));
144  }
145 };
146 
147 // ============================================================================
148 // view_translate_single (range definition)
149 // ============================================================================
150 
157 template <std::ranges::view urng_t>
159  requires std::ranges::sized_range<urng_t> &&
160  std::ranges::random_access_range<urng_t> &&
163 class view_translate_single : public std::ranges::view_base
164 {
165 private:
167  urng_t urange;
171  static constexpr small_string multiple_frame_error{"Error: Invalid type of frame. Choose one out of "
172  "forward_frame0, reverse_frame0, forward_frame1, "
173  "reverse_frame1, forward_frame2 and reverse_frame2."};
174 public:
179  using reference = aa27;
183  using value_type = aa27;
185  using size_type = std::ranges::range_size_t<urng_t>;
187  using difference_type = std::ranges::range_difference_t<urng_t>;
193 
197  view_translate_single() noexcept = default;
198  constexpr view_translate_single(view_translate_single const & rhs) noexcept = default;
199  constexpr view_translate_single(view_translate_single && rhs) noexcept = default;
200  constexpr view_translate_single & operator=(view_translate_single const & rhs) noexcept = default;
201  constexpr view_translate_single & operator=(view_translate_single && rhs) noexcept = default;
202  ~view_translate_single() noexcept = default;
203 
204 
213  view_translate_single(urng_t _urange, translation_frames const _tf = translation_frames::forward_frame0)
214  : urange{std::move(_urange)}, tf{_tf}
215  {
216  if (__builtin_popcount(static_cast<uint8_t>(_tf)) > 1)
217  {
219  }
220  }
221 
230  template <typename rng_t>
232  requires (!std::same_as<std::remove_cvref_t<rng_t>, view_translate_single>) &&
233  std::ranges::viewable_range<rng_t> &&
234  std::constructible_from<urng_t, std::ranges::ref_view<std::remove_reference_t<rng_t>>>
237  : view_translate_single{std::views::all(std::forward<rng_t>(_urange)), _tf}
238  {}
240 
257  iterator begin() noexcept
258  {
259  return {*this, 0};
260  }
261 
263  const_iterator begin() const noexcept
264  {
265  return {*this, 0};
266  }
267 
281  iterator end() noexcept
282  {
283  return {*this, size()};
284  }
285 
287  const_iterator end() const noexcept
288  {
289  return {*this, size()};
290  }
292 
305  {
306  switch (tf)
307  {
309  [[fallthrough]];
311  return std::ranges::size(urange) / 3;
312  break;
314  [[fallthrough]];
316  return (std::max<size_type>(std::ranges::size(urange), 1) - 1) / 3;
317  break;
319  [[fallthrough]];
321  return (std::max<size_type>(std::ranges::size(urange), 2) - 2) / 3;
322  break;
323  default:
325  break;
326  }
327  }
328 
330  size_type size() const
331  {
332  switch (tf)
333  {
335  [[fallthrough]];
337  return std::ranges::size(urange) / 3;
338  break;
340  [[fallthrough]];
342  return (std::max<size_type>(std::ranges::size(urange), 1) - 1) / 3;
343  break;
345  [[fallthrough]];
347  return (std::max<size_type>(std::ranges::size(urange), 2) - 2) / 3;
348  break;
349  default:
351  break;
352  }
353  }
354 
374  {
375  // size will throw (only in debug-builds!) if translation_frames is neither (FWD|REV)_FRAME_(0|1|2),
376  // we catch that error in debug-builds to make this function consistent with the behaviour in
377  // release-builds (-DNDEBUG).
378 #ifndef NDEBUG
379  try { assert(n < size()); } catch (std::invalid_argument const &) {}
380 #endif
381 
382  switch (tf)
383  {
385  return translate_triplet((urange)[n * 3], (urange)[n * 3 + 1], (urange)[n * 3 + 2]);
386  break;
388  return translate_triplet(complement((urange)[(urange).size() - n * 3 - 1]),
389  complement((urange)[(urange).size() - n * 3 - 2]),
390  complement((urange)[(urange).size() - n * 3 - 3]));
391  break;
393  return translate_triplet((urange)[n * 3 + 1], (urange)[n * 3 + 2], (urange)[n * 3 + 3]);
394  break;
396  return translate_triplet(complement((urange)[(urange).size() - n * 3 - 2]),
397  complement((urange)[(urange).size() - n * 3 - 3]),
398  complement((urange)[(urange).size() - n * 3 - 4]));
399  break;
401  return translate_triplet((urange)[n * 3 + 2], (urange)[n * 3 + 3], (urange)[n * 3 + 4]);
402  break;
404  return translate_triplet(complement((urange)[(urange).size() - n * 3 - 3]),
405  complement((urange)[(urange).size() - n * 3 - 4]),
406  complement((urange)[(urange).size() - n * 3 - 5]));
407  break;
408  default:
410  break;
411  }
412  }
413 
416  {
417  // size will throw (only in debug-builds!) if translation_frames is neither (FWD|REV)_FRAME_(0|1|2),
418  // we catch that error in debug-builds to make this function consistent with the behaviour in
419  // release-builds (-DNDEBUG).
420 #ifndef NDEBUG
421  try { assert(n < size()); } catch (std::invalid_argument const &) {}
422 #endif
423 
424  switch (tf)
425  {
427  return translate_triplet((urange)[n * 3], (urange)[n * 3 + 1], (urange)[n * 3 + 2]);
428  break;
430  return translate_triplet(complement((urange)[(urange).size() - n * 3 - 1]),
431  complement((urange)[(urange).size() - n * 3 - 2]),
432  complement((urange)[(urange).size() - n * 3 - 3]));
433  break;
435  return translate_triplet((urange)[n * 3 + 1], (urange)[n * 3 + 2], (urange)[n * 3 + 3]);
436  break;
438  return translate_triplet(complement((urange)[(urange).size() - n * 3 - 2]),
439  complement((urange)[(urange).size() - n * 3 - 3]),
440  complement((urange)[(urange).size() - n * 3 - 4]));
441  break;
443  return translate_triplet((urange)[n * 3 + 2], (urange)[n * 3 + 3], (urange)[n * 3 + 4]);
444  break;
446  return translate_triplet(complement((urange)[(urange).size() - n * 3 - 3]),
447  complement((urange)[(urange).size() - n * 3 - 4]),
448  complement((urange)[(urange).size() - n * 3 - 5]));
449  break;
450  default:
452  break;
453  }
454  }
456 };
457 
459 template <typename urng_t>
461 
462 
464 template <typename urng_t>
466 
467 } // namespace seqan3::detail
468 
469 // ============================================================================
470 // translate_single (adaptor object)
471 // ============================================================================
472 
473 namespace seqan3::views
474 {
475 
525 
526 } // seqan3::views
527 
528 // ============================================================================
529 // view_translate (range definition)
530 // ============================================================================
531 
532 namespace seqan3::detail
533 {
534 
543 template <std::ranges::view urng_t>
545  requires std::ranges::sized_range<urng_t> &&
546  std::ranges::random_access_range<urng_t> &&
549 class view_translate : public std::ranges::view_base
550 {
551 private:
553  urng_t urange;
558 
559 public:
570  using size_type = std::ranges::range_size_t<urng_t>;
572  using difference_type = std::ranges::range_difference_t<urng_t>;
578 
579 protected:
586  // unfortunately we cannot specialise the variable template so we have to add an auxiliary here
587  template <typename t>
588  requires (range_dimension_v<t> == range_dimension_v<value_type> + 1) &&
589  std::is_same_v<std::remove_cvref_t<range_innermost_value_t<value_type>>,
591  static constexpr bool is_compatible_this_aux = true;
594 
595 public:
596 
600  view_translate() noexcept = default;
601  constexpr view_translate(view_translate const & rhs) noexcept = default;
602  constexpr view_translate(view_translate && rhs) noexcept = default;
603  constexpr view_translate & operator=(view_translate const & rhs) noexcept = default;
604  constexpr view_translate & operator=(view_translate && rhs) noexcept = default;
605  ~view_translate() noexcept = default;
606 
611  view_translate(urng_t _urange, translation_frames const _tf = translation_frames::six_frames)
612  : urange{std::move(_urange)}, tf{_tf}
613  {
626  }
627 
632  template <typename rng_t>
634  requires (!std::same_as<std::remove_cvref_t<rng_t>, view_translate>) &&
635  std::ranges::viewable_range<rng_t> &&
636  std::constructible_from<urng_t, std::ranges::ref_view<std::remove_reference_t<rng_t>>>
638  view_translate(rng_t && _urange, translation_frames const _tf)
639  : view_translate{std::views::all(std::forward<rng_t>(_urange)), _tf}
640  {}
642 
659  iterator begin() noexcept
660  {
661  return {*this, 0};
662  }
663 
665  const_iterator begin() const noexcept
666  {
667  return {*this, 0};
668  }
669 
683  iterator end() noexcept
684  {
685  return {*this, size()};
686  }
687 
689  const_iterator end() const noexcept
690  {
691  return {*this, size()};
692  }
693 
705  size_type size() noexcept
706  {
707  return (size_type) selected_frames.size();
708  }
709 
711  size_type size() const noexcept
712  {
713  return (size_type) selected_frames.size();
714  }
715 
735  {
736  assert(n < size());
738  }
739 
742  {
743  assert(n < size());
745  }
747 };
748 
750 template <typename urng_t>
752  requires std::ranges::sized_range<urng_t> &&
753  std::ranges::random_access_range<urng_t> &&
757 } // namespace seqan3::detail
758 
759 // ============================================================================
760 // translate (adaptor object)
761 // ============================================================================
762 
763 namespace seqan3::views
764 {
813 inline constexpr auto translate = deep{detail::translate_fn<false>{}};
814 
815 } // namespace seqan3::views
Provides seqan3::aa27, container aliases and string literals.
Provides seqan3::detail::adaptor_from_functor.
Provides seqan3::add_enum_bitwise_operators.
The twenty-seven letter amino acid alphabet.
Definition: aa27.hpp:46
Template for range adaptor closure objects that store arguments and wrap a proto-adaptor.
Definition: adaptor_from_functor.hpp:57
A generic random access iterator that delegates most operations to the range.
Definition: random_access_iterator.hpp:310
The return type of seqan3::views::translate_single.
Definition: translate.hpp:164
const_reference operator[](size_type const n) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: translate.hpp:415
size_type size() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: translate.hpp:330
reference operator[](size_type const n)
Return the n-th element.
Definition: translate.hpp:373
view_translate_single(rng_t &&_urange, translation_frames const _tf=translation_frames::forward_frame0)
Construct from another range.
Definition: translate.hpp:236
size_type size()
Returns the number of elements in the view.
Definition: translate.hpp:304
translation_frames tf
The frame that should be used for translation.
Definition: translate.hpp:169
iterator end() noexcept
Returns an iterator to the element following the last element of the container.
Definition: translate.hpp:281
std::ranges::range_difference_t< urng_t > difference_type
A signed integer type, usually std::ptrdiff_t.
Definition: translate.hpp:187
static constexpr small_string multiple_frame_error
Error thrown if tried to be used with multiple frames.
Definition: translate.hpp:171
view_translate_single() noexcept=default
Defaulted.
iterator begin() noexcept
Returns an iterator to the first element of the container.
Definition: translate.hpp:257
urng_t urange
The input range (of ranges).
Definition: translate.hpp:167
const_iterator end() const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: translate.hpp:287
const_iterator begin() const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: translate.hpp:263
std::ranges::range_size_t< urng_t > size_type
The size_type.
Definition: translate.hpp:185
The return type of seqan3::views::translate.
Definition: translate.hpp:550
const_reference operator[](size_type const n) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: translate.hpp:741
translation_frames tf
The frames that should be used for translation.
Definition: translate.hpp:555
view_translate(rng_t &&_urange, translation_frames const _tf)
Construct from another range.
Definition: translate.hpp:638
view_translate() noexcept=default
Defaulted.
std::ranges::range_difference_t< urng_t > difference_type
A signed integer type, usually std::ptrdiff_t.
Definition: translate.hpp:572
const_iterator begin() const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: translate.hpp:665
reference operator[](size_type const n)
Return the n-th element.
Definition: translate.hpp:734
small_vector< translation_frames, 6 > selected_frames
The selected frames corresponding to the frames required.
Definition: translate.hpp:557
size_type size() noexcept
Returns the number of elements in the view.
Definition: translate.hpp:705
view_translate_single< urng_t > reference
The reference_type.
Definition: translate.hpp:564
iterator begin() noexcept
Returns an iterator to the first element of the container.
Definition: translate.hpp:659
std::ranges::range_size_t< urng_t > size_type
The size_type.
Definition: translate.hpp:570
iterator end() noexcept
Returns an iterator to the element following the last element of the container.
Definition: translate.hpp:683
urng_t urange
The data members of view_translate_single.
Definition: translate.hpp:553
const_iterator end() const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: translate.hpp:689
size_type size() const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: translate.hpp:711
Implements a small string that can be used for compile time computations.
Definition: small_string.hpp:44
constexpr char const * c_str() const noexcept
Returns the content represented as 0-terminated c-style string.
Definition: small_string.hpp:345
constexpr void push_back(value_type const value) noexcept
Appends the given element value to the end of the container.
Definition: small_vector.hpp:861
constexpr size_type size() const noexcept
Returns the number of elements in the container, i.e. std::distance(begin(), end()).
Definition: small_vector.hpp:590
A wrapper type around an existing view adaptor that enables "deep view" behaviour for that view.
Definition: deep.hpp:104
The Concepts library.
Provides various transformation traits used by the range module.
Provides seqan3::views::deep.
Provides seqan3::dna5, container aliases and string literals.
constexpr aa27 translate_triplet(nucl_type const &n1, nucl_type const &n2, nucl_type const &n3) noexcept
Translate one nucleotide triplet into single amino acid (single nucleotide interface).
Definition: translation.hpp:55
constexpr auto complement
Return the complement of a nucleotide object.
Definition: concept.hpp:104
constexpr auto translate
A view that translates nucleotide into aminoacid alphabet with 1, 2, 3 or 6 frames.
Definition: translate.hpp:813
constexpr auto translate_single
A view that translates nucleotide into aminoacid alphabet for one of the six frames.
Definition: translate.hpp:524
@ single
The text is a single range.
Definition: concept.hpp:74
constexpr size_t size
The size of a type pack.
Definition: traits.hpp:151
A concept that indicates whether an alphabet represents nucleotides.
The internal SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29
view_translate_single(urng_t &&, translation_frames const) -> view_translate_single< std::views::all_t< urng_t >>
Class template argument deduction for view_translate_single.
view_translate(urng_t &&, translation_frames const) -> view_translate< std::views::all_t< urng_t >>
Class template argument deduction for view_translate.
The SeqAn namespace for views.
Definition: char_to.hpp:22
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29
constexpr bool add_enum_bitwise_operators< translation_frames >
Enable bitwise operators for enum translation_frames.
Definition: translate.hpp:87
translation_frames
Specialisation values for single and multiple translation frames.
Definition: translate.hpp:68
@ forward_frame2
The third forward frame starting at position 2.
@ forward_frame0
The first forward frame starting at position 0.
@ reverse_frames
All reverse frames.
@ forward_frames
All forward frames.
@ reverse_frame0
The first reverse frame starting at position 0.
@ forward_reverse2
The first third and third reverse frame.
@ reverse_frame2
The third reverse frame starting at position 2.
@ forward_frame1
The second forward frame starting at position 1.
@ reverse_frame1
The second reverse frame starting at position 1.
@ forward_reverse0
The first forward and first reverse frame.
@ forward_reverse1
The second forward and second reverse frame.
SeqAn specific customisations in the standard namespace.
Adaptations of concepts from the Ranges TS.
A constexpr string implementation to manipulate string literals at compile time.
Definition of the range adaptor object type for seqan3::views::translate and seqan3::views::translate...
Definition: translate.hpp:104
constexpr auto operator()(translation_frames const tf=default_frames) const
Store the argument and return a range adaptor closure object.
Definition: translate.hpp:111
constexpr auto operator()(urng_t &&urange, translation_frames const tf=default_frames) const
Directly return an instance of the view, initialised with the given parameters.
Definition: translate.hpp:122
static constexpr translation_frames default_frames
The default frames parameter for the translation view adaptors.
Definition: translate.hpp:106
constexpr friend auto operator|(urng_t &&urange, translate_fn const &me)
This adaptor is usable without setting the frames parameter in which case the default is chosen.
Definition: translate.hpp:141
Provides functions for translating a triplet of nucleotides into an amino acid.