mirror of
https://github.com/chhylp123/hifiasm.git
synced 2026-09-15 20:57:57 +08:00
732 lines
20 KiB
C++
732 lines
20 KiB
C++
#define __STDC_LIMIT_MACROS
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include "partig.h"
|
|
#include "Purge_Dups.h"
|
|
#include "Correct.h"
|
|
#include "ksort.h"
|
|
|
|
#define generic_key(x) (x)
|
|
KRADIX_SORT_INIT(gfa64, uint64_t, generic_key, 8)
|
|
|
|
#define pt_a(x, id) ((x).ma.a + ((x).idx.a[(id)]>>32))
|
|
#define pt_n(x, id) ((uint32_t)((x).idx.a[(id)]))
|
|
|
|
typedef struct {
|
|
int32_t topn;
|
|
int32_t n_perturb;
|
|
uint64_t seed;
|
|
double f_perturb;
|
|
} pt_svopt_t;
|
|
|
|
typedef struct {
|
|
///uint32_t m, n, *shuffled;
|
|
uint32_t *shuffled;
|
|
uint32_t off, size; // offset in pt_match_t::cc; size of the component
|
|
uint64_t *buf;
|
|
kvec_t(uint64_t) a;
|
|
int8_t *s, *s_tmp;///s is the status (haplotype) of each unitig: for backup
|
|
} solve_aux_t;
|
|
|
|
static inline uint64_t kr_splitmix64(uint64_t x)
|
|
{
|
|
uint64_t z = (x += 0x9E3779B97F4A7C15ULL);
|
|
z = (z ^ (z >> 30)) * 0xBF58476D1CE4E5B9ULL;
|
|
z = (z ^ (z >> 27)) * 0x94D049BB133111EBULL;
|
|
return z ^ (z >> 31);
|
|
}
|
|
|
|
static inline double kr_drand_r(uint64_t *x)
|
|
{
|
|
union { uint64_t i; double d; } u;
|
|
*x = kr_splitmix64(*x);
|
|
u.i = 0x3FFULL << 52 | (*x) >> 12;
|
|
return u.d - 1.0;
|
|
}
|
|
|
|
void pt_svopt_init(pt_svopt_t *opt)
|
|
{
|
|
memset(opt, 0, sizeof(pt_svopt_t));
|
|
opt->seed = 11;
|
|
opt->topn = 1<<30;
|
|
opt->n_perturb = 1000;
|
|
opt->f_perturb = 0.1;
|
|
}
|
|
|
|
static void pt_pdist_idx(pt_match_t *ma)
|
|
{
|
|
uint32_t st, i;
|
|
kv_resize(uint64_t, ma->idx, ma->n_seq);
|
|
ma->idx.n = ma->n_seq;
|
|
memset(ma->idx.a, 0, ma->idx.n*sizeof(uint64_t));
|
|
for (st = 0, i = 1; i <= ma->ma.n; ++i)
|
|
if (i == ma->ma.n || ma->ma.a[i].sid[0] != ma->ma.a[st].sid[0])
|
|
ma->idx.a[ma->ma.a[st].sid[0]] = (uint64_t)st << 32 | (i - st), st = i;
|
|
}
|
|
|
|
static pt_match1_t *pt_pdist(const pt_match_t *ma, uint32_t sid1, uint32_t sid2)
|
|
{
|
|
pt_match1_t *o = pt_a(*ma, sid1);
|
|
uint32_t n = pt_n(*ma, sid1), k;
|
|
for (k = 0; k < n; ++k)
|
|
if (o[k].sid[1] == sid2)
|
|
return &(o[k]);
|
|
return NULL;
|
|
}
|
|
|
|
static void normalize_pdist(pt_match1_t *a, pt_match1_t *b)
|
|
{
|
|
if(a->w >= b->w)
|
|
{
|
|
b->sid[0] = a->sid[1];
|
|
b->sid[1] = a->sid[0];
|
|
b->w = a->w;
|
|
}
|
|
else
|
|
{
|
|
a->sid[0] = b->sid[1];
|
|
a->sid[1] = b->sid[0];
|
|
a->w = b->w;
|
|
}
|
|
}
|
|
|
|
uint32_t pt_pdist_symm(pt_match_t *ma)
|
|
{
|
|
uint8_t *del = NULL;
|
|
uint32_t i, k, n = 0;
|
|
pt_match1_t *t = NULL, *m = NULL;
|
|
CALLOC(del, ma->ma.n);
|
|
|
|
for (i = 0; i < ma->ma.n; ++i) {
|
|
m = &ma->ma.a[i];
|
|
if (m->sid[0] == m->sid[1])
|
|
{
|
|
del[i] = 1, ++n;///self overlap
|
|
continue;
|
|
}
|
|
t = pt_pdist(ma, m->sid[1], m->sid[0]);
|
|
if(!t)
|
|
{
|
|
del[i] = 1, ++n;///self overlap
|
|
continue;
|
|
}
|
|
normalize_pdist(m, t);
|
|
}
|
|
|
|
if (n > 0) {
|
|
for (i = k = 0; i < ma->ma.n; ++i)
|
|
if (!del[i]) ma->ma.a[k++] = ma->ma.a[i];
|
|
ma->ma.n = k;
|
|
pt_pdist_idx(ma);
|
|
}
|
|
|
|
free(del);
|
|
return n;
|
|
}
|
|
|
|
|
|
static void pt_pdist_flt(pt_match_t *ma, uint32_t min_cnt, double drop_thres)
|
|
{
|
|
uint32_t i, k, j, n, max, o;
|
|
uint8_t *mark = NULL;
|
|
CALLOC(mark, ma->ma.n);
|
|
for (i = 0; i < ma->n_seq; ++i) {
|
|
o = ma->idx.a[i] >> 32;
|
|
n = (uint32_t)ma->idx.a[i];
|
|
max = 0;
|
|
if (n == 0) continue;
|
|
for (j = o; j < o + n; ++j)
|
|
max = max > ma->ma.a[j].w? max : ma->ma.a[j].w;
|
|
for (j = o; j < o + n; ++j)
|
|
if (ma->ma.a[j].w >= (max*drop_thres) || ma->ma.a[j].w + min_cnt >= max)
|
|
mark[j] = 1;
|
|
}
|
|
for (i = 0; i < ma->ma.n; ++i)
|
|
{
|
|
if (mark[i] == 0) continue;
|
|
o = ma->idx.a[ma->ma.a[i].sid[1]]>>32;
|
|
n = (uint32_t)ma->idx.a[ma->ma.a[i].sid[1]];
|
|
for (j = o; j < o + n; ++j)
|
|
{
|
|
if (ma->ma.a[j].sid[1] == ma->ma.a[i].sid[0]) mark[j] = 1;
|
|
}
|
|
}
|
|
|
|
for (i = k = 0; i < ma->ma.n; ++i)
|
|
if (mark[i]) ma->ma.a[k++] = ma->ma.a[i];
|
|
ma->ma.n = k;
|
|
free(mark);
|
|
pt_pdist_idx(ma);
|
|
pt_pdist_symm(ma);
|
|
}
|
|
|
|
pt_match_t *init_pt_match_t(hap_overlaps_list* ha, pt_g_t *x, double f_rate)
|
|
{
|
|
pt_match_t *p = NULL; CALLOC(p, 1); p->n_seq = x->ug->g->n_seq;
|
|
kv_init(p->idx); kv_init(p->ma);
|
|
uint32_t v, i, k, qn, tn, qs, qe, ts, te, occ, as, ae;
|
|
uint64_t hetLen, homLen, oLen;
|
|
pt_node_t *a = NULL;
|
|
pt_match1_t *ma = NULL;
|
|
|
|
for (v = 0; v < ha->num; v++)
|
|
{
|
|
for (i = 0; i < ha->x[v].a.n; i++)
|
|
{
|
|
if(ha->x[v].a.a[i].score <= 0) continue;
|
|
if(ha->x[v].a.a[i].xUid == ha->x[v].a.a[i].yUid) continue;
|
|
/*****************qn*****************/
|
|
qn = ha->x[v].a.a[i].xUid;
|
|
qs = ha->x[v].a.a[i].x_beg_pos;
|
|
qe = ha->x[v].a.a[i].x_end_pos - 1;
|
|
|
|
a = x->p.a + x->p_idx.a[qn];
|
|
occ = x->p_idx.a[qn+1] - x->p_idx.a[qn];
|
|
for (k = 0, hetLen = 0, homLen = 0; k < occ; k++)
|
|
{
|
|
as = a[k].bS;
|
|
ae = a[k].bE;
|
|
oLen = ((MIN(qe, ae) >= MAX(qs, as))? MIN(qe, ae) - MAX(qs, as) + 1 : 0);
|
|
if(homLen + hetLen > 0 && oLen == 0) break;
|
|
if(oLen == 0) continue;
|
|
if(a[k].hs == N_HET)
|
|
{
|
|
homLen += oLen;
|
|
}
|
|
else if(asm_opt.polyploidy <= 2 && (a[k].hs&P_HET))///if(asm_opt.polyploidy <= 2 && (a[k].hs&S_HET))
|
|
{
|
|
homLen += oLen;
|
|
}
|
|
else
|
|
{
|
|
hetLen += oLen;
|
|
}
|
|
}
|
|
|
|
if(hetLen <= ((hetLen + homLen)*f_rate)) continue;
|
|
/*****************qn*****************/
|
|
|
|
|
|
/*****************tn*****************/
|
|
tn = ha->x[v].a.a[i].yUid;
|
|
ts = ha->x[v].a.a[i].y_beg_pos;
|
|
te = ha->x[v].a.a[i].y_end_pos - 1;
|
|
|
|
a = x->p.a + x->p_idx.a[tn];
|
|
occ = x->p_idx.a[tn+1] - x->p_idx.a[tn];
|
|
for (k = 0, hetLen = 0, homLen = 0; k < occ; k++)
|
|
{
|
|
as = a[k].bS;
|
|
ae = a[k].bE;
|
|
oLen = ((MIN(te, ae) >= MAX(ts, as))? MIN(te, ae) - MAX(ts, as) + 1 : 0);
|
|
if(homLen + hetLen > 0 && oLen == 0) break;
|
|
if(oLen == 0) continue;
|
|
if(a[k].hs == N_HET)
|
|
{
|
|
homLen += oLen;
|
|
}
|
|
else if(asm_opt.polyploidy <= 2 && (a[k].hs&P_HET))///if(asm_opt.polyploidy <= 2 && (a[k].hs&S_HET))
|
|
{
|
|
homLen += oLen;
|
|
}
|
|
else
|
|
{
|
|
hetLen += oLen;
|
|
}
|
|
}
|
|
|
|
if(hetLen <= ((hetLen + homLen)*f_rate)) continue;
|
|
/*****************tn*****************/
|
|
|
|
kv_pushp(pt_match1_t, p->ma, &ma);
|
|
ma->sid[0] = ha->x[v].a.a[i].xUid;
|
|
ma->sid[1] = ha->x[v].a.a[i].yUid;
|
|
ma->w = ha->x[v].a.a[i].score;
|
|
}
|
|
}
|
|
|
|
pt_pdist_idx(p);
|
|
pt_pdist_symm(p);
|
|
pt_pdist_flt(p, 5, 0.5);
|
|
return p;
|
|
}
|
|
|
|
|
|
void debug_pt_g_t(pt_g_t *pg)
|
|
{
|
|
fprintf(stderr, "0----------[M::%s]----------\n", __func__);
|
|
uint32_t i, offset, v, sid, eid, spos, epos, p_status, p_uid, occ;
|
|
ma_utg_t *u = NULL;
|
|
pt_node_t *a = NULL, *t = NULL;
|
|
|
|
for (v = 0; v < pg->ug->u.n; v++)
|
|
{
|
|
a = pg->p.a + pg->p_idx.a[v];
|
|
occ = pg->p_idx.a[v+1] - pg->p_idx.a[v];
|
|
for (i = 0; i < occ; i++)
|
|
{
|
|
if(a[i].uID != v) fprintf(stderr, "ERROR-s\n");
|
|
}
|
|
}
|
|
|
|
for (v = 0, p_status = (uint32_t)-1, p_uid = (uint32_t)-1; v < pg->p.n; v++)
|
|
{
|
|
t = &(pg->p.a[v]);
|
|
sid = t->nS;
|
|
eid = t->nE;
|
|
spos = t->bS;
|
|
epos = t->bE;
|
|
if(p_uid == t->uID && p_status == t->hs)
|
|
{
|
|
fprintf(stderr, "ERROR-a\n");
|
|
}
|
|
p_status = t->hs;
|
|
p_uid = t->uID;
|
|
u = &(pg->ug->u.a[t->uID]);
|
|
for (i = offset = 0; i < u->n; i++)
|
|
{
|
|
if(i == sid)
|
|
{
|
|
if(spos != offset)
|
|
{
|
|
fprintf(stderr, "ERROR-b\n");
|
|
}
|
|
}
|
|
|
|
if(i == eid)
|
|
{
|
|
if(epos != (offset+pg->rg->seq[u->a[i]>>33].len - 1))
|
|
{
|
|
fprintf(stderr, "ERROR-c, real end: %u\n",
|
|
(uint32_t)(offset+pg->rg->seq[u->a[i]>>33].len - 1));
|
|
}
|
|
}
|
|
|
|
offset += (uint32_t)u->a[i];
|
|
if(i >= sid && i <= eid)
|
|
{
|
|
if(pg->t_ch->is_r_het[u->a[i]>>33] != t->hs)
|
|
{
|
|
fprintf(stderr, "ERROR-d: is_r_het: %u, h_status: %u\n", pg->t_ch->is_r_het[u->a[i]>>33], t->hs);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
pt_match1_t *o = NULL, *s = NULL;
|
|
uint32_t k, n, cnt;
|
|
for (i = 0; i < pg->e->n_seq; ++i)
|
|
{
|
|
o = pt_a(*(pg->e), i); n = pt_n(*(pg->e), i);
|
|
for (k = 0; k < n; ++k)
|
|
{
|
|
if(o[k].sid[0] != i) fprintf(stderr, "ERROR-g\n");
|
|
s = pt_pdist(pg->e, o[k].sid[1], o[k].sid[0]);
|
|
if(!s) fprintf(stderr, "ERROR-e\n");
|
|
if(s)
|
|
{
|
|
if(!(s->sid[0] == o[k].sid[1] && s->sid[1] == o[k].sid[0] && s->w == o[k].w))
|
|
{
|
|
fprintf(stderr, "ERROR-f\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
for (k = cnt = 0; k < pg->e->ma.n; ++k)
|
|
{
|
|
if(pg->e->ma.a[k].sid[0] == i) cnt++;
|
|
}
|
|
|
|
if(cnt != n) fprintf(stderr, "ERROR-h\n");
|
|
}
|
|
}
|
|
|
|
pt_g_t *init_pt_g_t(hap_overlaps_list* ovlp, trans_chain* t_ch, ma_ug_t *ug, asg_t *read_g, double f_rate)
|
|
{
|
|
uint32_t v, l, k, offset, l_pos;
|
|
pt_g_t *p = NULL; CALLOC(p, 1);
|
|
asg_t* nsg = ug->g;
|
|
ma_utg_t *u = NULL;
|
|
pt_node_t *t = NULL;
|
|
p->ug = ug;
|
|
p->rg = read_g;
|
|
p->t_ch = t_ch;
|
|
kv_init(p->info); p->info.n = p->info.m = p->ug->g->n_seq; CALLOC(p->info.a, p->info.n);
|
|
kv_init(p->p);
|
|
kv_init(p->p_idx); kv_push(uint32_t, p->p_idx, 0);
|
|
|
|
for (v = 0; v < nsg->n_seq; v++)
|
|
{
|
|
if(nsg->seq[v].del || nsg->seq[v].c == ALTER_LABLE) continue;
|
|
|
|
u = &(ug->u.a[v]);
|
|
for (k = 1, l = 0, offset = 0, l_pos = 0; k <= u->n; ++k)
|
|
{
|
|
if (k == u->n || t_ch->is_r_het[u->a[k]>>33] != t_ch->is_r_het[u->a[l]>>33])
|
|
{
|
|
kv_pushp(pt_node_t, p->p, &t);
|
|
t->uID = v;
|
|
t->hs = t_ch->is_r_het[u->a[l]>>33];
|
|
|
|
t->bS = l_pos;
|
|
t->bE = offset + read_g->seq[u->a[k-1]>>33].len - 1;
|
|
|
|
t->nS = l;
|
|
t->nE = k - 1;
|
|
l = k;
|
|
l_pos = offset + (uint32_t)u->a[k-1];
|
|
}
|
|
offset += (uint32_t)u->a[k-1];
|
|
}
|
|
kv_push(uint32_t, p->p_idx, p->p.n);
|
|
}
|
|
|
|
p->e = init_pt_match_t(ovlp, p, f_rate);
|
|
return p;
|
|
}
|
|
|
|
void destory_pt_g_t(pt_g_t **p)
|
|
{
|
|
if(!p || !(*p)) return;
|
|
kv_destroy((*p)->p);
|
|
kv_destroy((*p)->info);
|
|
kv_destroy((*p)->p_idx);
|
|
kv_destroy((*p)->e->idx);
|
|
kv_destroy((*p)->e->ma);
|
|
free((*p)->e->cc);
|
|
free((*p)->e);
|
|
free((*p));
|
|
}
|
|
|
|
uint64_t *pt_cc_core(const pt_match_t *ma)
|
|
{
|
|
uint32_t i, x, y, *flag;
|
|
uint64_t *group;
|
|
pt_match1_t *o = NULL;
|
|
kvec_t(uint32_t) stack; kv_init(stack);
|
|
|
|
MALLOC(flag, ma->n_seq);
|
|
for (i = 0; i < ma->n_seq; ++i)
|
|
flag[i] = (uint32_t)-1;
|
|
|
|
// connected componets
|
|
for (i = 0; i < ma->n_seq; ++i) {
|
|
if (flag[i] != (uint32_t)-1) continue;
|
|
stack.n = 0;
|
|
kv_push(uint32_t, stack, i);
|
|
while (stack.n > 0) {
|
|
uint32_t k, j, n;
|
|
stack.n--;
|
|
k = stack.a[stack.n];
|
|
flag[k] = i;///group id
|
|
// n = (uint32_t)ma->idx[k];
|
|
// s = ma->idx[k] >> 32;
|
|
o = pt_a(*ma, k);
|
|
n = pt_n(*ma, k);
|
|
for (j = 0; j < n; ++j) {
|
|
uint32_t t = o[j].sid[1];
|
|
if (flag[t] != (uint32_t)-1) continue;
|
|
// if (ns == ms) PT_EXPAND(stack, ms);
|
|
// stack[ns++] = t;
|
|
kv_push(uint32_t, stack, t);
|
|
}
|
|
}
|
|
}
|
|
kv_destroy(stack);
|
|
|
|
// precalculate the size of each group
|
|
CALLOC(group, ma->n_seq);
|
|
for (i = 0; i < ma->n_seq; ++i)
|
|
group[i] = (uint64_t)flag[i] << 32 | i;
|
|
radix_sort_gfa64(group, group + ma->n_seq);
|
|
for (i = 1, x = y = 0; i <= ma->n_seq; ++i) {
|
|
if (i == ma->n_seq || group[i]>>32 != group[x]>>32) {
|
|
uint32_t j;
|
|
for (j = x; j < i; ++j)
|
|
group[j] = (uint64_t)y << 32 | (uint32_t)group[j];///(group id)|first element in this group
|
|
++y, x = i;
|
|
}
|
|
}
|
|
free(flag);
|
|
return group;
|
|
}
|
|
|
|
void pt_cc(pt_match_t *ma)
|
|
{
|
|
ma->cc = pt_cc_core(ma);
|
|
}
|
|
|
|
///inspect top INT edges
|
|
static int64_t pt_score(const pt_match_t *ma, uint32_t topn, solve_aux_t *aux)
|
|
{
|
|
uint32_t i;
|
|
int64_t z = 0;
|
|
for (i = 0; i < aux->size; ++i) {///aux->size: how many unitigs in this group
|
|
uint32_t k = (uint32_t)ma->cc[aux->off + i];
|
|
uint32_t o = ma->idx.a[k] >> 32;
|
|
uint32_t n = (uint32_t)ma->idx.a[k], j;
|
|
for (j = 0; j < n; ++j)
|
|
aux->buf[j] = (uint64_t)((uint32_t)-1 - ma->ma.a[o + j].w) << 32 | (o + j);
|
|
radix_sort_gfa64(aux->buf, aux->buf + n);
|
|
for (j = 0; j < n && j < topn; ++j) {
|
|
const pt_match1_t *m = &ma->ma.a[(uint32_t)aux->buf[j]];
|
|
z += -(int64_t)m->w * aux->s[m->sid[0]] * aux->s[m->sid[1]];
|
|
}
|
|
}
|
|
return z;
|
|
}
|
|
|
|
static int64_t pt_solve1_init_phase(const pt_match_t *ma, int32_t topn, uint64_t *x, solve_aux_t *aux)
|
|
{
|
|
uint32_t i;
|
|
aux->a.n = 0;
|
|
for (i = 0; i < aux->size; ++i) {
|
|
uint32_t k = (uint32_t)ma->cc[aux->off + i];///unitig id
|
|
uint32_t o = ma->idx.a[k] >> 32;///group id
|
|
uint32_t n = (uint32_t)ma->idx.a[k], j;
|
|
aux->shuffled[i] = k;///init shuffled status
|
|
for (j = 0; j < n; ++j) {
|
|
const pt_match1_t *m = &ma->ma.a[o + j];
|
|
///first is weight, second part is edge id
|
|
kv_push(uint64_t, aux->a, (uint64_t)((uint32_t)-1 - m->w) << 32 | (o + j));
|
|
}
|
|
}
|
|
radix_sort_gfa64(aux->a.a, aux->a.a + aux->a.n);///sort all edges in this group
|
|
///randomly assign each unitig
|
|
for (i = 0; i < aux->a.n; ++i) { // from the strongest edge to the weakest
|
|
const pt_match1_t *m = &ma->ma.a[(uint32_t)aux->a.a[i]];
|
|
///sid[0]: query id, sid[1]: target id
|
|
///the initial results of aux->s is 0
|
|
if (aux->s[m->sid[0]] == 0 && aux->s[m->sid[1]] == 0) {
|
|
*x = kr_splitmix64(*x);// random number
|
|
aux->s[m->sid[0]] = *x&1? 1 : -1;
|
|
aux->s[m->sid[1]] = -aux->s[m->sid[0]];
|
|
} else if (aux->s[m->sid[0]] == 0) {
|
|
aux->s[m->sid[0]] = -aux->s[m->sid[1]];
|
|
} else if (aux->s[m->sid[1]] == 0) {
|
|
aux->s[m->sid[1]] = -aux->s[m->sid[0]];
|
|
}
|
|
}
|
|
return pt_score(ma, topn, aux);
|
|
}
|
|
|
|
///size is how many unitigs in this group
|
|
static void ks_shuffle_uint32_t(size_t n, uint32_t a[], uint64_t *x)
|
|
{
|
|
size_t i, j;
|
|
for (i = n; i > 1; --i) {
|
|
uint32_t tmp;
|
|
j = (size_t)(kr_drand_r(x) * i);///semms
|
|
tmp = a[j]; a[j] = a[i-1]; a[i-1] = tmp;
|
|
}
|
|
}
|
|
|
|
static void pt_solve1_perturb(const pt_svopt_t *opt, const pt_match_t *ma, uint64_t *x, solve_aux_t *aux)
|
|
{
|
|
uint32_t i;
|
|
double y;
|
|
for (i = 0; i < aux->size; ++i) {
|
|
uint32_t k = (uint32_t)ma->cc[aux->off + i];
|
|
y = kr_drand_r(x);
|
|
if (y < opt->f_perturb)
|
|
aux->s[k] = -aux->s[k];
|
|
}
|
|
}
|
|
|
|
static int64_t pt_solve1_optimize(const pt_match_t *ma, uint32_t topn, uint64_t *x, solve_aux_t *aux, uint32_t *n_iter)
|
|
{
|
|
uint32_t i;
|
|
while (1) {
|
|
uint32_t n_flip = 0;
|
|
++(*n_iter);
|
|
ks_shuffle_uint32_t(aux->size, aux->shuffled, x);
|
|
for (i = 0; i < aux->size; ++i) {
|
|
uint32_t k = aux->shuffled[i];
|
|
uint32_t o = ma->idx.a[k] >> 32;
|
|
uint32_t n = (uint32_t)ma->idx.a[k], j;
|
|
uint64_t z[2];
|
|
int8_t s;
|
|
for (j = 0; j < n; ++j) {
|
|
const pt_match1_t *m = &ma->ma.a[o + j];
|
|
///assert(m->sid[0] == k);
|
|
aux->buf[j] = (uint64_t)((uint32_t)-1 - m->w) << 32 | (o + j);
|
|
}
|
|
radix_sort_gfa64(aux->buf, aux->buf + n);///still sort by edge weight
|
|
for (j = 0, z[0] = z[1] = 0; j < n && j < topn; ++j) {
|
|
const pt_match1_t *m = &ma->ma.a[(uint32_t)aux->buf[j]];
|
|
if (aux->s[m->sid[1]] > 0) z[0] += m->w;
|
|
else if (aux->s[m->sid[1]] < 0) z[1] += m->w;
|
|
}
|
|
if (z[0] == z[1]) continue;
|
|
s = z[0] > z[1]? -1 : 1;
|
|
if (aux->s[k] != s)
|
|
aux->s[k] = s, ++n_flip;
|
|
}
|
|
if (n_flip == 0) break;
|
|
}
|
|
return pt_score(ma, topn, aux);
|
|
}
|
|
|
|
uint32_t pt_solve1(const pt_svopt_t *opt, const pt_match_t *ma, uint64_t *x, solve_aux_t *aux)
|
|
{
|
|
uint32_t j, k, n_iter = 0;
|
|
int64_t sc_ori, sc_opt = -(1<<30), sc;
|
|
if (aux->size < 2) return 0;///how many unitigs
|
|
|
|
// first guess
|
|
///randomly assign haplotype status, and get a score
|
|
sc_ori = pt_solve1_init_phase(ma, opt->topn, x, aux);
|
|
if (aux->size == 2) return 0;
|
|
|
|
// optimize
|
|
sc_opt = pt_solve1_optimize(ma, opt->topn, x, aux, &n_iter);
|
|
for (j = 0; j < aux->size; ++j)
|
|
aux->s_tmp[aux->shuffled[j]] = aux->s[aux->shuffled[j]];
|
|
for (k = 0; k < (uint32_t)opt->n_perturb; ++k) {
|
|
pt_solve1_perturb(opt, ma, x, aux);
|
|
sc = pt_solve1_optimize(ma, opt->topn, x, aux, &n_iter);
|
|
if (sc > sc_opt) {
|
|
for (j = 0; j < aux->size; ++j)
|
|
aux->s_tmp[aux->shuffled[j]] = aux->s[aux->shuffled[j]];
|
|
sc_opt = sc;
|
|
} else {
|
|
for (j = 0; j < aux->size; ++j)
|
|
aux->s[aux->shuffled[j]] = aux->s_tmp[aux->shuffled[j]];
|
|
}
|
|
}
|
|
for (j = 0; j < aux->size; ++j)
|
|
aux->s[aux->shuffled[j]] = aux->s_tmp[aux->shuffled[j]];
|
|
fprintf(stderr, "[%s] group:%d, size:%d, #edges:%u, #iter:%d, sc_ori:%ld, sc_opt:%ld\n", __func__,
|
|
(uint32_t)(ma->cc[aux->off]>>32), (uint32_t)(aux->size), (uint32_t)(aux->a.n), n_iter, (long)sc_ori, (long)sc_opt);
|
|
return n_iter;
|
|
}
|
|
|
|
int8_t *pt_solve_core(const pt_svopt_t *opt, const pt_match_t *ma)
|
|
{
|
|
int8_t *s;
|
|
uint32_t st, i, max = 0;
|
|
uint64_t x = opt->seed;
|
|
solve_aux_t *aux;
|
|
CALLOC(aux, 1); CALLOC(aux->s, ma->n_seq); CALLOC(aux->s_tmp, ma->n_seq);
|
|
kv_init(aux->a);
|
|
for (i = 0; i < ma->n_seq; ++i) {///count how many links for each unitig
|
|
uint32_t n = pt_n(*ma, i);
|
|
max = max > n? max : n;
|
|
}
|
|
MALLOC(aux->buf, max);
|
|
MALLOC(aux->shuffled, ma->n_seq); // FIXME: this is over-allocation for convenience
|
|
for (st = 0, i = 1; i <= ma->n_seq; ++i) {
|
|
if (i == ma->n_seq || ma->cc[st]>>32 != ma->cc[i]>>32) {///at same group
|
|
if (i - st >= 2) {///all unitigs in the same group
|
|
aux->off = st, aux->size = i - st;
|
|
pt_solve1(opt, ma, &x, aux);
|
|
}
|
|
st = i;
|
|
}
|
|
}
|
|
s = aux->s;
|
|
kv_destroy(aux->a); free(aux->buf); free(aux->shuffled); free(aux->s_tmp);
|
|
free(aux);
|
|
return s;
|
|
}
|
|
|
|
void set_trio_flag(ma_ug_t *ug, asg_t *read_g, uint32_t uID, uint8_t* trio_flag, trans_chain* t_ch,
|
|
hap_overlaps_list* ha, pt_match_t *ma, int8_t s)
|
|
{
|
|
uint32_t i;
|
|
ma_utg_t *u = &(ug->u.a[uID]);
|
|
for (i = 0; i < u->n; i++)
|
|
{
|
|
trio_flag[u->a[i]>>33] |= SET_TRIO;
|
|
if(t_ch->is_r_het[u->a[i]>>33] == N_HET) continue;
|
|
if(s == 0)
|
|
{
|
|
if(t_ch->is_r_het[u->a[i]>>33]&P_HET)//special case
|
|
{
|
|
trio_flag[u->a[i]>>33] |= FATHER;
|
|
}
|
|
continue;
|
|
}
|
|
trio_flag[u->a[i]>>33] |= (s > 0? FATHER:MOTHER);
|
|
}
|
|
|
|
// pt_match1_t *o = pt_a(*ma, uID);
|
|
// uint32_t n = pt_n(*ma, uID), k, qn, tn, qs, qe, r_beg, r_end, offset, oLen, found;
|
|
// int index;
|
|
// for (k = 0; k < n; ++k)
|
|
// {
|
|
// qn = o[k].sid[0]; tn = o[k].sid[1]; qs = qe = (uint32_t)-1;
|
|
// index = get_specific_hap_overlap(&(ha->x[qn]), qn, tn);
|
|
// if(index != -1 && ha->x[qn].a.a[index].score == (long long)o[k].w)
|
|
// {
|
|
// qs = ha->x[qn].a.a[index].x_beg_pos;
|
|
// qe = ha->x[qn].a.a[index].x_end_pos - 1;
|
|
// }
|
|
// else
|
|
// {
|
|
// index = get_specific_hap_overlap(&(ha->x[tn]), tn, qn);
|
|
// if(index != -1 && ha->x[tn].a.a[index].score == (long long)o[k].w)
|
|
// {
|
|
// qs = ha->x[qn].a.a[index].y_beg_pos;
|
|
// qe = ha->x[qn].a.a[index].y_end_pos - 1;
|
|
// }
|
|
// }
|
|
|
|
// if(qs == (uint32_t)-1 || qe == (uint32_t)-1) fprintf(stderr, "ERROR\n");
|
|
// for (i = 0, offset = 0, found = 0; i < u->n; i++)
|
|
// {
|
|
// r_beg = offset; r_end = offset + (long long)(read_g->seq[u->a[i]>>33].len) - 1;
|
|
// offset += (uint32_t)u->a[i];
|
|
// oLen = ((MIN(qe, r_end) >= MAX(qs, r_beg))? MIN(qe, r_end) - MAX(qs, r_beg) + 1 : 0);
|
|
// if(oLen > 0) found = 1;
|
|
// if(found == 1 && oLen == 0) break;
|
|
|
|
// if(oLen > 0 && t_ch->is_r_het[u->a[i]>>33] != N_HET)
|
|
// {
|
|
// trio_flag[u->a[i]>>33] |= (s > 0? FATHER:MOTHER);
|
|
// }
|
|
|
|
// }
|
|
// }
|
|
}
|
|
|
|
void pt_solve(hap_overlaps_list* ovlp, trans_chain* t_ch, ma_ug_t *ug, asg_t *read_g, double f_rate, uint8_t* trio_flag)
|
|
{
|
|
pt_svopt_t opt;
|
|
int8_t *s = NULL;
|
|
uint64_t *buf = NULL, i;
|
|
pt_svopt_init(&opt);
|
|
pt_g_t *pg = init_pt_g_t(ovlp, t_ch, ug, read_g, f_rate);
|
|
///debug_pt_g_t(pg);
|
|
|
|
pt_cc(pg->e);
|
|
s = pt_solve_core(&opt, pg->e);
|
|
|
|
|
|
MALLOC(buf, pg->e->ma.n); // FIXME: this is over-allocation for convenience
|
|
for (i = 0; i < pg->e->n_seq; ++i) {
|
|
uint64_t z[2];
|
|
uint32_t o = pg->e->idx.a[i] >> 32;
|
|
uint32_t n = (uint32_t)pg->e->idx.a[i], j;
|
|
|
|
set_trio_flag(ug, read_g, i, trio_flag, t_ch, ovlp, pg->e, s[i]);
|
|
|
|
pg->info.a[i].s = s[i];
|
|
for (j = 0; j < n; ++j) {
|
|
const pt_match1_t *m = &pg->e->ma.a[o + j];
|
|
buf[j] = (uint64_t)((uint32_t)-1 - m->w) << 32 | (o + j);
|
|
}
|
|
radix_sort_gfa64(buf, buf + n);
|
|
for (j = 0, z[0] = z[1] = 0; j < n; ++j) {
|
|
const pt_match1_t *m = &pg->e->ma.a[(uint32_t)buf[j]];
|
|
if (s[m->sid[1]] > 0) z[0] += m->w;
|
|
else if (s[m->sid[1]] < 0) z[1] += m->w;
|
|
}
|
|
pg->info.a[i].m[0] = z[0], pg->info.a[i].m[1] = z[1];
|
|
}
|
|
|
|
free(buf);
|
|
free(s);
|
|
destory_pt_g_t(&pg);
|
|
} |