我正在处理长度为 25 的 DNA 序列(参见下面的示例)。我有一个 230,000 的列表,需要在整个基因组中寻找每个序列(弓形虫寄生虫)。我不确定基因组有多大,但比 230,000 个序列长得多。
我需要查找每个 25 个字符的序列,例如 (AGCCTCCCATGATTGAACAGATCAT)。
基因组被格式化为一个连续的字符串,即(CATGGGAGGCTTGCGGAGCCTGAGGGCGGAGCCTGAGGTGGGAGGCTTGCGGAGTGCGGAGCCTGAGCCTGAGGGCGGAGCCTGAGGTGGGAGGCTT....)
我不在乎它在哪里或被找到多少次,只关心它是否。
我认为这很简单--
str.find(AGCCTCCCATGATTGAACAGATCAT)
但是我也找到了在任何位置定义为错误(不匹配)的紧密匹配,但只有一个位置,并在序列中记录该位置。我不确定如何做到这一点。我唯一能想到的是使用通配符并在每个位置使用通配符执行搜索。即,搜索 25 次。
例如,
AGCCTCCCATGATTGAACAGATCAT
AGCCTCCCATGATAGAACAGATCAT
在位置 13 处出现不匹配的紧密匹配。
速度不是什么大问题,因为我只做了 3 次,不过如果速度快就好了。
有执行此操作的程序 - 查找匹配项和部分匹配项 - 但我正在寻找这些应用程序无法发现的部分匹配类型。
这是 perl 的类似帖子,尽管它们只是比较序列而不是搜索连续字符串:
最佳答案
在继续阅读之前,您看过 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 搜索的工作,这可以适应汉明搜索。请注意,位并行方法对查询字符串的长度和字母大小有限制,但您的方法分别是 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
关于python - 搜索允许在字符串的任何位置出现一个不匹配的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2420412/
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
我有一个字符串input="maybe(thisis|thatwas)some((nice|ugly)(day|night)|(strange(weather|time)))"Ruby中解析该字符串的最佳方法是什么?我的意思是脚本应该能够像这样构建句子:maybethisissomeuglynightmaybethatwassomenicenightmaybethiswassomestrangetime等等,你明白了......我应该一个字符一个字符地读取字符串并构建一个带有堆栈的状态机来存储括号值以供以后计算,还是有更好的方法?也许为此目的准备了一个开箱即用的库?
我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,
在我的Rails(2.3,Ruby1.8.7)应用程序中,我需要将字符串截断到一定长度。该字符串是unicode,在控制台中运行测试时,例如'א'.length,我意识到返回了双倍长度。我想要一个与编码无关的长度,以便对unicode字符串或latin1编码字符串进行相同的截断。我已经了解了Ruby的大部分unicode资料,但仍然有些一头雾水。应该如何解决这个问题? 最佳答案 Rails有一个返回多字节字符的mb_chars方法。试试unicode_string.mb_chars.slice(0,50)
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%