## ----global_settings, echo = FALSE, message = FALSE-----------------------------------------------
library(markdown)
options(markdown.HTML.options = c(options('markdown.HTML.options')[[1]], "toc"))

library(knitr)
knitr::opts_chunk$set(
    error = FALSE,
    tidy  = FALSE,
    message = FALSE,
    fig.align = "center",
    fig.width = 5,
    fig.height = 5)
options(markdown.HTML.stylesheet = "custom.css")

options(width = 100)

## ----heatmap_annotation, fig.width = 7, fig.height = 0.5------------------------------------------
library(ComplexHeatmap)
library(circlize)

df = data.frame(type = c(rep("a", 5), rep("b", 5)))
ha = HeatmapAnnotation(df = df)
ha
draw(ha, 1:10)

## ----heatmap_annotation_col, fig.width = 7, fig.height = 0.5--------------------------------------
ha = HeatmapAnnotation(df = df, col = list(type = c("a" =  "red", "b" = "blue")))
ha
draw(ha, 1:10)

## ----heatmap_annotation_colfun, fig.width = 7, fig.height = 0.5-----------------------------------
ha = HeatmapAnnotation(df = data.frame(age = sample(1:20, 10)),
    col = list(age = colorRamp2(c(0, 20), c("white", "red"))))
ha
draw(ha, 1:10)

## ---- fig.width = 7, fig.height = 1---------------------------------------------------------------
df2 = data.frame(type = c(rep("a", 5), rep("b", 5)),
                age = sample(1:20, 10))
df2$type[5] = NA
df2$age[5] = NA
ha = HeatmapAnnotation(df = df2, 
  col = list(type = c("a" =  "red", "b" = "blue"),
             age = colorRamp2(c(0, 20), c("white", "red"))),
  na_col = "grey")
draw(ha, 1:10)

## ----heatmap_annotation_mixed, fig.width = 7, fig.height = 1--------------------------------------
df = data.frame(type = c(rep("a", 5), rep("b", 5)),
                age = sample(1:20, 10))
ha = HeatmapAnnotation(df = df,
    col = list(type = c("a" = "red", "b" = "blue"),
               age = colorRamp2(c(0, 20), c("white", "red")))
)
ha
draw(ha, 1:10)

## ----heatmap_annotation_vector, fig.width = 7, fig.height = 1-------------------------------------
ha = HeatmapAnnotation(type = c(rep("a", 5), rep("b", 5)),
                       age = sample(1:20, 10),
    col = list(type = c("a" = "red", "b" = "blue"),
               age = colorRamp2(c(0, 20), c("white", "red")))
)
ha
draw(ha, 1:10)

## ----heatmap_column_annotation--------------------------------------------------------------------
ha1 = HeatmapAnnotation(df = df,
    col = list(type = c("a" = "red", "b" = "blue"),
               age = colorRamp2(c(0, 20), c("white", "red")))
)
ha2 = HeatmapAnnotation(df = data.frame(age = sample(1:20, 10)),
    col = list(age = colorRamp2(c(0, 20), c("white", "red"))))

set.seed(123)
mat = matrix(rnorm(80, 2), 8, 10)
mat = rbind(mat, matrix(rnorm(40, -2), 4, 10))
rownames(mat) = paste0("R", 1:12)
colnames(mat) = paste0("C", 1:10)

Heatmap(mat, top_annotation = ha1, bottom_annotation = ha2)

## ----heatmap_annotation_complex, fig.width = 7, fig.height = 1------------------------------------
value = rnorm(10)
column_anno = function(index) {
    n = length(index)
    # since middle of columns are in 1, 2, ..., n and each column has width 1
    # then the most left should be 1 - 0.5 and the most right should be n + 0.5
    pushViewport(viewport(xscale = c(0.5, n + 0.5), yscale = range(value)))
    # since order of columns will be adjusted by clustering, here we also 
    # need to change the order by `[index]`
    grid.points(index, value[index], pch = 16, default.unit = "native")
    # this is very important in order not to mess up the layout
    upViewport() 
}
ha = HeatmapAnnotation(points = column_anno)  # here the name is arbitrary
ha
draw(ha, 1:10)

