sam格式很精炼,几乎包含了比对的所有信息,我们平常用到的信息很少,但特殊情况下,我们会用到一些较为生僻的信息,关于这些信息sam官方文档的介绍比较精简,直接看估计很难看懂。

今天要介绍的是如何通过bam文件统计比对的indel和mismatch信息

首先要介绍一个非常重要的概念--编辑距离

定义:从字符串a变到字符串b,所需要的最少的操作步骤(插入,删除,更改)为两个字符串之间的编辑距离

(2016年11月17日:增加,有点误导,如果一个插入有两个字符,那编辑距离变了几呢?1还是2?我又验证了一遍:确实是2

这也是sam文档中对NM这个tag的定义。

 

编辑距离是对两个字符串相似度的度量(参见文章:Edit Distance

举个栗子:两个字符串“eeba”和“abca”的编辑距离是多少?

根据定义,通过三个步骤:1.将e变为a 2.删除e 3.添加c,我们可以将“eeba”变为“abca”

所以,“eeba”和“abca”之间的编辑距离为3

 

回到序列比对的问题上

下面是常见的二代比对到ref的结果(bwa):

D00360:96:H2YLYBCXX:1:2110:18364:84053    353    seq1_len154_cov5    1    1    92S59M8I17M1D6M1D67M    seq30532_len2134_cov76    1    0    AAAAAAAAAAAAAAAAAAAAAAAACCCTGTCTCTAATAAAATACAAACAATTAGCCGGGCATGGTGGCACGCGCCTTTAGTCCCAGCTACTAGGGAGGCTGAGGCAGGGGAATTGTTTGAACCCGGGAGGTGGAGGTTGCAGTGAGCGGAGTTTTTTTCACTGCACTCCAGCCTGGTGACAAATCAAAAATCCATTTCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAACAACAAA
DDDDDHIIIIIIII<EHHII?EHH0001111111<11<DEH1D1<FH1D<<<C<@GEHD</<11<101<1D<<C<E0D11<<1<D?1F1CC1DE110C0D1011100////0DD<1=@1=FGHCDHH<FG<D0<<<EF?CE<00<<0<D//0;<:D/////;///////;8F.;/.8.8......88.9........-8BBGADHIIHD?>D?HH<,>=HHDD,5CHDCDHD><,,,--8----8-8--    NM:i:25    MD:Z:16A21C16C0A3T15^A6^G1G0T0G3C2T0G1C41A4A2A3    AS:i:49    XS:i:42    SA:Z:seq13646_len513_cov63,125,-,103S125M21S,1,11;    RG:Z:chr22

这是ref序列

>seq1_len154_cov5
GGGAGGCTGAGGCAGGAGAATTGTTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCAAGATTGCACTCCAGCCTGGATGACAAGAGTGAAACTCTGTCTCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

cigar字段包含了序列比对的简化信息,M(匹配比对,包含match和mismatch),=(纯match),X(纯mismatch),I(插入),D(删除),还有N、P和S、H。(注:目前只在blasr比对结果中见过=和X)

根据cigar字段可以统计indel信息,但是无法统计mismatch。

这个时候就可以用到NM tag了,mismatch = NM – I - D = 25 – 8 – 1 – 1 = 15

有兴趣的可以对着cigar数一遍,下面是我无聊数着的结果,也是15个

 

使用python的pysam模块可以很容易的提取出每个比对结果的NM信息

参见之前的帖子:pysam - 多种数据格式读写与处理模块(python)

 

再次验证一遍:证明NM=len(mismatch) + len(insertion) + len(deletion), 而不是 count(mismatch) + count(insertion) + count(deletion) (count的意思是三个碱基的insertion算一个)

>>> bam_file = pysam.AlignmentFile(infile, "rb")
>>> for line in bam_file:
... if 300 < line.query_alignment_length < 500:
... break
...
>>> line.query_alignment_length
321
>>> line.seq
'CTCTTCATCACGTCACTTGTCCATGTCAATGGCTACAGGTTGGAAGTTTGGCCGCGGAGGGTGGGCAGGCAAGAGAAAGAAATCAGATAGGGCAGATGGTAGGGTAAAAGGAGGGGGTTAAGTGCAAATTGTCTACTGTTTGCAAATGGGAAGCATGTGATTGTTAAAATTTATACGATAAACCTTCTCATCATGTTGAGTCTCATGCTTGCGCCAAGAAGATCGGGTTCGGCGGGTCAAGCTGATAAGCAACTTGGGCAGCAAAGTCGTTCAGTGATACAAAATCATGTGCAAAAATCACAAGCATTCTTATAAACACCA'
>>> line.cigarstring
'5148H3M1I2M1I4M2I3M3I3M1D2M1I4M3I1M1I4M1D10M1D5M4I4M3D1M3I18M1I1M1I1M1I4M4D2M1I2M2I4M2I4M1I4M5I4M1I9M1I14M3I1M1I2M2I7M2I7M3I2M1I5M2I1M1I2M1I1M1I4M5I3M1I2M3I1M1I4M4I3M4I2M2I1M3I19M3I10M2I4M1I11M1D27M2I6M25212H'
>>> line.reference_name
'Backbone_1'
>>> line.reference_start
7164
>>> line.reference_end
7413
>>> line.get_tag('NM')
100

取出了一条长度适中的比对结果,cigar字段比较全面。

取出了比对上的ref:

>>> ref = 'CTCTCTCACCACTCCTATTCAACACAGTGTTGGAAGTTCTGGACAGGGCAATCAGGCAAGAGAAAGAAATAAAGGGTATTCAATTAGGAAAAGAGGAAGTCAAATTGTCCCCGTTTGCAGATGACATGATTGTATATTTAGAAAACCCCACTGTTTCAGCCCCAAATCTCCTTAAGCTGATAAGCAACTTCAGCAAAGTCTCAGGATACAAAATCAATGTGCAAAAATCACAAGCATTCTTATACACCA'

先通过我自己写的cigar校正函数校正:

def formatSeqByCigar(seq, cigar):
'''
Input: query_alignment_sequence and cigar from sam file
Output: formatSeq
Purpose: make sure the pos is one to one correspondence(seq to ref)
'''
formatSeq = ''
pointer = 0; qstart = 0; qend = -1; origin_seq_len = 0
if cigar[0][0] == 4 or cigar[0][0] == 5:
qstart = cigar[0][1]
if cigar[-1][0] == 4 or cigar[-1][0] == 5:
qend = - cigar[-1][1] - 1 # fushu count
for pair in cigar:
operation = pair[0]
cigar_len = pair[1]
if operation == 0: # 0==M
formatSeq += seq[pointer:(pointer+cigar_len)]
pointer += cigar_len
origin_seq_len += cigar_len
elif operation == 1: # 1==I
pointer += cigar_len
origin_seq_len += cigar_len
elif operation == 2: # 2==D
formatSeq += 'D'*cigar_len
elif operation == 4 or operation == 5: # 5==H
origin_seq_len += cigar_len
continue
else:
print (cigar)
raise TypeError("There are cigar besides S/M/D/I/H\n")
return formatSeq, qstart, qend, origin_seq_len

然后分别计算deletion和mismatch:

>>> i = 0
>>> count = 0
>>> while i < len(ref):
if formatSeq[i] != ref[i]:
count += 1
i += 1 >>> count
17
>>> formatSeq.count('D')
11

可以看出deletion有11个,退出mismatch有6个。

随手一推insertion有83个。

>>> cigarstring = '5148H3M1I2M1I4M2I3M3I3M1D2M1I4M3I1M1I4M1D10M1D5M4I4M3D1M3I18M1I1M1I1M1I4M4D2M1I2M2I4M2I4M1I4M5I4M1I9M1I14M3I1M1I2M2I7M2I7M3I2M1I5M2I1M1I2M1I1M1I4M5I3M1I2M3I1M1I4M4I3M4I2M2I1M3I19M3I10M2I4M1I11M1D27M2I6M25212H'
>>> cigarstring.count('I')
41
>>> cigarstring.count('D')
6

用count计算显然不对。

验证成功

 

真切的明白了计算机有多么伟大,如果要是你肉眼去比对去数的话,我估计你会立马崩溃。

Edit Distance编辑距离(NM tag)- sam/bam格式解读进阶的更多相关文章

  1. mismatch位置(MD tag)- sam/bam格式解读进阶

    这算是第二讲了,前面一讲是:Edit Distance编辑距离(NM tag)- sam/bam格式解读进阶 MD是mismatch位置的字符串的表示形式,貌似在call SNP和indel的时候会用 ...

  2. sam/bam格式

    1)Sam (Sequence Alignment/Map) ------------------------------------------------- 1) SAM 文件产生背景 随着Ill ...

  3. [LeetCode] Edit Distance 编辑距离

    Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2 ...

  4. leetCode 72.Edit Distance (编辑距离) 解题思路和方法

    Edit Distance Given two words word1 and word2, find the minimum number of steps required to convert  ...

  5. [LeetCode] 72. Edit Distance 编辑距离

    Given two words word1 and word2, find the minimum number of operations required to convert word1 to  ...

  6. leetcode72. Edit Distance(编辑距离)

    以下为个人翻译方便理解 编辑距离问题是一个经典的动态规划问题.首先定义dp[i][j表示word1[0..i-1]到word2[0..j-1]的最小操作数(即编辑距离). 状态转换方程有两种情况:边界 ...

  7. 【LeetCode每天一题】Edit Distance(编辑距离)

    Given two words word1 and word2, find the minimum number of operations required to convert word1 to  ...

  8. 【LeetCode】72. Edit Distance 编辑距离(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 递归 记忆化搜索 动态规划 日期 题目地址:http ...

  9. edit distance(编辑距离,两个字符串之间相似性的问题)

    Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2 ...

随机推荐

  1. [转]get,post数据长度的限制

    一.问题起因 在某项目释放后Bug统计的附件<释放后问题>里有: 问题 原因 分析 备注 CSV处理时,如果处理的主题数过多,发生URL参数上限的错误: 可变长度的参数通过URL方式传递, ...

  2. [Django_1_2]数据库设置

    Django 数据库设置 本篇将介绍Django中的数据库设置,了解模型(models,数据库中的表项设计). 上一篇文章为:<a href="http://www.cnblogs.c ...

  3. div+css基础

    Div+css技术 Div是用于存放文字,图片,元素的容器 Css 是用于指定存放在div中的内容如何显示,包括内容的位置和外观(层叠样式表) Html 文件 <!--必须引入的文件--> ...

  4. xcode下编译.a文件的路径

    http://www.it165.net/pro/html/201503/36842.html 每当我们编译之后, 实际上系统就给我编译好了一个可以运行的.app文件,在某个路径下 如果我们建立的是静 ...

  5. c++中char*\wchar_t*\string\wstring之间的相互转换

    string U2A(const wstring& str)//Unicode字符转Ascii字符 { string strDes; if ( str.empty() ) goto __end ...

  6. UVA 11552 四 Fewest Flops

    Fewest Flops Time Limit:2000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Statu ...

  7. MyBatis Mapper 接口如何通过JDK动态代理来包装SqlSession 源码分析

    我们以往使用ibatis或者mybatis 都是以这种方式调用XML当中定义的CRUD标签来执行SQL 比如这样 <?xml version="1.0" encoding=& ...

  8. s2-029 Struts2 标签远程代码执行分析(含POC)

    1.标签介绍 Struts2标签库提供了主题.模板支持,极大地简化了视图页面的编写,而且,struts2的主题.模板都提供了很好的扩展性.实现了更好的代码复用.Struts2允许在页面中使用自定义组件 ...

  9. JAVA帮助文档全系列 JDK1.5 JDK1.6 JDK1.7 官方中英完整版下载

    JAVA帮助文档全系列 JDK1.5 JDK1.6 JDK1.7 官方中英完整版下载JDK(Java Development Kit,Java开发包,Java开发工具)是一个写Java的applet和 ...

  10. SQL——存储过程实例 循环

    --循环 create or replace procedure p_xunhuan(input in number,output out number) is ); begin ; ..input ...