#define __STDC_LIMIT_MACROS #include "float.h" #include "horder.h" #include #include "hic.h" #include "htab.h" #include "assert.h" #include "Overlaps.h" #include "Hash_Table.h" #include "Correct.h" #include "Purge_Dups.h" #include "rcut.h" #include "khashl.h" #include "kthread.h" #include "ksort.h" #include "kseq.h" // FASTA/Q parser #include "kdq.h" KSEQ_INIT(gzFile, gzread) KDQ_INIT(uint64_t) #define pe_hit_an1_idx_key(x) ((x).s<<1) KRADIX_SORT_INIT(pe_hit_idx_hn1, pe_hit, pe_hit_an1_idx_key, member_size(pe_hit, s)) #define pe_hit_an2_idx_key(x) ((x).e<<1) KRADIX_SORT_INIT(pe_hit_idx_hn2, pe_hit, pe_hit_an2_idx_key, member_size(pe_hit, e)) #define generic_key(x) (x) KRADIX_SORT_INIT(ho64, uint64_t, generic_key, 8) #define get_hit_srev(x, k) ((x).a.a[(k)].s>>63) #define get_hit_slen(x, k) ((x).a.a[(k)].len>>32) #define get_hit_suid(x, k) (((x).a.a[(k)].s<<1)>>(64 - (x).uID_bits)) #define get_hit_spos(x, k) ((x).a.a[(k)].s & (x).pos_mode) #define get_hit_spos_e(x, k) (get_hit_srev((x),(k))?\ ((get_hit_spos((x),(k))+1>=get_hit_slen((x),(k)))?\ (get_hit_spos((x),(k))+1-get_hit_slen((x),(k))):0)\ :(get_hit_spos((x),(k))+get_hit_slen((x),(k))-1)) #define get_hit_erev(x, k) ((x).a.a[(k)].e>>63) #define get_hit_elen(x, k) ((uint32_t)((x).a.a[(k)].len)) #define get_hit_euid(x, k) (((x).a.a[(k)].e<<1)>>(64 - (x).uID_bits)) #define get_hit_epos(x, k) ((x).a.a[(k)].e & (x).pos_mode) #define get_hit_epos_e(x, k) (get_hit_erev((x),(k))?\ ((get_hit_epos((x),(k))+1>=get_hit_elen((x),(k)))?\ (get_hit_epos((x),(k))+1-get_hit_elen((x),(k))):0)\ :(get_hit_epos((x),(k))+get_hit_elen((x),(k))-1)) #define OVL(s_0, e_0, s_1, e_1) ((MIN((e_0), (e_1)) > MAX((s_0), (s_1)))? MIN((e_0), (e_1)) - MAX((s_0), (s_1)):0) #define BREAK_THRES 1000000 #define BREAK_CUTOFF 0.1 #define BREAK_BOUNDARY 0.01 #define GAP_LEN 100 typedef struct { uint64_t ruid; uint64_t off; } hit_aux_t; typedef struct { hit_aux_t *a; size_t n, m; kvec_t(uint64_t) idx; } u_hits_t; typedef struct { uint64_t s, e, dp; } h_cov_t; typedef struct { h_cov_t *a; size_t n, m; } h_covs; #define h_cov_s_key(x) ((x).s) KRADIX_SORT_INIT(h_cov_s, h_cov_t, h_cov_s_key, member_size(h_cov_t, s)) #define hit_aux_ruid_key(x) ((x).ruid) KRADIX_SORT_INIT(hit_aux_ruid, hit_aux_t, hit_aux_ruid_key, member_size(hit_aux_t, ruid)) void print_N50(ma_ug_t* ug) { kvec_t(uint64_t) b; kv_init(b); uint64_t i, s, len; for (i = s = 0; i < ug->g->n_seq; ++i) { kv_push(uint64_t, b, ug->u.a[i].len); s += ug->u.a[i].len; } len = s; fprintf(stderr, "[M::%s::] Genome Size: %lu, # Contigs: %u\n", __func__, len, ug->g->n_seq); radix_sort_ho64(b.a, b.a+b.n); i = b.n; s = 0; while (i > 0) { i--; s += b.a[i]; if(s >= (len>>1)) { fprintf(stderr, "[M::%s::] N50: %lu\n", __func__, b.a[i]); break; } } kv_destroy(b); } void get_r_hits(kvec_pe_hit *u_hits, kvec_pe_hit *r_hits, asg_t* r_g, ma_ug_t* ug, bubble_type* bub, uint64_t uID_bits, uint64_t pos_mode) { uint64_t k, l, i, r_i, offset, rid, rev, rBeg, rEnd, ubits, p_mode, upos, rpos, update; ma_utg_t *u = NULL; memset(r_hits, 0, sizeof(*r_hits)); r_hits->uID_bits = uID_bits; r_hits->pos_mode = pos_mode; //reset for reads for (ubits=1; (uint64_t)(1<n_seq; ubits++); p_mode = ((uint64_t)-1) >> (ubits + 1); kv_malloc(r_hits->a, u_hits->a.n); r_hits->a.n = r_hits->a.m = u_hits->a.n; memcpy(r_hits->a.a, u_hits->a.a, r_hits->a.n*sizeof(pe_hit)); radix_sort_pe_hit_idx_hn1(r_hits->a.a, r_hits->a.a + r_hits->a.n); for (k = 1, l = 0; k <= r_hits->a.n; ++k) { if (k == r_hits->a.n || get_hit_suid(*r_hits, k) != get_hit_suid(*r_hits, l))//same suid { ///already sort by spos u = &(ug->u.a[get_hit_suid(*r_hits, l)]); update = 0; for (i = offset = 0, r_i = l; i < u->n; i++) { rid = u->a[i]>>33; rBeg = offset; rEnd = rBeg + r_g->seq[rid].len - 1; for (; r_i < k; r_i++) { upos = get_hit_spos(*r_hits, r_i);///pos at unitig if(upos > rEnd) break; if(upos >= rBeg && upos <= rEnd) { if(bub) { r_hits->a.a[r_i].id = (uint32_t)r_hits->a.a[r_i].id; if(!IF_HOM(get_hit_suid(*r_hits, r_i), *bub)) { r_hits->a.a[r_i].id += ((uint64_t)(1)<<32); } } rpos = (((u->a[i]>>32)&1)? rEnd - upos : upos - rBeg);///pos at read rev = ((u->a[i]>>32)&1) ^ (r_hits->a.a[r_i].s>>63); r_hits->a.a[r_i].s = (rev<<63) | ((rid << (64-ubits))>>1) | (rpos & p_mode); update++; } } offset += (uint32_t)u->a[i]; } if(r_i != k || update != k - l) fprintf(stderr, "ERROR-r_i\n"); l = k; } } radix_sort_pe_hit_idx_hn2(r_hits->a.a, r_hits->a.a + r_hits->a.n); for (k = 1, l = 0; k <= r_hits->a.n; ++k) { if (k == r_hits->a.n || get_hit_euid(*r_hits, k) != get_hit_euid(*r_hits, l))//same euid { ///already sort by epos u = &(ug->u.a[get_hit_euid(*r_hits, l)]); update = 0; for (i = offset = 0, r_i = l; i < u->n; i++) { rid = u->a[i]>>33; rBeg = offset; rEnd = rBeg + r_g->seq[rid].len - 1; for (; r_i < k; r_i++) { upos = get_hit_epos(*r_hits, r_i);///pos at unitig if(upos > rEnd) break; if(upos >= rBeg && upos <= rEnd) { if(bub) { r_hits->a.a[r_i].id >>= 32; r_hits->a.a[r_i].id <<= 32; if(!IF_HOM(get_hit_euid(*r_hits, r_i), *bub)) { r_hits->a.a[r_i].id += 1; } } rpos = (((u->a[i]>>32)&1)? rEnd - upos : upos - rBeg);///pos at read rev = ((u->a[i]>>32)&1) ^ (r_hits->a.a[r_i].e>>63); r_hits->a.a[r_i].e = (rev<<63) | ((rid << (64-ubits))>>1) | (rpos & p_mode); update++; } } offset += (uint32_t)u->a[i]; } if(r_i != k || update != k - l) fprintf(stderr, "ERROR-r_i\n"); l = k; } } r_hits->uID_bits = ubits; r_hits->pos_mode = p_mode; } uint64_t get_corresp_usite(uint64_t rid, uint64_t rpos, uint64_t rev, uint64_t rlen, u_hits_t *x, uint64_t ubits, uint64_t p_mode, kvec_t_u64_warp *buf) { hit_aux_t *a = NULL; uint64_t a_n, i, new_uid, new_pos, new_rev; a = x->a + (x->idx.a[rid]>>32); a_n = (uint32_t)x->idx.a[rid]; for (i = 0; i < a_n; i++) { new_uid = (uint32_t)a[i].ruid; new_pos = (((a[i].ruid>>32)&1)? a[i].off + rlen - 1 - rpos : a[i].off + rpos); new_rev = ((a[i].ruid>>32)&1)^rev; kv_push(uint64_t, buf->a, (new_rev<<63) | ((new_uid << (64-ubits))>>1) | (new_pos & p_mode)); } return a_n; } void idx_hits(kvec_pe_hit* hits, uint64_t n) { uint64_t k, l; kv_resize(uint64_t, hits->idx, n); hits->idx.n = n; memset(hits->idx.a, 0, hits->idx.n*sizeof(uint64_t)); radix_sort_pe_hit_idx_hn1(hits->a.a, hits->a.a + hits->a.n); for (k = 1, l = 0; k <= hits->a.n; ++k) { if (k == hits->a.n || (get_hit_suid(*hits, k) != get_hit_suid(*hits, l))) { if (k - l > 1) radix_sort_pe_hit_idx_hn2(hits->a.a + l, hits->a.a + k); hits->idx.a[get_hit_suid(*hits, l)] = (uint64_t)l << 32 | (k - l); l = k; } } } void update_u_hits(kvec_pe_hit *u_hits, kvec_pe_hit *r_hits, ma_ug_t* ug, asg_t* r_g) { u_hits_t x; memset(&x, 0, sizeof(x)); hit_aux_t *p = NULL; ma_utg_t *u = NULL; pe_hit *t = NULL; uint64_t v, i, l, k, offset, occ_1, occ_2, *a_1, *a_2, i_1, i_2; for (v = 0; v < ug->u.n; v++) { u = &(ug->u.a[v]); for (i = offset = 0; i < u->n; i++) { if(u->a[i] != (uint64_t)-1) { kv_pushp(hit_aux_t, x, &p); p->ruid = u->a[i]>>32; p->ruid <<= 32; p->ruid |= v; p->off = offset; offset += (uint32_t)u->a[i]; } else { offset += GAP_LEN; } } } radix_sort_hit_aux_ruid(x.a, x.a + x.n); x.idx.n = x.idx.m = (x.n?(x.a[x.n-1].ruid>>33)+1:0); CALLOC(x.idx.a, x.idx.n); for (k = 1, l = 0; k <= x.n; ++k) { if (k == x.n || (x.a[k].ruid>>33) != (x.a[l].ruid>>33))//same rid { x.idx.a[x.a[l].ruid>>33] = (uint64_t)l << 32 | (k - l); l = k; } } u_hits->a.n = u_hits->idx.n = u_hits->occ.n = 0; for (u_hits->uID_bits=1; (uint64_t)(1<uID_bits)<(uint64_t)ug->g->n_seq; u_hits->uID_bits++); u_hits->pos_mode = ((uint64_t)-1) >> (u_hits->uID_bits + 1); kvec_t_u64_warp buf; kv_init(buf.a); for (i = 0; i < r_hits->a.n; i++) { buf.a.n = 0; occ_1 = get_corresp_usite(get_hit_suid(*r_hits, i), get_hit_spos(*r_hits, i), r_hits->a.a[i].s>>63, r_g->seq[get_hit_suid(*r_hits, i)].len, &x, u_hits->uID_bits, u_hits->pos_mode, &buf); occ_2 = get_corresp_usite(get_hit_euid(*r_hits, i), get_hit_epos(*r_hits, i), r_hits->a.a[i].e>>63, r_g->seq[get_hit_euid(*r_hits, i)].len, &x, u_hits->uID_bits, u_hits->pos_mode, &buf); if(occ_1 == 0 || occ_2 == 0) continue; a_1 = buf.a.a; a_2 = buf.a.a + occ_1; for (i_1 = 0; i_1 < occ_1; i_1++) { for (i_2 = 0; i_2 < occ_2; i_2++) { kv_pushp(pe_hit, u_hits->a, &t); t->id = r_hits->a.a[i].id; t->len = r_hits->a.a[i].len; t->s = a_1[i_1]; t->e = a_2[i_2]; } } } free(x.a); free(x.idx.a); kv_destroy(buf.a); idx_hits(u_hits, ug->u.n); } ma_ug_t* get_trio_unitig_graph(asg_t *sg, uint8_t flag, ug_opt_t *opt) { kvec_asg_arc_t_warp new_rtg_edges; kv_init(new_rtg_edges.a); ma_ug_t *ug = NULL; ug = ma_ug_gen(sg); adjust_utg_by_trio(&ug, sg, flag, TRIO_THRES, opt->sources, opt->reverse_sources, opt->coverage_cut, opt->tipsLen, opt->tip_drop_ratio, opt->stops_threshold, opt->ruIndex, opt->chimeric_rate, opt->drop_ratio, opt->max_hang, opt->min_ovlp, &new_rtg_edges, opt->b_mask_t); kv_destroy(new_rtg_edges.a); return ug; } static inline void asg_arc_unique_del(asg_t *g, uint32_t v, uint32_t w, int del) { uint32_t i, nv = asg_arc_n(g, v); asg_arc_t *av = asg_arc_a(g, v); for (i = 0; i < nv; ++i) { if (av[i].v == w) { av[i].del = !!del; break; } } } void horder_clean_sg_by_utg(asg_t *sg, ma_ug_t *ug) { uint32_t i, v, n_vx, w, k, m, nv, vx, wx; asg_arc_t *av = NULL; ma_utg_t *u = NULL; n_vx = sg->n_seq<<1; for (v = 0; v < n_vx; v++) { nv = asg_arc_n(sg, v); av = asg_arc_a(sg, v); for (m = 0; m < nv; m++) av[m].del = (!!1); sg->seq[v>>1].del = (!!1); } for (i = 0; i < ug->g->n_seq; ++i) { if(ug->g->seq[i].del) continue; u = &(ug->u.a[i]); for (k = 0; (k + 1) < u->n; k++) { v = u->a[k]>>32; w = u->a[k+1]>>32; asg_arc_unique_del(sg, v, w, 0); asg_arc_unique_del(sg, w^1, v^1, 0); } for (k = 0; k < u->n; k++) { sg->seq[u->a[k]>>33].del = (!!0); } v = i<<1; nv = asg_arc_n(ug->g, v); av = asg_arc_a(ug->g, v); for (k = 0; k < nv; k++) { if(av[k].del) continue; w = av[k].v; vx = (v&1?((ug->u.a[v>>1].a[0]>>32)^1):(ug->u.a[v>>1].a[ug->u.a[v>>1].n-1]>>32)); wx = (w&1?((ug->u.a[w>>1].a[ug->u.a[w>>1].n-1]>>32)^1):(ug->u.a[w>>1].a[0]>>32)); asg_arc_unique_del(sg, vx, wx, 0); asg_arc_unique_del(sg, wx^1, vx^1, 0); } v = (i<<1)+1; nv = asg_arc_n(ug->g, v); av = asg_arc_a(ug->g, v); for (k = 0; k < nv; k++) { if(av[k].del) continue; w = av[k].v; vx = (v&1?((ug->u.a[v>>1].a[0]>>32)^1):(ug->u.a[v>>1].a[ug->u.a[v>>1].n-1]>>32)); wx = (w&1?((ug->u.a[w>>1].a[ug->u.a[w>>1].n-1]>>32)^1):(ug->u.a[w>>1].a[0]>>32)); asg_arc_unique_del(sg, vx, wx, 0); asg_arc_unique_del(sg, wx^1, vx^1, 0); } } asg_cleanup(sg); /*******************************for debug************************************/ // ma_ug_t *dbg = ma_ug_gen(sg); // print_N50(dbg); // print_N50(ug); // uint8_t *end = NULL; CALLOC(end, sg->n_seq<<1); // for (i = 0; i < dbg->g->n_seq; ++i) // { // u = &(dbg->u.a[i]); // if(u->n == 0) continue; // end[(u->a[0]>>32)^1] = 1; // end[u->a[u->n-1]>>32] = 2; // } // for (i = 0; i < ug->g->n_seq; ++i) // { // u = &(ug->u.a[i]); // if(u->n == 0) continue; // for (k = 1; (k + 1) < u->n; k++) // { // if(end[(u->a[k]>>32)]) // { // fprintf(stderr, "(1) node-%lu, v-%lu, w-%lu, sg(v).n: %u\n", // u->a[k]>>33, (u->a[k]>>32), (u->a[k+1]>>32), asg_arc_n(sg, (u->a[k]>>32))); // } // if(end[(u->a[k]>>32)^1]) // { // fprintf(stderr, "(2) node-%lu, v-%lu, w-%lu, sg(v).n: %u\n", // u->a[k]>>33, (u->a[k]>>32)^1, (u->a[k-1]>>32)^1, asg_arc_n(sg, (u->a[k]>>32)^1)); // } // } // } // free(end); // ma_ug_destroy(dbg); /*******************************for debug************************************/ } uint64_t get_hic_cov_interval(uint64_t *b, uint64_t b_n, int64_t min_dp, int64_t *boundS, int64_t *boundE, h_covs *res) { if(res) res->n = 0; if(min_dp == 0 || b_n == 0) return (uint64_t)-1; uint64_t i, len = 0; int64_t dp, old_dp, start = 0, bs = b[0]>>1, be = b[b_n-1]>>1, olen; h_cov_t *p = NULL; if(boundS) bs = (*boundS); if(boundE) be = (*boundE); for (i = 0, dp = 0, start = 0; i < b_n; ++i) { old_dp = dp; ///if a[j] is qe if (b[i]&1) --dp; else ++dp; if (old_dp < min_dp && dp >= min_dp) ///old_dp < dp, b.a[j] is qs { ///case 2, a[j] is qs start = b[i]>>1; } else if (old_dp >= min_dp && dp < min_dp) ///old_dp > min_dp, b.a[j] is qe { olen = OVL(start, (int64_t)(b[i]>>1), bs, be); if(olen == 0) continue; if(res) { kv_pushp(h_cov_t, *res, &p); p->s = MAX(start, bs); p->e = MIN((int64_t)(b[i]>>1), be); p->dp = old_dp; } len += olen; } } return len; } void get_hic_breakpoint(uint64_t *b, uint64_t b_n, int64_t cutoff, h_covs *res, int64_t cov_s_pos, int64_t cov_e_pos, uint64_t *s, uint64_t *e) { uint64_t i; (*s) = (*e) = (uint64_t)-1; res->n = 0; get_hic_cov_interval(b, b_n, cutoff, &cov_s_pos, &cov_e_pos, res); if(res->n == 0) return; int64_t max = -1, max_cur = 0; int64_t max_s_idx, max_e_idx, cur_s_idx; for (i = 0; i < res->n; i++)//all intervals have cov >= cutoff { if(i > 0 && (res->a[i].s - res->a[i-1].e) > 0)//cov < cutoff { max_cur += (res->a[i].s - res->a[i-1].e);//at least positive if(max < max_cur) { max_s_idx = (max < 0? res->a[i-1].e:cur_s_idx); max_e_idx = res->a[i].s; max = max_cur; cur_s_idx = max_s_idx; } } //cov >= cutoff max_cur -= (res->a[i].e - res->a[i].s); if(max_cur < 0) { max_cur = 0; cur_s_idx = res->a[i].e; } } if(max > 0) { (*s) = max_s_idx; (*e) = max_e_idx; } } void get_consensus_break(h_covs *res, h_covs *tmp) { uint64_t i, k, n, m, max_cut = 0; h_cov_t *p = NULL; tmp->n = 0; if(res->n == 0) return; n = res->n; for (i = 0; i < n; i++) { res->a[i].s <<= 1; if(max_cut < res->a[i].dp) max_cut = res->a[i].dp; kv_pushp(h_cov_t, *res, &p); *p = res->a[i]; p->s = (res->a[i].e<<1)|1; } radix_sort_h_cov_s(res->a, res->a+res->n); int64_t dp, old_dp, start = 0, max_dp; p = NULL; max_dp = -1; tmp->n = 0; for (i = 0, dp = 0, start = 0; i < res->n; ++i) { old_dp = dp; ///if a[j] is qe if (res->a[i].s&1) --dp; else ++dp; if (old_dp < dp) ///old_dp < dp, b.a[j] is qs { ///case 2, a[j] is qs start = res->a[i].s>>1; } else if (old_dp > dp) ///old_dp > min_dp, b.a[j] is qe { if(max_dp < old_dp) { max_dp = old_dp; tmp->n = 0; kv_pushp(h_cov_t, *tmp, &p); p->s = start; p->e = res->a[i].s>>1; p->dp = max_cut; } else if(max_dp == old_dp) { kv_pushp(h_cov_t, *tmp, &p); p->s = start; p->e = res->a[i].s>>1; p->dp = max_cut; } } } if(tmp->n == 0) fprintf(stderr, "ERROR-break-0\n"); if(tmp->n == 1) return; for (i = m = 0; i < res->n; ++i) { if(res->a[i].s&1) continue; res->a[m] = res->a[i]; res->a[m].s >>= 1; m++; } res->n = m; if(res->n != n) fprintf(stderr, "ERROR-break-1\n"); for (i = 0; i < res->n; ++i) { for (k = 0; k < tmp->n; k++) { if(OVL(res->a[i].s, res->a[i].e, tmp->a[k].s, tmp->a[k].e) == 0) continue; tmp->a[k].dp = MIN(tmp->a[k].dp, res->a[i].dp); if(max_cut > tmp->a[k].dp) max_cut = tmp->a[k].dp; } } for (k = m = 0; k < tmp->n; k++) { if(max_cut != tmp->a[k].dp) continue; tmp->a[m] = tmp->a[k]; m++; } tmp->n = m; if(tmp->n == 0) fprintf(stderr, "ERROR-break-2\n"); } int64_t update_r_break(uint64_t rs, uint64_t re, h_covs *hits) { uint64_t i, hs, he; int64_t dp, old_dp, max_dp = 0; for (i = 0, dp = 0; i < hits->n; ++i) { if(hits->a[i].s&1) { hs = hits->a[i].e; he = hits->a[i].s>>1; } else { hs = hits->a[i].s>>1; he = hits->a[i].e; } if(hs <= rs && he >= re) { old_dp = dp; ///if a[j] is qe if (hits->a[i].s&1) --dp; else ++dp; ///hits->a[i].s is qe if (old_dp > dp && max_dp < old_dp) { max_dp = old_dp; } } } return max_dp; } void get_read_breaks(ma_utg_t *u, asg_t* r_g, h_covs *cov, h_covs *hit_tmp, kvec_pe_hit *hits, uint64_t sidx, uint64_t eidx, uint64_t ulen, uint64_t *idx, uint64_t *rdp) { (*idx) = (*rdp) = (uint64_t)-1; uint64_t i, k, offset, beg, end, n = cov->n, min_ovlp, o, mi, dp, min_dp; uint64_t p0s, p0e, p1s, p1e, span_s, span_e; h_cov_t *p = NULL, *a = NULL; for (i = offset = 0; i < u->n; i++) { end = offset + ((u->a[i] != (uint64_t)-1?r_g->seq[u->a[i]>>33].len:GAP_LEN)); offset += (u->a[i] != (uint64_t)-1? (uint32_t)u->a[i]:GAP_LEN); beg = offset; if(u->a[i] == (uint64_t)-1) beg -= GAP_LEN; if(end <= beg && i + 1 < u->n && u->a[i+1] == (uint64_t)-1) { end = beg + GAP_LEN; } for (k = 0; k < n; k++) { if(OVL(beg, end, cov->a[k].s, cov->a[k].e) == 0) continue; kv_pushp(h_cov_t, *cov, &p); p->s = beg; p->e = end; p->dp = i; break; } } a = cov->a + n; n = cov->n - n; if(n == 0) fprintf(stderr, "ERROR-r-break\n"); hit_tmp->n = 0; for (i = sidx; i < eidx; i++)///keep all hic hits that contain interval we want { if(get_hit_suid(*hits, i) != get_hit_euid(*hits, i)) continue; p0s = get_hit_spos(*hits, i); p0e = get_hit_spos_e(*hits, i); p1s = get_hit_epos(*hits, i); p1e = get_hit_epos_e(*hits, i); span_s = MIN(MIN(p0s, p0e), MIN(p1s, p1e)); span_s = MIN(span_s, ulen-1); span_e = MAX(MAX(p0s, p0e), MAX(p1s, p1e)); span_e = MIN(span_e, ulen-1) + 1; //if(span_e - span_s <= ulen*BREAK_CUTOFF)//need it or not? { for (k = 0; k < n; k++) { if(span_s <= a[k].s && span_e >= a[k].e) break; } if(k >= n) continue; kv_pushp(h_cov_t, *hit_tmp, &p); p->s = (span_s<<1); p->e = span_e; kv_pushp(h_cov_t, *hit_tmp, &p); p->s = ((span_e<<1)|1); p->e = span_s; } } radix_sort_h_cov_s(hit_tmp->a, hit_tmp->a+hit_tmp->n); for (k = 0, min_dp = (uint64_t)-1; k < n; k++) { //a[k].s, a[k].e dp = update_r_break(a[k].s, a[k].e, hit_tmp); a[k].dp = (uint32_t)a[k].dp; a[k].dp += (dp << 32); if(dp < min_dp) min_dp = dp; } min_ovlp = mi = (uint64_t)-1; for (k = 0; k < n; k++) { if((a[k].dp>>32) != min_dp) continue; i = (uint32_t)a[k].dp; o = 0; if(u->a[i] != (uint64_t)-1) { o = r_g->seq[u->a[i]>>33].len - (uint32_t)u->a[i]; } if(o < min_ovlp) { min_ovlp = o; mi = i; } } if(mi != (uint64_t)-1) (*idx) = mi, (*rdp) = min_dp; } void debug_sub_cov(kvec_pe_hit *hits, uint64_t sidx, uint64_t eidx, uint64_t ulen, ma_utg_t *u, asg_t* r_g, uint64_t rid, uint64_t i_cnt) { uint64_t i, offset, beg, end, rs, re; uint64_t p0s, p0e, p1s, p1e, span_s, span_e, cnt = 0; rs = re = (uint64_t)-1; for (i = offset = 0; i < u->n; i++) { end = offset + ((u->a[i] != (uint64_t)-1?r_g->seq[u->a[i]>>33].len:GAP_LEN)); offset += (u->a[i] != (uint64_t)-1? (uint32_t)u->a[i]:GAP_LEN); beg = offset; if(u->a[i] == (uint64_t)-1) beg -= GAP_LEN; if(end <= beg && i + 1 < u->n && u->a[i+1] == (uint64_t)-1) { end = beg + GAP_LEN; } if(rid == i) { rs = beg; re = end; } } for (i = sidx; i < eidx; i++)///keep all hic hits that contain interval we want { if(get_hit_suid(*hits, i) != get_hit_euid(*hits, i)) continue; p0s = get_hit_spos(*hits, i); p0e = get_hit_spos_e(*hits, i); p1s = get_hit_epos(*hits, i); p1e = get_hit_epos_e(*hits, i); span_s = MIN(MIN(p0s, p0e), MIN(p1s, p1e)); span_s = MIN(span_s, ulen-1); span_e = MAX(MAX(p0s, p0e), MAX(p1s, p1e)); span_e = MIN(span_e, ulen-1) + 1; //if(span_e - span_s <= ulen*BREAK_CUTOFF)//need it or not? { if(span_s <= rs && span_e >= re) cnt++; } } // if(cnt != i_cnt) fprintf(stderr, "cnt-%lu, i_cnt-%lu\n", cnt, i_cnt); fprintf(stderr, "******cnt-%lu, i_cnt-%lu\n", cnt, i_cnt); } void break_utg_horder(horder_t *h, h_covs *b_points) { uint64_t i, rid, uid; for (i = 0; i < b_points->n; i++) { rid = b_points->a[i].s; uid = b_points->a[i].e; } } void break_contig_init(horder_t *h, uint64_t cutoff_s, uint64_t cutoff_e) { uint64_t k, l, i, p0s, p0e, p1s, p1e, ulen, cov_hic, cov_utg, cov_ava, span_s, span_e, cutoff, bs, be, dp; kvec_t(uint64_t) b; kv_init(b); h_covs cov_buf; kv_init(cov_buf); h_covs res; kv_init(res); h_covs b_points; kv_init(b_points); h_cov_t *p = NULL; ma_ug_t *ug = h->ug; kvec_pe_hit *hits = &(h->u_hits); b_points.n = 0; for (k = 1, l = 0; k <= hits->a.n; ++k) { if (k == hits->a.n || (get_hit_suid(*hits, k) != get_hit_suid(*hits, l))) { ulen = ug->u.a[get_hit_suid(*hits, l)].len; b.n = 0; cov_hic = cov_utg = 0; if(ulen >= BREAK_THRES) { for (i = l; i < k; i++) { if(get_hit_suid(*hits, i) != get_hit_euid(*hits, i)) continue; p0s = get_hit_spos(*hits, i); p0e = get_hit_spos_e(*hits, i); p1s = get_hit_epos(*hits, i); p1e = get_hit_epos_e(*hits, i); span_s = MIN(MIN(p0s, p0e), MIN(p1s, p1e)); span_s = MIN(span_s, ulen-1); span_e = MAX(MAX(p0s, p0e), MAX(p1s, p1e)); span_e = MIN(span_e, ulen-1) + 1; //if(span_e - span_s <= ulen*BREAK_CUTOFF)//need it or not? { kv_push(uint64_t, b, (span_s<<1)); kv_push(uint64_t, b, (span_e<<1)|1); cov_hic += (span_e - span_s); } } radix_sort_ho64(b.a, b.a+b.n); cov_utg = get_hic_cov_interval(b.a, b.n, 1, NULL, NULL, NULL); cov_ava = (cov_utg? cov_hic/cov_utg:0); ///if cov_ava == 0, do nothing or break? fprintf(stderr, "\n[M::%s::] utg%.6lul, ulen: %lu, # hic hits: %lu, map cov: %lu, utg cov: %lu, average: %lu\n", __func__, get_hit_suid(*hits, l)+1, ulen, (uint64_t)(b.n>>1), cov_hic, cov_utg, cov_ava); res.n = 0; for (i = cutoff_s; i <= cutoff_e; i++) { if(i == 0) continue; cutoff = cov_ava/i; if(cutoff == 0) continue; get_hic_breakpoint(b.a, b.n, cutoff, &cov_buf, ulen*BREAK_BOUNDARY, ulen - ulen*BREAK_BOUNDARY, &bs, &be); if(bs != (uint64_t)-1 && be != (uint64_t)-1) { kv_pushp(h_cov_t, res, &p); p->s = bs; p->e = be; p->dp = cutoff; fprintf(stderr, "cutoff: %lu, bs: %lu, be: %lu\n", cutoff, bs, be); } } if(res.n > 0) { get_consensus_break(&res, &cov_buf); for (i = 0; i < cov_buf.n; i++) { fprintf(stderr, "consensus_break-s: %lu, e: %lu\n", cov_buf.a[i].s, cov_buf.a[i].e); } get_read_breaks(&(ug->u.a[get_hit_suid(*hits, l)]), h->r_g, &cov_buf, &res, hits, l, k, ulen, &bs, &dp); if(bs == (uint64_t)-1) fprintf(stderr, "ERROR-read\n"); kv_pushp(h_cov_t, b_points, &p); p->s = bs; p->e = get_hit_suid(*hits, l); p->dp = dp; fprintf(stderr, "consensus_break-rid: %lu, cov: %lu\n", bs, dp); // debug_sub_cov(hits, l, k, ulen, &(ug->u.a[get_hit_suid(*hits, l)]), h->r_g, bs, dp); } } l = k; } } kv_destroy(b); kv_destroy(cov_buf); kv_destroy(res); kv_destroy(b_points); } void generate_haplotypes(horder_t *h, ug_opt_t *opt) { uint64_t i, off; ma_ug_t *ug_1 = NULL, *ug_2 = NULL; // asg_cleanup(h->r_g); // asg_arc_del_trans(h->r_g, asm_opt.gap_fuzz);///must ug_1 = get_trio_unitig_graph(h->r_g, FATHER, opt); ug_2 = get_trio_unitig_graph(h->r_g, MOTHER, opt); h->ug = ug_1; off = ug_1->g->n_seq; ///update graph for (i = 0; i < ug_2->g->n_seq; i++) { asg_seq_set(h->ug->g, off + i, ug_2->g->seq[i].len, ug_2->g->seq[i].del); } asg_arc_t *p = NULL; for (i = 0; i < ug_2->g->n_arc; i++) { p = asg_arc_pushp(h->ug->g); *p = ug_2->g->arc[i]; p->v += (off<<1); p->ul += (off<<33); } free(h->ug->g->idx); h->ug->g->idx = 0; h->ug->g->is_srt = 0; asg_cleanup(h->ug->g); ///update unitigs ma_utg_t *pu = NULL; for (i = 0; i < ug_2->u.n; i++) { kv_pushp(ma_utg_t, h->ug->u, &pu); *pu = ug_2->u.a[i]; ug_2->u.a[i].a = NULL; ug_2->u.a[i].s = NULL; } for (i = 0; i < h->ug->g->n_seq; i++) { h->ug->g->seq[i].c = (i < off? FATHER:MOTHER); } /*******************************for debug************************************/ // if(h->ug->g->n_seq != h->ug->u.n) // { // fprintf(stderr, "ERROR-non-equal-length\n"); // } // fprintf(stderr, "h->ug->u.n-%u, off-%lu, ug_2->u.n-%u\n", (uint32_t)h->ug->u.n, off, (uint32_t)ug_2->u.n); // for (i = 0; i < h->ug->g->n_seq; i++) // { // if(h->ug->g->seq[i].len != h->ug->u.a[i].len) // { // fprintf(stderr, "****ERROR-1-%lu: g->seq[i].len-%u, u.a[i].len-%u\n", // i, (uint32_t)h->ug->g->seq[i].len, (uint32_t)h->ug->u.a[i].len); // } // pu = i < off? (&ug_1->u.a[i]) : (&ug_2->u.a[i - off]); // if(h->ug->g->seq[i].len != pu->len) // { // fprintf(stderr, "ERROR-2\n"); // } // } /*******************************for debug************************************/ ug_1 = NULL; ma_ug_destroy(ug_2); asg_destroy(h->ug->g); h->ug->g = NULL; } horder_t *init_horder_t(kvec_pe_hit *i_hits, uint64_t i_hits_uid_bits, uint64_t i_hits_pos_mode, asg_t *i_rg, ma_ug_t* i_ug, bubble_type* bub, ug_opt_t *opt) { horder_t *h = NULL; CALLOC(h, 1); get_r_hits(i_hits, &(h->r_hits), i_rg, i_ug, bub, i_hits_uid_bits, i_hits_pos_mode); h->r_g = copy_read_graph(i_rg); horder_clean_sg_by_utg(h->r_g, i_ug); generate_haplotypes(h, opt); print_N50(h->ug); update_u_hits(&(h->u_hits), &(h->r_hits), h->ug, h->r_g); break_contig_init(h, 10, 20); return h; } void destory_horder_t(horder_t **h) { kv_destroy((*h)->r_hits.a); kv_destroy((*h)->r_hits.idx); kv_destroy((*h)->r_hits.occ); kv_destroy((*h)->u_hits.a); kv_destroy((*h)->u_hits.idx); kv_destroy((*h)->u_hits.occ); kv_destroy((*h)->hp); ma_ug_destroy((*h)->ug); asg_destroy((*h)->r_g); free((*h)); }