欢迎光临散文网 会员登陆 & 注册

【ROSALIND】【练Python,学生信】14 寻找DNA模序

2019-02-10 21:14 作者:未琢  | 我要投稿

如果第一次阅读本系列文档请先移步阅读【ROSALIND】【练Python,学生信】00 写在前面  谢谢配合~

题目:

寻找DNA共有模序(Finding a Shared Motif)

Given: A collection of k (k<100) DNA strings of length at most 1 kbp, each in FASTA format.

所给:不超过100条DNA序列,长度均不超过1kb,以FASTA格式给出。

Return: A longest common substring of the collection. (If multiple solutions exist, you may return any single solution.)

需得:这些DNA序列的最长公共子串(如果有多个,返回任意一个即可)。

 

测试数据

>Rosalind_1

GATTACA

>Rosalind_2

TAGACCA

>Rosalind_3

ATACA

测试输出

AC

 

背景

在09 确定DNA子序列出现的位置中,我们练习了从DNA序列中寻找给定子序列位置的方法,但是在实际应用中,我们并不能提前知道哪些是有意义的模序,需要通过比较多条序列以找到公共序列。

本题假设模序不发生突变,我们需要在一组DNA序列中找到每个序列共有的最长子序列。

 

思路

对本题我的想法是任意取一条DNA序列,将其打成稀碎的碎片,这里“稀碎”指每一个打碎方式都要出现。比如对序列‘AGCT’,打碎后出现的碎片有:‘AGCT’、‘AGC’、‘GCT’、‘AG’、‘GC’、‘CT’,单个碱基的因为没有意义所以不需要列出。如果一个碎片是所有DNA序列的公共子序列,那么它一定在每条序列中都出现,所以我要做的是在剩下的序列中一一检查各碎片是否存在,都在则为公共子序列。

我的代码也是按这个思路实现的。我写了一个打碎序列的函数,在其中用了两个循环以罗列出所有长度大于一的碎片。随后我将第一条序列输入该函数,得到一个储存了所有碎片的列表,为了方便取最长子串和提高比对效率,我用.sort()方法对碎片进行了由长到段的排列。之后就是挨个取碎片与序列比对。用一个标志flag记录碎片在几条序列中出现,若比对完flag与序列条数相等,说明所有序列都有该碎片,即找到了一****序列。

这段代码还有多处可以优化的地方,比如选择最短序列进行打碎、找到一条序列即可停止等。此外网上还有很多更简洁的编码方式和解题思路,在此不作引述,仅展示我自己的原始想法。

 

代码

def readfasta(lines):

    '''读取FASTA文件的函数'''

    seq = []

    index = []

    seqplast = ""

    numlines = 0

    for i in lines:

        if '>' in i:

            index.append(i.replace("\n", "").replace(">", ""))

            seq.append(seqplast.replace("\n", ""))

            seqplast = ""

            numlines += 1

        else:

            seqplast = seqplast + i.replace("\n", "")

            numlines += 1

        if numlines == len(lines):

            seq.append(seqplast.replace("\n", ""))

    seq = seq[1:]

    return index, seq

 

 

def frag(seq):

    '''将一条字符串打成长度不等的碎片的函数'''

    res = []

    i = 0

    while i < len(seq):

        s_seq = seq[i:]

        j = 1

        while j < len(s_seq):

            res.append(s_seq[:(len(s_seq)-j+1)])

            j += 1

        i += 1

    return res

 

 

f = open('input.txt', 'r')

lines = f.readlines()

f.close()

[index, seq] = readfasta(lines)

 

frags = frag(seq[0])

frags.sort(key=len, reverse=True)  # 将碎片按从长到短排列

i = 0

while i < len(frags):

    flag = 0

    for j in seq:

        r = j.count(frags[i])  # .count()方法返回碎片在字符串中出现的次数

        if r != 0:  # 若碎片出现过,flag值加一

            flag += 1

        if flag >= len(seq):

            print(frags[i])  # 若flag与序列数相同,说明为公共子串,符合要求,输出

            break

    i += 1


【ROSALIND】【练Python,学生信】14 寻找DNA模序的评论 (共 条)

分享到微博请遵守国家法律