########################################################################################################
# Helpers for Nice Heatmap with Bioconductors ComplexHeamtap
########################################################################################################
.ArchRHeatmap <- function(
mat = NULL,
scale = FALSE,
limits = c(min(mat), max(mat)),
colData = NULL,
color = paletteContinuous(set = "solarExtra", n = 100),
clusterCols = TRUE,
clusterRows = FALSE,
labelCols = FALSE,
labelRows = FALSE,
colorMap = NULL,
useRaster = TRUE,
rasterQuality = 5,
split = NULL,
fontSizeRows = 10,
fontSizeCols = 10,
fontSizeLabels = 8,
colAnnoPerRow = 4,
showRowDendrogram = FALSE,
showColDendrogram = FALSE,
customRowLabel = NULL,
customRowLabelIDs = NULL,
customColLabel = NULL,
customColLabelIDs = NULL,
customLabelWidth = 0.75,
rasterDevice = "png",
padding = 45,
borderColor = NA,
draw = TRUE,
name = "Heatmap"
){
#Packages
.requirePackage("ComplexHeatmap", source = "bioc")
.requirePackage("circlize", source = "cran")
#Z-score
if (scale) {
message("Scaling Matrix..")
mat <- .rowZscores(mat, limit = FALSE)
name <- paste0(name," Z-Scores")
}
#Get A Color map if null
if (is.null(colorMap)) {
colorMap <- .colorMapAnno(colData)
}
#Prepare ColorMap format for Complex Heatmap
if (!is.null(colData)){
colData = data.frame(colData)
colorMap <- .colorMapForCH(colorMap, colData) #change
showLegend <- .checkShowLegend(colorMap[match(names(colorMap), colnames(colData))]) #change
}else {
colorMap <- NULL
showLegend <- NULL
}
#Prepare Limits if needed
breaks <- NULL
if (!is.null(limits)) {
mat[mat > max(limits)] <- max(limits)
mat[mat < min(limits)] <- min(limits)
}else{
limits <- c(round(min(mat),2), round(max(mat),2))
}
#Scale Values 0 - 1
mat <- (mat - min(limits)) / (max(limits) - min(limits))
breaks <- seq(0, 1, length.out = length(color))
color <- circlize::colorRamp2(breaks, color)
if(exists('anno_mark', where='package:ComplexHeatmap', mode='function')){
anno_check_version_rows <- ComplexHeatmap::anno_mark
anno_check_version_cols <- ComplexHeatmap::anno_mark
}else{
anno_check_version_rows <- ComplexHeatmap::row_anno_link
anno_check_version_cols <- ComplexHeatmap::column_anno_link
}
#Annotation Heatmap
if(!is.null(colData) & !is.null(customColLabel)){
message("Adding Annotations..")
if(is.null(customColLabelIDs)){
customColLabelIDs <- colnames(mat)[customColLabel]
}
ht1Anno <- HeatmapAnnotation(
df = colData,
col = colorMap,
show_legend = showLegend,
show_annotation_name = TRUE,
gp = gpar(col = "NA"),
annotation_legend_param =
list(
nrow = min(colAnnoPerRow, max(round(nrow(colData)/colAnnoPerRow), 1))
),
foo = anno_check_version_cols(at = customColLabel, labels = customColLabelIDs, labels_gp = gpar(fontsize = fontSizeLabels))
)
}else if(!is.null(colData)){
message("Adding Annotations..")
ht1Anno <- HeatmapAnnotation(
df = colData,
col = colorMap,
show_legend = showLegend,
show_annotation_name = TRUE,
gp = gpar(col = "NA"),
annotation_legend_param =
list(
nrow = min(colAnnoPerRow, max(round(nrow(colData)/colAnnoPerRow), 1))
)
)
}else if(is.null(colData) & !is.null(customColLabel)){
if(is.null(customColLabelIDs)){
customColLabelIDs <- colnames(mat)[customColLabel]
}
message("Adding Annotations..")
#print(customColLabel)
#print(customColLabelIDs)
#ht1Anno <- columnAnnotation(foo = anno_check_version_cols(
# at = customColLabel, labels = customColLabelIDs),
# width = unit(customLabelWidth, "cm") + max_text_width(customColLabelIDs))
#ht1Anno <- HeatmapAnnotation(foo = anno_mark(at = c(1:4, 20, 60, 1097:1100), labels = month.name[1:10]))
ht1Anno <- HeatmapAnnotation(foo = anno_check_version_cols(at = customColLabel, labels = customColLabelIDs, labels_gp = gpar(fontsize = fontSizeLabels)))
}else{
ht1Anno <- NULL
}
message("Preparing Main Heatmap..")
ht1 <- Heatmap(
#Main Stuff
matrix = as.matrix(mat),
name = name,
col = color,
#Heatmap Legend
heatmap_legend_param =
list(
at = c(0, 1),
labels = c(round(min(limits),2), round(max(limits),2)),
color_bar = "continuous",
legend_direction = "horizontal",
legend_width = unit(3, "cm")
),
rect_gp = gpar(col = borderColor),
#Column Options
show_column_names = labelCols,
cluster_columns = clusterCols,
show_column_dend = showColDendrogram,
clustering_method_columns = "ward.D2",
column_names_gp = gpar(fontsize = fontSizeCols),
column_names_max_height = unit(100, "mm"),
#Row Options
show_row_names = labelRows,
row_names_gp = gpar(fontsize = fontSizeRows),
cluster_rows = clusterRows,
show_row_dend = showRowDendrogram,
clustering_method_rows = "ward.D2",
split = split,
#Annotation
top_annotation = ht1Anno,
#Raster Info
use_raster = useRaster,
raster_device = rasterDevice,
raster_quality = rasterQuality
)
if(!is.null(customRowLabel)){
if(is.null(customRowLabelIDs)){
customRowLabelIDs <- rownames(mat)[customRowLabel]
}
ht1 <- ht1 + rowAnnotation(link =
anno_check_version_rows(at = customRowLabel, labels = customRowLabelIDs, labels_gp = gpar(fontsize = fontSizeLabels)),
width = unit(customLabelWidth, "cm") + max_text_width(customRowLabelIDs))
}
if(draw){
draw(ht1,
padding = unit(c(padding, padding, padding, padding), "mm"),
heatmap_legend_side = "bot",
annotation_legend_side = "bot")
}else{
ht1
}
}
.colorMapForCH <- function(colorMap = NULL, colData = NULL){
colorMap <- colorMap[which(names(colorMap) %in% colnames(colData))]
colorMapCH <- lapply(seq_along(colorMap), function(x){
if(attr(colorMap[[x]],"discrete")){
colorx <- colorMap[[x]]
}else{
vals <- colData[[names(colorMap)[x]]][!is.na(colData[[names(colorMap)[x]]])]
s <- seq(min(vals), max(vals), length.out = length(colorMap[[x]]))
colorx <- circlize::colorRamp2(s, colorMap[[x]])
}
if(any(is.na(names(colorx)))){
names(colorx)[is.na(names(colorx))] <- paste0("NA",seq_along(names(colorx)[is.na(names(colorx))]))
}
return(colorx)
})
names(colorMapCH) <- names(colorMap)
return(colorMapCH)
}
.checkShowLegend <- function(colorMap = NULL, max_discrete = 30){
show <- lapply(seq_along(colorMap), function(x){
if(attr(colorMap[[x]],"discrete") && length(unique(colorMap[[x]])) > max_discrete){
sl <- FALSE
}else{
sl <- TRUE
}
return(sl)
}) %>% unlist
names(show) <- names(colorMap)
return(show)
}
.colorMapAnno <- function(colData = NULL, customAnno = NULL, discreteSet = "stallion", continuousSet = "solarExtra"){
discreteCols <- sapply(colData,function(x) !is.numeric(x))
if(!is.null(customAnno)){
colorMap <- lapply(seq_along(discreteCols),function(x){
if(discreteCols[x]){
colors <- paletteDiscrete(values = colData[[names(discreteCols[x])]], set = discreteSet)
names(colors) <- unique(colData[[names(discreteCols[x])]])
attr(colors, "discrete") <- TRUE
}else{
colors <- paletteContinuous(set = continuousSet)
attr(colors, "discrete") <- FALSE
}
if(length(which(customAnno[,1] %in% names(discreteCols[x]))) > 0){
if(length(which(customAnno[,2] %in% names(colors))) > 0){
customAnnox <- customAnno[which(customAnno[,2] %in% names(colors)),]
colors[which(names(colors) %in% customAnnox[,2])] <- paste0(customAnnox[match(names(colors),customAnnox[,2]),3])
}
}
return(colors)
})
names(colorMap) <- colnames(colData)
return(colorMap)
}else{
colorMap <- lapply(seq_along(discreteCols), function(x){
if(discreteCols[x]){
colors <- paletteDiscrete(values = colData[[names(discreteCols[x])]], set = discreteSet)
names(colors) <- unique(colData[[names(discreteCols[x])]])
attr(colors, "discrete") <- TRUE
}else{
colors <- paletteContinuous(set = continuousSet)
attr(colors, "discrete") <- FALSE
}
return(colors)
})
names(colorMap) <- colnames(colData)
return(colorMap)
}
}
.binarySort <- function(m = NULL, scale = FALSE, cutOff = 1, lmat = NULL, clusterCols = TRUE){
if(is.null(lmat)){
#Compute Row-Zscores
if(scale){
lmat <- sweep(m - rowMeans(m), 1, matrixStats::rowSds(m), `/`)
}else{
lmat <- m
}
lmat <- lmat >= cutOff
}
#Transpose
m <- t(m)
lmat <- t(lmat)
#Identify Column Ordering
if(clusterCols){
hc <- hclust(dist(m))
colIdx <- hc$order
m <- t(m[colIdx,])
lmat <- t(lmat[colIdx,])
}else{
m <- t(m)
lmat <- t(lmat)
hc <- NULL
}
#Identify Row Ordering
rowIdx <- do.call("order", c(as.data.frame(lmat)[seq_len(ncol(lmat))], list(decreasing = TRUE)))
m <- t(m[rowIdx,])
lmat <- t(lmat[rowIdx,])
#Transpose
m <- t(m)
lmat <- t(lmat)
return(list(mat = m, hclust = hc))
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.