将字符串存储为int的函数

时间:2015-10-14 14:17:26

标签: python bioinformatics dna-sequence

我有一个固定的32位,用于存储尽可能多的DNA。存储1个字符的DNA('A''C''G''T')所需的空间量为2位(00,{{1} },0110,因为只有4种组合。)

要存储最多2个字符,(例如,11ACGTAA,...,AC)有20种可能的组合,我们可以使用函数GG来处理,其中((4**(x+1))-2)/(4-1)是我们想要的最大DNA长度储藏。因此,16个字符的DNA将具有5,726,623,060个组合,但是在32位中,我最多只能存储4,294,967,296个数字(2 ** 32)。

如此长的故事简短,在32位中,可以存储的可变长度DNA的最大量是15个字母(1,431,655,764种组合)。

因此,下一步是制作一个函数,最多可以将15个字母的DNA作为字符串,并将其转换为数字。哪个号码(x可以是'A',可能是0,可能是1,它确实无关紧要,这并不重要只要我们可以撤消该功能并稍后将该号码返回1332904

我开始通过制作包含1,431,655,764个元素的'A'对的字典来解决这个问题,但很快就用光了。这就是我需要从string到int的翻译函数的原因。

3 个答案:

答案 0 :(得分:4)

这是我的建议。

如果存储字母需要2到30位,则至少还有2位可以帮助您推断出长度。始终在表示字符的位之后添加1,并用零填充其余部分。这样,如果您在位模式中查找最后1 ,它将始终位于字符串结尾之后。

E.g。

A  -> 00 (meaning 'A') followed by 1 (meaning 'end') followed by 29 zeroes
   -> 00100000000000000000000000000000
C  -> 01 (meaning 'C') followed by 1 (meaning 'end') followed by 29 zeroes
   -> 01100000000000000000000000000000
G  -> 10 (meaning 'G') followed by 1 (meaning 'end') followed by 29 zeroes
   -> 10100000000000000000000000000000
T  -> 11 (meaning 'T') followed by 1 (meaning 'end') followed by 29 zeroes
   -> 11100000000000000000000000000000
AA -> 0000 (meaning 'AA') followed by 1, followed by 27 zeroes
   -> 00001000000000000000000000000000
...
AAAAAAAAAAAAAAA
   -> 000000000000000000000000000000 (meaning the 'A's) followed by 1, followed by 1 zero
   -> 00000000000000000000000000000010

应该明确地表示你的字符串,并允许你最多15个字符,32位。

答案 1 :(得分:2)

给定静态排序,您可以将每个单独的排列称为表示序列中顺序的单个数字。然后,而不是建立字典,你可以在另一边转换它。

import itertools

def build_sequence(length):
    return itertools.product("ACTG", repeat=length)

def encode(sequence: str):
    seq = build_sequence(len(str))
    t_seq = list(sequence)  # to compare to seq
    for idx, s in enumerate(seq):
        if s == t_seq:
            return idx

def decode(e_sequence):
    max_length = math.ceil(math.log(e_sequence, 4))
    # max_length is the character count of ATCGs that e_sequence contains,
    #   since each sequence has 4**length elements
    seq = build_sequence(max_length)
    for _ in range(e_sequence):
        # skipping these is like indexing a list
        next(seq)
    return next(seq)

然后,您可以将该号码打包成较小的类型并通过线路发送,再次打开包装并解码。

import struct

packed = struct.pack("I", encode(some_sequence))
#  send it? I'm not sure what you're doing with it

rcvd_pack = b'SUUU'
unpacked = struct.unpack("I", rcvd_pack)
# becomes a tuple of the value
enc_seq = unpacked[0]

result = decode(enc_seq)

这可以让你构建16个字符序列并将它们打包成32位数据。

答案 2 :(得分:1)

使用Khelwood的信息,我用以下代码解决了这个问题:

b = {'A':0b00,'C':0b01,'G':0b10,'T':0b11}
t = {'00':'A','01':'C','10':'G','11':'T'}

def binarize(string):
    result = 0
    for char in (string + 'G').ljust(16,'A'): result = (result << 2) + d[char]
    return result

def textualize(value):
    result = ''
    for twobits in [ format(value, '032b')[i:i+2] for i in range(0,32,2) ]:
        result += t[twobits]
    return result.rstrip('A')[:-1]

>>> binarize('TTTTTTTTTTTTTTT')
    4294967294

>>> textualize(4294967294)
    u'TTTTTTTTTTTTTTT'

我确信有一种更有效的方法来完成所有这些,我认为我需要这样做,因为我将编码和解码数十亿次,但现在它至少可以工作:)