跟着iMeta学做图|circlize绘制环状热图展示细菌功能聚类分析

本文主要是介绍跟着iMeta学做图|circlize绘制环状热图展示细菌功能聚类分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原始教程链接 

https://github.com/iMetaScience/iMetaPlot/tree/main/221116circlize

如果你使用本代码,请引用:

Jiao Xi et al. 2022. Microbial community roles and chemical mechanisms in the parasitic development of Orobanche cumana. iMeta https://doi.org/10.1002/imt2.31

写在前面

热图 (Heat map) 可以在微生物组研究中展示展示细菌功能聚类分析的结果,而环状热图是热图的一种表现形式。本期我们挑选2022年6月13日刊登在iMeta上的Microbial community roles and chemical mechanisms in the parasitic development of Orobanche cumana- iMeta | 西农林雁冰/ James M. Tiedje等揭示菌群对寄生植物列当的调控作用,选择文章的Figure 2B进行复现,基于顾祖光博士开发的circlize包,讲解和探讨环形热图的绘制方法,先上原图:

939bea14a50be39019d918a1cc326004.gif

8c564ee0d902770ff9bfb2f0a7c92de5.png

接下来,我们将通过详尽的代码逐步拆解原图,最终实现对原图的复现。

R包检测和安装

01

安装核心R包circlize以及一些功能辅助性R包,并载入所有R包。

# 检查开发者工具devtools,如没有则安装
if (!require("devtools"))install.packages("devtools")
# 加载开发者工具devtools
library(devtools)
# 检查circlize包,没有则通过github安装最新版
if (!require("circlize"))install_github("jokergoo/circlize")
if (!require("tidyverse"))install.packages('tidyverse') 
if (!require("ComplexHeatmap"))install.packages('ComplexHeatmap') 
if (!require("tidyverse"))install.packages('tidyverse') 
# 加载包
library(circlize)
library(tidyverse)
library(ComplexHeatmap)
library(gridBase)

生成测试数据

02

由于没有在补充文件里找到原文相关数据,在这里我们通过生成随机数据来替代。

#生成KEGG数据矩阵(矩阵1)
data1<-matrix(rnorm(670,mean=0.5),nrow=67)
rownames(data1)<-c("K01446","K01971","K01142","K01151","K01246","K00784","K02031","K01644","K02037","K02065","K01448","K01890","K00266","K01725","K00806","K00231","K01737","K00858","K00019","K01715","K01692","K00249","K00023","K00626","K00101","K00803","K01710","K01791","K01176","K00799","K00800","K01667","K01668","K01712","K00053","K01696","K01697","K00108","K00639","K01489","K00226","K01488","K02339","K01428","K01438","K02124","K02275","K01796","K00632","K00648","K00849","K01805","K01685","K00065","K00090","K01619","K01834","K00121","K02182","K02082","K02005","K01266","K01990","K01463","K02217","K01174","K02003")
colnames(data1)<-c(paste('H',seq(1:5),sep = ""),paste("PS",seq(1:5),sep = ""))
#生成EC数据矩阵(矩阵2)
data2<-matrix(rnorm(130,mean=1),nrow = 13)
rownames(data2)<-c("2.1.1.165","1.1.5.-","4.2.99.20","1.1.1.86","1.1.99.1","1.1.2.3","4.2.1.28","4.2.1.82","5.4.1.3","1.13.12.16","5.1.99.4","1.17.4.1","1.8.4.-")
colnames(data2)<-c(paste('H',seq(1:5),sep = ""),paste("PS",seq(1:5),sep = ""))
#生成细菌数据矩阵(矩阵3)
data3<-matrix(rnorm(20,mean=1),nrow = 10)
supdata<-matrix(0,nrow = 10,ncol = 8)
#由于该矩阵为10×2矩阵,需补充10×8全为0的矩阵,使得矩阵123均为m×10的矩阵
data3<-cbind(data3,supdata)
rownames(data3)<-c("Proteobacteria","Actinobacteria","Acidobacteria","Bacteroidetes","Gemmatimonadetes","Chloroflexi","Planctomycetes","Firmicutes","Verrucomicrobia","unidentified_Acidobacteria")
#将三个矩阵按行合并
mat_data<-rbind(data1,data2,data3)
#按行将矩阵反转,这样矩阵3的非零数据会出现在内圈
mat_dataR<-mat_data%>% as.data.frame() %>% rowwise() %>% rev() %>% as.matrix() 
rownames(mat_dataR)<-rownames(mat_data)

