SeqAn3  3.0.1
The Modern C++ library for sequence analysis.
translate.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 <vector>
16 #include <stdexcept>
17 
27 #include <seqan3/std/concepts>
28 #include <seqan3/std/ranges>
30 
31 // ============================================================================
32 // forwards
33 // ============================================================================
34 
35 namespace seqan3::detail
36 {
37 
38 template <std::ranges::view urng_t>
40  requires std::ranges::sized_range<urng_t> &&
41  std::ranges::random_access_range<urng_t> &&
44 class view_translate;
45 
46 template <std::ranges::view urng_t>
48  requires std::ranges::sized_range<urng_t> &&
49  std::ranges::random_access_range<urng_t> &&
52 class view_translate_single;
53 
54 } // namespace seqan3::detail
55 
56 // ============================================================================
57 // translation_frames
58 // ============================================================================
59 
60 namespace seqan3
61 {
62 
64 enum class translation_frames : uint8_t
65 {
66  FWD_FRAME_0 = 1,
67  FWD_FRAME_1 = 1 << 1,
68  FWD_FRAME_2 = 1 << 2,
69  REV_FRAME_0 = 1 << 3,
70  REV_FRAME_1 = 1 << 4,
71  REV_FRAME_2 = 1 << 5,
77  SIX_FRAME = FWD | REV
78 };
79 
81 template <>
83 
84 }
85 
86 namespace seqan3::detail
87 {
88 
89 // ============================================================================
90 // translate_fn (adaptor definition for both views)
91 // ============================================================================
92 
96 template <bool single>
97 struct translate_fn
98 {
100  static constexpr translation_frames default_frames = single ?
103 
105  constexpr auto operator()(translation_frames const tf = default_frames) const
106  {
107  return detail::adaptor_from_functor{*this, tf};
108  }
109 
115  template <std::ranges::range urng_t>
116  constexpr auto operator()(urng_t && urange, translation_frames const tf = default_frames) const
117  {
118  static_assert(std::ranges::viewable_range<urng_t>,
119  "The range parameter to views::translate[_single] cannot be a temporary of a non-view range.");
120  static_assert(std::ranges::sized_range<urng_t>,
121  "The range parameter to views::translate[_single] must model std::ranges::sized_range.");
122  static_assert(std::ranges::random_access_range<urng_t>,
123  "The range parameter to views::translate[_single] must model std::ranges::random_access_range.");
124  static_assert(nucleotide_alphabet<reference_t<urng_t>>,
125  "The range parameter to views::translate[_single] must be over elements of seqan3::nucleotide_alphabet.");
126 
127  if constexpr (single)
128  return detail::view_translate_single{std::forward<urng_t>(urange), tf};
129  else
130  return detail::view_translate{std::forward<urng_t>(urange), tf};
131  }
132 
134  template <std::ranges::range urng_t>
135  constexpr friend auto operator|(urng_t && urange, translate_fn const & me)
136  {
137  return me(std::forward<urng_t>(urange));
138  }
139 };
140 
141 // ============================================================================
142 // view_translate_single (range definition)
143 // ============================================================================
144 
151 template <std::ranges::view urng_t>
153  requires std::ranges::sized_range<urng_t> &&
154  std::ranges::random_access_range<urng_t> &&
157 class view_translate_single : public ranges::view_base
158 {
159 private:
161  urng_t urange;
165  static constexpr small_string multiple_frame_error{"Error: Invalid type of frame. Choose one out of FWD_FRAME_0, "
166  "REV_FRAME_0, FWD_FRAME_1, REV_FRAME_1, FWD_FRAME_2 and "
167  "REV_FRAME_2."};
168 public:
172  using reference = aa27;
175  using const_reference = aa27;
177  using value_type = aa27;
179  using size_type = size_type_t<urng_t>;
181  using difference_type = difference_type_t<urng_t>;
183  using iterator = detail::random_access_iterator<view_translate_single>;
185  using const_iterator = detail::random_access_iterator<view_translate_single const>;
187 
191  view_translate_single() noexcept = default;
192  constexpr view_translate_single(view_translate_single const & rhs) noexcept = default;
193  constexpr view_translate_single(view_translate_single && rhs) noexcept = default;
194  constexpr view_translate_single & operator=(view_translate_single const & rhs) noexcept = default;
195  constexpr view_translate_single & operator=(view_translate_single && rhs) noexcept = default;
196  ~view_translate_single() noexcept = default;
197 
198 
207  view_translate_single(urng_t _urange, translation_frames const _tf = translation_frames::FWD_FRAME_0)
208  : urange{std::move(_urange)}, tf{_tf}
209  {
210  if (__builtin_popcount(static_cast<uint8_t>(_tf)) > 1)
211  {
212  throw std::invalid_argument(multiple_frame_error.c_str());
213  }
214  }
215 
224  template <typename rng_t>
226  requires !std::same_as<remove_cvref_t<rng_t>, view_translate_single> &&
227  std::ranges::viewable_range<rng_t> &&
230  view_translate_single(rng_t && _urange, translation_frames const _tf = translation_frames::FWD_FRAME_0)
231  : view_translate_single{std::views::all(std::forward<rng_t>(_urange)), _tf}
232  {}
234 
251  iterator begin() noexcept
252  {
253  return {*this, 0};
254  }
255 
257  const_iterator begin() const noexcept
258  {
259  return {*this, 0};
260  }
261 
263  const_iterator cbegin() const noexcept
264  {
265  return begin();
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  }
291 
293  const_iterator cend() const noexcept
294  {
295  return end();
296  }
298 
310  size_type size()
311  {
312  switch (tf)
313  {
315  [[fallthrough]];
317  return seqan3::size(urange) / 3;
318  break;
320  [[fallthrough]];
322  return (std::max<size_type>(seqan3::size(urange), 1) - 1) / 3;
323  break;
325  [[fallthrough]];
327  return (std::max<size_type>(seqan3::size(urange), 2) - 2) / 3;
328  break;
329  default:
330  throw std::invalid_argument(multiple_frame_error.c_str());
331  break;
332  }
333  }
334 
336  size_type size() const
337  {
338  switch (tf)
339  {
341  [[fallthrough]];
343  return seqan3::size(urange) / 3;
344  break;
346  [[fallthrough]];
348  return (std::max<size_type>(seqan3::size(urange), 1) - 1) / 3;
349  break;
351  [[fallthrough]];
353  return (std::max<size_type>(seqan3::size(urange), 2) - 2) / 3;
354  break;
355  default:
356  throw std::invalid_argument(multiple_frame_error.c_str());
357  break;
358  }
359  }
360 
379  reference operator[](size_type const n)
380  {
381  assert(n < size());
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]), complement((urange)[(urange).size() - n * 3 - 2]), complement((urange)[(urange).size() - n * 3 - 3]));
389  break;
391  return translate_triplet((urange)[n * 3 + 1], (urange)[n * 3 + 2], (urange)[n * 3 + 3]);
392  break;
394  return translate_triplet(complement((urange)[(urange).size() - n * 3 - 2]), complement((urange)[(urange).size() - n * 3 - 3]), complement((urange)[(urange).size() - n * 3 - 4]));
395  break;
397  return translate_triplet((urange)[n * 3 + 2], (urange)[n * 3 + 3], (urange)[n * 3 + 4]);
398  break;
400  return translate_triplet(complement((urange)[(urange).size() - n * 3 - 3]), complement((urange)[(urange).size() - n * 3 - 4]), complement((urange)[(urange).size() - n * 3 - 5]));
401  break;
402  default:
403  throw std::invalid_argument(multiple_frame_error.c_str());
404  break;
405  }
406  }
407 
409  const_reference operator[](size_type const n) const
410  {
411  assert(n < size());
412  switch (tf)
413  {
415  return translate_triplet((urange)[n * 3], (urange)[n * 3 + 1], (urange)[n * 3 + 2]);
416  break;
418  return translate_triplet(complement((urange)[(urange).size() - n * 3 - 1]), complement((urange)[(urange).size() - n * 3 - 2]), complement((urange)[(urange).size() - n * 3 - 3]));
419  break;
421  return translate_triplet((urange)[n * 3 + 1], (urange)[n * 3 + 2], (urange)[n * 3 + 3]);
422  break;
424  return translate_triplet(complement((urange)[(urange).size() - n * 3 - 2]), complement((urange)[(urange).size() - n * 3 - 3]), complement((urange)[(urange).size() - n * 3 - 4]));
425  break;
427  return translate_triplet((urange)[n * 3 + 2], (urange)[n * 3 + 3], (urange)[n * 3 + 4]);
428  break;
430  return translate_triplet(complement((urange)[(urange).size() - n * 3 - 3]), complement((urange)[(urange).size() - n * 3 - 4]), complement((urange)[(urange).size() - n * 3 - 5]));
431  break;
432  default:
433  throw std::invalid_argument(multiple_frame_error.c_str());
434  break;
435  }
436  }
438 };
439 
441 template <typename urng_t>
442 view_translate_single(urng_t &&, translation_frames const) -> view_translate_single<std::ranges::all_view<urng_t>>;
443 
444 
446 template <typename urng_t>
447 view_translate_single(urng_t &&) -> view_translate_single<std::ranges::all_view<urng_t>>;
448 
449 } // namespace seqan3::detail
450 
451 // ============================================================================
452 // translate_single (adaptor object)
453 // ============================================================================
454 
455 namespace seqan3::views
456 {
457 
504 inline constexpr auto translate_single = deep{detail::translate_fn<true>{}};
505 
506 } // seqan3::views
507 
508 // ============================================================================
509 // view_translate (range definition)
510 // ============================================================================
511 
512 namespace seqan3::detail
513 {
514 
523 template <std::ranges::view urng_t>
525  requires std::ranges::sized_range<urng_t> &&
526  std::ranges::random_access_range<urng_t> &&
529 class view_translate : public ranges::view_base
530 {
531 private:
533  urng_t urange;
537  small_vector<translation_frames, 6> selected_frames{};
538 
539 public:
543  using reference = view_translate_single<urng_t>;
546  using const_reference = reference;
548  using value_type = reference;
550  using size_type = size_type_t<urng_t>;
552  using difference_type = difference_type_t<urng_t>;
554  using iterator = detail::random_access_iterator<view_translate>;
556  using const_iterator = detail::random_access_iterator<view_translate const>;
558 
559 protected:
564  // unfortunately we cannot specialise the variable template so we have to add an auxiliary here
566  template <typename t>
567  requires (dimension_v<t> == dimension_v<value_type> + 1) &&
568  std::is_same_v<remove_cvref_t<innermost_value_type_t<value_type>>,
569  remove_cvref_t<innermost_value_type_t<t>>>
570  static constexpr bool is_compatible_this_aux = true;
573 
574 public:
575 
579  view_translate() noexcept = default;
580  constexpr view_translate(view_translate const & rhs) noexcept = default;
581  constexpr view_translate(view_translate && rhs) noexcept = default;
582  constexpr view_translate & operator=(view_translate const & rhs) noexcept = default;
583  constexpr view_translate & operator=(view_translate && rhs) noexcept = default;
584  ~view_translate() noexcept = default;
585 
590  view_translate(urng_t _urange, translation_frames const _tf = translation_frames::SIX_FRAME)
591  : urange{std::move(_urange)}, tf{_tf}
592  {
594  selected_frames.push_back(translation_frames::FWD_FRAME_0);
596  selected_frames.push_back(translation_frames::FWD_FRAME_1);
598  selected_frames.push_back(translation_frames::FWD_FRAME_2);
600  selected_frames.push_back(translation_frames::REV_FRAME_0);
602  selected_frames.push_back(translation_frames::REV_FRAME_1);
604  selected_frames.push_back(translation_frames::REV_FRAME_2);
605  }
606 
611  template <typename rng_t>
613  requires !std::same_as<remove_cvref_t<rng_t>, view_translate> &&
614  std::ranges::viewable_range<rng_t> &&
617  view_translate(rng_t && _urange, translation_frames const _tf = translation_frames::SIX_FRAME)
618  : view_translate{std::views::all(std::forward<rng_t>(_urange)), _tf}
619  {}
621 
638  iterator begin() noexcept
639  {
640  return {*this, 0};
641  }
642 
644  const_iterator begin() const noexcept
645  {
646  return {*this, 0};
647  }
648 
650  const_iterator cbegin() const noexcept
651  {
652  return begin();
653  }
654 
668  iterator end() noexcept
669  {
670  return {*this, size()};
671  }
672 
674  const_iterator end() const noexcept
675  {
676  return {*this, size()};
677  }
678 
680  const_iterator cend() const noexcept
681  {
682  return end();
683  }
685 
697  size_type size() noexcept
698  {
699  return (size_type) selected_frames.size();
700  }
701 
703  size_type size() const noexcept
704  {
705  return (size_type) selected_frames.size();
706  }
707 
726  reference operator[](size_type const n)
727  {
728  assert(n < size());
729  return urange | views::translate_single(selected_frames[n]);
730  }
731 
733  const_reference operator[](size_type const n) const
734  {
735  assert(n < size());
736  return urange | views::translate_single(selected_frames[n]);
737  }
739 };
740 
742 template <typename urng_t>
744  requires std::ranges::sized_range<urng_t> &&
745  std::ranges::random_access_range<urng_t> &&
748 view_translate(urng_t &&, translation_frames const = translation_frames{}) -> view_translate<std::ranges::all_view<urng_t>>;
749 
750 } // namespace seqan3::detail
751 
752 // ============================================================================
753 // translate (adaptor object)
754 // ============================================================================
755 
756 namespace seqan3::views
757 {
758 
805 inline constexpr auto translate = deep{detail::translate_fn<false>{}};
807 
808 } // namespace seqan3::views
seqan3::translation_frames::FWD_REV_0
The first forward and first reverse frame.
seqan3::translation_frames::FWD_FRAME_2
The third forward frame starting at position 2.
seqan3::single
The text is a single range.
Definition: concept.hpp:84
seqan3::translation_frames::SIX_FRAME
All frames.
seqan3::views
The SeqAn namespace for views.
Definition: view_to_simd.hpp:672
seqan3::add_enum_bitwise_operators< translation_frames >
constexpr bool add_enum_bitwise_operators< translation_frames >
Enable bitwise operators for enum translation_frames.
Definition: translate.hpp:82
constructible_from
The std::constructible_from concept specifies that a variable of type T can be initialized with the g...
vector
seqan3::views::move
const auto move
A view that turns lvalue-references into rvalue-references.
Definition: move.hpp:68
concept.hpp
Adaptations of concepts from the standard library.
seqan3::translation_frames::REV_FRAME_1
The second reverse frame starting at position 1.
seqan3::translate_triplet
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:53
seqan3::operator|
auto operator|(validator1_type &&vali1, validator2_type &&vali2)
Enables the chaining of validators.
Definition: validators.hpp:1023
concepts
The Concepts library.
same_as
The concept std::same_as<T, U> is satisfied if and only if T and U denote the same type.
stdexcept
seqan3::views::deep
A wrapper type around an existing view adaptor that enables "deep view" behaviour for that view.
Definition: deep.hpp:101
random_access_iterator.hpp
Provides the seqan3::detail::random_access_iterator class.
translation.hpp
Provides functions for translating a triplet of nucleotides into an amino acid.
seqan3::views::translate
constexpr auto translate
A view that translates nucleotide into aminoacid alphabet with 1, 2, 3 or 6 frames.
Definition: translate.hpp:805
aa27.hpp
Provides seqan3::aa27, container aliases and string literals.
seqan3::translation_frames::FWD_FRAME_1
The second forward frame starting at position 1.
nucleotide_alphabet
A concept that indicates whether an alphabet represents nucleotides.
small_string.hpp
A constexpr string implementation to manipulate string literals at compile time.
range.hpp
Provides various transformation traits used by the range module.
dna5.hpp
Provides seqan3::dna5, container aliases and string literals.
seqan3::translation_frames::FWD_REV_2
The first third and third reverse frame.
seqan3
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:36
std::invalid_argument
seqan3::search_cfg::all
constexpr detail::search_mode_all all
Configuration element to receive all hits within the error bounds.
Definition: mode.hpp:43
seqan3::pack_traits::size
constexpr size_t size
The size of a type pack.
Definition: traits.hpp:116
seqan3::translation_frames::FWD
All forward frames.
ranges
Adaptations of concepts from the Ranges TS.
deep.hpp
Provides seqan3::views::deep.
add_enum_bitwise_operators.hpp
Provides seqan3::add_enum_bitwise_operators.
std::begin
T begin(T... args)
seqan3::complement
constexpr auto complement
Return the complement of a nucleotide object.
Definition: concept.hpp:93
std::end
T end(T... args)
seqan3::translation_frames
translation_frames
Specialisation values for single and multiple translation frames.
Definition: translate.hpp:64
seqan3::translation_frames::FWD_FRAME_0
The first forward frame starting at position 0.
detail.hpp
Auxiliary header for the views submodule .
seqan3::translation_frames::REV
All reverse frames.
seqan3::views::translate_single
constexpr auto translate_single
A view that translates nucleotide into aminoacid alphabet for one of the six frames.
Definition: translate.hpp:504
seqan3::translation_frames::REV_FRAME_0
The first reverse frame starting at position 0.
seqan3::translation_frames::REV_FRAME_2
The third reverse frame starting at position 2.
seqan3::translation_frames::FWD_REV_1
The second forward and second reverse frame.