Weighted Cross-Correlation

Issue #959 new
Michael Schwabe created an issue

Hello, similar to issue 888, I modified the dccm.xyz script to calculate a weighted Cross-Correlation and I wanted to check if this looked correct. I changed colMeans to colWeightedMeans from matrixStats and used cov.wt instead of cov.

wdccm.xyz <- function(x, weights, reference = NULL, grpby = NULL, method = c("pearson", "lmi"),
ncore = 1, nseg.scale = 1, ...) {

method = match.arg(method)

xyz <- x
ncore <- setup.ncore(ncore)

if (is.null(reference)) {
ref = colWeightedMeans(xyz, weights)
} else {
ref = reference
}
dxyz <- sweep(xyz, 2, ref)

covmat <- cov.wt(dxyz, wt = weights) # Use cov.wt for weighted covariance

if (!is.null(reference)) {
mxyz <- colWeightedMeans(dxyz, weights)
covmat <- covmat + outer(mxyz, mxyz)
}

ccmat <- .cov2dccm(covmat$cov, method = method, ncore = ncore)

if (is.null(grpby)) {
return(ccmat)
} else {
##- Group by consecutive numbers in 'grpby'
if (ncol(xyz) != (length(grpby) * 3))
stop("dimension miss-match in 'xyz' and 'grpby', check lengths")

##- Bounds of 'grpby' numbers
inds <- bounds(grpby, dup.inds = TRUE)
nres <- nrow(inds)

##- Per-residue matrix
m <- matrix(, ncol = nres, nrow = nres)
ij <- pairwise(nres)

##- Max (absolute value) per residue
for (k in 1:nrow(ij)) {
  m[ij[k, 1], ij[k, 2]] <-
    min(ccmat[(inds[ij[k, 1], "start"]:inds[ij[k, 1], "end"]),
               (inds[ij[k, 2], "start"]:inds[ij[k, 2], "end"])],
        na.rm = TRUE)
  tmax <- max(ccmat[(inds[ij[k, 1], "start"]:inds[ij[k, 1], "end"]),
                    (inds[ij[k, 2], "start"]:inds[ij[k, 2], "end"])],
              na.rm = TRUE)
  if (tmax > abs(m[ij[k, 1], ij[k, 2]])) m[ij[k, 1], ij[k, 2]] = tmax
}
m[lower.tri(m)] = t(m)[lower.tri(m)]
diag(m) <- 1

class(m) <- c("dccm", "matrix")
return(m)

}
}
.cov2dccm <- function(vcov, method = c("pearson", "lmi"), ncore = NULL) {
method = match.arg(method)

ncore = setup.ncore(ncore)
if(ncore == 1) mclapply = lapply

x <- vcov
ccmat = switch(method,
pearson = {
n <- nrow(x)
np <- pairwise(n/3)

               d <- sqrt(colSums(matrix(diag(x), nrow=3)))

               ltv <- mclapply(1:nrow(np), function(i) {
                 i1 <- (np[i, 2] - 1) * 3 + 1
                 i2 <- (np[i, 1] - 1) * 3 + 1
                 sum(diag(x[i1:(i1+2), i2:(i2+2)]))/ # sum of diagnol of submatrix
                   (d[np[i, 2]] * d[np[i, 1]])   # divided by product of standard deviations
               } )

               ccmat <- matrix(0, n/3, n/3)
               ccmat[lower.tri(ccmat)] <- unlist(ltv)

               # make full matrix
               ccmat <- ccmat + t(ccmat)
               diag(ccmat) <- 1
               ccmat
             },
             lmi = {
               # rm:r-value matrix
               cm <- x
               l <- dim(cm)[1]/3
               rm <- matrix(nrow=l, ncol=l)
               d <- 3
               ij <- pairwise(l)

               # list1: marginal-covariance 
               list1 <- mclapply(1:l, function(i) det(cm[(3*i-2):(3*i), (3*i-2):(3*i)]) )
               dm <- unlist(list1)

               # list2: pair-covariance
               list2 <- mclapply(1:nrow(ij), function(i) {
                 x <- det(cm[c((3*ij[i,1]-2):(3*ij[i,1]),(3*ij[i,2]-2):(3*ij[i,2])), c((3*ij[i,1]-2):(3*ij[i,1]),(3*ij[i,2]-2):(3*ij[i,2]))])
                 y <- 1/2 * (log(dm[ij[i,1]]) + log(dm[ij[i,2]]) - log(x))
                 (1 - exp(-2 * y / d))^(1/2)
               }
               )
               list2 <- unlist(list2)

               for (k in 1:nrow(ij)) {
                 rm[ij[k, 1], ij[k, 2]] <- list2[k]
               }
               rm[lower.tri(rm)] = t(rm)[lower.tri(rm)]
               diag(rm) <- 1
               rm
             } )

class(ccmat) = c("dccm", "matrix")
return(ccmat)
}

Thank you for your time,

Michael

Comments (2)

  1. Xinqiu Yao

    I am not familiar with colWeightedMeans(). One thing you need to think about (and probably you have already done) is to make sure the way it uses the weights is the same as cov.wt(). Also, do you need to normalize the weights before using it? Based on ?cov.wt, it seems so, but I am not sure. Btw, thanks for the contribution!

  2. Log in to comment