## Internal func: combining dependent test statistics.
# ' Adaptive variant-set association test
# '
# ' Adaptive test (AT) is defined based on the minimum p-value of weighted averages of generalized burden test (BT) and sum of squares test (VT).
# ' The required inputs are: U (vector of test statistics, say Score vector); R (covariance matrix of U); eta (BT coefficient);
# ' rho (vector of weights assigned to the BT).
# ' VT: \eqn{U^TU}; BT: \eqn{(\eta^TU)^2}; minimum p-value over weighted tests: \eqn{(1-\rho)U^TU + \rho(\eta^TU)^2}.
# '
# ' @param U vector of variant test statistics
# ' @param R covariance matrix for test statistics
# ' @param eta coefficient vector for the BT. Default to equal weights.
# ' @param rho weights for the BT
# ' @return
# ' \describe{
# ' \item{p.value}{ p-values for AT,VT,BT }
# ' \item{pval}{ vector of p-values for each rho }
# ' \item{rho.est}{ optimal rho value leading to the minimum p-value }
# ' }
# ' @keywords adaptive test
# ' @export
# ' @references
# ' Wu,B. and Zhao,H. (2018) Efficient and powerful meta-analysis of variant-set association tests using MetaSAT.
# ' @examples
# ' R = cor(matrix(rnorm(500),100,5)*sqrt(0.9)+rnorm(100)*sqrt(0.1))
# ' Rh = chol(R)
# ' Z = colSums(Rh*rnorm(5))
# ' AVAT(Z, R)
AVAT <- function(U,R, eta=NULL, rho=(0:10/10)^2){
if(is.null(eta)) eta = rep(1, length(U))
Q = sum(U^2); B = sum(U*eta)
Qs = (1-rho)*Q + rho*B^2
##
eR = eigen(R, sym=TRUE); D = sqrt(abs(eR$val))
U1 = colSums(eR$vec*eta)*D
Rs = colSums(R*eta); R1 = sum(Rs*eta); R2 = sum(Rs^2)
P1 = diag(D^2); P2 = outer(U1,U1)
## min-pval
L = length(rho); L1 = L-1
pval = rep(1,L)
pval[L] = pchisq(B^2/R1,1,lower=FALSE)
Lamk = vector('list', L1)
for(k in 1:L1){
ak = (1-rho[k])*P1 + rho[k]*P2
aae = zapsmall( abs( eigen(ak,sym=TRUE,only.val=TRUE)$val ) )
Lamk[[k]] = aae[aae>0]
pval[k] = KATpval(Qs[k], Lamk[[k]], acc=1e-3)
}
minp = min(pval)
## sim
## if( (minp<1e-9)|(minp>1e-8) ) return( list(p.value=c(minp*2.5,pval[c(1,K)]), pval=pval, rho.est=rho[which.min(pval)]) )
qval = rep(0,L1)
for(k in 1:L1) qval[k] = Liu0.qval(minp, Lamk[[k]])
V1 = P1 - P2*R2/R1^2
Lame = eigen(V1, sym=TRUE, only.val=TRUE)$val
##
rho1 = rho[-L]
tau1 = (1-rho1)*R2/R1^2+rho1
fint = function(xu){
sapply(xu, function(x){
x1 = min( (qval-tau1*x^2*R1)/(1-rho1) )
p1 = KATpval(x1,Lame, acc=1e-3)
p1*dnorm(x)
})
}
qkh = -qnorm(minp/2); prec = 1e-5
p.value = try({ minp + 2*integrate(fint, 0,qkh, subdivisions=1e3,abs.tol=minp*prec)$val }, silent=TRUE)
while(class(p.value)=='try-error'){
prec = prec*2
p.value = try({ minp + 2*integrate(fint, 0,qkh, abs.tol=minp*prec)$val }, silent=TRUE)
}
ans = c(p.value, pval[rho==0], pval[rho==1])
names(ans) = c('AT', 'VT', 'BT')
return( list(p.value=ans, pval=pval, rho.est=rho[which.min(pval)]) )
}
#' Fixed-effects (FE) meta-analysis of variant-set association
#'
#' Conduct meta-analysis of variant-set association test of m variants assuming constant effects across K studies.
#' These association statistics are typically Score vector, and a direct summation asymptotically amounts to inverse
#' variance weighting. In practice, we typically input weighted test statistics.
#' FE VT: \eqn{(\sum_kU_k)^T(\sum_kU_k)}; FE BT: \eqn{(\sum_k\eta^TU_k)^2}; FAT: adaptively combine FE VT and FE BT.
#'
#' @param Us matrix of variant test statistics (m by K)
#' @param Vs array of covariance matrix for test statistics (mxm by K)
#' @param eta coefficient vector for the FE BT. Default to equal weights.
#' @param rho weights assigned to the FE BT
#' @return
#' \describe{
#' \item{p.value}{ p-values for FAT, FE VT, FE BT }
#' \item{pval}{ vector of p-values for each rho }
#' \item{rho.est}{ optimal rho value leading to the minimum p-value }
#' }
#' @keywords FAT
#' @export
#' @references
#' Wu,B. and Zhao,H. (2018) Efficient and powerful meta-analysis of variant-set association tests using MetaSAT.
#' @examples
#' K = 3; m=10
#' Vs = array(0, dim=c(m,m,K)); Us = matrix(0, m,K)
#' for(k in 1:K){
#' ak = matrix(rnorm(100*m),100,m)*sqrt(0.8)+rnorm(100)*sqrt(0.2)
#' Vs[,,k] = cor(ak)
#' Rh = chol(Vs[,,k])
#' Us[,k] = colSums(Rh*rnorm(m))
#' }
#' FESAT(Us,Vs)
#' U1 = Us + runif(m*K, 0,2)
#' FESAT(U1,Vs)
FESAT <- function(Us,Vs, eta=NULL, rho=(0:10/10)^2){
## summary
U = rowSums(Us); R = apply(Vs, 1:2, sum)
## test
ans = AVAT(U,R, eta, rho)
names(ans$p.value) = c('FAT', 'FE VT', 'FE BT')
return(ans)
}
#' Heterogeneous-effects (HE) meta-analysis of variant-set association
#'
#' Conduct meta-analysis of variant-set association test of m variants assuming heterogeous effects across K studies.
#' HE VT: \eqn{\sum_k U_k^TU_k}; FE BT: \eqn{(\sum_k\eta_k^TU_k)^2}; HAT: adaptively combine HE VT and FE BT.
#'
#' @param Us matrix of variant test statistics (m, K)
#' @param Vs array of covariance matrix for test statistics (m, m, K)
#' @param eta coefficient vector for the FE BT. Default to equal weights.
#' @param rho weights assigned to the FE BT
#' @return
#' \describe{
#' \item{p.value}{ p-values for HAT, HE VT, FE BT }
#' \item{pval}{ vector of p-values for each rho }
#' \item{rho.est}{ optimal rho value leading to the minimum p-value }
#' }
#' @keywords HAT
#' @export
#' @references
#' Wu,B. and Zhao,H. (2018) Efficient and powerful meta-analysis of variant-set association tests using MetaSAT.
#' @examples
#' K = 3; m=10
#' Vs = array(0, dim=c(m,m,K)); Us = matrix(0, m,K)
#' for(k in 1:K){
#' ak = matrix(rnorm(100*m),100,m)*sqrt(0.8)+rnorm(100)*sqrt(0.2)
#' Vs[,,k] = cor(ak)
#' Rh = chol(Vs[,,k])
#' Us[,k] = colSums(Rh*rnorm(m))
#' }
#' HESAT(Us,Vs)
#' U1 = Us + rnorm(m*K)
#' HESAT(U1,Vs)
HESAT <- function(Us,Vs, eta=NULL, rho=(0:10/10)^2){
m = dim(Us)[1]; K = dim(Us)[2]; mK=m*K
if(is.null(eta)){
etah = rep(1,mK)
} else{
etah = rep(eta, K)[1:mK]
}
## summary
Uh = as.vector(Us)
Vh = matrix(0, mK, mK)
for(k in 1:K){
ik = (k-1)*m + 1:m
Vh[ik,ik] = Vs[,,k]
}
## test
ans = AVAT(Uh,Vh, etah, rho)
names(ans$p.value) = c('HAT', 'HE VT', 'FE BT')
return(ans)
}
#' Robust heterogeneous-effects meta-analysis of variant-set association
#'
#' Conduct meta-analysis of variant-set association test of m variants assuming heterogeous effects across K studies.
#' HE VT: \eqn{\sum_k U_k^TU_k}; RHE BT: \eqn{\sum_k(\eta_k^TU_k)^2}; RAT: adaptively combine HE VT and RHE BT.
#'
#' @param Us matrix of variant test statistics (m by K)
#' @param Vs array of covariance matrix for test statistics (m,m by K)
#' @param eta coefficient matrix for variants (m by K). Default to equal weights.
#' @param rho weights assigned to the RHE BT
#' @return
#' \describe{
#' \item{p.value}{ p-values for RAT, HE VT, RHE BT }
#' \item{pval}{ vector of p-values for each rho }
#' \item{rho.est}{ optimal rho value leading to the minimum p-value }
#' }
#' @keywords RAT
#' @export
#' @references
#' Wu,B. and Zhao,H. (2018) Efficient and powerful meta-analysis of variant-set association tests using MetaSAT.
#' @examples
#' K = 3; m=10
#' Vs = array(0, dim=c(m,m,K)); Us = matrix(0, m,K)
#' for(k in 1:K){
#' ak = matrix(rnorm(100*m),100,m)*sqrt(0.8)+rnorm(100)*sqrt(0.2)
#' Vs[,,k] = cor(ak)
#' Rh = chol(Vs[,,k])
#' Us[,k] = colSums(Rh*rnorm(m))
#' }
#' RESAT(Us,Vs)
#' U1 = Us + rnorm(m*K,1,1.25)
#' RESAT(U1,R=Vs)
RESAT <- function(Us,Vs, eta=NULL, rho=(0:10/10)^2){
m = dim(Us)[1]; K = dim(Us)[2]; mK=m*K
if(is.null(eta)){
etas = matrix(1, m,K)
} else{
etas = matrix(rep(eta, K)[1:mK], m,K)
}
R1 = R2 = rep(0, K)
for(k in 1:K){
a1 = colSums(Vs[,,k]*etas[,k])
R1[k] = sum(a1*etas[,k])
R2[k] = sum(a1^2)
}
##
Q = sum(Us^2); B = colSums(Us*etas)
Qs = (1-rho)*Q + rho*sum(R2/R1^2*B^2)
L = length(rho); rho1 = rho[-L]
Lamk = vector('list', L)
Lame = NULL
for(k in 1:K){
Rk = Vs[,,k]; eta = etas[,k]
eR = eigen(Rk, sym=TRUE); D = sqrt(abs(eR$val))
U1 = colSums(eR$vec*eta)*D
P1 = diag(D^2); P2 = outer(U1,U1)
for(j in 1:L){
ak = (1-rho[j])*P1 + rho[j]*R2[k]/R1[k]^2*P2
aae = zapsmall( abs( eigen(ak,sym=TRUE,only.val=TRUE)$val ) )
Lamk[[j]] = c(Lamk[[j]], aae[aae>0])
}
V1 = P1 - P2*R2[k]/R1[k]^2
Lame = c(Lame, eigen(V1, sym=TRUE, only.val=TRUE)$val )
}
pval = rep(1,L)
for(j in 1:L) pval[j] = KATpval(Qs[j], Lamk[[j]], acc=1e-3)
minp = min(pval)
## sim
## if( (minp<1e-9)|(minp>1e-8) ) return( list(p.value=c(minp*2.5,pval[c(1,L)]), pval=pval, rho.est=rho[which.min(pval)]) )
L1 = L-1
qval = rep(0,L1)
for(j in 1:L1) qval[j] = Liu0.qval(minp, Lamk[[j]])
##
Lamb = R2/R1; q2 = Liu0.qval(minp, Lamb) ## q2 = KATqval(minp, Lamb)
B = 1e3
q2x = seq(0, q2, length=B)
p2x = KATpval(q2x, Lamb, acc=1e-3)
q1x = sapply(q2x, function(x) min( (qval-x)/(1-rho1) ) )
p1x = KATpval(q1x, Lame, acc=1e-3)
p.val = minp - sum( diff(p2x)*(p1x[-1]+p1x[-B])/2 )
ans = c(p.val, pval[rho==0], pval[rho==1])
names(ans) = c('RAT', 'HE VT', 'RHE BT')
return( list(p.value=ans, pval=pval, rho.est=rho[which.min(pval)]) )
}
#' Adaptive variant-set association test based on FE and RHE meta-analysis models
#'
#' Conduct meta-analysis of variant-set association test of m variants assuming similar effects across variants.
#' RHE BT: \eqn{\sum_k(\eta_k^TU_k)^2}; FE BT: \eqn{(\sum_k\eta_k^TU_k)^2}; BAT: adaptively combine RHE BT and FE BT.
#'
#' @param Us matrix of variant test statistics (m by K)
#' @param Vs array of covariance matrix for test statistics (m,m by K)
#' @param eta coefficient matrix for variants (m by K). Default to equal weights.
#' @param rho weights assigned to the FE BT
#' @return
#' \describe{
#' \item{p.value}{ p-values for BAT, RHE BT, FE BT }
#' \item{pval}{ vector of p-values for each rho }
#' \item{rho.est}{ optimal rho value leading to the minimum p-value }
#' }
#' @keywords BAT
#' @export
#' @references
#' Wu,B. and Zhao,H. (2018) Efficient and powerful meta-analysis of variant-set association tests using MetaSAT.
#' @examples
#' K = 3; m=10
#' Vs = array(0, dim=c(m,m,K)); Us = matrix(0, m,K)
#' for(k in 1:K){
#' ak = matrix(rnorm(100*m),100,m)*sqrt(0.8)+rnorm(100)*sqrt(0.2)
#' Vs[,,k] = cor(ak)
#' Rh = chol(Vs[,,k])
#' Us[,k] = colSums(Rh*rnorm(m))
#' }
#' RBAT(Us,Vs)
#' U1 = Us + rnorm(m*K,1,1.25)
#' RBAT(U1,Vs)
RBAT <- function(Us,Vs, eta=NULL, rho=(0:10/10)^2){
m = dim(Us)[1]; K = dim(Us)[2]; mK=m*K
if(is.null(eta)){
etas = matrix(1, m,K)
} else{
etas = matrix(rep(eta, K)[1:mK], m,K)
}
## summary
R1 = R2 = rep(0, K)
for(k in 1:K){
a1 = colSums(Vs[,,k]*etas[,k])
R1[k] = sum(a1*etas[,k])
R2[k] = sum(a1^2)
}
## BAT
R = R2/R1; etau = R1/sqrt(R2)
U = colSums(Us*etas)/etau
## ans = AVAT(U,diag(R),etau, rho=rho)
ans = AVATi(U,R,etau, rho=rho)
names(ans$p.value) = c('BAT', 'RHE BT', 'FE BT')
return(ans)
}
## Reference implementation
RBAT0 <- function(Us,Vs, eta=NULL, rho=(0:10/10)^2){
m = dim(Us)[1]; K = dim(Us)[2]; mK=m*K
if(is.null(eta)){
etas = matrix(1, m,K)
} else{
etas = matrix(rep(eta, K)[1:mK], m,K)
}
## summary
R1 = rep(0, K)
for(k in 1:K){
a1 = colSums(Vs[,,k]*etas[,k])
R1[k] = sum(a1*etas[,k])
}
U = colSums(Us*etas)
## test
## ans = AVAT(U,diag(R1), rho=rho)
ans = AVATi(U,R1, rho=rho)
names(ans$p.value) = c('BAT0', 'RHE BT', 'FE BT')
return(ans)
}
## internal func: combining independent tests.
AVATi <- function(U,Ri, eta=NULL, rho=(0:10/10)^2){
m = length(U)
if(is.null(eta)) eta = rep(1,m)
Q = sum(U^2); B = sum(U*eta)
Qs = (1-rho)*Q + rho*B^2
##
U1 = eta*sqrt(Ri)
P1 = diag(Ri); P2 = outer(U1,U1)
R1 = sum(eta^2*Ri); R2 = sum(eta^2*Ri^2)
## min-pval
L = length(rho); L1 = L-1
pval = rep(1,L)
pval[L] = pchisq(B^2/R1, 1, lower=FALSE)
Lamk = vector('list', L1)
for(k in 1:L1){
ak = (1-rho[k])*P1 + rho[k]*P2
aae = zapsmall( abs( eigen(ak,sym=TRUE,only.val=TRUE)$val ) )
Lamk[[k]] = aae[aae>0]
pval[k] = KATpval(Qs[k], Lamk[[k]], acc=1e-3)
}
minp = min(pval)
## sim ## if( (minp<1e-9)|(minp>1e-8) ) return( list(p.value=c(minp*2.5,pval[c(1,K)]), pval=pval, rho.est=rho[which.min(pval)]) )
qval = rep(0,L1)
for(k in 1:L1) qval[k] = Liu0.qval(minp, Lamk[[k]])
V1 = P1 - P2*R2/R1^2
Lame = eigen(V1, sym=TRUE, only.val=TRUE)$val
##
rho1 = rho[-L]
tau1 = (1-rho1)*R2/R1^2+rho1
fint = function(xu){
sapply(xu, function(x){
x1 = min( (qval-tau1*x^2*R1)/(1-rho1) )
p1 = KATpval(x1,Lame, acc=1e-3)
p1*dnorm(x)
})
}
qkh = -qnorm(minp/2); prec = 1e-5
p.value = try({ minp + 2*integrate(fint, 0,qkh, subdivisions=1e3,abs.tol=minp*prec)$val }, silent=TRUE)
while(class(p.value)=='try-error'){
prec = prec*2
p.value = try({ minp + 2*integrate(fint, 0,qkh, abs.tol=minp*prec)$val }, silent=TRUE)
}
ans = c(p.value, pval[rho==0], pval[rho==1])
names(ans) = c('AT', 'VT', 'BT')
return( list(p.value=ans, pval=pval, rho.est=rho[which.min(pval)]) )
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.