计算DNA序列的编辑距离Python

4

我被分配了一个任务,需要对两个DNA序列之间的最低成本进行对齐。其中一个失败的输入如下:

CGCAATTCTGAAGCGCTGGGGAAGACGGGT & TATCCCATCGAACGCCTATTCTAGGAT 

适当的对齐成本是24,但我得到了23的成本。
我必须读取切换碱基的成本,例如A->T,G->C等等...我收到的成本文件如下:
*,-,A,T,G,C
-,0,1,2,1,3
A,1,0,1,5,1
T,2,1,0,9,1
G,1,5,9,0,1
C,3,1,1,1,0

我已经创建了一个Python字典,完美地将所有基本部分连接起来,它看起来像这样:

{'AT': '1', '-C': '3', 'TG': '9', '-G': '1', 'AC': '1', 'C-': '3', 'CA': '1', 'AA': '0', '--': '0', 'TA': '1', 'T-': '2', 'CG': '1', '-T': '2', 'CC': '0', 'GG': '0', 'A-': '1', 'CT': '1', 'AG': '5', 'GC': '1', 'GT': '9', 'GA': '5', 'G-': '1', '-A': '1', 'TC': '1', 'TT': '0'}

目前我的实现在某些情况下可以工作,在其他情况下可能会与实际结果相差 +/- 1。

下面是我的代码片段:

def align(one_Line, costBook):
    Split_Line = one_Line.split(",")
    array = [[0] * len(Split_Line[1]) for i in Split_Line[0]]  # Zero fill array,

    xLine = Split_Line[0]
    yLine = Split_Line[1]

    for i in range(1, len(xLine)):
        array[i][0] = array[i - 1][0] + int(costBook['-' + xLine[i - 1]])
    for i in range(1, len(yLine)):
        array[0][i] = array[0][i - 1] + int(costBook[yLine[i - 1] + '-'])

    for i in range(1, len(xLine)):
        for j in range(1, len(yLine)):
            array[i][j] = min(array[i - 1][j] + diff('-', xLine[i], costBook), 
                              array[i][j - 1] + diff(yLine[j], '-', costBook), 
                              array[i - 1][j - 1] + diff(yLine[j], xLine[i], costBook))

diff函数的作用是:

def diff(x, y, cost):
    if x == y:
        return 0
    keyStr = x + y
    return int(costBook[keyStr])

我哪里出错了?是在实际的数组填充过程中,还是我的基本情况处理有误?

编辑:这是一个半工作的版本,至少编辑成本是正确的:

AGTTGTGAAAGAACAAGCGCACAATATTGCCGCGCCGAAAGCT,TTCTTTCATTATTCAA‌​ATGTATAGTTTAGAGCGTTA‌​A

这是应该是 Needleman-Wunsch 算法吗? - nbryans
另外,你怎么知道适当的对齐成本应该是多少? - nbryans
相似但不完全相同,每个序列的长度都可以是任意的。匹配、不匹配或间隙的成本也可能会有所不同。哦,而且适当的成本已经给出了。 - Dringo
1个回答

4
我认为你的算法失败的原因是没有考虑数组(得分矩阵)中的“间隙”行。考虑两个序列A和B,每个序列的长度为n。如果我们查看Needleman-WunschSmith-Waterman算法的维基百科文章,我们会发现它们各自的“得分”矩阵在开头都有一行额外的行。这代表了A或B的第一个字符与间隙配对。我建议您快速查看这些页面以了解我的意思。
当您定义数组如下时:
array = [[0] * len(Split_Line[1]) for i in Split_Line[0]]

你没有包含这一额外的行。
你需要修改 align 函数以添加这个额外的行,并修改计算得分的逻辑。例如:
def align(one_Line, costBook):
    Split_Line = one_Line.split(",")

    # Defining an array with an extra row and col to represent a leading gap
    array = [[0] * (len(Split_Line[1])+1) for i in range(len(Split_Line[0])+1)]  # Zero fill array,

    xLine = Split_Line[0]
    yLine = Split_Line[1]

    # Changed so we include our extra line in the loop
    for i in range(1, len(xLine)+1):
        array[i][0] = array[i - 1][0] + int(costBook['-' + xLine[i - 1]])
    for i in range(1, len(yLine)+1):
        array[0][i] = array[0][i - 1] + int(costBook[yLine[i - 1] + '-'])

    # Changed so we include our extra row/col in the loop
    for i in range(1, len(xLine)+1):
        for j in range(1, len(yLine)+1):
            # The references to the original string now need -1 (i.e. i-1)
            array[i][j] = min(array[i - 1][j] + diff('-', xLine[i-1], costBook), 
                              array[i][j - 1] + diff(yLine[j-1], '-', costBook), 
                              array[i - 1][j - 1] + diff(yLine[j-1], xLine[i-1], costBook))
    return array

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接