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> &&
42  nucleotide_alphabet<reference_t<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> &&
50  nucleotide_alphabet<reference_t<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.");
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;
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;
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>>,
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  {
593  if ((_tf & translation_frames::FWD_FRAME_0) == translation_frames::FWD_FRAME_0)
594  selected_frames.push_back(translation_frames::FWD_FRAME_0);
595  if ((_tf & translation_frames::FWD_FRAME_1) == translation_frames::FWD_FRAME_1)
596  selected_frames.push_back(translation_frames::FWD_FRAME_1);
597  if ((_tf & translation_frames::FWD_FRAME_2) == translation_frames::FWD_FRAME_2)
598  selected_frames.push_back(translation_frames::FWD_FRAME_2);
599  if ((_tf & translation_frames::REV_FRAME_0) == translation_frames::REV_FRAME_0)
600  selected_frames.push_back(translation_frames::REV_FRAME_0);
601  if ((_tf & translation_frames::REV_FRAME_1) == translation_frames::REV_FRAME_1)
602  selected_frames.push_back(translation_frames::REV_FRAME_1);
603  if ((_tf & translation_frames::REV_FRAME_2) == translation_frames::REV_FRAME_2)
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
Provides seqan3::add_enum_bitwise_operators.
constexpr bool add_enum_bitwise_operators< translation_frames >
Enable bitwise operators for enum translation_frames.
Definition: translate.hpp:82
constexpr auto complement
Return the complement of a nucleotide object.
Definition: concept.hpp:93
A concept that indicates whether an alphabet represents nucleotides.
constexpr auto translate_single
A view that translates nucleotide into aminoacid alphabet for one of the six frames.
Definition: translate.hpp:504
Provides seqan3::aa27, container aliases and string literals.
The text is a single range.
Definition: concept.hpp:84
Provides the seqan3::detail::random_access_iterator class.
The main SeqAn3 namespace.
Provides seqan3::dna5, container aliases and string literals.
typename difference_type< t >::type difference_type_t
Shortcut for seqan3::difference_type (transformation_trait shortcut).
Definition: pre.hpp:166
Implements a small string that can be used for compile time computations.
Definition: small_string.hpp:42
The twenty-seven letter amino acid alphabet.
Definition: aa27.hpp:43
detail::search_mode_all constexpr all
Configuration element to receive all hits within the error bounds.
Definition: mode.hpp:43
The SeqAn namespace for views.
Definition: view_to_simd.hpp:672
Provides seqan3::views::deep.
Exposes the difference_type of another type.
Definition: pre.hpp:159
The Concepts library.
Adaptations of concepts from the Ranges TS.
The first third and third reverse frame.
Exposes the size_type of another type.
Definition: pre.hpp:188
constexpr auto translate
A view that translates nucleotide into aminoacid alphabet with 1, 2, 3 or 6 frames.
Definition: translate.hpp:805
The second forward and second reverse frame.
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
constexpr size_t size
The size of a type pack.
Definition: traits.hpp:116
A constexpr vector implementation with dynamic size at compile time.
Definition: small_vector.hpp:44
typename size_type< t >::type size_type_t
Shortcut for seqan3::size_type (transformation_trait shortcut).
Definition: pre.hpp:195
The second forward frame starting at position 1.
Definition: aligned_sequence_concept.hpp:36
A constexpr string implementation to manipulate string literals at compile time.
The std::constructible_from concept specifies that a variable of type T can be initialized with the g...
A wrapper type around an existing view adaptor that enables "deep view" behaviour for that view...
Definition: deep.hpp:101
auto const move
A view that turns lvalue-references into rvalue-references.
Definition: move.hpp:68
auto operator|(validator1_type &&vali1, validator2_type &&vali2)
Enables the chaining of validators.
Definition: validators.hpp:1023
Exposes the const_reference of another type.
Definition: pre.hpp:130
The first forward and first reverse frame.
Exposes the reference of another type.
Definition: pre.hpp:70
Provides various transformation traits used by the range module.
typename reference< t >::type reference_t
Shortcut for seqan3::reference (transformation_trait shortcut).
Definition: pre.hpp:77
The third forward frame starting at position 2.
The first forward frame starting at position 0.
The second reverse frame starting at position 1.
Adaptations of concepts from the standard library.
Exposes the value_type of another type.
Definition: pre.hpp:41
Provides functions for translating a triplet of nucleotides into an amino acid.
The concept std::same_as<T, U> is satisfied if and only if T and U denote the same type...
The first reverse frame starting at position 0.
translation_frames
Specialisation values for single and multiple translation frames.
Definition: translate.hpp:64
Auxiliary header for the views submodule .
The third reverse frame starting at position 2.