SeqAn3
scoring_scheme_base.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 
41 #pragma once
42 
43 #include <range/v3/algorithm/copy.hpp>
44 
49 #include <seqan3/std/ranges>
50 
51 #if SEQAN3_WITH_CEREAL
52 #include <cereal/types/array.hpp>
53 #endif // SEQAN3_WITH_CEREAL
54 
55 namespace seqan3
56 {
57 
58 // ------------------------------------------------------------------
59 // seqan3::match_score
60 // ------------------------------------------------------------------
61 
67 template <arithmetic_concept score_type>
68 struct match_score : detail::strong_type<score_type, match_score<score_type>, detail::strong_type_skill::convert>
69 {
70  using detail::strong_type<score_type, match_score<score_type>, detail::strong_type_skill::convert>::strong_type;
71 };
72 
77 template <arithmetic_concept score_type>
78 match_score(score_type &&) -> match_score<score_type>;
80 
81 // ------------------------------------------------------------------
82 // seqan3::mismatch_score
83 // ------------------------------------------------------------------
84 
90 template <arithmetic_concept score_type>
91 struct mismatch_score : detail::strong_type<score_type, mismatch_score<score_type>, detail::strong_type_skill::convert>
92 {
93  using detail::strong_type<score_type, mismatch_score<score_type>, detail::strong_type_skill::convert>::strong_type;
94 };
95 
100 template <arithmetic_concept score_type>
103 
104 // ------------------------------------------------------------------
105 // seqan3::scoring_scheme_base
106 // ------------------------------------------------------------------
107 
118 template <typename derived_t, alphabet_concept alphabet_t, arithmetic_concept score_t>
120 {
121 public:
125  using score_type = score_t;
128  using matrix_size_type = std::remove_const_t<decltype(alphabet_size_v<alphabet_t>)>;
130 
132  static constexpr matrix_size_type matrix_size = alphabet_size_v<alphabet_t>;
133 
137  using matrix_type = std::array<std::array<score_type, matrix_size>, matrix_size>;
140 
141 private:
143  friend derived_t;
144 
146 
149  constexpr scoring_scheme_base(scoring_scheme_base const &) noexcept = default;
150  constexpr scoring_scheme_base(scoring_scheme_base &&) noexcept = default;
151  constexpr scoring_scheme_base & operator=(scoring_scheme_base const &) noexcept = default;
152  constexpr scoring_scheme_base & operator=(scoring_scheme_base &&) noexcept = default;
153  ~scoring_scheme_base() noexcept = default;
154 
156  constexpr scoring_scheme_base() noexcept
157  {
158  set_hamming_distance();
159  }
160 
164  template <arithmetic_concept score_arg_t>
166  {
167  set_simple_scheme(ms, mms);
168  }
169 
173  constexpr scoring_scheme_base(matrix_type const & _matrix) noexcept
174  {
175  set_custom_matrix(_matrix);
176  }
178 
179 public:
183  constexpr void set_hamming_distance() noexcept
185  {
186  set_simple_scheme(match_score<score_t>{0}, mismatch_score<score_t>{-1});
187  }
188 
195  template <arithmetic_concept score_arg_t>
197  {
198  std::conditional_t<std::Integral<score_t>, int64_t, double> i_ms = static_cast<score_arg_t>(ms);
199  std::conditional_t<std::Integral<score_t>, int64_t, double> i_mms = static_cast<score_arg_t>(mms);
200  if ((i_ms < std::numeric_limits<score_t>::lowest() || i_ms > std::numeric_limits<score_t>::max()) ||
201  (i_mms < std::numeric_limits<score_t>::lowest() || i_mms > std::numeric_limits<score_t>::max()))
202  {
203  throw std::invalid_argument{"You passed a score value to set_simple_scheme that is out of range of the "
204  "scoring scheme's underlying type. Define your scoring scheme with a larger "
205  "template parameter or down-cast you score value beforehand to prevent "
206  "this exception."};
207  }
208 
209  for (matrix_size_type i = 0; i < matrix_size; ++i)
210  for (matrix_size_type j = 0; j < matrix_size; ++j)
211  matrix[i][j] = (i == j) ? static_cast<score_t>(i_ms) : static_cast<score_t>(i_mms);
212  }
213 
217  constexpr void set_custom_matrix(matrix_type const & _matrix) noexcept
218  {
219  std::ranges::copy(_matrix, begin(matrix));
220  }
222 
233  template <explicitly_convertible_to_concept<alphabet_t> alph1_t,
234  explicitly_convertible_to_concept<alphabet_t> alph2_t>
235  constexpr score_t & score(alph1_t const alph1, alph2_t const alph2) noexcept
236  {
237  return matrix[to_rank(static_cast<alphabet_t>(alph1))][to_rank(static_cast<alphabet_t>(alph2))];
238  }
239 
241  template <explicitly_convertible_to_concept<alphabet_t> alph1_t,
242  explicitly_convertible_to_concept<alphabet_t> alph2_t>
243  constexpr score_t score(alph1_t const alph1, alph2_t const alph2) const noexcept
244  {
245  return matrix[to_rank(static_cast<alphabet_t>(alph1))][to_rank(static_cast<alphabet_t>(alph2))];
246  }
248 
251  constexpr bool operator==(derived_t const & rhs) const noexcept
252  {
253  return matrix == rhs.matrix;
254  }
255 
256  constexpr bool operator!=(derived_t const & rhs) const noexcept
257  {
258  return matrix != rhs.matrix;
259  }
261 
269  template <cereal_archive_concept archive_t>
270  void CEREAL_SERIALIZE_FUNCTION_NAME(archive_t & archive)
271  {
272  archive(matrix);
273  }
275 
276 private:
278  matrix_type matrix{};
279 };
280 
281 } // namespace seqan3
Contains basic data structure for strong types.
A CRTP base class for scoring schemes.
Definition: scoring_scheme_base.hpp:119
Contains various shortcuts for common std::ranges functions.
score_t score_type
Type of the score values.
Definition: scoring_scheme_base.hpp:126
constexpr scoring_scheme_base(match_score< score_arg_t > const ms, mismatch_score< score_arg_t > const mms)
Constructor for the simple scheme (delegates to set_simple_scheme()).
Definition: scoring_scheme_base.hpp:165
constexpr score_t & score(alph1_t const alph1, alph2_t const alph2) noexcept
Score two letters (either two nucleotids or two amino acids).
Definition: scoring_scheme_base.hpp:235
::ranges::copy copy
Alias for ranges::copy. Copies a range of elements to a new location.
Definition: ranges:200
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:58
constexpr void set_custom_matrix(matrix_type const &_matrix) noexcept
Set a custom scheme by passing a full matrix with arbitrary content.
Definition: scoring_scheme_base.hpp:217
constexpr score_t score(alph1_t const alph1, alph2_t const alph2) const noexcept
Score two letters (either two nucleotids or two amino acids).
Definition: scoring_scheme_base.hpp:243
A strong type of underlying type score_type that represents the score of two matching characters...
Definition: scoring_scheme_base.hpp:68
A strong type of underlying type score_type that represents the score two different characters...
Definition: scoring_scheme_base.hpp:91
Adaptations of concepts from the Ranges TS.
constexpr void set_simple_scheme(match_score< score_arg_t > const ms, mismatch_score< score_arg_t > const mms)
Set the simple scheme (everything is either match or mismatch).
Definition: scoring_scheme_base.hpp:196
Adaptions of concepts from the Cereal library.
constexpr scoring_scheme_base(matrix_type const &_matrix) noexcept
Constructor for a custom scheme (delegates to set_custom_matrix()).
Definition: scoring_scheme_base.hpp:173
std::array< std::array< score_type, matrix_size >, matrix_size > matrix_type
Type of the internal matrix (a two-dimensional array).
Definition: scoring_scheme_base.hpp:138
Core alphabet concept and free function/metafunction wrappers.
constexpr underlying_rank_t< alphabet_type > to_rank(alphabet_type const alph) requires requires(alphabet_type alph)
Implementation of seqan3::semi_alphabet_concept::to_rank() that delegates to a member function...
Definition: member_exposure.hpp:97