-
Notifications
You must be signed in to change notification settings - Fork 0
/
cnv_simulation_initial_beneficial.py
95 lines (75 loc) · 2.82 KB
/
cnv_simulation_initial_beneficial.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import numpy as np
def get_params(parameters):
if isinstance(parameters, np.ndarray):
s_cnv, m_cnv, p_0 = np.power(10,parameters)
if not isinstance(parameters, np.ndarray):
s_cnv = np.power(10,parameters.sc)
m_cnv = np.power(10,parameters.mc)
p_0 = np.power(10, parameters.p0)
return s_cnv, m_cnv, p_0
## Wright Fisher stochastic discrete time model ##
## Modified to include p_0 - proportion of unreported CNVs at gen 0 ##
def simpleWF(N, generation, s_cnv, m_cnv, p_0, seed=None):
""" CNV evolution simulator
Simulates CNV and SNV evolution for x generations
Returns proportion of the population with a CNV for specific generations
Parameters
-------------------
N : int
population size
s_snv : float
fitness benefit of SNVs
m_snv : float
probability mutation to SNV
generation : np.array, 1d
with generations to output
seed : int
s_cnv : float
fitness benefit of CNVs
m_cnv : float
probability mutation to CNV
p_0: float
fraction of population with GAP1 CNV before beginning of experiment
"""
# SNV parameters as constants
s_snv = 1e-3
m_snv = 1e-5
if seed is not None:
np.random.seed(seed=seed)
else:
np.random.seed()
assert N > 0
N = np.uint64(N)
# Order is: wt, cnv+, cnv-, snv
w = np.array([1, 1 + s_cnv, 1 + s_cnv, 1 + s_snv], dtype='float64')
S = np.diag(w)
# make transition rate array
M = np.array([[1 - m_cnv - m_snv, 0, 0, 0],
[m_cnv, 1, 0, 0],
[0, 0, 1, 0],
[m_snv, 0, 0, 1]], dtype='float64')
assert np.allclose(M.sum(axis=0), 1)
# mutation and selection
E = M @ S
# rows are genotypes, p has proportions after initial (unreported) growth
n = np.zeros(4)
n[2] = N*p_0 # cnv-
n[0] = N*(1-p_0) # wt
# follow proportion of the population with CNV
# here rows will be generation, columns (there is only one) is replicate population
p_cnv = []
# run simulation to generation 116
for t in range(int(generation.max()+1)):
p = n/N # counts to frequencies
p_cnv.append(p[1]) # frequency of reported CNVs
p = E @ p.reshape((4, 1)) # natural selection + mutation
p /= p.sum() # rescale proportions
n = np.random.multinomial(N, np.ndarray.flatten(p)) # random genetic drift
return np.transpose(p_cnv)[generation.astype(int)]
def CNVsimulator_simpleWF(reps, N, generation, parameters, seed=None):
s_cnv, m_cnv, p_0 = get_params(parameters)
evo_reps = []
for i in range(reps):
out=simpleWF(N, generation, s_cnv, m_cnv, p_0, seed=seed)
evo_reps.append(out)
return np.array(evo_reps)