1 /*
2 * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
3 *
4 * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
5 *
6 * This file is part of scrm.
7 *
8 * scrm is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "model.h"
23
24
Model()25 Model::Model() :
26 has_migration_(false),
27 has_recombination_(false) {
28
29 this->set_loci_number(1);
30 this->setLocusLength(1);
31 this->addChangeTime(0.0);
32 this->addChangePosition(0.0);
33
34 this->set_population_number(1);
35
36 this->setMutationRate(0.0);
37 this->setRecombinationRate(0.0);
38
39 this->window_length_seq_ = 0;
40 this->set_window_length_rec(500);
41
42 this->setSequenceScaling(ms);
43
44 this->resetTime();
45 this->resetSequencePosition();
46 }
47
48
Model(size_t sample_size)49 Model::Model(size_t sample_size) :
50 has_migration_(false),
51 has_recombination_(false) {
52
53 this->set_loci_number(1);
54 this->setLocusLength(1);
55 this->addChangeTime(0.0);
56 this->addChangePosition(0.0);
57
58 this->set_population_number(1);
59
60 this->setMutationRate(0.0);
61 this->setRecombinationRate(0.0);
62
63 this->window_length_seq_ = 0;
64 this->set_window_length_rec(500);
65
66 this->setSequenceScaling(ms);
67
68 this->addSampleSizes(0.0, std::vector<size_t>(1, sample_size));
69 this->setLocusLength(1000);
70 this->resetTime();
71 this->resetSequencePosition();
72 }
73
74
75 /**
76 * Function to add a new change time to the model.
77 *
78 * It preserves the relation between the times and the *param*_list_ containers.
79 * If the same time is added multiple times, it is just added once to the model,
80 * but this should not make a difference when using this function.
81 *
82 * @param time The time that is added
83 * @param scaled set to TRUE if the time is in units of 4N0 generations, and
84 * FALSE if it is in units of generations.
85 *
86 * @returns The position the time has now in the vector
87 */
addChangeTime(double time,const bool & scaled)88 size_t Model::addChangeTime(double time, const bool &scaled) {
89 if (scaled) time *= 4 * default_pop_size();
90
91 size_t position = 0;
92 if ( change_times_.size() == 0 ) {
93 change_times_ = std::vector<double>(1, time);
94 pop_sizes_list_.push_back(std::vector<double>());
95 growth_rates_list_.push_back(std::vector<double>());
96 mig_rates_list_.push_back(std::vector<double>());
97 total_mig_rates_list_.push_back(std::vector<double>());
98 single_mig_list_.push_back(std::vector<MigEvent>());
99 return position;
100 }
101
102 std::vector<double>::iterator ti;
103 for (ti = change_times_.begin(); ti != change_times_.end(); ++ti) {
104 if ( *ti == time ) return position;
105 if ( *ti > time ) break;
106 ++position;
107 }
108
109 change_times_.insert(ti, time);
110
111 // Add Null at the right position in all parameter vectors
112 pop_sizes_list_.insert(pop_sizes_list_.begin() + position, std::vector<double>());
113 growth_rates_list_.insert(growth_rates_list_.begin() + position, std::vector<double>());
114 mig_rates_list_.insert(mig_rates_list_.begin() + position, std::vector<double>());
115 total_mig_rates_list_.insert(total_mig_rates_list_.begin() + position, std::vector<double>());
116 single_mig_list_.insert(single_mig_list_.begin() + position, std::vector<MigEvent>());
117 return position;
118 }
119
120
121 /**
122 * Adds a new change position to the model.
123 *
124 * Change position are sequence positions where mutation or recombination rates
125 * change. This creates a new position, but does not add the new rates.
126 *
127 * @param position The sequence position add which a change is added
128 *
129 * @returns The index of the new rates in the recombination_rates_ and
130 * mutation_rates vectors.
131 */
addChangePosition(const double position)132 size_t Model::addChangePosition(const double position) {
133 if (position < 0 || position > loci_length()) {
134 std::stringstream ss;
135 ss << "Rate change position " << position << " is outside of the simulated sequence.";
136 throw std::invalid_argument(ss.str());
137 }
138
139 if ( change_position_.size() == 0 ) {
140 change_position_ = std::vector<double>(1, position);
141 recombination_rates_.push_back(-1);
142 mutation_rates_.push_back(-1);
143 return 0;
144 }
145
146 size_t idx = 0;
147 std::vector<double>::iterator ti;
148 for (ti = change_position_.begin(); ti != change_position_.end(); ++ti) {
149 if ( *ti == position ) return idx;
150 if ( *ti > position ) break;
151 ++idx;
152 }
153
154 change_position_.insert(ti, position);
155
156 // Add Null at the right position in all parameter vectors
157 recombination_rates_.insert(recombination_rates_.begin() + idx, -1);
158 mutation_rates_.insert(mutation_rates_.begin() + idx, -1);
159
160 return idx;
161 }
162
163
addSampleSizes(double time,const std::vector<size_t> & samples_sizes,const bool & scaled)164 void Model::addSampleSizes(double time, const std::vector<size_t> &samples_sizes, const bool &scaled) {
165 if (scaled) time *= 4 * default_pop_size();
166
167 for (size_t pop = 0; pop < samples_sizes.size(); ++pop) {
168 for (size_t i = 0; i < samples_sizes.at(pop); ++i) {
169 sample_populations_.push_back(pop);
170 sample_times_.push_back(time);
171 }
172 }
173 }
174
175
176 /**
177 * @brief This changes the size of all populations to the given values at a
178 * specific point in time.
179 *
180 * The sizes apply for with point on backwards in time.
181 *
182 * @param time The time at which the population changes their sizes.
183 * @param pop_sizes A vector of new population sizes. Can either be given as
184 * fraction of N0 or as an absolute value. See relative.
185 * @param time_scaled Set to true if the time is given in units of 4*N0
186 * generations, or to false if the time is given in units of generations.
187 * @param relative set to TRUE, if the population sizes are given relative to
188 * N0, or to FALSE if they are absolute values.
189 */
addPopulationSizes(double time,const std::vector<double> & pop_sizes,const bool & time_scaled,const bool & relative)190 void Model::addPopulationSizes(double time, const std::vector<double> &pop_sizes,
191 const bool &time_scaled, const bool &relative) {
192
193 if ( pop_sizes.size() != population_number() )
194 throw std::logic_error("Population size values do not meet the number of populations");
195
196 size_t position = addChangeTime(time, time_scaled);
197
198 pop_sizes_list_[position].clear();
199 for (double pop_size : pop_sizes) {
200 if (!std::isnan(pop_size)) {
201 // Scale to absolute values if necessary
202 if (relative) { pop_size *= this->default_pop_size(); }
203
204 // Save inverse double value
205 if (pop_size <= 0.0) throw std::invalid_argument("population size <= 0");
206 pop_size = 1.0 / (2 * pop_size);
207 }
208 pop_sizes_list_[position].push_back(pop_size);
209 }
210 }
211
212
213 /**
214 * @brief This changes the size of all populations to a given value at a
215 * specific point in time.
216 *
217 * The sizes apply for with point on backwards in time.
218 *
219 * @param time The time at which the population changes their sizes.
220 * @param pop_sizes The size to which we set all populations. Can either be given as
221 * fraction of N0 or as an absolute value. See relative.
222 * @param time_scaled Set to true if the time is given in units of 4*N0
223 * generations, or to false if the time is given in units of generations.
224 * @param relative set to TRUE, if the population sizes are given relative to
225 * N0, or to FALSE if they are absolute values.
226 */
addPopulationSizes(const double time,const double pop_size,const bool & time_scaled,const bool & relative)227 void Model::addPopulationSizes(const double time, const double pop_size,
228 const bool &time_scaled, const bool &relative) {
229 addPopulationSizes(time, std::vector<double>(population_number(), pop_size), time_scaled, relative);
230 }
231
232
233 /**
234 * @brief This changes the size of a single populations to a given value at a
235 * specific point in time.
236 *
237 * The sizes apply for with point on backwards in time.
238 * Requires Model.finalization() to be called after the model is set up.
239 *
240 * @param time The time at which the population change its size.
241 * @param pop The population which will change its size.
242 * @param population_size The size to which we set the population. Can either be given as
243 * fraction of N0 or as an absolute value. See relative.
244 * @param time_scaled Set to true if the time is given in units of 4*N0
245 * generations, or to false if the time is given in units of generations.
246 * @param relative set to TRUE, if the population sizes are given relative to
247 * N0, or to FALSE if they are absolute values.
248 */
addPopulationSize(const double time,const size_t pop,double population_size,const bool & time_scaled,const bool & relative)249 void Model::addPopulationSize(const double time, const size_t pop, double population_size,
250 const bool &time_scaled, const bool &relative) {
251 checkPopulation(pop);
252 size_t position = addChangeTime(time, time_scaled);
253 if (relative) population_size *= default_pop_size();
254
255 if (population_size <= 0.0) throw std::invalid_argument("population size <= 0");
256 if (pop_sizes_list_.at(position).empty()) addPopulationSizes(time, nan("value to replace"), time_scaled);
257 pop_sizes_list_.at(position).at(pop) = 1.0/(2*population_size);
258 }
259
260
261 /**
262 * @brief Set the population size growth rates at a certain time point.
263 *
264 * The population growth or shrinks exponentially from that time point on
265 * backwards in time.
266 * Requires Model.finalization() to be called after the model is set up.
267 *
268 * @param time The time at which to set the growth rates
269 * @param growth_rates A vector of growth rates for all populations
270 * @param time_scaled Set to true if the time is given in units of 4*N0
271 * generations, or to false if the time is given in units of generations.
272 */
addGrowthRates(const double time,const std::vector<double> & growth_rates,const bool & time_scaled,const bool & rate_scaled)273 void Model::addGrowthRates(const double time, const std::vector<double> &growth_rates,
274 const bool &time_scaled, const bool &rate_scaled) {
275 if ( growth_rates.size() != population_number() )
276 throw std::logic_error("Growth rates values do not meet the number of populations");
277 size_t position = addChangeTime(time, time_scaled);
278
279 growth_rates_list_[position].clear();
280 for (double rate : growth_rates) {
281 if (rate_scaled) rate *= scaling_factor();
282 growth_rates_list_[position].push_back(rate);
283 }
284 }
285
286
287 /**
288 * @brief Set the population size growth rates at a certain time point.
289 *
290 * The population growth or shrinks exponentially from that time point on
291 * backwards in time.
292 * Requires Model.finalization() to be called after the model is set up.
293 *
294 * @param time The time at which to set the growth rates
295 * @param growth_rates The growth rate for all populations
296 * @param time_scaled Set to true if the time is given in units of 4*N0
297 * generations, or to false if the time is given in units of generations.
298 */
addGrowthRates(const double time,const double growth_rate,const bool & time_scaled,const bool & rate_scaled)299 void Model::addGrowthRates(const double time, const double growth_rate,
300 const bool &time_scaled, const bool &rate_scaled) {
301 addGrowthRates(time, std::vector<double>(population_number(), growth_rate), time_scaled, rate_scaled);
302 }
303
304
305 /**
306 * @brief Set the population size growth rates of a population at a certain time point.
307 *
308 * The population growth or shrinks exponentially from that time point on
309 * backwards in time.
310 * Requires Model.finalization() to be called after the model is set up.
311 *
312 * @param time The time at which to set the growth rates
313 * @param population The population to which the growth rate applies.
314 * @param growth_rates The growth rate for the populations
315 * @param time_scaled Set to true if the time is given in units of 4*N0
316 * generations, or to false if the time is given in units of generations.
317 */
addGrowthRate(const double time,const size_t population,double growth_rate,const bool & time_scaled,const bool & rate_scaled)318 void Model::addGrowthRate(const double time, const size_t population,
319 double growth_rate, const bool &time_scaled, const bool &rate_scaled) {
320 checkPopulation(population);
321 size_t position = addChangeTime(time, time_scaled);
322 if (rate_scaled) growth_rate *= scaling_factor();
323 if (growth_rates_list_.at(position).empty()) addGrowthRates(time, nan("number to replace"), time_scaled);
324 growth_rates_list_.at(position).at(population) = growth_rate;
325 }
326
327
328 /**
329 * @brief Sets a migration rate form a specific population to another starting from a
330 * certain time point (going backwards in time);
331 *
332 * This requires model finalization, e.g. call model.finalize() after you set up
333 * the model completely.
334 *
335 * @param time The time at which the migration is set to the given value.
336 * It applies backwards in time until it is changed again.
337 * @param source The population from which the individuals migrate from when
338 * looking backwards in time. Is the sink population when looking forward.
339 * @param sink The population to which the individuals migrate to (also
340 * when looking backwards in time)
341 * @param mig_rate The backwards scaled migration rate M_ij = 4N0 * m_ij,
342 * where m_ij is the fraction for population i = source that migrates
343 * to population j = sink (again, when looking backwards in time).
344 * @param scaled_time Set to true if the time is given in units of 4*N0
345 * generations, or to false if the time is given in units of generations.
346 * @param scaled_rate Set to true if the rate is given as M = 4*N0*m and to
347 * false if it is given as m.
348 *
349 */
addMigrationRate(double time,size_t source,size_t sink,double mig_rate,const bool & scaled_time,const bool & scaled_rates)350 void Model::addMigrationRate(double time, size_t source, size_t sink, double mig_rate,
351 const bool &scaled_time, const bool &scaled_rates) {
352 checkPopulation(source);
353 checkPopulation(sink);
354 size_t position = addChangeTime(time, scaled_time);
355 if (scaled_rates) mig_rate *= scaling_factor();
356 if (mig_rates_list_.at(position).empty()) {
357 addSymmetricMigration(time, nan("value to replace"), scaled_time);
358 }
359 mig_rates_list_.at(position).at(getMigMatrixIndex(source, sink)) = mig_rate;
360 }
361
362
363 /**
364 * @brief Sets the migration matrix to the given values for the time following at
365 * certain time point (backwards in time).
366 *
367 * This requires model finalization, e.g. call model.finalize() after you set up
368 * the model completely.
369 *
370 * @param time The time at which the migration is set to the given values.
371 * The values apply backwards in time until they are changed again.
372 * @param mig_rates The (backwards) scaled migration matrix, given as concatenation of
373 * row vectors (M_00, M_01, ..., M_0n, M_10, ..., M_n1, ..., M_nn), where
374 * M_ij = 4N0 * m_ij and m_ij is the faction of population i that
375 * migrates to population j (viewed backwards in time; forwards the
376 * migration is from population j to i). The diagonal elements of the
377 * matrix are ignored and can be set to "x" for better readability.
378 * @param scaled_time Set to true if the time is given in units of 4*N0
379 * generations, or to false if the time is given in units of generations.
380 * @param scaled_rate Set to true if the rate is given as M = 4*N0*m and to
381 * false if it is given as m.
382 */
addMigrationRates(double time,const std::vector<double> & mig_rates,const bool & scaled_time,const bool & scaled_rates)383 void Model::addMigrationRates(double time, const std::vector<double> &mig_rates,
384 const bool &scaled_time, const bool &scaled_rates) {
385 double popnr = population_number();
386 double scaling = 1;
387 if (scaled_rates) scaling = scaling_factor();
388 if ( mig_rates.size() != population_number()*population_number() )
389 throw std::logic_error("Migration rates values do not meet the number of populations");
390
391 size_t position = addChangeTime(time, scaled_time);
392 mig_rates_list_[position].clear();
393 mig_rates_list_[position].reserve(popnr*popnr-popnr);
394 for (size_t i = 0; i < popnr; ++i) {
395 for (size_t j = 0; j < popnr; ++j) {
396 if (i == j) continue;
397 mig_rates_list_[position].push_back(mig_rates.at(i*popnr+j) * scaling);
398 }
399 }
400 }
401
402
403
404 /**
405 * @brief Adds symmetric migration to a model.
406 *
407 * Sets migration between all population to the given value starting at a
408 * certain time point going backwards in time. Unlike 'ms', this uses the actual
409 * value provided and does not divide it by #population-1.
410 *
411 * This requires model finalization, e.g. call model.finalize() after you set up
412 * the model completely.
413 *
414 * @param time The time at which the migration is set to the given value.
415 * It applies backwards in time until it is changed again.
416 * @param mig_rate The scaled migration rate M_ij = 4N0 * m_ij that is used
417 * between all populations i and j. m_ij is the fraction of population i
418 * that migrates to population j.
419 * @param time_scaled Set to true if the time is given in units of 4*N0
420 * generations, or to false if the time is given in units of generations.
421 * @param rate_scaled Set to true if the rate is given as M = 4*N0*m and to
422 * false if it is given as m.
423 */
addSymmetricMigration(const double time,const double mig_rate,const bool & time_scaled,const bool & rate_scaled)424 void Model::addSymmetricMigration(const double time, const double mig_rate,
425 const bool &time_scaled, const bool &rate_scaled) {
426 std::vector<double> mig_rates = std::vector<double>(population_number()*population_number(), mig_rate);
427 this->addMigrationRates(time, mig_rates, time_scaled, rate_scaled);
428 }
429
430
addSingleMigrationEvent(const double time,const size_t source_pop,const size_t sink_pop,const double fraction,const bool & time_scaled)431 void Model::addSingleMigrationEvent(const double time, const size_t source_pop,
432 const size_t sink_pop, const double fraction,
433 const bool &time_scaled) {
434
435 size_t position = addChangeTime(time, time_scaled);
436
437 if ( time < 0.0 ) throw std::invalid_argument("Single migration event: Negative time");
438 if ( source_pop >= population_number() ) throw std::invalid_argument("Single migration event: Unknown population");
439 if ( sink_pop >= population_number() ) throw std::invalid_argument("Single migration event: Unknown population");
440 if ( fraction < 0.0 || fraction > 1.0 ) throw std::invalid_argument("Single migration event: Fraction out of range");
441
442 if ( single_mig_list_.at(position).empty() ) {
443 single_mig_list_.at(position) = std::vector<MigEvent>(0);
444 }
445
446 MigEvent migEvent = {source_pop, sink_pop, fraction};
447 single_mig_list_.at(position).push_back(migEvent);
448
449 this->has_migration_ = true;
450 }
451
452
operator <<(std::ostream & os,Model & model)453 std::ostream& operator<<(std::ostream& os, Model& model) {
454 size_t n_pops = model.population_number();
455 os << "---- Model: ------------------------" << std::endl;
456 os << "Total Sample Size: " << model.sample_size() << std::endl;
457 os << "N0 is assumed to be " << model.default_pop_size() << std::endl;
458
459 model.resetSequencePosition();
460 for (size_t idx = 0; idx < model.countChangePositions(); ++idx) {
461 os << std::endl << "At Position " << model.getCurrentSequencePosition() << ":" << std::endl;
462 os << " Mutation Rate: " << model.mutation_rate() << std::endl;
463 os << " Recombination Rate: " << model.recombination_rate() << std::endl;
464 model.increaseSequencePosition();
465 }
466 model.resetSequencePosition();
467
468 model.resetTime();
469 for (size_t idx = 0; idx < model.countChangeTimes(); ++idx) {
470 os << std::endl << "At Time " << model.getCurrentTime() << ":" << std::endl;
471
472 os << " Population Sizes: ";
473 for (size_t pop = 0; pop < n_pops; ++pop)
474 os << std::setw(10) << std::right << model.population_size(pop, model.getCurrentTime());
475 os << std::endl;
476
477 os << " Growth Rates: ";
478 for (size_t pop = 0; pop < n_pops; ++pop)
479 os << std::setw(10) << std::right << model.growth_rate(pop);
480 os << std::endl;
481
482 os << " Migration Matrix: " << std::endl;
483 for (size_t i = 0; i < n_pops; ++i) {
484 for (size_t j = 0; j < n_pops; ++j) {
485 os << std::setw(10) << std::right << model.migration_rate(i, j);
486 }
487 os << std::endl;
488 }
489
490 for (MigEvent me : model.single_mig_events()) {
491 os << " "
492 << me.prob * 100 << "% of pop "
493 << me.source_pop + 1 << " move to pop "
494 << me.sink_pop + 1 << std::endl;
495 }
496
497 if (idx < model.countChangeTimes() - 1) model.increaseTime();
498 }
499 model.resetTime();
500 os << "------------------------------------" << std::endl;
501 return(os);
502 }
503
504
updateTotalMigRates(const size_t position)505 void Model::updateTotalMigRates(const size_t position) {
506 if ( total_mig_rates_list_.at(position).empty() ) {
507 total_mig_rates_list_.at(position) = std::vector<double>(population_number(), 0.0);
508 }
509
510 std::vector<double>* mig_rates = &(total_mig_rates_list_.at(position));
511
512 for (size_t i = 0; i < population_number(); ++i) {
513 for (size_t j = 0; j < population_number(); ++j) {
514 if (i == j) continue;
515 mig_rates->at(i) += mig_rates_list_.at(position).at( getMigMatrixIndex(i,j) );
516 }
517 if (mig_rates->at(i) > 0) has_migration_ = true;
518 }
519 }
520
521
finalize()522 void Model::finalize() {
523 fillVectorList(mig_rates_list_, default_mig_rate);
524 fillVectorList(growth_rates_list_, default_growth_rate);
525 calcPopSizes();
526
527 for (size_t j = 0; j < mig_rates_list_.size(); ++j) {
528 if (mig_rates_list_.at(j).empty()) continue;
529 updateTotalMigRates(j);
530 }
531
532 // Fill in missing recombination rates
533 assert( mutation_rates_.at(0) != -1 );
534 assert( recombination_rates_.at(0) != -1 );
535 for (size_t j = 1; j < change_position_.size(); ++j) {
536 if (mutation_rates_.at(j) == -1) {
537 mutation_rates_.at(j) = mutation_rates_.at(j-1);
538 }
539
540 if (recombination_rates_.at(j) == -1) {
541 recombination_rates_.at(j) = recombination_rates_.at(j-1);
542 }
543 }
544
545 resetTime();
546 resetSequencePosition();
547 check();
548 }
549
550
calcPopSizes()551 void Model::calcPopSizes() {
552 // Set initial population sizes
553 if (pop_sizes_list_.at(0).empty()) addPopulationSizes(0, default_pop_size());
554 else {
555 // Replace values not set by the user with the default size
556 for (size_t pop = 0; pop < population_number(); ++pop) {
557 if (std::isnan(pop_sizes_list_.at(0).at(pop)))
558 addPopulationSize(0, pop, default_pop_size());
559 }
560 }
561
562 size_t last_growth = -1;
563 double duration = -1;
564 for (size_t i = 1; i < change_times_.size(); ++i) {
565 if (! growth_rates_list_.at(i - 1).empty()) last_growth = i - 1;
566
567 // Make sure we always have a pop sizes vector
568 if (pop_sizes_list_.at(i).empty()) {
569 addPopulationSizes(change_times_.at(i), nan("value to replace"));
570 assert( ! pop_sizes_list_.at(i).empty() );
571 }
572
573 // Calculate the effective duration of a growth period if it ends here
574 duration = change_times_.at(i) - change_times_.at(i - 1);
575
576 // Calculate the population sizes:
577 for (size_t pop = 0; pop < population_number(); ++pop) {
578 // If the user explicitly gave a value => always use this value
579 if ( !std::isnan(pop_sizes_list_.at(i).at(pop)) ) continue;
580
581 assert(!std::isnan(pop_sizes_list_.at(i - 1).at(pop)));
582 // Otherwise use last value
583 pop_sizes_list_.at(i).at(pop) = pop_sizes_list_.at(i - 1).at(pop);
584
585 // ... and scale it if there was growth
586 if (last_growth != -1) {
587 pop_sizes_list_.at(i).at(pop) *=
588 std::exp((growth_rates_list_.at(last_growth).at(pop)) * duration);
589 }
590 }
591 }
592 }
593
594
check()595 void Model::check() {
596 // Sufficient sample size?
597 if (sample_size() < 2) throw std::invalid_argument("Sample size needs be to at least 2");
598
599 // Structure without migration?
600 if (population_number() > 1 && !has_migration())
601 throw std::invalid_argument("Model has multiple populations but no migration. Coalescence impossible");
602 }
603
604
fillVectorList(std::vector<std::vector<double>> & vector_list,const double default_value)605 void Model::fillVectorList(std::vector<std::vector<double> > &vector_list, const double default_value) {
606 std::vector<double>* last = NULL;
607 std::vector<double>* current = NULL;
608 for (size_t j = 0; j < vector_list.size(); ++j) {
609 current = &(vector_list.at(j));
610 if (current->empty()) continue;
611
612 for (size_t i = 0; i < current->size(); ++i) {
613 if ( !std::isnan(current->at(i)) ) continue;
614
615 if (last == NULL) current->at(i) = default_value;
616 else current->at(i) = last->at(i);
617 }
618 last = current;
619 }
620 }
621
622
addPopulation()623 void Model::addPopulation() {
624 // Create the new population
625 size_t new_pop = population_number();
626 this->set_population_number(new_pop+1);
627
628 // Change Vectors
629 addPopToVectorList(growth_rates_list_);
630 addPopToVectorList(pop_sizes_list_);
631
632 // Change Matrices
633 addPopToMatrixList(mig_rates_list_, new_pop);
634 }
635
636
addPopToMatrixList(std::vector<std::vector<double>> & vector_list,size_t new_pop,double default_value)637 void Model::addPopToMatrixList(std::vector<std::vector<double> > &vector_list, size_t new_pop, double default_value) {
638 for (auto it = vector_list.begin(); it!= vector_list.end(); ++it) {
639 if (it->empty()) continue;
640 for (size_t i = 0; i < new_pop; ++i) {
641 it->insert(it->begin() + getMigMatrixIndex(i, new_pop), default_value);
642 }
643 for (size_t i = 0; i < new_pop; ++i) {
644 it->insert(it->begin() + getMigMatrixIndex(new_pop, i), default_value);
645 }
646 }
647 }
648
649
addPopToVectorList(std::vector<std::vector<double>> & vector_list)650 void Model::addPopToVectorList(std::vector<std::vector<double> > &vector_list) {
651 for (auto it = vector_list.begin(); it!= vector_list.end(); ++it) {
652 if (it->empty()) continue;
653 it->push_back(nan("value to replace"));
654 }
655 }
656
657
658 /**
659 * @brief Sets the recombination rate
660 *
661 * @param rate The recombination rate per sequence length per time unit.
662 * The sequence length can be either per locus or per base pair and the time
663 * can be given in units of 4N0 generations ("scaled") or per generation.
664 *
665 * @param loci_length The length of every loci.
666 * @param per_locus Set to TRUE, if the rate is given per_locus, and to FALSE
667 * if the rate is per base pair.
668 * @param scaled Set to TRUE is the rate is scaled with 4N0, or to FALSE if
669 * it isn't
670 */
setRecombinationRate(double rate,const bool & per_locus,const bool & scaled,const double seq_position)671 void Model::setRecombinationRate(double rate,
672 const bool &per_locus,
673 const bool &scaled,
674 const double seq_position) {
675
676 if (rate < 0.0) {
677 throw std::invalid_argument("Recombination rate must be non-negative");
678 }
679
680 if (scaled) rate /= 4.0 * default_pop_size();
681 if (per_locus) {
682 if (loci_length() <= 1) {
683 throw std::invalid_argument("Locus length must be at least two");
684 }
685 rate /= loci_length()-1;
686 }
687
688 if (rate > 0.0) has_recombination_ = true;
689 recombination_rates_[addChangePosition(seq_position)] = rate;
690 }
691
692
693 /**
694 * @brief Sets the mutation rate
695 *
696 * @param rate The mutation rate per locus, either scaled as theta=4N0*u or
697 * unscaled as u.
698 * @param per_locus TRUE if the rate is per locus, FALSE if per base.
699 * @param scaled Set this to TRUE if you give the mutation rate in scaled
700 * units (e.g. as theta rather than as u).
701 */
setMutationRate(double rate,const bool & per_locus,const bool & scaled,const double seq_position)702 void Model::setMutationRate(double rate, const bool &per_locus, const bool &scaled,
703 const double seq_position) {
704 if (scaled) rate /= 4.0 * default_pop_size();
705
706 size_t idx = addChangePosition(seq_position);
707 if (per_locus) {
708 mutation_rates_.at(idx) = rate / loci_length();
709 } else {
710 mutation_rates_.at(idx) = rate;
711 }
712 }
713
714