## ----heatmap_annotation_points, fig.width = 7, fig.height = 1-------------------------------------
ha = HeatmapAnnotation(points = anno_points(value))
draw(ha, 1:10)

## ----heatmap_annotation_barplot, fig.width = 7, fig.height = 1------------------------------------
ha = HeatmapAnnotation(barplot = anno_barplot(value))
draw(ha, 1:10)

## ----heatmap_annotation_boxplot, fig.width = 7, fig.height = 1------------------------------------
ha = HeatmapAnnotation(boxplot = anno_boxplot(mat))
draw(ha, 1:10)

## ----heatmap_annotation_mixed_with_complex, fig.width = 7, fig.height = 2-------------------------
ha = HeatmapAnnotation(df = df, 
                       points = anno_points(value),
    col = list(type = c("a" = "red", "b" = "blue"),
               age = colorRamp2(c(0, 20), c("white", "red"))))
ha
draw(ha, 1:10)

## ---- fig.width = 7, fig.height = 2---------------------------------------------------------------
ha = HeatmapAnnotation(type = c(rep("a", 5), rep("b", 5)),
                       points = anno_points(value),
                       age = sample(1:20, 10), 
                       bars = anno_barplot(value),
    col = list(type = c("a" = "red", "b" = "blue"),
               age = colorRamp2(c(0, 20), c("white", "red"))))
ha
draw(ha, 1:10)

## ----heatmap_annotation_anno_gp, fig.width = 7, fig.height = 3------------------------------------
ha = HeatmapAnnotation(barplot1 = anno_barplot(value, baseline = 0, gp = gpar(fill = ifelse(value > 0, "red", "green"))),
                       points = anno_points(value, gp = gpar(col = rep(1:2, 5))),
                       barplot2 = anno_barplot(value, gp = gpar(fill = rep(3:4, 5))))
ha
draw(ha, 1:10)

## ---- fig.width = 7, fig.height = 3---------------------------------------------------------------
# set annotation height as relative values
ha = HeatmapAnnotation(df = df, points = anno_points(value), boxplot = anno_boxplot(mat),
    col = list(type = c("a" = "red", "b" = "blue"),
               age = colorRamp2(c(0, 20), c("white", "red"))),
    annotation_height = c(1, 2, 3, 4))
draw(ha, 1:10)

## ---- fig.width = 7, fig.height = 3---------------------------------------------------------------
# set annotation height as absolute units
ha = HeatmapAnnotation(df = df, points = anno_points(value), boxplot = anno_boxplot(mat),
    col = list(type = c("a" = "red", "b" = "blue"),
               age = colorRamp2(c(0, 20), c("white", "red"))),
    annotation_height = unit.c((unit(1, "npc") - unit(4, "cm"))*0.5, (unit(1, "npc") - unit(4, "cm"))*0.5, 
        unit(2, "cm"), unit(2, "cm")))
draw(ha, 1:10)

## ----add_annotation-------------------------------------------------------------------------------
ha = HeatmapAnnotation(df = df, points = anno_points(value),
    col = list(type = c("a" = "red", "b" = "blue"),
               age = colorRamp2(c(0, 20), c("white", "red"))))
ha_boxplot = HeatmapAnnotation(boxplot = anno_boxplot(mat, axis = TRUE))
Heatmap(mat, name = "foo", top_annotation = ha, bottom_annotation = ha_boxplot, 
    bottom_annotation_height = unit(3, "cm"))

## -------------------------------------------------------------------------------------------------
ha = HeatmapAnnotation(df = df, points = anno_points(value), gap = unit(c(2, 4), "mm"),
    col = list(type = c("a" = "red", "b" = "blue"),
               age = colorRamp2(c(0, 20), c("white", "red"))))
Heatmap(mat, name = "foo", top_annotation = ha)

## ----annotation_show------------------------------------------------------------------------------
ha = HeatmapAnnotation(df = df, show_legend = c(FALSE, TRUE),
    col = list(type = c("a" = "red", "b" = "blue"),
               age = colorRamp2(c(0, 20), c("white", "red"))))
