1 #ifndef GENESIS_POPULATION_FUNCTIONS_STRUCTURE_H_
2 #define GENESIS_POPULATION_FUNCTIONS_STRUCTURE_H_
48 namespace population {
67 #if __cplusplus >= 201402L
110 template<
class ForwardIterator,
typename FstFunctor>
111 utils::Matrix<double> compute_pairwise_f_st(
112 ForwardIterator begin, ForwardIterator end,
113 FstFunctor fst_functor
123 size_t const size =
static_cast<std::vector<BaseCounts> const&
>( *begin ).size();
124 auto result = utils::Matrix<double>( size, size, 0.0 );
128 auto select_entry = [size]( ForwardIterator begin, ForwardIterator end,
size_t index ){
135 [size, index]( std::vector<BaseCounts>
const& samples ) -> BaseCounts
const& {
136 if( samples.size() != size ) {
137 throw std::runtime_error(
138 "In compute_pairwise_f_st(): The number of BaseCounts in the "
139 "provided range is not consistent throughout the iteration."
142 return samples[index];
151 for(
size_t i = 0; i < size; ++i ) {
152 for(
size_t j = i + 1; j < size; ++j ) {
153 auto range_i = select_entry( begin, end, i );
154 auto range_j = select_entry( begin, end, j );
155 auto const fst = fst_functor(
157 range_i.begin(), range_i.end(),
158 range_j.begin(), range_j.end()
160 result( i, j ) = fst;
161 result( j, i ) = fst;
168 #endif // __cplusplus >= 201402L
182 BaseCounts
const& p1, BaseCounts
const& p2
201 template<
class ForwardIterator1,
class ForwardIterator2>
203 size_t p1_poolsize,
size_t p2_poolsize,
204 ForwardIterator1 p1_begin, ForwardIterator1 p1_end,
205 ForwardIterator2 p2_begin, ForwardIterator2 p2_end
208 if( p1_poolsize <= 1 || p2_poolsize <= 1 ) {
209 throw std::invalid_argument(
"Cannot run f_st_pool_kofler() with poolsizes <= 1" );
213 double p1_pi_sum = 0.0;
214 double p2_pi_sum = 0.0;
215 double pp_pi_sum = 0.0;
219 auto p1_it = p1_begin;
220 auto p2_it = p2_begin;
221 while( p1_it != p1_end && p2_it != p2_end ) {
229 std::isfinite( std::get<0>( pi_snps )) &&
230 std::isfinite( std::get<1>( pi_snps )) &&
231 std::isfinite( std::get<2>( pi_snps ))
234 assert( p1_it->a_count + p1_it->c_count + p1_it->g_count + p1_it->t_count > 0 );
235 assert( p2_it->a_count + p2_it->c_count + p2_it->g_count + p2_it->t_count > 0 );
238 p1_pi_sum += std::get<0>( pi_snps );
239 p2_pi_sum += std::get<1>( pi_snps );
240 pp_pi_sum += std::get<2>( pi_snps );
245 ( p1_it->a_count + p1_it->c_count + p1_it->g_count + p1_it->t_count <= 1 ) ||
246 ( p2_it->a_count + p2_it->c_count + p2_it->g_count + p2_it->t_count <= 1 )
254 if( p1_it != p1_end || p2_it != p2_end ) {
255 throw std::invalid_argument(
256 "In f_st_pool_kofler(): Provided ranges have different length."
261 assert( p1_poolsize > 1 && p2_poolsize > 1 );
262 size_t const pp_poolsize = std::min( p1_poolsize, p2_poolsize );
263 p1_pi_sum *=
static_cast<double>( p1_poolsize ) /
static_cast<double>( p1_poolsize - 1 );
264 p2_pi_sum *=
static_cast<double>( p2_poolsize ) /
static_cast<double>( p2_poolsize - 1 );
265 pp_pi_sum *=
static_cast<double>( pp_poolsize ) /
static_cast<double>( pp_poolsize - 1 );
268 double const pp_avg = ( p1_pi_sum + p2_pi_sum ) / 2.0;
269 return ( pp_pi_sum - pp_avg ) / pp_pi_sum;
272 #if __cplusplus >= 201402L
281 template<
class ForwardIterator>
283 std::vector<size_t>
const& poolsizes,
284 ForwardIterator begin, ForwardIterator end
286 return compute_pairwise_f_st(
288 [&](
size_t i,
size_t j,
auto p1_begin,
auto p1_end,
auto p2_begin,
auto p2_end ){
289 if( i >= poolsizes.size() || j >= poolsizes.size() ) {
290 throw std::runtime_error(
291 "In f_st_pool_kofler(): Provided ranges have different lengths that "
292 "are not identical to the number of poolsizes provided."
296 poolsizes[i], poolsizes[j],
297 p1_begin, p1_end, p2_begin, p2_end
303 #endif // __cplusplus >= 201402L
317 std::pair<SortedBaseCounts, SortedBaseCounts>
const& sample_counts
338 template<
class ForwardIterator1,
class ForwardIterator2>
340 ForwardIterator1 p1_begin, ForwardIterator1 p1_end,
341 ForwardIterator2 p2_begin, ForwardIterator2 p2_end
350 auto p1_it = p1_begin;
351 auto p2_it = p2_begin;
352 while( p1_it != p1_end && p2_it != p2_end ) {
357 sum_nk += nkdk.first;
358 sum_dk += nkdk.second;
364 if( p1_it != p1_end || p2_it != p2_end ) {
365 throw std::invalid_argument(
366 "In f_st_pool_karlsson(): Provided ranges have different length."
370 return sum_nk / sum_dk;
373 #if __cplusplus >= 201402L
382 template<
class ForwardIterator>
384 ForwardIterator begin, ForwardIterator end
386 return compute_pairwise_f_st(
388 [&](
size_t i,
size_t j,
auto p1_begin,
auto p1_end,
auto p2_begin,
auto p2_end ){
392 p1_begin, p1_end, p2_begin, p2_end
398 #endif // __cplusplus >= 201402L
411 size_t p1_poolsize,
size_t p2_poolsize,
412 BaseCounts
const& p1, BaseCounts
const& p2
432 template<
class ForwardIterator1,
class ForwardIterator2>
434 size_t p1_poolsize,
size_t p2_poolsize,
435 ForwardIterator1 p1_begin, ForwardIterator1 p1_end,
436 ForwardIterator2 p2_begin, ForwardIterator2 p2_end
439 if( p1_poolsize <= 1 || p2_poolsize <= 1 ) {
440 throw std::invalid_argument(
"Cannot run f_st_pool_unbiased() with poolsizes <= 1" );
444 double pi_w_sum = 0.0;
445 double pi_b_sum = 0.0;
446 double pi_t_sum = 0.0;
450 auto p1_it = p1_begin;
451 auto p2_it = p2_begin;
452 while( p1_it != p1_end && p2_it != p2_end ) {
461 std::isfinite( std::get<0>( pi_snp )) &&
462 std::isfinite( std::get<1>( pi_snp )) &&
463 std::isfinite( std::get<2>( pi_snp ))
466 assert( p1_it->a_count + p1_it->c_count + p1_it->g_count + p1_it->t_count > 0 );
467 assert( p2_it->a_count + p2_it->c_count + p2_it->g_count + p2_it->t_count > 0 );
470 pi_w_sum += std::get<0>( pi_snp );
471 pi_b_sum += std::get<1>( pi_snp );
472 pi_t_sum += std::get<2>( pi_snp );
477 ( p1_it->a_count + p1_it->c_count + p1_it->g_count + p1_it->t_count <= 1 ) ||
478 ( p2_it->a_count + p2_it->c_count + p2_it->g_count + p2_it->t_count <= 1 )
486 if( p1_it != p1_end || p2_it != p2_end ) {
487 throw std::invalid_argument(
488 "In f_st_pool_unbiased(): Provided ranges have different length."
493 double const fst_nei = 1.0 - ( pi_w_sum / pi_t_sum );
494 double const fst_hud = 1.0 - ( pi_w_sum / pi_b_sum );
495 return { fst_nei, fst_hud };
498 #if __cplusplus >= 201402L
510 template<
class ForwardIterator>
512 std::vector<size_t>
const& poolsizes,
513 ForwardIterator begin, ForwardIterator end
515 return compute_pairwise_f_st(
517 [&](
size_t i,
size_t j,
auto p1_begin,
auto p1_end,
auto p2_begin,
auto p2_end ){
518 if( i >= poolsizes.size() || j >= poolsizes.size() ) {
519 throw std::runtime_error(
520 "In f_st_pool_unbiased_nei(): Provided ranges have different lengths that "
521 "are not identical to the number of poolsizes provided."
525 poolsizes[i], poolsizes[j],
526 p1_begin, p1_end, p2_begin, p2_end
542 template<
class ForwardIterator>
543 utils::Matrix<double> f_st_pool_unbiased_hudson(
544 std::vector<size_t>
const& poolsizes,
545 ForwardIterator begin, ForwardIterator end
547 return compute_pairwise_f_st(
549 [&](
size_t i,
size_t j,
auto p1_begin,
auto p1_end,
auto p2_begin,
auto p2_end ){
550 if( i >= poolsizes.size() || j >= poolsizes.size() ) {
551 throw std::runtime_error(
552 "In f_st_pool_unbiased_hudson(): Provided ranges have different lengths that "
553 "are not identical to the number of poolsizes provided."
557 poolsizes[i], poolsizes[j],
558 p1_begin, p1_end, p2_begin, p2_end
564 #endif // __cplusplus >= 201402L
569 #endif // include guard