SeqAn3  3.0.0
The Modern C++ library for sequence analysis.
translate.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2019, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2019, 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>
42  NucleotideAlphabet<reference_t<urng_t>>
44 class view_translate;
45 
46 template <std::ranges::View urng_t>
50  NucleotideAlphabet<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  {
119  "The range parameter to view::translate[_single] cannot be a temporary of a non-view range.");
120  static_assert(std::ranges::SizedRange<urng_t>,
121  "The range parameter to view::translate[_single] must model std::ranges::SizedRange.");
123  "The range parameter to view::translate[_single] must model std::ranges::RandomAccessRange.");
124  static_assert(NucleotideAlphabet<reference_t<urng_t>>,
125  "The range parameter to view::translate[_single] must be over elements of seqan3::NucleotideAlphabet.");
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>
155  NucleotideAlphabet<reference_t<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<remove_cvref_t<rng_t>, view_translate_single> &&
230  view_translate_single(rng_t && _urange, translation_frames const _tf = translation_frames::FWD_FRAME_0)
231  : view_translate_single{std::view::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 (seqan3::size(urange) - 1) / 3;
323  break;
325  [[fallthrough]];
327  return (seqan3::size(urange) - 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 (seqan3::size(urange) - 1) / 3;
349  break;
351  [[fallthrough]];
353  return (seqan3::size(urange) - 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::view
456 {
457 
507 inline constexpr auto translate_single = deep{detail::translate_fn<true>{}};
508 
509 } // seqan3::view
510 
511 // ============================================================================
512 // view_translate (range definition)
513 // ============================================================================
514 
515 namespace seqan3::detail
516 {
517 
526 template <std::ranges::View urng_t>
530  NucleotideAlphabet<reference_t<urng_t>>
532 class view_translate : public ranges::view_base
533 {
534 private:
536  urng_t urange;
540  small_vector<translation_frames, 6> selected_frames{};
541 
542 public:
546  using reference = view_translate_single<urng_t>;
549  using const_reference = reference;
551  using value_type = reference;
553  using size_type = size_type_t<urng_t>;
555  using difference_type = difference_type_t<urng_t>;
557  using iterator = detail::random_access_iterator<view_translate>;
559  using const_iterator = detail::random_access_iterator<view_translate const>;
561 
562 protected:
567  // unfortunately we cannot specialise the variable template so we have to add an auxiliary here
569  template <typename t>
570  requires (dimension_v<t> == dimension_v<value_type> + 1) &&
571  std::is_same_v<remove_cvref_t<innermost_value_type_t<value_type>>,
572  remove_cvref_t<innermost_value_type_t<t>>>
573  static constexpr bool is_compatible_this_aux = true;
576 
577 public:
578 
582  view_translate() noexcept = default;
583  constexpr view_translate(view_translate const & rhs) noexcept = default;
584  constexpr view_translate(view_translate && rhs) noexcept = default;
585  constexpr view_translate & operator=(view_translate const & rhs) noexcept = default;
586  constexpr view_translate & operator=(view_translate && rhs) noexcept = default;
587  ~view_translate() noexcept = default;
588 
593  view_translate(urng_t _urange, translation_frames const _tf = translation_frames::SIX_FRAME)
594  : urange{std::move(_urange)}, tf{_tf}
595  {
597  selected_frames.push_back(translation_frames::FWD_FRAME_0);
599  selected_frames.push_back(translation_frames::FWD_FRAME_1);
601  selected_frames.push_back(translation_frames::FWD_FRAME_2);
603  selected_frames.push_back(translation_frames::REV_FRAME_0);
605  selected_frames.push_back(translation_frames::REV_FRAME_1);
607  selected_frames.push_back(translation_frames::REV_FRAME_2);
608  }
609 
614  template <typename rng_t>
616  requires !std::Same<remove_cvref_t<rng_t>, view_translate> &&
620  view_translate(rng_t && _urange, translation_frames const _tf = translation_frames::SIX_FRAME)
621  : view_translate{std::view::all(std::forward<rng_t>(_urange)), _tf}
622  {}
624 
641  iterator begin() noexcept
642  {
643  return {*this, 0};
644  }
645 
647  const_iterator begin() const noexcept
648  {
649  return {*this, 0};
650  }
651 
653  const_iterator cbegin() const noexcept
654  {
655  return begin();
656  }
657 
671  iterator end() noexcept
672  {
673  return {*this, size()};
674  }
675 
677  const_iterator end() const noexcept
678  {
679  return {*this, size()};
680  }
681 
683  const_iterator cend() const noexcept
684  {
685  return end();
686  }
688 
700  size_type size() noexcept
701  {
702  return (size_type) selected_frames.size();
703  }
704 
706  size_type size() const noexcept
707  {
708  return (size_type) selected_frames.size();
709  }
710 
729  reference operator[](size_type const n)
730  {
731  assert(n < size());
732  return urange | view::translate_single(selected_frames[n]);
733  }
734 
736  const_reference operator[](size_type const n) const
737  {
738  assert(n < size());
739  return urange | view::translate_single(selected_frames[n]);
740  }
742 };
743 
745 template <typename urng_t>
749  NucleotideAlphabet<reference_t<urng_t>>
751 view_translate(urng_t &&, translation_frames const = translation_frames{}) -> view_translate<std::ranges::all_view<urng_t>>;
752 
753 } // namespace seqan3::detail
754 
755 // ============================================================================
756 // translate (adaptor object)
757 // ============================================================================
758 
759 namespace seqan3::view
760 {
761 
811 inline constexpr auto translate = deep{detail::translate_fn<false>{}};
813 
814 } // namespace seqan3::view
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
::ranges::cbegin cbegin
Alias for ranges::cbegin. Returns an iterator to the beginning of a range.
Definition: ranges:209
constexpr auto complement
Return the complement of a nucleotide object.
Definition: concept.hpp:104
Specifies the requirements of a Range type that is either a std::ranges::View or an lvalue-reference...
constexpr auto translate_single
A view that translates nucleotide into aminoacid alphabet for one of the six frames.
Definition: translate.hpp:507
constexpr auto translate
A view that translates nucleotide into aminoacid alphabet with 1, 2, 3 or 6 frames.
Definition: translate.hpp:811
Specifies requirements of a Range type for which begin returns a type that models std::RandomAccessIt...
decltype(view::all(declval< R >())) all_view
The type that would be returned by the std::view::all adaptor.
Definition: ranges:397
Provides seqan3::aa27, container aliases and string literals.
constexpr auto all
A view adaptor that behaves like std::view:all, but type erases contiguous ranges.
Definition: view_all.hpp:160
Provides the seqan3::detail::random_access_iterator class.
::ranges::size size
Alias for ranges::size. Obtains the size of a range whose size can be calculated in constant time...
Definition: ranges:189
The main SeqAn3 namespace.
Provides seqan3::dna5, container aliases and string literals.
constexpr auto single
Given a value, produces a view that contains exactly one element.
Definition: ranges:756
Specifies the requirements of a Range type that knows its size in constant time with the size functio...
Provides seqan3::view::deep.
The Concepts library.
Auxiliary header for the view submodule .
Adaptations of concepts from the Ranges TS.
::ranges::begin begin
Alias for ranges::begin. Returns an iterator to the beginning of a range.
Definition: ranges:174
The first third and third reverse frame.
The SeqAn3 namespace for views.
The second forward and second reverse frame.
The second forward frame starting at position 1.
Definition: aligned_sequence_concept.hpp:35
A constexpr string implementation to manipulate string literals at compile time.
The std::Constructible concept specifies that a variable of type T can be initialized with the given ...
auto operator|(validator1_type &&vali1, validator2_type &&vali2)
Enables the chaining of validators.
Definition: validators.hpp:889
The first forward and first reverse frame.
A wrapper type around an existing view adaptor that enables "deep view" behaviour for that view...
Definition: deep.hpp:101
Provides various transformation traits used by the range module.
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:56
The third forward frame starting at position 2.
The first forward frame starting at position 0.
::ranges::cend cend
Alias for ranges::cend. Returns an iterator to the end of a range.
Definition: ranges:214
The second reverse frame starting at position 1.
The concept std::Same<T, U> is satisfied if and only if T and U denote the same type.
Adaptations of concepts from the standard library.
Provides functions for translating a triplet of nucleotides into an amino acid.
The first reverse frame starting at position 0.
translation_frames
Specialisation values for single and multiple translation frames.
Definition: translate.hpp:64
::ranges::end end
Alias for ranges::end. Returns an iterator to the end of a range.
Definition: ranges:179
The third reverse frame starting at position 2.