【问题标题】:Search for string allowing for one mismatch in any location of the string搜索允许在字符串的任何位置出现一个不匹配的字符串
【发布时间】:2011-01-26 02:21:49
【问题描述】:

我正在处理长度为 25 的 DNA 序列(参见下面的示例)。我有一个 230,000 的列表,需要在整个基因组中寻找每个序列(弓形虫寄生虫)。我不确定基因组有多大,但比 230,000 个序列长得多。

我需要查找每个 25 个字符的序列,例如 (AGCCTCCCATGATTGAACAGATCAT)。

基因组被格式化为一个连续的字符串,即 (CATGGGAGGCTTGCGGAGCCTGAGGGCGGAGCCTGAGGTGGGAGGCTTGCGGAGTGCGGAGCCTGAGCCTGAGGGCGGAGCCTGAGGTGGGAGGCTT....)

我不在乎它在哪里或被找到了多少次,只关心它是否存在。
我认为这很简单--

str.find(AGCCTCCCATGATTGAACAGATCAT)

但我也找到了在任何位置定义为错误(不匹配)的紧密匹配,但只有一个位置,并在序列中记录该位置。我不确定如何做到这一点。我唯一能想到的是使用通配符并在每个位置使用通配符执行搜索。即,搜索 25 次。

例如,

AGCCTCCCATGATTGAACAGATCAT    
AGCCTCCCATGATAGAACAGATCAT

在第 13 位出现不匹配的紧密匹配。

速度不是什么大问题,因为我只做了 3 次,不过如果速度快就好了。

有执行此操作的程序 - 查找匹配项和部分匹配项 - 但我正在寻找这些应用程序无法发现的部分匹配类型。

这是 perl 的类似帖子,尽管它们只是比较序列而不是搜索连续字符串:

Related post

