library(ape)
library(MASS)
library(phytools)
## Loading required package: maps
library(geiger)
## Registered S3 method overwritten by 'geiger':
## method from
## unique.multiPhylo ape
CompareRates.multTrait<-function(phy,x,TraitCov=T,ms.err=NULL,ms.cov=NULL){
build.chol<-function(b){
c.mat<-matrix(0,nrow = p,ncol = p)
c.mat[lower.tri(c.mat)]<-b[-1]
c.mat[p,p]<-exp(b[1])
c.mat[1,1]<-sqrt(sum((c.mat[p,])^2))
if(p>2){
for(i in 2:(p-1)){
c.mat[i,i]<-ifelse((c.mat[1,1]^2-sum((c.mat[i,])^2))>0,sqrt(c.mat[1,1]^2-sum((c.mat[i,])^2)),0)
}
}
return(c.mat)
}
x<-as.matrix(x)
N<-nrow(x)
p<-ncol(x)
C<-vcv.phylo(phy)
C<-C[rownames(x),rownames(x)]
I<-diag(1,N)
if (is.matrix(ms.err)){
ms.err<-as.matrix(ms.err[rownames(x),])}
if (is.matrix(ms.cov)){
ms.cov<-as.matrix(ms.cov[rownames(x),])}
# a.obs<-colSums(solve(C)) %*% x / sum(solve(C))
# R.obs<-t(x-one%*%a.obs)%*%solve(C)%*%(x-one%*%a.obs)/N
IIDcon<-function(trait=trait,mu=mu,sigma=sigma,C=C){
z<- (trait-mu)/sigma
eC<-eigen(C)
D.n5<-diag(1/sqrt(eC$values))
C.neg.5<-eC$vectors%*%D.n5%*%t(eC$vectors)
return(C.neg.5%*%trait)
}
one<-matrix(1,N,1)
a.obs.ou<-array(NA,p)
R.obs.ou<-array(NA,c(p,p))
IIDtrait<-array(NA,dim(x))
alpha.array<-array(NA,p)
for(Index in 1:p){
# ?phylosig
# ?fitContinuous
# Index<-1
alpha<-fitContinuous(phy=phy,dat=x[,Index],model="OU")$opt$alpha
alpha.array[Index]<-alpha
Sa<-(exp(-2*alpha*(max(C)-C)))*(1-exp(-2*alpha*C))/2/alpha
assign(paste("Sa",Index,sep=""),Sa)
a.obs.ou[Index]<-colSums(solve(Sa)) %*% x[,Index] / sum(solve(Sa))
R.obs.ou[Index,Index]<-t(x[,Index]-one%*%a.obs.ou[Index])%*%solve(Sa)%*%(x[,Index]-one%*%a.obs.ou[Index])/N
IIDtrait[,Index]<-IIDcon(trait=x[,Index],mu=a.obs.ou[Index],sigma=R.obs.ou[Index,Index],C=Sa)
}
for(i in 1: (p-1)){
for( j in (i+1):p){
R.obs.ou[i,j]<-R.obs.ou[j,i]<- cov(IIDtrait[,i],IIDtrait[,j])
}
}
dim(a.obs.ou)
a.obs.ou<-matrix(a.obs.ou,nrow=1,ncol=p)
a.obs.ou
dim(a.obs.ou)
R.obs.ou
D<-matrix(0,N*p,p)
for(i in 1:(N*p)){
for(j in 1:p){
if((j-1)*N < i && i<=j*N){
D[i,j]=1.0
}
}
}
y<-as.matrix(as.vector(x))
if (TraitCov==F){R.obs.ou<-diag(diag(R.obs.ou),p)}
Sa1
Sa2
alpha1<-alpha.array[1]
alpha2<-alpha.array[2]
################################
# NEED TO REFER THEIS
#alpha12<-(alpha1+alpha2)/2
#alpha12<-sqrt(alpha1*alpha2)
#alpha12<-1/(1/alpha1+1/alpha2)
Sa12 <-(exp(-(alpha1+alpha2)*(max(C)-C)))*(1-exp(-(alpha1+alpha2)*C))/(alpha1+alpha2)
################################
RkronSa<-rbind(cbind(R.obs.ou[1,1]*Sa1,R.obs.ou[1,2]*Sa12),
cbind(R.obs.ou[1,2]*Sa12,R.obs.ou[2,2]*Sa2))
RkronSa
LLik.obs.ou<-ifelse(is.matrix(ms.err)==TRUE,
-t(y-D%*%t(a.obs.ou))%*%ginv((RkronSa+diag(as.vector(ms.err))))%*%(y-D%*%t(a.obs.ou))/2-N*p*log(2*pi)/2-determinant((RkronSa+ diag(as.vector(ms.err))))$modulus[1]/2,
-t(y-D%*%t(a.obs.ou))%*%ginv(RkronSa)%*%(y-D%*%t(a.obs.ou))/2-N*p*log(2*pi)/2-determinant(RkronSa)$modulus[1]/2)
# sigma.mn<-mean(diag(R.obs))
sigma.mn.ou<-mean(diag(R.obs.ou))
if(is.matrix(ms.err) && is.matrix(ms.cov)){
within.spp<-cbind(ms.err,ms.cov)
rc.label<-NULL
for(i in 1:p){
rc.label<-rbind(rc.label,c(i,i))
}
for(j in 2:p){
if(i!=j&&i<j){
rc.label<-rbind(rc.label,c(i,j))
}
}
m.e<-NULL
for(i in 1:p){
temp<-NULL
for(j in 1:p){
for(k in 1:nrow(rc.label)){
if(setequal(c(i,j),rc.label[k,])==T)
{tmp<-cbind(tmp,diag(within.spp[,k]))}
}
}
m.e<-rbind(m.e,tmp)
}
}
R<-R.obs.ou
#param<-c(sigma.mn.ou,alpha1,alpha2)
#names(param)<-c("sigma","alpha1","alpha2")
lik.covF.ou<-function(param){
alpha1<-param["alpha1"]
alpha2<-param["alpha2"]
sigma<-param["sigma"]
Sa12 <-(exp(-(alpha1+alpha2)*(max(C)-C)))*(1-exp(-(alpha1+alpha2)*C))/(alpha1+alpha2)
diag(R)<-sigma.mn.ou
RkronSa<-rbind(cbind(R[1,1]*Sa1,R[1,2]*Sa12),
cbind(R[2,1]*Sa12,R[2,2]*Sa2))
LLik<-ifelse(is.matrix(ms.err)==TRUE,
-t(y-D%*%t(a.obs.ou))%*%ginv((RkronSa+m.e))%*%(y-D%*%t(a.obs.ou))/2-N*p*log(2*pi)/2-determinant((RkronSa+ m.e))$modulus[1]/2,
-t(y-D%*%t(a.obs.ou))%*%ginv(RkronSa)%*%(y-D%*%t(a.obs.ou))/2-N*p*log(2*pi)/2-determinant(RkronSa)$modulus[1]/2)
if(LLik==-Inf){LLik<--1e+10}
return(-LLik)
}
#param<-c(alpha1,alpha2,sigma.mn.ou,0)
#names(param)<-c("alpha1","alpha2","sigma","R.offd")
lik.covT.ou<-function(param){
alpha1<-param["alpha1"]
alpha2<-param["alpha2"]
sigma<-param["sigma"]
R.offd<-param["R.offd"]
alpha12<-(alpha1+alpha2)/2
Sa12 <-(exp(-(alpha1+alpha2)*(max(C)-C)))*(1-exp(-(alpha1+alpha2)*C))/(alpha1+alpha2)
low.chol<-build.chol(c(sigma,R.offd))
R<-low.chol%*%t(low.chol)
RkronSa<-rbind(cbind(R[1,1]*Sa1,R[1,2]*Sa12),
cbind(R[1,2]*Sa12,R[2,2]*Sa2))
LLik<-ifelse(is.matrix(ms.err)==TRUE,
-t(y-D%*%t(a.obs.ou))%*%ginv((RkronSa+m.e))%*%(y-D%*%t(a.obs.ou))/2-N*p*log(2*pi)/2-determinant((RkronSa+ m.e))$modulus[1]/2,
-t(y-D%*%t(a.obs.ou))%*%ginv(RkronSa)%*%(y-D%*%t(a.obs.ou))/2-N*p*log(2*pi)/2-determinant(RkronSa)$modulus[1]/2)
# print(LLik)
if(LLik==-Inf){LLik<--1e+10}
return(-LLik)
}
sigma.upper<-2*max(apply(x,2,sd))
p0<-c(alpha1,alpha2,sigma.mn.ou)
names(p0)<-c("alpha1","alpha2","sigma")
if(TraitCov==F){model.ou<-
optim(p0,fn=lik.covF.ou,method="L-BFGS-B",lower = c(1e-5,1e-5,1e-5),upper=c(5,5,sigma.upper))
}
R.offd<-rep(0,(p*(p-1)/2))
p0<-c(alpha1,alpha2,sigma.mn.ou,0)
names(p0)<-c("alpha1","alpha2","sigma","R.offd")
if(TraitCov==T){model1.ou<-
optim(p0,fn=lik.covT.ou,method="L-BFGS-B",lower = c(1e-5,1e-5,1e-5,1e-5),upper=c(5,5,sigma.upper,sigma.upper))
}
if(TraitCov==F){R.constr.ou<-diag(model.ou$par["sigma"],p)}
if(TraitCov==T){
chol.mat<-build.chol(model1.ou$par[c("sigma","R.offd")])
R.constr.ou<-chol.mat%*%t(chol.mat)
}
if(model1.ou$convergence==0){
message.ou<-"Optimization has converged."}else{
message.ou<-"Optim may not have converrged.
Consideer changing startt value or lower/upper limits."}
LRT.ou<-(-2*((-model1.ou$value-LLik.obs.ou)))
LRT.prob.ou<-pchisq(LRT.ou, (p-1),lower.tail = FALSE)
AIC.obs.ou<- -2*LLik.obs.ou+2*p+2*p+2*p #(2p twice: 1x for rates, 1x for anc.states,1x for h)
AIC.common.ou<--2*(-model1.ou$value)+2+2*p+2*p #(2*1:for 1 rate 2p for anc.states)
return(
list(
Robs.ou=R.obs.ou,
Rconstrained.ou=R.constr.ou,
Lobs.ou=LLik.obs.ou,
Lconstrained.ou=(-model1.ou$value),
LRTest.ou=LRT.ou,
Prob.ou=LRT.prob.ou,
AICc.obs.ou=AIC.obs.ou,
AICc.constrained.ou=AIC.common.ou,
optimmessage.ou=message.ou
)
)
}
### Sample code
phy<-rcoal(5)
plot(phy)
x<- matrix(c(rnorm(5,2,1),rnorm(5,0,0.5)),ncol=2)
rownames(x)<-phy$tip.label#LETTERS[1:N]
CompareRates.multTrait(phy=phy,x=x,TraitCov=T,ms.err=NULL,ms.cov=NULL)
## Warning in fitContinuous(phy = phy, dat = x[, Index], model = "OU"): Parameter estimates appear at bounds:
## alpha
## Warning in fitContinuous(phy = phy, dat = x[, Index], model = "OU"): Parameter estimates appear at bounds:
## alpha
## $Robs.ou
## [,1] [,2]
## [1,] 2.217276 1.994654
## [2,] 1.994654 10.023080
##
## $Rconstrained.ou
## [,1] [,2]
## [1,] 8.304172 3.372123
## [2,] 3.372123 8.304172
##
## $Lobs.ou
## [1] -12.43279
##
## $Lconstrained.ou
## [1] -7.487144
##
## $LRTest.ou
## [1] -9.891285
##
## $Prob.ou
## [1] 1
##
## $AICc.obs.ou
## [1] 36.86557
##
## $AICc.constrained.ou
## [1] 24.97429
##
## $optimmessage.ou
## [1] "Optimization has converged."
#####
tree<-read.tree("http://tonyjhwueng.info/phyrates/ple.nwk")
plot(tree)
tree$tip.label
## [1] "Plethodon_dorsalis" "Plethodon_ventralis"
## [3] "Plethodon_angusticlavius" "Plethodon_welleri"
## [5] "Plethodon_punctatus" "Plethodon_wehrlei"
## [7] "Plethodon_websteri" "Plethodon_teyahalee"
## [9] "Plethodon_cylindraceus" "Plethodon_variolatus"
## [11] "Plethodon_chlorobryonis" "Plethodon_chattahoochee"
## [13] "Plethodon_cheoah" "Plethodon_shermani"
## [15] "Plethodon_amplus" "Plethodon_meridianus"
## [17] "Plethodon_montanus" "Plethodon_albagula"
## [19] "Plethodon_sequoyah" "Plethodon_ocmulgee"
## [21] "Plethodon_savannah" "Plethodon_grobmani"
## [23] "Plethodon_kisatchie" "Plethodon_mississippi"
## [25] "Plethodon_kiamichi" "Plethodon_aureolus"
## [27] "Plethodon_glutinosus" "Plethodon_jordani"
## [29] "Plethodon_metcalfi" "Plethodon_ouachitae"
## [31] "Plethodon_fourchensis" "Plethodon_caddoensis"
## [33] "Plethodon_kentucki" "Plethodon_petraeus"
## [35] "Plethodon_yonahlossee" "Plethodon_hubrichti"
## [37] "Plethodon_nettingi" "Plethodon_richmondi"
## [39] "Plethodon_electromorphus" "Plethodon_cinereus"
## [41] "Plethodon_shenandoah" "Plethodon_hoffmani"
## [43] "Plethodon_virginia" "Plethodon_serratus"
df<-read.csv("http://tonyjhwueng.info/phyrates/Adams2012-SystBiolData.csv")
head(df)
## X HeadLength BodyWidth Forelimb
## 1 P_albagula 12.320000 8.160000 16.12000
## 2 P_amplus 11.120000 7.580000 16.44000
## 3 P_angusticlavius 7.033333 3.700000 8.10000
## 4 P_aureolus 9.200000 5.314286 12.52857
## 5 P_caddoensis 8.200000 3.600000 9.20000
## 6 P_chattahoochee 10.371429 6.400000 13.67143
phy<-tree
spX<-strsplit(as.character(df$X),"_")
spname<-array(NA,length(phy$tip.label))
for(Index in 1:length(phy$tip.label)){
spname[Index]<-paste("Plethodon_", spX[[Index]][2],sep="")
}
spname
## [1] "Plethodon_albagula" "Plethodon_amplus"
## [3] "Plethodon_angusticlavius" "Plethodon_aureolus"
## [5] "Plethodon_caddoensis" "Plethodon_chattahoochee"
## [7] "Plethodon_cheoah" "Plethodon_chlorobryonis"
## [9] "Plethodon_cinereus" "Plethodon_cylindraceus"
## [11] "Plethodon_dorsalis" "Plethodon_electromorphus"
## [13] "Plethodon_fourchensis" "Plethodon_glutinosus"
## [15] "Plethodon_grobmani" "Plethodon_hoffmani"
## [17] "Plethodon_hubrichti" "Plethodon_jordani"
## [19] "Plethodon_kentucki" "Plethodon_kiamichi"
## [21] "Plethodon_kisatchie" "Plethodon_meridianus"
## [23] "Plethodon_metcalfi" "Plethodon_mississippi"
## [25] "Plethodon_montanus" "Plethodon_nettingi"
## [27] "Plethodon_ocmulgee" "Plethodon_ouachitae"
## [29] "Plethodon_petraeus" "Plethodon_punctatus"
## [31] "Plethodon_richmondi" "Plethodon_savannah"
## [33] "Plethodon_sequoyah" "Plethodon_serratus"
## [35] "Plethodon_shenandoah" "Plethodon_shermani"
## [37] "Plethodon_teyahalee" "Plethodon_variolatus"
## [39] "Plethodon_ventralis" "Plethodon_virginia"
## [41] "Plethodon_websteri" "Plethodon_wehrlei"
## [43] "Plethodon_welleri" "Plethodon_yonahlossee"
df$X<-spname
head(df)
## X HeadLength BodyWidth Forelimb
## 1 Plethodon_albagula 12.320000 8.160000 16.12000
## 2 Plethodon_amplus 11.120000 7.580000 16.44000
## 3 Plethodon_angusticlavius 7.033333 3.700000 8.10000
## 4 Plethodon_aureolus 9.200000 5.314286 12.52857
## 5 Plethodon_caddoensis 8.200000 3.600000 9.20000
## 6 Plethodon_chattahoochee 10.371429 6.400000 13.67143
HeadLength<-df$HeadLength
names(HeadLength)<-spname
BodyWidth<-df$BodyWidth
names(BodyWidth)<-spname
HeadLength<-HeadLength[phy$tip.label]
BodyWidth<-BodyWidth[phy$tip.label]
x<-cbind(HeadLength,BodyWidth)
CompareRates.multTrait(phy=phy,x=x,TraitCov=T,ms.err=NULL,ms.cov=NULL)
## $Robs.ou
## [,1] [,2]
## [1,] 0.2343296 0.1322438
## [2,] 0.1322438 0.1302819
##
## $Rconstrained.ou
## [,1] [,2]
## [1,] 1.0243149 0.1577517
## [2,] 0.1577517 1.0243149
##
## $Lobs.ou
## [1] -126.3931
##
## $Lconstrained.ou
## [1] -185.9488
##
## $LRTest.ou
## [1] 119.1114
##
## $Prob.ou
## [1] 9.901163e-28
##
## $AICc.obs.ou
## [1] 264.7862
##
## $AICc.constrained.ou
## [1] 381.8976
##
## $optimmessage.ou
## [1] "Optimization has converged."