Files
hifiasm/partig.cpp
2021-04-04 14:00:28 -04:00

834 lines
22 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 filter_ovlp(ma_ug_t *ug, asg_t *read_g, uint32_t uID, hap_overlaps_list* ha, pt_match_t *ma,
int8_t *s)
{
pt_match1_t *o = pt_a(*ma, uID);
uint32_t n = pt_n(*ma, uID), k, qn, tn;
hap_overlaps *p = NULL;
int index;
for (k = 0; k < n; ++k)
{
qn = o[k].sid[0]; tn = o[k].sid[1]; p = NULL;
if((s[qn]*s[tn])!=-1) continue;
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)
{
p = &(ha->x[qn].a.a[index]);
}
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)
{
p = &(ha->x[tn].a.a[index]);
}
}
if(!p) fprintf(stderr, "ERROR\n");
p->status = FLIP;
}
}
void clean_ovlp(ma_ug_t *ug, asg_t *read_g, hap_overlaps_list* ha, pt_g_t *pg, int8_t* s)
{
uint32_t v, i, k, qn, tn, types[4];
types[X2Y] = Y2X; types[Y2X] = X2Y; types[XCY] = YCX; types[YCX] = XCY;
int index;
hap_overlaps *x = NULL, *y = NULL;
for (i = 0; i < pg->e->n_seq; ++i)
{
filter_ovlp(ug, read_g, i, ha, pg->e, s);
}
for (v = 0; v < ha->num; v++)
{
for (i = 0; i < ha->x[v].a.n; i++)
{
qn = ha->x[v].a.a[i].xUid;
tn = ha->x[v].a.a[i].yUid;
x = &(ha->x[v].a.a[i]);
if(x->status != FLIP) continue;
index = get_specific_hap_overlap(&(ha->x[tn]), tn, qn);
if(index != -1)
{
y = &(ha->x[tn].a.a[index]);
set_reverse_hap_overlap(y, x, types);
y->status = FLIP;
}
if(index == -1) fprintf(stderr, "ERROR\n");
}
}
// for (v = 0; v < ha->num; v++)
// {
// for (i = k = 0; i < ha->x[v].a.n; i++)
// {
// if(ha->x[v].a.a[i].status != FLIP)
// {
// if(s[ha->x[v].a.a[i].xUid]*s[ha->x[v].a.a[i].yUid] == -1)
// {
// fprintf(stderr, "\ns[0]=%d, s[1]=%d\n", s[ha->x[v].a.a[i].xUid], s[ha->x[v].a.a[i].yUid]);
// print_hap_paf(ug, &(ha->x[v].a.a[i]));
// }
// continue;
// }
// ha->x[v].a.a[k] = ha->x[v].a.a[i];
// k++;
// }
// ha->x[v].a.n = k;
// }
for (v = 0; v < ha->num; v++)
{
for (i = k = 0; i < ha->x[v].a.n; i++)
{
if(ha->x[v].a.a[i].status != FLIP) continue;
ha->x[v].a.a[k] = ha->x[v].a.a[i];
k++;
}
ha->x[v].a.n = k;
}
}
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);
if(asm_opt.flag & HA_F_PARTITION)
{
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];
}
}
clean_ovlp(ug, read_g, ovlp, pg, s);
free(buf);
free(s);
destory_pt_g_t(&pg);
}