11#include <unordered_set>
14#include <btllib/bihash_hashing_internals.hpp>
15#include <btllib/status.hpp>
19using hashing_internals::extend_hashes;
20using hashing_internals::srol;
21using hashing_internals::sror;
23using hashing_internals::base_forward_bi_hash;
24using hashing_internals::next_forward_bi_hash;
25using hashing_internals::prev_forward_bi_hash;
27using hashing_internals::base_reverse_bi_hash;
28using hashing_internals::next_reverse_bi_hash;
29using hashing_internals::prev_reverse_bi_hash;
31using hashing_internals::BI_CONVERT_TAB;
32using hashing_internals::BI_RC_CONVERT_TAB;
34using hashing_internals::CA_DIMER_TAB;
35using hashing_internals::CC_DIMER_TAB;
36using hashing_internals::CG_DIMER_TAB;
37using hashing_internals::CT_DIMER_TAB;
39using hashing_internals::MS_TAB_31L_CA;
40using hashing_internals::MS_TAB_31L_CC;
41using hashing_internals::MS_TAB_31L_CG;
42using hashing_internals::MS_TAB_31L_CT;
43using hashing_internals::MS_TAB_33R_CA;
44using hashing_internals::MS_TAB_33R_CC;
45using hashing_internals::MS_TAB_33R_CG;
46using hashing_internals::MS_TAB_33R_CT;
69 hashing_internals::NUM_HASHES_TYPE num_hashes,
70 hashing_internals::K_TYPE k,
75 , num_hashes(num_hashes)
79 , hash_arr(new uint64_t[num_hashes])
81 check_error(k == 0,
"BiHash: k must be greater than 0");
83 check_error((k / 2) % 2 == 0,
"BiHash: k must have odd number of dimers");
85 "BiHash: sequence length (" + std::to_string(this->seq_len) +
86 ") is smaller than k (" + std::to_string(k) +
")");
88 "BiHash: passed position (" + std::to_string(pos) +
89 ") is larger than sequence length (" +
90 std::to_string(this->seq_len) +
")");
91 static const std::unordered_set<std::string> valid_modes = {
92 "CG",
"CC",
"CT",
"CA"
94 check_error(valid_modes.find(mode) == valid_modes.end(),
95 "BiHash: mode must be one of [CG, CC, CT, CA], but got '" +
99 DIMER_TAB = CC_DIMER_TAB;
100 TAB_33R = MS_TAB_33R_CC;
101 TAB_31L = MS_TAB_31L_CC;
102 meth_signal = {
"CC",
"GG" };
103 }
else if (mode ==
"CG") {
104 DIMER_TAB = CG_DIMER_TAB;
105 TAB_33R = MS_TAB_33R_CG;
106 TAB_31L = MS_TAB_31L_CG;
107 meth_signal = {
"CG" };
108 }
else if (mode ==
"CT") {
109 DIMER_TAB = CT_DIMER_TAB;
110 TAB_33R = MS_TAB_33R_CT;
111 TAB_31L = MS_TAB_31L_CT;
112 meth_signal = {
"CT",
"AG" };
113 }
else if (mode ==
"CA") {
114 DIMER_TAB = CA_DIMER_TAB;
115 TAB_33R = MS_TAB_33R_CA;
116 TAB_31L = MS_TAB_31L_CA;
117 meth_signal = {
"CA",
"TG" };
136 hashing_internals::NUM_HASHES_TYPE num_hashes,
137 hashing_internals::K_TYPE k,
138 std::string mode =
"CG",
140 :
BiHash(seq.data(), seq.size(), num_hashes, k, mode, pos)
146 , seq_len(obj.seq_len)
147 , num_hashes(obj.num_hashes)
150 , initialized(obj.initialized)
151 , fwd_hashes(obj.fwd_hashes)
152 , rev_hashes(obj.rev_hashes)
153 , hash_arr(new uint64_t[obj.num_hashes])
155 DIMER_TAB = obj.DIMER_TAB;
156 TAB_33R = obj.TAB_33R;
157 TAB_31L = obj.TAB_31L;
159 hash_arr.get(), obj.hash_arr.get(), num_hashes *
sizeof(uint64_t));
182 auto dimer_valid = [&](
size_t p) ->
bool {
183 if (p + 1 > seq_len - 1)
186 char c2 = seq[p + 1];
187 uint8_t a = BI_CONVERT_TAB[(
unsigned char)c1];
188 uint8_t b = BI_CONVERT_TAB[(
unsigned char)c2];
189 uint8_t loc = 10 * a + b;
190 return DIMER_TAB[loc] != 0;
194 if (pos >= seq_len - k)
196 if (!dimer_valid(pos + k - 1)) {
205 fwd_hashes[1], rev_hashes[1], k, num_hashes, hash_arr.get());
209 if (pos >= seq_len - k)
212 if (!dimer_valid(pos + k - 1)) {
217 bool can_roll_second = dimer_valid(pos + k);
219 for (
int i = 0; i < 2; i++) {
220 if (i == 0 || can_roll_second) {
222 char out1 = seq[pos + i - 1];
223 char out2 = seq[pos + i + 1 - 1];
225 char in1 = seq[pos + k + i - 1];
226 char in2 = seq[pos + k + i + 1 - 1];
228 fwd_hashes[i] = next_forward_bi_hash(
229 fwd_hashes[i], k, out1, out2, in1, in2, DIMER_TAB, TAB_33R, TAB_31L);
231 rev_hashes[i] = next_reverse_bi_hash(
232 rev_hashes[i], k, out1, out2, in1, in2, DIMER_TAB, TAB_33R, TAB_31L);
236 extend_hashes(fwd_hashes[0], rev_hashes[0], k, num_hashes, hash_arr.get());
241 if (!can_roll_second) {
261 constexpr size_t DIMER_LEN = 2;
262 const size_t center_idx = pos + (k / 4) * DIMER_LEN;
263 return std::string_view(seq + center_idx, DIMER_LEN);
277 size_t num_dimers = k / 2;
278 size_t center_idx = pos + (num_dimers / 2) * 2;
281 dimer += seq[center_idx];
282 dimer += seq[center_idx + 1];
284 std::transform(dimer.begin(), dimer.end(), dimer.begin(), ::toupper);
285 return std::find(meth_signal.begin(), meth_signal.end(), dimer) !=
295 size_t idx = even ? 0 : 1;
296 return fwd_hashes[idx] > rev_hashes[idx];
313 auto dimer_valid = [&](
size_t p) ->
bool {
314 if (p + 1 >= seq_len)
316 uint8_t a = BI_CONVERT_TAB[(
unsigned char)seq[p]];
317 uint8_t b = BI_CONVERT_TAB[(
unsigned char)seq[p + 1]];
318 uint8_t loc = 10 * a + b;
319 return DIMER_TAB[loc] != 0;
325 fwd_hashes[0], rev_hashes[0], k, num_hashes, hash_arr.get());
333 if (!dimer_valid(pos - 1)) {
341 bool can_roll_second =
true;
342 if (pos <= 1 || !dimer_valid(pos - 2)) {
343 can_roll_second =
false;
347 if (fwd_hashes[1] == 0) {
352 fwd_hashes[1], rev_hashes[1], k, num_hashes, hash_arr.get());
358 for (
int i = 0; i < 2; i++) {
359 if (i == 1 || can_roll_second) {
361 char out1 = seq[pos + k - 2 + i];
362 char out2 = seq[pos + k - 1 + i];
363 char in1 = seq[pos - 2 + i];
364 char in2 = seq[pos - 1 + i];
366 fwd_hashes[i] = prev_forward_bi_hash(
367 fwd_hashes[i], k, out1, out2, in1, in2, DIMER_TAB, TAB_33R, TAB_31L);
369 rev_hashes[i] = prev_reverse_bi_hash(
370 rev_hashes[i], k, out1, out2, in1, in2, DIMER_TAB, TAB_33R, TAB_31L);
374 extend_hashes(fwd_hashes[1], rev_hashes[1], k, num_hashes, hash_arr.get());
385 const uint64_t*
hashes()
const {
return hash_arr.get(); }
398 hashing_internals::NUM_HASHES_TYPE
get_hash_num()
const {
return num_hashes; }
404 hashing_internals::K_TYPE
get_k()
const {
return k; }
413 return fwd_hashes[0];
415 return fwd_hashes[1];
426 return rev_hashes[0];
428 return rev_hashes[1];
434 const size_t seq_len;
435 hashing_internals::NUM_HASHES_TYPE num_hashes;
436 hashing_internals::K_TYPE k;
439 std::vector<uint64_t> fwd_hashes = { 0, 0 };
440 std::vector<uint64_t> rev_hashes = { 0, 0 };
441 std::vector<std::string> meth_signal;
443 std::unique_ptr<uint64_t[]> hash_arr;
444 const uint64_t* DIMER_TAB =
nullptr;
445 const uint64_t*
const* TAB_33R =
nullptr;
446 const uint64_t*
const* TAB_31L =
nullptr;
458 while (pos <= seq_len - k + 1 && has_n) {
460 for (
unsigned i = 0; i < k && pos <= seq_len - k + 1; i += 2) {
461 const char c1 = seq[pos + k - i - 2];
462 const char c2 = seq[pos + k - i - 1];
463 const uint8_t a = BI_CONVERT_TAB[(
unsigned char)c1];
464 const uint8_t b = BI_CONVERT_TAB[(
unsigned char)c2];
465 const uint8_t loc = 10 * a + b;
467 if (DIMER_TAB[loc] == 0) {
479 if (pos > seq_len - k) {
483 auto dimer_valid = [&](
size_t p) ->
bool {
484 if (p + 1 > seq_len - 1)
487 char c2 = seq[p + 1];
488 uint8_t a = BI_CONVERT_TAB[(
unsigned char)c1];
489 uint8_t b = BI_CONVERT_TAB[(
unsigned char)c2];
490 uint8_t loc = 10 * a + b;
491 return DIMER_TAB[loc] != 0;
493 bool has_second =
true;
494 if (pos == seq_len - k || !dimer_valid(pos + k - 1)) {
498 fwd_hashes = base_forward_bi_hash(seq + pos, has_second, k, DIMER_TAB);
499 rev_hashes = base_reverse_bi_hash(seq + pos, has_second, k, DIMER_TAB);
501 extend_hashes(fwd_hashes[0], rev_hashes[0], k, num_hashes, hash_arr.get());
Definition bihash_kmer.hpp:49
bool is_methylated()
Definition bihash_kmer.hpp:274
bool roll_back()
Definition bihash_kmer.hpp:303
const uint64_t * hashes() const
Definition bihash_kmer.hpp:385
BiHash(const char *seq, size_t seq_len, hashing_internals::NUM_HASHES_TYPE num_hashes, hashing_internals::K_TYPE k, std::string mode, size_t pos=0)
Definition bihash_kmer.hpp:67
uint64_t get_forward_hash() const
Definition bihash_kmer.hpp:410
hashing_internals::NUM_HASHES_TYPE get_hash_num() const
Definition bihash_kmer.hpp:398
BiHash(const std::string &seq, hashing_internals::NUM_HASHES_TYPE num_hashes, hashing_internals::K_TYPE k, std::string mode="CG", size_t pos=0)
Definition bihash_kmer.hpp:135
uint64_t get_reverse_hash() const
Definition bihash_kmer.hpp:423
std::string_view center_dimer() const
Definition bihash_kmer.hpp:259
size_t get_pos() const
Definition bihash_kmer.hpp:392
hashing_internals::K_TYPE get_k() const
Definition bihash_kmer.hpp:404
bool is_forward_higher()
Definition bihash_kmer.hpp:293
bool roll()
Definition bihash_kmer.hpp:176
void check_error(bool condition, const std::string &msg)