Heatmap(mat, name = "foo", top_annotation = ha)

## ----annotation_more, fig.height = 10, fig.width = 7----------------------------------------------
ha_mix_top = HeatmapAnnotation(histogram = anno_histogram(mat, gp = gpar(fill = rep(2:3, each = 5))),
    density_line = anno_density(mat, type = "line", gp = gpar(col = rep(2:3, each = 5))),
    violin = anno_density(mat, type = "violin", gp = gpar(fill = rep(2:3, each = 5))),
    heatmap = anno_density(mat, type = "heatmap"))
Heatmap(mat, name = "foo", top_annotation = ha_mix_top, top_annotation_height = unit(8, "cm"))

## ----rotated_column_names-------------------------------------------------------------------------
long_cn = do.call("paste0", rep(list(colnames(mat)), 3))  # just to construct long text
ha_rot_cn = HeatmapAnnotation(text = anno_text(long_cn, rot = 45, just = "left", offset = unit(2, "mm")))
Heatmap(mat, name = "foo", top_annotation = ha_rot_cn, top_annotation_height = unit(2, "cm"))

## ----row_annotation, fig.width = 1, fig.height = 7------------------------------------------------
df = data.frame(type = c(rep("a", 6), rep("b", 6)))
ha = HeatmapAnnotation(df = df, col = list(type = c("a" = "red", "b" = "blue")),
    which = "row", width = unit(1, "cm"))
draw(ha, 1:12)

## ---- eval = FALSE--------------------------------------------------------------------------------
#  ha = rowAnnotation(df = df, col = list(type = c("a" = "red", "b" = "blue")), width = unit(1, "cm"))

## ---- eval = FALSE--------------------------------------------------------------------------------
#  ha = rowAnnotation(points = anno_points(runif(10), which = "row"))

## ---- fig.width = 3, fig.height = 7---------------------------------------------------------------
ha_combined = rowAnnotation(df = df, boxplot = row_anno_boxplot(mat), 
    col = list(type = c("a" = "red", "b" = "blue")),
    annotation_width = c(1, 3))
draw(ha_combined, 1:12)

## ----heatmap_list_with_row_annotation, fig.width = 9----------------------------------------------
ha = rowAnnotation(df = df, col = list(type = c("a" = "red", "b" = "blue")),
    width = unit(1, "cm"))
ht1 = Heatmap(mat, name = "ht1")
ht2 = Heatmap(mat, name = "ht2")
ht1 + ha + ht2

## ----heatmap_list_with_row_annotation_complex-----------------------------------------------------
ht1 = Heatmap(mat, name = "ht1", km = 2)
ha = rowAnnotation(df = df, col = list(type = c("a" = "red", "b" = "blue")),
    boxplot = row_anno_boxplot(mat, axis = TRUE), 
    annotation_width = unit(c(1, 5), "cm"))
ha + ht1

## ----heatmap_list_with_row_annotation_graphical_parameter-----------------------------------------
ha = rowAnnotation(boxplot = row_anno_boxplot(mat, gp = gpar(fill = c("red", "blue"))), 
    width = unit(2, "cm"))
ha + ht1

## ----heatmap_list_hclust_title_side---------------------------------------------------------------
draw(ha + ht1, row_dend_side = "left", row_sub_title_side = "right")

## -------------------------------------------------------------------------------------------------
value = rowMeans(mat)
row_anno = function(index) {
    n = length(index)
    pushViewport(viewport(xscale = range(value), yscale = c(0.5, n + 0.5)))
    grid.rect()
    # recall row order will be adjusted, here we specify `value[index]`
    grid.points(value[index], seq_along(index), pch = 16, default.unit = "native")
    upViewport()
}
ha = rowAnnotation(points = row_anno, width = unit(1, "cm"))
ht1 + ha

## -------------------------------------------------------------------------------------------------
row_anno = function(index, k) {
    n = length(index)
    col = c("blue", "red")[k]
    pushViewport(viewport(xscale = range(value), yscale = c(0.5, n + 0.5)))
    grid.rect()
    grid.points(value[index], seq_along(index), pch = 16, default.unit = "native", gp = gpar(col = col))
    upViewport()
}
ha = rowAnnotation(points = row_anno, width = unit(1, "cm"))
ht1 + ha

