介紹和demo一個(gè)圓形布局包含扇形(sector)和軌道(track)兩個(gè)部分.扇形和軌道交叉的地方稱之為cell.circlize 使用的是R的base圖層寫的,因此和R自帶的畫圖系統(tǒng)一樣,包含high-level函數(shù)和低級繪圖函數(shù).高級繪圖函數(shù)可以直接繪圖,而低級繪圖則只能在創(chuàng)建track之后,才能在上面繪圖. circlize中的low level function包括以下幾種,每一個(gè)其實(shí)都在R中存在對應(yīng)的函數(shù),因此,只要熟悉R基礎(chǔ)繪圖函數(shù), 對下面這些都不會陌生,只是將在笛卡爾坐標(biāo)轉(zhuǎn)換為極坐標(biāo): circos.points() : 添加點(diǎn).
circos.lines() : 添加直線.
circos.segments() : 添加segment.
circos.rect() : 在cell中添加矩形,比如熱圖,其實(shí)就是用該函數(shù)來繪制的.
circos.polygon() : 添加多邊形.
circos.text() : 添加文字.
circos.axis() and circos.yaxis() :對x和y坐標(biāo)軸進(jìn)行設(shè)置.
circlize中與layout相關(guān)的函數(shù)如下: circos.initialize() : 用來啟動一個(gè)初始的circos layout,其實(shí)就是用來創(chuàng)建sector,只有創(chuàng)建sector之后,才能添加track,進(jìn)而在cell中繪圖.
circos.track() : 在sector中創(chuàng)建track.
circos.update() : 對某一個(gè)已經(jīng)創(chuàng)建并繪圖的cell進(jìn)行更行.
circos.par() : 與par 相當(dāng),對一些整體參數(shù)進(jìn)行設(shè)置,比如繪制扇形時(shí)的起始角度和順序等.
circos.info() : prints general parameters of current circular plot.
circos.clear() : 關(guān)閉現(xiàn)在的circos圖形,從而不會影響下一個(gè)圖形的繪制.
下面用一個(gè)簡單的例子,來一步步說明如何使用circlize 繪制circos圖形. 構(gòu)建數(shù)據(jù)并啟動一個(gè)circos layout.我們一共構(gòu)建8個(gè)種類的數(shù)據(jù),在circos的表現(xiàn)就是8個(gè)sector. set.seed(999) n = 1000
df = data.frame(factors = sample(letters[1:8],
n, replace = TRUE),
x = rnorm(n), y = runif(n))
library(circlize) circos.par('track.height' = 0.1)
circos.initialize(factors = df$factors,
x = df$x)
track.height 用來設(shè)置所有軌道的默認(rèn)高度.整個(gè)circos的直徑默認(rèn)為為1,所以將其設(shè)置為0.1意味著每個(gè)軌道的高度是整個(gè)圓圈直徑的10%.當(dāng)然,在后面繪制單個(gè)track的時(shí)候,也可以通過函數(shù)中的track.height 參數(shù)來對單個(gè)track進(jìn)行設(shè)置.
circos.initialize() 函數(shù)中必須要設(shè)置的兩個(gè)參數(shù),factors 和x 或者xlim .它會根據(jù)factors的level(如果不是factor則使用unique(factors))來確定創(chuàng)建幾個(gè)sector.x則會根據(jù)factor自動進(jìn)行分組,然后根據(jù)每組的range自動設(shè)置每個(gè)sector的寬度(寬度代表的是x軸).
使用上述代碼初始化一個(gè)circos plot之后,下面要做的就是按照一層層軌道往上添加?xùn)|西了. 添加軌道之前,首先需要使用circos.track() 函數(shù)來創(chuàng)建軌道,然后才可以使用low-level的函數(shù)往里面添加各種元素. 創(chuàng)建第一個(gè)track并添加點(diǎn)和文字circos.track(factors = df$factors, y = df$y, panel.fun = function(x, y) { circos.text(x = get.cell.meta.data('xcenter'), y = get.cell.meta.data('cell.ylim')[2] + uy(5, 'mm'), labels = get.cell.meta.data('sector.index')) circos.axis(labels.cex = 0.6) })
col <- rep(c('skyblue', 'red'), 4) circos.trackPoints(factors = df$factors, x = df$x, y = df$y, col = col, pch = 16, cex = 0.5) circos.text(x = -1, y = 0.5, labels = 'text', sector.index = 'a', track.index = 1)
circos.track() 函數(shù)中的panel.fun函數(shù)用來在創(chuàng)建cell的時(shí)候,自定義執(zhí)行一定的功能.比如可以和低級繪圖函數(shù)結(jié)合,來自動對每一個(gè)cell中自動添加點(diǎn)等等信息.
get.cell.meta.data() 函數(shù)可以提供當(dāng)前的cell的meta信息.有很多信息可以從`中提取,后面再詳細(xì)講解.
circos.trackPoints() 函數(shù)與circos.points() 函數(shù)不同的點(diǎn)就是,他可以接受factors 參數(shù),從而可以自動將x和y按照factor分組,自動在每個(gè)cell分別繪制點(diǎn).因此,他的效果,相當(dāng)于使用circos.track() 函數(shù),然后結(jié)合panel.fun() 函數(shù),在其中使用circos.points() 函數(shù).因此,上面的函數(shù)也可以寫成下面的函數(shù),效果相同.
circos.track(factors = df$factors, x = df$x, y = df$y, panel.fun = function(x, y) { circos.text(x = get.cell.meta.data('xcenter'), y = get.cell.meta.data('cell.ylim')[2] + uy(5, 'mm'), labels = get.cell.meta.data('sector.index')) circos.axis(labels.cex = 0.6) circos.points(x = x, y = y, col = col, pch = 16, cex = 0.5) })

添加第二個(gè)track并添加柱狀圖
使用circos.trackHist() 函數(shù).這是一個(gè)high-level的函數(shù).high-level函數(shù)意味著它自己可以直接創(chuàng)建新的track,然后直接繪圖. bgcol <- rep(c('#EFEFEF', '#CCCCCC'), 4) circos.trackHist(df$factors, df$x, bin.size = 0.2, bg.col = bgcol, col = NA)

可以看到,默認(rèn)的話,track是一層一層從外往里進(jìn)行添加.
添加第三個(gè)track.注意在circos.track() 函數(shù)中,x坐標(biāo)(x)和y坐標(biāo)(y)是自動被factor所分類的,也就是說傳遞到內(nèi)部函數(shù)panel.fun 中的x和y都是當(dāng)前cell(也就是分類)的x和y. 下面,在第三個(gè)track中,我們在每個(gè)cell中隨機(jī)選取10個(gè)點(diǎn),然后按照x排序,連接成線. circos.track(factors = df$factors, x = df$x, y = df$y, panel.fun = function(x, y) { ind = sample(length(x), 10) x2 = x[ind] y2 = y[ind] od = order(x2) circos.lines(x = x2[od], y = y2[od]) })

如果需要對某個(gè)cell中用的內(nèi)容進(jìn)行重新繪制,可以使用circos.update() 函數(shù)進(jìn)行更新.注意一定需要指明所需要更新的sector和track的index.
注意,更新某個(gè)cell之后,當(dāng)前(current)的cell就是你更新的cell,所以如果你想要對整個(gè)cell進(jìn)行修改,比如添加新的點(diǎn)等,可以不需要指明cell. circos.update(sector.index = 'd', track.index = 2, bg.col = '#FF8080', bg.border = 'black') circos.points(x = -2:2, y = rep(0.5, 5), col = 'white') circos.text(x = get.cell.meta.data('xcenter'), y = get.cell.meta.data('ycenter'), labels = 'updated', col = 'white')

但是,如果接著添加track,仍然是在最里層的track的基礎(chǔ)上,往里面接著添加. 添加第四個(gè)track.我們接著添加track,這次我們添加一個(gè)熱圖,使用的是circos.rect() 函數(shù).因?yàn)樵摵瘮?shù)并不是high-level函數(shù),因此我們需要使用circos.track() 先創(chuàng)建track,然后在其內(nèi)部的panel.fun() 函數(shù)中在使用circos.rect() 函數(shù)為每個(gè)cell創(chuàng)建熱圖. circos.track(ylim = c(0, 1), panel.fun = function(x, y) { xlim = get.cell.meta.data('xlim') ylim = get.cell.meta.data('ylim') breaks = seq(xlim[1], xlim[2], by = 0.5) n_breaks = length(breaks) circos.rect(xleft = breaks[-n_breaks], ybottom = rep(ylim[1], n_breaks - 1), xright = breaks[-1], ytop = rep(ylim[2], n_breaks - 1), col = rand_color(n_breaks), border = NA) })

可以看到,circos.rect() 函數(shù)內(nèi)部的四個(gè)參數(shù):xleft ,ybottom ,xright 和ytop 可以是vector.
在內(nèi)部添加連線(links)我們添加連線或者緞帶.也就是所謂的和弦圖.連接可以是點(diǎn)對點(diǎn),也可以點(diǎn)對區(qū)域,或者區(qū)域?qū)^(qū)域.使用的是低級函數(shù)circos.link() 函數(shù). circos.link(sector.index1 = 'a', point1 = 0, sector.index2 = 'b', point2 = 0, h = 0.4) circos.link(sector.index1 = 'c', point1 = c(-0.5, 0.5), sector.index2 = 'd', point2 = c(-0.5,0.5), col = 'skyblue', border = 'skyblue', h = 0.2) circos.link(sector.index1 = 'e', point1 = 0, sector.index2 = 'g', point2 = c(-1,1), col = 'green', border = 'black', lwd = 2, lty = 2)

最后,所有track都做完之后,需要重置你的graphic的參數(shù)等等,從而使你畫下一個(gè)figure的時(shí)候,才不會搞混到一起. circos.clear()
layout(布局)使用circlize 進(jìn)行畫圖的過程其實(shí)很簡單: 初始化啟動layout(創(chuàng)建了sector)->創(chuàng)建track->畫圖形->常見track->畫圖形-…-clear. 其中,對于畫圖來說,只要創(chuàng)建了該cell,就可以通過指定cell在任意時(shí)間進(jìn)行畫圖. 初始化layout(circos.initialize() 函數(shù)). 創(chuàng)建track并畫圖.有三種方法可以創(chuàng)建track并畫圖.
使用circos.track() 創(chuàng)建track之后,使用low-level函數(shù)(如circols.points() ,circols.lines() )畫圖.這時(shí)候,一般需要使用使用for循環(huán),并且需要你手動提出每個(gè)cell對應(yīng)的分類的數(shù)據(jù)(指定sector.index和track.index參數(shù)). 可以直接使用circos.trackPoints() , circos.trackLines() 等函數(shù)直接創(chuàng)建track并添加圖形.也就是每個(gè)低級參數(shù)都有其對應(yīng)的circos.tracl...() 函數(shù). 在circos.track() 函數(shù)中使用panel.fun() 函數(shù).panel函數(shù)需要x和y參數(shù),這個(gè)參數(shù)是在當(dāng)前cell的x和y.這是作者推薦使用的方法.
sector和tracksector是一列(從外到里),而track是一行(一圈).sector在使用circos.initialize() 函數(shù)進(jìn)行初始化的時(shí)候,就已經(jīng)分配好了,一個(gè)sector代表著一類,因此,數(shù)據(jù)至少需要一組. 每個(gè)sector的寬度,與該組內(nèi)的數(shù)據(jù)x的的range成正比.當(dāng)然這是默認(rèn)的,也可以通過手動設(shè)置xlim 參數(shù)(circos.initialize() )來指定每個(gè)sector的寬度. xlim 參數(shù)需要是一個(gè)兩列的matrix,每一行對應(yīng)著每一個(gè)sector的寬度的兩個(gè)界限.因此,該matix的行數(shù)應(yīng)該和sector的個(gè)數(shù)一致.
當(dāng)然,你也可以設(shè)置xlim為兩個(gè)元素的vector,這樣,所有的sector的寬度就是一致的. 當(dāng)初始化的時(shí)候,sector的順序也已經(jīng)被決定了.sector的順序和你的數(shù)據(jù)中的分類的factor的因此水平時(shí)一致的,所以如果需要更改sector的順序,請到原始數(shù)據(jù)中更改. 另外需要注意的時(shí),在同一個(gè)sector中的不同track的cell,他們共享一個(gè)x軸.因此,當(dāng)新建一個(gè)track的時(shí)候,我們沒有必要設(shè)置xlim,只需要設(shè)置ylim就行了. 而對于一個(gè)track中的所有cell來說.他們共享一個(gè)ylim,因此像circos.track() 中的ylim 參數(shù),直接設(shè)置為兩位的vector即可. circos.track(factors, y = y) circos.track(factors, ylim = c(0, 1)) circos.track(factors, x = x, y = y)
當(dāng)創(chuàng)建新的track的時(shí)候,如果不想創(chuàng)建所有sector的track,可以在circos.track() 的factor參數(shù)只提供想要設(shè)置track的名字即可. 創(chuàng)建sector的時(shí)候,默認(rèn)角度為0(水平).方向?yàn)轫槙r(shí)針,如果希望修改,可以通過設(shè)置: circos.par('clock.wise' = TRUE, start.degree = 90)
總體參數(shù)總體參數(shù)可以通過circos.par() 參數(shù)進(jìn)行設(shè)置. 創(chuàng)建繪圖區(qū)域只有創(chuàng)建了繪圖區(qū)域之后,才能夠使用low-level函數(shù)進(jìn)行繪圖.一般,使用circos.track() 函數(shù)來進(jìn)行繪制track. panel.fun() 函數(shù)
該函數(shù)都是和circos.track() 函數(shù)配合使用. 在panel.fun() 中使用low-level繪圖函數(shù),不需要指明sector.index 和track.index . 在panel.fun() 內(nèi)部,可以使用get.cell.meta.data() 函數(shù)來獲得當(dāng)前cell的信息. 可以使用其獲得的cell信息包括: sector.index: The name for the sector.
sector.numeric.index: Numeric index for the sector.
track.index: Numeric index for the track.
xlim: Minimal and maximal values on the x-axis.
ylim: Minimal and maximal values on the y-axis.
xcenter: mean of xlim.
ycenter: mean of ylim.
xrange: defined as xlim[2] - xlim[1].
yrange: defined as ylim[2] - ylim[1].
cell.xlim: Minimal and maximal values on the x-axis extended by cell paddings.
cell.ylim: Minimal and maximal values on the y-axis extended by cell paddings.
xplot: Degree of right and left borders in the plotting region. The first element corresponds to the start point of values on x-axis and the second element corresponds to the end point of values on x-axis Since x-axis in data coordinate in cells are always clockwise, xplot[1] is larger than xplot[2].
yplot: Radius of bottom and top radius in the plotting region.
cell.start.degree: Same as xplot[1].
cell.end.degree: Same as xplot[2].
cell.bottom.radius: Same as yplot[1].
cell.top.radius: Same as yplot[2].
track.margin: Margins of the cell.
cell.padding: Paddings of the cell.
比如,可以使用下面的代碼,在每個(gè)cell的中間,加上該cell的index. circos.track(ylim = ylim, panel.fun = function(x, y) { sector.index = get.cell.meta.data('sector.index') xcenter = get.cell.meta.data('xcenter') ycenter = get.cell.meta.data('ycenter') circos.text(xcenter, ycenter, sector.index) })
CELL_META 和get.cell.meta.data() 是等價(jià)的,比如,CELL_META$sector.index 就等于get.cell.meta.data('sector.index') .
但是該函數(shù)只能在panel.fun() 內(nèi)部使用,用來獲得當(dāng)前cell的信息,而get.cell.meta.data() 則可以在指明sector和track index的前提下,在panel.fun() 外部使用. ------------------------------------------------------------------------
|