ʻOhana
Population structure, admixture history, and selection using learning methods.
jade.verification.hpp
1 /* -------------------------------------------------------------------------
2  Ohana
3  Copyright (c) 2015-2020 Jade Cheng (\___/)
4  Jade Cheng <info@jade-cheng.com> (='.'=)
5  ------------------------------------------------------------------------- */
6 
7 #ifndef JADE_VERIFICATION_HPP__
8 #define JADE_VERIFICATION_HPP__
9 
10 #include "jade.genotype_matrix.hpp"
11 
12 namespace jade
13 {
14  ///
15  /// A template for a class that performs validation on various types of
16  /// matrices.
17  ///
18  template <typename TValue>
20  {
21  public:
22  /// The value type.
23  typedef TValue value_type;
24 
25  /// The matrix type.
27 
28  /// The genotype matrix type.
30 
31  /// The epsilon value.
32  static constexpr value_type epsilon = value_type(0.000001);
33 
34  ///
35  /// Validates the C matrix and throws an exception if validation fails.
36  /// \return True.
37  ///
38  static bool validate_c(
39  const matrix_type & c) ///< The C matrix to validate.
40  {
41  if (!c.is_square())
42  throw error() << "invalid C matrix size " << c.get_size_str()
43  << " is not square";
44 
45  const auto rk = c.get_height();
46  if (0 == rk)
47  throw error() << "invalid C matrix size " << c.get_size_str()
48  << " does not contain any components";
49 
50  for (size_t y = 0; y < rk; y++)
51  for (size_t x = y + 1; x < rk; x++)
52  if (std::fabs(c(y, x) - c(x, y)) > epsilon)
53  throw error()
54  << "invalid C matrix cell [" << y+1 << ","
55  << x+1 << "] (" << c(y, x)
56  << ") is not equal to symmetric cell ["
57  << x+1 << "," << y+1 << "] (" << c(x, y) << ")";
58 
59 
60  // Create a copy of C before LAPACK replaces it with the
61  // Cholesky square root and then its inverse.
62  matrix_type cholesky (c);
63  if (!cholesky.potrf_lower() || !cholesky.potri_lower())
64  throw error("invalid C matrix is not positive semidefinite");
65 
66  return true;
67  }
68 
69  ///
70  /// Validates the F matrix and throws an exception if validation fails.
71  /// \return True.
72  ///
73  static bool validate_f(
74  const matrix_type & f) ///< The F matrix to validate.
75  {
76  static const auto epsilon = value_type(1.0e-6);
77  static const auto min = value_type(0.0) + epsilon;
78  static const auto max = value_type(1.0) - epsilon;
79 
80  const auto K = f.get_height();
81  const auto J = f.get_width();
82 
83  if (0 == K)
84  throw error() << "invalid F matrix size " << f.get_size_str()
85  << " does not contain any components";
86 
87  if (0 == J)
88  throw error() << "invalid F matrix size " << f.get_size_str()
89  << " does not contain any markers";
90 
91  for (size_t k = 0; k < K; k++)
92  {
93  for (size_t j = 0; j < J; j++)
94  {
95  const auto f_kj = f(k, j);
96 
97  if (f_kj >= min && f_kj <= max)
98  continue;
99 
100  throw error()
101  << "invalid F matrix cell [" << k+1 << "," << j+1
102  << "] (" << f_kj << ") is not between 0 and 1";
103  }
104  }
105 
106  return true;
107  }
108 
109  ///
110  /// Validates the sizes of the F and C matrices and throws an exception
111  /// if validation fails.
112  /// \return True.
113  ///
114  static bool validate_fc_sizes(
115  const matrix_type & f, ///< The F matrix to validate.
116  const matrix_type & c) ///< The C matrix to validate.
117  {
118  if (f.get_height() != c.get_height() + 1)
119  throw error()
120  << "inconsistent F matrix size " << f.get_size_str()
121  << " and C matrix size " << c.get_size_str();
122 
123  return true;
124  }
125 
126  ///
127  /// Validates the size of the Fin-force matrix and throws an exception
128  /// if validation fails.
129  /// \return True.
130  ///
131  static bool validate_fif_size(
132  const matrix_type & fif, ///< The Fin-force matrix.
133  const size_t k, ///< The component count.
134  const size_t j) ///< The marker count.
135  {
136  const auto fif_height = fif.get_height();
137  const auto fif_width = fif.get_width();
138 
139  if (fif_width != j)
140  throw error()
141  << "inconsistent marker count (" << j
142  << ") and width of matrix specified for --fin-force "
143  << "option (" << fif_width << ")";
144 
145  if (fif_height >= k)
146  throw error()
147  << "inconsistent component count (" << k << ") and "
148  << "height of matrix specified for --fin-force "
149  << "option (" << fif_height << ")";
150 
151  return true;
152  }
153 
154  ///
155  /// Validates the G matrix and throws an exception if validation fails.
156  /// \return True.
157  ///
158  static bool validate_g(
159  const genotype_matrix_type & g) ///< The G matrix to validate.
160  {
161  if (0 == g.get_height())
162  throw error() << "invalid G matrix size " << g.get_size_str()
163  << " does not contain any individuals";
164 
165  if (0 == g.get_width())
166  throw error() << "invalid G matrix size " << g.get_size_str()
167  << " does not contain any markers";
168 
169  return true;
170  }
171 
172  ///
173  /// Validates the sizes of the G and F matrices and throws an exception
174  /// if validation fails.
175  /// \return True.
176  ///
177  static bool validate_gf_sizes(
178  const genotype_matrix_type & g, ///< The G matrix to validate.
179  const matrix_type & f) ///< The F matrix to validate.
180  {
181  if (g.get_width() != f.get_width())
182  throw error()
183  << "inconsistent G matrix size " << g.get_size_str()
184  << " and F matrix size " << f.get_size_str();
185 
186  return true;
187  }
188 
189  ///
190  /// Validates the sizes of the G and Q matrices and throws an exception
191  /// if validation fails.
192  /// \return True.
193  ///
194  static bool validate_gq_sizes(
195  const genotype_matrix_type & g, ///< The G matrix to validate.
196  const matrix_type & q) ///< The Q matrix to validate.
197  {
198  if (g.get_height() != q.get_height())
199  throw error()
200  << "inconsistent G matrix size " << g.get_size_str()
201  << " and Q matrix size " << q.get_size_str();
202 
203  return true;
204  }
205 
206  ///
207  /// Validates the sizes of the G, Q, and F matrices and throws an
208  /// exception if validation fails.
209  /// \return True.
210  ///
211  static bool validate_gqf_sizes(
212  const genotype_matrix_type & g, ///< The G matrix to validate.
213  const matrix_type & q, ///< The Q matrix to validate.
214  const matrix_type & f) ///< The F matrix to validate.
215  {
216  return validate_gq_sizes(g, q)
217  && validate_gf_sizes(g, f)
218  && validate_qf_sizes(q, f);
219  }
220 
221  ///
222  /// Validates the Q matrix and throws an exception if validation fails.
223  /// \return True.
224  ///
225  static bool validate_q(
226  const matrix_type & q) ///< The Q matrix to validate.
227  {
228  const auto I = q.get_height();
229  const auto K = q.get_width();
230 
231  if (0 == I)
232  throw error() << "invalid Q matrix size " << q.get_size_str()
233  << " does not contain any individuals";
234 
235  if (0 == K)
236  throw error() << "invalid Q matrix size " << q.get_size_str()
237  << " does not contain any components";
238 
239  for (size_t i = 0; i < I; i++)
240  {
241  auto sum = value_type(0);
242 
243  for (size_t k = 0; k < K; k++)
244  {
245  const auto q_ik = q(i, k);
246 
247  if (q_ik < value_type(0) || q_ik > value_type(1))
248  throw error()
249  << "invalid Q matrix cell [" << i+1 << "," << k+1
250  << "] (" << q_ik << ") is not between 0 and 1";
251 
252  sum += q_ik;
253  }
254 
255  if (std::fabs(sum - value_type(1)) > epsilon)
256  throw error() << "invalid Q matrix row " << i+1
257  << " does not sum to 1 (" << sum << ")";
258  }
259 
260  return true;
261  }
262 
263  ///
264  /// Validates the sizes of the Q and F matrices and throws an exception
265  /// if validation fails.
266  /// \return True.
267  ///
268  static bool validate_qf_sizes(
269  const matrix_type & q, ///< The Q matrix to validate.
270  const matrix_type & f) ///< The F matrix to validate.
271  {
272  if (q.get_width() != f.get_height())
273  throw error()
274  << "inconsistent Q matrix size " << q.get_size_str()
275  << " and F matrix size " << f.get_size_str();
276 
277  return true;
278  }
279  };
280 }
281 
282 #endif // JADE_VERIFICATION_HPP__
jade::basic_verification::epsilon
static constexpr value_type epsilon
The epsilon value.
Definition: jade.verification.hpp:32
jade::basic_verification::value_type
TValue value_type
The value type.
Definition: jade.verification.hpp:23
jade::basic_matrix::is_square
bool is_square() const
Definition: jade.matrix.hpp:917
jade::basic_verification
A template for a class that performs validation on various types of matrices.
Definition: jade.verification.hpp:20
jade::basic_verification::validate_c
static bool validate_c(const matrix_type &c)
Validates the C matrix and throws an exception if validation fails.
Definition: jade.verification.hpp:38
jade::basic_verification::validate_qf_sizes
static bool validate_qf_sizes(const matrix_type &q, const matrix_type &f)
Validates the sizes of the Q and F matrices and throws an exception if validation fails.
Definition: jade.verification.hpp:268
jade::basic_verification::validate_gf_sizes
static bool validate_gf_sizes(const genotype_matrix_type &g, const matrix_type &f)
Validates the sizes of the G and F matrices and throws an exception if validation fails.
Definition: jade.verification.hpp:177
jade::basic_matrix::get_width
size_t get_width() const
Definition: jade.matrix.hpp:757
jade::basic_genotype_matrix::get_size_str
virtual std::string get_size_str() const =0
jade::basic_verification::matrix_type
basic_matrix< value_type > matrix_type
The matrix type.
Definition: jade.verification.hpp:26
jade::basic_genotype_matrix
A template for an abstract class implementing operations for a genotype matrix.
Definition: jade.genotype_matrix.hpp:26
jade::basic_verification::validate_fc_sizes
static bool validate_fc_sizes(const matrix_type &f, const matrix_type &c)
Validates the sizes of the F and C matrices and throws an exception if validation fails.
Definition: jade.verification.hpp:114
jade::basic_genotype_matrix::get_width
virtual size_t get_width() const =0
jade::basic_matrix::get_size_str
std::string get_size_str() const
Definition: jade.matrix.hpp:735
jade::basic_verification::validate_f
static bool validate_f(const matrix_type &f)
Validates the F matrix and throws an exception if validation fails.
Definition: jade.verification.hpp:73
jade::basic_matrix::potrf_lower
bool potrf_lower()
Forms the Cholesky factorization of a symmetric positive-definite matrix: [A = L * L^T] where L is th...
Definition: jade.matrix.hpp:1018
jade::basic_matrix::get_height
size_t get_height() const
Definition: jade.matrix.hpp:603
jade::basic_verification::validate_gqf_sizes
static bool validate_gqf_sizes(const genotype_matrix_type &g, const matrix_type &q, const matrix_type &f)
Validates the sizes of the G, Q, and F matrices and throws an exception if validation fails.
Definition: jade.verification.hpp:211
jade::basic_verification::validate_gq_sizes
static bool validate_gq_sizes(const genotype_matrix_type &g, const matrix_type &q)
Validates the sizes of the G and Q matrices and throws an exception if validation fails.
Definition: jade.verification.hpp:194
jade::basic_verification::validate_q
static bool validate_q(const matrix_type &q)
Validates the Q matrix and throws an exception if validation fails.
Definition: jade.verification.hpp:225
jade::basic_genotype_matrix::get_height
virtual size_t get_height() const =0
jade::basic_verification::validate_g
static bool validate_g(const genotype_matrix_type &g)
Validates the G matrix and throws an exception if validation fails.
Definition: jade.verification.hpp:158
jade::basic_verification::genotype_matrix_type
basic_genotype_matrix< value_type > genotype_matrix_type
The genotype matrix type.
Definition: jade.verification.hpp:29
jade::basic_error
A template for a class representing an exception thrown from this namespace.
Definition: jade.error.hpp:20
jade::basic_verification::validate_fif_size
static bool validate_fif_size(const matrix_type &fif, const size_t k, const size_t j)
Validates the size of the Fin-force matrix and throws an exception if validation fails.
Definition: jade.verification.hpp:131
jade::basic_matrix< value_type >
jade::basic_matrix::potri_lower
bool potri_lower()
Computes the inverse inv(A) of a symmetric positive definite matrix A. Before calling this routine,...
Definition: jade.matrix.hpp:1039