## ----zero_row_heatmap, fig.height = 2-------------------------------------------------------------
ha = HeatmapAnnotation(df = data.frame(value = runif(10), type = rep(letters[1:2], 5)),
    barplot = anno_barplot(runif(10)),
    points = anno_points(runif(10)))
zero_row_mat = matrix(nrow = 0, ncol = 10)
colnames(zero_row_mat) = letters[1:10]
Heatmap(zero_row_mat, top_annotation = ha, column_title = "only annotations")

## ---- fig.height = 5------------------------------------------------------------------------------
ha = HeatmapAnnotation(df = data.frame(value = runif(10), type = rep(letters[1:2], 5)),
    barplot = anno_barplot(runif(10), axis = TRUE),
    points = anno_points(runif(10), axis = TRUE),
    annotation_height = unit(c(0.5, 0.5, 4, 4), "cm"))
zero_row_mat = matrix(nrow = 0, ncol = 10)
colnames(zero_row_mat) = letters[1:10]
ht = Heatmap(zero_row_mat, top_annotation = ha, column_title = "only annotations")
draw(ht, padding = unit(c(2, 20, 2, 2), "mm"))
decorate_annotation("value", {grid.text("value", unit(-2, "mm"), just = "right")})
decorate_annotation("type", {grid.text("type", unit(-2, "mm"), just = "right")})
decorate_annotation("barplot", {
    grid.text("barplot", unit(-10, "mm"), just = "bottom", rot = 90)
    grid.lines(c(0, 1), unit(c(0.2, 0.2), "native"), gp = gpar(lty = 2, col = "blue"))
})
decorate_annotation("points", {
    grid.text("points", unit(-10, "mm"), just = "bottom", rot = 90)
})

## ----all_row_annotations, fig.width = 4-----------------------------------------------------------
ha_boxplot = rowAnnotation(boxplot = row_anno_boxplot(mat), width = unit(3, "cm"))
ha = rowAnnotation(df = df, col = list(type = c("a" = "red", "b" = "blue")), width = unit(2, "cm"))
text = paste0("row", seq_len(nrow(mat)))
ha_text = rowAnnotation(text = row_anno_text(text), width = max_text_width(text))
nr = nrow(mat)
Heatmap(matrix(nrow = nr, ncol = 0), split = sample(c("A", "B"), nr, replace = TRUE)) + 
    ha_boxplot + ha + ha_text

## ----no_heatmap_but_with_cluster, fig.width = 4---------------------------------------------------
dend = hclust(dist(mat))
Heatmap(matrix(nrow = nr, ncol = 0), cluster_rows = dend) + 
    ha_boxplot + ha + ha_text

## -------------------------------------------------------------------------------------------------
df = data.frame(type = c(rep("a", 6), rep("b", 6)))
Heatmap(mat) + rowAnnotation(df = df, col = list(type = c("a" = "red", "b" = "blue")), 
    width = unit(1, "cm"))
Heatmap(mat) + Heatmap(df, name = "type", col = c("a" = "red", "b" = "blue"), 
    width = unit(1, "cm"))

## -------------------------------------------------------------------------------------------------
ha1 = HeatmapAnnotation(b1 = anno_boxplot(mat, axis = TRUE),
    p1 = anno_points(colMeans(mat), axis = TRUE))
ha2 = rowAnnotation(b2 = row_anno_boxplot(mat, axis = TRUE),
    p2 = row_anno_points(rowMeans(mat), axis = TRUE), width = unit(2, "cm"))
Heatmap(mat, top_annotation = ha1, top_annotation_height = unit(2, "cm")) + ha2

## ---- fig.width = 10------------------------------------------------------------------------------
pushViewport(viewport(layout = grid.layout(nr = 1, nc = 2)))
pushViewport(viewport(layout.pos.row = 1, layout.pos.col = 1))
ha = rowAnnotation(boxplot = row_anno_boxplot(mat, axis = TRUE), width = unit(3, "cm"))
ht_list = ha + Heatmap(mat)
draw(ht_list, column_title = "normal axis direction", newpage = FALSE)
upViewport()

