【问题标题】:Two's complement in Python (shift left on many bits with rounding)Python中的二进制补码(四舍五入的多位左移)
【发布时间】:2017-08-10 20:58:24
【问题描述】:

我们如何从其代码中编码反向完整的 DNA 序列?

一个 DNA 序列可以包含 4 个不同的字符 A、C、G、T;其中A是T的补码,C是G的补码。

A DNA 序列的反向补码是序列的补码,但方式相反(我们从右到左计算每个字符的补码)。

例子:(AA)的补码是:TT,(AC)的补码是GT等等……

一般来说,使用 python,我们通过将每个字符映射到一个从 0 到 3 的数字来编码一个序列,

    {A:0, C:1, G:2, T:3}

那么AA的编码是:0,AC的编码是:

    AC = 0*4^0+1*4^1 = 4

GT的编码是:

    GT = 2*4^0+3*4^1 = 14 

如何在不创建字典的情况下将每个序列的代码转换为 python 中的反向补码?对于上面的示例:将 4 转换为 14?和 0 到 15 ...

【问题讨论】:

  • 你不能只使用位掩码吗?听起来像预先计算并将它们存储在字典中可能会更容易。
  • 这对你有帮助或者给你一些提示吗? stackoverflow.com/questions/1604464/… 我同意 @beoliver,为什么不使用位掩码?
  • 你是从教科书上复制sn-ps还是什么?我们没有给出一个例子,对整数进行四舍五入是没有意义的。他们的意思是轮换吗?如果是这样的话,它们会非常具体,因为这只适用于两个符号,并且说你正在交换它们比改变任何一个方向更有意义。
  • 我建议你从具体的操作中退后一步,向我们解释1)什么是序列的“反向完成”,2)序列存储为什么格式。从这个描述中,我只能猜测成对的位可能映射到这 4 个字母,但不能猜测它们是什么或为什么相互关联。

标签: python bit-shift twos-complement


【解决方案1】:

您的符号集太小,哈希映射实际上无法有效。将二进制补码混合到您的问题中只会引起混乱。

symbols = 'ACGT'
complements = symbols[::-1]   # reverse order
import string
table = string.maketrans(symbols, complements)
sample = 'ACCGTT'
print(sample[::-1].translate(table))
# output: AACGGT

转换为一些位压缩格式将占用更少的空间,但需要更多的特殊处理,因为您需要单独跟踪大小,执行任意宽的移位等等。 Python 当然可以做到这一点,特别是 int() 接受许多基数并创建任意宽度的结果,但这可能会适得其反。

digits = string.digits[:len(symbols)]
length = len(sample)
digitmap = string.maketrans(symbols, digits)
number = int(sample.translate(digitmap), len(digits))

def reversemapnumber(function=id, number=0, radix=0b100, length=0):
    result = 0
    for i in range(length):
        number,digit = divmod(number, radix)
        result = result*radix + function(digit)
    return result
revcomplemented = reversemapnumber(function=lambda x: 3-x,
        number=number, length=length)
# binary form
print('{:0{}b}'.format(revcomplemented, length*2))
# back to text form
print(''.join(symbols[(revcomplemented>>i)&0b11]
    for i in range(2*length-2, -2, -2)))

在混乱的代码中,我使用除法而不是移位来更通用(支持基数不是 2 的幂),但打印示例完全依赖于宽度。最后,它只是棘手和不清楚。

【讨论】:

    【解决方案2】:

    python中列表的逆向

    >>> xs = [1,2,3]
    >>> reversed(xs)
    <listreverseiterator object at 0x10089c9d0>
    >>> list(reversed(xs))
    [3, 2, 1]
    >>>
    
    def complement(x):
       return ~x & 15 # as 15 == int('1111', 2) 
    

    15 是位掩码。它代表二进制1111。然后我们使用二进制and 运算符。

    >>> "{0:b}".format(complement(int('1111',2)))
    '0'
    >>> "{0:b}".format(complement(int('0001',2)))
    '1110'
    >>> "{0:b}".format(complement(int('1001',2)))
    '110'
    
    >>> xs = [int('1111',2), int('1001',2), int('0110',2), int('1011',2)]
    >>> map(complement, xs)
    [0, 6, 9, 4]
    >>> list(reversed(map(complement, xs)))
    [4, 9, 6, 0]
    

    以你的例子为基础

    给定一个 6 个字符的序列:ACCGTT,A 的补码是:T, C的补码是G;所以ACCGTT的反补是:AACGGT。

    假设您有一个 complemnt 函数 complement 和一个反向函数 reverse

    我们有reverse(ACCGTT) = TTGCCAcomplement(ACCGTT) = TGGCAA .在对每个元素调用函数后反转列表与对列表中的每个元素调用函数相同。

    complement(reverse(ACCGTT)) = reverse(complement(ACCGTT))
    

    所以问题的另一部分是你想要映射

    {A:0, C:1, G:2, T:3}
    A -> T | 0 -> 3
    T -> A | 3 -> 0
    C -> G | 1 -> 2
    G -> C | 2 -> 1
    

    二进制是

    a = int('00', 2) # 0
    c = int('01', 2) # 1
    g = int('10', 2) # 2
    t = int('11', 2) # 3
    
    def complement(x):
        return ~x & 3 # this 3 is the same as int('11', 2)
    
    def reverse_complement(list_of_ints):
        return list(reversed(map(complement, list_of_ints)))
    

    【讨论】:

    • 在您的示例中,您只需将每个数字取反即可。对于我的问题,如果我们只有 2 个字符,我需要进行以下转换:0--15、1--11、2 -- 7、3 --3、4 -- 14 等等..,如果我们有 3 个字符: 0 -- 63, 16 -- 62, 48 -- 60 ,..
    • Cecile,该函数如何知道一个数字中有多少个字符?您在这里有 0 映射到任意大的值集。
    • Yann Vernier,字符数是程序的输入变量。例如,如果输入数字是 2,我们可以从 AA (0) 到 TT(15)。如果我们有 3 作为输入,我们可以从 AAA (0) 到 TTT (63)。但是一个数字中有多少个字符?这是我的问题,我试图寻找每个数字的二进制代码,希望找到一个数字与其反向补码之间的一些关系......
    • @Cecile 如果 AA = 0 且 AAA = 0,那么您可以拥有无​​限数量的 A = 0。您从哪里获得这些信息?
    • @beoliver,AA's=0,此编码用于 DNA 和 RNA 序列。 (researchgate.net/publication/…)
    猜你喜欢
    • 1970-01-01
    • 2019-07-13
    • 1970-01-01
    • 1970-01-01
    • 2019-09-06
    • 2014-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多