##############################################################################
# calculate the moderated profile likelihood
##############################################################################
#' @importFrom stats loess predict loess.control
dm_profileLikModeration <- function(loglik, mean_expression,
prec_moderation = "trended", prec_prior_df, prec_span){
prec_grid_length <- ncol(loglik)
### Check where the grid is maximized
grid_max <- apply(loglik, 1, which.max)
# In the calculation of moderation, do not take into account genes
# that have precision on the top and bottom boundry of the grid
# (skipp 4 last grid points and 1 first grid point)
not_boundry <- grid_max < (prec_grid_length - 3) & grid_max > 1
boundry_last <- grid_max == prec_grid_length
### Calculate the span of the boundry loglikelihoods
if(sum(boundry_last) > 1){
loglik_span_boundry <- apply(loglik[boundry_last, , drop = FALSE], 1,
function(x){max(x) - min(x)})
}
switch(prec_moderation,
common={
### Calculate the moderating likelihood
if(sum(not_boundry) == length(not_boundry)){
moderation <- colMeans(loglik)
}else{
moderation <- colMeans(loglik[not_boundry, , drop = FALSE])
}
# Estimate priorN - calculate the ratio between moderation lik span
# and lik span of boundry genes
if(sum(boundry_last) > 10){
moderation_span <- max(moderation) - min(moderation)
span_ratio <- moderation_span / loglik_span_boundry
priorN <- 1/span_ratio
### Use median
priorN <- quantile(priorN, 0.5)
}else{
priorN <- prec_prior_df
}
message(paste0("! Using ", round(priorN, 4),
" as a shrinkage factor !\n"))
loglik <- sweep(loglik, 2, priorN * moderation, FUN = "+")
},
trended={
moderation <- dm_movingAverageByCol(loglik = loglik,
mean_expression = mean_expression, not_boundry = not_boundry,
prec_span = prec_span)
# Estimate priorN - calculate the ratio between moderation lik span
# and lik span of boundry genes
if(sum(boundry_last) > 10){
moderation_span_boundry <- apply(
moderation[boundry_last, , drop = FALSE], 1,
function(x){max(x) - min(x)})
span_ratio <- moderation_span_boundry / loglik_span_boundry
priorN <- 1/span_ratio
### Do loess fitting if there is enough points. Otherwise, use median
if(length(loglik_span_boundry) > 100){
df_priorN_loglog <- data.frame(priorN = log10(priorN),
mean_expression = log10(mean_expression[boundry_last]))
priorN_loess_loglog <- loess(priorN ~ mean_expression,
df_priorN_loglog, control = loess.control(surface = "direct"))
priorN_predict_loglog <- predict(priorN_loess_loglog,
data.frame(mean_expression = log10(mean_expression)), se = FALSE)
priorN <- 10 ^ priorN_predict_loglog
}else{
priorN <- quantile(priorN, 0.5)
}
}else{
priorN <- prec_prior_df
}
if(length(priorN) == 1){
message(paste0("! Using ", round(priorN, 6),
" as a shrinkage factor !\n"))
}else{
message(paste0("! Using loess fit as a shrinkage factor !\n"))
}
loglik <- loglik + priorN * moderation
}
)
return(loglik)
}
dm_movingAverageByCol <- function(loglik, mean_expression,
not_boundry, prec_span){
if(sum(not_boundry) == length(not_boundry)){
o <- order(mean_expression)
oo <- order(o)
width <- floor(prec_span * nrow(loglik))
moderation <- edgeR::movingAverageByCol(loglik[o,], width = width)[oo,]
}else{
### Use non boundry genes for calculating the moderation
mean_expression_not_boundry <- mean_expression[not_boundry]
loglik_not_boundry <- loglik[not_boundry, , drop = FALSE]
o <- order(mean_expression_not_boundry)
oo <- order(o)
width <- floor(prec_span * nrow(loglik_not_boundry))
moderation_not_boundry <- edgeR::movingAverageByCol(
loglik_not_boundry[o, , drop = FALSE], width = width)[oo, , drop = FALSE]
### Fill in moderation values for the boundy genes
moderation <- matrix(NA, nrow = nrow(loglik), ncol = ncol(loglik))
moderation[not_boundry, ] <- moderation_not_boundry
o <- order(mean_expression)
oo <- order(o)
moderation <- moderation[o, , drop = FALSE]
not_boundry <- not_boundry[o]
### Last value in not_boundry must be TRUE
if(not_boundry[length(not_boundry)] == FALSE){
last_true <- max(which(not_boundry))
moderation[length(not_boundry), ] <- moderation[last_true, ]
not_boundry[length(not_boundry)] <- TRUE
}
not_boundry_diff <- diff(not_boundry, lag = 1)
not_boundry_cumsum <- cumsum(not_boundry)
### Values used for filling in the boundry NAs - swith from FALSE to TRUE
replacement_indx <- which(not_boundry_diff == 1) + 1
replaced_indx <- which(!not_boundry)
replaced_freq <- as.numeric(table(not_boundry_cumsum[replaced_indx]))
moderation_boundry <- moderation[rep(replacement_indx,
times = replaced_freq), , drop = FALSE]
moderation[!not_boundry, ] <- moderation_boundry
moderation <- moderation[oo, , drop = FALSE]
}
return(moderation)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.