【问题讨论】:

    标签: python string pattern-matching string-matching dna-sequence


    【解决方案1】:

    您可以使用 Python 的内置功能通过正则表达式匹配进行搜索。

    在python中重新模块 http://docs.python.org/library/re.html

    正则表达式入门 http://www.regular-expressions.info/

    【讨论】:

      【解决方案2】:

      您可能会在Python-Levenshtein 中找到一些有用的各种例程。

      【讨论】:

      • 与他的问题最接近的答案是计算两个字符串之间的汉明距离的函数。他需要一个近似的 search 函数,而不是一个近似的 match 函数。
      【解决方案3】:

      这暗示了longest common subsequence problem。这里字符串相似性的问题是您需要针对 230000 个序列的连续字符串进行测试;因此,如果您将 25 个序列中的一个与连续字符串进行比较,您将获得非常低的相似性。

      如果计算 25 个序列和连续字符串之间的最长公共子序列,如果长度相同,您就会知道它是否在字符串中。

      【讨论】:

        【解决方案4】:
        >>> import re
        >>> seq="AGCCTCCCATGATTGAACAGATCAT"
        >>> genome = "CATGGGAGGCTTGCGGAGCCTGAGGGCGGAGCCTGAGGTGGGAGGCTTGCGGAGTGCGGAGCCTGAGCCTGAGGGCGGAGCCTGAGGTGGGAGGCTT..."
        >>> seq_re=re.compile('|'.join(seq[:i]+'.'+seq[i+1:] for i in range(len(seq))))
        
        >>> seq_re.findall(genome)  # list of matches
        []  
        
        >>> seq_re.search(genome) # None if not found, otherwise a match object
        

        这个会停止第一个匹配,所以当有多个匹配时可能会更快一些

        >>> print "found" if any(seq_re.finditer(genome)) else "not found"
        not found
        
        >>> print "found" if seq_re.search(genome) else "not found" 
        not found
        
        >>> seq="CAT"
        >>> seq_re=re.compile('|'.join(seq[:i]+'.'+seq[i+1:] for i in range(len(seq))))
        >>> print "found" if seq_re.search(genome) else "not found"
        found
        

        对于长度为 10,000,000 的基因组,单线程扫描 230,000 个序列大约需要 2.5 天,因此您可能希望将任务拆分到几个核心/cpu 上。

        当这个算法正在运行时,你总是可以开始实现更高效的算法:)

        如果您希望搜索单个删除或添加的元素,请将正则表达式更改为此

        >>> seq_re=re.compile('|'.join(seq[:i]+'.{0,2}'+seq[i+1:] for i in range(len(seq))))
        

        【讨论】:

        • 基因组是 80 兆碱基。所以我会有很多时间来获得更好的算法。有没有一种好的/简单的方法可以将它从 python 中划分出来?
        • @Vincent,可能值得将此作为一个单独的问题提出。无论您使用哪种算法,都值得分解任务。您有多少核心/cpu 可供使用?
        • @Vincent 看到这个问题stackoverflow.com/questions/2359253/…
        • 我看到了一个使用 fnmatch.fnmatch() 的解决方案你知道那个种子可能会比较吗?
        【解决方案5】:

        在继续阅读之前,您看过biopython吗?

        您似乎希望找到一个替换错误和零插入/删除错误(即汉明距离为 1)的近似匹配。

        如果您有汉明距离匹配功能(例如,请参阅 Ignacio 提供的链接),您可以像这样使用它来搜索第一个匹配项:

        any(Hamming_distance(genome[x:x+25], sequence) == 1 for x in xrange(len(genome)))
        

        但这会相当慢,因为 (1) 汉明距离函数会在第二次替换错误后继续研磨 (2) 在失败后,它会将光标前进一格,而不是根据它看到的内容向前跳过(比如Boyer-Moore 搜索确实如此)。

        您可以使用以下函数克服 (1):

        def Hamming_check_0_or_1(genome, posn, sequence):
            errors = 0
            for i in xrange(25):
                if genome[posn+i] != sequence[i]:
                    errors += 1
                    if errors >= 2:
                        return errors
            return errors 
        

        注意:这不是 Pythonic,而是 Cic,因为您需要使用 C(可能通过 Cython)才能获得合理的速度。

        Navarro 和 Raffinot(谷歌“Navarro Raffinot nrgrep”)已经在位并行近似 Levenshtein 搜索上进行了一些工作,这可以适用于 Hamming 搜索。请注意,位并行方法对查询字符串的长度和字母大小有限制,但您的方法分别为 25 和 4,因此没有问题。更新:对于字母大小为 4 的跳过可能没有多大帮助。

        当您在谷歌上搜索汉明距离搜索时,您会注意到很多关于在硬件中实现它的东西,而在软件中却很少。这是一个很大的提示,也许你想出的任何算法都应该用 C 或其他编译语言来实现。

        更新: 位并行方法的工作代码

        我还提供了一种简单的方法来帮助进行正确性检查,并且我打包了 Paul 的 re 代码的变体以进行一些比较。请注意,使用 re.finditer() 会提供不重叠的结果,这可能会导致距离为 1 的匹配掩盖了精确匹配;查看我的最后一个测试用例。

        位并行方法具有以下特点:保证线性行为 O(N),其中 N 是文本长度。注意天真的方法是 O(NM) 和正则表达式方法一样(M 是模式长度)。 Boyer-Moore 风格的方法将是最坏情况 O(NM) 和预期 O(N)。当输入必须被缓冲时,也可以很容易地使用位并行方法:它可以一次输入一个字节或一个兆字节;没有前瞻,缓冲区边界没有问题。最大的优势:用 C 编写的每个输入字节的简单代码的速度。

        缺点:模式长度实际上受限于快速寄存器中的位数,例如32 或 64。在这种情况下,图案长度为 25;没问题。它使用与模式中不同字符的数量成比例的额外内存(S_table)。在这种情况下,“字母大小”只有 4;没问题。

        来自this technical report 的详细信息。该算法用于使用 Levenshtein 距离进行近似搜索。为了转换为使用汉明距离,我只是(!)删除了处理插入和删除的语句 2.1 的片段。您会注意到很多带有“d”上标的“R”引用。 “d”是距离。我们只需要 0 和 1。这些“R”成为下面代码中的 R0 和 R1 变量。

        # coding: ascii
        
        from collections import defaultdict
        import re
        
        _DEBUG = 0
        
        
        # "Fast Text Searching with Errors" by Sun Wu and Udi Manber
        # TR 91-11, Dept of Computer Science, University of Arizona, June 1991.
        # http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.20.8854
        
        def WM_approx_Ham1_search(pattern, text):
            """Generate (Hamming_dist, start_offset)
            for matches with distance 0 or 1"""
            m = len(pattern)
            S_table = defaultdict(int)
            for i, c in enumerate(pattern):
                S_table[c] |= 1 << i
            R0 = 0
            R1 = 0
            mask = 1 << (m - 1)
            for j, c in enumerate(text):
                S = S_table[c]
                shR0 = (R0 << 1) | 1
                R0 = shR0 & S
                R1 = ((R1 << 1) | 1) & S | shR0
                if _DEBUG:
                    print "j= %2d msk=%s S=%s R0=%s R1=%s" \
                        % tuple([j] + map(bitstr, [mask, S, R0, R1]))
                if R0 & mask: # exact match
                    yield 0, j - m + 1
                elif R1 & mask: # match with one substitution
                    yield 1, j - m + 1
        
        if _DEBUG:
        
            def bitstr(num, mlen=8):
               wstr = ""
               for i in xrange(mlen):
                  if num & 1:
                     wstr = "1" + wstr
                  else:
                     wstr = "0" + wstr
                  num >>= 1
               return wstr
        
        def Ham_dist(s1, s2):
            """Calculate Hamming distance between 2 sequences."""
            assert len(s1) == len(s2)
            return sum(c1 != c2 for c1, c2 in zip(s1, s2))
        
        def long_check(pattern, text):
            """Naively and understandably generate (Hamming_dist, start_offset)
            for matches with distance 0 or 1"""
            m = len(pattern)
            for i in xrange(len(text) - m + 1):
                d = Ham_dist(pattern, text[i:i+m])
                if d < 2:
                    yield d, i
        
        def Paul_McGuire_regex(pattern, text):
            searchSeqREStr = (
                '('
                + pattern
                + ')|('
                + ')|('.join(
                    pattern[:i]
                    + "[ACTGN]".replace(c,'')
                    + pattern[i+1:]
                    for i,c in enumerate(pattern)
                    )
                + ')'
                )
            searchSeqRE = re.compile(searchSeqREStr)
            for match in searchSeqRE.finditer(text):
                locn = match.start()
                dist = int(bool(match.lastindex - 1))
                yield dist, locn
        
        
        if __name__ == "__main__":
        
            genome1 = "TTTACGTAAACTAAACTGTAA"
            #         01234567890123456789012345
            #                   1         2
        
            tests = [
                (genome1, "ACGT ATGT ACTA ATCG TTTT ATTA TTTA"),
                ("T" * 10, "TTTT"),
                ("ACGTCGTAAAA", "TCGT"), # partial match can shadow an exact match
                ]
        
            nfailed = 0
            for genome, patterns in tests:
                print "genome:", genome
                for pattern in patterns.split():
                    print pattern
                    a1 = list(WM_approx_Ham1_search(pattern, genome))
                    a2 = list(long_check(pattern, genome))
                    a3 = list(Paul_McGuire_regex(pattern, genome))
                    print a1
                    print a2
                    print a3
                    print a1 == a2, a2 == a3
                    nfailed += (a1 != a2 or a2 != a3)
            print "***", nfailed
        

        【讨论】:

        • 这至少值得一看,以避免整个重新发明轮子的事情!
        • 我在 biopython 上发布了这个问题。他们建议只使用 BLAST 并用 python 解析结果。因为结果将包括许多/广泛的匹配结果。
        • shshR0 中代表什么?
        • 谢谢。 WM_approx_Ham1_search 是否应该在 len(text) &lt; 100000len(pattern) &lt; len(text) 和基数为 27 的字母表中顺利工作?
        • @Randomblue: len(text) 不是问题,一次只需要 1 个字符。 len(pattern) 完全不同:见上文(“缺点:模式长度实际上受限于快速寄存器中的位数,例如 32 或 64”)。 Python 代码应该可以顺利运行,但对于长模式来说运行缓慢。
        【解决方案6】:

        您可以从您想要匹配的所有不同序列中创建一个trie。现在是使深度优先搜索功能向下尝试最多允许一个不匹配的棘手部分。

        这种方法的优点是您可以一次搜索所有序列。这将为您节省很多比较。例如,当您从顶部节点开始并沿着“A”分支向下走时,您刚刚为自己节省了数千次比较,因为它立即与所有以“A”开头的序列匹配。对于不同的论点,考虑与给定序列完全匹配的基因组切片。如果您的序列列表中有一个不同的序列,仅在最后一个符号上有所不同,那么使用 trie 只是为您节省了 23 次比较操作。

        这是实现这一点的一种方法。将 'A','C',T',G' 转换为 0,1,2,3 或它的变体。然后使用元组的元组作为 trie 的结构。在每个节点上,数组中的第一个元素对应于“A”,第二个元素对应于“C”,依此类推。如果'A'是这个节点的一个分支,那么有另一个4个元素的元组作为这个节点元组的第一项。如果没有“A”分支,则将第一项设置为 0。在 trie 的底部是具有该序列 id 的节点,以便可以将其放入匹配列表中。

        以下是递归搜索函数,允许此类 trie 出现一个不匹配:

        def searchnomismatch(node,genome,i):
            if i == 25:
                addtomatches(node)
            else:
                for x in range(4):
                    if node[x]:
                        if x == genome[i]:
                            searchnomismatch(node[x],genome,i+1)
                        else:
                            searchmismatch(node[x],genome,i+1,i)
        
        def searchmismatch(node,genome,i,where):
            if i == 25:
                addtomatches(node,where)
            else:
                if node[genome[i]]:
                    searchmismatch(node[genome[i]],genome,i+1,where)
        

        在这里,我开始搜索类似

        searchnomismatch(trie,genome[ind:ind+25],0)
        

        addtomatches 类似于

        def addtomatches(id,where=-1):
            matches.append(id,where)
        

        等于 -1 表示没有不匹配。无论如何,我希望我说得足够清楚,以便您了解图片。

        【讨论】:

        • 有趣的是,我首先想到的是尝试从基因组的所有长度为 25 的子串中进行尝试,并以相同的方式将每个候选者与它匹配。那需要更多的内存。我认为您的方法可以进一步优化为 Aho-Corasick 字符串匹配的泛化。
        • @Darius 是的,我仍然认为 trie 是一个非常好的方法。我不认为内存会太多,特别是如果使用像基数特里这样的内存效率更高的特里。我发现在最坏的情况下,将访问 925 个节点(使用基本 trie)以找到与基因组的单个切片匹配的所有序列。平均情况远低于此。这对我来说似乎很快。我得看看 Aho-Corasick 算法。
        • 当然——我的意思是 my 答案的变体需要更多的内存。我确实对此表示赞同,这是一些愚蠢的 StackOverflow 错误,将我的投票转移到了其他随机答案——这在以前发生过。让我们期待这一次吧。
        • 顺便说一句,Aho-Corasick 的想法是在不备份的情况下逐字节检查基因组,而不是一次检查一个 25 字节的帧。您可以通过尝试来提前编译状态机,就好像您正在匹配基因组一样,只是还没有实际查看基因组——而是记录测试和状态。
        • (这相当于 gnibbler 的回答,除了 Python 的内置 regexp 实现显然没有创建状态机,而是回溯,所以它在这个问题上失败了。)
        【解决方案7】:

        我在网上搜索“弓形虫寄生虫基因组”以找到其中一些基因组文件。我发现了一个我认为很接近的文件,一个名为“TgondiiGenomic_ToxoDB-6.0.fasta”的文件,位于http://toxodb.org,大小约为 158Mb。我使用以下 pyparsing 表达式提取基因序列,只用了不到 2 分钟:

        fname = "TgondiiGenomic_ToxoDB-6.0.fasta"
        fastasrc = open(fname).read()   # yes! just read the whole dang 158Mb!
        
        """
        Sample header:
        >gb|scf_1104442823584 | organism=Toxoplasma_gondii_VEG | version=2008-07-23 | length=1448
        """
        integer = Word(nums).setParseAction(lambda t:int(t[0]))
        genebit = Group(">gb|" + Word(printables)("id") + SkipTo("length=") + 
                        "length=" + integer("genelen") + LineEnd() + 
                        Combine(OneOrMore(Word("ACGTN")),adjacent=False)("gene"))
        
        # read gene data from .fasta file - takes just under a couple of minutes
        genedata = OneOrMore(genebit).parseString(fastasrc)
        

        (惊奇!一些基因序列包括'N's的运行!这到底是什么?!)

        然后我把这个类写成 pyparsing Token 类的子类,用于进行近距离匹配:

        class CloseMatch(Token):
            def __init__(self, seq, maxMismatches=1):
                super(CloseMatch,self).__init__()
                self.name = seq
                self.sequence = seq
                self.maxMismatches = maxMismatches
                self.errmsg = "Expected " + self.sequence
                self.mayIndexError = False
                self.mayReturnEmpty = False
        
            def parseImpl( self, instring, loc, doActions=True ):
                start = loc
                instrlen = len(instring)
                maxloc = start + len(self.sequence)
        
                if maxloc <= instrlen:
                    seq = self.sequence
                    seqloc = 0
                    mismatches = []
                    throwException = False
                    done = False
                    while loc < maxloc and not done:
                        if instring[loc] != seq[seqloc]:
                            mismatches.append(seqloc)
                            if len(mismatches) > self.maxMismatches:
                                throwException = True
                                done = True
                        loc += 1
                        seqloc += 1
                else:
                    throwException = True
        
                if throwException:
                    exc = self.myException
                    exc.loc = loc
                    exc.pstr = instring
                    raise exc
        
                return loc, (instring[start:loc],mismatches)
        

        对于每个匹配,这将返回一个元组,其中包含匹配的实际字符串,以及不匹配位置的列表。精确匹配当然会为第二个值返回一个空列表。 (我喜欢这个类,我想我会把它添加到pyparsing的下一个版本中。)

        然后我运行此代码在从 .fasta 文件读取的所有序列中搜索“最多 2 个不匹配”匹配项(回想一下,genedata 是 ParseResults 组的序列,每个组包含一个 id、一个整数长度和一个序列字符串):

        searchseq = CloseMatch("ATCATCGAATGGAATCTAATGGAAT", 2)
        for g in genedata:
            print "%s (%d)" % (g.id, g.genelen)
            print "-"*24
            for t,startLoc,endLoc in searchseq.scanString(g.gene):
                matched, mismatches = t[0]
                print "MATCH:", searchseq.sequence
                print "FOUND:", matched
                if mismatches:
                    print "      ", ''.join(' ' if i not in mismatches else '*' 
                                    for i,c in enumerate(searchseq.sequence))
                else:
                    print "<exact match>"
                print "at location", startLoc
                print
            print
        

        我从一个基因位中随机提取了搜索序列,以确保我能找到精确匹配,只是出于好奇,看看有多少 1 元素和 2 元素不匹配。

        这需要一段时间才能运行。 45 分钟后,我得到了这个输出,列出了每个 id 和基因长度,以及找到的任何部分匹配项:

        scf_1104442825154 (964)
        ------------------------
        
        scf_1104442822828 (942)
        ------------------------
        
        scf_1104442824510 (987)
        ------------------------
        
        scf_1104442823180 (1065)
        ------------------------
        ...
        

        我越来越气馁,直到:

        scf_1104442823952 (1188)
        ------------------------
        MATCH: ATCATCGAATGGAATCTAATGGAAT
        FOUND: ATCATCGAACGGAATCGAATGGAAT
                        *      *        
        at location 33
        
        MATCH: ATCATCGAATGGAATCTAATGGAAT
        FOUND: ATCATCGAATGGAATCGAATGGAAT
                               *        
        at location 175
        
        MATCH: ATCATCGAATGGAATCTAATGGAAT
        FOUND: ATCATCGAATGGAATCGAATGGAAT
                               *        
        at location 474
        
        MATCH: ATCATCGAATGGAATCTAATGGAAT
        FOUND: ATCATCGAATGGAATCGAATGGAAT
                               *        
        at location 617
        
        MATCH: ATCATCGAATGGAATCTAATGGAAT
        FOUND: ATCATCGAATGGAATCGAATAGAAT
                               *   *    
        at location 718
        
        MATCH: ATCATCGAATGGAATCTAATGGAAT
        FOUND: ATCATCGAATGGATTCGAATGGAAT
                            *  *        
        at location 896
        
        MATCH: ATCATCGAATGGAATCTAATGGAAT
        FOUND: ATCATCGAATGGAATCGAATGGTAT
                               *     *  
        at location 945
        

        最后是我的完全匹配:

        scf_1104442823584 (1448)
        ------------------------
        MATCH: ATCATCGAATGGAATCTAATGGAAT
        FOUND: ATCATCGAATGGACTCGAATGGAAT
                            *  *        
        at location 177
        
        MATCH: ATCATCGAATGGAATCTAATGGAAT
        FOUND: ATCATCGAATGGAATCAAATGGAAT
                               *        
        at location 203
        
        MATCH: ATCATCGAATGGAATCTAATGGAAT
        FOUND: ATCATCAAATGGAATCGAATGGAAT
                     *         *        
        at location 350
        
        MATCH: ATCATCGAATGGAATCTAATGGAAT
        FOUND: ATCATCGAATGGAATCGAATGGAAA
                               *       *
        at location 523
        
        MATCH: ATCATCGAATGGAATCTAATGGAAT
        FOUND: ATCATCAAATGGAATCGAATGGAAT
                     *         *        
        at location 822
        
        MATCH: ATCATCGAATGGAATCTAATGGAAT
        FOUND: ATCATCGAATGGAATCTAATGGAAT
        <exact match>
        at location 848
        
        MATCH: ATCATCGAATGGAATCTAATGGAAT
        FOUND: ATCGTCGAATGGAGTCTAATGGAAT
                  *         *           
        at location 969
        

        因此,虽然这没有创造任何速度记录,但我完成了工作,并且还找到了一些 2 匹配项,以防他们可能感兴趣。

        为了比较,这里是一个基于 RE 的版本,它只发现 1 个不匹配的匹配项:

        import re
        seqStr = "ATCATCGAATGGAATCTAATGGAAT"
        searchSeqREStr = seqStr + '|' + \
            '|'.join(seqStr[:i]+"[ACTGN]".replace(c,'') +seqStr[i+1:] 
                     for i,c in enumerate(seqStr))
        
        searchSeqRE = re.compile(searchSeqREStr)
        
        for g in genedata:
            print "%s (%d)" % (g.id, g.genelen)
            print "-"*24
            for match in searchSeqRE.finditer(g.gene):
                print "MATCH:", seqStr
                print "FOUND:", match.group(0)
                print "at location", match.start()
                print
            print
        

        (起初,我尝试搜索原始 FASTA 文件源本身,但很困惑为什么与 pyparsing 版本相比匹配项如此之少。然后我意识到有些匹配项必须跨越换行符,因为 fasta 文件输出是包裹在 n 个字符处。)

        因此,在第一次 pyparsing 传递以提取要匹配的基因序列之后,这个基于 RE 的搜索器又花了大约 1-1/2 分钟来扫描所有未经过文本包装的序列,以找到所有相同的 1 - pyparsing 解决方案所做的不匹配条目。

        【讨论】:

        • 根据维基百科的FASTA格式页面,N是AGCT序列。
        • 哇!你得到奖品。我也喜欢汉明,但如果我想做更多这样的事情,我会从你的代码开始。看看我对我自己问题的回答。令人惊讶的是,nexalign 的速度有多快。在 30 秒内发现我的文件与 me49 gondii fasta 文件的每 1 个不匹配项。
        • 别忘了,原始的 fasta 文件以 60 个字符的行列出了序列,但实际的基因序列是许多这样的行的串联。所需的匹配可能跨越换行符。
        【解决方案8】:

        我想这可能来晚了,但是有一个名为 PatMaN 的工具可以完全满足您的需求: http://bioinf.eva.mpg.de/patman/

        【讨论】:

          【解决方案9】:

          我尝试了一些解决方案,但如前所述,它们在处理大量序列(字符串)时速度很慢。

          我想出了使用bowtie 并将感兴趣的子字符串 (soi) 映射到包含 FASTA 格式字符串的参考文件。您可以提供允许的不匹配数 (0..3),然后根据允许的不匹配返回 soi 映射到的字符串。这运行良好且速度非常快。

          【讨论】:

            【解决方案10】:

            您可以使用正则表达式匹配库 TRE 进行“近似匹配”。它还具有 Python、Perl 和 Haskell 的绑定。

            import tre
            
            pt = tre.compile("Don(ald)?( Ervin)? Knuth", tre.EXTENDED)
            data = """
            In addition to fundamental contributions in several branches of
            theoretical computer science, Donnald Erwin Kuth is the creator of
            the TeX computer typesetting system, the related METAFONT font
            definition language and rendering system, and the Computer Modern
            family of typefaces.
            """
            
            fz = tre.Fuzzyness(maxerr = 3)
            print fz
            m = pt.search(data, fz)
            
            if m:
                print m.groups()
                print m[0]
            

            哪个会输出

            tre.Fuzzyness(delcost=1,inscost=1,maxcost=2147483647,subcost=1, maxdel=2147483647,maxerr=3,maxins=2147483647,maxsub=2147483647)
            ((95, 113), (99, 108), (102, 108))
            Donnald Erwin Kuth
            

            http://en.wikipedia.org/wiki/TRE_%28computing%29

            http://laurikari.net/tre/

            【讨论】:

              【解决方案11】:

              Python regex 库支持模糊正则表达式匹配。与TRE 相比的一个优点是它允许查找文本中正则表达式的所有匹配项(也支持重叠匹配项)。

              import regex
              m=regex.findall("AA", "CAG")
              >>> []
              m=regex.findall("(AA){e<=1}", "CAAG") # means allow up to 1 error
              m
              >>> ['CA', 'AG']
              

              【讨论】:

              • 为什么不返回'AA'
              • 查找所有实例,包括重叠的实例:pm=regex.findall("(AA){e&lt;=1}", "CAAG", overlapped=True)
              • 注意,{e&lt;=1} 允许 1 个替换、插入或删除;如果您只想允许 1 个替换,请使用 {s&lt;=1}
              • 快速说明此方法 - 它似乎不起作用:例如。当{e
              • @suze1992 你有没有向regex的作者报告错误?
              【解决方案12】:

              我觉得下面的代码简单方便。

              in_pattern = "";
              in_genome = "";
              in_mistake = d;
              out_result = ""
              
              
              kmer = len(in_pattern)
              
              def FindMistake(v):
                  mistake = 0
                  for i in range(0, kmer, 1):
                      if (v[i]!=in_pattern[i]):
                          mistake+=1
                      if mistake>in_mistake:
                          return False
                  return True
              
              
              for i in xrange(len(in_genome)-kmer+1):
                  v = in_genome[i:i+kmer]
                  if FindMistake(v):
                      out_result+= str(i) + " "
              
              print out_result
              

              您可以轻松插入要检查的基因组和片段,还可以设置错配值。

              【讨论】:

                【解决方案13】:

                这已经很老了,但也许这个简单的解决方案可以工作。 循环遍历取 25 个字符切片的序列。将切片转换为 numpy 数组。与 25char 字符串(也作为 numpy 数组)进行比较。将答案相加,如果答案是 24,则打印出循环中的位置和不匹配的位置。

                接下来的几行显示它工作正常

                将 numpy 导入为 np

                a = ['A','B','C']

                b = np.array(a)

                b

                array(['A', 'B', 'C'], dtype='

                c = ['A','D','C']

                d = np.array(c)

                b==d

                数组([真,假,真])

                总和(b==d)

                2

                【讨论】:

                  猜你喜欢
                  • 2011-03-20
                  • 2015-09-30
                  • 1970-01-01
                  • 2022-12-09
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多