试图对DNA序列的k-mer实施哈希函数,DNA序列通常包含四个字符A,C,G,T的组合。
我发现这个thread非常有趣,
我使用了A,C,G,T的简单映射到{00,01,10,11}(以位为单位),允许在一个字节中编码四个碱基。然后,您可以使用hash(word)+ hash(rc(word))或任何其他对称函数。这种方法的优点是您可以使用当前哈希来查找下一个哈希值;当您将基数移入和移出k-mer时,您可以移入和移出散列或散列成分。这是sylamer采用的方法,而且速度非常快。
但是我不知道如何用2位编码一个字符,我的问题是,是否有任何教程,库,用于将字符映射到位的函数?
答案 0 :(得分:2)
也许是这样的:
typedef enum { NB_A = 0, NB_C, NB_G, NB_T } Nucleobase;
Nucleobase nucleobase_encode(char n)
{
n = tolower((unsigned char) n);
switch(n)
{
case 'a': return NB_A;
case 'c': return NB_C;
case 'g': return NB_G;
case 't': return NB_T;
}
return 0;
}
然后你可以使用上面的代码将四个碱基编码成一个字节:
uint8_t encode_quad(char b0, char b1, char b2, char b3)
{
return (nucleobase_encode(b3) << 6) | (nucleobase_encode(b2) << 4) |
(nucleobase_encode(b1) << 2) | nucleobase_encode(b0);
}
这将对四个基数进行编码,如下所示:
b3 | b2 | b1 | b0
答案 1 :(得分:2)
虽然A,C,G&amp; T可以任意映射到00,01,10,11或任何其他布置 - 至少有一个映射实际上没有ASCII码,A,C,G&amp; T - &gt; 00,01,11,10:
B
方便地,该排列也适用于RNA,因为U核苷酸在取代DNA T核苷酸时不会干扰位模式:
A 65 01000|00|1 0
C 67 01000|01|1 1
G 71 01000|11|1 3
T 84 01010|10|0 2
要从ASCII字母到位,只需移位和屏蔽:(N&gt;&gt; 1)&amp; 3
同样,您使用的映射是任意的,这只是一个很容易实现的映射。
考虑到上述方法,让我们编写一个编码器/解码器,将32基本k-mer打包成64位数字:
U 85 01010|10|1 2
<强>输出强>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>
#define TWO_BIT_MASK (3)
#define BITS_PER_BYTE (8)
#define BIG_ENOUGH (1024)
uint64_t encode(char *original) {
size_t length = strlen(original);
assert(length * 2 == sizeof(uint64_t) * BITS_PER_BYTE);
uint64_t result = 0;
for (size_t i = 0; i < length; i++) {
result = (result << 2) | ((original[i] >> 1) & TWO_BIT_MASK);
}
return result;
}
void decode(uint64_t encoded, char *decoded, bool rna_flag) {
int i = sizeof(uint64_t) * BITS_PER_BYTE / 2;
for (decoded[i--] = '\0'; i >= 0; i--, encoded >>= 2) {
unsigned char byte = encoded & TWO_BIT_MASK;
if (byte == 2) {
byte = (rna_flag) ? 'U' : 'T';
} else {
byte = 'A' | (byte << 1);
}
decoded[i] = byte;
}
}
int main() {
char *segment = "GCCGTGCTAAGCGTAACAACTTCAAATCCGCG";
printf("%s\n", segment);
uint64_t binary = encode(segment);
printf("%llu\n", binary);
char string[BIG_ENOUGH];
decode(binary, string, false);
printf("%s\n", string);
return 0;
}