1 #ifndef GENESIS_POPULATION_FUNCTION_FST_POOL_PROCESSOR_H_
2 #define GENESIS_POPULATION_FUNCTION_FST_POOL_PROCESSOR_H_
57 namespace population {
75 using PiVectorTuple = std::tuple<std::vector<double>, std::vector<double>, std::vector<double>>;
89 std::shared_ptr<utils::ThreadPool>
thread_pool =
nullptr,
126 thread_pool_ = value;
132 return threading_threshold_;
146 threading_threshold_ = value;
154 size_t index_p1,
size_t index_p2,
155 std::unique_ptr<BaseFstPoolCalculator> calculator
157 assert( sample_pairs_.size() == calculators_.size() );
158 assert( sample_pairs_.size() == results_.size() );
159 sample_pairs_.push_back({ index_p1, index_p2 });
160 calculators_.push_back( std::move( calculator ));
161 results_.push_back( std::numeric_limits<double>::quiet_NaN() );
174 assert( calculators_.size() == sample_pairs_.size() );
175 assert( calculators_.size() == results_.size() );
176 return calculators_.size();
181 assert( calculators_.size() == results_.size() );
182 for(
auto& calc : calculators_ ) {
186 filter_stats_.
clear();
188 results_.begin(), results_.end(),
189 std::numeric_limits<double>::quiet_NaN()
194 auto const res_sz = results_.size();
196 assert( std::get<0>( results_pi_ ).
size() == 0 || std::get<0>( results_pi_ ).
size() == res_sz );
197 assert( std::get<1>( results_pi_ ).
size() == 0 || std::get<1>( results_pi_ ).
size() == res_sz );
198 assert( std::get<2>( results_pi_ ).
size() == 0 || std::get<2>( results_pi_ ).
size() == res_sz );
200 std::get<0>( results_pi_ ).begin(), std::get<0>( results_pi_ ).end(),
201 std::numeric_limits<double>::quiet_NaN()
204 std::get<1>( results_pi_ ).begin(), std::get<1>( results_pi_ ).end(),
205 std::numeric_limits<double>::quiet_NaN()
208 std::get<2>( results_pi_ ).begin(), std::get<2>( results_pi_ ).end(),
209 std::numeric_limits<double>::quiet_NaN()
216 assert( sample_pairs_.size() == calculators_.size() );
225 auto process_ = [&](
size_t index ) {
226 auto const& indices = sample_pairs_[index];
228 indices.first >= variant.
samples.size() ||
229 indices.second >= variant.
samples.size()
231 throw std::runtime_error(
232 "Invalid sample indices for computing FST Pool: Variant contains " +
235 " have been requested."
238 calculators_[index]->process(
239 variant.
samples[indices.first],
240 variant.
samples[indices.second]
245 if( thread_pool_ && calculators_.size() >= threading_threshold_ ) {
247 0, sample_pairs_.size(), process_, thread_pool_
250 for(
size_t i = 0; i < sample_pairs_.size(); ++i ) {
268 std::shared_ptr<GenomeLocusSet> provided_loci
270 assert( results_.size() == calculators_.size() );
271 for(
size_t i = 0; i < results_.size(); ++i ) {
278 auto const* raw_calc = calculators_[i].get();
280 if( unbiased_calc ) {
281 results_[i] = unbiased_calc->get_result( window, provided_loci, filter_stats_ );
283 results_[i] = raw_calc->get_result();
296 assert( results_.size() == calculators_.size() );
297 for(
size_t i = 0; i < results_.size(); ++i ) {
300 results_[i] = calculators_[i]->get_result();
319 std::shared_ptr<GenomeLocusSet> provided_loci
321 allocate_pi_result_vectors_();
324 for(
size_t i = 0; i < calculators_.size(); ++i ) {
325 auto const& raw_calc = calculators_[i];
327 if( ! unbiased_calc ) {
328 throw std::domain_error(
329 "Can only call FstPoolProcessor::get_pi_vectors() "
330 "for calculators of type FstPoolCalculatorUnbiased."
337 auto const pis = unbiased_calc->get_pi_values( window, provided_loci, filter_stats_ );
338 std::get<0>(results_pi_)[i] = pis.pi_within;
339 std::get<1>(results_pi_)[i] = pis.pi_between;
340 std::get<2>(results_pi_)[i] = pis.pi_total;
355 allocate_pi_result_vectors_();
356 for(
size_t i = 0; i < calculators_.size(); ++i ) {
357 auto const& raw_calc = calculators_[i];
359 if( ! unbiased_calc ) {
360 throw std::domain_error(
361 "Can only call FstPoolProcessor::get_pi_vectors() "
362 "for calculators of type FstPoolCalculatorUnbiased."
365 auto const pis = unbiased_calc->get_pi_values();
366 std::get<0>(results_pi_)[i] = pis.pi_within;
367 std::get<1>(results_pi_)[i] = pis.pi_between;
368 std::get<2>(results_pi_)[i] = pis.pi_total;
383 return filter_stats_;
388 return sample_pairs_;
391 std::vector<std::unique_ptr<BaseFstPoolCalculator>>
const&
calculators()
const
402 void allocate_pi_result_vectors_()
const
406 auto const res_sz = calculators_.size();
407 assert( std::get<0>( results_pi_ ).
size() == 0 || std::get<0>( results_pi_ ).
size() == res_sz );
408 assert( std::get<1>( results_pi_ ).
size() == 0 || std::get<1>( results_pi_ ).
size() == res_sz );
409 assert( std::get<2>( results_pi_ ).
size() == 0 || std::get<2>( results_pi_ ).
size() == res_sz );
410 std::get<0>( results_pi_ ).resize( res_sz );
411 std::get<1>( results_pi_ ).resize( res_sz );
412 std::get<2>( results_pi_ ).resize( res_sz );
423 std::vector<std::pair<size_t, size_t>> sample_pairs_;
424 std::vector<std::unique_ptr<BaseFstPoolCalculator>> calculators_;
432 mutable std::vector<double> results_;
437 std::shared_ptr<utils::ThreadPool> thread_pool_;
438 size_t threading_threshold_ = 0;
453 template<
class Calculator,
typename... Args>
455 std::vector<size_t>
const& pool_sizes,
459 for(
size_t i = 0; i < pool_sizes.size(); ++i ) {
460 for(
size_t j = i + 1; j < pool_sizes.size(); ++j ) {
463 ::genesis::utils::make_unique<Calculator>(
483 template<
class Calculator,
typename... Args>
485 std::vector<std::pair<size_t, size_t>>
const& sample_pairs,
486 std::vector<size_t>
const& pool_sizes,
490 for(
auto const& p : sample_pairs ) {
491 if( p.first >= pool_sizes.size() || p.second >= pool_sizes.size() ) {
492 throw std::invalid_argument(
493 "Invalid sample indices for computing FST Pool Kofler: " +
495 " pool sizes provided, but asked to use indices " +
501 ::genesis::utils::make_unique<Calculator>(
503 pool_sizes[p.second],
520 template<
class Calculator,
typename... Args>
523 std::vector<size_t>
const& pool_sizes,
527 for(
size_t i = 0; i < pool_sizes.size(); ++i ) {
530 ::genesis::utils::make_unique<Calculator>(
549 template<
class Calculator,
typename... Args>
551 size_t index_1,
size_t index_2,
552 std::vector<size_t>
const& pool_sizes,
558 ::genesis::utils::make_unique<Calculator>(
580 std::vector<std::string>
const& sample_names
583 if( sample_names.empty() ) {
588 std::vector<std::pair<std::string, std::string>> result;
589 result.reserve( processor.
size() );
593 for(
auto const& sample_pair : processor.
sample_pairs() ) {
594 if( sample_pair.first >= sample_names.size() || sample_pair.second >= sample_names.size() ) {
595 throw std::invalid_argument(
596 "In fst_pool_processor_sample_names(): sample names at indices " +
598 " requested, but sample names with " +
std::to_string( sample_names.size() ) +
602 result.push_back( std::make_pair(
603 sample_names[ sample_pair.first ], sample_names[ sample_pair.second ]
612 #endif // include guard