/
Overdom.py
executable file
·194 lines (184 loc) · 6.37 KB
/
Overdom.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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#!/usr/bin/env python
#script used in 'Roux &al, Molecular Biology and Evolution (2012)'
import simuOpt, types, os, sys, time
simuOpt.setOptions(alleleType='long')
import simuPOP as sim
from simuPOP import *
from simuPOP.utils import *
from simuPOP.sampling import drawRandomSample
try:
from simuPOP.plotter import VarPlotter
except:
useRPy=False
else:
useRPy=True
options = [
{
'name':'NA',
'default':5000,
'label':'Ancestral Population Size',
'type':[int, long],
'validator':simuOpt.valueGT(0),
'description':'Ancestral population size'
},
{
'name':'N1',
'default':1000,
'label':'Daugther 1 Population Size',
'type':[int, long],
'validator':simuOpt.valueGT(0),
'description':'Daughter 1 population size'
},
{
'name':'N2',
'default':1000,
'label':'Daugther 2 Population Size',
'type':[int, long],
'validator':simuOpt.valueGT(0),
'description':'Daughter 2 population size'
},
{
'name':'Tbeforesplit',
'default':1000,
'label':'Number of Generations to simulate before split',
'type':[int, long],
'validator':simuOpt.valueGT(0),
'description':'Number of Generations to simulate before split'
},
{
'name':'Taftersplit',
'default':200,
'type':[int, long],
'label':'Number of Generations to simulate after the split',
'description':'Number of Generations to simulate after the split',
'validator':simuOpt.valueGT(0)
},
{
'name':'r2loci',
'default':0.01,
'label':'Recombination Rate between selected and neutral loci',
'type':[float],
'description':'Recombination rate',
'validator':simuOpt.valueBetween(0., 1.),
},
{
'name':'numLoci',
'default':2,
'label':'Number of loci',
'type':[int],
'description':'Number of loci',
'validator':simuOpt.valueGT(0),
},
{
'name':'K_sel',
'default':10,
'label':'Number of allelic states at selected locus',
'type':[int, long],
'validator':simuOpt.valueGT(0),
'description':'Number of allelic states at selected locus'
},
{
'name':'Mu_sel',
'default':0.000001,
'label':'Mutation rate at selected locus',
'type':[float],
'description':'Mutation rate at selected locus',
'validator':simuOpt.valueBetween(0., 1.),
},
{
'name':'S_sel',
'default':0.1,
'label':'Selection coefficient against homozygotes at selected locus',
'type':[float],
'description':'Selection coefficient against homozygotes at selected locus',
'validator':simuOpt.valueBetween(0., 1.),
},
{
'name':'L_neut',
'default':1000,
'label':'Number of biallelic positions in the neutral locus',
'type':[int, long],
'validator':simuOpt.valueGT(0),
'description':'Number of biallelic positions in the neutral locus'
},
{
'name':'Mu_neut',
'default':0.000001,
'label':'Mutation rate at each site of neutral locus',
'type':[float],
'description':'Mutation rate at each site of neutral locus',
'validator':simuOpt.valueBetween(0., 1.),
},
{
'name':'Nsample1',
'default':50,
'label':'Number of individuals to sample from population 1',
'type':[int, long],
'validator':simuOpt.valueGT(0),
'description':'Number of individuals to sample from population 1'
},
{
'name':'Nsample2',
'default':50,
'label':'Number of individuals to sample from population 2',
'type':[int, long],
'validator':simuOpt.valueGT(0),
'description':'Number of individuals to sample from population 2'
}
]
def simulate(NA, N1, N2, Tbeforesplit, Taftersplit, r2loci, numLoci, K_sel, Mu_sel, S_sel, L_neut, Mu_neut, Nsample1, Nsample2):
pop = Population(size=NA, ploidy=2, loci=[L_neut+1], infoFields='fitness')
def getfitness(geno):
# returns fitness of genotype geno at the overdominant locus with selection coeff S_sel
# geno is (A1 A2)
if geno[0] == geno[1] :
return 1 - S_sel # homozygote
else:
return 1 # heterozygote
if useRPy:
plotter=VarPlotter('alleleFreq[0][0],alleleFreq[0][1],alleleFreq[0][2],alleleFreq[0][3],alleleFreq[0][4]', ylim=[0,1], ylab='allele frequency', update=Tbeforesplit+Taftersplit-1, saveAs='slocus.png')
else:
plotter=NoneOp()
g = pop.evolve(
initOps = [
InitSex(),
#initially put 5 alleles at the selected locus with equal frequencies
InitGenotype(loci=0, freq=[.1] * 10)
# InitGenotype(loci=0, freq=[0.01, 0.1, 0.4, 0.2, 0.29])
],
preOps = [
#Resize the ancestral population at the time immediatly before the split
sim.ResizeSubPops([0], sizes=[N1+N2], at=Tbeforesplit-1),
# split ancestral population in 3 subpopulations only works if NA>N1+N2
sim.SplitSubPops(subPops=0, sizes=[N1, N2], at=Tbeforesplit),
# apply overdominant selection by invoking function getfitness
PySelector(loci=0, func=getfitness),
],
matingScheme = RandomMating(ops= [
#apply recombination between the selected locus and the neutral locus at rate r2loci
Recombinator(rates=r2loci, loci=0),
]),
postOps = [
# apply mutation to the selected locus according to K allele model
KAlleleMutator(k=K_sel, rates=[Mu_sel], loci=[0]),
# apply mutation to the neutral sequence
SNPMutator(u=Mu_neut,v=0,loci=range(1,L_neut)),
#Computes the frequency of each allele at selected locus at the last generation
Stat(alleleFreq=0,step=1),
#output to the screen the frequency of the 4 first alleles at the selected locus
PyEval(r'"%.0f\t %.3f\t %.3f\t %.3f\t %.3f\t %.3f\n" % (gen, alleleFreq[0][0], alleleFreq[0][1], alleleFreq[0][2], alleleFreq[0][3], alleleFreq[0][4])',step=100),
plotter,
],
# sets the last generation = Tbeforesplit+Taftersplit
gen = Tbeforesplit + Taftersplit
)
#draw two random samples from species 1 and 2 with size Nsample1 and Nsample2
sample = drawRandomSample(pop, sizes=[Nsample1,Nsample2])
#write to file the content of the two random samples
sim.utils.saveCSV(sample, filename='output.txt')
return g
if __name__ == '__main__':
pars = simuOpt.Params(options, doc ='This script simulates a speciation with variation at a selected locus under overdominant selection',details = '__doc__')
if not pars.getParam():
sys.exit(0)
simulate(pars.NA, pars.N1, pars.N2, pars.Tbeforesplit, pars.Taftersplit, pars.r2loci, pars.numLoci, pars.K_sel, pars.Mu_sel,pars.S_sel, pars.L_neut, pars.Mu_neut, pars.Nsample1, pars.Nsample2)