pushViewport(viewport(layout.pos.row = 1, layout.pos.col = 2))
ha = rowAnnotation(boxplot = row_anno_boxplot(mat, axis = TRUE, axis_direction = "reverse"), 
    width = unit(3, "cm"))
ht_list = ha + Heatmap(mat)
draw(ht_list, column_title = "reverse axis direction", newpage = FALSE)
upViewport(2)

## -------------------------------------------------------------------------------------------------
foo1 = matrix(abs(rnorm(20)), ncol = 2)
foo1[1, ] = -foo1[1, ]
column_ha = HeatmapAnnotation(foo1 = anno_barplot(foo1, axis = TRUE))
foo2 = matrix(abs(rnorm(24)), ncol = 2)
row_ha = rowAnnotation(foo2 = row_anno_barplot(foo2, axis = TRUE, axis_side = "top",
    gp = gpar(fill = c("red", "blue"))), width = unit(2, "cm"))
Heatmap(mat, top_annotation = column_ha, top_annotation_height = unit(2, "cm"), km = 2) + row_ha

## -------------------------------------------------------------------------------------------------
df = data.frame(type = c(rep("a", 5), rep("b", 5)),
                age = sample(1:20, 10))
value = rnorm(10)
ha = HeatmapAnnotation(df = df, points = anno_points(value, axis = TRUE),
    col = list(type = c("a" = "red", "b" = "blue"),
               age = colorRamp2(c(0, 20), c("white", "red"))),
    annotation_height = unit(c(0.5, 0.5, 2), "cm"),
    show_annotation_name = TRUE,
    annotation_name_offset = unit(2, "mm"),
    annotation_name_rot = c(0, 0, 90))
Heatmap(mat, name = "foo", top_annotation = ha)

## -------------------------------------------------------------------------------------------------
df = data.frame(type = c(rep("a", 6), rep("b", 6)),
                age = sample(1:20, 12))
value = rnorm(12)
ha = rowAnnotation(df = df, points = row_anno_points(value, axis = TRUE),
    col = list(type = c("a" = "red", "b" = "blue"),
               age = colorRamp2(c(0, 20), c("white", "red"))),
    annotation_width = unit(c(0.5, 0.5, 2), "cm"),
    show_annotation_name = c(TRUE, FALSE, TRUE),
    annotation_name_offset = unit(c(2, 2, 8), "mm"),
    annotation_name_rot = c(90, 90, 0))
ht = Heatmap(mat, name = "foo") + ha
draw(ht, padding = unit(c(4, 2, 2, 2), "mm"))

## -------------------------------------------------------------------------------------------------
ha = HeatmapAnnotation(type = df$type,
    col = list(type = c("a" = "red", "b" = "blue")))
Heatmap(mat, bottom_annotation = ha)

## -------------------------------------------------------------------------------------------------
ha = HeatmapAnnotation(type = df$type, 
    colname = anno_text(colnames(mat), rot = 90, just = "right", offset = unit(1, "npc") - unit(2, "mm")),
    col = list(type = c("a" = "red", "b" = "blue")),
    annotation_height = unit.c(unit(5, "mm"), max_text_width(colnames(mat)) + unit(2, "mm")))
Heatmap(mat, show_column_names = FALSE, bottom_annotation = ha)

## -------------------------------------------------------------------------------------------------
mat = matrix(rnorm(10000), nr = 1000)
rownames(mat) = sprintf("%.2f", rowMeans(mat))
subset = sample(1000, 20)
labels = rownames(mat)[subset]
Heatmap(mat, show_row_names = FALSE, show_row_dend = FALSE, show_column_dend = FALSE) + 
rowAnnotation(link = row_anno_link(at = subset, labels = labels),
  width = unit(1, "cm") + max_text_width(labels))
# here unit(1, "cm") is width of segments

## -------------------------------------------------------------------------------------------------
sessionInfo()

