In [1]:
%matplotlib inline
%pylab inline
from __future__ import print_function
import numpy as np
import array
import matplotlib.pyplot as plt
#population size
N=1000
#nlist corresponds to a constant population size for 10N generations
#note the "dtype" argument. Without it, we'd be defaulting to int64,
#which is a 64-bit signed integer.
nlist=np.array([N]*(10*N),dtype=np.uint32)
#This is a 'view' of the array starting from the beginning:
nlist[0:]
Out[1]:
In [2]:
#Evolve for 10N generations,
#bottleneck to 0.25N for 100 generations,
#recover to N for 50 generations
nlist = np.concatenate(([N]*(10*N),[int(0.25*N)]*100,[N]*50)).astype(np.int32)
plt.plot(nlist[0:])
plt.ylim(0,1.5*N)
Out[2]:
Please note the last command, which changes the concatenated array from an array of 64 bit signed integers to 32 bit unsigned integers.
In [3]:
import math
N2=5*N
tgrowth=500
#G is the growth rate
G = math.exp( (math.log(N2)-math.log(N))/float(tgrowth) )
nlist = np.array([N]*(10*N+tgrowth),dtype=np.uint32)
#Now, modify the list according to expoential growth rate
for i in range(tgrowth):
nlist[10*N+i] = round( N*math.pow(G,i+1) )
##Now, we see that the population does grown from
##N=1,000 to N=5,000 during the last 500 generations
## We need the + 1 below to transform
## from the generation's index to the generation itself
plt.plot(range(10*N+1,10*N+501,1),nlist[10*N:])
Out[3]:
Why do things with NumPy arrays or Python's array.array? Lots of reasons: