#' @title Contact map insulation
#' @name getDiamondInsulation
#' @rdname getDiamondInsulation
#' @description
#'
#' Computes diamond insulation score along the entire genome
#'
#' @param x A `HiCExperiment` object over a full genome
#' @param window_size Which window size to use to compute diamond insulation
#' score (default: 10 * resolution)
#' @param weak_threshold Less stringent cutoff to call borders in the
#' diamond insulation score
#' @param strong_threshold More stringent cutoff to call borders in the
#' diamond insulation score
#' @param BPPARAM BiocParallel parallelization settings
#' @return a `HiCExperiment` object with additional `insulation` metadata,
#' containing the diamond insulation score computed
#'
#' @importFrom Matrix sparseMatrix
#' @export
#' @examples
#' library(HiContacts)
#' hic <- contacts_yeast() |>
#' refocus('II:1-300000') |>
#' zoom(1000)
#' diams <- getDiamondInsulation(hic)
#' getDiamondInsulation(diams)
getDiamondInsulation <- function(
x,
window_size = NULL,
BPPARAM = BiocParallel::bpparam()
) {
message( "Going through preflight checklist..." )
# - Check resolutions
si <- seqinfo(x)
resolution <- resolution(x)
if(is.null(window_size)) window_size <- 8 * resolution
ress <- resolutions(x)
if (!resolution %in% ress) stop("Chosen resolution not available")
if (!window_size %in% ress) stop("Chosen window_size not available")
fact <- window_size / resolution
cm <- gi2cm(interactions(x), 'balanced')
cm_mat <- as.matrix(cm)
# - Scan each bin individually
message( "Scan each window and compute diamond insulation score..." )
idx_ids <- seq(fact+1, nrow(cm)-fact-1)
scores <- BiocParallel::bplapply(BPPARAM = BPPARAM,
idx_ids,
function(idx) {
# Extract matrix from chr-level, centered on idx
mat <- cm_mat[seq(idx-fact, idx+fact), seq(idx-fact, idx+fact)]
# Extract top-right quadrant
mat_trq <- mat[seq(1, fact) + 1 - 1, seq(fact, fact + fact - 1) + 1 + 1]
sum(mat_trq,na.rm = TRUE)
}
) |> unlist()
fbins <- regions(cm)[idx_ids]
fbins$score <- scores
fbins$insulation <- log2( scores / mean(scores) )
fbins <- fbins[!is.na(fbins$insulation)]
# - Annotate boundaries
message( "Annotating diamond score prominence for each window..." )
mins <- which(diff(sign(diff(fbins$insulation)))==+2)+1
maxs <- which(diff(sign(diff(fbins$insulation)))==-2)+1
if (length(maxs) < length(mins)) maxs[[length(maxs)+1]] <- length(fbins)
if (length(maxs) > length(mins)) maxs <- utils::tail(maxs, -1)
fbins$min <- seq_along(fbins) %in% mins
fbins$prominence <- NA
fbins$prominence[fbins$min] <- -{fbins$insulation[fbins$min] - fbins$insulation[seq_along(fbins) %in% maxs]}
## -- Return initial HiCExperiment object with insulation in metadata
metadata(x)$insulation <- fbins
return(x)
}
#' @rdname getDiamondInsulation
#' @export
getBorders <- function(x, weak_threshold = 0.2, strong_threshold = 0.5) {
fbins <- metadata(x)$insulation
fbins$border <- fbins$prominence >= weak_threshold & fbins$min
fbins$type <- ifelse(fbins$prominence < weak_threshold, NA, ifelse(fbins$prominence < strong_threshold, 'weak', 'strong'))
gr <- fbins[which(fbins$border)]
gr$score <- gr$prominence
names(gr) <- gr$type
S4Vectors::mcols(gr) <- data.frame(score = gr$score)
topologicalFeatures(x, 'borders') <- gr
return(x)
}
.getDiamondScore <- function(cm, bin, fact) {
ids <- seq(bin$bin_id - fact, bin$bin_id + fact)
idx_ids <- seq(fact+1, nrow(cm_mat)-fact-1)
balanced <- l[ids+1, ids+1]
s <- sum(
balanced[seq(1, fact) + 1 - 1, seq(fact, fact + fact - 1) + 1 + 1],
na.rm = TRUE
)
return(s)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.