寻找多个序列之间的共享模式

1 投票
2 回答
998 浏览
提问于 2025-04-18 00:59

我需要写一个脚本,循环遍历一组序列,找出它们之间的共同特征(可能会有多个不同的特征),并打印出所有序列共享的这个特征。

在下面的例子中:

chains = ['GATTACA', 'TAGACCA', 'ATACA']

AT就是一个共享的特征。我会很感激任何能解决这个问题的方法,包括使用BioPython的函数。

最近我写了一个脚本,它会循环处理同一组序列,把较短的序列作为参考,然后尝试在其他序列的每个位置中找到这个参考序列。但我真的不知道如何在不定义参考的情况下找到共享的特征。

# reference
xz=" ".join(chains)
ref= min(xz.split(), key=len)


# LOOKING FOR THE MOTIFS
for chain in chains:
    for i in range(len(chain)):
        if chain==ref:
            pass
        elif ref not in chain:
            print "%s has not been found in the  %s"%(ref, chain)
            break
        elif chain[i:].startswith(ref):
            print "%s has been detected in %s in the %d position" %(ref, chain, i+1)

2 个回答

0

最简单的方法是先明白,最长的公共子串不可能比我们正在查看的最短字符串还要长。很明显,如果我们从可能的最长子串开始,先检查它,然后再检查更短的子串,直到找到一个公共子串,我们就可以停止了。

所以,我们首先按照长度对DNA字符串进行排序。我们把最短的那个字符串的长度称为 l。接下来,我们的步骤是测试这个字符串的子串,首先检查长度为 l 的子串,然后是长度为 l-1 的两个子串,依此类推,直到找到匹配的子串并返回它。

from Bio import SeqIO

def get_all_substrings(iterable):
    s = tuple(iterable)
    seen = set()
    for size in range(len(s)+1, 1, -1):
        for index in range(len(s)+1-size):
            substring = iterable[index:index+size]
            if substring not in seen:
                seen.add(substring)
                yield substring

def main(input_file, return_all=False):
    substrings = []
    records = list(SeqIO.parse(open(input_file),'fasta'))
    records = sorted(records, key=lambda record: len(str(record.seq)))
    first, rest = records[0], records[1:]
    rest_sequences = [str(record.seq) for record in rest]
    for substring in get_all_substrings(str(first.seq)):
        if all(substring in seq for seq in rest_sequences):
            if return_all:
                substrings.append(substring)
            else:
                return substring
    return substrings
1

这只是个简单的想法。你需要对它进行改进,因为它几乎会搜索所有的空间。我希望这能对你有所帮助。

def cut_into_parts(chain, n):
    return [chain[x:x+n] for x in range(0, len(chain)-n)]

def cut_chains(chains, n):
    rlist = []
    for k,v in enumerate(chains):
        rlist.extend(cut_into_parts(chains, n))
    return rlist

def is_str_common(str, chains):
    for k,v in enumerate(chains):
        if !chains[k].contains(str):
            return false
    return true

def find_best_common(chains):
    clist = []
    for i in inverse(range(0, len(chains)))://inverse - I dont remmeber exactly the name of func
        clist.extend(cut_chains(chains, i))
    for k, v in enumerate(clist):
        return is_str_common(clist[k], chains)

撰写回答