为什么要查找共有和独有基因?
共有基因一般是同源基因,独有基因是指该物种因为环境而被迫演化出的的基因,这意味这在对应的环境下,必定有一些适应该环境的特殊基因,这可以帮助我们弄清楚物种的之间的演化过程,也可以在育种方面提供原材料。
共有基因往往对应的是一些基因家族,在漫长的演化过程中,基因家族中有一些基因减少,或者增多,这其实就对应着基因家族的扩张收缩,这也是研究物种演化的关键数据之一。
查找共有和独有基因其实就是做基因家族的聚类,分析基因家族的扩张收缩,常有的软件有orthofinder和orthomcl,orthofinder的集成度更好,还可以自动完成建树因此此处我们学习orthofinder的使用。
1.安装
下载和官方教程地址:https://github.com/davidemms/OrthoFinder
可以使用conda安装
1
| conda install orthofinder -c bioconda
|
也可以手动安装
1 2
| wget https://github.com/davidemms/OrthoFinder/releases/latest/download/OrthoFinder.tar.gz tar xzvf OrthoFinder.tar.gz
|
2.准备数据
本次所使用的数据是Magnolia_biondii.chr.pep和Msin.chr.pep两物种的蛋白质数据,但这两个数据往往不可以直接获得,就算直接获得的,也往往不是最长转录本,因此我们先要进行一些处理
首先需要根据数据提取最长转录本
为什么要提取最长转录本?
由于可变剪切的存在,通常一个基因可以转录为多个转录本。但是如果将多个转录本同时进行分析,那么分析会因此受到影响。所以,目前的解决办法是,选取一个最具代表性的转录本(最长转录本)来进行分析。
最长转录本其实可以从序列文件中获取,也可以从gff文件中获取,获取的方式也有很多,可以直接使用gettranstool,用
1
| GetLongestTransFromGencode --file example.fa --outfile longest_trans_gencode.fa
|
官方的教程:https://github.com/junjunlab/GetTransTool,有需要自己可以查阅
在此介绍对于小白最友好的方法,即使用之前提过多次的软件,TBtools:
sequence toolkit->fasta tools->fasta get representative
note部分不需要管,ID grouping pattern处为正则表达式,这是序列名称的编号规则,一般不需要更改,然后是输入蛋白质序列数据以及输出文件名的设置
建议直接使用TBtools最简单,只需要弄清楚ID号的正则表达式即可
##蛋白质序列的序列名应该尽量简单,否则可能会出现报错
ValueError: too many values to unpack
这种情况一般在10个以上物种进行聚类的时候出现,出现这种情况时,可以直接使用python脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| #!/usr/bin/env python3 import os import re from Bio import SeqIO import sys
def simplify_fasta_headers(input_file, output_file): """简化单个FASTA文件的序列头,保留第一个有效标识符""" with open(output_file, "w") as out_handle: for record in SeqIO.parse(input_file, "fasta"): new_id = record.id.split()[0] # 取第一个空格前的部分 record.id = new_id record.description = new_id SeqIO.write(record, out_handle, "fasta")
def process_directory(input_dir, output_dir): """批量处理目录下所有.fasta文件""" if not os.path.exists(output_dir): os.makedirs(output_dir)
for filename in os.listdir(input_dir): if filename.endswith(".fasta") or filename.endswith(".fa"): input_path = os.path.join(input_dir, filename) output_path = os.path.join(output_dir, filename) simplify_fasta_headers(input_path, output_path) print(f"处理完成: {filename} -> {output_path}")
if __name__ == "__main__": if len(sys.argv) != 3: print(f"用法: {sys.argv[0]} <输入文件夹> <输出文件夹>") print(f"示例: {sys.argv[0]} ./input_fasta ./cleaned_fasta") sys.exit(1)
input_dir = sys.argv[1] output_dir = sys.argv[2] process_directory(input_dir, output_dir) print(f"\n所有文件处理完成!结果保存在: {output_dir}")
|
该脚本是终端脚本,使用方式为
1
| python simplify_headers.py ./原始文件夹 ./输出文件夹
|
删除所有非标准氨基酸字符
1
| for i in data4/*;do sed -i '/^>/! s/[^A-Za-z]//g' "$i"; done
|
3.家族聚类及结果解读
1 2 3 4 5 6
| orthofinder -f data -S diamond -M msa -T fasttree -t 20 -f: 数据目录,先将所有蛋白放进文件夹data中 -S: 比对方法,blast, mmseqs, blast_gz, diamond -M: 基因树推断方法,dendroblast,msa -T:建树软件,iqtree, raxml-ng, fasttree, raxml -t: 线程数,根据服务器配置选择,默认为56
|
聚类结果如下:
Results_XX #结果文件夹名
Citation.txt
Comparative_Genomics_Statistics #统计结果
Gene_Duplication_Events
Gene_Trees # 每个家族基因树
Log.txt
MultipleSequenceAlignments # 多序列比对结果 包含单拷贝基因supergene
Orthogroups # 主要结果目录
Orthogroup_Sequences # 每个家族序列文件
Orthologues
Phylogenetically_Misplaced_Genes
Phylogenetic_Hierarchical_Orthogroups
Putative_Xenologs
Resolved_Gene_Trees
Single_Copy_Orthologue_Sequences # 单拷贝基因家族序列
Species_Tree # 物种树构建结果
WorkingDirectory
Results_XX/Orthogroups#主要结果
Orthogroups.GeneCount.tsv # 基因数目
Orthogroups_SingleCopyOrthologues.txt # 单拷贝基因家族列表
Orthogroups.tsv # 聚类结果
Orthogroups.txt # 聚类结果
Orthogroups_UnassignedGenes.tsv # 未聚类基因
4.处理聚类结果并绘制韦恩图
1 2 3 4
| awk '{ if(NR==1){ for(i=2;i<NF;i++ ){printf $i"\t"} }else{ \ for(i=2;i<NF;i++){ if($i>0){printf $1 } ; printf "\t" }}; \ printf "\n"}' Orthogroups.GeneCount.tsv | \ sed 's/\t$//' > Orthogroups.GeneCount.venn
|
脚本解释:
NR==1: 当读取到文件的第一行时(通常是列标题行),执行以下操作:
for(i=2;i<NF;i++): 从第2列开始(跳过第1列),循环处理每一列直到倒数第2列。
printf $i"\t": 输出每列的内容,后面跟一个制表符(\t),这些输出结果是列标题(从第2列开始),将用于标记维恩图中不同组的名称。
else{ for(i=2;i<NF;i++){ if($i>0){printf $1 }; printf "\t" }}
非第一行时
for(i=2;i<NF;i++): 对每一行,从第2列开始直到倒数第2列进行循环。
if($i>0){printf $1 }: 如果当前列的值大于0,则输出该行的第1列内容(通常是一个基因组的名称或ID)。
printf "\t": 在输出内容之后,加入一个制表符。
每处理完一行后,脚本在行尾输出一个换行符(\n),以确保每行的数据换行。
1 2 3 4
| sed 's/\t$//' sed命令用于对awk生成的输出进行后处理。s/\t$//是一个替换操作: \t$表示行末的制表符(\t)。 //表示将匹配到的行末制表符删除。
|
或者直接使用dos2unix进行转换
处理好的.venn文件可以直接拿来做韦恩图,可以使用在线网站也可以用R,通常情况下我会使用jvenn网站绘制完,根据数据使用AI自己重新绘制一个
jvenn网址:https://jvenn.toulouse.inrae.fr/app/example.html
下面介绍使用R绘制
下面是脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| # 加载必要的库 library(ggVennDiagram) library(ggplot2)
# 读取文件数据 file_path <- "Orthogroups.GeneCount.venn" # 请根据实际文件路径进行替换 data <- read.table(file_path, header = TRUE, sep = "\t", stringsAsFactors = FALSE)
# 提取非空值的集合 set_JNYL <- data$JNYL[data$JNYL != ""] set_WCYL <- data$WCYL[data$WCYL != ""]
# 创建集合列表 sets <- list( JNYL = set_JNYL, WCYL = set_WCYL )
# 使用ggVennDiagram绘制维恩图 ggVennDiagram(sets, category.names = c("JNYL", "WCYL"), # 集合名字 set_color = c("blue", "red"), # 集合颜色 set_size = 6, # 集合名字大小 label = "both", # 标签显示"count"和"percent" label_geom = "label", # 标签样式 label_alpha = 0, # 标签背景透明 label_color = "firebrick", # 标签颜色 label_percent_digit = 2, # 百分比保留2位小数 edge_lty = "dashed", # 边框线型 edge_size = 1.2 # 边框粗细 ) + scale_fill_gradient(low = "grey90", high = "grey60") + # 填充色 scale_color_manual(values = c("grey10", "grey10")) # 边框颜色
结果可以使用ggplot2进行优化,这也是为什么要调用ggplot2的原因个人感觉其实到这就可以了 #先将文件转为数据框 venn <- Venn(sets) df <- process_data(venn) df #ggplot2绘图 ggplot()+ geom_sf(data = venn_region(df), aes(fill=count))+ geom_sf(data = venn_setedge(df),size=2,lty="dashed",color="grey")+ geom_sf(data = venn_setlabel(df),aes(label=name))+ geom_sf_label(data = venn_region(df),aes(label=id),fontface="bold")+ scale_fill_distiller(palette = 5)+ theme_void()
|
其实到这我对图还是不满意,我后面又用AI换了一下颜色
提取独有共有基因的OGid
使用jvenn,点击venn图中想要继续分析的区域的数字,即可获得该区域内的所有OGid
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| #将OGid与基因名相匹配 cp ../../Results_May02/Orthogroups/Orthogroups.tsv ./ #将之前结果文件复制到当前目录下 grep -f Ms.txt Orthogroups.tsv | cut -f3 | sed "s/ /\n/g" | sed "s/\t/\n/g" | sed "s/,//g" | sort | uniq > Ms.specific #Ms.txt是得到的OGid,必须是unix格式,即使用cat -A打开后结尾是^I^M$,如果不是使用dos2unix转换一下 -f表示从文件中读取关键词 | cut -f3 cut 用于按列提取内容,-f3 表示提取每行的第 3 列,因为Ms在Orthogroups.tsv的第三列 "s/ /\n/g": s:表示替换命令。 / /:表示匹配空格字符。 \n:表示将空格替换为换行符。 g:表示全局替换,即替换行中所有的空格 | sed "s/\t/\n/g":将制表符(\t)替换为换行符 | sed "s/,//g":将逗号(,)移除 | sort:用于对文本内容进行排序 | uniq: 用于去除相邻的重复行
|
提取得到基因列表,可以按之前的教程继续后面的GO、KEGG分析