6cbed2cca8fbcec940cdd5ed9bd68a9e.png

环形热图预览

03

开始作图,首先画一个最基本的环形热图:

pdf("plot1.pdf",width = 8, height = 6)
#设置热图颜色范围:
colpattern = colorRamp2(c(-1, 0, 1), c("#2574AA", "white", "#ED7B79"))
#设置扇区,这里划分了三个扇区,KEGG,EC和细菌种类。
level_test<-c(rep("KEGG",67),rep("EC",13),rep("SP",10)) %>% factor()#画图
circos.heatmap(mat_dataR, col = colpattern, rownames.side = "outside", cluster = TRUE)
circos.clear()dev.off()

935ed5cd0d448eb356f592d4ddabb600.png

04

添加扇区分化,单元格边框,轨道高度,扇区间间隔:

pdf("plot2.pdf",width = 8, height = 6)
circos.par(gap.after = c(10, 10, 12))
circos.heatmap(mat_dataR, split = level_test, col = colpattern, rownames.side = "outside", cluster = TRUE,cell.lwd=0.8,cell.border="white",track.height = 0.2)
circos.clear()dev.off()

16e6d132267b54781c860773c86b2bd0.png

05

添加矩阵的列名。circos.heatmap()不直接支持矩阵的列名,可以通过自定义panel.fun函数轻松添加:

