在python中折叠DNA序列正向和反向补码的算法?

时间:2016-12-03 21:32:15

标签: python algorithm bioinformatics

我有一系列包含许多DNA序列片段的fasta文件。我正在尝试计算每个文件中可以找到的k-mers的总出现次数。计算k-mers的好处是可以创建大小为4 ** k的单个数组,其中k是所使用的k-mer的大小。我正在处理的序列文件是来自新一代测序机的短读序列,因此假设读数全部来自5' - > 3'结束无法完成。解决该问题的最佳方法是将观察到的所有k聚体映射到正向和反向补体序列的单个索引。

所需的映射:

k = 2&数组的起始索引是0

string ='aa'; 映射到索引 - > 0

string ='tt'; 映射到索引 - > 0

string ='at'; 映射到索引 - > 1

手动我能够发现所有具有正向和反向补充崩溃的mers的数组长度为10,具体指数代表以下mers: AA,AT,AC,AG,TA,TC,TG,CC,CG,GC

我无法考虑使用广义算法来了解更大尺寸k的可能mers的数量。应该在count数组中分配多少个单元格?

在我现有的代码中,我提出了这三个函数来处理片段,生成反向补码,并将mer(或反向补码)映射到索引。

第一个函数将获取mer字符串并返回与4 ** k size数组中的mer相关的索引。

def mer_index_finder(my_string, mer_size):
    # my_string = my_string.lower()
    char_value = {}
    char_value["a"] = 0
    char_value["t"] = 1
    char_value["c"] = 2
    char_value["g"] = 3
    i = 0
    j = 0
    base_four_string = ""

    while(i < mer_size):
        base_four_string += str(char_value[my_string[i]])
        i += 1

    index = int(base_four_string, 4)

    return index

此函数处理所有DNA片段并将计数映射到大小为4 **的数组中的索引

def get_mer_count(mer_size, file_fragments, slidingSize):
    mer_counts = {}
    for fragment in file_fragments:
        j = 0
        max_j = len(fragment) - mer_size
        while( j < max_j):
            mer_frag = fragment[j:j+mer_size]
            mer_frag = mer_frag.lower()
            if( "n" not in mer_frag):
                try:
                    mer_counts[mer_frag] += 1
                except:
                    mer_counts[mer_frag] = 1
            j += slidingSize

    myNSV = [0] * (4**mer_size)
    for mer in mer_counts.keys():
        mer_index = mer_index_finder(mer, mer_size)
        # examples showing how to collapse, 
        # without shrinking the array
        # rev_mer = make_complment_mer(mer)
        # print rev_mer
        # rev_index = mer_index_finder(rev_mer, mer_size)
        # min_index = min(mer_index, rev_index)
        # print mer_index,"\t",rev_index,"\t",min_index
        # myNSV[min_index] += mer_counts[mer]
        myNSV[mer_index] = mer_counts[mer]

    return myNSV[:]

最后这个函数将采用一个mer并生成反向补码:

def make_complment_mer(mer_string):
    nu_mer = ""
    compliment_map = {"a" : "t", "c" : "g", "t" : "a", "g" : "c"}
    for base in mer_string:
        nu_mer += compliment_map[base]
    nu_mer = nu_mer[::-1]
    return nu_mer[:]

似乎应该有一种明显的方法可以随时了解阵列在将正向和反向互补物折叠在一起时应该具有多少个单元格,并且文献中有一些示例,并且已经完成了一些包装。但是,我没有在源代码中找到它们能够生成这些计算的位置。

这个问题的第二部分是你如何知道mer是前向还是反向补码而不检查两者?

示例:

(向前)

AAGATCACGG

(补体)

TTCTAGTGCC

(反向补充)

CCGTGATCTT

在上面的代码中,我采用了两个索引中的较低者,但似乎应该有一种方法可以解决这个问题,而无需为每个mer找到两次索引:一次前进,一次作为反向补码。

TL; DR如果正向和反向补码映射到同一索引,那么数组的大小是多少?

编辑: 为了使用答案找到数组大小,我修改了get_mer_count()以包含以下行来创建索引的大小:

array_size = (4 ** mer_size) / 2
if mer_size % 2 == 0:
    array_size += 2**(mer_size - 1)

myNSV = [0] * array_size

1 个答案:

答案 0 :(得分:5)

对于每个k - mer,有两种可能性:要么它只有一个反向补码,要么就是它自己的反向补语(&#34;回文&#34; mer)。因此,如果有p回文k - mers,那么我们知道数组大小应为p + (4**k - p)/2

  • 对于k奇数,没有回文mers,因为中间核苷酸不能是它自己的赞美。因此,数组的大小应为4**k / 2

  • 对于某些k,对于k = 2*j甚至j。当且仅当前半部分是其后半部分的反向赞美时,mer才是回文。前半部分可能4**j,因此有p = 4**j = 2**k回文k - mers。因此,使用上面的公式,数组的大小应为p + (4**k - p)/2 = 2**k + (4**k - 2**k)/2