Hi all,
I would like to try a very simple nonWF simulation using a highly skewed (heavy tailed) distribution
for the number of (potential) offspring ; when initialising I would like to specify a particular heavy-tailed offspring distribution, where there can be large families, but the population size is kept constant, so that after each round of producing offspring the total pool of offspring, which with high probability is larger than the population size (number of parents) in any given generation is cut down to match the number of parents.
my skript is below, I just wanted to check with you if you would see anything strange,
and in case you would find this useful - in particular the reproduction step in the skript below is the critical part
thanks in advance for any input
best regards
bjarki
// try a simple sim
// possibly useful functions
// function (float)pow(float x, float y)
// { return x^y;}
// probability of k juveniles, this is the probability mass function I use for producing
// number of offspring
// return( (pow( 1./k, a) - pow( 1./(k+1.), a))/( pow( .5, a) - pow( 1./(cutoff + 1.), a) ) );
// function (float)pxi( float a, float x, float m)
// {
// // take x from 2 to m
// return (pow(1.0/x, a) - pow( 1.0/(x + 1.0), a))/( pow(0.5, a) - pow( 1.0/(m+1) , a));
// }
// OK, here begins the real code
initialize() {
// set non-Wright Fisher evolution
initializeSLiMModelType("nonWF");
defineConstant("N", 10000 );
defineConstant("K", 2*N);
//define population size - or number of parents
// in each generation
defineConstant("POPSIZE_", 2*N);
// set cutoff for numbers of juveniles -
// maximum number of (potential) offspring per family
defineConstant("CUTOFF_", 2*100*N);
// set alpha parameter for the offspring distribution
defineConstant("ALPHA_", 1.25);
// set overall mutation rate
initializeMutationRate(5.0e-7);
// m1 mutaton type negative
// 0.1: dominance coefficient 0.1
// g: selection coefficient random Gamma
// -0.03: mean of gamma
// 0.2: shape parameter
initializeMutationType("m1", 0.1, "g", -0.1, 0.2);
// initializeMutationType("m1", 0.5, "f", 0.0);
// m2 mutation type neutral
initializeMutationType("m2", 0.5, "f", 0.0);
// g1 genomic element; use m2 all muts
initializeGenomicElementType("g1", m2, 1.0);
// initializeGenomicElementType("g1", c(m1,m2), c(1, 1));
// uniform chrom of length 100 kb
// see chromosomesize.txt
initializeGenomicElement(g1, 0, 99999);
// uniform recombination along chrom
initializeRecombinationRate(1e-8);
// here I construct the offspring distribution, or
// the CDF (cumulative mass function) for sampling
// construct the probabilities for sampling juveniles
cdf = (1.0/(2.0:(CUTOFF_)))^ALPHA_ ;
cdf = cdf - ( (1.0/(3.0:(CUTOFF_ + 1.0)))^ALPHA_ );
cdf = cdf / sum(cdf);
cdf = c(0.0, 0.0, cdf);
// construct the cdf for sampling juveniles
for( i in 3:(CUTOFF_))
{ cdf[i] = cdf[i] + cdf[i-1]; }
// store the cdf - this CDF should be used in
// every generation for sampling number of offspring
defineConstant("CDF_", cdf);
// print(CDF_);
}
// this is the critical part - here I wanted to ask if this guarantees that
// I sample number of offspring from the CDF defined in the
// initialisation step
reproduction() {
parents = sample(p1.individuals, p1.individualCount);
for ( i in seq( 0, p1.individualCount -2, by=2))
{ parent1 = parents[i]; parent2 = parents[i+1];
// sample a random uniform and check where it lands in the CDF
u = runif(1); k = 2;
while( u > CDF_[k]){
// assert( CDF_[k] > 0)
// assert( CDF_[k] <= 1)
k = k + 1; }
// assert(k > 1);
for( j in seqLen(k)){
p1.addCrossed(parent1, parent2); }
}
// disable for the generation
self.active = 0;
}
// the rest I suppose is standard SLIM
1 early()
{
sim.addSubpop("p1", POPSIZE_);
}
early()
{
p1.fitnessScaling = K/p1.individualCount;
}
// run to given generation
500 late() {
// output a random sample of sequences
p1.outputMSSample(136);
}
// end