mirror of
https://github.com/chhylp123/hifiasm.git
synced 2026-09-25 22:28:11 +08:00
prepare for further changes
This commit is contained in:
+319
@@ -0,0 +1,319 @@
|
||||
#include <assert.h>
|
||||
#include "utils.h"
|
||||
#include "CommandLines.h"
|
||||
#include "Overlaps.h"
|
||||
|
||||
/*******************************
|
||||
* Dropping strong containment *
|
||||
*******************************/
|
||||
|
||||
static ma_hit_t *get_specific_overlap_with_del(ma_hit_t_alloc *sources, const ma_sub_t *coverage_cut, uint32_t qn, uint32_t tn)
|
||||
{
|
||||
if (coverage_cut[qn].del || coverage_cut[tn].del) return NULL;
|
||||
ma_hit_t_alloc *x = &sources[qn];
|
||||
uint32_t i;
|
||||
for (i = 0; i < x->length; i++) {
|
||||
if (x->buffer[i].del) continue;
|
||||
if (coverage_cut[Get_qn(x->buffer[i])].del) continue;
|
||||
if (coverage_cut[Get_tn(x->buffer[i])].del) continue;
|
||||
if (Get_tn(x->buffer[i]) == tn && Get_qn(x->buffer[i]) == qn)
|
||||
return &x->buffer[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void delete_single_edge(ma_hit_t_alloc *sources, const ma_sub_t *coverage_cut, uint32_t qn, uint32_t tn)
|
||||
{
|
||||
ma_hit_t *tmp = get_specific_overlap_with_del(sources, coverage_cut, qn, tn);
|
||||
if (tmp != NULL) tmp->del = 1;
|
||||
}
|
||||
|
||||
void delete_all_edges(ma_hit_t_alloc *sources, ma_sub_t *coverage_cut, uint32_t qn)
|
||||
{
|
||||
ma_hit_t_alloc* x = &sources[qn];
|
||||
uint32_t i;
|
||||
for (i = 0; i < x->length; i++) {
|
||||
x->buffer[i].del = 1;
|
||||
delete_single_edge(sources, coverage_cut, Get_tn(x->buffer[i]), Get_qn(x->buffer[i]));
|
||||
}
|
||||
coverage_cut[qn].del = 1;
|
||||
}
|
||||
|
||||
void ma_hit_contained_advance(ma_hit_t_alloc *sources, long long n_read, ma_sub_t *coverage_cut, R_to_U *ruIndex, int max_hang, int min_ovlp)
|
||||
{
|
||||
int32_t r;
|
||||
long long i, j, n_strong_contain = 0, n_weak_contain = 0;
|
||||
asg_arc_t t;
|
||||
ma_hit_t *h = NULL;
|
||||
ma_sub_t *sq = NULL;
|
||||
ma_sub_t *st = NULL;
|
||||
|
||||
for (i = 0; i < n_read; ++i) {
|
||||
if (coverage_cut[i].del) continue;
|
||||
for (j = 0; j < (long long)sources[i].length; j++) {
|
||||
h = &sources[i].buffer[j];
|
||||
//check the corresponding two reads
|
||||
sq = &coverage_cut[Get_qn(*h)];
|
||||
st = &coverage_cut[Get_tn(*h)];
|
||||
/****************************may have trio bugs********************************/
|
||||
if (sq->del || st->del) continue;
|
||||
if (h->del) continue;
|
||||
/****************************may have trio bugs********************************/
|
||||
r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, asm_opt.max_hang_rate, min_ovlp, &t);
|
||||
//assert(r != MA_HT_INT && r != MA_HT_SHORT_OVLP);
|
||||
if (r == MA_HT_QCONT) {
|
||||
if (h->ml || 1) {
|
||||
h->del = 1;
|
||||
++n_strong_contain;
|
||||
delete_single_edge(sources, coverage_cut, Get_tn(*h), Get_qn(*h));
|
||||
delete_all_edges(sources, coverage_cut, Get_qn(*h));
|
||||
set_R_to_U(ruIndex, Get_qn(*h), Get_tn(*h), 0);
|
||||
|
||||
// if (delete_all_edges_carefully(sources, coverage_cut, max_hang, min_ovlp, Get_qn(*h)) == 0)
|
||||
// set_R_to_U(ruIndex, Get_qn(*h), Get_tn(*h), 0);
|
||||
// sq->del = 1;
|
||||
// set_R_to_U(ruIndex, Get_qn(*h), Get_tn(*h), 0);
|
||||
} else {
|
||||
sq->weak_contain = 1;
|
||||
++n_weak_contain;
|
||||
}
|
||||
} else if (r == MA_HT_TCONT) {
|
||||
if (h->ml || 1) {
|
||||
h->del = 1;
|
||||
++n_strong_contain;
|
||||
delete_single_edge(sources, coverage_cut, Get_tn(*h), Get_qn(*h));
|
||||
delete_all_edges(sources, coverage_cut, Get_tn(*h));
|
||||
set_R_to_U(ruIndex, Get_tn(*h), Get_qn(*h), 0);
|
||||
|
||||
// if (delete_all_edges_carefully(sources, coverage_cut, max_hang, min_ovlp, Get_tn(*h)) == 0)
|
||||
// set_R_to_U(ruIndex, Get_tn(*h), Get_qn(*h), 0);
|
||||
// st->del = 1;
|
||||
// set_R_to_U(ruIndex, Get_tn(*h), Get_qn(*h), 0);
|
||||
} else {
|
||||
st->weak_contain = 1;
|
||||
++n_weak_contain;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
transfor_R_to_U(ruIndex);
|
||||
|
||||
for (i = 0; i < n_read; ++i) {
|
||||
int m = 0;
|
||||
for (j = 0; j < (long long)sources[i].length; j++) {
|
||||
ma_hit_t *h = &(sources[i].buffer[j]);
|
||||
if (h->del) continue;
|
||||
/// both the qn and tn have not been deleted
|
||||
if (coverage_cut[Get_qn(*h)].del != 1 && coverage_cut[Get_tn(*h)].del != 1)
|
||||
h->del = 0, ++m;
|
||||
else h->del = 1;
|
||||
}
|
||||
/// sources[i].length == 0 means all overlapped reads with read i are the contained reads
|
||||
if (m == 0) coverage_cut[i].del = 1;
|
||||
}
|
||||
|
||||
fprintf(stderr, "[M::%s] %lld strong containments; %lld weak containments\n", __func__,
|
||||
n_strong_contain, n_weak_contain);
|
||||
}
|
||||
|
||||
/************************************
|
||||
* Graph construction and reduction *
|
||||
************************************/
|
||||
|
||||
static inline void asg_con_push(asg_t *g, uint32_t lower, uint32_t upper, int rev)
|
||||
{
|
||||
if (g->n_con == g->m_con) {
|
||||
g->m_con = g->m_con? g->m_con<<1 : 16;
|
||||
REALLOC(g->contain, g->m_con);
|
||||
}
|
||||
g->contain[g->n_con++] = (uint64_t)lower << 32 | upper << 1 | (!!rev);
|
||||
}
|
||||
|
||||
void asg_con_sort(asg_t *g)
|
||||
{
|
||||
if (g->n_con > 1) radix_sort_ha64(g->contain, g->contain + g->n_con);
|
||||
}
|
||||
|
||||
void asg_con_index(asg_t *g)
|
||||
{
|
||||
uint32_t i, k;
|
||||
if (g->n_con == 0 || g->contain == 0) return;
|
||||
if (g->con_idx) free(g->con_idx);
|
||||
CALLOC(g->con_idx, g->n_seq);
|
||||
for (k = 0, i = 1; i < g->n_con; ++i)
|
||||
if (g->contain[k] != g->contain[i])
|
||||
g->contain[k++] = g->contain[i];
|
||||
g->n_con = k;
|
||||
for (i = 1, k = 0; i <= g->n_con; ++i)
|
||||
if (i == g->n_con || g->contain[i-1]>>32 != g->contain[i]>>32)
|
||||
g->con_idx[g->contain[i-1]>>32] = (uint64_t)k << 32 | (i - k), k = i;
|
||||
}
|
||||
|
||||
asg_t *ma_sg_gen(const ma_hit_t_alloc* sources, long long n_read, const ma_sub_t *coverage_cut, int max_hang, int min_ovlp)
|
||||
{
|
||||
size_t i, j;
|
||||
asg_t *g;
|
||||
g = asg_init();
|
||||
|
||||
// add seq to graph, seq just save the length of each read
|
||||
for (i = 0; i < (uint64_t)n_read; ++i) {
|
||||
///if a read has been deleted, should we still add them?
|
||||
asg_seq_set(g, i, coverage_cut[i].e - coverage_cut[i].s, coverage_cut[i].del);
|
||||
g->seq[i].c = coverage_cut[i].c;
|
||||
}
|
||||
|
||||
g->seq_vis = (uint8_t*)calloc(g->n_seq*2, sizeof(uint8_t));
|
||||
|
||||
for (i = 0; i < (uint64_t)n_read; ++i) {
|
||||
for (j = 0; j < sources[i].length; ++j) {
|
||||
int r, ql, tl;
|
||||
asg_arc_t t, *p;
|
||||
const ma_hit_t *h = &sources[i].buffer[j];
|
||||
uint32_t qn, tn;
|
||||
if (h->del) continue;
|
||||
qn = Get_qn(*h);
|
||||
tn = Get_tn(*h);
|
||||
ql = coverage_cut[qn].e - coverage_cut[qn].s;
|
||||
tl = coverage_cut[tn].e - coverage_cut[tn].s;
|
||||
r = ma_hit2arc(h, ql, tl, max_hang, asm_opt.max_hang_rate, min_ovlp, &t);
|
||||
assert(r >= 0);
|
||||
if (r >= 0) {
|
||||
p = asg_arc_pushp(g);
|
||||
*p = t;
|
||||
} else if (r == MA_HT_QCONT) {
|
||||
assert(h->ml == 0);
|
||||
asg_con_push(g, h->qns>>32, h->tn, h->rev);
|
||||
} else if (r == MA_HT_TCONT) {
|
||||
assert(h->ml == 0);
|
||||
asg_con_push(g, h->tn, h->qns>>32, h->rev);
|
||||
}
|
||||
}
|
||||
}
|
||||
asg_cleanup(g);
|
||||
g->r_seq = g->n_seq;
|
||||
return g;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint32_t len;
|
||||
uint8_t mark; // can only be 0, 1 or 2
|
||||
} trinfo_t;
|
||||
|
||||
// transitive reduction; see Myers, 2005
|
||||
int asg_arc_del_trans(asg_t *g, int fuzz)
|
||||
{
|
||||
trinfo_t *info;
|
||||
///n_vtx = number of seq * 2; the reason is that each read has two direction (query->target, target->query)
|
||||
uint32_t v, n_vtx = g->n_seq * 2, n_reduced = 0;
|
||||
///at first, all nodes should be set to vacant
|
||||
CALLOC(info, n_vtx);
|
||||
|
||||
/**v is the id+direction of a node,
|
||||
* the high 31-bit is the id,
|
||||
* and the lowest 1-bit is the direction
|
||||
* (0 means query-to-target, 1 means target-to-query)**/
|
||||
for (v = 0; v < n_vtx; ++v) {
|
||||
///nv is the number of overlaps with v(qn+direction)
|
||||
uint32_t L, i, nv = asg_arc_n(g, v);
|
||||
///av is the array of v
|
||||
asg_arc_t *av = asg_arc_a(g, v);
|
||||
///that means in this direction, read v is not overlapped with any other reads
|
||||
if (nv == 0) continue; // no hits
|
||||
|
||||
// if the read itself has been removed
|
||||
if (g->seq[v>>1].del) {
|
||||
for (i = 0; i < nv; ++i) av[i].del = 1, ++n_reduced;
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
********************************query-to-target overlap****************************
|
||||
case 1: u = 0, rev = 0 in the view of target: direction is 1
|
||||
query: CCCCCCCCTAATTAAAAT target: TAATTAAAATGGGGGG (use ex-target as query)
|
||||
|||||||||| <---> ||||||||||
|
||||
target: TAATTAAAATGGGGGG query: CCCCCCCCTAATTAAAAT (use ex-query as target)
|
||||
|
||||
case 2: u = 0, rev = 1 in the view of target: direction is 0
|
||||
query: CCCCCCCCTAATTAAAAT target: CCCCCCATTTTAATTA (use ex-target as query)
|
||||
|||||||||| <---> ||||||||||
|
||||
target: TAATTAAAATGGGGGG query: ATTTTAATTAGGGGGGGG (use ex-query as target)
|
||||
********************************query-to-target overlap****************************
|
||||
|
||||
********************************target-to-query overlap****************************
|
||||
case 3: u = 1, rev = 0 in the view of target: direction is 0
|
||||
query: AAATAATATCCCCCCGCG target: GGGCCGGCAAATAATAT (use ex-target as query)
|
||||
||||||||| <---> |||||||||
|
||||
target: GGGCCGGCAAATAATAT query: AAATAATATCCCCCCGCG (use ex-query as target)
|
||||
|
||||
case 4: u = 1, rev = 1 in the view of target: direction is 1
|
||||
query: AAATAATATCCCCCCGCG target: ATATTATTTGCCGGCCC (use ex-target as query)
|
||||
||||||||| <---> |||||||||
|
||||
target: GGGCCGGCAAATAATAT query: CGCGGGGGATATTATTT (use ex-query as target)
|
||||
********************************target-to-query overlap****************************
|
||||
|
||||
p->ul: |____________31__________|__________1___________|______________32_____________|
|
||||
qns direction of overlap length of this node (not overlap length)
|
||||
(in the view of query)
|
||||
p->v : |___________31___________|__________1___________|
|
||||
tns reverse direction of overlap
|
||||
(in the view of target)
|
||||
p->ol: overlap length
|
||||
**/
|
||||
|
||||
// all outnode of v should be set to "not reduce"
|
||||
for (i = 0; i < nv; ++i) {
|
||||
uint32_t w = av[i].v;
|
||||
info[w].mark = g->seq[w>>1].del? 2 : 1;
|
||||
info[w].len = asg_arc_len(av[i]);
|
||||
}
|
||||
|
||||
// length of node (not overlap length)
|
||||
// av[nv-1] is longest out-dege
|
||||
/**
|
||||
* v---------------
|
||||
* w1---------------
|
||||
* w2--------------
|
||||
* w3--------------
|
||||
* w4--------------
|
||||
* w5-------------
|
||||
* for v, the longest out-edge is v->w5
|
||||
**/
|
||||
L = asg_arc_len(av[nv-1]) + fuzz;
|
||||
|
||||
for (i = 0; i < nv; ++i) {
|
||||
uint32_t w = av[i].v;
|
||||
uint32_t j, nw = asg_arc_n(g, w);
|
||||
asg_arc_t *aw = asg_arc_a(g, w);
|
||||
if (info[w].mark != 1) continue;
|
||||
for (j = 0; j < nw; ++j) {
|
||||
uint32_t x, sum = asg_arc_len(aw[j]) + asg_arc_len(av[i]);
|
||||
if (sum > L) break;
|
||||
x = aw[j].v;
|
||||
if (info[x].mark == 1 && sum < info[x].len + fuzz && sum + fuzz > info[x].len)
|
||||
info[x].mark = 2;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
for (i = 0; i < nv; ++i) {
|
||||
uint32_t w = av[i].v;
|
||||
uint32_t j, nw = asg_arc_n(g, w);
|
||||
asg_arc_t *aw = asg_arc_a(g, w);
|
||||
for (j = 0; j < nw && (j == 0 || asg_arc_len(aw[j]) < fuzz); ++j)
|
||||
if (info[aw[j].v].mark) info[aw[j].v].mark = 2;
|
||||
}
|
||||
#endif
|
||||
// remove edges
|
||||
for (i = 0; i < nv; ++i) {
|
||||
if (info[av[i].v].mark == 2) av[i].del = 1, ++n_reduced;
|
||||
info[av[i].v].mark = 0;
|
||||
}
|
||||
}
|
||||
free(info);
|
||||
|
||||
if (n_reduced) {
|
||||
asg_cleanup(g);
|
||||
asg_symm(g);
|
||||
}
|
||||
return n_reduced;
|
||||
}
|
||||
Reference in New Issue
Block a user