Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
| Download

COMPLEX 425 group work

Views: 25
Kernel: Python 3 (Ubuntu Linux)

Lets start playing with randomness

Genetic Drift is a name for the effects of random sampling on the frequency of alleles in replicating organisms.

Because populations are finite, sampling effects occur from generation to generation even in the absence of selection, and will cause mutations to sweep through a population over time.

We'll use the random library to generate random numbers and sample from a list.

import random

You can view the random library reference here: https://docs.python.org/3/library/random.html

My general philosophy on coding is that it is never a bad idea to google something!

#We'll start just considering two possible genotypes, a 0 and a 1 genotypes = [0,1] #Lets also use a variable for population size so we can easily #manipulate this value later without having to change #magic numbers around all over the place pop_size = 10

We'll use the choices function from the random library to sample (with replacement) from a collection. In this case, we're sampling from the possible genotypes to fill up a population of pop_size individuals.

Important! This is a feature of the python3 random library. If you're using python2 we'll have to get a python3 instance running now.

population = random.choices(genotypes, k=pop_size) print(population)
[1, 0, 1, 1, 0, 0, 0, 0, 0, 1]

Now that we have a population, and know how to sample from a collection, we can simulate a generation by filling up the next generation with a random sampling of the original population.

next_generation = random.choices(population, k=pop_size) print(next_generation)
[1, 1, 1, 0, 1, 0, 0, 0, 1, 1]

Let's do that one more time...

even_next_generation = random.choices(next_generation, k=pop_size) even_next_generation
[0, 1, 1, 0, 0, 1, 1, 1, 1, 1]

Let's write a little function that returns the frequency of 1s in a population

def freq_ones(population): count = 0 for individual in population: if individual == 1: count += 1 return count/len(population) #Of course we could do this a little bit more terse #by taking advantage of our genotype choices! def freq_ones(population): return(sum(population)/len(population))
print(freq_ones(population), freq_ones(next_generation), freq_ones(even_next_generation))
0.5 0.3 0.2

Now let's plot a simple figure showing the frequency of 1s over these couple of generations

We'll use the matplotlib library, which mimics the way Matlab (hence the name) plots figures.

For a brief tutorial on plotting with matplotlib see this link: https://matplotlib.org/tutorials/introductory/pyplot.html#sphx-glr-tutorials-introductory-pyplot-py

from matplotlib import pyplot pyplot.plot([freq_ones(population), freq_ones(next_generation), freq_ones(even_next_generation)]) pyplot.ylim(-0.1, 1.1) pyplot.xlabel("Generation") pyplot.ylabel("Freq of 1s") pyplot.show()
Image in a Jupyter notebook

We can start with a perfect 50/50 mix of genotypes by being explicit about the initial population.

We can also plot multiple lines in the same figure by calling plot() multiple times before calling show()!

population = [0]*int(pop_size/2) + [1]*int(pop_size/2) next_generation = random.choices(population, k=pop_size) even_next_generation = random.choices(next_generation, k=pop_size) #We could build up a list by appending to an #empty list... first_sim_freqs = [] first_sim_freqs.append(freq_ones(population)) first_sim_freqs.append(freq_ones(next_generation)) first_sim_freqs.append(freq_ones(even_next_generation)) #plot the first simulation pyplot.plot(first_sim_freqs) #Now simulate another few generations.... population = [0]*int(pop_size/2) + [1]*int(pop_size/2) next_generation = random.choices(population, k=pop_size) even_next_generation = random.choices(next_generation, k=pop_size) #and plot them, this time making the list all at once... pyplot.plot([freq_ones(population), freq_ones(next_generation), freq_ones(even_next_generation)]) pyplot.ylim(-0.1, 1.1) pyplot.xlabel("Generation") pyplot.ylabel("Freq of 1s") pyplot.show()
Image in a Jupyter notebook

1. Now in your groups, simulate many (100) generations, and many replicates and plot the dynamics like we did above

Obviously you're not going to want to keep creating variables for each new population... So, you'll want to loop through generations, keeping track of the frequency of ones over time.

num_generations = 100

2. Now plot many replicates on the same plot!

Insert a Markdown cell and describe what you notice about the populations.

num_generations = 100 num_replicates = 100

3. If you're breezing through these questions, try visualizing the distribution of generation time until populations fix a genotype (when the population is all 0s or all 1s).

Then, play with the population size to see how the distribution changes!

Insert a Markdown cell and describe what you notice about how the distribution changes.

4. WHOA! You're really flying through this...

If you're here, try figuring out a way to add a fitness value to the "1" genotype that increases their likelihood of being sampled into the next generation (hint: look at the documentation for random.choices).

See how starting with just one or a few of "1" genotypes affects their chances at fixing in the population. How does the value for fitness change the probability of fixation?

5. Now you're just showing off. If you got all that done, see if you can add mutations between genotypes

( 010 \rightarrow 1 and 101 \rightarrow 0 ) With some small probability, for example.

How does mutation change the dynamics of fixation?