二代测序通过bam文件统计深度和覆盖度

2024年3月1日更新

推荐直接用最近的新软件PanDepth,C语言写的,速度很快。

#命令示例
pandepth -i input.bam -o test
#软件结果最后一行
##RegionLength: 1416543111  CoveredSite: 1239625885 Coverage(%): 87.51  MeanDepth: 26.74

以下为旧流程或仅供原理了解:

群体分析一般会对所有个体进行深度和覆盖度的统计,以便确认个体的测序质量,及时去除质量差的个体。

计算深度和覆盖度的软件有很多,PanDepth(推荐)、samtools、mosdepth、bedtools、bamdst等等,可以计算个体、染色体、某窗口上的深度和覆盖度。以下文章都有很好的总结:
测序数据的深度、覆盖度等计算 - 简书 (jianshu.com)
Bedtools genomecov 计算覆盖度 - 简书 (jianshu.com)
基因组质量评估:(五)mapping法:7. 用软件mosdepth统计BAM文件的深度 - 知乎 (zhihu.com)

但针对于群体分析,批量计算所有个体的深度和覆盖度,这些软件则显得命令繁琐,本文通过python脚本一步到位多进程同时计算深度和覆盖度,省心省力。

一、生成depth.gz文件

这一步需要排序好、去除pcr重复的bam文件,通过samtools生成深度文件。

samtools depth -aa input.bam
#-aa计算所有位点的深度,包括深度为0的位点
#默认输出input.bam.depth.gz
image.png

二、统计深度和覆盖度

1. 原理

深度 = 每个位点深度相加/有深度的位点总数
覆盖度 = 有深度的位点/所有位点


bedtools
2.python多进程加速计算

需要安装tqdm库:pip install tqdm
使用方法:

python3 cal_genome_avg.py filepath out.txt cpu_number
#第一个参数为路径,则会匹配路径下该所有depth.gz文件,并计算深度
python3 cal_genome_avg.py file.depth.gz out.txt cpu_number
#第一个参数为depth.gz文件,则会自动计算该文件深度,追加到out.txt中
# -*- coding: utf-8 -*-
import multiprocessing as mp
import gzip
import os
from tqdm import tqdm
import sys

#1、创建函数执行计算每个文件平均深度
#2、主函数多进程

def cal_ave_depth(file):
    """
    输入:文件名
    输出:个体名称、被覆盖到的位点的深度、没有被覆盖的位点/所有位点
    """
    counter = 0   # 所有位点的总数 预期是基因组的全长
    dp = 0        # 所有位点的深度
    gap = 0       # 深度为0的位点数
    o = gzip.open(file,'r')
    print("open "+file+" successfully!")
    for line in o:
        site_depth = int(line.rstrip().split()[-1])
        if site_depth == 0:
            gap += 1
        else:
            dp += site_depth
        counter +=1
    o.close()
    avg = float(dp)/float(counter-gap)# 被覆盖到的位点的深度。按照原来的计算方法,需要减去0的地方
    genome_cov = float(gap)/float(counter)  # 没有被覆盖的位点/所有位点
    indiv_name=file.split('/')[-1].split('.')[0]    # 获取个体名称
    j=round(avg,3)                   # 被覆盖到的位点的深度,保留三位有效数字 The round() function returns a floating point number that is a rounded version of the specified number, with the specified number of decimals.
    k=1-round(genome_cov,3)            # 1-没有被覆盖的位点/所有位点
    dp =0
    counter = 0
    print(file+" caluate down!")
    return indiv_name,j,k     # 个体名称   被覆盖到的位点的深度   没有被覆盖的位点/所有位点
if __name__ == "__main__":
    if(len(sys.argv) < 3):
        print("This script is to count average depth.\nUsage:InDir \nAttention: InDir includes all your .depth.gz file.")
        exit(1)
  
    filepath=sys.argv[1]
    outfile=sys.argv[2]
    cpu_num=int(sys.argv[3])
    print(filepath,outfile,cpu_num)
    filelist = []
    if os.path.isfile(filepath):
        print("Your input is only one file.")
        i,j,k = cal_ave_depth(filepath)  # 个体的名字,深度,覆盖度
        with open(outfile,"a+") as f:
            f.write(str(i)+"\t"+str(j)+"\t"+str(k)+"\n")
    elif os.path.exists(filepath):
        for root,curdirs,files in os.walk(filepath):
            for file in files:
                if ("depth.gz" in file):
                    filelist.append(filepath+file)
                else:
                    pass
    else:
        print("input filepath is error! Please check it!")
    #print(len(filelist))
    #print(filelist)
    pool=mp.Pool(cpu_num)
    for indiv_name,j,k in tqdm(pool.imap(cal_ave_depth,filelist)):
        #print(indiv_name)
        with open(outfile,"a+") as f:# 每计算完成一个,写入outfile
            f.write(str(i)+"\t"+str(j)+"\t"+str(k)+"\n")
    pool.close()
    pool.join()   
    filelist=[]
3.结果

每列依次为个体名字、深度、覆盖度,这个图片是第v1版本脚本,需要1-第三列才为真实的覆盖度。第三列计算结果就是覆盖度80.4%。


results
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容