pdf("plot3.pdf",width = 8, height = 6)
circos.par(gap.after = c(10, 10, 12))
circos.heatmap(mat_dataR, split = level_test, col = colpattern, rownames.side = "outside", cluster = TRUE,cell.lwd=0.8,cell.border="white",track.height = 0.2) 
circos.track(track.index = get.current.track.index(), panel.fun = function(x, y) {if(CELL_META$sector.numeric.index == 1) { # the last sectorcn = colnames(mat_dataR)n = length(cn)circos.text(rep(CELL_META$cell.xlim[2], n) + convert_x(1, "mm"), 1:n - 0.5, cn, cex = 0.3, adj = c(0, 0.5), facing = "inside")}
}, bg.border = NA)circos.track(track.index = get.current.track.index(), panel.fun = function(x, y) {if(CELL_META$sector.numeric.index == 3) { # the last sectorcn = colnames(mat_dataR)n = length(cn)circos.text(rep(CELL_META$cell.xlim[2], n) + convert_x(1, "mm"), 1:n - 0.5, cn, cex = 0.3, adj = c(0, 0.5), facing = "inside")}
}, bg.border = NA)
circos.clear()dev.off()

24f54bb23849419100e586d834eb0d93.png

06

接下来添加连接线,连接线表示位置和位置的对应关系。首先生成数据:

#灰色连接线数据
df_link = data.frame(from_index = sample(nrow(mat_dataR), 30),to_index = sample(nrow(mat_dataR), 30)
)
#红色连接线数据
red_df_link<-data.frame(from_index = c(86,87,82),to_index = c(2,15,36))
#蓝色连接线数据
blue_df_link<-data.frame(from_index = c(84,86,90),to_index = c(72,76,69))

5bed0fb9a9e2a75c7ccdc92953c7bbfa.png

07

接下来开始添加link:

pdf("plot4.pdf",width = 8, height = 6)
circos.par(gap.after = c(10, 10, 12))
circos.heatmap(mat_dataR, split = level_test, col = colpattern, rownames.side = "outside", cluster = TRUE,cell.lwd=0.8,cell.border="white",track.height = 0.2) 
circos.track(track.index = get.current.track.index(), panel.fun = function(x, y) {if(CELL_META$sector.numeric.index == 1) { # the last sectorcn = colnames(mat_dataR)n = length(cn)circos.text(rep(CELL_META$cell.xlim[2], n) + convert_x(1, "mm"), 1:n - 0.5, cn, cex = 0.3, adj = c(0, 0.5), facing = "inside")}
}, bg.border = NA)circos.track(track.index = get.current.track.index(), panel.fun = function(x, y) {if(CELL_META$sector.numeric.index == 3) { # the last sectorcn = colnames(mat_dataR)n = length(cn)circos.text(rep(CELL_META$cell.xlim[2], n) + convert_x(1, "mm"), 1:n - 0.5, cn, cex = 0.3, adj = c(0, 0.5), facing = "inside")}
}, bg.border = NA)for(i in seq_len(nrow(df_link))) {circos.heatmap.link(df_link$from_index[i],df_link$to_index[i],col = "grey")
}for(i in seq_len(nrow(red_df_link))) {circos.heatmap.link(red_df_link$from_index[i],red_df_link$to_index[i],col = "red")
}for(i in seq_len(nrow(blue_df_link))) {circos.heatmap.link(blue_df_link$from_index[i],blue_df_link$to_index[i],col = "blue")
}
circos.clear()dev.off()

13bd8f48fe8ee022b4a586671417a515.png

08

添加图例,circos.heatmap()本身是不支持添加图例的,但我们可以利用gridBase和ComplexHeatmap包添加图例:

pdf("plot5.pdf",width = 8, height = 6)
plot.new()
circle_size = unit(1, "snpc") # snpc unit gives you a square regionpushViewport(viewport(x = 0, y = 0.5, width = circle_size, height = circle_size,just = c("left", "center")))
par(omi = gridOMI(), new = TRUE)
circos.par(gap.after = c(10, 10, 12))
circos.heatmap(mat_dataR, split = level_test, col = colpattern, rownames.side = "outside", cluster = TRUE,cell.lwd=0.8,cell.border="white",track.height = 0.2) 
circos.track(track.index = get.current.track.index(), panel.fun = function(x, y) {if(CELL_META$sector.numeric.index == 1) { # the last sectorcn = colnames(mat_dataR)n = length(cn)circos.text(rep(CELL_META$cell.xlim[2], n) + convert_x(1, "mm"), 1:n - 0.5, cn, cex = 0.3, adj = c(0, 0.5), facing = "inside")}
}, bg.border = NA)circos.track(track.index = get.current.track.index(), panel.fun = function(x, y) {if(CELL_META$sector.numeric.index == 3) { # the last sectorcn = colnames(mat_dataR)n = length(cn)circos.text(rep(CELL_META$cell.xlim[2], n) + convert_x(1, "mm"), 1:n - 0.5, cn, cex = 0.3, adj = c(0, 0.5), facing = "inside")}
}, bg.border = NA)for(i in seq_len(nrow(df_link))) {circos.heatmap.link(df_link$from_index[i],df_link$to_index[i],col = "grey")
}for(i in seq_len(nrow(red_df_link))) {circos.heatmap.link(red_df_link$from_index[i],red_df_link$to_index[i],col = "red")
}for(i in seq_len(nrow(blue_df_link))) {circos.heatmap.link(blue_df_link$from_index[i],blue_df_link$to_index[i],col = "blue")
}
circos.clear()
upViewport()h = dev.size()[2]
lgd = Legend(title = "", col_fun = colpattern)
draw(lgd, x = circle_size, just = "left")dev.off()

49334a7f3203152529d925d27b46e01d.png

09

距离成功只差一步啦,最后用AI进行修图,处理掉不合理的部分。成品图如下:

c3044785366a61daa8ffd47802140514.jpeg

完整代码

# 检查开发者工具devtools,如没有则安装
if (!require("devtools"))install.packages("devtools")
# 加载开发者工具devtools
library(devtools)
# 检查circlize包,没有则通过github安装最新版
if (!require("circlize"))install_github("jokergoo/circlize")
if (!require("tidyverse"))install.packages('tidyverse') 
if (!require("ComplexHeatmap"))install.packages('ComplexHeatmap') 
if (!require("tidyverse"))install.packages('tidyverse') 
# 加载包
library(circlize)
library(tidyverse)
library(ComplexHeatmap)
library(gridBase)#part1 生成数据
set.seed(123)
#生成KEGG数据矩阵(矩阵1)
data1<-matrix(rnorm(670,mean=0.5),nrow=67)
rownames(data1)<-c("K01446","K01971","K01142","K01151","K01246","K00784","K02031","K01644","K02037","K02065","K01448","K01890","K00266","K01725","K00806","K00231","K01737","K00858","K00019","K01715","K01692","K00249","K00023","K00626","K00101","K00803","K01710","K01791","K01176","K00799","K00800","K01667","K01668","K01712","K00053","K01696","K01697","K00108","K00639","K01489","K00226","K01488","K02339","K01428","K01438","K02124","K02275","K01796","K00632","K00648","K00849","K01805","K01685","K00065","K00090","K01619","K01834","K00121","K02182","K02082","K02005","K01266","K01990","K01463","K02217","K01174","K02003")
colnames(data1)<-c(paste('H',seq(1:5),sep = ""),paste("PS",seq(1:5),sep = ""))
#生成EC数据矩阵(矩阵2)
data2<-matrix(rnorm(130,mean=1),nrow = 13)
rownames(data2)<-c("2.1.1.165","1.1.5.-","4.2.99.20","1.1.1.86","1.1.99.1","1.1.2.3","4.2.1.28","4.2.1.82","5.4.1.3","1.13.12.16","5.1.99.4","1.17.4.1","1.8.4.-")
colnames(data2)<-c(paste('H',seq(1:5),sep = ""),paste("PS",seq(1:5),sep = ""))
#生成细菌数据矩阵(矩阵3)
data3<-matrix(rnorm(20,mean=1),nrow = 10)
supdata<-matrix(0,nrow = 10,ncol = 8)
#由于该矩阵为10×2矩阵,需补充10×8全为0的矩阵,使得矩阵123均为m×10的矩阵
data3<-cbind(data3,supdata)
rownames(data3)<-c("Proteobacteria","Actinobacteria","Acidobacteria","Bacteroidetes","Gemmatimonadetes","Chloroflexi","Planctomycetes","Firmicutes","Verrucomicrobia","unidentified_Acidobacteria")
#将三个矩阵按行合并
mat_data<-rbind(data1,data2,data3)
#按行将矩阵反转,这样矩阵3的非零数据会出现在内圈
mat_dataR<-mat_data%>% as.data.frame() %>% rowwise() %>% rev() %>% as.matrix() 
rownames(mat_dataR)<-rownames(mat_data)
#设置热图颜色范围
colpattern = colorRamp2(c(-1, 0, 1), c("#2574AA", "white", "#ED7B79"))
#设置扇区,这里划分了三个扇区,KEGG,EC和细菌种类
level_test<-c(rep("KEGG",67),rep("EC",13),rep("SP",10)) %>% factor()
#level_test<-row.names(mat_dataR) %>% str_match("[k]+") %>% replace_na("EC") %>% factor()
#生成连接线数据
df_link = data.frame(from_index = sample(nrow(mat_dataR), 30),to_index = sample(nrow(mat_dataR), 30)
)
red_df_link<-data.frame(from_index = c(86,87,82),to_index = c(2,15,36))blue_df_link<-data.frame(from_index = c(84,86,90),to_index = c(72,76,69))#开始画图
pdf("Figure 2B.pdf",width = 8, height = 6)
plot.new()
circle_size = unit(1, "snpc") # snpc unit gives you a square regionpushViewport(viewport(x = 0, y = 0.5, width = circle_size, height = circle_size,just = c("left", "center")))
par(omi = gridOMI(), new = TRUE)
circos.par(gap.after = c(10, 10, 12))
circos.heatmap(mat_dataR, split = level_test, col = colpattern, rownames.side = "outside", cluster = TRUE,cell.lwd=0.8,cell.border="white",track.height = 0.2) 
circos.track(track.index = get.current.track.index(), panel.fun = function(x, y) {if(CELL_META$sector.numeric.index == 1) { # the last sectorcn = colnames(mat_dataR)n = length(cn)circos.text(rep(CELL_META$cell.xlim[2], n) + convert_x(1, "mm"), 1:n - 0.5, cn, cex = 0.3, adj = c(0, 0.5), facing = "inside")}
}, bg.border = NA)circos.track(track.index = get.current.track.index(), panel.fun = function(x, y) {if(CELL_META$sector.numeric.index == 3) { # the last sectorcn = colnames(mat_dataR)n = length(cn)circos.text(rep(CELL_META$cell.xlim[2], n) + convert_x(1, "mm"), 1:n - 0.5, cn, cex = 0.3, adj = c(0, 0.5), facing = "inside")}
}, bg.border = NA)for(i in seq_len(nrow(df_link))) {circos.heatmap.link(df_link$from_index[i],df_link$to_index[i],col = "grey")
}for(i in seq_len(nrow(red_df_link))) {circos.heatmap.link(red_df_link$from_index[i],red_df_link$to_index[i],col = "red")
}for(i in seq_len(nrow(blue_df_link))) {circos.heatmap.link(blue_df_link$from_index[i],blue_df_link$to_index[i],col = "blue")
}
circos.clear()
upViewport()h = dev.size()[2]
lgd = Legend(title = "", col_fun = colpattern)
draw(lgd, x = circle_size, just = "left")dev.off()

这篇关于跟着iMeta学做图|circlize绘制环状热图展示细菌功能聚类分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/675787

相关文章

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

【WebGPU Unleashed】1.1 绘制三角形

一部2024新的WebGPU教程,作者Shi Yan。内容很好,翻译过来与大家共享,内容上会有改动,加上自己的理解。更多精彩内容尽在 dt.sim3d.cn ,关注公众号【sky的数孪技术】,技术交流、源码下载请添加微信号:digital_twin123 在 3D 渲染领域,三角形是最基本的绘制元素。在这里,我们将学习如何绘制单个三角形。接下来我们将制作一个简单的着色器来定义三角形内的像素

Flutter 进阶:绘制加载动画

绘制加载动画:由小圆组成的大圆 1. 定义 LoadingScreen 类2. 实现 _LoadingScreenState 类3. 定义 LoadingPainter 类4. 总结 实现加载动画 我们需要定义两个类:LoadingScreen 和 LoadingPainter。LoadingScreen 负责控制动画的状态,而 LoadingPainter 则负责绘制动画。

Spring框架5 - 容器的扩展功能 (ApplicationContext)

private static ApplicationContext applicationContext;static {applicationContext = new ClassPathXmlApplicationContext("bean.xml");} BeanFactory的功能扩展类ApplicationContext进行深度的分析。ApplicationConext与 BeanF

JavaFX应用更新检测功能(在线自动更新方案)

JavaFX开发的桌面应用属于C端,一般来说需要版本检测和自动更新功能,这里记录一下一种版本检测和自动更新的方法。 1. 整体方案 JavaFX.应用版本检测、自动更新主要涉及一下步骤: 读取本地应用版本拉取远程版本并比较两个版本如果需要升级,那么拉取更新历史弹出升级控制窗口用户选择升级时,拉取升级包解压,重启应用用户选择忽略时,本地版本标志为忽略版本用户选择取消时,隐藏升级控制窗口 2.

Android 10.0 mtk平板camera2横屏预览旋转90度横屏拍照图片旋转90度功能实现

1.前言 在10.0的系统rom定制化开发中,在进行一些平板等默认横屏的设备开发的过程中,需要在进入camera2的 时候,默认预览图像也是需要横屏显示的,在上一篇已经实现了横屏预览功能,然后发现横屏预览后,拍照保存的图片 依然是竖屏的,所以说同样需要将图片也保存为横屏图标了,所以就需要看下mtk的camera2的相关横屏保存图片功能, 如何实现实现横屏保存图片功能 如图所示: 2.mtk

Spring+MyBatis+jeasyui 功能树列表

java代码@EnablePaging@RequestMapping(value = "/queryFunctionList.html")@ResponseBodypublic Map<String, Object> queryFunctionList() {String parentId = "";List<FunctionDisplay> tables = query(parent

PostgreSQL核心功能特性与使用领域及场景分析

PostgreSQL有什么优点? 开源和免费 PostgreSQL是一个开源的数据库管理系统,可以免费使用和修改。这降低了企业的成本,并为开发者提供了一个活跃的社区和丰富的资源。 高度兼容 PostgreSQL支持多种操作系统(如Linux、Windows、macOS等)和编程语言(如C、C++、Java、Python、Ruby等),并提供了多种接口(如JDBC、ODBC、ADO.NET等

利用matlab bar函数绘制较为复杂的柱状图,并在图中进行适当标注

示例代码和结果如下:小疑问:如何自动选择合适的坐标位置对柱状图的数值大小进行标注?😂 clear; close all;x = 1:3;aa=[28.6321521955954 26.2453660695847 21.69102348512086.93747104431360 6.25442246899816 3.342835958564245.51365061796319 4.87