熱圖注釋
前面我們介紹了如何繪制聚類熱圖嗤锉,在這一節(jié)我們將介紹如何添加注釋
熱圖的注釋是聚類熱圖的重要組成部分,能夠?qū)釄D的行扼倘、列附加信息添加到熱圖中嗓奢。
ComplexHeatmap
提供了靈活的熱圖注釋功能,可以在熱圖主體的上燎窘、下摹闽、左、右四個方向上添加注釋褐健,且支持自定義注釋圖形付鹿。
熱圖注釋使用 HeatmapAnnotation
類來構(gòu)建,例如
column_ha <- HeatmapAnnotation(
foo1 = runif(10),
bar1 = anno_barplot(runif(10))
)
row_ha <- rowAnnotation(
foo2 = runif(10),
bar2 = anno_barplot(runif(10))
)
其中 rowAnnotation
是行注釋 HeatmapAnnotation(..., which = "row")
的簡便寫法蚜迅,對應(yīng)的也有 columnAnnotation
在這里舵匾,我們分別創(chuàng)建了行列注釋,每個注釋中包含一個顏色條和一個柱狀圖谁不。
注意坐梯,注釋圖形是以 name-value
對的方式指定,即 foo1
表示繪制的圖形名稱刹帕,value
為繪制的內(nèi)容吵血。
如果傳遞的值是向量,則繪制的圖形是 簡單注釋轩拨,而想柱狀圖這種稱為 復(fù)雜注釋
我們可以將這些注釋添加到熱圖中
set.seed(123)
mat <- matrix(rnorm(100), 10)
rownames(mat) <- paste0("R", 1:10)
colnames(mat) <- paste0("C", 1:10)
Heatmap(
mat,
name = "mat",
top_annotation = column_ha,
right_annotation = row_ha
)
其中 top_annotation
践瓷、right_annotation
指定了注釋放置的位置,我們也可以將注釋放置另外兩個位置
Heatmap(
mat,
name = "mat",
bottom_annotation = column_ha,
left_annotation = row_ha
)
熱圖注釋是可以獨立于熱圖而存在的亡蓉,可以使用 +
(水平添加)或 %v%
(豎直添加)將注釋添加到熱圖中
Heatmap(
mat,
name = "mat"
) + row_ha
Heatmap(
mat,
name = "mat"
) %v% column_ha
查看注釋對象信息
> row_ha
A HeatmapAnnotation object with 2 annotations
name: heatmap_annotation_1
position: row
items: 10
width: 15.3514598035146mm
height: 1npc
this object is subsetable
9.96242222222223mm extension on the bottom
name annotation_type color_mapping width
foo2 continuous vector random 5mm
bar2 anno_barplot() 10mm
1. 簡單注釋
簡單注釋是最常用的熱圖注釋晕翠,只需要傳遞一個向量,會將向量的值映射到顏色值砍濒,繪制出一個顏色條淋肾,例如
grid.newpage()
pushViewport(viewport(y = 0.7, height = 0.6, width = 0.8))
ha <- HeatmapAnnotation(foo = 1:10)
draw(ha)
這樣就可以單獨繪制注釋了,為了方便爸邢,除非必要樊卓,后面我們將只貼出注釋的代碼,重要的是知道怎么繪制的就行杠河。
離散型顏色條
ha <- HeatmapAnnotation(
bar = sample(letters[1:3], 10, replace = TRUE)
)
這些顏色是隨機的碌尔,每次運行的結(jié)果都不一樣,如果要固定顏色券敌,需要用到 col
參數(shù)
library(circlize)
col_fun <- colorRamp2(
c(0, 5, 10),
c("#ff7f00", "white", "#1f78b4")
)
ha <- HeatmapAnnotation(
foo = 1:10,
col = list(
foo = col_fun
)
)
注意:col
參數(shù)的值是一個 list
唾戚,這意味著,如果有多個注釋圖形待诅,可以分別為不同的圖形指定顏色
例如叹坦,我們添加離散型數(shù)據(jù)
ha <- HeatmapAnnotation(
foo = 1:10,
bar = sample(letters[1:3], 10, replace = TRUE),
col = list(
foo = col_fun,
bar = c("a" = "red", "b" = "green", "c" = "blue")
)
)
NA
值可以的顏色使用 na_col
參數(shù)來設(shè)置
ha <- HeatmapAnnotation(
foo = c(1:4, NA, 6:10),
bar = c(sample(letters[1:3], 4, replace = TRUE), NA, sample(letters[1:3], 5, replace = TRUE)),
col = list(
foo = col_fun,
bar = c("a" = "red", "b" = "green", "c" = "blue")
),
na_col = "black"
)
設(shè)置圖形屬性
ha <- HeatmapAnnotation(
foo = 1:10,
bar = sample(letters[1:3], 10, replace = TRUE),
col = list(
foo = col_fun,
bar = c("a" = "red", "b" = "green", "c" = "blue")
),
gp = gpar(col = "black")
)
簡單注釋也可以接受一個數(shù)值或字符矩陣,傳入的矩陣的列對應(yīng)于列注釋的行卑雁,例如
ha <- HeatmapAnnotation(
foo = cbind(a = runif(10), b = runif(10))
)
如果矩陣沒有列名募书,則會將參數(shù)名放置在注釋的中間
ha <- HeatmapAnnotation(
foo = cbind(runif(10), runif(10))
)
可以將一個數(shù)據(jù)框傳遞給 df
參數(shù)
ha <- HeatmapAnnotation(
df = data.frame(
foo = 1:10,
bar = sample(letters[1:3], 10, replace = TRUE)
)
)
混合使用
ha <- HeatmapAnnotation(
df = data.frame(
foo = 1:10,
bar = sample(letters[1:3], 10, replace = TRUE)
),
foo2 = rnorm(10),
col = list(
foo = col_fun,
bar = c("a" = "red", "b" = "green", "c" = "blue")
)
)
使用 border = TRUE
來添加單個注釋的框線
ha <- HeatmapAnnotation(
df = data.frame(
foo = 1:10,
bar = sample(letters[1:3], 10, replace = TRUE)
),
foo2 = cbind(rnorm(10), rnorm(10)),
col = list(
foo = col_fun,
bar = c("a" = "red", "b" = "green", "c" = "blue")
),
border = TRUE
)
注意:矩陣型和數(shù)據(jù)框型的區(qū)別绪囱,矩陣表示的是一個注釋,而數(shù)據(jù)框的每個變量都是一個注釋
所有單個注釋的高度是一樣的莹捡,使用 simple_anno_size
來設(shè)置單個注釋的高度
ha <- HeatmapAnnotation(
df = data.frame(
foo = 1:10,
bar = sample(letters[1:3], 10, replace = TRUE)
),
col = list(
foo = col_fun,
bar = c("a" = "red", "b" = "green", "c" = "blue")
),
simple_anno_size = unit(1, "cm")
)
也可以設(shè)置全局變量 ht_opt$simple_anno_size
的值來控制單個注釋的大小
2. 注釋函數(shù)
HeatmapAnnotation
支持將注釋作為一個函數(shù)鬼吵,注釋函數(shù)定義了如何在指定的位置繪制相應(yīng)的圖片。
ComplexHeatmap
定義了許多注釋函數(shù)道盏,還可以自定義自己的注釋函數(shù)
所有注釋函數(shù)都是 anno_*()
的形式而柑,不需要指定要將其繪制在什么位置,它會自動檢測該放置在行還是列上荷逞。
上述的簡單注釋,都是隱式的使用了 anno_simple()
函數(shù)粹排,直接使用 anno_simple()
不會自動生成圖例种远,在后面的章節(jié)我們將會介紹如何繪制圖例
例如
ha <- HeatmapAnnotation(
foo = anno_simple(1:10)
)
等價于
ha <- HeatmapAnnotation(
foo = 1:10
)
anno_simple()
可以在注釋中添加額外的點或單字母字符,并通過 pch
, pt_gp
和 pt_size
參數(shù)來控制
ha <- HeatmapAnnotation(
foo = anno_simple(
1:10,
pch = 1,
pt_gp = gpar(col = "red"),
pt_size = unit(1:10, "mm"))
)
將 pch
設(shè)置為向量
ha <- HeatmapAnnotation(
foo = anno_simple(
1:10,
pch = 1:10
)
)
將 pch
設(shè)置為字符向量
ha <- HeatmapAnnotation(
foo = anno_simple(
1:10,
pch = sample(letters[1:3], 10, replace = TRUE)
)
)
如果 pch
值向量中有 NA
值顽耳,則什么也不會畫
ha <- HeatmapAnnotation(
foo = anno_simple(
1:10,
pch = c(1:4, NA, 6:8, NA, 10, 11)
)
)
如果 anno_simple()
函數(shù)的值是矩陣坠敷,那么 pch
的長度與矩陣的行數(shù)、列數(shù)或矩陣的長度一致
例如射富,pch
與列數(shù)一致
ha <- HeatmapAnnotation(
foo = anno_simple(
cbind(1:10, 10:1),
pch = 1:2
)
)
pch
對應(yīng)行數(shù)
ha <- HeatmapAnnotation(
foo = anno_simple(
cbind(1:10, 10:1),
pch = 1:10
)
)
pch
為矩陣
pch <- matrix(1:20, nc = 2)
pch[sample(length(pch), 10)] <- NA
ha <- HeatmapAnnotation(
foo = anno_simple(
cbind(1:10, 10:1),
pch = pch
)
)
anno_simple()
也有 simple_anno_size
參數(shù)膝迎,用于控制單個注釋的高度,height/width
參數(shù)用于控制簡單注釋的高度和寬度
ha <- HeatmapAnnotation(
foo = anno_simple(
1:10,
height = unit(2, "cm")
)
)
ha <- HeatmapAnnotation(
foo = anno_simple(
cbind(1:10, 10:1),
simple_anno_size = unit(2, "cm")
)
)
注意:
應(yīng)該在 anno_*()
函數(shù)內(nèi)設(shè)置 width
和 height
胰耗。HeatmapAnnotation()
函數(shù)內(nèi)的 width
, height
, annotation_width
和 annotation_height
參數(shù)是用來設(shè)置多熱圖的大小
3. 空注釋
anno_empty()
函數(shù)用于繪制一個空白占位符限次,可以在之后使用 decorate_annotation()
函數(shù)將自定義圖形添加到該空白處
anno = anno_empty()
draw(anno, test = "anno_empty")
下面我們舉一個簡單的例子,decoration
函數(shù)的具體介紹將放在后面
有時候柴灯,我們想根據(jù)基因所在的通路對基因進行分組卖漫,我們將文本注釋放置在熱圖的右邊,同時添加顏色柱形
group <- list(
A = "Cell cycle",
B = "DNA replication",
C = "Mismatch repair",
D = "MAPK signaling pathway"
)
ha = rowAnnotation(
foo = anno_empty(
border = FALSE,
# 計算空白注釋的寬度
width = max_text_width(unlist(group)) + unit(4, "mm"))
)
Heatmap(matrix(
rnorm(1000), nrow = 100),
name = "mat",
# 分 4 塊
row_km = 4,
right_annotation = ha
)
for(i in 1:4) {
decorate_annotation(
"foo",
# 選擇熱圖塊
slice = i, {
# 添加顏色框
grid.rect(
x = 0,
width = unit(2, "mm"),
gp = gpar(
fill = rainbow(4)[i],
col = NA
),
just = "left"
)
# 繪制文本
grid.text(
group[[i]],
x = unit(4, "mm"),
gp = gpar(
col = rainbow(4)[i]
),
just = "left")
})
}
在來個例子吧赠群,我們使用 decorate_annotation
函數(shù)來繪制一個散點圖
ha <- HeatmapAnnotation(
foo = anno_empty(
border = TRUE,
# 固定注釋的高度
height = unit(3, "cm"))
)
ht <- Heatmap(
matrix(rnorm(100), nrow = 10),
name = "mat",
top_annotation = ha
)
# 先繪制熱圖
ht <- draw(ht)
# 獲取熱圖的列順序
co <- column_order(ht)
# 生成 10 個均勻分布的隨機值
value <- runif(10)
# 將空白裝飾一下
decorate_annotation("foo", {
# 對應(yīng)于矩陣的列
x = 1:10
# 根據(jù)列順序重排這些隨機值羊始,用于設(shè)置 y 軸的值
value = value[co]
# 添加 viewport
pushViewport(
viewport(
# x 軸范圍
xscale = c(0.5, 10.5),
# y 軸范圍
yscale = c(0, 1))
)
# 在中間添加一條水平虛線
grid.lines(
c(0.5, 10.5), c(0.5, 0.5),
gp = gpar(lty = 2),
default.units = "native"
)
# 添加點
grid.points(
x, value,
pch = 16,
size = unit(2, "mm"),
gp = gpar(
# 虛線上下的值設(shè)置不同顏色
col = ifelse(value > 0.5, "red", "blue")),
default.units = "native"
)
# 設(shè)置 y 軸斷點
grid.yaxis(at = c(0, 0.5, 1))
popViewport()
})
雖然代碼比較長,但是還是很簡單的查描。當然突委,你首先得看懂我前面說的 grid
系統(tǒng)是個什么東西
獲取代碼:https://github.com/dxsbiocc/learn/blob/main/R/plot/decorate_example.R
4. 塊注釋
塊注釋也就是添加一個顏色條,用于標識不同的分組冬三,例如
Heatmap(
matrix(rnorm(100), 10),
name = "mat",
top_annotation = HeatmapAnnotation(
foo = anno_block(
gp = gpar(fill = 2:4))
),
column_km = 3
)
可以在每個塊中添加文本注釋
Heatmap(
matrix(rnorm(100), 10),
column_km = 3,
# 添加上方注釋
top_annotation = HeatmapAnnotation(
foo = anno_block(
# 設(shè)置填充色
gp = gpar(fill = 2:4),
# 設(shè)置文本標簽
labels = c("group1", "group2", "group3"),
# 文本標簽樣式
labels_gp = gpar(col = "white", fontsize = 10)
)
),
row_km = 3,
# 設(shè)置左邊注釋
left_annotation = rowAnnotation(
foo = anno_block(
gp = gpar(fill = 2:4),
labels = c("group1", "group2", "group3"),
labels_gp = gpar(col = "white", fontsize = 10))
)
)
記住:標簽和圖形參數(shù)的長度必須與熱圖塊的數(shù)量一致
anno_block()
函數(shù)只能為一個切片繪制一個顏色塊匀油,那如果分組是兩個層級呢?比如长豁,基因有與之相關(guān)的通路钧唐,通路又可以分為信號通路、細胞進程等
例如
set.seed(123)
mat <- matrix(
rnorm(50*50),
nrow = 50
)
group <- c(
"MAPK",
"PI3K-Akt",
"ErbB",
"Cell cycle",
"Apoptosis"
)
ha <- HeatmapAnnotation(
foo = anno_block(
gp = gpar(
fill = 2:6,
fontsize = 10),
labels = group
)
)
split = rep(1:5, each = 10)
Heatmap(
mat, name = "mat",
column_split = split,
top_annotation = ha,
column_title = NULL
)
現(xiàn)在匠襟,我們想再添加一個塊注釋钝侠,標識前三個為信號通路该园,后兩個為細胞進程通路
該怎么添加呢?要繪制圖形帅韧,首先要有個位置來繪制圖片里初,那可不可以先在上方添加一個空白的注釋
ha <- HeatmapAnnotation(
empty = anno_empty(border = FALSE),
foo = anno_block(
gp = gpar(fill = 2:6),
labels = LETTERS[1:5]
)
)
Heatmap(
mat, name = "mat",
column_split = split,
top_annotation = ha,
column_title = NULL
)
現(xiàn)在,已經(jīng)有位置來繪制顏色塊了忽舟,還有一個關(guān)鍵信息双妨,如何獲取到前三個塊的坐標,和后兩個塊的坐標呢叮阅?
對于每個注釋刁品,都有相應(yīng)的 viewport
,其命名方式為 annotation_{annotation_name}_{slice_index}
浩姥,可以使用 list_components()
函數(shù)來獲取所有的 viewport
> list_components()
[1] "ROOT" "global" "global_layout" "global-heatmaplist"
[5] "main_heatmap_list" "heatmap_mat" "mat_heatmap_body_wrap" "mat_heatmap_body_1_1"
[9] "mat_heatmap_body_1_2" "mat_heatmap_body_1_3" "mat_heatmap_body_1_4" "mat_heatmap_body_1_5"
[13] "mat_dend_row_1" "mat_dend_column_1" "mat_dend_column_2" "mat_dend_column_3"
[17] "mat_dend_column_4" "mat_dend_column_5" "annotation_empty_1" "annotation_foo_1"
[21] "annotation_empty_2" "annotation_foo_2" "annotation_empty_3" "annotation_foo_3"
[25] "annotation_empty_4" "annotation_foo_4" "annotation_empty_5" "annotation_foo_5"
[29] "global-heamap_legend_right" "heatmap_legend"
我們可以看到挑随,空白注釋的 viewport
為 annotation_empty_1 - 5
知道了 viewport
的名稱,可以使用 seekViewport
函數(shù)切換到對應(yīng)的 viewport
# 獲取第一個切片的左側(cè)坐標
seekViewport("annotation_empty_1")
loc1 <- deviceLoc(
x = unit(0, "npc"),
y = unit(0, "npc")
)
# 獲取第三個切片的右側(cè)坐標
seekViewport("annotation_empty_3")
loc2 <- deviceLoc(
x = unit(1, "npc"),
y = unit(1, "npc")
)
然后使用 grid::deviceLoc()
函數(shù)來獲取 viewport
對應(yīng)點在整個圖形設(shè)備中的坐標
> loc1
$x
[1] 0.492125984251969in
$y
[1] 7.11417322834646in
獲取到所有信息之后勒叠,我們要切換到 global
這個全局的 viewport
下兜挨,繪制顏色塊
seekViewport("global")
grid.rect(
loc1$x, loc1$y,
width = loc2$x - loc1$x,
height = loc2$y - loc1$y,
just = c("left", "bottom"),
gp = gpar(fill = "red")
)
grid.text(
"Signal transduction",
x = (loc1$x + loc2$x) * 0.5,
y = (loc1$y + loc2$y) * 0.5
)
最后,獻上完整的代碼
pdf("~/Downloads/hm.pdf")
set.seed(123)
mat <- matrix(
rnorm(50*50),
nrow = 50
)
group <- c(
"MAPK",
"PI3K-Akt",
"ErbB",
"Cell cycle",
"Apoptosis"
)
split = rep(1:5, each = 10)
ha <- HeatmapAnnotation(
empty = anno_empty(border = FALSE),
foo = anno_block(
gp = gpar(fill = 2:6),
labels = group
)
)
Heatmap(
mat, name = "mat",
column_split = split,
top_annotation = ha,
column_title = NULL
)
library(glue)
block_group_anno <- function(group, empty_anno, gp = gpar(),
label = NULL, label_gp = gpar()) {
# 獲取最左側(cè) viewport
seekViewport(glue(
'annotation_{anno}_{slice}',
slice = min(group),
anno = empty_anno)
)
# 獲取左下角坐標點
loc1 <- deviceLoc(
x = unit(0, "npc"),
y = unit(0, "npc")
)
# 獲取最右側(cè) viewport
seekViewport(glue(
'annotation_{anno}_{slice}',
slice = max(group),
anno = empty_anno)
)
# 獲取右上角坐標點
loc2 <- deviceLoc(
x = unit(1, "npc"),
y = unit(1, "npc")
)
# 切換到全局 viewport
seekViewport("global")
# 繪制矩形
grid.rect(
loc1$x, loc1$y,
width = loc2$x - loc1$x,
height = loc2$y - loc1$y,
just = c("left", "bottom"),
gp = gp
)
# 如果傳遞了標簽眯分,則添加標簽
if (!is.null(label)) {
grid.text(
label,
x = (loc1$x + loc2$x) * 0.5,
y = (loc1$y + loc2$y) * 0.5,
gp = label_gp
)
}
}
# 將前三個熱圖塊作為一組
block_group_anno(1:3, "empty", gp = gpar(fill = "red"), label = "Signal transduction")
# 后兩個作為一組
block_group_anno(4:5, "empty", gp = gpar(fill = "green"), label = "Cellular Processes")
dev.off()
獲取代碼:https://github.com/dxsbiocc/learn/blob/main/R/plot/multi_group_plock_anno.R
注意:我們將圖片保存成了文件拌汇,而不是在 RStudio
中直接繪制。
可能是由于 deviceLoc
獲取的是圖形設(shè)備的坐標位置弊决,而不是相對于繪圖窗口的位置噪舀,所以,在 RStudio
中需要拉伸繪圖窗口才能看到后面繪制的矩形丢氢。所以我們直接使用 pdf
來保存成文件傅联,就不會有這個問題了。
5. 圖片注釋
可以將圖片作為注釋添加到熱圖中疚察,anno_image()
函數(shù)支持 png
, svg
, pdf
, eps
, jpeg/jpg
, tiff
圖片格式
anno_image()
函數(shù)會在內(nèi)部自動解析各種格式的圖片蒸走,只需要傳遞圖片路徑即可。但是需要安裝對應(yīng)的包
-
grImport2
:該包用于處理svg
圖片貌嫡,但是安裝之后所有圖片都無法顯示比驻,有問題,不建議安裝 -
rsvg
:轉(zhuǎn)換svg
格式 -
grImport
:處理pdf
和eps
圖片
同時岛抄,要確保系統(tǒng)中安裝了 ghostscript
别惦,不然無法使用 pdf
和 eps
格式文件
例如,我們從 https://github.com/Keyamoon/IcoMoon-Free
下載到圖標文件
path <- '~/Downloads/IcoMoon-Free-master/'
image_png = sample(dir(glue("{path}/PNG/64px"), full.names = TRUE), 10)
image_eps = sample(dir(glue("{path}/EPS/"), full.names = TRUE), 10)
image_pdf = sample(dir(glue("{path}/PDF/"), full.names = TRUE), 10)
添加圖標注釋
grid.newpage()
pushViewport(viewport(y = 0.6, height = 0.6, width = 0.8))
ha <- HeatmapAnnotation(foo = anno_image(image_png))
draw(ha)
混合不同格式的圖片
ha <- HeatmapAnnotation(
foo = anno_image(
c(image_png[1:3],
image_eps[1:3],
image_pdf[1:3]
),
gp = gpar(
fill = rainbow(9),
col = "grey"
)
)
)
設(shè)置邊框以及圖片周圍空白填充間距
ha <- HeatmapAnnotation(
foo = anno_image(
image_pdf,
border = TRUE,
space = unit(3, "mm"),
gp = gpar(
fill = rainbow(9),
col = "grey"
)
)
)
如果圖片的路徑為空或 NA
夫椭,則不會顯示
image_pdf[1:2] = c("", NA)
ha <- HeatmapAnnotation(
foo = anno_image(
image_pdf,
border = TRUE,
space = unit(3, "mm"),
gp = gpar(
fill = rainbow(9),
col = "grey"
)
)
)
6. 點注釋
散點注釋使用 anno_points()
函數(shù)來展示點的分布掸掸。
點數(shù)據(jù)對象可以是向量或矩陣,如果是矩陣,則圖形屬性參數(shù)如 pch
扰付、size
和 gp
是按列設(shè)置的堤撵。
注意:矩陣的行對應(yīng)熱圖的列
傳遞一個向量
image_pdf[1:2] = c("", NA)
ha <- HeatmapAnnotation(
foo = anno_points(runif(10))
)
傳遞矩陣,圖形參數(shù)值的長度與列數(shù)一致
ha <- HeatmapAnnotation(
foo = anno_points(
matrix(runif(20), nc = 2),
pch = 1:2,
gp = gpar(col = 2:3)
)
)
ylim
可以設(shè)置 y
軸的范圍,extend
控制數(shù)據(jù)軸上的擴展空間,axis
參數(shù)控制是否顯示軸滔驶,axis_param
參數(shù)用于設(shè)置軸
使用 default_axis_param()
可以獲取行或列注釋的軸默認屬性
> default_axis_param("column")
$at
NULL
$labels
NULL
$labels_rot
[1] 0
$gp
$fontsize
[1] 8
$side
[1] "left"
$facing
[1] "outside"
$direction
[1] "normal"
自定義軸屬性
ha <- HeatmapAnnotation(
foo = anno_points(
runif(10),
ylim = c(0, 1),
extend = 0.1,
axis_param = list(
side = "right",
at = c(0, 0.5, 1),
labels = c("zero", "half", "one")
)
)
)
標簽旋轉(zhuǎn)
ha <- rowAnnotation(
foo = anno_points(
runif(10),
ylim = c(0, 1),
extend = 0.1,
width = unit(2, "cm"),
axis_param = list(
side = "bottom",
at = c(0, 0.5, 1),
labels = c("zero", "half", "one"),
labels_rot = 45
)
)
)
其他有軸的圖形設(shè)置都是類似的
7. 線注釋
anno_lines()
用于繪制線條,與點注釋類似航揉,數(shù)據(jù)對象可以是數(shù)值向量
ha <- HeatmapAnnotation(
foo = anno_lines(
runif(10)
)
)
或者矩陣
ha <- HeatmapAnnotation(
foo = anno_lines(
cbind(c(1:5, 1:5), c(5:1, 5:1)),
gp = gpar(col = 2:3),
add_points = TRUE,
pt_gp = gpar(col = 5:6),
pch = c(1, 5)
)
)
我們可以設(shè)置 add_points = TRUE
來添加點,pt_gp
設(shè)置點的圖形屬性,pch
設(shè)置點的形狀
可以設(shè)置 smooth = TRUE
來添加擬合曲線,在這種情況下志电,add_points
默認為 TRUE
。同時也需要注意长酗,擬合是按照排序后的列順序執(zhí)行的溪北,需要確保該順序符合你的要求
ha <- HeatmapAnnotation(
foo = anno_lines(
cbind(c(1:5, 1:5), c(5:1, 5:1)),
gp = gpar(col = 2:3),
smooth = TRUE,
pt_gp = gpar(col = 5:6),
pch = c(1, 5)
)
)
線注釋的默認大小為 5mm
,可以在函數(shù)內(nèi)使用 height/width
來調(diào)整
8. 條形圖注釋
anno_barplot()
函數(shù)用于添加條形圖注釋夺脾,其中一些參數(shù),如 ylim
, axis
, axis_param
與 anno_points()
一樣
ha <- HeatmapAnnotation(
foo = anno_barplot(1:10)
)
bar_width
用于設(shè)置條形的寬度茉继,其值為相對于熱圖主體單元格的寬度
ha <- HeatmapAnnotation(
foo = anno_barplot(
1:10,
bar_width = 0.8)
)
設(shè)置圖形屬性
ha <- HeatmapAnnotation(
foo = anno_barplot(
1:10,
gp = gpar(
fill = rainbow(10)
))
)
使用 baseline
參數(shù)來設(shè)置基線
ha <- HeatmapAnnotation(
foo = anno_barplot(
-5:5,
baseline = 0,
gp = gpar(
fill = rainbow(10)
))
)
ha <- HeatmapAnnotation(
foo = anno_barplot(
-5:5,
baseline = "min",
gp = gpar(
fill = rainbow(10)
))
)
如果輸入的是矩陣咧叭,可以設(shè)置堆積條形圖
ha <- HeatmapAnnotation(
foo = anno_barplot(
matrix(c(1:10, 10:1), nc = 2),
gp = gpar(
fill = rainbow(2),
col = 3:4
)
)
)
圖形屬性參數(shù)的長度與矩陣列數(shù)一致
條形圖注釋的大小默認為 5mm
,我們可以使用 height/width
設(shè)置其高度和寬度
ha <- HeatmapAnnotation(
foo = anno_barplot(
matrix(c(1:10, 10:1), nc = 2),
height = unit(2, "cm"),
gp = gpar(
fill = rainbow(2),
col = 3:4
)
)
)
繪制百分比條形圖
m <- matrix(runif(4*10), nc = 4)
m <- t(apply(m, 1, function(x) x/sum(x)))
ha <- HeatmapAnnotation(
foo = anno_barplot(
m,
height = unit(6, "cm"),
bar_width = 1,
gp = gpar(
fill = rainbow(4))
)
)
也可以設(shè)置軸的朝向
ha_list <-
rowAnnotation(
axis_reverse = anno_barplot(
m, gp = gpar(fill = rainbow(4)),
axis_param = list(direction = "reverse"),
bar_width = 1, width = unit(4, "cm"))
) +
rowAnnotation(
axis_normal = anno_barplot(
m, gp = gpar(fill = rainbow(4)),
bar_width = 1,
width = unit(4, "cm"))
)
draw(ha_list, ht_gap = unit(4, "mm"))
9. 箱線圖注釋
anno_boxplot()
用于繪制箱線圖注釋烁竭,數(shù)據(jù)對象為矩陣或列表菲茬。
如果數(shù)據(jù)是矩陣,且為列注釋派撕,將會按列對矩陣進行統(tǒng)計婉弹,行注釋將按行執(zhí)行統(tǒng)計
注意:箱線圖適用于小型數(shù)據(jù),如果數(shù)據(jù)列太多终吼,不推薦使用
mat <- matrix(rnorm(100), 10)
ha <- HeatmapAnnotation(
foo = anno_boxplot(
mat,
height = unit(4, "cm")
)
)
添加圖形屬性
mat <- matrix(rnorm(100), 10)
ha <- HeatmapAnnotation(
foo = anno_boxplot(
mat,
height = unit(4, "cm"),
gp = gpar(
fill = rainbow(10)
)
)
)
outline
用于設(shè)置是否顯示離群點镀赌,box_width
用于設(shè)置箱子寬度
mat <- matrix(rnorm(100), 10)
ha <- HeatmapAnnotation(
foo = anno_boxplot(
mat,
height = unit(4, "cm"),
box_width = 0.8,
outline = FALSE,
gp = gpar(
fill = rainbow(10)
)
)
)
10。 直方圖注釋
anno_histogram()
用于添加直方圖注釋际跪,適用于行注釋商佛,其參數(shù)與 anno_boxplot()
類似
mat <- matrix(rnorm(1000), nc = 100)
ha <- rowAnnotation(
foo = anno_histogram(
mat,
n_breaks = 20,
gp = gpar(fill = rainbow(10))
)
)
n_breaks
用于設(shè)置柱子的數(shù)量
11. 密度注釋
anno_density()
函數(shù)用于繪制密度曲線注釋
mat <- matrix(rnorm(1000), nc = 100)
ha <- rowAnnotation(
foo = anno_density(
mat,
joyplot_scale = 2,
gp = gpar(fill = rainbow(10))
)
)
使用 joyplot_scale
來控制分布峰值的高度,讓它看起來像山脊圖
以小提琴的方式繪制
ha <- rowAnnotation(
foo = anno_density(
mat,
type = "violin",
gp = gpar(fill = rainbow(10))
)
)
如果行數(shù)太多了姆打,可以繪制熱圖
ha <- rowAnnotation(
foo = anno_density(
mat,
type = "heatmap",
heatmap_colors = c("#9970ab", "#5aae61")
)
)
使用 heatmap_colors
來控制熱圖的顏色
12. Joyplot 注釋
joyplot
圖也就是我們說的山脊圖良姆,使用 anno_joyplot()
函數(shù)繪制,接受矩陣或列表數(shù)據(jù)
如果數(shù)據(jù)為矩陣幔戏,則總是按列計算的玛追,如果你不確定怎么設(shè)置,可以轉(zhuǎn)換為 list
輸入變量的格式為:
- 矩陣:
x
坐標為1:nrow(matrix)
且矩陣的每一列是一個分布 - 列表:數(shù)據(jù)框列表闲延,每個數(shù)據(jù)框包含兩列痊剖,表示
x
和y
坐標
mat <- matrix(rnorm(1000), nc = 10)
lt <- apply(mat, 2, function(x) data.frame(density(x)[c("x", "y")]))
ha <- rowAnnotation(
foo = anno_joyplot(
lt,
width = unit(4, "cm"),
gp = gpar(fill = rainbow(10)),
transparency = 0.6
)
)
或者韩玩,只顯示線條,同時使用 scale
設(shè)置峰值的高度
ha <- rowAnnotation(
foo = anno_joyplot(
lt,
width = unit(4, "cm"),
gp = gpar(fill = NA),
scale = 2
)
)
13. 地平線圖注釋
地平線圖只能作為行注釋邢笙,輸入數(shù)據(jù)的格式類似于 anno_joyplot()
lt <- lapply(1:20, function(x) cumprod(1 + runif(1000, -x/100, x/100)) - 1)
ha <- rowAnnotation(
foo = anno_horizon(
lt,
height = unit(6, "cm"),
gp = gpar(
pos_fill = "orange",
neg_fill = "darkgreen"
)
)
)
使用 pos_fill
和 neg_fill
來設(shè)置正負值的填充色
也可以為 pos_fill
和 neg_fill
設(shè)置向量值
ha <- rowAnnotation(
foo = anno_horizon(
lt,
height = unit(6, "cm"),
gp = gpar(
pos_fill = rep(rainbow(10)[5:6], 10),
neg_fill = rep(rainbow(10)[8:9], 10)
)
)
)
使用 gap
設(shè)置兩張圖的間距啸如,negative_from_top
參數(shù)用于設(shè)置負值的峰值是否從頂部開始
ha <- rowAnnotation(
foo = anno_horizon(
lt,
height = unit(6, "cm"),
negative_from_top = TRUE,
gap = unit(1, "mm"),
gp = gpar(
pos_fill = rep(rainbow(10)[5:6], 10),
neg_fill = rep(rainbow(10)[8:9], 10)
)
)
)
14 文本注釋
使用 anno_text()
來添加文本注釋
ha <- rowAnnotation(
foo = anno_text(
month.name,
location = 1,
just = "center",
rot = 45,
gp = gpar(
fontsize = 5:17
)
)
)
location
和 just
會根據(jù)注釋的位置自動計算,如果注釋放置在右邊氮惯,則文本會左對齊叮雳,反之,在左邊妇汗,右對齊
根據(jù)所有文本會自動計算 width/height
的值帘不,一般不需要手動設(shè)置
ha <- rowAnnotation(
foo = anno_text(
month.name,
location = 0.5,
just = "center",
gp = gpar(
fill = rep(rainbow(10)[2:5], each = 4),
col = "black",
border = "black"
),
width = max_text_width(month.name) * 1.2
)
)
可以使用 gridtext
包繪制更復(fù)雜的文本
15. 標記注釋
anno_mark
(代替了被替換的 anno_link
)用于標記某些行/列,并使用線條連接文本和對應(yīng)的行/列
anno_mark()
至少需要兩個參數(shù)杨箭,at
提供原始數(shù)據(jù)矩陣的索引寞焙,labels
為相應(yīng)的文本標記
mat <- matrix(rnorm(1000), nrow = 100)
rownames(mat) <- 1:100
ha <- rowAnnotation(
foo = anno_mark(
at = c(1:4, 20, 60, 97:100),
labels = month.name[1:10])
)
Heatmap(
mat, name = "mat",
cluster_rows = FALSE,
right_annotation = ha,
row_names_side = "left",
row_names_gp = gpar(fontsize = 4)
)
16 摘要注釋
anno_summary()
用于對只有一行或一列的熱圖提供統(tǒng)計匯總注釋
如果數(shù)據(jù)為離散型向量,將繪制條形圖
v <- sample(letters[1:2], 50, replace = TRUE)
split <- sample(letters[1:2], 50, replace = TRUE)
ha <- HeatmapAnnotation(
summary = anno_summary(height = unit(4, "cm"))
)
Heatmap(
v, name = "mat",
col = c("a" = "red", "b" = "blue"),
top_annotation = ha,
width = unit(2, "cm"),
row_split = split
)
對于連續(xù)型向量將繪制箱線圖
v <- rnorm(50)
ha <- HeatmapAnnotation(
summary = anno_summary(
gp = gpar(fill = 3:4),
height = unit(4, "cm")
)
)
Heatmap(
v, name = "mat",
top_annotation = ha,
width = unit(2, "cm"),
row_split = split
)
我們通常不會單獨繪制只包含一列的熱圖互婿,而是會與其他熱圖繪制在一起
比如捣郊,我們在基因表達矩陣的邊上,繪制一個 lncRNA
或 MiRNA
的表達熱圖
# 設(shè)置熱圖配色
col_fun <- colorRamp2(
c(-2, 0, 2),
c("#8c510a", "white", "#01665e")
)
# 繪制主熱圖
exp <- matrix(rnorm(50*10), nrow = 50)
main <- Heatmap(
exp, name = "main_matrix",
col = col_fun
)
# 繪制一列離散型熱圖
v <- sample(letters[1:2], 50, replace = TRUE)
lnc <- Heatmap(
v, name = "mat1",
# 設(shè)置離散型顏色
col = structure(c("#f46d43", "#66bd63"), name = letters[1:2]),
top_annotation = HeatmapAnnotation(
summary = anno_summary(
height = unit(3, "cm")
)
),
width = unit(1, "cm"),
)
# 繪制一列連續(xù)型熱圖
v <- rnorm(50)
mi <- Heatmap(
v, name = "mat2",
col = col_fun,
top_annotation = HeatmapAnnotation(
summary = anno_summary(
gp = gpar(fill = 2:3),
height = unit(3, "cm"))
),
width = unit(1, "cm")
)
# 按列添加多個熱圖
ht_list <- main + lnc + mi
split <- sample(letters[1:2], 50, replace = TRUE)
draw(ht_list,
row_split = split,
ht_gap = unit(5, "mm"),
heatmap_legend_list = list(lgd_boxplot)
)
17. 縮放/連接注釋
anno_mark()
用于將某些行/列連接到文本標簽慈参,anno_zoom()
則用于將行列子集連接到一個繪圖區(qū)域呛牲,并可在該區(qū)域繪制自定義圖形⊥耘洌可以理解為從熱圖矩陣中拿出部分子集來繪制一個任意的圖形
例如娘扩,我們可以為每個分組繪制一個箱線圖
# 設(shè)置熱圖配色
col_fun <- colorRamp2(
c(-2, 0, 2),
c("#8c510a", "white", "#01665e")
)
# 生成表達譜
exp <- matrix(rnorm(100*10), nrow = 100)
# 設(shè)置分組
group <- sample(letters[1:3], 100,
replace = TRUE,
prob = c(1, 5, 10)
)
panel_fun <- function(index, nm) {
# 添加繪圖 viewport
pushViewport(viewport(xscale = range(exp), yscale = c(0, 2)))
# 繪制區(qū)域外側(cè)框線
grid.rect()
grid.xaxis(gp = gpar(fontsize = 8))
# 添加箱線圖
grid.boxplot(
exp[index, ], pos = 1,
gp = gpar(fill = index + 6),
direction = "horizontal"
)
popViewport()
}
Heatmap(
exp, name = "exp",
col = col_fun,
row_split = group,
height = unit(10, "cm"),
width = unit(12, "cm"),
right_annotation = rowAnnotation(
foo = anno_zoom(
align_to = group,
which = "row",
panel_fun = panel_fun,
size = unit(2, "cm"),
gap = unit(1, "cm"),
width = unit(4, "cm")
))
)
anno_zoom()
函數(shù)的參數(shù)
align_to
:定義了行或列的分組繪圖區(qū)域。如果是索引列表壮锻,則其中每個向量為一組琐旁,如果為分類變量,則將根據(jù)level
分組panel_fun
:自定義的繪圖函數(shù)猜绣。函數(shù)的第一個參數(shù)為index
灰殴,表示分組在矩陣中的索引,第二個參數(shù)為nm
途事,代表選擇的熱圖區(qū)域的名稱验懊,該名稱來自align_to
的分類變量或list
中的名稱size
:箱子的大小,可以是絕對值或相對值尸变,相對于熱圖的寬度和高度gap
:箱子的間隔
18. 多個注釋
18.1 常規(guī)設(shè)置
在前面的示例中义图,我們以鍵值對的方式在 HeatmapAnnotation()
函數(shù)中添加多個注釋,還有一些參數(shù)用于控制多個注釋召烂,這些參數(shù)的值長度要與注釋數(shù)目相同
不管是向量碱工、矩陣或數(shù)據(jù)框數(shù)據(jù),繪制簡單注釋都會自動添加圖例,使用 show_legend
可以控制圖例的顯示
對于輸入數(shù)據(jù)的不同怕篷,show_legend
的格式也有區(qū)別:
- 長度為簡單注釋數(shù)量的邏輯向量
- 長度為所有注釋的數(shù)量历筝,對應(yīng)于復(fù)雜注釋的值將被忽略
- 命名向量,控制簡單注釋的子集
例如
ha = HeatmapAnnotation(
foo = 1:10,
bar = cbind(1:10, 10:1),
pt = anno_points(1:10),
show_legend = c("bar" = FALSE)
)
Heatmap(
matrix(rnorm(100), 10),
name = "mat",
top_annotation = ha
)
border
控制單個注釋的外側(cè)框線廊谓,show_annotation_name
控制注釋名稱的顯示
ha <- HeatmapAnnotation(
foo = 1:10,
bar = cbind(1:10, 10:1),
pt = anno_points(1:10),
gp = gpar(col = "red"),
show_annotation_name = c(bar = FALSE),
border = c(foo = TRUE)
)
annotation_name_gp
, annotation_name_offset
, annotation_name_side
和 annotation_name_rot
用于控制注釋名的樣式屬性和位置梳猪,后面三個可以被設(shè)置為命名向量。
當 annotation_name_offset
設(shè)置為命名向量時蒸痹,值不需要 unit
函數(shù)設(shè)置春弥,可以直接使用字符表示
annotation_name_offset = c(foo = "1cm")
gap
參數(shù)用于設(shè)置兩個注釋的間隔,可以是單個值或向量
ha <- HeatmapAnnotation(
foo = 1:10,
bar = cbind(1:10, 10:1),
pt = anno_points(1:10),
gap = unit(2, "mm")
)
ha <- HeatmapAnnotation(
foo = 1:10,
bar = cbind(1:10, 10:1),
pt = anno_points(1:10),
gap = unit(c(2, 10), "mm")
)
18.2 注釋的大小
height
, width
, annotation_height
和 annotation_width
用于控制復(fù)雜注釋的大小叠荠,通常來說匿沛,簡單注釋不需要設(shè)置,會根據(jù)圖形自動調(diào)整榛鼎。
例如
# foo: 1cm, bar: 5mm, pt: 1cm
ha <- HeatmapAnnotation(
foo = cbind(1:10, 10:1),
bar = 1:10,
pt = anno_points(1:10)
)
當使用 height
參數(shù)設(shè)置注釋的高度時逃呼,簡單注釋的高度不會改變,只會改變復(fù)雜注釋的高度
# foo: 1cm, bar: 5mm, pt: 4.5cm
ha <- HeatmapAnnotation(
foo = cbind(1:10, 10:1),
bar = 1:10,
pt = anno_points(1:10),
height = unit(6, "cm")
)
simple_anno_size
控制所有簡單注釋的大小者娱,全局簡單注釋的大小可以使用 ht_opt$simple_anno_size
設(shè)置
# foo: 2cm, bar:1cm, pt: 3cm
ha <- HeatmapAnnotation(
foo = cbind(1:10, 10:1),
bar = 1:10,
pt = anno_points(1:10),
simple_anno_size = unit(1, "cm"),
height = unit(6, "cm")
)
所有簡單注釋都被設(shè)置為 1cm
annotation_height
可以分別為每個注釋設(shè)置高度
# foo: 1cm, bar: 2cm, pt: 3cm
ha <- HeatmapAnnotation(
foo = cbind(1:10, 10:1),
bar = 1:10,
pt = anno_points(1:10),
annotation_height = unit(1:3, "cm")
)
annotation_height
也可以設(shè)置為純數(shù)值抡笼,會將其作為注釋的相對比例值
# foo: 1cm, bar: 2cm, pt: 3cm
ha <- HeatmapAnnotation(
foo = cbind(1:10, 10:1),
bar = 1:10,
pt = anno_points(1:10),
annotation_height = 1:3,
height = unit(6, "cm")
)
annotation_height
也可以混合絕對值和相對值
# foo: 1.5cm, bar: 1.5cm, pt: 3cm
ha <- HeatmapAnnotation(
foo = cbind(1:10, 10:1),
bar = 1:10,
pt = anno_points(1:10),
annotation_height = unit(c(1, 1, 3), c("null", "null", "cm")),
height = unit(6, "cm")
)
如果只有簡單注釋,設(shè)置 height
將不會有任何作用
# foo: 1cm, bar: 5mm
ha <- HeatmapAnnotation(
foo = cbind(1:10, 10:1),
bar = 1:10,
height = unit(6, "cm")
)
除非將 simple_anno_size_adjust
設(shè)置為 TRUE
ha <- HeatmapAnnotation(
foo = cbind(1:10, 10:1),
bar = 1:10,
simple_anno_size_adjust = TRUE,
height = unit(6, "cm")
)
19. 實用函數(shù)
有一些實用函數(shù)黄鳍,可以對注釋進行更靈活的操作蔫缸,例如,對于如下注釋
ha <- HeatmapAnnotation(
foo = 1:10,
bar = cbind(1:10, 10:1),
pt = anno_points(1:10)
)
計算注釋的數(shù)量际起,觀察值的數(shù)量
> draw(ha)
> length(ha)
[1] 3
> nobs(ha)
[1] 10
獲取和設(shè)置注釋的名稱
> names(ha)
[1] "foo" "bar" "pt"
> names(ha) <- c("A", "B", "C")
> names(ha)
[1] "A" "B" "C"
如果兩個 HeatmapAnnotation
對象具有相同的觀測值且注釋名稱不同,可以連接起來
ha1 <- HeatmapAnnotation(
foo = 1:10,
bar = cbind(1:10, 10:1),
pt = anno_points(1:10)
)
ha2 <- HeatmapAnnotation(
FOO = runif(10),
BAR = sample(c("a", "b"), 10, replace = TRUE),
PT = anno_points(rnorm(10))
)
ha <- c(ha1, ha2)
> names(ha)
[1] "foo" "bar" "pt" "FOO" "BAR" "PT"
可以對 HeatmapAnnotation
對象進行取子集操作吐葱,行對應(yīng)為觀察值街望,列對應(yīng)注釋名稱
> ha_subset <- ha[1:5, c("foo", "PT")]
> ha_subset
A HeatmapAnnotation object with 2 annotations
name: heatmap_annotation_154
position: column
items: 5
width: 1npc
height: 15.3514598035146mm
this object is subsetable
5.21733333333333mm extension on the left
6.75733333333333mm extension on the right
name annotation_type color_mapping height
foo continuous vector random 5mm
PT anno_points() 10mm
20. 自定義注釋函數(shù)
ComplexHeatmap
中的所有注釋函數(shù)都是使用 AnnotationFunction
類來構(gòu)造的
AnnotationFunction
類的重要部分是一個函數(shù),該函數(shù)定義如何在與熱圖中的行或列相對應(yīng)的特定位置處進行繪制圖形
該函數(shù)包含三個參數(shù):
-
index
:對應(yīng)于熱圖矩陣的行或列的索引弟跑,包含行或列重新排序后當前切片的行或列索引的列表 -
k
:代表當前熱圖塊的索引 -
n
:代表所有熱圖塊數(shù)目
后兩個參數(shù)是可選的灾前,注釋函數(shù)會在每個切片中獨立繪制。
var_import
參數(shù)用于存儲該函數(shù)的額外參數(shù)
AnnotationFunction
的一個特性是可子集化孟辑,用于需要定義輸入變量的拆分規(guī)則哎甲,包中自帶了子集化規(guī)則函數(shù) subset_gp()
, subset_matrix_by_row()
和 subset_vector()
,如果未指定饲嗽,會根據(jù)輸入對象的類型自動推斷
例如炭玫,定義一個簡單的注釋函數(shù)
x <- 1:10
anno1 <- AnnotationFunction(
fun = function(index, k, n) {
n = length(index)
# 根據(jù)索引長度分配 viewport 空間
pushViewport(viewport(xscale = c(0.5, n + 0.5), yscale = c(0, 10)))
grid.rect()
# 繪制散點
grid.points(1:n, x[index], default.units = "native")
if(k == 1) grid.yaxis()
popViewport()
},
# 傳遞函數(shù)的額外參數(shù)
var_import = list(x = x),
n = 10,
subsetable = TRUE,
height = unit(2, "cm")
)
下面來使用它
m = rbind(1:10, 11:20)
Heatmap(
m,
top_annotation = HeatmapAnnotation(foo = anno1)
)
應(yīng)用于分割熱圖塊
Heatmap(
m,
top_annotation = HeatmapAnnotation(foo = anno1),
column_split = rep(c("A", "B"), each = 5)
)
上面的函數(shù)可以改進,將數(shù)據(jù)變量放入內(nèi)部
anno2 <- AnnotationFunction(
fun = function(index) {
x = 1:10
n = length(index)
pushViewport(viewport())
grid.points(1:n, x[index])
popViewport()
},
n = 10,
subsetable = TRUE
)
最精簡的方式是貌虾,只定義函數(shù)
anno3 <- AnnotationFunction(
fun = function(index) {
x = 1:10
n = length(index)
pushViewport(viewport())
grid.points(1:n, x[index])
popViewport()
}
)
其實吞加,本節(jié)中介紹的所有 anno_*()
函數(shù)實際上并不是真正的注釋函數(shù),它們只是生成具有特定配置的注釋函數(shù)的函數(shù)
事實上,ComplexHeatmap
已經(jīng)提供了足夠多的函數(shù)了衔憨,可以滿足絕大部分的需求叶圃。是在沒有的,也可以通過 anno_empty()
放置一個空白占位践图,然后使用 decorate_annotation()
函數(shù)快速添加自定義圖形掺冠。