### TIPS ###
# We first load all the libraries we will need for this practical.
# Make sure you have those installed
# If not then please visit https://www2.unil.ch/popgen/teaching/SISG22/
library(hierfstat)
library(gaston)
library(SNPRelate)
library(JGTeach)
JGTeach::drift
function the allelic frequency trajectories for a number of replicates,
corresponding to the different cages. Use \(100\) individuals, and initial frequency of
\(0.5\) and \(1000\) replicatesdum<-drift(nind=100,p0=0.5,nrep=1000,ngen=100,PlotIt = TRUE)
We see allele frequencies fluctuating as time goes, with the first replicates fixing one or the other allele after \(\approx 35\) generations. After a 100 generations, many replicates have fixed one or the other allele, but still many have the two alleles segregating.
dum<-drift(nind=10,p0=0.5,nrep=1000,ngen=100,PlotIt = TRUE)
dum<-drift(nind=1000,p0=0.5,nrep=1000,ngen=100,PlotIt = TRUE)
With 10 individuals only, allele frequencies fluctuations are much larger than with \(100\), and fixation of one or the other allele occurs very fast. After a 100 generation, only a handful of replicates retains polymorhism.
With \(1000\) individuals, we see the reverse pattern, fluctuations of allele frequencies are much smaller, and all replicates remain polymorphic after 100 generations, with allele frequencies remaining within the range \([0.2-0.8]\).
x<-drift(nind=100,ngen=1000)
gens<-c(1,2,3,5,10,20,50,100,1000)
par(mfrow=c(3,3))
for (i in gens)
hist(x[i,],breaks=0:50/50,main=paste("generation:", i),xlab="Freq",ylab="")
par(mfrow=c(1,1))
The figures show allele frequency distribution spreading from a pic at 0.5 for the initial generation, to something belle shaped around 0.5 until the 20th generation but with increasing spread. At generation 50, the flattening is more pronounced, and at generation 100, the distribution is U -shaped with several replicates having fixed one or the other allele, but still many replicates maintain a polymorphic state. At generation 1000, all replicates have fixed one or the other allele, in equal proportion
Several ways to answer this question.
x
:g<-c(10,20,50,100)
hom1<-x[g,]^2
het<-2*x[g,]*(1-x[g,])
hom2<-(1-x[g,])^2
round(rbind(rowMeans(hom1),rowMeans(het),rowMeans(hom2)),digits=3)
## [,1] [,2] [,3] [,4]
## [1,] 0.264 0.274 0.311 0.367
## [2,] 0.478 0.452 0.394 0.301
## [3,] 0.259 0.274 0.295 0.332
Vp<-apply(x[g,],1,var)
barp<-rowMeans(x[g,])
(Fsts<-Vp/barp/(1-barp)) #alternatively Fsts<-Vp/0.5^2
## [1] 0.04484019 0.09558799 0.21156659 0.39819122
round(Fsts,digits=3)
## [1] 0.045 0.096 0.212 0.398
round(rbind(barp^2+barp*(1-barp)*Fsts,2*barp*(1-barp)*(1-Fsts),(1-barp)^2+barp*(1-barp)*Fsts),digits=3)
## [,1] [,2] [,3] [,4]
## [1,] 0.264 0.274 0.311 0.367
## [2,] 0.478 0.452 0.394 0.301
## [3,] 0.259 0.274 0.295 0.332
thetas<-numeric(100)
p0<-.5
N<-100
thetas[1]<-1/2/N
theta0<-0; for (i in 2:100) thetas[i]<-1/2/N+(1-1/2/N)*thetas[i-1]
round(thetas[g],digits=3)
## [1] 0.049 0.095 0.222 0.394
round(rbind(p0^2+p0^2*thetas[g],2*p0*(1-p0)*(1-thetas[g]),(1-p0)^2+p0*(1-p0)*thetas[g]),digits=3)
## [,1] [,2] [,3] [,4]
## [1,] 0.262 0.274 0.305 0.349
## [2,] 0.476 0.452 0.389 0.303
## [3,] 0.262 0.274 0.305 0.349
We see the estimated \(F_{ST}\) are close to their expectations for all generations, as are the proportion of the different genotypes.
JGTeach::drift
function to
explore some properties of drift, namely the probability and time to
fixation of an allele.Theory tells us that the probability of fixation of an allele is its frequency, and that time to fixation is
\[ \frac{4N(1-p) \ln(1-p)}{p} \]
which, for a frequency of \(0.5\), corresponds to \(2.7N\) generations.
x1<-drift(nind=50,ngen=1000,nrep=10000)
par(mfrow=c(3,3))
for (i in gens)
hist(x1[i,],breaks=seq(0,1,0.01),main=paste("generation:", i),xlab="Freq",ylab="")
par(mfrow=c(1,1))
# distribution of fixation times: take the first occurrence of 1 for each replicate
dist.tfix<-apply(x1,2,function(y) which(y>=1.0)[1])
# fixation probability
(pfix<-sum(!is.na(dist.tfix))/10000)
## [1] 0.4982
# mean time to fixation
(tfix<-mean(dist.tfix,na.rm=T))
## [1] 137.3695
Both the probability of fixation 0.5 and the mean time to fixation 137 are close to their expected values
hist(dist.tfix, main="Distribution of time to fixation, p0=0.50, N=50",xlab="Generations",ylab="")
abline(v=tfix, col="red",lwd=2)
The distribution of fixation time as a long right tail, and a mode to the left of the mean time to fixation: many replicates will fix before the mean time to fixation, but a few will take a very long time to reach fixation.
hierfstat::sim.genot.t
3 populations
evolving independently one from another, in order to check the
approximation\[ F_{ST_i} \approx \frac{t}{2N_{i}} \]
The 3 populations have diploid size \(N_1=100,N_2=1000\) and \(N_3=10000\) respectively. after 50 generations, we expect \(\beta_{1,2,3}\) to be approximately 0.25, 0.025, 0.0025. Is it the case ?
# 50 loci with 20 alleles each,
dat<-sim.genot.t(size=100,nbal=20,N=c(100,1000,10000),
nbloc=50,mig=0.0,t=50)
# the betas function estimates population specific Fsts from a
# fstat format data frame assuming random mating
(beta.ci<-betas(dat,nboot=100)$ci)
## boot.bW
## 2.5% 0.1843812 0.02237260 -0.004061785 0.07162905
## 97.5% 0.2366347 0.03460005 0.007309045 0.09018959
The confidence intervals of \(F_{ST_i}\)s overlap with the expectation for population 2 and 3 (\(1000\) and \(10000\) individuals respectively), but not for population 1, where the upper limit of the confidence interval of \(F_{ST_1}\), 0.2366347 is just below the approximation 0.25.
# 50 loci with 20 alleles each,
dat<-sim.genot.t(size=100,nbal=20,N=c(100,1000,10000),
nbloc=50,mig=0.0,t=200)
# the betas functiom estimates population specific Fst from a
# fstat format data frame assuming random mating
betas(dat,nboot=100)$ci
## boot.bW
## 2.5% 0.5904312 0.0900153 0.005164215 0.2368829
## 97.5% 0.6912153 0.1276246 0.028368175 0.2725287
#expectation
200/c(200,2000,20000)
## [1] 1.00 0.10 0.01
The pattern we saw after 50 generations is exemplified: \(F_{ST_1}\) confidence interval does not include the approximation of its expectation (\(1\)). For the other two, the approximation is still within the confidence interval, but barely so for the second. A rule of thumb for the approximation to work is \(t \leq 0.2N\)
Imagine a way to do this simulation with ms
.
# assumes mu=1e-8, r=1e-8, N0=1e+5, nbp=1e+5,
# simulate 10 replicates, 100 diploid individuals from each pop
#
# pop 4 will be the ancestral population with N4=N0=1e+5
# Only pops 1-3 are sampled, and there is no migration:
# -I 4 200 200 200 0 0
# pop1 is a 1000th of anc pop, pop2 a 100th and pop 3 a 10th:
# -n 1 0.001 -n 2 0.01 -n 3 0.1
# split occured (backward) 50 generation ago
# in unit of 4* Anc pop size ->50/4/100000=0.000125:
# -ej 0.000125 1 4 -ej 0.000125 2 4 -ej 0.000125 3 4
ms 600 10 -t 400 -r 400 100000 -I 4 200 200 200 0 0 -n 1 0.001 -n 2 0.01 -n 3 0.1
-ej 0.000125 1 4 -ej 0.000125 2 4 -ej 0.000125 3 4 > 3popsdrift.txt
bed<-ms2bed("../3popsdrift.txt")
# expectation is (50/2/c(100,1000,10000)),
# but works well for t<0.2N only
fst.dosage(bed,pop=rep(1:3,each=50))
## 1 2 3 All
## 3.020749e-01 2.661630e-02 -9.885836e-05 1.095308e-01
50/c(200,2000,20000)
## [1] 0.2500 0.0250 0.0025
We will now explore the first 20 megabases of chromosome 22 from samples of the 1000 genome project and will find that negative population specific \(F_{ST}^i\) are not uncommon.
ch22<-read.VCF("../chr22_Mb0_20.recode.vcf.gz")
## ped stats and snps stats have been set.
## 'p' has been set.
## 'mu' and 'sigma' have been set.
samp.desc.url<-"https://www2.unil.ch/popgen/teaching/SISG18/integrated_call_samples_v3.20130502.ALL.panel"
samp.desc<-read.table(samp.desc.url,header=TRUE,stringsAsFactors = TRUE)
samp.desc
: Print a table of the number
of samples per super_pop and pop.with(samp.desc,table(pop,super_pop))
## super_pop
## pop AFR AMR EAS EUR SAS
## ACB 96 0 0 0 0
## ASW 61 0 0 0 0
## BEB 0 0 0 0 86
## CDX 0 0 93 0 0
## CEU 0 0 0 99 0
## CHB 0 0 103 0 0
## CHS 0 0 105 0 0
## CLM 0 94 0 0 0
## ESN 99 0 0 0 0
## FIN 0 0 0 99 0
## GBR 0 0 0 91 0
## GIH 0 0 0 0 103
## GWD 113 0 0 0 0
## IBS 0 0 0 107 0
## ITU 0 0 0 0 102
## JPT 0 0 104 0 0
## KHV 0 0 99 0 0
## LWK 99 0 0 0 0
## MSL 85 0 0 0 0
## MXL 0 64 0 0 0
## PEL 0 85 0 0 0
## PJL 0 0 0 0 96
## PUR 0 104 0 0 0
## STU 0 0 0 0 102
## TSI 0 0 0 107 0
## YRI 108 0 0 0 0
ch22
and samp.desc
.all.equal(ch22@ped$id,as.character(samp.desc$sample),check.attributes = FALSE)
## [1] TRUE
# if not (in different order and or some missing) :
# use match(ch22@ped$id,samp.desc$sample)
# From dosage data:
# fst.ch22.pop<-fst.dosage(ch22,pop=samp.desc$pop)
# fst.ch22.cont<-fst.dosage(ch22,pop=samp.desc$super_pop)
# More efficiently from matching data
# Matching.ch22<-matching(ch22)
# takes some time, so saved in matching.ch22.RDS available from # website
Matching.ch22<-readRDS("../matching.ch22.RDS")
fs.ch22.pop<-fs.dosage(Matching.ch22,pop=samp.desc$pop,matching=TRUE)
fs.ch22.cont<-fs.dosage(Matching.ch22,pop=samp.desc$super_pop,matching=TRUE)
fs.ch22.pop$Fs[2,]
## ACB ASW BEB CDX CEU CHB CHS
## -0.09355343 -0.08075169 0.10151305 0.17074313 0.14365325 0.17838039 0.17711221
## CLM ESN FIN GBR GIH GWD IBS
## 0.08806118 -0.08344716 0.16672832 0.14865051 0.07875782 -0.07935443 0.14356831
## ITU JPT KHV LWK MSL MXL PEL
## 0.10161283 0.16150007 0.15666623 -0.08451502 -0.10001199 0.13114569 0.18725503
## PJL PUR STU TSI YRI All
## 0.07933950 0.08566280 0.09944818 0.14146696 -0.08124044 0.07455351
fs.ch22.cont$Fs[2,]
## AFR AMR EAS EUR SAS All
## -0.09971103 0.09566666 0.15940128 0.13837331 0.08328910 0.07540386
Population specific \(F_{ST}\)s vary between \(-0.10\) for Mende from Sierra Leone (MSL) and \(0.18\) for Han Chinese in Bejing, China (CHB) 1000 genomes population codes with an overall \(F_{ST}=0.075\).
Continent specific \(F_{ST}\)s vary between \(-0.10\) for Africa (AFR) and \(0.16\) for Esat Asia (EAS), with the same overall value.
plot
function associated to
fs.dosage
. Produce the corresponding plot after having
ordeered the population by continent and discuss the results in the
light of what you know about human demographic history: the top left
panel show individual inbreeding coefficients per population, relative
to the mean kinship in their population. The right column panels show
\(F_{ST}^{XY}\) (or \(\beta^{XY}\)) on top and population
specific \(F_{ST}\) at the bottom.
Last, the bottom left panel shows pairwise \(F_{ST}\). Do you see a similarity between
\(F_{ST}^{XY}\) and the heatmap of
\(K_{AS}\) kinship?#extract popnames in the correct order
pnames<-unlist(lapply(strsplit(with(samp.desc,
levels(factor(paste(super_pop,pop,sep=":")))),":"),function(x) x[[2]]))
#forces factor to take this order
pop<-with(samp.desc,factor(pop,levels=pnames))
fs.ch22.pop<-fs.dosage(Matching.ch22,pop=pop,matching=TRUE)
coul<-rep(c("orange","gold","red","green","blue","purple"),c(2,5,4,5,5,5))
plot(fs.ch22.pop,las=2,cex.axis=0.5,col=coul)
The plot function of hierfstat::fs.dosage
produces four
panels:
The top left panel shows individual inbreeding coefficients, estimated with the reference being the population to which the individual belongs. Samples are arranged according to their continent. Values of individual inbreeding cefficients are centered around 0, with Admixed Americans (AMR, red) samples showing more variation and South Asian (SAS, purple) samples hinting at slightly positive values.
The top right panel shows a heatmap of the FsM matrix containing population specific FSTs on the diagonal. The off diagonal elements contains the average of the kinships for pairs of individuals, one from each population, relative to the mean kinship for pairs of individuals between populations. This basically boils down to the average kinship per population or pair of we saw in the previous practical). African samples (AFR) show lower values than non african samples, with EAS and Europe (EUR) showing the largest within continent values.
The bottom left panel shows the Fst2x2 matrix, the classical pairwise \(F_{ST}\)s. All values within continents are low (with a small exception for AMR), while values between AFR and non AFR samples are high. We also see sightly higher values in the non AFR bloc for pairwise \(F_{ST}\)s between EAS and EUR.
The bottom right panel shows Population specific \(F_{ST}\)s as barplot. It’s immediately clear that all AFR values are negative, while all other populations show positive population specific \(F_{ST}\)s, with EAS population being largest, followed by EUR, and AMR showing the largest variance.
sim.genot
function of the
hierfstat
package.np<-5
dat5<-sim.genot(nbal=2,nbloc=1000,nbpop=np,mig=0.003)
biall2dos
function.dos<-biall2dos(dat5[,-1])
scale
function useful
for this.ps<-colMeans(dos)/2
sdp<-(ps*(1-ps))^(0.5)
#first, filter out the fixed loci
nfixed<-which(ps>0 & ps <1)
dosnf<-dos[,nfixed]
X<-scale(dosnf)
# or
# X<-sweep(dosnf,2,ps[nfixed],FUN="-")
# X<-sweep(X,2,sdp[nfixed],FUN="/")
tcrossprod
.XXT<-tcrossprod(X)
eigen
function.eigx<-eigen(XXT)
ind.coord<-sweep(eigx$vectors,2,eigx$values^0.5,FUN="*")
prcomp
function on matrix \(X\).prx<-prcomp(X)
#check equality of the absolute values of the PCs
all.equal(abs(matrix(prx$x)),abs(matrix(ind.coord)))
## [1] TRUE
par(mfrow=c(2,2))
plot((eigx$values/sum(eigx$values))[1:20],type="h",
main="screeplot",xlab="Eigen values",ylab="")
plot(prx$x[,1:2],col=rep(1:np,each=50),pch=16)
plot(prx$x[,3:4],col=rep(1:np,each=50),pch=16)
plot(prx$x[,5:6],col=rep(1:np,each=50),pch=16)
par(mfrow=c(1,1))
The top left panel (scree plot) shows 4 eigen values standing out. Samples are indeed grouped according to their population of origin along axes 1 to 4. The bottom right panel (axes 5 and 6) shows no more structure remains after the first 4 axes, with individuals from all groups overlapping.
colpca<-rep(1:np,each=50)
ns<-5
plot(1:ns,prx$x[1,1:ns],col=colpca[1],type="l",ylim=range(prx$x[,1:ns]),
xlab="Axis",ylab="coord.",main="parallel coordinate plot")
for (i in 2:nrow(prx$x)) lines(1:ns,prx$x[i,1:ns],col=colpca[i])
The parallel coordinate plot representation is an easy way to visualize more than 2 axes at the same time: we see from the figure that individuals from the same population share similar coordinates along axes 1 to 4, the red population standing out on axis 1, the green on axis 2, the turquois on axis 3 and well separated from the black population, and finally the blue on axis 4.
X<-scale(dosnf,scale=FALSE)
XXT<-tcrossprod(X)
eigx<-eigen(XXT)
ind.coord<-sweep(eigx$vectors,2,eigx$values^0.5,FUN="*")
prx<-prcomp(X)
all.equal(abs(matrix(prx$x)),abs(matrix(ind.coord)))
## [1] "'is.NA' value mismatch: 250 in current 0 in target"
par(mfrow=c(2,2))
plot((eigx$values/sum(eigx$values))[1:20],type="h",
main="screeplot",xlab="Eigen values",ylab="")
plot(prx$x[,1:2],col=rep(1:np,each=50),pch=16)
plot(prx$x[,3:4],col=rep(1:np,each=50),pch=16)
plot(prx$x[,5:6],col=rep(1:np,each=50),pch=16)
par(mfrow=c(1,1))
The pattern we observed is very similar to the one obtained with the scaled matrix. With SNPs data, with many rare alleles, scaling gives the same weight to rare and common alleles, which might not be what ones want. If interested on this topic, there is a vast literature on using PCA in population genetics, see e.g. Novembre and Stephens, Nat. gent (2008).
hierfstat::beta.dosage
function for this. Conclusions?Kas<-beta.dosage(dos)
eigKas<-eigen(Kas)
ind.coord<-sweep(eigKas$vectors,2,eigKas$values^0.5,FUN="*")
par(mfrow=c(2,2))
plot((eigKas$values/sum(eigKas$values))[1:20],type="h",
main="screeplot",xlab="Eigen values",ylab="")
plot(ind.coord[,1:2],col=rep(1:np,each=50),pch=16)
plot(ind.coord[,3:4],col=rep(1:np,each=50),pch=16)
plot(ind.coord[,5:6],col=rep(1:np,each=50),pch=16)
par(mfrow=c(1,1))
Again, we obtain a picture separating well the 5 population along 4 axes.
np<-3
dat3<-sim.genot(nbal=2,nbloc=1000,nbpop=np,mig=0.003)
dos<-biall2dos(dat3[,-1])
ps<-colMeans(dos)/2
sdp<-(ps*(1-ps))^(0.5)
#first, filter out the fixed loci
nfixed<-which(ps>0 & ps <1)
dosnf<-dos[,nfixed]
X<-scale(dosnf)
prx<-prcomp(X)
par(mfrow=c(2,2))
plot((prx$sdev^2/sum(prx$sdev^2))[1:20],type="h",
main="screeplot",xlab="Eigen values",ylab="")
plot(prx$x[,1:2],col=rep(1:np,each=50),pch=16)
plot(prx$x[,3:4],col=rep(1:np,each=50),pch=16)
plot(prx$x[,5:6],col=rep(1:np,each=50),pch=16)
par(mfrow=c(1,1))
With only 3 populations, 2 axes are sufficient to describe the structure in the data set
np<-5
#migration 3 times larger
dat5<-sim.genot(nbal=2,nbloc=1000,nbpop=np,mig=0.01)
dos<-biall2dos(dat5[,-1])
ps<-colMeans(dos)/2
sdp<-(ps*(1-ps))^(0.5)
#first, filter out the fixed loci
nfixed<-which(ps>0 & ps <1)
dosnf<-dos[,nfixed]
X<-scale(dosnf)
prx<-prcomp(X)
par(mfrow=c(2,2))
plot((prx$sdev^2/sum(prx$sdev^2))[1:20],type="h",
main="screeplot",xlab="Eigen values",ylab="")
plot(prx$x[,1:2],col=rep(1:np,each=50),pch=16)
plot(prx$x[,3:4],col=rep(1:np,each=50),pch=16)
plot(prx$x[,5:6],col=rep(1:np,each=50),pch=16)
par(mfrow=c(1,1))
colpca<-rep(1:np,each=50)
ns<-5
plot(1:ns,prx$x[1,1:ns],col=colpca[1],type="l",
ylim=range(prx$x[,1:ns]),xlab="Axis",
ylab="coord.",main="par. coord. plot")
for (i in 2:nrow(prx$x)) lines(1:ns,prx$x[i,1:ns],col=colpca[i])
With more migration, we retain the 4 significant axes, but individuals are not as tightly clustered as previously.
hierfstat::sim.genot.metapop.t
function. Assume 8 demes,
connected by migration with nearest neighbors only, and with 5%
migration between neighbors. Redo the PCA on the data set. Interpret the
figure.np<-8
nl<-1000
t<-1000
M<-matrix(0,ncol=np,nrow=np)
diag(M[-1,-np])<-0.05
diag(M[-np,-1])<-0.05
diag(M)<-1-rowSums(M,na.rm=TRUE)
ss1d<-sim.genot.metapop.t(nbal=2,nbpop=np,nbloc=nl,mig=M,t=t)
dos<-biall2dos(ss1d[,-1])
ps<-colMeans(dos)/2
sdp<-(ps*(1-ps))^(0.5)
#first, filter out the fixed loci
nfixed<-which(ps>0 & ps <1)
dosnf<-dos[,nfixed]
X<-scale(dosnf)
prx<-prcomp(X)
par(mfrow=c(2,2))
plot((prx$sdev^2/sum(prx$sdev^2))[1:20],type="h",
main="screeplot",xlab="Eigen values",ylab="")
plot(prx$x[,1:2],col=rep(1:np,each=50),pch=16)
plot(prx$x[,3:4],col=rep(1:np,each=50),pch=16)
plot(prx$x[,5:6],col=rep(1:np,each=50),pch=16)
par(mfrow=c(1,1))
In a 1D-stepping stone, only the first axis of the PCA is significant, and points of different colors overlap, but do so in a geographical fashion: black dots to the left and grey dots to the right along the 1st axis, with other colors coming in turn (black, then red, then green, blue, turquoise, purple, orange and finally grey)
If enough time only Here, we are reproducing figs 1. and 3 of Weir and Goudet (2017). The following two questions will help you understand the material in this paper, but are not essential.
The two populations system presented during the lecture and given in
eq 5 of the paper has been implemented in
JGTeach::thet.bet.2pops
.
# reproduces fig 1 in Weir and Goudet (2017)
#top row
first<-thet.bet.2pops(mu=0.0,m2=0.0,m1=0.0,n1=10000,n2=100,ngen=10000)
#middle row
second<-thet.bet.2pops(mu=0.001,m2=0.0,m1=0.0,n1=10000,n2=100,ngen=10000)
#bottom row
third<-thet.bet.2pops(mu=0.001,m2=0.0,m1=0.01,n1=10000,n2=100,ngen=10000)
sim.genot.metapop.t
to generate genetic data according to
this model.This may take some time, so a data file fig3.RData containing the results is available from the website, you should download it.
gens<-1:10*100
ngen<-gens[length(gens)]
#generate data
mig.mat2<-matrix(c(.99,0.01,0,1),nrow=2,byrow=TRUE)
mig.mat2
## [,1] [,2]
## [1,] 0.99 0.01
## [2,] 0.00 1.00
mutrate<-10^{-3} #10^{-6} initial value
# As sim.genot.metapop.t only outputs genotypes from the
# last generation, necessary to run the function
# with several end time points. This is the essence of
# using lapply to a here
# x<-lapply(gens,function(y){
# sim.genot.metapop.t(t=y,nbal=20,nbpop=2,N=c(10000,100),
# mig=mig.mat2,nbloc=1000,mut=mutrate)})
# estimate betas for data sets
# beta.x<-lapply(x,betas,nboot=1000)
load("../fig3.RData")
betas.ci<-lapply(beta.x,function(x) x$ci)
#expected values
etb1<-thet.bet.2pops(mu=mutrate,n1=10000,n2=100,m1=0.01,m2=0,ngen=ngen,plotit=FALSE)
gens<-1:10*100
ngen<-gens[length(gens)]
#create the plot
plot(1:ngen,etb1$Be[,1],type="l",ylim=range(etb1$Be,betas.ci),col="red",lwd=2,
xlab="Generations",ylab=expression(beta))
lines(1:ngen,etb1$Be[,2],col="blue",lwd=2)
lines(1:ngen,etb1$Be[,3],lwd=2)
abline(h=0)
segments(gens,unlist(lapply(betas.ci,function(x) x[1,2])),gens,
unlist(lapply(betas.ci,function(x) x[2,2])),lwd=2,col="blue")
segments(gens,unlist(lapply(betas.ci,function(x) x[1,1])),gens,
unlist(lapply(betas.ci,function(x) x[2,1])),lwd=2,col="red")
points(gens,unlist(lapply(beta.x,function(x) x$betaiovl[1])),
col="red",cex=1.5,pch=16)
points(gens,unlist(lapply(beta.x,function(x) x$betaiovl[2])),
col="blue",cex=1.5,pch=16)
#beta_w added too
points(gens,unlist(lapply(beta.x,function(x) mean(x$betaiovl))),
col="black",cex=1.5,pch=16)
title("2 populations with migration model. \n N1=10'000; N2=100; m1=0.01; m2=0.0")
END OF PRACTICAL 4.