SeqAn3
translation.hpp
Go to the documentation of this file.
1 // ============================================================================
2 // SeqAn - The Library for Sequence Analysis
3 // ============================================================================
4 //
5 // Copyright (c) 2006-2018, Knut Reinert & Freie Universitaet Berlin
6 // Copyright (c) 2016-2018, Knut Reinert & MPI Molekulare Genetik
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // * Redistributions of source code must retain the above copyright
13 // notice, this list of conditions and the following disclaimer.
14 // * Redistributions in binary form must reproduce the above copyright
15 // notice, this list of conditions and the following disclaimer in the
16 // documentation and/or other materials provided with the distribution.
17 // * Neither the name of Knut Reinert or the FU Berlin nor the names of
18 // its contributors may be used to endorse or promote products derived
19 // from this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 // ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
25 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31 // DAMAGE.
32 //
33 // ============================================================================
34 
40 #pragma once
41 
42 #include <vector>
43 #include <stdexcept>
44 
54 #include <seqan3/std/concepts>
55 #include <seqan3/std/ranges>
57 
58 namespace seqan3
59 {
61 enum class translation_frames : uint8_t
62 {
63  FWD_FRAME_0 = 1,
64  FWD_FRAME_1 = 1 << 1,
65  FWD_FRAME_2 = 1 << 2,
66  REV_FRAME_0 = 1 << 3,
67  REV_FRAME_1 = 1 << 4,
68  REV_FRAME_2 = 1 << 5,
74  SIX_FRAME = FWD | REV
75 };
76 
78 template<>
80 }
81 
82 namespace seqan3::detail
83 {
84 
91 template <typename urng_t>
97 class view_translate_single
98 {
99 private:
101  struct data_members_t
102  {
104  urng_t urange;
106  translation_frames const tf;
107  };
109  std::shared_ptr<data_members_t> data_members;
110 
112  static constexpr constexpr_string multiple_frame_error = "Error: Invalid type of frame. Choose one out of FWD_FRAME_0, "
113  "REV_FRAME_0, FWD_FRAME_1, REV_FRAME_1, FWD_FRAME_2 and REV_FRAME_2.";
114 public:
118  using reference = aa27;
121  using const_reference = aa27;
123  using value_type = aa27;
129  using iterator = detail::random_access_iterator<view_translate_single const>;
131  using const_iterator = iterator;
133 
137  view_translate_single() = default;
138  constexpr view_translate_single(view_translate_single const & rhs) = default;
139  constexpr view_translate_single(view_translate_single && rhs) = default;
140  constexpr view_translate_single & operator=(view_translate_single const & rhs) = default;
141  constexpr view_translate_single & operator=(view_translate_single && rhs) = default;
142  ~view_translate_single() = default;
143 
152  view_translate_single(urng_t && urange, translation_frames const tf = translation_frames::FWD_FRAME_0)
153  : data_members{new data_members_t{std::forward<urng_t>(urange), tf}}
154  {
155  if (__builtin_popcount(static_cast<uint8_t>(tf)) > 1)
156  {
157  throw std::invalid_argument(multiple_frame_error.c_str());
158  }
159  }
161 
178  iterator begin() const noexcept
179  {
180  return {*this, 0};
181  }
182 
184  iterator cbegin() const noexcept
185  {
186  return begin();
187  }
188 
202  iterator end() const noexcept
203  {
204  return {*this, size()};
205  }
206 
208  iterator cend() const noexcept
209  {
210  return end();
211  }
213 
225  size_type size() const
226  {
227  switch (data_members->tf)
228  {
230  [[fallthrough]];
232  return seqan3::size(data_members->urange) / 3;
233  break;
235  [[fallthrough]];
237  return (seqan3::size(data_members->urange) - 1) / 3;
238  break;
240  [[fallthrough]];
242  return (seqan3::size(data_members->urange) - 2) / 3;
243  break;
244  default:
245  throw std::invalid_argument(multiple_frame_error.c_str());
246  break;
247  }
248  }
249 
267  reference operator[](size_type const n) const
268  {
269  assert(n < size());
270  switch (data_members->tf)
271  {
273  return translate_triplet((data_members->urange)[n * 3], (data_members->urange)[n * 3 + 1], (data_members->urange)[n * 3 + 2]);
274  break;
276  return translate_triplet(complement((data_members->urange)[(data_members->urange).size() - n * 3 - 1]), complement((data_members->urange)[(data_members->urange).size() - n * 3 - 2]), complement((data_members->urange)[(data_members->urange).size() - n * 3 - 3]));
277  break;
279  return translate_triplet((data_members->urange)[n * 3 + 1], (data_members->urange)[n * 3 + 2], (data_members->urange)[n * 3 + 3]);
280  break;
282  return translate_triplet(complement((data_members->urange)[(data_members->urange).size() - n * 3 - 2]), complement((data_members->urange)[(data_members->urange).size() - n * 3 - 3]), complement((data_members->urange)[(data_members->urange).size() - n * 3 - 4]));
283  break;
285  return translate_triplet((data_members->urange)[n * 3 + 2], (data_members->urange)[n * 3 + 3], (data_members->urange)[n * 3 + 4]);
286  break;
288  return translate_triplet(complement((data_members->urange)[(data_members->urange).size() - n * 3 - 3]), complement((data_members->urange)[(data_members->urange).size() - n * 3 - 4]), complement((data_members->urange)[(data_members->urange).size() - n * 3 - 5]));
289  break;
290  default:
291  throw std::invalid_argument(multiple_frame_error.c_str());
292  break;
293  }
294  }
296 
298  template <random_access_container_concept container_type>
299  explicit operator container_type()
301  requires std::is_same_v<aa27, value_type_t<container_type>>
303  {
304  container_type ret;
305  ret.resize(size());
306  std::copy(cbegin(), cend(), ret.begin());
307  return ret;
308  }
309 };
310 
312 template <typename urng_t>
318 view_translate_single(urng_t &&, translation_frames const) -> view_translate_single<urng_t>;
319 
321 template <typename urng_t>
327 view_translate_single(urng_t &&) -> view_translate_single<urng_t>;
328 
329 } // namespace seqan3::detail
330 
331 namespace seqan3::view
332 {
333 
378 inline constexpr auto translate_single =deep{detail::generic_pipable_view_adaptor<detail::view_translate_single>{}};
379 
381 
382 } // namespace seqan3::view
383 
384 namespace seqan3::detail
385 {
394 template <typename urng_t>
400 class view_translate
401 {
402 private:
404  struct data_members_t
405  {
407  urng_t urange;
409  translation_frames const tf;
411  std::vector<translation_frames> selected_frames{};
412  };
414  std::shared_ptr<data_members_t> data_members;
415 
416 public:
420  using reference = view_translate_single<urng_t &>;
423  using const_reference = reference;
425  using value_type = reference;
431  using iterator = detail::random_access_iterator<view_translate const>;
433  using const_iterator = iterator;
435 
436 protected:
441  // unfortunately we cannot specialise the variable template so we have to add an auxiliary here
443  template <typename t>
444  requires (dimension_v<t> == dimension_v<value_type> + 1) &&
445  std::is_same_v<remove_cvref_t<innermost_value_type_t<value_type>>,
447  static constexpr bool is_compatible_this_aux = true;
450 
451 public:
452 
456  view_translate() = default;
457  constexpr view_translate(view_translate const & rhs) = default;
458  constexpr view_translate(view_translate && rhs) = default;
459  constexpr view_translate & operator=(view_translate const & rhs) = default;
460  constexpr view_translate & operator=(view_translate && rhs) = default;
461  ~view_translate() = default;
462 
467  view_translate(urng_t && urange, translation_frames const tf = translation_frames::SIX_FRAME)
468  : data_members{new data_members_t{std::forward<urng_t>(urange), tf}}
469  {
471  data_members->selected_frames.push_back(translation_frames::FWD_FRAME_0);
472  if ((tf & translation_frames::FWD_FRAME_1) == translation_frames::FWD_FRAME_1)
473  data_members->selected_frames.push_back(translation_frames::FWD_FRAME_1);
474  if ((tf & translation_frames::FWD_FRAME_2) == translation_frames::FWD_FRAME_2)
475  data_members->selected_frames.push_back(translation_frames::FWD_FRAME_2);
476  if ((tf & translation_frames::REV_FRAME_0) == translation_frames::REV_FRAME_0)
477  data_members->selected_frames.push_back(translation_frames::REV_FRAME_0);
478  if ((tf & translation_frames::REV_FRAME_1) == translation_frames::REV_FRAME_1)
479  data_members->selected_frames.push_back(translation_frames::REV_FRAME_1);
480  if ((tf & translation_frames::REV_FRAME_2) == translation_frames::REV_FRAME_2)
481  data_members->selected_frames.push_back(translation_frames::REV_FRAME_2);
482  }
484 
501  iterator begin() const
502  {
503  return {*this, 0};
504  }
505 
507  iterator cbegin() const
508  {
509  return begin();
510  }
511 
525  iterator end() const
526  {
527  return {*this, size()};
528  }
529 
531  iterator cend() const
532  {
533  return end();
534  }
536 
548  size_type size() const noexcept
549  {
550  return (size_type) data_members->selected_frames.size();
551  }
552 
570  reference operator[](size_type const n) const
571  {
572  assert(n < size());
573  return data_members->urange | view::translate_single(data_members->selected_frames[n]);
574  }
576 
578  template <random_access_container_concept container_type>
579  explicit operator container_type()
581  requires is_compatible_this_aux<container_type>
583  {
584  container_type ret;
585  ret.resize(size());
586  for (size_type i = 0; i < size(); i++)
587  ret[i] = static_cast<value_type_t<container_type>>(operator[](i));
588  return ret;
589  }
590 };
591 
593 template <typename urng_t>
599 view_translate(urng_t &&, translation_frames const) -> view_translate<urng_t>;
600 
602 template <typename urng_t>
608 view_translate(urng_t &&) -> view_translate<urng_t>;
609 
610 } // namespace seqan3::detail
611 
612 namespace seqan3::view
613 {
614 
659 inline constexpr auto translate = deep{detail::generic_pipable_view_adaptor<detail::view_translate>{}};
661 
662 } // 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: translation.hpp:79
::ranges::cbegin cbegin
Alias for ranges::cbegin. Returns an iterator to the beginning of a range.
Definition: ranges:245
A constexpr string implementation to manipulate string literals at compile time.
constexpr nucleotide_type complement(nucleotide_type const alph) requires requires(nucleotide_type alph)
Implementation of seqan3::nucleotide_concept::complement() that delegates to a member function...
Definition: member_exposure.hpp:220
constexpr auto translate_single
A view that translates nucleotide into aminoacid alphabet for one of the six frames.
Definition: translation.hpp:378
constexpr auto translate
A view that translates nucleotide into aminoacid alphabet with 1, 2, 3 or 6 frames.
Definition: translation.hpp:659
Contains seqan3::aa27, container aliases and string literals.
::ranges::copy copy
Alias for ranges::copy. Copies a range of elements to a new location.
Definition: ranges:200
Contains functions for translating a triplet of nucleotides into an amino acid.
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:195
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:58
Contains seqan3::dna5, container aliases and string literals.
The twenty-seven letter amino acid alphabet.
Definition: aa27.hpp:67
typename size_type< t >::type size_type_t
Type metafunction shortcut for seqan3::size_type.
Definition: pre.hpp:204
Provides seqan3::view::deep.
Type metafunction that returns the difference_type of another type [metafunction declaration].
Definition: pre.hpp:172
The Concepts library.
Auxiliary header for the view submodule .
std::remove_cv_t< std::remove_reference_t< t > > remove_cvref_t
Return the input type with const, volatile and references removed [Type metafunction].
Definition: basic.hpp:64
Adaptations of concepts from the Ranges TS.
The first third and third reverse frame.
The SeqAn3 namespace for views.
Type metafunction that returns the size_type of another type [metafunction declaration].
Definition: pre.hpp:198
The second forward and second reverse frame.
Specifies requirements of a Range type for which begin returns a type that models std::RandomAccessIt...
typename difference_type< t >::type difference_type_t
Type metafunction shortcut for seqan3::difference_type.
Definition: pre.hpp:178
The second forward frame starting at position 1.
Definition: aligned_sequence_concept.hpp:288
Implements a constexpr string that can be used for compile time computations.
Definition: constexpr_string.hpp:65
Type metafunction that returns the const_reference of another type [metafunction declaration].
Definition: pre.hpp:146
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:129
Type metafunction that returns the reference of another type [metafunction declaration].
Definition: pre.hpp:92
Provides various metafunctions used by the range module.
typename value_type< t >::type value_type_t
Type metafunction shortcut for seqan3::value_type.
Definition: pre.hpp:72
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:83
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:250
The second reverse frame starting at position 1.
Adaptations of concepts from the standard library.
Type metafunction that returns the value_type of another type [metafunction declaration].
Definition: pre.hpp:66
Specifies the requirements of a Range type that knows its size in constant time with the size functio...
The first reverse frame starting at position 0.
translation_frames
Specialisation values for single and multiple translation frames.
Definition: translation.hpp:61
The third reverse frame starting at position 2.
A concept that indicates whether an alphabet represents nucleotides.In addition to the requirements f...