SeqAn3 3.4.0-rc.1
The Modern C++ library for sequence analysis.
Loading...
Searching...
No Matches
translate.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2006-2024 Knut Reinert & Freie Universität Berlin
2// SPDX-FileCopyrightText: 2016-2024 Knut Reinert & MPI für molekulare Genetik
3// SPDX-License-Identifier: BSD-3-Clause
4
10#pragma once
11
12#include <concepts>
13#include <ranges>
14#include <stdexcept>
15#include <vector>
16
25
26// ============================================================================
27// forwards
28// ============================================================================
29
30namespace seqan3::detail
31{
32
33template <std::ranges::view urng_t>
34 requires std::ranges::sized_range<urng_t> && std::ranges::random_access_range<urng_t>
36class view_translate;
37
38template <std::ranges::view urng_t>
39 requires std::ranges::sized_range<urng_t> && std::ranges::random_access_range<urng_t>
41class view_translate_single;
42
43} // namespace seqan3::detail
44
45// ============================================================================
46// translation_frames
47// ============================================================================
48
49namespace seqan3
50{
51
73
77template <>
78inline constexpr bool add_enum_bitwise_operators<translation_frames> = true;
80
81} // namespace seqan3
82
83namespace seqan3::detail
84{
85
86// ============================================================================
87// translate_fn (adaptor definition for both views)
88// ============================================================================
89
93template <bool single>
94struct translate_fn
95{
97 static constexpr translation_frames default_frames =
99
101 constexpr auto operator()(translation_frames const tf = default_frames) const
102 {
103 return detail::adaptor_from_functor{*this, tf};
104 }
105
111 template <std::ranges::range urng_t>
112 constexpr auto operator()(urng_t && urange, translation_frames const tf = default_frames) const
113 {
114 static_assert(std::ranges::viewable_range<urng_t>,
115 "The range parameter to views::translate[_single] cannot be a temporary of a non-view range.");
116 static_assert(std::ranges::sized_range<urng_t>,
117 "The range parameter to views::translate[_single] must model std::ranges::sized_range.");
118 static_assert(std::ranges::random_access_range<urng_t>,
119 "The range parameter to views::translate[_single] must model std::ranges::random_access_range.");
120 static_assert(
122 "The range parameter to views::translate[_single] must be over elements of seqan3::nucleotide_alphabet.");
123
124 if constexpr (single)
125 return detail::view_translate_single{std::forward<urng_t>(urange), tf};
126 else
127 return detail::view_translate{std::forward<urng_t>(urange), tf};
128 }
129
131 template <std::ranges::range urng_t>
132 constexpr friend auto operator|(urng_t && urange, translate_fn const & me)
133 {
134 return me(std::forward<urng_t>(urange));
135 }
136};
137
138// ============================================================================
139// view_translate_single (range definition)
140// ============================================================================
141
148template <std::ranges::view urng_t>
149 requires std::ranges::sized_range<urng_t> && std::ranges::random_access_range<urng_t>
151class view_translate_single : public std::ranges::view_base
152{
153private:
155 urng_t urange;
159 static constexpr small_string multiple_frame_error{"Error: Invalid type of frame. Choose one out of "
160 "forward_frame0, reverse_frame0, forward_frame1, "
161 "reverse_frame1, forward_frame2 and reverse_frame2."};
162
163public:
168 using reference = aa27;
170 using const_reference = aa27;
172 using value_type = aa27;
174 using size_type = std::ranges::range_size_t<urng_t>;
176 using difference_type = std::ranges::range_difference_t<urng_t>;
178 using iterator = detail::random_access_iterator<view_translate_single>;
180 using const_iterator = detail::random_access_iterator<view_translate_single const>;
182
186 view_translate_single() noexcept = default;
187 constexpr view_translate_single(view_translate_single const & rhs) noexcept = default;
188 constexpr view_translate_single(view_translate_single && rhs) noexcept = default;
189 constexpr view_translate_single & operator=(view_translate_single const & rhs) noexcept = default;
190 constexpr view_translate_single & operator=(view_translate_single && rhs) noexcept = default;
191 ~view_translate_single() noexcept = default;
192
201 view_translate_single(urng_t _urange, translation_frames const _tf = translation_frames::forward_frame0) :
202 urange{std::move(_urange)},
203 tf{_tf}
204 {
205 if (__builtin_popcount(static_cast<uint8_t>(_tf)) > 1)
206 {
207 throw std::invalid_argument(multiple_frame_error.c_str());
208 }
209 }
210
219 template <typename rng_t>
220 requires (!std::same_as<std::remove_cvref_t<rng_t>, view_translate_single>)
221 && std::ranges::viewable_range<rng_t>
222 && std::constructible_from<urng_t, std::ranges::ref_view<std::remove_reference_t<rng_t>>>
223 view_translate_single(rng_t && _urange, translation_frames const _tf = translation_frames::forward_frame0) :
224 view_translate_single{std::views::all(std::forward<rng_t>(_urange)), _tf}
225 {}
227
244 iterator begin() noexcept
245 {
246 return {*this, 0};
247 }
248
250 const_iterator begin() const noexcept
251 {
252 return {*this, 0};
253 }
254
268 iterator end() noexcept
269 {
270 return {*this, size()};
271 }
272
274 const_iterator end() const noexcept
275 {
276 return {*this, size()};
277 }
279
291 size_type size()
292 {
293 switch (tf)
294 {
296 [[fallthrough]];
298 return std::ranges::size(urange) / 3;
299 break;
301 [[fallthrough]];
303 return (std::max<size_type>(std::ranges::size(urange), 1) - 1) / 3;
304 break;
306 [[fallthrough]];
308 return (std::max<size_type>(std::ranges::size(urange), 2) - 2) / 3;
309 break;
310 default:
311 throw std::invalid_argument(multiple_frame_error.c_str());
312 break;
313 }
314 }
315
317 size_type size() const
318 {
319 switch (tf)
320 {
322 [[fallthrough]];
324 return std::ranges::size(urange) / 3;
325 break;
327 [[fallthrough]];
329 return (std::max<size_type>(std::ranges::size(urange), 1) - 1) / 3;
330 break;
332 [[fallthrough]];
334 return (std::max<size_type>(std::ranges::size(urange), 2) - 2) / 3;
335 break;
336 default:
337 throw std::invalid_argument(multiple_frame_error.c_str());
338 break;
339 }
340 }
341
360 reference operator[](size_type const n)
361 {
362 // size will throw (only in debug-builds!) if translation_frames is neither (FWD|REV)_FRAME_(0|1|2),
363 // we catch that error in debug-builds to make this function consistent with the behaviour in
364 // release-builds (-DNDEBUG).
365#ifndef NDEBUG
366 try
367 {
368 assert(n < size());
369 }
370 catch (std::invalid_argument const &)
371 {}
372#endif
373
374 switch (tf)
375 {
377 return translate_triplet((urange)[n * 3], (urange)[n * 3 + 1], (urange)[n * 3 + 2]);
378 break;
380 return translate_triplet(complement((urange)[(urange).size() - n * 3 - 1]),
381 complement((urange)[(urange).size() - n * 3 - 2]),
382 complement((urange)[(urange).size() - n * 3 - 3]));
383 break;
385 return translate_triplet((urange)[n * 3 + 1], (urange)[n * 3 + 2], (urange)[n * 3 + 3]);
386 break;
388 return translate_triplet(complement((urange)[(urange).size() - n * 3 - 2]),
389 complement((urange)[(urange).size() - n * 3 - 3]),
390 complement((urange)[(urange).size() - n * 3 - 4]));
391 break;
393 return translate_triplet((urange)[n * 3 + 2], (urange)[n * 3 + 3], (urange)[n * 3 + 4]);
394 break;
396 return translate_triplet(complement((urange)[(urange).size() - n * 3 - 3]),
397 complement((urange)[(urange).size() - n * 3 - 4]),
398 complement((urange)[(urange).size() - n * 3 - 5]));
399 break;
400 default:
401 throw std::invalid_argument(multiple_frame_error.c_str());
402 break;
403 }
404 }
405
407 const_reference operator[](size_type const n) const
408 {
409 // size will throw (only in debug-builds!) if translation_frames is neither (FWD|REV)_FRAME_(0|1|2),
410 // we catch that error in debug-builds to make this function consistent with the behaviour in
411 // release-builds (-DNDEBUG).
412#ifndef NDEBUG
413 try
414 {
415 assert(n < size());
416 }
417 catch (std::invalid_argument const &)
418 {}
419#endif
420
421 switch (tf)
422 {
424 return translate_triplet((urange)[n * 3], (urange)[n * 3 + 1], (urange)[n * 3 + 2]);
425 break;
427 return translate_triplet(complement((urange)[(urange).size() - n * 3 - 1]),
428 complement((urange)[(urange).size() - n * 3 - 2]),
429 complement((urange)[(urange).size() - n * 3 - 3]));
430 break;
432 return translate_triplet((urange)[n * 3 + 1], (urange)[n * 3 + 2], (urange)[n * 3 + 3]);
433 break;
435 return translate_triplet(complement((urange)[(urange).size() - n * 3 - 2]),
436 complement((urange)[(urange).size() - n * 3 - 3]),
437 complement((urange)[(urange).size() - n * 3 - 4]));
438 break;
440 return translate_triplet((urange)[n * 3 + 2], (urange)[n * 3 + 3], (urange)[n * 3 + 4]);
441 break;
443 return translate_triplet(complement((urange)[(urange).size() - n * 3 - 3]),
444 complement((urange)[(urange).size() - n * 3 - 4]),
445 complement((urange)[(urange).size() - n * 3 - 5]));
446 break;
447 default:
448 throw std::invalid_argument(multiple_frame_error.c_str());
449 break;
450 }
451 }
453};
454
456template <typename urng_t>
457view_translate_single(urng_t &&, translation_frames const) -> view_translate_single<std::views::all_t<urng_t>>;
458
460template <typename urng_t>
461view_translate_single(urng_t &&) -> view_translate_single<std::views::all_t<urng_t>>;
462
463} // namespace seqan3::detail
464
465// ============================================================================
466// translate_single (adaptor object)
467// ============================================================================
468
469namespace seqan3::views
470{
471
520inline constexpr auto translate_single = deep{detail::translate_fn<true>{}};
521
522} // namespace seqan3::views
523
524// ============================================================================
525// view_translate (range definition)
526// ============================================================================
527
528namespace seqan3::detail
529{
530
539template <std::ranges::view urng_t>
540 requires std::ranges::sized_range<urng_t> && std::ranges::random_access_range<urng_t>
542class view_translate : public std::ranges::view_base
543{
544private:
546 urng_t urange;
550 small_vector<translation_frames, 6> selected_frames{};
551
552public:
557 using reference = view_translate_single<urng_t>;
559 using const_reference = reference;
561 using value_type = reference;
563 using size_type = std::ranges::range_size_t<urng_t>;
565 using difference_type = std::ranges::range_difference_t<urng_t>;
567 using iterator = detail::random_access_iterator<view_translate>;
569 using const_iterator = detail::random_access_iterator<view_translate const>;
571
572protected:
579 // unfortunately we cannot specialise the variable template so we have to add an auxiliary here
580 template <typename t>
581 requires (range_dimension_v<t> == range_dimension_v<value_type> + 1)
582 && std::is_same_v<std::remove_cvref_t<range_innermost_value_t<value_type>>,
583 std::remove_cvref_t<range_innermost_value_t<t>>>
584 static constexpr bool is_compatible_this_aux = true;
587
588public:
592 view_translate() noexcept = default;
593 constexpr view_translate(view_translate const & rhs) noexcept = default;
594 constexpr view_translate(view_translate && rhs) noexcept = default;
595 constexpr view_translate & operator=(view_translate const & rhs) noexcept = default;
596 constexpr view_translate & operator=(view_translate && rhs) noexcept = default;
597 ~view_translate() noexcept = default;
598
603 view_translate(urng_t _urange, translation_frames const _tf = translation_frames::six_frames) :
604 urange{std::move(_urange)},
605 tf{_tf}
606 {
608 selected_frames.push_back(translation_frames::forward_frame0);
610 selected_frames.push_back(translation_frames::forward_frame1);
612 selected_frames.push_back(translation_frames::forward_frame2);
614 selected_frames.push_back(translation_frames::reverse_frame0);
616 selected_frames.push_back(translation_frames::reverse_frame1);
618 selected_frames.push_back(translation_frames::reverse_frame2);
619 }
620
625 template <typename rng_t>
626 requires (!std::same_as<std::remove_cvref_t<rng_t>, view_translate>) && std::ranges::viewable_range<rng_t>
627 && std::constructible_from<urng_t, std::ranges::ref_view<std::remove_reference_t<rng_t>>>
628 view_translate(rng_t && _urange, translation_frames const _tf) :
629 view_translate{std::views::all(std::forward<rng_t>(_urange)), _tf}
630 {}
632
649 iterator begin() noexcept
650 {
651 return {*this, 0};
652 }
653
655 const_iterator begin() const noexcept
656 {
657 return {*this, 0};
658 }
659
673 iterator end() noexcept
674 {
675 return {*this, size()};
676 }
677
679 const_iterator end() const noexcept
680 {
681 return {*this, size()};
682 }
683
695 size_type size() noexcept
696 {
697 return (size_type)selected_frames.size();
698 }
699
701 size_type size() const noexcept
702 {
703 return (size_type)selected_frames.size();
704 }
705
724 reference operator[](size_type const n)
725 {
726 assert(n < size());
727 return urange | views::translate_single(selected_frames[n]);
728 }
729
731 const_reference operator[](size_type const n) const
732 {
733 assert(n < size());
734 return urange | views::translate_single(selected_frames[n]);
735 }
737};
738
740template <typename urng_t>
741 requires std::ranges::sized_range<urng_t> && std::ranges::random_access_range<urng_t>
743 view_translate(urng_t &&, translation_frames const) -> view_translate<std::views::all_t<urng_t>>;
744} // namespace seqan3::detail
745
746// ============================================================================
747// translate (adaptor object)
748// ============================================================================
749
750namespace seqan3::views
751{
800inline constexpr auto translate = deep{detail::translate_fn<false>{}};
801
802} // namespace seqan3::views
Provides seqan3::aa27, container aliases and string literals.
Provides seqan3::detail::adaptor_from_functor.
Provides seqan3::add_enum_bitwise_operators.
T begin(T... args)
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.
Provides seqan3::views::deep.
Provides seqan3::dna5, container aliases and string literals.
T end(T... args)
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:52
constexpr auto complement
Return the complement of a nucleotide object.
Definition alphabet/nucleotide/concept.hpp:102
constexpr auto translate
A view that translates nucleotide into aminoacid alphabet with 1, 2, 3 or 6 frames.
Definition translate.hpp:800
constexpr auto translate_single
A view that translates nucleotide into aminoacid alphabet for one of the six frames.
Definition translate.hpp:520
auto operator|(validator1_type &&vali1, validator2_type &&vali2)
Enables the chaining of validators.
Definition validators.hpp:1121
@ single
The text is a single range.
Definition search/fm_index/concept.hpp:90
constexpr size_t size
The size of a type pack.
Definition type_pack/traits.hpp:143
A concept that indicates whether an alphabet represents nucleotides.
T is_same_v
The SeqAn namespace for views.
Definition char_strictly_to.hpp:19
The main SeqAn3 namespace.
Definition aligned_sequence_concept.hpp:26
translation_frames
Specialisation values for single and multiple translation frames.
Definition translate.hpp:59
@ 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.
A constexpr string implementation to manipulate string literals at compile time.
Provides functions for translating a triplet of nucleotides into an amino acid.
Hide me